@@ -14,6 +14,11 @@ const validatePhone = (rule, value, callback) => {
|
||||
callback(new Error('请输入手机号'));
|
||||
return;
|
||||
}
|
||||
// 详情回显为脱敏手机号(含 *)时放行,未修改则提交时剔除该字段
|
||||
if (phone.includes('*')) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
if (!/^1\d{10}$/.test(phone)) {
|
||||
callback(new Error('请输入正确的手机号'));
|
||||
return;
|
||||
@@ -121,6 +126,62 @@ export default {
|
||||
order: 60,
|
||||
rules: [{ required: true, message: '请选择小程序身份', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
label: '所属组织',
|
||||
prop: 'deptId',
|
||||
formslot: true,
|
||||
hide: true,
|
||||
span: 24,
|
||||
order: 55,
|
||||
rules: [{ required: true, message: '请选择所属组织', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
label: '所属组织',
|
||||
prop: 'deptName',
|
||||
minWidth: 180,
|
||||
overHidden: true,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
viewDisplay: false,
|
||||
order: 54,
|
||||
},
|
||||
{
|
||||
label: '数据权限范围',
|
||||
prop: 'dataScopeRange',
|
||||
type: 'radio',
|
||||
span: 24,
|
||||
hide: true,
|
||||
order: 53,
|
||||
value: 1,
|
||||
dicData: [
|
||||
{ label: '仅所属组织', value: 1 },
|
||||
{ label: '全部组织', value: 2 },
|
||||
{ label: '自定义', value: 3 },
|
||||
],
|
||||
rules: [{ required: true, message: '请选择数据权限范围', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
label: '数据层级范围',
|
||||
prop: 'dataLevelRange',
|
||||
type: 'radio',
|
||||
span: 24,
|
||||
hide: true,
|
||||
order: 52,
|
||||
value: 1,
|
||||
dicData: [
|
||||
{ label: '包含下级', value: 1 },
|
||||
{ label: '仅本级', value: 2 },
|
||||
],
|
||||
rules: [{ required: true, message: '请选择数据层级范围', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
label: '数据权限',
|
||||
prop: 'dataScopeDeptIds',
|
||||
formslot: true,
|
||||
span: 24,
|
||||
hide: true,
|
||||
order: 51,
|
||||
},
|
||||
{
|
||||
label: '性别',
|
||||
prop: 'sex',
|
||||
|
||||
+185
-39
@@ -20,33 +20,32 @@
|
||||
@on-load="onLoad"
|
||||
>
|
||||
<template #menu-left>
|
||||
<el-button
|
||||
type="primary"
|
||||
v-if="permission.mp_user_add"
|
||||
@click="$refs.crud.rowAdd()"
|
||||
>
|
||||
<el-button type="primary" v-if="permission.mp_user_add" @click="$refs.crud.rowAdd()">
|
||||
新增
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
v-if="permission.mp_user_reset"
|
||||
@click="handleReset"
|
||||
>
|
||||
<el-button type="primary" plain v-if="permission.mp_user_reset" @click="handleReset">
|
||||
密码重置
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
v-if="permission.mp_user_delete"
|
||||
@click="handleDelete"
|
||||
>
|
||||
<el-button type="danger" plain v-if="permission.mp_user_delete" @click="handleDelete">
|
||||
批量删除
|
||||
</el-button>
|
||||
</template>
|
||||
<template #identities="{ row }">
|
||||
{{ row.identitiesName || formatIdentities(row.identities) }}
|
||||
</template>
|
||||
<template #deptName="{ row }">
|
||||
<template v-if="formatDeptNames(row.deptName).length">
|
||||
<el-tag
|
||||
v-for="name in formatDeptNames(row.deptName)"
|
||||
:key="name"
|
||||
size="small"
|
||||
class="dept-tag"
|
||||
>
|
||||
{{ name }}
|
||||
</el-tag>
|
||||
</template>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
<template #status="{ row }">
|
||||
<el-tag :type="row.status === 1 ? 'primary' : 'info'" class="status-text">
|
||||
{{ row.status === 1 ? '启用' : '停用' }}
|
||||
@@ -55,6 +54,33 @@
|
||||
<template #updateUserName="{ row }">
|
||||
{{ formatUpdateUserName(row) }}
|
||||
</template>
|
||||
<template #deptId-form>
|
||||
<el-cascader
|
||||
v-model="deptCascaderValue"
|
||||
:options="permissionDeptTree"
|
||||
:props="deptCascaderProps"
|
||||
:disabled="isViewMode"
|
||||
clearable
|
||||
filterable
|
||||
collapse-tags
|
||||
collapse-tags-tooltip
|
||||
placeholder="请选择所属组织(可多选)"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</template>
|
||||
<template #dataScopeDeptIds-form>
|
||||
<el-tree
|
||||
v-if="Number(form.dataScopeRange) === 3"
|
||||
ref="dataScopeTree"
|
||||
:data="permissionDeptTree"
|
||||
show-checkbox
|
||||
node-key="id"
|
||||
:default-checked-keys="form.dataScopeDeptIds || []"
|
||||
:props="{ label: 'title', children: 'children' }"
|
||||
@check="handleDataScopeCheck"
|
||||
/>
|
||||
<span v-else class="form-tip">选择「自定义」后可勾选数据权限组织</span>
|
||||
</template>
|
||||
<template #menu="{ row, index }">
|
||||
<el-link
|
||||
type="primary"
|
||||
@@ -70,25 +96,13 @@
|
||||
>
|
||||
编辑
|
||||
</el-link>
|
||||
<el-link
|
||||
type="primary"
|
||||
v-if="permission.mp_user_status"
|
||||
@click="handleStatus(row)"
|
||||
>
|
||||
<el-link type="primary" v-if="permission.mp_user_status" @click="handleStatus(row)">
|
||||
{{ row.status === 1 ? '停用' : '启用' }}
|
||||
</el-link>
|
||||
<el-link
|
||||
type="primary"
|
||||
v-if="permission.mp_user_reset"
|
||||
@click="handleResetForRow(row)"
|
||||
>
|
||||
<el-link type="primary" v-if="permission.mp_user_reset" @click="handleResetForRow(row)">
|
||||
重置密码
|
||||
</el-link>
|
||||
<el-link
|
||||
type="danger"
|
||||
v-if="permission.mp_user_delete"
|
||||
@click="rowDel(row)"
|
||||
>
|
||||
<el-link type="danger" v-if="permission.mp_user_delete" @click="rowDel(row)">
|
||||
删除
|
||||
</el-link>
|
||||
</template>
|
||||
@@ -108,9 +122,12 @@
|
||||
<script>
|
||||
import { h } from 'vue';
|
||||
import { getList, getDetail, submit, remove, changeStatus, resetPassword } from '@/api/system/mpUser';
|
||||
import { getDeptTree } from '@/api/system/dept';
|
||||
import option from '@/option/system/mpUser';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { formatUpdateUserName } from '@/utils/audit';
|
||||
import { sensitive } from '@/utils/sensitive';
|
||||
import func from '@/utils/func';
|
||||
|
||||
const IDENTITY_LABEL = {
|
||||
driver: '司机',
|
||||
@@ -132,10 +149,12 @@ export default {
|
||||
selectionList: [],
|
||||
option,
|
||||
data: [],
|
||||
permissionDeptTree: [],
|
||||
sensitiveManager: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['permission']),
|
||||
...mapGetters(['permission', 'userInfo']),
|
||||
permissionList() {
|
||||
return {
|
||||
addBtn: this.validData(this.permission.mp_user_add, false),
|
||||
@@ -147,6 +166,46 @@ export default {
|
||||
ids() {
|
||||
return this.selectionList.map(item => item.id).join(',');
|
||||
},
|
||||
isViewMode() {
|
||||
return this.dialogType === 'view';
|
||||
},
|
||||
deptCascaderProps() {
|
||||
return {
|
||||
label: 'title',
|
||||
value: 'id',
|
||||
children: 'children',
|
||||
emitPath: false,
|
||||
multiple: true,
|
||||
checkStrictly: true,
|
||||
expandTrigger: 'click',
|
||||
disabled: 'disabled',
|
||||
};
|
||||
},
|
||||
deptCascaderValue: {
|
||||
get() {
|
||||
const ids = Array.isArray(this.form.deptId)
|
||||
? this.form.deptId
|
||||
: this.form.deptId
|
||||
? String(this.form.deptId).split(',').filter(Boolean)
|
||||
: [];
|
||||
return ids
|
||||
.filter(item => item !== undefined && item !== null && item !== '')
|
||||
.map(item => (typeof item === 'number' ? item : String(item)));
|
||||
},
|
||||
set(value) {
|
||||
this.form.deptId = Array.isArray(value)
|
||||
? value.filter(item => item !== undefined && item !== null && item !== '')
|
||||
: value
|
||||
? [value]
|
||||
: [];
|
||||
},
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.sensitiveManager = sensitive.create({
|
||||
fields: ['phone', 'email'],
|
||||
});
|
||||
this.loadDeptTree();
|
||||
},
|
||||
methods: {
|
||||
formatUpdateUserName,
|
||||
@@ -158,19 +217,59 @@ export default {
|
||||
.filter(Boolean)
|
||||
.join(',');
|
||||
},
|
||||
normalizeSubmitRow(row = {}) {
|
||||
const payload = { ...row };
|
||||
formatDeptNames(deptName) {
|
||||
if (!deptName) {
|
||||
return [];
|
||||
}
|
||||
return String(deptName)
|
||||
.split(',')
|
||||
.map(item => item.trim())
|
||||
.filter(Boolean);
|
||||
},
|
||||
loadDeptTree() {
|
||||
const tenantId = this.userInfo?.tenantId;
|
||||
if (!tenantId) {
|
||||
return;
|
||||
}
|
||||
getDeptTree(tenantId).then(res => {
|
||||
this.permissionDeptTree = res.data.data || [];
|
||||
});
|
||||
},
|
||||
handleDataScopeCheck(_, checked) {
|
||||
if (this.isViewMode) {
|
||||
return;
|
||||
}
|
||||
this.form.dataScopeDeptIds = checked.checkedKeys || [];
|
||||
},
|
||||
normalizeSubmitRow(row = {}, isUpdate = false) {
|
||||
let payload = { ...row };
|
||||
// 编辑时剔除未改动的脱敏字段,避免把 138****8000 写回库
|
||||
if (isUpdate && this.sensitiveManager) {
|
||||
payload = this.sensitiveManager.getSubmitData(payload);
|
||||
}
|
||||
if (Array.isArray(payload.identities)) {
|
||||
payload.identities = payload.identities.filter(Boolean).join(',');
|
||||
}
|
||||
payload.deptId = func.join(payload.deptId);
|
||||
if (payload.phone) {
|
||||
payload.phone = String(payload.phone).trim();
|
||||
}
|
||||
if (!payload.account && payload.phone) {
|
||||
// 脱敏手机号不能作为账号默认值
|
||||
if (!payload.account && payload.phone && !String(payload.phone).includes('*')) {
|
||||
payload.account = payload.phone;
|
||||
}
|
||||
payload.dataScopeRange = Number(payload.dataScopeRange || 1);
|
||||
payload.dataLevelRange = Number(payload.dataLevelRange || 1);
|
||||
if (payload.dataScopeRange === 3) {
|
||||
payload.dataScopeDeptIds = Array.isArray(payload.dataScopeDeptIds)
|
||||
? payload.dataScopeDeptIds
|
||||
: [];
|
||||
} else {
|
||||
payload.dataScopeDeptIds = [];
|
||||
}
|
||||
delete payload.password;
|
||||
delete payload.identitiesName;
|
||||
delete payload.deptName;
|
||||
delete payload.sexName;
|
||||
delete payload.createUserName;
|
||||
delete payload.updateUserName;
|
||||
@@ -178,13 +277,25 @@ export default {
|
||||
},
|
||||
beforeOpen(done, type) {
|
||||
this.dialogType = type;
|
||||
this.loadDeptTree();
|
||||
if (['edit', 'view'].includes(type) && this.form.id) {
|
||||
getDetail(this.form.id).then(res => {
|
||||
const detail = res.data.data || {};
|
||||
if (detail.identities && typeof detail.identities === 'string') {
|
||||
detail.identities = detail.identities.split(',').filter(Boolean);
|
||||
}
|
||||
this.form = detail;
|
||||
const deptIds = func.split(detail.deptId || '');
|
||||
this.form = {
|
||||
...detail,
|
||||
deptId: Array.isArray(deptIds) ? deptIds : [],
|
||||
dataScopeRange: detail.dataScopeRange || 1,
|
||||
dataLevelRange: detail.dataLevelRange || 1,
|
||||
dataScopeDeptIds: detail.dataScopeDeptIds || [],
|
||||
};
|
||||
this.sensitiveManager?.saveInitialData(this.form);
|
||||
this.$nextTick(() => {
|
||||
this.$refs.dataScopeTree?.setCheckedKeys?.(this.form.dataScopeDeptIds || []);
|
||||
});
|
||||
done();
|
||||
});
|
||||
return;
|
||||
@@ -193,12 +304,28 @@ export default {
|
||||
this.form = {
|
||||
status: 1,
|
||||
identities: ['driver'],
|
||||
deptId: [],
|
||||
dataScopeRange: 1,
|
||||
dataLevelRange: 1,
|
||||
dataScopeDeptIds: [],
|
||||
};
|
||||
this.sensitiveManager?.saveInitialData({});
|
||||
}
|
||||
done();
|
||||
},
|
||||
rowSave(row, done, loading) {
|
||||
submit(this.normalizeSubmitRow(row)).then(
|
||||
const payload = this.normalizeSubmitRow(row, false);
|
||||
if (!payload.deptId) {
|
||||
this.$message.warning('请选择所属组织');
|
||||
loading();
|
||||
return;
|
||||
}
|
||||
if (payload.dataScopeRange === 3 && (!payload.dataScopeDeptIds || !payload.dataScopeDeptIds.length)) {
|
||||
this.$message.warning('请选择自定义数据权限组织');
|
||||
loading();
|
||||
return;
|
||||
}
|
||||
submit(payload).then(
|
||||
() => {
|
||||
this.onLoad(this.page);
|
||||
this.$message.success('操作成功');
|
||||
@@ -208,7 +335,18 @@ export default {
|
||||
);
|
||||
},
|
||||
rowUpdate(row, index, done, loading) {
|
||||
submit(this.normalizeSubmitRow(row)).then(
|
||||
const payload = this.normalizeSubmitRow(row, true);
|
||||
if (!payload.deptId) {
|
||||
this.$message.warning('请选择所属组织');
|
||||
loading();
|
||||
return;
|
||||
}
|
||||
if (payload.dataScopeRange === 3 && (!payload.dataScopeDeptIds || !payload.dataScopeDeptIds.length)) {
|
||||
this.$message.warning('请选择自定义数据权限组织');
|
||||
loading();
|
||||
return;
|
||||
}
|
||||
submit(payload).then(
|
||||
() => {
|
||||
this.onLoad(this.page);
|
||||
this.$message.success('操作成功');
|
||||
@@ -351,5 +489,13 @@ export default {
|
||||
:deep(.avue-crud__menu) {
|
||||
min-height: auto;
|
||||
}
|
||||
.dept-tag {
|
||||
margin-right: 4px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.form-tip {
|
||||
color: var(--el-text-color-secondary);
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user