You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
besure_web/src/views/mes/moldoperate/MoldOperateForm.vue

601 lines
20 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="120px"
v-loading="formLoading"
>
<el-form-item :label="t('MoldManagement.MoldOperate.operateType')" prop="operateType">
<el-radio-group v-model="formData.operateType">
<el-radio :label="1">{{ t('MoldManagement.MoldOperate.operateTypeUp') }}</el-radio>
<el-radio :label="2">{{ t('MoldManagement.MoldOperate.operateTypeDown') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('MoldManagement.MoldOperate.device')" prop="deviceId" v-if="formData.operateType != null">
<!-- <el-select
v-model="formData.deviceId"
filterable
clearable
:loading="deviceLoading"
:placeholder="t('MoldManagement.MoldOperate.placeholderDevice')"
class="!w-full"
@change="deviceChange(formData.deviceId)"
>
<el-option v-for="opt in deviceOptions" :key="String(opt.value)" :label="opt.label" :value="opt.value" />
</el-select>-->
<el-input :model-value="displayItemDevice" readonly clearable class="device-ledger-selection-input"
:placeholder="t('MoldManagement.MoldOperate.placeholderDevice')"
@click="openCriticalComponentDialog" @clear="clearBeijian" />
</el-form-item>
<el-form-item :label="t('MoldManagement.MoldOperate.mold')" prop="moldId" v-if="formData.operateType == '1'">
<el-select
v-model="formData.moldId"
multiple
clearable
filterable
:placeholder="t('MoldManagement.MoldOperate.placeholderMold')"
class="!w-full"
>
<el-option
v-for="item in moldList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="formData.operateType == '2' && formData.deviceId"
:label="t('MoldManagement.MoldOperate.lowerMold')"
prop="lowerMoldId"
>
<el-select
v-model="formData.lowerMoldId"
multiple
clearable
filterable
:placeholder="t('MoldManagement.MoldOperate.placeholderLowerMold')"
class="!w-full"
>
<el-option
v-for="item in lowerMoldList"
:key="item.id"
:label="item.name || item.moldName || `ID:${item.id}`"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('MoldManagement.MoldOperate.remark')" prop="remark">
<el-input v-model="formData.remark" :placeholder="t('MoldManagement.MoldOperate.placeholderRemark')" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading">{{ t('common.ok') }}</el-button>
<el-button @click="dialogVisible = false">{{ t('common.cancel') }}</el-button>
</template>
</Dialog>
<el-dialog
v-model="itemDialogVisible"
:title="t('QualityManagement.ZjSchema.selectItemDialogTitle')"
width="1300px"
draggable
>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true"
label-width="60px">
<el-form-item :label="t('EquipmentManagement.EquipmentLedger.deviceCode')"
prop="deviceCode">
<el-input
v-model="queryParams.deviceCode"
:placeholder="t('EquipmentManagement.EquipmentLedger.placeholderDeviceCode')"
clearable @keyup.enter="handleQuery"
class="!w-240px"/>
</el-form-item>
<el-form-item :label="t('EquipmentManagement.EquipmentLedger.deviceName')"
prop="deviceName">
<el-input
v-model="queryParams.deviceName"
:placeholder="t('EquipmentManagement.EquipmentLedger.placeholderDeviceName')"
clearable @keyup.enter="handleQuery"
class="!w-240px"/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery">
<Icon icon="ep:search" class="mr-5px"/>
{{ t('common.query') }}
</el-button>
<el-button @click="resetQuery">
<Icon icon="ep:refresh" class="mr-5px"/>
{{ t('common.reset') }}
</el-button>
</el-form-item>
</el-form>
<ContentWrap>
<el-table ref="multipleTableRef" v-loading="loading" :data="deviceList" :stripe="true"
@selection-change="handleSelectionChange" @select="handleSelect" @select-all="handleSelectAll" :show-overflow-tooltip="true"
class="no-select-all"
row-key="id">
<el-table-column type="selection" width="55" :reserve-selection="true" />
<el-table-column :label="t('EquipmentManagement.EquipmentLedger.deviceCode')"
align="center" prop="deviceCode" min-width="160px" sortable/>
<el-table-column :label="t('EquipmentManagement.EquipmentLedger.deviceName')"
align="center" prop="deviceName" min-width="140px" sortable/>
<el-table-column :label="t('EquipmentManagement.EquipmentLedger.ratedCapacity')"
align="center" prop="ratedCapacity" min-width="120px"/>
<el-table-column :label="t('EquipmentManagement.EquipmentLedger.deviceSpec')"
align="center" prop="deviceSpec"/>
<!-- <el-table-column :label="t('EquipmentManagement.EquipmentLedger.deviceModel')"
align="center" prop="deviceModel"/>-->
<!-- <el-table-column :label="t('EquipmentManagement.EquipmentLedger.deviceBrand')" align="center" prop="deviceBrand" /> -->
<el-table-column
:label="t('EquipmentManagement.EquipmentLedger.productionDate')" align="center"
prop="productionDate" :formatter="dateFormatter2"
width="120px" sortable/>
<el-table-column
:label="t('EquipmentManagement.EquipmentLedger.factoryEntryDate')" align="center"
prop="factoryEntryDate" :formatter="dateFormatter2"
width="120px" sortable/>
</el-table>
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
@pagination="getList" />
</ContentWrap>
<template #footer>
<el-button @click="itemDialogVisible = false">
{{ t('common.cancel') }}
</el-button>
<el-button type="primary" @click="confirmSelectItems">
{{ t('common.ok') }}
</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { MoldOperateApi, MoldOperateVO } from '@/api/mes/moldoperate'
import { MoldBrandApi, MoldVO } from '@/api/erp/mold'
import { DeviceLedgerApi, DeviceLedgerVO } from '@/api/mes/deviceledger'
import {ref} from "vue";
import {ElTable} from "element-plus";
import {ZjItemApi, ZjItemVO} from "@/api/mes/zjitem";
import { dateFormatter2 } from '@/utils/formatTime'
/** 模具上下模 表单 */
defineOptions({ name: 'MoldOperateForm' })
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const moldList = ref<MoldVO[]>([]) // 上模可选模具列表(在途)
const lowerMoldList = ref<any[]>([]) // 下模可选模具列表
const deviceLoading = ref(false)
const deviceOptions = ref<{ label: string; value: number; raw?: DeviceLedgerVO }[]>([])
const deviceOptionsLoaded = ref(false)
const initializingOperateType = ref(false)
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中1修改时的数据加载2提交的按钮禁用
const formType = ref('') // 表单的类型create - 新增update - 修改
const formData = ref({
id: undefined,
operateType: undefined,
moldId: undefined,
deviceId: undefined,
remark: undefined,
lowerMoldId: undefined,
})
const validateMoldId = (_rule: any, value: any, callback: (error?: Error) => void) => {
if (String(formData.value.operateType) !== '1') {
callback()
return
}
const hasValue = Array.isArray(value) ? value.length > 0 : value !== undefined && value !== null && value !== ''
if (!hasValue) {
callback(new Error(t('MoldManagement.MoldOperate.validatorMoldRequired')))
} else {
callback()
}
}
const validateLowerMoldId = (_rule: any, value: any, callback: (error?: Error) => void) => {
if (String(formData.value.operateType) !== '2') {
callback()
return
}
const hasValue = Array.isArray(value) ? value.length > 0 : value !== undefined && value !== null && value !== ''
if (!hasValue) {
callback(new Error(t('MoldManagement.MoldOperate.validatorLowerMoldRequired')))
} else {
callback()
}
}
const formRules = reactive({
operateType: [{ required: true, message: t('MoldManagement.MoldOperate.validatorOperateTypeRequired'), trigger: 'blur' }],
deviceId: [{ required: true, message: t('MoldManagement.MoldOperate.validatorDeviceRequired'), trigger: 'blur' }],
moldId: [{ required: true, validator: validateMoldId, trigger: 'change' }],
lowerMoldId: [{ required: true, validator: validateLowerMoldId, trigger: 'change' }],
})
const formRef = ref() // 表单 Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
initSelectedItems()
await ensureDeviceOptionsLoaded()
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
initializingOperateType.value = true
const data = await MoldOperateApi.getMoldOperate(id)
formData.value = {
...formData.value,
...data,
lowerMoldId: (data as any).lowerMoldId,
}
// 编辑时根据类型格式化模具字段
if (String(formData.value.operateType) === '1') {
if (typeof formData.value.moldId === 'string') {
const parts = formData.value.moldId.split(',').map((v: string) => Number(v)).filter((v) => !Number.isNaN(v))
formData.value.moldId = parts as any
}
await loadUpMoldList()
} else if (String(formData.value.operateType) === '2') {
const rawLower = (formData.value as any).lowerMoldId
if (typeof rawLower === 'string') {
const parts = rawLower.split(',').map((v: string) => Number(v)).filter((v) => !Number.isNaN(v))
;(formData.value as any).lowerMoldId = parts
}
await loadLowerMoldList()
}
} finally {
initializingOperateType.value = false
formLoading.value = false
}
}else{
ids.value=[]
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
// const submitForm = async () => {
// // 校验表单
// await formRef.value.validate()
// // 检验
// if (formData.value.operateType === '1') {
// const data = await someApiToCheck(formData.value.deviceId)
// if (data === true) {
// message.alert('请先将该设备上的模具换下!')
// return;
// }
// }
// // 提交请求
// formLoading.value = true
// try {
// const data = formData.value as unknown as MoldOperateVO
// if (formType.value === 'create') {
// await MoldOperateApi.createMoldOperate(data)
// message.success(t('common.createSuccess'))
// } else {
// await MoldOperateApi.updateMoldOperate(data)
// message.success(t('common.updateSuccess'))
// }
// dialogVisible.value = false
// // 发送操作成功的事件
// emit('success')
// } finally {
// formLoading.value = false
// }
// }
const submitForm = async () => {
// 立即开始 loading
formLoading.value = true
try {
// 1. 表单校验
await formRef.value.validate()
// 2. 组装提交数据
const raw = formData.value as any
const submitData: any = {
id: raw.id,
operateType: raw.operateType,
deviceId: raw.deviceId,
remark: raw.remark,
}
if (String(raw.operateType) === '1') {
const ids = Array.isArray(raw.moldId) ? raw.moldId : raw.moldId != null ? [raw.moldId] : []
submitData.moldId = ids.map((v: any) => v).join(',')
} else if (String(raw.operateType) === '2') {
const allIds = lowerMoldList.value
.map((item: any) => item?.id)
.filter((id: any) => id !== undefined && id !== null)
const lowerIds = Array.isArray(raw.lowerMoldId)
? raw.lowerMoldId
: raw.lowerMoldId != null
? [raw.lowerMoldId]
: []
submitData.lowerMoldId = lowerIds.map((v: any) => v).join(',')
const lowerIdSet = new Set(lowerIds.map((v: any) => String(v)))
const remainIds = allIds.filter((id: any) => !lowerIdSet.has(String(id)))
submitData.moldId = remainIds.join(',')
}
// 3. 提交数据
if (formType.value === 'create') {
await MoldOperateApi.createMoldOperate(submitData)
message.success(t('common.createSuccess'))
} else {
await MoldOperateApi.updateMoldOperate(submitData)
message.success(t('common.updateSuccess'))
}
// 4. 成功处理
dialogVisible.value = false
emit('success')
} catch (error) {
} finally {
// 确保 loading 状态被清除
formLoading.value = false
}
}
const ensureDeviceOptionsLoaded = async () => {
if (deviceOptionsLoaded.value) return
deviceLoading.value = true
try {
const data = await DeviceLedgerApi.getDeviceLedgerPage({})
const rows = (data?.list ?? []) as DeviceLedgerVO[]
deviceOptions.value = rows
.filter((r) => typeof r?.id === 'number')
.map((r) => ({ label: `${r.deviceCode ?? ''} ${r.deviceName ?? ''}`.trim(), value: r.id, raw: r }))
deviceOptionsLoaded.value = true
} finally {
deviceLoading.value = false
}
}
// 设备更改
const deviceChange = async (deviceId:number) => {
if (String(formData.value.operateType) === '2' && deviceId) {
await loadLowerMoldList()
formData.value.lowerMoldId = undefined as any
}
}
const loadUpMoldList = async () => {
moldList.value = await MoldBrandApi.getInTransitMoldAllList()
}
const loadLowerMoldList = async () => {
if (!formData.value.deviceId) {
lowerMoldList.value = []
return
}
const list = await MoldOperateApi.getLowerMoldList(formData.value.deviceId)
lowerMoldList.value = Array.isArray(list) ? list : []
}
watch(
() => formData.value.operateType,
async (val) => {
if (initializingOperateType.value) {
return
}
formData.value.deviceId = undefined as any
formData.value.moldId = undefined as any
formData.value.lowerMoldId = undefined as any
moldList.value = []
lowerMoldList.value = []
if (!val) {
return
}
if (String(val) === '1') {
await loadUpMoldList()
} else if (String(val) === '2') {
await loadLowerMoldList()
}
}
)
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
operateType: undefined,
moldId: undefined,
deviceId: undefined,
remark: undefined,
lowerMoldId: undefined,
}
formRef.value?.resetFields()
}
const ids = ref([])
const itemList = ref<DeviceLedgerVO[]>([])
const itemDialogVisible = ref(false)
const multipleTableRef = ref<InstanceType<typeof ElTable>>()
const deviceList = ref<DeviceLedgerVO[]>([])
const selectedRows = ref<any[]>([])
const total = ref(0)
const queryFormRef = ref()
const loading = ref(true)
const displayItemDevice = computed( () => {
if (!ids.value.length)return ''
if (!itemList.value.length) {
return formData.value.deviceId ? String(formData.value.deviceId) : ''
}
const map = new Map(itemList.value.map((item) => [item.id, item.deviceName]))
const names = ids.value
.map((id) => map.get(id))
.filter((name) => name)
return names.join(',')
})
const openCriticalComponentDialog = async () => {
itemDialogVisible.value = true
let initIds= formData.value.deviceId!=undefined?formData.value.deviceId.toString().split(","):[]
ids.value=initIds.map((id) => Number(id))
setDefaultSelections()
}
// 设置默认选中的行
const setDefaultSelections = () => {
// 等待DOM更新完成
nextTick(() => {
if (!multipleTableRef.value) return
multipleTableRef.value.clearSelection()
let initIds= formData.value.deviceId!=undefined?formData.value.deviceId.toString().split(","):[]
const rawSubjectIds =initIds.map((id) => Number(id))
if (rawSubjectIds.length != 0) {
let row = {
id: undefined
}
multipleTableRef.value.toggleRowSelection(row, true)
}
// 遍历数据,找到需要选中的行
deviceList.value.forEach(row => {
let id = row.id;
if (rawSubjectIds.includes(row.id)) {
multipleTableRef.value.toggleRowSelection(row, true)
}
})
})
}
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
deviceCode: undefined,
deviceName: undefined,
})
const clearBeijian = () => {
formData.value.item = ''
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
const getList = async () => {
loading.value = true
try {
const data = await DeviceLedgerApi.getDeviceLedgerPage(queryParams)
deviceList.value = data.list
total.value = data.total
// 数据加载后,重新设置选中状态
nextTick(() => {
toggleSelection()
})
} finally {
loading.value = false
}
}
// 切换选中状态
const toggleSelection = () => {
if (!multipleTableRef.value || !selectedRows.value.length) return
// 遍历当前页的数据
deviceList.value.forEach(row => {
// 检查这一行是否在已选中数组中
const isSelected = selectedRows.value.some(item => item.id === row.id)
if (isSelected) {
// 如果应该选中,就选中
multipleTableRef.value!.toggleRowSelection(row, true)
} else {
// 否则取消选中
multipleTableRef.value!.toggleRowSelection(row, false)
}
})
}
const handleSelectionChange = (rows: ZjItemVO[]) => {
// 获取当前页所有行的 id
const currentPageIds = rows.map(item => item.id)
// 从已选中的数组中移除当前页的数据
selectedRows.value = selectedRows.value.filter(
item => !currentPageIds.includes(item.id)
)
// 添加当前页新选中的数据
selectedRows.value.push(...rows)
let a=1;
}
// 存储当前已选中的行
const currentSelectedRows = ref([])
const handleSelectAll = (selection) => {
let initIds=selection?.map((row) => row.id).filter((id) => id !== undefined) ?? []
ids.value =initIds.map((id) => Number(id))
}
// select 事件row 是当前操作的行selected 是操作后的状态
const handleSelect = (selection, row) => {
// 判断是选中还是取消选中
const isSelected = selection.includes(row)
if (isSelected) {
// console.log(`✅ 行被选中: ID=${row.id}, Name=${row.name}`)
ids.value.push(row.id)
} else {
ids.value = ids.value.filter(
item => item !== row.id
)
// console.log(`❌ 行被取消选中: ID=${row.id}, Name=${row.name}`)
}
// 更新当前选中状态
currentSelectedRows.value = selection
}
const confirmSelectItems = () => {
formData.value.deviceId = ids.value.join(',')
itemDialogVisible.value = false
}
const initSelectedItems = async () => {
if (!itemList.value.length) {
loading.value = true
try {
itemList.value = await DeviceLedgerApi.getDeviceLedgerList()
} finally {
loading.value = false
}
}
}
/** 初始化 **/
onMounted(async () => {
getList()
})
</script>
<style scoped lang="scss">
.no-select-all :deep(.el-table__header-wrapper .el-checkbox) {
display: none;
}
</style>