liding
2026-04-07 c0790dfa4a3a7a30be3c6ecdf94799267e46948d
feat:批号
已修改2个文件
1132 ■■■■■ 文件已修改
src/views/procurementManagement/procurementLedger/index.vue 794 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/workOrder/index.vue 338 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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);
    }
src/views/productionManagement/workOrder/index.vue
@@ -5,98 +5,112 @@
      <div class="search-row">
        <div class="search-item">
          <span class="search_title">工单编号:</span>
          <el-input v-model="searchForm.workOrderNo"
          <el-input
            v-model="searchForm.workOrderNo"
                    style="width: 240px"
                    placeholder="请输入"
                    @change="handleQuery"
                    clearable
                    prefix-icon="Search"/>
            prefix-icon="Search"
          />
        </div>
        <div class="search-item">
          <span class="search_title">生产订单号:</span>
          <el-input v-model="searchForm.productOrderNpsNo"
          <el-input
            v-model="searchForm.productOrderNpsNo"
                    style="width: 240px"
                    placeholder="请输入"
                    @change="handleQuery"
                    clearable
                    prefix-icon="Search"/>
            prefix-icon="Search"
          />
        </div>
        <div class="search-item">
          <el-button type="primary"
                     @click="handleQuery">搜索
          </el-button>
          <el-button type="primary" @click="handleQuery">搜索 </el-button>
        </div>
      </div>
    </div>
    <div class="table_list">
      <PIMTable rowKey="id"
      <PIMTable
        rowKey="id"
                :column="tableColumn"
                :tableData="tableData"
                :page="page"
                :tableLoading="tableLoading"
                :rowClassName="rowClassName"
                @pagination="pagination">
        @pagination="pagination"
      >
        <template #completionStatus="{ row }">
          <el-progress :percentage="toProgressPercentage(row?.completionStatus)"
          <el-progress
            :percentage="toProgressPercentage(row?.completionStatus)"
                       :color="progressColor(toProgressPercentage(row?.completionStatus))"
                       :status="toProgressPercentage(row?.completionStatus) >= 100 ? 'success' : ''"/>
            :status="
              toProgressPercentage(row?.completionStatus) >= 100
                ? 'success'
                : ''
            "
          />
        </template>
      </PIMTable>
    </div>
    <el-dialog v-model="editDialogVisible"
               title="编辑时间"
               width="500px">
      <el-form :model="editrow"
               label-width="120px">
    <el-dialog v-model="editDialogVisible" title="编辑时间" width="500px">
      <el-form :model="editrow" label-width="120px">
        <el-form-item label="计划开始时间">
          <el-date-picker v-model="editrow.planStartTime"
          <el-date-picker
            v-model="editrow.planStartTime"
                          type="date"
                          placeholder="请选择"
                          value-format="YYYY-MM-DD"
                          style="width: 300px"/>
            style="width: 300px"
          />
        </el-form-item>
        <el-form-item label="计划结束时间">
          <el-date-picker v-model="editrow.planEndTime"
          <el-date-picker
            v-model="editrow.planEndTime"
                          type="date"
                          placeholder="请选择"
                          value-format="YYYY-MM-DD"
                          style="width: 300px"/>
            style="width: 300px"
          />
        </el-form-item>
        <el-form-item label="实际开始时间">
          <el-date-picker v-model="editrow.actualStartTime"
          <el-date-picker
            v-model="editrow.actualStartTime"
                          type="date"
                          placeholder="请选择"
                          value-format="YYYY-MM-DD"
                          style="width: 300px"/>
            style="width: 300px"
          />
        </el-form-item>
        <el-form-item label="实际结束时间">
          <el-date-picker v-model="editrow.actualEndTime"
          <el-date-picker
            v-model="editrow.actualEndTime"
                          type="date"
                          placeholder="请选择"
                          value-format="YYYY-MM-DD"
                          style="width: 300px"/>
            style="width: 300px"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary"
                     @click="handleUpdate">确定</el-button>
          <el-button type="primary" @click="handleUpdate">确定</el-button>
          <el-button @click="editDialogVisible = false">取消</el-button>
        </span>
      </template>
    </el-dialog>
    <el-dialog v-model="transferCardVisible"
               title="流转卡"
               width="1000px">
    <el-dialog v-model="transferCardVisible" title="流转卡" width="1000px">
      <div class="transfer-card-title">工单流转卡</div>
      <div class="transfer-card-container">
        <div class="transfer-card-info">
          <div class="info-group">
            <div class="info-item">
              <span class="info-label">工单编号</span>
              <span class="info-value">{{ transferCardRowData.workOrderNo }}</span>
              <span class="info-value">{{
                transferCardRowData.workOrderNo
              }}</span>
            </div>
            <!-- <div class="info-item">
              <span class="info-label">产品编号</span>
