!369 feat(@vben/web-antdv-next): 补充 MES SN 详情并修复IM等模块兼容性问题

Merge pull request !369 from XuZhiqiang/feat-antdv-next
pull/368/MERGE
芋道源码 2026-06-20 17:29:31 +00:00 committed by Gitee
commit 31db712610
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
53 changed files with 404 additions and 485 deletions

View File

@ -12,6 +12,7 @@ export namespace CrmReceivableApi {
customerId?: number;
customerName?: string;
contractId?: number;
contractNo?: string;
contract?: Contract;
auditStatus: number;
processInstanceId: number;
@ -34,6 +35,11 @@ export namespace CrmReceivableApi {
no: string;
totalPrice: number;
}
export interface ReceivablePageParam extends PageParam {
contractId?: number;
customerId?: number;
}
}
/** 查询回款列表 */
@ -45,7 +51,9 @@ export function getReceivablePage(params: PageParam) {
}
/** 查询回款列表,基于指定客户 */
export function getReceivablePageByCustomer(params: PageParam) {
export function getReceivablePageByCustomer(
params: CrmReceivableApi.ReceivablePageParam,
) {
return requestClient.get<PageResult<CrmReceivableApi.Receivable>>(
'/crm/receivable/page-by-customer',
{ params },

View File

@ -17,6 +17,21 @@ export namespace MesWmSnApi {
createTime?: Date; // 生成时间
}
/** MES SN 码明细 */
export interface Sn {
id?: number; // 编号
uuid?: string; // 批次 UUID
code?: string; // SN 码
itemId?: number; // 物料编号
itemCode?: string; // 物料编码
itemName?: string; // 物料名称
specification?: string; // 规格型号
unitName?: string; // 单位名称
batchCode?: string; // 批次号
workOrderId?: number; // 生产工单编号
createTime?: Date; // 生成时间
}
/** MES SN 码生成参数 */
export interface SnGenerate {
itemId?: number; // 物料编号
@ -48,6 +63,13 @@ export function getSnGroupPage(params: MesWmSnApi.PageParams) {
);
}
/** 查询批次 SN 码明细列表 */
export function getSnListByUuid(uuid: string) {
return requestClient.get<MesWmSnApi.Sn[]>('/mes/wm/sn/list-by-uuid', {
params: { uuid },
});
}
/** 批量删除 SN 码(按批次 UUID */
export function deleteSnBatch(uuid: string) {
return requestClient.delete('/mes/wm/sn/delete-batch', {

View File

@ -136,9 +136,13 @@ function autoSearch(queryValue: string) {
}
/** 处理地址选择 */
function handleAddressSelect(value: string) {
if (value) {
regeoCode(value);
function handleAddressSelect(value: unknown) {
const selectedValue =
typeof value === 'object' && value !== null && 'value' in value
? (value as { value?: number | string }).value
: value;
if (selectedValue !== undefined && selectedValue !== null) {
regeoCode(String(selectedValue));
}
}

View File

@ -22,8 +22,6 @@ const document = ref<null | {
}[];
title: string;
}>(null); //
const dialogVisible = ref(false); //
const documentRef = ref<HTMLElement>(); // Ref
/** 按照 document 聚合 segments */
const documentList = computed(() => {
@ -49,7 +47,6 @@ const documentList = computed(() => {
/** 点击 document 处理 */
function handleClick(doc: any) {
document.value = doc;
dialogVisible.value = true;
}
</script>
@ -79,7 +76,7 @@ function handleClick(doc: any) {
</div>
</div>
<Tooltip placement="topLeft" :trigger="['click']">
<div ref="documentRef"></div>
<div></div>
<template #title>
<div class="mb-3 text-base font-bold">{{ document?.title }}</div>
<div class="max-h-[60vh] overflow-y-auto">

View File

@ -19,8 +19,6 @@ const props = defineProps({
});
const emits = defineEmits(['onBtnClick', 'onMjBtnClick']);
const cardImageRef = ref<any>(); // image ref
/** 处理点击事件 */
async function handleButtonClick(type: string, detail: AiImageApi.Image) {
emits('onBtnClick', type, detail);
@ -110,7 +108,7 @@ onMounted(async () => {
</div>
<!-- 图片展示区域 -->
<div class="mt-5 h-72 flex-1 overflow-hidden" ref="cardImageRef">
<div class="mt-5 h-72 flex-1 overflow-hidden">
<Image class="w-full rounded-lg" :src="detail?.picUrl" />
<div v-if="detail?.status === AiImageStatusEnum.FAIL">
{{ detail?.errorMessage }}

View File

@ -33,7 +33,6 @@ const queryParams = reactive({
}); //
const pageTotal = ref<number>(0); // page size
const imageList = ref<AiImageApi.Image[]>([]); // image
const imageListRef = ref<any>(); // ref
const inProgressImageMap = ref<{}>({}); // image key image value image
const inProgressTimer = ref<any>(); // image
@ -192,7 +191,6 @@ onUnmounted(async () => {
<div
class="flex flex-1 flex-wrap content-start overflow-y-auto p-3 pb-28 pt-5"
ref="imageListRef"
>
<ImageCard
v-for="image in imageList"

View File

@ -44,8 +44,8 @@ const currentFile = ref<any>(null); // 当前选中的文件
const submitLoading = ref(false); //
/** 选择文件 */
async function selectFile(index: number) {
currentFile.value = modelData.value.list[index];
async function selectFile(index: number | string) {
currentFile.value = modelData.value.list[Number(index)];
await splitContentFile(currentFile.value);
}
@ -258,7 +258,8 @@ onMounted(async () => {
class="mb-2.5"
>
<div class="mb-1 text-sm text-gray-500">
分片-{{ index + 1 }} · {{ segment.contentLength || 0 }} 字符数 ·
分片-{{ Number(index) + 1 }} ·
{{ segment.contentLength || 0 }} 字符数 ·
{{ segment.tokens || 0 }} Token
</div>
<div class="rounded-md bg-card p-2">

View File

@ -22,8 +22,6 @@ const props = defineProps({
});
const emit = defineEmits(['update:modelValue']);
const formRef = ref(); //
const uploadRef = ref(); //
const parent = inject('parent', null); //
const { uploadUrl, httpRequest } = useUpload(); // 使
const fileList = ref<UploadProps['fileList']>([]); //
@ -147,10 +145,10 @@ async function customRequest(info: UploadRequestOption) {
*
* @param index 要移除的文件索引
*/
function removeFile(index: number) {
function removeFile(index: number | string) {
//
const newList = [...props.modelValue.list];
newList.splice(index, 1);
newList.splice(Number(index), 1);
//
emit('update:modelValue', {
...props.modelValue,
@ -185,14 +183,13 @@ onMounted(() => {
</script>
<template>
<Form ref="formRef" :model="modelData" label-width="0" class="mt-5">
<Form :model="modelData" label-width="0" class="mt-5">
<FormItem class="mb-5">
<div class="w-full">
<div
class="w-full rounded-md border-2 border-dashed border-gray-200 p-5 text-center hover:border-blue-500"
>
<UploadDragger
ref="uploadRef"
class="upload-demo"
:action="uploadUrl"
v-model:file-list="fileList"

View File

@ -1,4 +1,3 @@
<!-- eslint-disable no-unused-vars -->
<script lang="ts" setup>
import { computed, inject, nextTick, onMounted, ref, toRaw, watch } from 'vue';
@ -24,26 +23,7 @@ const prefix = inject('prefix');
const formKey = ref<number | string | undefined>(undefined);
const businessKey = ref('');
const optionModelTitle = ref('');
const fieldList = ref<any[]>([]);
const formFieldForm = ref<any>({});
const fieldType = ref({
long: '长整型',
string: '字符串',
boolean: '布尔类',
date: '日期类',
enum: '枚举类',
custom: '自定义类型',
});
const formFieldIndex = ref(-1); // -1
const formFieldOptionIndex = ref(-1); // -1
const fieldModelVisible = ref(false);
const fieldOptionModelVisible = ref(false);
const fieldOptionForm = ref<any>({}); //
const fieldOptionType = ref(''); //
const fieldEnumList = ref<any[]>([]); //
const fieldConstraintsList = ref<any[]>([]); //
const fieldPropertiesList = ref<any[]>([]); //
const bpmnELement = ref();
const elExtensionElements = ref();
const formData = ref();
@ -94,173 +74,6 @@ const _updateElementBusinessKey = () => {
},
);
};
// type
const _changeFieldTypeType = (type: any) => {
formFieldForm.value.type = type === 'custom' ? '' : type;
};
//
const _openFieldForm = (field: any, index: any) => {
formFieldIndex.value = index;
if (index === -1) {
formFieldForm.value = {};
//
fieldEnumList.value = [];
//
fieldConstraintsList.value = [];
//
fieldPropertiesList.value = [];
} else {
const FieldObject = formData.value.fields[index];
formFieldForm.value = cloneDeep(field);
//
// this.$set(this.formFieldForm, "typeType", !this.fieldType[field.type] ? "custom" : field.type);
formFieldForm.value.typeType = fieldType.value[
field.type as keyof typeof fieldType.value
]
? field.type
: 'custom';
//
field.type === 'enum' &&
(fieldEnumList.value = cloneDeep(FieldObject?.values || []));
//
fieldConstraintsList.value = cloneDeep(
FieldObject?.validation?.constraints || [],
);
//
fieldPropertiesList.value = cloneDeep(
FieldObject?.properties?.values || [],
);
}
fieldModelVisible.value = true;
};
//
const _openFieldOptionForm = (option: any, index: any, type: any) => {
fieldOptionModelVisible.value = true;
fieldOptionType.value = type;
formFieldOptionIndex.value = index;
if (type === 'property') {
fieldOptionForm.value = option ? cloneDeep(option) : {};
return (optionModelTitle.value = '属性配置');
}
if (type === 'enum') {
fieldOptionForm.value = option ? cloneDeep(option) : {};
return (optionModelTitle.value = '枚举值配置');
}
fieldOptionForm.value = option ? cloneDeep(option) : {};
return (optionModelTitle.value = '约束条件配置');
};
//
const _saveFieldOption = () => {
if (formFieldOptionIndex.value === -1) {
if (fieldOptionType.value === 'property') {
fieldPropertiesList.value.push(fieldOptionForm.value);
}
if (fieldOptionType.value === 'constraint') {
fieldConstraintsList.value.push(fieldOptionForm.value);
}
if (fieldOptionType.value === 'enum') {
fieldEnumList.value.push(fieldOptionForm.value);
}
} else {
fieldOptionType.value === 'property' &&
fieldPropertiesList.value.splice(
formFieldOptionIndex.value,
1,
fieldOptionForm.value,
);
fieldOptionType.value === 'constraint' &&
fieldConstraintsList.value.splice(
formFieldOptionIndex.value,
1,
fieldOptionForm.value,
);
fieldOptionType.value === 'enum' &&
fieldEnumList.value.splice(
formFieldOptionIndex.value,
1,
fieldOptionForm.value,
);
}
fieldOptionModelVisible.value = false;
fieldOptionForm.value = {};
};
//
const _saveField = () => {
const { id, type, label, defaultValue, datePattern } = formFieldForm.value;
const Field = bpmnInstances().moddle.create(`${prefix}:FormField`, {
id,
type,
label,
});
defaultValue && (Field.defaultValue = defaultValue);
datePattern && (Field.datePattern = datePattern);
//
if (fieldPropertiesList.value && fieldPropertiesList.value.length > 0) {
const fieldPropertyList = fieldPropertiesList.value.map((fp: any) => {
return bpmnInstances().moddle.create(`${prefix}:Property`, {
id: fp.id,
value: fp.value,
});
});
Field.properties = bpmnInstances().moddle.create(`${prefix}:Properties`, {
values: fieldPropertyList,
});
}
//
if (fieldConstraintsList.value && fieldConstraintsList.value.length > 0) {
const fieldConstraintList = fieldConstraintsList.value.map((fc: any) => {
return bpmnInstances().moddle.create(`${prefix}:Constraint`, {
name: fc.name,
config: fc.config,
});
});
Field.validation = bpmnInstances().moddle.create(`${prefix}:Validation`, {
constraints: fieldConstraintList,
});
}
//
if (fieldEnumList.value && fieldEnumList.value.length > 0) {
Field.values = fieldEnumList.value.map((fe: any) => {
return bpmnInstances().moddle.create(`${prefix}:Value`, {
name: fe.name,
id: fe.id,
});
});
}
//
if (formFieldIndex.value === -1) {
fieldList.value.push(formFieldForm.value);
formData.value.fields.push(Field);
} else {
fieldList.value.splice(formFieldIndex.value, 1, formFieldForm.value);
formData.value.fields.splice(formFieldIndex.value, 1, Field);
}
updateElementExtensions();
fieldModelVisible.value = false;
};
//
const _removeFieldOptionItem = (_option: any, index: any, type: any) => {
// console.log(option, 'option')
if (type === 'property') {
fieldPropertiesList.value.splice(index, 1);
return;
}
if (type === 'enum') {
fieldEnumList.value.splice(index, 1);
return;
}
fieldConstraintsList.value.splice(index, 1);
};
//
const _removeField = (field: any, index: any) => {
console.warn(field, 'field');
fieldList.value.splice(index, 1);
formData.value.fields.splice(index, 1);
updateElementExtensions();
};
const updateElementExtensions = () => {
//
@ -328,210 +141,5 @@ watch(
/>
</FormItem>
</Form>
<!--字段列表-->
<!-- <div class="element-property list-property">-->
<!-- <Divider><Icon icon="ep:coin" /> 表单字段</Divider>-->
<!-- <Table :data-source="fieldList" :scroll="{ y: 240 }" bordered>-->
<!-- <TableColumn title="序号" type="index" width="50px" />-->
<!-- <TableColumn title="字段名称" dataIndex="label" width="80px" :ellipsis="true" />-->
<!-- <TableColumn-->
<!-- title="字段类型"-->
<!-- dataIndex="type"-->
<!-- width="80px"-->
<!-- :customRender="({ text }) => fieldType[text] || text"-->
<!-- :ellipsis="true"-->
<!-- />-->
<!-- <TableColumn-->
<!-- title="默认值"-->
<!-- dataIndex="defaultValue"-->
<!-- width="80px"-->
<!-- :ellipsis="true"-->
<!-- />-->
<!-- <TableColumn title="操作" width="90px">-->
<!-- <template #default="scope">-->
<!-- <Button type="link" @click="openFieldForm(scope, scope.$index)">-->
<!-- 编辑-->
<!-- </Button>-->
<!-- <Divider type="vertical" />-->
<!-- <Button-->
<!-- type="link"-->
<!-- danger-->
<!-- @click="removeField(scope, scope.$index)"-->
<!-- >-->
<!-- 移除-->
<!-- </Button>-->
<!-- </template>-->
<!-- </TableColumn>-->
<!-- </Table>-->
<!-- </div>-->
<!-- <div class="element-drawer__button">-->
<!-- <Button type="primary" @click="openFieldForm(null, -1)">添加字段</Button>-->
<!-- </div>-->
<!--字段配置侧边栏-->
<!-- <Drawer-->
<!-- v-model:open="fieldModelVisible"-->
<!-- title="字段配置"-->
<!-- :width="`${width}px`"-->
<!-- destroyOnClose-->
<!-- >-->
<!-- <Form :model="formFieldForm" :label-col="{ style: { width: '90px' } }">-->
<!-- <FormItem label="字段ID">-->
<!-- <Input v-model:value="formFieldForm.id" allowClear />-->
<!-- </FormItem>-->
<!-- <FormItem label="类型">-->
<!-- <Select-->
<!-- v-model:value="formFieldForm.typeType"-->
<!-- placeholder="请选择字段类型"-->
<!-- allowClear-->
<!-- @change="changeFieldTypeType"-->
<!-- >-->
<!-- </Select>-->
<!-- </FormItem>-->
<!-- <FormItem label="类型名称" v-if="formFieldForm.typeType === 'custom'">-->
<!-- <Input v-model:value="formFieldForm.type" allowClear />-->
<!-- </FormItem>-->
<!-- <FormItem label="名称">-->
<!-- <Input v-model:value="formFieldForm.label" allowClear />-->
<!-- </FormItem>-->
<!-- <FormItem label="时间格式" v-if="formFieldForm.typeType === 'date'">-->
<!-- <Input v-model:value="formFieldForm.datePattern" allowClear />-->
<!-- </FormItem>-->
<!-- <FormItem label="默认值">-->
<!-- <Input v-model:value="formFieldForm.defaultValue" allowClear />-->
<!-- </FormItem>-->
<!-- </Form>-->
<!-- &lt;!&ndash; 枚举值设置 &ndash;&gt;-->
<!-- <template v-if="formFieldForm.type === 'enum'">-->
<!-- <Divider key="enum-divider" />-->
<!-- <p class="listener-filed__title" key="enum-title">-->
<!-- <span><Icon icon="ep:menu" />枚举值列表</span>-->
<!-- <Button type="primary" @click="openFieldOptionForm(null, -1, 'enum')"-->
<!-- >添加枚举值</Button-->
<!-- >-->
<!-- </p>-->
<!-- <Table :data-source="fieldEnumList" key="enum-table" :scroll="{ y: 240 }" bordered>-->
<!-- <TableColumn title="序号" width="50px" type="index" />-->
<!-- <TableColumn title="枚举值编号" dataIndex="id" width="100px" :ellipsis="true" />-->
<!-- <TableColumn title="枚举值名称" dataIndex="name" width="100px" :ellipsis="true" />-->
<!-- <TableColumn title="操作" width="90px">-->
<!-- <template #default="scope">-->
<!-- <Button-->
<!-- type="link"-->
<!-- @click="openFieldOptionForm(scope, scope.$index, 'enum')"-->
<!-- >-->
<!-- 编辑-->
<!-- </Button>-->
<!-- <Divider type="vertical" />-->
<!-- <Button-->
<!-- type="link"-->
<!-- danger-->
<!-- @click="removeFieldOptionItem(scope, scope.$index, 'enum')"-->
<!-- >-->
<!-- 移除-->
<!-- </Button>-->
<!-- </template>-->
<!-- </TableColumn>-->
<!-- </Table>-->
<!-- </template>-->
<!-- &lt;!&ndash; 校验规则 &ndash;&gt;-->
<!-- <Divider key="validation-divider" />-->
<!-- <p class="listener-filed__title" key="validation-title">-->
<!-- <span><Icon icon="ep:menu" />约束条件列表</span>-->
<!-- <Button type="primary" @click="openFieldOptionForm(null, -1, 'constraint')"-->
<!-- >添加约束</Button-->
<!-- >-->
<!-- </p>-->
<!-- <Table :data-source="fieldConstraintsList" key="validation-table" :scroll="{ y: 240 }" bordered>-->
<!-- <TableColumn title="序号" width="50px" type="index" />-->
<!-- <TableColumn title="约束名称" dataIndex="name" width="100px" :ellipsis="true" />-->
<!-- <TableColumn title="约束配置" dataIndex="config" width="100px" :ellipsis="true" />-->
<!-- <TableColumn title="操作" width="90px">-->
<!-- <template #default="scope">-->
<!-- <Button-->
<!-- type="link"-->
<!-- @click="openFieldOptionForm(scope, scope.$index, 'constraint')"-->
<!-- >-->
<!-- 编辑-->
<!-- </Button>-->
<!-- <Divider type="vertical" />-->
<!-- <Button-->
<!-- type="link"-->
<!-- danger-->
<!-- @click="removeFieldOptionItem(scope, scope.$index, 'constraint')"-->
<!-- >-->
<!-- 移除-->
<!-- </Button>-->
<!-- </template>-->
<!-- </TableColumn>-->
<!-- </Table>-->
<!-- &lt;!&ndash; 表单属性 &ndash;&gt;-->
<!-- <Divider key="property-divider" />-->
<!-- <p class="listener-filed__title" key="property-title">-->
<!-- <span><Icon icon="ep:menu" />字段属性列表</span>-->
<!-- <Button type="primary" @click="openFieldOptionForm(null, -1, 'property')"-->
<!-- >添加属性</Button-->
<!-- >-->
<!-- </p>-->
<!-- <Table :data-source="fieldPropertiesList" key="property-table" :scroll="{ y: 240 }" bordered>-->
<!-- <TableColumn title="序号" width="50px" type="index" />-->
<!-- <TableColumn title="属性编号" dataIndex="id" width="100px" :ellipsis="true" />-->
<!-- <TableColumn title="属性值" dataIndex="value" width="100px" :ellipsis="true" />-->
<!-- <TableColumn title="操作" width="90px">-->
<!-- <template #default="scope">-->
<!-- <Button-->
<!-- type="link"-->
<!-- @click="openFieldOptionForm(scope, scope.$index, 'property')"-->
<!-- >-->
<!-- 编辑-->
<!-- </Button>-->
<!-- <Divider type="vertical" />-->
<!-- <Button-->
<!-- type="link"-->
<!-- danger-->
<!-- @click="removeFieldOptionItem(scope, scope.$index, 'property')"-->
<!-- >-->
<!-- 移除-->
<!-- </Button>-->
<!-- </template>-->
<!-- </TableColumn>-->
<!-- </Table>-->
<!-- &lt;!&ndash; 底部按钮 &ndash;&gt;-->
<!-- <div class="element-drawer__button">-->
<!-- <Button> </Button>-->
<!-- <Button type="primary" @click="saveField"> </Button>-->
<!-- </div>-->
<!-- </Drawer>-->
<!-- <Modal-->
<!-- v-model:open="fieldOptionModelVisible"-->
<!-- :title="optionModelTitle"-->
<!-- width="600px"-->
<!-- destroyOnClose-->
<!-- >-->
<!-- <Form :model="fieldOptionForm" :label-col="{ style: { width: '96px' } }">-->
<!-- <FormItem label="编号/ID" v-if="fieldOptionType !== 'constraint'" key="option-id">-->
<!-- <Input v-model:value="fieldOptionForm.id" allowClear />-->
<!-- </FormItem>-->
<!-- <FormItem label="名称" v-if="fieldOptionType !== 'property'" key="option-name">-->
<!-- <Input v-model:value="fieldOptionForm.name" allowClear />-->
<!-- </FormItem>-->
<!-- <FormItem label="配置" v-if="fieldOptionType === 'constraint'" key="option-config">-->
<!-- <Input v-model:value="fieldOptionForm.config" allowClear />-->
<!-- </FormItem>-->
<!-- <FormItem label="值" v-if="fieldOptionType === 'property'" key="option-value">-->
<!-- <Input v-model:value="fieldOptionForm.value" allowClear />-->
<!-- </FormItem>-->
<!-- </Form>-->
<!-- <template #footer>-->
<!-- <Button @click="fieldOptionModelVisible = false"> </Button>-->
<!-- <Button type="primary" @click="saveFieldOption"> </Button>-->
<!-- </template>-->
<!-- </Modal>-->
</div>
</template>

View File

@ -32,7 +32,7 @@ const props = defineProps({
default: '',
},
});
const prefix = inject('prefix');
const prefix = inject<string>('prefix', 'flowable');
const elementListenersList = ref<any[]>([]); //
const listenerForm = ref<any>({}); //
const fieldsListOfListener = ref<any[]>([]);

View File

@ -30,7 +30,7 @@ interface Props {
type?: string;
}
const prefix = inject<string>('prefix');
const prefix = inject<string>('prefix', 'flowable');
const elementListenersList = ref<any[]>([]);
const listenerEventTypeObject = ref(eventType);

View File

@ -1,4 +1,6 @@
<script lang="ts" setup>
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { inject, nextTick, ref, watch } from 'vue';
import { confirm, useVbenModal } from '@vben/common-ui';
@ -151,7 +153,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
pagerConfig: {
enabled: false,
},
},
} as VxeTableGridOptions<{ name: string; value: string }>,
});
const [FieldModal, fieldModalApi] = useVbenModal({

View File

@ -1,7 +1,35 @@
const bpmnInstances = () => (window as any)?.bpmnInstances;
interface ListenerFieldOptions {
expression?: string;
fieldType: string;
name: string;
string?: string;
}
interface ListenerOptions {
class?: string;
delegateExpression?: string;
event?: string;
eventDefinitionType?: string;
eventTimeDefinitions?: string;
expression?: string;
fields?: ListenerFieldOptions[];
id?: string;
listenerType?: string;
resource?: string;
scriptFormat?: string;
scriptType?: string;
value?: string;
}
// 创建监听器实例
export function createListenerObject(options, isTask, prefix) {
const listenerObj = Object.create(null);
export function createListenerObject(
options: ListenerOptions,
isTask: boolean,
prefix: string,
) {
const listenerObj: Record<string, any> = Object.create(null);
listenerObj.event = options.event;
isTask && (listenerObj.id = options.id); // 任务监听器特有的 id 字段
switch (options.listenerType) {
@ -52,7 +80,10 @@ export function createListenerObject(options, isTask, prefix) {
}
// 创建 监听器的注入字段 实例
export function createFieldObject(option, prefix) {
export function createFieldObject(
option: ListenerFieldOptions,
prefix: string,
) {
const { name, fieldType, string, expression } = option;
const fieldConfig =
fieldType === 'string' ? { name, string } : { name, expression };
@ -60,7 +91,7 @@ export function createFieldObject(option, prefix) {
}
// 创建脚本实例
export function createScriptObject(options, prefix) {
export function createScriptObject(options: ListenerOptions, prefix: string) {
const { scriptType, scriptFormat, value, resource } = options;
const scriptConfig =
scriptType === 'inlineScript'
@ -70,7 +101,7 @@ export function createScriptObject(options, prefix) {
}
// 更新元素扩展属性
export function updateElementExtensions(element, extensionList) {
export function updateElementExtensions(element: any, extensionList: any[]) {
const extensions = bpmnInstances().moddle.create('bpmn:ExtensionElements', {
values: extensionList,
});

View File

@ -64,6 +64,11 @@ const currentNode = useWatchNode(props);
/** 节点名称配置 */
const { nodeName, showInput, clickIcon, changeNodeName, inputRef } =
useNodeName(BpmNodeTypeEnum.CHILD_PROCESS_NODE);
function setInputRef(el: unknown) {
inputRef.value = el as HTMLInputElement | null;
}
// Tab
const activeTabName = ref('child');
//
@ -389,7 +394,7 @@ onMounted(async () => {
<div class="config-header">
<Input
v-if="showInput"
ref="inputRef"
:ref="setInputRef"
type="text"
class="focus:border-blue-500 focus:shadow-[0_0_0_2px_rgba(24,144,255,0.2)] focus:outline-none"
@blur="changeNodeName()"

View File

@ -74,6 +74,10 @@ const currentNode = useWatchNode(props);
const { nodeName, showInput, clickIcon, changeNodeName, inputRef } =
useNodeName(BpmNodeTypeEnum.COPY_TASK_NODE);
function setInputRef(el: unknown) {
inputRef.value = el as HTMLInputElement | null;
}
// Tab
const activeTabName = ref('user');
@ -208,7 +212,7 @@ defineExpose({ showCopyTaskNodeConfig }); // 暴露方法给父组件
<div class="config-header">
<Input
v-if="showInput"
ref="inputRef"
:ref="setInputRef"
type="text"
class="focus:border-blue-500 focus:shadow-[0_0_0_2px_rgba(24,144,255,0.2)] focus:outline-none"
@blur="changeNodeName()"

View File

@ -44,6 +44,11 @@ const currentNode = useWatchNode(props);
//
const { nodeName, showInput, clickIcon, changeNodeName, inputRef } =
useNodeName(BpmNodeTypeEnum.DELAY_TIMER_NODE);
function setInputRef(el: unknown) {
inputRef.value = el as HTMLInputElement | null;
}
//
const formRef = ref(); // Ref
@ -154,7 +159,7 @@ defineExpose({ openDrawer }); // 暴露方法给父组件
<div class="flex items-center">
<Input
v-if="showInput"
ref="inputRef"
:ref="setInputRef"
type="text"
class="mr-2 w-48"
@blur="changeNodeName()"

View File

@ -103,21 +103,21 @@ function changeConditionType() {
}
}
function deleteConditionGroup(conditions: any, index: number) {
conditions.splice(index, 1);
function deleteConditionGroup(conditions: any, index: number | string) {
conditions.splice(Number(index), 1);
}
function deleteConditionRule(condition: any, index: number) {
condition.rules.splice(index, 1);
function deleteConditionRule(condition: any, index: number | string) {
condition.rules.splice(Number(index), 1);
}
function addConditionRule(condition: any, index: number) {
function addConditionRule(condition: any, index: number | string) {
const rule = {
opCode: '==',
leftSide: undefined,
rightSide: '',
};
condition.rules.splice(index + 1, 0, rule);
condition.rules.splice(Number(index) + 1, 0, rule);
}
function addConditionGroup(conditions: any) {

View File

@ -50,9 +50,9 @@ function addHttpResponseSetting(responseSetting: Record<string, string>[]) {
/** 删除 HTTP 请求返回值设置项 */
function deleteHttpResponseSetting(
responseSetting: Record<string, string>[],
index: number,
index: number | string,
) {
responseSetting.splice(index, 1);
responseSetting.splice(Number(index), 1);
}
</script>
<template>

View File

@ -41,6 +41,11 @@ const currentNode = useWatchNode(props);
/** 节点名称 */
const { nodeName, showInput, clickIcon, changeNodeName, inputRef } =
useNodeName(BpmNodeTypeEnum.ROUTER_BRANCH_NODE);
function setInputRef(el: unknown) {
inputRef.value = el as HTMLInputElement | null;
}
const routerGroups = ref<RouterSetting[]>([]);
const nodeOptions = ref<any[]>([]);
const conditionRef = ref<any[]>([]);
@ -202,7 +207,7 @@ defineExpose({ openDrawer }); // 暴露方法给父组件
<template #title>
<div class="flex items-center">
<Input
ref="inputRef"
:ref="setInputRef"
v-if="showInput"
type="text"
class="mr-2 w-48"

View File

@ -53,6 +53,11 @@ const currentNode = useWatchNode(props);
//
const { nodeName, showInput, clickIcon, changeNodeName, inputRef } =
useNodeName(BpmNodeTypeEnum.START_USER_NODE);
function setInputRef(el: unknown) {
inputRef.value = el as HTMLInputElement | null;
}
// Tab
const activeTabName = ref('user');
@ -144,7 +149,7 @@ defineExpose({ showStartUserNodeConfig });
<template #title>
<div class="config-header">
<Input
ref="inputRef"
:ref="setInputRef"
v-if="showInput"
type="text"
class="focus:border-blue-500 focus:shadow-[0_0_0_2px_rgba(24,144,255,0.2)] focus:outline-none"

View File

@ -39,6 +39,10 @@ const { showInput, changeNodeName, clickTitle, inputRef } = useNodeName2(
BpmNodeTypeEnum.TRIGGER_NODE,
);
function setInputRef(el: unknown) {
inputRef.value = el as HTMLInputElement | null;
}
const nodeSetting = ref();
//
function openNodeConfig() {
@ -68,7 +72,7 @@ function deleteNode() {
<span class="iconfont icon-trigger"></span>
</div>
<Input
ref="inputRef"
:ref="setInputRef"
v-if="!readonly && showInput"
type="text"
class="editable-title-input"

View File

@ -47,7 +47,7 @@ const [Grid] = useVbenVxeGrid({
toolbarConfig: {
enabled: false,
},
},
} as VxeTableGridOptions<BpmProcessExpressionApi.ProcessExpression>,
});
// Modal
@ -88,7 +88,7 @@ function useGridFormSchema(): VbenFormSchema[] {
},
];
}
function useGridColumns(): VxeTableGridOptions['columns'] {
function useGridColumns(): VxeTableGridOptions<BpmProcessExpressionApi.ProcessExpression>['columns'] {
return [
{ field: 'name', title: '名字', minWidth: 160 },
{ field: 'expression', title: '表达式', minWidth: 260 },

View File

@ -79,7 +79,6 @@ const tempStartUserSelectAssignees = ref<Record<string, string[]>>({});
const bpmnXML = ref<string | undefined>(undefined);
const simpleJson = ref<string | undefined>(undefined);
const timelineRef = ref<any>();
const activeTab = ref('form');
const activityNodes = ref<BpmProcessInstanceApi.ApprovalNodeInfo[]>([]);
const processInstanceStartLoading = ref(false);
@ -314,7 +313,6 @@ defineExpose({ initProcessInfo });
</Col>
<Col :xs="24" :sm="24" :md="6" :lg="6" :xl="6">
<ProcessInstanceTimeline
ref="timelineRef"
:activity-nodes="activityNodes"
:show-status-icon="false"
@select-user-confirm="selectUserConfirm"

View File

@ -1,5 +1,8 @@
<script lang="ts" setup>
import type { VxeGridPropTypes } from '#/adapter/vxe-table';
import type {
VxeGridPropTypes,
VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { BpmProcessListenerApi } from '#/api/bpm/processListener';
import { ref } from 'vue';
@ -47,7 +50,7 @@ const [Grid] = useVbenVxeGrid({
toolbarConfig: {
enabled: false,
},
},
} as VxeTableGridOptions<BpmProcessListenerApi.ProcessListener>,
});
// Modal

View File

@ -65,7 +65,12 @@ defineExpose({ open });
</script>
<template>
<Drawer v-model:open="visible" destroy-on-hidden title="群详情" :styles="{ wrapper: { width: '900px' } }">
<Drawer
v-model:open="visible"
destroy-on-hidden
title="群详情"
:styles="{ wrapper: { width: '900px' } }"
>
<Descriptions bordered :column="2">
<DescriptionsItem label="群编号">{{ detail.id }}</DescriptionsItem>
<DescriptionsItem label="群名称">{{ detail.name }}</DescriptionsItem>
@ -77,12 +82,17 @@ defineExpose({ open });
<DescriptionsItem label="群主">
{{ formatUserLabel(detail.ownerNickname, detail.ownerUserId) }}
</DescriptionsItem>
<DescriptionsItem label="成员数">{{ detail.memberCount || 0 }}</DescriptionsItem>
<DescriptionsItem label="成员数">
{{ detail.memberCount || 0 }}
</DescriptionsItem>
<DescriptionsItem label="群状态">
<DictTag :type="DICT_TYPE.IM_GROUP_STATUS" :value="detail.status" />
</DescriptionsItem>
<DescriptionsItem label="封禁状态">
<DictTag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="detail.banned" />
<DictTag
:type="DICT_TYPE.INFRA_BOOLEAN_STRING"
:value="detail.banned"
/>
<span v-if="detail.banned" class="ml-2 text-gray-400">
{{ detail.bannedReason }}
</span>
@ -112,17 +122,23 @@ defineExpose({ open });
row-key="userId"
size="small"
>
<template #bodyCell="{ column, record }">
<template #bodyCell="{ column, record, text }">
<template v-if="column.dataIndex === 'avatar'">
<Avatar :src="record.avatar" :size="40">
{{ record.nickname?.charAt(0) || '?' }}
</Avatar>
</template>
<template v-else-if="column.dataIndex === 'role'">
<DictTag :type="DICT_TYPE.IM_GROUP_MEMBER_ROLE" :value="record.role" />
<DictTag
:type="DICT_TYPE.IM_GROUP_MEMBER_ROLE"
:value="record.role"
/>
</template>
<template v-else-if="column.dataIndex === 'silent'">
<DictTag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="record.silent" />
<DictTag
:type="DICT_TYPE.INFRA_BOOLEAN_STRING"
:value="record.silent"
/>
</template>
<template v-else-if="column.dataIndex === 'status'">
<DictTag :type="DICT_TYPE.COMMON_STATUS" :value="record.status" />
@ -134,7 +150,11 @@ defineExpose({ open });
{{ formatDateTimeText(record.quitTime) }}
</template>
<template v-else-if="column.dataIndex === 'muteEndTime'">
<template v-if="record.muteEndTime && new Date(record.muteEndTime) > new Date()">
<template
v-if="
record.muteEndTime && new Date(record.muteEndTime) > new Date()
"
>
<Tag color="error">禁言中</Tag>
<div class="mt-1 text-xs text-gray-400">
{{ formatDateTimeText(record.muteEndTime) }}
@ -143,7 +163,7 @@ defineExpose({ open });
<span v-else>-</span>
</template>
<template v-else>
{{ record[column.dataIndex] || '-' }}
{{ text || '-' }}
</template>
</template>
</Table>

View File

@ -51,21 +51,34 @@ defineExpose({ open });
</script>
<template>
<Drawer v-model:open="visible" destroy-on-hidden title="通话记录详情" :styles="{ wrapper: { width: '900px' } }">
<Drawer
v-model:open="visible"
destroy-on-hidden
title="通话记录详情"
:styles="{ wrapper: { width: '900px' } }"
>
<Descriptions bordered :column="2">
<DescriptionsItem label="编号">{{ detail.id }}</DescriptionsItem>
<DescriptionsItem label="业务通话编号">{{ detail.room }}</DescriptionsItem>
<DescriptionsItem label="业务通话编号">
{{ detail.room }}
</DescriptionsItem>
<DescriptionsItem label="发起人">
{{ formatUserLabel(detail.inviterNickname, detail.inviterUserId) }}
</DescriptionsItem>
<DescriptionsItem label="会话类型">
<DictTag :type="DICT_TYPE.IM_RTC_CALL_CONVERSATION_TYPE" :value="detail.conversationType" />
<DictTag
:type="DICT_TYPE.IM_RTC_CALL_CONVERSATION_TYPE"
:value="detail.conversationType"
/>
</DescriptionsItem>
<DescriptionsItem label="群">
{{ formatGroupLabel(detail.groupName, detail.groupId) }}
</DescriptionsItem>
<DescriptionsItem label="媒体类型">
<DictTag :type="DICT_TYPE.IM_RTC_CALL_MEDIA_TYPE" :value="detail.mediaType" />
<DictTag
:type="DICT_TYPE.IM_RTC_CALL_MEDIA_TYPE"
:value="detail.mediaType"
/>
</DescriptionsItem>
<DescriptionsItem label="通话状态">
<DictTag :type="DICT_TYPE.IM_RTC_CALL_STATUS" :value="detail.status" />
@ -100,18 +113,30 @@ defineExpose({ open });
row-key="id"
size="small"
>
<template #bodyCell="{ column, record }">
<template #bodyCell="{ column, record, text }">
<template v-if="column.dataIndex === 'role'">
<DictTag :type="DICT_TYPE.IM_RTC_PARTICIPANT_ROLE" :value="record.role" />
<DictTag
:type="DICT_TYPE.IM_RTC_PARTICIPANT_ROLE"
:value="record.role"
/>
</template>
<template v-else-if="column.dataIndex === 'status'">
<DictTag :type="DICT_TYPE.IM_RTC_PARTICIPANT_STATUS" :value="record.status" />
<DictTag
:type="DICT_TYPE.IM_RTC_PARTICIPANT_STATUS"
:value="record.status"
/>
</template>
<template v-else-if="['inviteTime', 'acceptTime', 'leaveTime'].includes(column.dataIndex as string)">
{{ formatDateTimeText(record[column.dataIndex]) }}
<template
v-else-if="
['inviteTime', 'acceptTime', 'leaveTime'].includes(
column.dataIndex as string,
)
"
>
{{ formatDateTimeText(text) }}
</template>
<template v-else>
{{ record[column.dataIndex] || '-' }}
{{ text || '-' }}
</template>
</template>
</Table>

View File

@ -144,7 +144,7 @@ defineExpose({ open: openModal });
v-model:open="open"
title="班组选择"
width="720px"
:destroy-on-close="true"
:destroy-on-hidden="true"
@ok="handleConfirm"
@cancel="closeModal"
>

View File

@ -210,7 +210,7 @@ defineExpose({ open: openModal });
v-model:open="open"
title="点检方案选择"
width="70%"
:destroy-on-close="true"
:destroy-on-hidden="true"
@ok="handleConfirm"
@cancel="closeModal"
>

View File

@ -219,7 +219,7 @@ defineExpose({ open: openModal });
v-model:open="open"
title="设备选择"
width="80%"
:destroy-on-close="true"
:destroy-on-hidden="true"
@ok="handleConfirm"
@cancel="closeModal"
>

View File

@ -203,7 +203,7 @@ defineExpose({ open: openModal });
v-model:open="open"
title="客户选择"
width="70%"
:destroy-on-close="true"
:destroy-on-hidden="true"
@ok="handleConfirm"
@cancel="closeModal"
>

View File

@ -107,7 +107,7 @@ defineExpose({ open: openModal });
v-model:open="open"
title="产品 BOM 物料选择"
width="800px"
:destroy-on-close="true"
:destroy-on-hidden="true"
@ok="handleConfirm"
@cancel="closeModal"
>

View File

@ -213,7 +213,7 @@ defineExpose({ open: openModal });
v-model:open="open"
title="物料产品选择"
width="80%"
:destroy-on-close="true"
:destroy-on-hidden="true"
@ok="handleConfirm"
@cancel="closeModal"
>

View File

@ -203,7 +203,7 @@ defineExpose({ open: openModal });
v-model:open="open"
title="供应商选择"
width="70%"
:destroy-on-close="true"
:destroy-on-hidden="true"
@ok="handleConfirm"
@cancel="closeModal"
>

View File

@ -212,7 +212,7 @@ defineExpose({ open: openModal });
v-model:open="open"
title="工作站选择"
width="70%"
:destroy-on-close="true"
:destroy-on-hidden="true"
@ok="handleConfirm"
@cancel="closeModal"
>

View File

@ -189,7 +189,7 @@ defineExpose({ open: openModal });
v-model:open="open"
title="流转卡选择"
width="70%"
:destroy-on-close="true"
:destroy-on-hidden="true"
@ok="handleConfirm"
@cancel="closeModal"
>

View File

@ -232,7 +232,7 @@ defineExpose({ open: openModal });
v-model:open="open"
title="生产任务选择"
width="80%"
:destroy-on-close="true"
:destroy-on-hidden="true"
@ok="handleConfirm"
@cancel="closeModal"
>

View File

@ -224,7 +224,7 @@ defineExpose({ open: openModal });
v-model:open="open"
title="生产工单选择"
width="80%"
:destroy-on-close="true"
:destroy-on-hidden="true"
@ok="handleConfirm"
@cancel="closeModal"
>

View File

@ -190,7 +190,7 @@ defineExpose({ open: openModal });
<template>
<Modal
v-model:open="open"
:destroy-on-close="true"
:destroy-on-hidden="true"
title="质检指标选择"
width="70%"
@cancel="closeModal"

View File

@ -197,7 +197,7 @@ defineExpose({ open: openModal });
v-model:open="open"
title="工具选择"
width="75%"
:destroy-on-close="true"
:destroy-on-hidden="true"
@ok="handleConfirm"
@cancel="closeModal"
>

View File

@ -194,7 +194,7 @@ defineExpose({ open: openModal });
v-model:open="open"
title="到货通知单行选择"
width="70%"
:destroy-on-close="true"
:destroy-on-hidden="true"
@cancel="closeModal"
@ok="handleConfirm"
>

View File

@ -279,7 +279,7 @@ defineExpose({ open: openModal });
v-model:open="open"
title="到货通知单选择"
width="70%"
:destroy-on-close="true"
:destroy-on-hidden="true"
@cancel="closeModal"
@ok="handleConfirm"
>

View File

@ -235,7 +235,7 @@ defineExpose({ open: openModal });
v-model:open="open"
title="批次选择"
width="80%"
:destroy-on-close="true"
:destroy-on-hidden="true"
@ok="handleConfirm"
@cancel="closeModal"
>

View File

@ -243,7 +243,7 @@ defineExpose({ open: openModal });
<template>
<Modal
v-model:open="open"
:destroy-on-close="true"
:destroy-on-hidden="true"
title="库存物资选择"
width="80%"
@cancel="closeModal"

View File

@ -209,7 +209,7 @@ defineExpose({ open: openModal });
<template>
<Modal
v-model:open="open"
:destroy-on-close="true"
:destroy-on-hidden="true"
title="装箱单选择"
width="80%"
@cancel="closeModal"

View File

@ -189,7 +189,7 @@ defineExpose({ open: openModal });
v-model:open="open"
title="发货通知单行选择"
width="70%"
:destroy-on-close="true"
:destroy-on-hidden="true"
@cancel="closeModal"
@ok="handleConfirm"
>

View File

@ -311,7 +311,7 @@ defineExpose({ open: openModal });
v-model:open="open"
title="发货通知单选择"
width="70%"
:destroy-on-close="true"
:destroy-on-hidden="true"
@cancel="closeModal"
@ok="handleConfirm"
>

View File

@ -117,6 +117,7 @@ export function useGridColumns(): VxeTableGridOptions<MesWmSnApi.SnGroup>['colum
field: 'count',
title: 'SN 码数量',
width: 100,
slots: { default: 'count' },
},
{
field: 'createTime',
@ -126,7 +127,55 @@ export function useGridColumns(): VxeTableGridOptions<MesWmSnApi.SnGroup>['colum
},
{
title: '操作',
width: 180,
width: 240,
fixed: 'right',
slots: { default: 'actions' },
},
];
}
/** SN 码明细弹窗的字段 */
export function useDetailGridColumns(): VxeTableGridOptions<MesWmSnApi.Sn>['columns'] {
return [
{
field: 'code',
title: 'SN 码',
minWidth: 180,
},
{
field: 'itemCode',
title: '物料编码',
minWidth: 120,
},
{
field: 'itemName',
title: '物料名称',
minWidth: 150,
},
{
field: 'specification',
title: '规格型号',
minWidth: 120,
},
{
field: 'unitName',
title: '单位',
width: 80,
},
{
field: 'batchCode',
title: '批次号',
minWidth: 120,
},
{
field: 'createTime',
title: '生成时间',
width: 180,
formatter: 'formatDateTime',
},
{
title: '操作',
width: 100,
fixed: 'right',
slots: { default: 'actions' },
},

View File

@ -17,6 +17,7 @@ import {
import { $t } from '#/locales';
import { useGridColumns, useGridFormSchema } from './data';
import Detail from './modules/detail.vue';
import Form from './modules/form.vue';
const [FormModal, formModalApi] = useVbenModal({
@ -24,6 +25,11 @@ const [FormModal, formModalApi] = useVbenModal({
destroyOnClose: true,
});
const [DetailModal, detailModalApi] = useVbenModal({
connectedComponent: Detail,
destroyOnClose: true,
});
/** 刷新表格 */
function handleRefresh() {
gridApi.query();
@ -46,6 +52,11 @@ async function handleExportDetail(row: MesWmSnApi.SnGroup) {
downloadFileFromBlobPart({ fileName: 'SN码明细.xls', source: data });
}
/** 查看 SN 码明细 */
function handleDetail(row: MesWmSnApi.SnGroup) {
detailModalApi.setData(row).open();
}
/** 删除 SN 码批次 */
async function handleDelete(row: MesWmSnApi.SnGroup) {
const hideLoading = message.loading({
@ -104,6 +115,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
</template>
<FormModal @success="handleRefresh" />
<DetailModal />
<Grid table-title="SN ">
<template #toolbar-tools>
@ -126,9 +138,27 @@ const [Grid, gridApi] = useVbenVxeGrid({
]"
/>
</template>
<template #count="{ row }">
<TableAction
:actions="[
{
label: `${row.count ?? 0}`,
type: 'link',
auth: ['mes:wm-sn:query'],
onClick: handleDetail.bind(null, row),
},
]"
/>
</template>
<template #actions="{ row }">
<TableAction
:actions="[
{
label: '查看明细',
type: 'link',
auth: ['mes:wm-sn:query'],
onClick: handleDetail.bind(null, row),
},
{
label: '导出明细',
type: 'link',

View File

@ -0,0 +1,100 @@
<script lang="ts" setup>
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { MesWmSnApi } from '#/api/mes/wm/sn';
import { nextTick, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { BarcodeBizTypeEnum } from '@vben/constants';
import { message } from 'antdv-next';
import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import { getSnListByUuid } from '#/api/mes/wm/sn';
import { BarcodeDetail } from '#/views/mes/wm/barcode/components';
import { useDetailGridColumns } from '../data';
defineOptions({ name: 'MesWmSnDetail' });
const barcodeDetailRef = ref<InstanceType<typeof BarcodeDetail>>();
/** 查看 SN 码条码 */
function handleBarcode(row: MesWmSnApi.Sn) {
if (!row.id) {
message.warning('缺少 SN 码编号,无法查看条码');
return;
}
barcodeDetailRef.value?.openByBusiness(
row.id,
BarcodeBizTypeEnum.SN,
row.code,
row.itemName || row.code,
);
}
/** 加载 SN 码明细 */
async function loadDetail(row?: MesWmSnApi.SnGroup) {
if (!row?.uuid) {
await gridApi.grid?.loadData([]);
return;
}
gridApi.setLoading(true);
try {
const list = await getSnListByUuid(row.uuid);
await gridApi.grid?.loadData(list);
} finally {
gridApi.setLoading(false);
}
}
const [Grid, gridApi] = useVbenVxeGrid({
gridOptions: {
columns: useDetailGridColumns(),
height: 520,
pagerConfig: {
enabled: false,
},
rowConfig: {
keyField: 'id',
isHover: true,
},
toolbarConfig: {
enabled: false,
},
} as VxeTableGridOptions<MesWmSnApi.Sn>,
});
const [Modal, modalApi] = useVbenModal({
showCancelButton: false,
showConfirmButton: false,
async onOpenChange(isOpen: boolean) {
if (!isOpen) {
await gridApi.grid?.loadData([]);
return;
}
await nextTick();
await loadDetail(modalApi.getData<MesWmSnApi.SnGroup>());
},
});
</script>
<template>
<Modal class="w-3/5" title="SN 码明细">
<Grid class="mx-4">
<template #actions="{ row }">
<TableAction
:actions="[
{
label: '条码',
type: 'link',
auth: ['mes:wm-sn:query'],
onClick: handleBarcode.bind(null, row),
},
]"
/>
</template>
</Grid>
<BarcodeDetail ref="barcodeDetailRef" />
</Modal>
</template>

View File

@ -202,7 +202,7 @@ defineExpose({ open: openModal });
<template>
<Modal
v-model:open="open"
:destroy-on-close="true"
:destroy-on-hidden="true"
title="盘点方案选择"
width="70%"
@cancel="closeModal"

View File

@ -285,7 +285,7 @@ defineExpose({ open: openModal });
v-model:open="open"
title="人员选择"
width="80%"
:destroy-on-close="true"
:destroy-on-hidden="true"
@ok="handleConfirm"
@cancel="closeModal"
>

View File

@ -181,7 +181,7 @@ defineExpose({ open: openModal });
v-model:open="open"
title="库存选择"
width="80%"
:destroy-on-close="true"
:destroy-on-hidden="true"
@ok="handleConfirm"
@cancel="closeModal"
>

View File

@ -169,7 +169,7 @@ defineExpose({ open: openModal });
v-model:open="open"
title="商品选择"
width="80%"
:destroy-on-close="true"
:destroy-on-hidden="true"
@ok="handleConfirm"
@cancel="closeModal"
>