diff --git a/backend/internal/modules/dispute/repository.go b/backend/internal/modules/dispute/repository.go index 7982005..c2e9a6d 100644 --- a/backend/internal/modules/dispute/repository.go +++ b/backend/internal/modules/dispute/repository.go @@ -3,6 +3,7 @@ package dispute import ( "encoding/json" "errors" + "math" "time" "hfb_sys/backend/internal/model" @@ -302,10 +303,10 @@ type arbitrationSettlement struct { } func buildArbitrationSettlement(order model.RentalOrder, req ArbitrateRequest) (arbitrationSettlement, error) { - total := order.RentAmount + order.DepositAmount - ownerRentAmount := order.OwnerRentAmount + total := roundMoney(order.RentAmount + order.DepositAmount) + ownerRentAmount := roundMoney(order.OwnerRentAmount) if ownerRentAmount <= 0 || ownerRentAmount > order.RentAmount { - ownerRentAmount = order.RentAmount + ownerRentAmount = roundMoney(order.RentAmount) } settlement := arbitrationSettlement{} orderID := order.ID @@ -359,6 +360,7 @@ func buildArbitrationSettlement(order model.RentalOrder, req ArbitrateRequest) ( case "full_refund": addRenterRefund(total, "仲裁全额退款") case "partial_refund": + req.Amount = roundMoney(req.Amount) if req.Amount <= 0 || req.Amount > total { return settlement, ErrInvalidDispute } @@ -368,7 +370,7 @@ func buildArbitrationSettlement(order model.RentalOrder, req ArbitrateRequest) ( addOwnerIncome(ownerRentAmount, "仲裁确认订单金额结算给号主") addRenterRefund(order.DepositAmount, "仲裁释放押金给租客") case "deduct_deposit", "compensate_owner": - deductAmount := req.Amount + deductAmount := roundMoney(req.Amount) if deductAmount <= 0 { deductAmount = order.DepositAmount } @@ -390,9 +392,13 @@ func buildArbitrationSettlement(order model.RentalOrder, req ArbitrateRequest) ( func minMoney(a float64, b float64) float64 { if a < b { - return a + return roundMoney(a) } - return b + return roundMoney(b) +} + +func roundMoney(value float64) float64 { + return math.Round(value) } func (r *Repository) baseQuery() *gorm.DB { diff --git a/backend/internal/modules/listing/repository.go b/backend/internal/modules/listing/repository.go index d85126f..7ab8206 100644 --- a/backend/internal/modules/listing/repository.go +++ b/backend/internal/modules/listing/repository.go @@ -61,11 +61,12 @@ func (r *Repository) Create(ownerID uint64, req CreateRequest, reviewRequired bo return err } price := normalizedListingPrice(req) + depositAmount := roundMoney(req.DepositAmount) listing := model.RentalListing{ AccountID: account.ID, OwnerID: ownerID, Price: price, - DepositAmount: req.DepositAmount, + DepositAmount: depositAmount, Status: listingStatus, ReviewStatus: reviewStatus, PublishedAt: publishedAt, @@ -109,7 +110,7 @@ func (r *Repository) Update(ownerID uint64, listingID uint64, req UpdateRequest, price := normalizedListingPrice(req) listing.Price = price - listing.DepositAmount = req.DepositAmount + listing.DepositAmount = roundMoney(req.DepositAmount) listingStatus, reviewStatus, publishedAt := initialPublishState(reviewRequired) listing.Status = listingStatus listing.ReviewStatus = reviewStatus @@ -488,7 +489,15 @@ func rowsToDTO(rows []listingRow) []ListingDTO { } func normalizedListingPrice(req CreateRequest) float64 { - return req.Price + if req.AssetSummary != nil { + if breakdown, ok := req.AssetSummary["price_breakdown"].(map[string]any); ok { + buyerPrice := readSummaryNumber(breakdown["buyer_total_price"]) + if buyerPrice > 0 { + return roundMoney(buyerPrice) + } + } + } + return roundMoney(req.Price) } func publicListings(items []ListingDTO) []ListingDTO { @@ -524,6 +533,15 @@ func applySellerListingPrice(item *ListingDTO) { if sellerPrice > 0 { item.Price = sellerPrice } + sellerRatio := readSummaryNumber(breakdown["seller_ratio"]) + if sellerRatio > 0 { + item.AssetSummary["publish_ratio"] = sellerRatio + } + delete(breakdown, "buyer_coin_base_price") + delete(breakdown, "buyer_total_price") + delete(breakdown, "buyer_ratio") + delete(breakdown, "platform_markup_amount") + delete(breakdown, "platform_rule_type") } func (row listingRow) toDTO() ListingDTO { diff --git a/backend/internal/modules/listing/service.go b/backend/internal/modules/listing/service.go index 8ee51d2..720c736 100644 --- a/backend/internal/modules/listing/service.go +++ b/backend/internal/modules/listing/service.go @@ -313,7 +313,7 @@ func readUnitPrice(priceText string) float64 { } func roundMoney(value float64) float64 { - return math.Round(value*100) / 100 + return math.Round(value) } func readFireLevel(summary map[string]any) (int, bool) { diff --git a/backend/internal/modules/listing/service_test.go b/backend/internal/modules/listing/service_test.go index 392fee9..9c6c2b9 100644 --- a/backend/internal/modules/listing/service_test.go +++ b/backend/internal/modules/listing/service_test.go @@ -11,8 +11,8 @@ func TestConsumableValueOnlyCountsChargedResources(t *testing.T) { }, }) - if value != 1.5 { - t.Fatalf("expected 1.5, got %.2f", value) + if value != 2 { + t.Fatalf("expected 2, got %.2f", value) } } @@ -21,7 +21,7 @@ func TestValidateRequestRequiresDepositAboveConsumables(t *testing.T) { Title: "测试账号", ServerRegion: "烽火地带", Price: 100, - DepositAmount: 1.5, + DepositAmount: 2, HafCoinAmount: 1000000, ScreenshotURLS: []string{"https://example.com/a.png"}, AssetSummary: map[string]any{ @@ -35,7 +35,7 @@ func TestValidateRequestRequiresDepositAboveConsumables(t *testing.T) { t.Fatalf("expected ErrDepositTooLow, got %v", err) } - req.DepositAmount = 2.01 + req.DepositAmount = 3 if err := validateRequest(req, publishRules{}); err != nil { t.Fatalf("expected valid request, got %v", err) } diff --git a/backend/internal/modules/order/dto.go b/backend/internal/modules/order/dto.go index dd52fe1..9ebf592 100644 --- a/backend/internal/modules/order/dto.go +++ b/backend/internal/modules/order/dto.go @@ -20,10 +20,12 @@ type OrderDTO struct { LoginPlatform string `json:"login_platform"` RentedAt *time.Time `json:"rented_at"` EstimatedDurationHours int `json:"estimated_duration_hours"` - RentAmount float64 `json:"rent_amount"` - OwnerRentAmount float64 `json:"owner_rent_amount"` + PriceRole string `json:"price_role,omitempty"` + DisplayAmount float64 `json:"display_amount"` + RentAmount *float64 `json:"rent_amount,omitempty"` + OwnerRentAmount *float64 `json:"owner_rent_amount,omitempty"` DepositAmount float64 `json:"deposit_amount"` - PlatformFee float64 `json:"platform_fee"` + PlatformFee *float64 `json:"platform_fee,omitempty"` AccountSnapshot datatypes.JSON `json:"account_snapshot"` Status string `json:"status"` HandoffStatus string `json:"handoff_status"` @@ -88,16 +90,18 @@ type CheckoutDTO struct { OrderID uint64 `json:"order_id"` InitiatedBy uint64 `json:"initiated_by"` Status string `json:"status"` - RentAmount float64 `json:"rent_amount"` - OwnerRentAmount float64 `json:"owner_rent_amount"` - PlatformFee float64 `json:"platform_fee"` + PriceRole string `json:"price_role,omitempty"` + DisplayAmount float64 `json:"display_amount"` + RentAmount *float64 `json:"rent_amount,omitempty"` + OwnerRentAmount *float64 `json:"owner_rent_amount,omitempty"` + PlatformFee *float64 `json:"platform_fee,omitempty"` DepositAmount float64 `json:"deposit_amount"` ConsumableAmount float64 `json:"consumable_amount"` CoinConsumedM float64 `json:"coin_consumed_m"` OtherAmount float64 `json:"other_amount"` DepositDeductAmount float64 `json:"deposit_deduct_amount"` - RenterRefundAmount float64 `json:"renter_refund_amount"` - OwnerIncomeAmount float64 `json:"owner_income_amount"` + RenterRefundAmount *float64 `json:"renter_refund_amount,omitempty"` + OwnerIncomeAmount *float64 `json:"owner_income_amount,omitempty"` Content string `json:"content"` EvidenceURLS []string `json:"evidence_urls"` OwnerAdjustmentReason string `json:"owner_adjustment_reason"` diff --git a/backend/internal/modules/order/repository.go b/backend/internal/modules/order/repository.go index 5f3c5f9..70392bb 100644 --- a/backend/internal/modules/order/repository.go +++ b/backend/internal/modules/order/repository.go @@ -624,7 +624,12 @@ func (r *Repository) CounterCheckout(userID uint64, orderID uint64, req CounterC if err != nil { return nil, err } - dto := toCheckoutDTO(*checkout) + dto := toCheckoutDTOForUser(*checkout, userID, model.RentalOrder{ + OwnerID: userID, + RentAmount: checkout.RentAmount, + OwnerRentAmount: checkout.OwnerRentAmount, + DepositAmount: checkout.DepositAmount, + }) return &dto, nil } @@ -665,7 +670,7 @@ func (r *Repository) ListForUser(userID uint64) ([]OrderDTO, error) { } items := make([]OrderDTO, 0, len(rows)) for _, row := range rows { - items = append(items, row.toDTO()) + items = append(items, row.toDTOForUser(userID)) } return items, nil } @@ -681,7 +686,7 @@ func (r *Repository) ListAdmin() ([]OrderDTO, error) { } items := make([]OrderDTO, 0, len(rows)) for _, row := range rows { - items = append(items, row.toDTO()) + items = append(items, row.toAdminDTO()) } return items, nil } @@ -691,8 +696,8 @@ func (r *Repository) FindAdmin(orderID uint64) (*OrderDTO, error) { if err := r.adminQuery().Where("o.id = ?", orderID).First(&row).Error; err != nil { return nil, err } - dto := row.toDTO() - dto.Checkout = r.latestCheckoutDTO(orderID) + dto := row.toAdminDTO() + dto.Checkout = r.latestCheckoutAdminDTO(orderID) return &dto, nil } @@ -882,8 +887,8 @@ func (r *Repository) FindForUser(userID uint64, orderID uint64) (*OrderDTO, erro First(&row).Error; err != nil { return nil, err } - dto := row.toDTO() - dto.Checkout = r.latestCheckoutDTO(orderID) + dto := row.toDTOForUser(userID) + dto.Checkout = r.latestCheckoutDTOForUser(orderID, userID, row.RentalOrder) return &dto, nil } @@ -1018,7 +1023,10 @@ func buildCheckout(order model.RentalOrder, initiatedBy uint64, status string, c if consumableAmount < 0 || coinConsumedM < 0 || otherAmount < 0 || explicitDeduct < 0 { return model.OrderCheckout{}, ErrInvalidCheckoutAmount } - deductAmount := consumableAmount + otherAmount + consumableAmount = roundMoney(consumableAmount) + otherAmount = roundMoney(otherAmount) + explicitDeduct = roundMoney(explicitDeduct) + deductAmount := otherAmount if useExplicitDeduct { deductAmount = explicitDeduct } @@ -1038,9 +1046,9 @@ func buildCheckout(order model.RentalOrder, initiatedBy uint64, status string, c OwnerRentAmount: order.OwnerRentAmount, PlatformFee: order.PlatformFee, DepositAmount: order.DepositAmount, - ConsumableAmount: roundMoney(consumableAmount), - CoinConsumedM: roundMoney(coinConsumedM), - OtherAmount: roundMoney(otherAmount), + ConsumableAmount: consumableAmount, + CoinConsumedM: roundQuantity(coinConsumedM), + OtherAmount: otherAmount, DepositDeductAmount: roundMoney(deductAmount), RenterRefundAmount: roundMoney(renterRefund), OwnerIncomeAmount: roundMoney(order.OwnerRentAmount + deductAmount), @@ -1069,6 +1077,10 @@ func decodeStringList(raw datatypes.JSON) []string { } func roundMoney(value float64) float64 { + return math.Round(value) +} + +func roundQuantity(value float64) float64 { return math.Round(value*100) / 100 } @@ -1080,12 +1092,21 @@ func hasOpenCheckout(tx *gorm.DB, orderID uint64) (bool, error) { return count > 0, err } -func (r *Repository) latestCheckoutDTO(orderID uint64) *CheckoutDTO { +func (r *Repository) latestCheckoutAdminDTO(orderID uint64) *CheckoutDTO { var checkout model.OrderCheckout if err := r.db.Where("order_id = ?", orderID).Order("id DESC").First(&checkout).Error; err != nil { return nil } - dto := toCheckoutDTO(checkout) + dto := toCheckoutAdminDTO(checkout) + return &dto +} + +func (r *Repository) latestCheckoutDTOForUser(orderID uint64, userID uint64, order model.RentalOrder) *CheckoutDTO { + var checkout model.OrderCheckout + if err := r.db.Where("order_id = ?", orderID).Order("id DESC").First(&checkout).Error; err != nil { + return nil + } + dto := toCheckoutDTOForUser(checkout, userID, order) return &dto } @@ -1120,9 +1141,12 @@ type orderRow struct { RenterPhone string } -func (row orderRow) toDTO() OrderDTO { +func (row orderRow) toAdminDTO() OrderDTO { rentedAt := row.RentedAt durationHours := orderDurationHours(row.RentalOrder) + rentAmount := row.RentAmount + ownerRentAmount := row.OwnerRentAmount + platformFee := row.PlatformFee return OrderDTO{ ID: row.ID, OrderNo: row.OrderNo, @@ -1137,10 +1161,12 @@ func (row orderRow) toDTO() OrderDTO { LoginPlatform: row.LoginPlatform, RentedAt: rentedAt, EstimatedDurationHours: durationHours, - RentAmount: row.RentAmount, - OwnerRentAmount: row.OwnerRentAmount, + PriceRole: "admin", + DisplayAmount: row.RentAmount, + RentAmount: &rentAmount, + OwnerRentAmount: &ownerRentAmount, DepositAmount: row.DepositAmount, - PlatformFee: row.PlatformFee, + PlatformFee: &platformFee, AccountSnapshot: row.AccountSnapshot, Status: row.Status, HandoffStatus: row.HandoffStatus, @@ -1150,6 +1176,12 @@ func (row orderRow) toDTO() OrderDTO { } } +func (row orderRow) toDTOForUser(userID uint64) OrderDTO { + dto := row.toAdminDTO() + applyOrderPriceView(&dto, row.RentalOrder, userID) + return dto +} + func toHandoffDTO(record model.HandoffRecord) HandoffRecordDTO { return HandoffRecordDTO{ ID: record.ID, @@ -1164,22 +1196,29 @@ func toHandoffDTO(record model.HandoffRecord) HandoffRecordDTO { } } -func toCheckoutDTO(checkout model.OrderCheckout) CheckoutDTO { +func toCheckoutAdminDTO(checkout model.OrderCheckout) CheckoutDTO { + rentAmount := checkout.RentAmount + ownerRentAmount := checkout.OwnerRentAmount + platformFee := checkout.PlatformFee + renterRefundAmount := checkout.RenterRefundAmount + ownerIncomeAmount := checkout.OwnerIncomeAmount return CheckoutDTO{ ID: checkout.ID, OrderID: checkout.OrderID, InitiatedBy: checkout.InitiatedBy, Status: checkout.Status, - RentAmount: checkout.RentAmount, - OwnerRentAmount: checkout.OwnerRentAmount, - PlatformFee: checkout.PlatformFee, + PriceRole: "admin", + DisplayAmount: checkout.RentAmount, + RentAmount: &rentAmount, + OwnerRentAmount: &ownerRentAmount, + PlatformFee: &platformFee, DepositAmount: checkout.DepositAmount, ConsumableAmount: checkout.ConsumableAmount, CoinConsumedM: checkout.CoinConsumedM, OtherAmount: checkout.OtherAmount, DepositDeductAmount: checkout.DepositDeductAmount, - RenterRefundAmount: checkout.RenterRefundAmount, - OwnerIncomeAmount: checkout.OwnerIncomeAmount, + RenterRefundAmount: &renterRefundAmount, + OwnerIncomeAmount: &ownerIncomeAmount, Content: checkout.Content, EvidenceURLS: decodeStringList(checkout.EvidenceURLS), OwnerAdjustmentReason: checkout.OwnerAdjustmentReason, @@ -1191,6 +1230,123 @@ func toCheckoutDTO(checkout model.OrderCheckout) CheckoutDTO { } } +func toCheckoutDTOForUser(checkout model.OrderCheckout, userID uint64, order model.RentalOrder) CheckoutDTO { + dto := toCheckoutAdminDTO(checkout) + applyCheckoutPriceView(&dto, order, userID) + return dto +} + +func applyOrderPriceView(dto *OrderDTO, order model.RentalOrder, userID uint64) { + if dto == nil { + return + } + dto.PlatformFee = nil + switch { + case userID == order.OwnerID: + ownerAmount := order.OwnerRentAmount + if ownerAmount <= 0 { + ownerAmount = order.RentAmount + } + dto.PriceRole = "owner" + dto.DisplayAmount = ownerAmount + dto.RentAmount = nil + dto.OwnerRentAmount = &ownerAmount + sanitizeOrderSnapshot(&dto.AccountSnapshot, "owner") + case userID == order.RenterID: + rentAmount := order.RentAmount + dto.PriceRole = "renter" + dto.DisplayAmount = rentAmount + dto.RentAmount = &rentAmount + dto.OwnerRentAmount = nil + sanitizeOrderSnapshot(&dto.AccountSnapshot, "renter") + default: + dto.PriceRole = "" + dto.DisplayAmount = 0 + dto.RentAmount = nil + dto.OwnerRentAmount = nil + sanitizeOrderSnapshot(&dto.AccountSnapshot, "") + } +} + +func applyCheckoutPriceView(dto *CheckoutDTO, order model.RentalOrder, userID uint64) { + if dto == nil { + return + } + dto.PlatformFee = nil + dto.RenterRefundAmount = nil + dto.OwnerIncomeAmount = nil + switch { + case userID == order.OwnerID: + ownerAmount := order.OwnerRentAmount + if ownerAmount <= 0 { + ownerAmount = order.RentAmount + } + ownerIncomeAmount := dto.DepositDeductAmount + ownerAmount + dto.PriceRole = "owner" + dto.DisplayAmount = ownerAmount + dto.RentAmount = nil + dto.OwnerRentAmount = &ownerAmount + dto.OwnerIncomeAmount = &ownerIncomeAmount + case userID == order.RenterID: + rentAmount := order.RentAmount + renterRefundAmount := order.DepositAmount - dto.DepositDeductAmount + if renterRefundAmount < 0 { + renterRefundAmount = 0 + } + dto.PriceRole = "renter" + dto.DisplayAmount = rentAmount + dto.RentAmount = &rentAmount + dto.OwnerRentAmount = nil + dto.RenterRefundAmount = &renterRefundAmount + default: + dto.PriceRole = "" + dto.DisplayAmount = 0 + dto.RentAmount = nil + dto.OwnerRentAmount = nil + } +} + +func sanitizeOrderSnapshot(snapshot *datatypes.JSON, role string) { + if snapshot == nil || len(*snapshot) == 0 { + return + } + var payload map[string]any + if err := json.Unmarshal(*snapshot, &payload); err != nil { + return + } + rawSummary, ok := payload["asset_summary"] + if !ok { + return + } + var summary map[string]any + switch typed := rawSummary.(type) { + case map[string]any: + summary = typed + case string: + if err := json.Unmarshal([]byte(typed), &summary); err != nil { + return + } + default: + raw, err := json.Marshal(typed) + if err != nil || json.Unmarshal(raw, &summary) != nil { + return + } + } + breakdown, _ := summary["price_breakdown"].(map[string]any) + if role == "owner" && breakdown != nil { + if sellerRatio := readJSONNumber(breakdown["seller_ratio"]); sellerRatio > 0 { + summary["publish_ratio"] = sellerRatio + } + } + delete(summary, "price_breakdown") + payload["asset_summary"] = summary + raw, err := json.Marshal(payload) + if err != nil { + return + } + *snapshot = datatypes.JSON(raw) +} + func makeAccountSnapshot(account model.GameAccount) (datatypes.JSON, error) { payload := map[string]any{ "account_id": account.ID, diff --git a/backend/internal/modules/wallet/repository.go b/backend/internal/modules/wallet/repository.go index ca3c3bd..d9d2b09 100644 --- a/backend/internal/modules/wallet/repository.go +++ b/backend/internal/modules/wallet/repository.go @@ -202,7 +202,7 @@ func applyEntry(account *model.WalletAccount, entry Entry) (float64, error) { } func roundWalletMoney(value float64) float64 { - return math.Round(value*100) / 100 + return math.Round(value) } func toAccountDTO(account model.WalletAccount) *AccountDTO { diff --git a/frontend/src/api/orders.ts b/frontend/src/api/orders.ts index 99b9d5d..8e5304f 100644 --- a/frontend/src/api/orders.ts +++ b/frontend/src/api/orders.ts @@ -16,10 +16,12 @@ export interface Order { login_platform: string rented_at?: string estimated_duration_hours: number - rent_amount: number - owner_rent_amount: number + price_role?: 'renter' | 'owner' | 'admin' | string + display_amount: number + rent_amount?: number + owner_rent_amount?: number deposit_amount: number - platform_fee: number + platform_fee?: number account_snapshot?: Record status: OrderStatus handoff_status: HandoffStatus @@ -34,16 +36,18 @@ export interface Checkout { order_id: number initiated_by: number status: SettlementStatus - rent_amount: number - owner_rent_amount: number - platform_fee: number + price_role?: 'renter' | 'owner' | 'admin' | string + display_amount: number + rent_amount?: number + owner_rent_amount?: number + platform_fee?: number deposit_amount: number consumable_amount: number coin_consumed_m: number other_amount: number deposit_deduct_amount: number - renter_refund_amount: number - owner_income_amount: number + renter_refund_amount?: number + owner_income_amount?: number content: string evidence_urls: string[] owner_adjustment_reason: string diff --git a/frontend/src/utils/pricing.ts b/frontend/src/utils/pricing.ts index 8839d5a..847963e 100644 --- a/frontend/src/utils/pricing.ts +++ b/frontend/src/utils/pricing.ts @@ -13,7 +13,7 @@ export const dailyLossOptions = [10, 20, 30, 40, 50] export const commonOnlineTimes = ['00:00', '08:00', '10:00', '12:00', '14:00', '18:00', '20:00', '22:00', '23:59'] export function roundMoney(value: number) { - return Math.round(value * 100) / 100 + return Math.round(value) } export function roundRatio(value: number) { diff --git a/frontend/src/views/account/OrderDetailView.vue b/frontend/src/views/account/OrderDetailView.vue index 065ba78..99552dc 100644 --- a/frontend/src/views/account/OrderDetailView.vue +++ b/frontend/src/views/account/OrderDetailView.vue @@ -64,6 +64,7 @@ const disputeEvidenceText = ref('') const isOwner = computed(() => order.value?.owner_id === session.userId) const isRenter = computed(() => order.value?.renter_id === session.userId) +const orderAmountLabel = computed(() => (isOwner.value ? '我的租金' : '订单金额')) const canOpenDispute = computed(() => { if (!order.value || (!isOwner.value && !isRenter.value)) return false return !['completed', 'cancelled', 'closed', 'disputing', 'checkout_disputing', 'abnormal'].includes(order.value.status) @@ -86,10 +87,10 @@ const resourceChargeAmount = computed(() => { }) const snapshotHafCoinM = computed(() => { const snapshot = readSnapshot() - return roundMoney(readNumber(snapshot?.haf_coin_amount) / 1000000) + return roundQuantity(readNumber(snapshot?.haf_coin_amount) / 1000000) }) const remainingHafCoinM = computed(() => { - return roundMoney(Math.max(snapshotHafCoinM.value - Number(checkoutForm.value.coin_consumed_m || 0), 0)) + return roundQuantity(Math.max(snapshotHafCoinM.value - Number(checkoutForm.value.coin_consumed_m || 0), 0)) }) onMounted(loadOrder) @@ -387,12 +388,12 @@ function checkoutContentWithSummary() { if (usedResources.length) { lines.push( `额外消耗品:${usedResources - .map((item) => `${item.label} ${readResourceUsage(item.key)}/${item.quantity}${isChargedResource(item) ? `,扣款¥${resourceLineAmount(item).toFixed(2)}` : ',赠送不扣款'}`) + .map((item) => `${item.label} ${readResourceUsage(item.key)}/${item.quantity}${isChargedResource(item) ? `,金额¥${money(resourceLineAmount(item))}` : ',赠送不扣款'}`) .join(';')}`, ) } if (Number(checkoutForm.value.coin_consumed_m || 0) > 0) { - lines.push(`哈夫币消耗:${Number(checkoutForm.value.coin_consumed_m).toFixed(2)}M,预计剩余${remainingHafCoinM.value.toFixed(2)}M`) + lines.push(`哈夫币消耗:${quantity(Number(checkoutForm.value.coin_consumed_m))}M,预计剩余${quantity(remainingHafCoinM.value)}M`) } if (lines.length === 0) { lines.push('租客发起结账。') @@ -415,9 +416,22 @@ function readUnitPrice(priceText: string) { } function roundMoney(value: number) { + return Math.round(value) +} + +function roundQuantity(value: number) { return Math.round(value * 100) / 100 } +function money(value: unknown) { + return `${roundMoney(readNumber(value))}` +} + +function quantity(value: unknown) { + const rounded = roundQuantity(readNumber(value)) + return Number.isInteger(rounded) ? `${rounded}` : rounded.toFixed(2) +} + function readNumber(value: unknown) { const number = Number(value || 0) return Number.isFinite(number) ? number : 0 @@ -462,16 +476,12 @@ function linesToList(value: string) { {{ handoffStatusLabel(order.handoff_status) }}
- 订单金额 - ¥{{ order.rent_amount }} -
-
- 平台费用 - ¥{{ order.platform_fee }} + {{ orderAmountLabel }} + ¥{{ money(order.display_amount) }}
押金 - ¥{{ order.deposit_amount }} + ¥{{ money(order.deposit_amount) }}
@@ -518,7 +528,7 @@ function linesToList(value: string) {
额外消耗品 - 扣款合计:¥{{ resourceChargeAmount.toFixed(2) }} + 金额合计:¥{{ money(resourceChargeAmount) }}
@@ -533,16 +543,16 @@ function linesToList(value: string) { :precision="0" controls-position="right" /> - ¥{{ resourceLineAmount(item).toFixed(2) }} + ¥{{ money(resourceLineAmount(item)) }}
- 订单快照 {{ snapshotHafCoinM.toFixed(2) }}M,预计剩余 {{ remainingHafCoinM.toFixed(2) }}M + 订单快照 {{ quantity(snapshotHafCoinM) }}M,预计剩余 {{ quantity(remainingHafCoinM) }}M - +

结账明细

-

买家租金:¥{{ order.checkout.rent_amount }},号主租金:¥{{ order.checkout.owner_rent_amount }},平台费用:¥{{ order.checkout.platform_fee }}

-

押金:¥{{ order.checkout.deposit_amount }}

-

扣除:¥{{ order.checkout.deposit_deduct_amount }},退还租客:¥{{ order.checkout.renter_refund_amount }},号主收入:¥{{ order.checkout.owner_income_amount }}

+

{{ orderAmountLabel }}:¥{{ money(order.checkout.display_amount) }},押金:¥{{ money(order.checkout.deposit_amount) }}

+

额外消耗品金额:¥{{ money(order.checkout.consumable_amount) }},押金扣除:¥{{ money(order.checkout.deposit_deduct_amount) }}

+

退还租客:¥{{ money(order.checkout.renter_refund_amount) }}

+

号主收入:¥{{ money(order.checkout.owner_income_amount) }}

说明:{{ order.checkout.content }}

修正原因:{{ order.checkout.owner_adjustment_reason }}

@@ -571,17 +582,17 @@ function linesToList(value: string) {

修改结账

- - + + - + - + diff --git a/frontend/src/views/account/OrdersView.vue b/frontend/src/views/account/OrdersView.vue index 2b6196a..85c094d 100644 --- a/frontend/src/views/account/OrdersView.vue +++ b/frontend/src/views/account/OrdersView.vue @@ -48,6 +48,10 @@ function orderRole(order: Order) { if (order.owner_id === session.userId) return '号主' return '-' } + +function money(value: unknown) { + return Math.round(Number(value || 0)) +}