src/views/procurementManagement/procurementLedger/index.vue
@@ -53,6 +53,7 @@
      <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
@@ -89,6 +90,11 @@
                               prop="unit" />
              <el-table-column label="数量"
                               prop="quantity" />
              <el-table-column label="可用数量"
                               prop="availableQuality" />
              <el-table-column label="退货数量"
                               prop="returnQuality" />
              <el-table-column label="税率(%)"
                               prop="taxRate" />
              <el-table-column label="含税单价(元)"
@@ -156,6 +162,10 @@
                         prop="entryDate"
                         width="100"
                         show-overflow-tooltip />
        <el-table-column label="备注"
                         prop="remarks"
                         width="200"
                         show-overflow-tooltip />
        <el-table-column fixed="right"
                         label="操作"
                         width="120"
@@ -163,12 +173,10 @@
          <template #default="scope">
            <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
                       type="primary"
                       size="small"
                       @click="downLoadFile(scope.row)">附件</el-button>
          </template>
        </el-table-column>
@@ -228,7 +236,7 @@
                <el-option v-for="item in supplierList"
                           :key="item.id"
                           :label="item.supplierName"
                           :value="item.id" />
                                        :value="item.id" >{{item.supplierName + '---' + item.supplierType}}</el-option>
              </el-select>
            </el-form-item>
          </el-col>
@@ -287,50 +295,6 @@
                              type="date"
                              placeholder="请选择"
                              clearable />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="24">
            <el-form-item>
              <template #label>
                <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>
                </div>
              </template>
              <div class="approver-nodes-container">
                <div
                  v-for="(node, index) in approverNodes"
                  :key="node.id"
                  class="approver-node-item"
                >
                  <div class="approver-node-header">
                    <span class="approver-node-label">审批节点 {{ index + 1 }}</span>
                    <el-button
                      v-if="approverNodes.length > 1"
                      type="danger"
                      size="small"
                      text
                      @click="removeApproverNode(index)"
                      icon="Delete"
                    >删除</el-button>
                  </div>
                  <el-select
                    v-model="node.userId"
                    placeholder="请选择审批人"
                    filterable
                    style="width: 100%;"
                  >
                    <el-option
                      v-for="user in userList"
                      :key="user.userId"
                      :label="user.nickName"
                      :value="user.userId"
                    />
                  </el-select>
                </div>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
@@ -441,7 +405,6 @@
            <template #default="scope">
              <el-button link
                         type="primary"
                         size="small"
                         @click="openProductForm('edit', scope.row, scope.$index)">编辑</el-button>
            </template>
          </el-table-column>
@@ -449,8 +412,8 @@
        <el-row :gutter="30">
          <el-col :span="24">
            <el-form-item label="备注·:"
                          prop="remark">
              <el-input v-model="form.remark"
                          prop="remarks">
              <el-input v-model="form.remarks"
                        placeholder="请输入"
                        clearable
                        type="textarea"
@@ -461,7 +424,7 @@
        <el-row :gutter="30">
          <el-col :span="24">
            <el-form-item label="附件材料:"
                          prop="remark">
                          prop="purchaseLedgerFiles">
              <el-upload v-model:file-list="fileList"
                         :action="upload.url"
                         multiple
@@ -485,6 +448,41 @@
        </el-row>
      </el-form>
    </FormDialog>
    <!-- 导入弹窗 -->
    <FormDialog
      v-model="importUpload.open"
      :title="importUpload.title"
      :width="'600px'"
      @close="importUpload.open = false"
      @confirm="submitImportFile"
      @cancel="importUpload.open = false"
    >
      <el-upload
        ref="importUploadRef"
        :limit="1"
        accept=".xlsx,.xls"
        :action="importUpload.url"
        :headers="importUpload.headers"
        :before-upload="importUpload.beforeUpload"
        :on-success="importUpload.onSuccess"
        :on-error="importUpload.onError"
        :on-progress="importUpload.onProgress"
        :on-change="importUpload.onChange"
        :auto-upload="false"
        drag
      >
        <i class="el-icon-upload"></i>
        <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>
          </div>
        </template>
      </el-upload>
    </FormDialog>
    <FormDialog v-model="productFormVisible"
               :title="productOperationType === 'add' ? '新增产品' : '编辑产品'"
               :width="'40%'"
