diff --git a/apps/web-antdv-next/src/adapter/component/date-picker.ts b/apps/web-antdv-next/src/adapter/component/date-picker.ts new file mode 100644 index 000000000..2428cd4fb --- /dev/null +++ b/apps/web-antdv-next/src/adapter/component/date-picker.ts @@ -0,0 +1,86 @@ +import type { Component } from 'vue'; + +import type { Recordable } from '@vben/types'; + +import { defineAsyncComponent, defineComponent, h, ref } from 'vue'; + +const RawDatePicker = defineAsyncComponent( + () => import('antdv-next/dist/date-picker/index'), +); +const RawRangePicker = defineAsyncComponent(() => + import('antdv-next/dist/date-picker/index').then( + (res) => res.DateRangePicker, + ), +); + +const TIMESTAMP_VALUE_FORMATS = new Set(['x', 'X']); + +function isTimestampValueFormat(valueFormat: unknown) { + return ( + typeof valueFormat === 'string' && TIMESTAMP_VALUE_FORMATS.has(valueFormat) + ); +} + +function normalizeTimestampPickerValue(value: any, valueFormat: unknown): any { + if (!isTimestampValueFormat(valueFormat)) { + return value; + } + if (Array.isArray(value)) { + return value.map((item) => normalizeTimestampPickerValue(item, valueFormat)); + } + return typeof value === 'number' ? String(value) : value; +} + +function withTimestampValueFormat( + component: Component, + name: 'DatePicker' | 'RangePicker', +) { + return defineComponent({ + name, + inheritAttrs: false, + setup(_, { attrs, expose, slots }) { + const innerRef = ref(); + expose( + new Proxy( + {}, + { + get: (_target, key) => innerRef.value?.[key], + has: (_target, key) => key in (innerRef.value || {}), + }, + ), + ); + + return () => { + const pickerAttrs: Recordable = { ...attrs }; + if ( + 'value-format' in pickerAttrs && + !Reflect.has(pickerAttrs, 'valueFormat') + ) { + pickerAttrs.valueFormat = pickerAttrs['value-format']; + } + const valueFormat = pickerAttrs.valueFormat; + + for (const key of [ + 'value', + 'defaultValue', + 'pickerValue', + 'defaultPickerValue', + ]) { + if (Reflect.has(pickerAttrs, key)) { + pickerAttrs[key] = normalizeTimestampPickerValue( + pickerAttrs[key], + valueFormat, + ); + } + } + + return h(component, { ...pickerAttrs, ref: innerRef }, slots); + }; + }, + }); +} + +const DatePicker = withTimestampValueFormat(RawDatePicker, 'DatePicker'); +const RangePicker = withTimestampValueFormat(RawRangePicker, 'RangePicker'); + +export { DatePicker, RangePicker }; diff --git a/apps/web-antdv-next/src/adapter/component/index.ts b/apps/web-antdv-next/src/adapter/component/index.ts index 9a0897d5b..846473793 100644 --- a/apps/web-antdv-next/src/adapter/component/index.ts +++ b/apps/web-antdv-next/src/adapter/component/index.ts @@ -75,6 +75,9 @@ import { message, Modal, notification } from 'antdv-next'; import { uploadFile as uploadFileApi } from '#/api/infra/file'; import { Tinymce as RichTextarea } from '#/components/tinymce'; import { FileUpload, ImageUpload } from '#/components/upload'; + +import { DatePicker, RangePicker } from './date-picker'; + type AdapterUploadProps = UploadProps & { aspectRatio?: string; crop?: boolean; @@ -97,9 +100,6 @@ const Checkbox = defineAsyncComponent( const CheckboxGroup = defineAsyncComponent(() => import('antdv-next/dist/checkbox/index').then((res) => res.CheckboxGroup), ); -const DatePicker = defineAsyncComponent( - () => import('antdv-next/dist/date-picker/index'), -); const Divider = defineAsyncComponent( () => import('antdv-next/dist/divider/index'), ); @@ -117,11 +117,6 @@ const Radio = defineAsyncComponent(() => import('antdv-next/dist/radio/index')); const RadioGroup = defineAsyncComponent(() => import('antdv-next/dist/radio/index').then((res) => res.RadioGroup), ); -const RangePicker = defineAsyncComponent(() => - import('antdv-next/dist/date-picker/index').then( - (res) => res.DateRangePicker, - ), -); const Rate = defineAsyncComponent(() => import('antdv-next/dist/rate/index')); const Select = defineAsyncComponent( () => import('antdv-next/dist/select/index'), @@ -794,4 +789,4 @@ async function initComponentAdapter() { }); } -export { initComponentAdapter }; +export { DatePicker, initComponentAdapter, RangePicker }; diff --git a/apps/web-antdv-next/src/api/bpm/processInstance/index.ts b/apps/web-antdv-next/src/api/bpm/processInstance/index.ts index 7ee5421f8..f8442c35c 100644 --- a/apps/web-antdv-next/src/api/bpm/processInstance/index.ts +++ b/apps/web-antdv-next/src/api/bpm/processInstance/index.ts @@ -83,6 +83,7 @@ export namespace BpmProcessInstanceApi { reason: string; signPicUrl: string; status: number; + attachments?: string[]; } /** 抄送流程实例 */ diff --git a/apps/web-antdv-next/src/api/iot/thingmodel/index.ts b/apps/web-antdv-next/src/api/iot/thingmodel/index.ts index 002ccd9c2..888e64663 100644 --- a/apps/web-antdv-next/src/api/iot/thingmodel/index.ts +++ b/apps/web-antdv-next/src/api/iot/thingmodel/index.ts @@ -1,4 +1,4 @@ -import type { Rule } from 'antdv-next/es/form'; +import type { FormItemProps } from 'antdv-next'; import type { PageParam, PageResult } from '@vben/request'; @@ -6,6 +6,8 @@ import { isEmpty } from '@vben/utils'; import { requestClient } from '#/api/request'; +type FormItemRule = NonNullable[number]; + export namespace ThingModelApi { /** IoT 物模型数据 */ export interface ThingModel { @@ -95,46 +97,42 @@ export namespace ThingModelApi { /** 生成「必填 + 数字」类校验器:拼到 size / length / 枚举值上 */ function buildRequiredNumberValidator(label: string) { - return (_rule: any, value: any, callback: any) => { + return (_rule: any, value: any) => { if (isEmpty(value)) { - callback(new Error(`${label}不能为空`)); - return; + return Promise.reject(new Error(`${label}不能为空`)); } if (Number.isNaN(Number(value))) { - callback(new Error(`${label}必须是数字`)); - return; + return Promise.reject(new Error(`${label}必须是数字`)); } - callback(); + return Promise.resolve(); }; } /** 生成「标识符样式」名称校验器:开头需为中文 / 英文 / 数字,整体仅允许中文、英文、数字、下划线、短划线,长度 ≤ 20 */ export function buildIdentifierLikeNameValidator(label: string) { - return (_rule: any, value: string, callback: any) => { + return (_rule: any, value: string) => { if (isEmpty(value)) { - callback(new Error(`${label}不能为空`)); - return; + return Promise.reject(new Error(`${label}不能为空`)); } if (!/^[一-龥A-Za-z0-9]/.test(value)) { - callback(new Error(`${label}必须以中文、英文字母或数字开头`)); - return; + return Promise.reject( + new Error(`${label}必须以中文、英文字母或数字开头`), + ); } if (!/^[一-龥A-Za-z0-9][\w一-龥-]*$/.test(value)) { - callback( + return Promise.reject( new Error(`${label}只能包含中文、英文字母、数字、下划线和短划线`), ); - return; } if (value.length > 20) { - callback(new Error(`${label}长度不能超过 20 个字符`)); - return; + return Promise.reject(new Error(`${label}长度不能超过 20 个字符`)); } - callback(); + return Promise.resolve(); }; } /** IoT 物模型表单校验规则 */ -export const ThingModelFormRules: Record = { +export const ThingModelFormRules: Record = { name: [ { required: true, message: '功能名称不能为空', trigger: 'blur' }, { @@ -153,7 +151,7 @@ export const ThingModelFormRules: Record = { trigger: 'blur', }, { - validator: (_rule: any, value: string, callback: any) => { + validator: (_rule: any, value: string) => { const reservedKeywords = [ 'set', 'get', @@ -164,18 +162,16 @@ export const ThingModelFormRules: Record = { 'value', ]; if (reservedKeywords.includes(value)) { - callback( + return Promise.reject( new Error( 'set, get, post, property, event, time, value 是系统保留字段,不能用于标识符定义', ), ); - return; } if (/^\d+$/.test(value)) { - callback(new Error('标识符不能是纯数字')); - return; + return Promise.reject(new Error('标识符不能是纯数字')); } - callback(); + return Promise.resolve(); }, trigger: 'blur', }, diff --git a/apps/web-antdv-next/src/components/cron-tab/cron-tab.vue b/apps/web-antdv-next/src/components/cron-tab/cron-tab.vue index d1b123585..ab9366e30 100644 --- a/apps/web-antdv-next/src/components/cron-tab/cron-tab.vue +++ b/apps/web-antdv-next/src/components/cron-tab/cron-tab.vue @@ -8,6 +8,7 @@ import { computed, onMounted, reactive, ref, watch } from 'vue'; import { Button, Form, + FormItem, Input, InputNumber, message, @@ -417,22 +418,21 @@ function inputChange() { @input="inputChange" > @@ -496,14 +496,10 @@ function inputChange() { v-model:value="cronValue.second.appoint" mode="multiple" style="width: 100%" - > - - + :options=" + data.second.map((item) => ({ label: item, value: item })) + " + /> @@ -560,14 +556,10 @@ function inputChange() { v-model:value="cronValue.minute.appoint" mode="multiple" style="width: 100%" - > - - + :options=" + data.minute.map((item) => ({ label: item, value: item })) + " + /> @@ -624,14 +616,10 @@ function inputChange() { v-model:value="cronValue.hour.appoint" mode="multiple" style="width: 100%" - > - - + :options=" + data.hour.map((item) => ({ label: item, value: item })) + " + /> @@ -690,14 +678,10 @@ function inputChange() { v-model:value="cronValue.day.appoint" mode="multiple" style="width: 100%" - > - - + :options=" + data.day.map((item) => ({ label: item, value: item })) + " + /> @@ -754,14 +738,10 @@ function inputChange() { v-model:value="cronValue.month.appoint" mode="multiple" style="width: 100%" - > - - + :options=" + data.month.map((item) => ({ label: item, value: item })) + " + /> @@ -785,23 +765,15 @@ function inputChange() { - + - - + - - + + :options="data.week" + /> - + + :options=" + data.year.map((item) => ({ label: item, value: item })) + " + /> diff --git a/apps/web-antdv-next/src/components/description/description.vue b/apps/web-antdv-next/src/components/description/description.vue index 09f5c2697..116741755 100644 --- a/apps/web-antdv-next/src/components/description/description.vue +++ b/apps/web-antdv-next/src/components/description/description.vue @@ -9,7 +9,7 @@ import { computed, defineComponent, ref, unref, useAttrs } from 'vue'; import { get, getNestedValue, isFunction } from '@vben/utils'; -import { Card, Descriptions } from 'antdv-next'; +import { Card, Descriptions, DescriptionsItem } from 'antdv-next'; const props = { bordered: { default: true, type: Boolean }, diff --git a/apps/web-antdv-next/src/components/form-create/components/dict-select.vue b/apps/web-antdv-next/src/components/form-create/components/dict-select.vue index 11b961c5f..04a62f109 100644 --- a/apps/web-antdv-next/src/components/form-create/components/dict-select.vue +++ b/apps/web-antdv-next/src/components/form-create/components/dict-select.vue @@ -6,14 +6,7 @@ import { computed, useAttrs } from 'vue'; import { getDictOptions } from '@vben/hooks'; -import { - Checkbox, - CheckboxGroup, - Radio, - RadioGroup, - Select, - SelectOption, -} from 'antdv-next'; +import { Checkbox, CheckboxGroup, Radio, RadioGroup, Select } from 'antdv-next'; defineOptions({ name: 'DictSelect' }); @@ -41,18 +34,22 @@ const getDictOption = computed(() => { } } }); + +const selectOptions = computed(() => + getDictOption.value.map((dict) => ({ + label: dict.label, + value: dict.value as any, + })), +); diff --git a/apps/web-antdv-next/src/views/iot/thingmodel/modules/data-specs/struct.vue b/apps/web-antdv-next/src/views/iot/thingmodel/modules/data-specs/struct.vue index 280a3a105..c62a42856 100644 --- a/apps/web-antdv-next/src/views/iot/thingmodel/modules/data-specs/struct.vue +++ b/apps/web-antdv-next/src/views/iot/thingmodel/modules/data-specs/struct.vue @@ -33,12 +33,11 @@ const structFormRef = ref(); const formData = ref(buildEmptyFormData()); /** 校验结构体属性对象非空 */ -function validateStructSpecsList(_rule: any, _value: any, callback: any) { +function validateStructSpecsList(_rule: any, _value: any) { if (isEmpty(dataSpecsList.value)) { - callback(new Error('请至少添加一个结构体属性对象')); - return; + return Promise.reject(new Error('请至少添加一个结构体属性对象')); } - callback(); + return Promise.resolve(); } const [Modal, modalApi] = useVbenModal({ diff --git a/apps/web-antdv-next/src/views/iot/thingmodel/modules/property.vue b/apps/web-antdv-next/src/views/iot/thingmodel/modules/property.vue index d9a50b3af..18743ae1a 100644 --- a/apps/web-antdv-next/src/views/iot/thingmodel/modules/property.vue +++ b/apps/web-antdv-next/src/views/iot/thingmodel/modules/property.vue @@ -14,14 +14,7 @@ import { import { isEmpty } from '@vben/utils'; import { useVModel } from '@vueuse/core'; -import { - FormItem, - Input, - Radio, - RadioGroup, - Select, - SelectOption, -} from 'antdv-next'; +import { FormItem, Input, Radio, RadioGroup, Select } from 'antdv-next'; import { ThingModelFormRules, validateBoolName } from '#/api/iot/thingmodel'; @@ -118,16 +111,13 @@ if (!props.isStructDataSpecs && !props.isParams) { v-model:value="property.dataType" placeholder="请选择数据类型" @change="handleChange" - > - - - {{ `${option.value}(${option.label})` }} - - + :options="[ + ...dataTypeOptions.map((option) => ({ + label: `{{ \`${option.value}(${option.label})\` }}`, + value: option.value, + })), + ]" + /> - - {{ item2.name }} - - + :options="attributeOptions" + :field-names="{ label: 'name', value: 'name' }" + /> (); const emit = defineEmits(['update:modelValue']); const formData = useVModel(props, 'modelValue', emit); +const themeOptions = THEME_LIST.map((theme) => ({ + label: theme.name, + value: theme.id, + raw: theme, +})); // 将数据库的值更新到右侧属性栏 component.property.items = formData.value.items; @@ -51,18 +55,20 @@ const handleThemeChange = () => { :wrapper-col="{ span: 18 }" > - + diff --git a/apps/web-antdv-next/src/views/mall/promotion/diy/template/decorate/index.vue b/apps/web-antdv-next/src/views/mall/promotion/diy/template/decorate/index.vue index ed11fefc4..bdf984307 100644 --- a/apps/web-antdv-next/src/views/mall/promotion/diy/template/decorate/index.vue +++ b/apps/web-antdv-next/src/views/mall/promotion/diy/template/decorate/index.vue @@ -11,7 +11,7 @@ import { IconifyIcon } from '@vben/icons'; import { useAccessStore } from '@vben/stores'; import { isEmpty } from '@vben/utils'; -import { message, RadioGroup } from 'antdv-next'; +import { message, RadioButton, RadioGroup } from 'antdv-next'; import { updateDiyPageProperty } from '#/api/mall/promotion/diy/page'; import { diff --git a/apps/web-antdv-next/src/views/mes/md/item/type/components/tree.vue b/apps/web-antdv-next/src/views/mes/md/item/type/components/tree.vue index 347e87b6a..acb3ad22b 100644 --- a/apps/web-antdv-next/src/views/mes/md/item/type/components/tree.vue +++ b/apps/web-antdv-next/src/views/mes/md/item/type/components/tree.vue @@ -54,8 +54,17 @@ function handleSearch(value: string) { } /** 处理节点点击:支持点击同一节点取消选中 */ -function handleSelect(_selectedKeys: any[], info: any) { - const row = info.node.dataRef as MesMdItemTypeApi.ItemType; +function handleSelect(selectedNodeKeys: any[], info: any) { + const selectedKey = selectedNodeKeys[0] ?? info.node?.id ?? info.node?.key; + const row = itemTypeList.value.find( + (item) => String(item.id) === String(selectedKey), + ); + if (!row) { + currentNodeId.value = undefined; + selectedKeys.value = []; + emit('nodeClick', undefined); + return; + } if (currentNodeId.value === row.id) { currentNodeId.value = undefined; selectedKeys.value = []; diff --git a/apps/web-antdv-next/src/views/mes/md/unitmeasure/components/select.vue b/apps/web-antdv-next/src/views/mes/md/unitmeasure/components/select.vue index 1abc361f3..4cd0dd28b 100644 --- a/apps/web-antdv-next/src/views/mes/md/unitmeasure/components/select.vue +++ b/apps/web-antdv-next/src/views/mes/md/unitmeasure/components/select.vue @@ -3,7 +3,7 @@ import type { MesMdUnitMeasureApi } from '#/api/mes/md/unitmeasure'; import { computed, onMounted, ref, watch } from 'vue'; -import { Select, SelectOption, Tag, Tooltip } from 'antdv-next'; +import { Select, Tag, Tooltip } from 'antdv-next'; import { getUnitMeasureSimpleList } from '#/api/mes/md/unitmeasure'; @@ -32,6 +32,13 @@ const emit = defineEmits<{ const allList = ref([]); // 计量单位列表 const filteredList = ref([]); // 过滤后的计量单位列表 const selectedItem = ref(); // 当前选中计量单位 +const selectOptions = computed(() => + filteredList.value.map((item) => ({ + label: item.name, + value: item.id, + raw: item, + })), +); const selectValue = computed({ // 选择器绑定值 @@ -44,7 +51,7 @@ const selectValue = computed({ /** 前端按名称和编码过滤计量单位 */ function handleFilter(input: string, option: any) { const keyword = input.toLowerCase(); - const item = option?.item as MesMdUnitMeasureApi.UnitMeasure | undefined; + const item = option?.raw as MesMdUnitMeasureApi.UnitMeasure | undefined; return Boolean( item?.name?.toLowerCase().includes(keyword) || item?.code?.toLowerCase().includes(keyword), @@ -104,19 +111,17 @@ onMounted(async () => { :placeholder="placeholder" class="w-full" show-search + :options="selectOptions" @change="handleChange" > - + diff --git a/apps/web-antdv-next/src/views/mes/md/workstation/components/workshop-select.vue b/apps/web-antdv-next/src/views/mes/md/workstation/components/workshop-select.vue index 18d044f09..9e82e0119 100644 --- a/apps/web-antdv-next/src/views/mes/md/workstation/components/workshop-select.vue +++ b/apps/web-antdv-next/src/views/mes/md/workstation/components/workshop-select.vue @@ -3,7 +3,7 @@ import type { MesMdWorkshopApi } from '#/api/mes/md/workstation/workshop'; import { computed, onMounted, ref, watch } from 'vue'; -import { Select, SelectOption, Tag, Tooltip } from 'antdv-next'; +import { Select, Tag, Tooltip } from 'antdv-next'; import { getWorkshopSimpleList } from '#/api/mes/md/workstation/workshop'; @@ -31,6 +31,13 @@ const emit = defineEmits<{ const allList = ref([]); const selectedItem = ref(); +const selectOptions = computed(() => + allList.value.map((item) => ({ + label: item.name, + value: item.id, + raw: item, + })), +); const selectValue = computed({ get: () => props.modelValue, @@ -41,7 +48,7 @@ const selectValue = computed({ function handleFilter(input: string, option: any) { const keyword = input.toLowerCase(); - const item = option?.item as MesMdWorkshopApi.Workshop | undefined; + const item = option?.raw as MesMdWorkshopApi.Workshop | undefined; return Boolean( item?.name?.toLowerCase().includes(keyword) || item?.code?.toLowerCase().includes(keyword), @@ -99,19 +106,17 @@ onMounted(async () => { :placeholder="placeholder" class="w-full" show-search + :options="selectOptions" @change="handleChange" > - + diff --git a/apps/web-antdv-next/src/views/mes/pro/andon/config/components/select.vue b/apps/web-antdv-next/src/views/mes/pro/andon/config/components/select.vue index b7c820f74..20572e945 100644 --- a/apps/web-antdv-next/src/views/mes/pro/andon/config/components/select.vue +++ b/apps/web-antdv-next/src/views/mes/pro/andon/config/components/select.vue @@ -5,7 +5,7 @@ import { computed, onMounted, ref } from 'vue'; import { DICT_TYPE } from '@vben/constants'; -import { Select, SelectOption } from 'antdv-next'; +import { Select } from 'antdv-next'; import { getAndonConfigList } from '#/api/mes/pro/andon/config'; import DictTag from '#/components/dict-tag/dict-tag.vue'; @@ -34,6 +34,13 @@ const emit = defineEmits<{ }>(); const allList = ref([]); +const selectOptions = computed(() => + allList.value.map((item) => ({ + label: item.reason, + value: item.id, + raw: item, + })), +); const selectValue = computed({ get: () => props.modelValue, @@ -45,7 +52,7 @@ const selectValue = computed({ /** 前端过滤:按 reason 模糊匹配 */ function handleFilter(input: string, option: any) { const keyword = input.toLowerCase(); - const item = option?.item as MesProAndonConfigApi.AndonConfig | undefined; + const item = option?.raw as MesProAndonConfigApi.AndonConfig | undefined; return Boolean(item?.reason?.toLowerCase().includes(keyword)); } @@ -71,18 +78,17 @@ onMounted(async () => { :placeholder="placeholder" class="w-full" show-search + :options="selectOptions" @change="handleChange" > - + diff --git a/apps/web-antdv-next/src/views/mes/pro/process/components/select.vue b/apps/web-antdv-next/src/views/mes/pro/process/components/select.vue index 47b8550d6..51604a41c 100644 --- a/apps/web-antdv-next/src/views/mes/pro/process/components/select.vue +++ b/apps/web-antdv-next/src/views/mes/pro/process/components/select.vue @@ -3,7 +3,7 @@ import type { MesProProcessApi } from '#/api/mes/pro/process'; import { computed, onMounted, ref, watch } from 'vue'; -import { Select, SelectOption, Tag, Tooltip } from 'antdv-next'; +import { Select, Tag, Tooltip } from 'antdv-next'; import { getProcessSimpleList } from '#/api/mes/pro/process'; @@ -31,6 +31,13 @@ const emit = defineEmits<{ const allList = ref([]); const selectedItem = ref(); +const selectOptions = computed(() => + allList.value.map((item) => ({ + label: item.name, + value: item.id, + raw: item, + })), +); const selectValue = computed({ get: () => props.modelValue, @@ -42,7 +49,7 @@ const selectValue = computed({ /** 前端过滤:按工序名称或编码模糊匹配 */ function handleFilter(input: string, option: any) { const keyword = input.toLowerCase(); - const item = option?.item as MesProProcessApi.Process | undefined; + const item = option?.raw as MesProProcessApi.Process | undefined; return Boolean( item?.name?.toLowerCase().includes(keyword) || item?.code?.toLowerCase().includes(keyword), @@ -96,19 +103,17 @@ onMounted(async () => { :placeholder="placeholder" class="w-full" show-search + :options="selectOptions" @change="handleChange" > - + diff --git a/apps/web-antdv-next/src/views/mes/wm/warehouse/components/area-select.vue b/apps/web-antdv-next/src/views/mes/wm/warehouse/components/area-select.vue index fc2db97cf..9d6548af7 100644 --- a/apps/web-antdv-next/src/views/mes/wm/warehouse/components/area-select.vue +++ b/apps/web-antdv-next/src/views/mes/wm/warehouse/components/area-select.vue @@ -3,7 +3,7 @@ import type { MesWmWarehouseAreaApi } from '#/api/mes/wm/warehouse/area'; import { computed, ref, useAttrs, watch, watchEffect } from 'vue'; -import { Select, SelectOption, Tag, Tooltip } from 'antdv-next'; +import { Select, Tag, Tooltip } from 'antdv-next'; import { getWarehouseAreaSimpleList } from '#/api/mes/wm/warehouse/area'; @@ -34,6 +34,13 @@ const emit = defineEmits<{ const attrs = useAttrs(); const allList = ref([]); const selectedItem = ref(); +const selectOptions = computed(() => + allList.value.map((item) => ({ + label: item.name, + value: item.id, + raw: item, + })), +); const selectValue = computed({ get: () => props.modelValue, @@ -49,7 +56,7 @@ function handleChange(val: any) { /** 前端过滤(name + code) */ function filterOption(input: string, option: any) { - const item = allList.value.find((o) => o.id === option.value); + const item = option?.raw as MesWmWarehouseAreaApi.WarehouseArea | undefined; if (!item) { return false; } @@ -101,14 +108,17 @@ watchEffect(async () => { :filter-option="filterOption" :placeholder="placeholder" show-search + :options="selectOptions" @change="handleChange" > - + diff --git a/apps/web-antdv-next/src/views/mes/wm/warehouse/components/location-select.vue b/apps/web-antdv-next/src/views/mes/wm/warehouse/components/location-select.vue index 4ad5f432d..c04361227 100644 --- a/apps/web-antdv-next/src/views/mes/wm/warehouse/components/location-select.vue +++ b/apps/web-antdv-next/src/views/mes/wm/warehouse/components/location-select.vue @@ -3,7 +3,7 @@ import type { MesWmWarehouseLocationApi } from '#/api/mes/wm/warehouse/location' import { computed, ref, useAttrs, watch, watchEffect } from 'vue'; -import { Select, SelectOption, Tag, Tooltip } from 'antdv-next'; +import { Select, Tag, Tooltip } from 'antdv-next'; import { getWarehouseLocationSimpleList } from '#/api/mes/wm/warehouse/location'; @@ -34,6 +34,13 @@ const emit = defineEmits<{ const attrs = useAttrs(); const allList = ref([]); const selectedItem = ref(); +const selectOptions = computed(() => + allList.value.map((item) => ({ + label: item.name, + value: item.id, + raw: item, + })), +); const selectValue = computed({ get: () => props.modelValue, @@ -49,7 +56,9 @@ function handleChange(val: any) { /** 前端过滤(name + code) */ function filterOption(input: string, option: any) { - const item = allList.value.find((o) => o.id === option.value); + const item = option?.raw as + | MesWmWarehouseLocationApi.WarehouseLocation + | undefined; if (!item) { return false; } @@ -100,14 +109,17 @@ watchEffect(async () => { :filter-option="filterOption" :placeholder="placeholder" show-search + :options="selectOptions" @change="handleChange" > - + diff --git a/apps/web-antdv-next/src/views/mes/wm/warehouse/components/select.vue b/apps/web-antdv-next/src/views/mes/wm/warehouse/components/select.vue index a68d4cd02..935b2b681 100644 --- a/apps/web-antdv-next/src/views/mes/wm/warehouse/components/select.vue +++ b/apps/web-antdv-next/src/views/mes/wm/warehouse/components/select.vue @@ -3,7 +3,7 @@ import type { MesWmWarehouseApi } from '#/api/mes/wm/warehouse'; import { computed, onMounted, ref, useAttrs, watch } from 'vue'; -import { Select, SelectOption, Tag, Tooltip } from 'antdv-next'; +import { Select, Tag, Tooltip } from 'antdv-next'; import { getWarehouseSimpleList } from '#/api/mes/wm/warehouse'; @@ -32,6 +32,13 @@ const emit = defineEmits<{ const attrs = useAttrs(); const allList = ref([]); const selectedItem = ref(); +const selectOptions = computed(() => + allList.value.map((item) => ({ + label: item.name, + value: item.id, + raw: item, + })), +); const selectValue = computed({ get: () => props.modelValue, @@ -47,7 +54,7 @@ function handleChange(val: any) { /** 前端过滤(name + code) */ function filterOption(input: string, option: any) { - const item = allList.value.find((o) => o.id === option.value); + const item = option?.raw as MesWmWarehouseApi.Warehouse | undefined; if (!item) { return false; } @@ -97,14 +104,17 @@ onMounted(async () => { :filter-option="filterOption" :placeholder="placeholder" show-search + :options="selectOptions" @change="handleChange" > - + diff --git a/apps/web-antdv-next/src/views/mp/components/wx-account-select/wx-account-select.vue b/apps/web-antdv-next/src/views/mp/components/wx-account-select/wx-account-select.vue index 4e55f933f..442d0a911 100644 --- a/apps/web-antdv-next/src/views/mp/components/wx-account-select/wx-account-select.vue +++ b/apps/web-antdv-next/src/views/mp/components/wx-account-select/wx-account-select.vue @@ -61,9 +61,7 @@ onMounted(handleQuery); placeholder="请选择公众号" class="!w-full" @change="onChanged" - > - - {{ item.name }} - - + :options="accountList" + :field-names="{ label: 'name', value: 'id' }" + /> diff --git a/apps/web-antdv-next/src/views/mp/material/modules/UploadVideo.vue b/apps/web-antdv-next/src/views/mp/material/modules/UploadVideo.vue index 1553bdd05..6dc6eee77 100644 --- a/apps/web-antdv-next/src/views/mp/material/modules/UploadVideo.vue +++ b/apps/web-antdv-next/src/views/mp/material/modules/UploadVideo.vue @@ -11,6 +11,7 @@ import { Button, Divider, Form, + FormItem, Input, message, Modal, diff --git a/apps/web-antdv-next/src/views/mp/menu/modules/editor.vue b/apps/web-antdv-next/src/views/mp/menu/modules/editor.vue index e61f96b36..c7223af1b 100644 --- a/apps/web-antdv-next/src/views/mp/menu/modules/editor.vue +++ b/apps/web-antdv-next/src/views/mp/menu/modules/editor.vue @@ -99,16 +99,8 @@ function deleteMaterial() { placeholder="请选择" class="mr-[2%] w-[240px]" allow-clear - > - - {{ item.label }} - - + :options="menuOptions" + />
String(item.id) === String(selectedKey)) + : undefined; + emit('select', dept); } /** 重置选中状态(供外部重置按钮调用) */ diff --git a/apps/web-antdv-next/src/views/system/user/modules/dept-tree.vue b/apps/web-antdv-next/src/views/system/user/modules/dept-tree.vue index beea3f314..48ffe69c4 100644 --- a/apps/web-antdv-next/src/views/system/user/modules/dept-tree.vue +++ b/apps/web-antdv-next/src/views/system/user/modules/dept-tree.vue @@ -32,8 +32,12 @@ function handleSearch(e: any) { } /** 选中部门 */ -function handleSelect(_selectedKeys: any[], info: any) { - emit('select', info.node.dataRef); +function handleSelect(selectedNodeKeys: any[], info: any) { + const selectedKey = selectedNodeKeys[0] ?? info.node?.id ?? info.node?.key; + const dept = info.selected + ? deptList.value.find((item) => String(item.id) === String(selectedKey)) + : undefined; + emit('select', dept); } /** 初始化 */ diff --git a/apps/web-antdv-next/src/views/wms/md/item/category/components/tree.vue b/apps/web-antdv-next/src/views/wms/md/item/category/components/tree.vue index 7954aea91..e682d58c9 100644 --- a/apps/web-antdv-next/src/views/wms/md/item/category/components/tree.vue +++ b/apps/web-antdv-next/src/views/wms/md/item/category/components/tree.vue @@ -55,8 +55,17 @@ function handleSearch(value: string) { } /** 处理节点点击:支持点击同一节点取消选中 */ -function handleSelect(_selectedKeys: any[], info: any) { - const row = info.node.dataRef as WmsItemCategoryApi.ItemCategory; +function handleSelect(selectedNodeKeys: any[], info: any) { + const selectedKey = selectedNodeKeys[0] ?? info.node?.id ?? info.node?.key; + const row = categoryList.value.find( + (item) => String(item.id) === String(selectedKey), + ); + if (!row) { + currentNodeId.value = undefined; + selectedKeys.value = []; + emit('nodeClick', undefined); + return; + } if (currentNodeId.value === row.id) { currentNodeId.value = undefined; selectedKeys.value = [];