展示额外消耗品总价与明细悬浮卡片

租金改为「包含额外物品」;按 resources 收费项汇总额外消耗品金额,悬浮展示物品明细。
This commit is contained in:
yml2213
2026-07-13 23:54:09 +08:00
parent 35b0278524
commit 51991071e7
4 changed files with 300 additions and 21 deletions
+72 -1
View File
@@ -11,6 +11,7 @@ import Pagination from "antd/es/pagination";
import Select from "antd/es/select";
import Spin from "antd/es/spin";
import Tag from "antd/es/tag";
import Tooltip from "antd/es/tooltip";
import { useEffect, useMemo, useState } from "react";
import {
fetchListingsPage,
@@ -26,12 +27,14 @@ import {
formatListingInfoText,
formatMoney,
formatRatio,
getConsumablePrice,
getListingDeposit,
getListingPrice,
getMainChips,
getOnlineTimeText,
getRegions,
getResourceQuantity,
getResources,
getSkinNames,
readAssetNumber,
readAssetString,
@@ -618,12 +621,17 @@ function ListingRow({ codeCopied, infoCopied, item, onCopyCode, onCopyInfo }: Li
const code = formatListingCode(item);
const price = getListingPrice(item);
const deposit = getListingDeposit(item);
const consumable = getConsumablePrice(item);
const totalPrice = Math.round((price + deposit) * 100) / 100;
const rentalDuration = formatEstimatedRentalDuration(item);
const remark = getAssetText(item, "remark");
const regions = getRegions(item);
const skinNames = getSkinNames(item);
const fireLevel = readAssetNumber(item, "fire_level");
const resources = getResources(item);
const resourceTooltip = (
<ResourceTooltipContent consumable={consumable} resources={resources} />
);
const details = [
["哈夫币", formatCoin(item)],
["保险格", readAssetString(item, "season_insurance") || "-"],
@@ -675,13 +683,33 @@ function ListingRow({ codeCopied, infoCopied, item, onCopyCode, onCopyInfo }: Li
{chip.label}
</Tag>
))}
{resources.length ? <Tag color="orange">{resources.length}</Tag> : null}
{remark ? <span className="remark">{remark}</span> : null}
</div>
<div className="price-line">
<span>
<strong>{formatMoney(price)}</strong>
() <strong>{formatMoney(price)}</strong>
</span>
<Tooltip
arrow={false}
placement="top"
rootClassName="resource-tooltip-root"
styles={{
container: {
padding: 0,
background: "#fff",
color: "#172033",
borderRadius: 12,
boxShadow: "0 12px 32px rgba(21, 32, 43, 0.14)",
},
}}
title={resourceTooltip}
>
<span className="price-hint">
<strong>{formatMoney(consumable)}</strong>
</span>
</Tooltip>
<span>
<strong className="rental-days">{rentalDuration}</strong>
</span>
@@ -700,6 +728,49 @@ function ListingRow({ codeCopied, infoCopied, item, onCopyCode, onCopyInfo }: Li
);
}
function ResourceTooltipContent({
consumable,
resources,
}: {
consumable: number;
resources: ReturnType<typeof getResources>;
}) {
if (!resources.length) {
return <div className="resource-popover empty"></div>;
}
return (
<div className="resource-popover">
<div className="resource-popover-head">
<div>
<strong></strong>
<span>{resources.length} </span>
</div>
<em> {formatMoney(consumable)}</em>
</div>
<div className="resource-popover-list">
{resources.map((resource) => (
<div key={resource.key} className="resource-popover-row">
<div className="resource-popover-main">
<span className="resource-name">{resource.label}</span>
<span className="resource-qty">×{resource.quantity}</span>
<span className={resource.mode === "收费" ? "resource-mode paid" : "resource-mode gift"}>
{resource.mode || "-"}
</span>
</div>
<div className="resource-popover-side">
<span className="resource-unit">{resource.price || "-"}</span>
<strong className="resource-amount">
{resource.mode === "收费" && resource.amount > 0 ? `${formatMoney(resource.amount)}` : "—"}
</strong>
</div>
</div>
))}
</div>
</div>
);
}
function buildQuery(nextPage: number, filters: Filters, sort: string): PublicListingQuery {
return {
page: nextPage,