feat-wip(components): 数据字典相关页面代码提交

This commit is contained in:
2025-12-04 23:16:29 +08:00
parent 0943818fec
commit ccf2565e1d
9 changed files with 167 additions and 36 deletions

View File

@ -1,5 +1,5 @@
# backend service base url, test environment # backend service base url, test environment
VITE_SERVICE_BASE_URL=http://localhost:8080 VITE_SERVICE_BASE_URL=http://192.168.1.7:8080
# other backend service base url, test environment # other backend service base url, test environment
VITE_OTHER_SERVICE_BASE_URL=`{ VITE_OTHER_SERVICE_BASE_URL=`{

View File

@ -332,7 +332,13 @@ const local: App.I18n.Schema = {
} }
}, },
item: { item: {
title: 'Item' title: 'Item',
fields: {
name: 'Name',
code: 'Code',
sort: 'Sort',
description: 'Description'
}
} }
} }
}, },

View File

@ -328,7 +328,13 @@ const local: App.I18n.Schema = {
} }
}, },
item: { item: {
title: '字典项' title: '字典项',
fields: {
name: '名称',
code: '代码',
sort: '排序',
description: '描述'
}
} }
} }
}, },

View File

@ -43,3 +43,13 @@ export function fetchDictionaryDeleteBatch(ids: string[]) {
} }
}); });
} }
export function fetchTreeDictionaryItem(dictionaryId: string) {
return request<Api.Sys.Core.DictionaryItem[]>({
url: '/dictionaryItem/tree',
method: 'post',
data: {
dictionaryId
}
});
}

View File

@ -575,6 +575,12 @@ declare namespace App {
}; };
item: { item: {
title: string; title: string;
fields: {
name: string;
code: string;
sort: string;
description: string;
};
}; };
}; };
}; };

View File

