From f3f855be1fd86d28485fceb02c30b6c6b2853aef Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期三, 04 十一月 2026 18:15:40 +0800
Subject: [PATCH] feat(mes): 质检附件与来源关联界面,新增工单技术文件、废料登记与领料单打印
---
src/views/mes/workbench/components/tabs/ProductIssueTab.vue | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 51 insertions(+), 1 deletions(-)
diff --git a/src/views/mes/workbench/components/tabs/ProductIssueTab.vue b/src/views/mes/workbench/components/tabs/ProductIssueTab.vue
index 27f62be..52c91e7 100644
--- a/src/views/mes/workbench/components/tabs/ProductIssueTab.vue
+++ b/src/views/mes/workbench/components/tabs/ProductIssueTab.vue
@@ -22,10 +22,13 @@
cancelProductIssue,
createProductIssue,
deleteProductIssue,
+ getProductIssue,
getProductIssuePage,
submitProductIssue,
updateProductIssue,
} from '#/api/mes/wm/productissue';
+import { getProductIssueLinesByIssue } from '#/api/mes/wm/productissue/line';
+import dayjs from 'dayjs';
import { MdWorkstationSelect } from '#/views/mes/md/workstation/components';
import { ProWorkOrderSelect } from '#/views/mes/pro/workorder/components';
@@ -240,7 +243,7 @@
props: { type: DICT_TYPE.MES_WM_PRODUCT_ISSUE_STATUS },
},
},
- { title: '鎿嶄綔', width: 260, fixed: 'right', slots: { default: 'actions' } },
+ { title: '鎿嶄綔', width: 360, fixed: 'right', slots: { default: 'actions' } },
];
const gridHeight = ref(300);
@@ -304,6 +307,52 @@
/** 鏄惁宸查�変腑宸ヤ綔绔欏拰浠诲姟锛屾湭閫変腑鏃朵笉灞曠ず琛ㄦ牸 */
const isReady = computed(() => !!props.taskId && !!props.workstationId);
+/** 鍗曟嵁鍐呭鍏ㄩ儴鎸夋枃鏈浆涔夛紝閬垮厤鐗╂枡鍚嶇О鎴栧娉ㄥ奖鍝嶆墦鍗伴〉闈㈢粨鏋勩�� */
+function escapePrintText(value: unknown) {
+ return String(value ?? '').replace(/[&<>"']/g, (char) => ({
+ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''',
+ })[char] || char);
+}
+
+async function handlePrintIssue(row: MesWmProductIssueApi.ProductIssue) {
+ if (!row.id) return;
+ // 鍏堟墦寮�绐楀彛锛岄伩鍏嶅紓姝ヨ姹傜粨鏉熷悗琚祻瑙堝櫒浣滀负寮圭獥鎷︽埅銆�
+ const popup = window.open('', '_blank');
+ if (!popup) { message.warning('娴忚鍣ㄦ嫤鎴簡鎵撳嵃绐楀彛锛岃鍏佽寮圭獥鍚庨噸璇�'); return; }
+ popup.document.title = '姝e湪鍑嗗棰嗘枡鍗�';
+ popup.document.body.textContent = '姝e湪鍑嗗棰嗘枡鍗曗��';
+ try {
+ const [issue, lines] = await Promise.all([getProductIssue(row.id), getProductIssueLinesByIssue(row.id)]);
+ if (!issue) throw new Error('棰嗘枡鍗曚笉瀛樺湪');
+ const safe = escapePrintText;
+ const date = (value: unknown) => value && dayjs(value as string | number | Date).isValid()
+ ? dayjs(value as string | number | Date).format('YYYY-MM-DD HH:mm') : '';
+ const statusNames: Record<number, string> = {
+ [MesWmProductIssueStatusEnum.PREPARE]: '鑽夌',
+ [MesWmProductIssueStatusEnum.APPROVING]: '寰呮嫞璐�',
+ [MesWmProductIssueStatusEnum.APPROVED]: '寰呴鍑�',
+ [MesWmProductIssueStatusEnum.FINISHED]: '宸插畬鎴�',
+ [MesWmProductIssueStatusEnum.CANCELED]: '宸插彇娑�',
+ };
+ const rows = lines.map((item, index) => `<tr><td>${index + 1}</td><td>${safe(item.itemCode)}</td><td>${safe(item.itemName)}</td><td>${safe(item.specification)}</td><td>${safe(item.unitMeasureName)}</td><td>${safe(item.quantity)}</td><td>${safe(item.remark)}</td></tr>`).join('');
+ popup.document.open();
+ popup.document.write(`<!doctype html><html lang="zh-CN"><head><meta charset="UTF-8"><title>棰嗘枡鍗� ${safe(issue.code)}</title><style>
+ @page { size: A4; margin: 15mm; } body { color: #111; font: 13px 'Microsoft YaHei', sans-serif; margin: 0 auto; max-width: 180mm; }
+ h1 { text-align: center; font-size: 22px; margin: 12px 0 20px; } .meta { display: grid; grid-template-columns: 1fr 1fr; gap: 9px 16px; margin-bottom: 16px; overflow-wrap: anywhere; }
+ table { border-collapse: collapse; width: 100%; table-layout: fixed; } th,td { border: 1px solid #555; padding: 7px 4px; word-break: break-word; text-align: left; } th:first-child,td:first-child { width: 32px; text-align: center; } th:nth-child(5),td:nth-child(5) { width: 42px; } th:nth-child(6),td:nth-child(6) { width: 56px; } thead { display: table-header-group; } tr { break-inside: avoid; }
+ .sign { display: flex; justify-content: space-between; gap: 18px; margin-top: 32px; } .toolbar { text-align: right; padding: 12px 0; } button { padding: 7px 14px; cursor: pointer; } @media print { .toolbar { display: none; } }
+ </style></head><body><div class="toolbar"><button onclick="window.print()">鎵撳嵃 / 淇濆瓨涓� PDF</button></div><h1>棰嗘枡鍗�</h1>
+ <div class="meta"><div>棰嗘枡鍗曞彿锛�${safe(issue.code)}</div><div>棰嗘枡鍗曞悕绉帮細${safe(issue.name)}</div><div>鐢熶骇浠诲姟锛�${safe(issue.taskCode)}</div><div>鐢熶骇璁㈠崟锛�${safe(issue.workOrderCode)}</div><div>宸ヤ綔绔欙細${safe(issue.workstationName || issue.workstationCode)}</div><div>闇�姹傛椂闂达細${safe(date(issue.requiredTime))}</div><div>鐘舵�侊細${safe(statusNames[issue.status ?? -1] ?? '鏈煡')}</div><div>澶囨敞锛�${safe(issue.remark)}</div></div>
+ <table><thead><tr><th>搴忓彿</th><th>鐗╂枡缂栫爜</th><th>鐗╂枡鍚嶇О</th><th>瑙勬牸鍨嬪彿</th><th>鍗曚綅</th><th>鐢宠鏁伴噺</th><th>澶囨敞</th></tr></thead><tbody>${rows || '<tr><td colspan="7">鏆傛棤棰嗘枡鏄庣粏</td></tr>'}</tbody></table>
+ <div class="sign"><span>鐢宠浜猴細____________</span><span>鍙戞枡浜猴細____________</span><span>棰嗘枡浜猴細____________</span><span>鏃ユ湡锛歘___________</span></div></body></html>`);
+ popup.document.close();
+ } catch (error) {
+ popup.close();
+ message.error('鏃犳硶鐢熸垚棰嗘枡鍗曪紝璇风◢鍚庨噸璇�');
+ console.error(error);
+ }
+}
+
/** 缂栬緫寮圭獥 */
const [EditFormModal, editFormModalApi] = useVbenModal({
connectedComponent: ProductIssueFormModal,
@@ -361,6 +410,7 @@
<div ref="listRef" class="issue-tab__list">
<Grid table-title="棰嗘枡璁板綍">
<template #actions="{ row }">
+ <Button type="link" size="small" @click="handlePrintIssue(row)">鎵撳嵃 / 瀵煎嚭 PDF</Button>
<Button
v-if="row.status === MesWmProductIssueStatusEnum.PREPARE"
type="link"
--
Gitblit v1.9.3