diff --git a/backend/app/services/order_service.py b/backend/app/services/order_service.py
index c3d17d1..9f43dce 100644
--- a/backend/app/services/order_service.py
+++ b/backend/app/services/order_service.py
@@ -816,7 +816,7 @@ class OrderService:
sale_total = sum(item["quantity"] * item["sale_price"] for item in items)
cost_total = sum(item["quantity"] * item["cost_price"] for item in items)
- income_amount = payload.get("contract_amount") or order.contract_amount or sale_total
+ income_amount = payload.get("contract_amount", 0) or sale_total
rebate_total = payload.get("rebate_total", float(order.rebate_total or 0))
freight_total = payload.get("freight_total", float(order.freight_total or 0))
tax_total = payload.get("tax_total", float(order.tax_total or 0))
@@ -824,7 +824,7 @@ class OrderService:
profit_total = income_amount - cost_total - rebate_total - freight_total - tax_total - other_fee_total
profit_rate = round((profit_total / income_amount) * 100, 2) if income_amount else 0
- self.order_repository.update_order_with_items(
+ self.order_repository.update_order_financials_with_items(
session,
order,
{
diff --git a/frontend/mini-app/pages/manager/approve-detail/approve-detail.js b/frontend/mini-app/pages/manager/approve-detail/approve-detail.js
index 6826807..eb914f5 100644
--- a/frontend/mini-app/pages/manager/approve-detail/approve-detail.js
+++ b/frontend/mini-app/pages/manager/approve-detail/approve-detail.js
@@ -171,6 +171,7 @@ Page({
// 费用明细:有值才显示
var feeItems = [
{ label: "合同金额", value: fmt(data.contract_amount), isIncome: true },
+ { label: "销售总价", value: fmt(sale) },
{ label: "成本", value: fmt(cost) },
];
if (rebate > 0) feeItems.push({ label: "回扣", value: fmt(rebate) });
@@ -198,6 +199,8 @@ Page({
unit: ci.unit || "",
baseUnitPrice: fmt(ci.base_unit_price || ci.cost_price),
pricingUnit: ci.pricing_unit || "",
+ saleUnitPrice: fmt(ci.sale_price || 0),
+ costUnitPrice: fmt(ci.cost_price || 0),
costPrice: fmt(ci.cost_price),
costAmount: fmt(Number(ci.quantity || 0) * Number(ci.cost_price || 0)),
pricingType: pricingTypeMap[ci.pricing_type] || "",
diff --git a/frontend/mini-app/pages/manager/approve-detail/approve-detail.wxml b/frontend/mini-app/pages/manager/approve-detail/approve-detail.wxml
index 0ca319c..8dcbec3 100644
--- a/frontend/mini-app/pages/manager/approve-detail/approve-detail.wxml
+++ b/frontend/mini-app/pages/manager/approve-detail/approve-detail.wxml
@@ -95,8 +95,9 @@
计价过程: {{item.formulaDetail}}
- 单价: ¥{{item.baseUnitPrice}}{{item.pricingUnit ? '/' + item.pricingUnit : ''}}
- 成本: ¥{{item.costAmount}}
+ 售价: ¥{{item.saleUnitPrice}}
+ 成本: ¥{{item.costUnitPrice}}{{item.pricingUnit ? '/' + item.pricingUnit : ''}}
+ 小计: ¥{{item.costAmount}}
diff --git a/frontend/mini-app/pages/manager/approve-detail/approve-detail.wxss b/frontend/mini-app/pages/manager/approve-detail/approve-detail.wxss
index dbdd335..fb29443 100644
--- a/frontend/mini-app/pages/manager/approve-detail/approve-detail.wxss
+++ b/frontend/mini-app/pages/manager/approve-detail/approve-detail.wxss
@@ -284,3 +284,79 @@
background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%);
color: #ffffff;
}
+
+
+/* 成本核算编辑弹窗 */
+.edit-modal {
+ width: 100%;
+ max-height: 85vh;
+ padding: 28rpx;
+ border-radius: 20rpx;
+ background: #ffffff;
+ box-shadow: 0 24rpx 60rpx rgba(15, 23, 42, 0.18);
+ display: flex;
+ flex-direction: column;
+}
+
+.edit-items-scroll {
+ max-height: 60vh;
+ margin-top: 16rpx;
+}
+
+.edit-item-card {
+ background: #f8fafc;
+ border: 1rpx solid #e5eaf1;
+ border-radius: 14rpx;
+ padding: 20rpx;
+ margin-bottom: 16rpx;
+}
+
+.edit-item-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 12rpx;
+}
+
+.edit-item-index {
+ font-size: 26rpx;
+ font-weight: 600;
+ color: #0f172a;
+}
+
+.edit-item-delete {
+ font-size: 24rpx;
+ color: #dc2626;
+}
+
+.edit-item-row {
+ display: flex;
+ gap: 12rpx;
+ margin-bottom: 20rpx;
+}
+
+.edit-item-col {
+ flex: 1;
+}
+
+.field-readonly {
+ padding: 16rpx 20rpx;
+ background: #f1f5f9;
+ border: 1rpx solid #e2e8f0;
+ border-radius: 12rpx;
+ font-size: 28rpx;
+ color: #64748b;
+}
+
+.add-item-btn {
+ margin-top: 12rpx;
+ margin-bottom: 8rpx;
+ text-align: center;
+ background: #f8fafc;
+ color: #2563eb;
+ border: 2rpx dashed #93c5fd;
+ border-radius: 12rpx;
+ font-size: 28rpx;
+ height: 72rpx;
+ line-height: 72rpx;
+}
\ No newline at end of file
diff --git a/frontend/web-admin/src/views/OrdersPage.vue b/frontend/web-admin/src/views/OrdersPage.vue
index c04f10a..697ab0e 100644
--- a/frontend/web-admin/src/views/OrdersPage.vue
+++ b/frontend/web-admin/src/views/OrdersPage.vue
@@ -314,7 +314,7 @@
需求规格 |
单位 |
数量 |
- 销售单价 |
+ 销售单价 |
成本单价 |
计价过程 |
成本金额 |
@@ -328,6 +328,7 @@
{{ item.demand_specification || "-" }} |
{{ item.unit || '-' }} |
{{ computeTotalDemand(item) || item.quantity }} |
+ ¥{{ Number(item.sale_price || 0).toFixed(2) }} |
¥{{ Number(item.base_unit_price || item.cost_price || 0).toFixed(2) }}{{ item.pricing_unit ? '/' + item.pricing_unit : '' }} |
{{ formatPricingProcess(item) }}
@@ -393,6 +394,10 @@
¥{{ isEditing ? editFinanceSummary.contractAmount : detail.order.contractAmount }}
+
+
+ ¥{{ isEditing ? editFinanceSummary.salePriceTotal : detail.order.salePriceTotal }}
+
¥{{ isEditing ? editFinanceSummary.costPriceTotal : detail.order.costPriceTotal }}
@@ -1228,16 +1233,19 @@ const productOptions = ref([]);
const editFinanceSummary = computed(() => {
const contractAmount = Number(editForm.contract_amount) || 0;
+ const salePriceTotal = editItems.value.reduce((sum, item) => (Number(item.quantity) || 0) * (Number(item.sale_price) || 0) + sum, 0);
const costPriceTotal = editItems.value.reduce((sum, item) => sum + itemCostTotal(item), 0);
const rebateTotal = Number(editForm.rebate_total) || 0;
const freightTotal = Number(editForm.freight_total) || 0;
const taxTotal = Number(editForm.tax_total) || 0;
const otherFeeTotal = Number(editForm.other_fee_total) || 0;
- const profitTotal = contractAmount - costPriceTotal - rebateTotal - freightTotal - taxTotal - otherFeeTotal;
- const profitRate = contractAmount ? (profitTotal / contractAmount) * 100 : 0;
+ const incomeAmount = contractAmount || salePriceTotal;
+ const profitTotal = incomeAmount - costPriceTotal - rebateTotal - freightTotal - taxTotal - otherFeeTotal;
+ const profitRate = incomeAmount ? (profitTotal / incomeAmount) * 100 : 0;
return {
contractAmount: formatMoney(contractAmount),
+ salePriceTotal: formatMoney(salePriceTotal),
costPriceTotal: formatMoney(costPriceTotal),
profitTotal: formatMoney(profitTotal),
profitRate: `${formatMoney(profitRate)}%`,
@@ -1530,7 +1538,6 @@ async function saveEdit() {
const payload = {
items: itemsPayload,
revision_reason: editForm.revision_reason?.trim() || '管理员修改',
- contract_amount: Number(editForm.contract_amount) || undefined,
rebate_total: Number(editForm.rebate_total) || 0,
freight_total: Number(editForm.freight_total) || 0,
tax_total: Number(editForm.tax_total) || 0,
|