@ -63,6 +63,7 @@ declare module 'vue' {
NFormItemGi: typeof import('naive-ui')['NFormItemGi'] NFormItemGi: typeof import('naive-ui')['NFormItemGi']
NGi: typeof import('naive-ui')['NGi'] NGi: typeof import('naive-ui')['NGi']
NGrid: typeof import('naive-ui')['NGrid'] NGrid: typeof import('naive-ui')['NGrid']
NHr: typeof import('naive-ui')['NHr']
NInput: typeof import('naive-ui')['NInput'] NInput: typeof import('naive-ui')['NInput']
NInputGroup: typeof import('naive-ui')['NInputGroup'] NInputGroup: typeof import('naive-ui')['NInputGroup']
NInputNumber: typeof import('naive-ui')['NInputNumber'] NInputNumber: typeof import('naive-ui')['NInputNumber']
@ -154,6 +155,7 @@ declare global {
const NFormItemGi: typeof import('naive-ui')['NFormItemGi'] const NFormItemGi: typeof import('naive-ui')['NFormItemGi']
const NGi: typeof import('naive-ui')['NGi'] const NGi: typeof import('naive-ui')['NGi']
const NGrid: typeof import('naive-ui')['NGrid'] const NGrid: typeof import('naive-ui')['NGrid']
const NHr: typeof import('naive-ui')['NHr']
const NInput: typeof import('naive-ui')['NInput'] const NInput: typeof import('naive-ui')['NInput']
const NInputGroup: typeof import('naive-ui')['NInputGroup'] const NInputGroup: typeof import('naive-ui')['NInputGroup']
const NInputNumber: typeof import('naive-ui')['NInputNumber'] const NInputNumber: typeof import('naive-ui')['NInputNumber']

View File

@ -82,9 +82,6 @@ const { columns, columnChecks, data, loading, getData, getDataByPage, mobilePagi
align: 'center', align: 'center',
render: row => ( render: row => (
<div class="flex-center gap-8px"> <div class="flex-center gap-8px">
<NButton type="success" ghost size="small" onClick={() => handleOpenChildren(row.id)}>
{$t('common.children')}
</NButton>
<NButton type="primary" ghost size="small" onClick={() => edit(row.id)}> <NButton type="primary" ghost size="small" onClick={() => edit(row.id)}>
{$t('common.edit')} {$t('common.edit')}
</NButton> </NButton>
@ -122,8 +119,6 @@ function handleDelete(id: string) {
function edit(id: string) { function edit(id: string) {
handleEdit(id); handleEdit(id);
} }
function handleOpenChildren(_: string) {}
</script> </script>
<template> <template>

View File

@ -0,0 +1,59 @@
<script setup lang="ts">
import { computed } from 'vue';
import { $t } from '@/locales';
defineOptions({
name: 'DictionaryOperateDialog'
});
const props = defineProps<{
/** the type of operation */
operateType: NaiveUI.TableOperateType;
/** the edit row data */
// rowData?: Api.Sys.Core.Dictionary | null;
}>();
const emit = defineEmits<{
(e: 'submitted'): void;
}>();
const visible = defineModel<boolean>('visible', {
default: false
});
const title = computed(() => {
const titles: Record<NaiveUI.TableOperateType, string> = {
add: $t('common.add'),
edit: $t('common.edit')
};
return titles[props.operateType];
});
function closeDialog(): void {
visible.value = false;
}
function handleSubmit() {
window.$message?.success($t('common.updateSuccess'));
closeDialog();
emit('submitted');
}
</script>
<template>
<NModal
v-model:show="visible"
preset="dialog"
:title="title"
@positive-click="handleSubmit"
@negative-click="visible = false"
>
<div class="dialog-wrapper">111</div>
</NModal>
</template>
<style scoped>
.dialog-wrapper {
width: 1000px;
}
</style>

View File

@ -1,10 +1,12 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import type { DataTableColumns } from 'naive-ui';
import { jsonClone } from '@sa/utils'; import { jsonClone } from '@sa/utils';
import { dictionaryTypeOptions } from '@/constants/sys/core/dictionary'; import { dictionaryTypeOptions } from '@/constants/sys/core/dictionary';
import { fetchDictionaryAdd, fetchDictionaryEdit } from '@/service/api'; import { fetchDictionaryAdd, fetchDictionaryEdit, fetchTreeDictionaryItem } from '@/service/api';
import { useFormRules, useNaiveForm } from '@/hooks/common/form'; import { useFormRules, useNaiveForm } from '@/hooks/common/form';
import { $t } from '@/locales'; import { $t } from '@/locales';
import DictionaryItem = Api.Sys.Core.DictionaryItem;
defineOptions({ defineOptions({
name: 'DictionaryOperateDrawer' name: 'DictionaryOperateDrawer'
@ -40,20 +42,48 @@ const title = computed(() => {
return titles[props.operateType]; return titles[props.operateType];
}); });
type Model = Pick<Api.Sys.Core.Dictionary, 'name' | 'code' | 'type' | 'description'>; interface Model {
name: string;
code: string;
type: Api.Sys.Core.DictionaryType;
description: string | null;
children: Api.Sys.Core.DictionaryItem[];
}
const model = ref(createDefaultModel()); const model = ref(createDefaultModel());
const childrenColumns: DataTableColumns<DictionaryItem> = [
{
key: 'name',
title: $t('page.sys.core.dictionary.item.fields.name'),
align: 'center',
resizable: true
},
{
key: 'code',
title: $t('page.sys.core.dictionary.item.fields.code'),
align: 'center',
resizable: true
},
{
key: 'sort',
title: $t('page.sys.core.dictionary.item.fields.sort'),
align: 'center',
resizable: true
}
];
function createDefaultModel(): Model { function createDefaultModel(): Model {
return { return {
name: '', name: '',
code: '', code: '',
type: 'enum', type: 'enum',
description: null description: null,
children: []
}; };
} }
type RuleKey = Exclude<keyof Model, 'description'>; type RuleKey = 'name' | 'code' | 'type';
const rules: Record<RuleKey, App.Global.FormRule> = { const rules: Record<RuleKey, App.Global.FormRule> = {
name: defaultRequiredRule, name: defaultRequiredRule,
@ -69,6 +99,17 @@ function handleInitModel() {
} }
} }
function handleInitChildrenModel() {
if (props.operateType !== 'edit' || !props.rowData?.id) {
return;
}
fetchTreeDictionaryItem(props.rowData.id).then(res => {
if (res.data) {
model.value.children = res.data ? res.data : [];
}
});
}
function closeDrawer() { function closeDrawer() {
visible.value = false; visible.value = false;
} }
@ -93,6 +134,7 @@ watch(visible, () => {
if (visible.value) { if (visible.value) {
handleInitModel(); handleInitModel();
restoreValidation(); restoreValidation();
handleInitChildrenModel();
} }
}); });
</script> </script>
@ -100,6 +142,7 @@ watch(visible, () => {
<template> <template>
<NDrawer v-model:show="visible" display-directive="show" :default-width="600" resizable> <NDrawer v-model:show="visible" display-directive="show" :default-width="600" resizable>
<NDrawerContent :title="title" :native-scrollbar="false" closable> <NDrawerContent :title="title" :native-scrollbar="false" closable>
<NScrollbar>
<NForm ref="formRef" :model="model" :rules="rules"> <NForm ref="formRef" :model="model" :rules="rules">
<NFormItem :label="$t('page.sys.core.dictionary.fields.name')" path="name"> <NFormItem :label="$t('page.sys.core.dictionary.fields.name')" path="name">
<NInput v-model:value="model.name" :placeholder="$t('page.sys.core.dictionary.fields.name')" /> <NInput v-model:value="model.name" :placeholder="$t('page.sys.core.dictionary.fields.name')" />
@ -125,6 +168,10 @@ watch(visible, () => {
/> />
</NFormItem> </NFormItem>
</NForm> </NForm>
<NCard v-if="props.operateType === 'edit'" :title="$t('page.sys.core.dictionary.item.title')">
<NDataTable :data="model.children" :columns="childrenColumns" :bordered="true" />
</NCard>
</NScrollbar>
<template #footer> <template #footer>
<NSpace :size="16"> <NSpace :size="16">
<NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton> <NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton>