mirror of
https://github.com/JetSprow/J-Board-Lite.git
synced 2026-05-01 09:14:11 +05:30
feat: polish internal value displays
This commit is contained in:
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -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 });
|
||||
|
||||
Reference in New Issue
Block a user