diff --git a/app/(protected)/admin/records/page.tsx b/app/(protected)/admin/records/page.tsx
index 21ee1ab..43b35f8 100644
--- a/app/(protected)/admin/records/page.tsx
+++ b/app/(protected)/admin/records/page.tsx
@@ -3,9 +3,9 @@ import { redirect } from "next/navigation";
import { getCurrentUser } from "@/lib/session";
import { constructMetadata } from "@/lib/utils";
import { DashboardHeader } from "@/components/dashboard/header";
+import { UserRecordStatus } from "@/components/dashboard/status-card";
import UserRecordsList from "../../dashboard/records/record-list";
-import UserRecordStatus from "../../dashboard/records/record-statu";
export const metadata = constructMetadata({
title: "DNS Records",
@@ -25,16 +25,7 @@ export default async function DashboardPage() {
link="/docs/dns-records"
linkText="DNS records"
/>
-
+
-
+
+
+
+
+
+
>
);
diff --git a/app/(protected)/admin/urls/page.tsx b/app/(protected)/admin/urls/page.tsx
index 5ec3b30..baeabc8 100644
--- a/app/(protected)/admin/urls/page.tsx
+++ b/app/(protected)/admin/urls/page.tsx
@@ -24,7 +24,6 @@ export default async function DashboardPage() {
link="/docs/short-urls"
linkText="short urls"
/>
-
-
+
;
- action: string;
-}
-
-export default function UserRecordStatus({ action }: RecordStatusProps) {
- const { data, isLoading, error } = useSWR>(
- `${action}/status`,
- fetcher,
- );
-
- if (isLoading || error)
- return (
-
-
-
-
-
-
- );
- return (
- data && (
-
-
-
-
-
-
- )
- );
-}
-
-export function StatuInfoCard({
- title,
- total,
- monthTotal,
-}: {
- title: string;
- total?: number;
- monthTotal: number;
-}) {
- const t = useTranslations("Components");
-
- const statusConfig = {
- Active: {
- color: "bg-green-500",
- textColor: "text-green-500",
- gradient: "from-green-400 to-green-600",
- shadow: "shadow-green-500/25",
- },
- Inactive: {
- color: "bg-gray-700",
- textColor: "text-gray-700",
- gradient: "from-gray-400 to-gray-600",
- shadow: "shadow-gray-500/25",
- },
- Pending: {
- color: "bg-yellow-500",
- textColor: "text-yellow-500",
- gradient: "from-yellow-400 to-yellow-600",
- shadow: "shadow-yellow-500/25",
- },
- Rejected: {
- color: "bg-red-500",
- textColor: "text-red-500",
- gradient: "from-red-400 to-red-600",
- shadow: "shadow-red-500/25",
- },
- };
-
- const config = statusConfig[title];
- const percentage = total && total > 0 ? (monthTotal / total) * 100 : 0;
- const barHeight = Math.max(8, Math.min(100, percentage));
-
- return (
-
-
-
-
{t(title)}
-
-
-
- / {nFormatter(total || 0)}
-
-
-
-
-
-
- {/* 柱状图背景 */}
-
- {/* 主柱状图 */}
-
- {/* 光泽效果 */}
-
- {/* 顶部高光 */}
- {barHeight > 15 && (
-
- )}
-
- {percentage.toFixed(0)}%
-
-
-
-
-
-
- );
-}
diff --git a/app/(protected)/dashboard/urls/loading.tsx b/app/(protected)/dashboard/urls/loading.tsx
index 0b40922..6247767 100644
--- a/app/(protected)/dashboard/urls/loading.tsx
+++ b/app/(protected)/dashboard/urls/loading.tsx
@@ -8,7 +8,12 @@ export default function DashboardUrlsLoading() {
heading="Manage Short URLs"
text="List and manage short urls"
/>
-
+
+
+
+
+
+
>
);
diff --git a/app/(protected)/dashboard/urls/url-list.tsx b/app/(protected)/dashboard/urls/url-list.tsx
index 9039523..c0f6038 100644
--- a/app/(protected)/dashboard/urls/url-list.tsx
+++ b/app/(protected)/dashboard/urls/url-list.tsx
@@ -47,6 +47,7 @@ import {
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
+import { UrlStatus } from "@/components/dashboard/status-card";
import { FormType } from "@/components/forms/record-form";
import { UrlForm } from "@/components/forms/url-form";
import ApiReference from "@/components/shared/api-reference";
@@ -725,11 +726,13 @@ export default function UserUrlsList({ user, action }: UrlListProps) {
+
{rendeSeachInputs()}
{rendeList()}
{rendLogs()}
+
{rendeSeachInputs()}
{rendeGrid()}
{rendLogs()}
diff --git a/app/api/url/admin/status/route.ts b/app/api/url/admin/status/route.ts
new file mode 100644
index 0000000..797541b
--- /dev/null
+++ b/app/api/url/admin/status/route.ts
@@ -0,0 +1,23 @@
+import { getUrlStatusOptimized } from "@/lib/dto/short-urls";
+import { checkUserStatus } from "@/lib/dto/user";
+import { getCurrentUser } from "@/lib/session";
+
+export async function GET(req: Request) {
+ try {
+ const user = checkUserStatus(await getCurrentUser());
+ if (user instanceof Response) return user;
+ if (user.role !== "ADMIN") {
+ return Response.json("Unauthorized", {
+ status: 401,
+ });
+ }
+
+ const status = await getUrlStatusOptimized(user.id, "ADMIN");
+
+ return Response.json(status);
+ } catch (error) {
+ return Response.json(error?.statusText || error, {
+ status: error.status || 500,
+ });
+ }
+}
diff --git a/app/api/url/status/route.ts b/app/api/url/status/route.ts
new file mode 100644
index 0000000..fca74a0
--- /dev/null
+++ b/app/api/url/status/route.ts
@@ -0,0 +1,18 @@
+import { getUrlStatusOptimized } from "@/lib/dto/short-urls";
+import { checkUserStatus } from "@/lib/dto/user";
+import { getCurrentUser } from "@/lib/session";
+
+export async function GET(req: Request) {
+ try {
+ const user = checkUserStatus(await getCurrentUser());
+ if (user instanceof Response) return user;
+
+ const status = await getUrlStatusOptimized(user.id, "USER");
+
+ return Response.json(status);
+ } catch (error) {
+ return Response.json(error?.statusText || error, {
+ status: error.status || 500,
+ });
+ }
+}
diff --git a/components/dashboard/count-up.tsx b/components/dashboard/count-up.tsx
index 3fae8c6..a362a69 100644
--- a/components/dashboard/count-up.tsx
+++ b/components/dashboard/count-up.tsx
@@ -4,9 +4,16 @@ import CountUp from "react-countup";
import { nFormatter } from "@/lib/utils";
-export default function CountUpFn({ count }: { count: number }) {
+export default function CountUpFn({
+ count,
+ className,
+}: {
+ count: number;
+ className?: string;
+}) {
return (
+ );
+}
+
+// 短链状态组件
+export function UrlStatus({ action }: { action: string }) {
+ return (
+
+ );
+}
+
+export function GenericStatusDashboard({
+ apiEndpoint,
+ statusItems,
+ statusConfig,
+ gridCols = 4,
+}: {
+ apiEndpoint: string;
+ statusItems: string[];
+ statusConfig: StatusConfig;
+ gridCols?: number;
+}) {
+ const { data, isLoading, error } = useSWR>(
+ `${apiEndpoint}/status`,
+ fetcher,
+ );
+
+ const gridClasses =
+ {
+ 2: "grid-cols-2 sm:grid-cols-2 lg:grid-cols-2",
+ 3: "grid-cols-2 sm:grid-cols-3 lg:grid-cols-3",
+ 4: "grid-cols-2 sm:grid-cols-4 lg:grid-cols-4",
+ 5: "grid-cols-2 sm:grid-cols-3 lg:grid-cols-5",
+ }[gridCols] || "grid-cols-2 sm:grid-cols-4 lg:grid-cols-4";
+
+ if (isLoading || error) {
+ return (
+
+ {statusItems.map((_, index) => (
+
+ ))}
+
+ );
+ }
+
+ return (
+ data && (
+
+ {statusItems.map((status) => (
+
+ ))}
+
+ )
+ );
+}
+
+export function StatusInfoCard({
+ title,
+ total,
+ currentTotal,
+ statusConfig,
+}: {
+ title: string;
+ total?: number;
+ currentTotal: number;
+ statusConfig: StatusConfig;
+}) {
+ const t = useTranslations("Components");
+
+ const config = statusConfig[title];
+ const percentage =
+ total && total > 0 && currentTotal > 0 ? (currentTotal / total) * 100 : 0;
+ const barHeight = Math.max(8, Math.min(100, percentage));
+
+ return (
+
+
+
+
{t(title)}
+
+ {nFormatter(currentTotal || 0)}
+
+ / {nFormatter(total || 0)}
+
+
+
+
+
+
+
+
+
+ {barHeight > 15 && (
+
+ )}
+
+ {percentage.toFixed(0)}%
+
+
+
+
+
+
+ );
+}
diff --git a/lib/dto/short-urls.ts b/lib/dto/short-urls.ts
index 2b4220f..45bcda1 100644
--- a/lib/dto/short-urls.ts
+++ b/lib/dto/short-urls.ts
@@ -2,6 +2,7 @@ import { UrlMeta, UserRole } from "@prisma/client";
import { prisma } from "@/lib/db";
+import { EXPIRATION_ENUMS } from "../enums";
import { getStartDate } from "../utils";
export interface ShortUrlFormData {
@@ -154,6 +155,93 @@ export async function getUrlClicksByIds(
}
}
+export async function getUrlStatus(userId: string, role: UserRole = "USER") {
+ try {
+ } catch (error) {
+ return { status: error };
+ }
+}
+
+export interface UrlStatusStats {
+ total: number;
+ actived: number; // 正常可用
+ disabled: number; // 已禁用
+ expired: number; // 已过期
+ passwordProtected: number; // 密码保护
+}
+
+function isValidExpirationValue(expiration: string): boolean {
+ return EXPIRATION_ENUMS.some((item) => item.value === expiration);
+}
+
+export async function getUrlStatusOptimized(
+ userId: string,
+ role: UserRole = "USER",
+): Promise {
+ try {
+ const whereCondition = role === "USER" ? { userId } : {};
+
+ const urlRecords = await prisma.userUrl.findMany({
+ where: whereCondition,
+ select: {
+ id: true,
+ userId: true,
+ active: true,
+ expiration: true,
+ password: true,
+ createdAt: true,
+ updatedAt: true,
+ },
+ });
+
+ const now = Date.now();
+ const stats: UrlStatusStats = {
+ total: urlRecords.length,
+ actived: 0,
+ disabled: 0,
+ expired: 0,
+ passwordProtected: 0,
+ };
+
+ // 遍历记录并分类
+ urlRecords.forEach((record) => {
+ const updatedAt = new Date(
+ record.updatedAt || record.createdAt!,
+ ).getTime();
+
+ // 判断是否过期
+ let isExpired = false;
+ if (
+ record.expiration !== "-1" &&
+ isValidExpirationValue(record.expiration)
+ ) {
+ const expirationSeconds = Number(record.expiration);
+ const expirationMilliseconds = expirationSeconds * 1000;
+ const expirationTime = updatedAt + expirationMilliseconds;
+ isExpired = now > expirationTime;
+ }
+
+ const isDisabled = record.active === 0;
+ const hasPassword = Boolean(record.password && record.password.trim());
+
+ if (isExpired) {
+ stats.expired++;
+ } else if (isDisabled) {
+ stats.disabled++;
+ } else if (hasPassword) {
+ stats.passwordProtected++;
+ } else {
+ stats.actived++;
+ }
+ });
+
+ return stats;
+ } catch (error) {
+ console.error("Error getting URL status (optimized):", error);
+ return { status: error };
+ }
+}
+
export async function createUserShortUrl(data: ShortUrlFormData) {
try {
const res = await prisma.userUrl.create({
diff --git a/locales/en.json b/locales/en.json
index 08cb0f5..d1e7cc5 100644
--- a/locales/en.json
+++ b/locales/en.json
@@ -320,7 +320,11 @@
"retry": "Retry",
"backToHome": "Back to Home",
"goBack": "Go Back",
- "contactSupportIfError": "If you believe this is an error, please contact technical support"
+ "contactSupportIfError": "If you believe this is an error, please contact technical support",
+ "Actived": "Active",
+ "Disabled": "Disabled",
+ "Expired": "Expired",
+ "PasswordProtected": "Password Protected"
},
"Landing": {
"settings": "Settings",
diff --git a/locales/zh.json b/locales/zh.json
index 5a7e0b0..d1e11df 100644
--- a/locales/zh.json
+++ b/locales/zh.json
@@ -320,7 +320,11 @@
"retry": "重试",
"backToHome": "返回首页",
"goBack": "返回上页",
- "contactSupportIfError": "如果您认为这是一个错误,请联系技术支持"
+ "contactSupportIfError": "如果您认为这是一个错误,请联系技术支持",
+ "Actived": "有效",
+ "Disabled": "已禁用",
+ "Expired": "已过期",
+ "PasswordProtected": "密码保护"
},
"Landing": {
"settings": "设置",
diff --git a/public/sw.js.map b/public/sw.js.map
index afde4d3..8d5bb4e 100644
--- a/public/sw.js.map
+++ b/public/sw.js.map
@@ -1 +1 @@
-{"version":3,"file":"sw.js","sources":["../../../../../../private/var/folders/9b/3qmyp8zd2xvdspdrp149fyg00000gn/T/982d10a57b1ab0281e8eec16db8c2713/sw.js"],"sourcesContent":["import {registerRoute as workbox_routing_registerRoute} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-routing@6.6.0/node_modules/workbox-routing/registerRoute.mjs';\nimport {NetworkFirst as workbox_strategies_NetworkFirst} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-strategies@6.6.0/node_modules/workbox-strategies/NetworkFirst.mjs';\nimport {NetworkOnly as workbox_strategies_NetworkOnly} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-strategies@6.6.0/node_modules/workbox-strategies/NetworkOnly.mjs';\nimport {clientsClaim as workbox_core_clientsClaim} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-core@6.6.0/node_modules/workbox-core/clientsClaim.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\nimportScripts(\n \n);\n\n\n\n\n\n\n\nself.skipWaiting();\n\nworkbox_core_clientsClaim();\n\n\n\nworkbox_routing_registerRoute(\"/\", new workbox_strategies_NetworkFirst({ \"cacheName\":\"start-url\", plugins: [{ cacheWillUpdate: async ({ request, response, event, state }) => { if (response && response.type === 'opaqueredirect') { return new Response(response.body, { status: 200, statusText: 'OK', headers: response.headers }) } return response } }] }), 'GET');\nworkbox_routing_registerRoute(/.*/i, new workbox_strategies_NetworkOnly({ \"cacheName\":\"dev\", plugins: [] }), 'GET');\n\n\n\n\n"],"names":["importScripts","self","skipWaiting","workbox_core_clientsClaim","workbox_routing_registerRoute","workbox_strategies_NetworkFirst","plugins","cacheWillUpdate","request","response","event","state","type","Response","body","status","statusText","headers","workbox_strategies_NetworkOnly"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"sw.js","sources":["../../../../../../private/var/folders/9b/3qmyp8zd2xvdspdrp149fyg00000gn/T/c1e18fb54d3ad49ae1827e1b42c07b7f/sw.js"],"sourcesContent":["import {registerRoute as workbox_routing_registerRoute} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-routing@6.6.0/node_modules/workbox-routing/registerRoute.mjs';\nimport {NetworkFirst as workbox_strategies_NetworkFirst} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-strategies@6.6.0/node_modules/workbox-strategies/NetworkFirst.mjs';\nimport {NetworkOnly as workbox_strategies_NetworkOnly} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-strategies@6.6.0/node_modules/workbox-strategies/NetworkOnly.mjs';\nimport {clientsClaim as workbox_core_clientsClaim} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-core@6.6.0/node_modules/workbox-core/clientsClaim.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\nimportScripts(\n \n);\n\n\n\n\n\n\n\nself.skipWaiting();\n\nworkbox_core_clientsClaim();\n\n\n\nworkbox_routing_registerRoute(\"/\", new workbox_strategies_NetworkFirst({ \"cacheName\":\"start-url\", plugins: [{ cacheWillUpdate: async ({ request, response, event, state }) => { if (response && response.type === 'opaqueredirect') { return new Response(response.body, { status: 200, statusText: 'OK', headers: response.headers }) } return response } }] }), 'GET');\nworkbox_routing_registerRoute(/.*/i, new workbox_strategies_NetworkOnly({ \"cacheName\":\"dev\", plugins: [] }), 'GET');\n\n\n\n\n"],"names":["importScripts","self","skipWaiting","workbox_core_clientsClaim","workbox_routing_registerRoute","workbox_strategies_NetworkFirst","plugins","cacheWillUpdate","request","response","event","state","type","Response","body","status","statusText","headers","workbox_strategies_NetworkOnly"],"mappings":"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"}
\ No newline at end of file