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-antd/src/views/mall/product/spu/components/sku-list.vue b/apps/web-antd/src/views/mall/product/spu/components/sku-list.vue index a5f6f383a..383cda1cd 100644 --- a/apps/web-antd/src/views/mall/product/spu/components/sku-list.vue +++ b/apps/web-antd/src/views/mall/product/spu/components/sku-list.vue @@ -56,6 +56,7 @@ const tableHeaders = ref<{ label: string; prop: string }[]>([]); /** 创建空 SKU 数据 */ function createEmptySku(): MallSpuApi.Sku { return { + name: '', // SKU 名称,提交时会自动使用 SPU 名称 price: 0, marketPrice: 0, costPrice: 0, diff --git a/apps/web-antd/src/views/mall/product/spu/form/index.vue b/apps/web-antd/src/views/mall/product/spu/form/index.vue index 0d654b318..e8aa3ea3a 100644 --- a/apps/web-antd/src/views/mall/product/spu/form/index.vue +++ b/apps/web-antd/src/views/mall/product/spu/form/index.vue @@ -50,6 +50,7 @@ const formData = ref({ subCommissionType: false, skus: [ { + name: '', // SKU 名称,提交时会自动使用 SPU 名称 price: 0, marketPrice: 0, costPrice: 0, @@ -181,6 +182,11 @@ async function handleSubmit() { .merge(otherFormApi) .submitAllForm(true); values.skus = formData.value.skus; + // 校验商品名称不能为空(用于 SKU name) + if (!values.name || values.name.trim() === '') { + message.error('商品名称不能为空'); + return; + } if (values.skus) { try { // 校验 sku @@ -190,6 +196,8 @@ async function handleSubmit() { return; } values.skus.forEach((item) => { + // 给 sku name 赋值(使用商品名称作为 SKU 名称) + item.name = values.name; // 金额转换:元转分 item.price = convertToInteger(item.price); item.marketPrice = convertToInteger(item.marketPrice); @@ -277,6 +285,7 @@ function handleChangeSpec() { // 重置 sku 列表 formData.value.skus = [ { + name: '', // SKU 名称,提交时会自动使用 SPU 名称 price: 0, marketPrice: 0, costPrice: 0, 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', }); diff --git a/apps/web-ele/src/views/mall/product/spu/components/sku-list.vue b/apps/web-ele/src/views/mall/product/spu/components/sku-list.vue index 06dc595b9..bcf6eb617 100644 --- a/apps/web-ele/src/views/mall/product/spu/components/sku-list.vue +++ b/apps/web-ele/src/views/mall/product/spu/components/sku-list.vue @@ -62,6 +62,7 @@ const tableHeaders = ref<{ label: string; prop: string }[]>([]); /** 创建空 SKU 数据 */ function createEmptySku(): MallSpuApi.Sku { return { + name: '', // SKU 名称,提交时会自动使用 SPU 名称 price: 0, marketPrice: 0, costPrice: 0, diff --git a/apps/web-ele/src/views/mall/product/spu/form/index.vue b/apps/web-ele/src/views/mall/product/spu/form/index.vue index 5f8a53d66..b2d65e30e 100644 --- a/apps/web-ele/src/views/mall/product/spu/form/index.vue +++ b/apps/web-ele/src/views/mall/product/spu/form/index.vue @@ -50,6 +50,7 @@ const formData = ref({ subCommissionType: false, skus: [ { + name: '', // SKU 名称,提交时会自动使用 SPU 名称 price: 0, marketPrice: 0, costPrice: 0, @@ -168,8 +169,8 @@ const [OtherForm, otherFormApi] = useVbenForm({ }); /** tab 切换 */ -function handleTabChange(key: string) { - activeTabName.value = key; +function handleTabChange(key: number | string) { + activeTabName.value = key as string; } /** 提交表单 */ @@ -181,6 +182,11 @@ async function handleSubmit() { .merge(otherFormApi) .submitAllForm(true); values.skus = formData.value.skus; + // 校验商品名称不能为空(用于 SKU name) + if (!values.name || values.name.trim() === '') { + ElMessage.error('商品名称不能为空'); + return; + } if (values.skus) { try { // 校验 sku @@ -190,6 +196,8 @@ async function handleSubmit() { return; } values.skus.forEach((item) => { + // 给 sku name 赋值(使用商品名称作为 SKU 名称) + item.name = values.name; // 金额转换:元转分 item.price = convertToInteger(item.price); item.marketPrice = convertToInteger(item.marketPrice); @@ -277,6 +285,7 @@ function handleChangeSpec() { // 重置 sku 列表 formData.value.skus = [ { + name: '', // SKU 名称,提交时会自动使用 SPU 名称 price: 0, marketPrice: 0, costPrice: 0, @@ -320,7 +329,6 @@ onMounted(async () => {