feat: polish internal value displays

This commit is contained in:
JetSprow
2026-04-30 16:38:38 +10:00
parent abc2d4aa72
commit 042c5b34ab
25 changed files with 498 additions and 163 deletions

View File

@@ -5,6 +5,7 @@ import { requireAdmin } from "@/lib/require-auth";
import { revalidatePath } from "next/cache";
import {
decryptPaymentConfigForUse,
getPaymentProviderName,
normalizePaymentConfig,
parsePaymentConfig,
preparePaymentConfigForStorage,
@@ -54,8 +55,8 @@ export async function savePaymentConfig(
action: "payment.config",
targetType: "PaymentConfig",
targetId: provider,
targetLabel: provider,
message: `${enabled ? "启用并更新" : "更新"}支付配置 ${provider}`,
targetLabel: getPaymentProviderName(provider),
message: `${enabled ? "启用并更新" : "更新"}支付配置 ${getPaymentProviderName(provider)}`,
});
revalidatePath("/admin/payments");
}

View File

@@ -11,24 +11,15 @@ import { normalizeSiteUrl } from "@/services/site-url";
import { encrypt, isEncryptedValue } from "@/lib/crypto";
import { getErrorMessage } from "@/lib/errors";
import { sendSmtpTestEmail } from "@/services/email";
import {
booleanAppSettingFields,
getBooleanAppSettingLabel,
type BooleanAppSettingField,
} from "@/lib/domain-labels";
const booleanSettingFields = [
"allowRegistration",
"emailVerificationRequired",
"requireInviteCode",
"autoReminderDispatchEnabled",
"trafficSyncEnabled",
"networkRecommendationsEnabled",
"networkInsightsEnabled",
"subscriptionRiskEnabled",
"subscriptionRiskAutoSuspend",
"nodeAccessRiskEnabled",
"inviteRewardEnabled",
"smtpEnabled",
"smtpSecure",
] as const;
const booleanSettingFields = booleanAppSettingFields;
export type BooleanSettingField = (typeof booleanSettingFields)[number];
export type BooleanSettingField = BooleanAppSettingField;
const settingsSchema = z.object({
siteName: z.string().trim().min(1, "站点名称不能为空"),
@@ -363,7 +354,7 @@ export async function saveBooleanAppSetting(input: {
targetType: "AppConfig",
targetId: current.id,
targetLabel: current.siteName,
message: `${parsed.value ? "开启" : "关闭"}系统开关 ${parsed.field}`,
message: `${parsed.value ? "开启" : "关闭"}${getBooleanAppSettingLabel(parsed.field)}开关`,
});
revalidateSettingsViews();

View File

@@ -7,6 +7,7 @@ import { dispatchSubscriptionReminders } from "@/services/notifications";
import { confirmPendingOrder } from "@/services/payment/process";
import { runTask, updateTaskRun } from "@/services/task-center";
import { prisma } from "@/lib/prisma";
import { getTaskKindLabel } from "@/lib/domain-labels";
function revalidateTaskViews() {
revalidatePath("/admin/tasks");
@@ -37,7 +38,7 @@ export async function runReminderTask() {
action: "task.run",
targetType: "TaskRun",
targetId: outcome.taskId,
targetLabel: "REMINDER_DISPATCH",
targetLabel: getTaskKindLabel("REMINDER_DISPATCH"),
message: "手动执行提醒派发任务",
});
@@ -82,7 +83,7 @@ export async function retryTaskRun(taskId: string) {
action: "task.retry",
targetType: "TaskRun",
targetId: task.id,
targetLabel: task.kind,
targetLabel: getTaskKindLabel(task.kind),
message: `重试任务 ${task.title}`,
});
} catch (error) {

View File

@@ -7,6 +7,7 @@ import bcrypt from "bcryptjs";
import { z } from "zod";
import { actorFromSession, recordAuditLog } from "@/services/audit";
import { createPanelAdapter } from "@/services/node-panel/factory";
import { getUserStatusLabel } from "@/lib/domain-labels";
const createUserSchema = z.object({
email: z.string().email(),
@@ -86,7 +87,7 @@ export async function updateUserStatus(id: string, status: "ACTIVE" | "DISABLED"
targetType: "User",
targetId: user.id,
targetLabel: user.email,
message: `将用户 ${user.email} 状态改为 ${status}`,
message: `将用户 ${user.email} 状态改为${getUserStatusLabel(status)}`,
});
revalidatePath("/admin/users");
revalidatePath(`/admin/users/${user.id}`);
@@ -291,7 +292,7 @@ export async function batchUpdateUserStatus(formData: FormData) {
actor: actorFromSession(session),
action: "user.batch_status",
targetType: "User",
message: `批量更新 ${userIds.length} 个用户状态为 ${status}`,
message: `批量更新 ${userIds.length} 个用户状态为${getUserStatusLabel(String(status))}`,
metadata: {
userIds,
status: String(status),

View File

@@ -6,6 +6,7 @@ import { requireAuth } from "@/lib/require-auth";
import { buildUnavailableMessage, getPlanAvailability } from "@/services/plan-availability";
import { getPlanPurchasePrice, calculateCheckoutDiscounts } from "@/services/commerce";
import { ensurePlanTrafficPoolCapacity } from "@/services/plan-traffic-pool";
import { getSubscriptionTypeLabel } from "@/lib/domain-labels";
async function assertNoPendingOrder(userId: string) {
const pendingOrder = await prisma.order.findFirst({
@@ -33,7 +34,7 @@ async function getProxyPlanForCart(planId: string) {
},
});
if (plan.type !== "PROXY") throw new Error(`套餐类型不匹配:${plan.name} ${plan.type},不能作为代理套餐加入购物车`);
if (plan.type !== "PROXY") throw new Error(`套餐类型不匹配:${plan.name}${getSubscriptionTypeLabel(plan.type)},不能作为代理套餐加入购物车`);
if (!plan.isActive) throw new Error(`套餐已下架:${plan.name} 当前不可购买`);
return plan;
}
@@ -115,7 +116,7 @@ export async function addProxyPlanToCart(
export async function addStreamingPlanToCart(planId: string) {
const session = await requireAuth();
const plan = await prisma.subscriptionPlan.findUniqueOrThrow({ where: { id: planId } });
if (plan.type !== "STREAMING") throw new Error(`套餐类型不匹配:${plan.name} ${plan.type},不能作为流媒体套餐加入购物车`);
if (plan.type !== "STREAMING") throw new Error(`套餐类型不匹配:${plan.name}${getSubscriptionTypeLabel(plan.type)},不能作为流媒体套餐加入购物车`);
if (!plan.isActive) throw new Error(`套餐已下架:${plan.name} 当前不可购买`);
const availability = await getPlanAvailability(plan, { userId: session.user.id });

View File

@@ -13,6 +13,7 @@ import {
getPlanTrafficPoolState,
} from "@/services/plan-traffic-pool";
import { getPlanPurchasePrice, roundMoney } from "@/services/commerce";
import { getSubscriptionTypeLabel } from "@/lib/domain-labels";
async function assertNoPendingOrder(userId: string) {
const pendingOrder = await prisma.order.findFirst({
@@ -133,7 +134,7 @@ export async function purchaseProxy(
},
});
if (plan.type !== "PROXY") throw new Error(`套餐类型不匹配:${plan.name} ${plan.type},不能作为代理套餐购买`);
if (plan.type !== "PROXY") throw new Error(`套餐类型不匹配:${plan.name}${getSubscriptionTypeLabel(plan.type)},不能作为代理套餐购买`);
if (!plan.isActive) throw new Error(`套餐已下架:${plan.name} 当前不可购买`);
const price = getPlanPurchasePrice(plan, trafficGb);
@@ -213,7 +214,7 @@ export async function purchaseStreaming(planId: string): Promise<string> {
where: { id: planId },
});
if (plan.type !== "STREAMING") throw new Error(`套餐类型不匹配:${plan.name} ${plan.type},不能作为流媒体套餐购买`);
if (plan.type !== "STREAMING") throw new Error(`套餐类型不匹配:${plan.name}${getSubscriptionTypeLabel(plan.type)},不能作为流媒体套餐购买`);
if (!plan.isActive) throw new Error(`套餐已下架:${plan.name} 当前不可购买`);
const availability = await getPlanAvailability(plan, { userId: session.user.id });