dingdanquanliucheng/frontend/mini-app/pages/manager/approve-detail/approve-detail.js
taiyi 20b3486512 feat: 小程序审批详情页增加利润计算过程和订单明细
管理员审批时可看到完整的利润公式推导(销售价-成本-回扣-运费-税费-其他=利润)
以及每个产品的数量、售价、成本、销售金额明细表格,辅助审批决策。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-06 18:43:52 +08:00

202 lines
7.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 审批详情页面
* 职责:展示订单完整信息(含报价明细和分层价格),支持审批通过/驳回操作。
*/
function mapOrderStatus(status) {
var app = getApp();
return app.mapOrderStatus(status);
}
function getStatusBadge(status) {
var map = {
pending_approve: "badge-orange", cancel_pending: "badge-orange",
approved: "badge-green", rejected: "badge-red",
pending_factory: "badge-blue", delivered: "badge-green", canceled: "badge-red",
};
return map[status] || "badge-gray";
}
Page({
data: {
statusBarHeight: 20,
taskId: null,
loading: true,
actionLoading: false,
message: "",
approveOpinion: "",
orderInfo: null,
pricingItems: [],
orderAttachments: [],
// 利润计算过程
calcFormula: "",
calcRateFormula: "",
calcSaleTotal: "0.00",
calcCostTotal: "0.00",
calcRebateTotal: "0.00",
calcFreightTotal: "0.00",
calcTaxTotal: "0.00",
calcTaxDesc: "",
calcOtherFeeTotal: "0.00",
calcProfitTotal: "0.00",
calcProfitRate: "0.00",
// 订单明细行
orderItems: [],
},
async onLoad(options) {
var app = getApp();
this.setData({
statusBarHeight: app.globalData.statusBarHeight || 20,
taskId: Number(options.id || 0),
});
await this.loadDetail();
},
async loadDetail() {
var app = getApp();
this.setData({ loading: true, message: "" });
try {
var data = await app.request({ url: "/api/orders/" + this.data.taskId, method: "GET" });
var sale = Number(data.sale_price_total || 0);
var cost = Number(data.cost_price_total || 0);
var profit = Number(data.profit_total || 0);
var profitRate = sale > 0 ? (profit / sale * 100).toFixed(1) + "%" : "-";
// 解析利润计算明细
var calcDetail = data.calculation_detail || {};
var calcItems = calcDetail.item_details || [];
// 计算过程汇总
var calcTaxDesc = "";
if (calcDetail.tax_detail) {
calcTaxDesc = calcDetail.tax_detail.desc || "";
}
// 报价明细(仅含 pricing_type 的行)
var pricingItems = [];
// 订单产品明细(所有行)
var orderItems = [];
for (var i = 0; i < calcItems.length; i++) {
var ci = calcItems[i];
// 订单明细:所有行都加入
orderItems.push({
product_name: ci.product_name,
quantity: Number(ci.quantity || 0),
sale_price: Number(ci.sale_price || 0).toFixed(2),
cost_price: Number(ci.cost_price || 0).toFixed(2),
sale_amount: Number(ci.sale_amount || 0).toFixed(2),
cost_amount: Number(ci.cost_amount || 0).toFixed(2),
tax_amount: Number(ci.tax_amount || 0).toFixed(2),
});
// 报价明细:仅有 pricing_type 的行
if (!ci.pricing_type) continue;
var surchargeItems = [];
if (ci.surcharge_items) {
for (var j = 0; j < ci.surcharge_items.length; j++) {
surchargeItems.push({ key: ci.surcharge_items[j].key, name: ci.surcharge_items[j].name, amount: Number(ci.surcharge_items[j].amount || 0).toFixed(2) });
}
}
var totalSurcharge = 0;
for (var k = 0; k < surchargeItems.length; k++) { totalSurcharge += Number(surchargeItems[k].amount); }
var tierPrices = [];
if (data.sale_price_tier) {
var tierNames = { special: "特批价", tier1: "一级经销", tier2: "二级经销", default: "默认" };
var tierKeys = Object.keys(data.sale_price_tier);
for (var t = 0; t < tierKeys.length; t++) {
tierPrices.push({ code: tierKeys[t], name: tierNames[tierKeys[t]] || tierKeys[t], price: Number(data.sale_price_tier[tierKeys[t]] || 0).toFixed(2) });
}
}
pricingItems.push({
product_name: ci.product_name, pricing_type: ci.pricing_type,
length_m: ci.length_m, width_m: ci.width_m,
area_sqm: ci.area_sqm ? Number(ci.area_sqm).toFixed(4) : null,
baseCost: Number(ci.cost_amount || 0).toFixed(2),
surchargeItems: surchargeItems, totalSurcharge: totalSurcharge.toFixed(2),
costPrice: (Number(ci.cost_amount || 0) + totalSurcharge).toFixed(2),
formula_detail: ci.pricing_type ? ci.product_name + " " + (ci.length_m ? ci.length_m + "m × " + ci.width_m + "m" : "") + " 成本¥" + Number(ci.cost_amount || 0).toFixed(2) : "",
tierPrices: tierPrices,
});
}
this.setData({
orderInfo: Object.assign({}, data, {
statusText: mapOrderStatus(data.order_status), badgeClass: getStatusBadge(data.order_status),
salePriceTotalText: sale.toFixed(2), costPriceTotalText: cost.toFixed(2),
rebateTotalText: Number(data.rebate_total || 0).toFixed(2),
freightTotalText: Number(data.freight_total || 0).toFixed(2),
profitTotalText: profit.toFixed(2), profitRate: profitRate,
}),
pricingItems: pricingItems,
orderItems: orderItems,
orderAttachments: (data.attachments || []).filter(function (a) { return a.biz_type === "sales_order"; }),
// 利润计算过程
calcFormula: calcDetail.formula || "",
calcRateFormula: calcDetail.rate_formula || "",
calcSaleTotal: Number(calcDetail.sale_total || 0).toFixed(2),
calcCostTotal: Number(calcDetail.cost_total || 0).toFixed(2),
calcRebateTotal: Number(calcDetail.rebate_total || 0).toFixed(2),
calcFreightTotal: Number(calcDetail.freight_total || 0).toFixed(2),
calcTaxTotal: Number(calcDetail.tax_total || 0).toFixed(2),
calcTaxDesc: calcTaxDesc,
calcOtherFeeTotal: Number(calcDetail.other_fee_total || 0).toFixed(2),
calcProfitTotal: Number(calcDetail.profit_total || 0).toFixed(2),
calcProfitRate: Number(calcDetail.profit_rate || 0).toFixed(1),
});
} catch (error) {
this.setData({ message: error.message || "加载失败" });
} finally {
this.setData({ loading: false });
}
},
handleOpinionInput: function (event) {
this.setData({ approveOpinion: event.detail.value });
},
handleApprove: function (event) {
var that = this;
var result = event.currentTarget.dataset.result;
var orderInfo = this.data.orderInfo;
if (!orderInfo) return;
var isCancelFlow = ["cancel_pending", "cancel_fulfillment_pending"].indexOf(orderInfo.order_status) >= 0;
var targetUrl = isCancelFlow
? "/api/orders/" + orderInfo.order_id + "/cancel-approve"
: "/api/orders/" + orderInfo.order_id + "/approve";
var confirmMsg = result === "pass"
? (isCancelFlow ? "确认同意取消此订单?" : "确认审批通过?")
: (isCancelFlow ? "确认驳回取消申请?" : "确认退回此订单?");
wx.showModal({
title: "确认操作",
content: confirmMsg,
confirmColor: result === "pass" ? "#2563eb" : "#be123c",
success: function (res) {
if (!res.confirm) return;
var app = getApp();
that.setData({ actionLoading: true, message: "" });
var opinion = that.data.approveOpinion || (result === "pass" ? "同意" : "退回");
app.request({
url: targetUrl, method: "POST",
data: { approve_result: result, approve_opinion: opinion },
}).then(function () {
wx.showToast({ title: result === "pass" ? "审批通过" : "已退回", icon: "success" });
return that.loadDetail();
}).catch(function (error) {
that.setData({ message: error.message || "操作失败" });
}).finally(function () {
that.setData({ actionLoading: false });
});
},
});
},
handleBack: function () { wx.navigateBack({ delta: 1 }); },
handlePreviewAttachment: function (event) {
var url = event.currentTarget.dataset.url;
var urls = this.data.orderAttachments.map(function (a) { return a.file_url; });
wx.previewImage({ current: url, urls: urls });
},
});