@@ -104,7 +118,9 @@
            </div> -->
            <div class="info-item">
              <span class="info-label">产品名称</span>
              <span class="info-value">{{ transferCardRowData.productName }}</span>
              <span class="info-value">{{
                transferCardRowData.productName
              }}</span>
            </div>
            <div class="info-item">
              <span class="info-label">产品规格</span>
@@ -112,7 +128,9 @@
            </div>
            <div class="info-item">
              <span class="info-label">料号</span>
              <span class="info-value">{{ transferCardRowData.materialCode }}</span>
              <span class="info-value">{{
                transferCardRowData.materialCode
              }}</span>
            </div>
            <!-- <div class="info-item">
              <span class="info-label">工单状态</span>
@@ -127,11 +145,15 @@
            <div class="info-item">
              <span class="info-label">计划开始时间</span>
              <span class="info-value">{{ transferCardRowData.planStartTime }}</span>
              <span class="info-value">{{
                transferCardRowData.planStartTime
              }}</span>
            </div>
            <div class="info-item">
              <span class="info-label">计划结束时间</span>
              <span class="info-value">{{ transferCardRowData.planEndTime }}</span>
              <span class="info-value">{{
                transferCardRowData.planEndTime
              }}</span>
            </div>
            <div class="info-item">
              <span class="info-label">备注</span>
@@ -141,11 +163,15 @@
          <div class="info-group">
            <div class="info-item">
              <span class="info-label">需求数量</span>
              <span class="info-value">{{ transferCardRowData.planQuantity }}</span>
              <span class="info-value">{{
                transferCardRowData.planQuantity
              }}</span>
            </div>
            <div class="info-item">
              <span class="info-label">完成数量</span>
              <span class="info-value">{{ transferCardRowData.completeQuantity }}</span>
              <span class="info-value">{{
                transferCardRowData.completeQuantity
              }}</span>
            </div>
            <div class="info-item">
              <span class="info-label">良品数量</span>
