From 1196dab9e4fef656c1703e52653b7081b82abee8 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Wed, 28 Jan 2026 17:23:39 +0800 Subject: [PATCH] =?UTF-8?q?feat(form-create):=20=E3=80=90antd/ele=E3=80=91?= =?UTF-8?q?=E8=A1=A8=E5=8D=95=E9=80=89=E6=8B=A9=E5=99=A8=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E9=80=89=E4=B8=AD=E5=BD=93=E5=89=8D=E7=94=A8?= =?UTF-8?q?=E6=88=B7/=E9=83=A8=E9=97=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - UserSelect 组件新增 defaultCurrentUser 配置,支持默认选中当前登录用户 - DeptSelect 组件重构为独立的树形选择器,支持 defaultCurrentDept 配置 - DeptSelect 支持 returnType 配置,可返回部门 ID 或部门名称 - 修复 useSelectRule 未将自定义 props 默认值传递给组件的问题 - 修复 DeptSelect 数据加载完成前回显失败的问题 - 同时支持 web-antd 和 web-ele 两个应用 --- .../form-create/components/dept-select.vue | 210 +++++++++++++++++ .../form-create/components/use-api-select.tsx | 39 +++- .../src/components/form-create/helpers.ts | 14 ++ .../form-create/rules/use-select-rule.ts | 13 +- .../web-antd/src/plugins/form-create/index.ts | 7 +- .../form-create/components/dept-select.vue | 218 ++++++++++++++++++ .../form-create/components/use-api-select.tsx | 39 +++- .../src/components/form-create/helpers.ts | 14 ++ .../form-create/rules/use-select-rule.ts | 13 +- apps/web-ele/src/plugins/form-create/index.ts | 7 +- 10 files changed, 558 insertions(+), 16 deletions(-) create mode 100644 apps/web-antd/src/components/form-create/components/dept-select.vue create mode 100644 apps/web-ele/src/components/form-create/components/dept-select.vue diff --git a/apps/web-antd/src/components/form-create/components/dept-select.vue b/apps/web-antd/src/components/form-create/components/dept-select.vue new file mode 100644 index 000000000..9f70ff0aa --- /dev/null +++ b/apps/web-antd/src/components/form-create/components/dept-select.vue @@ -0,0 +1,210 @@ + + + + diff --git a/apps/web-antd/src/components/form-create/components/use-api-select.tsx b/apps/web-antd/src/components/form-create/components/use-api-select.tsx index c63e2cd1e..dba12f326 100644 --- a/apps/web-antd/src/components/form-create/components/use-api-select.tsx +++ b/apps/web-antd/src/components/form-create/components/use-api-select.tsx @@ -2,6 +2,7 @@ import type { ApiSelectProps } from '#/components/form-create/typing'; import { defineComponent, onMounted, ref, useAttrs } from 'vue'; +import { useUserStore } from '@vben/stores'; import { isEmpty } from '@vben/utils'; import { @@ -74,12 +75,46 @@ export function useApiSelect(option: ApiSelectProps) { type: String, default: 'id', }, + // 是否默认选中当前用户(仅用于 UserSelect) + defaultCurrentUser: { + type: Boolean, + default: false, + }, }, - setup(props) { + setup(props, { emit }) { const attrs = useAttrs(); const options = ref([]); // 下拉数据 const loading = ref(false); // 是否正在从远程获取数据 const queryParam = ref(); // 当前输入的值 + + // 检查是否有有效的预设值 + function hasValidPresetValue(): boolean { + const value = attrs.modelValue; + if (value === undefined || value === null || value === '') { + return false; + } + if (Array.isArray(value)) { + return value.length > 0; + } + return true; + } + + // 设置默认当前用户 + function setDefaultCurrentUser(): void { + if (option.name !== 'UserSelect' || !props.defaultCurrentUser) { + return; + } + if (hasValidPresetValue()) { + return; + } + const userStore = useUserStore(); + const currentUserId = userStore.userInfo?.id; + if (currentUserId) { + const defaultValue = props.multiple ? [currentUserId] : currentUserId; + emit('update:modelValue', defaultValue); + } + } + const getOptions = async () => { options.value = []; // 接口选择器 @@ -199,6 +234,8 @@ export function useApiSelect(option: ApiSelectProps) { onMounted(async () => { await getOptions(); + // 设置默认当前用户(仅用于 UserSelect) + setDefaultCurrentUser(); }); const buildSelect = () => { diff --git a/apps/web-antd/src/components/form-create/helpers.ts b/apps/web-antd/src/components/form-create/helpers.ts index f43b1ce6d..f04638945 100644 --- a/apps/web-antd/src/components/form-create/helpers.ts +++ b/apps/web-antd/src/components/form-create/helpers.ts @@ -189,6 +189,14 @@ export async function useFormCreateDesigner(designer: Ref) { name: 'UserSelect', label: '用户选择器', icon: 'icon-eye', + props: [ + { + type: 'switch', + field: 'defaultCurrentUser', + title: '默认选中当前用户', + value: true, + }, + ], }); const deptSelectRule = useSelectRule({ name: 'DeptSelect', @@ -205,6 +213,12 @@ export async function useFormCreateDesigner(designer: Ref) { { label: '部门名称', value: 'name' }, ], }, + { + type: 'switch', + field: 'defaultCurrentDept', + title: '默认选中当前部门', + value: true, + }, ], }); const dictSelectRule = useDictSelectRule(); diff --git a/apps/web-antd/src/components/form-create/rules/use-select-rule.ts b/apps/web-antd/src/components/form-create/rules/use-select-rule.ts index 3efd8c9d5..fc89b9a24 100644 --- a/apps/web-antd/src/components/form-create/rules/use-select-rule.ts +++ b/apps/web-antd/src/components/form-create/rules/use-select-rule.ts @@ -23,13 +23,24 @@ export function useSelectRule(option: SelectRuleOption) { name, event: option.event, rule() { - return { + // 构建基础规则 + const baseRule: any = { type: name, field: buildUUID(), title: label, info: '', $required: false, }; + // 将自定义 props 的默认值添加到 rule 的 props 中 + if (option.props && option.props.length > 0) { + baseRule.props = {}; + option.props.forEach((prop: any) => { + if (prop.field && prop.value !== undefined) { + baseRule.props[prop.field] = prop.value; + } + }); + } + return baseRule; }, props(_: any, { t }: any) { if (!option.props) { diff --git a/apps/web-antd/src/plugins/form-create/index.ts b/apps/web-antd/src/plugins/form-create/index.ts index db60c0f51..024aae834 100644 --- a/apps/web-antd/src/plugins/form-create/index.ts +++ b/apps/web-antd/src/plugins/form-create/index.ts @@ -34,6 +34,7 @@ import { // ======================= 自定义组件 ======================= import { useApiSelect } from '#/components/form-create'; +import DeptSelect from '#/components/form-create/components/dept-select.vue'; import DictSelect from '#/components/form-create/components/dict-select.vue'; import { useImagesUpload } from '#/components/form-create/components/use-images-upload'; import { Tinymce } from '#/components/tinymce'; @@ -45,12 +46,6 @@ const UserSelect = useApiSelect({ valueField: 'id', url: '/system/user/simple-list', }); -const DeptSelect = useApiSelect({ - name: 'DeptSelect', - labelField: 'name', - valueField: 'id', - url: '/system/dept/simple-list', -}); const ApiSelect = useApiSelect({ name: 'ApiSelect', }); diff --git a/apps/web-ele/src/components/form-create/components/dept-select.vue b/apps/web-ele/src/components/form-create/components/dept-select.vue new file mode 100644 index 000000000..ffe3a7c75 --- /dev/null +++ b/apps/web-ele/src/components/form-create/components/dept-select.vue @@ -0,0 +1,218 @@ + + + + diff --git a/apps/web-ele/src/components/form-create/components/use-api-select.tsx b/apps/web-ele/src/components/form-create/components/use-api-select.tsx index 3041e796a..accd8190b 100644 --- a/apps/web-ele/src/components/form-create/components/use-api-select.tsx +++ b/apps/web-ele/src/components/form-create/components/use-api-select.tsx @@ -2,6 +2,7 @@ import type { ApiSelectProps } from '#/components/form-create/typing'; import { defineComponent, onMounted, ref, useAttrs } from 'vue'; +import { useUserStore } from '@vben/stores'; import { isEmpty } from '@vben/utils'; import { @@ -74,12 +75,46 @@ export function useApiSelect(option: ApiSelectProps) { type: String, default: 'id', }, + // 是否默认选中当前用户(仅用于 UserSelect) + defaultCurrentUser: { + type: Boolean, + default: false, + }, }, - setup(props) { + setup(props, { emit }) { const attrs = useAttrs(); const options = ref([]); // 下拉数据 const loading = ref(false); // 是否正在从远程获取数据 const queryParam = ref(); // 当前输入的值 + + // 检查是否有有效的预设值 + function hasValidPresetValue(): boolean { + const value = attrs.modelValue; + if (value === undefined || value === null || value === '') { + return false; + } + if (Array.isArray(value)) { + return value.length > 0; + } + return true; + } + + // 设置默认当前用户 + function setDefaultCurrentUser(): void { + if (option.name !== 'UserSelect' || !props.defaultCurrentUser) { + return; + } + if (hasValidPresetValue()) { + return; + } + const userStore = useUserStore(); + const currentUserId = userStore.userInfo?.id; + if (currentUserId) { + const defaultValue = props.multiple ? [currentUserId] : currentUserId; + emit('update:modelValue', defaultValue); + } + } + const getOptions = async () => { options.value = []; // 接口选择器 @@ -199,6 +234,8 @@ export function useApiSelect(option: ApiSelectProps) { onMounted(async () => { await getOptions(); + // 设置默认当前用户(仅用于 UserSelect) + setDefaultCurrentUser(); }); const buildSelect = () => { diff --git a/apps/web-ele/src/components/form-create/helpers.ts b/apps/web-ele/src/components/form-create/helpers.ts index a5b123225..dbe938a5e 100644 --- a/apps/web-ele/src/components/form-create/helpers.ts +++ b/apps/web-ele/src/components/form-create/helpers.ts @@ -189,6 +189,14 @@ export async function useFormCreateDesigner(designer: Ref) { name: 'UserSelect', label: '用户选择器', icon: 'icon-eye', + props: [ + { + type: 'switch', + field: 'defaultCurrentUser', + title: '默认选中当前用户', + value: true, + }, + ], }); const deptSelectRule = useSelectRule({ name: 'DeptSelect', @@ -205,6 +213,12 @@ export async function useFormCreateDesigner(designer: Ref) { { label: '部门名称', value: 'name' }, ], }, + { + type: 'switch', + field: 'defaultCurrentDept', + title: '默认选中当前部门', + value: true, + }, ], }); const dictSelectRule = useDictSelectRule(); diff --git a/apps/web-ele/src/components/form-create/rules/use-select-rule.ts b/apps/web-ele/src/components/form-create/rules/use-select-rule.ts index 3efd8c9d5..fc89b9a24 100644 --- a/apps/web-ele/src/components/form-create/rules/use-select-rule.ts +++ b/apps/web-ele/src/components/form-create/rules/use-select-rule.ts @@ -23,13 +23,24 @@ export function useSelectRule(option: SelectRuleOption) { name, event: option.event, rule() { - return { + // 构建基础规则 + const baseRule: any = { type: name, field: buildUUID(), title: label, info: '', $required: false, }; + // 将自定义 props 的默认值添加到 rule 的 props 中 + if (option.props && option.props.length > 0) { + baseRule.props = {}; + option.props.forEach((prop: any) => { + if (prop.field && prop.value !== undefined) { + baseRule.props[prop.field] = prop.value; + } + }); + } + return baseRule; }, props(_: any, { t }: any) { if (!option.props) { diff --git a/apps/web-ele/src/plugins/form-create/index.ts b/apps/web-ele/src/plugins/form-create/index.ts index f4578b4f2..785c901de 100644 --- a/apps/web-ele/src/plugins/form-create/index.ts +++ b/apps/web-ele/src/plugins/form-create/index.ts @@ -34,6 +34,7 @@ import { // ======================= 自定义组件 ======================= import { useApiSelect } from '#/components/form-create'; +import DeptSelect from '#/components/form-create/components/dept-select.vue'; import DictSelect from '#/components/form-create/components/dict-select.vue'; import { useImagesUpload } from '#/components/form-create/components/use-images-upload'; import { Tinymce } from '#/components/tinymce'; @@ -45,12 +46,6 @@ const UserSelect = useApiSelect({ valueField: 'id', url: '/system/user/simple-list', }); -const DeptSelect = useApiSelect({ - name: 'DeptSelect', - labelField: 'name', - valueField: 'id', - url: '/system/dept/simple-list', -}); const ApiSelect = useApiSelect({ name: 'ApiSelect', });