feat(admin-listing): 商品管理列表在租金/押金左侧展示号主纯币价格
- listingDisplay 新增 getListingSellerCoinPrice,读取价格快照 seller_coin_base_price (号主收号价中的纯币部分,不含额外消耗品) - 商品管理表格新增「纯币价格」列并置于「租金/押金」左侧,悬停显示完整说明 - 快照缺失(旧数据/无定价快照)时展示 -,与相邻列风格一致 - PNG 导出列定义同步新增该列,保持导出与页面一致 - 补 listingDisplay 单测:纯币价读取、消耗品单独计价时与号主总价区分、缺快照兜底
This commit is contained in:
@@ -22,6 +22,7 @@ import {
|
|||||||
formatRatio,
|
formatRatio,
|
||||||
getCoinWan,
|
getCoinWan,
|
||||||
getDailyLoss,
|
getDailyLoss,
|
||||||
|
getListingSellerCoinPrice,
|
||||||
getResourceQuantity,
|
getResourceQuantity,
|
||||||
getSkinGroup,
|
getSkinGroup,
|
||||||
} from '@/shared/utils/listingDisplay'
|
} from '@/shared/utils/listingDisplay'
|
||||||
@@ -135,6 +136,7 @@ const screenshotColumns = [
|
|||||||
read: (row: Listing) => characterAndWeaponSkinText(row),
|
read: (row: Listing) => characterAndWeaponSkinText(row),
|
||||||
},
|
},
|
||||||
{ label: '号主备注', width: 160, read: (row: Listing) => ownerRemarkText(row) },
|
{ label: '号主备注', width: 160, read: (row: Listing) => ownerRemarkText(row) },
|
||||||
|
{ label: '纯币价格', width: 90, read: (row: Listing) => ownerPureCoinPriceText(row) },
|
||||||
{ label: '租金/押金', width: 96, read: (row: Listing) => rentAndDepositText(row) },
|
{ label: '租金/押金', width: 96, read: (row: Listing) => rentAndDepositText(row) },
|
||||||
{ label: '比例', width: 64, read: (row: Listing) => formatRatio(row) },
|
{ label: '比例', width: 64, read: (row: Listing) => formatRatio(row) },
|
||||||
{
|
{
|
||||||
@@ -599,6 +601,13 @@ function rentAndDepositText(row: Listing) {
|
|||||||
return `${listingPrice(row)}/${formatCentWithSymbol(row.deposit_amount_cent)}`
|
return `${listingPrice(row)}/${formatCentWithSymbol(row.deposit_amount_cent)}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 号主纯币价格:号主收号价里的纯币部分(不含额外消耗品),取自发布时固化的价格快照。
|
||||||
|
function ownerPureCoinPriceText(row: Listing) {
|
||||||
|
const price = getListingSellerCoinPrice(row)
|
||||||
|
if (price <= 0) return '-'
|
||||||
|
return formatCentWithSymbol(Math.round(price * 100))
|
||||||
|
}
|
||||||
|
|
||||||
function estimateTitle(row: Listing) {
|
function estimateTitle(row: Listing) {
|
||||||
const dailyLoss = getDailyLoss(row)
|
const dailyLoss = getDailyLoss(row)
|
||||||
return dailyLoss ? `按哈夫币 ${listingCoinM(row)}、日耗 ${dailyLoss} 估算` : '未配置日耗'
|
return dailyLoss ? `按哈夫币 ${listingCoinM(row)}、日耗 ${dailyLoss} 估算` : '未配置日耗'
|
||||||
@@ -965,6 +974,14 @@ function formatQuantity(value: number) {
|
|||||||
<el-table-column label="号主备注" min-width="150">
|
<el-table-column label="号主备注" min-width="150">
|
||||||
<template #default="{ row }">{{ ownerRemarkText(row) }}</template>
|
<template #default="{ row }">{{ ownerRemarkText(row) }}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column label="纯币价格" width="90">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span :title="`号主纯币价格(不含消耗品)${ownerPureCoinPriceText(row)}`">
|
||||||
|
{{ ownerPureCoinPriceText(row) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column label="租金/押金" width="90">
|
<el-table-column label="租金/押金" width="90">
|
||||||
<template #default="{ row }">{{ rentAndDepositText(row) }}</template>
|
<template #default="{ row }">{{ rentAndDepositText(row) }}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import { describe, expect, it } from 'vitest'
|
||||||
|
|
||||||
|
import { getListingSellerCoinPrice, getListingSellerPrice } from '../listingDisplay'
|
||||||
|
import type { PublicListingItem } from '@/features/listings/api/listings'
|
||||||
|
|
||||||
|
function buildListing(assetSummary?: Record<string, unknown>): PublicListingItem {
|
||||||
|
return {
|
||||||
|
id: 1,
|
||||||
|
listing_no: 'L1',
|
||||||
|
account_id: 1,
|
||||||
|
owner_id: 1,
|
||||||
|
title: '测试商品',
|
||||||
|
description: '',
|
||||||
|
game_name: 'delta',
|
||||||
|
server_region: 'QQ',
|
||||||
|
login_platform: 'PC',
|
||||||
|
rank_level: '钻石',
|
||||||
|
haf_coin_amount: 100_000_000,
|
||||||
|
asset_summary: assetSummary,
|
||||||
|
screenshot_urls: [],
|
||||||
|
cover_url: '',
|
||||||
|
price_cent: 26320,
|
||||||
|
deposit_amount_cent: 15000,
|
||||||
|
in_transaction: false,
|
||||||
|
status: 'published' as PublicListingItem['status'],
|
||||||
|
review_status: 'approved' as PublicListingItem['review_status'],
|
||||||
|
review_reason: '',
|
||||||
|
created_at: '',
|
||||||
|
updated_at: '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('号主纯币价格读取', () => {
|
||||||
|
it('从价格快照读取 seller_coin_base_price(不含消耗品)', () => {
|
||||||
|
const listing = buildListing({
|
||||||
|
price_breakdown: {
|
||||||
|
seller_coin_base_price: 232.6,
|
||||||
|
consumable_price: 0,
|
||||||
|
seller_total_price: 232.6,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
expect(getListingSellerCoinPrice(listing)).toBe(232.6)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('消耗品单独计价时纯币价格低于号主总收号价', () => {
|
||||||
|
const listing = buildListing({
|
||||||
|
price_breakdown: {
|
||||||
|
seller_coin_base_price: 200,
|
||||||
|
consumable_price: 32.6,
|
||||||
|
seller_total_price: 232.6,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
expect(getListingSellerCoinPrice(listing)).toBe(200)
|
||||||
|
expect(getListingSellerPrice(listing)).toBe(232.6)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('缺少价格快照时返回 0,供调用方展示占位符', () => {
|
||||||
|
expect(getListingSellerCoinPrice(buildListing())).toBe(0)
|
||||||
|
expect(getListingSellerCoinPrice(buildListing({}))).toBe(0)
|
||||||
|
expect(
|
||||||
|
getListingSellerCoinPrice(buildListing({ price_breakdown: { seller_ratio: 43 } }))
|
||||||
|
).toBe(0)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -77,6 +77,11 @@ export function getListingSellerPrice(item: PublicListingItem) {
|
|||||||
return getListingDisplayPrice(item)
|
return getListingDisplayPrice(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 号主纯币价格:不含额外消耗品的纯币部分(快照 seller_coin_base_price,单位元)。
|
||||||
|
export function getListingSellerCoinPrice(item: PublicListingItem) {
|
||||||
|
return Math.max(0, roundMoney(readPriceBreakdownNumber(item, 'seller_coin_base_price')))
|
||||||
|
}
|
||||||
|
|
||||||
export function getRatioValue(item: PublicListingItem) {
|
export function getRatioValue(item: PublicListingItem) {
|
||||||
const ratio = readAssetNumber(item, 'publish_ratio')
|
const ratio = readAssetNumber(item, 'publish_ratio')
|
||||||
if (ratio > 0) return ratio
|
if (ratio > 0) return ratio
|
||||||
|
|||||||
Reference in New Issue
Block a user