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

524 lines
18 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-input :model-value="displayItemDevice" readonly clearable class="device-ledger-selection-input"
:placeholder="t('MoldManagement.MoldOperate.placeholderDevice')"
@click="openCriticalComponentDialog" />
</el-form-item>
<el-form-item :label="t('MoldManagement.MoldOperate.mold')" prop="moldId" v-if="formData.operateType != null">
<el-input
:model-value="moldDisplayText"
:placeholder="t('MoldManagement.MoldOperate.placeholderMold')"
readonly
@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>
<el-form-item :label="t('MoldManagement.MoldOperate.operateTime')" prop="operateTime">
<el-date-picker
v-model="formData.operateTime"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
:placeholder="t('MoldManagement.MoldOperate.placeholderOperateTime')"
class="!w-full"
/>
</el-form-item>
<el-form-item :label="t('MoldManagement.MoldOperate.operatorName')" prop="operatorId">
<el-select v-model="formData.operatorId" filterable clearable :placeholder="t('MoldManagement.MoldOperate.placeholderOperatorName')" 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="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>
<TableSelectDialog
ref="deviceSelectDialogRef"
title="选择设备"
:columns="deviceColumns"
:fetch-api="fetchDeviceLedgerPage"
row-key="id"
selection-type="single"
@confirm="handleDeviceSelectConfirm"
:query-params="mergedQueryParams"
>
<!-- 使用 header 插槽插入查询表单 -->
<template #header>
<el-form ref="searchFormRef" :model="searchParams" :inline="true" >
<el-form-item label="设备编号" prop="deviceCode">
<el-input v-model="searchParams.deviceCode" placeholder="请输入编号" clearable />
</el-form-item>
<el-form-item label="设备名称" prop="deviceName">
<el-input v-model="searchParams.deviceName" placeholder="请输入名称" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">{{ t('FactoryModeling.ProductInformation.searchButtonText') }}</el-button>
<el-button @click="resetSearch">{{ t('FactoryModeling.ProductInformation.resetButtonText') }}</el-button>
</el-form-item>
</el-form>
</template>
</TableSelectDialog>
<TableSelectDialog
ref="moldSelectDialogRef"
title="选择模具"
:columns="moldColumns"
:fetch-api="fetchMoldBrandPage"
row-key="id"
selection-type="single"
@confirm="handleMoldSelectConfirm"
:query-params="mergedMoldQueryParams"
>
<!-- 使用 header 插槽插入查询表单 -->
<template #header>
<el-form ref="searchMoldFormRef" :model="searchMoldParams" :inline="true" >
<el-form-item label="模具编号" prop="code">
<el-input v-model="searchMoldParams.code" placeholder="请输入编号" clearable />
</el-form-item>
<el-form-item label="模具名称" prop="name">
<el-input v-model="searchMoldParams.name" placeholder="请输入名称" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleMoldSearch">{{ t('FactoryModeling.ProductInformation.searchButtonText') }}</el-button>
<el-button @click="resetMoldSearch">{{ t('FactoryModeling.ProductInformation.resetButtonText') }}</el-button>
</el-form-item>
</el-form>
</template>
</TableSelectDialog>
</template>
<script setup lang="ts">
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 { getSimpleUserList, type UserVO } from '@/api/system/user'
import TableSelectDialog from '@/components/TableSelectDialog/TableSelectDialog.vue'
/** */
defineOptions({ name: 'MoldOperateForm' })
const { t } = useI18n() //
const message = useMessage() //
const lineOptions = ref<OrganizationVO[]>([])
const operatorOptions = ref<UserVO[]>([])
const initializingOperateType = ref(false)
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中1修改时的数据加载2提交的按钮禁用
const formType = ref('') // 表单的类型create - 新增update - 修改
type MoldOperateFormData = {
id: number | undefined
operateType: string | number | undefined
moldId: number | undefined
deviceId: number | undefined
lineId: number | undefined
operateTime: string | undefined
operatorId: number | undefined
remark: string | undefined
}
const formData = ref<MoldOperateFormData>({
id: undefined,
operateType: undefined,
moldId: undefined,
deviceId: undefined,
lineId: undefined,
operateTime: undefined,
operatorId: undefined,
remark: undefined,
})
const validateMoldId = (_rule: any, value: any, callback: (error?: Error) => void) => {
if (formData.value.operateType == null) {
callback()
return
}
const hasValue = value !== undefined && value !== null && value !== ''
if (!hasValue) {
callback(new Error(t('MoldManagement.MoldOperate.validatorMoldRequired')))
} else {
callback()
}
}
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' }],
})
const formRef = ref() // 表单 Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
initSelectedItems()
// 新增时默认设置操作时间为当前时间
if (type === 'create') {
const now = new Date()
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())}`
}
await ensureLineOptionsLoaded()
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
initializingOperateType.value = true
const data = await MoldOperateApi.getMoldOperate(id)
formData.value = {
...formData.value,
...data,
}
if (formData.value.deviceId != null) {
ids.value = [Number(formData.value.deviceId)].filter((v) => Number.isFinite(v))
}
if (formData.value.moldId != null) {
moldIds.value = [Number(formData.value.moldId)].filter((v) => Number.isFinite(v))
}
} finally {
initializingOperateType.value = false
formLoading.value = false
}
}else{
ids.value=[]
moldIds.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,
moldId: raw.moldId,
lineId: raw.lineId,
operateTime: raw.operateTime,
operatorId: raw.operatorId,
remark: raw.remark,
}
// 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 ensureLineOptionsLoaded = async () => {
if (lineOptions.value.length) return
try {
const data = await OrganizationApi.getOrganizationList()
lineOptions.value = Array.isArray(data) ? data : []
} catch {
lineOptions.value = []
}
try {
operatorOptions.value = (await getSimpleUserList()) ?? []
} catch {
operatorOptions.value = []
}
}
// 设备更改
const deviceChange = async (deviceId:number) => {
if (String(formData.value.operateType) === '2' && deviceId) {
formData.value.moldId = undefined as any
}
}
watch(
() => formData.value.operateType,
async (val) => {
if (initializingOperateType.value) {
return
}
formData.value.deviceId = undefined as any
formData.value.moldId = undefined as any
ids.value = []
moldIds.value = []
selectedDeviceRows.value = []
selectedMoldRows.value = []
if (!val) {
return
}
}
)
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
operateType: undefined,
moldId: undefined,
deviceId: undefined,
lineId: undefined,
operateTime: undefined,
operatorId: undefined,
remark: undefined,
}
selectedDeviceRows.value = []
selectedMoldRows.value = []
ids.value = []
moldIds.value = []
formRef.value?.resetFields()
}
const deviceColumns = [
{ label: '设备编号', prop: 'deviceCode', minWidth: 140 },
{ label: '设备名称', prop: 'deviceName', minWidth: 160 },
{ label: '设备型号', prop: 'deviceModel', minWidth: 140 },
{ label: '所属车间', prop: 'workshop', minWidth: 140 }
]
const moldColumns = [
{ label: '模具编码', prop: 'code', minWidth: 140 },
{ label: '模具名称', prop: 'name', minWidth: 160 },
{ label: '版本', prop: 'version', minWidth: 100 },
{ label: '状态', prop: 'status', minWidth: 100 }
]
const fetchDeviceLedgerPage = (params: Record<string, any>) => {
return DeviceLedgerApi.getDeviceLedgerPage({
...params,
isScheduled: 1
})
}
const fetchMoldBrandPage = async (params: Record<string, any>) => {
const data = await MoldBrandApi.getMoldBrandPage(params)
const pageResult = data?.pageResult ?? data ?? {}
return { list: pageResult.list ?? [], total: pageResult.total ?? 0 }
}
const selectedDeviceRows = ref<any[]>([])
const selectedMoldRows = ref<any[]>([])
const handleDeviceSelectConfirm = (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)]
} else {
selectedDeviceRows.value = []
formData.value.deviceId = undefined
ids.value = []
}
nextTick(() => {
formRef.value?.clearValidate?.('deviceId')
})
}
const handleMoldSelectConfirm = (payload: { ids: (number | string)[]; rows: any[] }) => {
const row = payload.rows[0]
if (row) {
selectedMoldRows.value = [row]
formData.value.moldId = Number(row.id)
moldIds.value = [Number(row.id)]
} else {
selectedMoldRows.value = []
formData.value.moldId = undefined
moldIds.value = []
}
nextTick(() => {
formRef.value?.clearValidate?.('moldId')
})
}
// 1. 自定义表单的查询参数
const searchParams = reactive({
deviceCode: '',
deviceName: '',
})
const searchFormRef = ref()
const handleSearch = () => {
// 触发弹窗内部重新加载数据
deviceSelectDialogRef.value?.reload?.()
}
const resetSearch = () => {
searchFormRef.value?.resetFields()
handleSearch()
}
// 1. 自定义表单的查询参数
const searchMoldParams = reactive({
code: '',
name: '',
})
const searchMoldFormRef = ref()
const handleMoldSearch = () => {
// 触发弹窗内部重新加载数据
moldSelectDialogRef.value?.reload?.()
}
const resetMoldSearch = () => {
searchMoldFormRef.value?.resetFields()
handleMoldSearch()
}
const moldSelectDialogRef = ref<InstanceType<typeof TableSelectDialog> | null>(null)
// 2. 合并参数:将表单参数与组件内部的分页参数合并
const mergedQueryParams = computed(() => ({ ...searchParams }))
const mergedMoldQueryParams = computed(() => {
const status = String(formData.value.operateType) === '1' ? 1 : String(formData.value.operateType) === '2' ? 0 : undefined
return { ...searchMoldParams, ...(status !== undefined ? { status } : {}) }
})
const ids = ref<number[]>([])
const moldIds= ref<number[]>([])
const itemList = ref<DeviceLedgerVO[]>([])
const moldItemList = ref<MoldVO[]>([])
const deviceSelectDialogRef = ref<InstanceType<typeof TableSelectDialog> | null>(null)
const deviceList = ref<DeviceLedgerVO[]>([])
const selectedRows = ref<any[]>([])
const total = ref(0)
const queryFormRef = ref()
const loading = ref(true)
const displayItemDevice = computed( () => {
if (formData.value.deviceId == null) return ''
if (selectedDeviceRows.value.length) {
const row = selectedDeviceRows.value[0]
return row.deviceName || row.name || row.deviceCode || ''
}
if (!itemList.value.length) {
return String(formData.value.deviceId)
}
const map = new Map(itemList.value.map((item) => [item.id, item.deviceName]))
return map.get(formData.value.deviceId) || ''
})
const moldDisplayText = computed(() => {
if (formData.value.moldId == null) return ''
if (selectedMoldRows.value.length) {
const row = selectedMoldRows.value[0]
return row.name || row.code || ''
}
if (!moldItemList.value.length) {
return String(formData.value.moldId)
}
const map = new Map(moldItemList.value.map((item) => [item.id, item.name]))
return map.get(formData.value.moldId) || ''
})
const openCriticalComponentDialog = async () => {
searchParams.deviceCode=''
searchParams.deviceName=''
const rows = selectedDeviceRows.value.map((item) => ({ ...item, id: Number(item.id) }))
deviceSelectDialogRef.value?.open(rows)
}
const openMoldSelectDialog = () => {
searchMoldParams.code=''
searchMoldParams.name=''
const rows = selectedMoldRows.value.map((item) => ({ ...item, id: Number(item.id) }))
moldSelectDialogRef.value?.open(rows)
}
const toDeviceRows = (split: any) => {
return split.map((item: any) => ({
id: item,
deviceName: item
}))
}
const initSelectedItems = async () => {
if (!itemList.value.length) {
loading.value = true
try {
itemList.value = await DeviceLedgerApi.getDeviceLedgerList()
} finally {
loading.value = false
}
}
if (!moldItemList.value.length) {
loading.value = true
try {
moldItemList.value = await MoldBrandApi.getMoldAllList()
} finally {
loading.value = false
}
}
}
</script>