feat: 新增商户管理员账号自动创建功能,优化租户权限控制
1. 后端实现租户创建时自动绑定创建管理员账号,支持超管/普通管理员权限区分 2. 前端适配超管权限控制业务库名、连接串等敏感字段展示与编辑 3. 优化租户数据库回退逻辑,未配置独立库时自动回落默认库 4. 调整租户列表与详情页的权限数据脱敏逻辑
This commit is contained in:
@@ -37,16 +37,17 @@
|
||||
<n-select
|
||||
v-model:value="formValue.state"
|
||||
:options="stateOptions"
|
||||
:disabled="formValue.id === 0"
|
||||
placeholder="请选择状态"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-gi>
|
||||
<n-gi span="1">
|
||||
<n-gi span="1" v-if="isAdminSuper && formValue.id > 0">
|
||||
<n-form-item label="业务库名" path="dbName">
|
||||
<n-input placeholder="请输入业务库名" v-model:value="formValue.dbName" />
|
||||
</n-form-item>
|
||||
</n-gi>
|
||||
<n-gi span="2">
|
||||
<n-gi span="2" v-if="isAdminSuper && formValue.id > 0">
|
||||
<n-form-item label="独立连接串" path="dbDsn">
|
||||
<n-input
|
||||
type="textarea"
|
||||
@@ -55,6 +56,25 @@
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-gi>
|
||||
<n-gi span="1" v-if="formValue.id === 0">
|
||||
<n-form-item label="管理员账号" path="adminUsername">
|
||||
<n-input
|
||||
placeholder="默认为商户编码+admin,可修改"
|
||||
v-model:value="formValue.adminUsername"
|
||||
@update:value="adminUsernameEdited = true"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-gi>
|
||||
<n-gi span="1" v-if="formValue.id === 0">
|
||||
<n-form-item label="管理员密码" path="adminPassword">
|
||||
<n-input
|
||||
type="password"
|
||||
show-password-on="click"
|
||||
placeholder="请输入初始密码(6-32位)"
|
||||
v-model:value="formValue.adminPassword"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-gi>
|
||||
<n-gi span="1">
|
||||
<n-form-item label="最大用户" path="maxUsers">
|
||||
<n-input-number
|
||||
@@ -64,15 +84,6 @@
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-gi>
|
||||
<n-gi span="1">
|
||||
<n-form-item label="最大群组" path="maxGroups">
|
||||
<n-input-number
|
||||
placeholder="0 表示不限"
|
||||
:min="0"
|
||||
v-model:value="formValue.maxGroups"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-gi>
|
||||
<n-gi span="1">
|
||||
<n-form-item label="群成员上限" path="maxGroupMembers">
|
||||
<n-input-number
|
||||
@@ -142,10 +153,10 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { useDictStore } from '@/store/modules/dict';
|
||||
import { Add, Edit, View } from '@/api/imTenant';
|
||||
import { newState, rules, State } from './model';
|
||||
import { isAdminSuper, newState, rules, State } from './model';
|
||||
import { useProjectSettingStore } from '@/store/modules/projectSetting';
|
||||
import { useMessage } from 'naive-ui';
|
||||
import { adaModalWidth } from '@/utils/hotgo';
|
||||
@@ -168,16 +179,32 @@
|
||||
{ label: '自动审核,失败后转人工', value: 1 },
|
||||
];
|
||||
|
||||
// 新增时管理员账号默认跟随商户编码生成,手动修改后不再覆盖
|
||||
const adminUsernameEdited = ref(false);
|
||||
watch(
|
||||
() => formValue.value.code,
|
||||
(code) => {
|
||||
if (formValue.value.id === 0 && !adminUsernameEdited.value) {
|
||||
formValue.value.adminUsername = code ? code + 'admin' : '';
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// 提交表单
|
||||
function confirmForm(e) {
|
||||
e.preventDefault();
|
||||
formRef.value.validate((errors) => {
|
||||
if (!errors) {
|
||||
formBtnLoading.value = true;
|
||||
const submit = formValue.value.id > 0 ? Edit : Add;
|
||||
const isCreate = formValue.value.id < 1;
|
||||
const submit = isCreate ? Add : Edit;
|
||||
submit(formValue.value)
|
||||
.then((_res) => {
|
||||
message.success('操作成功');
|
||||
message.success(
|
||||
isCreate
|
||||
? '商户与后台管理员账号 ' + formValue.value.adminUsername + ' 已创建'
|
||||
: '操作成功'
|
||||
);
|
||||
closeForm();
|
||||
emit('reloadTable');
|
||||
})
|
||||
@@ -201,6 +228,7 @@
|
||||
showModal.value = true;
|
||||
|
||||
if (!state || state.id < 1) {
|
||||
adminUsernameEdited.value = false;
|
||||
formValue.value = newState(state);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
import { useDictStore } from '@/store/modules/dict';
|
||||
import { List, Restore, Status } from '@/api/imTenant';
|
||||
import { PlusOutlined } from '@vicons/antd';
|
||||
import { columns, loadOptions, schemas, State } from './model';
|
||||
import { buildColumns, isAdminSuper, loadOptions, schemas, State } from './model';
|
||||
import { adaTableScrollX } from '@/utils/hotgo';
|
||||
import Edit from './edit.vue';
|
||||
import UsageModal from './usage.vue';
|
||||
@@ -116,14 +116,18 @@
|
||||
},
|
||||
});
|
||||
|
||||
// 业务库名列仅admin超管可见
|
||||
const columns = computed(() => buildColumns(isAdminSuper.value));
|
||||
|
||||
const scrollX = computed(() => {
|
||||
return adaTableScrollX(columns, actionColumn.width);
|
||||
return adaTableScrollX(columns.value, actionColumn.width);
|
||||
});
|
||||
|
||||
const [register, {}] = useForm({
|
||||
gridProps: { cols: '1 s:1 m:2 l:3 xl:4 2xl:4' },
|
||||
labelWidth: 90,
|
||||
schemas,
|
||||
// 业务库名搜索项仅admin超管可见
|
||||
schemas: schemas.filter((item) => item.field !== 'dbName' || isAdminSuper.value),
|
||||
});
|
||||
|
||||
// 加载表格数据
|
||||
|
||||
@@ -5,8 +5,13 @@ import { FormSchema } from '@/components/Form';
|
||||
import { defRangeShortcuts } from '@/utils/dateUtil';
|
||||
import { renderPopoverMemberSumma, MemberSumma } from '@/utils';
|
||||
import { useDictStore } from '@/store/modules/dict';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
|
||||
const dict = useDictStore();
|
||||
const userStore = useUserStore();
|
||||
|
||||
// 是否admin超管(业务库名/独立连接串仅超管可见可编辑)
|
||||
export const isAdminSuper = computed(() => userStore.getUserInfo?.username === 'admin');
|
||||
|
||||
export class State {
|
||||
public id = 0; // ID
|
||||
@@ -15,6 +20,8 @@ export class State {
|
||||
public tenantDesc = ''; // 商户描述
|
||||
public dbName = ''; // 业务库名
|
||||
public dbDsn = ''; // 独立连接串
|
||||
public adminUsername = ''; // 新增商户时创建的后台管理员账号
|
||||
public adminPassword = ''; // 新增商户时创建的后台管理员初始密码
|
||||
public state = 1; // 状态
|
||||
public maxUsers = 0; // 最大用户数
|
||||
public maxGroups = 0; // 最大群组数
|
||||
@@ -87,6 +94,18 @@ export const rules = {
|
||||
type: 'number',
|
||||
message: '请选择商户状态',
|
||||
},
|
||||
adminUsername: {
|
||||
required: true,
|
||||
trigger: ['blur', 'input'],
|
||||
type: 'string',
|
||||
message: '请输入管理员账号',
|
||||
},
|
||||
adminPassword: {
|
||||
required: true,
|
||||
trigger: ['blur', 'input'],
|
||||
type: 'string',
|
||||
message: '请输入管理员密码',
|
||||
},
|
||||
};
|
||||
|
||||
// 表格搜索表单
|
||||
@@ -138,7 +157,7 @@ export const schemas = ref<FormSchema[]>([
|
||||
]);
|
||||
|
||||
// 表格列
|
||||
export const columns = [
|
||||
const baseColumns = [
|
||||
{
|
||||
title: 'ID',
|
||||
key: 'id',
|
||||
@@ -194,15 +213,6 @@ export const columns = [
|
||||
return row.maxUsers > 0 ? row.maxUsers : '不限';
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '最大群组',
|
||||
key: 'maxGroups',
|
||||
align: 'left',
|
||||
width: 110,
|
||||
render(row: State) {
|
||||
return row.maxGroups > 0 ? row.maxGroups : '不限';
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '群成员上限',
|
||||
key: 'maxGroupMembers',
|
||||
@@ -287,6 +297,14 @@ export const columns = [
|
||||
},
|
||||
];
|
||||
|
||||
// 业务库名列仅admin超管可见
|
||||
export function buildColumns(isAdmin: boolean) {
|
||||
if (isAdmin) {
|
||||
return baseColumns;
|
||||
}
|
||||
return baseColumns.filter((item) => item.key !== 'dbName');
|
||||
}
|
||||
|
||||
// 加载字典数据选项
|
||||
export function loadOptions() {
|
||||
dict.loadOptions(['ImTenantStateOptions']);
|
||||
|
||||
Reference in New Issue
Block a user