liding
2026-04-07 c0790dfa4a3a7a30be3c6ecdf94799267e46948d
src/views/procurementManagement/procurementLedger/index.vue
@@ -2,64 +2,72 @@
  <div class="app-container">
    <div class="search_form">
      <div>
        <el-form :model="searchForm"
                 :inline="true">
        <el-form :model="searchForm" :inline="true">
          <el-form-item label="供应商名称:">
            <el-input v-model="searchForm.supplierName"
            <el-input
              v-model="searchForm.supplierName"
                      placeholder="请输入"
                      clearable
                      prefix-icon="Search"
                      @change="handleQuery" />
              @change="handleQuery"
            />
          </el-form-item>
          <el-form-item label="采购合同号:">
            <el-input v-model="searchForm.purchaseContractNumber"
            <el-input
              v-model="searchForm.purchaseContractNumber"
                      style="width: 240px"
                      placeholder="请输入"
                      @change="handleQuery"
                      clearable
                      :prefix-icon="Search" />
              :prefix-icon="Search"
            />
          </el-form-item>
          <el-form-item label="销售合同号:">
            <el-input v-model="searchForm.salesContractNo"
            <el-input
              v-model="searchForm.salesContractNo"
                      placeholder="请输入"
                      clearable
                      prefix-icon="Search"
                      @change="handleQuery" />
              @change="handleQuery"
            />
          </el-form-item>
          <el-form-item label="项目名称:">
            <el-input v-model="searchForm.projectName"
            <el-input
              v-model="searchForm.projectName"
                      placeholder="请输入"
                      clearable
                      prefix-icon="Search"
                      @change="handleQuery" />
              @change="handleQuery"
            />
          </el-form-item>
          <el-form-item label="录入日期:">
            <el-date-picker v-model="searchForm.entryDate"
            <el-date-picker
              v-model="searchForm.entryDate"
                            value-format="YYYY-MM-DD"
                            format="YYYY-MM-DD"
                            type="daterange"
                            placeholder="请选择"
                            clearable
                            @change="changeDaterange" />
              @change="changeDaterange"
            />
          </el-form-item>
          <el-form-item>
            <el-button type="primary"
                       @click="handleQuery"> 搜索 </el-button>
            <el-button type="primary" @click="handleQuery"> 搜索 </el-button>
          </el-form-item>
        </el-form>
      </div>
    </div>
    <div class="table_list">
      <div style="display: flex;justify-content: flex-end;margin-bottom: 20px;">
        <el-button type="primary"
                   @click="openForm('add')">新增台账</el-button>
      <div
        style="display: flex; justify-content: flex-end; margin-bottom: 20px"
      >
        <el-button type="primary" @click="openForm('add')">新增台账</el-button>
        <el-button type="primary" plain @click="handleImport">导入</el-button>
        <el-button @click="handleOut">导出</el-button>
        <el-button type="danger"
                   plain
                   @click="handleDelete">删除</el-button>
        <el-button type="danger" plain @click="handleDelete">删除</el-button>
      </div>
      <el-table :data="tableData"
      <el-table
        :data="tableData"
                border
                v-loading="tableLoading"
                @selection-change="handleSelectionChange"
