<template>
<div class="p-3 position-relative" v-loading="isLoading">
<DControl
:excludes="excludesData"
@add="handleEdit"
@copy="handleEdit('copy')"
@save="handleSubmit(0)"
@submit="handleSubmit(1)"
@audit="handleExecute"
@unAudit="handleAudit"
@upQuery="handleUpDownQueryList('up')"
@downQuery="handleUpDownQueryList('down')"
@pushDown="handlePushDown"
@exprot="handlEexprot"
@setHit="handleSetHit"
:auth="authConfig"
:type="controlType"
:operateList="operateData"
:includes="includesList"
@checkOrder="handleSelectOrderList"
@return="handleReturn"
/>
<DStateImg :type="formData.state" />
<t-form
:data="formData"
class="edit-page"
ref="formValidator"
:rules="rules"
scrollToFirstError="smooth"
:disabled="isDisabled"
:showErrorMessage="showErrorMessage"
>
<hr style="border-color: #ccc;">
<div class="flex justify-between mb-4 mt-4">
<t-form-item label="单据编号" name="orderNo" class="w-33%">
<t-input
v-model="formData.orderNo"
placeholder="保存时自动生成"
disabled
clearable
size="small"
></t-input>
</t-form-item>
<t-form-item label="物料编码" name="materialCode" class="w-33%">
<t-input v-model="formData.materialCode" placeholder="" disabled size="small"></t-input>
</t-form-item>
<t-form-item label="物料名称" name="materialName" class="w-33%">
<t-input v-model="formData.materialName" placeholder="请选择" disabled size="small"></t-input>
</t-form-item>
</div>
<div class="flex justify-between mb-4">
<t-form-item label="规格属性" name="specification" class="w-66%">
<t-input v-model="formData.specification" disabled size="small"></t-input>
</t-form-item>
<t-form-item label="生产数量" name="quantity" class="w-33%">
<t-input v-model="formData.quantity" disabled size="small"></t-input>
</t-form-item>
</div>
<div class="flex justify-between mb-4">
<t-form-item label="工单负责人" name="" class="w-33%">
<t-select v-model="formData.warehouseIds" multiple placeholder="请选择" size="small" :options="warehouseData" :min-collapsed-num="1" ></t-select>
</t-form-item>
<t-form-item label="加工要求" name="" class="w-66%">
<t-input
v-model="formData.remark"
type="textarea"
placeholder="请输入要求"
clearable
class="w-full"
:maxlength="200"
:disabled="isDisabled"
show-limit-number
/>
</t-form-item>
</div>
<div class="flex justify-between mb-8">
<t-form-item label="源头单据" name="materialCode" class="w-33%">
<t-input v-model="formData.sourceOrderNo" placeholder="" disabled size="small"></t-input>
</t-form-item>
</div>
<t-card :title="`明细信息`" :bordered="false" header-bordered>
<t-form-item name="itemList" class="hideStar" label-width="0">
<SubItemInfo v-model="formData.itemList" :state="formData.state" />
</t-form-item>
</t-card>
<br />
</t-form>
<upOrDownQueryDialog ref="queryRef" />
<orderSelectDrawer ref="orderSelectDrawerRef" @order-select="orderSelectBack" />
<pushDownDialog ref="pushDownRef" @handle-success="pushDownSuccess" />
<selectListDialog ref="selectListDialogRef" @order-select="orderSelectBack" />
<ExecTask ref="execTask" @success="() => getData()" />
<t-image-viewer v-model:visible="imageVisible" :images="[imageUrl]"> </t-image-viewer>
</div>
</template>
<script setup lang="jsx">
import { merge, get, post, put, jsonToObj } from '@common'
import { nextTick, onMounted, ref} from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useDict } from '@/store/dict'
import { useErp } from '@/store/erp'
import { useStock } from '@/store/stock'
import { MessagePlugin } from 'tdesign-vue-next'
import dayjs from 'dayjs'
import { download, useEditRefresh } from '@/utils'
import SubItemInfo from './components/subItemInfo.vue'
import upOrDownQueryDialog from '@/components/upOrDownQueryDialog.vue'
import orderSelectDrawer from '@/components/OrderSelectDrawer.vue'
import selectListDialog from '@/components/selectListDialog/index.vue'
import { debounce } from 'lodash'
import { saveAs } from 'file-saver'
const dict = useDict()
const route = useRoute()
const router = useRouter()
const stock = useStock()
const erp = useErp()
const pushDownRef = ref(null)
const editRefresh = useEditRefresh('productionReturn')
// 下推
const handlePushDown = async () => {
// 组合数据
const list = []
const itemList = JSON.parse(formData.value.itemList)
itemList.forEach((e) => list.push(`${formData.value.id}_${e.id}`))
pushDownRef.value.show(list, '13', 'productionOrder', 'details', '13,14,15,16,23')
}
const INIT_STATUS = {
productionOrgId: window.$wujiePropsData?.userInfo?.orgId,
productionOrgName: window.$wujiePropsData?.userInfo?.orgName,
orderNo: '',
returnUserId: '',
warehouseUserId: '',
productionWorkshop: '0',
returnTime: dayjs().format('YYYY-MM-DD'),
itemList: '',
id: '',
state: '',
remark: '',
materialCode: '', // 物料编码
materialName: '', // 物料名称
specification: '', // 规格属性
quantity: '', // 生产数量
sourceOrderNo:'',//源头单据
files:[]
}
const execTask = ref(null)
const queryRef = ref(null)
const formValidator = ref(null)
const orderSelectDrawerRef = ref(null)
const selectListDialogRef = ref(null)
const isLoading = ref(false)
const formData = ref({ ...INIT_STATUS })
const excludesData = ref(['filter', 'del', 'link'])
// const disablesData = ref(['audit', 'submit'])
const controlType = ref('add') // DControl 展示类型
const imageVisible = ref(false)
const imageUrl = ref('')
const first = ref(null)
const isDisabled = ref(false)
const showErrorMessage = ref(false)
const warehouseData = ref([])
const authConfig = {
copy: 'erp:productionWorkOrder:add',
pushDown: 'erp:productionWorkOrder:push',
add: 'erp:productionWorkOrder:add',
save: 'erp:productionWorkOrder:add',
del: 'erp:productionWorkOrder:remove',
submit: 'erp:productionWorkOrder:approval:submit',
audit: 'erp:productionWorkOrder:approval:execute:pass',
unAudit: 'erp:productionWorkOrder:approval:reverse',
upQuery: 'erp:productionWorkOrder:upQuery',
downQuery: 'erp:productionWorkOrder:downQuery',
exprot: 'erp:productionWorkOrder:export',
checkOrder: 'erp:productionWorkOrder:checkOrder',
setHit: 'erp:productionWorkOrder:template'
}
const operateData = ref([
{
value: 'upQuery',
content: '上查'
},
{
value: 'downQuery',
content: '下查'
},
{
value: 'setHit',
content: '套打'
},
{
value: 'exprot',
content: '导出'
}
])
const includesList = ref([
{
key: 'pushDown',
label: '下推'
},
{
key: 'checkOrder',
label: '选单'
},
{
key: 'return',
label: '列表'
}
])
const { id, schemeId } = route.query
const pushProductionReturnData = window.pushProductionReturnData
const rules = {
productionOrgId: [{ required: true, message: '请选择', trigger: 'blur' }],
returnTime: [{ required: true, message: '请选择', trigger: 'blur' }],
itemList: [
{ required: true, message: '请输入', trigger: 'blur' },
{
validator: (v) => {
const arr = jsonToObj(v, [])
let bool = true
let errorMsg = {}
if (arr.length == 0) {
return {
result: false,
message: '请输入'
}
}
// 如果启用序列号,需验证序列号是否录入/导入
arr.forEach((e, i) => {
if (bool) {
let isSerialStatus =
e.serialNumberManager == '0' || !e.serialNumberManager
? true
: !!e.serialCodeList && e.serialCodeList.length == e.quantity
// 启用仓位控制
let invokeState =
e.positionControl == '0' || !e.positionControl ? true : !!e.warehousePositionId
// 实际数量不能大于申请数量
let maxNumberState = e.quantity <= e.applyQuantity ? true : false
bool =
!!e.quantity &&
!!e.materialId &&
!!e.warehouseId &&
isSerialStatus &&
invokeState &&
!!e.returnType &&
maxNumberState
if (!bool) {
errorMsg = {
...e,
currKey: i,
materialStatus: !!e.materialId,
quantityStatus: !!e.quantity,
isSerialStatus: isSerialStatus,
invokeState: invokeState,
warehouseStatus: !!e.warehouseId,
returnTypeStatus: !!e.returnType,
maxNumberState: maxNumberState
}
}
}
})
return {
result: bool,
message: `${
!bool
? `请输入第${errorMsg.currKey + 1}行的明细信息${[
!errorMsg.materialStatus && ',选择关联物料',
!errorMsg.quantityStatus && ',输入实收数量',
!errorMsg.warehouseStatus && ',选择仓库',
!errorMsg.invokeState && ',选择仓位',
!errorMsg.isSerialStatus && ',序列号数量不匹配',
!errorMsg.returnTypeStatus && ',选择退回类型',
!errorMsg.maxNumberState && ',申请与实退数量不匹配'
]
.filter(Boolean)
.join('')}`
: ''
}`
}
},
message: '请输入'
}
]
}
if (id) {
formData.value.id = id
}
const getData = async () => {
isLoading.value = true
showErrorMessage.value = false
const isEdit = !!formData.value.id
if (isEdit) {
stock.getRoomList({ inventoryControl: null }) // 获取仓库列表
const res = await get(`/erp/productionWorkOrder/${formData.value.id}`)
const { isCopy } = route.query
const { state, itemList } = res.data
// 审核通过组合菜单WorkOrder
if (state == 0) {
controlType.value = 'save'
isDisabled.value = false
}
if (state == 1) {
controlType.value = 'submit'
// 0=创建,1=审核中,2=已审核,3=重新审核,4=审核拒绝
isDisabled.value = true
}
if (state == 2) {
controlType.value = 'audit'
isDisabled.value = true
}
if (state == 3) {
controlType.value = 'unAudit'
isDisabled.value = false
}
// 设置序号
itemList?.map((e, i) => {
e.tableId = i + 1
e.purchaseUnitId = e.baseUnitId
e.orderNo = e.purchaseOrderNo
e.positionControl = stock.warehouseList?.find(
(w) => w.value == e.warehouseId
)?.positionControl
e.roomList = stock.warehouseList
?.find((w) => w.value == e.warehouseId)
?.warehousePositionList?.map((p) => {
return {
...p,
label: p.positionName,
value: p.id
}
})
})
res.data.itemList = JSON.stringify(res.data.itemList || [])
res.data.files = res.data.files ? JSON.parse(res.data.files) : []
let obj = null
if (!!isCopy) {
obj = merge({ ...INIT_STATUS, isEdit }, res.data)
obj.state = ''
obj.orderNo = ''
controlType.value = 'add'
isDisabled.value = false
} else {
obj = { ...INIT_STATUS, isEdit, ...res.data }
}
formData.value = obj
}
if (pushProductionReturnData && formData.value.id == '') {
stock.getRoomList({ inventoryControl: null }) // 获取仓库列表
getPushDownData()
}
isLoading.value = false
}
const handleSubmit = async (state) => {
showErrorMessage.value = true // 显示验证提示
const result = await formValidator.value.validate()
if (result === true) {
try {
isLoading.value = true
const { isCopy } = route.query
const params = JSON.parse(JSON.stringify(formData.value))
params.operateType = state
params.itemList = JSON.parse(params.itemList)
params.files = params.files.length == 0 ? null : JSON.stringify(params.files || [])
// 复制
if (isCopy && first.value == null) {
params.id = ''
}
const func = params.id ? put : post
const res = await func('/erp/productionReturn', {
...params
})
if (res.data) {
formData.value.id = res.data
if (isCopy) {
first.value = true
}
}
formValidator.value.clearValidate()
if (state == 1) {
MessagePlugin.success('提交成功')
if (!res.data) {
getData()
}
} else {
MessagePlugin.success('保存成功')
if (!res.data) {
getData()
}
}
if (res.data) {
router.replace({
path: '/production/return/edit',
query: { id: res.data, schemeId: schemeId, _t: Date.now() }
})
nextTick(() => {
getData()
})
}
} finally {
isLoading.value = false
}
editRefresh.emit()
}
}
// 新增复制
const handleEdit = (type) => {
controlType.value = 'add'
isDisabled.value = false
window.pushProductionReturnData = null
if (type == 'copy') {
formData.value.state = ''
formData.value.orderNo = ''
first.value = null
} else {
formData.value = { ...INIT_STATUS }
}
setTimeout(() => {
router.replace({
path: '/production/productionWorkOrder/edit',
query: { id: formData.value.id, schemeId: schemeId, isCopy: !!type, _t: Date.now() }
})
}, 0)
// getData()
}
// 审核
const handleExecute = async () => {
// if (erp.approvalDataDic?.production_return) {
// MessagePlugin.warning('操作失败,已启用审批流程!')
// } else {
if (erp.approvalDataDic?.production_return) {
let next = await execTask.value.show({
id: formData.value.id,
approvalModel: 'production_return'
})
if (next != 1) {
return
}
}
await post(`erp/productionReturn/approval/execute/${formData.value.id}`)
MessagePlugin.success('审核成功')
getData()
editRefresh.emit()
// }
}
// 反审
const handleAudit = async () => {
await put(`erp/productionReturn/approval/reverse/${formData.value.id}`)
MessagePlugin.success('操作成功')
getData()
editRefresh.emit()
}
// 导出
const handlEexprot = async () => {
const params = {
userFilterSchemeId: schemeId,
idList: formData.value.id
}
const currentDay = dayjs().format('YYYY-MM-DD')
await download(
`erp/productionReturn/export`,
{
...params
},
`生产退料单-${currentDay}.xlsx`
)
}
// 上查下查
const handleUpDownQueryList = (type) => {
// 组合数据
const list = []
const itemList = JSON.parse(formData.value.itemList)
itemList.forEach((e) => list.push(e.id))
queryRef.value.show(list, type, 'productionReturn')
}
// 选单功能
const handleSelectOrderList = () => {
let urls = 'erp/productionOrder/list'
// 已存在子项
const iList = formData.value.itemList ? JSON.parse(formData.value.itemList) : []
const sourceType = '11'
const list = iList.filter((e) => e.sourceOrderType == sourceType)
const disList = JSON.parse(JSON.stringify(list))
// orderSelectDrawerRef.value.show(urls, list, disList, null, sourceType)
const filterObj = {}
selectListDialogRef.value.show(urls, list, disList, 11, sourceType, filterObj)
}
// 销售订单选择
const orderSelectBack = async (res, sourceType) => {
console.log('res - > ', res);
if (!res || res.length === 0) return;
const materialIds = [...new Set(res.map(item => item.materialId))];
if (materialIds.length > 1) {
MessagePlugin.warning('只允许单个物料下推到生产工单');
return;
}
const firstSelectedItem = res[0];
formData.value.materialCode = firstSelectedItem.materialCode || ''; // 物料编码
formData.value.materialName = firstSelectedItem.materialName || ''; // 物料名称
formData.value.specification = firstSelectedItem.specification || ''; // 规格属性
formData.value.quantity = firstSelectedItem.quantity || ''; // 生产数量
formData.value.sourceOrderNo = firstSelectedItem.sourceOrderNo || ""; // 源头单据
const ids = res.map(e => e.itemId);
// 组合选中数据的itemId
// res.forEach((e) => ids.push(e.itemId))
// 根据选中订单的itemId查询生产单
const result = await get(
`erp/productionOrder/list?type=15&itemIdList=${ids.join(',')}`
)
const params = formData.value.itemList ? JSON.parse(formData.value.itemList) : []
const list = result.data?.map((e) => ({
...e,
tableId: Math.random() * 100000000,
sourceOrderId: e.id,
sourceOrderItemId: e.itemId,
sourceOrderNo: e.orderNo,
sourceOrderType: sourceType,
productionOrderMaterialCode: e.productionOrderMaterialCode || e.itemProductionOrderMaterialCode,
applyQuantity: '',
quantity: '',
remark: '',
id: ''
})) || [];
const combined = params.length === 1 && !params[0].materialId
? [...params.slice(0, 0), ...list]
: params.concat(list);
formData.value.itemList = JSON.stringify(combined);
}
// 获取下推的数据
const getPushDownData = async () => {
// 投放过来的参数
const pushDownData = JSON.parse(pushProductionReturnData)
const urls =
pushDownData.sourceOrderType == '11'
? `erp/productionOrder/push`
: pushDownData.sourceOrderType == '13'
? `erp/productionReceived/push`
: `erp/productionMaterial/push`
// 请求下推的数据
const res = await post(urls, {
...pushDownData
})
// 检查是否包含多个不同物料
if (res.data && res.data.length > 0) {
const allItems = res.data.flatMap(item => item.itemList || []);
const materialIds = [...new Set(allItems.map(item => item.materialId))];
if (materialIds.length > 1) {
MessagePlugin.warning('只允许单个物料下推到生产工单');
return;
}
}
// 提取父级物料信息(从第一条明细获取)
const firstItem = res.data?.[0]?.itemList?.[0] || {};
formData.value.materialCode = firstItem.materialCode || ''; // 物料编码
formData.value.materialName = firstItem.materialName || ''; // 物料名称
formData.value.specification = firstItem.specification || ''; // 规格属性
formData.value.quantity = firstItem.quantity || ''; // 生产数量
formData.value.sourceOrderNo = firstItem.sourceOrderNo || ""; // 源头单据
const list = []
res.data?.[0]?.itemList?.forEach((f) => {
list.push(f.itemId)
})
const ids = list.join(',')
let itemList = []
if (list.length > 0) {
const res = await get('erp/productionOrder/list', {
itemIdList: ids,
// type: 2 //类型 1领料单 2退料单 3补料单
type: 15 //类型 13领料单 15退料单 14补料单
})
res.data.map((e) => {
e.tableId = Math.random() * 100000000
e.productionOrderNo = e.orderNo // 生产单号??
e.productionOrderMaterialCode =
e.productionOrderMaterialCode || e.itemProductionOrderMaterialCode // 产品编码
// 来源
e.sourceOrderId = e.id
e.sourceOrderItemId = e.itemId
e.sourceOrderNo = e.orderNo
e.sourceOrderType = pushDownData.sourceOrderType
e.remark = '' // 清空备注
e.id = '' //下推、选单的数据去掉id
});
itemList = res.data || []
formData.value.itemList = JSON.stringify(itemList)
}
}
// 返回
const handleReturn = () => {
const path = route.path.replace('/edit', '')
router.push({
path: path,
query: { _t: Date.now() }
})
}
// 套打
const handleSetHit = async () => {
window.open(`api/erp/productionReturn/template/${formData.value.id}`, '_blank')
}
</script>
<style lang="less" scoped>
.edit-page {
.wrap-style {
margin-bottom: var(--td-comp-margin-xxl) !important;
}
.hideStar {
:deep(.t-form__label) {
label {
&::before {
display: none !important;
}
}
}
}
:deep(.t-input.t-is-disabled .t-input__inner),
:deep(.t-textarea__inner.t-is-disabled),
:deep(.t-checkbox.t-is-disabled .t-checkbox__label) {
color: #000;
}
.hide_upload_btn {
.t-upload__trigger {
display: none;
}
}
:deep(.t-upload__single-display-text){
margin-top: 0 !important;
}
}
</style>
<template>
<div class="subitem-info w-100%">
<div class="py-2px flex justify-between">
<div>
<t-link hover="color" theme="primary" class="mr-16px" @click="addItem">新增行</t-link>
<d-pop-btn
:tips="`确认删除选中的${selectedRowKeys.length}行数据吗?`"
class="mr-16px"
placement="left"
:disabled="selectedRowKeys.length == 0"
@click="removeItem()"
>删除行</d-pop-btn
>
<t-link hover="color" theme="primary" class="mr-16px" @click="allEdit">批量填充</t-link>
<t-link hover="color" theme="primary" class="mr-16px" @click="importProcessProcedures">
导入工艺工序
</t-link>
<t-link :disabled="false" hover="color" class="mr-16px" theme="primary" @click="allCopy"
>批量复制编号</t-link>
<t-link
hover="color"
theme="primary"
:disabled="false"
@click="() => infoTableRef.openDColumn()"
>明细方案</t-link
>
</div>
</div>
<!-- 子项明细 -->
<div class="subitem-info-table">
<d-table
ref="infoTableRef"
:isColumnDialog="true"
code="table/#/production/return/edit"
class="right-table"
row-key="tableId"
:columns="columns"
:data="inputList"
:rowSelection=" { trigger: 'row', multiple: true }"
v-model:selectedRowKeys="selectedRowKeys"
@select-change="(e) => (selectedRowKeys = e)"
:hasPagination="false"
:controllerVisible="false"
:hasColumnControl="false"
cellEmptyContent=""
>
<!-- 新增:工序编号的自定义模板 -->
<template #technologyId="{ row }">
<!-- 禁用或勾选状态下直接显示编号 -->
<div
v-if="disabled || !!row.isChecked"
class="procedure-no-display">
{{ row.processCode }}
</div>
<!-- 编辑状态下显示选择组件 -->
<div v-else class="procedure-no-edit">
<div class="w-80%">
<DSelectCopy
placeholder="请选择工序"
v-model="row.technologyId"
@focus="setInputValue"
:getData="getProcessListData"
:info="row.technologyId ? row : null"
:keys="{ value: 'technologyId', label: 'procedureNo' }"
@change="(e, f) => handleProcessChange(e, f, row.tableId)"
:disabled="disabled || !!row.isChecked"
:popup-props="{
overlayInnerStyle: { width: '450px' }
}"
:format="
(e) => {
e.content = (h) => {
return `${e.procedureNo}${e.procedureName ? ` - (${e.procedureName})` : ''}`
}
return `${e.procedureNo}`
}
"
/>
</div>
<div class="w-20%">
<CreditcardAddIcon
@click="openProcessDialog(row)"
class="cursor-pointer color-blue"
title="选择工艺工序"
/>
</div>
</div>
</template>
<template #productionDept="{ row }">
<t-select
v-model="row.productionDept"
:options="workShopData"
class="w-100%"
placeholder="请选择"
:disabled="disabled"
></t-select>
</template>
<template #personInCharge="{ row }">
<t-select
v-model="row.personInCharge"
:options="workShopData"
class="w-100%"
placeholder="请选择"
:disabled="disabled"
></t-select>
</template>
<!-- 开始时间 -->
<template #planStartTime="{ row }">
<t-date-picker
:disabled="disabled"
clearable
valueType="time-stamp"
class="w-100%"
v-model="row.planStartTime"
:popupProps="{ overlayClassName: 'project-edit-date-picker' }"
@change="
() => {
updateItem(row.tableId, 'planEndTime', '')
}
"
/>
</template>
<!-- 结束时间 -->
<template #planEndTime="{ row }">
<t-date-picker
:disabled="disabled"
clearable
valueType="time-stamp"
class="w-100%"
v-model="row.planEndTime"
:popupProps="{ overlayClassName: 'project-edit-date-picker' }"
:disableDate="{ before: row.planStartTime }"
/>
</template>
</d-table>
</div>
<scanOrImportDialog ref="scanRef" @dialog-close="handleCloseDialog" />
<!-- 业务操作 -->
<businessOperation ref="businessOperationRef" @backStockData="backSelectStockData" />
<!-- 批量设置数据 -->
<!-- 批量设置数据 -->
<FormEditData ref="formEditData" @success="setItemList">
<!-- 计划加工数量 -->
<template #applyQuantity>
<t-input-number
class="w-100%"
theme="normal"
v-model="batchForm.applyQuantity"
placeholder="请输入"
:decimal-places="0"
/>
</template>
<!-- 计划开始时间 -->
<template #planStartTime>
<t-date-picker
v-model="batchForm.planStartTime"
type="datetime"
placeholder="请选择"
format="YYYY-MM-DD HH:mm"
/>
</template>
<!-- 计划结束时间 -->
<template #planEndTime>
<t-date-picker
v-model="batchForm.planEndTime"
type="datetime"
placeholder="请选择"
format="YYYY-MM-DD HH:mm"
:disableDate="{ before: batchForm.planStartTime }"
/>
</template>
<!-- 生产部门 -->
<template #productionDept>
<t-select
placeholder="请选择"
v-model="batchForm.productionDept"
:options="workShopData"
filterable
/>
</template>
<!-- 负责人 -->
<template #personInCharge>
<t-select
placeholder="请选择"
v-model="batchForm.personInCharge"
:options="workShopData"
filterable
/>
</template>
<!-- 设备 -->
<template #equipment>
<t-input-number
class="w-100%"
theme="normal"
v-model="batchForm.equipment"
placeholder="请输入"
:decimal-places="0"
/>
</template>
<!-- 备注 -->
<template #remark>
<t-input
class="w-100%"
theme="normal"
v-model="batchForm.remark"
placeholder="请输入"
maxlength="100"
/>
</template>
</FormEditData>
</div>
<t-dialog
v-model:visible="processDialogVisible"
:header="processDialogTitle"
width="80%"
top="5%"
:footer="null"
destroy-on-close
>
</t-dialog>
</template>
<script setup lang="jsx">
import { watch, ref, computed } from 'vue'
import { useDict } from '@/store/dict'
import { useErp } from '@/store/erp'
import { useStock } from '@/store/stock'
import { MessagePlugin } from 'tdesign-vue-next'
import { get } from '@common'
import scanOrImportDialog from '@/components/scanOrImportDialog.vue'
import { CreditcardAddIcon } from 'tdesign-icons-vue-next'
import businessOperation from '@/components/businessOperation.vue'
import { useScroll } from '@/utils/scroll.hook'
import { onCopy } from '@/utils'
useScroll(['.right-table .t-table__content', '.edit-page'])
// const systemObj = useSystem()
const infoTableRef = ref(null)
const formEditData = ref(null)
const batchForm = ref({
applyQuantity: '',
planStartTime: '',
planEndTime: '',
productionDept: '',
personInCharge: '',
equipment: '',
remark: ''
})
const initInfo = {
id: '',
tableId: 1,
orderNum: '',
technologyId: '',
processCode: '',
processName: '',
applyQuantity: '',
workInstruction: '',
planStartTime: '',
planEndTime: '',
productionDept: '',
equipment: '',
personInCharge: '',
technologyFileFlag:'',
remark: '',
isDispatched: '0'
}
const props = defineProps({
modelValue: {
type: String,
default: ''
},
parentId: {
type: [Number, String]
},
state: {
type: [Number, String],
default: ''
},
disabled: {
type: Boolean,
default: false
}
})
const dict = useDict()
const erp = useErp()
const stock = useStock()
const selectedRowKeys = ref([]) //当前高亮行
const scanRef = ref(null)
const workShopData = ref(dict.production_workshop || [])
const clickRowIndex = ref('')
const parentIds = ref(''); // 初始化为空字符串
const processDialogVisible = ref(false)
const processDialogTitle = ref('选择工艺工序')
const openProcessDialog = (row) => {
clickRowIndex.value = row.tableId // 记录当前行ID
processDialogVisible.value = true
}
const importProcessProcedures = () => {
processDialogVisible.value = true
}
const allCopy = () => {
const keys = selectedRowKeys.value
let arr = []
inputList.value.forEach((e) => {
if (e.processCode && (keys.includes(e.tableId) || !keys?.length)) {
arr.push(e.processCode)
}
})
if (!arr.length) {
MessagePlugin.warning('复制数据不能为空')
return
}
let str = arr.join('\n')
onCopy(str)
}
// 新增更新行数据的方法
const updateItem = (tableId, key, value) => {
const row = inputList.value.find(item => item.tableId === tableId);
if (row) row[key] = value;
};
const businessOperationRef = ref(null)
const columns = computed(() => {
return [
{
colKey: 'row-select',
type: 'multiple',
fixed: 'left',
isDisabled: true,
width: 50
},
{
title: '序',
colKey: 'orderNum',
width: 50,
fixed: 'left',
isDisabled: true,
cell: (_, { row, rowIndex }) => {
return `序${rowIndex + 1}`
}
},
{
title: () => {
return <div class="title-required">工序编号</div>
},
colKey: 'technologyId',
width: 170,
ellipsis: true,
// cell: (_, { row }) => row.processCode || '1', // 强制显示工序编号(processCode)
isDisabled: true // 禁止列隐藏
},
{
title: '工序名称',
colKey: 'procedureName',
width: 150,
ellipsis: true
},
{
title: '作业指导书',
colKey: 'technologyFileFlag',
width: 150,
ellipsis: true,
cell: (_, { row }) => row.technologyFileFlag || '无'
},
{
title: '计划加工数量',
colKey: 'applyQuantity',
width: 100,
cell: (h, { row }) => {
return (
<t-input-number
class="w-100%"
theme="normal"
modelValue={row.applyQuantity}
onUpdate:modelValue={(val) => (row.applyQuantity = val)}
placeholder="请输入"
decimal-places={0}
/>
)
}
},
{
title: () => {
return <div class="title-required">计划开始时间</div>
},
colKey: 'planStartTime',
isDisabled: true,
width: 200
},
{
title: () => {
return <div class="title-required">计划结束时间</div>
},
colKey: 'planEndTime',
isDisabled: true,
width: 200
},
{
title: '生产部门',
colKey: 'productionDept',
width: 140
},
{
title: '负责人',
colKey: 'personInCharge',
width: 140
},
{
title: '设备',
colKey: 'equipment',
width: 120,
cell: (h, { row }) => {
return (
<t-input
class="w-100%"
theme="normal"
v-model={row.equipment}
placeholder="请输入"
maxlength="100"
/>
)
}
},
{
title: '备注',
colKey: 'remark',
width: 120,
cell: (h, { row }) => {
return (
<t-input
class="w-100%"
theme="normal"
v-model={row.remark}
placeholder="请输入"
maxlength="100"
/>
)
}
},
{
title: '是否派工',
colKey: 'isDispatched',
width: 150,
ellipsis: true,
cell: (_, { row }) => {
const option = isDispatchedOptions.value.find((item) => item.value === row.isDispatched)
return option ? option.label : '未派工' // 默认显示未派工
}
},
{
title: '源头单据',
colKey: 'sourceDocument',
width: 150,
ellipsis: true
}
]
})
const emit = defineEmits(['update:modelValue'])
const inputList = ref([{ ...initInfo }])
// 生成唯一tableId
const generateTableId = () => {
return Date.now() + Math.floor(Math.random() * 1000); // 时间戳+随机数,降低重复概率
};
const addItem = () => {
const obj = {
...initInfo,
tableId: Math.random() * 100000000
}
inputList.value.push(obj)
}
const removeItem = () => {
const keys = selectedRowKeys.value
if (keys && keys.length) {
keys.forEach((k) => {
const list = JSON.parse(JSON.stringify(inputList.value || []))
const index = list.findIndex((e) => e.tableId == k)
list.splice(index, 1)
inputList.value = list
})
selectedRowKeys.value = []
} else {
MessagePlugin.info('请选择要删除的行')
}
}
const allEdit = () => {
// 重置批量表单,可根据需求设置默认值(如当前时间)
batchForm.value = {
applyQuantity: '',
planStartTime: '',
planEndTime: '',
productionDept: '',
personInCharge: '',
equipment: '',
remark: ''
}
formEditData.value.show([
{
title: '计划加工数量',
colKey: 'applyQuantity',
type: 'item'
},
{
title: '计划开始时间',
colKey: 'planStartTime',
type: 'item'
},
{
title: '计划结束时间',
colKey: 'planEndTime',
type: 'item'
},
{
title: '生产部门',
colKey: 'productionDept',
type: 'item'
},
{
title: '负责人',
colKey: 'personInCharge',
type: 'item'
},
{
title: '设备',
colKey: 'equipment',
type: 'item'
},
{
title: '备注',
colKey: 'remark',
type: 'item'
}
])
}
// 新增:工序列表数据查询方法(类似物料列表)
const getProcessListData = async (params) => {
// 调用接口查询工序列表(根据实际接口调整)
const res = await get(`erp/developTechnology/list`, {
searchContent: params, // 支持通过编号或名称搜索
state: 2 // 假设1为有效状态
})
// 映射工序ID
// res.data?.map((e) => {
// // e.technologyId = e.technologyId // ID映射(绑定v-model)
// e.technologyNo = e.technologyNo // 确保编号字段正确(根据接口返回调整)
// e.technologyName = e.technologyName // 名称字段映射
// })
console.log('接口返回最后一项工序数据:', res.data?.[res.data.length - 1]);
return res
}
const handleProcessChange = async (value, item, key) => {
const { procedureNo , procedureName ,technologyFileFlag} = item?.option || {}
console.log(item?.option, key)
// 更新当前行的工序信息
inputList.value.forEach((row) => {
if (row.tableId === key) {
row.technologyId = value // 绑定ID
row.procedureNo = procedureNo // 更新编号
row.procedureName = procedureName // 更新名称
row.technologyFileFlag = technologyFileFlag ;//更新作业指导书
}
})
// 自动新增行(如果最后一行已填写工序)
const lastRow = inputList.value[inputList.value.length - 1]
if (lastRow && lastRow.technologyId) {
addItem()
}
}
// 批量设置
const setItemList = () => {
const keys = selectedRowKeys.value
const rowList = JSON.parse(JSON.stringify(inputList.value))
let formData = batchForm.value
rowList.forEach((row) => {
if (keys.length === 0 || keys.includes(row.tableId)) {
// 计划加工数量
if (formData.applyQuantity !== '') {
row.applyQuantity = formData.applyQuantity
}
// 计划开始时间
if (formData.planStartTime) {
row.planStartTime = formData.planStartTime
}
// 计划结束时间(需与开始时间联动,若开始时间更新,结束时间可清空或同步)
if (formData.planEndTime) {
row.planEndTime = formData.planEndTime
}
// 生产部门
if (formData.productionDept) {
row.productionDept = formData.productionDept
}
// 负责人
if (formData.personInCharge) {
row.personInCharge = formData.personInCharge
}
// 设备
if (formData.equipment !== '') {
row.equipment = formData.equipment
}
// 备注
if (formData.remark) {
row.remark = formData.remark
}
}
})
// 更新表格数据
inputList.value = rowList
// 提示用户填充成功
MessagePlugin.success('批量填充成功')
}
// 定义是否派工的选项(若已有字典可直接使用字典数据)
const isDispatchedOptions = ref([
{ label: '未派工', value: '0' },
{ label: '已派工', value: '1' }
])
watch(
() => props.modelValue,
(newValue, oldValue) => {
if (newValue !== oldValue) {
if (!newValue || newValue.length == 0) {
inputList.value = [{ ...initInfo }]
// inputList.value = []
} else {
inputList.value = JSON.parse(newValue)
}
}
},
{ immediate: true, deep: true }
)
watch(
() => props.parentId,
(n, o) => {
if (n != o) {
parentIds.value = n + ''
}
},
{ immediate: true, deep: true }
)
watch(
() => inputList.value,
(v) => {
emit('update:modelValue', JSON.stringify(v))
},
{
immediate: true,
deep: true
}
)
// erp.getBaseUnitList()
stock.getRoomList({ inventoryControl: null })
// getDictList()
</script>
<style lang="less" scoped>
.subitem-info-table {
.t-table__cell {
text-align: left; // 或center,与物料编码单元格对齐方式一致
}
}
.procedure-no-display {
width: calc(100% - 32px); /* 给图标留空间 */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.procedure-no-edit {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
.procedure-icon {
width: 24px;
height: 24px;
// margin-left: 8px;
// display: flex;
// align-items: center;
// justify-content: center;
cursor: pointer;
/* 模拟图标样式,根据实际图标调整 */
color: #409eff;
font-size: 16px;
}
// 禁用状态下的文本样式
:deep(.t-table__cell) div:has(+ div) {
// 匹配禁用状态的显示容器
color: #999; // 与物料编码禁用状态颜色一致
background: #f5f5f5; // 可选:添加背景色区分
}
</style>
分析上述三段代码,我需要实现点击导入工艺工序,弹出工艺工序的弹窗,工艺工序的页面为@/views/develop/technology/list.vue,应该如何修改代码