Merge remote-tracking branch 'origin/main'

main
liutao 2 weeks ago
commit 14c6c0ac50

@ -181,6 +181,11 @@ export const MoldBrandApi = {
return await request.post({ url: `/erp/mold-pressure-net-record/create`, data })
},
// 批量增压网记录
batchCreatePressureNetRecord: async (data: any) => {
return await request.post({ url: `/erp/mold-pressure-net-record/batch-create`, data })
},
// 查询压网记录分页
getPressureNetRecordPage: async (params: any) => {
return await request.get({ url: `/erp/mold-pressure-net-record/page`, params })

@ -15,6 +15,8 @@ export interface DeviceLedgerVO {
deviceSpec: string // 设备规格
deviceType: string | number // 设备类型
deviceLine?: string | number // 设备产线
topCategoryId?: number // 顶级分类 id
topCategoryName?: string // 顶级分类名称
deviceTypeName?: string // 设备类型名称
supplier: string // 供应商
workshop: string // 所属车间

@ -1591,6 +1591,7 @@ export default {
judgmentCriteria: 'Judgment Criteria',
inspectionResult: 'Inspection Result',
images: 'Images',
inputValue: 'Input Value',
remark: 'Remark',
operate: 'Operate',
dialogTitleDefault: 'Inspection Result',
@ -2110,7 +2111,8 @@ export default {
dialogPurchaseCycleLabel: 'Purchase Cycle (Days)',
dialogBrandLabel: 'Brand',
dialogBrandPlaceholder: 'Please enter brand',
categoryTree: 'Category Tree',
images: 'Image',
categoryTree: 'Material Category',
addCategory: 'Add Category',
refreshTree: 'Refresh'
},
@ -3184,6 +3186,7 @@ export default {
inspectionResultPass: 'Pass',
inspectionResultFail: 'Fail',
images: 'Images',
inputValue: 'Input Value',
remark: 'Remark',
operate: 'Operate',
pass: 'Pass',
@ -3387,6 +3390,7 @@ export default {
inspectionResultPass: 'Pass',
inspectionResultFail: 'Fail',
images: 'Images',
inputValue: 'Input Value',
remark: 'Remark',
operate: 'Operate',
pass: 'Pass',

@ -1588,6 +1588,7 @@ export default {
judgmentCriteria: '判定基准',
inspectionResult: '检验结果',
images: '图片',
inputValue: '输入值',
remark: '备注',
operate: '操作',
dialogTitleDefault: '检验结果',
@ -1955,6 +1956,7 @@ export default {
status: '状态',
qrcode: '二维码/条形码',
images: '图片',
inputValue: '输入值',
remark: '备注',
isEnable: '是否启用',
fileUrl: '资料',
@ -2182,6 +2184,7 @@ export default {
moldSize: '模穴数',
useTime: '预期寿命',
images: '图片',
inputValue: '输入值',
remark: '备注',
isEnable: '是否启用',
enable: '启用',
@ -2674,6 +2677,7 @@ export default {
inspectionResultPass: '通过',
inspectionResultFail: '不通过',
images: '图片',
inputValue: '输入值',
remark: '备注',
operate: '操作',
pass: '通过',
@ -2884,6 +2888,7 @@ export default {
inspectionResultPass: '通过',
inspectionResultFail: '不通过',
images: '图片',
inputValue: '输入值',
remark: '备注',
operate: '操作',
pass: '通过',
@ -3294,7 +3299,8 @@ export default {
dialogPurchaseCycleLabel: '采购周期(天)',
dialogBrandLabel: '品牌',
dialogBrandPlaceholder: '请输入品牌',
categoryTree: '产品分类树',
images: '图片',
categoryTree: '物料分类',
addCategory: '新增分类',
refreshTree: '刷新'
},

@ -338,15 +338,15 @@
<template v-if="isReplaceNet">
<section class="dv-repair-section">
<div class="dv-repair-section__title">{{ t('MoldManagement.MoldBrandPage.maintainTypeReplaceNet') }}</div>
<el-form-item :label="t('MoldManagement.MoldBrandPage.subMold')" prop="moldId">
<el-form-item :label="t('MoldManagement.MoldBrandPage.subMold')" prop="moldIds">
<el-select
v-model="replaceNetFormData.moldId"
v-model="replaceNetFormData.moldIds"
filterable
clearable
multiple
:loading="subMoldLoading"
:placeholder="t('MoldManagement.MoldBrandPage.placeholderSubMold')"
class="!w-full"
@change="handleSubMoldChange"
>
<el-option
v-for="item in subMoldList"
@ -423,7 +423,19 @@
</el-table-column>
<el-table-column :label="t('MoldManagement.MoldInspectionPlan.subjectCode')" align="center" prop="subjectCode" />
<el-table-column :label="t('MoldManagement.MoldInspectionPlan.subjectName')" align="center" prop="subjectName" />
<el-table-column :label="t('MoldManagement.MoldInspectionPlan.inspectionMethod')" align="center" prop="inspectionMethod" width="120" />
<el-table-column :label="t('MoldManagement.MoldInspectionPlan.inspectionMethod')" align="center" prop="inspectionMethod" width="120">
<template #default="scope">
<el-tag
effect="light"
:type="getTagType('Inspection_method', scope.row.inspectionMethod)"
:color="getTagColor('Inspection_method', scope.row.inspectionMethod)"
:style="getTagStyle('Inspection_method', scope.row.inspectionMethod)"
disable-transitions
>
{{ getTagLabel('Inspection_method', scope.row.inspectionMethod) }}
</el-tag>
</template>
</el-table-column>
<el-table-column :label="t('MoldManagement.MoldInspectionPlan.judgmentCriteria')" align="center" prop="judgmentCriteria" />
</el-table>
</div>
@ -472,6 +484,7 @@ import { MoldRepairApi, type MoldRepairVO } from '@/api/mold/moldrepair'
import { PlanMaintenanceApi } from '@/api/mold/planmaintenance'
import { getSimpleUserList, type UserVO } from '@/api/system/user'
import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
import { isHexColor } from '@/utils/color'
import { dateFormatter } from '@/utils/formatTime'
defineOptions({ name: 'MoldMaintainView' })
@ -506,7 +519,7 @@ const formRules = reactive({
shutdown: [{ required: true, message: t('MoldManagement.MoldRepair.validatorIsShutdownRequired'), trigger: 'blur' }],
faultPhenomenon: [{ required: true, message: t('MoldManagement.MoldRepair.validatorFaultPhenomenonRequired'), trigger: 'blur' }],
//
moldId: [{ required: true, message: t('MoldManagement.MoldBrandPage.validatorSubMoldRequired'), trigger: 'blur' }],
moldIds: [{ required: true, message: t('MoldManagement.MoldBrandPage.validatorSubMoldRequired'), trigger: 'change' }],
pressureNetTime: [{ required: true, message: t('MoldManagement.MoldBrandPage.validatorPressureNetTimeRequired'), trigger: 'blur' }],
})
@ -521,7 +534,7 @@ const formModel = computed(() => ({
faultLevel: repairFormData.faultLevel,
shutdown: repairFormData.shutdown,
faultPhenomenon: repairFormData.faultPhenomenon,
moldId: replaceNetFormData.moldId,
moldIds: replaceNetFormData.moldIds,
pressureNetTime: replaceNetFormData.pressureNetTime,
}))
@ -555,8 +568,7 @@ const repairFormData = reactive({
//
const replaceNetFormData = reactive({
moldId: undefined as number | undefined,
moldName: undefined as string | undefined,
moldIds: [] as number[],
pressureNetTime: undefined as string | undefined,
remark: undefined as string | undefined
})
@ -576,11 +588,6 @@ const loadSubMoldList = async () => {
}
}
const handleSubMoldChange = (moldId: number) => {
const selected = subMoldList.value.find((item: any) => item.id === moldId)
replaceNetFormData.moldName = selected?.name ?? ''
}
//
const isInspectOrMaintain = computed(() => [1, 2].includes(maintainFormData.maintainType ?? 0))
const isRepair = computed(() => maintainFormData.maintainType === 3)
@ -588,6 +595,36 @@ const isReplaceNet = computed(() => maintainFormData.maintainType === 4)
const repairCodeDisabled = computed(() => repairFormData.isCode === true)
const failureLevelOptions = computed(() => getStrDictOptions(DICT_TYPE.FAILURE_LEVEL))
const getTagDict = (dictType: string, value: any) => {
const v = value === '' || value === null || value === undefined ? undefined : String(value)
if (!v) return undefined
return getStrDictOptions(dictType).find((d) => d.value === v)
}
const getTagLabel = (dictType: string, value: any) => {
const found = getTagDict(dictType, value)
return found?.label ?? (value ?? '')
}
const getTagType = (dictType: string, value: any) => {
const found = getTagDict(dictType, value)
const type = found?.colorType
if (type + '' === 'primary' || type + '' === 'default') return '' as any
return (type ?? '') as any
}
const getTagColor = (dictType: string, value: any) => {
const found = getTagDict(dictType, value)
if (found?.cssClass && isHexColor(found.cssClass)) return found.cssClass
return ''
}
const getTagStyle = (dictType: string, value: any) => {
const color = getTagColor(dictType, value)
if (!color) return ''
return 'color: #fff'
}
//
const maintainTypes = computed(() => [
{ value: 1, label: t('MoldManagement.MoldBrandPage.maintainTypeInspect'), icon: Search },
@ -870,19 +907,22 @@ const submitForm = async () => {
repairFormData.remark = undefined
repairFormData.isCode = true
} else if (isReplaceNet.value) {
//
await MoldBrandApi.createPressureNetRecord({
moldBrandId: props.mold?.id,
moldBrandName: props.mold?.name ?? '',
moldId: replaceNetFormData.moldId,
moldName: replaceNetFormData.moldName ?? '',
pressureNetTime: replaceNetFormData.pressureNetTime,
remark: replaceNetFormData.remark
//
const createReqVOList = replaceNetFormData.moldIds.map((moldId: number) => {
const selected = subMoldList.value.find((item: any) => item.id === moldId)
return {
moldBrandId: props.mold?.id,
moldBrandName: props.mold?.name ?? '',
moldId: moldId,
moldName: selected?.name ?? '',
pressureNetTime: replaceNetFormData.pressureNetTime,
remark: replaceNetFormData.remark
}
})
await MoldBrandApi.batchCreatePressureNetRecord(createReqVOList)
message.success(t('common.createSuccess'))
//
replaceNetFormData.moldId = undefined
replaceNetFormData.moldName = undefined
replaceNetFormData.moldIds = []
replaceNetFormData.pressureNetTime = undefined
replaceNetFormData.remark = undefined
await nextTick()

@ -46,11 +46,8 @@
<!-- 左侧表单 -->
<div class="mold-operate-page__form">
<el-form ref="operateFormRef" :model="operateFormData" :rules="operateFormRules" label-width="100px">
<el-form-item :label="t('MoldManagement.MoldBrandPage.targetLine')" prop="lineId">
<el-select v-model="operateFormData.lineId" filterable clearable
:placeholder="t('MoldManagement.MoldBrandPage.placeholderTargetLine')" class="!w-full">
<el-option v-for="line in lineOptions" :key="line.id" :label="line.name" :value="String(line.id)" />
</el-select>
<el-form-item :label="t('MoldManagement.MoldBrandPage.targetLine')">
<el-input v-model="displayTopCategory" disabled :placeholder="'选择目标设备后自动显示'" class="!w-full" />
</el-form-item>
<el-form-item :label="t('MoldManagement.MoldBrandPage.targetDevice')" prop="deviceId">
<el-select v-model="operateFormData.deviceId" filterable clearable
@ -115,7 +112,7 @@
import { MoldBrandApi, type MoldBrandVO } from '@/api/erp/mold'
import { DeviceLedgerApi, type DeviceLedgerVO } from '@/api/mes/deviceledger'
import { MoldOperateApi, type MoldOperateVO } from '@/api/mes/moldoperate'
import { OrganizationApi, type OrganizationVO } from '@/api/mes/organization'
import { DeviceLineApi, type DeviceLineTreeVO } from '@/api/mes/deviceline'
import { getSimpleUserList, type UserVO } from '@/api/system/user'
import { DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
@ -148,16 +145,16 @@ const operateFormData = reactive({
remark: undefined as string | undefined
})
//
// 线
const operateFormRules = reactive({
lineId: [{ required: true, message: t('MoldManagement.MoldBrandPage.validatorTargetLineRequired'), trigger: 'blur' }],
deviceId: [{ required: true, message: t('MoldManagement.MoldBrandPage.validatorTargetDeviceRequired'), trigger: 'blur' }],
operateTime: [{ required: true, message: t('MoldManagement.MoldBrandPage.validatorOperateTimeRequired'), trigger: 'blur' }],
operatorId: [{ required: true, message: t('MoldManagement.MoldBrandPage.validatorOperatorRequired'), trigger: 'blur' }]
})
//
const lineOptions = ref<OrganizationVO[]>([])
const deviceLineTree = ref<DeviceLineTreeVO[]>([])
const displayTopCategory = ref('')
const operatorOptions = ref<UserVO[]>([])
//
@ -177,10 +174,10 @@ const getImageList = (images?: string) => {
const initOperateOptions = async () => {
try {
const data = await OrganizationApi.getOrganizationList()
lineOptions.value = Array.isArray(data) ? data : []
const data = await DeviceLineApi.getDeviceLineTree()
deviceLineTree.value = Array.isArray(data) ? data : []
} catch {
lineOptions.value = []
deviceLineTree.value = []
}
try {
operatorOptions.value = (await getSimpleUserList()) ?? []
@ -189,6 +186,34 @@ const initOperateOptions = async () => {
}
}
// 线
watch(() => operateFormData.deviceId, async (deviceId) => {
displayTopCategory.value = ''
if (!deviceId) return
try {
const detail = await DeviceLedgerApi.getDeviceLedger(deviceId)
if (detail?.deviceLine != null) {
operateFormData.lineId = detail.deviceLine
}
//
displayTopCategory.value = detail?.topCategoryName || ''
// fallback: 线
if (!displayTopCategory.value && detail?.deviceLine != null && deviceLineTree.value.length) {
const lineId = Number(detail.deviceLine)
const containsId = (nodes: DeviceLineTreeVO[] | undefined, id: number): boolean => {
if (!nodes) return false
return nodes.some((n) => n.id === id || containsId(n.children, id))
}
for (const root of deviceLineTree.value) {
if (root.id === lineId || containsId(root.children, lineId)) {
displayTopCategory.value = root.name
break
}
}
}
} catch {}
})
const fetchRecentOperateList = async () => {
if (!props.mold?.id) return
recentLoading.value = true
@ -217,6 +242,7 @@ const submitOperateForm = async () => {
operateType: props.type,
moldId: props.mold?.id,
lineId: operateFormData.lineId,
lineName: displayTopCategory.value,
deviceId: operateFormData.deviceId,
remark: operateFormData.remark,
operateTime: operateFormData.operateTime,
@ -240,6 +266,7 @@ const open = async () => {
operateFormData.operateTime = undefined
operateFormData.operatorId = undefined
operateFormData.remark = undefined
displayTopCategory.value = ''
await initOperateOptions()
recentPageNo.value = 1
await fetchRecentOperateList()

@ -179,24 +179,34 @@
</el-form-item>
</el-col>
<el-col v-if="formType === 'update'" :span="24">
<el-form-item :label="t('FactoryModeling.ProductInformation.qrcode')" prop="qrcodeUrl">
<QrcodeActionCard
:image-url="formData.qrcodeUrl"
:print-id="formData.id"
:print-template-type="1"
:print-title="`${formData.name || '产品'}二维码打印预览`"
:empty-text="t('FactoryModeling.ProductInformation.qrcodeEmpty')"
:refresh-url="getQrcodeRefreshUrl()"
:refresh-disabled="!formData.id || !formData.barCode"
refresh-confirm-text="确认刷新该产品二维码吗?"
:template-json="formData.templateJson"
:print-data="buildPrintData()"
@refresh-success="handleQrcodeRefreshSuccess"
/>
<div class="flex items-start gap-20px">
<el-form-item :label="t('FactoryModeling.ProductInformation.qrcode')" prop="qrcodeUrl" class="flex-1">
<QrcodeActionCard
:image-url="formData.qrcodeUrl"
:print-id="formData.id"
:print-template-type="1"
:print-title="`${formData.name || '产品'}二维码打印预览`"
:empty-text="t('FactoryModeling.ProductInformation.qrcodeEmpty')"
:refresh-url="getQrcodeRefreshUrl()"
:refresh-disabled="!formData.id || !formData.barCode"
refresh-confirm-text="确认刷新该产品二维码吗?"
:template-json="formData.templateJson"
:print-data="buildPrintData()"
@refresh-success="handleQrcodeRefreshSuccess"
/>
</el-form-item>
<el-form-item :label="t('FactoryModeling.ProductInformation.images')" prop="images" class="image-form-item flex-1">
<UploadImg v-model="formData.images" />
</el-form-item>
</div>
</el-col>
<el-col v-else :span="24">
<el-form-item :label="t('FactoryModeling.ProductInformation.images')" prop="images" class="image-form-item">
<UploadImg v-model="formData.images" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item :label="t('FactoryModeling.ProductInformation.dialogRemarkLabel')" prop="remark">
<el-form-item :label="t('FactoryModeling.ProductInformation.dialogRemarkLabel')" prop="remark" style="margin-top: 8px;">
<el-input type="textarea" v-model="formData.remark" :placeholder="t('FactoryModeling.ProductInformation.dialogRemarkPlaceholder')" />
</el-form-item>
</el-col>
@ -289,7 +299,13 @@
<el-table-column :label="t('ErpStock.PackagingScheme.palletTotalQuantity')" prop="palletTotalQuantity" minWidth="120" />
<el-table-column :label="t('FactoryModeling.ProductInformation.dialogDefaultStatusLabel')" width="130" align="center">
<template #default="{ row }">
<el-radio v-model="packagingSchemeDefaultId" :label="row.id">&nbsp;</el-radio>
<el-radio
v-model="packagingSchemeDefaultId"
:label="row.id"
:disabled="!packagingSchemeSelectedRows.some((item) => item.id === row.id)"
>
&nbsp;
</el-radio>
</template>
</el-table-column>
</el-table>
@ -333,9 +349,15 @@
<el-table-column :label="t('ErpPurchase.Supplier.contact')" prop="contact" minWidth="100" />
<el-table-column :label="t('ErpPurchase.Supplier.mobile')" prop="mobile" minWidth="120" />
<el-table-column :label="t('ErpPurchase.Supplier.telephone')" prop="telephone" minWidth="120" />
<el-table-column :label="t('FactoryModeling.ProductInformation.dialogDefaultStatusLabel')" width="130" align="center">
<el-table-column label="是否默认供应商" width="130" align="center">
<template #default="{ row }">
<el-radio v-model="supplierDefaultId" :label="row.id">&nbsp;</el-radio>
<el-radio
v-model="supplierDefaultId"
:label="row.id"
:disabled="!supplierSelectedRows.some((item) => item.id === row.id)"
>
&nbsp;
</el-radio>
</template>
</el-table-column>
</el-table>
@ -435,6 +457,7 @@ const formData = ref({
fragileFlag: undefined as number | undefined,
purchaseCycle: undefined as number | undefined,
brand: undefined as string | undefined,
images: undefined as string | undefined,
sparePartLevel: undefined as number | undefined
})
const selectedDeviceRows = ref<any[]>([])
@ -662,6 +685,14 @@ const getPackagingSchemeDialogList = async () => {
const handlePackagingSchemeSelectionChange = (selection: any[]) => {
packagingSchemeSelectedRows.value = selection
if (!selection.length) {
packagingSchemeDefaultId.value = undefined
return
}
const selectedIds = selection.map((item) => item.id)
if (selection.length === 1 || !selectedIds.includes(packagingSchemeDefaultId.value)) {
packagingSchemeDefaultId.value = selection[0].id
}
}
const displayPackagingSchemeText = computed(() => {
@ -703,6 +734,9 @@ const confirmPackagingSchemeSelect = () => {
message.warning(t('FactoryModeling.ProductInformation.validatorPackagingSchemeRequired'))
return
}
if (!packagingSchemeDefaultId.value) {
packagingSchemeDefaultId.value = packagingSchemeSelectedRows.value[0].id
}
formData.value.packagingSchemes = packagingSchemeSelectedRows.value.map((row) => ({
packagingSchemeId: row.id,
defaultStatus: row.id === packagingSchemeDefaultId.value ? 1 : 0
@ -764,6 +798,14 @@ const getSupplierDialogList = async () => {
const handleSupplierSelectionChange = (selection: any[]) => {
supplierSelectedRows.value = selection
if (!selection.length) {
supplierDefaultId.value = undefined
return
}
const selectedIds = selection.map((item) => item.id)
if (selection.length === 1 || !selectedIds.includes(supplierDefaultId.value)) {
supplierDefaultId.value = selection[0].id
}
}
const displaySupplierText = computed(() => {
@ -804,6 +846,9 @@ const confirmSupplierSelect = () => {
message.warning(t('FactoryModeling.ProductInformation.validatorSupplierRequired'))
return
}
if (!supplierDefaultId.value) {
supplierDefaultId.value = supplierSelectedRows.value[0].id
}
formData.value.suppliers = supplierSelectedRows.value.map((row) => ({
supplierId: row.id,
defaultStatus: row.id === supplierDefaultId.value ? 1 : 0
@ -888,8 +933,8 @@ const open = async (type: string, id?: number) => {
sparePartLevel: productData.sparePartLevel != null ? Number(productData.sparePartLevel) : undefined,
devices,
molds,
packagingSchemes: (productData as any).packagingSchemes || [],
suppliers: (productData as any).suppliers || []
packagingSchemes: normalizeDefaultStatus((productData as any).packagingSchemes, (productData as any).defaultPackagingSchemeId, 'packagingSchemeId'),
suppliers: normalizeDefaultStatus((productData as any).suppliers, (productData as any).defaultSupplierId, 'supplierId')
}
selectedDeviceRows.value = toDeviceRows(devices)
selectedMoldRows.value = toMoldRows(molds)
@ -971,6 +1016,24 @@ const buildRelationIdListString = (list: { id: number; name: string }[]) => {
return list.map((item) => Number(item.id)).filter((id) => Number.isFinite(id))
}
const getDefaultPackagingSchemeId = () => {
const defaultItem = formData.value.packagingSchemes?.find((item) => item.defaultStatus === 1)
return defaultItem?.packagingSchemeId ?? undefined
}
const getDefaultSupplierId = () => {
const defaultItem = formData.value.suppliers?.find((item) => item.defaultStatus === 1)
return defaultItem?.supplierId ?? undefined
}
const normalizeDefaultStatus = (list: any[] | undefined, defaultId: number | undefined, idKey: string) => {
if (!list?.length) return []
return list.map((item: any) => ({
...item,
defaultStatus: defaultId != null && item[idKey] === defaultId ? 1 : 0
}))
}
const submitForm = async () => {
await formRef.value.validate()
formLoading.value = true
@ -980,7 +1043,9 @@ const submitForm = async () => {
const data = {
...formData.value,
deviceIds: buildRelationIdListString(relationDevices),
moldIds: buildRelationIdListString(relationMolds)
moldIds: buildRelationIdListString(relationMolds),
defaultPackagingSchemeId: formData.value.categoryType === 1 ? getDefaultPackagingSchemeId() : undefined,
defaultSupplierId: (formData.value.categoryType === 2 || formData.value.categoryType === 3) ? getDefaultSupplierId() : undefined
} as unknown as ProductVO
delete (data as any).devices
delete (data as any).molds
@ -1081,6 +1146,15 @@ watch(
border-top: 1px solid #ebeef5;
}
.image-form-item {
margin-bottom: 28px;
:deep(.el-form-item__content) {
min-height: 150px;
align-items: flex-start;
}
}
@media (max-width: 768px) {
.dv-repair-panel__header {
padding: 14px 16px;

@ -80,10 +80,16 @@
</ContentWrap>
<!-- 右侧产品表格 -->
<ContentWrap class="product-page-right">
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<div class="product-page-right">
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" :row-class-name="getRowClassName">
<el-table-column :label="t('FactoryModeling.ProductInformation.tableBarCodeColumn')" align="center" prop="barCode"
sortable />
<el-table-column :label="t('FactoryModeling.ProductInformation.dialogCategoryTypeLabel')" align="center" prop="categoryType" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE" :value="scope.row.categoryType" />
</template>
</el-table-column>
<el-table-column :label="t('FactoryModeling.ProductInformation.tableNameColumn')" align="left" prop="name"
width="220px" sortable />
<el-table-column :label="t('FactoryModeling.ProductInformation.tableStandardColumn')" align="center"
@ -100,8 +106,11 @@
</el-table-column>
<el-table-column :label="t('FactoryModeling.ProductInformation.tableCreateTimeColumn')" align="center"
prop="createTime" :formatter="dateFormatter" width="180px" sortable />
<el-table-column :label="t('FactoryModeling.ProductInformation.tableOperateColumn')" align="center" width="150px">
<el-table-column :label="t('FactoryModeling.ProductInformation.tableOperateColumn')" align="center" width="210px">
<template #default="scope">
<el-button link type="primary" @click="handleShowDetail(scope.row.id)">
详情
</el-button>
<el-button link type="primary" @click="openForm('update', scope.row.id)" v-hasPermi="['erp:product:update']">
{{ t('FactoryModeling.ProductInformation.tableEditAction') }}
</el-button>
@ -111,10 +120,178 @@
</template>
</el-table-column>
</el-table>
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
@pagination="getList" />
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
@pagination="getList" />
</ContentWrap>
<ContentWrap v-if="detailVisible" class="product-detail-wrap" v-loading="detailLoading">
<template v-if="productDetail">
<div class="detail-header">
<div class="detail-title">物料详情</div>
<el-button text @click="closeDetail">
<Icon icon="ep:close" />
</el-button>
</div>
<div class="detail-card">
<div class="detail-image-box">
<div class="detail-image-item">
<div class="detail-image-label">{{ t('FactoryModeling.ProductInformation.qrcode') }}</div>
<el-image
v-if="productDetail.qrcodeUrl"
class="detail-image"
:src="productDetail.qrcodeUrl"
fit="contain"
:preview-src-list="[productDetail.qrcodeUrl]"
preview-teleported
/>
<el-empty v-else :image-size="64" :description="t('FactoryModeling.ProductInformation.qrcodeEmpty')" />
</div>
</div>
<div class="detail-info">
<div class="detail-field">
<span class="field-label">{{ t('FactoryModeling.ProductInformation.dialogBarCodeLabel') }}</span>
<span class="field-value">{{ formatValue(productDetail.barCode) }}</span>
</div>
<div class="detail-field">
<span class="field-label">{{ t('FactoryModeling.ProductInformation.dialogCategoryTypeLabel') }}</span>
<span class="field-value">{{ formatCategoryType(productDetail.categoryType) }}</span>
</div>
<div class="detail-field">
<span class="field-label">{{ t('FactoryModeling.ProductInformation.dialogNameLabel') }}</span>
<span class="field-value">{{ formatValue(productDetail.name) }}</span>
</div>
<div class="detail-field">
<span class="field-label">{{ t('FactoryModeling.ProductInformation.dialogCategoryLabel') }}</span>
<span class="field-value">{{ formatValue(productDetail.subCategoryName) }}</span>
</div>
<div class="detail-field">
<span class="field-label">{{ t('FactoryModeling.ProductInformation.dialogUnitLabel') }}</span>
<span class="field-value">{{ formatValue(productDetail.unitName) }}</span>
</div>
<div class="detail-field">
<span class="field-label">{{ t('FactoryModeling.ProductInformation.dialogStandardLabel') }}</span>
<span class="field-value">{{ formatValue(productDetail.standard || productDetail.deviceSpec || productDetail.model) }}</span>
</div>
<div class="detail-field">
<span class="field-label">{{ t('FactoryModeling.ProductInformation.dialogExpiryDayLabel') }}</span>
<span class="field-value">{{ formatValue(productDetail.expiryDay) }}</span>
</div>
<div class="detail-field">
<span class="field-label">{{ t('FactoryModeling.ProductInformation.dialogStatusLabel') }}</span>
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="productDetail.status" />
</div>
<!-- 产品类型关联设备关联模具 -->
<template v-if="productDetail.categoryType === 1">
<div class="detail-field">
<span class="field-label">关联设备</span>
<span class="field-value">{{ formatDeviceText(productDetail) }}</span>
</div>
<div class="detail-field">
<span class="field-label">关联模具</span>
<span class="field-value">{{ formatMoldText(productDetail) }}</span>
</div>
</template>
<!-- 物料/备件类型供应商 -->
<template v-if="productDetail.categoryType === 2 || productDetail.categoryType === 3">
<div class="detail-field">
<span class="field-label">{{ t('FactoryModeling.ProductInformation.dialogSupplierLabel') }}</span>
<span class="field-value">{{ formatSupplierText(productDetail) }}</span>
</div>
</template>
<!-- 备件类型备件等级是否易损件采购周期品牌 -->
<template v-if="productDetail.categoryType === 3">
<div class="detail-field">
<span class="field-label">{{ t('FactoryModeling.ProductInformation.dialogSparePartLevelLabel') }}</span>
<span class="field-value">{{ formatSparePartLevel(productDetail.sparePartLevel) }}</span>
</div>
<div class="detail-field">
<span class="field-label">{{ t('FactoryModeling.ProductInformation.dialogFragileFlagLabel') }}</span>
<span class="field-value">{{ productDetail.fragileFlag === 1 ? t('common.yes') : productDetail.fragileFlag === 0 ? t('common.no') : '-' }}</span>
</div>
<div class="detail-field">
<span class="field-label">{{ t('FactoryModeling.ProductInformation.dialogPurchaseCycleLabel') }}</span>
<span class="field-value">{{ formatValue(productDetail.purchaseCycle) }}</span>
</div>
<div class="detail-field">
<span class="field-label">{{ t('FactoryModeling.ProductInformation.dialogBrandLabel') }}</span>
<span class="field-value">{{ formatValue(productDetail.brand) }}</span>
</div>
</template>
<div class="detail-field detail-field--full">
<span class="field-label">{{ t('FactoryModeling.ProductInformation.dialogRemarkLabel') }}</span>
<span class="field-value">{{ formatValue(productDetail.remark) }}</span>
</div>
</div>
<div class="detail-summary">
<div class="section-title">{{ detailSummaryTitle }}</div>
<!-- 产品类型包装方案摘要 -->
<template v-if="productDetail.categoryType === 1">
<div class="summary-item">
<Icon icon="ep:box" class="summary-icon" />
<span>{{ t('FactoryModeling.ProductInformation.dialogPackagingSchemeLabel') }}{{ packagingSchemeCount }} </span>
</div>
<div class="summary-item">
<Icon icon="ep:document-checked" class="summary-icon" />
<span>默认参考方案{{ defaultPackagingSchemeText }}</span>
</div>
</template>
<!-- 物料/备件类型供应商摘要 -->
<template v-if="productDetail.categoryType === 2 || productDetail.categoryType === 3">
<div class="summary-item">
<Icon icon="ep:office-building" class="summary-icon" />
<span>{{ t('FactoryModeling.ProductInformation.dialogSupplierLabel') }}{{ supplierCount }} </span>
</div>
<div class="summary-item">
<Icon icon="ep:star" class="summary-icon" />
<span>默认供应商{{ defaultSupplierText }}</span>
</div>
</template>
<div class="detail-image-item" style="margin-top: 12px;">
<div class="detail-image-label">{{ t('FactoryModeling.ProductInformation.images') }}</div>
<el-image
v-if="productDetail.images"
class="detail-image"
:src="productDetail.images"
fit="contain"
:preview-src-list="[productDetail.images]"
preview-teleported
/>
<el-empty v-else :image-size="64" description="暂无图片" />
</div>
</div>
<!-- 产品类型包装方案表格 -->
<div v-if="productDetail.categoryType === 1" class="detail-table-box">
<div class="detail-table-title">
<span>{{ t('FactoryModeling.ProductInformation.dialogPackagingSchemeLabel') }}</span>
<span> {{ packagingSchemeCount }} </span>
</div>
<el-table :data="productDetail.packagingSchemes || []" border size="small" :show-overflow-tooltip="true">
<el-table-column :label="t('ErpStock.PackagingScheme.name')" prop="packagingSchemeName" min-width="130" />
<el-table-column :label="t('ErpStock.PackagingScheme.packageQuantity')" prop="packageQuantity" min-width="100" />
<el-table-column :label="t('ErpStock.PackagingScheme.palletPackageQuantity')" prop="palletPackageQuantity" min-width="100" />
</el-table>
</div>
<!-- 物料/备件类型供应商表格 -->
<div v-else-if="productDetail.categoryType === 2 || productDetail.categoryType === 3" class="detail-table-box">
<div class="detail-table-title">
<span>{{ t('FactoryModeling.ProductInformation.dialogSupplierLabel') }}</span>
<span> {{ supplierCount }} </span>
</div>
<el-table :data="productDetail.suppliers || []" border size="small" :show-overflow-tooltip="true">
<el-table-column :label="t('ErpPurchase.Supplier.name')" prop="supplierName" min-width="160" />
<el-table-column :label="t('ErpPurchase.Supplier.contact')" prop="supplierContact" min-width="100" />
<el-table-column :label="t('ErpPurchase.Supplier.mobile')" prop="supplierMobile" min-width="120" />
</el-table>
</div>
</div>
</template>
</ContentWrap>
</div>
</div>
</template>
<ProductForm v-else-if="formType === 'product'" ref="formRef" @success="getList" @closed="handleFormClosed" />
@ -126,7 +303,7 @@
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import { dateFormatter, formatDate } from '@/utils/formatTime'
import download from '@/utils/download'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { ProductCategoryApi } from '@/api/erp/product/category'
@ -156,6 +333,10 @@ const queryFormRef = ref()
const exportLoading = ref(false)
const formVisible = ref(false)
const formType = ref('')
const detailVisible = ref(false)
const detailLoading = ref(false)
const currentDetailId = ref<number>()
const productDetail = ref<any>()
/** 分类树数据 */
const groupTreeData = ref<any[]>([])
@ -226,6 +407,9 @@ const getList = async () => {
const data = await ProductApi.getProductPage(queryParams)
list.value = data.list
total.value = data.total
if (currentDetailId.value && !list.value.some((item) => item.id === currentDetailId.value)) {
closeDetail()
}
} finally {
loading.value = false
}
@ -233,11 +417,13 @@ const getList = async () => {
const handleQuery = () => {
queryParams.pageNo = 1
closeDetail()
getList()
}
const resetQuery = () => {
queryFormRef.value.resetFields()
closeDetail()
handleQuery()
}
@ -255,6 +441,9 @@ const handleDelete = async (id: number) => {
await message.delConfirm()
await ProductApi.deleteProduct(id)
message.success(t('common.delSuccess'))
if (currentDetailId.value === id) {
closeDetail()
}
await getList()
} catch { }
}
@ -293,6 +482,98 @@ const handleFormClosed = () => {
formVisible.value = false
formType.value = ''
}
const handleShowDetail = async (id: number) => {
detailVisible.value = true
currentDetailId.value = id
detailLoading.value = true
try {
productDetail.value = await ProductApi.getProduct(id)
} finally {
detailLoading.value = false
}
}
const closeDetail = () => {
detailVisible.value = false
detailLoading.value = false
currentDetailId.value = undefined
productDetail.value = undefined
}
const getRowClassName = ({ row }: { row: ProductVO }) => {
return row.id === currentDetailId.value ? 'current-detail-row' : ''
}
const packagingSchemes = computed(() => productDetail.value?.packagingSchemes || [])
const packagingSchemeCount = computed(() => packagingSchemes.value.length)
const defaultPackagingScheme = computed(() => {
const defaultId = productDetail.value?.defaultPackagingSchemeId
return packagingSchemes.value.find((item: any) => item.defaultStatus === 1)
|| packagingSchemes.value.find((item: any) => item.packagingSchemeId === defaultId)
})
const defaultPackagingSchemeText = computed(() => {
const scheme = defaultPackagingScheme.value
if (!scheme) return '-'
return formatValue(scheme.packagingSchemeName)
})
const detailSummaryTitle = computed(() => {
const categoryType = formatCategoryType(productDetail.value?.categoryType)
return categoryType === '-' ? '物料属性摘要' : `${categoryType}属性摘要`
})
//
const suppliers = computed(() => productDetail.value?.suppliers || [])
const supplierCount = computed(() => suppliers.value.length)
const defaultSupplier = computed(() => {
return suppliers.value.find((item: any) => item.defaultStatus === 1)
})
const defaultSupplierText = computed(() => {
const supplier = defaultSupplier.value
if (!supplier) return '-'
return supplier.supplierName || '-'
})
//
const formatDeviceText = (detail: any) => {
if (!detail?.devices?.length && !detail?.deviceList?.length) return '-'
const list = detail.devices || detail.deviceList || []
return list.map((item: any) => item.name || item.deviceName || `ID:${item.id}`).join('、') || '-'
}
const formatMoldText = (detail: any) => {
if (!detail?.molds?.length && !detail?.moldList?.length) return '-'
const list = detail.molds || detail.moldList || []
return list.map((item: any) => item.name || item.code || `ID:${item.id}`).join('、') || '-'
}
const formatSupplierText = (detail: any) => {
if (!detail?.suppliers?.length) return '-'
return detail.suppliers.map((item: any) => item.supplierName || `ID:${item.supplierId}`).join('、') || '-'
}
const formatSparePartLevel = (value: any) => {
if (value === undefined || value === null || value === '') return '-'
const dictItem = sparePartLevelDict.value.find((item: any) => item.value === Number(value))
return dictItem?.label || formatValue(value)
}
const sparePartLevelDict = computed(() => getIntDictOptions(DICT_TYPE.SPARE_PARTS_LEVEL))
const formatValue = (value: any) => {
return value === undefined || value === null || value === '' ? '-' : value
}
const formatCategoryType = (value: any) => {
const dictItem = typeDict.value.find((item: any) => item.value === Number(value))
return dictItem?.label || formatValue(value)
}
const formatDateTime = (value: any) => {
if (value === undefined || value === null || value === '') return '-'
return formatDate(value)
}
</script>
<style lang="scss" scoped>
@ -311,6 +592,145 @@ const handleFormClosed = () => {
min-width: 0;
}
.product-detail-wrap {
margin-top: 12px;
}
:deep(.current-detail-row) {
--el-table-tr-bg-color: var(--el-color-primary-light-9);
}
.detail-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 12px;
}
.detail-title {
font-size: 16px;
font-weight: 600;
color: var(--el-text-color-primary);
}
.detail-card {
display: grid;
grid-template-columns: 200px 1fr 300px 1fr;
gap: 16px;
padding: 16px;
border: 1px solid var(--el-border-color-lighter);
border-radius: 4px;
}
.detail-info {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px 28px;
align-content: start;
}
.detail-field {
display: flex;
min-width: 0;
font-size: 14px;
line-height: 24px;
}
.detail-field--full {
grid-column: 1 / -1;
}
.field-label {
flex: 0 0 auto;
color: var(--el-text-color-regular);
}
.field-value {
min-width: 0;
color: var(--el-text-color-primary);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.detail-image-box {
display: flex;
flex-direction: column;
gap: 12px;
align-items: center;
}
.detail-image-item {
display: flex;
flex-direction: column;
align-items: left;
gap: 6px;
}
.detail-image-label {
font-size: 13px;
font-weight: 600;
color: var(--el-text-color-primary);
}
.detail-image {
width: 170px;
height: 170px;
}
.detail-summary {
min-width: 0;
}
.section-title {
margin-bottom: 8px;
font-size: 14px;
font-weight: 600;
color: var(--el-text-color-primary);
}
.summary-item {
display: flex;
gap: 10px;
align-items: center;
min-height: 32px;
font-size: 14px;
color: var(--el-text-color-primary);
}
.summary-icon {
flex: 0 0 auto;
color: var(--el-color-primary);
}
.detail-table-box {
min-width: 0;
}
.detail-table-title {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 8px;
font-size: 14px;
color: var(--el-text-color-primary);
span:last-child {
color: var(--el-text-color-secondary);
}
}
@media (max-width: 1200px) {
.detail-card {
grid-template-columns: 1fr 1fr;
}
.detail-summary,
.detail-table-box {
grid-column: 1 / -1;
}
}
.tree-header {
display: flex;
align-items: center;

@ -26,10 +26,8 @@
@click="openMoldSelectDialog"
/>
</el-form-item>
<el-form-item :label="t('MoldManagement.MoldOperate.productionLine')" prop="lineId">
<el-select v-model="formData.lineId" filterable clearable :placeholder="t('MoldManagement.MoldOperate.placeholderProductionLine')" class="!w-full">
<el-option v-for="line in lineOptions" :key="line.id" :label="line.name" :value="line.id" />
</el-select>
<el-form-item :label="t('MoldManagement.MoldOperate.productionLine')" prop="lineId" v-if="formData.operateType != null">
<el-input :model-value="displayLineName" readonly />
</el-form-item>
<el-form-item :label="t('MoldManagement.MoldOperate.operateTime')" prop="operateTime">
<el-date-picker
@ -113,7 +111,7 @@
import { MoldOperateApi } from '@/api/mes/moldoperate'
import { MoldBrandApi, MoldVO } from '@/api/erp/mold'
import { DeviceLedgerApi, DeviceLedgerVO } from '@/api/mes/deviceledger'
import { OrganizationApi, OrganizationVO } from '@/api/mes/organization'
import { DeviceLineApi, DeviceLineTreeVO } from '@/api/mes/deviceline'
import { getSimpleUserList, type UserVO } from '@/api/system/user'
import TableSelectDialog from '@/components/TableSelectDialog/TableSelectDialog.vue'
@ -123,7 +121,8 @@ defineOptions({ name: 'MoldOperateForm' })
const { t } = useI18n() //
const message = useMessage() //
const lineOptions = ref<OrganizationVO[]>([])
const deviceLineTree = ref<DeviceLineTreeVO[]>([])
const displayTopCategory = ref('')
const operatorOptions = ref<UserVO[]>([])
const initializingOperateType = ref(false)
@ -169,7 +168,6 @@ const validateMoldId = (_rule: any, value: any, callback: (error?: Error) => voi
const formRules = reactive({
operateType: [{ required: true, message: t('MoldManagement.MoldOperate.validatorOperateTypeRequired'), trigger: 'blur' }],
deviceId: [{ required: true, message: t('MoldManagement.MoldOperate.validatorDeviceRequired'), trigger: 'change' }],
lineId: [{ required: true, message: t('MoldManagement.MoldOperate.validatorProductionLineRequired'), trigger: 'change' }],
moldId: [{ required: true, validator: validateMoldId, trigger: 'change' }],
operateTime: [{ required: true, message: t('MoldManagement.MoldOperate.validatorOperateTimeRequired'), trigger: 'blur' }],
operatorId: [{ required: true, message: t('MoldManagement.MoldOperate.validatorOperatorRequired'), trigger: 'change' }],
@ -265,6 +263,7 @@ const submitForm = async () => {
deviceId: raw.deviceId,
moldId: raw.moldId,
lineId: raw.lineId,
lineName: displayTopCategory.value, // 线
operateTime: raw.operateTime,
operatorId: raw.operatorId,
remark: raw.remark,
@ -292,12 +291,12 @@ const submitForm = async () => {
}
const ensureLineOptionsLoaded = async () => {
if (lineOptions.value.length) return
if (deviceLineTree.value.length) return
try {
const data = await OrganizationApi.getOrganizationList()
lineOptions.value = Array.isArray(data) ? data : []
const data = await DeviceLineApi.getDeviceLineTree()
deviceLineTree.value = Array.isArray(data) ? data : []
} catch {
lineOptions.value = []
deviceLineTree.value = []
}
try {
operatorOptions.value = (await getSimpleUserList()) ?? []
@ -347,6 +346,7 @@ const resetForm = () => {
selectedMoldRows.value = []
ids.value = []
moldIds.value = []
displayTopCategory.value = ''
formRef.value?.resetFields()
}
const deviceColumns = [
@ -377,12 +377,42 @@ const fetchMoldBrandPage = async (params: Record<string, any>) => {
}
const selectedDeviceRows = ref<any[]>([])
const selectedMoldRows = ref<any[]>([])
const handleDeviceSelectConfirm = (payload: { ids: (number | string)[]; rows: any[] }) => {
const handleDeviceSelectConfirm = async (payload: { ids: (number | string)[]; rows: any[] }) => {
const row = payload.rows[0]
if (row) {
selectedDeviceRows.value = [row]
formData.value.deviceId = Number(row.id)
ids.value = [Number(row.id)]
const deviceId = Number(row.id)
formData.value.deviceId = deviceId
ids.value = [deviceId]
// deviceLine
try {
const detail = await DeviceLedgerApi.getDeviceLedger(deviceId)
console.log('设备详情:', { detail, topCategoryName: detail?.topCategoryName, topCategoryId: detail?.topCategoryId, deviceLine: detail?.deviceLine })
if (detail?.deviceLine != null) {
formData.value.lineId = detail.deviceLine
}
//
displayTopCategory.value = detail?.topCategoryName || ''
// fallback: 线DeviceLineTree
if (!displayTopCategory.value && detail?.deviceLine != null && deviceLineTree.value.length) {
const lineId = Number(detail.deviceLine)
console.log('fallback 匹配: deviceLine=', lineId, '产线树根数=', deviceLineTree.value.length)
//
const containsId = (nodes: DeviceLineTreeVO[] | undefined, id: number): boolean => {
if (!nodes) return false
return nodes.some((n) => n.id === id || containsId(n.children, id))
}
for (const root of deviceLineTree.value) {
if (root.id === lineId || containsId(root.children, lineId)) {
displayTopCategory.value = root.name
console.log('产线匹配成功:', root.name)
break
}
}
}
} catch (e) {
console.error('获取设备详情失败', e)
}
} else {
selectedDeviceRows.value = []
formData.value.deviceId = undefined
@ -481,6 +511,10 @@ const moldDisplayText = computed(() => {
return map.get(formData.value.moldId) || ''
})
const displayLineName = computed(() => displayTopCategory.value)
const openCriticalComponentDialog = async () => {
searchParams.deviceCode=''

@ -41,21 +41,22 @@ v-else-if="scope.row.images" :src="parseFirstImage(scope.row.images)"
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column label="输入值" align="center" min-width="150">
<el-table-column :label="t('MoldManagement.TicketResultDialog.inputValue')" align="center" min-width="150">
<template #default="scope">
<el-input
v-if="String(scope.row.valueType) === '0' || String(scope.row.valueType) === '2'"
v-model="scope.row.textInput"
:disabled="String(scope.row.inspectionResult) !== '0'"
clearable
placeholder="请输入"
:placeholder="t('common.inputText')"
/>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column :label="t('MoldManagement.TicketResultDialog.remark')" align="center" prop="remark" min-width="180">
<template #default="scope">
<el-input v-model="scope.row.remark" clearable :placeholder="t('common.inputText')" />
<el-input v-if="String(scope.row.inspectionResult) === '0'" v-model="scope.row.remark" clearable :placeholder="t('common.inputText')" />
<span v-else>{{ scope.row.remark || '-' }}</span>
</template>
</el-table-column>
<el-table-column :label="t('MoldManagement.TicketResultDialog.operate')" align="center" min-width="220" fixed="right">
@ -84,7 +85,7 @@ v-else-if="scope.row.images" :src="parseFirstImage(scope.row.images)"
<template #footer>
<el-button @click="dialogVisible = false">{{ t('MoldManagement.TicketResultDialog.cancel') }}</el-button>
<el-button type="primary" @click="handleSave" :loading="submitLoading">{{ t('MoldManagement.TicketResultDialog.save') }}</el-button>
<el-button v-if="String(jobStatus) === '0'" type="primary" @click="handleSave" :loading="submitLoading">{{ t('MoldManagement.TicketResultDialog.save') }}</el-button>
</template>
</Dialog>
</template>
@ -97,6 +98,8 @@ import { useDictStoreWithOut } from '@/store/modules/dict'
defineOptions({ name: 'TicketResultDialog' })
const emit = defineEmits(['success'])
const { t } = useI18n()
const message = useMessage()
@ -223,6 +226,7 @@ const handleSave = async () => {
await TicketManagementApi.batchUpdateTicketResults(payload)
message.success(t('MoldManagement.TicketResultDialog.updateSuccess'))
dialogVisible.value = false
emit('success')
} catch {
message.error(t('MoldManagement.TicketResultDialog.updateFail'))
} finally {

@ -106,7 +106,7 @@
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
</ContentWrap>
<TicketResultDialog ref="resultDialogRef" />
<TicketResultDialog ref="resultDialogRef" @success="getList" />
</template>
<script setup lang="ts">

Loading…
Cancel
Save