mirror of
https://gitee.com/nicefold/seewis-soybean-plus.git
synced 2026-10-14 03:52:28 +08:00
feat(projects): 新增部门管理页面
This commit is contained in:
Vendored
+1
-1
@@ -201,7 +201,7 @@ function handleExport() {
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
size="small"
|
||||
:indent="32"
|
||||
:indent="64"
|
||||
:flex-height="!appStore.isMobile"
|
||||
:scroll-x="scrollX"
|
||||
:loading="loading"
|
||||
|
||||
Vendored
+1
-1
@@ -13,7 +13,7 @@ defineOptions({
|
||||
#if($tplCategory == 'tree')
|
||||
interface Props {
|
||||
/** the tree list */
|
||||
treeList?: Api.Demo.Tree[] | null;
|
||||
treeList?: Api.$ModuleName.${BusinessName}[] | null;
|
||||
}
|
||||
#end
|
||||
|
||||
|
||||
@@ -272,6 +272,7 @@ const local: App.I18n.Schema = {
|
||||
system_user: 'User Management',
|
||||
system_role: 'Role Management',
|
||||
system_menu: 'Menu Management',
|
||||
system_dept: 'Dept Management',
|
||||
monitor: 'Monitor',
|
||||
'social-callback': 'Social Callback',
|
||||
monitor_cache: 'Cache Monitor',
|
||||
|
||||
@@ -269,6 +269,7 @@ const local: App.I18n.Schema = {
|
||||
system_user: '用户管理',
|
||||
system_role: '角色管理',
|
||||
system_menu: '菜单管理',
|
||||
system_dept: '部门管理',
|
||||
monitor: '系统监控',
|
||||
'social-callback': '单点登录回调',
|
||||
monitor_cache: '缓存监控',
|
||||
|
||||
@@ -26,6 +26,7 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
|
||||
demo_tree: () => import("@/views/demo/tree/index.vue"),
|
||||
home: () => import("@/views/home/index.vue"),
|
||||
monitor_cache: () => import("@/views/monitor/cache/index.vue"),
|
||||
system_dept: () => import("@/views/system/dept/index.vue"),
|
||||
system_menu: () => import("@/views/system/menu/index.vue"),
|
||||
system_role: () => import("@/views/system/role/index.vue"),
|
||||
system_user: () => import("@/views/system/user/index.vue"),
|
||||
|
||||
@@ -146,6 +146,15 @@ export const generatedRoutes: GeneratedRoute[] = [
|
||||
order: 1
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'system_dept',
|
||||
path: '/system/dept',
|
||||
component: 'view.system_dept',
|
||||
meta: {
|
||||
title: 'system_dept',
|
||||
i18nKey: 'route.system_dept'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'system_menu',
|
||||
path: '/system/menu',
|
||||
|
||||
@@ -180,6 +180,7 @@ const routeMap: RouteMap = {
|
||||
"monitor_cache": "/monitor/cache",
|
||||
"social-callback": "/social-callback",
|
||||
"system": "/system",
|
||||
"system_dept": "/system/dept",
|
||||
"system_menu": "/system/menu",
|
||||
"system_role": "/system/role",
|
||||
"system_user": "/system/user",
|
||||
|
||||
Vendored
+4
@@ -48,6 +48,10 @@ declare module 'vue' {
|
||||
IconMdiGithub: typeof import('~icons/mdi/github')['default']
|
||||
IconMdiKeyboardEsc: typeof import('~icons/mdi/keyboard-esc')['default']
|
||||
IconMdiKeyboardReturn: typeof import('~icons/mdi/keyboard-return')['default']
|
||||
'IconQuill:collapse': typeof import('~icons/quill/collapse')['default']
|
||||
'IconQuill:expand': typeof import('~icons/quill/expand')['default']
|
||||
IconQuillCollapse: typeof import('~icons/quill/collapse')['default']
|
||||
IconQuillExpand: typeof import('~icons/quill/expand')['default']
|
||||
IconSimpleIconsGitee: typeof import('~icons/simple-icons/gitee')['default']
|
||||
IconTooltip: typeof import('./../components/common/icon-tooltip.vue')['default']
|
||||
IconUilSearch: typeof import('~icons/uil/search')['default']
|
||||
|
||||
Vendored
+2
@@ -34,6 +34,7 @@ declare module "@elegant-router/types" {
|
||||
"monitor_cache": "/monitor/cache";
|
||||
"social-callback": "/social-callback";
|
||||
"system": "/system";
|
||||
"system_dept": "/system/dept";
|
||||
"system_menu": "/system/menu";
|
||||
"system_role": "/system/role";
|
||||
"system_user": "/system/user";
|
||||
@@ -115,6 +116,7 @@ declare module "@elegant-router/types" {
|
||||
| "demo_tree"
|
||||
| "home"
|
||||
| "monitor_cache"
|
||||
| "system_dept"
|
||||
| "system_menu"
|
||||
| "system_role"
|
||||
| "system_user"
|
||||
|
||||
@@ -50,12 +50,6 @@ const { columns, columnChecks, data, getData, getDataByPage, loading, mobilePagi
|
||||
width: 64,
|
||||
render: (_, index) => index + 1
|
||||
},
|
||||
{
|
||||
key: 'id',
|
||||
title: '主键',
|
||||
align: 'center',
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
key: 'deptId',
|
||||
title: '部门 ID',
|
||||
|
||||
@@ -50,13 +50,6 @@ const {
|
||||
align: 'center',
|
||||
width: 48
|
||||
},
|
||||
{
|
||||
key: 'index',
|
||||
title: $t('common.index'),
|
||||
align: 'center',
|
||||
width: 64,
|
||||
render: (_, index) => index + 1
|
||||
},
|
||||
{
|
||||
key: 'id',
|
||||
title: '主键',
|
||||
@@ -219,7 +212,7 @@ function handleExport() {
|
||||
v-model:expanded-row-keys="expandedRowKeys"
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
:indent="32"
|
||||
:indent="64"
|
||||
:flex-height="!appStore.isMobile"
|
||||
:scroll-x="scrollX"
|
||||
:loading="loading"
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
<script setup lang="tsx">
|
||||
import { ref } from 'vue';
|
||||
import { NButton, NDivider } from 'naive-ui';
|
||||
import { jsonClone } from '@sa/utils';
|
||||
import { fetchBatchDeleteDept, fetchGetDeptList } from '@/service/api/system/dept';
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
import { useAuth } from '@/hooks/business/auth';
|
||||
import { treeTransform, useNaiveTreeTable, useTableOperate } from '@/hooks/common/table';
|
||||
import { useDict } from '@/hooks/business/dict';
|
||||
import DictTag from '@/components/custom/dict-tag.vue';
|
||||
import { $t } from '@/locales';
|
||||
import ButtonIcon from '@/components/custom/button-icon.vue';
|
||||
import DeptOperateDrawer from './modules/dept-operate-drawer.vue';
|
||||
import DeptSearch from './modules/dept-search.vue';
|
||||
|
||||
defineOptions({
|
||||
name: 'DeptList'
|
||||
});
|
||||
|
||||
useDict('sys_normal_disable');
|
||||
|
||||
const appStore = useAppStore();
|
||||
const { hasAuth } = useAuth();
|
||||
|
||||
const searchParams = ref<Api.System.DeptSearchParams>({
|
||||
deptName: null,
|
||||
status: null,
|
||||
params: {}
|
||||
});
|
||||
|
||||
const {
|
||||
columns,
|
||||
columnChecks,
|
||||
data,
|
||||
rows,
|
||||
getData,
|
||||
loading,
|
||||
expandedRowKeys,
|
||||
isCollapse,
|
||||
expandAll,
|
||||
collapseAll,
|
||||
scrollX
|
||||
} = useNaiveTreeTable({
|
||||
keyField: 'deptId',
|
||||
api: () => fetchGetDeptList(searchParams.value),
|
||||
transform: response => treeTransform(response, { idField: 'deptId' }),
|
||||
columns: () => [
|
||||
{
|
||||
key: 'deptName',
|
||||
title: $t('page.system.dept.deptName'),
|
||||
align: 'center',
|
||||
minWidth: 180
|
||||
},
|
||||
{
|
||||
key: 'deptCategory',
|
||||
title: $t('page.system.dept.deptCategory'),
|
||||
align: 'center',
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
key: 'orderNum',
|
||||
title: $t('page.system.dept.sort'),
|
||||
align: 'center',
|
||||
minWidth: 60
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
title: $t('page.system.dept.status'),
|
||||
align: 'center',
|
||||
minWidth: 120,
|
||||
render(row) {
|
||||
return <DictTag size="small" value={row.status} dictCode="sys_normal_disable" />;
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'createTime',
|
||||
title: $t('page.system.dept.createTime'),
|
||||
align: 'center',
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
key: 'operate',
|
||||
title: $t('common.operate'),
|
||||
align: 'center',
|
||||
width: 150,
|
||||
render: row => {
|
||||
const addBtn = () => {
|
||||
return (
|
||||
<ButtonIcon
|
||||
text
|
||||
type="primary"
|
||||
icon="material-symbols:add-2-rounded"
|
||||
tooltipContent={$t('common.add')}
|
||||
onClick={() => addInRow(row)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const editBtn = () => {
|
||||
return (
|
||||
<ButtonIcon
|
||||
text
|
||||
type="primary"
|
||||
icon="material-symbols:drive-file-rename-outline-outline"
|
||||
tooltipContent={$t('common.edit')}
|
||||
onClick={() => edit(row.deptId)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const deleteBtn = () => {
|
||||
return (
|
||||
<ButtonIcon
|
||||
text
|
||||
type="error"
|
||||
icon="material-symbols:delete-outline"
|
||||
tooltipContent={$t('common.delete')}
|
||||
popconfirmContent={$t('common.confirmDelete')}
|
||||
onPositiveClick={() => handleDelete(row.deptId)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const buttons = [];
|
||||
if (hasAuth('system:dept:add')) buttons.push(addBtn());
|
||||
if (hasAuth('system:dept:edit')) buttons.push(editBtn());
|
||||
if (hasAuth('system:dept:remove')) buttons.push(deleteBtn());
|
||||
|
||||
return (
|
||||
<div class="flex-center gap-8px">
|
||||
{buttons.map((btn, index) => (
|
||||
<>
|
||||
{index !== 0 && <NDivider vertical />}
|
||||
{btn}
|
||||
</>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const { drawerVisible, operateType, editingData, handleAdd, handleEdit, onDeleted } = useTableOperate(
|
||||
rows,
|
||||
'deptId',
|
||||
getData
|
||||
);
|
||||
|
||||
async function handleDelete(deptId: CommonType.IdType) {
|
||||
// request
|
||||
const { error } = await fetchBatchDeleteDept([deptId]);
|
||||
if (error) return;
|
||||
onDeleted();
|
||||
}
|
||||
|
||||
function edit(deptId: CommonType.IdType) {
|
||||
handleEdit(deptId);
|
||||
}
|
||||
|
||||
function addInRow(row: Api.System.Dept) {
|
||||
editingData.value = jsonClone(row);
|
||||
handleAdd();
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
|
||||
<DeptSearch v-model:model="searchParams" @search="getData" />
|
||||
<NCard :title="$t('page.system.dept.title')" :bordered="false" size="small" class="card-wrapper sm:flex-1-hidden">
|
||||
<template #header-extra>
|
||||
<TableHeaderOperation
|
||||
v-model:columns="columnChecks"
|
||||
:loading="loading"
|
||||
:show-add="hasAuth('system:dept:add')"
|
||||
:show-delete="false"
|
||||
@add="handleAdd"
|
||||
@refresh="getData"
|
||||
>
|
||||
<template #prefix>
|
||||
<NButton v-if="!isCollapse" :disabled="!data.length" size="small" @click="expandAll">
|
||||
<template #icon>
|
||||
<icon-quill:expand />
|
||||
</template>
|
||||
{{ $t('page.system.dept.expandAll') }}
|
||||
</NButton>
|
||||
<NButton v-if="isCollapse" :disabled="!data.length" size="small" @click="collapseAll">
|
||||
<template #icon>
|
||||
<icon-quill:collapse />
|
||||
</template>
|
||||
{{ $t('page.system.dept.collapseAll') }}
|
||||
</NButton>
|
||||
</template>
|
||||
</TableHeaderOperation>
|
||||
</template>
|
||||
<NDataTable
|
||||
v-model:expanded-row-keys="expandedRowKeys"
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
size="small"
|
||||
:indent="64"
|
||||
:flex-height="!appStore.isMobile"
|
||||
:scroll-x="scrollX"
|
||||
:loading="loading"
|
||||
:row-key="row => row.deptId"
|
||||
class="sm:h-full"
|
||||
/>
|
||||
<DeptOperateDrawer
|
||||
v-model:visible="drawerVisible"
|
||||
:operate-type="operateType"
|
||||
:row-data="editingData"
|
||||
@submitted="getData"
|
||||
/>
|
||||
</NCard>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,247 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { NInputNumber } from 'naive-ui';
|
||||
import { useLoading } from '@sa/hooks';
|
||||
import { jsonClone } from '@sa/utils';
|
||||
import { fetchCreateDept, fetchGetDeptList, fetchGetExcludeDeptList, fetchUpdateDept } from '@/service/api/system/dept';
|
||||
import { fetchGetDeptUserList } from '@/service/api/system/user';
|
||||
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
|
||||
import { handleTree } from '@/utils/common';
|
||||
import { $t } from '@/locales';
|
||||
|
||||
defineOptions({
|
||||
name: 'DeptOperateDrawer'
|
||||
});
|
||||
|
||||
interface Props {
|
||||
/** the type of operation */
|
||||
operateType: NaiveUI.TableOperateType;
|
||||
/** the edit row data */
|
||||
rowData?: Api.System.Dept | null;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
interface Emits {
|
||||
(e: 'submitted'): void;
|
||||
}
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const visible = defineModel<boolean>('visible', {
|
||||
default: false
|
||||
});
|
||||
|
||||
const { formRef, validate, restoreValidation } = useNaiveForm();
|
||||
const { createRequiredRule, patternRules } = useFormRules();
|
||||
|
||||
const { loading: deptLoading, startLoading: startDeptLoading, endLoading: endDeptLoading } = useLoading();
|
||||
const { loading: userLoading, startLoading: startUserLoading, endLoading: endUserLoading } = useLoading();
|
||||
const deptData = ref<Api.System.Dept[]>([]);
|
||||
const userOptions = ref<CommonType.Option<CommonType.IdType>[]>([]);
|
||||
const placeholder = ref<string>($t('page.system.dept.placeholder.defaultLeaderPlaceHolder'));
|
||||
const disabled = ref<boolean>(false);
|
||||
const expandedKeys = ref<CommonType.IdType[]>([]);
|
||||
|
||||
const title = computed(() => {
|
||||
const titles: Record<NaiveUI.TableOperateType, string> = {
|
||||
add: $t('page.system.dept.addDept'),
|
||||
edit: $t('page.system.dept.editDept')
|
||||
};
|
||||
return titles[props.operateType];
|
||||
});
|
||||
|
||||
type Model = Api.System.DeptOperateParams;
|
||||
|
||||
const model = ref<Model>(createDefaultModel());
|
||||
|
||||
function createDefaultModel(): Model {
|
||||
return {
|
||||
parentId: props.rowData?.deptId || '',
|
||||
deptName: '',
|
||||
deptCategory: '',
|
||||
orderNum: null,
|
||||
leader: null,
|
||||
phone: '',
|
||||
email: '',
|
||||
status: '0'
|
||||
};
|
||||
}
|
||||
|
||||
type RuleKey = Extract<keyof Model, 'deptId' | 'parentId' | 'orderNum' | 'deptName' | 'phone' | 'email'>;
|
||||
|
||||
const rules: Record<RuleKey, App.Global.FormRule> = {
|
||||
deptId: createRequiredRule($t('page.system.dept.form.deptId.invalid')),
|
||||
parentId: createRequiredRule($t('page.system.dept.form.parentId.invalid')),
|
||||
orderNum: createRequiredRule($t('page.system.dept.form.orderNum.invalid')),
|
||||
deptName: createRequiredRule($t('page.system.dept.form.deptName.invalid')),
|
||||
phone: patternRules.phone,
|
||||
email: patternRules.email
|
||||
};
|
||||
|
||||
function handleUpdateModelWhenEdit() {
|
||||
model.value = createDefaultModel();
|
||||
|
||||
if (props.operateType === 'edit' && props.rowData) {
|
||||
Object.assign(model.value, jsonClone(props.rowData));
|
||||
}
|
||||
}
|
||||
|
||||
function closeDrawer() {
|
||||
visible.value = false;
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
await validate();
|
||||
|
||||
const { deptId, parentId, deptName, deptCategory, orderNum, leader, phone, email, status } = model.value;
|
||||
|
||||
// request
|
||||
if (props.operateType === 'add') {
|
||||
const { error } = await fetchCreateDept({
|
||||
parentId,
|
||||
deptName,
|
||||
deptCategory,
|
||||
orderNum,
|
||||
leader,
|
||||
phone,
|
||||
email,
|
||||
status
|
||||
});
|
||||
if (error) return;
|
||||
}
|
||||
|
||||
if (props.operateType === 'edit') {
|
||||
const { error } = await fetchUpdateDept({
|
||||
deptId,
|
||||
parentId,
|
||||
deptName,
|
||||
deptCategory,
|
||||
orderNum,
|
||||
leader,
|
||||
phone,
|
||||
email,
|
||||
status
|
||||
});
|
||||
if (error) return;
|
||||
}
|
||||
|
||||
window.$message?.success($t('common.updateSuccess'));
|
||||
closeDrawer();
|
||||
emit('submitted');
|
||||
}
|
||||
|
||||
async function getDeptData() {
|
||||
startDeptLoading();
|
||||
const { data, error } =
|
||||
props.operateType === 'add' ? await fetchGetDeptList() : await fetchGetExcludeDeptList(props.rowData?.deptId);
|
||||
|
||||
if (error) {
|
||||
window.$message?.error(error.message || $t('page.system.dept.error.getDeptDataFail'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
deptData.value = handleTree(data, { idField: 'deptId' });
|
||||
if (deptData.value?.length) {
|
||||
expandedKeys.value = [deptData.value[0].deptId];
|
||||
}
|
||||
}
|
||||
endDeptLoading();
|
||||
}
|
||||
|
||||
async function getUserData() {
|
||||
if (props.operateType === 'add' || !props.rowData?.deptId) {
|
||||
placeholder.value = $t('page.system.dept.placeholder.addDataLeaderPlaceHolder');
|
||||
disabled.value = true;
|
||||
return;
|
||||
}
|
||||
startUserLoading();
|
||||
const { data, error } = await fetchGetDeptUserList(props.rowData.deptId);
|
||||
if (error) {
|
||||
window.$message?.error(error.message || $t('page.system.dept.error.getDeptUserDataFail'));
|
||||
return;
|
||||
}
|
||||
if (data.length === 0) {
|
||||
placeholder.value = $t('page.system.dept.placeholder.deptUserIsEmptyLeaderPlaceHolder');
|
||||
disabled.value = true;
|
||||
}
|
||||
userOptions.value = data.map(item => ({
|
||||
label: `${item.userName} | ${item.nickName}`,
|
||||
value: item.userId
|
||||
}));
|
||||
endUserLoading();
|
||||
}
|
||||
|
||||
watch(visible, () => {
|
||||
if (visible.value) {
|
||||
disabled.value = false;
|
||||
getDeptData();
|
||||
getUserData();
|
||||
handleUpdateModelWhenEdit();
|
||||
restoreValidation();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NDrawer v-model:show="visible" :title="title" display-directive="show" :width="800" class="max-w-90%">
|
||||
<NDrawerContent :title="title" :native-scrollbar="false" closable>
|
||||
<NForm ref="formRef" :model="model" :rules="rules">
|
||||
<NFormItem v-if="model.parentId !== 0" :label="$t('page.system.dept.parentId')" path="parentId">
|
||||
<NTreeSelect
|
||||
v-model:value="model.parentId"
|
||||
v-model:expanded-keys="expandedKeys"
|
||||
:loading="deptLoading"
|
||||
clearable
|
||||
:options="deptData"
|
||||
label-field="deptName"
|
||||
key-field="deptId"
|
||||
:placeholder="$t('page.system.dept.form.parentId.required')"
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem :label="$t('page.system.dept.deptName')" path="deptName">
|
||||
<NInput v-model:value="model.deptName" :placeholder="$t('page.system.dept.form.deptName.required')" />
|
||||
</NFormItem>
|
||||
<NFormItem :label="$t('page.system.dept.orderNum')" path="orderNum">
|
||||
<NInputNumber
|
||||
v-model:value="model.orderNum"
|
||||
class="w-full"
|
||||
:placeholder="$t('page.system.dept.form.orderNum.required')"
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem :label="$t('page.system.dept.deptCategory')" path="deptCategory">
|
||||
<NInput v-model:value="model.deptCategory" :placeholder="$t('page.system.dept.form.deptCategory.required')" />
|
||||
</NFormItem>
|
||||
|
||||
<NFormItem :label="$t('page.system.dept.leader')" path="leader">
|
||||
<NSelect
|
||||
v-model:value="model.leader"
|
||||
:loading="userLoading"
|
||||
:disabled="disabled"
|
||||
:placeholder="placeholder"
|
||||
:options="userOptions"
|
||||
/>
|
||||
</NFormItem>
|
||||
|
||||
<NFormItem :label="$t('page.system.dept.phone')" path="phone">
|
||||
<NInput v-model:value="model.phone" :placeholder="$t('page.system.dept.form.phone.required')" />
|
||||
</NFormItem>
|
||||
<NFormItem :label="$t('page.system.dept.email')" path="email">
|
||||
<NInput v-model:value="model.email" :placeholder="$t('page.system.dept.form.email.required')" />
|
||||
</NFormItem>
|
||||
<NFormItem :label="$t('page.system.dept.status')" path="status">
|
||||
<DictRadio v-model:value="model.status" dict-code="sys_normal_disable" />
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
<template #footer>
|
||||
<NSpace :size="16">
|
||||
<NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton>
|
||||
<NButton type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</NButton>
|
||||
</NSpace>
|
||||
</template>
|
||||
</NDrawerContent>
|
||||
</NDrawer>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,83 @@
|
||||
<script setup lang="ts">
|
||||
import { toRaw } from 'vue';
|
||||
import { jsonClone } from '@sa/utils';
|
||||
import { useNaiveForm } from '@/hooks/common/form';
|
||||
import { useDict } from '@/hooks/business/dict';
|
||||
import { $t } from '@/locales';
|
||||
|
||||
defineOptions({
|
||||
name: 'DeptSearch'
|
||||
});
|
||||
|
||||
interface Emits {
|
||||
(e: 'reset'): void;
|
||||
(e: 'search'): void;
|
||||
}
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const { formRef, validate, restoreValidation } = useNaiveForm();
|
||||
|
||||
const { options: sysNormalDisableOptions } = useDict('sys_normal_disable', false);
|
||||
|
||||
const model = defineModel<Api.System.DeptSearchParams>('model', { required: true });
|
||||
|
||||
const defaultModel = jsonClone(toRaw(model.value));
|
||||
|
||||
function resetModel() {
|
||||
Object.assign(model.value, defaultModel);
|
||||
}
|
||||
|
||||
async function reset() {
|
||||
await restoreValidation();
|
||||
resetModel();
|
||||
emit('reset');
|
||||
}
|
||||
|
||||
async function search() {
|
||||
await validate();
|
||||
emit('search');
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NCard :bordered="false" size="small" class="card-wrapper">
|
||||
<NCollapse>
|
||||
<NCollapseItem :title="$t('common.search')" name="user-search">
|
||||
<NForm ref="formRef" :model="model" label-placement="left" :label-width="80">
|
||||
<NGrid responsive="screen" item-responsive>
|
||||
<NFormItemGi span="24 s:12 m:8" :label="$t('page.system.dept.deptName')" path="deptName" class="pr-24px">
|
||||
<NInput v-model:value="model.deptName" :placeholder="$t('page.system.dept.form.deptName.required')" />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:8 " :label="$t('page.system.dept.status')" path="status" class="pr-24px">
|
||||
<NSelect
|
||||
v-model:value="model.status"
|
||||
:placeholder="$t('page.system.dept.form.status.required')"
|
||||
:options="sysNormalDisableOptions"
|
||||
clearable
|
||||
/>
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:8" class="pr-24px">
|
||||
<NSpace class="w-full" justify="end">
|
||||
<NButton @click="reset">
|
||||
<template #icon>
|
||||
<icon-ic-round-refresh class="text-icon" />
|
||||
</template>
|
||||
{{ $t('common.reset') }}
|
||||
</NButton>
|
||||
<NButton type="primary" ghost @click="search">
|
||||
<template #icon>
|
||||
<icon-ic-round-search class="text-icon" />
|
||||
</template>
|
||||
{{ $t('common.search') }}
|
||||
</NButton>
|
||||
</NSpace>
|
||||
</NFormItemGi>
|
||||
</NGrid>
|
||||
</NForm>
|
||||
</NCollapseItem>
|
||||
</NCollapse>
|
||||
</NCard>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup lang="tsx">
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import type { SelectOption } from 'naive-ui';
|
||||
import { jsonClone } from '@sa/utils';
|
||||
import { menuIconTypeOptions, menuIsFrameOptions, menuTypeOptions } from '@/constants/business';
|
||||
import { fetchCreateMenu, fetchUpdateMenu } from '@/service/api/system';
|
||||
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
|
||||
@@ -121,10 +122,10 @@ const localIconOptions = localIcons.map<SelectOption>(item => ({
|
||||
function handleInitModel() {
|
||||
queryList.value = [];
|
||||
iconType.value = '1';
|
||||
Object.assign(model, createDefaultModel());
|
||||
model.value = createDefaultModel();
|
||||
|
||||
if (props.operateType === 'edit' && props.rowData) {
|
||||
Object.assign(model, props.rowData);
|
||||
Object.assign(model.value, jsonClone(props.rowData));
|
||||
if (isMenu.value && isInternalType.value) {
|
||||
model.value.component = model.value.component?.slice(0, -6);
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ const { columns, columnChecks, data, getData, getDataByPage, loading, mobilePagi
|
||||
type="primary"
|
||||
icon="material-symbols:drive-file-rename-outline-outline"
|
||||
tooltipContent={$t('common.edit')}
|
||||
onClick={() => edit(row.roleId!)}
|
||||
onClick={() => edit(row.roleId)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -161,7 +161,7 @@ const { columns, columnChecks, data, getData, getDataByPage, loading, mobilePagi
|
||||
icon="material-symbols:delete-outline"
|
||||
tooltipContent={$t('common.delete')}
|
||||
popconfirmContent={$t('common.confirmDelete')}
|
||||
onPositiveClick={() => handleDelete(row.roleId!)}
|
||||
onPositiveClick={() => handleDelete(row.roleId)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -78,8 +78,8 @@ const rules: Record<RuleKey, App.Global.FormRule> = {
|
||||
|
||||
async function handleUpdateModelWhenEdit() {
|
||||
menuOptions.value = [];
|
||||
model.value = createDefaultModel();
|
||||
model.value.menuIds = [];
|
||||
Object.assign(model.value, jsonClone(props.rowData));
|
||||
|
||||
if (props.operateType === 'add') {
|
||||
menuTreeRef.value?.refresh();
|
||||
@@ -88,7 +88,7 @@ async function handleUpdateModelWhenEdit() {
|
||||
|
||||
if (props.operateType === 'edit' && props.rowData) {
|
||||
startMenuLoading();
|
||||
Object.assign(model, props.rowData);
|
||||
Object.assign(model.value, jsonClone(props.rowData));
|
||||
const { data, error } = await fetchGetRoleMenuTreeSelect(model.value.roleId!);
|
||||
if (error) return;
|
||||
model.value.menuIds = data.checkedKeys;
|
||||
|
||||
@@ -22,6 +22,8 @@ const dateRangeCreateTime = ref<[string, string] | null>(null);
|
||||
|
||||
const model = defineModel<Api.System.RoleSearchParams>('model', { required: true });
|
||||
|
||||
const defaultModel = jsonClone(toRaw(model.value));
|
||||
|
||||
const { options: sysNormalDisableOptions } = useDict('sys_normal_disable', false);
|
||||
|
||||
function onDateRangeCreateTimeUpdate(value: [string, string] | null) {
|
||||
@@ -34,8 +36,6 @@ function onDateRangeCreateTimeUpdate(value: [string, string] | null) {
|
||||
}
|
||||
}
|
||||
|
||||
const defaultModel = jsonClone(toRaw(model.value));
|
||||
|
||||
function resetModel() {
|
||||
dateRangeCreateTime.value = null;
|
||||
Object.assign(model.value, defaultModel);
|
||||
|
||||
@@ -145,7 +145,7 @@ const { columns, columnChecks, data, getData, getDataByPage, loading, mobilePagi
|
||||
type="primary"
|
||||
icon="material-symbols:drive-file-rename-outline-outline"
|
||||
tooltipContent={$t('common.edit')}
|
||||
onClick={() => edit(row.userId!)}
|
||||
onClick={() => edit(row.userId)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -157,7 +157,7 @@ const { columns, columnChecks, data, getData, getDataByPage, loading, mobilePagi
|
||||
type="primary"
|
||||
icon="material-symbols:key-vertical-outline"
|
||||
tooltipContent="重置密码"
|
||||
onClick={() => handleResetPwd(row.userId!)}
|
||||
onClick={() => handleResetPwd(row.userId)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -170,7 +170,7 @@ const { columns, columnChecks, data, getData, getDataByPage, loading, mobilePagi
|
||||
icon="material-symbols:delete-outline"
|
||||
tooltipContent={$t('common.delete')}
|
||||
popconfirmContent={$t('common.confirmDelete')}
|
||||
onPositiveClick={() => handleDelete(row.userId!)}
|
||||
onPositiveClick={() => handleDelete(row.userId)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user