4 Komitmen f5a1cce1bc ... 7598a1c059

Pembuat SHA1 Pesan Tanggal
  mlchen 7598a1c059 fix:5277【流程已办】【特瑞】增加发起人查询;还有关键字查询那里可以提示下都是哪些关键字,现在关键字输入发起人、任务名称都查不到数据 3 hari lalu
  liujt f8cd192d80 Merge branch 'master' of http://110.41.163.243:9980/kd-aiot/kd-aiot-frontend-wt 3 hari lalu
  liujt 15ed38e1f0 feat: 发票审批 3 hari lalu
  mlchen df249a58a6 fix:5279【销售订单-发货单】发货单列表返回销售订单的订单类型;新增发货单也显示订单类型,5278【入库管理】新增操作,填写信息后点击入库操作,提示入库来源收货单号不能为空,手动入库的不需要此限制 4 hari lalu

+ 45 - 4
src/BIZComponents/inventoryTableDetails.vue

@@ -149,6 +149,11 @@
         type: Boolean,
         default: false
       },
+      // 是否同时显示库存数量和可用数量
+      showStockCount: {
+        type: Boolean,
+        default: false
+      },
       //是否显示订单编码
       isOrderNo: {
         type: Boolean,
@@ -378,12 +383,20 @@
             isNone: this.quoteType === 2,
           },
           {
-            width: 160,
-            prop: 'availableCountBase',
+            width: 120,
+            prop: 'stockCountBase',
             label: '库存数量',
             showOverflowTooltip: true,
             align: 'center',
-            isNone: this.quoteType === 2,
+            isNone: this.quoteType === 2 || !this.showStockCount
+          },
+          {
+            width: 120,
+            prop: 'availableCountBase',
+            label: this.showStockCount ? '可用数量' : '库存数量',
+            showOverflowTooltip: true,
+            align: 'center',
+            isNone: this.quoteType === 2
           },
           {
             width: 200,
@@ -923,6 +936,25 @@
           .add(addDay, dateType)
           .format('YYYY-MM-DD');
       },
+      // 兼容未返回 stockCountBase 的旧库存接口
+      getStockCount(item) {
+        if (item.stockCountBase !== undefined && item.stockCountBase !== null) {
+          return Number(item.stockCountBase);
+        }
+        if (
+          item.measureQuantity !== undefined &&
+          item.measureQuantity !== null
+        ) {
+          return Number(item.measureQuantity);
+        }
+        return Number(item.availableCountBase || 0);
+      },
+      // 可用数量统一按库存余额扣减锁库数量计算
+      getAvailableStockCount(item) {
+        const availableCount =
+          this.getStockCount(item) - Number(item.lockQuantity || 0);
+        return Number(availableCount.toFixed(4));
+      },
       //修改回显
       async putTableValue(data) {
         let productList =
@@ -956,10 +988,19 @@
                                     (key) => (key.code + ',' + key.batchNo == item.productCode+','+item.batchNo)
                                   ) || {};
                 this.form.datasource;
+                if (this.showStockCount) {
+                  this.$set(
+                    this.form.datasource[index],
+                    'stockCountBase',
+                    this.getStockCount(find)
+                  );
+                }
                 this.$set(
                   this.form.datasource[index],
                   'availableCountBase',
-                  find.availableCountBase
+                  this.showStockCount
+                    ? this.getAvailableStockCount(find)
+                    : find.availableCountBase
                 );
               });
           }

+ 78 - 0
src/BIZComponents/setAllValue.vue

@@ -0,0 +1,78 @@
+<template>
+  <el-button
+    size="small"
+    type="primary"
+    class="ele-btn-icon"
+    style="margin-left: 5px"
+    :disabled="disabled"
+    @click="show = true"
+    >批量设置{{ title }}
+
+    <ele-modal
+      custom-class="ele-dialog-form long-dialog-form"
+      :centered="true"
+      :visible.sync="show"
+      :close-on-click-modal="false"
+      width="600px"
+      :maxable="true"
+      :resizable="true"
+      :append-to-body="true"
+    >
+      <div v-if="inputType === 'number'">
+        {{ title }}:
+        <el-input v-model="value" placeholder="请输入" type="number" />
+      </div>
+      <div v-else>
+        {{ title }}:
+        <el-date-picker
+          v-model="value"
+          type="date"
+          placeholder="选择日期"
+          value-format="yyyy-MM-dd"
+        >
+        </el-date-picker>
+      </div>
+      <div slot="footer" class="footer">
+        <el-button type="primary" @click="warehouseChangeAll">确认</el-button>
+        <el-button @click="show = false">返回</el-button>
+      </div>
+    </ele-modal>
+  </el-button>
+</template>
+<script>
+  export default {
+    components: {},
+    data() {
+      return {
+        show: false,
+        value: ''
+      };
+    },
+    props: {
+      disabled: {
+        default: true,
+        type: Boolean
+      },
+      valueKey: '',
+      inputType: '',
+      title: ''
+    },
+    created() {},
+    computed: {},
+    methods: {
+      warehouseChangeAll() {
+        if (!this.value) {
+          return this.$message.error(this.title + '不能为空!');
+        }
+        this.$emit('success', { key: this.valueKey, value: this.value });
+        this.cancel();
+      },
+      cancel() {
+        this.value = '';
+        this.show = false;
+      }
+    }
+  };
+</script>
+
+<style scoped lang="scss"></style>

+ 5 - 2
src/api/afterSales/index.js

@@ -30,7 +30,10 @@ export async function getWarehouseOutStock(params) {
     params
   });
   if (res.data.code == 0) {
-    return res.data.data;
+    const data = res.data.data;
+    return data && typeof data === 'object'
+      ? data.availableCountBase || 0
+      : data;
   }
   return Promise.reject(new Error(res.data.message));
 }
@@ -62,4 +65,4 @@ export async function contactDetail(id) {
     return res.data.data;
   }
   return Promise.reject(new Error(res.data.message));
-}
+}

+ 5 - 2
src/api/bpm/components/saleManage/saleorder.js

@@ -30,7 +30,10 @@ export async function getWarehouseOutStock(params) {
     params
   });
   if (res.data.code == 0) {
-    return res.data.data;
+    const data = res.data.data;
+    return data && typeof data === 'object'
+      ? data.availableCountBase || 0
+      : data;
   }
   return Promise.reject(new Error(res.data.message));
 }
@@ -456,4 +459,4 @@ export async function getPunchSlipOrderInfo(id) {
     return res.data.data;
   }
   return Promise.reject(new Error(res.data.message));
-}
+}

+ 281 - 0
src/api/wms/index.js

