<template>
|
<FormDialog
|
v-model="visible"
|
:title="type === 'add' ? '绑定工艺路线' : type === 'detail' ? '查看工艺路线' : '编辑工艺路线'"
|
width="1400px"
|
:operation-type="type"
|
:column="8"
|
@close="handleClose"
|
@confirm="handleConfirm"
|
@cancel="handleClose"
|
>
|
<div :class="{ 'is-detail': isDetail }">
|
<!-- ================= 基本信息 ================= -->
|
<el-descriptions :column="3">
|
<el-descriptions-item label="编号" align="center" v-if="formData.productOrderList">
|
{{ formData.productOrderList.salesContractNo || "暂无数据" }}
|
</el-descriptions-item>
|
|
<el-descriptions-item label="制单日期" align="center" v-if="formData.productOrderList">
|
{{ formData.productOrderList.entryDate || "暂无数据" }}
|
</el-descriptions-item>
|
|
<el-descriptions-item label="交付日期" align="center" v-if="formData.productOrderList">
|
{{ formData.productOrderList.deliveryDate || "暂无数据" }}
|
</el-descriptions-item>
|
</el-descriptions>
|
|
<el-descriptions border :column="4">
|
<el-descriptions-item label="委托单位" :span="2" align="center">
|
{{formData.clientName || "--"}}
|
</el-descriptions-item>
|
|
<el-descriptions-item label="数量" :span="1" align="center">
|
{{formData.orderQty || "--"}}
|
</el-descriptions-item>
|
|
<el-descriptions-item label="成品尺寸" :span="1" align="center">
|
{{formData.finishedSize || "--"}}
|
</el-descriptions-item>
|
|
<el-descriptions-item label="产品名称" :span="2" align="center">
|
{{formData.productName || "--"}}
|
</el-descriptions-item>
|
|
<el-descriptions-item label="单据类型" :span="2" align="center">
|
<el-checkbox-group v-model="introductionLetterList" :disabled="isDetail">
|
<el-checkbox label="介绍信" value="介绍信" />
|
<el-checkbox label="商标注册书" value="商标注册书" />
|
<el-checkbox label="委印单" value="委印单" />
|
</el-checkbox-group>
|
</el-descriptions-item>
|
</el-descriptions>
|
|
<!-- ================= 材料表 ================= -->
|
<div class="process-table-header">
|
<div class="section-title">材料信息</div>
|
<el-button v-if="!isDetail" type="primary" size="small" @click="addMaterialRow">新增一行</el-button>
|
</div>
|
<el-table border :data="formData.materialInfo" style="width: 100%">
|
<el-table-column label="材料名称">
|
<template #default="{ row }" >
|
<el-tree-select
|
v-if="!isDetail"
|
v-model="row.productId"
|
placeholder="请选择"
|
clearable
|
check-strictly
|
@change="(val) => getModels(val, row)"
|
:data="productOptions"
|
:render-after-expand="false"
|
:disabled="isDetail"
|
style="width: 100%"
|
/>
|
<span v-else>{{ row.name }}</span>
|
</template>
|
</el-table-column>
|
<el-table-column label="规格">
|
<template #default="{ row }">
|
<el-select
|
v-if="!isDetail"
|
v-model="row.productModelId"
|
placeholder="请选择规格"
|
filterable
|
clearable
|
@change="(val) => handleMaterialModelChange(val, row)"
|
:disabled="isDetail"
|
>
|
<el-option
|
v-for="item in row.modelOptions || []"
|
:key="item.id"
|
:label="item.model"
|
:value="item.id"
|
/>
|
</el-select>
|
<span v-else>{{ row.model }}</span>
|
</template>
|
</el-table-column>
|
<el-table-column label="数量">
|
<template #default="{ row }">
|
<el-input v-model="row.num" placeholder="数量" :disabled="isDetail">
|
</el-input>
|
</template>
|
</el-table-column>
|
<el-table-column label="计量单位">
|
<template #default="{ row }">
|
<el-input v-model="row.unit" placeholder="计量单位" :disabled="isDetail" />
|
</template>
|
</el-table-column>
|
<el-table-column label="单价">
|
<template #default="{ row }">
|
<el-input v-model="row.price" placeholder="单价" :disabled="isDetail">
|
</el-input>
|
</template>
|
</el-table-column>
|
<el-table-column label="金额">
|
<template #default="{ row }">
|
<el-input v-model="row.totalAmount" placeholder="金额" :disabled="isDetail" />
|
</template>
|
</el-table-column>
|
<el-table-column v-if="!isDetail" label="操作" width="80">
|
<template #default="{ $index }">
|
<el-button type="danger" size="small" @click="removeMaterialRow($index)">删除</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
<el-descriptions border :column="2" :span="2">
|
<el-descriptions-item
|
label="注意事项"
|
:span="2"
|
align="center"
|
style="white-space: pre-line; word-break: break-all; min-height: 60px;"
|
>
|
<el-input
|
v-model="formData.productDescription"
|
:autosize="{ minRows: 2, maxRows: 4 }"
|
type="textarea"
|
placeholder="请输入注意事项"
|
:disabled="isDetail"
|
/>
|
</el-descriptions-item>
|
</el-descriptions>
|
<!-- ================= 切料图示 ================= -->
|
<div class="section-title">切料图示</div>
|
<ActionFileUpload
|
style="width: 50%;float: left;"
|
v-model:file-list="formData.cuttingFileVo"
|
:action="upload.url"
|
:headers="upload.headers"
|
:multiple="false"
|
:limit="1"
|
:replaceOnExceed="true"
|
:disabled="isDetail"
|
:name="'files'"
|
:onSuccess="onSuccess"
|
:onDownload="onDownload"
|
:onRemove="onRemove"
|
:onPreview="onPreview"
|
:onView="type === 'detail' ? false : true"
|
:tip-text="type === 'detail' ? '' : '支持图片(jpg, jpeg, png)格式'"
|
/>
|
<el-image
|
v-if="formData.cuttingFileVo.length > 0"
|
style="width: 100px; height: 100px"
|
:src="resolveFileUrl(getUploadFileUrl(formData.cuttingFileVo[0]))"
|
fit="cover"
|
/>
|
<!-- ================= 切料信息 ================= -->
|
<el-descriptions
|
border
|
:column="6"
|
direction="vertical"
|
style="width: 100%"
|
class="fixed-desc"
|
>
|
<el-descriptions-item label="切料尺寸" align="center">
|
<el-input v-model="formData.cutNum" placeholder="切料尺寸" :disabled="isDetail" />
|
</el-descriptions-item>
|
<el-descriptions-item label="切料数量" align="center">
|
<el-input v-model="formData.cutSize" placeholder="切料尺寸" :disabled="isDetail" />
|
</el-descriptions-item>
|
<el-descriptions-item label="中盒数量" align="center">
|
<el-input v-model="formData.mediumBoxQty" placeholder="中盒数量" :disabled="isDetail" />
|
</el-descriptions-item>
|
<el-descriptions-item label="小盒数量" align="center">
|
<el-input v-model="formData.smallBoxQty" placeholder="小盒数量" :disabled="isDetail" />
|
</el-descriptions-item>
|
<el-descriptions-item label="正数" align="center">
|
<el-input v-model="formData.positiveQty" placeholder="正数" :disabled="isDetail" />
|
</el-descriptions-item>
|
<el-descriptions-item label="加放数" align="center">
|
<el-input v-model="formData.allowanceQty" placeholder="加放数" :disabled="isDetail" />
|
</el-descriptions-item>
|
</el-descriptions>
|
|
<div class="middle-sheet-table">
|
<table class="middle-sheet-table__inner">
|
<tbody>
|
<tr>
|
<th>软片版:</th>
|
<th colspan="2">开张色</th>
|
<th>晒板</th>
|
<th colspan="2">开拼</th>
|
<th>别刀版</th>
|
<th>联色块</th>
|
</tr>
|
<tr>
|
<th rowspan="2">制版</th>
|
<th>设计制作费</th>
|
<th>拼版费</th>
|
<th>出片费</th>
|
<th>打样费</th>
|
<th>别刀版费</th>
|
<th>烫/凸版费</th>
|
<th>小计</th>
|
</tr>
|
<tr v-for="(plate, index) in formData.plateMaking" :key="index">
|
<td>
|
<el-input v-model="plate.designProductionFee" placeholder="请输入设计制作费" :disabled="isDetail" />
|
</td>
|
<td>
|
<el-input v-model="plate.impositionFee" placeholder="请输入拼版费" :disabled="isDetail" />
|
</td>
|
<td>
|
<el-input v-model="plate.filmOutputFee" placeholder="请输入出片费" :disabled="isDetail" />
|
</td>
|
<td>
|
<el-input v-model="plate.proofingFee" placeholder="请输入打样费" :disabled="isDetail" />
|
</td>
|
<td>
|
<el-input v-model="plate.doctorBladePlateFee" placeholder="请输入别刀版费" :disabled="isDetail" />
|
</td>
|
<td>
|
<el-input v-model="plate.hotEmbossingPlateFee" placeholder="请输入烫/凸版费" :disabled="isDetail" />
|
</td>
|
<td>
|
<el-input v-model="plate.subtotalFee" placeholder="请输入小计" :disabled="isDetail" />
|
</td>
|
</tr>
|
</tbody>
|
</table>
|
</div>
|
<!-- class="section-title" -->
|
<!-- ================= 工艺加工 ================= -->
|
<div class="process-table-header">
|
<div class="section-title">工艺加工</div>
|
<el-button v-if="!isDetail" type="primary" size="small" @click="addProcessRow">新增一行</el-button>
|
</div>
|
<el-table border :data="formData.processContent" style="width: 100%" :span-method="objectSpanMethod">
|
<el-table-column label="工序" width="140">
|
<template #default="{ row }">
|
<el-select
|
v-model="row.processId"
|
placeholder="请选择工序"
|
@change="(val) => onProcessChange(val, row)"
|
:disabled="isDetail"
|
>
|
<el-option
|
v-for="item in processOptions"
|
:key="item.id"
|
:label="item.name"
|
:value="item.id"
|
/>
|
</el-select>
|
</template>
|
</el-table-column>
|
<el-table-column label="开数">
|
<template #default="{ row }">
|
<el-input v-model="row.openCount" placeholder="请输入开数" :disabled="isDetail" />
|
</template>
|
</el-table-column>
|
<el-table-column label="工艺正数">
|
<template #default="{ row }">
|
<el-input v-model="row.processPositive" placeholder="请输入工艺正数" :disabled="isDetail" />
|
</template>
|
</el-table-column>
|
<el-table-column label="加放数">
|
<template #default="{ row }">
|
<el-input v-model="row.allowanceQty" placeholder="请输入加放数" :disabled="isDetail" />
|
</template>
|
</el-table-column>
|
<el-table-column width="180">
|
<template #header>
|
<span class="required">*</span>机台
|
</template>
|
<template #default="{ row }">
|
<el-select
|
v-model="row.deviceId"
|
placeholder="请选择机台"
|
filterable
|
clearable
|
@change="(val) => handleDeviceChange(val, row)"
|
:disabled="isDetail"
|
>
|
<el-option
|
v-for="item in deviceOptions"
|
:key="item.id"
|
:label="item.deviceName"
|
:value="item.id"
|
/>
|
</el-select>
|
</template>
|
</el-table-column>
|
<el-table-column width="220">
|
<template #header>
|
<span class="required">*</span>报工人
|
</template>
|
<template #default="{ row }">
|
<el-select
|
v-if="!isDetail"
|
v-model="row.reportUserIds"
|
placeholder="请选择报工人"
|
filterable
|
clearable
|
multiple
|
collapse-tags
|
collapse-tags-tooltip
|
@change="(val) => handleReportUsersChange(val, row)"
|
:disabled="isDetail"
|
>
|
<el-option
|
v-for="item in userOptions"
|
:key="item.userId"
|
:label="item.nickName"
|
:value="item.userId"
|
/>
|
</el-select>
|
<el-tag
|
v-else
|
v-for="item in row.reportWorkerList"
|
|
:key="item.id"
|
>
|
{{ item.userName }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="工艺要求">
|
<template #default="{ rowIndex }">
|
<el-input
|
v-model="formData.processRequirement"
|
type="textarea"
|
:rows="6"
|
placeholder="请输入工艺要求"
|
:disabled="isDetail"
|
/>
|
</template>
|
</el-table-column>
|
<el-table-column v-if="!isDetail" label="操作" width="80">
|
<template #default="{ $index }">
|
<el-button type="danger" size="small" @click="removeProcessRow($index)">删除</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
|
<!-- ================= 包装信息 ================= -->
|
<el-descriptions border :column="3" class="mt">
|
<el-descriptions-item label="送货地点" align="center">
|
<el-input v-model="formData.deliveryAddress" placeholder="送货地点" :disabled="isDetail" />
|
</el-descriptions-item>
|
|
<el-descriptions-item label="联系人" align="center">
|
<el-input v-model="formData.contactName" placeholder="联系人" :disabled="isDetail" />
|
</el-descriptions-item>
|
|
<el-descriptions-item label="包装要求" align="center">
|
<el-input v-model="formData.packagingRequirement" placeholder="包装要求" :disabled="isDetail" />
|
</el-descriptions-item>
|
|
<el-descriptions-item label="尺寸" align="center">
|
<el-input v-model="formData.postProcessSize" placeholder="尺寸" :disabled="isDetail" />
|
</el-descriptions-item>
|
|
<el-descriptions-item label="定货数量" align="center">
|
{{formData.orderQty || "--"}}
|
</el-descriptions-item>
|
|
<el-descriptions-item label="实交数量" :span="3" align="center">
|
<el-input v-model="formData.actualDeliveryQty" placeholder="实交数量" :disabled="isDetail" />
|
</el-descriptions-item>
|
</el-descriptions>
|
</div>
|
</FormDialog>
|
<filePreview ref="filePreviewRef" />
|
</template>
|
|
<script setup>
|
import { ref, reactive, computed, onMounted, watch, getCurrentInstance } from 'vue'
|
import dayjs from 'dayjs'
|
import FormDialog from '@/components/Dialog/FormDialog.vue'
|
import ActionFileUpload from "@/components/Upload/ActionFileUpload.vue";
|
import { list } from "@/api/productionManagement/productionProcess.js"
|
import { modelList, productTreeList } from "@/api/basicData/product.js"
|
import {getSalesLedgerWithProducts} from "@/api/salesManagement/salesLedger.js"
|
import { getDeviceLedger } from "@/api/equipmentManagement/ledger.js"
|
import { userListNoPageByTenantId } from "@/api/system/user.js"
|
import { getToken } from "@/utils/auth";
|
import filePreview from '@/components/filePreview/index.vue'
|
import { ElMessage } from "element-plus";
|
|
const props = defineProps({
|
modelValue: {
|
type: Boolean,
|
default: false
|
},
|
type: {
|
type: String,
|
default: 'add'
|
},
|
orderData: {
|
type: Object,
|
default: () => ({})
|
},
|
rowData: {
|
type: Object,
|
default: null
|
}
|
})
|
|
const emit = defineEmits(['update:modelValue', 'confirm'])
|
const { proxy } = getCurrentInstance()
|
|
const visible = computed({
|
get: () => props.modelValue,
|
set: (val) => emit('update:modelValue', val)
|
})
|
|
const isDetail = computed(() => props.type === 'detail')
|
const processOptions = ref([])
|
const deviceOptions = ref([])
|
const userOptions = ref([])
|
const productOptions = ref([])
|
const introductionLetterList = ref([])
|
const upload = reactive({
|
url: import.meta.env.VITE_APP_BASE_API + '/basic/customer-follow/upload',
|
headers: { Authorization: 'Bearer ' + getToken() }
|
})
|
|
const filePreviewRef = ref()
|
const formData = reactive({
|
productOrderList:null,
|
salesLedgerId: null,
|
productOrderId: null,
|
printOrderTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
cuttingFileVo:[],
|
finishTime: "",
|
no: "",
|
productName: "",
|
productDescription: "",
|
clientName: "",
|
finishedSize: "",
|
cutNum: "",
|
cutSize:"",
|
mediumBoxQty: "",
|
smallBoxQty: "",
|
positiveQty: "",
|
allowanceQty: "",
|
introductionLetter: "",
|
plateMaking: [
|
{
|
designProductionFee: "",
|
impositionFee: "",
|
filmOutputFee: "",
|
proofingFee: "",
|
doctorBladePlateFee: "",
|
hotEmbossingPlateFee: "",
|
subtotalFee: ""
|
}
|
],
|
processContent: [
|
{
|
id: "1",
|
processId: "",
|
processName: "",
|
mediumBoxQty: "",
|
smallBoxQty: "",
|
openCount: "",
|
processPositive: "",
|
allowanceQty: "",
|
deviceId: "",
|
deviceName: "",
|
reportUserIds: [],
|
reportWorkerList: []
|
}
|
],
|
materialInfo: [
|
{
|
id: "1",
|
productId: "",
|
name: "",
|
productModelId: "",
|
model: "",
|
modelOptions: [],
|
num: "",
|
numSuffix: "张",
|
unitSuffix: "元/kg",
|
unit: "",
|
price: "",
|
totalAmount: ""
|
}
|
],
|
processRequirement: "",
|
deliveryAddress: "",
|
contactName: "",
|
packagingRequirement: "",
|
postProcessSize: "",
|
orderQty: "",
|
actualDeliveryQty: "",
|
productionDept: "",
|
technicalDept: "",
|
warehouseDept: "",
|
productModelId: "",
|
specificationModel:"",
|
})
|
|
const getUploadFileUrl = (file) => {
|
console.log("file", file)
|
const response = file?.response
|
const data = response?.data
|
if (Array.isArray(data) && data.length) {
|
return data[0]?.fileUrl || data[0]?.url || data[0]?.tempPath || ""
|
}
|
|
return file?.url || file?.fileUrl || data?.tempPath || data?.url || data?.fileUrl || ""
|
}
|
|
// 监听 checkbox group 变化并同步到 introductionLetter 字符串
|
watch(introductionLetterList, (val) => {
|
formData.introductionLetter = val.join(',')
|
})
|
const onProcessChange = (processId, row) => {
|
const selected = processOptions.value.find(item => item.id === processId)
|
row.processName = selected?.name || ''
|
}
|
const cloneDeep = (val) => JSON.parse(JSON.stringify(val))
|
|
const createDefaultFormData = () => ({
|
productOrderList: null,
|
salesLedgerId: null,
|
productOrderId: null,
|
printOrderTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
cuttingFileVo: [],
|
finishTime: "",
|
no: "",
|
productName: "",
|
productDescription: "",
|
clientName: "",
|
finishedSize: "",
|
cutNum: "",
|
cutSize: "",
|
mediumBoxQty: "",
|
smallBoxQty: "",
|
positiveQty: "",
|
allowanceQty: "",
|
introductionLetter: "",
|
plateMaking: [
|
{
|
designProductionFee: "",
|
impositionFee: "",
|
filmOutputFee: "",
|
proofingFee: "",
|
doctorBladePlateFee: "",
|
hotEmbossingPlateFee: "",
|
subtotalFee: ""
|
}
|
],
|
processContent: [
|
{
|
id: "1",
|
processId: "",
|
processName: "",
|
mediumBoxQty: "",
|
smallBoxQty: "",
|
openCount: "",
|
processPositive: "",
|
allowanceQty: "",
|
deviceId: "",
|
deviceName: "",
|
reportUserIds: [],
|
reportWorkerList: []
|
}
|
],
|
materialInfo: [
|
{
|
id: "1",
|
productId: "",
|
name: "",
|
productModelId: "",
|
model: "",
|
modelOptions: [],
|
num: "",
|
numSuffix: "张",
|
unitSuffix: "元/kg",
|
unit: "",
|
price: "",
|
totalAmount: ""
|
}
|
],
|
processRequirement: "",
|
deliveryAddress: "",
|
contactName: "",
|
packagingRequirement: "",
|
postProcessSize: "",
|
orderQty: "",
|
actualDeliveryQty: "",
|
productionDept: "",
|
technicalDept: "",
|
warehouseDept: "",
|
productModelId: "",
|
specificationModel: "",
|
cuttingFileId:""
|
})
|
|
const resetForm = () => {
|
const next = createDefaultFormData()
|
Object.keys(next).forEach((key) => {
|
formData[key] = Array.isArray(next[key]) ? cloneDeep(next[key]) : next[key]
|
})
|
introductionLetterList.value = []
|
}
|
|
const onSuccess = (response, uploadFile, uploadFiles) => {
|
const data = response?.data
|
|
if (uploadFile && !uploadFile.url) {
|
uploadFile.url = (Array.isArray(data) ? data?.[0]?.fileUrl : data?.fileUrl) || data?.tempPath || data?.url || response?.url || ""
|
}
|
if (Array.isArray(uploadFiles) && uploadFiles.length) {
|
formData.cuttingFileVo = [uploadFiles[uploadFiles.length - 1]]
|
formData.cuttingFileId = data?.[0]?.id || ""
|
}
|
}
|
|
const JavaApi = computed(() => proxy?.javaApi || "")
|
|
const onRemove = (file) => {
|
formData.cuttingFileVo = []
|
formData.cuttingFileId = ""
|
}
|
|
const resolveFileUrl = (rawUrl) => {
|
console.log("rawUrl", rawUrl)
|
const u = String(rawUrl || "")
|
if (!u) return ""
|
if (/^(https?:)?\/\//i.test(u)) return u
|
if (/^(blob:|data:)/i.test(u)) return u
|
const base = String(JavaApi.value || "").replace(/\/+$/, "")
|
if (!base) return u
|
if (u.startsWith("/")) return base + u
|
return base + "/" + u
|
}
|
|
// 文件预览/下载
|
const onDownload = (file) => {
|
console.log(file)
|
const url = resolveFileUrl(getUploadFileUrl(file))
|
if (!url) return
|
proxy?.$modal?.loading?.("正在下载文件,请稍候...")
|
proxy.$download.name(url);
|
proxy?.$modal?.closeLoading?.()
|
}
|
|
const onPreview = (file) => {
|
const url = resolveFileUrl(getUploadFileUrl(file))
|
if (!url) return
|
filePreviewRef.value?.openUrl?.(url);
|
}
|
|
|
const mergeRowDataToForm = (source) => {
|
if (!source || typeof source !== 'object') {
|
return
|
}
|
|
Object.keys(formData).forEach((key) => {
|
if (source[key] !== undefined) {
|
formData[key] = Array.isArray(source[key]) ? cloneDeep(source[key]) : source[key]
|
}
|
})
|
|
if (formData.cuttingFileVo && !Array.isArray(formData.cuttingFileVo)) {
|
formData.cuttingFileVo = [formData.cuttingFileVo]
|
}
|
if (Array.isArray(formData.cuttingFileVo)) {
|
formData.cuttingFileVo = formData.cuttingFileVo
|
.filter(Boolean)
|
.map((f) => ({
|
...f,
|
name: f?.name || f?.fileName || "",
|
url: f?.url || f?.fileUrl || "",
|
}))
|
}
|
|
// 兼容 index.vue 里常用字段名与弹窗字段名不一致的情况
|
if (source.productName === undefined && source.productCategory !== undefined) {
|
formData.productName = source.productCategory
|
}
|
if (source.orderQty === undefined && source.quantity !== undefined) {
|
formData.orderQty = source.quantity
|
}
|
if (source.no === undefined && source.salesContractNo !== undefined) {
|
formData.no = source.salesContractNo
|
}
|
if (source.clientName === undefined && source.customerName !== undefined) {
|
formData.clientName = source.customerName
|
}
|
if (source.productOrderId === undefined && source.id !== undefined) {
|
formData.productOrderId = source.id
|
}
|
|
introductionLetterList.value = String(formData.introductionLetter || "")
|
.split(",")
|
.map(s => s.trim())
|
.filter(Boolean)
|
}
|
|
// 获取销售订单
|
const getProductOrder = () => {
|
if(!formData.salesLedgerId) return
|
getSalesLedgerWithProducts({
|
type: "1",
|
id: formData.salesLedgerId
|
}).then(res => {
|
if(res){
|
formData.productOrderList = res
|
}
|
console.log(formData)
|
})
|
|
}
|
|
watch(() => props.orderData, (val) => {
|
mergeRowDataToForm(val)
|
}, { immediate: true, deep: true })
|
|
watch(
|
() => props.rowData,
|
(val) => {
|
mergeRowDataToForm(val)
|
getProductOrder()
|
},
|
{ immediate: true, deep: true }
|
)
|
|
const getProcessList = () => {
|
list().then(res => {
|
processOptions.value = res.data
|
})
|
}
|
|
|
|
const getDeviceList = () => {
|
getDeviceLedger().then(res => {
|
deviceOptions.value = Array.isArray(res?.data) ? res.data : []
|
})
|
}
|
|
const getUserList = () => {
|
userListNoPageByTenantId().then(res => {
|
userOptions.value = Array.isArray(res?.data) ? res.data : []
|
})
|
}
|
|
const convertProductOptions = (data) => {
|
return data.map(item => ({
|
label: item.label || item.productName || item.name || "",
|
value: item.id,
|
children: item.children?.length ? convertProductOptions(item.children) : undefined
|
}))
|
}
|
|
const findProductLabelById = (options, productId) => {
|
for (const item of options) {
|
if (item.value === productId) {
|
return item.label
|
}
|
if (item.children?.length) {
|
const label = findProductLabelById(item.children, productId)
|
if (label) {
|
return label
|
}
|
}
|
}
|
return ""
|
}
|
|
const getMaterialProductOptions = () => {
|
productTreeList().then(res => {
|
const rawData = Array.isArray(res?.data) ? res.data : Array.isArray(res) ? res : []
|
productOptions.value = convertProductOptions(rawData)
|
})
|
}
|
|
const handleProcessChange = (val, row) => {
|
console.log(row)
|
const process = processOptions.value.find(item => item.id === val)
|
if (process) {
|
row.processName = process.name
|
console.log(process)
|
if (process.deviceId) {
|
row.deviceId = process.deviceId || ""
|
row.deviceName = process.deviceName || ""
|
}
|
}
|
}
|
|
const handleDeviceChange = (val, row) => {
|
const device = deviceOptions.value.find(item => item.id === val)
|
row.deviceName = device?.deviceName || ""
|
row.deviceId = val || ""
|
}
|
|
const handleReportUsersChange = (val, row) => {
|
const userMap = new Map(
|
userOptions.value.map(item => [item.userId, item.nickName])
|
)
|
row.reportWorkerList = (val || []).map(userId => ({
|
userId,
|
userName: userMap.get(userId) || ''
|
}))
|
}
|
|
const getModels = (val, row) => {
|
row.productId = val || ""
|
row.name = val ? findProductLabelById(productOptions.value, val) : ""
|
row.productModelId = ""
|
row.model = ""
|
row.unit = ""
|
row.modelOptions = []
|
if (!val) {
|
return
|
}
|
modelList({ id: val }).then(res => {
|
row.modelOptions = Array.isArray(res) ? res : Array.isArray(res?.data) ? res.data : []
|
})
|
}
|
|
const handleMaterialModelChange = (val, row) => {
|
const currentModel = (row.modelOptions || []).find(item => item.id === val)
|
row.productModelId = val || ""
|
row.model = currentModel?.model || ""
|
row.unit = currentModel?.unit || ""
|
}
|
|
// 材料信息
|
const addMaterialRow = () => {
|
formData.materialInfo.push({
|
id: Date.now().toString(),
|
productId: "",
|
name: "",
|
productModelId: "",
|
model: "",
|
modelOptions: [],
|
num: "",
|
numSuffix: "张",
|
unitSuffix: "元/kg",
|
unit: "",
|
price: "",
|
totalAmount: ""
|
})
|
}
|
|
const removeMaterialRow = (index) => {
|
formData.materialInfo.splice(index, 1)
|
}
|
|
const addProcessRow = () => {
|
formData.processContent.push({
|
id: Date.now().toString(),
|
processId: "",
|
processName: "",
|
openCount: "",
|
processPositive: "",
|
allowanceQty: "",
|
deviceId: "",
|
deviceName: "",
|
reportUserIds: [],
|
reportWorkerList: []
|
})
|
}
|
|
const removeProcessRow = (index) => {
|
formData.processContent.splice(index, 1)
|
}
|
|
const objectSpanMethod = ({ column, rowIndex }) => {
|
if (column.label === "工艺要求") {
|
if (rowIndex === 0) {
|
return {
|
rowspan: Math.max(formData.processContent.length, 1),
|
colspan: 1,
|
}
|
}
|
return {
|
rowspan: 0,
|
colspan: 0,
|
}
|
}
|
}
|
|
const handleClose = () => {
|
visible.value = false
|
}
|
|
const handleConfirm = () => {
|
if (isDetail.value) {
|
return
|
}
|
const rows = Array.isArray(formData.processContent) ? formData.processContent : []
|
for (let i = 0; i < rows.length; i++) {
|
const row = rows[i] || {}
|
if (!row.deviceId) {
|
ElMessage.warning(`工艺加工第${i + 1}行:机台必填`)
|
return
|
}
|
if (!Array.isArray(row.reportUserIds) || row.reportUserIds.length === 0) {
|
ElMessage.warning(`工艺加工第${i + 1}行:报工人必填`)
|
return
|
}
|
}
|
const payload = cloneDeep(formData)
|
delete payload.productOrderList
|
if (Array.isArray(payload.materialInfo)) {
|
payload.materialInfo = payload.materialInfo.map((item) => {
|
const { modelOptions, ...rest } = item || {}
|
return rest
|
})
|
}
|
emit('confirm', payload)
|
}
|
|
onMounted(() => {
|
getProcessList()
|
getDeviceList()
|
getUserList()
|
getMaterialProductOptions()
|
})
|
defineExpose({
|
getProductOrder,
|
resetForm
|
})
|
</script>
|
|
<style scoped lang="scss">
|
.section-title {
|
font-size: 16px;
|
font-weight: bold;
|
margin: 20px 0 10px;
|
padding-left: 10px;
|
border-left: 4px solid #409eff;
|
}
|
|
.fixed-desc {
|
margin-top: 20px;
|
:deep(.el-descriptions__table) {
|
table-layout: fixed;
|
width: 100%;
|
}
|
:deep(.el-descriptions__cell) {
|
width: 25%;
|
word-break: break-word;
|
}
|
}
|
|
.middle-sheet-table {
|
margin-top: 20px;
|
width: 100%;
|
border: 1px solid #ebeef5;
|
}
|
|
.middle-sheet-table__inner {
|
width: 100%;
|
border-collapse: collapse;
|
table-layout: fixed;
|
|
th, td {
|
border: 1px solid #ebeef5;
|
padding: 8px;
|
text-align: center;
|
font-size: 14px;
|
}
|
|
th {
|
background-color: #f5f7fa;
|
color: #606266;
|
font-weight: bold;
|
}
|
|
:deep(.el-input__wrapper) {
|
box-shadow: none !important;
|
background-color: transparent;
|
}
|
}
|
|
.process-table-header {
|
margin-top: 20px;
|
margin-bottom: 10px;
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
span {
|
font-size: 16px;
|
font-weight: bold;
|
}
|
}
|
|
.mt {
|
margin-top: 20px;
|
}
|
:deep(.required) {
|
color: #f56c6c;
|
}
|
:deep(.el-textarea__inner){
|
box-shadow: none;
|
}
|
|
.is-detail {
|
:deep(.el-input__wrapper) {
|
box-shadow: none !important;
|
background-color: transparent !important;
|
}
|
|
:deep(.el-input__inner) {
|
color: var(--el-text-color-regular) !important;
|
-webkit-text-fill-color: var(--el-text-color-regular) !important;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
overflow: hidden;
|
}
|
|
:deep(.el-input-group__append),
|
:deep(.el-input-group__prepend) {
|
background-color: transparent !important;
|
box-shadow: none !important;
|
color: var(--el-text-color-regular) !important;
|
}
|
|
:deep(.el-select__wrapper) {
|
box-shadow: none !important;
|
background-color: transparent !important;
|
}
|
|
:deep(.el-select__selected-item) {
|
color: var(--el-text-color-regular) !important;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
overflow: hidden;
|
}
|
|
:deep(.el-select__caret) {
|
display: none;
|
}
|
|
:deep(.el-textarea__inner) {
|
box-shadow: none !important;
|
background-color: transparent !important;
|
color: var(--el-text-color-regular) !important;
|
-webkit-text-fill-color: var(--el-text-color-regular) !important;
|
overflow: hidden;
|
display: -webkit-box;
|
-webkit-line-clamp: 2;
|
-webkit-box-orient: vertical;
|
}
|
}
|
</style>
|