@@ -504,6 +502,7 @@
              <el-tree-select v-model="productForm.productId"
                              placeholder="请选择"
                              clearable
                              filterable
                              check-strictly
                              @change="getModels"
                              :data="productOptions"
@@ -518,6 +517,7 @@
                          prop="productModelId">
              <el-select v-model="productForm.productModelId"
                         placeholder="请选择"
                         filterable
                         clearable
                         @change="getProductModel">
                <el-option v-for="item in modelOptions"
@@ -718,16 +718,6 @@
  const userStore = useUserStore();
  // 审批人节点(仿销售台账发货审批人)
  const approverNodes = ref([{ id: 1, userId: null }]);
  let nextApproverId = 2;
  const addApproverNode = () => {
    approverNodes.value.push({ id: nextApproverId++, userId: null });
  };
  const removeApproverNode = (index) => {
    approverNodes.value.splice(index, 1);
  };
  // 订单审批状态显示文本
  const approvalStatusText = {
    1: "待审核",
@@ -872,14 +862,11 @@
      supplierId: "",
      paymentMethod: "",
      executionDate: "",
      isChecked: true,
      isChecked: false,
    },
    rules: {
      purchaseContractNumber: [
        { required: true, message: "请输入", trigger: "blur" },
      ],
      approverId: [
        { required: true, message: "请选择审批人", trigger: "change" },
      ],
      projectName: [
        { required: true, message: "请输入项目名称", trigger: "blur" },
@@ -920,7 +907,7 @@
      taxExclusiveTotalPrice: "",
      invoiceType: "",
      warnNum: "",
      isChecked: true,
      isChecked: false,
    },
    productRules: {
      productId: [{ required: true, message: "请选择", trigger: "change" }],
@@ -949,6 +936,71 @@
    // 设置上传的请求头部
    headers: { Authorization: "Bearer " + getToken() },
  });
  // 导入相关
  const importUploadRef = ref(null);
  const importUpload = reactive({
    title: "导入采购台账",
    open: false,
    url: import.meta.env.VITE_APP_BASE_API + "/purchase/ledger/import",
    headers: { Authorization: "Bearer " + getToken() },
    isUploading: false,
    beforeUpload: (file) => {
      const isExcel = file.name.endsWith(".xlsx") || file.name.endsWith(".xls");
      const isLt10M = file.size / 1024 / 1024 < 10;
      if (!isExcel) {
        proxy.$modal.msgError("上传文件只能是 xlsx/xls 格式!");
        return false;
      }
      if (!isLt10M) {
        proxy.$modal.msgError("上传文件大小不能超过 10MB!");
        return false;
      }
      return true;
    },
    onChange: (file, fileList) => {
      // noop
    },
    onProgress: (event, file, fileList) => {
      // noop
    },
    onSuccess: (response, file, fileList) => {
      importUpload.isUploading = false;
      if (response?.code === 200) {
        proxy.$modal.msgSuccess("导入成功");
        importUpload.open = false;
        if (importUploadRef.value) {
          importUploadRef.value.clearFiles?.();
        }
        getList();
      } else {
        proxy.$modal.msgError(response?.msg || "导入失败");
      }
    },
    onError: () => {
      importUpload.isUploading = false;
      proxy.$modal.msgError("导入失败,请重试");
    },
  });
  const handleImport = () => {
    importUpload.title = "导入采购台账";
    importUpload.open = true;
    importUpload.isUploading = false;
    if (importUploadRef.value) {
      importUploadRef.value.clearFiles?.();
    }
  };
  // 下载导入模板(如后端路径不同,可在此处调整)
  const downloadTemplate = () => {
    proxy.download("/purchase/ledger/exportTemplate", {}, "采购台账导入模板.xlsx");
  };
  const submitImportFile = () => {
    importUpload.isUploading = true;
    proxy.$refs["importUploadRef"]?.submit?.();
  };
  const changeDaterange = value => {
    if (value) {
@@ -1014,19 +1066,12 @@
    }
    try {
      // 获取审批人ID字符串
      const approveUserIds = approverNodes.value
        .filter(node => node.userId)
        .map(node => node.userId)
        .join(",");
      let params = {
        productData: proxy.HaveJson(productData.value),
        supplierId: form.value.supplierId,
        paymentMethod: form.value.paymentMethod,
        recorderId: form.value.recorderId,
        projectName: form.value.projectName,
        approveUserIds: approveUserIds,
        templateName: templateName.value.trim(),
      };
      console.log("template params ===>", params, "currentTemplateId:", currentTemplateId.value);
@@ -1177,18 +1222,13 @@
    templateName.value = "";
    filterInputValue.value = "";
    isTemplateNameDuplicate.value = false;
    // 重置审批人节点(默认一个空节点)
    approverNodes.value = [{ id: 1, userId: null }];
    nextApproverId = 2;
    try {
      // 并行加载基础数据
      const [userRes, salesRes, supplierRes] = await Promise.all([
        userListNoPage(),
      const [salesRes, supplierRes] = await Promise.all([
        getSalesNo(),
        getOptions(),
      ]);
      userList.value = userRes.data || [];
      salesContractList.value = salesRes || [];
      // 供应商过滤出isWhite=0 的数据
      supplierList.value = (supplierRes.data || []).filter(
@@ -1218,15 +1258,6 @@
          form.value = { ...purchaseRes };
          productData.value = purchaseRes.productData || [];
          fileList.value = purchaseRes.salesLedgerFiles || [];
          // 如果编辑时有审批人,解析审批人ID字符串并设置到节点中
          if (purchaseRes.approveUserIds) {
            const approverIds = purchaseRes.approveUserIds.split(",");
            approverNodes.value = approverIds.map((id, index) => ({
              id: index + 1,
              userId: Number(id)
            }));
            nextApproverId = approverIds.length + 1;
          }
        } catch (error) {
          console.error("加载采购台账数据失败:", error);
          proxy.$modal.msgError("加载数据失败");
@@ -1295,14 +1326,6 @@
  const submitForm = () => {
    proxy.$refs["formRef"].validate(valid => {
      if (valid) {
        // 审批人必填校验(所有节点都要选人)
        const hasEmptyApprover = approverNodes.value.some(node => !node.userId);
        if (hasEmptyApprover) {
          proxy.$modal.msgError("请为所有审批节点选择审批人!");
          return;
        }
        const approveUserIds = approverNodes.value.map(node => node.userId).join(",");
        if (productData.value.length > 0) {
          // 新增时,需要从每个产品对象中删除 id 字段
          let processedProductData = productData.value;
@@ -1323,7 +1346,6 @@
        }
        form.value.tempFileIds = tempFileIds;
        form.value.type = 2;
        form.value.approveUserIds = approveUserIds;
        // 如果salesLedgerId为空,则不传递salesContractNo
        if (!form.value.salesLedgerId) {
@@ -1347,9 +1369,6 @@
  // 关闭弹框
  const closeDia = () => {
    proxy.resetForm("formRef");
    // 重置审批人节点(默认一个空节点)
    approverNodes.value = [{ id: 1, userId: null }];
    nextApproverId = 2;
    dialogFormVisible.value = false;
  };
  // 打开产品弹框
@@ -1543,7 +1562,7 @@
          delProduct(ids).then(res => {
            proxy.$modal.msgSuccess("删除成功");
            closeProductDia();
            getSalesLedgerWithProducts({ id: currentId.value, type: 2 }).then(
            getPurchaseById({ id: currentId.value, type: 2 }).then(
              res => {
                productData.value = res.productData;
              }
@@ -1578,20 +1597,12 @@
  const handleDelete = () => {
    let ids = [];
    if (selectedRows.value.length > 0) {
      // 检查是否有他人维护的数据
      const unauthorizedData = selectedRows.value.filter(
        item => item.recorderName !== userStore.nickName
      );
      if (unauthorizedData.length > 0) {
        proxy.$modal.msgWarning("不可删除他人维护的数据");
        return;
      }
      ids = selectedRows.value.map(item => item.id);
      ids = selectedRows.value.filter(item => item.salesLedgerId === null).map(item => item.id);
    } else {
      proxy.$modal.msgWarning("请选择数据");
      return;
    }
    ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "导出", {
    ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",