@@ -157,92 +183,113 @@
            </div>
            <div class="info-item">
              <span class="info-label">实际开始时间</span>
              <span class="info-value">{{ transferCardRowData.actualStartTime }}</span>
              <span class="info-value">{{
                transferCardRowData.actualStartTime
              }}</span>
            </div>
            <div class="info-item">
              <span class="info-label">实际结束时间</span>
              <span class="info-value">{{ transferCardRowData.actualEndTime }}</span>
              <span class="info-value">{{
                transferCardRowData.actualEndTime
              }}</span>
            </div>
          </div>
        </div>
        <div class="transfer-card-qr">
          <div class="qr-container">
            <img :src="transferCardQrUrl"
            <img
              :src="transferCardQrUrl"
                 alt="流转卡二维码"
                 style="width: 200px; height: 200px;"/>
              style="width: 200px; height: 200px"
            />
            <!-- <div class="qr-tip"
                 style="margin-top: 10px; text-align: center;">流转卡二维码</div> -->
          </div>
        </div>
      </div>
      <div class="print-button-container"
           style=" text-align: center;
      margin-bottom: 40px;">
        <el-button type="primary"
                   style="margin-top: 20px;"
                   @click="printTransferCard">打印流转卡
      <div
        class="print-button-container"
        style="text-align: center; margin-bottom: 40px"
      >
        <el-button
          type="primary"
          style="margin-top: 20px"
          @click="printTransferCard"
          >打印流转卡
        </el-button>
      </div>
    </el-dialog>
    <el-dialog v-model="reportDialogVisible"
               title="报工"
               width="800px">
      <el-form ref="reportFormRef"
    <el-dialog v-model="reportDialogVisible" title="报工" width="800px">
      <el-form
        ref="reportFormRef"
               :model="reportForm"
               :rules="reportFormRules"
               label-width="120px">
        label-width="120px"
      >
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="待生产数量">
              <el-input v-model="reportForm.planQuantity"
              <el-input
                v-model="reportForm.planQuantity"
                        readonly
                        style="width: 100%"/>
                style="width: 100%"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="本次生产数量" prop="quantity">
              <el-input v-model.number="reportForm.quantity"
              <el-input
                v-model.number="reportForm.quantity"
                        type="number"
                        min="1"
                        step="1"
                        style="width: 100%"
                        placeholder="请输入本次生产数量"
                        @input="handleQuantityInput"/>
                @input="handleQuantityInput"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="报废数量" prop="scrapQty">
              <el-input v-model.number="reportForm.scrapQty"
              <el-input
                v-model.number="reportForm.scrapQty"
                        type="number"
                        min="0"
                        step="1"
                        style="width: 100%"
                        placeholder="请输入报废数量"
                        @input="handleScrapQtyInput"/>
                @input="handleScrapQtyInput"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="班组信息">
              <el-select v-model="reportForm.userId"
              <el-select
                v-model="reportForm.userId"
                         style="width: 100%"
                         placeholder="请选择班组信息"
                         clearable
                         filterable
                         @change="handleUserChange">
                <el-option v-for="user in userOptions"
                @change="handleUserChange"
              >
                <el-option
                  v-for="user in userOptions"
                           :key="user.userId"
                           :label="user.userName"
                           :value="user.userId"/>
                  :value="user.userId"
                />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <ProductionRecordForm ref="productionRecordFormRef" :list="processParamList"/>
        <ProductionRecordForm
          ref="productionRecordFormRef"
          :list="processParamList"
        />
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary"
                     @click="handleReport">确定</el-button>
          <el-button type="primary" @click="handleReport">确定</el-button>
          <el-button @click="reportDialogVisible = false">取消</el-button>
        </span>
      </template>
@@ -253,19 +300,22 @@
        v-model:isShow="copperPrintingFormVisible"
        :isEdit="true"
        :row="currentReportRowData"
        @refreshData="getList"/>
      @refreshData="getList"
    />
    <VoltageSortingForm
        v-if="voltageSortingFormVisible"
        v-model:isShow="voltageSortingFormVisible"
        :isEdit="true"
        :row="currentReportRowData"
        @refreshData="getList"/>
      @refreshData="getList"
    />
    <GranulationForm
        v-if="granulationFormVisible"
        v-model:isShow="granulationFormVisible"
        :isEdit="true"
        :row="currentReportRowData"
        @refreshData="getList"/>
      @refreshData="getList"
    />
  </div>
