You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1770 lines
54 KiB

8 months ago
3 months ago
3 months ago
3 months ago
8 months ago
3 months ago
8 months ago
3 months ago
8 months ago
6 months ago
6 months ago
8 months ago
5 months ago
5 months ago
7 months ago
5 months ago
8 months ago
8 months ago
7 months ago
8 months ago
5 months ago
8 months ago
5 months ago
5 months ago
5 months ago
8 months ago
8 months ago
8 months ago
3 months ago
8 months ago
8 months ago
6 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
6 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
6 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
3 months ago
8 months ago
3 months ago
8 months ago
3 months ago
3 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
8 months ago
3 months ago
8 months ago
  1. <template>
  2. <div class="mod-config">
  3. <!-- 条件查询 -->
  4. <el-card :class="['search-card', { 'collapsed': !searchExpanded }]" shadow="hover">
  5. <div slot="header" class="search-header">
  6. <div class="header-left">
  7. <i class="el-icon-search"></i>
  8. <span class="header-title">销售发货装箱</span>
  9. </div>
  10. <div class="header-right">
  11. <el-button
  12. type="text"
  13. size="small"
  14. @click="toggleSearchExpand"
  15. class="collapse-btn">
  16. <i :class="searchExpanded ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"></i>
  17. {{ searchExpanded ? '收起' : '展开' }}
  18. </el-button>
  19. </div>
  20. </div>
  21. <el-form
  22. :inline="true"
  23. label-position="top"
  24. :model="searchData"
  25. class="search-form"
  26. @keyup.enter.native="getMainData">
  27. <!-- 查询条件 - 可展开/收起 -->
  28. <template v-if="searchExpanded">
  29. <el-row :gutter="12">
  30. <el-col :span="2">
  31. <el-form-item label="BU">
  32. <el-input v-model="searchData.buNo" placeholder="BU" clearable style="width: 100%"></el-input>
  33. </el-form-item>
  34. </el-col>
  35. <el-col :span="3">
  36. <el-form-item label="销售出库单号">
  37. <el-input v-model="searchData.orderNo" placeholder="单号" clearable style="width: 100%"></el-input>
  38. </el-form-item>
  39. </el-col>
  40. <el-col :span="3">
  41. <el-form-item label="客户编号">
  42. <el-input v-model="searchData.customerId" placeholder="客户编号" clearable style="width: 100%"></el-input>
  43. </el-form-item>
  44. </el-col>
  45. <el-col :span="3">
  46. <el-form-item label="客户名称">
  47. <el-input v-model="searchData.customerName" placeholder="客户名称" clearable style="width: 100%"></el-input>
  48. </el-form-item>
  49. </el-col>
  50. <el-col :span="4">
  51. <el-form-item label="单据状态">
  52. <el-select multiple collapse-tags v-model="searchData.orderStatusList" clearable placeholder="请选择" style="width: 120%">
  53. <el-option label="待包装" value="待包装"></el-option>
  54. <el-option label="待检验" value="待检验"></el-option>
  55. <el-option label="待出库" value="待出库"></el-option>
  56. <el-option label="已完成" value="已完成"></el-option>
  57. </el-select>
  58. </el-form-item>
  59. </el-col>
  60. <el-col :span="2">
  61. <el-form-item label="是否送检">
  62. <el-select v-model="searchData.inspectionFlag" clearable placeholder="选择" style="width: 100%">
  63. <el-option label="是" value="Y"></el-option>
  64. <el-option label="否" value="N"></el-option>
  65. </el-select>
  66. </el-form-item>
  67. </el-col>
  68. <el-col :span="7">
  69. <el-form-item label="要求发货日期">
  70. <el-date-picker
  71. v-model="searchData.startDate"
  72. type="date"
  73. value-format="yyyy-MM-dd"
  74. placeholder="开始日期"
  75. style="width: 44%">
  76. </el-date-picker>
  77. <span style="margin: 0 6px; color: #DCDFE6;">~</span>
  78. <el-date-picker
  79. v-model="searchData.endDate"
  80. type="date"
  81. value-format="yyyy-MM-dd"
  82. placeholder="结束日期"
  83. style="width: 44%">
  84. </el-date-picker>
  85. </el-form-item>
  86. </el-col>
  87. </el-row>
  88. </template>
  89. <!-- 操作按钮区域 -->
  90. <el-row :gutter="16">
  91. <el-col :span="24">
  92. <div class="search-actions">
  93. <div class="action-left">
  94. <el-button
  95. type="primary"
  96. icon="el-icon-search"
  97. @click="getMainData">
  98. 查询
  99. </el-button>
  100. <el-button
  101. type="primary"
  102. icon="el-icon-download"
  103. @click="exportExcel()">
  104. 导出
  105. </el-button>
  106. </div>
  107. </div>
  108. </el-col>
  109. </el-row>
  110. </el-form>
  111. </el-card>
  112. <!-- 数据列表 -->
  113. <div class="section-title-bar">
  114. <i class="el-icon-document"></i>
  115. <span>销售发货清单</span>
  116. <span class="total-count"> {{ totalPage }} </span>
  117. </div>
  118. <el-table
  119. :height="tableHeight"
  120. :data="mainDataList"
  121. border
  122. ref="mainTable"
  123. highlight-current-row
  124. @row-click="changeData"
  125. v-loading="dataListLoading"
  126. style="margin-top: 0px; width: 100%;">
  127. <el-table-column
  128. v-for="(item,index) in columnArray1" :key="index"
  129. :sortable="item.columnSortable"
  130. :prop="item.columnProp"
  131. :header-align="item.headerAlign"
  132. :show-overflow-tooltip="item.showOverflowTooltip"
  133. :align="item.align"
  134. :fixed="item.fixed==''?false:item.fixed"
  135. :min-width="item.columnWidth"
  136. :label="item.columnLabel">
  137. <template slot-scope="scope">
  138. <span v-if="!item.columnHidden && item.columnProp !== 'inspectionFlag'"> {{scope.row[item.columnProp]}}</span>
  139. <span v-if="!item.columnHidden && item.columnProp === 'inspectionFlag'"> {{scope.row[item.columnProp] === 'Y' ? '' : scope.row[item.columnProp] === 'N' ? '' : ''}}</span>
  140. <span v-if="item.columnImage"><img :src="scope.row[item.columnProp]" style="width: 100px; height: 80px"/></span>
  141. </template>
  142. </el-table-column>
  143. <el-table-column
  144. fixed="right"
  145. header-align="center"
  146. align="center"
  147. width="80"
  148. label="操作">
  149. <template slot-scope="scope">
  150. <el-link v-if="scope.row.orderStatus === '待包装'" style="cursor: pointer" @click="handleComplete(scope.row)">送检</el-link>
  151. </template>
  152. </el-table-column>
  153. </el-table>
  154. <!-- 分页插件 -->
  155. <el-pagination style="margin-top: 0px"
  156. @size-change="sizeChangeHandle"
  157. @current-change="currentChangeHandle"
  158. :current-page="pageIndex"
  159. :page-sizes="[20, 50, 100, 200, 500]"
  160. :page-size="pageSize"
  161. :total="totalPage"
  162. layout="total, sizes, prev, pager, next, jumper">
  163. </el-pagination>
  164. <el-tabs v-model="activeName" style="margin-top: 0px; width: 99%;" @tab-click="tabClick" class="customer-tab" type="border-card">
  165. <el-tab-pane label="扫描装盒" name="cases">
  166. <el-form v-if="currentRow.orderStatus === '待包装'" label-position="top" style="margin-left: 2px; display: flex; align-items: center;">
  167. <el-button type="primary" size="small" @click="openCaseDialog">新增</el-button>
  168. <el-button type="danger" size="small" @click="deleteCaseRecord">删除</el-button>
  169. <el-button type="primary" size="small" :loading="printCasesLoading" @click="printSelectedCases">打印</el-button>
  170. <span style="margin-left: auto; font-size: 14px; display: flex; align-items: center;">
  171. <span style="margin-right: 20px;">
  172. <span style="color: #606266;">盒标签张数</span>
  173. <span style="color: rgb(38, 92, 147); font-weight: bold;">{{casesStatistics.boxCountCases}}</span>
  174. </span>
  175. <span style="margin-right: 20px;">
  176. <span style="color: #606266;">卷标签张数</span>
  177. <span style="color: rgb(38, 92, 147); font-weight: bold;">{{casesStatistics.boxCountRolls}}</span>
  178. </span>
  179. <span>
  180. <span style="color: #606266;">物料总数</span>
  181. <span style="color: rgb(38, 92, 147); font-weight: bold;">{{casesStatistics.totalQty}}</span>
  182. </span>
  183. </span>
  184. </el-form>
  185. <el-table
  186. ref="caseTable"
  187. :data="casesList"
  188. :height="height"
  189. border
  190. @selection-change="handleCaseSelectionChange"
  191. style="width: 100%;">
  192. <el-table-column
  193. type="selection"
  194. width="55"
  195. align="center">
  196. </el-table-column>
  197. <el-table-column
  198. prop="casesNo"
  199. header-align="center"
  200. align="center"
  201. min-width="120"
  202. label="盒标签">
  203. </el-table-column>
  204. <el-table-column
  205. prop="rollNo"
  206. header-align="center"
  207. align="center"
  208. min-width="120"
  209. label="卷标签">
  210. </el-table-column>
  211. <el-table-column
  212. prop="rollQty"
  213. header-align="center"
  214. align="right"
  215. min-width="100"
  216. label="卷数量">
  217. </el-table-column>
  218. <el-table-column
  219. prop="partNo"
  220. header-align="center"
  221. align="left"
  222. min-width="120"
  223. label="物料编码">
  224. </el-table-column>
  225. <el-table-column
  226. prop="partDesc"
  227. header-align="center"
  228. align="left"
  229. min-width="200"
  230. label="物料名称">
  231. </el-table-column>
  232. <el-table-column
  233. prop="createDate"
  234. header-align="center"
  235. align="center"
  236. min-width="160"
  237. label="创建时间">
  238. </el-table-column>
  239. <el-table-column
  240. prop="createBy"
  241. header-align="center"
  242. align="center"
  243. min-width="100"
  244. label="创建人">
  245. </el-table-column>
  246. </el-table>
  247. </el-tab-pane>
  248. <el-tab-pane label="扫描装箱" name="boxing">
  249. <boxing ref="boxing"></boxing>
  250. </el-tab-pane>
  251. <el-tab-pane label="装箱清单" name="rollDetail">
  252. <el-table
  253. :data="rollList"
  254. :height="height + 23"
  255. border
  256. style="width: 100%;">
  257. <el-table-column
  258. prop="orderId"
  259. header-align="center"
  260. align="center"
  261. min-width="60"
  262. label="序号">
  263. </el-table-column>
  264. <el-table-column
  265. prop="boxNo"
  266. header-align="center"
  267. align="center"
  268. min-width="100"
  269. label="箱号">
  270. </el-table-column>
  271. <el-table-column
  272. prop="finalRollNo"
  273. header-align="center"
  274. align="center"
  275. min-width="100"
  276. label="卷号">
  277. </el-table-column>
  278. <el-table-column
  279. prop="partNo"
  280. header-align="center"
  281. align="left"
  282. min-width="100"
  283. label="物料编码">
  284. </el-table-column>
  285. <el-table-column
  286. prop="rollQty"
  287. header-align="center"
  288. align="right"
  289. min-width="100"
  290. label="数量">
  291. </el-table-column>
  292. <el-table-column
  293. prop="receivedDate"
  294. header-align="center"
  295. align="center"
  296. min-width="100"
  297. label="装箱日期">
  298. </el-table-column>
  299. <el-table-column
  300. prop="receivedBy"
  301. header-align="center"
  302. align="left"
  303. min-width="100"
  304. label="装箱人">
  305. </el-table-column>
  306. <el-table-column
  307. prop="batchNo"
  308. header-align="center"
  309. align="left"
  310. min-width="100"
  311. label="合约号">
  312. </el-table-column>
  313. <el-table-column
  314. prop="wareHouseID"
  315. header-align="center"
  316. align="left"
  317. min-width="100"
  318. label="仓库">
  319. </el-table-column>
  320. <el-table-column
  321. prop="locationId"
  322. header-align="center"
  323. align="left"
  324. min-width="100"
  325. label="库位">
  326. </el-table-column>
  327. </el-table>
  328. </el-tab-pane>
  329. <el-tab-pane label="扫描装托" name="pallet">
  330. <pallet ref="pallet"></pallet>
  331. </el-tab-pane>
  332. </el-tabs>
  333. <!-- 盒清单新增对话框 -->
  334. <el-dialog title="装盒扫描" :visible.sync="caseDialogVisible" width="70%" :close-on-click-modal="false" @close="closeCaseDialog">
  335. <el-form :inline="true" label-position="top" style="margin-left: 7px;margin-top: -5px;" @submit.native.prevent>
  336. <el-form-item label="卷标签">
  337. <el-input ref="rollNoInput" v-model="caseForm.rollNo" @keyup.enter.native="scanCaseRoll" placeholder="请扫描卷标签" style="width: 200px"></el-input>
  338. </el-form-item>
  339. <span style="margin-left: 20px; font-size: 14px; display: inline-block; margin-top: 20px;">
  340. <span style="color: #606266;">需求数量</span>
  341. <span style="color: rgb(38, 92, 147); font-weight: bold;">{{currentRow.requiredQty || 0}}</span>
  342. </span>
  343. <span style="margin-left: 20px; font-size: 14px; display: inline-block; margin-top: 20px;">
  344. <span style="color: #606266;">盒标签张数</span>
  345. <span style="color: rgb(38, 92, 147); font-weight: bold;">{{caseStatistics.casesCount}}</span>
  346. </span>
  347. <span style="margin-left: 20px; font-size: 14px; display: inline-block; margin-top: 20px;">
  348. <span style="color: #606266;">卷标签张数</span>
  349. <span style="color: rgb(38, 92, 147); font-weight: bold;">{{caseStatistics.rollCount}}</span>
  350. </span>
  351. <span style="margin-left: 20px; font-size: 14px; display: inline-block; margin-top: 20px;">
  352. <span style="color: #606266;">物料总数</span>
  353. <span style="color: rgb(38, 92, 147); font-weight: bold;">{{caseStatistics.totalQty}}</span>
  354. </span>
  355. </el-form>
  356. <!-- 中部分扫描列表 -->
  357. <el-table
  358. ref="caseRollTable"
  359. :data="caseRollList"
  360. border
  361. height="300"
  362. @selection-change="handleCaseRollSelectionChange"
  363. style="width: 100%; margin-top: 10px;">
  364. <el-table-column
  365. type="selection"
  366. width="55"
  367. header-align="center"
  368. align="center">
  369. </el-table-column>
  370. <el-table-column
  371. type="index"
  372. label="序号"
  373. width="50"
  374. header-align="center"
  375. align="right">
  376. </el-table-column>
  377. <el-table-column
  378. prop="casesNo"
  379. label="盒标签"
  380. min-width="120"
  381. header-align="center"
  382. align="left">
  383. </el-table-column>
  384. <el-table-column
  385. prop="rollNo"
  386. label="卷标签"
  387. min-width="120"
  388. header-align="center"
  389. align="left">
  390. </el-table-column>
  391. <el-table-column
  392. prop="rollQty"
  393. label="卷数量"
  394. min-width="100"
  395. header-align="center"
  396. align="right">
  397. </el-table-column>
  398. <el-table-column
  399. prop="partNo"
  400. label="物料编码"
  401. min-width="120"
  402. header-align="center"
  403. align="left">
  404. </el-table-column>
  405. <el-table-column
  406. prop="partDesc"
  407. label="物料名称"
  408. min-width="200"
  409. header-align="center"
  410. align="left">
  411. </el-table-column>
  412. <el-table-column
  413. prop="batchNo"
  414. label="合约号"
  415. min-width="120"
  416. header-align="center"
  417. align="left">
  418. </el-table-column>
  419. <el-table-column
  420. label="操作"
  421. width="80"
  422. header-align="center"
  423. align="center">
  424. <template slot-scope="scope">
  425. <el-link style="cursor: pointer" @click="deleteRollFromList(scope.$index)">删除</el-link>
  426. </template>
  427. </el-table-column>
  428. </el-table>
  429. <el-footer style="height:35px;margin-top: 15px;text-align:center">
  430. <el-button type="primary" :loading="printLoading" @click="printCaseRolls">打印</el-button>
  431. <el-button type="primary" @click="applyCaseScan">应用</el-button>
  432. <el-button type="success" @click="saveCaseScan">保存</el-button>
  433. <el-button @click="closeCaseDialog">关闭</el-button>
  434. </el-footer>
  435. </el-dialog>
  436. </div>
  437. </template>
  438. <script>
  439. /*组件*/
  440. import excel from "@/utils/excel-util.js";
  441. import boxing from "./com_saleBoxManage_boxing.vue"
  442. import pallet from "./com_saleBoxManage_pallet.vue"
  443. import {
  444. searchRollForOrderNo,
  445. searchSoReceiveCasesData,
  446. deleteSoReceiveCasesData,
  447. validateAndScanCaseRoll,
  448. saveCaseRollList,
  449. searchOutboundNotificationWithDetail,
  450. searchOutboundNotificationWithDetailByPage,
  451. updateOrderStatus
  452. } from '../../../api/boxManage/boxManage'
  453. import { callUspPartLabelTemplate } from '@/api/wms/wms'
  454. import getLodop from '@/utils/LodopFuncs.js'
  455. import labelPrintTemplates from '@/mixins/labelPrintTemplates.js'
  456. export default {
  457. mixins: [labelPrintTemplates],
  458. data() {
  459. return {
  460. functionId: this.$route.meta.menuId,
  461. height: 200,
  462. tableHeight: 200,
  463. searchExpanded: true,
  464. currentRow: {},
  465. selectedCaseRolls: [], // 装盒对话框中选中的卷标签
  466. printLoading: false, // 打印loading
  467. printCasesLoading: false, // 扫描装盒页签打印loading
  468. searchData:{
  469. orderNo:'',
  470. customerId:'',
  471. orderType:'销售出库',
  472. orderStatus: '',
  473. orderStatusList: ['待包装'],
  474. inspectionFlag: '',
  475. buNo:'',
  476. customerName:'',
  477. startDate: new Date().toISOString().split('T')[0],
  478. endDate: new Date().toISOString().split('T')[0],
  479. site:this.$store.state.user.site,
  480. userName:this.$store.state.user.name,
  481. page: 1,
  482. limit: 10,
  483. },
  484. pageIndex: 1,
  485. pageSize: 50,
  486. totalPage: 0,
  487. tagNo:'',
  488. rollList:[],
  489. mainDataList:[],
  490. dataListLoading: false,
  491. activeName: 'cases',
  492. // 盒清单相关数据
  493. casesList: [],
  494. casesStatistics: {
  495. boxCountCases: 0, // 盒标签张数
  496. boxCountRolls: 0, // 卷标签张数
  497. totalQty: 0 // 物料总数
  498. },
  499. caseDialogVisible: false,
  500. caseForm: {
  501. casesNo: '',
  502. rollNo: '',
  503. site: this.$store.state.user.site,
  504. buNo: '',
  505. notifyNo: '',
  506. partNo: ''
  507. },
  508. caseRollList: [],
  509. caseStatistics: {
  510. casesCount: 0,
  511. rollCount: 0,
  512. totalQty: 0
  513. },
  514. selectedCaseRecords: [],
  515. columnArray1: [
  516. {
  517. userId: this.$store.state.user.name,
  518. functionId: this.functionId,
  519. serialNumber: '750001Table1BU',
  520. tableId: "750001Table1",
  521. tableName: "销售发货清单",
  522. columnProp: "buNo",
  523. headerAlign: "center",
  524. align: "left",
  525. columnLabel: "BU",
  526. columnWidth: '60',
  527. columnHidden: false,
  528. columnImage: false,
  529. columnSortable: false,
  530. sortLv: 0,
  531. status: true,
  532. fixed: false
  533. },
  534. {
  535. userId: this.$store.state.user.name,
  536. functionId: this.functionId,
  537. serialNumber: '750001Table1OrderNo',
  538. tableId: "750001Table1",
  539. tableName: "销售发货清单",
  540. columnProp: "orderNo",
  541. headerAlign: "center",
  542. align: "left",
  543. columnLabel: "销售出库单号",
  544. columnWidth: '100',
  545. columnHidden: false,
  546. columnImage: false,
  547. columnSortable: false,
  548. sortLv: 0,
  549. status: true,
  550. fixed: false
  551. },
  552. {
  553. userId: this.$store.state.user.name,
  554. functionId: this.functionId,
  555. serialNumber: '750001Table1OrderStatus',
  556. tableId: "750001Table1",
  557. tableName: "销售发货清单",
  558. columnProp: "orderStatus",
  559. headerAlign: "center",
  560. align: "left",
  561. columnLabel: "通知单状态",
  562. columnWidth: '80',
  563. columnHidden: false,
  564. columnImage: false,
  565. columnSortable: false,
  566. sortLv: 0,
  567. status: true,
  568. fixed: false
  569. },
  570. {
  571. userId: this.$store.state.user.name,
  572. functionId: this.functionId,
  573. serialNumber: '750001Table1InspectionFlag',
  574. tableId: "750001Table1",
  575. tableName: "销售发货清单",
  576. columnProp: "inspectionFlag",
  577. headerAlign: "center",
  578. align: "center",
  579. columnLabel: "是否送检",
  580. columnWidth: '80',
  581. columnHidden: false,
  582. columnImage: false,
  583. columnSortable: false,
  584. sortLv: 0,
  585. status: true,
  586. fixed: false
  587. },
  588. {
  589. userId: this.$store.state.user.name,
  590. functionId: this.functionId,
  591. serialNumber: '750001Table1CustomerId',
  592. tableId: "750001Table1",
  593. tableName: "销售发货清单",
  594. columnProp: "customerId",
  595. headerAlign: "center",
  596. align: "left",
  597. columnLabel: "客户编号",
  598. columnWidth: '100',
  599. columnHidden: false,
  600. columnImage: false,
  601. columnSortable: false,
  602. sortLv: 0,
  603. status: true,
  604. fixed: false
  605. },
  606. {
  607. userId: this.$store.state.user.name,
  608. functionId: this.functionId,
  609. serialNumber: '750001Table1CustomerName',
  610. tableId: "750001Table1",
  611. tableName: "销售发货清单",
  612. columnProp: "customerName",
  613. headerAlign: "center",
  614. align: "left",
  615. columnLabel: "客户名称",
  616. columnWidth: '240',
  617. columnHidden: false,
  618. columnImage: false,
  619. columnSortable: false,
  620. sortLv: 0,
  621. status: true,
  622. fixed: false
  623. },
  624. {
  625. userId: this.$store.state.user.name,
  626. functionId: this.functionId,
  627. serialNumber: '750001Table1CustomerAbb',
  628. tableId: "750001Table1",
  629. tableName: "销售发货清单",
  630. columnProp: "customerAbb",
  631. headerAlign: "center",
  632. align: "left",
  633. columnLabel: "客户简称",
  634. columnWidth: '120',
  635. columnHidden: false,
  636. columnImage: false,
  637. columnSortable: false,
  638. sortLv: 0,
  639. status: true,
  640. fixed: false
  641. },
  642. {
  643. userId: this.$store.state.user.name,
  644. functionId: this.functionId,
  645. serialNumber: '750001Table1RequiredOutboundDate',
  646. tableId: "750001Table1",
  647. tableName: "销售发货清单",
  648. columnProp: "requiredOutboundDate",
  649. headerAlign: "center",
  650. align: "left",
  651. columnLabel: "要求发货日期",
  652. columnWidth: '120',
  653. columnHidden: false,
  654. columnImage: false,
  655. columnSortable: false,
  656. sortLv: 0,
  657. status: true,
  658. fixed: false
  659. },
  660. {
  661. userId: this.$store.state.user.name,
  662. functionId: this.functionId,
  663. serialNumber: '750001Table1RelatedOrderNo',
  664. tableId: "750001Table1",
  665. tableName: "销售发货清单",
  666. columnProp: "relatedOrderNo",
  667. headerAlign: "center",
  668. align: "left",
  669. columnLabel: "销售订单号",
  670. columnWidth: '100',
  671. columnHidden: false,
  672. columnImage: false,
  673. columnSortable: false,
  674. sortLv: 0,
  675. status: true,
  676. fixed: false
  677. },
  678. {
  679. userId: this.$store.state.user.name,
  680. functionId: this.functionId,
  681. serialNumber: '750001Table1RelatedOrderLineNo',
  682. tableId: "750001Table1",
  683. tableName: "销售发货清单",
  684. columnProp: "relatedOrderLineNo",
  685. headerAlign: "center",
  686. align: "right",
  687. columnLabel: "销售订单行号",
  688. columnWidth: '100',
  689. columnHidden: false,
  690. columnImage: false,
  691. columnSortable: false,
  692. sortLv: 0,
  693. status: true,
  694. fixed: false
  695. },
  696. {
  697. userId: this.$store.state.user.name,
  698. functionId: this.functionId,
  699. serialNumber: '750001Table1PartNo',
  700. tableId: "750001Table1",
  701. tableName: "销售发货清单",
  702. columnProp: "partNo",
  703. headerAlign: "center",
  704. align: "left",
  705. columnLabel: "物料编码",
  706. columnWidth: '120',
  707. columnHidden: false,
  708. columnImage: false,
  709. columnSortable: false,
  710. sortLv: 0,
  711. status: true,
  712. fixed: false
  713. },
  714. {
  715. userId: this.$store.state.user.name,
  716. functionId: this.functionId,
  717. serialNumber: '750001Table1PartDesc',
  718. tableId: "750001Table1",
  719. tableName: "销售发货清单",
  720. columnProp: "partDesc",
  721. headerAlign: "center",
  722. align: "left",
  723. columnLabel: "物料名称",
  724. columnWidth: '200',
  725. columnHidden: false,
  726. columnImage: false,
  727. columnSortable: false,
  728. sortLv: 0,
  729. status: true,
  730. fixed: false
  731. },
  732. {
  733. userId: this.$store.state.user.name,
  734. functionId: this.functionId,
  735. serialNumber: '750001Table1OutBatchNo',
  736. tableId: "750001Table1",
  737. tableName: "销售发货清单",
  738. columnProp: "outBatchNo",
  739. headerAlign: "center",
  740. align: "left",
  741. columnLabel: "合约号",
  742. columnWidth: '100',
  743. columnHidden: false,
  744. columnImage: false,
  745. columnSortable: false,
  746. sortLv: 0,
  747. status: true,
  748. fixed: false
  749. },
  750. {
  751. userId: this.$store.state.user.name,
  752. functionId: this.functionId,
  753. serialNumber: '750001Table1OrderQty',
  754. tableId: "750001Table1",
  755. tableName: "销售发货清单",
  756. columnProp: "orderQty",
  757. headerAlign: "center",
  758. align: "right",
  759. columnLabel: "销售订单数量",
  760. columnWidth: '100',
  761. columnHidden: false,
  762. columnImage: false,
  763. columnSortable: false,
  764. sortLv: 0,
  765. status: true,
  766. fixed: false
  767. },
  768. {
  769. userId: this.$store.state.user.name,
  770. functionId: this.functionId,
  771. serialNumber: '750001Table1RequiredQty',
  772. tableId: "750001Table1",
  773. tableName: "销售发货清单",
  774. columnProp: "requiredQty",
  775. headerAlign: "center",
  776. align: "right",
  777. columnLabel: "要求发货数量",
  778. columnWidth: '100',
  779. columnHidden: false,
  780. columnImage: false,
  781. columnSortable: false,
  782. sortLv: 0,
  783. status: true,
  784. fixed: false
  785. },
  786. {
  787. userId: this.$store.state.user.name,
  788. functionId: this.functionId,
  789. serialNumber: '750001Table1AvailableStock',
  790. tableId: "750001Table1",
  791. tableName: "销售发货清单",
  792. columnProp: "availableStock",
  793. headerAlign: "center",
  794. align: "right",
  795. columnLabel: "可用库存",
  796. columnWidth: '100',
  797. columnHidden: false,
  798. columnImage: false,
  799. columnSortable: false,
  800. sortLv: 0,
  801. status: true,
  802. fixed: false
  803. },
  804. {
  805. userId: this.$store.state.user.name,
  806. functionId: this.functionId,
  807. serialNumber: '750001Table1RollQty',
  808. tableId: "750001Table1",
  809. tableName: "销售发货清单",
  810. columnProp: "rollQty",
  811. headerAlign: "center",
  812. align: "right",
  813. columnLabel: "已扫描数量",
  814. columnWidth: '100',
  815. columnHidden: false,
  816. columnImage: false,
  817. columnSortable: false,
  818. sortLv: 0,
  819. status: true,
  820. fixed: false
  821. },
  822. {
  823. userId: this.$store.state.user.name,
  824. functionId: this.functionId,
  825. serialNumber: '750001Table1UnScanQty',
  826. tableId: "750001Table1",
  827. tableName: "销售发货清单",
  828. columnProp: "unScanQty",
  829. headerAlign: "center",
  830. align: "right",
  831. columnLabel: "未扫描数量",
  832. columnWidth: '100',
  833. columnHidden: false,
  834. columnImage: false,
  835. columnSortable: false,
  836. sortLv: 0,
  837. status: true,
  838. fixed: false
  839. },
  840. {
  841. userId: this.$store.state.user.name,
  842. functionId: this.functionId,
  843. serialNumber: '750001Table1Unit',
  844. tableId: "750001Table1",
  845. tableName: "销售发货清单",
  846. columnProp: "unit",
  847. headerAlign: "center",
  848. align: "left",
  849. columnLabel: "单位",
  850. columnWidth: '80',
  851. columnHidden: false,
  852. columnImage: false,
  853. columnSortable: false,
  854. sortLv: 0,
  855. status: true,
  856. fixed: false
  857. },
  858. ],
  859. exportName: '销售出库单'+this.dayjs().format('YYYYMMDDHHmmss'),
  860. }
  861. },
  862. /*组件*/
  863. components: {
  864. boxing,
  865. pallet
  866. },
  867. mounted() {
  868. this.$nextTick(() => {
  869. this.calculateTableHeight();
  870. window.addEventListener('resize', this.calculateTableHeight);
  871. })
  872. },
  873. beforeDestroy() {
  874. window.removeEventListener('resize', this.calculateTableHeight);
  875. },
  876. methods: {
  877. // 计算表格高度
  878. calculateTableHeight() {
  879. this.$nextTick(() => {
  880. const windowHeight = window.innerHeight;
  881. // 根据搜索条件展开状态动态计算
  882. const headerHeight = this.searchExpanded ? 220 : 152;
  883. this.tableHeight = (windowHeight - headerHeight - 162) / 2;
  884. this.height = this.tableHeight - 51;
  885. });
  886. },
  887. // 切换搜索展开/收起
  888. toggleSearchExpand() {
  889. this.searchExpanded = !this.searchExpanded;
  890. this.calculateTableHeight();
  891. },
  892. getMainData(){
  893. this.dataListLoading = true
  894. this.searchData.limit = this.pageSize
  895. this.searchData.page = this.pageIndex
  896. this.searchData.orderStatus = this.searchData.orderStatusList.join(',')
  897. searchOutboundNotificationWithDetailByPage(this.searchData).then(({data}) => {
  898. if (data.code === 0) {
  899. this.mainDataList = data.page.list
  900. this.totalPage = data.page.totalCount
  901. //判断是否全部存在数据
  902. if (this.mainDataList && this.mainDataList.length > 0) {
  903. //设置选中行
  904. this.$refs.mainTable.setCurrentRow(this.mainDataList[0])
  905. this.changeData(this.mainDataList[0])
  906. } else {
  907. this.changeData(null)
  908. }
  909. }
  910. this.dataListLoading = false
  911. }).catch(() => {
  912. this.dataListLoading = false
  913. })
  914. },
  915. tabClick(tab, event){
  916. this.refreshCurrentTabTable()
  917. },
  918. // 每页数
  919. sizeChangeHandle (val) {
  920. this.pageSize = val
  921. this.pageIndex = 1
  922. this.getMainData()
  923. },
  924. // 当前页
  925. currentChangeHandle (val) {
  926. this.pageIndex = val
  927. this.getMainData()
  928. },
  929. changeData(row){
  930. this.currentRow=JSON.parse(JSON.stringify(row))
  931. this.refreshCurrentTabTable ();
  932. },
  933. refreshCurrentTabTable(){
  934. if (this.currentRow === '' || this.currentRow === null) {
  935. this.currentRow = {
  936. site: '',
  937. buNo: '',
  938. supplierNo: ''
  939. }
  940. }
  941. if(this.activeName==='boxing'){
  942. this.refreshBoxingTable();
  943. }
  944. if(this.activeName==='pallet'){
  945. this.refreshPalletTable();
  946. }
  947. if(this.activeName==='rollDetail'){
  948. this.refreshRollsTable();
  949. }
  950. if(this.activeName==='cases'){
  951. this.refreshCasesTable();
  952. }
  953. },
  954. async exportExcel() {
  955. this.searchData.limit = -1
  956. this.searchData.page = 1
  957. excel.exportTable({
  958. url: "/boxForNotification/searchOutboundNotificationWithDetail",
  959. columnMapping: this.columnArray1,//可以直接用table,不需要的列就剔除
  960. mergeSetting: [],//需要合并的列
  961. params: this.searchData,
  962. fileName: this.exportName+".xlsx",
  963. rowFetcher: res => res.data.rows,
  964. columnFormatter: [],
  965. dropColumns: [],//需要剔除的列,例如dropColumns: ["netWeight"],即剔除净重列
  966. });
  967. },
  968. refreshBoxingTable(){
  969. // 检查是否有有效的当前行数据
  970. if (!this.currentRow || !this.currentRow.orderNo) {
  971. return;
  972. }
  973. this.$nextTick(() => {
  974. if (!this.$refs.boxing) {
  975. return;
  976. }
  977. let inData={
  978. site: this.currentRow.site,
  979. buNo: this.currentRow.buNo,
  980. orderNo: this.currentRow.orderNo,
  981. saleOrderNo: this.currentRow.relatedOrderNo || '', // 销售订单号,用于生成箱号
  982. boxType: this.currentRow.orderType,
  983. height: this.height,
  984. orderStatus: this.currentRow.orderStatus
  985. }
  986. this.$refs.boxing.init(inData)
  987. })
  988. },
  989. refreshPalletTable(){
  990. this.$nextTick(() => {
  991. // 检查组件引用是否存在
  992. if (!this.$refs.pallet) {
  993. return;
  994. }
  995. // 检查 init 方法是否存在且是函数
  996. if (typeof this.$refs.pallet.init !== 'function') {
  997. return;
  998. }
  999. // 准备初始化数据,即使没有选中行也要初始化组件
  1000. let inData={
  1001. site: this.currentRow ? this.currentRow.site : '',
  1002. buNo: this.currentRow ? this.currentRow.buNo : '',
  1003. orderNo: this.currentRow ? this.currentRow.orderNo : '',
  1004. palletType: this.currentRow ? this.currentRow.orderType : '',
  1005. height: this.height,
  1006. orderStatus: this.currentRow ? this.currentRow.orderStatus : ''
  1007. }
  1008. this.$refs.pallet.init(inData)
  1009. })
  1010. },
  1011. refreshRollsTable(){
  1012. let templateData = {
  1013. site: this.currentRow.site,
  1014. buNo: this.currentRow.buNo,
  1015. orderNo: this.currentRow.orderNo,
  1016. }
  1017. searchRollForOrderNo(templateData).then(({data}) => {
  1018. this.rollList = data.rows
  1019. })
  1020. },
  1021. // ===== 盒清单相关方法 =====
  1022. refreshCasesTable(){
  1023. let templateData = {
  1024. site: this.currentRow.site,
  1025. buNo: this.currentRow.buNo,
  1026. notifyNo: this.currentRow.orderNo,
  1027. }
  1028. searchSoReceiveCasesData(templateData).then(({data}) => {
  1029. this.casesList = data.rows || []
  1030. // 更新统计数据 - 从列表第一条记录中获取
  1031. if (data.rows && data.rows.length > 0) {
  1032. const firstRecord = data.rows[0]
  1033. this.casesStatistics.boxCountCases = firstRecord.boxCountCases || 0
  1034. this.casesStatistics.boxCountRolls = firstRecord.boxCountRolls || 0
  1035. this.casesStatistics.totalQty = firstRecord.totalQty || 0
  1036. } else {
  1037. this.casesStatistics.boxCountCases = 0
  1038. this.casesStatistics.boxCountRolls = 0
  1039. this.casesStatistics.totalQty = 0
  1040. }
  1041. })
  1042. },
  1043. openCaseDialog(){
  1044. if(!this.currentRow || !this.currentRow.orderNo){
  1045. this.$message.warning('请先选择一条出库单记录')
  1046. return
  1047. }
  1048. this.caseDialogVisible = true
  1049. this.resetCaseForm()
  1050. // 对话框打开后自动聚焦到卷标签输入框
  1051. this.$nextTick(() => {
  1052. this.$refs.rollNoInput.focus()
  1053. })
  1054. },
  1055. resetCaseForm(){
  1056. this.caseForm = {
  1057. casesNo: '',
  1058. rollNo: '',
  1059. site: this.currentRow.site,
  1060. buNo: this.currentRow.buNo,
  1061. notifyNo: this.currentRow.orderNo,
  1062. partNo: ''
  1063. }
  1064. this.caseRollList = []
  1065. this.selectedCaseRolls = []
  1066. this.updateCaseStatistics()
  1067. },
  1068. async scanCaseRoll(){
  1069. // 校验必填项
  1070. if(!this.caseForm.rollNo){
  1071. this.$message.warning('请扫描卷标签')
  1072. return
  1073. }
  1074. // 将卷标签值赋给盒标签(casesNo = rollNo)
  1075. this.caseForm.casesNo = this.caseForm.rollNo
  1076. // 从当前行获取物料编码
  1077. let partNo = this.currentRow.partNo || ''
  1078. this.caseForm.partNo = partNo
  1079. try {
  1080. const {data} = await validateAndScanCaseRoll(this.caseForm)
  1081. if(data && data.code === 0){
  1082. // 后端现在返回的是集合,需要遍历所有记录
  1083. const rollList = data.rollInfo || []
  1084. if(rollList.length === 0){
  1085. this.$message.warning('未查询到卷数据')
  1086. this.caseForm.rollNo = ''
  1087. this.$refs.rollNoInput.focus()
  1088. return
  1089. }
  1090. // 检查卷标签是否重复(根据 site 和 rollNo)
  1091. const duplicateRolls = []
  1092. const newRolls = []
  1093. rollList.forEach(rollInfo => {
  1094. // 检查当前列表中是否已存在相同 site 和 rollNo 的记录
  1095. const isDuplicate = this.caseRollList.some(item =>
  1096. item.site === this.caseForm.site && item.rollNo === rollInfo.rollNo
  1097. )
  1098. if (isDuplicate) {
  1099. duplicateRolls.push(rollInfo.rollNo)
  1100. } else {
  1101. newRolls.push(rollInfo)
  1102. }
  1103. })
  1104. // 如果有重复的卷标签,提示用户
  1105. if (duplicateRolls.length > 0) {
  1106. this.$message.warning(`以下卷标签已存在,不能重复添加:${duplicateRolls.join(', ')}`)
  1107. }
  1108. // 只添加不重复的卷到列表最前面(后扫描的在上面)
  1109. newRolls.forEach(rollInfo => {
  1110. this.caseRollList.unshift({
  1111. casesNo: this.caseForm.casesNo,
  1112. rollNo: rollInfo.rollNo,
  1113. rollQty: rollInfo.rollQty,
  1114. partNo: rollInfo.partNo,
  1115. partDesc: rollInfo.partDesc,
  1116. batchNo: rollInfo.batchNo,
  1117. notifyNo: this.caseForm.notifyNo,
  1118. site: this.caseForm.site,
  1119. buNo: this.caseForm.buNo
  1120. })
  1121. })
  1122. // 更新统计信息
  1123. this.updateCaseStatistics()
  1124. // 重置输入框,准备下一次扫描
  1125. this.caseForm.casesNo = ''
  1126. this.caseForm.rollNo = ''
  1127. // 光标回到卷标签输入框,继续扫描
  1128. this.$nextTick(() => {
  1129. this.$refs.rollNoInput.focus()
  1130. })
  1131. // 提示添加成功(仅显示实际添加的记录数)
  1132. if (newRolls.length > 0) {
  1133. this.$message.success(`扫描成功,添加了 ${newRolls.length} 条记录`)
  1134. }
  1135. } else {
  1136. this.$message.error(data.msg || '扫描失败')
  1137. }
  1138. } catch (error) {
  1139. this.$message.error(error.msg || '扫描失败,请检查')
  1140. // 清空卷标签输入框
  1141. this.caseForm.rollNo = ''
  1142. this.$refs.rollNoInput.focus()
  1143. }
  1144. },
  1145. updateCaseStatistics(){
  1146. // 盒数量 = 去重的盒标签数量
  1147. const uniqueCases = new Set(this.caseRollList.map(item => item.casesNo))
  1148. this.caseStatistics.casesCount = uniqueCases.size
  1149. // 卷数量 = 列表行数
  1150. this.caseStatistics.rollCount = this.caseRollList.length
  1151. // 物料总数 = 所有行的卷数量求和
  1152. this.caseStatistics.totalQty = this.caseRollList.reduce((sum, item) => {
  1153. return sum + (parseFloat(item.rollQty) || 0)
  1154. }, 0)
  1155. },
  1156. // 从扫描列表中删除某一行
  1157. deleteRollFromList(index){
  1158. this.$confirm('确定删除这条扫描记录吗?', '提示', {
  1159. confirmButtonText: '确定',
  1160. cancelButtonText: '取消',
  1161. type: 'warning'
  1162. }).then(() => {
  1163. this.caseRollList.splice(index, 1)
  1164. this.updateCaseStatistics()
  1165. this.$message.success('删除成功')
  1166. }).catch(() => {})
  1167. },
  1168. async applyCaseScan(){
  1169. if(this.caseRollList.length === 0){
  1170. this.$message.warning('请先扫描卷标签')
  1171. return
  1172. }
  1173. // 校验数量
  1174. if(!await this.validateCaseQty()){
  1175. return
  1176. }
  1177. // 应用:保存但不关闭对话框,重置输入框、计数和列表
  1178. this.saveCaseData(false)
  1179. },
  1180. async saveCaseScan(){
  1181. if(this.caseRollList.length === 0){
  1182. this.$message.warning('请先扫描卷标签')
  1183. return
  1184. }
  1185. // 校验数量
  1186. if(!await this.validateCaseQty()){
  1187. return
  1188. }
  1189. // 保存:保存后关闭对话框
  1190. this.saveCaseData(true)
  1191. },
  1192. // 校验盒清单数量不能超过要求发货数量
  1193. async validateCaseQty(){
  1194. // 获取当前主信息行的要求发货数量
  1195. const requiredQty = parseFloat(this.currentRow.requiredQty) || 0
  1196. if(requiredQty === 0){
  1197. this.$message.warning('要求发货数量为0,无需装箱')
  1198. return false
  1199. }
  1200. // 计算新扫描的数据总量
  1201. const newScanQty = this.caseRollList.reduce((sum, item) => {
  1202. return sum + (parseFloat(item.rollQty) || 0)
  1203. }, 0)
  1204. // 查询已保存的盒清单数据,计算已装箱的总数量
  1205. try {
  1206. let templateData = {
  1207. site: this.currentRow.site,
  1208. buNo: this.currentRow.buNo,
  1209. notifyNo: this.currentRow.orderNo,
  1210. }
  1211. const {data} = await searchSoReceiveCasesData(templateData)
  1212. const existingQty = (data.rows || []).reduce((sum, item) => {
  1213. // 只统计相同物料的数量
  1214. if(item.partNo === this.currentRow.partNo){
  1215. return sum + (parseFloat(item.rollQty) || 0)
  1216. }
  1217. return sum
  1218. }, 0)
  1219. // 总数量 = 已装箱数量 + 新扫描数量
  1220. const totalQty = existingQty + newScanQty
  1221. if(totalQty > requiredQty){
  1222. this.$message.error(`装箱数量超出限制!要求发货数量:${requiredQty},本次扫描:${newScanQty},总计:${totalQty}`)
  1223. return false
  1224. }
  1225. return true
  1226. } catch (error) {
  1227. this.$message.error('校验数量失败,请重试')
  1228. return false
  1229. }
  1230. },
  1231. async saveCaseData(closeDialog){
  1232. try {
  1233. const {data} = await saveCaseRollList(this.caseRollList)
  1234. if(data && data.code === 0){
  1235. this.$message.success('保存成功')
  1236. if(closeDialog){
  1237. // 关闭对话框
  1238. this.closeCaseDialog()
  1239. } else {
  1240. // 应用:重置表单继续扫描
  1241. this.resetCaseForm()
  1242. this.$nextTick(() => {
  1243. this.$refs.caseNoInput.focus()
  1244. })
  1245. }
  1246. // 刷新盒清单列表
  1247. this.refreshCasesTable()
  1248. } else {
  1249. this.$message.error(data.msg || '保存失败')
  1250. }
  1251. } catch (error) {
  1252. this.$message.error(error.msg || '保存失败')
  1253. }
  1254. },
  1255. closeCaseDialog(){
  1256. this.caseDialogVisible = false
  1257. this.resetCaseForm()
  1258. },
  1259. handleCaseSelectionChange(selection){
  1260. this.selectedCaseRecords = selection
  1261. },
  1262. // 装盒对话框中卷标签选择变化
  1263. handleCaseRollSelectionChange(selection){
  1264. this.selectedCaseRolls = selection
  1265. },
  1266. // 打印选中的卷标签
  1267. async printCaseRolls(){
  1268. if(this.selectedCaseRolls.length === 0){
  1269. this.$message.warning('请先选择要打印的卷标签')
  1270. return
  1271. }
  1272. this.printLoading = true
  1273. try {
  1274. // 1. 获取 LODOP 打印控件
  1275. const LODOP = getLodop()
  1276. if (!LODOP) {
  1277. this.$message.error('无法连接到打印控件,请确保已安装并启动 CLodop!')
  1278. this.printLoading = false
  1279. return
  1280. }
  1281. // 2. 获取默认打印机
  1282. const printerCount = LODOP.GET_PRINTER_COUNT()
  1283. if (printerCount <= 0) {
  1284. this.$message.error('未检测到打印机,请确保已安装并连接打印机!')
  1285. this.printLoading = false
  1286. return
  1287. }
  1288. // 3. 循环调用存储过程获取打印参数并打印
  1289. for (const rollItem of this.selectedCaseRolls) {
  1290. const params = {
  1291. site: this.currentRow.site,
  1292. buNo: this.currentRow.buNo,
  1293. menuID: this.$route.meta.menuId,
  1294. relatedOrderNo: this.currentRow.orderNo,
  1295. relatedOrderLineNo: this.currentRow.relatedOrderLineNo || '',
  1296. documentNo: this.currentRow.orderNo,
  1297. partNo: rollItem.partNo,
  1298. labelNo: '',
  1299. rollNo: rollItem.rollNo
  1300. }
  1301. const {data: printData} = await callUspPartLabelTemplate(params)
  1302. if (printData && printData.code === 0 && printData.row) {
  1303. const labelData = printData.row
  1304. // 初始化打印任务
  1305. LODOP.PRINT_INIT('卷标签打印_' + rollItem.rollNo)
  1306. LODOP.SET_PRINT_MODE("PRINT_NOCOLLATE", true)
  1307. // 根据 labelNo 调用不同的打印方法
  1308. if (labelData.labelNo === 'A001') {
  1309. await this.printLabelA001(LODOP, labelData, false)
  1310. } else if (labelData.labelNo === 'A002') {
  1311. this.printLabelA002(LODOP, labelData, false)
  1312. } else if (labelData.labelNo === 'A003') {
  1313. this.printLabelA003(LODOP, labelData, false)
  1314. } else if (labelData.labelNo === 'A004') {
  1315. this.printLabelA004(LODOP, labelData, false)
  1316. } else {
  1317. console.warn(`未知的标签模板:${labelData.labelNo},跳过该标签`)
  1318. continue
  1319. }
  1320. // 执行打印
  1321. LODOP.PRINT()
  1322. console.log(`标签已发送打印, 卷号: ${rollItem.rollNo}`)
  1323. } else {
  1324. console.warn(`获取卷号 ${rollItem.rollNo} 的打印参数失败`)
  1325. }
  1326. }
  1327. this.$message.success('打印任务已发送!')
  1328. } catch (error) {
  1329. console.error('打印标签失败:', error)
  1330. this.$message.error('打印标签失败: ' + (error.message || '请重试'))
  1331. } finally {
  1332. this.printLoading = false
  1333. }
  1334. },
  1335. // 打印选中的盒清单卷标签
  1336. async printSelectedCases(){
  1337. if(this.selectedCaseRecords.length === 0){
  1338. this.$message.warning('请先选择要打印的记录')
  1339. return
  1340. }
  1341. this.printCasesLoading = true
  1342. try {
  1343. // 1. 获取 LODOP 打印控件
  1344. const LODOP = getLodop()
  1345. if (!LODOP) {
  1346. this.$message.error('无法连接到打印控件,请确保已安装并启动 CLodop!')
  1347. this.printCasesLoading = false
  1348. return
  1349. }
  1350. // 2. 获取默认打印机
  1351. const printerCount = LODOP.GET_PRINTER_COUNT()
  1352. if (printerCount <= 0) {
  1353. this.$message.error('未检测到打印机,请确保已安装并连接打印机!')
  1354. this.printCasesLoading = false
  1355. return
  1356. }
  1357. // 3. 循环调用存储过程获取打印参数并打印
  1358. for (const caseRecord of this.selectedCaseRecords) {
  1359. const params = {
  1360. site: this.currentRow.site,
  1361. buNo: this.currentRow.buNo,
  1362. menuID: this.$route.meta.menuId,
  1363. relatedOrderNo: this.currentRow.orderNo,
  1364. relatedOrderLineNo: this.currentRow.relatedOrderLineNo || '',
  1365. documentNo: this.currentRow.orderNo,
  1366. partNo: caseRecord.partNo,
  1367. labelNo: '',
  1368. rollNo: caseRecord.rollNo
  1369. }
  1370. const {data: printData} = await callUspPartLabelTemplate(params)
  1371. if (printData && printData.code === 0 && printData.row) {
  1372. const labelData = printData.row
  1373. // 初始化打印任务
  1374. LODOP.PRINT_INIT('卷标签打印_' + caseRecord.rollNo)
  1375. LODOP.SET_PRINT_MODE("PRINT_NOCOLLATE", true)
  1376. // 根据 labelNo 调用不同的打印方法
  1377. if (labelData.labelNo === 'A001') {
  1378. await this.printLabelA001(LODOP, labelData, false)
  1379. } else if (labelData.labelNo === 'A002') {
  1380. this.printLabelA002(LODOP, labelData, false)
  1381. } else if (labelData.labelNo === 'A003') {
  1382. this.printLabelA003(LODOP, labelData, false)
  1383. } else if (labelData.labelNo === 'A004') {
  1384. this.printLabelA004(LODOP, labelData, false)
  1385. } else {
  1386. console.warn(`未知的标签模板:${labelData.labelNo},跳过该标签`)
  1387. continue
  1388. }
  1389. // 执行打印
  1390. LODOP.PRINT()
  1391. console.log(`标签已发送打印, 卷号: ${caseRecord.rollNo}`)
  1392. } else {
  1393. console.warn(`获取卷号 ${caseRecord.rollNo} 的打印参数失败`)
  1394. }
  1395. }
  1396. this.$message.success('打印任务已发送!')
  1397. } catch (error) {
  1398. console.error('打印标签失败:', error)
  1399. this.$message.error('打印标签失败: ' + (error.message || '请重试'))
  1400. } finally {
  1401. this.printCasesLoading = false
  1402. }
  1403. },
  1404. async deleteCaseRecord(){
  1405. if(this.selectedCaseRecords.length === 0){
  1406. this.$message.warning('请先选择要删除的记录')
  1407. return
  1408. }
  1409. this.$confirm('确定删除选中的记录吗?删除后将恢复库存卷的装盒状态', '提示', {
  1410. confirmButtonText: '确定',
  1411. cancelButtonText: '取消',
  1412. type: 'warning'
  1413. }).then(async () => {
  1414. try {
  1415. for(let record of this.selectedCaseRecords){
  1416. await deleteSoReceiveCasesData({
  1417. id: record.id,
  1418. site: record.site,
  1419. buNo: record.buNo
  1420. })
  1421. }
  1422. this.$message.success('删除成功')
  1423. this.refreshCasesTable()
  1424. } catch (error) {
  1425. this.$message.error(error.msg || '删除失败')
  1426. }
  1427. }).catch(() => {})
  1428. },
  1429. // 处理完成操作
  1430. async handleComplete(row){
  1431. this.$confirm('是否包装完成?完成后将创建检验任务', '提示', {
  1432. confirmButtonText: '是',
  1433. cancelButtonText: '否',
  1434. type: 'warning'
  1435. }).then(async () => {
  1436. try {
  1437. const {data} = await this.$http({
  1438. url: this.$http.adornUrl('/boxForNotification/completePacking'),
  1439. method: 'post',
  1440. data: this.$http.adornData({
  1441. site: row.site,
  1442. buNo: row.buNo,
  1443. orderNo: row.orderNo,
  1444. partNo: row.partNo,
  1445. customerId: row.customerId,
  1446. relatedOrderNo: row.relatedOrderNo,
  1447. relatedOrderLineNo: row.relatedOrderLineNo,
  1448. requiredQty: row.requiredQty,
  1449. orderQty: row.orderQty
  1450. })
  1451. })
  1452. if(data && data.code === 0){
  1453. this.$message.success('包装完成,检验任务已创建')
  1454. // 刷新列表
  1455. this.getMainData()
  1456. } else {
  1457. this.$message.error(data.msg || '操作失败')
  1458. }
  1459. } catch (error) {
  1460. this.$message.error(error.msg || '操作失败,请重试')
  1461. }
  1462. }).catch(() => {
  1463. // 用户点击了"否",不做任何操作
  1464. })
  1465. },
  1466. },
  1467. created() {
  1468. //查询报表的类型
  1469. this.getMainData();
  1470. },
  1471. }
  1472. </script>
  1473. <!--当前页面的标签样式-->
  1474. <style scoped lang="scss">
  1475. /deep/ .customer-tab .el-tabs__content {
  1476. padding: 5px !important;
  1477. }
  1478. /* 主容器 */
  1479. .mod-config {
  1480. padding: 8px;
  1481. background: #f5f7fa;
  1482. min-height: 100%;
  1483. }
  1484. /* 搜索卡片样式 */
  1485. .search-card {
  1486. margin-bottom: 8px;
  1487. border-radius: 8px;
  1488. overflow: hidden;
  1489. transition: all 0.3s ease;
  1490. }
  1491. .search-card:hover {
  1492. box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
  1493. }
  1494. .search-card /deep/ .el-card__header {
  1495. padding: 5px 20px;
  1496. background: linear-gradient(135deg, #9ac3d0 20%, #b6c7dd 80%);
  1497. border-bottom: none;
  1498. }
  1499. .search-header {
  1500. display: flex;
  1501. justify-content: space-between;
  1502. align-items: center;
  1503. }
  1504. .header-left {
  1505. display: flex;
  1506. align-items: center;
  1507. color: #fff;
  1508. }
  1509. .header-left i {
  1510. font-size: 16px;
  1511. margin-right: 8px;
  1512. }
  1513. .header-title {
  1514. font-size: 14px;
  1515. font-weight: 600;
  1516. letter-spacing: 0.5px;
  1517. }
  1518. .header-right {
  1519. color: #fff;
  1520. }
  1521. .collapse-btn {
  1522. color: #fff;
  1523. font-weight: 500;
  1524. transition: all 0.3s ease;
  1525. }
  1526. .collapse-btn:hover {
  1527. color: #f0f0f0;
  1528. transform: translateY(-1px);
  1529. }
  1530. .collapse-btn i {
  1531. transition: transform 0.3s ease;
  1532. }
  1533. /* 搜索表单样式 */
  1534. .search-form {
  1535. padding: 6px 0;
  1536. min-height: 0;
  1537. }
  1538. /* 卡片主体样式 */
  1539. .search-card /deep/ .el-card__body {
  1540. padding: 10px;
  1541. transition: all 0.3s ease;
  1542. }
  1543. /* 收起时的样式 */
  1544. .search-card.collapsed /deep/ .el-card__body {
  1545. padding: 10px 20px;
  1546. }
  1547. .search-form /deep/ .el-form-item {
  1548. margin-bottom: 12px;
  1549. }
  1550. .search-form /deep/ .el-form-item__label {
  1551. font-weight: 500;
  1552. color: #606266;
  1553. padding-bottom: 4px;
  1554. }
  1555. .search-form /deep/ .el-input__inner,
  1556. .search-form /deep/ .el-textarea__inner {
  1557. border-radius: 6px;
  1558. border: 1px solid #DCDFE6;
  1559. transition: all 0.3s ease;
  1560. }
  1561. .search-form /deep/ .el-input__inner:focus,
  1562. .search-form /deep/ .el-textarea__inner:focus {
  1563. border-color: #9ac3d0;
  1564. box-shadow: 0 0 0 2px rgba(154, 195, 208, 0.1);
  1565. }
  1566. .search-form /deep/ .el-select {
  1567. width: 100%;
  1568. }
  1569. /* 操作按钮区域 */
  1570. .search-actions {
  1571. display: flex;
  1572. justify-content: space-between;
  1573. align-items: center;
  1574. padding: 8px 0 2px 0;
  1575. }
  1576. /* 展开时显示上边框 */
  1577. .search-card:not(.collapsed) .search-actions {
  1578. border-top: 1px solid #f0f0f0;
  1579. margin-top: 6px;
  1580. }
  1581. /* 收起时不显示上边框和上边距 */
  1582. .search-card.collapsed .search-actions {
  1583. border-top: none;
  1584. margin-top: 0;
  1585. padding-top: 0;
  1586. }
  1587. .action-left {
  1588. display: flex;
  1589. gap: 8px;
  1590. align-items: center;
  1591. }
  1592. .search-actions .el-button {
  1593. border-radius: 4px;
  1594. padding: 5px 10px;
  1595. font-size: 12px;
  1596. font-weight: 500;
  1597. transition: all 0.3s ease;
  1598. }
  1599. .search-actions .el-button:hover {
  1600. transform: translateY(-2px);
  1601. box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  1602. }
  1603. .search-actions .el-button--primary {
  1604. background: #60aeff;
  1605. border-color: #60aeff;
  1606. }
  1607. .search-actions .el-button--primary:hover {
  1608. background: #7dbdff;
  1609. border-color: #7dbdff;
  1610. }
  1611. /* 区域标题栏样式 */
  1612. .section-title-bar {
  1613. display: flex;
  1614. align-items: center;
  1615. padding: 8px 12px;
  1616. background: linear-gradient(135deg, #f5f7fa 0%, #e4e7eb 100%);
  1617. border-radius: 4px;
  1618. margin-bottom: 8px;
  1619. font-size: 14px;
  1620. font-weight: 600;
  1621. color: #303133;
  1622. }
  1623. .section-title-bar i {
  1624. font-size: 16px;
  1625. margin-right: 8px;
  1626. color: #409eff;
  1627. }
  1628. .section-title-bar .total-count {
  1629. margin-left: 10px;
  1630. font-size: 12px;
  1631. font-weight: normal;
  1632. color: #909399;
  1633. }
  1634. /* 表格样式 */
  1635. /deep/ .el-table th {
  1636. background-color: #f5f7fa;
  1637. color: #303133;
  1638. font-weight: 600;
  1639. }
  1640. /deep/ .el-table tr:hover > td {
  1641. background-color: #f5f7fa !important;
  1642. }
  1643. /* 响应式设计 */
  1644. @media (max-width: 1200px) {
  1645. .search-actions {
  1646. flex-direction: column;
  1647. gap: 10px;
  1648. }
  1649. .action-left {
  1650. width: 100%;
  1651. justify-content: center;
  1652. }
  1653. }
  1654. </style>