@@ -68,232 +76,284 @@
                show-summary
                :summary-method="summarizeMainTable"
                @expand-change="expandChange"
                height="calc(100vh - 21.5em)">
        <el-table-column align="center"
                         type="selection"
                         width="55" />
        height="calc(100vh - 21.5em)"
      >
        <el-table-column align="center" type="selection" width="55" />
        <el-table-column type="expand">
          <template #default="props">
            <el-table :data="props.row.children"
            <el-table
              :data="props.row.children"
                      border
                      show-summary
                      :summary-method="summarizeChildrenTable">
              <el-table-column align="center"
              :summary-method="summarizeChildrenTable"
            >
              <el-table-column
                align="center"
                               label="序号"
                               type="index"
                               width="60" />
              <el-table-column label="产品大类"
                               prop="productCategory" />
              <el-table-column label="规格型号"
                               prop="specificationModel" />
              <el-table-column label="单位"
                               prop="unit" />
              <el-table-column label="料号"
                               prop="materialCode" />
              <el-table-column label="数量"
                               prop="quantity" />
              <el-table-column label="税率(%)"
                               prop="taxRate" />
              <el-table-column label="含税单价(元)"
                width="60"
              />
              <el-table-column label="产品大类" prop="productCategory" />
              <el-table-column label="规格型号" prop="specificationModel" />
              <el-table-column label="单位" prop="unit" />
              <el-table-column label="料号" prop="materialCode" />
              <el-table-column label="数量" prop="quantity" />
              <el-table-column label="税率(%)" prop="taxRate" />
              <el-table-column
                label="含税单价(元)"
                               prop="taxInclusiveUnitPrice"
                               :formatter="formattedNumber" />
              <el-table-column label="含税总价(元)"
                :formatter="formattedNumber"
              />
              <el-table-column
                label="含税总价(元)"
                               prop="taxInclusiveTotalPrice"
                               :formatter="formattedNumber" />
              <el-table-column label="不含税总价(元)"
                :formatter="formattedNumber"
              />
              <el-table-column
                label="不含税总价(元)"
                               prop="taxExclusiveTotalPrice"
                               :formatter="formattedNumber" />
                :formatter="formattedNumber"
              />
            </el-table>
          </template>
        </el-table-column>
        <el-table-column align="center"
                         label="序号"
                         type="index"
                         width="60" />
        <el-table-column label="采购合同号"
        <el-table-column align="center" label="序号" type="index" width="60" />
        <el-table-column
          label="采购合同号"
                         prop="purchaseContractNumber"
                         width="160"
                         show-overflow-tooltip />
        <el-table-column label="销售合同号"
          show-overflow-tooltip
        />
        <el-table-column
          label="销售合同号"
                         prop="salesContractNo"
                          width="160"
                         show-overflow-tooltip />
        <el-table-column label="供应商名称"
          show-overflow-tooltip
        />
        <el-table-column
          label="供应商名称"
                         prop="supplierName"
                          width="160"
                         show-overflow-tooltip />
        <el-table-column label="项目名称"
          show-overflow-tooltip
        />
        <el-table-column
          label="项目名称"
                         prop="projectName"
                         width="320"
                         show-overflow-tooltip />
        <el-table-column label="审批状态"
          show-overflow-tooltip
        />
        <el-table-column
          label="审批状态"
                         prop="approvalStatus"
                         width="100"
                         show-overflow-tooltip>
          show-overflow-tooltip
        >
          <template #default="scope">
            <el-tag 
              :type="getApprovalStatusType(scope.row.approvalStatus)"
              size="small">
              {{ approvalStatusText[scope.row.approvalStatus] || '未知状态' }}
              size="small"
            >
              {{ approvalStatusText[scope.row.approvalStatus] || "未知状态" }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="签订日期"
        <el-table-column
          label="签订日期"
                         prop="executionDate"
                         width="100"
                         show-overflow-tooltip />
        <el-table-column label="付款方式"
          show-overflow-tooltip
        />
        <el-table-column
          label="付款方式"
                         width="100"
                         prop="paymentMethod"
                         show-overflow-tooltip />
        <el-table-column label="合同金额(元)"
          show-overflow-tooltip
        />
        <el-table-column
          label="合同金额(元)"
                         prop="contractAmount"
                         width="200"
                         show-overflow-tooltip
                         :formatter="formattedNumber" />
        <el-table-column label="录入人"
          :formatter="formattedNumber"
        />
        <el-table-column
          label="录入人"
                         prop="recorderName"
                         width="120"
                         show-overflow-tooltip />
        <el-table-column label="录入日期"
          show-overflow-tooltip
        />
        <el-table-column
          label="录入日期"
                         prop="entryDate"
                         width="100"
                         show-overflow-tooltip />
        <el-table-column label="备注"
          show-overflow-tooltip
        />
        <el-table-column
          label="备注"
                         prop="remarks"
                         width="200"
                         show-overflow-tooltip />
        <el-table-column fixed="right"
                         label="操作"
                         width="120"
                         align="center">
          show-overflow-tooltip
        />
        <el-table-column fixed="right" label="操作" width="120" align="center">
          <template #default="scope">
            <el-button link
            <el-button
              link
                       type="primary"
                       size="small"
                       @click="openForm('edit', scope.row)"
                       :disabled="scope.row.approvalStatus !== 1 && scope.row.approvalStatus !== 4">编辑</el-button>
            <el-button link
              :disabled="
                scope.row.approvalStatus !== 1 && scope.row.approvalStatus !== 4
              "
              >编辑</el-button
            >
            <el-button
              link
                       type="primary"
                       size="small"
                       @click="downLoadFile(scope.row)">附件</el-button>
              @click="downLoadFile(scope.row)"
              >附件</el-button
            >
          </template>
        </el-table-column>
      </el-table>
      <pagination v-show="total > 0"
      <pagination
        v-show="total > 0"
                  :total="total"
                  layout="total, sizes, prev, pager, next, jumper"
                  :page="page.current"
                  :limit="page.size"
                  @pagination="paginationChange" />
        @pagination="paginationChange"
      />
    </div>
    <FormDialog v-model="dialogFormVisible"
    <FormDialog
      v-model="dialogFormVisible"
               :title="operationType === 'add' ? '新增采购台账页面' : '编辑采购台账页面'"
               :width="'70%'"
               :operation-type="operationType"
               @close="closeDia"
               @confirm="submitForm"
               @cancel="closeDia">
      <el-form :model="form"
      @cancel="closeDia"
    >
      <el-form
        :model="form"
               label-width="140px"
               label-position="top"
               :rules="rules"
               ref="formRef">
        ref="formRef"
      >
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="采购合同号:"
                          prop="purchaseContractNumber">
              <el-input v-model="form.purchaseContractNumber"
            <el-form-item label="采购合同号:" prop="purchaseContractNumber">
              <el-input
                v-model="form.purchaseContractNumber"
                        placeholder="请输入"
                        clearable />
                clearable
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="销售合同号:"
                          prop="salesLedgerId">
              <el-select v-model="form.salesLedgerId"
            <el-form-item label="销售合同号:" prop="salesLedgerId">
              <el-select
                v-model="form.salesLedgerId"
                         placeholder="请选择"
                         filterable
                         clearable
                         @change="salesLedgerChange">
                <el-option v-for="item in salesContractList"
                @change="salesLedgerChange"
              >
                <el-option
                  v-for="item in salesContractList"
                           :key="item.id"
                           :label="item.salesContractNo"
                           :value="item.id" />
                  :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="供应商名称:"
                          prop="supplierId">
              <el-select v-model="form.supplierId"
            <el-form-item label="供应商名称:" prop="supplierId">
              <el-select
                v-model="form.supplierId"
                         placeholder="请选择"
                         filterable
                         clearable>
                <el-option v-for="item in supplierList"
                clearable
              >
                <el-option
                  v-for="item in supplierList"
                           :key="item.id"
                           :label="item.supplierName"
                                        :value="item.id" >{{item.supplierName + '---' + item.supplierType}}</el-option>
                  :value="item.id"
                  >{{
                    item.supplierName + "---" + item.supplierType
                  }}</el-option
                >
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="项目名称"
                          prop="projectName">
              <el-input v-model="form.projectName"
            <el-form-item label="项目名称" prop="projectName">
              <el-input
                v-model="form.projectName"
                        placeholder="请输入"
                        clearable />
                clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="付款方式">
              <el-input v-model="form.paymentMethod"
              <el-input
                v-model="form.paymentMethod"
                        placeholder="请输入"
                        clearable />
                clearable
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="签订日期:"
                          prop="executionDate">
              <el-date-picker style="width: 100%"
            <el-form-item label="签订日期:" prop="executionDate">
              <el-date-picker
                style="width: 100%"
                              v-model="form.executionDate"
                              value-format="YYYY-MM-DD"
                              format="YYYY-MM-DD"
                              type="date"
                              placeholder="请选择"
                              clearable />
                clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="录入人:"
                          prop="recorderId">
              <el-select v-model="form.recorderId"
            <el-form-item label="录入人:" prop="recorderId">
              <el-select
                v-model="form.recorderId"
                         placeholder="请选择"
                         clearable
                         filterable>
                <el-option v-for="item in userList"
                filterable
              >
                <el-option
                  v-for="item in userList"
                           :key="item.userId"
                           :label="item.nickName"
                           :value="item.userId" />
                  :value="item.userId"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="录入日期:"
                          prop="entryDate">
              <el-date-picker style="width: 100%"
            <el-form-item label="录入日期:" prop="entryDate">
              <el-date-picker
                style="width: 100%"
                              v-model="form.entryDate"
                              value-format="YYYY-MM-DD"
                              format="YYYY-MM-DD"
                              type="date"
                              placeholder="请选择"
                              clearable />
                clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
@@ -301,9 +361,22 @@
          <el-col :span="24">
            <el-form-item>
              <template #label>
                <div style="display: flex; align-items: center; justify-content: space-between; width: 100%;">
                <div
                  style="
                    display: flex;
                    align-items: center;
                    justify-content: space-between;
                    width: 100%;
                  "
                >
                  <span>审批人选择:</span>
                  <el-button type="primary" size="small" @click="addApproverNode" icon="Plus">新增节点</el-button>
                  <el-button
                    type="primary"
                    size="small"
                    @click="addApproverNode"
                    icon="Plus"
                    >新增节点</el-button
                  >
                </div>
              </template>
              <div class="approver-nodes-container">
@@ -313,7 +386,9 @@
                  class="approver-node-item"
                >
                  <div class="approver-node-header">
                    <span class="approver-node-label">审批节点 {{ index + 1 }}</span>
                    <span class="approver-node-label"
                      >审批节点 {{ index + 1 }}</span
                    >
                    <el-button
                      v-if="approverNodes.length > 1"
                      type="danger"
@@ -321,13 +396,14 @@
                      text
                      @click="removeApproverNode(index)"
                      icon="Delete"
                    >删除</el-button>
                      >删除</el-button
                    >
                  </div>
                  <el-select
                    v-model="node.userId"
                    placeholder="请选择审批人"
                    filterable
                    style="width: 100%;"
                    style="width: 100%"
                  >
                    <el-option
                      v-for="user in userList"
@@ -342,18 +418,21 @@
          </el-col>
        </el-row>
        <el-row>
          <el-form-item label="产品信息:"
                        prop="entryDate">
            <el-button type="primary"
                       @click="openProductForm('add')">添加</el-button>
            <el-button plain
                       type="danger"
                       @click="deleteProduct">删除</el-button>
          <el-form-item label="产品信息:" prop="entryDate">
            <el-button type="primary" @click="openProductForm('add')"
              >添加</el-button
            >
            <el-button plain type="danger" @click="deleteProduct"
              >删除</el-button
            >
          </el-form-item>
          <div class="select-button-group"
               style="width: 500px; margin: 20px 0;"
               v-if="operationType === 'add'">
            <el-select filterable
          <div
            class="select-button-group"
            style="width: 500px; margin: 20px 0"
            v-if="operationType === 'add'"
          >
            <el-select
              filterable
                       allow-create
                       :reserve-keyword="true"
                       :default-first-option="false"
@@ -363,77 +442,100 @@
                       @filter-change="onTemplateFilterChange"
                       @change="onTemplateChange"
                       @focus="getTemplateList"
                       style="width: 500px;"
              style="width: 500px"
                       placeholder="请选择模版或者输入新的模版名称后选择"
                       class="no-arrow-select">
              <el-option v-for="item in templateList"
              class="no-arrow-select"
            >
              <el-option
                v-for="item in templateList"
                         :key="item.id || item.value"
                         :label="item.templateName"
                         :value="item.templateName">
                <div style="display: flex; justify-content: space-between; align-items: center;">
                :value="item.templateName"
              >
                <div
                  style="
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                  "
                >
                  <span>{{ item.templateName }}</span>
                  <el-icon 
                    v-if="item.id"
                    class="delete-icon"
                    @click.stop="handleDeleteTemplate(item)"
                    style="cursor: pointer; color: #f56c6c; font-size: 14px; margin-left: 8px;">
                    style="
                      cursor: pointer;
                      color: #f56c6c;
                      font-size: 14px;
                      margin-left: 8px;
                    "
                  >
                    <Delete />
                  </el-icon>
                </div>
              </el-option>
            </el-select>
            <!-- 按钮:与 Select 高度匹配,去掉左侧边框,无缝衔接 -->
            <el-button size="small"
                       style="height: 32px;margin-left: 8px;"
            <el-button
              size="small"
              style="height: 32px; margin-left: 8px"
                       @click="handleButtonClick"
                       :disabled="!templateName || templateName.trim() === '' || (!currentTemplateId && isTemplateNameDuplicate)">
              :disabled="
                !templateName ||
                templateName.trim() === '' ||
                (!currentTemplateId && isTemplateNameDuplicate)
              "
            >
              保存
            </el-button>
          </div>
        </el-row>
        <el-table :data="productData"
        <el-table
          :data="productData"
                  border
                  @selection-change="productSelected"
                  show-summary
                  :summary-method="summarizeProTable">
          <el-table-column align="center"
                           type="selection"
                           width="55" />
          <el-table-column align="center"
          :summary-method="summarizeProTable"
        >
          <el-table-column align="center" type="selection" width="55" />
          <el-table-column
            align="center"
                           label="序号"
                           type="index"
                           width="60" />
          <el-table-column label="产品大类"
                           prop="productCategory" />
          <el-table-column label="规格型号"
                           prop="specificationModel" />
          <el-table-column label="料号"
                           prop="materialCode" />
          <el-table-column label="单位"
                           prop="unit"
                           width="70" />
          <el-table-column label="数量"
                           prop="quantity"
                           width="70" />
          <el-table-column label="库存预警数量"
            width="60"
          />
          <el-table-column label="产品大类" prop="productCategory" />
          <el-table-column label="规格型号" prop="specificationModel" />
          <el-table-column label="料号" prop="materialCode" />
          <el-table-column label="批号" prop="batchNo" />
          <el-table-column label="单位" prop="unit" width="70" />
          <el-table-column label="数量" prop="quantity" width="70" />
          <el-table-column
            label="库存预警数量"
                           prop="warnNum"
                           width="120"
                           show-overflow-tooltip />
          <el-table-column label="税率(%)"
                           prop="taxRate"
                           width="80" />
          <el-table-column label="含税单价(元)"
            show-overflow-tooltip
          />
          <el-table-column label="税率(%)" prop="taxRate" width="80" />
          <el-table-column
            label="含税单价(元)"
                           prop="taxInclusiveUnitPrice"
                           :formatter="formattedNumber"
                           width="150" />
          <el-table-column label="含税总价(元)"
            width="150"
          />
          <el-table-column
            label="含税总价(元)"
                           prop="taxInclusiveTotalPrice"
                           :formatter="formattedNumber"
                           width="150" />
          <el-table-column label="不含税总价(元)"
            width="150"
          />
          <el-table-column
            label="不含税总价(元)"
                           prop="taxExclusiveTotalPrice"
                           :formatter="formattedNumber"
                           width="150" />
            width="150"
          />
<!--          <el-table-column label="是否质检"-->
<!--                           prop="isChecked"-->
<!--                           width="150">-->
@@ -443,35 +545,41 @@
<!--              </el-tag>-->
<!--            </template>-->
<!--          </el-table-column>-->
          <el-table-column fixed="right"
          <el-table-column
            fixed="right"
                           label="操作"
                           min-width="60"
                           align="center">
            align="center"
          >
            <template #default="scope">
              <el-button link
              <el-button
                link
                         type="primary"
                         size="small"
                         @click="openProductForm('edit', scope.row, scope.$index)">编辑</el-button>
                @click="openProductForm('edit', scope.row, scope.$index)"
                >编辑</el-button
              >
            </template>
          </el-table-column>
        </el-table>
        <el-row :gutter="30">
          <el-col :span="24">
            <el-form-item label="备注·:"
                          prop="remarks">
              <el-input v-model="form.remarks"
            <el-form-item label="备注·:" prop="remarks">
              <el-input
                v-model="form.remarks"
                        placeholder="请输入"
                        clearable
                        type="textarea"
                        :rows="2" />
                :rows="2"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="24">
            <el-form-item label="附件材料:"
                          prop="purchaseLedgerFiles">
              <el-upload v-model:file-list="fileList"
            <el-form-item label="附件材料:" prop="purchaseLedgerFiles">
              <el-upload
                v-model:file-list="fileList"
                         :action="upload.url"
                         multiple
                         ref="fileUpload"
@@ -480,7 +588,8 @@
                         :before-upload="handleBeforeUpload"
                         :on-error="handleUploadError"
                         :on-success="handleUploadSuccess"
                         :on-remove="handleRemove">
                :on-remove="handleRemove"
              >
                <el-button type="primary">上传</el-button>
                <template #tip>
                  <div class="el-upload__tip">
@@ -518,179 +627,195 @@
        drag
      >
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">
          将文件拖到此处,或<em>点击上传</em>
        </div>
        <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
        <template #tip>
          <div class="el-upload__tip">
            仅支持 xls/xlsx,大小不超过 10MB。
            <el-button link type="primary" @click="downloadTemplate">下载导入模板</el-button>
            <el-button link type="primary" @click="downloadTemplate"
              >下载导入模板</el-button
            >
          </div>
        </template>
      </el-upload>
    </FormDialog>
    <FormDialog v-model="productFormVisible"
    <FormDialog
      v-model="productFormVisible"
               :title="productOperationType === 'add' ? '新增产品' : '编辑产品'"
               :width="'40%'"
               :operation-type="productOperationType"
               @close="closeProductDia"
               @confirm="submitProduct"
               @cancel="closeProductDia">
      <el-form :model="productForm"
      @cancel="closeProductDia"
    >
      <el-form
        :model="productForm"
               label-width="140px"
               label-position="top"
               :rules="productRules"
               ref="productFormRef">
        ref="productFormRef"
      >
        <el-row :gutter="30">
          <el-col :span="24">
            <el-form-item label="产品大类:"
                          prop="productId">
              <el-tree-select v-model="productForm.productId"
            <el-form-item label="产品大类:" prop="productId">
              <el-tree-select
                v-model="productForm.productId"
                              placeholder="请选择"
                              clearable
                              check-strictly
                              @change="getModels"
                              :data="productOptions"
                              :render-after-expand="false"
                              style="width: 100%" />
                style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="24">
            <el-form-item label="规格型号:"
                          prop="productModelId">
              <el-select v-model="productForm.productModelId"
            <el-form-item label="规格型号:" prop="productModelId">
              <el-select
                v-model="productForm.productModelId"
                         placeholder="请选择"
                         clearable
                         @change="getProductModel">
                <el-option v-for="item in modelOptions"
                @change="getProductModel"
              >
                <el-option
                  v-for="item in modelOptions"
                           :key="item.id"
                           :label="item.model"
                           :value="item.id" />
                  :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="料号:"
                          prop="materialCode">
              <el-input v-model="productForm.materialCode"
            <el-form-item label="料号:" prop="materialCode">
              <el-input
                v-model="productForm.materialCode"
                        placeholder="请输入"
                        disabled />
                disabled
              />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="批号:"
                          prop="batchNo">
              <el-input v-model="productForm.batchNo"
            <el-form-item label="批号:" prop="batchNo">
              <el-input
                v-model="productForm.batchNo"
                        clearable
                        placeholder="选填,可输入批号;留空将自动生成" />
                placeholder="选填,可输入批号;留空将自动生成"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="单位:"
                          prop="unit">
              <el-input v-model="productForm.unit"
            <el-form-item label="单位:" prop="unit">
              <el-input
                v-model="productForm.unit"
                        placeholder="请输入"
                        clearable />
                clearable
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="税率(%):"
                          prop="taxRate">
              <el-select v-model="productForm.taxRate"
            <el-form-item label="税率(%):" prop="taxRate">
              <el-select
                v-model="productForm.taxRate"
                         placeholder="请选择"
                         clearable
                         @change="mathNum">
                <el-option label="1"
                           value="1" />
                <el-option label="6"
                           value="6" />
                <el-option label="13"
                           value="13" />
                @change="mathNum"
              >
                <el-option label="1" value="1" />
                <el-option label="6" value="6" />
                <el-option label="13" value="13" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="含税单价(元):"
                          prop="taxInclusiveUnitPrice">
              <el-input-number v-model="productForm.taxInclusiveUnitPrice"
            <el-form-item label="含税单价(元):" prop="taxInclusiveUnitPrice">
              <el-input-number
                v-model="productForm.taxInclusiveUnitPrice"
                               :precision="2"
                               :step="0.1"
                               :min="0"
                               clearable
                               style="width: 100%"
                               @change="mathNum" />
                @change="mathNum"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="数量:"
                          prop="quantity">
              <el-input-number :step="0.1"
            <el-form-item label="数量:" prop="quantity">
              <el-input-number
                :step="0.1"
                               clearable
                               :precision="2"
                               :min="0"
                               style="width: 100%"
                               v-model="productForm.quantity"
                               placeholder="请输入"
                               @change="mathNum" />
                @change="mathNum"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="含税总价(元):"
                          prop="taxInclusiveTotalPrice">
              <el-input-number v-model="productForm.taxInclusiveTotalPrice"
            <el-form-item label="含税总价(元):" prop="taxInclusiveTotalPrice">
              <el-input-number
                v-model="productForm.taxInclusiveTotalPrice"
                               :precision="2"
                               :step="0.1"
                               :min="0"
                               clearable
                               style="width: 100%"
                               @change="reverseMathNum('taxInclusiveTotalPrice')" />
                @change="reverseMathNum('taxInclusiveTotalPrice')"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="不含税总价(元):"
                          prop="taxExclusiveTotalPrice">
              <el-input-number v-model="productForm.taxExclusiveTotalPrice"
            <el-form-item
              label="不含税总价(元):"
              prop="taxExclusiveTotalPrice"
            >
              <el-input-number
                v-model="productForm.taxExclusiveTotalPrice"
                               :precision="2"
                               :step="0.1"
                               :min="0"
                               clearable
                               style="width: 100%"
                               @change="reverseMathNum('taxExclusiveTotalPrice')" />
                @change="reverseMathNum('taxExclusiveTotalPrice')"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="发票类型:"
                          prop="invoiceType">
              <el-select v-model="productForm.invoiceType"
            <el-form-item label="发票类型:" prop="invoiceType">
              <el-select
                v-model="productForm.invoiceType"
                         placeholder="请选择"
                         clearable>
                <el-option label="增普票"
                           value="增普票" />
                <el-option label="增专票"
                           value="增专票" />
                clearable
              >
                <el-option label="增普票" value="增普票" />
                <el-option label="增专票" value="增专票" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="库存预警数量:"
                          prop="warnNum">
              <el-input-number v-model="productForm.warnNum"
            <el-form-item label="库存预警数量:" prop="warnNum">
              <el-input-number
                v-model="productForm.warnNum"
                               :precision="2"
                               :step="0.1"
                               :min="0"
                               clearable
                               style="width: 100%" />
                style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
@@ -731,8 +856,8 @@
  import { Search, Delete } from "@element-plus/icons-vue";
  import { ElMessageBox, ElMessage } from "element-plus";
  import { userListNoPage } from "@/api/system/user.js";
  import FormDialog from '@/components/Dialog/FormDialog.vue';
  import FileListDialog from '@/components/Dialog/FileListDialog.vue';
import FormDialog from "@/components/Dialog/FormDialog.vue";
import FileListDialog from "@/components/Dialog/FileListDialog.vue";
  import {
    getSalesLedgerWithProducts,
    addOrUpdateSalesLedgerProduct,
@@ -816,13 +941,13 @@
  const currentTemplateId = ref(null);
  // 检查模板名称是否重复
  const checkTemplateNameDuplicate = name => {
const checkTemplateNameDuplicate = (name) => {
    if (!name || name.trim() === "") {
      isTemplateNameDuplicate.value = false;
      return false;
    }
    const isDuplicate = templateList.value.some(
      item => item.templateName === name.trim()
    (item) => item.templateName === name.trim()
    );
    isTemplateNameDuplicate.value = isDuplicate;
    return isDuplicate;
@@ -830,7 +955,7 @@
  // 防抖定时器
  let duplicateCheckTimer = null;
  const onTemplateFilterChange = val => {
const onTemplateFilterChange = (val) => {
    filterInputValue.value = val ?? "";
    // 清除之前的定时器
    if (duplicateCheckTimer) {
@@ -854,7 +979,7 @@
  };
  // allow-create 时,输入不存在的内容会作为 string 值返回;这里同步回输入框以确保文字不丢
  const onTemplateChange = async val => {
const onTemplateChange = async (val) => {
    if (typeof val === "string") {
      filterInputValue.value = val;
      // 选择或输入时检查重复
@@ -863,7 +988,7 @@
    // 过滤数据,查找匹配的模板
    const matchedTemplate = templateList.value.find(
      item => item.templateName === val
    (item) => item.templateName === val
    );
    if (matchedTemplate?.id) {
@@ -885,7 +1010,8 @@
        form.value.paymentMethod = matchedTemplate.paymentMethod;
      }
      // 模板数据中的产品字段是 productList,需要转换为 productData
      productData.value = matchedTemplate.productList || matchedTemplate.productData || [];
    productData.value =
      matchedTemplate.productList || matchedTemplate.productData || [];
    } else {
      // 未匹配到已有模板,视为新模板
      currentTemplateId.value = null;
@@ -1070,7 +1196,11 @@
  // 下载导入模板(如后端路径不同,可在此处调整)
  const downloadTemplate = () => {
    proxy.download("/purchase/ledger/exportTemplate", {}, "采购台账导入模板.xlsx");
  proxy.download(
    "/purchase/ledger/exportTemplate",
    {},
    "采购台账导入模板.xlsx"
  );
  };
  const submitImportFile = () => {
@@ -1078,7 +1208,7 @@
    proxy.$refs["importUploadRef"]?.submit?.();
  };
  const changeDaterange = value => {
const changeDaterange = (value) => {
    if (value) {
      searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
      searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
@@ -1135,8 +1265,8 @@
    // 检查是否有产品数据
    if (!productData.value || productData.value.length === 0) {
      ElMessage({
        message: '请先添加产品信息',
        type: 'warning',
      message: "请先添加产品信息",
      type: "warning",
      });
      return;
    }
@@ -1144,8 +1274,8 @@
    try {
      // 获取审批人ID字符串
      const approveUserIds = approverNodes.value
        .filter(node => node.userId)
        .map(node => node.userId)
      .filter((node) => node.userId)
      .map((node) => node.userId)
        .join(",");
      
      let params = {
@@ -1157,7 +1287,12 @@
        approveUserIds: approveUserIds,
        templateName: templateName.value.trim(),
      };
      console.log("template params ===>", params, "currentTemplateId:", currentTemplateId.value);
    console.log(
      "template params ===>",
      params,
      "currentTemplateId:",
      currentTemplateId.value
    );
      // 如果 currentTemplateId 有值,说明当前是“编辑已有模板” → 调用更新接口
      // 否则为“新建模板” → 调用新增接口
@@ -1199,7 +1334,7 @@
    }
  };
  // 子表合计方法
  const summarizeChildrenTable = param => {
const summarizeChildrenTable = (param) => {
    return proxy.summarizeTable(
      param,
      [
@@ -1217,7 +1352,7 @@
      }
    );
  };
  const paginationChange = obj => {
const paginationChange = (obj) => {
    page.current = obj.page;
    page.size = obj.limit;
    getList();
@@ -1226,14 +1361,14 @@
    tableLoading.value = true;
    const { entryDate, ...rest } = searchForm;
    purchaseListPage({ ...rest, ...page })
      .then(res => {
    .then((res) => {
        tableLoading.value = false;
        // tableData.value = res.data.records;
        tableData.value = res.data.records.map(record => ({
      tableData.value = res.data.records.map((record) => ({
          ...record,
        }));
        // 初始化子数据数组
        tableData.value.forEach(item => {
      tableData.value.forEach((item) => {
          item.children = [];
        });
        total.value = res.data.total;
@@ -1244,10 +1379,10 @@
      });
  };
  // 表格选择数据
  const handleSelectionChange = selection => {
const handleSelectionChange = (selection) => {
    selectedRows.value = selection;
  };
  const productSelected = selectedRows => {
const productSelected = (selectedRows) => {
    productSelectedRows.value = selectedRows;
  };
  const expandedRowKeys = ref([]);
@@ -1257,7 +1392,7 @@
      expandedRowKeys.value = [];
      try {
        const res = await productList({ salesLedgerId: row.id, type: 2 });
        const index = tableData.value.findIndex(item => item.id === row.id);
      const index = tableData.value.findIndex((item) => item.id === row.id);
        if (index > -1) {
          tableData.value[index].children = res.data || [];
          expandedRowKeys.value.push(row.id);
@@ -1266,7 +1401,7 @@
        console.error("加载产品列表失败:", error);
        proxy.$modal.msgError("加载产品列表失败");
        // 展开失败时,移除展开状态
        const index = expandedRows.findIndex(item => item.id === row.id);
      const index = expandedRows.findIndex((item) => item.id === row.id);
        if (index > -1) {
          expandedRows.splice(index, 1);
        }
@@ -1276,11 +1411,11 @@
    }
  };
  // 主表合计方法
  const summarizeMainTable = param => {
const summarizeMainTable = (param) => {
    return proxy.summarizeTable(param, ["contractAmount"]);
  };
  // 子表合计方法
  const summarizeProTable = param => {
const summarizeProTable = (param) => {
    return proxy.summarizeTable(param, [
      "taxInclusiveUnitPrice",
      "taxInclusiveTotalPrice",
@@ -1320,7 +1455,7 @@
      salesContractList.value = salesRes || [];
      // 供应商过滤出isWhite=0 的数据
      supplierList.value = (supplierRes.data || []).filter(
        item => item.isWhite === 0
      (item) => item.isWhite === 0
      );
      // 设置默认值
@@ -1351,7 +1486,7 @@
            const approverIds = purchaseRes.approveUserIds.split(",");
            approverNodes.value = approverIds.map((id, index) => ({
              id: index + 1,
              userId: Number(id)
            userId: Number(id),
            }));
            nextApproverId = approverIds.length + 1;
          }
@@ -1421,21 +1556,23 @@
  }
  // 提交表单
  const submitForm = () => {
    proxy.$refs["formRef"].validate(valid => {
  proxy.$refs["formRef"].validate((valid) => {
      if (valid) {
        // 审批人必填校验(所有节点都要选人)
        const hasEmptyApprover = approverNodes.value.some(node => !node.userId);
      const hasEmptyApprover = approverNodes.value.some((node) => !node.userId);
        if (hasEmptyApprover) {
          proxy.$modal.msgError("请为所有审批节点选择审批人!");
          return;
        }
        const approveUserIds = approverNodes.value.map(node => node.userId).join(",");
      const approveUserIds = approverNodes.value
        .map((node) => node.userId)
        .join(",");
        
        if (productData.value.length > 0) {
          // 新增时,需要从每个产品对象中删除 id 字段
          let processedProductData = productData.value;
          if (operationType.value === "add") {
            processedProductData = productData.value.map(product => {
          processedProductData = productData.value.map((product) => {
              const { id, ...rest } = product;
              return rest;
            });
@@ -1447,7 +1584,7 @@
        }
        let tempFileIds = [];
        if (fileList.value.length > 0) {
          tempFileIds = fileList.value.map(item => item.tempId);
        tempFileIds = fileList.value.map((item) => item.tempId);
        }
        form.value.tempFileIds = tempFileIds;
        form.value.type = 2;
@@ -1464,7 +1601,7 @@
          delete submitData.id;
        }
        addOrEditPurchase(submitData).then(res => {
      addOrEditPurchase(submitData).then((res) => {
          proxy.$modal.msgSuccess("提交成功");
          closeDia();
          getList();
@@ -1524,14 +1661,20 @@
              return nodes[i].value;
            }
            if (nodes[i].children && nodes[i].children.length > 0) {
              const found = findProductIdByCategory(nodes[i].children, categoryName);
            const found = findProductIdByCategory(
              nodes[i].children,
              categoryName
            );
              if (found) return found;
            }
          }
          return null;
        };
        
        const productId = findProductIdByCategory(productOptions.value, productForm.value.productCategory);
      const productId = findProductIdByCategory(
        productOptions.value,
        productForm.value.productCategory
      );
        if (productId) {
          productForm.value.productId = productId;
          // 获取型号列表并等待完成
@@ -1542,9 +1685,12 @@
          await nextTick();
          
          // 根据 specificationModel 查找 productModelId
          if (productForm.value.specificationModel && modelOptions.value.length > 0) {
        if (
          productForm.value.specificationModel &&
          modelOptions.value.length > 0
        ) {
            const modelItem = modelOptions.value.find(
              item => item.model === productForm.value.specificationModel
            (item) => item.model === productForm.value.specificationModel
            );
            if (modelItem) {
              productForm.value.productModelId = modelItem.id;
@@ -1570,7 +1716,7 @@
    }
  };
  const getProductOptions = () => {
    return productTreeList().then(res => {
  return productTreeList().then((res) => {
      const tree = convertIdToValue(res);
      productOptions.value = filterOutSemiFinished(tree);
      return res;
@@ -1579,11 +1725,11 @@
  const filterOutSemiFinished = (nodes = []) => {
    return (nodes || [])
      .filter(node => {
    .filter((node) => {
        const label = String(node?.label ?? "");
        return !label.includes("半成品");
      })
      .map(node => {
    .map((node) => {
        const next = { ...node };
        if (next.children && next.children.length > 0) {
          next.children = filterOutSemiFinished(next.children);
@@ -1591,11 +1737,11 @@
        return next;
      });
  };
  const getModels = value => {
const getModels = (value) => {
    if (value) {
      productForm.value.productCategory =
        findNodeById(productOptions.value, value) || "";
      return modelList({ id: value }).then(res => {
    return modelList({ id: value }).then((res) => {
        modelOptions.value = res;
        return res;
      });
@@ -1605,8 +1751,8 @@
      return Promise.resolve([]);
    }
  };
  const getProductModel = value => {
    const index = modelOptions.value.findIndex(item => item.id === value);
const getProductModel = (value) => {
  const index = modelOptions.value.findIndex((item) => item.id === value);
    if (index !== -1) {
      productForm.value.specificationModel = modelOptions.value[index].model;
      productForm.value.unit = modelOptions.value[index].unit;
@@ -1632,7 +1778,7 @@
    return null; // 没有找到节点,返回null
  };
  function convertIdToValue(data) {
    return data.map(item => {
  return data.map((item) => {
      const { id, children, ...rest } = item;
      const newItem = {
        ...rest,
@@ -1650,7 +1796,9 @@
  const generateProductBatchNo = () => {
    const d = new Date();
    const pad = (n) => String(n).padStart(2, "0");
    const ts = `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
  const ts = `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(
    d.getDate()
  )}${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
    const r = Math.floor(Math.random() * 10000)
      .toString()
      .padStart(4, "0");
@@ -1664,7 +1812,7 @@
  // 提交产品表单
  const submitProduct = () => {
    proxy.$refs["productFormRef"].validate(valid => {
  proxy.$refs["productFormRef"].validate((valid) => {
      if (valid) {
        ensureProductBatchNo();
        if (operationType.value === "edit") {
@@ -1686,10 +1834,10 @@
  const submitProductEdit = () => {
    productForm.value.salesLedgerId = currentId.value;
    productForm.value.type = 2;
    addOrUpdateSalesLedgerProduct(productForm.value).then(res => {
  addOrUpdateSalesLedgerProduct(productForm.value).then((res) => {
      proxy.$modal.msgSuccess("提交成功");
      closeProductDia();
      getPurchaseById({ id: currentId.value, type: 2 }).then(res => {
    getPurchaseById({ id: currentId.value, type: 2 }).then((res) => {
        productData.value = res.productData;
      });
    });
@@ -1701,9 +1849,9 @@
      return;
    }
    if (operationType.value === "add") {
      productSelectedRows.value.forEach(selectedRow => {
    productSelectedRows.value.forEach((selectedRow) => {
        const index = productData.value.findIndex(
          product => product.id === selectedRow.id
        (product) => product.id === selectedRow.id
        );
        if (index !== -1) {
          productData.value.splice(index, 1);
@@ -1712,7 +1860,7 @@
    } else {
      let ids = [];
      if (productSelectedRows.value.length > 0) {
        ids = productSelectedRows.value.map(item => item.id);
      ids = productSelectedRows.value.map((item) => item.id);
      }
      ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "导出", {
        confirmButtonText: "确认",
@@ -1720,14 +1868,12 @@
        type: "warning",
      })
        .then(() => {
          delProduct(ids).then(res => {
        delProduct(ids).then((res) => {
            proxy.$modal.msgSuccess("删除成功");
            closeProductDia();
            getPurchaseById({ id: currentId.value, type: 2 }).then(
              res => {
          getPurchaseById({ id: currentId.value, type: 2 }).then((res) => {
                productData.value = res.productData;
              }
            );
          });
          });
        })
        .catch(() => {
@@ -1758,7 +1904,7 @@
  const handleDelete = () => {
    let ids = [];
    if (selectedRows.value.length > 0) {
      ids = selectedRows.value.map(item => item.id);
    ids = selectedRows.value.map((item) => item.id);
    } else {
      proxy.$modal.msgWarning("请选择数据");
      return;
@@ -1769,7 +1915,7 @@
      type: "warning",
    })
      .then(() => {
        delPurchase(ids).then(res => {
      delPurchase(ids).then((res) => {
          proxy.$modal.msgSuccess("删除成功");
          getList();
        });
@@ -1812,7 +1958,7 @@
        );
    }
  };
  const reverseMathNum = field => {
const reverseMathNum = (field) => {
    if (!productForm.value.taxRate) {
      proxy.$modal.msgWarning("请先选择税率");
      return;
@@ -1900,9 +2046,9 @@
    }
  };
  // 销售合同选择改变方法
  const salesLedgerChange = async row => {
const salesLedgerChange = async (row) => {
    console.log("row", row);
    var index = salesContractList.value.findIndex(item => item.id == row);
  var index = salesContractList.value.findIndex((item) => item.id == row);
    console.log("index", index);
    if (index > -1) {
      await querygProductInfoByContractNo();
@@ -1920,7 +2066,7 @@
  const fileListRef = ref(null);
  const fileListDialogVisible = ref(false);
  const downLoadFile = row => {
const downLoadFile = (row) => {
    if (fileListRef.value) {
      fileListRef.value.open(row.salesLedgerFiles);
    }