heli-mes/mes-ui/mes-ui-admin-vue3/src/views/heli/purchaseorderno/detail.vue
2025-06-27 08:56:36 +08:00

529 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<el-card class="hl-card" style="position: relative">
<template #header>
<span>详情页</span>
</template>
<el-form ref="formRef" :model="formData" label-width="160px" v-loading="formLoading">
<!-- 基础信息 -->
<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="24">
<el-row>
<el-col :span="6">
<el-row>
<el-col :span="24">
<el-form-item label="采购单号" prop="purchaseNo">
<el-input class="!w-300px" placeholder="系统自动生成" v-model="formData.purchaseNo" disabled />
</el-form-item>
</el-col>
</el-row>
</el-col>
<el-col :span="6">
<el-form-item label="供应商" prop="supplierName">
<el-input class="!w-300px" placeholder="供应商" v-model="formData.supplierName" disabled />
</el-form-item>
</el-col>
</el-row>
</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-form ref="multipleTable" :model="formData.list" :rules="subMatPlanFormRules" v-loading="loading" label-width="0">
<el-table :data="formData.list" class="hl-table" @selection-change="handleSelectionChange" >
<el-table-column type="selection" width="55" />
<el-table-column label="收货状态" align="center" prop="receivingStatus" min-width="120">
<template #default="scope">
<dict-tag :type="DICT_TYPE.HELI_PURCHASE_RECEIVING_STATUS" :value="scope.row.receivingStatus" />
</template>
</el-table-column>
<el-table-column prop="projectSubCode" min-width="150" label="子项目编码" align="center"/>
<el-table-column prop="boomName" min-width="120" label="零件名称" align="center"/>
<el-table-column prop="procedureName" min-width="120" label="工序" align="center"/>
<el-table-column prop="compositionName" min-width="100" label="材质" align="center"/>
<el-table-column prop="purchaseAmount" min-width="100" label="采购数量" align="center" />
<el-table-column prop="purchaseRemAmount" min-width="100" label="剩余数量" align="center"/>
<el-table-column prop="purchaseAmount" min-width="180" align="center">
<template #header><span class="hl-table_header">*</span>入库数量</template>
<template #default="scope">
<el-form-item :prop="`${scope.$index}.purchaseRemAmounts`" :rules="subMatPlanFormRules.purchaseRemAmounts" class="mb-0px!">
<el-input-number style="width: 100%" v-model="scope.row.purchaseRemAmounts" placeholder="入库数量" :min="0" :precision="2" />
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="requireTime" min-width="150" label="需要完成日期" align="center" :formatter="dateFormatter1"/>
<el-table-column prop="arriveTime" min-width="150" label="预计到货日期" align="center" :formatter="dateFormatter1" />
<el-table-column prop="description" min-width="150" label="技术要求" align="center"/>
<el-table-column prop="theWeight" min-width="100" label="理论重量" align="center"/>
<el-table-column prop="estimatedPrice" min-width="150" label="预估总价(元)" align="center"/>
</el-table>
</el-form>
<!-- <Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"-->
<!-- @pagination="getList" />-->
</el-card>
</el-col>
</el-row>
</el-card>
</el-form>
<div class="hl-footer text-center">
<el-button @click="receiveGoods()" type="primary" size="large" >收货</el-button>
<el-button @click="isPrint()" type="primary" size="large" :loading="printLoading">打印</el-button>
<el-button @click="deleteForm()" type="danger" size="large" >删除</el-button>
</div>
</el-card>
<!-- 表单弹窗:物料列表 -->
<!-- 表单弹窗:物料列表 -->
<el-dialog v-model="printDialogVisible" width="80%" title="采购单打印" :close-on-click-modal="false">
<div id="printArea" class="print-content">
<div class="print-header">
<div class="order-info">
<div style="display: flex;">
<span style="width: 210px;">订单编号:{{ printData.purchaseNo }}</span>
<span style="margin-left:20px; width: 170px;">订单日期:{{ formatDate(printData.ordDate) }}</span>
<span style="margin-left:20px;width: 150px">供应商:{{ printData.supplierName }}</span>
</div>
<div style="display: flex;">
<span style="margin-left:20px;width: 110px">联系人:{{ printData.contactName }}</span>
<span style="margin-left:20px;width: 150px">电话:{{ printData.contactMobile }}</span>
</div>
</div>
</div>
<table class="print-table">
<colgroup>
<col style="width: 4%;" />
<col style="width: 14%;" />
<col style="width: 4%;" />
<col style="width: 15%;" />
<col style="width: 7%;" />
<col style="width: 4%;" />
<col style="width: 7%;" />
<col style="width: 8%;" />
<col style="width: 8%;" />
<col style="width: 7%;" />
<col style="width: 6%;" />
<col style="width: 7%;" />
</colgroup>
<thead>
<tr>
<th>序号</th>
<th>子项目编号</th>
<th>件号</th>
<th>标准件名称</th>
<th>物料编码</th>
<th>材料</th>
<th>规格型号</th>
<th>要求完成日期</th>
<th>计划到货日期</th>
<th>采购数量</th>
<th>单价(元)</th>
<th>总价格(元)</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in 17" :key="index">
<td>{{ index + 1 }}</td>
<td>{{ printData.purchaseOrderNoDetailList[index]?.projectSubCode || '' }}</td>
<td>{{ printData.purchaseOrderNoDetailList[index]?.blueprintNo || '' }}</td>
<td>{{ printData.purchaseOrderNoDetailList[index]?.boomName ? limitTo20Chars(printData.purchaseOrderNoDetailList[index].boomName) : '' }}</td>
<td>{{ printData.purchaseOrderNoDetailList[index]?.matCode || '' }}</td>
<td></td>
<td>{{ printData.purchaseOrderNoDetailList[index]?.boomSpec || '' }}</td>
<td>{{ printData.purchaseOrderNoDetailList[index]?.requireTime ? formatDate(printData.purchaseOrderNoDetailList[index].requireTime) : '' }}</td>
<td>{{ printData.purchaseOrderNoDetailList[index]?.arriveTime ? formatDate(printData.purchaseOrderNoDetailList[index].arriveTime) : '' }}</td>
<td>{{ printData.purchaseOrderNoDetailList[index]?.purchaseAmount || '' }}</td>
<td>{{ printData.purchaseOrderNoDetailList[index]?.unitPrice || '' }}</td>
<td>{{ printData.purchaseOrderNoDetailList[index]?.estimatedPrice || '' }}</td>
</tr>
<tr>
<td colspan="8"></td>
<td style="font-weight: bold;">合计</td>
<td style="font-weight: bold;">{{ printData.purchaseAmountSum }}</td>
<td></td>
<td style="font-weight: bold;">{{ printData.estimatedPriceSum }}</td>
</tr>
</tbody>
</table>
<div class="order-info" style="margin-top: 10px;border-bottom: 1px solid #ccc;padding-bottom: 10px;">
<div style="display: flex;width: 40%;">
<span >交货地址{{ printData.deliveryAddress }}</span>
</div>
<div style="display: flex;width: 20%;justify-content: center;">
<span style="margin-left:20px;width: 120px">审核{{ printData.auditorName }}</span>
<span style="margin-left:20px;width: 120px">签字区</span>
</div>
<div style="display: flex; width: 40%;justify-content: right;">
<span style="margin-left:20px;width: 130px">接收人{{ printData.username }}</span>
<span style="margin-left:20px;width: 150px">电话{{ printData.userMobile }}</span>
</div>
</div>
</div>
<template #footer>
<el-button @click="printDialogVisible = false">关闭</el-button>
<el-button type="primary" @click="doPrint">打印</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import * as MaterialPlanApi from '@/api/heli/materialplan'
import * as MaterialPlanDetailApi from '@/api/heli/materialplandetail'
import * as MaterialPlanBoomApi from '@/api/heli/materialplanboom'
import {ElTable, UploadUserFile} from 'element-plus'
import * as PlanApi from '@/api/heli/plan'
import * as PlanSubApi from '@/api/heli/plansub'
import * as ProjectOrderApi from '@/api/heli/projectorder'
import * as UserApi from '@/api/system/user'
import * as MaterialApi from '@/api/heli/material'
import { deleteFile, downloadFile, getFilePage } from '@/api/infra/file'
import download from '@/utils/download'
import { getAccessToken, getTenantId } from '@/utils/auth'
import {dateFormatter, dateFormatter1, formatDate} from '@/utils/formatTime'
import { useUserStore } from '@/store/modules/user'
import { useTagsViewStore } from '@/store/modules/tagsView'
import MaterialSelect from '@/views/heli/hlvuestyle/materialSelect.vue'
import booms from './boom.vue'
const reload: any = inject('reload')
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const { query } = useRoute()
const router = useRouter()
const tagsViewStore = useTagsViewStore()
import * as PurchaseOrderNoApi from '@/api/heli/purchaseorderno'
import * as PurchaseOrderNoDetailApi from '@/api/heli/purchaseordernodetail'
import {PurchaseOrderNoDetailVO} from "@/api/heli/purchaseordernodetail";
import {ref} from "vue";
const dialogVisible = ref(false) // 弹窗的是否展示
const formLoading = ref(false) // 表单的加载中1修改时的数据加载2提交的按钮禁用
const formData = ref({
id: undefined,
purchaseNo: undefined,
projectId: undefined,
projectPlanId: undefined,
projectPlanNo: undefined,
projectCode: undefined,
auditor: undefined,
createTime: new Date(),
status: undefined,
description: undefined,
boomItemDOList: [],
boomItemRemoveList: [],
matBoomDOList: [],
matItemRemoveList: [],
attachments: [],
supplierName:undefined,
list:[]
})
const subMatPlanFormRules = reactive({
purchaseRemAmounts: [{ required: true, message: '入库数量不能为空', trigger: 'blur' }]})
const formRef = ref() // 表单 Ref
const subFormRef = ref() // 表单 Ref
const loading = ref(true) // 列表的加载中
const total = ref(0) // 列表的总页数
const subBoomFormLoading = ref(false)
const subBoomFormRef = ref()
const multipleTable = ref<InstanceType<typeof ElTable>>()
const handleSelectionChange = (val) => {
// multipleTable.value.clearSelection()
multipleTable.value=val
}
const closeForm = async () => {
router.push({ path: '/purchase/purchaseorderno' })
tagsViewStore.delVisitedView(router.currentRoute.value)
}
const userList = ref<UserApi.UserVO[]>([]) // 用户列表
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
projectMaterialPlanId: query.id
})
// 页面数据加载初始化
onMounted(async () => {
// 获取物料需求计划信息
formData.value = await PurchaseOrderNoApi.getPurchaseOrderNo(query.id)
getList();
})
const printLoading = ref(false)
// 打印弹窗内容
const printDialogVisible = ref(false)
const printData = ref({})
function openPrintDialog(data) {
printData.value = data
printDialogVisible.value = true
}
const isPrint = async () => {
printLoading.value = true
printLoading.value = true
try {
var newVar = await PurchaseOrderNoApi.isPrint(query.id);
console.log(newVar)
openPrintDialog(newVar)
} finally {
printLoading.value = false
}
}
function doPrint() {
// 创建新的打印窗口
const printContent = document.getElementById('printArea')
if (!printContent) return
const iframe = document.createElement('iframe')
iframe.style.position = 'absolute'
iframe.style.width = '0'
iframe.style.height = '0'
iframe.style.border = 'none'
document.body.appendChild(iframe)
const doc = iframe.contentWindow?.document
doc?.open()
doc?.write(`
<!DOCTYPE html>
<html>
<head>
<title >采购单</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 10px;
font-size: 12px;
}
.print-content {
width: 100%;
padding-top: 15px;
}
.order-info {
justify-content: space-between;
display: flex;
flex-wrap: wrap;
align-items: center;
}
.stamp-info {
margin-top: 10px;
}
.stamp-info span{
font-size: 15px !important;
}
.order-info span{
font-size: 15px !important;
}
.print-table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}
.print-table th, .print-table td {
border: 1px solid #ddd;
padding: 5px;
text-align: center;
height: 20px; /* 设置固定高度 */
line-height: 20px; /* 垂直居中 */
}
.print-table th {
background-color: #f5f5f5;
}
@media print {
body { margin: 0; }
.print-content {
width: 100%;
margin: 0;
padding: 10px;
}
}
</style>
</head>
<body>
${printContent.innerHTML}
</body>
</html>
`)
doc?.close()
iframe.onload = () => {
iframe.contentWindow?.focus()
iframe.contentWindow?.print()
setTimeout(() => document.body.removeChild(iframe), 1000)
}
}
function limitTo20Chars(input) {
if (typeof input !== 'string') return '';
return input.length > 20 ? input.slice(0, 20) : input;
}
function formatDate(val) {
if (!val) return ''
const date = new Date(val)
return date.toLocaleDateString()
}
const deleteForm = async () => {
await PurchaseOrderNoApi.deleteForm(query.id)
router.push({ path: '/purchase/purchaseorderno' })
tagsViewStore.delVisitedView(router.currentRoute.value)
}
const receiveGoods = async () => {
try {
const list = multipleTable.value|| []; // 安全获取数据
// 1. 检查空数据
if (!list || list.length==null||list.length==0) {
message.error("采购单信息未选择,请确认");
return;
}
await PurchaseOrderNoDetailApi.verification(list)
const res = await Promise.race([
PurchaseOrderNoDetailApi.receiveGoods(list),
new Promise((_, reject) =>
setTimeout(() => reject(new Error("请求超时")), 30000)
)
]);
loading.value = true;
message.success("收货成功");
getList(); // 确保刷新完成
emit('success');
} catch (error) {
} finally {
loading.value = false;
}
}
const getList = async () => {
loading.value = true
try {
const data = await PurchaseOrderNoDetailApi.getPurchaseOrderNoDetailById(query.id)
formData.value.list = data
} finally {
loading.value = false
}
}
</script>
<style scoped>
/* 打印样式 */
@media print {
/* 隐藏所有非打印内容 */
body * {
visibility: hidden;
}
/* 只显示打印区域 */
#printArea, #printArea * {
visibility: visible;
}
/* 打印区域定位 */
#printArea {
position: absolute;
left: 0;
top: 0;
width: 100%;
}
/* 隐藏弹窗相关元素 */
.el-dialog, .el-dialog__wrapper, .el-dialog__header, .el-dialog__footer {
display: none !important;
}
}
.order-info {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
}
.order-info span {
font-size: 15px !important;
margin-right: 10px !important;
}
.stamp-info {
margin-top: 10px;
}
.stamp-info span{
font-size: 15px !important;
}
.print-table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
border: 1px solid #ccc;
}
.print-table th,
.print-table td {
border: 1px solid #ccc;
padding: 6px 8px;
text-align: center;
font-size: 13px !important;
height: 30px; /* 设置固定高度 */
line-height: 30px; /* 垂直居中 */
}
.print-table th {
background-color: #f5f7fa;
color: #303133;
font-weight: 600;
font-size: 13px !important;
}
</style>