|
|
@@ -1,228 +1,146 @@
|
|
|
<script lang="ts" setup>
|
|
|
-import type { Recordable } from '@vben/types';
|
|
|
+import type { TreeSelectMenuNode } from '#/api/model/menu';
|
|
|
|
|
|
import type { SystemModel } from '#/api';
|
|
|
|
|
|
-import { computed, ref } from 'vue';
|
|
|
+import { computed, nextTick, ref } from 'vue';
|
|
|
|
|
|
import { useVbenDrawer, VbenTree } from '@vben/common-ui';
|
|
|
-import { IconifyIcon } from '@vben/icons';
|
|
|
|
|
|
-import { useRequest } from '@six/request';
|
|
|
import { Spin } from 'ant-design-vue';
|
|
|
|
|
|
import { useVbenForm } from '#/adapter/form';
|
|
|
-import { editRoleMethod, getMenusMethod } from '#/api';
|
|
|
+import {
|
|
|
+ editRoleMethod,
|
|
|
+ getRoleMenuTreeselectMethod,
|
|
|
+ getRoleMethod,
|
|
|
+} from '#/api';
|
|
|
import { $t } from '#/locales';
|
|
|
|
|
|
-import { useRoleFormSchema } from '../data';
|
|
|
+import { useRequest } from '@six/request';
|
|
|
|
|
|
-import { mockData } from '../mock';
|
|
|
+import { useRoleFormSchema } from '../data';
|
|
|
|
|
|
const emits = defineEmits(['success']);
|
|
|
|
|
|
-// const {
|
|
|
-// loading,
|
|
|
-// data: menus,
|
|
|
-// send: loadMenus,
|
|
|
-// } = useRequest(getMenusMethod, { immediate: false, initialData: [] });
|
|
|
-
|
|
|
-const loading = ref(false);
|
|
|
-const menus = [
|
|
|
- {
|
|
|
- meta: {
|
|
|
- icon: 'ion:settings-outline',
|
|
|
- order: 9997,
|
|
|
- title: 'system.title',
|
|
|
- },
|
|
|
- name: 'System',
|
|
|
- path: '/system',
|
|
|
- children: [
|
|
|
- {
|
|
|
- path: '/system/organization',
|
|
|
- name: 'MedicalOrganization',
|
|
|
- meta: {
|
|
|
- icon: 'mdi:account-group',
|
|
|
- title: '医疗机构管理',
|
|
|
- },
|
|
|
- component: '/system/organization/list',
|
|
|
- },
|
|
|
- {
|
|
|
- path: '/system/enterprise',
|
|
|
- name: 'SystemEnterprise',
|
|
|
- meta: {
|
|
|
- icon: 'mdi:account-group',
|
|
|
- title: '企业管理',
|
|
|
- },
|
|
|
- component: '/system/enterprise/list',
|
|
|
- },
|
|
|
- {
|
|
|
- path: '/system/user',
|
|
|
- name: 'SystemUser',
|
|
|
- meta: {
|
|
|
- icon: 'charm:organisation',
|
|
|
- title: '煎药中心管理',
|
|
|
- },
|
|
|
- component: '/system/user/list',
|
|
|
- },
|
|
|
- {
|
|
|
- path: '/system/role',
|
|
|
- name: 'SystemRole',
|
|
|
- meta: {
|
|
|
- icon: 'charm:organisation',
|
|
|
- title: '角色管理',
|
|
|
- },
|
|
|
- component: '/system/role/list',
|
|
|
- },
|
|
|
- {
|
|
|
- path: '/system/project',
|
|
|
- name: 'SystemProject',
|
|
|
- meta: {
|
|
|
- icon: 'charm:organisation',
|
|
|
- title: '用户管理',
|
|
|
- },
|
|
|
- component: '/system/project/list',
|
|
|
- },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- meta: {
|
|
|
- icon: 'ion:settings-outline',
|
|
|
- order: 9998,
|
|
|
- title: '处方管理',
|
|
|
- },
|
|
|
- name: 'RegisterRegister',
|
|
|
- path: '/register/register',
|
|
|
- children: [
|
|
|
- {
|
|
|
- path: '/system/role',
|
|
|
- name: 'SystemRole1',
|
|
|
- meta: {
|
|
|
- icon: 'mdi:account-group',
|
|
|
- title: '处方列表',
|
|
|
- },
|
|
|
- component: '/system/role/list',
|
|
|
- },
|
|
|
- ],
|
|
|
- },
|
|
|
-];
|
|
|
-
|
|
|
const edit = useRequest(editRoleMethod, { immediate: false }).onSuccess(() => {
|
|
|
emits('success');
|
|
|
});
|
|
|
|
|
|
const formData = ref<SystemModel.Role>();
|
|
|
-const getTitle = computed(() => {
|
|
|
- return formData.value?.id
|
|
|
- ? $t('ui.actionTitle.edit', [$t('system.role.name')])
|
|
|
- : $t('ui.actionTitle.create', [$t('system.role.name')]);
|
|
|
-});
|
|
|
+const mode = ref<'add' | 'edit' | 'setting'>('add');
|
|
|
+const menuTree = ref<TreeSelectMenuNode[]>([]);
|
|
|
+const menuLoading = ref(false);
|
|
|
|
|
|
-const title = ref('新增');
|
|
|
const setTitle = computed(() => {
|
|
|
- if (title.value === 'setting') {
|
|
|
+ if (mode.value === 'setting') {
|
|
|
return '角色权限设置';
|
|
|
}
|
|
|
- if (title.value === 'edit') {
|
|
|
+ if (mode.value === 'edit') {
|
|
|
return $t('ui.actionTitle.edit', [$t('system.role.name')]);
|
|
|
}
|
|
|
return $t('ui.actionTitle.create', [$t('system.role.name')]);
|
|
|
});
|
|
|
|
|
|
-const mode = ref<'add' | 'edit' | 'setting'>('add');
|
|
|
-
|
|
|
const [Form, formApi] = useVbenForm({
|
|
|
schema: [],
|
|
|
showDefaultActions: false,
|
|
|
});
|
|
|
|
|
|
+async function loadRoleMenuTree(roleId: string) {
|
|
|
+ menuLoading.value = true;
|
|
|
+ try {
|
|
|
+ const { menus, checkedKeys } = await getRoleMenuTreeselectMethod(roleId);
|
|
|
+ menuTree.value = menus;
|
|
|
+ if (formData.value) {
|
|
|
+ formData.value.permissions = checkedKeys;
|
|
|
+ }
|
|
|
+ await nextTick();
|
|
|
+ await formApi.setValues({
|
|
|
+ name: formData.value?.name,
|
|
|
+ permissions: checkedKeys,
|
|
|
+ });
|
|
|
+ await formApi.resetValidate();
|
|
|
+ } finally {
|
|
|
+ menuLoading.value = false;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
const [Drawer, drawerApi] = useVbenDrawer({
|
|
|
async onConfirm() {
|
|
|
- mockData.value.Items.push({
|
|
|
- id: String(Math.random()),
|
|
|
- name: formData.value?.name || '',
|
|
|
- code: 'new_role_code',
|
|
|
- createUser: 'admin',
|
|
|
- lastTime: new Date().toISOString(),
|
|
|
- });
|
|
|
- drawerApi.close();
|
|
|
- // const { valid } = await formApi.validate();
|
|
|
- // if (!valid) return;
|
|
|
- // drawerApi.lock();
|
|
|
- // const data = await formApi.getValues();
|
|
|
- // try {
|
|
|
- // await edit.send({ ...formData.value, ...data });
|
|
|
- // await drawerApi.close();
|
|
|
- // } finally {
|
|
|
- // drawerApi.unlock();
|
|
|
- // }
|
|
|
+ const { valid } = await formApi.validate();
|
|
|
+ if (!valid) return;
|
|
|
+ drawerApi.lock();
|
|
|
+ const data = await formApi.getValues();
|
|
|
+ try {
|
|
|
+ await edit.send({ ...formData.value, ...data });
|
|
|
+ await drawerApi.close();
|
|
|
+ } finally {
|
|
|
+ drawerApi.unlock();
|
|
|
+ }
|
|
|
},
|
|
|
|
|
|
async onOpenChange(isOpen) {
|
|
|
if (isOpen) {
|
|
|
- // const data = drawerApi.getData<SystemModel.Role>();
|
|
|
const data = drawerApi.getData<{
|
|
|
row?: SystemModel.Role;
|
|
|
type: 'add' | 'edit' | 'setting';
|
|
|
}>();
|
|
|
await formApi.resetForm();
|
|
|
- if (data) {
|
|
|
- // formData.value = data;
|
|
|
- formData.value = data.row;
|
|
|
- title.value = data.type;
|
|
|
- mode.value = data.type;
|
|
|
- await formApi.setState({
|
|
|
- schema: useRoleFormSchema(mode.value),
|
|
|
- });
|
|
|
+ mode.value = data?.type ?? 'add';
|
|
|
+ menuTree.value = [];
|
|
|
+ await formApi.setState({
|
|
|
+ schema: useRoleFormSchema(mode.value),
|
|
|
+ });
|
|
|
+
|
|
|
+ if (mode.value === 'setting' && data?.row?.id) {
|
|
|
+ formData.value = await getRoleMethod(data.row.id);
|
|
|
+ await formApi.setValues({ name: formData.value.name });
|
|
|
+ await loadRoleMenuTree(data.row.id);
|
|
|
+ } else if (data?.row?.id) {
|
|
|
+ formData.value = await getRoleMethod(data.row.id);
|
|
|
+ await formApi.setValues(formData.value ?? {});
|
|
|
+ await formApi.resetValidate();
|
|
|
+ } else if (mode.value === 'add') {
|
|
|
+ formData.value = {
|
|
|
+ id: '',
|
|
|
+ name: '',
|
|
|
+ permissions: [],
|
|
|
+ deptIds: [],
|
|
|
+ roleSort: 0,
|
|
|
+ status: 0,
|
|
|
+ remark: '',
|
|
|
+ };
|
|
|
await formApi.setValues(formData.value);
|
|
|
- // 清除验证状态,避免在数据设置后立即显示验证错误
|
|
|
await formApi.resetValidate();
|
|
|
- }
|
|
|
- if (menus.value.length === 0) {
|
|
|
- await loadMenus();
|
|
|
- if (formData.value?.permissions?.length) {
|
|
|
- await formApi.setValues(formData.value);
|
|
|
- // 再次清除验证状态
|
|
|
- await formApi.resetValidate();
|
|
|
- }
|
|
|
+ } else {
|
|
|
+ formData.value = data?.row;
|
|
|
+ await formApi.setValues(formData.value ?? {});
|
|
|
+ await formApi.resetValidate();
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
});
|
|
|
-
|
|
|
-function getNodeClass(node: Recordable<any>) {
|
|
|
- const classes: string[] = [];
|
|
|
- if (node.value?.type === 'button') {
|
|
|
- classes.push('inline-flex');
|
|
|
- if (node.index % 3 >= 1) {
|
|
|
- classes.push('!pl-0');
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return classes.join(' ');
|
|
|
-}
|
|
|
</script>
|
|
|
<template>
|
|
|
<Drawer :title="setTitle">
|
|
|
<Form>
|
|
|
<template #permissions="slotProps">
|
|
|
- <Spin :spinning="loading" wrapper-class-name="w-full menus-loading">
|
|
|
+ <Spin :spinning="menuLoading" wrapper-class-name="w-full menus-loading">
|
|
|
<VbenTree
|
|
|
- :tree-data="menus"
|
|
|
+ v-if="menuTree.length > 0"
|
|
|
+ :tree-data="menuTree"
|
|
|
multiple
|
|
|
bordered
|
|
|
:default-expanded-level="2"
|
|
|
- :get-node-class="getNodeClass"
|
|
|
+ :show-icon="false"
|
|
|
v-bind="slotProps"
|
|
|
value-field="id"
|
|
|
- label-field="meta.title"
|
|
|
- icon-field="meta.icon"
|
|
|
- >
|
|
|
- <template #node="{ value }">
|
|
|
- <IconifyIcon v-if="value.meta.icon" :icon="value.meta.icon" />
|
|
|
- {{ $t(value.meta.title) }}
|
|
|
- </template>
|
|
|
- </VbenTree>
|
|
|
+ label-field="label"
|
|
|
+ />
|
|
|
+ <div v-else-if="!menuLoading" class="text-sm text-gray-400">
|
|
|
+ 暂无菜单数据
|
|
|
+ </div>
|
|
|
</Spin>
|
|
|
</template>
|
|
|
</Form>
|
|
|
@@ -232,20 +150,4 @@ function getNodeClass(node: Recordable<any>) {
|
|
|
.menus-loading {
|
|
|
min-height: 24px;
|
|
|
}
|
|
|
-
|
|
|
-:deep(.ant-tree-title) {
|
|
|
- .tree-actions {
|
|
|
- display: none;
|
|
|
- margin-left: 20px;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-:deep(.ant-tree-title:hover) {
|
|
|
- .tree-actions {
|
|
|
- display: flex;
|
|
|
- flex: auto;
|
|
|
- justify-content: flex-end;
|
|
|
- margin-left: 20px;
|
|
|
- }
|
|
|
-}
|
|
|
</style>
|