chenhj
4 天以前 4db45250f9e0e47b1df480eb4e325a931f40c9c6
src/views/procurementManagement/procurementLedger/index.vue
@@ -54,7 +54,6 @@
        :summary-method="summarizeMainTable"
        @expand-change="expandChange"
        height="calc(100vh - 18.5em)"
        :row-class-name="tableRowClassName"
      >
        <el-table-column align="center" type="selection" width="55" />
        <el-table-column type="expand">
@@ -113,30 +112,35 @@
          prop="supplierName"
          show-overflow-tooltip
        />
        <el-table-column label="订单状态" width="100" align="center">
          <template #default="scope">
            <el-tag v-if="scope.row.isInvalid" type="danger" size="small">失效</el-tag>
            <el-tag v-else type="success" size="small">正常</el-tag>
          </template>
        </el-table-column>
        <el-table-column
          label="项目名称"
          prop="projectName"
          width="420"
          show-overflow-tooltip
        />
        <el-table-column
            label="审批状态"
            prop="approvalStatus"
            width="200"
            show-overflow-tooltip
        >
        <el-table-column label="审批状态" width="140">
          <template #default="scope">
            <el-tag
                size="small"
            >
              {{ approvalStatusText[scope.row.approvalStatus] || '未知状态' }}
            </el-tag>
              v-if="(scope.row.approveStatus ?? scope.row.approvalStatus ?? scope.row.auditStatus) == 0"
              type="warning"
            >待审核</el-tag>
            <el-tag
              v-else-if="(scope.row.approveStatus ?? scope.row.approvalStatus ?? scope.row.auditStatus) == 1"
              type="primary"
            >审核中</el-tag>
            <el-tag
              v-else-if="(scope.row.approveStatus ?? scope.row.approvalStatus ?? scope.row.auditStatus) == 2"
              type="success"
            >审核完成</el-tag>
            <el-tag
              v-else-if="(scope.row.approveStatus ?? scope.row.approvalStatus ?? scope.row.auditStatus) == 3"
              type="danger"
            >审核未通过</el-tag>
            <el-tag
              v-else-if="(scope.row.approveStatus ?? scope.row.approvalStatus ?? scope.row.auditStatus) == 4"
              type="info"
            >已重新提交</el-tag>
            <el-tag v-else type="info">-</el-tag>
          </template>
        </el-table-column>
        <el-table-column
@@ -246,8 +250,6 @@
                v-model="form.supplierId"
                placeholder="请选择"
                clearable
                filterable
                allow-create
              >
                <el-option
                  v-for="item in supplierList"
@@ -321,6 +323,48 @@
                placeholder="请选择"
                clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item>
              <template #label>
                <span>审批人选择:</span>
                <el-button type="primary" @click="addApproverNode" style="margin-left: 8px;">新增节点</el-button>
              </template>
              <div style="display: flex; align-items: flex-end; flex-wrap: wrap;">
                <div
                  v-for="(node, index) in approverNodes"
                  :key="node.id"
                  style="margin-right: 30px; text-align: center; margin-bottom: 10px;"
                >
                  <div>
                    <span>审批人</span>
                    →
                  </div>
                  <el-select
                    v-model="node.userId"
                    placeholder="选择人员"
                    style="width: 140px; margin-bottom: 8px;"
                  >
                    <el-option
                      v-for="user in userList"
                      :key="user.userId"
                      :label="user.nickName"
                      :value="user.userId"
                    />
                  </el-select>
                  <div>
                    <el-button
                      type="danger"
                      size="small"
                      @click="removeApproverNode(index)"
                      v-if="approverNodes.length > 1"
                    >删除</el-button>
                  </div>
                </div>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
@@ -508,6 +552,11 @@
                     </el-select>
                  </el-form-item>
               </el-col>
          <el-col :span="24">
            <el-form-item label=" ">
              <el-button type="warning" :disabled="!(productForm.productId && productForm.productModelId && productForm.taxRate)" @click="showPriceReference" icon="Search">查看历史采购价格参考</el-button>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
@@ -554,7 +603,7 @@
              label="不含税总价(元):"
              prop="taxExclusiveTotalPrice"
            >
              <el-input
              <el-input
                v-model="productForm.taxExclusiveTotalPrice"
                @change="reverseMathNum('taxExclusiveTotalPrice')"
              />
@@ -594,7 +643,63 @@
        </div>
      </template>
    </el-dialog>
    <!-- 历史采购价格参考弹窗 -->
    <el-dialog
      v-model="priceReferenceVisible"
      title="历史采购价格参考"
      width="1000px"
      append-to-body
    >
      <el-table
        v-loading="priceReferenceLoading"
        :data="priceReferenceData"
        border
        style="width: 100%"
      >
        <el-table-column label="商品名称" prop="productName" min-width="150" show-overflow-tooltip />
        <el-table-column label="规格型号" prop="specification" width="150" show-overflow-tooltip />
        <el-table-column label="供应商" prop="supplierName" width="200" show-overflow-tooltip />
        <el-table-column label="基础价格" width="120" align="right">
          <template #default="{ row }">
            <span style="color: #f56c6c; font-weight: bold;">¥{{ row.basePrice }}</span>
          </template>
        </el-table-column>
        <el-table-column label="折扣信息" width="120" align="center">
          <template #default="{ row }">
            <el-tag v-if="row.discountType === 'percentage'" type="success">
              {{ row.discountValue }}%
            </el-tag>
            <el-tag v-else-if="row.discountType === 'fixed'" type="warning">
              -¥{{ row.discountValue }}
            </el-tag>
            <span v-else>无折扣</span>
          </template>
        </el-table-column>
        <el-table-column label="生效时间" prop="effectiveTime" width="180" align="center" />
        <el-table-column label="操作" width="100" align="center" fixed="right">
          <template #default="{ row }">
            <el-button type="primary" link @click="selectPriceReference(row)">选择</el-button>
          </template>
        </el-table-column>
      </el-table>
      <div class="pagination-container" style="margin-top: 20px; display: flex; justify-content: flex-end;">
        <el-pagination
          v-model:current-page="priceReferencePagination.current"
          v-model:page-size="priceReferencePagination.size"
          :page-sizes="[10, 20, 50]"
          :total="priceReferenceTotal"
          layout="total, sizes, prev, pager, next"
          @size-change="handlePriceReferenceSizeChange"
          @current-change="handlePriceReferenceCurrentChange"
        />
      </div>
      <template #footer>
        <el-button @click="priceReferenceVisible = false">关闭</el-button>
      </template>
    </el-dialog>
    <!-- 二维码显示对话框 -->
    <el-dialog
      v-model="qrCodeDialogVisible"
@@ -855,8 +960,11 @@
});
const total = ref(0);
const fileList = ref([]);
const approverNodes = ref([{ id: 1, userId: null }]);
let nextApproverId = 2;
import useUserStore from "@/store/modules/user";
import { modelList, productTreeList } from "@/api/basicData/product.js";
import { listPage as listAdvancedPrice } from "@/api/procurementManagement/advancedPriceManagement.js";
import dayjs from "dayjs";
const userStore = useUserStore();
@@ -864,13 +972,6 @@
// 二维码相关变量
const qrCodeDialogVisible = ref(false);
const qrCodeUrl = ref("");
// 订单审批状态显示文本
const approvalStatusText = {
  0: '审批中',
  1: '审批通过',
  2: '审批失败'
};
// 用户信息表单弹框数据
const operationType = ref("");
@@ -909,6 +1010,13 @@
});
const {  form, rules } = toRefs(data);
const { form: searchForm } = useFormData(data.searchForm);
const addApproverNode = () => {
  approverNodes.value.push({ id: nextApproverId++, userId: null });
};
const removeApproverNode = (index) => {
  approverNodes.value.splice(index, 1);
};
// 产品表单弹框数据
const productFormVisible = ref(false);
@@ -950,6 +1058,72 @@
  },
});
const { productForm, productRules } = toRefs(productFormData);
// 采购价格管理参考弹窗
const priceReferenceVisible = ref(false);
const priceReferenceLoading = ref(false);
const priceReferenceData = ref([]);
const priceReferenceTotal = ref(0);
const priceReferencePagination = reactive({
  current: 1,
  size: 10
});
const showPriceReference = () => {
  priceReferenceVisible.value = true;
  handlePriceReferenceSearch();
};
const handlePriceReferenceSearch = () => {
  priceReferenceLoading.value = true;
  // 模拟搜索参数:productId 映射为 productName 或 ID,这里根据 advancedPriceManagement 的 API 确定参数
  // 假设高级价格管理的 listPage 接收 productId
  const query = {
    productId: productForm.value.productId,
    specificationId: productForm.value.productModelId,
    current: priceReferencePagination.current,
    size: priceReferencePagination.size
  };
  listAdvancedPrice(query).then(res => {
    priceReferenceData.value = res.data.records;
    priceReferenceTotal.value = res.data.total;
    priceReferenceLoading.value = false;
  }).catch(() => {
    priceReferenceLoading.value = false;
  });
};
const handlePriceReferenceSizeChange = (size) => {
  priceReferencePagination.size = size;
  handlePriceReferenceSearch();
};
const handlePriceReferenceCurrentChange = (page) => {
  priceReferencePagination.current = page;
  handlePriceReferenceSearch();
};
const selectPriceReference = (row) => {
   // 计算实际价格:基础价格 - 折扣
   let actualPrice = row.basePrice;
   if (row.discountType === 'percentage') {
     actualPrice = row.basePrice * (1 - row.discountValue / 100);
   } else if (row.discountType === 'fixed') {
     actualPrice = row.basePrice - row.discountValue;
   }
   // 填充含税单价,保留两位小数
   productForm.value.taxInclusiveUnitPrice = Number(Math.max(actualPrice, 0)).toFixed(2);
   // 如果已经输入了数量,则自动计算总价
   if (productForm.value.quantity) {
     mathNum();
   }
   priceReferenceVisible.value = false;
   proxy.$modal.msgSuccess("已引用历史价格");
 };
const upload = reactive({
  // 上传的地址
  url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
@@ -1007,12 +1181,7 @@
  purchaseListPage({ ...rest, ...page })
    .then((res) => {
      tableLoading.value = false;
      // tableData.value = res.data.records;
      // 处理数据,添加失效状态标记
      tableData.value = res.data.records.map(record => ({
        ...record,
        isInvalid: record.isWhite === 1
      }));
      tableData.value = res.data.records;
      tableData.value.map((item) => {
        item.children = [];
      });
@@ -1068,6 +1237,8 @@
  form.value = {};
  productData.value = [];
  fileList.value = [];
  approverNodes.value = [{ id: 1, userId: null }];
  nextApproverId = 2;
  if (operationType.value == "add") {
    createPurchaseNo().then((res) => {
      form.value.purchaseContractNumber = res.data;
@@ -1080,8 +1251,7 @@
    salesContractList.value = res;
  });
  getOptions().then((res) => {
    // 供应商过滤出isWhite=0 的数据
    supplierList.value = res.data.filter((item) => item.isWhite == 0);
    supplierList.value = res.data;
  });
  form.value.recorderId = userStore.id;
  form.value.entryDate = getCurrentDate();
@@ -1090,6 +1260,17 @@
    getPurchaseById({ id: row.id, type: 2 }).then((res) => {
      form.value = { ...res };
      productData.value = form.value.productData;
      const approveUserIds = form.value.approveUserIds || form.value.approverIds;
      if (approveUserIds) {
        const ids = String(approveUserIds)
          .split(",")
          .map((id) => Number(id.trim()))
          .filter((id) => !Number.isNaN(id));
        if (ids.length > 0) {
          approverNodes.value = ids.map((id, idx) => ({ id: idx + 1, userId: id }));
          nextApproverId = ids.length + 1;
        }
      }
      if (form.value.salesLedgerFiles) {
        fileList.value = form.value.salesLedgerFiles;
      } else {
@@ -1128,9 +1309,9 @@
// 移除文件
function handleRemove(file) {
  console.log("handleRemove", file.id);
  if (file.size > 1024 * 1024 * 10) {
  if (file.size > 1024 * 1024 * 10) {
    // 仅前端清理,不调用删除接口和提示
    return;
    return;
  }
  if (operationType.value === "edit") {
    let ids = [];
@@ -1144,6 +1325,12 @@
const submitForm = () => {
  proxy.$refs["formRef"].validate((valid) => {
    if (valid) {
      const hasEmptyApprover = approverNodes.value.some((node) => !node.userId);
      if (hasEmptyApprover) {
        proxy.$modal.msgWarning("请为所有审批节点选择审批人");
        return;
      }
      form.value.approveUserIds = approverNodes.value.map((node) => node.userId).join(",");
      if (productData.value.length > 0) {
        form.value.productData = proxy.HaveJson(productData.value);
      } else {
@@ -1171,6 +1358,10 @@
};
// 打开产品弹框
const openProductForm = (type, row, index) => {
  if(!form.value.supplierId){
    proxy.$modal.msgWarning("请选择供应商");
    return;
  }
  productOperationType.value = type;
  productOperationIndex.value = index;
  productForm.value = {};
@@ -1400,29 +1591,29 @@
  if (field === 'taxInclusiveTotalPrice') {
    // 已知含税总价和数量,反算含税单价
    if (productForm.value.quantity) {
      productForm.value.taxInclusiveUnitPrice =
      productForm.value.taxInclusiveUnitPrice =
        (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.quantity)).toFixed(2);
    }
    // 已知含税总价和含税单价,反算数量
    else if (productForm.value.taxInclusiveUnitPrice) {
      productForm.value.quantity =
      productForm.value.quantity =
        (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.taxInclusiveUnitPrice)).toFixed(2);
    }
    // 反算不含税总价
    productForm.value.taxExclusiveTotalPrice =
    productForm.value.taxExclusiveTotalPrice =
      (Number(productForm.value.taxInclusiveTotalPrice) / (1 + taxRate / 100)).toFixed(2);
  } else if (field === 'taxExclusiveTotalPrice') {
    // 反算含税总价
    productForm.value.taxInclusiveTotalPrice =
    productForm.value.taxInclusiveTotalPrice =
      (Number(productForm.value.taxExclusiveTotalPrice) * (1 + taxRate / 100)).toFixed(2);
    // 已知数量,反算含税单价
    if (productForm.value.quantity) {
      productForm.value.taxInclusiveUnitPrice =
      productForm.value.taxInclusiveUnitPrice =
        (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.quantity)).toFixed(2);
    }
    // 已知含税单价,反算数量
    else if (productForm.value.taxInclusiveUnitPrice) {
      productForm.value.quantity =
      productForm.value.quantity =
        (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.taxInclusiveUnitPrice)).toFixed(2);
    }
  }
@@ -1478,7 +1669,7 @@
    proxy.$modal.msgWarning("二维码未生成");
    return;
  }
  const a = document.createElement('a');
  a.href = qrCodeUrl.value;
  a.download = `采购合同号二维码_${new Date().getTime()}.png`;
@@ -1538,7 +1729,7 @@
// 解析扫码内容(模拟解析二维码数据)
const parseScanContent = (content) => {
  if (!content) return;
  // 模拟解析二维码内容,这里可以根据实际需求调整解析逻辑
  // 假设扫码内容格式为:合同号|供应商|项目|金额|付款方式
  const parts = content.split('|');
@@ -1573,11 +1764,11 @@
        remark: scanAddForm.scanRemark,
        type: 2
      };
      // 模拟新增成功
      proxy.$modal.msgSuccess("扫码新增成功!");
      closeScanAddDialog();
      // 可以选择是否刷新列表
      // getList();
    }
@@ -1633,19 +1824,11 @@
  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
// 添加行类名方法
const tableRowClassName = ({ row }) => {
  return row.isInvalid ? 'invalid-row' : '';
};
onMounted(() => {
  getList();
});
</script>
<style scoped lang="scss">
.invalid-row {
  opacity: 0.6;
  background-color: #f5f7fa;
}
</style>
<style scoped lang="scss"></style>