基本功能已初步完善
Some checks failed
build / build (api, amd64, linux) (push) Has been cancelled
build / build (api, arm64, linux) (push) Has been cancelled
build / build (api.exe, amd64, windows) (push) Has been cancelled

This commit is contained in:
CN-JS-HuiBai
2026-04-17 20:41:47 +08:00
parent 25fd919477
commit b3435e5ef8
34 changed files with 3495 additions and 429 deletions

View File

@@ -195337,21 +195337,6 @@ const DQe =
{ path: "subscribe-template", element: Q.jsx(LQe, {}) },
],
},
{
path: "payment",
lazy: async () => ({
Component: (
await xp(
async () => {
const { default: e } = await Promise.resolve().then(() => kXt);
return { default: e };
},
void 0,
import.meta.url,
)
).default,
}),
},
{
path: "plugin",
lazy: async () => ({
@@ -195499,36 +195484,6 @@ const DQe =
).default,
}),
},
{
path: "coupon",
lazy: async () => ({
Component: (
await xp(
async () => {
const { default: e } = await Promise.resolve().then(() => z3t);
return { default: e };
},
void 0,
import.meta.url,
)
).default,
}),
},
{
path: "gift-card",
lazy: async () => ({
Component: (
await xp(
async () => {
const { default: e } = await Promise.resolve().then(() => d6t);
return { default: e };
},
void 0,
import.meta.url,
)
).default,
}),
},
],
},
{
@@ -195565,6 +195520,18 @@ const DQe =
).default,
}),
},
{
path: "realname",
lazy: async () => ({ Component: codexNativeRealnamePage }),
},
{
path: "online-devices",
lazy: async () => ({ Component: codexNativeOnlineDevicesPage }),
},
{
path: "ipv6-subscription",
lazy: async () => ({ Component: codexNativeIPv6Page }),
},
{
path: "traffic-reset-logs",
lazy: async () => ({
@@ -233443,17 +233410,11 @@ var Zst = {
href: "/config/system",
icon: Q.jsx(Kf, { size: 18 }),
},
{
title: "nav:pluginManagement",
label: "",
href: "/config/plugin",
icon: Q.jsx(Fat, { size: 18 }),
},
{
title: "nav:themeConfig",
label: "",
href: "/config/theme",
icon: Q.jsx(im, { size: 18 }),
icon: Q.jsx(Kf, { size: 18 }),
},
{
title: "nav:noticeManagement",
@@ -233461,12 +233422,6 @@ var Zst = {
href: "/config/notice",
icon: Q.jsx(pm, { size: 18 }),
},
{
title: "nav:paymentConfig",
label: "",
href: "/config/payment",
icon: Q.jsx(tm, { size: 18 }),
},
{
title: "nav:knowledgeManagement",
label: "",
@@ -233519,18 +233474,6 @@ var Zst = {
href: "/finance/order",
icon: Q.jsx(tm, { size: 18 }),
},
{
title: "nav:couponManagement",
label: "",
href: "/finance/coupon",
icon: Q.jsx(rm, { size: 18 }),
},
{
title: "nav:giftCardManagement",
label: "",
href: "/finance/gift-card",
icon: Q.jsx(lm, { size: 18 }),
},
],
},
{
@@ -233551,6 +233494,24 @@ var Zst = {
href: "/user/ticket",
icon: Q.jsx(xm, { size: 18 }),
},
{
title: "实名认证",
label: "",
href: "/user/realname",
icon: Q.jsx(xm, { size: 18 }),
},
{
title: "在线 IP 统计",
label: "",
href: "/user/online-devices",
icon: Q.jsx(xm, { size: 18 }),
},
{
title: "IPv6 子账号",
label: "",
href: "/user/ipv6-subscription",
icon: Q.jsx(xm, { size: 18 }),
},
],
},
];
@@ -264036,26 +263997,6 @@ function x$t({ className: e }) {
return Q.jsxs("div", {
className: Rf("grid gap-4 md:grid-cols-2 lg:grid-cols-4", e),
children: [
Q.jsx(y$t, {
title: n("dashboard:stats.todayIncome"),
value: DS(i.todayIncome),
icon: Q.jsx(Jst, { className: "h-4 w-4 text-emerald-500" }),
trend: {
value: i.dayIncomeGrowth,
label: n("dashboard:stats.vsYesterday"),
isPositive: i.dayIncomeGrowth > 0,
},
}),
Q.jsx(y$t, {
title: n("dashboard:stats.monthlyIncome"),
value: DS(i.currentMonthIncome),
icon: Q.jsx(rat, { className: "h-4 w-4 text-blue-500" }),
trend: {
value: i.monthIncomeGrowth,
label: n("dashboard:stats.vsLastMonth"),
isPositive: i.monthIncomeGrowth > 0,
},
}),
Q.jsx(y$t, {
title: n("dashboard:stats.pendingTickets"),
value: i.ticketPendingTotal,
@@ -264072,38 +264013,6 @@ function x$t({ className: e }) {
onClick: () => t("/user/ticket"),
highlight: i.ticketPendingTotal > 0,
}),
Q.jsx(y$t, {
title: n("dashboard:stats.pendingCommission"),
value: i.commissionPendingTotal,
icon: Q.jsx(oat, {
className: Rf(
"h-4 w-4",
i.commissionPendingTotal > 0 ? "text-blue-500" : "text-muted-foreground",
),
}),
description:
i.commissionPendingTotal > 0
? n("dashboard:stats.hasPendingCommission")
: n("dashboard:stats.noPendingCommission"),
onClick: () => {
const e = new URLSearchParams();
(e.set("commission_status", c$t.PENDING.toString()),
e.set("status", o$t.COMPLETED.toString()),
e.set("commission_balance", "gt:0"),
t(`/finance/order?${e.toString()}`));
},
highlight: i.commissionPendingTotal > 0,
}),
Q.jsx(y$t, {
title: n("dashboard:stats.monthlyNewUsers"),
value: i.currentMonthNewUsers,
icon: Q.jsx(dlt, { className: "h-4 w-4 text-blue-500" }),
trend: {
value: i.userGrowth,
label: n("dashboard:stats.vsLastMonth"),
isPositive: i.userGrowth > 0,
},
}),
Q.jsx(y$t, {
title: n("dashboard:stats.totalUsers"),
value: i.totalUsers,
@@ -269438,7 +269347,7 @@ const tGt = Object.freeze(
className: "space-y-6",
children: Q.jsxs("div", {
className: "grid gap-6",
children: [Q.jsx(x$t, {}), Q.jsx(t$t, {}), Q.jsx(dqt, {}), Q.jsx(eGt, {})],
children: [Q.jsx(x$t, {}), Q.jsx(dqt, {}), Q.jsx(eGt, {})],
}),
}),
}),
@@ -293836,23 +293745,27 @@ const I5t = {
Q.jsxs("span", {
className: "flex flex-col items-start gap-0.5 leading-tight",
children: [
Q.jsx("span", { className: "flex items-center gap-0.5", children: i ?? n }),
e.parent
? Q.jsxs("span", {
className: "flex items-center gap-1",
children: [
Q.jsx("span", { children: n }),
Q.jsx("span", {
className: "text-sm text-muted-foreground/30",
children: "\u2192",
}),
Q.jsx("span", { children: e.parent_id ?? e.parent?.id }),
],
})
: Q.jsx("span", {
className: "flex items-center gap-0.5",
children: n,
}),
i &&
Q.jsxs("span", {
className: "font-mono text-[10px] text-muted-foreground",
children: [t("columns.originalId"), ": ", n],
children: [t("columns.customId"), ": ", i],
}),
e.parent
? Q.jsxs(Q.Fragment, {
children: [
Q.jsx("span", {
className: "text-sm text-muted-foreground/30",
children: "→",
}),
Q.jsx("span", { children: e.parent?.code || e.parent?.id }),
],
})
: null,
],
}),
],
@@ -304571,6 +304484,496 @@ function l8t() {
})
);
}
function codexNativePageLayout(e, t, n) {
return Q.jsxs(Wot, {
children: [
Q.jsxs(Hot, {
children: [
Q.jsx(Vdt, {}),
Q.jsxs("div", {
className: "ml-auto flex items-center space-x-4",
children: [Q.jsx(Wdt, {}), Q.jsx(vut, {})],
}),
],
}),
Q.jsxs(zot, {
className: "flex flex-col",
fixedHeight: !0,
children: [
Q.jsx("div", {
className: "mb-2 flex items-center justify-between space-y-2",
children: Q.jsxs("div", {
children: [
Q.jsx("h2", { className: "text-2xl font-bold tracking-tight", children: e }),
Q.jsx("p", { className: "mt-2 text-muted-foreground", children: t }),
],
}),
}),
Q.jsx("div", {
className: "-mx-4 flex-1 overflow-auto px-4 py-1 lg:flex-row lg:space-x-12 lg:space-y-0",
children: Q.jsx("div", { className: "w-full", children: n }),
}),
],
}),
],
});
}
function codexNativeStatusBadge(e) {
const t = String(e || "-").toLowerCase(),
n = /approved|active|enabled|ready/.test(t)
? "bg-emerald-500/15 text-emerald-600 dark:text-emerald-400"
: /pending|eligible|unverified/.test(t)
? "bg-yellow-500/15 text-yellow-700 dark:text-yellow-400"
: "bg-destructive/10 text-destructive";
return Q.jsx("span", {
className: Rf("inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold", n),
children: e || "-",
});
}
function codexNativeRelationChip(e, t) {
return Q.jsxs("span", {
className:
"inline-flex items-center gap-1 rounded-full border bg-muted/50 px-2.5 py-1 font-mono text-xs",
children: [
e,
Q.jsx("span", { className: "text-muted-foreground/60", children: "\u2192" }),
t,
],
});
}
function codexNativeSearchToolbar({
keyword: e,
setKeyword: t,
onSearch: n,
onReset: i,
refetch: r,
actions: o,
}) {
return Q.jsxs("div", {
className: "flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between",
children: [
Q.jsxs("div", {
className: "flex flex-1 flex-wrap items-center gap-2 sm:flex-nowrap",
children: [
Q.jsx(Q6e, {
placeholder: "搜索用户 ID / 邮箱",
value: e,
onChange: (e) => t(e.target.value),
onKeyDown: (e) => {
"Enter" === e.key && n();
},
className: "h-8 w-full min-w-[150px] sm:w-[180px] lg:w-[280px]",
}),
Q.jsx(Nm, { variant: "outline", className: "h-8 px-3", onClick: n, children: "搜索" }),
Q.jsx(Nm, { variant: "ghost", className: "h-8 px-3", onClick: i, children: "重置" }),
Q.jsx(Nm, { variant: "ghost", className: "h-8 px-3", onClick: () => r(), children: "刷新" }),
],
}),
o ? Q.jsx("div", { className: "flex flex-wrap items-center gap-2", children: o }) : null,
],
});
}
function codexNativeRealnameTable() {
const [e, t] = H.useState(""),
[n, i] = H.useState(""),
[r, o] = H.useState({}),
[s, a] = H.useState({}),
[l, c] = H.useState({ pageIndex: 0, pageSize: 20 }),
{
refetch: d,
data: u,
isLoading: h,
} = gC({
queryKey: ["codexNativeRealname", l, n],
queryFn: () =>
TL(`${RL()}/realname/records`, {
params: { page: l.pageIndex + 1, per_page: l.pageSize, keyword: n },
}),
}),
g = H.useMemo(
() => [
{
accessorKey: "id",
header: () => "用户 ID",
cell: ({ row: e }) =>
Q.jsx("div", { className: "font-mono text-sm font-medium", children: e.getValue("id") }),
},
{
accessorKey: "email",
header: () => "邮箱",
cell: ({ row: e }) =>
Q.jsx("div", { className: "max-w-[240px] truncate", children: e.getValue("email") || "-" }),
},
{
accessorKey: "real_name",
header: () => "姓名",
cell: ({ row: e }) => e.getValue("real_name") || "-",
},
{
accessorKey: "identity_no_masked",
header: () => "证件号",
cell: ({ row: e }) =>
Q.jsx("div", { className: "font-mono text-xs", children: e.getValue("identity_no_masked") || "-" }),
},
JKt.display({
id: "status",
header: () => "状态",
cell: ({ row: e }) => codexNativeStatusBadge(e.original.status_label || e.original.status),
}),
JKt.display({
id: "actions",
header: () => "操作",
cell: ({ row: e }) =>
Q.jsxs("div", {
className: "flex flex-wrap items-center gap-2",
children: [
Q.jsx(Nm, {
size: "sm",
className: "h-8",
onClick: async () => {
await IL(`${RL()}/realname/review/${e.original.id}`, { status: "approved", reason: "" });
hN.success("已通过实名认证");
d();
},
children: "通过",
}),
Q.jsx(Nm, {
size: "sm",
variant: "outline",
className: "h-8",
onClick: async () => {
const t = window.prompt("请输入驳回原因", "") || "";
await IL(`${RL()}/realname/review/${e.original.id}`, {
status: "rejected",
reason: t,
});
hN.success("已驳回实名认证");
d();
},
children: "驳回",
}),
Q.jsx(Nm, {
size: "sm",
variant: "ghost",
className: "h-8",
onClick: async () => {
await IL(`${RL()}/realname/reset/${e.original.id}`, {});
hN.success("已重置实名记录");
d();
},
children: "重置",
}),
],
}),
}),
],
[d],
),
p = PKt({
data: u?.data?.data ?? [],
columns: g,
state: { columnVisibility: o, rowSelection: s, pagination: l },
getRowId: (e) => String(e.id),
rowCount: u?.data?.pagination?.total ?? 0,
manualPagination: !0,
enableRowSelection: !0,
onRowSelectionChange: a,
onColumnVisibilityChange: o,
onPaginationChange: c,
getCoreRowModel: LKt(),
getPaginationRowModel: OKt(),
});
return Q.jsxs("div", {
className: "space-y-4",
children: [
Q.jsx(codexNativeSearchToolbar, {
keyword: e,
setKeyword: t,
onSearch: () => {
c((e) => ({ ...e, pageIndex: 0 }));
i(e.trim());
},
onReset: () => {
t("");
i("");
c((e) => ({ ...e, pageIndex: 0 }));
},
refetch: d,
actions: Q.jsxs(Q.Fragment, {
children: [
Q.jsx(Nm, {
variant: "outline",
className: "h-8",
onClick: async () => {
await IL(`${RL()}/realname/sync-all`, {});
hN.success("已同步全部实名状态");
d();
},
children: "同步全部",
}),
Q.jsx(Nm, {
className: "h-8",
onClick: async () => {
await IL(`${RL()}/realname/approve-all`, {});
hN.success("已全部通过");
d();
},
children: "全部通过",
}),
],
}),
}),
Q.jsx(QKt, {
table: p,
isLoading: h,
showPagination: !0,
mobilePrimaryField: "email",
mobileGridFields: ["real_name", "status", "identity_no_masked"],
}),
],
});
}
function codexNativeRealnamePage() {
return codexNativePageLayout("实名认证", "审核实名记录并同步实名状态。", Q.jsx(codexNativeRealnameTable, {}));
}
function codexNativeOnlineDevicesTable() {
const [e, t] = H.useState(""),
[n, i] = H.useState(""),
[r, o] = H.useState({}),
[s, a] = H.useState({}),
[l, c] = H.useState({ pageIndex: 0, pageSize: 20 }),
{
refetch: d,
data: u,
isLoading: h,
} = gC({
queryKey: ["codexNativeOnlineDevices", l, n],
queryFn: () =>
TL(`${RL()}/user-online-devices/users`, {
params: { page: l.pageIndex + 1, per_page: l.pageSize, keyword: n },
}),
}),
g = H.useMemo(
() => [
{
accessorKey: "id",
header: () => "用户 ID",
cell: ({ row: e }) =>
Q.jsx("div", { className: "font-mono text-sm font-medium", children: e.getValue("id") }),
},
{
accessorKey: "email",
header: () => "邮箱",
cell: ({ row: e }) =>
Q.jsx("div", { className: "max-w-[240px] truncate", children: e.getValue("email") || "-" }),
},
{
accessorKey: "subscription_name",
header: () => "套餐",
cell: ({ row: e }) => e.getValue("subscription_name") || "-",
},
JKt.display({
id: "online_devices",
header: () => "在线 IP",
cell: ({ row: e }) => {
const t = e.original.online_devices || [];
return t.length
? Q.jsx("div", {
className: "flex flex-col gap-1 font-mono text-xs",
children: t.map((e, t) => Q.jsx("span", { children: e }, `${e}-${t}`)),
})
: "-";
},
}),
{
accessorKey: "online_count",
header: () => "数量",
cell: ({ row: e }) =>
Q.jsx("div", { className: "font-mono text-sm", children: e.getValue("online_count") || 0 }),
},
JKt.display({
id: "status",
header: () => "Status",
cell: ({ row: e }) => codexNativeStatusBadge(e.original.status_label || e.original.status),
}),
{
accessorKey: "last_online_text",
header: () => "最后在线",
cell: ({ row: e }) =>
Q.jsx("div", { className: "text-nowrap text-sm text-muted-foreground", children: e.getValue("last_online_text") || "-" }),
},
],
[],
),
p = PKt({
data: u?.data?.list ?? [],
columns: g,
state: { columnVisibility: r, rowSelection: s, pagination: l },
getRowId: (e) => String(e.id),
rowCount: u?.data?.pagination?.total ?? 0,
manualPagination: !0,
enableRowSelection: !0,
onRowSelectionChange: a,
onColumnVisibilityChange: o,
onPaginationChange: c,
getCoreRowModel: LKt(),
getPaginationRowModel: OKt(),
});
return Q.jsxs("div", {
className: "space-y-4",
children: [
Q.jsx(codexNativeSearchToolbar, {
keyword: e,
setKeyword: t,
onSearch: () => {
c((e) => ({ ...e, pageIndex: 0 }));
i(e.trim());
},
onReset: () => {
t("");
i("");
c((e) => ({ ...e, pageIndex: 0 }));
},
refetch: d,
}),
Q.jsx(QKt, {
table: p,
isLoading: h,
showPagination: !0,
mobilePrimaryField: "email",
mobileGridFields: ["subscription_name", "online_count", "status", "last_online_text"],
}),
],
});
}
function codexNativeOnlineDevicesPage() {
return codexNativePageLayout("在线设备", "查看用户在线 IP、数量和最后在线时间。", Q.jsx(codexNativeOnlineDevicesTable, {}));
}
function codexNativeIPv6Table() {
const [e, t] = H.useState(""),
[n, i] = H.useState(""),
[r, o] = H.useState({}),
[s, a] = H.useState({}),
[l, c] = H.useState({ pageIndex: 0, pageSize: 20 }),
{
refetch: d,
data: u,
isLoading: h,
} = gC({
queryKey: ["codexNativeIPv6", l, n],
queryFn: () =>
TL(`${RL()}/user-add-ipv6-subscription/users`, {
params: { page: l.pageIndex + 1, per_page: l.pageSize, keyword: n },
}),
}),
g = H.useMemo(
() => [
JKt.display({
id: "relation",
header: () => "主从关系",
cell: ({ row: e }) =>
codexNativeRelationChip(e.original.id, e.original.shadow_user_id || "-"),
}),
{
accessorKey: "email",
header: () => "主账号",
cell: ({ row: e }) =>
Q.jsx("div", { className: "max-w-[240px] truncate", children: e.getValue("email") || "-" }),
},
{
accessorKey: "ipv6_email",
header: () => "IPv6 账号",
cell: ({ row: e }) =>
Q.jsx("div", { className: "font-mono text-xs", children: e.getValue("ipv6_email") || "-" }),
},
{
accessorKey: "plan_name",
header: () => "套餐",
cell: ({ row: e }) => e.getValue("plan_name") || "-",
},
JKt.display({
id: "status",
header: () => "状态",
cell: ({ row: e }) => codexNativeStatusBadge(e.original.status_label || e.original.status),
}),
JKt.display({
id: "actions",
header: () => "操作",
cell: ({ row: e }) =>
Q.jsxs("div", {
className: "flex flex-wrap items-center gap-2",
children: [
Q.jsx(Nm, {
size: "sm",
className: "h-8",
onClick: async () => {
await IL(`${RL()}/user-add-ipv6-subscription/enable/${e.original.id}`, {});
hN.success("已开通并同步 IPv6 子账号");
d();
},
children: "开通并同步",
}),
Q.jsx(Nm, {
size: "sm",
variant: "outline",
className: "h-8",
onClick: async () => {
await IL(`${RL()}/user-add-ipv6-subscription/sync-password/${e.original.id}`, {});
hN.success("已同步密码");
d();
},
children: "同步密码",
}),
],
}),
}),
],
[d],
),
p = PKt({
data: u?.data?.list ?? [],
columns: g,
state: { columnVisibility: r, rowSelection: s, pagination: l },
getRowId: (e) => String(e.id),
rowCount: u?.data?.pagination?.total ?? 0,
manualPagination: !0,
enableRowSelection: !0,
onRowSelectionChange: a,
onColumnVisibilityChange: o,
onPaginationChange: c,
getCoreRowModel: LKt(),
getPaginationRowModel: OKt(),
});
return Q.jsxs("div", {
className: "space-y-4",
children: [
Q.jsx(codexNativeSearchToolbar, {
keyword: e,
setKeyword: t,
onSearch: () => {
c((e) => ({ ...e, pageIndex: 0 }));
i(e.trim());
},
onReset: () => {
t("");
i("");
c((e) => ({ ...e, pageIndex: 0 }));
},
refetch: d,
}),
Q.jsx(QKt, {
table: p,
isLoading: h,
showPagination: !0,
mobilePrimaryField: "email",
mobileGridFields: ["ipv6_email", "plan_name", "status"],
}),
],
});
}
function codexNativeIPv6Page() {
return codexNativePageLayout("IPv6 子账号", "管理 IPv6 子账号开通、主从关系和密码同步。", Q.jsx(codexNativeIPv6Table, {}));
}
function c8t() {
const [e] = Hg(),
[t, n] = H.useState({}),