@@ -0,0 +1,281 @@
+import request from '@/utils/request';
+
+/**
+ * 获取产品所有库存
+ */
+export async function getInventoryTotalAPI(data) {
+  if (data.length == 0) {
+    return []
+  }
+  const res = await request.post(`wms/stocktwo/getInventoryTotal`, data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+export async function getSubPage(data) {
+  const res = await request.get('/main/categoryLevel/getSubPage', {
+    params: data
+  });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+export async function saveOrUpdate(data) {
+  const res = await request.post('/main/categoryLevel/saveOrUpdate', data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 根据父级id查分类树
+export async function getTreeByPid(parentId) {
+  const res = await request.get(`/main/categoryLevel/getTreeByPid/${parentId}`);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 查询所有物品分类
+export async function allCategoryLevel() {
+  const res = await request.get(`/main/categoryLevel/allCategoryLevel`);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 根据type查分类树组
+export async function getTreeByGroup(data) {
+  const res = await request.get(`/main/categoryLevel/getProduceTreeByPid`, {
+    params: data
+  });
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 根据类型查分类树
+export async function getTreeByType(type) {
+  const res = await request.get(`/main/categoryLevel/getTreeByType/${type}`);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 删除分类
+export async function deleteCategory(id) {
+  const res = await request.get(`/main/categoryLevel/delete/${id}`);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+//根据ID查询分类详情系信息
+export async function getInfoById(id) {
+  const res = await request.get(`/main/categoryLevel/getById/${id}`);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 批次明细
+
+export async function getBatchDetails(data) {
+  const res = await request.get(`/wms/outin/getBatchDetails`, {
+    params: data
+  });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+export async function getDetailById(data) {
+  const res = await request.post(`/wms/outin/getDetailById`, data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 产品列表
+ */
+export async function getProductList(params) {
+  const res = await request.get(`/main/category/getList`, {
+    params
+  });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+//库存台账-库存明细-物料维度
+
+export async function getMaterielDetails(params) {
+  const res = await request.get(`/wms/outin/getMaterielDetails/page`, {
+    params
+  });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+//库存台账-库存明细
+
+export async function getInventoryDetails(params) {
+  const res = await request.get(`/wms/outInDetailRecordTwo/page`, {
+    params
+  });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 查询仓库下拉列表
+export async function getWarehouseList() {
+  const res = await request.post(`/wms/warehouse/getWarehouseList`, {});
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 查询出入库详情
+//sourceBizNo
+export async function getInfoBySourceBizNoAPI(sourceBizNo) {
+  const res = await request.get(
+    `/wms/outintwo/getInfoBySourceBizNo/${sourceBizNo}`, {}
+  );
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.resolve({});
+}
+// 查询出入库详情
+//sourceBizNo
+export async function getInfoBySourceBizNoAll(sourceBizNo, data = {}) {
+  const res = await request.get(
+    `/wms/outintwo/getInfoBySourceBizNoAll/${sourceBizNo}`, {params: data}
+  );
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.resolve({});
+}
+
+export async function getByIdSplit(sourceBizNo, data = {}) {
+  const res = await request.get(
+    `/eom/saleordersendrecord/getByIdSplit/${sourceBizNo}`, {params: data}
+  );
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.resolve({});
+}
+
+// 仓库树
+export async function getWarehouseTrees(data) {
+  const res = await request.get('/wms/warehouse/getTrees', {
+    params: data
+  });
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+// 物品维度台账列表
+export async function getOutindetailtwoList(params) {
+  const res = await request.get(`/wms/outindetailtwo/page`, {
+    params
+  });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+// 批次维度台账列表
+export async function getBatchList(params) {
+  const res = await request.get(`/wms/outindetailtwo/batchPage`, {
+    params
+  });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+// 获取物料维度台账列表
+export async function getMaterialList(params) {
+  const res = await request.get(`/wms/materialDetail/page`, {
+    params
+  });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+// 包装维度台账列表
+export async function getPackingList(params) {
+  const res = await request.get(`/wms/outInDetailRecordTwo/page`, {
+    params
+  });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+export async function getCategoryPackageDisposition (data){
+  const res = await request.post(
+    '/main/categoryPackageDisposition/list',
+    data
+  );
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 库内调拨列表
+  export async function getAllotApplyPage(data) {
+    const res = await request.get(`/wms/allotApply/page`, {
+      params: data
+    });
+    if (res.data.code == 0) {
+      return res.data.data;
+    }
+    return Promise.reject(new Error(res.data.message));
+  }
+
+ // 库内调拨详情列表
+  export async function getAllotDetailList(data) {
+    const res = await request.get(`/wms/allotDetail/list`, {
+      params: data
+    });
+    if (res.data.code == 0) {
+      return res.data.data;
+    }
+    return Promise.reject(new Error(res.data.message));
+  }
+
+  // 库内调拨详情
+  export async function getAllotDetail(id) {
+    const res = await request.get(`/wms/allotApply/getById/${id}`);
+    if (res.data.code == 0) {
+      return res.data.data;
+    }
+    return Promise.reject(new Error(res.data.message));
+  }

+ 16 - 6
src/views/bpm/done/index.vue

@@ -9,17 +9,26 @@
           @submit.native.prevent
         >
           <el-row :gutter="15">
-            <el-col v-bind="styleResponsive ? { lg: 4, md: 12 } : { span: 4 }">
+            <el-col v-bind="styleResponsive ? { xl: 4, lg: 6, md: 12 } : { span: 4 }">
               <el-form-item label="关键字:" prop="keyword">
                 <el-input clearable v-model.trim="params.keyword"></el-input>
               </el-form-item>
             </el-col>
-            <el-col v-bind="styleResponsive ? { lg: 4, md: 12 } : { span: 4 }">
+            <el-col v-bind="styleResponsive ? { xl: 4, lg: 6, md: 12 } : { span: 4 }">
               <el-form-item label="流程名:" prop="name">
                 <el-input clearable v-model.trim="params.name"></el-input>
               </el-form-item>
             </el-col>
-            <el-col v-bind="styleResponsive ? { lg: 4, md: 12 } : { span: 4 }">
+            <el-col v-bind="styleResponsive ? { xl: 4, lg: 6, md: 12 } : { span: 4 }">
+              <el-form-item label="流程发起人:" prop="startUserName">
+                <el-input
+                  v-model.trim="params.startUserName"
+                  clearable
+                  maxlength="64"
+                ></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col v-bind="styleResponsive ? { xl: 4, lg: 6, md: 12 } : { span: 4 }">
               <el-form-item label="结果:" prop="result">
                 <!-- <el-select
                   v-model="params.status"
@@ -41,7 +50,7 @@
                 </DictSelection>
               </el-form-item>
             </el-col>
-            <el-col v-bind="styleResponsive ? { lg: 6, md: 12 } : { span: 6 }">
+            <el-col v-bind="styleResponsive ? { xl: 5, lg: 12, md: 12 } : { span: 5 }">
               <el-form-item label="创建时间:" prop="createTime">
                 <el-date-picker
                   v-model="params.createTime"
@@ -57,7 +66,7 @@
             </el-col>
             <el-col
               style="display: flex; justify-content: flex-end"
-              v-bind="styleResponsive ? { lg: 4, md: 12 } : { span: 4 }"
+              v-bind="styleResponsive ? { xl: 3, lg: 12, md: 12 } : { span: 3 }"
             >
               <div class="ele-form-actions">
                 <el-button
@@ -125,7 +134,8 @@
   // 默认表单数据
   const defaultParams = {
     status: '',
-    name: ''
+    name: '',
+    startUserName: ''
   };
   export default {
     name: 'BpmDoneTask',

+ 13 - 2
src/views/bpm/handleTask/components/financialManage/invoiceManage/components/addOrEditDialog.vue

@@ -226,7 +226,7 @@
       ref="table"
       @setPrice="setPrice"
     ></table-info> -->
-    <div style="margin-top: 20px; margin-bottom: 20px;">
+    <div v-if="form.sourceType != 99" style="margin-top: 20px; margin-bottom: 20px;">
         <headerTitle title="收款计划信息"></headerTitle>
         <!-- <el-form ref="form" :model="tableForm"> -->
           <ele-pro-table
@@ -281,9 +281,15 @@
       ref="table"
     ></table-info> -->
    <table-info-new
+      v-if="form.sourceType != 99"
       dialogType="view"
       ref="tableInfoNewRef"
     ></table-info-new>
+    <table-info
+      v-else
+      dialogType="view"
+      ref="tableInfoNoOrderRef"
+    ></table-info>
   </div>
 </template>
 <script>
@@ -511,7 +517,12 @@
       async getInfo(id) {
         this.form = await invoiceApplyInfoV2API(id);
         this.$nextTick(() => {
-          this.$refs.tableInfoNewRef && this.$refs.tableInfoNewRef.putValue(this.form);
+          // 根据来源类型设置数据源:99 用 tableInfo(setValue),非 99 用 tableInfoNew(putValue)
+          if (this.form.sourceType == 99) {
+            this.$refs.tableInfoNoOrderRef?.setValue(this.form);
+          } else {
+            this.$refs.tableInfoRef?.putValue(this.form);
+          }
         })
       },
       //获取分类管理中的数据

+ 503 - 0
src/views/bpm/handleTask/components/financialManage/invoiceManage/components/commodityPriceListDialog.vue

@@ -0,0 +1,503 @@
+<template>
+  <ele-modal
+    title="选择商品"
+    custom-class="ele-dialog-form long-dialog-form"
+    :visible.sync="visible"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    append-to-body
+    width="70%"
+    :maxable="true"
+    :resizable="true"
+  >
+    <div class="ele-body">
+      <el-card shadow="never" v-loading="loading">
+        <ele-split-layout
+          width="210px"
+          allow-collapse
+          :right-style="{ overflow: 'hidden' }"
+        >
+          <div>
+            <div class="ele-border-lighter sys-organization-list">
+              <AssetTree
+                @handleNodeClick="handleNodeClick"
+                id="1789827921908150274"
+                :isIds="false"
+                :isFirstRefreshTable="false"
+                ref="treeList"
+              />
+            </div>
+          </div>
+          <template v-slot:content>
+            <div
+              class="ele-border-lighter form-content"
+              v-loading="loading"
+            ></div>
+            <PriceSearch @search="reload"> </PriceSearch>
+            <!-- 数据表格 -->
+            <ele-pro-table
+              ref="table"
+              :columns="columns"
+              :datasource="datasource"
+              height="calc(100vh - 500px)"
+              tool-class="ele-toolbar-form"
+              :page-size="20"
+              :selection.sync="selection"
+              @cell-click="cellClick"
+              row-key="id"
+              v-if="visible"
+            >
+              <!-- 展开列 -->
+              <template v-slot:expand="{ row }">
+                <el-form
+                  v-for="item in row.goodsPriceList"
+                  :key="item.id"
+                  label-width="100px"
+                  class="el-form-box"
+                >
+                  <el-row class="price-info">
+                    <el-col :span="3"
+                      ><el-form-item label="价格类型:">
+                        {{ getDictValue('商品价格类型', item.priceType) }}
+                      </el-form-item></el-col
+                    >
+                    <el-col :span="3"
+                      ><el-form-item label="含税单价:">{{
+                        item.unitPrice
+                      }}</el-form-item></el-col
+                    >
+                    <el-col :span="3"
+                      ><el-form-item label="税率:"
+                        >{{ item.taxRate }}%</el-form-item
+                      ></el-col
+                    >
+                    <el-col :span="3"
+                      ><el-form-item label="不含税单价:">{{
+                        item.excludeTaxPrice
+                      }}</el-form-item></el-col
+                    >
+
+                    <el-col :span="3">
+                      <el-form-item label="">
+                        <el-link
+                          @click="openHistoricalprice(item)"
+                          type="primary"
+                          :underline="false"
+                          icon="el-icon-sort-edit"
+                        >
+                          历史价格
+                        </el-link>
+                      </el-form-item>
+                    </el-col>
+                  </el-row>
+                </el-form>
+              </template>
+              <!-- 列详情 -->
+              <template v-slot:goodsName="{ row }">
+                <el-link
+                  type="primary"
+                  :underline="false"
+                  @click="openEdit('view', row)"
+                >
+                  {{ row.goodsName }}</el-link
+                >
+              </template>
+
+              <!-- 商品图片 -->
+              <template v-slot:imagesPaths="{ row }">
+                <el-image
+                  v-if="row.imagesPaths"
+                  style="width: 50px; height: 50px"
+                  fit="cover"
+                  :src="
+                    locationUrl +
+                    '/api/main/file/getFile?objectName=' +
+                    row.imagesPaths.split(',')[0]
+                  "
+                  :preview-src-list="
+                    row.imagesPaths
+                      .split(',')
+                      .map(
+                        (url) =>
+                          locationUrl +
+                          '/api/main/file/getFile?objectName=' +
+                          url
+                      )
+                  "
+                />
+              </template>
+              <!-- 表头工具栏 -->
+              <template v-slot:action="{ row }">
+                <!-- <el-radio class="radio" v-model="radio" :label="row.code"></el-radio> -->
+                <el-radio class="radio" v-model="radio" :label="row.id">
+                  <i></i>
+                </el-radio>
+              </template>
+            </ele-pro-table>
+          </template>
+        </ele-split-layout>
+      </el-card>
+
+      <!-- <AddDialog ref="addContactDialogRef" @done="reload"></AddDialog> -->
+      <!-- <EditPriceDialog ref="editPriceDialogRef" @done="reload">
+      </EditPriceDialog> -->
+      <!-- <HistoricalpriceDialog
+        ref="historicalpriceDialogRef"
+        @done="reload"
+      ></HistoricalpriceDialog> -->
+    </div>
+
+    <div class="btns" slot="footer">
+      <el-button type="primary" size="small" @click="selected">选择</el-button>
+      <el-button size="small" @click="visible = false">关闭</el-button>
+    </div>
+  </ele-modal>
+</template>
+
+<script>
+  // import HistoricalpriceDialog from './historicalpriceDialog.vue';
+  // import EditPriceDialog from './editPriceDialog.vue';
+  import AssetTree from '@/components/AssetTree';
+  import PriceSearch from './priceSearch.vue';
+  // import AddDialog from './addDialog.vue';
+  import { getList } from '@/api/bpm/components/goodsManage/index.js';
+  import dictMixins from '@/mixins/dictMixins';
+  import { reviewStatus } from '@/enum/dict';
+  import { mapGetters } from 'vuex';
+  import {
+    getInventoryTotalAPI,
+    getCategoryPackageDisposition
+  } from '@/api/wms';
+  import { contactQueryByCategoryIdsAPI } from '@/api/bpm/components/saleManage/contact.js';
+
+  export default {
+    mixins: [dictMixins],
+    components: {
+      // HistoricalpriceDialog,
+      // EditPriceDialog,
+      AssetTree,
+      PriceSearch,
+      // AddDialog
+    },
+
+    data() {
+      return {
+        locationUrl: window.location.origin,
+        visible: false,
+        loading: false,
+        // 表格列配置
+        currentIndex: '',
+        current: null,
+        radio: null,
+        selection: [],
+        curNodeData: {} //右侧菜单选择对象
+      };
+    },
+    created() {
+      this.requestDict('商品价格类型');
+    },
+    computed: {
+      ...mapGetters(['user']),
+      columns() {
+        let data = null;
+        if (this.currentIndex != -1) {
+          data = {
+            action: 'action',
+            slot: 'action',
+            align: 'center',
+            label: '选择',
+            reserveSelection: true
+          };
+        }
+        if (this.currentIndex == -1) {
+          data = {
+            label: '选择',
+            width: 45,
+            type: 'selection',
+            columnKey: 'selection',
+            align: 'center',
+            reserveSelection: true
+          };
+        }
+
+        return [
+          data,
+
+          {
+            width: 45,
+            type: 'expand',
+            columnKey: 'expand',
+            align: 'center',
+            slot: 'expand'
+          },
+          {
+            columnKey: 'index',
+            type: 'index',
+            width: 50,
+            align: 'center',
+            showOverflowTooltip: true,
+            label: '序号'
+          },
+          {
+            prop: 'goodsCode',
+            label: '商品编码',
+            align: 'center',
+            showOverflowTooltip: true,
+            sortable: true,
+            width: 180
+          },
+          {
+            prop: 'imagesPaths',
+            label: '商品图片',
+            align: 'center',
+            slot: 'imagesPaths',
+            width: 180
+          },
+          {
+            prop: 'goodsName',
+            label: '商品名称',
+            align: 'center',
+            slot: 'goodsName',
+            showOverflowTooltip: true,
+            minWidth: 180
+          },
+          {
+            prop: 'categoryLevelName',
+            label: '商品分类',
+            align: 'center',
+            showOverflowTooltip: true,
+            width: 180
+          },
+          {
+            prop: 'categoryName',
+            align: 'center',
+            label: '产品名称',
+            showOverflowTooltip: true,
+            minWidth: 180
+          },
+          // {
+          //   prop: '产品编码',
+          //   label: '产品编码',
+          //   align: 'center',
+          //   showOverflowTooltip: true
+          // },
+          // {
+          //   prop: '产品类型',
+          //   label: '产品类型',
+          //   align: 'center',
+          //   showOverflowTooltip: true
+          // },
+          // {
+          //   prop: 'priceType',
+          //   label: '价格类型',
+          //   slot: 'priceType',
+          //   align: 'center',
+          //   width: 120,
+          //   formatter: (row, column) => {
+          //     if (row.priceType) {
+          //       return this.goodsTypeList.find((item) => item[row.priceType])?.[
+          //         row.priceType
+          //       ];
+          //     }
+          //   }
+          // },
+          // {
+          //   prop: 'unitPrice',
+          //   label: '含税单价',
+          //   slot: 'unitPrice',
+          //   align: 'center'
+          // },
+          // {
+          //   prop: 'taxRate',
+          //   slot: 'taxRate',
+          //   label: '税率',
+          //   align: 'center'
+          // },
+          // {
+          //   prop: 'excludeTaxPrice',
+          //   label: '不含税单价',
+          //   slot: 'excludeTaxPrice',
+          //   align: 'center'
+          // },
+          {
+            prop: 'goodsStatus',
+            align: 'center',
+            width: 150,
+            label: '状态',
+            showOverflowTooltip: true,
+            formatter: (row, column) => {
+              return row.goodsStatus === 0
+                ? '下架'
+                : row.goodsStatus === 1
+                ? '上架'
+                : '';
+            }
+          },
+          {
+            prop: 'approvalStatus',
+            label: '审核状态',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 100,
+            formatter: (_row, _column, cellValue) => {
+              return reviewStatus[_row.approvalStatus];
+            }
+          },
+          {
+            prop: 'createTime',
+            label: '创建时间',
+            align: 'center',
+            showOverflowTooltip: true,
+            width: 180
+          }
+        ];
+      }
+    },
+    methods: {
+      open(index) {
+        this.currentIndex = index;
+        this.current = null;
+        this.radio = null;
+        this.selection = [];
+        this.visible = true;
+      },
+      // 单击获取id
+      cellClick(row) {
+        if (this.currentIndex == -1) return;
+        this.current = row;
+        this.radio = row.id;
+      },
+      /* 表格数据源 */
+      datasource({ page, limit, where }) {
+        return getList({
+          pageNum: page,
+          size: limit,
+          // goodsStatus:1,
+          ...where
+        });
+      },
+      handleNodeClick(data, node) {
+        this.curNodeData = data;
+        this.reload({ categoryLevelId: data.id });
+      },
+      /* 刷新表格 */
+      reload(where) {
+        this.$refs.table.reload({ page: 1, where });
+      },
+      async getSupplierObj(productList, queryName) {
+        try {
+          let categoryIds = productList
+            .filter((item) => item.productId)
+            .map((item) => item.productId);
+          if (categoryIds.length > 0) {
+            return await contactQueryByCategoryIdsAPI({
+              categoryIds,
+              isQueryEE: 1
+            });
+          } else {
+            return Promise.resolve({});
+          }
+        } catch (e) {
+          return Promise.resolve({});
+        }
+      },
+      //历史价格
+      openHistoricalprice(row) {
+        this.$refs.historicalpriceDialogRef.open(row);
+      },
+
+      openEdit(type, row) {
+        this.$refs.addContactDialogRef.open(type, row, this.curNodeData.id);
+        this.$refs.addContactDialogRef.$refs.form &&
+          this.$refs.addContactDialogRef.$refs.form.clearValidate();
+      },
+
+      openEditPrice(row) {
+        this.$refs.editPriceDialogRef.open(row);
+        this.$refs.editPriceDialogRef.$refs.form &&
+          this.$refs.editPriceDialogRef.$refs.form.clearValidate();
+      },
+      async selected() {
+        if (!this.selection.length && !this.current) {
+          return this.$message.warning('请至少选择一条数据');
+        }
+        let list = this.currentIndex == -1 ? this.selection : [this.current];
+        list = list.map((item) => {
+          const itemList  = item.goodsPriceList.filter(item => item.isDefault == 1)
+          const goodsPrice = itemList.length > 0 ? itemList[0] :  item.goodsPriceList[0];
+          return {
+            ...item.categoryInfo,
+            goodsId: item.id,
+            to: item.id,
+            goodsPriceId: goodsPrice?.id,
+            level: item.level,
+            goodsPriceType: goodsPrice?.priceType,
+            singlePrice: goodsPrice?.unitPrice,
+            notaxSinglePrice: goodsPrice?.excludeTaxPrice,
+            taxRate: goodsPrice?.taxRate,
+            technologyRouteName: goodsPrice?.technologyRouteName,
+            technologyRouteId: goodsPrice?.technologyRouteId,
+          };
+        });
+        let codeList = list.map((item) => item.code);
+        let idList = list.map((item) => item.id);
+        // 获取包装规格
+        let packingSpecification = await getCategoryPackageDisposition({
+          categoryIds: idList
+        });
+        //获取仓库库存
+
+        let inventoryTotalList = await getInventoryTotalAPI(codeList);
+        list.forEach((item) => {
+          let find =
+            inventoryTotalList.find((key) => key.code == item.code) || {};
+          item.availableCountBase = find.availableCountBase;
+        });
+        let supplierList = await this.getSupplierObj(list);
+        list.forEach((item) => {
+          item['entrustedEnterpriseIdList'] = supplierList[item.id];
+          if (supplierList[item.id]?.length === 1) {
+            item['entrustedEnterpriseId'] = supplierList[item.id][0].id;
+          }
+          item['packageDispositionList'] = packingSpecification
+            .filter((ite) => item.id == ite.categoryId && ite.conversionUnit)
+            .sort((a, b) => a.sort - b.sort);
+        });
+        this.$emit('changeParent', list, this.currentIndex);
+        this.visible = false;
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .tree_col {
+    border: 1px solid #eee;
+    padding: 10px 0;
+    box-sizing: border-box;
+    height: 500px;
+    overflow: auto;
+  }
+
+  .table_col {
+    padding-left: 10px;
+
+    ::v-deep .el-table th.el-table__cell {
+      background: #f2f2f2;
+    }
+  }
+
+  .pagination {
+    text-align: right;
+    padding: 10px 0;
+  }
+
+  .btns {
+    text-align: center;
+    padding: 10px 0;
+  }
+
+  .topsearch {
+    margin-bottom: 15px;
+  }
+</style>

+ 13 - 2
src/views/bpm/handleTask/components/financialManage/invoiceManage/components/detailDialog.vue

@@ -177,7 +177,7 @@
         </el-col>
       </el-row>
     </el-form>
-    <div style="margin-top: 20px; margin-bottom: 20px;">
+    <div v-if="form.sourceType != 99" style="margin-top: 20px; margin-bottom: 20px;">
         <headerTitle title="收款计划信息"></headerTitle>
         <!-- <el-form ref="form" :model="tableForm"> -->
           <ele-pro-table
@@ -232,9 +232,15 @@
       ref="table"
     ></table-info> -->
    <table-info-new
+      v-if="form.sourceType != 99"
       dialogType="view"
       ref="tableInfoNewRef"
     ></table-info-new>
+    <table-info
+      v-else
+      dialogType="view"
+      ref="tableInfoNoOrderRef"
+    ></table-info>
   </div>
 </template>
 
@@ -391,7 +397,12 @@
       async getInfo(id) {
         this.form = await invoiceApplyInfoV2API(id);
         this.$nextTick(() => {
-          this.$refs.tableInfoNewRef && this.$refs.tableInfoNewRef.putValue(this.form);
+          // 根据来源类型设置数据源:99 用 tableInfo(setValue),非 99 用 tableInfoNew(putValue)
+          if (this.form.sourceType == 99) {
+            this.$refs.tableInfoNoOrderRef?.setValue(this.form);
+          } else {
+            this.$refs.tableInfoRef?.putValue(this.form);
+          }
         })
       },
       downloadFile(file) {

+ 81 - 0
src/views/bpm/handleTask/components/financialManage/invoiceManage/components/priceSearch.vue

@@ -0,0 +1,81 @@
+<!-- 搜索表单 -->
+<template>
+  <seekPage :seekList="seekList" :formLength="3" @search="search"></seekPage>
+</template>
+<script>
+export default {
+  data() {
+    return {};
+  },
+
+  computed: {
+    // 表格列配置
+    seekList() {
+      return [
+        {
+          label: '关键字:',
+          value: 'searchName',
+          type: 'input',
+          placeholder: '商品编码/商品名称/产品名称'
+        },
+        // {
+        //   label: '价格类型:',
+        //   value: 'categoryLevelId',
+        //   type: 'DictSelection',
+        //   placeholder: '',
+        //   dictName: "商品价格类型"
+        // },
+        {
+          label: '商品编码:',
+          value: 'goodsCode',
+          type: 'input',
+          placeholder: '请输入'
+        },
+        {
+          label: '商品名称:',
+          value: 'goodsName',
+          // width: 380,
+          type: 'input',
+          placeholder: '请输入'
+        },
+        // {
+        //   label: '商品分类:',
+        //   value: 'workCode',
+        //   width: 380,
+        //   type: 'input',
+        //   placeholder: ''
+        // },
+        // {
+        //   label: '产品名称:',
+        //   value: 'workCode',
+        //   width: 380,
+        //   type: 'input',
+        //   placeholder: ''
+        // },
+        // {
+        //   label: '状态:',
+        //   value: 'workCode',
+        //   width: 380,
+        //   type: 'input',
+        //   placeholder: ''
+        // },
+        // {
+        //   label: '创建时间:',
+        //   value: 'workCode',
+        //   width: 380,
+        //   type: 'input',
+        //   placeholder: ''
+        // },
+      ];
+    }
+  },
+  methods: {
+    /* 搜索 */
+    search(e) {
+      this.$emit('search', {
+        ...e
+      });
+    }
+  }
+};
+</script>

+ 642 - 129
src/views/bpm/handleTask/components/financialManage/invoiceManage/components/tableInfo.vue

@@ -1,20 +1,149 @@
 <template>
   <div>
-    <ele-pro-table
-      ref="table"
-      :needPage="false"
-      :columns="columns"
-      :toolkit="[]"
-      :datasource="tableForm.detailList"
-      row-key="id"
-    >
-    </ele-pro-table>
+    <el-form ref="form" :model="tableForm">
+      <ele-pro-table
+        ref="table"
+        :needPage="false"
+        :columns="columns"
+        :datasource="tableForm.detailList"
+        row-key="id"
+        :selection.sync="selection"
+        class="time-form"
+      >
+        <template v-slot:toolbar>
+          <el-button type="primary" @click="handParent('', -1)">新增</el-button>
+          <el-button type="primary" @click="handGoods(-1)">选择商品</el-button>
+          <setAllValue :disabled="!selection.length" inputType="number" title="税率" valueKey="taxRate" @success="confirmBatchSet" />
+          <setAllValue :disabled="!selection.length" inputType="number" title="单价" valueKey="singlePrice" @success="confirmBatchSet" />
+          <setAllValue :disabled="!selection.length" inputType="number" title="折让比例" valueKey="discountRatio" @success="confirmBatchSet" />
+        </template>
+        
+        <template v-slot:totalCount="scope">
+        <el-form-item
+          style="width: 100%;"
+          :prop="'detailList.' + scope.$index + '.totalCount'"
+          :rules="[
+            {
+              required: true,
+              message: '请输入数量',
+              trigger: 'blur'
+            },
+            {
+              validator: (rule, value, callback) => {
+                if (value === undefined || value === null || value === '') {
+                  callback('请输入数量');
+                } else if (parseFloat(value) <= 0) {
+                  callback('数量必须大于0');
+                } else {
+                  callback();
+                }
+              },
+              trigger: 'blur'
+            }
+          ]"
+        > 
+          <span v-if="dialogType === 'view'">{{ scope.row.totalCount }}</span>
+          <el-input v-else v-model="scope.row.totalCount" type="number" @input="recalcDetailList(scope.row, scope.$index)"></el-input>
+        </el-form-item>
+      </template>
+
+      <!-- 单价 -->
+      <template v-slot:singlePrice="scope">
+        <span v-if="dialogType === 'view'">{{ scope.row.singlePrice }}</span>
+        <el-input v-else v-model="scope.row.singlePrice" type="number" @input="recalcDetailList(scope.row, scope.$index)"></el-input>
+      </template>
+
+      <!-- 计价方式 -->
+      <template v-slot:pricingWay="scope">
+        <span v-if="dialogType === 'view'">{{ pricingWayLabel(scope.row.pricingWay) }}</span>
+        <el-select
+          v-else
+          v-model="scope.row.pricingWay"
+          placeholder="请选择"
+          style="width: 100%"
+          @change="recalcDetailList(scope.row, scope.$index)"
+        >
+          <el-option
+            v-for="item in pricingWayList"
+            :key="item.id"
+            :label="item.name"
+            :value="item.id"
+          />
+        </el-select>
+      </template>
+
+      <!-- 税率 -->
+      <template v-slot:taxRate="scope">
+        <span v-if="dialogType === 'view'">{{ scope.row.taxRate }}</span>
+        <el-input
+          v-else
+          v-model="scope.row.taxRate"
+          type="number"
+          @input="recalcDetailList(scope.row, scope.$index)"
+        ></el-input>
+      </template>
+
+      <!-- 折让比例 -->
+      <template v-slot:discountRatio="scope">
+        <span v-if="dialogType === 'view'">{{ scope.row.discountRatio }}</span>
+        <el-input
+          v-else
+          v-model="scope.row.discountRatio"
+          type="number"
+          :min="0"
+          :max="100"
+          placeholder="请输入"
+        ></el-input>
+      </template>
+
+      <!-- 工艺路线 -->
+      <template v-slot:technologyRouteName="scope">
+        <span v-if="dialogType === 'view'">{{ scope.row.technologyRouteName }}</span>
+        <el-input
+          v-else
+          :value="scope.row.technologyRouteName"
+          placeholder="请选择"
+          readonly
+          @click.native="openVersion(scope.$index)"
+        ></el-input>
+      </template>
+
+      <!-- 操作:删除 -->
+      <template v-slot:action="scope">
+        <el-link
+          v-if="dialogType !== 'view'"
+          type="danger"
+          :underline="false"
+          icon="el-icon-delete"
+          @click="removeRow(scope.$index)"
+        >删除</el-link>
+      </template>
+
+      </ele-pro-table>
+    </el-form>
+    <product-list ref="productListRef" classType="1" :is-get-inventory-total="true" @changeParent="changeParent" :isSupplier="true"></product-list>
+    <commodityPriceListDialog ref="commodityPriceListDialogRef" @changeParent="changeParent"></commodityPriceListDialog>
+    <ProductionVersion ref="versionRefs" @changeProduct="changeProduct"></ProductionVersion>
   </div>
 </template>
 <script>
+import setAllValue from '@/BIZComponents/setAllValue.vue'; //批量修改
+import productList from '@/BIZComponents/product-list.vue';
+import commodityPriceListDialog from './commodityPriceListDialog.vue';
+import ProductionVersion from '@/components/ProductionVersion2/index.vue';
+import { pricingWayList } from '@/enum/dict.js';
+const dayjs = require('dayjs');
+
+import {
+  changeCount,
+  getAllPrice,
+  getAllDiscountPrice,
+  formatPrice,
+  getAllQuantity
+} from '@/BIZComponents/setProduct.js';
   export default {
     name: 'tableInfo',
-    components: {},
+    components: { setAllValue, productList, commodityPriceListDialog, ProductionVersion },
     props: {
       form: {
         type: Object,
@@ -37,55 +166,106 @@
         default: () => {
           return {};
         }
-      }
+      },
+      invoiceAmount: {
+        type: Number,
+        default: 0
+      },
+      contractBookType: {
+        //合同类型 1销售 2采购
+        type: [String, Number],
+        default: 1
+      },
+      //是否商品
+      isGoods: {
+        type: Boolean,
+        default: false
+      },
     },
     data() {
+      const defaultForm = {
+            key: null,
+            endTime: '',
+            isFirst: 0,
+            name: '',
+            startTime: '',
+            workHour: '',
+            guaranteePeriodUnitCode: '',
+            technicalDrawings: [],
+            arrivalWay: 1,
+            // 生产加工类型特有字段
+            thickNess: '',
+            squareNumber: '',
+            processingFeeBeforeTax: '',
+            packagingFeeNotTaxed: '',
+            transportationFeeWithoutTax: '',
+            extraTax: '',
+            quotationSubtotalTax: '',
+            // 新增未税小记字段
+            quotationSubtotalBeforeTax: '',
+            quoteWay: 1,
+            discountRatio: 100
+          };
       return {
         columns: [
           {
             width: 45,
-            type: 'index',
-            columnKey: 'index',
+            type: 'selection',
+            columnKey: 'selection',
             align: 'center',
             fixed: 'left'
           },
-
           {
-            width: 100,
-            prop: 'typeName',
-            label: '类型',
-            slot: 'typeName',
-            align: 'center'
+            width: 45,
+            type: 'index',
+            columnKey: 'index',
+            align: 'center',
+            fixed: 'left'
           },
           // {
-          //   minWidth: 100,
-          //   prop: 'sourceCode',
-          //   label: '类型编码',
-          //   slot: 'sourceCode',
+          //   width: 150,
+          //   prop: 'key',
+          //   label: '来源编码',
+          //   align: 'center'
+          // },
+          // {
+          //   width: 100,
+          //   prop: 'key',
+          //   label: '对账日期',
+          //   align: 'center'
+          // },
+          // {
+          //   width: 150,
+          //   prop: 'sourceOrderNo',
+          //   label: '销售订单编码',
           //   align: 'center'
           // },
           // {
           //   width: 100,
-          //   prop: 'productCategoryName',
-          //   label: '分类',
-          //   slot: 'productCategoryName',
-          //   align: "center"
+          //   prop: 'key',
+          //   label: '发货单编码',
+          //   align: 'center'
           // },
           // {
           //   width: 100,
-          //   prop: 'productCode',
-          //   label: '编码',
-          //   slot: 'productCode',
-          //   align: "center"
+          //   prop: 'key',
+          //   label: '发货日期',
+          //   align: 'center'
           // },
           {
-            minWidth: 100,
+            width: 100,
+            prop: 'productCode',
+            label: '产品编码',
+            align: 'center'
+          },
+          {
+            minWidth: 150,
             prop: 'productName',
-            label: '名称',
+            label: '产品名称',
             slot: 'productName',
             align: 'center'
           },
-          {
+           {
             minWidth: 100,
             prop: 'modelType',
             label: '型号',
@@ -100,75 +280,130 @@
             slot: 'specification',
             align: 'center'
           },
-          // {
-          //   width: 100,
-          //   prop: 'productBrand',
-          //   label: '牌号',
-          //   slot: 'productBrand',
-          //   align: "center"
-          // },
-     
+
+          {
+            minWidth: 100,
+            prop: 'batchNo',
+            label: '批次号',
+            slot: 'batchNo',
+            align: 'center'
+          },
           {
-            width: 80,
+            width: 100,
             prop: 'totalCount',
             label: '数量',
             slot: 'totalCount',
+            align: 'center',
+          },
+          
+          {
+            minWidth: 130,
+            prop: 'unit',
+            label: '计量单位',
+            slot: 'unit',
             align: 'center'
           },
-      
           {
-            width: 100,
-            prop: 'measuringUnit',
-            label: '单位',
-            slot: 'measuringUnit',
+            minWidth: 130,
+            prop: 'pricingWay',
+            label: '计价方式',
+            slot: 'pricingWay',
+            align: 'center'
+          },
+          {
+            minWidth: 130,
+            prop: 'technologyRouteName',
+            label: '工艺路线',
+            slot: 'technologyRouteName',
             align: 'center'
           },
-          // {
-          //   width: 150,
-          //   prop: 'pricingWay',
-          //   label: '计价方式',
-          //   formatter: (row, column) => {
-          //     return row.pricingWay == 1
-          //       ? '按数量计费'
-          //       : row.pricingWay == 2
-          //       ? '按重量计费'
-          //       : '';
-          //   },
-          //   align: 'center'
-
-          // },
           {
-            minWidth: 80,
+            minWidth: 130,
             prop: 'singlePrice',
-            label: '单价(¥)',
+            label: '单价',
             slot: 'singlePrice',
             align: 'center'
           },
+          {
+            minWidth: 130,
+            prop: 'taxRate',
+            label: '税率',
+            align: 'center',
+            slot: 'taxRate',
+            // formatter: (_row, _column, cellValue) => {
+            //   return _row.taxRate
+            //     ? _row.taxRate+'%'
+            //     : '';
+            // },
+          },
+          {
+            minWidth: 100,
+            prop: 'noTaxSinglePrice',
+            label: '不含税单价',
+            slot: 'noTaxSinglePrice',
+            align: 'center'
+          },
+          {
+            minWidth: 130,
+            prop: 'weight',
+            label: '重量',
+            align: 'center'
+          },
+          {
+            minWidth: 130,
+            prop: 'weightUnit',
+            label: '重量单位',
+            align: 'center'
+          },
           // {
-          //   width: 80,
-          //   prop: 'singleWeight',
-          //   label: '单量',
+          //   width: 150,
+          //   prop: 'quoteWay',
+          //   label: '报价方式',
+          //   formatter: (row, column) => {
+          //     return row.quoteWay == 1
+          //       ? '常规价'
+          //       : row.quoteWay == 2
+          //       ? '内部价'
+          //       : row.quoteWay == 3 ? '议价' : '';
+          //   },
           //   align: 'center'
+
           // },
           
           {
-            minWidth: 80,
+            width: 100,
             prop: 'totalPrice',
-            label: '金额(¥)',
-            slot: 'totalPrice',
+            label: '合计',
             align: 'center'
           },
           {
-            minWidth: 80,
-            prop: 'taxRate',
-            label: '税率',
-            formatter: (_row, _column, cellValue) => {
-              return _row.taxRate
-                ? _row.taxRate+'%'
-                : '';
-            },
+            width: 100,
+            prop: 'discountRatio',
+            label: '折让比例',
+            slot: 'discountRatio',
             align: 'center'
-          }
+          },
+          {
+            width: 100,
+            prop: 'discountSinglePrice',
+            label: '折让单价',
+            align: 'center'
+          },
+          {
+            width: 100,
+            prop: 'discountAmount',
+            label: '折让合计',
+            align: 'center'
+          },
+          {
+            width: 100,
+            columnKey: 'action',
+            label: '操作',
+            slot: 'action',
+            align: 'center',
+            fixed: 'right'
+          },
+         
           // {
           //   width: 100,
           //   prop: 'sourceType',
@@ -184,6 +419,18 @@
           detailList: [],
           link: []
         },
+        defaultForm,
+        // 计数单位字段映射(本页数量字段为 totalCount)
+        countObj: {
+          countKey: 'totalCount',
+          unitKey: 'measuringUnit',
+          unitIdKey: 'measuringUnitId'
+        },
+        allPrice: 0,
+        allQuantity: 0,
+        allDiscountPrice: 0,
+        selection: [],
+        pricingWayList,
         typeList: [
           {
             label: '销售发货',
@@ -201,57 +448,279 @@
             label: '采购退货',
             value: '21'
           }
-        ]
+        ],
       };
     },
     mounted() {
       this.tableForm = this.form;
     },
+    watch: {
+      form(val) {
+        this.tableForm = this.form;
+      }
+    },
     methods: {
-      //获取选择的对账单数据
-      async getAccountData(params) {
-        if (params.children.orderType == 6) {
-          this.tableForm.detailList = params.children.detailList;
-          this.tableForm.detailList.forEach((item, index) => {
-            item.sourceCode = params.children.orderNo;
-            item.sourceId = params.children.id;
-            item.sourceType = params.type == 1 ? 2 : 3;
-            item.type = 12;
-            item.singlePrice = item.discountSinglePrice;
-            item.totalPrice = item.discountTotalPrice;
-            item.typeName = '销售赔付';
+      guaranteePeriodUnit(code) {
+        return code == 3
+          ? 'day'
+          : code == 4
+          ? 'month'
+          : code == 5
+          ? 'year'
+          : 'second';
+      },
+      // 改变数量(适配本页面:数据源为 tableForm.detailList,数量字段为 totalCount)
+      // 参考 inventoryTable.changeCount 逻辑,独立实现,不依赖原方法
+      recalcDetailList(row, index, weightType) {
+        if (!row) {
+          // 全量重算
+          this.tableForm.detailList = this.tableForm.detailList.map((item) => {
+            const updated = changeCount(item, this.countObj, false);
+            return this.syncDiscountAmount(updated);
           });
         } else {
-          this.tableForm.detailList = [];
-          params.children.subList.forEach((item, index) => {
-            item.detailList.forEach((i, n) => {
-              i.sourceCode = item.statementSubOrderCode;
-              i.sourceId = params.children.id;
-              i.sourceType = params.type == 1 ? 2 : 3;
-              i.type = item.subType;
-              console.log(item.subType);
-              i.typeName = this.typeList.find(
-                (i) => i.value == item.subType
-              ).label;
-              // i.singlePrice = item.discountSinglePrice
-              i.totalPrice = i.discountTotalPrice;
-            });
-            this.tableForm.detailList.push(...item.detailList);
-          });
-          this.$refs.table.reload();
+          // 单行重算
+          const updatedRow = changeCount(row, this.countObj, false, weightType);
+          this.$set(this.tableForm.detailList, index, this.syncDiscountAmount(updatedRow));
         }
-        this.$emit('setPrice', params.children.amountTotalPrice);
-        let row = {
-          id: params.id,
-          name: params.statementNo,
-          code: params.statementNo,
-          linkType: params.type == 1 ? 190 : 290,
-          linkTypeName: params.type == 1 ? '销售对账单' : '采购对账单'
-        };
-        this.setSelectData(row);
+        this.$nextTick(() => {
+          this.getNotaxSinglePrice();
+          this.calcAllTotal();
+        });
+      },
+      // 同步折让合计:changeCount 输出 discountTotalPrice,表格列用 discountAmount
+      syncDiscountAmount(row) {
+        this.$set(row, 'discountAmount', row.discountTotalPrice ?? '');
+        return row;
+      },
+      // 删除行并重新计算
+      removeRow(index) {
+        if (index < 0 || index >= this.tableForm.detailList.length) return;
+        this.tableForm.detailList.splice(index, 1);
+        this.$nextTick(() => {
+          this.calcAllTotal();
+        });
+      },
+      // 计算不含税单价
+      getNotaxSinglePrice() {
+        this.tableForm.detailList.forEach((item, index) => {
+          if (item.singlePrice && item.taxRate) {
+            this.$set(
+              this.tableForm.detailList[index],
+              'noTaxSinglePrice',
+              +((+item.singlePrice / (1 + +item.taxRate / 100)).toFixed(2))
+            );
+          } else {
+            this.$set(this.tableForm.detailList[index], 'noTaxSinglePrice', '');
+          }
+        });
+      },
+      // 汇总金额与数量
+      calcAllTotal() {
+        this.allPrice = getAllPrice(this.tableForm.detailList) || 0;
+        this.allQuantity = getAllQuantity(this.tableForm.detailList, this.countObj) || 0;
+        this.allDiscountPrice =
+          getAllDiscountPrice(this.tableForm.detailList) || 0;
+        // 通知父组件金额变化
+        this.$emit('setPrice', this.allPrice);
+      },
+      setDay(addDay, dateType = 'day', item) {
+        let tiem =
+          this.contractBookType == 1
+            ? item.produceDeliveryDeadline
+            : item.customerExpectDeliveryDeadline;
+        return dayjs(tiem || new Date())
+          .add(addDay, dateType)
+          .format('YYYY-MM-DD');
+      },
+      //选择产品回调
+    changeParent(obj, idx) {
+      console.log(obj, idx);
+      obj.forEach((item, index) => {
+        let i = idx == -1 ? index : idx;
+        let row = JSON.parse(JSON.stringify(this.defaultForm));
+        console.log(row);
+        row.key = this.tableForm.detailList.length + 1;
+        let parasm = idx == -1 ? row : this.tableForm.detailList[i];
+
+        this.$set(parasm, 'productId', item.id);
+        this.$set(parasm, 'categoryName', item.name);
+        this.$set(parasm, 'productCategoryId', item.categoryLevelId);
+        this.$set(parasm, 'productBrand', item.brandNum);
+        this.$set(parasm, 'productCategoryName', item.categoryLevelPath);
+        this.$set(parasm, 'productCode', item.code);
+        this.$set(parasm, 'productName', item.name);
+        this.$set(parasm, 'modelType', item.modelType);
+        this.$set(parasm, 'availableCountBase', item.availableCountBase);
+        this.$set(parasm, 'measuringUnit', item.measuringUnit);
+        this.$set(parasm, 'specification', item.specification);
+        this.$set(parasm, 'weightUnit', item.weightUnit);
+        this.$set(parasm, 'singleWeight', item.netWeight);
+        this.$set(parasm, 'pricingWay', 1);
+        this.$set(parasm, 'goodsLevel', item.goodsLevel);
+        this.$set(parasm, 'guaranteePeriod', item.warrantyPeriod);
+        this.$set(
+          parasm,
+          'customerExpectDeliveryDeadline',
+          dayjs(new Date()).format('YYYY-MM-DD')
+        );
+        // console.log('colorKey~~', item.colorKey);
+        this.$set(parasm, 'modelKey', item.modelKey?.split(',')?.[0] || '');
+        this.$set(parasm, 'colorKey', item.colorKey?.split(',')?.[0] || '');
+        this.$set(parasm, 'technologyRouteName', item.technologyRouteName || '');
+        this.$set(parasm, 'technologyRouteId', item.technologyRouteId || '');
+       
+          this.$set(
+            parasm,
+            'taxRate',
+            parasm.taxRate
+          );
+        
+        // this.$set(
+        //   parasm,
+        //   'guaranteePeriodUnitCode',
+        //   item.warrantyPeriodUnit ? item.warrantyPeriodUnit + '' : ''
+        // );
+        // if (item.warrantyPeriod && item.warrantyPeriodUnit) {
+        //   this.$set(
+        //     parasm,
+        //     'guaranteePeriodDeadline',
+        //     this.setDay(
+        //       item.warrantyPeriod,
+        //       this.guaranteePeriodUnit(item.warrantyPeriodUnit),
+        //       {}
+        //     )
+        //   );
+        // }
+
+        this.$set(
+          parasm,
+          'packageDispositionList',
+          item.packageDispositionList
+        );
+        if (item.packageDispositionList?.length) {
+          this.$set(
+            parasm,
+            this.countObj.unitIdKey,
+            item.packageDispositionList[0].id
+          );
+          this.$set(
+            parasm,
+            this.countObj.unitKey,
+            item.packageDispositionList[0].conversionUnit
+          );
+        }
+
+        this.$set(parasm, 'arrivalWay', item.arrivalWay || 1);
+
+        this.$set(parasm, 'imgCode', item.imgCode);
+        this.$set(parasm, 'produceType', item.componentAttribute);
+   
+        if (this.isGoods && item.goodsId) {
+          this.$set(parasm, 'goodsId', item.goodsId);
+          this.$set(parasm, 'goodsPriceId', item.goodsPriceId);
+          this.$set(parasm, 'goodsPriceType', item.goodsPriceType);
+          this.$set(parasm, 'singlePrice', item.singlePrice);
+          this.$set(parasm, 'notaxSinglePrice', item.notaxSinglePrice);
+          this.$set(parasm, 'taxRate', item.taxRate);
+          this.$set(parasm, 'discountSinglePrice', item.singlePrice);
+          this.$set(parasm, 'totalCount', '');
+          this.$set(parasm, 'discountRatio', item.discountRatio);
+          this.$set(parasm, 'quoteWay', item.quoteWay || 1);
+        } else {
+          this.$set(parasm, 'singlePrice', parasm.singlePrice || 0);
+          this.$set(parasm, 'discountRatio', parasm.discountRatio || 100);
+          this.$set(parasm, 'quoteWay', parasm.quoteWay || 1);
+        }
+
+
+      
+          this.$set(
+            parasm,
+            'entrustedEnterpriseIdList',
+            item.entrustedEnterpriseIdList
+          );
+          this.$set(
+            parasm,
+            'entrustedEnterpriseId',
+            item.entrustedEnterpriseId
+          );
+        
+        this.$set(parasm, 'approvalNumber', item.extField?.approvalNumber);
+        this.$set(
+          parasm,
+          'packingSpecification',
+          item.extField.packingSpecification
+        );
+        this.$set(parasm, 'customerMark', this.customerMark);
+        if (item.purchaseOrigins?.length > 0) {
+          item.purchaseOrigins = item.purchaseOrigins.map((val) => val + '');
+        }
+        this.$set(parasm, 'provenance', item.purchaseOrigins || []);
+
+        if (idx == -1) {
+          this.tableForm.detailList.push(row);
+        }
+      });
+
+      console.log('changeParent~~~', this.tableForm.detailList);
+      this.recalcDetailList();
+    },
+      //选择产品
+    handParent(row, index) {
+      let item = {
+        id: row?.productCode
+      };
+      if (row?.goodsId) {
+        this.handGoods(index);
+        return;
+      }
+      
+      this.$refs.productListRef.open(item, index);
+  
+    },
+    handGoods(index) {
+      this.$refs.commodityPriceListDialogRef.open(index);
+    },
+      confirmBatchSet({ key, value }) {
+        if (!this.selection.length) {
+          this.$message.warning('请先勾选需要批量设置的行');
+          return;
+        }
+        // 批量设置选中行字段,并重算金额(合并回原对象,保持勾选引用不失效)
+        this.selection.forEach((item) => {
+          this.$set(item, key, value);
+          const updated = changeCount(item, this.countObj, false);
+          Object.keys(updated).forEach((k) => {
+            this.$set(item, k, updated[k]);
+          });
+          // 同步折让合计字段
+          this.$set(item, 'discountAmount', item.discountTotalPrice ?? '');
+        });
+        this.$nextTick(() => {
+          this.getNotaxSinglePrice();
+          this.calcAllTotal();
+        });
       },
       setValue(data) {
-        this.tableForm.detailList = data;
+        console.log('data~~~', data);
+        // 将 productMap(对象,key 为订单号,值为明细数组)转换为扁平行数组
+        this.tableForm.detailList = this.convertProductMapToArray(data);
+      },
+      // productMap -> 扁平行数组(表格展示用),key 固定为 99
+      convertProductMapToArray(data) {
+        const productMap = data?.productMap || {};
+        const result = [];
+        Object.keys(productMap).forEach((key) => {
+          const details = productMap[key] || [];
+          details.forEach((detail) => {
+            result.push({
+              key: 'UNKNOWN_ORDER', // 固定 key 99,提交时用于还原分组
+              ...detail
+            });
+          });
+        });
+        return result;
       },
       clearTable() {
         this.tableForm = {
@@ -259,24 +728,68 @@
           link: []
         };
       },
+      // 当数量变化时更新金额
+      updateTotalPrice(row) {
+        if (row.totalCount && row.singlePrice) {
+          row.totalPrice = (parseFloat(row.totalCount) * parseFloat(row.singlePrice)).toFixed(2);
+        }
+      },
+      // 计价方式 label
+      pricingWayLabel(value) {
+        const item = this.pricingWayList.find((i) => i.id == value);
+        return item ? item.name : '';
+      },
+      // 打开工艺路线选择弹窗
+      openVersion(index) {
+        this.$refs.versionRefs.open(index);
+      },
+      // 工艺路线选择回调
+      changeProduct(data, index) {
+        if (data && this.tableForm.detailList[index]) {
+          this.$set(this.tableForm.detailList[index], 'technologyRouteName', data.name);
+          this.$set(this.tableForm.detailList[index], 'technologyRouteId', data.id);
+          this.$set(this.tableForm.detailList[index], 'technologyRouteVersion', data.version);
+        }
+      },
       getTableValidate() {
         return new Promise((resolve, reject) => {
-          if (this.tableForm.detailList.length == 0)
+          if (
+            this.tableForm.detailList.length == 0 &&
+            ![4, 5].includes(this.form.sourceType)
+          )
             return this.$message.warning('请选择关联信息');
           resolve(this.tableForm);
         });
       },
-      setSelectData(val) {
-        this.tableForm.link = [{}];
-        this.$set(this.tableForm.link[0], 'linkId', val.id);
-        this.$set(this.tableForm.link[0], 'linkName', val.name);
-        this.$set(this.tableForm.link[0], 'linkCode', val.code);
-        this.$set(this.tableForm.link[0], 'linkType', val.linkType);
-        this.$set(this.tableForm.link[0], 'linkTypeName', val.linkTypeName);
+      validateForm(callback) {
+        //开始表单校验
+        this.$refs.form.validate((valid, obj) => {
+          if (obj) {
+            let messages = Object.keys(obj).map((key) => obj[key][0]);
+            if (messages.length > 0) {
+              this.$message.warning(messages[0].message);
+            }
+          }
+          callback(valid);
+        });
       },
-      getTableData() {}
+  
+      // 扁平行数组 -> productMap(提交格式),key 固定为 99
+      getTableData() {
+        const data = JSON.parse(JSON.stringify(this.tableForm.detailList));
+        const productMap = { UNKNOWN_ORDER: [] };
+        data.forEach((item) => {
+          const { key, ...detail } = item;
+          productMap['UNKNOWN_ORDER'].push(detail);
+        });
+        return productMap;
+      }
     }
   };
 </script>
 
-<style scoped lang="scss"></style>
+<style scoped lang="scss">
+.time-form .el-form-item {
+  margin-bottom: 0 !important;
+}
+</style>

+ 282 - 0
src/views/bpm/handleTask/components/financialManage/invoiceManage/components/tableInfoOld.vue

@@ -0,0 +1,282 @@
+<template>
+  <div>
+    <ele-pro-table
+      ref="table"
+      :needPage="false"
+      :columns="columns"
+      :toolkit="[]"
+      :datasource="tableForm.detailList"
+      row-key="id"
+    >
+    </ele-pro-table>
+  </div>
+</template>
+<script>
+  export default {
+    name: 'tableInfo',
+    components: {},
+    props: {
+      form: {
+        type: Object,
+        default: () => {
+          return {
+            detailList: []
+          };
+        }
+      },
+      dialogType: {
+        type: String,
+        default: ''
+      },
+      isOtherSourceFlag: {
+        type: Boolean,
+        default: false
+      },
+      contactData: {
+        type: Object,
+        default: () => {
+          return {};
+        }
+      }
+    },
+    data() {
+      return {
+        columns: [
+          {
+            width: 45,
+            type: 'index',
+            columnKey: 'index',
+            align: 'center',
+            fixed: 'left'
+          },
+
+          {
+            width: 100,
+            prop: 'typeName',
+            label: '类型',
+            slot: 'typeName',
+            align: 'center'
+          },
+          // {
+          //   minWidth: 100,
+          //   prop: 'sourceCode',
+          //   label: '类型编码',
+          //   slot: 'sourceCode',
+          //   align: 'center'
+          // },
+          // {
+          //   width: 100,
+          //   prop: 'productCategoryName',
+          //   label: '分类',
+          //   slot: 'productCategoryName',
+          //   align: "center"
+          // },
+          // {
+          //   width: 100,
+          //   prop: 'productCode',
+          //   label: '编码',
+          //   slot: 'productCode',
+          //   align: "center"
+          // },
+          {
+            minWidth: 100,
+            prop: 'productName',
+            label: '名称',
+            slot: 'productName',
+            align: 'center'
+          },
+          {
+            minWidth: 100,
+            prop: 'modelType',
+            label: '型号',
+            slot: 'modelType',
+            align: 'center'
+          },
+
+          {
+            minWidth: 100,
+            prop: 'specification',
+            label: '规格',
+            slot: 'specification',
+            align: 'center'
+          },
+          // {
+          //   width: 100,
+          //   prop: 'productBrand',
+          //   label: '牌号',
+          //   slot: 'productBrand',
+          //   align: "center"
+          // },
+     
+          {
+            width: 80,
+            prop: 'totalCount',
+            label: '数量',
+            slot: 'totalCount',
+            align: 'center'
+          },
+      
+          {
+            width: 100,
+            prop: 'measuringUnit',
+            label: '单位',
+            slot: 'measuringUnit',
+            align: 'center'
+          },
+          // {
+          //   width: 150,
+          //   prop: 'pricingWay',
+          //   label: '计价方式',
+          //   formatter: (row, column) => {
+          //     return row.pricingWay == 1
+          //       ? '按数量计费'
+          //       : row.pricingWay == 2
+          //       ? '按重量计费'
+          //       : '';
+          //   },
+          //   align: 'center'
+
+          // },
+          {
+            minWidth: 80,
+            prop: 'singlePrice',
+            label: '单价(¥)',
+            slot: 'singlePrice',
+            align: 'center'
+          },
+          // {
+          //   width: 80,
+          //   prop: 'singleWeight',
+          //   label: '单量',
+          //   align: 'center'
+          // },
+          
+          {
+            minWidth: 80,
+            prop: 'totalPrice',
+            label: '金额(¥)',
+            slot: 'totalPrice',
+            align: 'center'
+          },
+          {
+            minWidth: 80,
+            prop: 'taxRate',
+            label: '税率',
+            formatter: (_row, _column, cellValue) => {
+              return _row.taxRate
+                ? _row.taxRate+'%'
+                : '';
+            },
+            align: 'center'
+          }
+          // {
+          //   width: 100,
+          //   prop: 'sourceType',
+          //   label: '来源类型',
+          //   slot: 'sourceType',
+          //   align: "center",
+          //   formatter: (row, column) => {
+          //     return row.sourceType == 2 ? '对账销售订单' : '对账采购订单';
+          //   }
+          // },
+        ],
+        tableForm: {
+          detailList: [],
+          link: []
+        },
+        typeList: [
+          {
+            label: '销售发货',
+            value: '10'
+          },
+          {
+            label: '销售退货',
+            value: '11'
+          },
+          {
+            label: '采购收货',
+            value: '20'
+          },
+          {
+            label: '采购退货',
+            value: '21'
+          }
+        ]
+      };
+    },
+    mounted() {
+      this.tableForm = this.form;
+    },
+    methods: {
+      //获取选择的对账单数据
+      async getAccountData(params) {
+        if (params.children.orderType == 6) {
+          this.tableForm.detailList = params.children.detailList;
+          this.tableForm.detailList.forEach((item, index) => {
+            item.sourceCode = params.children.orderNo;
+            item.sourceId = params.children.id;
+            item.sourceType = params.type == 1 ? 2 : 3;
+            item.type = 12;
+            item.singlePrice = item.discountSinglePrice;
+            item.totalPrice = item.discountTotalPrice;
+            item.typeName = '销售赔付';
+          });
+        } else {
+          this.tableForm.detailList = [];
+          params.children.subList.forEach((item, index) => {
+            item.detailList.forEach((i, n) => {
+              i.sourceCode = item.statementSubOrderCode;
+              i.sourceId = params.children.id;
+              i.sourceType = params.type == 1 ? 2 : 3;
+              i.type = item.subType;
+              console.log(item.subType);
+              i.typeName = this.typeList.find(
+                (i) => i.value == item.subType
+              ).label;
+              // i.singlePrice = item.discountSinglePrice
+              i.totalPrice = i.discountTotalPrice;
+            });
+            this.tableForm.detailList.push(...item.detailList);
+          });
+          this.$refs.table.reload();
+        }
+        this.$emit('setPrice', params.children.amountTotalPrice);
+        let row = {
+          id: params.id,
+          name: params.statementNo,
+          code: params.statementNo,
+          linkType: params.type == 1 ? 190 : 290,
+          linkTypeName: params.type == 1 ? '销售对账单' : '采购对账单'
+        };
+        this.setSelectData(row);
+      },
+      setValue(data) {
+        this.tableForm.detailList = data;
+      },
+      clearTable() {
+        this.tableForm = {
+          detailList: [],
+          link: []
+        };
+      },
+      getTableValidate() {
+        return new Promise((resolve, reject) => {
+          if (this.tableForm.detailList.length == 0)
+            return this.$message.warning('请选择关联信息');
+          resolve(this.tableForm);
+        });
+      },
+      setSelectData(val) {
+        this.tableForm.link = [{}];
+        this.$set(this.tableForm.link[0], 'linkId', val.id);
+        this.$set(this.tableForm.link[0], 'linkName', val.name);
+        this.$set(this.tableForm.link[0], 'linkCode', val.code);
+        this.$set(this.tableForm.link[0], 'linkType', val.linkType);
+        this.$set(this.tableForm.link[0], 'linkTypeName', val.linkTypeName);
+      },
+      getTableData() {}
+    }
+  };
+</script>
+
+<style scoped lang="scss"></style>

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

@@ -248,6 +248,7 @@
         :isProductionRequirements="true"
         :isIncreaseTotalWeight="true"
         :isWms="true"
+        :showStockCount="true"
       ></inventoryTabledetail>
       <headerTitle title="类型清单" v-if="form.needProduce == 4"></headerTitle>