| | |
| | | v-model="form.supplierId" |
| | | placeholder="请选择" |
| | | clearable |
| | | @change="handleSupplierChange" |
| | | > |
| | | <el-option |
| | | v-for="item in supplierList" |
| | |
| | | <!-- 历史采购价格参考弹窗 --> |
| | | <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 }}% |
| | | <div v-if="row.discountType"> |
| | | <el-tag :type="getDiscountTagType(row.discountType)" size="small"> |
| | | {{ getDiscountText(row.discountType) }} |
| | | </el-tag> |
| | | <el-tag v-else-if="row.discountType === 'fixed'" type="warning"> |
| | | -¥{{ row.discountValue }} |
| | | </el-tag> |
| | | <span v-else>无折扣</span> |
| | | <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> |
| | |
| | | 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 { |
| | |
| | | taxExclusiveTotalPrice: "", |
| | | invoiceType: "", |
| | | warnNum: "", |
| | | supplierName: "", |
| | | productName: "", |
| | | productModel: "", |
| | | }, |
| | | productRules: { |
| | | productId: [{ required: true, message: "请选择", trigger: "change" }], |
| | |
| | | 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(); |
| | | }; |
| | |
| | | // 假设高级价格管理的 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; |
| | |
| | | }; |
| | | |
| | | 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; |
| | | // 计算历史价格(作为不含税单价):基础价格 - 折扣 |
| | | 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; |
| | | } |
| | | |
| | | // 填充含税单价,保留两位小数 |
| | | productForm.value.taxInclusiveUnitPrice = Number(Math.max(actualPrice, 0)).toFixed(2); |
| | | // 如果已有税率,则计算含税单价 |
| | | 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("请选择税率以准确计算含税价格"); |
| | | } |
| | | |
| | | // 如果已经输入了数量,则自动计算总价 |
| | | if (productForm.value.quantity) { |
| | | // 自动触发计算逻辑(计算总价等) |
| | | mathNum(); |
| | | } |
| | | |
| | | priceReferenceVisible.value = false; |
| | | proxy.$modal.msgSuccess("已引用历史价格"); |
| | | proxy.$modal.msgSuccess("已引用历史价格(不含税)"); |
| | | }; |
| | | |
| | | const upload = reactive({ |
| | |
| | | } |
| | | 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(); |
| | | }; |
| | |
| | | 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 = []; |
| | | } |
| | | }; |
| | |
| | | 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) { |