倍率问题和图片问题调整
This commit is contained in:
@@ -21,6 +21,7 @@ import {
|
||||
} from "lucide-react";
|
||||
import { billingUnitLabel, formatBillingAmount } from "@/lib/billing";
|
||||
import { parseAdminBillingPayload, parseMemberBillingPayload } from "@/lib/client/billing-api";
|
||||
import { groupedPriceRuleSections, priceTierEditTarget, type PriceEditTarget } from "@/lib/client/billing-price-catalog";
|
||||
import { pulseFeedback, revealChildren, runScopedMotion } from "@/lib/ui/motion";
|
||||
import type { BillingAccountConfig, BillingParameterDimension, BillingParameterTier, BillingPriceRule, OrganizationWallet } from "@/lib/types";
|
||||
|
||||
@@ -89,13 +90,6 @@ type AdjustmentDraft = {
|
||||
note: string;
|
||||
};
|
||||
|
||||
type PriceEditTarget = {
|
||||
dimensionKey?: string;
|
||||
tierValue?: string;
|
||||
label: string;
|
||||
markupMultiplier: number;
|
||||
};
|
||||
|
||||
type PriceEditState = {
|
||||
rule: BillingPriceRule;
|
||||
target: PriceEditTarget;
|
||||
@@ -615,7 +609,7 @@ function priceEditStandardUnitPriceFen(rule: BillingPriceRule, target: PriceEdit
|
||||
return Math.ceil(rule.standardUnitPriceFen * Number(tier?.standardFactor || 1));
|
||||
}
|
||||
|
||||
function PriceCatalog({ rules, onEdit, disabled }: { rules: BillingPriceRule[]; onEdit: (rule: BillingPriceRule, target: PriceEditTarget) => void; disabled: boolean }) {
|
||||
export function PriceCatalog({ rules, onEdit, disabled }: { rules: BillingPriceRule[]; onEdit: (rule: BillingPriceRule, target: PriceEditTarget) => void; disabled: boolean }) {
|
||||
const groups = groupPriceRules(rules);
|
||||
return <div className="billing-price-catalog">
|
||||
{groups.length ? groups.map(([key, group]) => group.length === 1 ? <PriceServiceCard key={key} rule={group[0]} onEdit={onEdit} disabled={disabled} /> : <PriceServiceGroup key={key} rules={group} onEdit={onEdit} disabled={disabled} />) : <div className="billing-empty-state"><Settings2 size={19} /><span>暂无平台价格标准。</span></div>}
|
||||
@@ -652,40 +646,48 @@ function PriceServiceCard({ rule, onEdit, disabled }: { rule: BillingPriceRule;
|
||||
|
||||
function PriceServiceGroup({ rules, onEdit, disabled }: { rules: BillingPriceRule[]; onEdit: (rule: BillingPriceRule, target: PriceEditTarget) => void; disabled: boolean }) {
|
||||
const rule = rules[0];
|
||||
const sections = groupedPriceRuleSections(rules);
|
||||
const hasDimensions = sections.some((section) => section.dimensions.length > 0);
|
||||
return <article className="billing-price-service-card">
|
||||
<div className="billing-price-service-heading">
|
||||
<div className="billing-price-service-title"><span className="billing-provider-mark">{providerName(rule.provider).slice(0, 2)}</span><div><strong>{providerName(rule.provider)} · {rule.capability === "video.generate" ? "视频生成" : "图片生成"}</strong><small>{rule.reqKey || "默认服务"}</small></div></div>
|
||||
<div className="billing-price-base"><span>平台参数档位</span><strong>{rules.length}<small> 个</small></strong></div>
|
||||
<div className="billing-price-base"><span>{hasDimensions ? "计费业务" : "平台参数档位"}</span><strong>{rules.length}<small> 个</small></strong></div>
|
||||
</div>
|
||||
<div className="billing-price-service-meta">
|
||||
{rule.source?.url ? <a href={rule.source.url} target="_blank" rel="noreferrer">查看价格来源 <ArrowUpRight size={12} aria-hidden="true" /></a> : <span className="billing-price-source-placeholder">平台标准目录</span>}
|
||||
<span className="billing-price-note">平台标准目录按参数档位列出,用户选择后自动匹配。</span>
|
||||
</div>
|
||||
<section className="billing-price-dimension">
|
||||
{hasDimensions ? <div className="billing-price-dimensions">{sections.flatMap((section) => section.dimensions.length
|
||||
? section.dimensions.map((dimension) => <PriceDimension key={`${section.rule.id}-${dimension.key}`} rule={section.rule} dimension={dimension} businessLabel={section.label} onEdit={onEdit} disabled={disabled} />)
|
||||
: [<section className="billing-price-dimension" key={section.rule.id}>
|
||||
<div className="billing-price-dimension-heading"><div><strong>{section.label}</strong><small>不同标准费率独立计费,倍率仅影响用户价</small></div></div>
|
||||
<div className="billing-price-tier-head"><span>参数档位</span><span>标准成本</span><span>用户价</span><span>倍率</span><span>操作</span></div>
|
||||
<div className="billing-price-tier-list"><LegacyPriceRow rule={section.rule} onEdit={onEdit} disabled={disabled} /></div>
|
||||
</section>])}</div> : <section className="billing-price-dimension">
|
||||
<div className="billing-price-dimension-heading"><div><strong>参数档位</strong><small>不同标准费率独立计费,倍率仅影响用户价</small></div></div>
|
||||
<div className="billing-price-tier-head"><span>参数档位</span><span>标准成本</span><span>用户价</span><span>倍率</span><span>操作</span></div>
|
||||
<div className="billing-price-tier-list">{rules.map((item) => <LegacyPriceRow key={item.id} rule={item} onEdit={onEdit} disabled={disabled} />)}</div>
|
||||
</section>
|
||||
</section>}
|
||||
</article>;
|
||||
}
|
||||
|
||||
function PriceDimension({ rule, dimension, onEdit, disabled }: { rule: BillingPriceRule; dimension: BillingParameterDimension; onEdit: (rule: BillingPriceRule, target: PriceEditTarget) => void; disabled: boolean }) {
|
||||
function PriceDimension({ rule, dimension, businessLabel, onEdit, disabled }: { rule: BillingPriceRule; dimension: BillingParameterDimension; businessLabel?: string; onEdit: (rule: BillingPriceRule, target: PriceEditTarget) => void; disabled: boolean }) {
|
||||
const baseline = dimension.tiers.find((tier) => String(tier.value).toLowerCase() === String(dimension.baselineValue).toLowerCase());
|
||||
return <section className="billing-price-dimension">
|
||||
<div className="billing-price-dimension-heading"><div><strong>{dimension.label}</strong><small>基准档位:{baseline?.label || String(dimension.baselineValue)} · 组合报价按实际选择自动计算</small></div></div>
|
||||
<div className="billing-price-dimension-heading"><div><strong>{businessLabel ? `${businessLabel} · ${dimension.label || dimension.key}` : dimension.label || dimension.key}</strong><small>基准档位:{baseline?.label || String(dimension.baselineValue)} · 组合报价按实际选择自动计算</small></div></div>
|
||||
<div className="billing-price-tier-head"><span>参数档位</span><span>标准成本</span><span>用户价</span><span>倍率</span><span>操作</span></div>
|
||||
<div className="billing-price-tier-list">{dimension.tiers.map((tier) => <PriceTierRow key={`${dimension.key}-${String(tier.value)}`} rule={rule} dimension={dimension} tier={tier} onEdit={onEdit} disabled={disabled} />)}</div>
|
||||
<div className="billing-price-tier-list">{dimension.tiers.map((tier) => <PriceTierRow key={`${dimension.key}-${String(tier.value)}`} rule={rule} dimension={dimension} tier={tier} businessLabel={businessLabel} onEdit={onEdit} disabled={disabled} />)}</div>
|
||||
</section>;
|
||||
}
|
||||
|
||||
function PriceTierRow({ rule, dimension, tier, onEdit, disabled }: { rule: BillingPriceRule; dimension: BillingParameterDimension; tier: BillingParameterTier; onEdit: (rule: BillingPriceRule, target: PriceEditTarget) => void; disabled: boolean }) {
|
||||
function PriceTierRow({ rule, dimension, tier, businessLabel, onEdit, disabled }: { rule: BillingPriceRule; dimension: BillingParameterDimension; tier: BillingParameterTier; businessLabel?: string; onEdit: (rule: BillingPriceRule, target: PriceEditTarget) => void; disabled: boolean }) {
|
||||
const standardUnitPriceFen = Math.ceil(rule.standardUnitPriceFen * tier.standardFactor);
|
||||
return <div className={`billing-price-tier-row${tier.enabled ? "" : " billing-price-tier-row-disabled"}`}>
|
||||
<div className="billing-price-tier-name"><strong>{tier.label}</strong><small>{String(tier.value)}{tier.note ? ` · ${tier.note}` : ""}</small></div>
|
||||
<div className="billing-price-tier-name"><strong>{tier.label || String(tier.value)}</strong><small>{String(tier.value)}{tier.note ? ` · ${tier.note}` : ""}</small></div>
|
||||
<div className="billing-price-values"><strong>{formatBillingAmount(standardUnitPriceFen)}</strong><small>/{billingUnitLabel(rule.unit)}</small></div>
|
||||
<div className="billing-price-values"><strong>{formatBillingAmount(customerUnitPriceFen(standardUnitPriceFen, tier.markupMultiplier))}</strong><small>/{billingUnitLabel(rule.unit)}</small></div>
|
||||
<span className="billing-multiplier">{tier.markupMultiplier.toFixed(2)}×</span>
|
||||
<div className="billing-price-actions"><button type="button" onClick={() => onEdit(rule, { dimensionKey: dimension.key, tierValue: String(tier.value), label: `${dimension.label} · ${tier.label}`, markupMultiplier: tier.markupMultiplier })} disabled={disabled || !tier.enabled}>调整倍率</button></div>
|
||||
<div className="billing-price-actions"><button type="button" onClick={() => onEdit(rule, priceTierEditTarget(dimension, tier, businessLabel))} disabled={disabled || !rule.enabled || !tier.enabled}>调整倍率</button></div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user