Files
smartDriveEEFront/src/views/lb-business/user-manage/index.vue
2026-05-19 08:52:09 +08:00

804 lines
29 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container">
<el-card class="filter-container" shadow="never">
<el-form :model="queryParams" :inline="true" label-width="100px">
<el-form-item label="上级ID">
<el-input v-model="queryParams.pid" clearable placeholder="上级用户ID" style="width: 140px" />
</el-form-item>
<el-form-item label="用户名">
<el-input v-model="queryParams.username" clearable placeholder="用户名" style="width: 140px" />
</el-form-item>
<el-form-item label="昵称">
<el-input v-model="queryParams.nickname" clearable placeholder="昵称" style="width: 140px" />
</el-form-item>
<el-form-item label="手机号">
<el-input v-model="queryParams.mobile" clearable placeholder="手机号" style="width: 140px" />
</el-form-item>
<el-form-item label="上级昵称">
<el-input v-model="queryParams.pname" clearable placeholder="上级昵称" style="width: 140px" />
</el-form-item>
<el-form-item label="状态">
<el-select v-model="queryParams.status" clearable placeholder="不限" style="width: 100px">
<el-option label="正常" :value="1" />
<el-option label="禁用" :value="0" />
</el-select>
</el-form-item>
<el-form-item label="是否VIP">
<el-select v-model="queryParams.isVip" clearable placeholder="不限" style="width: 100px">
<el-option label="否" :value="0" />
<el-option label="是" :value="1" />
</el-select>
</el-form-item>
<el-form-item label="可转卖">
<el-select v-model="queryParams.isResell" clearable placeholder="不限" style="width: 100px">
<el-option label="否" :value="0" />
<el-option label="是" :value="1" />
</el-select>
</el-form-item>
<el-form-item label="注册时间">
<el-date-picker
v-model="joinTimeRange"
type="datetimerange"
range-separator=""
start-placeholder="开始"
end-placeholder="结束"
value-format="yyyy-MM-dd HH:mm:ss"
:default-time="['00:00:00', '23:59:59']"
style="width: 360px"
/>
</el-form-item>
<el-form-item label="更新时间">
<el-date-picker
v-model="updatedAtRange"
type="datetimerange"
range-separator=""
start-placeholder="开始"
end-placeholder="结束"
value-format="yyyy-MM-dd HH:mm:ss"
:default-time="['00:00:00', '23:59:59']"
style="width: 360px"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleQuery">查询</el-button>
<el-button icon="el-icon-delete" @click="resetQuery">清空</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="action-container" shadow="never">
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">新增</el-button>
<el-button
type="warning"
icon="el-icon-refresh"
:loading="syncLoading"
style="margin-left: 12px"
@click="handleSyncFromHxr"
>
同步用户
</el-button>
</el-card>
<el-card class="table-container" shadow="never">
<el-table v-loading="loading" :data="list" style="width: 100%">
<el-table-column label="用户ID" prop="id" min-width="120" show-overflow-tooltip />
<el-table-column label="账号" prop="username" min-width="110" show-overflow-tooltip />
<el-table-column label="昵称" prop="nickname" min-width="100" show-overflow-tooltip />
<el-table-column label="昨日卖/今日买" min-width="120" align="center">
<template slot-scope="scope">
{{ formatSellBuyCount(scope.row) }}
</template>
</el-table-column>
<el-table-column label="合同" prop="contract" min-width="100" show-overflow-tooltip />
<el-table-column label="联系方式" prop="mobile" min-width="120" show-overflow-tooltip />
<el-table-column label="上级ID" prop="pid" min-width="110" show-overflow-tooltip />
<el-table-column label="上级姓名" prop="pname" min-width="100" show-overflow-tooltip />
<el-table-column label="上级电话" prop="pmobile" min-width="130" show-overflow-tooltip />
<el-table-column label="最高可抢单数" prop="maxOrder" width="110" align="center" />
<el-table-column label="今日购买总金额" prop="todayBuyTotal" min-width="120" show-overflow-tooltip />
<el-table-column label="今日卖出总金额" prop="todaySellTotal" min-width="120" show-overflow-tooltip />
<el-table-column label="用户等级" prop="level" width="80" align="center" />
<el-table-column label="余额" prop="money" min-width="90" show-overflow-tooltip />
<el-table-column label="优惠券" prop="coupon" min-width="90" show-overflow-tooltip />
<el-table-column label="个人奖金" prop="selfBonus" min-width="90" show-overflow-tooltip />
<el-table-column label="推广奖金" prop="shareBonus" min-width="90" show-overflow-tooltip />
<el-table-column label="状态" width="80" align="center">
<template slot-scope="scope">
{{ formatStatusLabel(scope.row.status) }}
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="140">
<template slot-scope="scope">
<el-button type="text" @click="handleEdit(scope.row)">编辑</el-button>
<el-button type="text" style="color:#F56C6C;" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
:current-page="queryParams.current"
:page-size="queryParams.size"
:page-sizes="[10, 20, 50, 100]"
:total="total"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</el-card>
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="920px" top="5vh" @close="resetForm">
<el-form ref="dataForm" :model="form" :rules="formRules" label-width="120px" class="user-form">
<el-divider content-position="left">基本信息</el-divider>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="用户ID" prop="id">
<el-input v-model="form.id" :disabled="isEdit" placeholder="外部用户主键,新增时必填" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="上级用户ID" prop="pid">
<el-input v-model="form.pid" placeholder="上级用户ID" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="用户名" prop="username">
<el-input v-model="form.username" placeholder="用户名" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="昵称" prop="nickname">
<el-input v-model="form.nickname" placeholder="昵称" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="手机号" prop="mobile">
<el-input v-model="form.mobile" placeholder="手机号" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="邀请码" prop="invite">
<el-input v-model="form.invite" placeholder="邀请码" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="密码" prop="password">
<el-input v-model="form.password" type="password" show-password placeholder="加密后密码" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="密码盐" prop="salt">
<el-input v-model="form.salt" placeholder="密码盐" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="性别" prop="sex">
<el-input v-model="form.sex" placeholder="性别" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="等级" prop="level">
<el-input v-model="form.level" placeholder="等级" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="状态" prop="status">
<el-select v-model="form.status" clearable placeholder="状态" style="width: 100%">
<el-option label="禁用" :value="0" />
<el-option label="正常" :value="1" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="头像路径" prop="avatar">
<el-input v-model="form.avatar" placeholder="头像路径" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="生日" prop="birthday">
<el-date-picker
v-model="form.birthday"
type="date"
clearable
value-format="yyyy-MM-dd"
placeholder="生日"
style="width: 100%"
/>
</el-form-item>
</el-col>
</el-row>
<el-divider content-position="left">资产与等级</el-divider>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="余额" prop="money">
<el-input v-model="form.money" placeholder="余额" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="优惠券" prop="coupon">
<el-input v-model="form.coupon" placeholder="优惠券金额" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="积分" prop="score">
<el-input v-model="form.score" placeholder="积分" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="自购奖金" prop="selfBonus">
<el-input v-model="form.selfBonus" placeholder="自购奖金" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="分享奖金" prop="shareBonus">
<el-input v-model="form.shareBonus" placeholder="分享奖金" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="贫困标识" prop="poor">
<el-input v-model="form.poor" placeholder="贫困标识" />
</el-form-item>
</el-col>
</el-row>
<el-divider content-position="left">VIP 与交易</el-divider>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="是否VIP" prop="isVip">
<el-select v-model="form.isVip" clearable placeholder="是否VIP" style="width: 100%">
<el-option label="否" :value="0" />
<el-option label="是" :value="1" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="可转卖" prop="isResell">
<el-select v-model="form.isResell" clearable placeholder="是否可转卖" style="width: 100%">
<el-option label="否" :value="0" />
<el-option label="是" :value="1" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="最大订单数" prop="maxOrder">
<el-input v-model="form.maxOrder" placeholder="最大订单数" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="VIP到期" prop="viptime">
<el-date-picker
v-model="form.viptime"
type="datetime"
clearable
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="VIP到期时间"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="签约合同" prop="contract">
<el-input v-model="form.contract" placeholder="合同文件路径" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="昨日卖出笔数" prop="yesterdaySellCount">
<el-input v-model="form.yesterdaySellCount" placeholder="昨日卖出笔数" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="今日买入笔数" prop="todayBuyCount">
<el-input v-model="form.todayBuyCount" placeholder="今日买入笔数" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="今日买入总额" prop="todayBuyTotal">
<el-input v-model="form.todayBuyTotal" placeholder="今日买入总额" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="今日卖出总额" prop="todaySellTotal">
<el-input v-model="form.todaySellTotal" placeholder="今日卖出总额" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="上级昵称" prop="pname">
<el-input v-model="form.pname" placeholder="上级用户昵称" />
</el-form-item>
</el-col>
</el-row>
<el-divider content-position="left">登录与时间</el-divider>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="最后登录时间" prop="lastTime">
<el-date-picker
v-model="form.lastTime"
type="datetime"
clearable
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="最后登录时间"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="最后登录IP" prop="lastIp">
<el-input v-model="form.lastIp" placeholder="最后登录IP" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="注册时间" prop="joinTime">
<el-date-picker
v-model="form.joinTime"
type="datetime"
clearable
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="注册时间"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="注册IP" prop="joinIp">
<el-input v-model="form.joinIp" placeholder="注册IP" />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="登录令牌" prop="token">
<el-input v-model="form.token" placeholder="登录令牌" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" :loading="submitLoading" @click="handleSubmit">确定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {
addLbUser,
deleteLbUser,
getLbUserList,
syncLbUserFromHxr,
updateLbUser
} from '@/api/lb-user'
import { getBusinessHeaders } from '@/utils/business-headers'
function emptyForm() {
return {
id: '',
pid: '',
username: '',
nickname: '',
mobile: '',
password: '',
salt: '',
sex: '',
avatar: '',
invite: '',
level: '',
birthday: '',
money: '',
coupon: '',
selfBonus: '',
shareBonus: '',
score: '',
lastTime: '',
lastIp: '',
joinTime: '',
joinIp: '',
token: '',
status: undefined,
viptime: '',
isVip: undefined,
contract: '',
maxOrder: '',
isResell: undefined,
yesterdaySellCount: '',
todayBuyCount: '',
todayBuyTotal: '',
todaySellTotal: '',
poor: '',
pname: ''
}
}
function parseOptionalLong(value) {
if (value === undefined || value === null || String(value).trim() === '') return undefined
const n = Number(String(value).trim())
return Number.isFinite(n) ? n : undefined
}
function parseOptionalInt(value) {
if (value === undefined || value === null || String(value).trim() === '') return undefined
const n = parseInt(String(value).trim(), 10)
return Number.isFinite(n) ? n : undefined
}
export default {
name: 'LbUserManage',
data() {
const requireId = (rule, value, callback) => {
if (this.isEdit) {
callback()
return
}
if (value === undefined || value === null || String(value).trim() === '') {
callback(new Error('请输入用户ID'))
return
}
const n = Number(String(value).trim())
if (!Number.isFinite(n)) {
callback(new Error('用户ID需为数字'))
return
}
callback()
}
return {
loading: false,
submitLoading: false,
syncLoading: false,
list: [],
total: 0,
dialogVisible: false,
dialogTitle: '',
isEdit: false,
joinTimeRange: null,
updatedAtRange: null,
queryParams: {
current: 1,
size: 10,
pid: '',
username: '',
nickname: '',
mobile: '',
pname: '',
status: undefined,
isVip: undefined,
isResell: undefined
},
form: emptyForm(),
formRules: {
id: [{ validator: requireId, trigger: 'blur' }]
}
}
},
created() {
this.fetchList()
},
methods: {
fetchList() {
this.loading = true
getLbUserList(this.buildListParams())
.then((res) => {
if (res && (res.code === 20000 || res.code === 200 || res.success === true)) {
this.list = Array.isArray(res.data) ? res.data : []
this.total = typeof res.total === 'number'
? res.total
: (res.page && typeof res.page.total === 'number' ? res.page.total : this.list.length)
} else {
this.list = []
this.total = 0
if (res && res.message) {
this.$message.error(res.message)
}
}
})
.catch(() => {
this.list = []
this.total = 0
})
.finally(() => {
this.loading = false
})
},
buildListParams() {
const params = {
current: this.queryParams.current,
size: this.queryParams.size,
pid: parseOptionalLong(this.queryParams.pid),
username: this.queryParams.username || undefined,
nickname: this.queryParams.nickname || undefined,
mobile: this.queryParams.mobile || undefined,
pname: this.queryParams.pname || undefined,
status: this.queryParams.status === 0 || this.queryParams.status === 1
? this.queryParams.status
: undefined,
isVip: this.queryParams.isVip === 0 || this.queryParams.isVip === 1
? this.queryParams.isVip
: undefined,
isResell: this.queryParams.isResell === 0 || this.queryParams.isResell === 1
? this.queryParams.isResell
: undefined
}
if (Array.isArray(this.joinTimeRange) && this.joinTimeRange.length === 2) {
params.joinTimeStart = this.joinTimeRange[0]
params.joinTimeEnd = this.joinTimeRange[1]
}
if (Array.isArray(this.updatedAtRange) && this.updatedAtRange.length === 2) {
params.updatedAtStart = this.updatedAtRange[0]
params.updatedAtEnd = this.updatedAtRange[1]
}
Object.keys(params).forEach((key) => {
if (params[key] === undefined || params[key] === '') delete params[key]
})
return params
},
handleQuery() {
this.queryParams.current = 1
this.fetchList()
},
resetQuery() {
this.queryParams = {
current: 1,
size: 10,
pid: '',
username: '',
nickname: '',
mobile: '',
pname: '',
status: undefined,
isVip: undefined,
isResell: undefined
}
this.joinTimeRange = null
this.updatedAtRange = null
this.fetchList()
},
handleSizeChange(size) {
this.queryParams.size = size
this.fetchList()
},
handleCurrentChange(current) {
this.queryParams.current = current
this.fetchList()
},
rowToForm(row) {
const pick = (k) => (row[k] !== undefined && row[k] !== null ? String(row[k]) : '')
return {
id: pick('id'),
pid: pick('pid'),
username: row.username || '',
nickname: row.nickname || '',
mobile: row.mobile || '',
password: row.password || '',
salt: row.salt || '',
sex: row.sex || '',
avatar: row.avatar || '',
invite: row.invite || '',
level: pick('level'),
birthday: row.birthday || '',
money: pick('money'),
coupon: pick('coupon'),
selfBonus: pick('selfBonus'),
shareBonus: pick('shareBonus'),
score: pick('score'),
lastTime: row.lastTime || '',
lastIp: row.lastIp || '',
joinTime: row.joinTime || '',
joinIp: row.joinIp || '',
token: row.token || '',
status: row.status !== undefined && row.status !== null ? row.status : undefined,
viptime: row.viptime || '',
isVip: row.isVip !== undefined && row.isVip !== null ? row.isVip : undefined,
contract: row.contract || '',
maxOrder: pick('maxOrder'),
isResell: row.isResell !== undefined && row.isResell !== null ? row.isResell : undefined,
yesterdaySellCount: pick('yesterdaySellCount'),
todayBuyCount: pick('todayBuyCount'),
todayBuyTotal: pick('todayBuyTotal'),
todaySellTotal: pick('todaySellTotal'),
poor: pick('poor'),
pname: row.pname || ''
}
},
getTenantIdFromBusinessHeaders() {
const headers = getBusinessHeaders()
const value = headers && headers['X-Tenant-Id']
return value ? String(value).trim() : ''
},
handleSyncFromHxr() {
const tenantId = this.getTenantIdFromBusinessHeaders()
if (!tenantId) {
this.$message.error('未获取到租户ID请先登录或配置业务请求头中的租户')
return
}
this.syncLoading = true
syncLbUserFromHxr({ tenantId })
.then((res) => {
const isSuccess = res && (res.success === true || res.code === 200 || res.code === 20000)
if (!isSuccess) {
this.$message.error((res && res.message) || '同步用户失败')
return
}
this.$message.success((res && res.message) || '同步用户成功')
this.fetchList()
})
.finally(() => {
this.syncLoading = false
})
},
handleAdd() {
this.dialogTitle = '新增用户'
this.isEdit = false
this.form = emptyForm()
this.dialogVisible = true
this.$nextTick(() => {
this.$refs.dataForm && this.$refs.dataForm.clearValidate()
})
},
handleEdit(row) {
this.dialogTitle = '编辑用户'
this.isEdit = true
this.form = this.rowToForm(row)
this.dialogVisible = true
this.$nextTick(() => {
this.$refs.dataForm && this.$refs.dataForm.clearValidate()
})
},
handleDelete(row) {
this.$confirm('确定删除该用户吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => deleteLbUser(row.id))
.then((res) => {
const isSuccess = res && (res.success === true || res.code === 200 || res.code === 20000)
if (!isSuccess) {
this.$message.error((res && res.message) || '删除失败')
return
}
this.$message.success((res && res.message) || '删除成功')
this.fetchList()
})
.catch(() => {})
},
handleSubmit() {
this.$refs.dataForm.validate((valid) => {
if (!valid) return
const payload = this.buildPayload()
this.submitLoading = true
const req = this.isEdit ? updateLbUser(payload) : addLbUser(payload)
req.then((res) => {
const isSuccess = res && (res.success === true || res.code === 200 || res.code === 20000)
if (!isSuccess) {
this.$message.error((res && res.message) || (this.isEdit ? '更新失败' : '新增失败'))
return
}
this.$message.success((res && res.message) || (this.isEdit ? '更新成功' : '新增成功'))
this.dialogVisible = false
this.fetchList()
}).finally(() => {
this.submitLoading = false
})
})
},
buildPayload() {
const payload = {
id: parseOptionalLong(this.form.id),
pid: parseOptionalLong(this.form.pid),
username: this.form.username || undefined,
nickname: this.form.nickname || undefined,
mobile: this.form.mobile || undefined,
password: this.form.password || undefined,
salt: this.form.salt || undefined,
sex: this.form.sex || undefined,
avatar: this.form.avatar || undefined,
invite: this.form.invite || undefined,
level: parseOptionalInt(this.form.level),
birthday: this.form.birthday || undefined,
money: this.form.money !== '' ? this.form.money : undefined,
coupon: this.form.coupon !== '' ? this.form.coupon : undefined,
selfBonus: this.form.selfBonus !== '' ? this.form.selfBonus : undefined,
shareBonus: this.form.shareBonus !== '' ? this.form.shareBonus : undefined,
score: parseOptionalInt(this.form.score),
lastTime: this.form.lastTime || undefined,
lastIp: this.form.lastIp || undefined,
joinTime: this.form.joinTime || undefined,
joinIp: this.form.joinIp || undefined,
token: this.form.token || undefined,
status: this.form.status === 0 || this.form.status === 1 ? this.form.status : undefined,
viptime: this.form.viptime || undefined,
isVip: this.form.isVip === 0 || this.form.isVip === 1 ? this.form.isVip : undefined,
contract: this.form.contract || undefined,
maxOrder: parseOptionalInt(this.form.maxOrder),
isResell: this.form.isResell === 0 || this.form.isResell === 1 ? this.form.isResell : undefined,
yesterdaySellCount: parseOptionalInt(this.form.yesterdaySellCount),
todayBuyCount: parseOptionalInt(this.form.todayBuyCount),
todayBuyTotal: this.form.todayBuyTotal !== '' ? this.form.todayBuyTotal : undefined,
todaySellTotal: this.form.todaySellTotal !== '' ? this.form.todaySellTotal : undefined,
poor: parseOptionalInt(this.form.poor),
pname: this.form.pname || undefined
}
Object.keys(payload).forEach((key) => {
if (payload[key] === undefined || payload[key] === '') delete payload[key]
})
return payload
},
resetForm() {
this.$refs.dataForm && this.$refs.dataForm.resetFields()
this.form = emptyForm()
},
formatSellBuyCount(row) {
const sell = row.yesterdaySellCount !== undefined && row.yesterdaySellCount !== null
? row.yesterdaySellCount
: '-'
const buy = row.todayBuyCount !== undefined && row.todayBuyCount !== null
? row.todayBuyCount
: '-'
return `${sell}/${buy}`
},
formatStatusLabel(status) {
if (status === 1) return '正常'
if (status === 0) return '禁用'
return status !== undefined && status !== null ? status : '-'
},
formatYesNo(value) {
if (value === 1) return '是'
if (value === 0) return '否'
return '-'
},
formatDateTime(dateTime) {
if (!dateTime) return '-'
const date = new Date(String(dateTime).replace('T', ' '))
if (Number.isNaN(date.getTime())) return String(dateTime)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
const seconds = String(date.getSeconds()).padStart(2, '0')
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
}
}
}
</script>
<style lang="scss" scoped>
.app-container {
.filter-container {
margin-bottom: 20px;
}
.action-container {
margin-bottom: 20px;
}
.table-container {
.el-pagination {
margin-top: 20px;
text-align: right;
}
}
.user-form {
max-height: 65vh;
overflow-y: auto;
padding-right: 8px;
}
}
</style>