heli-mes/mes-ui/mes-ui-admin-vue3/src/views/heli/storage/StorageOutAudit.vue

1232 lines
44 KiB
Vue
Raw Normal View History

2025-11-13 09:22:25 +08:00
<template>
<!-- 出库 -->
<el-card class="hl-card" style="position: relative">
<template #header>
<span v-text="dialogTitle"></span>
</template>
<div class="abstatus">
<img src="/src/assets/imgs/status/status2.png" v-if="formData.status == 2" alt="" />
<img src="/src/assets/imgs/status/statuszf.png" v-else-if="formData.status == 3" alt="" />
<img src="/src/assets/imgs/status/status16.png" v-else-if="formData.status == 4" alt="" />
<span v-else></span>
</div>
<el-form
ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading"
:disabled="isShowBtnOther">
<!-- 基础信息 -->
<el-card class="hl-card-info">
<template #header>
<div class="hl-card-info-icona"></div><span class="hl-card-info-text">基础信息</span>
</template>
<el-row>
<el-col :span="8">
<el-row>
<el-col :span="24">
<el-form-item prop="name" label="出库单号">
<el-input v-model="formData.stockNo" disabled placeholder="系统自动生成" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item prop="stockInType" label="出库类型">
<el-select
v-model="formData.stockInType" clearable style="width: 100%" @change="handleStockType"
:disabled="ctrView || ctrSave">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.HELI_STORAGE_OUT_TYPE)" :key="dict.value"
:label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item prop="projectSubName" label="子项目名称">
<el-input v-model="formData.projectSubName" :disabled="ctrView || ctrSave" readonly>
<template #append><el-button @click="openProjectForm(scope)">
<Icon icon="ep:search" class="mr-5px" />
</el-button></template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="领料人" prop="materialReceiver">
<UserSelect v-model="formData.materialReceiver" placeholder="请选择领料人" @update:newValue="handleSelectedUser" class="!w-700px" :disabled="ctrView || ctrSave"/>
</el-form-item>
</el-col>
</el-row>
</el-col>
<el-col :span="8">
<el-row>
<el-col :span="24">
<el-form-item prop="industry" label="单据状态">
<el-select v-model="formData.status" placeholder="下拉选择" clearable class="!w-700px" disabled>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.HELI_STORAGE_STATUS)" :key="dict.value"
:label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item prop="headerNo" label="上游单号">
<el-input
v-model="formData.headerNo" class="!w-700px"
:disabled="ctrView || ctrSave || enableHeadNo" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item prop="pickmode" label="领料模式" >
<el-select
v-model="formData.pickmode" placeholder="下拉选择" clearable class="!w-400px" @change="changebom"
:disabled="ctrView || ctrSave">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.PICKMODE)" :key="dict.value"
:label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-col>
<el-col :span="8">
<el-row>
<el-col :span="24">
<el-form-item label="单据日期" prop="createTime">
<el-date-picker
v-model="formData.createTime" value-format="x" placeholder="单据日期" disabled
class="!w-400px" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item prop="whId" label="出库仓库" required>
<el-select
v-model="formData.whId" placeholder="下拉选择" clearable class="!w-400px" @change="handleWh"
:disabled="ctrView || ctrSave">
<el-option v-for="dict in whList" :key="dict.id" :label="dict.whName" :value="dict.id" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item prop="pickcar" label="领料车间" >
<el-select
v-model="formData.pickcar" placeholder="下拉选择" clearable class="!w-400px"
:disabled="ctrView || ctrSave">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.PICKCAR)" :key="dict.value"
:label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="备注" prop="description">
<el-input
type="textarea" v-model="formData.description" show-word-limit maxlength="200" class="!w-2080px"
:disabled="ctrView || ctrSave" />
</el-form-item>
</el-col>
</el-row>
</el-card>
<!-- 物料信息 -->
<el-card class="hl-card-info">
<template #header>
<div class="hl-card-info-icona"></div><span class="hl-card-info-text">物料信息</span>
</template>
<el-row>
<el-col>
<el-card class="hl-incard">
<el-col>
<el-button
class="hl-addbutton" type="primary" size="large" :disabled="ctrView || ctrSave"
@click="openMatForm">新增</el-button>
</el-col>
<el-form
ref="matSubFormRef" :model="formData.matItemDOList" :rules="subFormRules"
v-loading="subFormLoading" label-width="0">
<el-table :data="formData.matItemDOList" class="hl-table">
<el-table-column type="index" label="序号" min-width="80" align="center" fixed />
<el-table-column prop="matCode" min-width="180" align="center">
<template #header> <span class="hl-table_header">*</span> 物料编码</template>
<template #default="scope">
<el-form-item :prop="`${scope.$index}.matCode`" :rules="subFormRules.matCode" class="mb-0px!">
<!-- <MaterialSelect v-model="scope.row.matId"
@update:newValue="handleSelectedMaterial(scope.$index, $event)"
v-bind:disabled="ctrView || ctrSave" /> -->
<el-input
class="!w-265px" placeholder="物料编码" :disabled="true || ctrView || ctrSave"
v-model="scope.row.matCode" readonly>
<!-- <template #append><el-button @click="openMatForm" disabled>
<Icon icon="ep:search" class="mr-5px" />
</el-button></template> -->
</el-input>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="matName" label="物料名称" min-width="180" align="center" />
<el-table-column prop="matType" label="物料类型" min-width="120" align="center">
<!-- <template #default="scope">
<dict-tag :type="DICT_TYPE.HELI_MATERIAL_TYPE" :value="scope.row.matType"
v-if="scope.row.matType ? true : false" />
</template> -->
</el-table-column>
<el-table-column prop="matSpec" label="规格/型号" min-width="120" align="center" />
<el-table-column prop="matUnit" label="系统单位" min-width="120" align="center">
<!-- <template #default="scope">
<dict-tag :type="DICT_TYPE.HELI_MATERIAL_UNIT" :value="scope.row.matUnit"
v-if="scope.row.matUnit ? true : false" />
</template> -->
</el-table-column>
<el-table-column prop="rgId" min-width="120" align="center">
<template #header> <span class="hl-table_header">*</span>出库库区 </template>
<template #default="scope">
<el-form-item :prop="`${scope.$index}.rgId`" :rules="subFormRules.rgId" class="mb-0px!">
<el-select v-model="scope.row.rgId" placeholder="" style="width: 100%" :disabled="true">
<el-option v-for="dict in rgList" :key="dict.id" :label="dict.rg_name" :value="dict.id" />
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="pnId" min-width="160" align="center">
<template #header> <span class="hl-table_header">*</span>出库库位 </template>
<template #default="scope">
<el-form-item :prop="`${scope.$index}.pnId`" :rules="subFormRules.pnId" class="mb-0px!">
<el-select
v-model="scope.row.pnId" placeholder="" style="width: 100%"
:disabled="ctrView || ctrSave" @change="handlePn(scope)">
<el-option
v-for="dict in scope.row.pnlist" :key="dict.id" :label="dict.pn_name"
:value="dict.id" />
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="matRest" label="库存数量" min-width="120" align="center" />
<el-table-column prop="storageOkQty" min-width="120" align="center">
<template #header> <span class="hl-table_header">*</span>出库数量</template>
<template #default="scope">
<el-form-item
:prop="`${scope.$index}.storageOkQty`" :rules="subFormRules.storageOkQty"
class="mb-0px!">
<el-input v-model="scope.row.storageOkQty" :disabled="ctrView || ctrSave" />
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="price" label="库存单价" min-width="120" align="center" />
<el-table-column prop="lotNo" min-width="120" label="批次号" align="center" v-if="false" />
<el-table-column prop="projectSubName" label="子项目名称" align="center" min-width="180">
<template #default="scope">
<el-input v-model="scope.row.projectSubName" disabled>
<template #append></template>
</el-input>
</template>
</el-table-column>
<el-table-column prop="description" min-width="180" label="备注" align="center">
<template #default="scope">
<el-input v-model="scope.row.description" :disabled="ctrView || ctrSave" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="100">
<template #default="scope">
<!-- <el-button v-if="!scope.row.editable" type="primary" size="small" link
@click="handleEdit(scope.$index)">
编辑
</el-button>
<el-button link v-else type="success" size="small" @click="handleSave(scope.$index)">
保存
</el-button>
<el-button link type="primary" @click="handlefuke(scope.$index, scope.row)">复制</el-button> -->
<el-button
link type="danger" size="small" @click.prevent="handleDelete2(scope.$index)"
:disabled="ctrView || ctrDelete">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-form>
</el-card>
</el-col>
</el-row>
</el-card>
<!-- 附件信息 -->
<el-card class="hl-card-info">
<template #header>
<div class="hl-card-info-icona"></div><span class="hl-card-info-text">附件信息</span>
</template>
<el-row>
<el-col>
<el-card class="hl-incard">
<el-col>
<el-upload
ref="matUploadRef" :file-list="matUploadFiles" multiple :action="uploadUrl" :headers="{
Authorization: 'Bearer ' + getAccessToken(),
'tenant-id': getTenantId()
}" name="files" :show-file-list="false" :auto-upload="false" :data="matUploadData"
:on-change="matUploadChange" :on-error="handleError" :on-success="handleSuccess"
:before-upload="before" class="upload-file-uploader">
<el-button type="primary" :disabled="ctrView || ctrSave">
<Icon icon="ep:upload-filled" />上传
</el-button>
</el-upload>
</el-col>
<el-table
:data="formData.attachments" class="hl-table" v-loading.fullscreen.lock="uploading"
element-loading-text="附件上传中..." element-loading-background="rgba(122, 122, 122, 0.6)">
<el-table-column prop="name" label="文件名称" align="center">
<!-- <template #default="scope">
<a :href="scope.row.url" target="_blank" style="color: #409eff">{{ scope.row.name }} </a>
</template> -->
</el-table-column>
<el-table-column prop="createTime" align="center" label="上传日期" :formatter="dateFormatter" />
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link type="danger" size="small" :disabled="ctrView || ctrDelete"
@click="handleDeleteAttachment(scope.$index, scope.row.businessFileType)">
删除
</el-button>
<el-button
link type="primary" size="small" :disabled="ctrView || ctrDelete"
@click="downloadAttachment(scope.row.name, scope.row.url)">
下载
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
</el-col>
</el-row>
</el-card>
<!-- 系统信息 -->
<el-card class="hl-card-info">
<template #header>
<div class="hl-card-info-icona"></div><span class="hl-card-info-text">系统信息</span>
<el-button @click="() => router.go(-1)" size="large" style="margin-left: 5rem"> </el-button>
<el-button @click="handleStatus(4)" type="success" v-if="btnok " size="large">审核</el-button>
</template>
<el-row justify="center">
<el-col :span="8">
<el-form-item prop="creator" label="创建人">
{{ userList.find((user) => user.id == formData.creator)?.nickname }}
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item prop="createTime" label="创建时间">
{{ formatDate(formData.createTime, 'YYYY-MM-DD HH:mm') }}
</el-form-item>
</el-col>
</el-row>
<el-row justify="center">
<el-col :span="8">
<el-form-item prop="outbound" label="出库人">
{{ userList.find((user) => user.id == formData.outbound)?.nickname }}
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item prop="outboundTime" label="出库时间">
{{ formatDate(formData.outboundTime, 'YYYY-MM-DD HH:mm') }}
</el-form-item>
</el-col>
</el-row>
<el-row justify="center">
<el-col :span="8">
<el-form-item prop="cancel" label="作废人">
{{ userList.find((user) => user.id == formData.cancel)?.nickname }}
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item prop="cancelTime" label="作废时间">
{{ formatDate(formData.cancelTime, 'YYYY-MM-DD HH:mm') }}
</el-form-item>
</el-col>
</el-row>
</el-card>
</el-form>
<!-- <div class="hl-footer text-center">-->
<!-- -->
<!-- </div>-->
</el-card>
<el-dialog v-model="centerDialogVisible" title="提示" width="30%" center>
<span>
作废该单据后无法复原请确认是否作废
</span>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="deleteStorage()">
确认
</el-button>
<el-button @click="centerDialogVisible = false">取消</el-button>
</span>
</template>
</el-dialog>
<!-- 表单弹窗物料列表 -->
<materials ref="matOpenFormRef" @success="getList" />
<!-- 表单弹窗物料列表 -->
<projects ref="proOpenFormRef" @success="getProject" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { useRoute } from 'vue-router'
import { dateFormatter, formatDate } from '@/utils/formatTime'
import type { UploadUserFile } from 'element-plus'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import * as StorageApi from '@/api/heli/storage'
import * as StorageMatApi from '@/api/heli/storagemat'
import { getAccessToken, getTenantId } from '@/utils/auth'
import { useUserStore } from '@/store/modules/user'
import MaterialSelect from '@/views/heli/hlvuestyle/materialSelect.vue'
import * as MaterialApi from '@/api/heli/material'
import * as WarehouseApi from '@/api/heli/warehouse'
import * as RgApi from '@/api/heli/rg'
import * as PnApi from '@/api/heli/pn'
import { deleteFile, downloadFile, getFilePage } from '@/api/infra/file'
import download from '@/utils/download'
import * as UserApi from '@/api/system/user'
import materials from './materials.vue'
import projects from './subproject.vue'
import UserSelect from "@/views/heli/hlvuestyle/userSelect.vue";
const reload: any = inject('reload')
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const { query } = useRoute()
const router = useRouter()
const centerDialogVisible = ref(false)
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中1修改时的数据加载2提交的按钮禁用
const formType = ref('') // 表单的类型create - 新增update - 修改
const formData = ref({
id: undefined,
stockType: 2,
stockInType: undefined,
projectSubName:undefined,
pickmode:undefined,
pickcar:undefined,
projectNo:undefined,
stockOutType: undefined,
stockNo: undefined,
headerNo: undefined,
description: undefined,
status: 1,
whId: undefined,
creator: undefined,
createTime: undefined,
keeper: undefined,
keeperTime: undefined,
outbound: undefined,
outboundTime: undefined,
cancel: undefined,
cancelTime: undefined,
matItemDOList: [],
attachments: [],
beforeStatus:undefined,
})
const formRules = reactive({
// name: [{ required: true, message: '模具类型不能为空', trigger: 'blur' }],
status: [{ required: true, message: '启用状态不能为空', trigger: 'blur' }],
stockInType: [{ required: true, message: '出库类型不能为空', trigger: 'blur' }],
// projectSubName: [{ required: true, message: '子项目名称不能为空', trigger: 'blur' }],
// pickmode: [{ required: true, message: '领料模式不能为空', trigger: 'blur' }],
// pickcar: [{ required: true, message: '领料车间不能为空', trigger: 'blur' }],
whId: [{ required: true, message: '出库仓库不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
const matSubFormRef = ref() //子表单 Ref
const subFormLoading = ref(false) // 子表单的加载中
const subFormRules = reactive({
matId: [{ required: true, message: '物料不能为空', trigger: 'blur' }],
matCode: [{ required: true, message: '物料编码不能为空', trigger: 'blur' }],
rgId: [{ required: true, message: '库区不能为空', trigger: 'blur' }],
pnId: [{ required: true, message: '库位不能为空', trigger: 'blur' }],
storageOkQty: [{ required: true, message: '出库数量不能为空', trigger: 'blur' }]
})
const matOpenFormRef = ref()
const proOpenFormRef = ref()
const openMatForm = () => {
// if (formData.value.whId == undefined || formData.value.whId == '') {
// message.alertWarning('请选择入库仓库')
// return
// }
// formData.value.whId
if(formData.value.pickmode==1){
matOpenFormRef.value.open(formData.value.projectNo, 'bomfind')
}else{
matOpenFormRef.value.open(formData.value.whId, 'out')
}
}
const openProjectForm = (scope) => {
proOpenFormRef.value.open(scope)
}
const handleSelectedUser = (newValue: any) => {
formData.value.materialReceiver = newValue?.id
}
const getList = async (arrMat) => {
arrMat.forEach((row) => {
if (
formData.value.matItemDOList.filter(
(item) =>
item.matId == row.id &&
item.whId == row.whId &&
item.rgId == row.rgId &&
item.pnId == row.pnId
).length == 0
) {
if(row.whId1){
row.matId = row.matId
}else{
row.matId = row.id
}
row.projectNo = formData.value.projectNo
row.projectSubName =formData.value.projectSubName
row.pnlist = ref([])
row.pnlist = pnList.value.filter((pn) => pn.wh_id == row.whId && pn.rg_id == row.rgId)
if (row.pnlist.length == 0) {
row.rgId = ''
row.pnId = ''
row.matRest = 0
row.projectNo = formData.value.projectNo
row.projectSubName =formData.value.projectSubName
}
formData.value.matItemDOList.push(row)
}
})
}
const getProject = async (pro, scope) => {
formData.value.projectSubName=pro.projectSubName
formData.value.projectNo=pro.projectSubId
// formData.value.matItemDOList.forEach(
// (item) => {
// if (item.matId == scope.value.row.matId && item.whId == scope.value.row.whId && item.rgId == scope.value.row.rgId && item.pnId == scope.value.row.pnId) {
// item.projectNo = pro.projectSubId
// item.projectSubName = pro.projectSubName
// }
// }
// )
}
// 根据出库类型显示上游单号
const enableHeadNo = ref(false)
const handleStockType = async (typeid) => {
if(typeid==5){
// 当 typeid 等于 5 时,启用验证规则
formRules.projectSubName = [{ required: true, message: '子项目名称不能为空', trigger: 'blur' }]
formRules.pickmode = [{ required: true, message: '领料模式不能为空', trigger: 'blur' }]
formRules.pickcar = [{ required: true, message: '领料车间不能为空', trigger: 'blur' }]
} else {
// 当 typeid 不等于 5 时,移除验证规则
delete formRules.projectSubName
delete formRules.pickmode
delete formRules.pickcar
}
formData.value.headerNo = ''
if (typeid == 1) {
enableHeadNo.value = false
} else {
enableHeadNo.value = true
}
}
const deleteData = ref<StorageApi.StorageVO>();
const deleteStorage = async() =>{
await StorageApi.updateStorage(deleteData.value)
deleteData.value.cancel = useUserStore().getUser.id
commonResult = 'common.updateSuccess'
await StorageApi.updateStorageStatus(deleteData.value)
message.success(t('common.updateSuccess'))
query.id = formData.value.id
query.type = 'update'
if (sumbefore.value == 0) {
reload()
}
centerDialogVisible.value = false
}
const handleStatus = async (num) => {
formData.value.status = num
const data = formData.value as unknown as StorageApi.StorageVO
if (num == 2) {
// 校验表单
await formRef.value.validate()
if (formData.value.matItemDOList.length === 0) {
message.alertWarning('请添加物料信息!')
return
}
// 校验子表单
try {
await matSubFormRef.value.validate()
} catch (e) {
return
}
var repeatItem = []
formData.value.matItemDOList.forEach(item => {
if (formData.value.matItemDOList.filter((mat) => mat.matId == item.matId && mat.pnId == item.pnId).length > 1) {
var tmpCode = "[" + item.matCode + "]"
if (repeatItem.indexOf(tmpCode) < 0) {
repeatItem.push(tmpCode)
}
}
})
if (repeatItem.length > 0) {
message.alertWarning(
'物料编码' + repeatItem.join(',') + '出库库位存在多行数据,请修改,避免重复出库'
)
return
}
//获取最新库存信息
const matCurrentData = await StorageMatApi.getStorageMatList(0)
var hasRestNum = true
formData.value.matItemDOList.forEach((rest) => {
if (
matCurrentData.find(
(mat) =>
mat.matId == rest.matId &&
mat.pnId == rest.pnId &&
mat.matRest < Number(rest.storageOkQty)
) !== undefined ||
rest.storageOkQty.length == 0
) {
hasRestNum = false
}
})
if (!hasRestNum) {
message.alertWarning('物料库存不足')
return
}
// 提示用户是否保存出库信息
await message.confirm('确认提交出库信息?')
//保存表单数据
await saveFormData()
data.outbound = useUserStore().getUser.id
} else if(num ==3) {
deleteData.value = data;
centerDialogVisible.value = true;
}else{
await StorageApi.updateStorageok(data)
if(formData.value.stockOutType == 1){
const dataMats = formData.value.matItemDOList as unknown as StorageMatApi.StorageMatVO[]
await StorageMatApi.createStorageMatBatch(dataMats, formData.value.id)
}
}
if(num != 3){
await StorageApi.updateStorageStatus(data)
message.success(t('common.updateSuccess'))
query.id = formData.value.id
query.type = 'update'
if (sumbefore.value == 0) {
reload()
}
}
}
// ====================附件信息 开始=======================================
const uploadUrl = ref(import.meta.env.VITE_UPLOAD_BATCH_URL)
const matUploadRef = ref()
const matUploadFiles = ref<UploadUserFile[]>([])
const uploading = ref(false)
const matUploadData = ref({
businessType: 'STORAGE',
businessId: formData.value.id,
businessFileType: 'MATERIAL'
})
const matUploadChange = (file, files) => {
matUploadFiles.value = files
refreshAttachments(files, 'MATERIAL')
}
// 记录待上传、成功上传及失败上传的文件数量
const sumbefore = ref(0)
const successfulUploadsCount = ref(0)
const failedUploadsCount = ref(0)
const failedAttachments = ref<UploadUserFile[]>([])
const failedAttachmentsName = ref()
// 处理单个文件上传成功的情况
const handleSuccess = (response: any, file: UploadUserFile) => {
successfulUploadsCount.value++
// 更新附件信息等其他逻辑...
// console.log('上传成功数量', successfulUploadsCount.value)
}
// 处理单个文件上传失败的情况
const handleError = (error: Error, file: UploadUserFile) => {
failedUploadsCount.value++
if (failedUploadsCount.value > 0) {
// 当有上传错误时
// 将失败的附件添加到failedAttachments.value数组中
failedAttachments.value.push(file)
failedAttachmentsName.value = failedAttachments.value.map((value) => value.name)
}
// console.log('上传失败数量', failedUploadsCount.value)
}
// 文件上传前的钩子
const before = (rawFile) => {
sumbefore.value++
}
const refreshAttachments = (files, type) => {
formData.value.attachments = formData.value.attachments.filter((value) => value.id)
// 避免重复添加
const newFiles = files.filter(
(file) => !formData.value.attachments.some((att) => att.name === file.name)
)
for (let i = 0; i < newFiles.length; i++) {
let file = newFiles[i]
file.businessFileType = type
file.createTime = new Date()
formData.value.attachments.push(file)
}
// 排序
formData.value.attachments.sort((v1, v2) => v1.createTime - v2.createTime)
// 文件上传一遍 上传总数等于要上传文件时 刷新页面
const sum = successfulUploadsCount.value + failedUploadsCount.value
// console.log('上传总数', sum)
// console.log('要上传文件数量', sumbefore.value)
if (sumbefore.value !== sum && sumbefore.value !== 0 && sum !== 0) {
// console.log('要上传文件数量不等于上传总数时等待',uploading.value)
uploading.value = true
} else if (sum == sumbefore.value && sumbefore.value > 0 && sum > 0) {
// console.log('要上传文件数量等于上传总数 刷新页面并给出提示')
if (failedUploadsCount.value > 0) {
ElMessageBox.alert(
// 使用错误信息作为提示内容
`文件名为:${failedAttachmentsName.value.join(' / ')}上传失败`,
`文件格式不正确或网络问题 请您稍后再试`,
{
dangerouslyUseHTMLString: false,
confirmButtonText: '知道了',
center: true
}
)
}
reload()
uploading.value = false
}
}
// 删除附件
const handleDeleteAttachment = async (index, type) => {
const deletedAttachments = formData.value.attachments.splice(index, 1)
for (let i = 0; i < deletedAttachments.length; i++) {
const attachment = deletedAttachments[i]
if (attachment.id) {
// 清理已上传文件
await deleteFile(attachment.id)
}
// 清理待上传文件
matUploadFiles.value = matUploadFiles.value.filter((file1) => {
return file1.name != attachment.name || file1.businessFileType != type
})
}
}
// 下载文件
const downloadAttachment = async (name, url) => {
if (url) {
const baseUrl = import.meta.env.VITE_BASE_URL;
url =baseUrl+'/admin-api/'+ url.split('/admin-api/')[1]; const data = await downloadFile(url)
download.any(data, name)
}
}
// ====================附件信息 结束=======================================
var commonResult = ''
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const saveFormData = async () => {
// 提交请求
formLoading.value = true
try {
const data = formData.value as unknown as StorageApi.StorageVO
if (query.type === 'create') {
//库存信息保存
formData.value.id = await StorageApi.createStorage(data)
commonResult = 'common.createSuccess'
} else {
await StorageApi.updateStorage(data)
commonResult = 'common.updateSuccess'
}
//物料信息保存
formData.value.matItemDOList.forEach((item) => {
item.stockId = formData.value.id
item.whId = formData.value.whId
})
const dataMats = formData.value.matItemDOList as unknown as StorageMatApi.StorageMatVO[]
await StorageMatApi.createStorageMatBatch(dataMats, formData.value.id)
if (formData.value.attachments != undefined && formData.value.attachments.length > 0) {
//附件信息保存
matUploadData.value.businessId = formData.value.id
await matUploadRef.value!.submit()
}
await initStatus(formData.value.status)
message.success(t(commonResult))
} finally {
formLoading.value = false
}
}
const submitForm = async () => {
// 校验表单
await formRef.value.validate()
var repeatItem = []
formData.value.matItemDOList.forEach(item => {
if (formData.value.matItemDOList.filter((mat) => mat.matId == item.matId && mat.pnId == item.pnId).length > 1) {
var tmpCode = "[" + item.matCode + "]"
if (repeatItem.indexOf(tmpCode) < 0) {
repeatItem.push(tmpCode)
}
}
})
if (repeatItem.length > 0) {
message.alertWarning(
'物料编码' + repeatItem.join(',') + '出库库位存在多行数据,请修改,避免重复出库'
)
return
}
// if (formData.value.matItemDOList.length === 0) {
// message.alertWarning('请添加物料信息!')
// return
// }
// 校验子表单
try {
await matSubFormRef.value.validate()
} catch (e) {
return
}
//获取最新库存信息
const matCurrentData = await StorageMatApi.getStorageMatList(0)
var hasRestNum = true
formData.value.matItemDOList.forEach((rest) => {
if (
matCurrentData.find(
(mat) =>
mat.matId == rest.matId &&
mat.pnId == rest.pnId &&
mat.matRest < Number(rest.storageOkQty)
) !== undefined ||
rest.storageOkQty.length == 0
) {
hasRestNum = false
}
})
if (!hasRestNum) {
message.alertWarning('物料库存不足')
return
}
// // 提示用户是否保存出库信息
// await message.confirm('确认保存出库信息?')
//保存表单数据
await saveFormData()
// 成功后刷新
query.id = formData.value.id
query.type = 'update'
if (sumbefore.value == 0) {
reload()
}
}
const onAddItem = () => {
if (formData.value.whId) {
const newData = {
// 新数据的属性
stockId: 0,
matId: '',
matName: '',
matCode: '',
matType: '',
matSpec: '',
matUnit: '',
whId: '',
rgId: '',
pnId: '',
pnlist: ref([]),
storageOkQty: '',
lotNo: '',
description: '',
productBomItemValueDOList: [],
matList: matList.value
}
formData.value.matItemDOList.push(newData)
} else {
message.alertWarning('请选择出库仓库')
}
}
//删除新增物料信息
const handleDelete2 = (index: number) => {
formData.value.matItemDOList.splice(index, 1)
}
//仓库全数据
const whList = ref([])
//库区全数据
const rgList = ref([])
//库位全数据
const pnList = ref([])
const handleWh = async (wid) => {
formData.value.matItemDOList = []
formData.value.rgId = ''
// 获得库区列表
rgList.value = (await RgApi.getSimpList()).filter((rg) => rg.wh_id == wid)
// 获得库位列表
pnList.value = (await PnApi.getSimpList()).filter((pn) => pn.wh_id == wid)
//await getMatList()
}
// const changebom = async (pickmode) => {
// debugger
// if(pickmode==1){
// }
// }
const getMatList = async (name) => {
// 获得物料列表
let matParams = {
pageNo: 1,
pageSize: 10,
status: '1'
}
if (name.length > 0) {
matParams.name = name
}
//const matLastRemoteData = await StorageMatApi.getStorageMatList(0)
const dataMat = await MaterialApi.getMaterialPage(matParams)
matList.value = dataMat.list
// matList.value = dataMat.list.filter(
// (item) =>
// matLastRemoteData.find(
// (fish) => fish.matId === item.id && fish.whId == formData.value.whId
// ) !== undefined
// )
}
const handlePn = async (scope) => {
scope.row.matList = matList.value
// var repeatItem = formData.value.matItemDOList.filter(
// (mat) => mat.matId == scope.row.matId && mat.pnId == scope.row.pnId
// )
// if (repeatItem.length > 1) {
// message.alertWarning(
// '物料编码[' + repeatItem[0].matCode + ']出库库位存在多行数据,请修改,避免重复出库'
// )
// return
// }
if (
matLastData.value.find(
(item) =>
item.matId === scope.row.matId &&
item.whId == formData.value.whId &&
item.pnId == scope.row.pnId
)
) {
const matVo = matLastData.value.find(
(item) =>
item.matId === scope.row.matId &&
item.whId == formData.value.whId &&
item.pnId == scope.row.pnId
)
// scope.row.matId = matVo.matId
// scope.row.matName = matVo.matName
// scope.row.matCode = matVo.matCode
// scope.row.matSpec = matVo.matSpec
// scope.row.matType = matVo.materialType
// scope.row.matUnit = matVo.matUnit
scope.row.rgId = matVo.rgId
scope.row.pnId = matVo.pnId
scope.row.matRest = matVo.matRest
// scope.row.storageOkQty = matVo.storageOkQty
// scope.row.lotNo = matVo.lotNo
// scope.row.description = matVo.description
} else {
scope.row.rgId = ''
scope.row.matRest = '0'
message.alertWarning('当前库位无库存数量可出库')
}
}
const matSelectLoading = ref(false)
const remoteMatNameSearch = async (name) => {
matSelectLoading.value = true
// 获得物料列表
await getMatList(name)
matSelectLoading.value = false
}
const handleMatName = async (scope, matid) => {
scope.row.matId = scope.row.matList.find((item) => item.id === matid)?.id
scope.row.matName = scope.row.matList.find((item) => item.id === matid)?.name
scope.row.matCode = scope.row.matList.find((item) => item.id === matid)?.code
scope.row.matSpec = scope.row.matList.find((item) => item.id === matid)?.spec
scope.row.matType = scope.row.matList.find((item) => item.id === matid)?.materialType
scope.row.matUnit = scope.row.matList.find((item) => item.id === matid)?.unit
scope.row.rgId = ''
scope.row.pnId = ''
if (matid.length == 0) {
}
scope.row.pnlist = pnList.value.filter(
(pn) =>
pn.wh_id == formData.value.whId &&
matLastData.value.filter((mat) => mat.matId == matid && mat.pnId == pn.id).length > 0
)
}
const matLastData = ref([])
// 按钮控制
const ctrView = ref(false)
const ctrSave = ref(false)
const ctrCancel = ref(true)
const ctrDelete = ref(false)
const btnSave = ref(true)
const btnCancel = ref(false)
const btnok = ref(true)
// 根据页面动作和数据状态控制按钮输入框信息
const initStatus = async (status) => {
switch (status) {
case 1:
ctrView.value = false
ctrSave.value = false
ctrCancel.value = true
ctrDelete.value = false
btnSave.value = true
btnCancel.value = false
break
case 2:
ctrView.value = false
ctrSave.value = true
ctrCancel.value = false
ctrDelete.value = true
btnSave.value = false
btnCancel.value = true
break
case 3:
ctrView.value = true
ctrSave.value = true
ctrCancel.value = true
ctrDelete.value = true
btnSave.value = false
btnCancel.value = false
btnok.value=false
break
case 4:
ctrView.value = true
ctrSave.value = false
ctrCancel.value = true
ctrDelete.value = false
btnSave.value = false
btnCancel.value = false
btnok.value=false
break
default:
break
}
// 查看页面时可操作控件禁用
if (query.type === 'review') {
ctrView.value = true
ctrSave.value = true
ctrCancel.value = true
ctrDelete.value = true
btnSave.value = false
btnok.value=false
// if(formData.value.status == 4){
// btnCancel.value = true
// }else{
// btnCancel.value = false
// }
}
}
const matList = ref<MaterialApi.MaterialVO[]>([]) // 物料列表
const matEditList = ref<MaterialApi.MaterialVO[]>([]) // 物料列表
const userList = ref<UserApi.UserVO[]>([]) // 用户列表
const matSimpList = ref([]) // 物料基本信息列表
const matSimpVirtualList = ref([]) // 物料基本信息列表
/** 初始化 **/
onMounted(async () => {
// 页面标题展示
dialogTitle.value = query.type === 'review' ? '查看' : t('action.' + query.type)
//- 获取仓库全数据
whList.value = await WarehouseApi.getWarehouseSimpList()
formData.value.whId = Math.min.apply(Math, whList.value.map(function(i) {return i.id}));
//获取状态为启用的物料信息
await getMatList('')
// // 获取当前最新库存信息
// matLastData.value = await StorageMatApi.getStorageMatList(0)
// 编辑时获取入库单据信息,包括基础信息、物料信息、附件信息
if (query.id) {
// 获取原始物料信息
matSimpList.value = await MaterialApi.getSimpList()
matSimpVirtualList.value = await MaterialApi.getSimpVirtualList()
matEditList.value = matSimpList.value //matSimpList.value.filter( mat => matLastData.value.filter( row => row.matId == mat.id).length>0)
// 获取库存信息
formData.value = await StorageApi.getStorage(query.id)
if (formData.value.vmatName) {
matEditList.value = matSimpVirtualList.value
}
// 页面控件可视初始化
await initStatus(formData.value.status)
// 获得库区列表
const dataRgList = await RgApi.getSimpList()
rgList.value = dataRgList.filter((rg) => rg.wh_id == formData.value.whId)
// 获得库区列表
const dataPnList = await PnApi.getSimpList()
pnList.value = dataPnList.filter((pn) => pn.wh_id == formData.value.whId)
// 获取库存物料列表信息
const queryParamsMat = reactive({
pageNo: 1,
pageSize: 99,
stockId: query.id
})
const dataMats = await StorageMatApi.getStorageMatPage(queryParamsMat)
formData.value.matItemDOList = dataMats
var matTypes = getIntDictOptions(DICT_TYPE.HELI_MATERIAL_TYPE)
var matUnits = getIntDictOptions(DICT_TYPE.HELI_MATERIAL_UNIT)
// 填充物料原始信息
formData.value.matItemDOList.forEach((item) => {
item.matId = matEditList.value.find((record) => record.id === item.matId)?.id
item.matCode = matEditList.value.find((record) => record.id === item.matId)?.code
item.matName = matEditList.value.find((record) => record.id === item.matId)?.name
item.matSpec = matEditList.value.find((record) => record.id === item.matId)?.spec
item.matType = matTypes.find( op => op.value == matEditList.value.find((record) => record.id === item.matId)?.material_type)?.label
item.matUnit = matUnits.find( op => op.value == matEditList.value.find((record) => record.id === item.matId)?.unit)?.label//matSimpList.value.find((record) => record.id === item.matId)?.unit
// item.matRest = matLastData.value.find(
// (row) => row.matId == item.matId && row.pnId == item.pnId
// )?.matRest
// console.log('ss'+item.matRest);
// item.matRest = item.matRest == undefined || item.matRest.length == 0 ? 0 : item.matRest
item.pnlist = pnList.value.filter((pn) => pn.wh_id === item.whId)
item.matList = matEditList.value.filter((record) => record.id === item.matId)
})
// matList.value = matSimpList.value.filter( mat => matLastData.value.filter( row => row.matId == mat.id).length>0 || formData.value.matItemDOList.filter(fan => fan.matId == mat.id).length>0)
// if(matList.value.length == 0){
// matList.value = matSimpVirtualList.value.filter( mat => matLastData.value.filter( row => row.matId == mat.id).length>0 || formData.value.matItemDOList.filter(fan => fan.matId == mat.id).length>0)
// }
// 附件信息
let attParams = {
pageNo: 1,
pageSize: 99,
businessId: query.id,
businessType: 'STORAGE'
}
formData.value.attachments = (await getFilePage(attParams)).list
}
//用户信息,用于底部数据展示
userList.value = await UserApi.getSimpleUserList()
formData.value.beforeStatus = formData.value.status;
})
//接收物料传递的数据
const handleSelectedMaterial = (currentIndex: number, newValue: any) => {
// console.log(currentIndex,'接收物料对应的数据:', newValue)
formData.value.matItemDOList[currentIndex].matId = newValue?.id
formData.value.matItemDOList[currentIndex].matName = newValue?.name
formData.value.matItemDOList[currentIndex].matCode = newValue?.code
formData.value.matItemDOList[currentIndex].matSpec = newValue?.spec
formData.value.matItemDOList[currentIndex].matType = newValue?.materialType
formData.value.matItemDOList[currentIndex].matUnit = newValue?.unit
formData.value.matItemDOList[currentIndex].rgId = ''
formData.value.matItemDOList[currentIndex].pnId = ''
formData.value.matItemDOList[currentIndex].pnlist = pnList.value.filter(
(pn) =>
pn.wh_id == formData.value.whId &&
matLastData.value.filter((mat) => mat.matId == newValue?.id && mat.pnId == pn.id).length > 0
)
}
</script>
<style>
a {
color: #409eff;
text-decoration: none;
}
</style>