</template>
@@ -283,25 +333,31 @@
import QRCode from "qrcode";
import {getCurrentInstance, reactive, toRefs} from "vue";
import FilesDia from "./components/filesDia.vue";
import {
  listPage as listProcessParamPage,
} from "@/api/productionManagement/productProcessParameter.js";
import { listPage as listProcessParamPage } from "@/api/productionManagement/productProcessParameter.js";
const {proxy} = getCurrentInstance();
const {priority_type} = proxy.useDict("priority_type");
const CopperPrintingForm = defineAsyncComponent(() => import("./components/CopperPrintingForm.vue"));
const VoltageSortingForm = defineAsyncComponent(() => import("./components/VoltageSortingForm.vue"));
const ProductionRecordForm = defineAsyncComponent(() => import("./components/ProductionRecordForm.vue"));
const GranulationForm = defineAsyncComponent(() => import("./components/GranulationForm.vue"));
const CopperPrintingForm = defineAsyncComponent(() =>
  import("./components/CopperPrintingForm.vue")
);
const VoltageSortingForm = defineAsyncComponent(() =>
  import("./components/VoltageSortingForm.vue")
);
const ProductionRecordForm = defineAsyncComponent(() =>
  import("./components/ProductionRecordForm.vue")
);
const GranulationForm = defineAsyncComponent(() =>
  import("./components/GranulationForm.vue")
);
const tableColumn = ref([
  {
    label: "优先级",
    prop: "priority",
    width: '100px',
    width: "100px",
    dataType: "tag",
    formatData: val => proxy.selectDictLabel(priority_type.value, val),
    formatType: val => {
    formatData: (val) => proxy.selectDictLabel(priority_type.value, val),
    formatType: (val) => {
      const v = Number(val);
      if (v === 0) return "danger";   // 红色
      if (v === 1) return "warning";  // 黄色
@@ -391,29 +447,29 @@
    operation: [
      {
        name: "编辑",
        clickFun: row => {
        clickFun: (row) => {
          handleEdit(row);
          handleEdit(row);
        },
      },
      {
        name: "流转卡",
        clickFun: row => {
        clickFun: (row) => {
          downloadAndPrintWorkOrder(row);
        },
      },
      {
        name: "附件",
        clickFun: row => {
        clickFun: (row) => {
          openWorkOrderFiles(row);
        },
      },
      {
        name: "报工",
        clickFun: row => {
        clickFun: (row) => {
          showReportDialog(row);
        },
        disabled: row => !row.isCanReport || row.planQuantity <= 0,
        disabled: (row) => !row.isCanReport || row.planQuantity <= 0,
      },
    ],
  },
@@ -444,22 +500,23 @@
  productProcessRouteItemId: "",
  userId: "",
  productMainId: null,
  batchNo: "",
  otherData: {
    rows: [],
  }
  },
});
const productionRecordFormRef = ref();
// 本次生产数量验证规则
const validateQuantity = (rule, value, callback) => {
  if (value === null || value === undefined || value === '') {
    callback(new Error('请输入本次生产数量'));
  if (value === null || value === undefined || value === "") {
    callback(new Error("请输入本次生产数量"));
    return;
  }
  const num = Number(value);
  // 整数且大于等于1
  if (isNaN(num) || !Number.isInteger(num) || num < 1) {
    callback(new Error('本次生产数量必须大于等于1'));
    callback(new Error("本次生产数量必须大于等于1"));
    return;
  }
  callback();
@@ -467,14 +524,14 @@
// 报废数量验证规则
const validateScrapQty = (rule, value, callback) => {
  if (value === null || value === undefined || value === '') {
  if (value === null || value === undefined || value === "") {
    callback();
    return;
  }
  const num = Number(value);
  // 整数且大于等于0
  if (isNaN(num) || !Number.isInteger(num) || num < 0) {
    callback(new Error('报废数量必须大于等于0'));
    callback(new Error("报废数量必须大于等于0"));
    return;
  }
  callback();
@@ -482,24 +539,23 @@
// 验证规则
const reportFormRules = {
  quantity: [
    {required: true, validator: validateQuantity, trigger: 'blur'}
  ],
  scrapQty: [
    {validator: validateScrapQty, trigger: 'blur'}
  ]
  quantity: [{ required: true, validator: validateQuantity, trigger: "blur" }],
  scrapQty: [{ validator: validateScrapQty, trigger: "blur" }],
};
const rowClassName = ({row}) => {
  if (Number(row.completionStatus) > 0 && Number(row.actualQualifiedRate) < Number(row.processQualifiedRate)) {
    return 'danger-row';
  if (
    Number(row.completionStatus) > 0 &&
    Number(row.actualQualifiedRate) < Number(row.processQualifiedRate)
  ) {
    return "danger-row";
  }
  return '';
  return "";
};
// 处理本次生产数量输入,限制必须大于等于1
const handleQuantityInput = (value) => {
  if (value === '' || value === null || value === undefined) {
  if (value === "" || value === null || value === undefined) {
    reportForm.quantity = null;
    return;
  }
@@ -528,7 +584,7 @@
// 处理报废数量
const handleScrapQtyInput = (value) => {
  if (value === '' || value === null || value === undefined) {
  if (value === "" || value === null || value === undefined) {
    reportForm.scrapQty = null;
    return;
  }
@@ -564,14 +620,14 @@
  },
});
const {searchForm} = toRefs(data);
const toProgressPercentage = val => {
const toProgressPercentage = (val) => {
  const n = Number(val);
  if (!Number.isFinite(n)) return 0;
  if (n <= 0) return 0;
  if (n >= 100) return 100;
  return Math.round(n);
};
const progressColor = percentage => {
const progressColor = (percentage) => {
  const p = toProgressPercentage(percentage);
  if (p < 30) return "#f56c6c";
  if (p < 50) return "#e6a23c";
@@ -586,7 +642,7 @@
  page.current = 1;
  getList();
};
const pagination = obj => {
const pagination = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
  getList();
@@ -595,7 +651,7 @@
  tableLoading.value = true;
  const params = {...searchForm.value, ...page};
  productWorkOrderPage(params)
      .then(res => {
    .then((res) => {
        tableLoading.value = false;
        tableData.value = res.data.records;
        page.total = res.data.total;
@@ -606,7 +662,7 @@
};
// 下载并打印工单流转卡(文件流)
const downloadAndPrintWorkOrder = async row => {
const downloadAndPrintWorkOrder = async (row) => {
  if (!row || !row.id) {
    proxy.$modal.msgError("缺少工单ID,无法下载流转卡");
    return;
@@ -625,7 +681,9 @@
    // 创建 Blob URL
    const fileBlob =
        blob instanceof Blob ? blob : new Blob([blob], {type: blob.type || "application/octet-stream"});
      blob instanceof Blob
        ? blob
        : new Blob([blob], { type: blob.type || "application/octet-stream" });
    const url = window.URL.createObjectURL(fileBlob);
    // 创建隐藏 iframe,用于触发浏览器打印
@@ -655,7 +713,7 @@
  }
};
const showTransferCard = async row => {
const showTransferCard = async (row) => {
  transferCardRowData.value = row;
  const qrContent = String(row.id);
@@ -667,14 +725,14 @@
  window.print();
};
const handleEdit = row => {
const handleEdit = (row) => {
  editrow.value = JSON.parse(JSON.stringify(row));
  editDialogVisible.value = true;
};
const handleUpdate = () => {
  updateProductWorkOrder(editrow.value)
      .then(res => {
    .then((res) => {
        proxy.$modal.msgSuccess("提交成功");
        editDialogVisible.value = false;
        getList();
@@ -696,57 +754,60 @@
    processId: row.processId,
    ...processParamPage,
  };
  const res = await listProcessParamPage(params)
  return res.data.records
  const res = await listProcessParamPage(params);
  return res.data.records;
};
const processParamList = ref([])
const showReportDialog = async row => {
const processParamList = ref([]);
const showReportDialog = async (row) => {
  currentReportRowData.value = row;
  if (row.processName === '印铜' || row.processName === '印银') {
    copperPrintingFormVisible.value = true
    return
  }
  if (row.processName === '电压分选') {
    voltageSortingFormVisible.value = true
  if (row.processName === "印铜" || row.processName === "印银") {
    copperPrintingFormVisible.value = true;
    return;
  }
  if (row.processName === '造粒') {
    granulationFormVisible.value = true
  if (row.processName === "电压分选") {
    voltageSortingFormVisible.value = true;
    return;
  }
  processParamList.value = await getProcessParamList(row)
  if (row.processName === "造粒") {
    granulationFormVisible.value = true;
    return;
  }
  processParamList.value = await getProcessParamList(row);
  reportForm.planQuantity = row.planQuantity;
  reportForm.quantity = row.quantity !== undefined && row.quantity !== null ? row.quantity : null;
  reportForm.quantity =
    row.quantity !== undefined && row.quantity !== null ? row.quantity : null;
  reportForm.productProcessRouteItemId = row.productProcessRouteItemId;
  reportForm.batchNo = row.batchNo;
  reportForm.workOrderId = row.id;
  reportForm.reportWork = row.reportWork;
  reportForm.productMainId = row.productMainId;
  reportForm.scrapQty = row.scrapQty !== undefined && row.scrapQty !== null ? row.scrapQty : null;
  reportForm.scrapQty =
    row.scrapQty !== undefined && row.scrapQty !== null ? row.scrapQty : null;
  nextTick(() => {
    reportFormRef.value?.clearValidate();
  });
  // 获取当前登录用户信息,设置为默认选中
  getUserProfile()
      .then(res => {
    .then((res) => {
        if (res.code === 200) {
          reportForm.userId = res.data.userId;
          reportForm.userName = res.data.userName;
        }
      })
      .catch(err => {
    .catch((err) => {
        console.error("获取用户信息失败", err);
      });
  reportDialogVisible.value = true;
};
const openWorkOrderFiles = row => {
const openWorkOrderFiles = (row) => {
  workOrderFilesRef.value?.openDialog(row);
};
const handleReport = async () => {
  const data = await productionRecordFormRef.value.submitData()
  const data = await productionRecordFormRef.value.submitData();
  if (!data) {
    return;
  }
@@ -764,7 +825,11 @@
    }
    // 验证本次生产数量
    if (reportForm.quantity === null || reportForm.quantity === undefined || reportForm.quantity === '') {
    if (
      reportForm.quantity === null ||
      reportForm.quantity === undefined ||
      reportForm.quantity === ""
    ) {
      ElMessageBox.alert("请输入本次生产数量", "提示", {
        confirmButtonText: "确定",
      });
@@ -772,7 +837,10 @@
    }
    const quantity = Number(reportForm.quantity);
    const scrapQty = reportForm.scrapQty === null || reportForm.scrapQty === undefined || reportForm.scrapQty === ''
    const scrapQty =
      reportForm.scrapQty === null ||
      reportForm.scrapQty === undefined ||
      reportForm.scrapQty === ""
        ? 0
        : Number(reportForm.scrapQty);
@@ -803,11 +871,11 @@
      ...reportForm,
      quantity: quantity,
      scrapQty: scrapQty,
      otherData: JSON.stringify(reportForm.otherData)
      otherData: JSON.stringify(reportForm.otherData),
    };
    // console.log(submitData);
    addProductMain(submitData).then(res => {
    addProductMain(submitData).then((res) => {
      if (res.code === 200) {
        proxy.$modal.msgSuccess("报工成功");
        reportDialogVisible.value = false;
@@ -824,12 +892,12 @@
// 获取用户列表
const getUserList = () => {
  userListNoPageByTenantId()
      .then(res => {
    .then((res) => {
        if (res.code === 200) {
          userOptions.value = res.data || [];
        }
      })
      .catch(err => {
    .catch((err) => {
        console.error("获取用户列表失败", err);
      });
};
@@ -837,7 +905,9 @@
// 用户选择变化时更新 userName
const handleUserChange = (userId) => {
  if (userId) {
    const selectedUser = userOptions.value.find(user => user.userId === userId);
    const selectedUser = userOptions.value.find(
      (user) => user.userId === userId
    );
    if (selectedUser) {
      reportForm.userName = selectedUser.userName;
    }