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.

920 lines
26 KiB

3 months ago
3 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
3 months ago
  1. <template>
  2. <div class="packing-detail-tab">
  3. <el-table
  4. :data="dataListBoxes"
  5. :height="height"
  6. border
  7. v-loading="dataListLoading"
  8. style="width: 100%;"
  9. :expand-row-keys="expandedBoxRows"
  10. :row-key="getBoxRowKey"
  11. @expand-change="handleBoxExpand"
  12. show-summary
  13. :summary-method="getSummaries">
  14. <el-table-column type="expand">
  15. <template slot-scope="props">
  16. <!-- 加载状态 -->
  17. <div v-if="props.row.loading" class="expand-loading">
  18. <i class="el-icon-loading"></i>
  19. <span>正在加载明细数据...</span>
  20. </div>
  21. <!-- 明细内容区域 -->
  22. <div v-else class="expand-detail-container">
  23. <!-- 明细表格 -->
  24. <el-table
  25. v-if="props.row.palletDetails && props.row.palletDetails.length > 0"
  26. :data="props.row.palletDetails"
  27. :max-height="300"
  28. size="mini"
  29. stripe
  30. class="expand-detail-table">
  31. <el-table-column
  32. v-for="(item,index) in columnList3" :key="index"
  33. :sortable="item.columnSortable"
  34. :prop="item.columnProp"
  35. :header-align="item.headerAlign"
  36. :show-overflow-tooltip="item.showOverflowTooltip"
  37. :align="item.align"
  38. :min-width="item.columnWidth"
  39. :label="item.columnLabel">
  40. <template slot-scope="scope">
  41. <span v-if="!item.columnHidden">
  42. {{ formatDetailValue(scope.row[item.columnProp], item.columnProp) }}
  43. </span>
  44. <span v-if="item.columnImage">
  45. <img :src="scope.row[item.columnProp]" style="width: 100px; height: 80px"/>
  46. </span>
  47. </template>
  48. </el-table-column>
  49. <!-- 明细操作列 -->
  50. <el-table-column
  51. label="操作"
  52. width="120"
  53. align="center"
  54. fixed="right"
  55. v-if="showActions">
  56. <template slot-scope="scope">
  57. <a type="text" size="small" @click="handleEditDetail(scope.row, props.row)">修改</a>
  58. <a type="text" size="small" @click="handleDeleteDetail(scope.row, props.row)">删除</a>
  59. </template>
  60. </el-table-column>
  61. </el-table>
  62. <!-- 空数据状态 -->
  63. <div v-else class="expand-empty-state">
  64. <i class="el-icon-box"></i>
  65. <p>暂无明细数据</p>
  66. <span>该栈板下暂时没有装箱明细信息</span>
  67. </div>
  68. </div>
  69. </template>
  70. </el-table-column>
  71. <el-table-column
  72. v-for="(item,index) in columnListBoxes" :key="index"
  73. :sortable="item.columnSortable"
  74. :prop="item.columnProp"
  75. :header-align="item.headerAlign"
  76. :show-overflow-tooltip="item.showOverflowTooltip"
  77. :align="item.align"
  78. :fixed="item.fixed==''?false:item.fixed"
  79. :min-width="item.columnWidth"
  80. :label="item.columnLabel">
  81. <template slot-scope="scope">
  82. <span v-if="!item.columnHidden"> {{ scope.row[item.columnProp] }}</span>
  83. <span v-if="item.columnImage"><img :src="scope.row[item.columnProp]"
  84. style="width: 100px; height: 80px"/></span>
  85. </template>
  86. </el-table-column>
  87. <!-- 主表格操作列 -->
  88. <el-table-column
  89. label="操作"
  90. width="120"
  91. align="center"
  92. fixed="right"
  93. v-if="showActions">
  94. <template slot-scope="scope">
  95. <a type="text" size="small" @click="handleEditBox(scope.row)">修改</a>
  96. <a type="text" size="small" @click="handleDeleteBox(scope.row)">删除</a>
  97. </template>
  98. </el-table-column>
  99. </el-table>
  100. <!-- 修改箱信息弹窗 -->
  101. <el-dialog
  102. title="修改箱信息"
  103. :visible.sync="editBoxDialogVisible"
  104. width="200px"
  105. :close-on-click-modal="false">
  106. <el-form :model="editBoxForm" ref="editBoxForm" label-position="top" label-width="100px">
  107. <el-row :gutter="20">
  108. <el-col :span="24">
  109. <el-form-item label="箱数" prop="box_qty">
  110. <el-input v-model="editBoxForm.box_qty" :min="1" :precision="0" style="width: 100%"></el-input>
  111. </el-form-item>
  112. </el-col>
  113. <el-col :span="24">
  114. <el-form-item label="毛重" prop="grossWeight">
  115. <el-input v-model="editBoxForm.grossWeight" :min="0" :precision="2" style="width: 100%"></el-input>
  116. </el-form-item>
  117. </el-col>
  118. <el-col :span="24">
  119. <el-form-item label="净重" prop="netWeight">
  120. <el-input v-model="editBoxForm.netWeight" :min="0" :precision="2" style="width: 100%"></el-input>
  121. </el-form-item>
  122. </el-col>
  123. </el-row>
  124. </el-form>
  125. <div slot="footer" class="dialog-footer">
  126. <el-button @click="editBoxDialogVisible = false">取消</el-button>
  127. <el-button type="primary" @click="submitEditBox" >确定</el-button>
  128. </div>
  129. </el-dialog>
  130. <!-- 修改明细弹窗 -->
  131. <el-dialog
  132. title="修改明细信息"
  133. :visible.sync="editDetailDialogVisible"
  134. width="400px"
  135. :close-on-click-modal="false">
  136. <el-form :model="editDetailForm" ref="editDetailForm" label-position="top" label-width="100px">
  137. <el-row :gutter="20">
  138. <el-col :span="12">
  139. <el-form-item label="PO" prop="poNo">
  140. <el-input v-model="editDetailForm.poNo" disabled></el-input>
  141. </el-form-item>
  142. </el-col>
  143. <el-col :span="12">
  144. <el-form-item label="PN" prop="pn">
  145. <el-input v-model="editDetailForm.pn" disabled></el-input>
  146. </el-form-item>
  147. </el-col>
  148. <el-col :span="12">
  149. <el-form-item label="数量" prop="qty">
  150. <el-input v-model="editDetailForm.qty" style="width: 100%"></el-input>
  151. </el-form-item>
  152. </el-col>
  153. <el-col :span="12">
  154. <el-form-item label="Rolls" prop="rolls">
  155. <el-input v-model="editDetailForm.rolls" style="width: 100%"></el-input>
  156. </el-form-item>
  157. </el-col>
  158. </el-row>
  159. </el-form>
  160. <div slot="footer" class="dialog-footer">
  161. <el-button @click="editDetailDialogVisible = false">取消</el-button>
  162. <el-button type="primary" @click="submitEditDetail" >确定</el-button>
  163. </div>
  164. </el-dialog>
  165. </div>
  166. </template>
  167. <script>
  168. import { selectBoxList, searchCoDelPalletDataNew, updateBoxInfo, deleteBoxInfo, updateDetailInfo, deleteDetailInfo } from "@/api/ecss/ecss.js"
  169. export default {
  170. name: "PackingDetailTab",
  171. props: {
  172. currentRow: {
  173. type: Object,
  174. default: () => ({})
  175. },
  176. height: {
  177. type: Number,
  178. default: 200
  179. },
  180. showActions: {
  181. type: Boolean,
  182. default: true
  183. }
  184. },
  185. data() {
  186. return {
  187. dataListBoxes: [], // 箱数据列表
  188. expandedBoxRows: [], // 展开的行
  189. dataListLoading: false,
  190. // 修改箱信息弹窗相关
  191. editBoxDialogVisible: false,
  192. editBoxForm: {
  193. item_no: '',
  194. box_qty: 1,
  195. grossWeight: 0,
  196. netWeight: 0
  197. },
  198. editBoxSubmitting: false,
  199. currentEditBox: null,
  200. // 修改明细弹窗相关
  201. editDetailDialogVisible: false,
  202. editDetailForm: {
  203. itemNo: '',
  204. poNo: '',
  205. pn: '',
  206. qty: 1,
  207. rolls: 0
  208. },
  209. editDetailSubmitting: false,
  210. currentEditDetail: null,
  211. currentEditBoxForDetail: null,
  212. // 装箱明细列定义
  213. columnList3: [
  214. {
  215. userId: this.$store.state.user.name,
  216. functionId: 801002,
  217. serialNumber: '801002Table3ItemNo',
  218. tableId: "801002Table3",
  219. tableName: "装箱明细",
  220. columnProp: "itemNo",
  221. headerAlign: "center",
  222. align: "right",
  223. columnLabel: "序号",
  224. columnHidden: false,
  225. columnImage: false,
  226. columnSortable: false,
  227. sortLv: 0,
  228. status: true,
  229. fixed: '',
  230. columnWidth: 40
  231. },
  232. {
  233. userId: this.$store.state.user.name,
  234. functionId: 801002,
  235. serialNumber: '801002Table3PoNo',
  236. tableId: "801002Table3",
  237. tableName: "装箱明细",
  238. columnProp: "poNo",
  239. headerAlign: "center",
  240. align: "left",
  241. columnLabel: "PO",
  242. columnHidden: false,
  243. columnImage: false,
  244. columnSortable: false,
  245. sortLv: 0,
  246. status: true,
  247. fixed: '',
  248. columnWidth: 100
  249. },
  250. {
  251. userId: this.$store.state.user.name,
  252. functionId: 801002,
  253. serialNumber: '801002Table3PN',
  254. tableId: "801002Table3",
  255. tableName: "装箱明细",
  256. columnProp: "pn",
  257. headerAlign: "center",
  258. align: "left",
  259. columnLabel: "PN",
  260. columnHidden: false,
  261. columnImage: false,
  262. columnSortable: false,
  263. sortLv: 0,
  264. status: true,
  265. fixed: '',
  266. columnWidth: 100
  267. },
  268. {
  269. userId: this.$store.state.user.name,
  270. functionId: 801002,
  271. serialNumber: '801002Table3Qty',
  272. tableId: "801002Table3",
  273. tableName: "装箱明细",
  274. columnProp: "qty",
  275. headerAlign: "center",
  276. align: "right",
  277. columnLabel: "数量",
  278. columnHidden: false,
  279. columnImage: false,
  280. columnSortable: false,
  281. sortLv: 0,
  282. status: true,
  283. fixed: '',
  284. columnWidth: 50
  285. },
  286. {
  287. userId: this.$store.state.user.name,
  288. functionId: 801002,
  289. serialNumber: '801002Table3Rolls',
  290. tableId: "801002Table3",
  291. tableName: "装箱明细",
  292. columnProp: "rolls",
  293. headerAlign: "center",
  294. align: "right",
  295. columnLabel: "Rolls",
  296. columnHidden: false,
  297. columnImage: false,
  298. columnSortable: false,
  299. sortLv: 0,
  300. status: true,
  301. fixed: '',
  302. columnWidth: 50
  303. },
  304. ],
  305. // 箱数据列定义
  306. columnListBoxes: [
  307. {
  308. userId: this.$store.state.user.name,
  309. functionId: 801002,
  310. serialNumber: '801002Table3ItemNo',
  311. tableId: "801002Table3",
  312. tableName: "装箱明细",
  313. columnProp: "item_no",
  314. headerAlign: "center",
  315. align: "right",
  316. columnLabel: "序号",
  317. columnHidden: false,
  318. columnImage: false,
  319. columnSortable: false,
  320. sortLv: 0,
  321. status: true,
  322. fixed: '',
  323. columnWidth: 40
  324. },
  325. {
  326. userId: this.$store.state.user.name,
  327. functionId: 801002,
  328. serialNumber: '801002Table3BoxQty',
  329. tableId: "801002Table3",
  330. tableName: "装箱明细",
  331. columnProp: "box_qty",
  332. headerAlign: "center",
  333. align: "right",
  334. columnLabel: "箱数",
  335. columnHidden: false,
  336. columnImage: false,
  337. columnSortable: false,
  338. sortLv: 0,
  339. status: true,
  340. fixed: '',
  341. columnWidth: 50
  342. },
  343. {
  344. userId: this.$store.state.user.name,
  345. functionId: 801002,
  346. serialNumber: '801002TableGrossWeight',
  347. tableId: "801002Table3",
  348. tableName: "装箱明细",
  349. columnProp: "grossWeight",
  350. headerAlign: "center",
  351. align: "right",
  352. columnLabel: "毛重",
  353. columnHidden: false,
  354. columnImage: false,
  355. columnSortable: false,
  356. sortLv: 0,
  357. status: true,
  358. fixed: '',
  359. columnWidth: 50
  360. },
  361. {
  362. userId: this.$store.state.user.name,
  363. functionId: 801002,
  364. serialNumber: '801002TableNetWeight',
  365. tableId: "801002Table3",
  366. tableName: "装箱明细",
  367. columnProp: "netWeight",
  368. headerAlign: "center",
  369. align: "right",
  370. columnLabel: "净重",
  371. columnHidden: false,
  372. columnImage: false,
  373. columnSortable: false,
  374. sortLv: 0,
  375. status: true,
  376. fixed: '',
  377. columnWidth: 50
  378. },
  379. ]
  380. }
  381. },
  382. watch: {
  383. currentRow: {
  384. handler(newVal) {
  385. if (newVal && newVal.site) {
  386. this.loadBoxList();
  387. }
  388. },
  389. deep: true,
  390. immediate: true
  391. }
  392. },
  393. methods: {
  394. // 装箱明细相关方法
  395. loadBoxList() {
  396. if (!this.currentRow || !this.currentRow.site) {
  397. this.dataListBoxes = [];
  398. return;
  399. }
  400. // 清理之前的展开状态
  401. this.expandedBoxRows = [];
  402. this.dataListLoading = true;
  403. // 获取ecss_CoDelBoxList数据
  404. selectBoxList(this.currentRow).then(({data}) => {
  405. if (data && data.code == 0) {
  406. this.dataListBoxes = data.rows.map(row => ({
  407. ...row,
  408. palletDetails: [], // 初始化明细数据为空
  409. loading: false, // 初始化加载状态
  410. hadDetails: false // 初始化是否有明细标记
  411. }))
  412. } else {
  413. this.dataListBoxes = [];
  414. }
  415. }).catch(error => {
  416. console.error('加载箱数据失败:', error);
  417. this.dataListBoxes = [];
  418. }).finally(() => {
  419. this.dataListLoading = false;
  420. });
  421. },
  422. // 获取行的唯一标识
  423. getBoxRowKey(row) {
  424. // 使用多个字段组合确保唯一性
  425. return `${row.item_no || ''}_${row.palletRemark || ''}_${row.box_qty || ''}`;
  426. },
  427. // 处理行展开事件
  428. handleBoxExpand(row, expandedRows) {
  429. // 判断当前操作是展开还是收起
  430. const isExpanding = expandedRows.includes(row);
  431. if (isExpanding) {
  432. // 如果是展开操作,则展开所有行
  433. this.expandAll();
  434. } else {
  435. // 如果是收起操作,则收起所有行
  436. this.collapseAll();
  437. }
  438. },
  439. // 加载栈板明细数据
  440. loadPalletDetails(boxRow) {
  441. if (boxRow.palletDetails && boxRow.palletDetails.length > 0) {
  442. // 如果已经加载过,直接返回
  443. return;
  444. }
  445. // 设置加载状态
  446. this.$set(boxRow, 'loading', true);
  447. // 构造查询参数
  448. let detailParams = {
  449. site: this.currentRow.site,
  450. buNo: this.currentRow.buNo,
  451. delNo: this.currentRow.delNo,
  452. seqNo: boxRow.item_no,
  453. palletRemark: boxRow.palletRemark
  454. };
  455. // 调用API获取明细数据
  456. searchCoDelPalletDataNew(detailParams).then(({data}) => {
  457. if (data && data.code == 0) {
  458. // 将明细数据赋值给当前行
  459. this.$set(boxRow, 'palletDetails', data.rows);
  460. // 如果明细为空,且之前有明细数据,说明明细被删除了,需要检查box是否也应该被删除
  461. if (data.rows.length === 0 && boxRow.hadDetails) {
  462. // 延迟刷新列表,让后端有时间处理删除逻辑
  463. setTimeout(() => {
  464. this.loadBoxList();
  465. }, 500);
  466. }
  467. // 标记是否有过明细数据
  468. this.$set(boxRow, 'hadDetails', data.rows.length > 0);
  469. } else {
  470. this.$set(boxRow, 'palletDetails', []);
  471. this.$set(boxRow, 'hadDetails', false);
  472. }
  473. }).catch(error => {
  474. console.error('加载栈板明细数据失败:', error);
  475. this.$set(boxRow, 'palletDetails', []);
  476. this.$set(boxRow, 'hadDetails', false);
  477. }).finally(() => {
  478. // 清除加载状态
  479. this.$set(boxRow, 'loading', false);
  480. });
  481. },
  482. // 格式化明细值显示
  483. formatDetailValue(value, columnProp) {
  484. if (value === null || value === undefined || value === '') {
  485. return '-';
  486. }
  487. // 数字类型格式化
  488. if (columnProp === 'qty' || columnProp === 'rolls') {
  489. return parseInt(value).toLocaleString();
  490. }
  491. return value;
  492. },
  493. // 展开所有行
  494. expandAll() {
  495. // 获取所有行的key
  496. this.expandedBoxRows = this.dataListBoxes.map(row => this.getBoxRowKey(row));
  497. // 为每个行加载明细数据
  498. this.dataListBoxes.forEach(row => {
  499. this.loadPalletDetails(row);
  500. });
  501. },
  502. // 收起所有行
  503. collapseAll() {
  504. this.expandedBoxRows = [];
  505. },
  506. // 刷新数据的公共方法
  507. refresh() {
  508. this.loadBoxList();
  509. },
  510. /*
  511. * 删除逻辑说明
  512. * 1. 删除明细时
  513. * - 先删除明细数据
  514. * - 检查该明细所属的box是否还有其他明细
  515. * - 如果没有明细了自动删除对应的box
  516. *
  517. * 2. 删除box时
  518. * - 先检查是否有明细数据
  519. * - 如果有明细提示用户并同时删除所有明细和box
  520. * - 如果没有明细直接删除box
  521. */
  522. // 处理修改箱信息
  523. handleEditBox(boxRow) {
  524. this.currentEditBox = boxRow;
  525. this.editBoxForm.item_no = boxRow.item_no;
  526. this.editBoxForm.box_qty = boxRow.box_qty;
  527. this.editBoxForm.grossWeight = boxRow.grossWeight;
  528. this.editBoxForm.netWeight = boxRow.netWeight;
  529. this.editBoxDialogVisible = true;
  530. },
  531. // 处理删除箱信息
  532. handleDeleteBox(boxRow) {
  533. // 直接删除box及其所有明细,无需校验
  534. this.deleteBoxWithDetails(boxRow);
  535. },
  536. // 删除箱信息(包含明细)
  537. deleteBoxWithDetails(boxRow) {
  538. this.$confirm(`确定要删除序号为 ${boxRow.item_no} 的箱信息吗?删除后无法恢复!`, '警告', {
  539. confirmButtonText: '确定',
  540. cancelButtonText: '取消',
  541. type: 'warning'
  542. }).then(() => {
  543. // 构造删除参数
  544. const deleteParams = {
  545. site: this.currentRow.site,
  546. buNo: this.currentRow.buNo,
  547. delNo: this.currentRow.delNo,
  548. item_no: boxRow.item_no,
  549. palletRemark: boxRow.palletRemark
  550. };
  551. deleteBoxInfo(deleteParams).then(({data}) => {
  552. if (data && data.code === 0) {
  553. this.loadBoxList()
  554. this.$message({
  555. message: '操作成功',
  556. type: 'success',
  557. duration: 1500,
  558. onClose: () => {}
  559. })
  560. } else {
  561. this.$alert(data.msg, '错误', {
  562. confirmButtonText: '确定'
  563. })
  564. }
  565. })
  566. });
  567. },
  568. // 处理修改明细
  569. handleEditDetail(detailRow, boxRow) {
  570. this.currentEditDetail = detailRow;
  571. this.currentEditBoxForDetail = boxRow;
  572. this.editDetailForm.itemNo = detailRow.itemNo;
  573. this.editDetailForm.poNo = detailRow.poNo;
  574. this.editDetailForm.pn = detailRow.pn;
  575. this.editDetailForm.qty = detailRow.qty;
  576. this.editDetailForm.rolls = detailRow.rolls;
  577. this.editDetailDialogVisible = true;
  578. },
  579. // 提交修改箱信息
  580. submitEditBox() {
  581. this.$refs.editBoxForm.validate(valid => {
  582. if (valid) {
  583. this.editBoxSubmitting = true;
  584. // 构造更新参数
  585. const updateParams = {
  586. site: this.currentRow.site,
  587. buNo: this.currentRow.buNo,
  588. delNo: this.currentRow.delNo,
  589. item_no: this.currentEditBox.item_no,
  590. palletRemark: this.currentEditBox.palletRemark,
  591. box_qty: this.editBoxForm.box_qty,
  592. grossWeight: this.editBoxForm.grossWeight,
  593. netWeight: this.editBoxForm.netWeight,
  594. updateBy: this.$store.state.user.name
  595. };
  596. updateBoxInfo(updateParams).then(({ data }) => {
  597. if (data && data.code === 0) {
  598. this.editBoxDialogVisible = false;
  599. this.loadBoxList()
  600. this.$message({
  601. message: '操作成功',
  602. type: 'success',
  603. duration: 1500,
  604. onClose: () => {}
  605. })
  606. } else {
  607. this.$alert(data.msg, '错误', {
  608. confirmButtonText: '确定'
  609. })
  610. }
  611. });
  612. }
  613. });
  614. },
  615. // 提交修改明细
  616. submitEditDetail() {
  617. this.$refs.editDetailForm.validate(valid => {
  618. if (valid) {
  619. this.editDetailSubmitting = true;
  620. // 构造更新参数
  621. const updateParams = {
  622. site: this.currentRow.site,
  623. buNo: this.currentRow.buNo,
  624. delNo: this.currentRow.delNo,
  625. seqNo: this.currentEditDetail.seqNo,
  626. itemNo: this.currentEditDetail.itemNo,
  627. notifyDetailItemNo: this.currentEditDetail.notifyDetailItemNo,
  628. poNo: this.editDetailForm.poNo,
  629. pn: this.editDetailForm.pn,
  630. qty: this.editDetailForm.qty,
  631. oldQty: this.currentEditDetail.qty,
  632. rolls: this.editDetailForm.rolls,
  633. updateBy: this.$store.state.user.name
  634. };
  635. updateDetailInfo(updateParams).then(({ data }) => {
  636. if (data && data.code === 0) {
  637. this.editDetailDialogVisible = false;
  638. this.loadBoxList()
  639. this.$message({
  640. message: '操作成功',
  641. type: 'success',
  642. duration: 1500,
  643. onClose: () => {}
  644. })
  645. } else {
  646. this.$alert(data.msg, '错误', {
  647. confirmButtonText: '确定'
  648. })
  649. }
  650. });
  651. }
  652. });
  653. },
  654. // 删除明细
  655. handleDeleteDetail(detailRow, boxRow) {
  656. this.$confirm(`确定要删除这个明细信息吗?删除后无法恢复!`, '警告', {
  657. confirmButtonText: '确定',
  658. cancelButtonText: '取消',
  659. type: 'warning'
  660. }).then(() => {
  661. // 构造删除参数
  662. const deleteParams = {
  663. site: this.currentRow.site,
  664. buNo: this.currentRow.buNo,
  665. delNo: this.currentRow.delNo,
  666. seqNo: detailRow.seqNo,
  667. itemNo: detailRow.itemNo,
  668. notifyDetailItemNo: detailRow.notifyDetailItemNo,
  669. partNo: detailRow.part_no,
  670. qty: detailRow.qty
  671. };
  672. deleteDetailInfo(deleteParams).then(({data}) => {
  673. if (data && data.code === 0) {
  674. this.loadBoxList()
  675. this.$message({
  676. message: '操作成功',
  677. type: 'success',
  678. duration: 1500,
  679. onClose: () => {}
  680. })
  681. } else {
  682. this.$alert(data.msg, '错误', {
  683. confirmButtonText: '确定'
  684. })
  685. }
  686. })
  687. });
  688. },
  689. // 计算合计行数据
  690. getSummaries(param) {
  691. const { columns, data } = param;
  692. const sums = [];
  693. columns.forEach((column, index) => {
  694. if (index === 0) {
  695. // 第一列(展开列)显示"合计"
  696. sums[index] = '合计';
  697. return;
  698. }
  699. const values = data.map(item => Number(item[column.property]));
  700. // 根据列属性计算合计
  701. if (column.property === 'box_qty') {
  702. // 箱数合计
  703. const sum = values.reduce((prev, curr) => {
  704. const value = Number(curr);
  705. if (!isNaN(value)) {
  706. return prev + value;
  707. } else {
  708. return prev;
  709. }
  710. }, 0);
  711. sums[index] = sum;
  712. } else if (column.property === 'grossWeight') {
  713. // 毛重合计
  714. const sum = values.reduce((prev, curr) => {
  715. const value = Number(curr);
  716. if (!isNaN(value)) {
  717. return prev + value;
  718. } else {
  719. return prev;
  720. }
  721. }, 0);
  722. sums[index] = sum.toFixed(3);
  723. } else if (column.property === 'netWeight') {
  724. // 净重合计
  725. const sum = values.reduce((prev, curr) => {
  726. const value = Number(curr);
  727. if (!isNaN(value)) {
  728. return prev + value;
  729. } else {
  730. return prev;
  731. }
  732. }, 0);
  733. sums[index] = sum.toFixed(3);
  734. } else if (column.property === 'item_no') {
  735. // 序号列显示空
  736. sums[index] = '';
  737. } else {
  738. // 其他列显示空
  739. sums[index] = '';
  740. }
  741. });
  742. return sums;
  743. }
  744. }
  745. }
  746. </script>
  747. <style scoped>
  748. .packing-detail-tab {
  749. width: 100%;
  750. }
  751. /* 展开明细容器样式 */
  752. .expand-detail-container {
  753. background: #fafafa;
  754. border-radius: 6px;
  755. overflow: visible;
  756. box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
  757. }
  758. /* 加载状态样式 */
  759. .expand-loading {
  760. text-align: center;
  761. padding: 30px;
  762. color: #666;
  763. background: #fafafa;
  764. margin: 8px 16px;
  765. border-radius: 6px;
  766. }
  767. .expand-loading i {
  768. font-size: 18px;
  769. margin-right: 8px;
  770. color: #409eff;
  771. }
  772. /* 明细表格样式 */
  773. .expand-detail-table {
  774. margin: 0;
  775. border: none;
  776. }
  777. /deep/ .expand-detail-table .el-table__body-wrapper {
  778. overflow-y: auto;
  779. }
  780. /deep/ .expand-detail-table .el-table__header {
  781. background: #f8f9fa;
  782. }
  783. /deep/ .expand-detail-table .el-table__header th {
  784. background: #eef7f0;
  785. color: #333;
  786. font-weight: 500;
  787. border-bottom: 2px solid #e9ecef;
  788. }
  789. /deep/ .expand-detail-table .el-table__row:hover > td {
  790. background-color: #f0f9ff;
  791. }
  792. /deep/ .expand-detail-table .el-table__row.el-table__row--striped {
  793. background: #fbfcfd;
  794. }
  795. /deep/ .expand-detail-table .el-table__row.el-table__row--striped:hover > td {
  796. background-color: #f0f9ff;
  797. }
  798. /* 空数据状态样式 */
  799. .expand-empty-state {
  800. text-align: center;
  801. padding: 40px 20px;
  802. color: #999;
  803. }
  804. .expand-empty-state i {
  805. font-size: 48px;
  806. color: #ddd;
  807. margin-bottom: 12px;
  808. display: block;
  809. }
  810. .expand-empty-state p {
  811. font-size: 16px;
  812. margin: 0 0 8px 0;
  813. color: #666;
  814. }
  815. .expand-empty-state span {
  816. font-size: 13px;
  817. color: #999;
  818. }
  819. /* 响应式调整 */
  820. @media (max-width: 768px) {
  821. .expand-detail-container {
  822. margin: 8px 8px;
  823. padding: 6px;
  824. }
  825. }
  826. /* 确保主表格容器的滚动行为 */
  827. /deep/ .el-table__expanded-cell {
  828. padding: 0 !important;
  829. }
  830. /deep/ .el-table__expand-column .cell {
  831. padding: 0;
  832. }
  833. /* 确保表格滚动条正常显示 */
  834. /deep/ .el-table .el-table__body-wrapper {
  835. overflow-y: auto;
  836. }
  837. /deep/ .el-table__body-wrapper::-webkit-scrollbar {
  838. width: 6px;
  839. }
  840. /deep/ .el-table__body-wrapper::-webkit-scrollbar-track {
  841. background: #f1f1f1;
  842. border-radius: 3px;
  843. }
  844. /deep/ .el-table__body-wrapper::-webkit-scrollbar-thumb {
  845. background: #c1c1c1;
  846. border-radius: 3px;
  847. }
  848. /deep/ .el-table__body-wrapper::-webkit-scrollbar-thumb:hover {
  849. background: #a8a8a8;
  850. }
  851. </style>