style: 上下模修改-上模选择设备可以进行下模,下模选择设备只展示有在机模具的设备

main
zhongwenkai 1 day ago
parent 278360f931
commit 8e66ad443c

@ -19,13 +19,18 @@
<el-table-column type="selection" width="55" reserve-selection /> <el-table-column type="selection" width="55" reserve-selection />
<el-table-column <el-table-column
v-for="column in columns" v-for="column in columns"
:key="column.prop" :key="column.prop || column.slotName"
:label="column.label" :label="column.label"
:prop="column.prop" :prop="column.slotName ? undefined : column.prop"
:width="column.width" :width="column.width"
:min-width="column.minWidth" :min-width="column.minWidth"
:align="column.align || 'center'" :align="column.align || 'center'"
/> :fixed="column.fixed"
>
<template v-if="column.slotName" #default="scope">
<slot :name="column.slotName" :row="scope.row"></slot>
</template>
</el-table-column>
</el-table> </el-table>
<Pagination <Pagination
v-model:page="queryParams.pageNo" v-model:page="queryParams.pageNo"
@ -48,10 +53,12 @@ defineOptions({ name: 'TableSelectDialog' })
type TableColumn = { type TableColumn = {
label: string label: string
prop: string prop?: string
slotName?: string
width?: string | number width?: string | number
minWidth?: string | number minWidth?: string | number
align?: 'left' | 'center' | 'right' align?: 'left' | 'center' | 'right'
fixed?: string | boolean
} }
const props = withDefaults( const props = withDefaults(

@ -18,7 +18,11 @@
:placeholder="t('MoldManagement.MoldOperate.placeholderDevice')" :placeholder="t('MoldManagement.MoldOperate.placeholderDevice')"
@click="openCriticalComponentDialog" /> @click="openCriticalComponentDialog" />
</el-form-item> </el-form-item>
<el-form-item :label="t('MoldManagement.MoldOperate.mold')" prop="moldId" v-if="formData.operateType != null"> <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.mold')" prop="moldId" v-if="formData.operateType == 1">
<el-input <el-input
:model-value="moldDisplayText" :model-value="moldDisplayText"
:placeholder="t('MoldManagement.MoldOperate.placeholderMold')" :placeholder="t('MoldManagement.MoldOperate.placeholderMold')"
@ -26,8 +30,9 @@
@click="openMoldSelectDialog" @click="openMoldSelectDialog"
/> />
</el-form-item> </el-form-item>
<el-form-item :label="t('MoldManagement.MoldOperate.productionLine')" prop="lineId" v-if="formData.operateType != null"> <!-- 下模自动带出该设备的在机模具 -->
<el-input :model-value="displayLineName" readonly /> <el-form-item label="在机模具" v-if="formData.operateType == 2">
<el-input :model-value="currentDeviceMoldText" readonly />
</el-form-item> </el-form-item>
<el-form-item :label="t('MoldManagement.MoldOperate.operateTime')" prop="operateTime"> <el-form-item :label="t('MoldManagement.MoldOperate.operateTime')" prop="operateTime">
<el-date-picker <el-date-picker
@ -78,6 +83,16 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
</template> </template>
<!-- 操作列对有在机模具的设备显示下模按钮 -->
<template #deviceAction="{ row }">
<el-button
v-if="row.moldGroup"
type="danger"
link
size="small"
@click.stop="openDownMoldDialog(row)"
>下模</el-button>
</template>
</TableSelectDialog> </TableSelectDialog>
<TableSelectDialog <TableSelectDialog
@ -105,7 +120,47 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
</template> </template>
<!-- 状态列插槽将数字转为中文 -->
<template #moldStatus="{ row }">
{{ moldStatusMap[row.status] || row.status }}
</template>
</TableSelectDialog> </TableSelectDialog>
<!-- 下模弹窗 -->
<Dialog title="设备下模" v-model="downMoldDialogVisible" width="580px">
<el-form ref="downMoldFormRef" :model="downMoldForm" :rules="downMoldFormRules" label-width="100px" v-loading="downMoldLoading">
<el-form-item label="设备">
<el-input :model-value="downMoldTarget?.deviceName || ''" disabled />
</el-form-item>
<el-form-item label="在机模具">
<div v-if="downMoldTargetMolds.length">
<el-tag v-for="mold in downMoldTargetMolds" :key="mold.id" class="mr-5px mb-5px">{{ mold.name }}</el-tag>
</div>
<span v-else class="text-gray-400">暂无在机模具</span>
</el-form-item>
<el-form-item label="操作员" prop="operatorId">
<el-select v-model="downMoldForm.operatorId" filterable clearable placeholder="请选择操作员" class="!w-full">
<el-option v-for="item in operatorOptions" :key="item.id" :label="item.nickname" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="操作时间" prop="operateTime">
<el-date-picker
v-model="downMoldForm.operateTime"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="选择操作时间"
class="!w-full"
/>
</el-form-item>
<el-form-item label="备注">
<el-input v-model="downMoldForm.remark" type="textarea" :rows="2" placeholder="可选备注" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="downMoldDialogVisible = false"> </el-button>
<el-button type="primary" :loading="downMoldLoading" @click="confirmDownMold"> </el-button>
</template>
</Dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { MoldOperateApi } from '@/api/mes/moldoperate' import { MoldOperateApi } from '@/api/mes/moldoperate'
@ -113,6 +168,7 @@ import { MoldBrandApi, MoldVO } from '@/api/erp/mold'
import { DeviceLedgerApi, DeviceLedgerVO } from '@/api/mes/deviceledger' import { DeviceLedgerApi, DeviceLedgerVO } from '@/api/mes/deviceledger'
import { DeviceLineApi, DeviceLineTreeVO } from '@/api/mes/deviceline' import { DeviceLineApi, DeviceLineTreeVO } from '@/api/mes/deviceline'
import { getSimpleUserList, type UserVO } from '@/api/system/user' import { getSimpleUserList, type UserVO } from '@/api/system/user'
import { useUserStore } from '@/store/modules/user'
import TableSelectDialog from '@/components/TableSelectDialog/TableSelectDialog.vue' import TableSelectDialog from '@/components/TableSelectDialog/TableSelectDialog.vue'
/** 模具上下模 表单 */ /** 模具上下模 表单 */
@ -120,6 +176,7 @@ defineOptions({ name: 'MoldOperateForm' })
const { t } = useI18n() // const { t } = useI18n() //
const message = useMessage() // const message = useMessage() //
const { user: currentUser } = useUserStore() //
const deviceLineTree = ref<DeviceLineTreeVO[]>([]) const deviceLineTree = ref<DeviceLineTreeVO[]>([])
const displayTopCategory = ref('') const displayTopCategory = ref('')
@ -168,7 +225,6 @@ const validateMoldId = (_rule: any, value: any, callback: (error?: Error) => voi
const formRules = reactive({ const formRules = reactive({
operateType: [{ required: true, message: t('MoldManagement.MoldOperate.validatorOperateTypeRequired'), trigger: 'blur' }], operateType: [{ required: true, message: t('MoldManagement.MoldOperate.validatorOperateTypeRequired'), trigger: 'blur' }],
deviceId: [{ required: true, message: t('MoldManagement.MoldOperate.validatorDeviceRequired'), trigger: 'change' }], deviceId: [{ required: true, message: t('MoldManagement.MoldOperate.validatorDeviceRequired'), trigger: 'change' }],
moldId: [{ required: true, validator: validateMoldId, trigger: 'change' }],
operateTime: [{ required: true, message: t('MoldManagement.MoldOperate.validatorOperateTimeRequired'), trigger: 'blur' }], operateTime: [{ required: true, message: t('MoldManagement.MoldOperate.validatorOperateTimeRequired'), trigger: 'blur' }],
operatorId: [{ required: true, message: t('MoldManagement.MoldOperate.validatorOperatorRequired'), trigger: 'change' }], operatorId: [{ required: true, message: t('MoldManagement.MoldOperate.validatorOperatorRequired'), trigger: 'change' }],
}) })
@ -181,11 +237,12 @@ const open = async (type: string, id?: number) => {
formType.value = type formType.value = type
resetForm() resetForm()
initSelectedItems() initSelectedItems()
// //
if (type === 'create') { if (type === 'create') {
const now = new Date() const now = new Date()
const pad = (n: number) => String(n).padStart(2, '0') const pad = (n: number) => String(n).padStart(2, '0')
formData.value.operateTime = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}` formData.value.operateTime = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`
formData.value.operatorId = currentUser.id
} }
await ensureLineOptionsLoaded() await ensureLineOptionsLoaded()
// //
@ -248,7 +305,6 @@ const emit = defineEmits(['success']) // 定义 success 事件,用于操作成
// } // }
const submitForm = async () => { const submitForm = async () => {
// loading
formLoading.value = true formLoading.value = true
try { try {
@ -257,35 +313,62 @@ const submitForm = async () => {
// 2. // 2.
const raw = formData.value as any const raw = formData.value as any
const submitData: any = { const isDown = String(raw.operateType) === '2'
id: raw.id,
operateType: raw.operateType, //
deviceId: raw.deviceId, if (isDown && !currentDeviceMolds.value.length) {
moldId: raw.moldId, message.warning('该设备暂无在机模具,无法下模')
lineId: raw.lineId, formLoading.value = false
lineName: displayTopCategory.value, // 线 return
operateTime: raw.operateTime,
operatorId: raw.operatorId,
remark: raw.remark,
} }
// 3. // 3.
if (formType.value === 'create') { if (formType.value === 'create') {
await MoldOperateApi.createMoldOperate(submitData) if (isDown) {
//
const promises = currentDeviceMolds.value.map((mold: any) =>
MoldOperateApi.createMoldOperate({
operateType: raw.operateType,
deviceId: raw.deviceId,
moldId: mold.id,
lineId: raw.lineId,
lineName: displayTopCategory.value,
operateTime: raw.operateTime,
operatorId: raw.operatorId,
remark: raw.remark,
id: undefined as any
} as any)
)
await Promise.all(promises)
} else {
//
await MoldOperateApi.createMoldOperate({
id: raw.id,
operateType: raw.operateType,
deviceId: raw.deviceId,
moldId: raw.moldId,
lineId: raw.lineId,
lineName: displayTopCategory.value,
operateTime: raw.operateTime,
operatorId: raw.operatorId,
remark: raw.remark,
})
}
message.success(t('common.createSuccess')) message.success(t('common.createSuccess'))
} else { } else {
await MoldOperateApi.updateMoldOperate(submitData) await MoldOperateApi.updateMoldOperate(raw)
message.success(t('common.updateSuccess')) message.success(t('common.updateSuccess'))
} }
// 4. // 4.
deviceMoldLoaded.value = false
deviceMoldMap.value = new Map()
dialogVisible.value = false dialogVisible.value = false
emit('success') emit('success')
} catch (error) { } catch (error) {
} finally { } finally {
// loading
formLoading.value = false formLoading.value = false
} }
} }
@ -349,25 +432,112 @@ const resetForm = () => {
displayTopCategory.value = '' displayTopCategory.value = ''
formRef.value?.resetFields() formRef.value?.resetFields()
} }
const deviceColumns = [ const deviceColumns = computed(() => {
{ label: '设备编号', prop: 'deviceCode', minWidth: 140 }, const baseColumns = [
{ label: '设备名称', prop: 'deviceName', minWidth: 160 }, { label: '设备编号', prop: 'deviceCode', minWidth: 140 },
{ label: '设备型号', prop: 'deviceModel', minWidth: 140 }, { label: '设备名称', prop: 'deviceName', minWidth: 160 },
{ label: '所属车间', prop: 'workshop', minWidth: 140 } { label: '设备型号', prop: 'deviceModel', minWidth: 140 },
] { label: '所属产线', prop: 'lineName', minWidth: 140 },
{ label: '模具组', prop: 'moldGroup', minWidth: 180 }
]
//
if (String(formData.value.operateType) !== '2') {
baseColumns.push({ label: '操作', slotName: 'deviceAction', width: 80, fixed: 'right' })
}
return baseColumns
})
//
const moldStatusMap: Record<number, string> = {
0: '在机',
1: '待用',
}
const moldColumns = [ const moldColumns = [
{ label: '模具编码', prop: 'code', minWidth: 140 }, { label: '模具编码', prop: 'code', minWidth: 140 },
{ label: '模具名称', prop: 'name', minWidth: 160 }, { label: '模具名称', prop: 'name', minWidth: 160 },
{ label: '版本', prop: 'version', minWidth: 100 }, { label: '版本', prop: 'version', minWidth: 100 },
{ label: '状态', prop: 'status', minWidth: 100 } { label: '状态', slotName: 'moldStatus', minWidth: 100 }
] ]
const fetchDeviceLedgerPage = (params: Record<string, any>) => { // deviceName APP deviceName
return DeviceLedgerApi.getDeviceLedgerPage({ const deviceMoldMap = ref<Map<string, any[]>>(new Map())
const deviceMoldLoaded = ref(false)
/** 从产线树中根据 deviceLine id 查找顶级分类(根节点)名称,与外层表单产线显示逻辑一致 */
const resolveTopCategoryName = (deviceLineId: string | number | undefined): string => {
if (deviceLineId == null || deviceLineId === '') return ''
if (!deviceLineTree.value.length) return ''
const targetId = Number(deviceLineId)
const containsId = (nodes: any[] | 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 === targetId || containsId(root.children, targetId)) {
return root.name
}
}
return ''
}
/** 批量加载设备在机模具,缓存到 deviceMoldMapdeviceName → 模具型号列表),与 APP 端逻辑一致 */
const loadDeviceMolds = async () => {
if (deviceMoldLoaded.value) return
try {
// pageSize 100
const res: any = await MoldBrandApi.getMoldBrandPage({ pageSize: 100 })
const allMolds = res?.list ?? res?.pageResult?.list ?? []
const map = new Map<string, any[]>()
if (Array.isArray(allMolds)) {
allMolds.forEach((mold: any) => {
const deviceName = mold.deviceName
if (!deviceName) return
if (!map.has(deviceName)) map.set(deviceName, [])
map.get(deviceName)!.push(mold)
})
}
deviceMoldMap.value = map
deviceMoldLoaded.value = true
} catch {
deviceMoldMap.value = new Map()
deviceMoldLoaded.value = true
}
}
const fetchDeviceLedgerPage = async (params: Record<string, any>) => {
const data = await DeviceLedgerApi.getDeviceLedgerPage({
...params, ...params,
isScheduled: 1 isScheduled: 1
}) })
const list = data.list || []
const total = data.total || 0
if (list.length) {
// 线
await ensureLineOptionsLoaded()
//
await loadDeviceMolds()
list.forEach((item: any) => {
// 线线
item.lineName = resolveTopCategoryName(item.deviceLine) || item.topCategoryName || ''
// deviceName APP
const molds = deviceMoldMap.value.get(item.deviceName) || []
item.moldGroup = molds.length
? molds.map((m: any) => m.name || '').filter(Boolean).join('、')
: ''
})
//
if (String(formData.value.operateType) === '2') {
const filteredList = list.filter((item: any) => item.moldGroup)
return { list: filteredList, total: filteredList.length }
}
}
return { list, total }
} }
const fetchMoldBrandPage = async (params: Record<string, any>) => { const fetchMoldBrandPage = async (params: Record<string, any>) => {
@ -513,8 +683,90 @@ const moldDisplayText = computed(() => {
const displayLineName = computed(() => displayTopCategory.value) const displayLineName = computed(() => displayTopCategory.value)
//
const currentDeviceMolds = computed(() => {
if (!selectedDeviceRows.value.length) return []
const deviceName = selectedDeviceRows.value[0]?.deviceName
if (!deviceName) return []
return deviceMoldMap.value.get(deviceName) || []
})
//
const currentDeviceMoldText = computed(() => {
const molds = currentDeviceMolds.value
return molds.length ? molds.map((m: any) => m.name).join('、') : ''
})
// ========== ==========
const downMoldDialogVisible = ref(false)
const downMoldLoading = ref(false)
const downMoldTarget = ref<any>(null)
const downMoldFormRef = ref()
const downMoldForm = reactive({
moldIds: [] as number[],
operatorId: undefined as number | undefined,
operateTime: '',
remark: ''
})
const downMoldFormRules = reactive({
operatorId: [{ required: true, message: '请选择操作员', trigger: 'change' }],
operateTime: [{ required: true, message: '请选择操作时间', trigger: 'change' }]
})
//
const downMoldTargetMolds = computed(() => {
if (!downMoldTarget.value) return []
return deviceMoldMap.value.get(downMoldTarget.value.deviceName) || []
})
/** 打开下模弹窗 */
const openDownMoldDialog = (row: any) => {
downMoldTarget.value = row
const molds = deviceMoldMap.value.get(row.deviceName) || []
downMoldForm.moldIds = molds.map((m: any) => m.id)
downMoldForm.operatorId = currentUser.id
downMoldForm.remark = ''
const now = new Date()
const pad = (n: number) => String(n).padStart(2, '0')
downMoldForm.operateTime = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`
downMoldDialogVisible.value = true
nextTick(() => downMoldFormRef.value?.clearValidate?.())
}
/** 确认下模 */
const confirmDownMold = async () => {
await downMoldFormRef.value?.validate()
downMoldLoading.value = true
try {
const target = downMoldTarget.value
const promises = downMoldForm.moldIds.map((moldId) =>
MoldOperateApi.createMoldOperate({
operateType: '2', //
deviceId: target.id,
moldId,
operateTime: downMoldForm.operateTime,
operatorId: downMoldForm.operatorId!,
remark: downMoldForm.remark,
lineId: undefined,
lineName: target.lineName || target.topCategoryName || '',
id: undefined as any
} as any)
)
await Promise.all(promises)
message.success('下模成功')
downMoldDialogVisible.value = false
//
deviceMoldLoaded.value = false
deviceMoldMap.value = new Map()
//
deviceSelectDialogRef.value?.reload?.()
} catch (e: any) {
const msg = e?.message || e?.data?.msg || '下模失败'
message.error(String(msg).substring(0, 50))
} finally {
downMoldLoading.value = false
}
}
const openCriticalComponentDialog = async () => { const openCriticalComponentDialog = async () => {
searchParams.deviceCode='' searchParams.deviceCode=''
@ -555,3 +807,5 @@ const initSelectedItems = async () => {
} }
} }
</script> </script>

Loading…
Cancel
Save