feat: 字典
This commit is contained in:
parent
454ca3d2e6
commit
3e750a0943
@ -1 +1,2 @@
|
|||||||
|
export { tagSelectOptions, tagTypes } from './src/data';
|
||||||
export { default as DictTag } from './src/index.vue';
|
export { default as DictTag } from './src/index.vue';
|
||||||
|
71
apps/web-antd/src/views/system/dict/data/data.ts
Normal file
71
apps/web-antd/src/views/system/dict/data/data.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import type { FormSchemaGetter } from '#/adapter';
|
||||||
|
|
||||||
|
export const drawerSchema: FormSchemaGetter = () => [
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
dependencies: {
|
||||||
|
show: () => false,
|
||||||
|
triggerFields: [''],
|
||||||
|
},
|
||||||
|
fieldName: 'dictCode',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
fieldName: 'dictType',
|
||||||
|
label: '字典类型',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'listClass',
|
||||||
|
label: '标签样式',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入',
|
||||||
|
},
|
||||||
|
fieldName: 'dictLabel',
|
||||||
|
label: '数据标签',
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入',
|
||||||
|
},
|
||||||
|
fieldName: 'dictValue',
|
||||||
|
label: '数据键值',
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Textarea',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '可使用tailwind类名 如bg-blue w-full h-full等',
|
||||||
|
},
|
||||||
|
fieldName: 'cssClass',
|
||||||
|
formItemClass: 'items-baseline',
|
||||||
|
help: '标签的css样式, 可添加已经编译的css类名',
|
||||||
|
label: 'css类名',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'InputNumber',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入',
|
||||||
|
},
|
||||||
|
fieldName: 'dictSort',
|
||||||
|
label: '显示排序',
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Textarea',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入',
|
||||||
|
},
|
||||||
|
fieldName: 'remark',
|
||||||
|
formItemClass: 'items-baseline',
|
||||||
|
label: '备注',
|
||||||
|
},
|
||||||
|
];
|
125
apps/web-antd/src/views/system/dict/data/dict-data-drawer.vue
Normal file
125
apps/web-antd/src/views/system/dict/data/dict-data-drawer.vue
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from 'vue';
|
||||||
|
|
||||||
|
import { useVbenDrawer } from '@vben/common-ui';
|
||||||
|
import { $t } from '@vben/locales';
|
||||||
|
|
||||||
|
import { useVbenForm } from '#/adapter';
|
||||||
|
import { clientAdd, clientUpdate } from '#/api/system/client';
|
||||||
|
import { dictDetailInfo } from '#/api/system/dict/dict-data';
|
||||||
|
import { tagTypes } from '#/components/dict';
|
||||||
|
|
||||||
|
import { drawerSchema } from './data';
|
||||||
|
import TagStylePicker from './tag-style-picker.vue';
|
||||||
|
|
||||||
|
const emit = defineEmits<{ reload: [] }>();
|
||||||
|
|
||||||
|
interface DrawerProps {
|
||||||
|
dictCode?: number | string;
|
||||||
|
dictType: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isUpdate = ref(false);
|
||||||
|
const title = computed(() => {
|
||||||
|
return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add');
|
||||||
|
});
|
||||||
|
|
||||||
|
const [BasicForm, formApi] = useVbenForm({
|
||||||
|
commonConfig: {
|
||||||
|
componentProps: {
|
||||||
|
class: 'w-full',
|
||||||
|
},
|
||||||
|
formItemClass: 'col-span-2',
|
||||||
|
labelWidth: 80,
|
||||||
|
},
|
||||||
|
schema: drawerSchema(),
|
||||||
|
showDefaultActions: false,
|
||||||
|
wrapperClass: 'grid-cols-2',
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标签样式选择器
|
||||||
|
* default: 预设标签样式
|
||||||
|
* custom: 自定义标签样式
|
||||||
|
*/
|
||||||
|
const selectType = ref('default');
|
||||||
|
/**
|
||||||
|
* 根据标签样式判断是自定义还是默认
|
||||||
|
* @param listClass 标签样式
|
||||||
|
*/
|
||||||
|
function setupSelectType(listClass: string) {
|
||||||
|
// 判断是自定义还是预设
|
||||||
|
const isDefault = Reflect.has(tagTypes, listClass);
|
||||||
|
selectType.value = isDefault ? 'default' : 'custom';
|
||||||
|
}
|
||||||
|
|
||||||
|
const [BasicDrawer, drawerApi] = useVbenDrawer({
|
||||||
|
onCancel: handleCancel,
|
||||||
|
onConfirm: handleConfirm,
|
||||||
|
async onOpenChange(isOpen) {
|
||||||
|
if (!isOpen) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
drawerApi.drawerLoading(true);
|
||||||
|
|
||||||
|
const { dictCode, dictType } = drawerApi.getData() as DrawerProps;
|
||||||
|
isUpdate.value = !!dictCode;
|
||||||
|
formApi.setFieldValue('dictType', dictType);
|
||||||
|
|
||||||
|
if (dictCode && isUpdate.value) {
|
||||||
|
const record = await dictDetailInfo(dictCode);
|
||||||
|
setupSelectType(record.listClass);
|
||||||
|
for (const key in record) {
|
||||||
|
await formApi.setFieldValue(key, record[key as keyof typeof record]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drawerApi.drawerLoading(false);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
async function handleConfirm() {
|
||||||
|
try {
|
||||||
|
drawerApi.drawerLoading(true);
|
||||||
|
const { valid } = await formApi.validate();
|
||||||
|
if (!valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const data = await formApi.getValues();
|
||||||
|
await (isUpdate.value ? clientUpdate(data) : clientAdd(data));
|
||||||
|
emit('reload');
|
||||||
|
await handleCancel();
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
} finally {
|
||||||
|
drawerApi.drawerLoading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleCancel() {
|
||||||
|
drawerApi.close();
|
||||||
|
await formApi.resetForm();
|
||||||
|
selectType.value = 'default';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消标签选中 必须设置为undefined才行
|
||||||
|
*/
|
||||||
|
async function handleDeSelect() {
|
||||||
|
await formApi.setFieldValue('listClass', undefined);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<BasicDrawer :close-on-click-modal="false" :title="title" class="w-[600px]">
|
||||||
|
<BasicForm>
|
||||||
|
<template #listClass="slotProps">
|
||||||
|
<TagStylePicker
|
||||||
|
v-bind="slotProps"
|
||||||
|
v-model:select-type="selectType"
|
||||||
|
@deselect="handleDeSelect"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</BasicForm>
|
||||||
|
</BasicDrawer>
|
||||||
|
</template>
|
@ -1,5 +1,24 @@
|
|||||||
<script setup lang="ts"></script>
|
<script setup lang="ts">
|
||||||
|
import { useVbenDrawer } from '@vben/common-ui';
|
||||||
|
import { $t } from '@vben/locales';
|
||||||
|
|
||||||
|
import dictDataDrawer from './dict-data-drawer.vue';
|
||||||
|
|
||||||
|
const [DictDataDrawer, drawerApi] = useVbenDrawer({
|
||||||
|
connectedComponent: dictDataDrawer,
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleAdd() {
|
||||||
|
drawerApi.setData({ dictType: 'aa_bb_cc' });
|
||||||
|
drawerApi.open();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div></div>
|
<div>
|
||||||
|
<a-button type="primary" @click="handleAdd">
|
||||||
|
{{ $t('pages.common.add') }}
|
||||||
|
</a-button>
|
||||||
|
<DictDataDrawer />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -0,0 +1,75 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, type PropType } from 'vue';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Input,
|
||||||
|
type RadioChangeEvent,
|
||||||
|
RadioGroup,
|
||||||
|
Select,
|
||||||
|
} from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { tagSelectOptions } from '#/components/dict';
|
||||||
|
|
||||||
|
defineEmits<{ deselect: [] }>();
|
||||||
|
|
||||||
|
const options = [
|
||||||
|
{ label: '默认颜色', value: 'default' },
|
||||||
|
{ label: '自定义颜色', value: 'custom' },
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主要是加了const报错
|
||||||
|
*/
|
||||||
|
const computedOptions = computed(
|
||||||
|
() => options as unknown as { label: string; value: string }[],
|
||||||
|
);
|
||||||
|
|
||||||
|
type SelectType = (typeof options)[number]['value'];
|
||||||
|
|
||||||
|
const selectType = defineModel('selectType', {
|
||||||
|
default: 'default',
|
||||||
|
type: String as PropType<SelectType>,
|
||||||
|
});
|
||||||
|
|
||||||
|
const color = defineModel('value', {
|
||||||
|
default: '',
|
||||||
|
type: String,
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleSelectTypeChange(e: RadioChangeEvent) {
|
||||||
|
// 必须给默认hex颜色 不能为空字符串
|
||||||
|
if (e.target.value === 'custom') {
|
||||||
|
color.value = '#FFFFFF';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex items-center gap-[6px]">
|
||||||
|
<RadioGroup
|
||||||
|
v-model:value="selectType"
|
||||||
|
:options="computedOptions"
|
||||||
|
button-style="solid"
|
||||||
|
option-type="button"
|
||||||
|
@change="handleSelectTypeChange"
|
||||||
|
/>
|
||||||
|
<Select
|
||||||
|
v-if="selectType === 'default'"
|
||||||
|
:allow-clear="true"
|
||||||
|
:options="tagSelectOptions()"
|
||||||
|
class="flex-1"
|
||||||
|
placeholder="请选择标签样式"
|
||||||
|
@deselect="$emit('deselect')"
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
v-if="selectType === 'custom'"
|
||||||
|
v-model:value="color"
|
||||||
|
class="flex-1"
|
||||||
|
disabled
|
||||||
|
>
|
||||||
|
<template #addonAfter>
|
||||||
|
<input v-model="color" class="rounded-lg" type="color" />
|
||||||
|
</template>
|
||||||
|
</Input>
|
||||||
|
</div>
|
||||||
|
</template>
|
@ -3,6 +3,7 @@ import { Page } from '@vben/common-ui';
|
|||||||
|
|
||||||
import { Card } from 'ant-design-vue';
|
import { Card } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import DictDataPanel from './data/index.vue';
|
||||||
import DictTypePanel from './type/index.vue';
|
import DictTypePanel from './type/index.vue';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -11,6 +12,8 @@ import DictTypePanel from './type/index.vue';
|
|||||||
<Card class="w-full">
|
<Card class="w-full">
|
||||||
<DictTypePanel />
|
<DictTypePanel />
|
||||||
</Card>
|
</Card>
|
||||||
<Card class="w-full">b</Card>
|
<Card class="w-full">
|
||||||
|
<DictDataPanel />
|
||||||
|
</Card>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
Loading…
Reference in New Issue
Block a user