金额使用整数, 不再扣押金, 价格每个人看到自己的-1
This commit is contained in:
@@ -3,6 +3,7 @@ package dispute
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"math"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"hfb_sys/backend/internal/model"
|
"hfb_sys/backend/internal/model"
|
||||||
@@ -302,10 +303,10 @@ type arbitrationSettlement struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func buildArbitrationSettlement(order model.RentalOrder, req ArbitrateRequest) (arbitrationSettlement, error) {
|
func buildArbitrationSettlement(order model.RentalOrder, req ArbitrateRequest) (arbitrationSettlement, error) {
|
||||||
total := order.RentAmount + order.DepositAmount
|
total := roundMoney(order.RentAmount + order.DepositAmount)
|
||||||
ownerRentAmount := order.OwnerRentAmount
|
ownerRentAmount := roundMoney(order.OwnerRentAmount)
|
||||||
if ownerRentAmount <= 0 || ownerRentAmount > order.RentAmount {
|
if ownerRentAmount <= 0 || ownerRentAmount > order.RentAmount {
|
||||||
ownerRentAmount = order.RentAmount
|
ownerRentAmount = roundMoney(order.RentAmount)
|
||||||
}
|
}
|
||||||
settlement := arbitrationSettlement{}
|
settlement := arbitrationSettlement{}
|
||||||
orderID := order.ID
|
orderID := order.ID
|
||||||
@@ -359,6 +360,7 @@ func buildArbitrationSettlement(order model.RentalOrder, req ArbitrateRequest) (
|
|||||||
case "full_refund":
|
case "full_refund":
|
||||||
addRenterRefund(total, "仲裁全额退款")
|
addRenterRefund(total, "仲裁全额退款")
|
||||||
case "partial_refund":
|
case "partial_refund":
|
||||||
|
req.Amount = roundMoney(req.Amount)
|
||||||
if req.Amount <= 0 || req.Amount > total {
|
if req.Amount <= 0 || req.Amount > total {
|
||||||
return settlement, ErrInvalidDispute
|
return settlement, ErrInvalidDispute
|
||||||
}
|
}
|
||||||
@@ -368,7 +370,7 @@ func buildArbitrationSettlement(order model.RentalOrder, req ArbitrateRequest) (
|
|||||||
addOwnerIncome(ownerRentAmount, "仲裁确认订单金额结算给号主")
|
addOwnerIncome(ownerRentAmount, "仲裁确认订单金额结算给号主")
|
||||||
addRenterRefund(order.DepositAmount, "仲裁释放押金给租客")
|
addRenterRefund(order.DepositAmount, "仲裁释放押金给租客")
|
||||||
case "deduct_deposit", "compensate_owner":
|
case "deduct_deposit", "compensate_owner":
|
||||||
deductAmount := req.Amount
|
deductAmount := roundMoney(req.Amount)
|
||||||
if deductAmount <= 0 {
|
if deductAmount <= 0 {
|
||||||
deductAmount = order.DepositAmount
|
deductAmount = order.DepositAmount
|
||||||
}
|
}
|
||||||
@@ -390,9 +392,13 @@ func buildArbitrationSettlement(order model.RentalOrder, req ArbitrateRequest) (
|
|||||||
|
|
||||||
func minMoney(a float64, b float64) float64 {
|
func minMoney(a float64, b float64) float64 {
|
||||||
if a < b {
|
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 {
|
func (r *Repository) baseQuery() *gorm.DB {
|
||||||
|
|||||||
@@ -61,11 +61,12 @@ func (r *Repository) Create(ownerID uint64, req CreateRequest, reviewRequired bo
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
price := normalizedListingPrice(req)
|
price := normalizedListingPrice(req)
|
||||||
|
depositAmount := roundMoney(req.DepositAmount)
|
||||||
listing := model.RentalListing{
|
listing := model.RentalListing{
|
||||||
AccountID: account.ID,
|
AccountID: account.ID,
|
||||||
OwnerID: ownerID,
|
OwnerID: ownerID,
|
||||||
Price: price,
|
Price: price,
|
||||||
DepositAmount: req.DepositAmount,
|
DepositAmount: depositAmount,
|
||||||
Status: listingStatus,
|
Status: listingStatus,
|
||||||
ReviewStatus: reviewStatus,
|
ReviewStatus: reviewStatus,
|
||||||
PublishedAt: publishedAt,
|
PublishedAt: publishedAt,
|
||||||
@@ -109,7 +110,7 @@ func (r *Repository) Update(ownerID uint64, listingID uint64, req UpdateRequest,
|
|||||||
|
|
||||||
price := normalizedListingPrice(req)
|
price := normalizedListingPrice(req)
|
||||||
listing.Price = price
|
listing.Price = price
|
||||||
listing.DepositAmount = req.DepositAmount
|
listing.DepositAmount = roundMoney(req.DepositAmount)
|
||||||
listingStatus, reviewStatus, publishedAt := initialPublishState(reviewRequired)
|
listingStatus, reviewStatus, publishedAt := initialPublishState(reviewRequired)
|
||||||
listing.Status = listingStatus
|
listing.Status = listingStatus
|
||||||
listing.ReviewStatus = reviewStatus
|
listing.ReviewStatus = reviewStatus
|
||||||
@@ -488,7 +489,15 @@ func rowsToDTO(rows []listingRow) []ListingDTO {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func normalizedListingPrice(req CreateRequest) float64 {
|
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 {
|
func publicListings(items []ListingDTO) []ListingDTO {
|
||||||
@@ -524,6 +533,15 @@ func applySellerListingPrice(item *ListingDTO) {
|
|||||||
if sellerPrice > 0 {
|
if sellerPrice > 0 {
|
||||||
item.Price = sellerPrice
|
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 {
|
func (row listingRow) toDTO() ListingDTO {
|
||||||
|
|||||||
@@ -313,7 +313,7 @@ func readUnitPrice(priceText string) float64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func roundMoney(value float64) float64 {
|
func roundMoney(value float64) float64 {
|
||||||
return math.Round(value*100) / 100
|
return math.Round(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func readFireLevel(summary map[string]any) (int, bool) {
|
func readFireLevel(summary map[string]any) (int, bool) {
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ func TestConsumableValueOnlyCountsChargedResources(t *testing.T) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
if value != 1.5 {
|
if value != 2 {
|
||||||
t.Fatalf("expected 1.5, got %.2f", value)
|
t.Fatalf("expected 2, got %.2f", value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ func TestValidateRequestRequiresDepositAboveConsumables(t *testing.T) {
|
|||||||
Title: "测试账号",
|
Title: "测试账号",
|
||||||
ServerRegion: "烽火地带",
|
ServerRegion: "烽火地带",
|
||||||
Price: 100,
|
Price: 100,
|
||||||
DepositAmount: 1.5,
|
DepositAmount: 2,
|
||||||
HafCoinAmount: 1000000,
|
HafCoinAmount: 1000000,
|
||||||
ScreenshotURLS: []string{"https://example.com/a.png"},
|
ScreenshotURLS: []string{"https://example.com/a.png"},
|
||||||
AssetSummary: map[string]any{
|
AssetSummary: map[string]any{
|
||||||
@@ -35,7 +35,7 @@ func TestValidateRequestRequiresDepositAboveConsumables(t *testing.T) {
|
|||||||
t.Fatalf("expected ErrDepositTooLow, got %v", err)
|
t.Fatalf("expected ErrDepositTooLow, got %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
req.DepositAmount = 2.01
|
req.DepositAmount = 3
|
||||||
if err := validateRequest(req, publishRules{}); err != nil {
|
if err := validateRequest(req, publishRules{}); err != nil {
|
||||||
t.Fatalf("expected valid request, got %v", err)
|
t.Fatalf("expected valid request, got %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,12 @@ type OrderDTO struct {
|
|||||||
LoginPlatform string `json:"login_platform"`
|
LoginPlatform string `json:"login_platform"`
|
||||||
RentedAt *time.Time `json:"rented_at"`
|
RentedAt *time.Time `json:"rented_at"`
|
||||||
EstimatedDurationHours int `json:"estimated_duration_hours"`
|
EstimatedDurationHours int `json:"estimated_duration_hours"`
|
||||||
RentAmount float64 `json:"rent_amount"`
|
PriceRole string `json:"price_role,omitempty"`
|
||||||
OwnerRentAmount float64 `json:"owner_rent_amount"`
|
DisplayAmount float64 `json:"display_amount"`
|
||||||
|
RentAmount *float64 `json:"rent_amount,omitempty"`
|
||||||
|
OwnerRentAmount *float64 `json:"owner_rent_amount,omitempty"`
|
||||||
DepositAmount float64 `json:"deposit_amount"`
|
DepositAmount float64 `json:"deposit_amount"`
|
||||||
PlatformFee float64 `json:"platform_fee"`
|
PlatformFee *float64 `json:"platform_fee,omitempty"`
|
||||||
AccountSnapshot datatypes.JSON `json:"account_snapshot"`
|
AccountSnapshot datatypes.JSON `json:"account_snapshot"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
HandoffStatus string `json:"handoff_status"`
|
HandoffStatus string `json:"handoff_status"`
|
||||||
@@ -88,16 +90,18 @@ type CheckoutDTO struct {
|
|||||||
OrderID uint64 `json:"order_id"`
|
OrderID uint64 `json:"order_id"`
|
||||||
InitiatedBy uint64 `json:"initiated_by"`
|
InitiatedBy uint64 `json:"initiated_by"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
RentAmount float64 `json:"rent_amount"`
|
PriceRole string `json:"price_role,omitempty"`
|
||||||
OwnerRentAmount float64 `json:"owner_rent_amount"`
|
DisplayAmount float64 `json:"display_amount"`
|
||||||
PlatformFee float64 `json:"platform_fee"`
|
RentAmount *float64 `json:"rent_amount,omitempty"`
|
||||||
|
OwnerRentAmount *float64 `json:"owner_rent_amount,omitempty"`
|
||||||
|
PlatformFee *float64 `json:"platform_fee,omitempty"`
|
||||||
DepositAmount float64 `json:"deposit_amount"`
|
DepositAmount float64 `json:"deposit_amount"`
|
||||||
ConsumableAmount float64 `json:"consumable_amount"`
|
ConsumableAmount float64 `json:"consumable_amount"`
|
||||||
CoinConsumedM float64 `json:"coin_consumed_m"`
|
CoinConsumedM float64 `json:"coin_consumed_m"`
|
||||||
OtherAmount float64 `json:"other_amount"`
|
OtherAmount float64 `json:"other_amount"`
|
||||||
DepositDeductAmount float64 `json:"deposit_deduct_amount"`
|
DepositDeductAmount float64 `json:"deposit_deduct_amount"`
|
||||||
RenterRefundAmount float64 `json:"renter_refund_amount"`
|
RenterRefundAmount *float64 `json:"renter_refund_amount,omitempty"`
|
||||||
OwnerIncomeAmount float64 `json:"owner_income_amount"`
|
OwnerIncomeAmount *float64 `json:"owner_income_amount,omitempty"`
|
||||||
Content string `json:"content"`
|
Content string `json:"content"`
|
||||||
EvidenceURLS []string `json:"evidence_urls"`
|
EvidenceURLS []string `json:"evidence_urls"`
|
||||||
OwnerAdjustmentReason string `json:"owner_adjustment_reason"`
|
OwnerAdjustmentReason string `json:"owner_adjustment_reason"`
|
||||||
|
|||||||
@@ -624,7 +624,12 @@ func (r *Repository) CounterCheckout(userID uint64, orderID uint64, req CounterC
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
return &dto, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -665,7 +670,7 @@ func (r *Repository) ListForUser(userID uint64) ([]OrderDTO, error) {
|
|||||||
}
|
}
|
||||||
items := make([]OrderDTO, 0, len(rows))
|
items := make([]OrderDTO, 0, len(rows))
|
||||||
for _, row := range rows {
|
for _, row := range rows {
|
||||||
items = append(items, row.toDTO())
|
items = append(items, row.toDTOForUser(userID))
|
||||||
}
|
}
|
||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
@@ -681,7 +686,7 @@ func (r *Repository) ListAdmin() ([]OrderDTO, error) {
|
|||||||
}
|
}
|
||||||
items := make([]OrderDTO, 0, len(rows))
|
items := make([]OrderDTO, 0, len(rows))
|
||||||
for _, row := range rows {
|
for _, row := range rows {
|
||||||
items = append(items, row.toDTO())
|
items = append(items, row.toAdminDTO())
|
||||||
}
|
}
|
||||||
return items, nil
|
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 {
|
if err := r.adminQuery().Where("o.id = ?", orderID).First(&row).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dto := row.toDTO()
|
dto := row.toAdminDTO()
|
||||||
dto.Checkout = r.latestCheckoutDTO(orderID)
|
dto.Checkout = r.latestCheckoutAdminDTO(orderID)
|
||||||
return &dto, nil
|
return &dto, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -882,8 +887,8 @@ func (r *Repository) FindForUser(userID uint64, orderID uint64) (*OrderDTO, erro
|
|||||||
First(&row).Error; err != nil {
|
First(&row).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dto := row.toDTO()
|
dto := row.toDTOForUser(userID)
|
||||||
dto.Checkout = r.latestCheckoutDTO(orderID)
|
dto.Checkout = r.latestCheckoutDTOForUser(orderID, userID, row.RentalOrder)
|
||||||
return &dto, nil
|
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 {
|
if consumableAmount < 0 || coinConsumedM < 0 || otherAmount < 0 || explicitDeduct < 0 {
|
||||||
return model.OrderCheckout{}, ErrInvalidCheckoutAmount
|
return model.OrderCheckout{}, ErrInvalidCheckoutAmount
|
||||||
}
|
}
|
||||||
deductAmount := consumableAmount + otherAmount
|
consumableAmount = roundMoney(consumableAmount)
|
||||||
|
otherAmount = roundMoney(otherAmount)
|
||||||
|
explicitDeduct = roundMoney(explicitDeduct)
|
||||||
|
deductAmount := otherAmount
|
||||||
if useExplicitDeduct {
|
if useExplicitDeduct {
|
||||||
deductAmount = explicitDeduct
|
deductAmount = explicitDeduct
|
||||||
}
|
}
|
||||||
@@ -1038,9 +1046,9 @@ func buildCheckout(order model.RentalOrder, initiatedBy uint64, status string, c
|
|||||||
OwnerRentAmount: order.OwnerRentAmount,
|
OwnerRentAmount: order.OwnerRentAmount,
|
||||||
PlatformFee: order.PlatformFee,
|
PlatformFee: order.PlatformFee,
|
||||||
DepositAmount: order.DepositAmount,
|
DepositAmount: order.DepositAmount,
|
||||||
ConsumableAmount: roundMoney(consumableAmount),
|
ConsumableAmount: consumableAmount,
|
||||||
CoinConsumedM: roundMoney(coinConsumedM),
|
CoinConsumedM: roundQuantity(coinConsumedM),
|
||||||
OtherAmount: roundMoney(otherAmount),
|
OtherAmount: otherAmount,
|
||||||
DepositDeductAmount: roundMoney(deductAmount),
|
DepositDeductAmount: roundMoney(deductAmount),
|
||||||
RenterRefundAmount: roundMoney(renterRefund),
|
RenterRefundAmount: roundMoney(renterRefund),
|
||||||
OwnerIncomeAmount: roundMoney(order.OwnerRentAmount + deductAmount),
|
OwnerIncomeAmount: roundMoney(order.OwnerRentAmount + deductAmount),
|
||||||
@@ -1069,6 +1077,10 @@ func decodeStringList(raw datatypes.JSON) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func roundMoney(value float64) float64 {
|
func roundMoney(value float64) float64 {
|
||||||
|
return math.Round(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func roundQuantity(value float64) float64 {
|
||||||
return math.Round(value*100) / 100
|
return math.Round(value*100) / 100
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1080,12 +1092,21 @@ func hasOpenCheckout(tx *gorm.DB, orderID uint64) (bool, error) {
|
|||||||
return count > 0, err
|
return count > 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Repository) latestCheckoutDTO(orderID uint64) *CheckoutDTO {
|
func (r *Repository) latestCheckoutAdminDTO(orderID uint64) *CheckoutDTO {
|
||||||
var checkout model.OrderCheckout
|
var checkout model.OrderCheckout
|
||||||
if err := r.db.Where("order_id = ?", orderID).Order("id DESC").First(&checkout).Error; err != nil {
|
if err := r.db.Where("order_id = ?", orderID).Order("id DESC").First(&checkout).Error; err != nil {
|
||||||
return 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
|
return &dto
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1120,9 +1141,12 @@ type orderRow struct {
|
|||||||
RenterPhone string
|
RenterPhone string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (row orderRow) toDTO() OrderDTO {
|
func (row orderRow) toAdminDTO() OrderDTO {
|
||||||
rentedAt := row.RentedAt
|
rentedAt := row.RentedAt
|
||||||
durationHours := orderDurationHours(row.RentalOrder)
|
durationHours := orderDurationHours(row.RentalOrder)
|
||||||
|
rentAmount := row.RentAmount
|
||||||
|
ownerRentAmount := row.OwnerRentAmount
|
||||||
|
platformFee := row.PlatformFee
|
||||||
return OrderDTO{
|
return OrderDTO{
|
||||||
ID: row.ID,
|
ID: row.ID,
|
||||||
OrderNo: row.OrderNo,
|
OrderNo: row.OrderNo,
|
||||||
@@ -1137,10 +1161,12 @@ func (row orderRow) toDTO() OrderDTO {
|
|||||||
LoginPlatform: row.LoginPlatform,
|
LoginPlatform: row.LoginPlatform,
|
||||||
RentedAt: rentedAt,
|
RentedAt: rentedAt,
|
||||||
EstimatedDurationHours: durationHours,
|
EstimatedDurationHours: durationHours,
|
||||||
RentAmount: row.RentAmount,
|
PriceRole: "admin",
|
||||||
OwnerRentAmount: row.OwnerRentAmount,
|
DisplayAmount: row.RentAmount,
|
||||||
|
RentAmount: &rentAmount,
|
||||||
|
OwnerRentAmount: &ownerRentAmount,
|
||||||
DepositAmount: row.DepositAmount,
|
DepositAmount: row.DepositAmount,
|
||||||
PlatformFee: row.PlatformFee,
|
PlatformFee: &platformFee,
|
||||||
AccountSnapshot: row.AccountSnapshot,
|
AccountSnapshot: row.AccountSnapshot,
|
||||||
Status: row.Status,
|
Status: row.Status,
|
||||||
HandoffStatus: row.HandoffStatus,
|
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 {
|
func toHandoffDTO(record model.HandoffRecord) HandoffRecordDTO {
|
||||||
return HandoffRecordDTO{
|
return HandoffRecordDTO{
|
||||||
ID: record.ID,
|
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{
|
return CheckoutDTO{
|
||||||
ID: checkout.ID,
|
ID: checkout.ID,
|
||||||
OrderID: checkout.OrderID,
|
OrderID: checkout.OrderID,
|
||||||
InitiatedBy: checkout.InitiatedBy,
|
InitiatedBy: checkout.InitiatedBy,
|
||||||
Status: checkout.Status,
|
Status: checkout.Status,
|
||||||
RentAmount: checkout.RentAmount,
|
PriceRole: "admin",
|
||||||
OwnerRentAmount: checkout.OwnerRentAmount,
|
DisplayAmount: checkout.RentAmount,
|
||||||
PlatformFee: checkout.PlatformFee,
|
RentAmount: &rentAmount,
|
||||||
|
OwnerRentAmount: &ownerRentAmount,
|
||||||
|
PlatformFee: &platformFee,
|
||||||
DepositAmount: checkout.DepositAmount,
|
DepositAmount: checkout.DepositAmount,
|
||||||
ConsumableAmount: checkout.ConsumableAmount,
|
ConsumableAmount: checkout.ConsumableAmount,
|
||||||
CoinConsumedM: checkout.CoinConsumedM,
|
CoinConsumedM: checkout.CoinConsumedM,
|
||||||
OtherAmount: checkout.OtherAmount,
|
OtherAmount: checkout.OtherAmount,
|
||||||
DepositDeductAmount: checkout.DepositDeductAmount,
|
DepositDeductAmount: checkout.DepositDeductAmount,
|
||||||
RenterRefundAmount: checkout.RenterRefundAmount,
|
RenterRefundAmount: &renterRefundAmount,
|
||||||
OwnerIncomeAmount: checkout.OwnerIncomeAmount,
|
OwnerIncomeAmount: &ownerIncomeAmount,
|
||||||
Content: checkout.Content,
|
Content: checkout.Content,
|
||||||
EvidenceURLS: decodeStringList(checkout.EvidenceURLS),
|
EvidenceURLS: decodeStringList(checkout.EvidenceURLS),
|
||||||
OwnerAdjustmentReason: checkout.OwnerAdjustmentReason,
|
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) {
|
func makeAccountSnapshot(account model.GameAccount) (datatypes.JSON, error) {
|
||||||
payload := map[string]any{
|
payload := map[string]any{
|
||||||
"account_id": account.ID,
|
"account_id": account.ID,
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ func applyEntry(account *model.WalletAccount, entry Entry) (float64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func roundWalletMoney(value float64) float64 {
|
func roundWalletMoney(value float64) float64 {
|
||||||
return math.Round(value*100) / 100
|
return math.Round(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func toAccountDTO(account model.WalletAccount) *AccountDTO {
|
func toAccountDTO(account model.WalletAccount) *AccountDTO {
|
||||||
|
|||||||
@@ -16,10 +16,12 @@ export interface Order {
|
|||||||
login_platform: string
|
login_platform: string
|
||||||
rented_at?: string
|
rented_at?: string
|
||||||
estimated_duration_hours: number
|
estimated_duration_hours: number
|
||||||
rent_amount: number
|
price_role?: 'renter' | 'owner' | 'admin' | string
|
||||||
owner_rent_amount: number
|
display_amount: number
|
||||||
|
rent_amount?: number
|
||||||
|
owner_rent_amount?: number
|
||||||
deposit_amount: number
|
deposit_amount: number
|
||||||
platform_fee: number
|
platform_fee?: number
|
||||||
account_snapshot?: Record<string, unknown>
|
account_snapshot?: Record<string, unknown>
|
||||||
status: OrderStatus
|
status: OrderStatus
|
||||||
handoff_status: HandoffStatus
|
handoff_status: HandoffStatus
|
||||||
@@ -34,16 +36,18 @@ export interface Checkout {
|
|||||||
order_id: number
|
order_id: number
|
||||||
initiated_by: number
|
initiated_by: number
|
||||||
status: SettlementStatus
|
status: SettlementStatus
|
||||||
rent_amount: number
|
price_role?: 'renter' | 'owner' | 'admin' | string
|
||||||
owner_rent_amount: number
|
display_amount: number
|
||||||
platform_fee: number
|
rent_amount?: number
|
||||||
|
owner_rent_amount?: number
|
||||||
|
platform_fee?: number
|
||||||
deposit_amount: number
|
deposit_amount: number
|
||||||
consumable_amount: number
|
consumable_amount: number
|
||||||
coin_consumed_m: number
|
coin_consumed_m: number
|
||||||
other_amount: number
|
other_amount: number
|
||||||
deposit_deduct_amount: number
|
deposit_deduct_amount: number
|
||||||
renter_refund_amount: number
|
renter_refund_amount?: number
|
||||||
owner_income_amount: number
|
owner_income_amount?: number
|
||||||
content: string
|
content: string
|
||||||
evidence_urls: string[]
|
evidence_urls: string[]
|
||||||
owner_adjustment_reason: string
|
owner_adjustment_reason: string
|
||||||
|
|||||||
@@ -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 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) {
|
export function roundMoney(value: number) {
|
||||||
return Math.round(value * 100) / 100
|
return Math.round(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function roundRatio(value: number) {
|
export function roundRatio(value: number) {
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ const disputeEvidenceText = ref('')
|
|||||||
|
|
||||||
const isOwner = computed(() => order.value?.owner_id === session.userId)
|
const isOwner = computed(() => order.value?.owner_id === session.userId)
|
||||||
const isRenter = computed(() => order.value?.renter_id === session.userId)
|
const isRenter = computed(() => order.value?.renter_id === session.userId)
|
||||||
|
const orderAmountLabel = computed(() => (isOwner.value ? '我的租金' : '订单金额'))
|
||||||
const canOpenDispute = computed(() => {
|
const canOpenDispute = computed(() => {
|
||||||
if (!order.value || (!isOwner.value && !isRenter.value)) return false
|
if (!order.value || (!isOwner.value && !isRenter.value)) return false
|
||||||
return !['completed', 'cancelled', 'closed', 'disputing', 'checkout_disputing', 'abnormal'].includes(order.value.status)
|
return !['completed', 'cancelled', 'closed', 'disputing', 'checkout_disputing', 'abnormal'].includes(order.value.status)
|
||||||
@@ -86,10 +87,10 @@ const resourceChargeAmount = computed(() => {
|
|||||||
})
|
})
|
||||||
const snapshotHafCoinM = computed(() => {
|
const snapshotHafCoinM = computed(() => {
|
||||||
const snapshot = readSnapshot()
|
const snapshot = readSnapshot()
|
||||||
return roundMoney(readNumber(snapshot?.haf_coin_amount) / 1000000)
|
return roundQuantity(readNumber(snapshot?.haf_coin_amount) / 1000000)
|
||||||
})
|
})
|
||||||
const remainingHafCoinM = computed(() => {
|
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)
|
onMounted(loadOrder)
|
||||||
@@ -387,12 +388,12 @@ function checkoutContentWithSummary() {
|
|||||||
if (usedResources.length) {
|
if (usedResources.length) {
|
||||||
lines.push(
|
lines.push(
|
||||||
`额外消耗品:${usedResources
|
`额外消耗品:${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(';')}`,
|
.join(';')}`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (Number(checkoutForm.value.coin_consumed_m || 0) > 0) {
|
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) {
|
if (lines.length === 0) {
|
||||||
lines.push('租客发起结账。')
|
lines.push('租客发起结账。')
|
||||||
@@ -415,9 +416,22 @@ function readUnitPrice(priceText: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function roundMoney(value: number) {
|
function roundMoney(value: number) {
|
||||||
|
return Math.round(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function roundQuantity(value: number) {
|
||||||
return Math.round(value * 100) / 100
|
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) {
|
function readNumber(value: unknown) {
|
||||||
const number = Number(value || 0)
|
const number = Number(value || 0)
|
||||||
return Number.isFinite(number) ? number : 0
|
return Number.isFinite(number) ? number : 0
|
||||||
@@ -462,16 +476,12 @@ function linesToList(value: string) {
|
|||||||
<strong>{{ handoffStatusLabel(order.handoff_status) }}</strong>
|
<strong>{{ handoffStatusLabel(order.handoff_status) }}</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="metric-card">
|
<div class="metric-card">
|
||||||
<span>订单金额</span>
|
<span>{{ orderAmountLabel }}</span>
|
||||||
<strong>¥{{ order.rent_amount }}</strong>
|
<strong>¥{{ money(order.display_amount) }}</strong>
|
||||||
</div>
|
|
||||||
<div class="metric-card">
|
|
||||||
<span>平台费用</span>
|
|
||||||
<strong>¥{{ order.platform_fee }}</strong>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="metric-card">
|
<div class="metric-card">
|
||||||
<span>押金</span>
|
<span>押金</span>
|
||||||
<strong>¥{{ order.deposit_amount }}</strong>
|
<strong>¥{{ money(order.deposit_amount) }}</strong>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -518,7 +528,7 @@ function linesToList(value: string) {
|
|||||||
<div class="checkout-resource-panel panel-action">
|
<div class="checkout-resource-panel panel-action">
|
||||||
<div class="checkout-resource-head">
|
<div class="checkout-resource-head">
|
||||||
<strong>额外消耗品</strong>
|
<strong>额外消耗品</strong>
|
||||||
<span>扣款合计:¥{{ resourceChargeAmount.toFixed(2) }}</span>
|
<span>金额合计:¥{{ money(resourceChargeAmount) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<el-empty v-if="checkoutResources.length === 0" description="订单快照中暂无额外消耗品" />
|
<el-empty v-if="checkoutResources.length === 0" description="订单快照中暂无额外消耗品" />
|
||||||
<div v-for="item in checkoutResources" v-else :key="item.key" class="checkout-resource-row">
|
<div v-for="item in checkoutResources" v-else :key="item.key" class="checkout-resource-row">
|
||||||
@@ -533,16 +543,16 @@ function linesToList(value: string) {
|
|||||||
:precision="0"
|
:precision="0"
|
||||||
controls-position="right"
|
controls-position="right"
|
||||||
/>
|
/>
|
||||||
<span class="checkout-resource-amount">¥{{ resourceLineAmount(item).toFixed(2) }}</span>
|
<span class="checkout-resource-amount">¥{{ money(resourceLineAmount(item)) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-form class="form-grid panel-action" label-position="top">
|
<el-form class="form-grid panel-action" label-position="top">
|
||||||
<el-form-item label="消耗哈夫币(M)">
|
<el-form-item label="消耗哈夫币(M)">
|
||||||
<el-input-number v-model="checkoutForm.coin_consumed_m" class="full-control" :min="0" :max="snapshotHafCoinM" :precision="2" controls-position="right" />
|
<el-input-number v-model="checkoutForm.coin_consumed_m" class="full-control" :min="0" :max="snapshotHafCoinM" :precision="2" controls-position="right" />
|
||||||
<span class="field-hint">订单快照 {{ snapshotHafCoinM.toFixed(2) }}M,预计剩余 {{ remainingHafCoinM.toFixed(2) }}M</span>
|
<span class="field-hint">订单快照 {{ quantity(snapshotHafCoinM) }}M,预计剩余 {{ quantity(remainingHafCoinM) }}M</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="其他扣款(元)">
|
<el-form-item label="其他扣款(元)">
|
||||||
<el-input-number v-model="checkoutForm.other_amount" class="full-control" :min="0" :precision="2" controls-position="right" />
|
<el-input-number v-model="checkoutForm.other_amount" class="full-control" :min="0" :precision="0" controls-position="right" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<el-input
|
<el-input
|
||||||
@@ -557,9 +567,10 @@ function linesToList(value: string) {
|
|||||||
|
|
||||||
<div v-if="order && order.checkout && ['pending_checkout_confirm', 'pending_checkout_accept'].includes(order.status)" class="order-panel">
|
<div v-if="order && order.checkout && ['pending_checkout_confirm', 'pending_checkout_accept'].includes(order.status)" class="order-panel">
|
||||||
<h2>结账明细</h2>
|
<h2>结账明细</h2>
|
||||||
<p>买家租金:¥{{ order.checkout.rent_amount }},号主租金:¥{{ order.checkout.owner_rent_amount }},平台费用:¥{{ order.checkout.platform_fee }}</p>
|
<p>{{ orderAmountLabel }}:¥{{ money(order.checkout.display_amount) }},押金:¥{{ money(order.checkout.deposit_amount) }}</p>
|
||||||
<p>押金:¥{{ order.checkout.deposit_amount }}</p>
|
<p>额外消耗品金额:¥{{ money(order.checkout.consumable_amount) }},押金扣除:¥{{ money(order.checkout.deposit_deduct_amount) }}</p>
|
||||||
<p>扣除:¥{{ order.checkout.deposit_deduct_amount }},退还租客:¥{{ order.checkout.renter_refund_amount }},号主收入:¥{{ order.checkout.owner_income_amount }}</p>
|
<p v-if="isRenter">退还租客:¥{{ money(order.checkout.renter_refund_amount) }}</p>
|
||||||
|
<p v-if="isOwner">号主收入:¥{{ money(order.checkout.owner_income_amount) }}</p>
|
||||||
<p v-if="order.checkout.content">说明:{{ order.checkout.content }}</p>
|
<p v-if="order.checkout.content">说明:{{ order.checkout.content }}</p>
|
||||||
<p v-if="order.checkout.owner_adjustment_reason">修正原因:{{ order.checkout.owner_adjustment_reason }}</p>
|
<p v-if="order.checkout.owner_adjustment_reason">修正原因:{{ order.checkout.owner_adjustment_reason }}</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -571,17 +582,17 @@ function linesToList(value: string) {
|
|||||||
|
|
||||||
<h2 class="panel-action">修改结账</h2>
|
<h2 class="panel-action">修改结账</h2>
|
||||||
<el-form class="form-grid" label-position="top">
|
<el-form class="form-grid" label-position="top">
|
||||||
<el-form-item label="消耗扣款(元)">
|
<el-form-item label="额外消耗品金额(已含租金)">
|
||||||
<el-input-number v-model="counterForm.consumable_amount" class="full-control" :min="0" :precision="2" controls-position="right" />
|
<el-input-number v-model="counterForm.consumable_amount" class="full-control" :min="0" :precision="0" controls-position="right" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="消耗哈夫币(M)">
|
<el-form-item label="消耗哈夫币(M)">
|
||||||
<el-input-number v-model="counterForm.coin_consumed_m" class="full-control" :min="0" :precision="2" controls-position="right" />
|
<el-input-number v-model="counterForm.coin_consumed_m" class="full-control" :min="0" :precision="2" controls-position="right" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="其他扣款(元)">
|
<el-form-item label="其他扣款(元)">
|
||||||
<el-input-number v-model="counterForm.other_amount" class="full-control" :min="0" :precision="2" controls-position="right" />
|
<el-input-number v-model="counterForm.other_amount" class="full-control" :min="0" :precision="0" controls-position="right" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="押金扣除(元)">
|
<el-form-item label="押金扣除(元)">
|
||||||
<el-input-number v-model="counterForm.deposit_deduct_amount" class="full-control" :min="0" :max="order.deposit_amount" :precision="2" controls-position="right" />
|
<el-input-number v-model="counterForm.deposit_deduct_amount" class="full-control" :min="0" :max="order.deposit_amount" :precision="0" controls-position="right" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<el-input v-model="counterForm.reason" class="panel-action" type="textarea" :rows="3" placeholder="填写修改原因" />
|
<el-input v-model="counterForm.reason" class="panel-action" type="textarea" :rows="3" placeholder="填写修改原因" />
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ function orderRole(order: Order) {
|
|||||||
if (order.owner_id === session.userId) return '号主'
|
if (order.owner_id === session.userId) return '号主'
|
||||||
return '-'
|
return '-'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function money(value: unknown) {
|
||||||
|
return Math.round(Number(value || 0))
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -61,8 +65,12 @@ function orderRole(order: Order) {
|
|||||||
<el-table v-loading="loading" class="table-panel" :data="orders">
|
<el-table v-loading="loading" class="table-panel" :data="orders">
|
||||||
<el-table-column prop="order_no" label="订单号" min-width="210" />
|
<el-table-column prop="order_no" label="订单号" min-width="210" />
|
||||||
<el-table-column prop="title" label="账号" min-width="180" />
|
<el-table-column prop="title" label="账号" min-width="180" />
|
||||||
<el-table-column prop="rent_amount" label="订单金额" width="100" />
|
<el-table-column label="我的金额" width="100">
|
||||||
<el-table-column prop="deposit_amount" label="押金" width="100" />
|
<template #default="{ row }">¥{{ money(row.display_amount) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="押金" width="100">
|
||||||
|
<template #default="{ row }">¥{{ money(row.deposit_amount) }}</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="身份" width="80">
|
<el-table-column label="身份" width="80">
|
||||||
<template #default="{ row }">{{ orderRole(row) }}</template>
|
<template #default="{ row }">{{ orderRole(row) }}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ function readError(error: unknown, fallback: string) {
|
|||||||
|
|
||||||
<div class="table-panel recharge-panel">
|
<div class="table-panel recharge-panel">
|
||||||
<h2>开发充值</h2>
|
<h2>开发充值</h2>
|
||||||
<el-input-number v-model="rechargeAmount" :min="0.01" :precision="2" controls-position="right" />
|
<el-input-number v-model="rechargeAmount" :min="1" :precision="0" controls-position="right" />
|
||||||
<el-button type="primary" :loading="recharging" @click="handleRecharge">充值</el-button>
|
<el-button type="primary" :loading="recharging" @click="handleRecharge">充值</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ async function loadDashboard() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function money(value?: number) {
|
function money(value?: number) {
|
||||||
return `¥${Number(value || 0).toFixed(2)}`
|
return `¥${Math.round(Number(value || 0))}`
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ function readError(error: unknown, fallback: string) {
|
|||||||
v-model="amount"
|
v-model="amount"
|
||||||
class="full-control panel-action"
|
class="full-control panel-action"
|
||||||
:min="0"
|
:min="0"
|
||||||
:precision="2"
|
:precision="0"
|
||||||
:step="10"
|
:step="10"
|
||||||
placeholder="裁决金额"
|
placeholder="裁决金额"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ async function submitAction() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function money(value: number) {
|
function money(value: number) {
|
||||||
return `¥${Number(value || 0).toFixed(2)}`
|
return `¥${Math.round(Number(value || 0))}`
|
||||||
}
|
}
|
||||||
|
|
||||||
function listingPrice(row: Listing) {
|
function listingPrice(row: Listing) {
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ function openEvidence(row: Listing) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function listingPrice(row: Listing) {
|
function listingPrice(row: Listing) {
|
||||||
return `¥${Number(row.price || 0).toFixed(2)}`
|
return `¥${Math.round(Number(row.price || 0))}`
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractObjectKey(url: string) {
|
function extractObjectKey(url: string) {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ function resetFilters() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function money(value: number) {
|
function money(value: number) {
|
||||||
return `¥${Number(value || 0).toFixed(2)}`
|
return `¥${Math.round(Number(value || 0))}`
|
||||||
}
|
}
|
||||||
|
|
||||||
function listingPrice(row: Listing) {
|
function listingPrice(row: Listing) {
|
||||||
|
|||||||
@@ -75,6 +75,10 @@ function orderEstimatedEndAt() {
|
|||||||
if (!rentedAt || durationHours <= 0) return undefined
|
if (!rentedAt || durationHours <= 0) return undefined
|
||||||
return new Date(new Date(rentedAt).getTime() + durationHours * 60 * 60 * 1000).toISOString()
|
return new Date(new Date(rentedAt).getTime() + durationHours * 60 * 60 * 1000).toISOString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function money(value: unknown) {
|
||||||
|
return Math.round(Number(value || 0))
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -105,15 +109,15 @@ function orderEstimatedEndAt() {
|
|||||||
</div>
|
</div>
|
||||||
<div class="metric-card">
|
<div class="metric-card">
|
||||||
<span>订单金额</span>
|
<span>订单金额</span>
|
||||||
<strong>¥{{ order.rent_amount }}</strong>
|
<strong>¥{{ money(order.rent_amount) }}</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="metric-card">
|
<div class="metric-card">
|
||||||
<span>平台费用</span>
|
<span>平台费用</span>
|
||||||
<strong>¥{{ order.platform_fee }}</strong>
|
<strong>¥{{ money(order.platform_fee) }}</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="metric-card">
|
<div class="metric-card">
|
||||||
<span>押金</span>
|
<span>押金</span>
|
||||||
<strong>¥{{ order.deposit_amount }}</strong>
|
<strong>¥{{ money(order.deposit_amount) }}</strong>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ function handleSizeChange() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function money(value: number) {
|
function money(value: number) {
|
||||||
return `¥${value.toFixed(2)}`
|
return `¥${Math.round(Number(value || 0))}`
|
||||||
}
|
}
|
||||||
|
|
||||||
function directionType(direction: string) {
|
function directionType(direction: string) {
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ onMounted(async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const orderTotal = computed(() => {
|
const orderTotal = computed(() => {
|
||||||
if (!listing.value) return "0.00";
|
if (!listing.value) return "0";
|
||||||
return getListingDisplayPrice(listing.value).toFixed(2);
|
return `${Math.round(getListingDisplayPrice(listing.value))}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
const detailMetrics = computed(() => {
|
const detailMetrics = computed(() => {
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ const showRejectPopup = ref(false);
|
|||||||
|
|
||||||
const isOwner = computed(() => order.value?.owner_id === session.userId);
|
const isOwner = computed(() => order.value?.owner_id === session.userId);
|
||||||
const isRenter = computed(() => order.value?.renter_id === session.userId);
|
const isRenter = computed(() => order.value?.renter_id === session.userId);
|
||||||
|
const orderAmountLabel = computed(() => (isOwner.value ? "我的租金" : "订单金额"));
|
||||||
const canOpenDispute = computed(() => {
|
const canOpenDispute = computed(() => {
|
||||||
if (!order.value || (!isOwner.value && !isRenter.value)) return false;
|
if (!order.value || (!isOwner.value && !isRenter.value)) return false;
|
||||||
return !["completed", "cancelled", "closed", "disputing", "checkout_disputing", "abnormal"].includes(order.value.status);
|
return !["completed", "cancelled", "closed", "disputing", "checkout_disputing", "abnormal"].includes(order.value.status);
|
||||||
@@ -94,10 +95,10 @@ const resourceChargeAmount = computed(() => {
|
|||||||
});
|
});
|
||||||
const snapshotHafCoinM = computed(() => {
|
const snapshotHafCoinM = computed(() => {
|
||||||
const snapshot = readSnapshot();
|
const snapshot = readSnapshot();
|
||||||
return roundMoney(readNumber(snapshot?.haf_coin_amount) / 1000000);
|
return roundQuantity(readNumber(snapshot?.haf_coin_amount) / 1000000);
|
||||||
});
|
});
|
||||||
const remainingHafCoinM = computed(() => {
|
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);
|
onMounted(loadOrder);
|
||||||
@@ -450,14 +451,14 @@ function checkoutContentWithSummary() {
|
|||||||
.map(
|
.map(
|
||||||
(item) =>
|
(item) =>
|
||||||
`${item.label} ${readResourceUsage(item.key)}/${item.quantity}${
|
`${item.label} ${readResourceUsage(item.key)}/${item.quantity}${
|
||||||
isChargedResource(item) ? `,扣款¥${resourceLineAmount(item).toFixed(2)}` : ",赠送不扣款"
|
isChargedResource(item) ? `,金额¥${money(resourceLineAmount(item))}` : ",赠送不扣款"
|
||||||
}`
|
}`
|
||||||
)
|
)
|
||||||
.join(";")}`
|
.join(";")}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (Number(checkoutForm.value.coin_consumed_m || 0) > 0) {
|
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) {
|
if (lines.length === 0) {
|
||||||
lines.push("租客发起结账。");
|
lines.push("租客发起结账。");
|
||||||
@@ -480,9 +481,22 @@ function readUnitPrice(priceText: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function roundMoney(value: number) {
|
function roundMoney(value: number) {
|
||||||
|
return Math.round(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function roundQuantity(value: number) {
|
||||||
return Math.round(value * 100) / 100;
|
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) {
|
function readNumber(value: unknown) {
|
||||||
const number = Number(value || 0);
|
const number = Number(value || 0);
|
||||||
return Number.isFinite(number) ? number : 0;
|
return Number.isFinite(number) ? number : 0;
|
||||||
@@ -560,12 +574,12 @@ function getStatusTagType(status: string) {
|
|||||||
<h2 class="order-title">{{ order.title }}</h2>
|
<h2 class="order-title">{{ order.title }}</h2>
|
||||||
<div class="order-meta-grid">
|
<div class="order-meta-grid">
|
||||||
<div class="meta-item">
|
<div class="meta-item">
|
||||||
<span class="meta-label">订单金额</span>
|
<span class="meta-label">{{ orderAmountLabel }}</span>
|
||||||
<strong class="meta-value accent">¥{{ order.rent_amount }}</strong>
|
<strong class="meta-value accent">¥{{ money(order.display_amount) }}</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="meta-item">
|
<div class="meta-item">
|
||||||
<span class="meta-label">押金</span>
|
<span class="meta-label">押金</span>
|
||||||
<strong class="meta-value">¥{{ order.deposit_amount }}</strong>
|
<strong class="meta-value">¥{{ money(order.deposit_amount) }}</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="meta-item">
|
<div class="meta-item">
|
||||||
<span class="meta-label">交接状态</span>
|
<span class="meta-label">交接状态</span>
|
||||||
@@ -711,12 +725,12 @@ function getStatusTagType(status: string) {
|
|||||||
min="0"
|
min="0"
|
||||||
:max="item.quantity"
|
:max="item.quantity"
|
||||||
/>
|
/>
|
||||||
<span class="resource-line-amount">¥{{ resourceLineAmount(item).toFixed(2) }}</span>
|
<span class="resource-line-amount">¥{{ money(resourceLineAmount(item)) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="resource-panel-footer">
|
<div class="resource-panel-footer">
|
||||||
<span>物资费用扣款合计:</span>
|
<span>物资金额合计:</span>
|
||||||
<strong>¥{{ resourceChargeAmount.toFixed(2) }}</strong>
|
<strong>¥{{ money(resourceChargeAmount) }}</strong>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -735,7 +749,7 @@ function getStatusTagType(status: string) {
|
|||||||
</template>
|
</template>
|
||||||
</van-field>
|
</van-field>
|
||||||
<div class="coin-hint">
|
<div class="coin-hint">
|
||||||
订单快照 {{ snapshotHafCoinM.toFixed(2) }}M,预计剩余 {{ remainingHafCoinM.toFixed(2) }}M
|
订单快照 {{ quantity(snapshotHafCoinM) }}M,预计剩余 {{ quantity(remainingHafCoinM) }}M
|
||||||
</div>
|
</div>
|
||||||
<van-field label="其他费用" label-width="100px">
|
<van-field label="其他费用" label-width="100px">
|
||||||
<template #input>
|
<template #input>
|
||||||
@@ -778,13 +792,12 @@ function getStatusTagType(status: string) {
|
|||||||
<section v-if="order.checkout && ['pending_checkout_confirm', 'pending_checkout_accept'].includes(order.status)" class="card-section">
|
<section v-if="order.checkout && ['pending_checkout_confirm', 'pending_checkout_accept'].includes(order.status)" class="card-section">
|
||||||
<h3 class="section-title">结账结算账单</h3>
|
<h3 class="section-title">结账结算账单</h3>
|
||||||
<van-cell-group inset :border="false">
|
<van-cell-group inset :border="false">
|
||||||
<van-cell title="买家租金" :value="`¥${order.checkout.rent_amount}`" />
|
<van-cell :title="orderAmountLabel" :value="`¥${money(order.checkout.display_amount)}`" />
|
||||||
<van-cell title="号主实收租金" :value="`¥${order.checkout.owner_rent_amount}`" />
|
<van-cell title="押金总额" :value="`¥${money(order.checkout.deposit_amount)}`" />
|
||||||
<van-cell title="平台服务费" :value="`¥${order.checkout.platform_fee}`" />
|
<van-cell title="额外消耗品金额" :value="`¥${money(order.checkout.consumable_amount)}`" />
|
||||||
<van-cell title="押金总额" :value="`¥${order.checkout.deposit_amount}`" />
|
<van-cell title="押金扣除" :value="`¥${money(order.checkout.deposit_deduct_amount)}`" value-class="red-text" />
|
||||||
<van-cell title="扣款总计" :value="`¥${order.checkout.deposit_deduct_amount}`" value-class="red-text" />
|
<van-cell v-if="isRenter" title="退还租客押金" :value="`¥${money(order.checkout.renter_refund_amount)}`" value-class="green-text" />
|
||||||
<van-cell title="退还租客押金" :value="`¥${order.checkout.renter_refund_amount}`" value-class="green-text" />
|
<van-cell v-if="isOwner" title="号主最终收益" :value="`¥${money(order.checkout.owner_income_amount)}`" value-class="green-text" />
|
||||||
<van-cell title="号主最终收益" :value="`¥${order.checkout.owner_income_amount}`" value-class="green-text" />
|
|
||||||
<van-cell v-if="order.checkout.content" title="结账备注" :label="order.checkout.content" />
|
<van-cell v-if="order.checkout.content" title="结账备注" :label="order.checkout.content" />
|
||||||
<van-cell v-if="order.checkout.owner_adjustment_reason" title="号主修正原因" :label="order.checkout.owner_adjustment_reason" />
|
<van-cell v-if="order.checkout.owner_adjustment_reason" title="号主修正原因" :label="order.checkout.owner_adjustment_reason" />
|
||||||
</van-cell-group>
|
</van-cell-group>
|
||||||
|
|||||||
@@ -93,6 +93,10 @@ function readError(error: unknown, fallback: string) {
|
|||||||
}
|
}
|
||||||
return fallback;
|
return fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function money(value: unknown) {
|
||||||
|
return Math.round(Number(value || 0));
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -164,12 +168,12 @@ function readError(error: unknown, fallback: string) {
|
|||||||
|
|
||||||
<div class="price-row">
|
<div class="price-row">
|
||||||
<div class="price-item">
|
<div class="price-item">
|
||||||
<span class="price-label">买家实付租金</span>
|
<span class="price-label">我的金额</span>
|
||||||
<span class="price-val">¥{{ order.rent_amount }}</span>
|
<span class="price-val">¥{{ money(order.display_amount) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="price-item">
|
<div class="price-item">
|
||||||
<span class="price-label">押金金额</span>
|
<span class="price-label">押金金额</span>
|
||||||
<span class="price-val deposit">¥{{ order.deposit_amount }}</span>
|
<span class="price-val deposit">¥{{ money(order.deposit_amount) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ function resolveAvatarURL(url: string | undefined | null) {
|
|||||||
<div class="balance-row">
|
<div class="balance-row">
|
||||||
<div class="balance-info">
|
<div class="balance-info">
|
||||||
<span class="balance-label">账户可用余额(元)</span>
|
<span class="balance-label">账户可用余额(元)</span>
|
||||||
<strong class="balance-value">¥{{ balance.toFixed(2) }}</strong>
|
<strong class="balance-value">¥{{ Math.round(Number(balance || 0)) }}</strong>
|
||||||
</div>
|
</div>
|
||||||
<button class="withdraw-btn" @click="handleWithdraw">提现</button>
|
<button class="withdraw-btn" @click="handleWithdraw">提现</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -375,7 +375,7 @@ function resolveAvatarURL(url: string | undefined | null) {
|
|||||||
<span class="ledger-time">{{ formatDateMinute(item.created_at) }}</span>
|
<span class="ledger-time">{{ formatDateMinute(item.created_at) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="ledger-right" :class="item.direction === 'in' ? 'in-color' : 'out-color'">
|
<div class="ledger-right" :class="item.direction === 'in' ? 'in-color' : 'out-color'">
|
||||||
{{ item.direction === 'in' ? '+' : '-' }}¥{{ item.amount.toFixed(2) }}
|
{{ item.direction === 'in' ? '+' : '-' }}¥{{ Math.round(Number(item.amount || 0)) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ function getStatusText(item: Listing) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function listingPrice(item: Listing) {
|
function listingPrice(item: Listing) {
|
||||||
return getListingSellerPrice(item).toFixed(2)
|
return `${Math.round(getListingSellerPrice(item))}`
|
||||||
}
|
}
|
||||||
|
|
||||||
function goBack() {
|
function goBack() {
|
||||||
@@ -197,7 +197,7 @@ function goBack() {
|
|||||||
|
|
||||||
<div class="price-row">
|
<div class="price-row">
|
||||||
<span class="price-val">¥{{ listingPrice(item) }}</span>
|
<span class="price-val">¥{{ listingPrice(item) }}</span>
|
||||||
<span class="deposit-val">押金: ¥{{ item.deposit_amount.toFixed(2) }}</span>
|
<span class="deposit-val">押金: ¥{{ Math.round(Number(item.deposit_amount || 0)) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ function readError(error: unknown, fallback: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function listingPrice(item: Listing) {
|
function listingPrice(item: Listing) {
|
||||||
return Number(item.price || 0).toFixed(2);
|
return `${Math.round(Number(item.price || 0))}`;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,10 @@ function actionText(order: Order) {
|
|||||||
if (['overdue', 'checkout_disputing', 'disputing', 'abnormal'].includes(order.status)) return '查看处理'
|
if (['overdue', 'checkout_disputing', 'disputing', 'abnormal'].includes(order.status)) return '查看处理'
|
||||||
return '详情'
|
return '详情'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function money(value: unknown) {
|
||||||
|
return Math.round(Number(value || 0))
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -103,7 +107,7 @@ function actionText(order: Order) {
|
|||||||
<el-table-column prop="order_no" label="订单号" min-width="220" />
|
<el-table-column prop="order_no" label="订单号" min-width="220" />
|
||||||
<el-table-column prop="title" label="账号" min-width="180" />
|
<el-table-column prop="title" label="账号" min-width="180" />
|
||||||
<el-table-column label="金额" width="120">
|
<el-table-column label="金额" width="120">
|
||||||
<template #default="{ row }">¥{{ row.rent_amount }}</template>
|
<template #default="{ row }">¥{{ money(row.display_amount) }}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="订单状态" width="150">
|
<el-table-column label="订单状态" width="150">
|
||||||
<template #default="{ row }">{{ orderStatusLabel(row.status) }}</template>
|
<template #default="{ row }">{{ orderStatusLabel(row.status) }}</template>
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ async function offline(id: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function listingPrice(row: Listing) {
|
function listingPrice(row: Listing) {
|
||||||
return `¥${getListingSellerPrice(row).toFixed(2)}`
|
return `¥${Math.round(getListingSellerPrice(row))}`
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user