feat: sublabel 智能显示 — 仅同名渠道冲突时自动标记

- 默认去掉所有渠道的 sublabel
- 当多个启用渠道有相同显示名(如支付宝+支付宝)时,
  自动用 provider 名标记区分
- 用户手动配置的 PAYMENT_SUBLABEL_* 优先级最高
- 管理后台 getPaymentTypeLabel 自动检测同名并区分

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
erio
2026-03-06 22:58:10 +08:00
parent bdf2577f28
commit e846cc1cce
2 changed files with 29 additions and 8 deletions

View File

@@ -3,6 +3,7 @@ import { getUser } from '@/lib/sub2api/client';
import { getEnv } from '@/lib/config';
import { queryMethodLimits } from '@/lib/order/limits';
import { initPaymentProviders, paymentRegistry } from '@/lib/payment';
import { PAYMENT_TYPE_META } from '@/lib/pay-utils';
export async function GET(request: NextRequest) {
const userId = Number(request.nextUrl.searchParams.get('user_id'));
@@ -16,8 +17,28 @@ export async function GET(request: NextRequest) {
const enabledTypes = paymentRegistry.getSupportedTypes();
const [user, methodLimits] = await Promise.all([getUser(userId), queryMethodLimits(enabledTypes)]);
// 收集 sublabel 覆盖(仅包含用户实际配置的项)
// 收集 sublabel 覆盖
const sublabelOverrides: Record<string, string> = {};
// 1. 检测同 label 冲突:多个启用渠道有相同的显示名,自动标记默认 sublabelprovider 名)
const labelCount = new Map<string, string[]>();
for (const type of enabledTypes) {
const meta = PAYMENT_TYPE_META[type];
if (!meta) continue;
const types = labelCount.get(meta.label) || [];
types.push(type);
labelCount.set(meta.label, types);
}
for (const [, types] of labelCount) {
if (types.length > 1) {
for (const type of types) {
const meta = PAYMENT_TYPE_META[type];
if (meta) sublabelOverrides[type] = meta.provider;
}
}
}
// 2. 用户手动配置的 PAYMENT_SUBLABEL_* 优先级最高,覆盖自动生成的
if (env.PAYMENT_SUBLABEL_ALIPAY) sublabelOverrides.alipay = env.PAYMENT_SUBLABEL_ALIPAY;
if (env.PAYMENT_SUBLABEL_ALIPAY_DIRECT) sublabelOverrides.alipay_direct = env.PAYMENT_SUBLABEL_ALIPAY_DIRECT;
if (env.PAYMENT_SUBLABEL_WXPAY) sublabelOverrides.wxpay = env.PAYMENT_SUBLABEL_WXPAY;

View File

@@ -92,7 +92,6 @@ export interface PaymentTypeMeta {
export const PAYMENT_TYPE_META: Record<string, PaymentTypeMeta> = {
[PAYMENT_TYPE.ALIPAY]: {
label: '支付宝',
sublabel: '易支付',
provider: '易支付',
color: '#00AEEF',
selectedBorder: 'border-cyan-400',
@@ -104,7 +103,6 @@ export const PAYMENT_TYPE_META: Record<string, PaymentTypeMeta> = {
},
[PAYMENT_TYPE.ALIPAY_DIRECT]: {
label: '支付宝',
sublabel: '官方',
provider: '支付宝',
color: '#1677FF',
selectedBorder: 'border-blue-500',
@@ -116,7 +114,6 @@ export const PAYMENT_TYPE_META: Record<string, PaymentTypeMeta> = {
},
[PAYMENT_TYPE.WXPAY]: {
label: '微信支付',
sublabel: '易支付',
provider: '易支付',
color: '#2BB741',
selectedBorder: 'border-green-500',
@@ -128,7 +125,6 @@ export const PAYMENT_TYPE_META: Record<string, PaymentTypeMeta> = {
},
[PAYMENT_TYPE.WXPAY_DIRECT]: {
label: '微信支付',
sublabel: '官方',
provider: '微信支付',
color: '#07C160',
selectedBorder: 'border-green-600',
@@ -140,7 +136,6 @@ export const PAYMENT_TYPE_META: Record<string, PaymentTypeMeta> = {
},
[PAYMENT_TYPE.STRIPE]: {
label: 'Stripe',
sublabel: '信用卡 / 借记卡',
provider: 'Stripe',
color: '#635bff',
selectedBorder: 'border-[#635bff]',
@@ -151,11 +146,16 @@ export const PAYMENT_TYPE_META: Record<string, PaymentTypeMeta> = {
},
};
/** 获取支付方式的显示名称(如 '支付宝(官方)' */
/** 获取支付方式的显示名称(如 '支付宝(易支付)'),用于管理后台等需要区分的场景 */
export function getPaymentTypeLabel(type: string): string {
const meta = PAYMENT_TYPE_META[type];
if (!meta) return type;
return meta.sublabel ? `${meta.label}${meta.sublabel}` : meta.label;
if (meta.sublabel) return `${meta.label}${meta.sublabel}`;
// 无 sublabel 时,检查是否有同名渠道需要用 provider 区分
const hasDuplicate = Object.entries(PAYMENT_TYPE_META).some(
([k, m]) => k !== type && m.label === meta.label,
);
return hasDuplicate ? `${meta.label}${meta.provider}` : meta.label;
}
/** 获取支付渠道和提供商的结构化信息 */