فهرست منبع

Merge branch 'master' of http://110.41.163.243:9980/kd-aiot/kd-aiot-frontend-wt into dengfei

695593266@qq.com 1 ماه پیش
والد
کامیت
a63a2cd60a

+ 110 - 0
src/directives/tableScrollSync.js

@@ -0,0 +1,110 @@
+// 工具函数:获取 .el-table__body-wrapper 下的滚动容器
+function getBodyWrapper(el) {
+  return el.querySelector('.el-table__body-wrapper');
+}
+
+// 创建滚动条并绑定事件,返回清理函数
+function setupScrollSync(el) {
+  const table = el; // el 就是容器元素
+  if (!table) return null;
+
+  const outerWidth = table.offsetWidth;
+  // 取第一个内部 table 的宽度作为内容宽度
+  const innerTable = table.querySelector('table');
+  const contentWidth = innerTable ? innerTable.offsetWidth : outerWidth;
+
+  const bodyWrapper = getBodyWrapper(table);
+  if (!bodyWrapper) {
+    console.warn('未找到 .el-table__body-wrapper,无法创建滚动同步');
+    return null;
+  }
+  // 隐藏原生横向滚动条,但保留纵向滚动条
+  bodyWrapper.style.overflowX = 'hidden';
+  bodyWrapper.style.overflowY = 'auto';
+  
+  // 创建自定义样式标签来隐藏横向滚动条
+  const styleId = 'v-scroll-sync-hide-x-scrollbar';
+  let styleEl = document.getElementById(styleId);
+  if (!styleEl) {
+    styleEl = document.createElement('style');
+    styleEl.id = styleId;
+    styleEl.textContent = `
+      .el-table__body-wrapper.v-scroll-sync-hide-x::-webkit-scrollbar {
+        width: 6px;
+        height: 0;
+      }
+      .el-table__body-wrapper.v-scroll-sync-hide-x::-webkit-scrollbar-track {
+        background: transparent;
+      }
+      .el-table__body-wrapper.v-scroll-sync-hide-x::-webkit-scrollbar-thumb {
+        background: #d9d9d9;
+        border-radius: 3px;
+      }
+    `;
+    document.head.appendChild(styleEl);
+  }
+  bodyWrapper.classList.add('v-scroll-sync-hide-x');
+  // 避免重复创建
+  const existingDiv = table.querySelector('.v-scroll-sync-bar');
+  if (existingDiv) existingDiv.remove();
+
+  const div = document.createElement('div');
+  div.className = 'v-scroll-sync-bar';
+  div.style.width = outerWidth + 'px';
+  div.style.height = '12px';
+  div.style.overflowX = 'auto';
+  div.innerHTML = `<div style="width:${contentWidth}px; height:1px;"></div>`;
+
+  const onScroll = () => {
+    bodyWrapper.scrollLeft = div.scrollLeft;
+  };
+  div.addEventListener('scroll', onScroll);
+
+  const tableContainer = table.querySelector('.el-table');
+
+  // 在tableContainer后面插入div(作为兄弟元素)
+  tableContainer.insertAdjacentElement('afterend', div);
+
+  // table.appendChild(div);
+
+  // 返回清理函数和事件引用
+  return {
+    div,
+    bodyWrapper,
+    handler: onScroll,
+    destroy() {
+      div.removeEventListener('scroll', onScroll);
+      if (div.parentNode) div.parentNode.removeChild(div);
+      // 移除添加的class
+      bodyWrapper.classList.remove('v-scroll-sync-hide-x');
+    }
+  };
+}
+
+// Vue 2 自定义指令
+const tableScrollSync = {
+  bind(el) {
+    // bind 时可能未插入文档,先不做操作,统一在 inserted 中处理
+    el._scrollSyncData = null;
+  },
+  inserted(el) {
+    // 元素插入 DOM 后初始化
+    el._scrollSyncData = setupScrollSync(el);
+  },
+  update(el) {
+    // 当表格数据变化导致内容宽度改变时(如切换分页、动态列),重新初始化
+    if (el._scrollSyncData) {
+      el._scrollSyncData.destroy();
+    }
+    el._scrollSyncData = setupScrollSync(el);
+  },
+  unbind(el) {
+    // 指令解绑时销毁
+    if (el._scrollSyncData) {
+      el._scrollSyncData.destroy();
+      el._scrollSyncData = null;
+    }
+  }
+};
+
+export default tableScrollSync;

