refactor(@vben/web-antdv-next): migrate SelectOption usages to options and optionRender
Replace remaining SelectOption children with Select options across form-create, BPM, IoT, MES, WMS, Mall, and infra pages. Use optionRender for custom option content and update the sync skill with Select slot migration guidance.pull/364/head
parent
456a91dfc2
commit
c20eb8e1f4
|
|
@ -6,14 +6,7 @@ import { computed, useAttrs } from 'vue';
|
||||||
|
|
||||||
import { getDictOptions } from '@vben/hooks';
|
import { getDictOptions } from '@vben/hooks';
|
||||||
|
|
||||||
import {
|
import { Checkbox, CheckboxGroup, Radio, RadioGroup, Select } from 'antdv-next';
|
||||||
Checkbox,
|
|
||||||
CheckboxGroup,
|
|
||||||
Radio,
|
|
||||||
RadioGroup,
|
|
||||||
Select,
|
|
||||||
SelectOption,
|
|
||||||
} from 'antdv-next';
|
|
||||||
|
|
||||||
defineOptions({ name: 'DictSelect' });
|
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,
|
||||||
|
})),
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Select v-if="selectType === 'select'" class="w-full" v-bind="attrs">
|
<Select
|
||||||
<SelectOption
|
v-if="selectType === 'select'"
|
||||||
v-for="(dict, index) in getDictOption"
|
class="w-full"
|
||||||
:key="index"
|
v-bind="attrs"
|
||||||
:value="dict.value"
|
:options="selectOptions"
|
||||||
>
|
/>
|
||||||
{{ dict.label }}
|
|
||||||
</SelectOption>
|
|
||||||
</Select>
|
|
||||||
<RadioGroup v-if="selectType === 'radio'" class="w-full" v-bind="attrs">
|
<RadioGroup v-if="selectType === 'radio'" class="w-full" v-bind="attrs">
|
||||||
<Radio
|
<Radio
|
||||||
v-for="(dict, index) in getDictOption"
|
v-for="(dict, index) in getDictOption"
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,7 @@ import { defineComponent, onMounted, ref, useAttrs } from 'vue';
|
||||||
import { useUserStore } from '@vben/stores';
|
import { useUserStore } from '@vben/stores';
|
||||||
import { isEmpty } from '@vben/utils';
|
import { isEmpty } from '@vben/utils';
|
||||||
|
|
||||||
import {
|
import { Checkbox, CheckboxGroup, Radio, RadioGroup, Select } from 'antdv-next';
|
||||||
Checkbox,
|
|
||||||
CheckboxGroup,
|
|
||||||
Radio,
|
|
||||||
RadioGroup,
|
|
||||||
Select,
|
|
||||||
SelectOption,
|
|
||||||
} from 'antdv-next';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
|
@ -256,18 +249,11 @@ export function useApiSelect(option: ApiSelectProps) {
|
||||||
onUpdate:value={onUpdateModelValue as any}
|
onUpdate:value={onUpdateModelValue as any}
|
||||||
value={modelValue as any}
|
value={modelValue as any}
|
||||||
{...restAttrs}
|
{...restAttrs}
|
||||||
|
options={options.value}
|
||||||
// TODO @xingyu remote 对等实现, 还是说没作用
|
// TODO @xingyu remote 对等实现, 还是说没作用
|
||||||
// remote={props.remote}
|
// remote={props.remote}
|
||||||
{...(props.remote && { remoteMethod })}
|
{...(props.remote && { remoteMethod })}
|
||||||
>
|
/>
|
||||||
{options.value.map(
|
|
||||||
(item: { label: any; value: any }, index: any) => (
|
|
||||||
<SelectOption key={index} value={item.value}>
|
|
||||||
{item.label}
|
|
||||||
</SelectOption>
|
|
||||||
),
|
|
||||||
)}
|
|
||||||
</Select>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
|
@ -277,18 +263,11 @@ export function useApiSelect(option: ApiSelectProps) {
|
||||||
onUpdate:value={onUpdateModelValue as any}
|
onUpdate:value={onUpdateModelValue as any}
|
||||||
value={modelValue as any}
|
value={modelValue as any}
|
||||||
{...restAttrs}
|
{...restAttrs}
|
||||||
|
options={options.value}
|
||||||
// TODO: @xingyu remote 对等实现, 还是说没作用
|
// TODO: @xingyu remote 对等实现, 还是说没作用
|
||||||
// remote={props.remote}
|
// remote={props.remote}
|
||||||
{...(props.remote && { remoteMethod })}
|
{...(props.remote && { remoteMethod })}
|
||||||
>
|
/>
|
||||||
{options.value.map(
|
|
||||||
(item: { label: any; value: any }, index: any) => (
|
|
||||||
<SelectOption key={index} value={item.value}>
|
|
||||||
{item.label}
|
|
||||||
</SelectOption>
|
|
||||||
),
|
|
||||||
)}
|
|
||||||
</Select>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
const buildCheckbox = () => {
|
const buildCheckbox = () => {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ import {
|
||||||
RadioGroup,
|
RadioGroup,
|
||||||
Row,
|
Row,
|
||||||
Select,
|
Select,
|
||||||
SelectOption,
|
|
||||||
Space,
|
Space,
|
||||||
Switch,
|
Switch,
|
||||||
TextArea,
|
TextArea,
|
||||||
|
|
@ -69,6 +68,14 @@ const conditionConfigTypes = computed(() => {
|
||||||
|
|
||||||
/** 条件规则可选择的表单字段 */
|
/** 条件规则可选择的表单字段 */
|
||||||
const fieldOptions = useFormFieldsAndStartUser();
|
const fieldOptions = useFormFieldsAndStartUser();
|
||||||
|
const fieldSelectOptions = computed(() =>
|
||||||
|
fieldOptions.map((field) => ({
|
||||||
|
label: field.title,
|
||||||
|
value: field.field,
|
||||||
|
disabled: !field.required,
|
||||||
|
raw: field,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
// 表单校验规则
|
// 表单校验规则
|
||||||
const formRules: Record<string, Rule[]> = reactive({
|
const formRules: Record<string, Rule[]> = reactive({
|
||||||
|
|
@ -172,10 +179,12 @@ defineExpose({ validate });
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Space orientation="vertical" size="small" class="w-11/12 pl-1">
|
<Space
|
||||||
<template #split>
|
orientation="vertical"
|
||||||
{{ condition.conditionGroups.and ? '且' : '或' }}
|
size="small"
|
||||||
</template>
|
class="w-11/12 pl-1"
|
||||||
|
:separator="condition.conditionGroups.and ? '且' : '或'"
|
||||||
|
>
|
||||||
<Card
|
<Card
|
||||||
class="group relative w-full hover:border-blue-500"
|
class="group relative w-full hover:border-blue-500"
|
||||||
v-for="(equation, cIdx) in condition.conditionGroups.conditions"
|
v-for="(equation, cIdx) in condition.conditionGroups.conditions"
|
||||||
|
|
@ -190,7 +199,10 @@ defineExpose({ validate });
|
||||||
icon="lucide:circle-x"
|
icon="lucide:circle-x"
|
||||||
class="size-4"
|
class="size-4"
|
||||||
@click="
|
@click="
|
||||||
deleteConditionGroup(condition.conditionGroups.conditions, cIdx)
|
deleteConditionGroup(
|
||||||
|
condition.conditionGroups.conditions,
|
||||||
|
Number(cIdx),
|
||||||
|
)
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -236,23 +248,18 @@ defineExpose({ validate });
|
||||||
v-model:value="rule.leftSide"
|
v-model:value="rule.leftSide"
|
||||||
allow-clear
|
allow-clear
|
||||||
placeholder="请选择表单字段"
|
placeholder="请选择表单字段"
|
||||||
|
:options="fieldSelectOptions"
|
||||||
>
|
>
|
||||||
<SelectOption
|
<template #optionRender="{ option }">
|
||||||
v-for="(field, fIdx) in fieldOptions"
|
|
||||||
:key="fIdx"
|
|
||||||
:label="field.title"
|
|
||||||
:value="field.field"
|
|
||||||
:disabled="!field.required"
|
|
||||||
>
|
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title="表单字段非必填时不能作为流程分支条件"
|
title="表单字段非必填时不能作为流程分支条件"
|
||||||
placement="right"
|
placement="right"
|
||||||
v-if="!field.required"
|
v-if="!option.data.raw.required"
|
||||||
>
|
>
|
||||||
<span>{{ field.title }}</span>
|
<span>{{ option.data.raw.title }}</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<template v-else>{{ field.title }}</template>
|
<template v-else>{{ option.data.raw.title }}</template>
|
||||||
</SelectOption>
|
</template>
|
||||||
</Select>
|
</Select>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -292,11 +299,11 @@ defineExpose({ validate });
|
||||||
<Trash2
|
<Trash2
|
||||||
v-if="equation.rules.length > 1"
|
v-if="equation.rules.length > 1"
|
||||||
class="mr-2 size-4 cursor-pointer text-red-500"
|
class="mr-2 size-4 cursor-pointer text-red-500"
|
||||||
@click="deleteConditionRule(equation, rIdx)"
|
@click="deleteConditionRule(equation, Number(rIdx))"
|
||||||
/>
|
/>
|
||||||
<Plus
|
<Plus
|
||||||
class="size-4 cursor-pointer text-blue-500"
|
class="size-4 cursor-pointer text-blue-500"
|
||||||
@click="addConditionRule(equation, rIdx)"
|
@click="addConditionRule(equation, Number(rIdx))"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ import {
|
||||||
Radio,
|
Radio,
|
||||||
RadioGroup,
|
RadioGroup,
|
||||||
Select,
|
Select,
|
||||||
SelectOption,
|
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from 'antdv-next';
|
} from 'antdv-next';
|
||||||
|
|
||||||
|
|
@ -107,16 +106,12 @@ defineExpose({ validate });
|
||||||
name="formId"
|
name="formId"
|
||||||
class="mb-5"
|
class="mb-5"
|
||||||
>
|
>
|
||||||
<Select v-model:value="modelData.formId" allow-clear>
|
<Select
|
||||||
<SelectOption
|
v-model:value="modelData.formId"
|
||||||
v-for="form in props.formList"
|
allow-clear
|
||||||
:key="form.id"
|
:options="props.formList"
|
||||||
:value="form.id"
|
:field-names="{ label: 'name', value: 'id' }"
|
||||||
>
|
/>
|
||||||
{{ form.name }}
|
|
||||||
</SelectOption>
|
|
||||||
>
|
|
||||||
</Select>
|
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem
|
<FormItem
|
||||||
v-if="modelData.formType === BpmModelFormType.CUSTOM"
|
v-if="modelData.formType === BpmModelFormType.CUSTOM"
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ import {
|
||||||
Input,
|
Input,
|
||||||
message,
|
message,
|
||||||
Select,
|
Select,
|
||||||
SelectOption,
|
|
||||||
Tag,
|
Tag,
|
||||||
TextArea,
|
TextArea,
|
||||||
} from 'antdv-next';
|
} from 'antdv-next';
|
||||||
|
|
@ -101,7 +100,15 @@ watchEffect(() => {
|
||||||
|
|
||||||
/** 发送消息 */
|
/** 发送消息 */
|
||||||
const sendText = ref(''); // 发送内容
|
const sendText = ref(''); // 发送内容
|
||||||
const sendUserId = ref('all'); // 发送人
|
const sendUserId = ref<'all' | number>('all'); // 发送人
|
||||||
|
const sendUserOptions = computed(() => [
|
||||||
|
{ label: '所有人', value: 'all', raw: null },
|
||||||
|
...userList.value.map((user) => ({
|
||||||
|
label: user.nickname,
|
||||||
|
value: user.id,
|
||||||
|
raw: user,
|
||||||
|
})),
|
||||||
|
]);
|
||||||
function handlerSend() {
|
function handlerSend() {
|
||||||
if (!sendText.value.trim()) {
|
if (!sendText.value.trim()) {
|
||||||
message.warning('消息内容不能为空');
|
message.warning('消息内容不能为空');
|
||||||
|
|
@ -229,26 +236,20 @@ onMounted(async () => {
|
||||||
size="large"
|
size="large"
|
||||||
placeholder="请选择接收人"
|
placeholder="请选择接收人"
|
||||||
:disabled="!getIsOpen"
|
:disabled="!getIsOpen"
|
||||||
|
:options="sendUserOptions"
|
||||||
>
|
>
|
||||||
<SelectOption key="" value="" label="所有人">
|
<template #optionRender="{ option }">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center" v-if="!option.data.raw">
|
||||||
<Avatar size="small" class="mr-2">全</Avatar>
|
<Avatar size="small" class="mr-2">全</Avatar>
|
||||||
<span>所有人</span>
|
<span>所有人</span>
|
||||||
</div>
|
</div>
|
||||||
</SelectOption>
|
<div class="flex items-center" v-else>
|
||||||
<SelectOption
|
|
||||||
v-for="user in userList"
|
|
||||||
:key="user.id"
|
|
||||||
:value="user.id"
|
|
||||||
:label="user.nickname"
|
|
||||||
>
|
|
||||||
<div class="flex items-center">
|
|
||||||
<Avatar size="small" class="mr-2">
|
<Avatar size="small" class="mr-2">
|
||||||
{{ user.nickname.slice(0, 1) }}
|
{{ option.data.raw.nickname?.slice(0, 1) }}
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<span>{{ user.nickname }}</span>
|
<span>{{ option.data.raw.nickname }}</span>
|
||||||
</div>
|
</div>
|
||||||
</SelectOption>
|
</template>
|
||||||
</Select>
|
</Select>
|
||||||
|
|
||||||
<TextArea
|
<TextArea
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
<!-- 当前时间条件配置组件 -->
|
<!-- 当前时间条件配置组件 -->
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Dayjs } from 'dayjs';
|
|
||||||
|
|
||||||
import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
|
|
||||||
import { computed, watch } from 'vue';
|
import { computed, watch } from 'vue';
|
||||||
|
|
@ -17,7 +15,6 @@ import {
|
||||||
FormItem,
|
FormItem,
|
||||||
Row,
|
Row,
|
||||||
Select,
|
Select,
|
||||||
SelectOption,
|
|
||||||
Tag,
|
Tag,
|
||||||
TimePicker,
|
TimePicker,
|
||||||
} from 'antdv-next';
|
} from 'antdv-next';
|
||||||
|
|
@ -130,7 +127,7 @@ function updateConditionField(field: any, value: any) {
|
||||||
* 处理第一个时间值变化
|
* 处理第一个时间值变化
|
||||||
* @param value 时间值
|
* @param value 时间值
|
||||||
*/
|
*/
|
||||||
function handleTimeValueChange(value: Dayjs | null | string) {
|
function handleTimeValueChange(value: any) {
|
||||||
const normalized = formatDayjs(value);
|
const normalized = formatDayjs(value);
|
||||||
const currentParams = condition.value.param
|
const currentParams = condition.value.param
|
||||||
? condition.value.param.split(',')
|
? condition.value.param.split(',')
|
||||||
|
|
@ -147,7 +144,7 @@ function handleTimeValueChange(value: Dayjs | null | string) {
|
||||||
* 处理第二个时间值变化
|
* 处理第二个时间值变化
|
||||||
* @param value 时间值
|
* @param value 时间值
|
||||||
*/
|
*/
|
||||||
function handleTimeValue2Change(value: Dayjs | null | string) {
|
function handleTimeValue2Change(value: any) {
|
||||||
const normalized = formatDayjs(value);
|
const normalized = formatDayjs(value);
|
||||||
const currentParams = condition.value.param
|
const currentParams = condition.value.param
|
||||||
? condition.value.param.split(',')
|
? condition.value.param.split(',')
|
||||||
|
|
@ -187,23 +184,22 @@ watch(
|
||||||
"
|
"
|
||||||
placeholder="请选择时间条件"
|
placeholder="请选择时间条件"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
|
:options="timeOperatorOptions"
|
||||||
>
|
>
|
||||||
<SelectOption
|
<template #optionRender="{ option }">
|
||||||
v-for="option in timeOperatorOptions"
|
|
||||||
:key="option.value"
|
|
||||||
:label="option.label"
|
|
||||||
:value="option.value"
|
|
||||||
>
|
|
||||||
<div class="flex w-full items-center justify-between">
|
<div class="flex w-full items-center justify-between">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<IconifyIcon :icon="option.icon" :class="option.iconClass" />
|
<IconifyIcon
|
||||||
<span>{{ option.label }}</span>
|
:icon="option.data.icon"
|
||||||
|
:class="option.data.iconClass"
|
||||||
|
/>
|
||||||
|
<span>{{ option.data.label }}</span>
|
||||||
</div>
|
</div>
|
||||||
<Tag :color="option.tag">
|
<Tag :color="option.data.tag">
|
||||||
{{ option.category }}
|
{{ option.data.category }}
|
||||||
</Tag>
|
</Tag>
|
||||||
</div>
|
</div>
|
||||||
</SelectOption>
|
</template>
|
||||||
</Select>
|
</Select>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import {
|
||||||
import { isObject } from '@vben/utils';
|
import { isObject } from '@vben/utils';
|
||||||
|
|
||||||
import { useVModel } from '@vueuse/core';
|
import { useVModel } from '@vueuse/core';
|
||||||
import { Col, FormItem, Row, Select, SelectOption, Tag } from 'antdv-next';
|
import { Col, FormItem, Row, Select, Tag } from 'antdv-next';
|
||||||
|
|
||||||
import { getThingModelTSLByProductId } from '#/api/iot/thingmodel';
|
import { getThingModelTSLByProductId } from '#/api/iot/thingmodel';
|
||||||
|
|
||||||
|
|
@ -39,6 +39,13 @@ const loadingThingModel = ref(false); // 物模型加载状态
|
||||||
const selectedService = ref<null | ThingModelApi.Service>(null); // 选中的服务对象
|
const selectedService = ref<null | ThingModelApi.Service>(null); // 选中的服务对象
|
||||||
const serviceList = ref<ThingModelApi.Service[]>([]); // 服务列表
|
const serviceList = ref<ThingModelApi.Service[]>([]); // 服务列表
|
||||||
const loadingServices = ref(false); // 服务加载状态
|
const loadingServices = ref(false); // 服务加载状态
|
||||||
|
const serviceOptions = computed(() =>
|
||||||
|
serviceList.value.map((service) => ({
|
||||||
|
label: service.name,
|
||||||
|
value: service.identifier,
|
||||||
|
raw: service,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
// 参数值的计算属性,用于双向绑定
|
// 参数值的计算属性,用于双向绑定
|
||||||
const paramsValue = computed({
|
const paramsValue = computed({
|
||||||
|
|
@ -346,23 +353,22 @@ watch(
|
||||||
allow-clear
|
allow-clear
|
||||||
class="w-full"
|
class="w-full"
|
||||||
:loading="loadingServices"
|
:loading="loadingServices"
|
||||||
|
:options="serviceOptions"
|
||||||
|
option-filter-prop="label"
|
||||||
@change="handleServiceChange"
|
@change="handleServiceChange"
|
||||||
>
|
>
|
||||||
<SelectOption
|
<template #optionRender="{ option }">
|
||||||
v-for="service in serviceList"
|
|
||||||
:key="service.identifier"
|
|
||||||
:label="service.name"
|
|
||||||
:value="service.identifier"
|
|
||||||
>
|
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<span>{{ service.name }}</span>
|
<span>{{ option.data.raw.name }}</span>
|
||||||
<Tag
|
<Tag
|
||||||
:color="service.callType === 'sync' ? 'processing' : 'success'"
|
:color="
|
||||||
|
option.data.raw.callType === 'sync' ? 'processing' : 'success'
|
||||||
|
"
|
||||||
>
|
>
|
||||||
{{ service.callType === 'sync' ? '同步' : '异步' }}
|
{{ option.data.raw.callType === 'sync' ? '同步' : '异步' }}
|
||||||
</Tag>
|
</Tag>
|
||||||
</div>
|
</div>
|
||||||
</SelectOption>
|
</template>
|
||||||
</Select>
|
</Select>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
<!-- 设备选择器组件 -->
|
<!-- 设备选择器组件 -->
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, watch } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
|
|
||||||
import { DEVICE_SELECTOR_OPTIONS, DICT_TYPE } from '@vben/constants';
|
import { DEVICE_SELECTOR_OPTIONS, DICT_TYPE } from '@vben/constants';
|
||||||
|
|
||||||
import { Select, SelectOption } from 'antdv-next';
|
import { Select } from 'antdv-next';
|
||||||
|
|
||||||
import { getDeviceListByProductId } from '#/api/iot/device/device';
|
import { getDeviceListByProductId } from '#/api/iot/device/device';
|
||||||
import { DictTag } from '#/components/dict-tag';
|
import { DictTag } from '#/components/dict-tag';
|
||||||
|
|
@ -24,6 +24,13 @@ const emit = defineEmits<{
|
||||||
|
|
||||||
const deviceLoading = ref(false); // 设备加载状态
|
const deviceLoading = ref(false); // 设备加载状态
|
||||||
const deviceList = ref<any[]>([]); // 设备列表
|
const deviceList = ref<any[]>([]); // 设备列表
|
||||||
|
const deviceOptions = computed(() =>
|
||||||
|
deviceList.value.map((device) => ({
|
||||||
|
label: device.deviceName,
|
||||||
|
value: device.id,
|
||||||
|
raw: device,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
/** 处理选择变化事件 */
|
/** 处理选择变化事件 */
|
||||||
function handleChange(value: any) {
|
function handleChange(value: any) {
|
||||||
|
|
@ -90,28 +97,28 @@ watch(
|
||||||
allow-clear
|
allow-clear
|
||||||
class="w-full"
|
class="w-full"
|
||||||
option-label-prop="label"
|
option-label-prop="label"
|
||||||
|
option-filter-prop="label"
|
||||||
:loading="deviceLoading"
|
:loading="deviceLoading"
|
||||||
:disabled="!productId"
|
:disabled="!productId"
|
||||||
|
:options="deviceOptions"
|
||||||
>
|
>
|
||||||
<SelectOption
|
<template #optionRender="{ option }">
|
||||||
v-for="device in deviceList"
|
|
||||||
:key="device.id"
|
|
||||||
:label="device.deviceName"
|
|
||||||
:value="device.id"
|
|
||||||
>
|
|
||||||
<div class="py-[4px] flex w-full items-center justify-between">
|
<div class="py-[4px] flex w-full items-center justify-between">
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<div class="text-[14px] font-medium mb-[2px] text-foreground">
|
<div class="text-[14px] font-medium mb-[2px] text-foreground">
|
||||||
{{ device.deviceName }}
|
{{ option.data.raw.deviceName }}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-[12px] text-muted-foreground">
|
<div class="text-[12px] text-muted-foreground">
|
||||||
{{ device.deviceKey }}
|
{{ option.data.raw.deviceKey }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="gap-[4px] flex items-center" v-if="device.id > 0">
|
<div class="gap-[4px] flex items-center" v-if="option.data.raw.id > 0">
|
||||||
<DictTag :type="DICT_TYPE.IOT_DEVICE_STATE" :value="device.state" />
|
<DictTag
|
||||||
|
:type="DICT_TYPE.IOT_DEVICE_STATE"
|
||||||
|
:value="option.data.raw.state"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</SelectOption>
|
</template>
|
||||||
</Select>
|
</Select>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import {
|
||||||
} from '@vben/constants';
|
} from '@vben/constants';
|
||||||
|
|
||||||
import { useVModel } from '@vueuse/core';
|
import { useVModel } from '@vueuse/core';
|
||||||
import { Select, SelectOption } from 'antdv-next';
|
import { Select } from 'antdv-next';
|
||||||
|
|
||||||
/** 操作符选择器组件 */
|
/** 操作符选择器组件 */
|
||||||
defineOptions({ name: 'OperatorSelector' });
|
defineOptions({ name: 'OperatorSelector' });
|
||||||
|
|
@ -204,6 +204,13 @@ const availableOperators = computed(() => {
|
||||||
(op.supportedTypes as any[]).includes(props.propertyType || ''),
|
(op.supportedTypes as any[]).includes(props.propertyType || ''),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
const availableOperatorOptions = computed(() =>
|
||||||
|
availableOperators.value.map((operator) => ({
|
||||||
|
label: operator.label,
|
||||||
|
value: operator.value,
|
||||||
|
raw: operator,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
// 计算属性:当前选中的操作符
|
// 计算属性:当前选中的操作符
|
||||||
const selectedOperator = computed(() => {
|
const selectedOperator = computed(() => {
|
||||||
|
|
@ -244,29 +251,25 @@ watch(
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
option-label-prop="label"
|
option-label-prop="label"
|
||||||
|
:options="availableOperatorOptions"
|
||||||
>
|
>
|
||||||
<SelectOption
|
<template #optionRender="{ option }">
|
||||||
v-for="operator in availableOperators"
|
|
||||||
:key="operator.value"
|
|
||||||
:label="operator.label"
|
|
||||||
:value="operator.value"
|
|
||||||
>
|
|
||||||
<div class="py-[4px] flex w-full items-center justify-between">
|
<div class="py-[4px] flex w-full items-center justify-between">
|
||||||
<div class="gap-[8px] flex items-center">
|
<div class="gap-[8px] flex items-center">
|
||||||
<div class="text-[14px] font-medium text-foreground">
|
<div class="text-[14px] font-medium text-foreground">
|
||||||
{{ operator.label }}
|
{{ option.data.raw.label }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="text-[12px] px-[6px] py-[2px] rounded-[4px] bg-primary-light-9 font-mono text-primary"
|
class="text-[12px] px-[6px] py-[2px] rounded-[4px] bg-primary-light-9 font-mono text-primary"
|
||||||
>
|
>
|
||||||
{{ operator.symbol }}
|
{{ option.data.raw.symbol }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-[12px] text-muted-foreground">
|
<div class="text-[12px] text-muted-foreground">
|
||||||
{{ operator.description }}
|
{{ option.data.raw.description }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</SelectOption>
|
</template>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
<!-- 产品选择器组件 -->
|
<!-- 产品选择器组件 -->
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, ref } from 'vue';
|
import { computed, onMounted, ref } from 'vue';
|
||||||
|
|
||||||
import { DICT_TYPE } from '@vben/constants';
|
import { DICT_TYPE } from '@vben/constants';
|
||||||
|
|
||||||
import { Select, SelectOption } from 'antdv-next';
|
import { Select } from 'antdv-next';
|
||||||
|
|
||||||
import { getSimpleProductList } from '#/api/iot/product/product';
|
import { getSimpleProductList } from '#/api/iot/product/product';
|
||||||
import { DictTag } from '#/components/dict-tag';
|
import { DictTag } from '#/components/dict-tag';
|
||||||
|
|
@ -23,6 +23,13 @@ const emit = defineEmits<{
|
||||||
|
|
||||||
const productLoading = ref(false); // 产品加载状态
|
const productLoading = ref(false); // 产品加载状态
|
||||||
const productList = ref<any[]>([]); // 产品列表
|
const productList = ref<any[]>([]); // 产品列表
|
||||||
|
const productOptions = computed(() =>
|
||||||
|
productList.value.map((product) => ({
|
||||||
|
label: product.name,
|
||||||
|
value: product.id,
|
||||||
|
raw: product,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理选择变化事件
|
* 处理选择变化事件
|
||||||
|
|
@ -62,25 +69,25 @@ onMounted(() => {
|
||||||
allow-clear
|
allow-clear
|
||||||
class="w-full"
|
class="w-full"
|
||||||
option-label-prop="label"
|
option-label-prop="label"
|
||||||
|
option-filter-prop="label"
|
||||||
:loading="productLoading"
|
:loading="productLoading"
|
||||||
|
:options="productOptions"
|
||||||
>
|
>
|
||||||
<SelectOption
|
<template #optionRender="{ option }">
|
||||||
v-for="product in productList"
|
|
||||||
:key="product.id"
|
|
||||||
:label="product.name"
|
|
||||||
:value="product.id"
|
|
||||||
>
|
|
||||||
<div class="py-[4px] flex w-full items-center justify-between">
|
<div class="py-[4px] flex w-full items-center justify-between">
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<div class="text-[14px] font-medium mb-[2px] text-foreground">
|
<div class="text-[14px] font-medium mb-[2px] text-foreground">
|
||||||
{{ product.name }}
|
{{ option.data.raw.name }}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-[12px] text-muted-foreground">
|
<div class="text-[12px] text-muted-foreground">
|
||||||
{{ product.productKey }}
|
{{ option.data.raw.productKey }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<DictTag :type="DICT_TYPE.IOT_PRODUCT_STATUS" :value="product.status" />
|
<DictTag
|
||||||
|
:type="DICT_TYPE.IOT_PRODUCT_STATUS"
|
||||||
|
:value="option.data.raw.status"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</SelectOption>
|
</template>
|
||||||
</Select>
|
</Select>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,7 @@ import {
|
||||||
import { IconifyIcon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
|
||||||
import { useVModel } from '@vueuse/core';
|
import { useVModel } from '@vueuse/core';
|
||||||
import {
|
import { Button, Popover, Select, Tag } from 'antdv-next';
|
||||||
Button,
|
|
||||||
Popover,
|
|
||||||
Select,
|
|
||||||
SelectOptGroup,
|
|
||||||
SelectOption,
|
|
||||||
Tag,
|
|
||||||
} from 'antdv-next';
|
|
||||||
|
|
||||||
import { getThingModelTSLByProductId } from '#/api/iot/thingmodel';
|
import { getThingModelTSLByProductId } from '#/api/iot/thingmodel';
|
||||||
|
|
||||||
|
|
@ -99,6 +92,16 @@ const propertyGroups = computed(() => {
|
||||||
);
|
);
|
||||||
return options.length > 0 ? [{ label: config.label, options }] : [];
|
return options.length > 0 ? [{ label: config.label, options }] : [];
|
||||||
});
|
});
|
||||||
|
const propertySelectOptions = computed(() =>
|
||||||
|
propertyGroups.value.map((group) => ({
|
||||||
|
label: group.label,
|
||||||
|
options: group.options.map((property) => ({
|
||||||
|
label: property.name,
|
||||||
|
value: property.identifier,
|
||||||
|
raw: property,
|
||||||
|
})),
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
/** 当前选中的属性 */
|
/** 当前选中的属性 */
|
||||||
const selectedProperty = computed(() =>
|
const selectedProperty = computed(() =>
|
||||||
|
|
@ -224,31 +227,20 @@ watch(
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
class="!w-[150px]"
|
class="!w-[150px]"
|
||||||
option-label-prop="label"
|
option-label-prop="label"
|
||||||
|
option-filter-prop="label"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
|
:options="propertySelectOptions"
|
||||||
>
|
>
|
||||||
<SelectOptGroup
|
<template #optionRender="{ option }">
|
||||||
v-for="group in propertyGroups"
|
<div class="py-[2px] flex w-full items-center justify-between">
|
||||||
:key="group.label"
|
<span class="text-[14px] font-medium flex-1 truncate text-foreground">
|
||||||
:label="group.label"
|
{{ option.data.raw.name }}
|
||||||
>
|
</span>
|
||||||
<SelectOption
|
<Tag class="ml-[8px] flex-shrink-0">
|
||||||
v-for="property in group.options"
|
{{ option.data.raw.identifier }}
|
||||||
:key="property.identifier"
|
</Tag>
|
||||||
:label="property.name"
|
</div>
|
||||||
:value="property.identifier"
|
</template>
|
||||||
>
|
|
||||||
<div class="py-[2px] flex w-full items-center justify-between">
|
|
||||||
<span
|
|
||||||
class="text-[14px] font-medium flex-1 truncate text-foreground"
|
|
||||||
>
|
|
||||||
{{ property.name }}
|
|
||||||
</span>
|
|
||||||
<Tag class="ml-[8px] flex-shrink-0">
|
|
||||||
{{ property.identifier }}
|
|
||||||
</Tag>
|
|
||||||
</div>
|
|
||||||
</SelectOption>
|
|
||||||
</SelectOptGroup>
|
|
||||||
</Select>
|
</Select>
|
||||||
|
|
||||||
<!-- 属性详情弹出层 -->
|
<!-- 属性详情弹出层 -->
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ import {
|
||||||
RadioButton,
|
RadioButton,
|
||||||
RadioGroup,
|
RadioGroup,
|
||||||
Select,
|
Select,
|
||||||
SelectOption,
|
|
||||||
} from 'antdv-next';
|
} from 'antdv-next';
|
||||||
|
|
||||||
import UploadImg from '#/components/upload/image-upload.vue';
|
import UploadImg from '#/components/upload/image-upload.vue';
|
||||||
|
|
@ -29,6 +28,11 @@ defineOptions({ name: 'TabBarProperty' });
|
||||||
const props = defineProps<{ modelValue: TabBarProperty }>();
|
const props = defineProps<{ modelValue: TabBarProperty }>();
|
||||||
const emit = defineEmits(['update:modelValue']);
|
const emit = defineEmits(['update:modelValue']);
|
||||||
const formData = useVModel(props, 'modelValue', emit);
|
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;
|
component.property.items = formData.value.items;
|
||||||
|
|
@ -51,18 +55,20 @@ const handleThemeChange = () => {
|
||||||
:wrapper-col="{ span: 18 }"
|
:wrapper-col="{ span: 18 }"
|
||||||
>
|
>
|
||||||
<FormItem label="主题" name="theme">
|
<FormItem label="主题" name="theme">
|
||||||
<Select v-model:value="formData!.theme" @change="handleThemeChange">
|
<Select
|
||||||
<SelectOption
|
v-model:value="formData!.theme"
|
||||||
v-for="(theme, index) in THEME_LIST"
|
:options="themeOptions"
|
||||||
:key="index"
|
@change="handleThemeChange"
|
||||||
:label="theme.name"
|
>
|
||||||
:value="theme.id"
|
<template #optionRender="{ option }">
|
||||||
>
|
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<IconifyIcon :icon="theme.icon" :color="theme.color" />
|
<IconifyIcon
|
||||||
<span>{{ theme.name }}</span>
|
:icon="option.data.raw.icon"
|
||||||
|
:color="option.data.raw.color"
|
||||||
|
/>
|
||||||
|
<span>{{ option.data.raw.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
</SelectOption>
|
</template>
|
||||||
</Select>
|
</Select>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem label="默认颜色">
|
<FormItem label="默认颜色">
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import type { MesMdUnitMeasureApi } from '#/api/mes/md/unitmeasure';
|
||||||
|
|
||||||
import { computed, onMounted, ref, watch } from 'vue';
|
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';
|
import { getUnitMeasureSimpleList } from '#/api/mes/md/unitmeasure';
|
||||||
|
|
||||||
|
|
@ -32,6 +32,13 @@ const emit = defineEmits<{
|
||||||
const allList = ref<MesMdUnitMeasureApi.UnitMeasure[]>([]); // 计量单位列表
|
const allList = ref<MesMdUnitMeasureApi.UnitMeasure[]>([]); // 计量单位列表
|
||||||
const filteredList = ref<MesMdUnitMeasureApi.UnitMeasure[]>([]); // 过滤后的计量单位列表
|
const filteredList = ref<MesMdUnitMeasureApi.UnitMeasure[]>([]); // 过滤后的计量单位列表
|
||||||
const selectedItem = ref<MesMdUnitMeasureApi.UnitMeasure>(); // 当前选中计量单位
|
const selectedItem = ref<MesMdUnitMeasureApi.UnitMeasure>(); // 当前选中计量单位
|
||||||
|
const selectOptions = computed(() =>
|
||||||
|
filteredList.value.map((item) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
raw: item,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
const selectValue = computed({
|
const selectValue = computed({
|
||||||
// 选择器绑定值
|
// 选择器绑定值
|
||||||
|
|
@ -44,7 +51,7 @@ const selectValue = computed({
|
||||||
/** 前端按名称和编码过滤计量单位 */
|
/** 前端按名称和编码过滤计量单位 */
|
||||||
function handleFilter(input: string, option: any) {
|
function handleFilter(input: string, option: any) {
|
||||||
const keyword = input.toLowerCase();
|
const keyword = input.toLowerCase();
|
||||||
const item = option?.item as MesMdUnitMeasureApi.UnitMeasure | undefined;
|
const item = option?.raw as MesMdUnitMeasureApi.UnitMeasure | undefined;
|
||||||
return Boolean(
|
return Boolean(
|
||||||
item?.name?.toLowerCase().includes(keyword) ||
|
item?.name?.toLowerCase().includes(keyword) ||
|
||||||
item?.code?.toLowerCase().includes(keyword),
|
item?.code?.toLowerCase().includes(keyword),
|
||||||
|
|
@ -104,19 +111,17 @@ onMounted(async () => {
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
show-search
|
show-search
|
||||||
|
:options="selectOptions"
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
>
|
>
|
||||||
<SelectOption
|
<template #optionRender="{ option }">
|
||||||
v-for="item in filteredList"
|
|
||||||
:key="item.id"
|
|
||||||
:item="item"
|
|
||||||
:value="item.id"
|
|
||||||
>
|
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<span>{{ item.name }}</span>
|
<span>{{ option.data.raw.name }}</span>
|
||||||
<Tag v-if="item.code" color="default">编号: {{ item.code }}</Tag>
|
<Tag v-if="option.data.raw.code" color="default">
|
||||||
|
编号: {{ option.data.raw.code }}
|
||||||
|
</Tag>
|
||||||
</div>
|
</div>
|
||||||
</SelectOption>
|
</template>
|
||||||
</Select>
|
</Select>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import type { MesMdWorkshopApi } from '#/api/mes/md/workstation/workshop';
|
||||||
|
|
||||||
import { computed, onMounted, ref, watch } from 'vue';
|
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';
|
import { getWorkshopSimpleList } from '#/api/mes/md/workstation/workshop';
|
||||||
|
|
||||||
|
|
@ -31,6 +31,13 @@ const emit = defineEmits<{
|
||||||
|
|
||||||
const allList = ref<MesMdWorkshopApi.Workshop[]>([]);
|
const allList = ref<MesMdWorkshopApi.Workshop[]>([]);
|
||||||
const selectedItem = ref<MesMdWorkshopApi.Workshop>();
|
const selectedItem = ref<MesMdWorkshopApi.Workshop>();
|
||||||
|
const selectOptions = computed(() =>
|
||||||
|
allList.value.map((item) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
raw: item,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
const selectValue = computed({
|
const selectValue = computed({
|
||||||
get: () => props.modelValue,
|
get: () => props.modelValue,
|
||||||
|
|
@ -41,7 +48,7 @@ const selectValue = computed({
|
||||||
|
|
||||||
function handleFilter(input: string, option: any) {
|
function handleFilter(input: string, option: any) {
|
||||||
const keyword = input.toLowerCase();
|
const keyword = input.toLowerCase();
|
||||||
const item = option?.item as MesMdWorkshopApi.Workshop | undefined;
|
const item = option?.raw as MesMdWorkshopApi.Workshop | undefined;
|
||||||
return Boolean(
|
return Boolean(
|
||||||
item?.name?.toLowerCase().includes(keyword) ||
|
item?.name?.toLowerCase().includes(keyword) ||
|
||||||
item?.code?.toLowerCase().includes(keyword),
|
item?.code?.toLowerCase().includes(keyword),
|
||||||
|
|
@ -99,19 +106,17 @@ onMounted(async () => {
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
show-search
|
show-search
|
||||||
|
:options="selectOptions"
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
>
|
>
|
||||||
<SelectOption
|
<template #optionRender="{ option }">
|
||||||
v-for="item in allList"
|
|
||||||
:key="item.id"
|
|
||||||
:item="item"
|
|
||||||
:value="item.id"
|
|
||||||
>
|
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<span>{{ item.name }}</span>
|
<span>{{ option.data.raw.name }}</span>
|
||||||
<Tag v-if="item.code" color="default">{{ item.code }}</Tag>
|
<Tag v-if="option.data.raw.code" color="default">
|
||||||
|
{{ option.data.raw.code }}
|
||||||
|
</Tag>
|
||||||
</div>
|
</div>
|
||||||
</SelectOption>
|
</template>
|
||||||
</Select>
|
</Select>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { computed, onMounted, ref } from 'vue';
|
||||||
|
|
||||||
import { DICT_TYPE } from '@vben/constants';
|
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 { getAndonConfigList } from '#/api/mes/pro/andon/config';
|
||||||
import DictTag from '#/components/dict-tag/dict-tag.vue';
|
import DictTag from '#/components/dict-tag/dict-tag.vue';
|
||||||
|
|
@ -34,6 +34,13 @@ const emit = defineEmits<{
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const allList = ref<MesProAndonConfigApi.AndonConfig[]>([]);
|
const allList = ref<MesProAndonConfigApi.AndonConfig[]>([]);
|
||||||
|
const selectOptions = computed(() =>
|
||||||
|
allList.value.map((item) => ({
|
||||||
|
label: item.reason,
|
||||||
|
value: item.id,
|
||||||
|
raw: item,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
const selectValue = computed({
|
const selectValue = computed({
|
||||||
get: () => props.modelValue,
|
get: () => props.modelValue,
|
||||||
|
|
@ -45,7 +52,7 @@ const selectValue = computed({
|
||||||
/** 前端过滤:按 reason 模糊匹配 */
|
/** 前端过滤:按 reason 模糊匹配 */
|
||||||
function handleFilter(input: string, option: any) {
|
function handleFilter(input: string, option: any) {
|
||||||
const keyword = input.toLowerCase();
|
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));
|
return Boolean(item?.reason?.toLowerCase().includes(keyword));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,18 +78,17 @@ onMounted(async () => {
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
show-search
|
show-search
|
||||||
|
:options="selectOptions"
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
>
|
>
|
||||||
<SelectOption
|
<template #optionRender="{ option }">
|
||||||
v-for="item in allList"
|
|
||||||
:key="item.id"
|
|
||||||
:item="item"
|
|
||||||
:value="item.id"
|
|
||||||
>
|
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<span>{{ item.reason }}</span>
|
<span>{{ option.data.raw.reason }}</span>
|
||||||
<DictTag :type="DICT_TYPE.MES_PRO_ANDON_LEVEL" :value="item.level" />
|
<DictTag
|
||||||
|
:type="DICT_TYPE.MES_PRO_ANDON_LEVEL"
|
||||||
|
:value="option.data.raw.level"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</SelectOption>
|
</template>
|
||||||
</Select>
|
</Select>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import type { MesProProcessApi } from '#/api/mes/pro/process';
|
||||||
|
|
||||||
import { computed, onMounted, ref, watch } from 'vue';
|
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';
|
import { getProcessSimpleList } from '#/api/mes/pro/process';
|
||||||
|
|
||||||
|
|
@ -31,6 +31,13 @@ const emit = defineEmits<{
|
||||||
|
|
||||||
const allList = ref<MesProProcessApi.Process[]>([]);
|
const allList = ref<MesProProcessApi.Process[]>([]);
|
||||||
const selectedItem = ref<MesProProcessApi.Process>();
|
const selectedItem = ref<MesProProcessApi.Process>();
|
||||||
|
const selectOptions = computed(() =>
|
||||||
|
allList.value.map((item) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
raw: item,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
const selectValue = computed({
|
const selectValue = computed({
|
||||||
get: () => props.modelValue,
|
get: () => props.modelValue,
|
||||||
|
|
@ -42,7 +49,7 @@ const selectValue = computed({
|
||||||
/** 前端过滤:按工序名称或编码模糊匹配 */
|
/** 前端过滤:按工序名称或编码模糊匹配 */
|
||||||
function handleFilter(input: string, option: any) {
|
function handleFilter(input: string, option: any) {
|
||||||
const keyword = input.toLowerCase();
|
const keyword = input.toLowerCase();
|
||||||
const item = option?.item as MesProProcessApi.Process | undefined;
|
const item = option?.raw as MesProProcessApi.Process | undefined;
|
||||||
return Boolean(
|
return Boolean(
|
||||||
item?.name?.toLowerCase().includes(keyword) ||
|
item?.name?.toLowerCase().includes(keyword) ||
|
||||||
item?.code?.toLowerCase().includes(keyword),
|
item?.code?.toLowerCase().includes(keyword),
|
||||||
|
|
@ -96,19 +103,17 @@ onMounted(async () => {
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
show-search
|
show-search
|
||||||
|
:options="selectOptions"
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
>
|
>
|
||||||
<SelectOption
|
<template #optionRender="{ option }">
|
||||||
v-for="item in allList"
|
|
||||||
:key="item.id"
|
|
||||||
:item="item"
|
|
||||||
:value="item.id"
|
|
||||||
>
|
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<span>{{ item.name }}</span>
|
<span>{{ option.data.raw.name }}</span>
|
||||||
<Tag v-if="item.code" color="default">{{ item.code }}</Tag>
|
<Tag v-if="option.data.raw.code" color="default">
|
||||||
|
{{ option.data.raw.code }}
|
||||||
|
</Tag>
|
||||||
</div>
|
</div>
|
||||||
</SelectOption>
|
</template>
|
||||||
</Select>
|
</Select>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import type { MesWmWarehouseAreaApi } from '#/api/mes/wm/warehouse/area';
|
||||||
|
|
||||||
import { computed, ref, useAttrs, watch, watchEffect } from 'vue';
|
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';
|
import { getWarehouseAreaSimpleList } from '#/api/mes/wm/warehouse/area';
|
||||||
|
|
||||||
|
|
@ -34,6 +34,13 @@ const emit = defineEmits<{
|
||||||
const attrs = useAttrs();
|
const attrs = useAttrs();
|
||||||
const allList = ref<MesWmWarehouseAreaApi.WarehouseArea[]>([]);
|
const allList = ref<MesWmWarehouseAreaApi.WarehouseArea[]>([]);
|
||||||
const selectedItem = ref<MesWmWarehouseAreaApi.WarehouseArea>();
|
const selectedItem = ref<MesWmWarehouseAreaApi.WarehouseArea>();
|
||||||
|
const selectOptions = computed(() =>
|
||||||
|
allList.value.map((item) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
raw: item,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
const selectValue = computed({
|
const selectValue = computed({
|
||||||
get: () => props.modelValue,
|
get: () => props.modelValue,
|
||||||
|
|
@ -49,7 +56,7 @@ function handleChange(val: any) {
|
||||||
|
|
||||||
/** 前端过滤(name + code) */
|
/** 前端过滤(name + code) */
|
||||||
function filterOption(input: string, option: any) {
|
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) {
|
if (!item) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -101,14 +108,17 @@ watchEffect(async () => {
|
||||||
:filter-option="filterOption"
|
:filter-option="filterOption"
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
show-search
|
show-search
|
||||||
|
:options="selectOptions"
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
>
|
>
|
||||||
<SelectOption v-for="item in allList" :key="item.id" :value="item.id">
|
<template #optionRender="{ option }">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<span>{{ item.name }}</span>
|
<span>{{ option.data.raw.name }}</span>
|
||||||
<Tag v-if="item.code" color="blue">编号: {{ item.code }}</Tag>
|
<Tag v-if="option.data.raw.code" color="blue">
|
||||||
|
编号: {{ option.data.raw.code }}
|
||||||
|
</Tag>
|
||||||
</div>
|
</div>
|
||||||
</SelectOption>
|
</template>
|
||||||
</Select>
|
</Select>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import type { MesWmWarehouseLocationApi } from '#/api/mes/wm/warehouse/location'
|
||||||
|
|
||||||
import { computed, ref, useAttrs, watch, watchEffect } from 'vue';
|
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';
|
import { getWarehouseLocationSimpleList } from '#/api/mes/wm/warehouse/location';
|
||||||
|
|
||||||
|
|
@ -34,6 +34,13 @@ const emit = defineEmits<{
|
||||||
const attrs = useAttrs();
|
const attrs = useAttrs();
|
||||||
const allList = ref<MesWmWarehouseLocationApi.WarehouseLocation[]>([]);
|
const allList = ref<MesWmWarehouseLocationApi.WarehouseLocation[]>([]);
|
||||||
const selectedItem = ref<MesWmWarehouseLocationApi.WarehouseLocation>();
|
const selectedItem = ref<MesWmWarehouseLocationApi.WarehouseLocation>();
|
||||||
|
const selectOptions = computed(() =>
|
||||||
|
allList.value.map((item) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
raw: item,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
const selectValue = computed({
|
const selectValue = computed({
|
||||||
get: () => props.modelValue,
|
get: () => props.modelValue,
|
||||||
|
|
@ -49,7 +56,9 @@ function handleChange(val: any) {
|
||||||
|
|
||||||
/** 前端过滤(name + code) */
|
/** 前端过滤(name + code) */
|
||||||
function filterOption(input: string, option: any) {
|
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) {
|
if (!item) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -100,14 +109,17 @@ watchEffect(async () => {
|
||||||
:filter-option="filterOption"
|
:filter-option="filterOption"
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
show-search
|
show-search
|
||||||
|
:options="selectOptions"
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
>
|
>
|
||||||
<SelectOption v-for="item in allList" :key="item.id" :value="item.id">
|
<template #optionRender="{ option }">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<span>{{ item.name }}</span>
|
<span>{{ option.data.raw.name }}</span>
|
||||||
<Tag v-if="item.code" color="blue">编号: {{ item.code }}</Tag>
|
<Tag v-if="option.data.raw.code" color="blue">
|
||||||
|
编号: {{ option.data.raw.code }}
|
||||||
|
</Tag>
|
||||||
</div>
|
</div>
|
||||||
</SelectOption>
|
</template>
|
||||||
</Select>
|
</Select>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import type { MesWmWarehouseApi } from '#/api/mes/wm/warehouse';
|
||||||
|
|
||||||
import { computed, onMounted, ref, useAttrs, watch } from 'vue';
|
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';
|
import { getWarehouseSimpleList } from '#/api/mes/wm/warehouse';
|
||||||
|
|
||||||
|
|
@ -32,6 +32,13 @@ const emit = defineEmits<{
|
||||||
const attrs = useAttrs();
|
const attrs = useAttrs();
|
||||||
const allList = ref<MesWmWarehouseApi.Warehouse[]>([]);
|
const allList = ref<MesWmWarehouseApi.Warehouse[]>([]);
|
||||||
const selectedItem = ref<MesWmWarehouseApi.Warehouse>();
|
const selectedItem = ref<MesWmWarehouseApi.Warehouse>();
|
||||||
|
const selectOptions = computed(() =>
|
||||||
|
allList.value.map((item) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
raw: item,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
const selectValue = computed({
|
const selectValue = computed({
|
||||||
get: () => props.modelValue,
|
get: () => props.modelValue,
|
||||||
|
|
@ -47,7 +54,7 @@ function handleChange(val: any) {
|
||||||
|
|
||||||
/** 前端过滤(name + code) */
|
/** 前端过滤(name + code) */
|
||||||
function filterOption(input: string, option: any) {
|
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) {
|
if (!item) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -97,14 +104,17 @@ onMounted(async () => {
|
||||||
:filter-option="filterOption"
|
:filter-option="filterOption"
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
show-search
|
show-search
|
||||||
|
:options="selectOptions"
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
>
|
>
|
||||||
<SelectOption v-for="item in allList" :key="item.id" :value="item.id">
|
<template #optionRender="{ option }">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<span>{{ item.name }}</span>
|
<span>{{ option.data.raw.name }}</span>
|
||||||
<Tag v-if="item.code" color="blue">编号: {{ item.code }}</Tag>
|
<Tag v-if="option.data.raw.code" color="blue">
|
||||||
|
编号: {{ option.data.raw.code }}
|
||||||
|
</Tag>
|
||||||
</div>
|
</div>
|
||||||
</SelectOption>
|
</template>
|
||||||
</Select>
|
</Select>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue