ZN
4 天以前 c0d6fe2638379e6fb23f1af5eff27355cb565e9d
src/views/procurementManagement/procurementLedger/index.vue
@@ -250,6 +250,7 @@
                v-model="form.supplierId"
                placeholder="请选择"
                clearable
                @change="handleSupplierChange"
              >
                <el-option
                  v-for="item in supplierList"
@@ -647,39 +648,60 @@
    <!-- 历史采购价格参考弹窗 -->
    <el-dialog
      v-model="priceReferenceVisible"
      title="历史采购价格参考"
      :title="`历史采购价格参考 ${productForm.supplierName}-${productForm.productName}-${productForm.productModel}`"
      width="1000px"
      append-to-body
    >
      <el-table 
        v-loading="priceReferenceLoading"
        :data="priceReferenceData" 
        border 
        style="width: 100%"
        v-loading="priceReferenceLoading"
        :default-sort="{ prop: 'updateTime', order: 'descending' }"
      >
        <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">
        <!-- <el-table-column label="商品信息" min-width="200">
          <template #default="{ row }">
            <span style="color: #f56c6c; font-weight: bold;">¥{{ row.basePrice }}</span>
            <div class="product-info">
              <div class="product-name">{{ row.productName }}</div>
              <div class="product-spec">{{ row.specification }}</div>
              <div class="product-code">编码: {{ row.productCode }}</div>
            </div>
          </template>
        </el-table-column> -->
        <!-- <el-table-column label="供应商" prop="supplierName" width="200" /> -->
        <el-table-column label="基础价格(不含税)" width="150" align="right">
          <template #default="{ row }">
            <span class="price-text">¥{{ row.basePrice }}</span>
          </template>
        </el-table-column>
        <el-table-column label="实际价格(不含税)" prop="actuallyPrice" width="150" align="right"/>
        <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>
            <div v-if="row.discountType">
              <el-tag :type="getDiscountTagType(row.discountType)" size="small">
                {{ getDiscountText(row.discountType) }}
              </el-tag>
              <div class="discount-value">{{ row.discountValue }}{{ row.discountType === 'percentage' ? '%' : '元' }}</div>
            </div>
            <span v-else class="no-discount">无折扣</span>
          </template>
        </el-table-column>
        <el-table-column label="生效时间" prop="effectiveTime" width="180" align="center" />
        <el-table-column label="状态" width="100" align="center">
          <template #default="{ row }">
            <el-tag :type="getStatusType(row.status)">{{ getStatusText(row.status) }}</el-tag>
            <!-- <div v-if="isPriceWarning(row)" class="warning-indicator">
              <el-icon color="#F56C6C"><Warning /></el-icon>
            </div> -->
          </template>
        </el-table-column>
        <el-table-column label="生效时间" prop="effectiveTime" width="100" align="center" />
        <el-table-column label="更新时间" prop="updateTime" width="160" sortable align="center" />
        <el-table-column label="备注" width="200" prop="remark" align="center" show-overflow-tooltip />
        <el-table-column label="操作" width="100" align="center" fixed="right">
          <template #default="{ row }">
            <el-button type="primary" link @click="selectPriceReference(row)">选择</el-button>
            <el-button type="success" link @click="selectPriceReference(row)">
              <el-icon><Check /></el-icon>
              引用
            </el-button>
          </template>
        </el-table-column>
      </el-table>
@@ -921,7 +943,7 @@
import { getToken } from "@/utils/auth";
import pagination from "@/components/PIMTable/Pagination.vue";
import { ref, onMounted, reactive, toRefs, getCurrentInstance, nextTick } from "vue";
import { Search } from "@element-plus/icons-vue";
import { Search, Check } from "@element-plus/icons-vue";
import { ElMessageBox } from "element-plus";
import { userListNoPage } from "@/api/system/user.js";
import {
@@ -1037,6 +1059,9 @@
    taxExclusiveTotalPrice: "",
    invoiceType: "",
      warnNum: "",
    supplierName: "",
    productName: "",
    productModel: "",
  },
  productRules: {
    productId: [{ required: true, message: "请选择", trigger: "change" }],
@@ -1069,7 +1094,59 @@
  size: 10
});
const calculateFinalPrice = (row) => {
  let finalPrice = row.basePrice;
  if (row.discountType === "percentage") {
    finalPrice = row.basePrice * (1 - row.discountValue / 100);
  } else if (row.discountType === "fixed") {
    finalPrice = row.basePrice - row.discountValue;
  }
  let man = Math.max(finalPrice, 0);
  return man.toFixed(2);
};
const getDiscountTagType = (discountType) => {
  const typeMap = {
    percentage: "success",
    fixed: "warning",
    tiered: "info",
  };
  return typeMap[discountType] || "info";
};
const getDiscountText = (discountType) => {
  const textMap = {
    percentage: "百分比",
    fixed: "固定金额",
  };
  return textMap[discountType] || "未知";
};
const getStatusType = (status) => {
  const statusMap = {
    active: "success",
    pending: "warning",
    expired: "info",
  };
  return statusMap[status] || "info";
};
const getStatusText = (status) => {
  const statusMap = {
    active: "有效",
    pending: "待生效",
    expired: "已过期",
  };
  return statusMap[status] || "未知";
};
const showPriceReference = () => {
  if (form.value.supplierId) {
    const supplier = supplierList.value.find((item) => item.id === form.value.supplierId);
    if (supplier) {
      productForm.value.supplierName = supplier.supplierName;
    }
  }
  priceReferenceVisible.value = true;
  handlePriceReferenceSearch();
};
@@ -1080,11 +1157,12 @@
  // 假设高级价格管理的 listPage 接收 productId
  const query = {
    productId: productForm.value.productId,
    specificationId: productForm.value.productModelId,
    supplierId: form.value.supplierId,
    current: priceReferencePagination.current,
    size: priceReferencePagination.size
  };
  listAdvancedPrice(query).then(res => {
    console.log(res);
    priceReferenceData.value = res.data.records;
    priceReferenceTotal.value = res.data.total;
    priceReferenceLoading.value = false;
@@ -1104,25 +1182,39 @@
};
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("已引用历史价格");
 };
  // 计算历史价格(作为不含税单价):基础价格 - 折扣
  let taxExclusivePrice = row.basePrice;
  if (row.discountType === "percentage") {
    taxExclusivePrice = row.basePrice * (1 - row.discountValue / 100);
  } else if (row.discountType === "fixed") {
    taxExclusivePrice = row.basePrice - row.discountValue;
  }
  taxExclusivePrice = Number(Math.max(taxExclusivePrice, 0));
  // 设置数量为 1
  if (!productForm.value.quantity) {
    productForm.value.quantity = 1;
  }
  // 如果已有税率,则计算含税单价
  if (productForm.value.taxRate) {
    const taxRate = Number(productForm.value.taxRate);
    productForm.value.taxInclusiveUnitPrice = (
      taxExclusivePrice *
      (1 + taxRate / 100)
    ).toFixed(2);
  } else {
    // 如果没有税率,暂时将含税单价设为不含税价格,提示用户选择税率
    productForm.value.taxInclusiveUnitPrice = taxExclusivePrice.toFixed(2);
    proxy.$modal.msgWarning("请选择税率以准确计算含税价格");
  }
  // 自动触发计算逻辑(计算总价等)
  mathNum();
  priceReferenceVisible.value = false;
  proxy.$modal.msgSuccess("已引用历史价格(不含税)");
};
const upload = reactive({
  // 上传的地址
@@ -1364,11 +1456,32 @@
  }
  productOperationType.value = type;
  productOperationIndex.value = index;
  productForm.value = {};
  productForm.value = {
    supplierName: "",
    productName: "",
    productModel: "",
  };
  proxy.resetForm("productFormRef");
  if (type === "edit") {
    productForm.value = { ...row };
    productForm.value = {
      ...row,
      productName: row.productCategory || "",
      productModel: row.specificationModel || ""
    };
    // 编辑时,根据 productId 预加载规格型号列表,确保下拉框显示名称而非 ID
    if (productForm.value.productId) {
      modelList({ id: productForm.value.productId }).then((res) => {
        modelOptions.value = res;
      });
    }
  }
  // 确保供应商名称始终同步
  const supplier = supplierList.value.find((item) => item.id === form.value.supplierId);
  if (supplier) {
    productForm.value.supplierName = supplier.supplierName;
  }
  productFormVisible.value = true;
  getProductOptions();
};
@@ -1380,11 +1493,14 @@
const getModels = (value) => {
  if (value) {
    productForm.value.productCategory = findNodeById(productOptions.value, value) || "";
    productForm.value.productName = productForm.value.productCategory;
    productForm.value.productModelId = "";
    modelList({ id: value }).then((res) => {
      modelOptions.value = res;
    });
  } else {
    productForm.value.productCategory = "";
    productForm.value.productName = "";
    modelOptions.value = [];
  }
};
@@ -1392,12 +1508,24 @@
  const index = modelOptions.value.findIndex((item) => item.id === value);
  if (index !== -1) {
    productForm.value.specificationModel = modelOptions.value[index].model;
    productForm.value.productModel = modelOptions.value[index].model;
    productForm.value.unit = modelOptions.value[index].unit;
  } else {
    productForm.value.specificationModel = null;
    productForm.value.productModel = null;
    productForm.value.unit = null;
  }
};
const handleSupplierChange = (value) => {
  const supplier = supplierList.value.find((item) => item.id === value);
  if (supplier) {
    form.value.supplierName = supplier.supplierName;
    productForm.value.supplierName = supplier.supplierName;
  } else {
    form.value.supplierName = "";
    productForm.value.supplierName = "";
  }
};
const findNodeById = (nodes, productId) => {
  for (let i = 0; i < nodes.length; i++) {
    if (nodes[i].value === productId) {