+ 3 - 0
src/main.js

@@ -42,6 +42,9 @@ Vue.component('seekPage', seekPage);
 import clickOnce from './utils/clickOnce.js';
 Vue.directive('click-once', clickOnce);
 
+import tableScrollSync from '@/directives/tableScrollSync';
+Vue.directive('table-scroll-sync', tableScrollSync);
+
 import Tooltip from './utils/tooltip'; // 引入封装的工具
 Vue.prototype.$tooltip = Tooltip;
 Vue.use(elTableInfiniteScroll);

+ 29 - 16
src/views/bpm/handleTask/components/purchaseOrder/invoice/receiptInfo.vue

@@ -78,20 +78,24 @@
       </el-row>
     </el-form>
     <div class="fontSize" style="margin-bottom: 12px">物品清单</div>
-    <ele-pro-table
-      ref="table"
-      :needPage="false"
-      :columns="columns"
-      :datasource="detailData.productList"
-      :cache-key="cacheKeyUrl"
-      @columns-change="handleColumnChange"
-      row-key="id"
-      max-height="500px"
-    >
-      <template v-slot:technicalDrawings="{ row }">
-        <fileMain v-model="row.receiveFiles" type="view"></fileMain>
-      </template>
-    </ele-pro-table>
+    <div v-table-scroll-sync>
+      <ele-pro-table
+        ref="table"
+        :needPage="false"
+        :columns="columns"
+        :datasource="detailData.productList"
+        :cache-key="cacheKeyUrl"
+        @columns-change="handleColumnChange"
+        row-key="id"
+        max-height="500px"
+        show-summary
+        :summary-method="getSummaries"
+      >
+        <template v-slot:technicalDrawings="{ row }">
+          <fileMain v-model="row.receiveFiles" type="view"></fileMain>
+        </template>
+      </ele-pro-table>
+    </div>
     <!-- </el-card> -->
   </div>
 </template>
@@ -103,6 +107,7 @@
   import { levelList,pricingWayList } from '@/enum/dict.js';
   import { parameterGetByCode } from '@/api/main/index.js';
   import tabMixins from '@/mixins/tableColumnsMixin';
+  import { getSummaries } from '@/utils/util.js';
   // import fileMain from '@/components/addDoc/index.vue';
   export default {
     // components: { fileMain },
@@ -162,7 +167,7 @@
 
         const list = [
           {
-            width: 45,
+            width: 50,
             type: 'index',
             columnKey: 'index',
             align: 'center',
@@ -514,7 +519,15 @@
         this.isHidePrice = res.value;
       });
     },
-    methods: {}
+    methods: {
+      getSummaries(param) {
+        return getSummaries(
+          param,
+          ['purchaseCount'],
+          ' '
+        );
+      },
+    }
   };
 </script>
 

+ 19 - 1
src/views/bpm/handleTask/components/saleOrder/saleReturnGoods/detailDialog.vue

@@ -437,7 +437,8 @@
             slot: 'remark',
             align: 'center'
           }
-        ]
+        ],
+        tempData: []
       };
     },
     props: {
@@ -517,6 +518,23 @@
             item['packingWeight'] = item.receiveTotalWeight;
             item['quantity'] = item.totalCount;
           });
+          const tempData = this.form.productList.filter((item) => item.packageId);
+          // 合并 productCode + orderNo + colorKey 相同的项
+          const mergedList = [];
+          tempData.forEach((item) => {
+            const key = `${item.productCode}_${item.orderNo}_${item.colorKey}`;
+            const existIndex = mergedList.findIndex(
+              (m) => `${m.productCode}_${m.orderNo}_${m.colorKey}` === key
+            );
+            if (existIndex > -1) {
+              mergedList[existIndex].quantity += item.quantity;
+              mergedList[existIndex].packingWeight += item.packingWeight;
+            } else {
+              mergedList.push({ ...item });
+            }
+          });
+          this.tempData = mergedList;
+
           this.$nextTick(() => {
             if (this.taskDefinitionKey == 'storemanApprove') {
               this.activeComp = 'inoutBound';