diff --git a/apps/admin/components/dashboard/revenue-statistics-card.tsx b/apps/admin/components/dashboard/revenue-statistics-card.tsx new file mode 100644 index 0000000..9edd9e3 --- /dev/null +++ b/apps/admin/components/dashboard/revenue-statistics-card.tsx @@ -0,0 +1,294 @@ +'use client'; + +import { queryRevenueStatistics } from '@/services/admin/console'; +import { unitConversion } from '@repo/ui/utils'; +import { Card, CardContent, CardFooter, CardHeader, CardTitle } from '@shadcn/ui/card'; +import { + ChartContainer, + ChartLegend, + ChartLegendContent, + ChartTooltip, + ChartTooltipContent, +} from '@shadcn/ui/chart'; +import { + Area, + AreaChart, + Bar, + BarChart, + CartesianGrid, + Label, + Pie, + PieChart, + XAxis, +} from '@shadcn/ui/lib/recharts'; +import { Separator } from '@shadcn/ui/separator'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@shadcn/ui/tabs'; +import { useQuery } from '@tanstack/react-query'; +import { useLocale, useTranslations } from 'next-intl'; +import { Display } from '../display'; +import { Empty } from '../empty'; + +export function RevenueStatisticsCard() { + const t = useTranslations('index'); + + const IncomeStatisticsConfig = { + new_purchase: { + label: t('newPurchase'), + color: 'hsl(var(--chart-1))', + }, + repurchase: { + label: t('repurchase'), + color: 'hsl(var(--chart-2))', + }, + }; + + const locale = useLocale(); + const { data: RevenueStatistics } = useQuery({ + queryKey: ['queryRevenueStatistics'], + queryFn: async () => { + const { data } = await queryRevenueStatistics(); + return data.data; + }, + }); + + return ( + + + + {t('revenueTitle')} + + {t('today')} + {t('month')} + {t('total')} + + + + + {RevenueStatistics?.today.new_order_amount || + RevenueStatistics?.today.renewal_order_amount ? ( + + + } /> + } /> + + + + + ) : ( + + )} + + +
+
+
{t('totalIncome')}
+
+ +
+
+ +
+
+ {IncomeStatisticsConfig.new_purchase.label} +
+
+ +
+
+ +
+
+ {IncomeStatisticsConfig.repurchase.label} +
+
+ +
+
+
+
+
+ + + + {RevenueStatistics?.monthly.list && RevenueStatistics?.monthly.list.length > 0 ? ( + + ({ + date: item.date, + new_purchase: unitConversion('centsToDollars', item.new_order_amount), + repurchase: unitConversion('centsToDollars', item.renewal_order_amount), + })) || [] + } + > + + { + return new Date(value).toLocaleDateString(locale, { + month: 'short', + day: 'numeric', + }); + }} + /> + + + } /> + } /> + + + ) : ( + + )} + + +
+
+
{t('totalIncome')}
+
+ +
+
+ +
+
+ {IncomeStatisticsConfig.new_purchase.label} +
+
+ +
+
+ +
+
+ {IncomeStatisticsConfig.repurchase.label} +
+
+ +
+
+
+
+
+ + + + {RevenueStatistics?.all.list && RevenueStatistics?.all.list.length > 0 ? ( + + ({ + date: item.date, + new_purchase: unitConversion('centsToDollars', item.new_order_amount), + repurchase: unitConversion('centsToDollars', item.renewal_order_amount), + })) || [] + } + margin={{ + left: 12, + right: 12, + }} + > + + { + return new Date(value).toLocaleDateString(locale, { + month: 'short', + }); + }} + /> + } /> + + + } /> + + + ) : ( + + )} + + +
+
+
{t('totalIncome')}
+
+ +
+
+
+
+
+
+
+ ); +} diff --git a/apps/admin/components/dashboard/statistics.tsx b/apps/admin/components/dashboard/statistics.tsx index 8d54ca6..5f9246a 100644 --- a/apps/admin/components/dashboard/statistics.tsx +++ b/apps/admin/components/dashboard/statistics.tsx @@ -1,692 +1,229 @@ 'use client'; +import { queryServerTotalData, queryTicketWaitReply } from '@/services/admin/console'; import { Icon } from '@iconify/react'; import { formatBytes, unitConversion } from '@repo/ui/utils'; -import { Card, CardContent, CardFooter, CardHeader, CardTitle } from '@shadcn/ui/card'; -import { - ChartConfig, - ChartContainer, - ChartLegend, - ChartLegendContent, - ChartTooltip, - ChartTooltipContent, -} from '@shadcn/ui/chart'; -import { - Area, - AreaChart, - Bar, - BarChart, - CartesianGrid, - Label, - LabelList, - Pie, - PieChart, - XAxis, - YAxis, -} from '@shadcn/ui/lib/recharts'; +import { Card, CardContent, CardHeader, CardTitle } from '@shadcn/ui/card'; +import { ChartContainer, ChartTooltip, ChartTooltipContent } from '@shadcn/ui/chart'; +import { Bar, BarChart, CartesianGrid, LabelList, XAxis, YAxis } from '@shadcn/ui/lib/recharts'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@shadcn/ui/select'; -import { Separator } from '@shadcn/ui/separator'; -import { Tabs, TabsContent, TabsList, TabsTrigger } from '@shadcn/ui/tabs'; -import { useLocale } from 'next-intl'; +import { Tabs, TabsList, TabsTrigger } from '@shadcn/ui/tabs'; +import { useQuery } from '@tanstack/react-query'; +import { useTranslations } from 'next-intl'; +import Link from 'next/link'; import { useState } from 'react'; - -const UserStatisticsConfig = { - register: { - label: '注册', - color: 'hsl(var(--chart-1))', - }, - new_purchase: { - label: '新购', - color: 'hsl(var(--chart-2))', - }, - repurchase: { - label: '复购', - color: 'hsl(var(--chart-3))', - }, -} satisfies ChartConfig; - -const IncomeStatisticsConfig = { - new_purchase: { - label: '新购', - color: 'hsl(var(--chart-1))', - }, - repurchase: { - label: '复购', - color: 'hsl(var(--chart-2))', - }, -}; - -// Sample data - replace with actual data -const trafficData = { - nodes: { - today: [ - { name: 'Node 1', traffic: 1000, type: 'Trojan', address: '127.0.0.1:443' }, - { name: 'Node 2', traffic: 800, type: 'Trojan', address: '127.0.0.1:444' }, - { name: 'Node 3', traffic: 600, type: 'Trojan', address: '127.0.0.1:445' }, - { name: 'Node 4', traffic: 400, type: 'Trojan', address: '127.0.0.1:446' }, - { name: 'Node 5', traffic: 200, type: 'Trojan', address: '127.0.0.1:447' }, - { name: 'Node 6', traffic: 1000, type: 'Trojan', address: '127.0.0.1:443' }, - { name: 'Node 7', traffic: 800, type: 'Trojan', address: '127.0.0.1:444' }, - { name: 'Node 8', traffic: 600, type: 'Trojan', address: '127.0.0.1:445' }, - { name: 'Node 9', traffic: 400, type: 'Trojan', address: '127.0.0.1:446' }, - { name: 'Node 10', traffic: 200, type: 'Trojan', address: '127.0.0.1:447' }, - ], - yesterday: [ - { name: 'Node 1', traffic: 900, type: 'Trojan', address: '127.0.0.1:443' }, - { name: 'Node 2', traffic: 750, type: 'Trojan', address: '127.0.0.1:444' }, - { name: 'Node 3', traffic: 550, type: 'Trojan', address: '127.0.0.1:445' }, - { name: 'Node 4', traffic: 350, type: 'Trojan', address: '127.0.0.1:446' }, - { name: 'Node 5', traffic: 150, type: 'Trojan', address: '127.0.0.1:447' }, - ], - }, - users: { - today: [ - { name: 'olivia.martin@email.com', traffic: 100, email: 'olivia.martin@email.com' }, - { name: 'jackson.lee@email.com', traffic: 90, email: 'jackson.lee@email.com' }, - { name: 'isabella.nguyen@email.com', traffic: 80, email: 'isabella.nguyen@email.com' }, - { name: 'william.chen@email.com', traffic: 70, email: 'william.chen@email.com' }, - { name: 'sophia.rodriguez@email.com', traffic: 60, email: 'sophia.rodriguez@email.com' }, - { name: 'olivia.martin@email.com', traffic: 100, email: 'olivia.martin@email.com' }, - { name: 'jackson.lee@email.com', traffic: 90, email: 'jackson.lee@email.com' }, - { name: 'isabella.nguyen@email.com', traffic: 80, email: 'isabella.nguyen@email.com' }, - { name: 'william.chen@email.com', traffic: 70, email: 'william.chen@email.com' }, - { name: 'sophia.rodriguez@email.com', traffic: 60, email: 'sophia.rodriguez@email.com' }, - ], - yesterday: [ - { name: 'olivia.martin@email.com', traffic: 95, email: 'olivia.martin@email.com' }, - { name: 'jackson.lee@email.com', traffic: 85, email: 'jackson.lee@email.com' }, - { name: 'isabella.nguyen@email.com', traffic: 75, email: 'isabella.nguyen@email.com' }, - { name: 'william.chen@email.com', traffic: 65, email: 'william.chen@email.com' }, - { name: 'sophia.rodriguez@email.com', traffic: 55, email: 'sophia.rodriguez@email.com' }, - ], - }, -}; +import { Empty } from '../empty'; +import { RevenueStatisticsCard } from './revenue-statistics-card'; +import { UserStatisticsCard } from './user-statistics-card'; export default function Statistics() { - const locale = useLocale(); + const t = useTranslations('index'); + + const { data: TicketTotal } = useQuery({ + queryKey: ['queryTicketWaitReply'], + queryFn: async () => { + const { data } = await queryTicketWaitReply(); + return data.data?.count; + }, + }); + const { data: ServerTotal } = useQuery({ + queryKey: ['queryServerTotalData'], + queryFn: async () => { + const { data } = await queryServerTotalData(); + return data.data; + }, + }); const [dataType, setDataType] = useState('nodes'); const [timeFrame, setTimeFrame] = useState('today'); + const trafficData = { + nodes: { + today: + ServerTotal?.server_traffic_ranking_today?.map((item) => ({ + name: item.name, + traffic: item.download + item.upload, + })) || [], + yesterday: + ServerTotal?.server_traffic_ranking_yesterday?.map((item) => ({ + name: item.name, + traffic: item.download + item.upload, + })) || [], + }, + users: { + today: + ServerTotal?.user_traffic_ranking_today?.map((item) => ({ + name: item.user_id, + traffic: item.download + item.upload, + email: item.email, + })) || [], + yesterday: + ServerTotal?.user_traffic_ranking_yesterday?.map((item) => ({ + name: item.user_id, + traffic: item.download + item.upload, + email: item.email, + })) || [], + }, + }; + const currentData = trafficData[dataType][timeFrame]; + return ( <> -

统计

+

{t('statisticsTitle')}

{[ { - title: '在线IP数', - value: '666', + title: t('onlineIPCount'), + value: ServerTotal?.online_user_ips || 0, icon: 'uil:users-alt', - onClick: () => console.log('在线IP数 clicked'), + href: '/dashboard/server', }, { - title: '在线节点数', - value: '99', + title: t('onlineNodeCount'), + value: ServerTotal?.online_servers || 0, icon: 'uil:server-network', - onClick: () => console.log('在线节点数 clicked'), + href: '/dashboard/server', }, { - title: '离线节点数', - value: '1', + title: t('offlineNodeCount'), + value: ServerTotal?.offline_servers || 0, icon: 'uil:server-network-alt', - onClick: () => console.log('离线节点数 clicked'), + href: '/dashboard/server', }, { - title: '待处理工单', - value: '1', + title: t('pendingTickets'), + value: TicketTotal || 0, icon: 'uil:clipboard-notes', - onClick: () => console.log('待处理工单 clicked'), + href: '/dashboard/ticket', }, { - title: '今日上传流量', - value: formatBytes(99999999999999), + title: t('todayUploadTraffic'), + value: formatBytes(ServerTotal?.upload_traffic_today || 0), icon: 'uil:arrow-up', - onClick: () => console.log('今日上传流量 clicked'), }, { - title: '今日下载流量', - value: formatBytes(99999999999999), + title: t('todayDownloadTraffic'), + value: formatBytes(ServerTotal?.download_traffic_today || 0), icon: 'uil:arrow-down', - onClick: () => console.log('今日下载流量 clicked'), }, { - title: '总上传流量', - value: formatBytes(99999999999999), + title: t('monthUploadTraffic'), + value: formatBytes(ServerTotal?.upload_traffic_month || 0), icon: 'uil:cloud-upload', - onClick: () => console.log('总上传流量 clicked'), }, { - title: '总下载流量', - value: formatBytes(99999999999999), + title: t('monthDownloadTraffic'), + value: formatBytes(ServerTotal?.download_traffic_month || 0), icon: 'uil:cloud-download', - onClick: () => console.log('总下载流量 clicked'), }, ].map((item, index) => ( - - - {item.title} - - - -
{item.value}
-
-
+ + + + {item.title} + + + +
{item.value}
+
+
+ ))}
- - - - 收入统计 - - 今日 - 本月 - 总计 - - - - - - - } /> - } /> - - - - - - -
-
-
总收入
-
6,666
-
- -
-
- {IncomeStatisticsConfig.new_purchase.label} -
-
123
-
- -
-
- {IncomeStatisticsConfig.repurchase.label} -
-
456
-
-
-
-
- - - - - - { - return new Date(value).toLocaleDateString(locale, { - month: 'short', - day: 'numeric', - }); - }} - /> - - - } /> - } /> - - - - -
-
-
总收入
-
654,321
-
- -
-
- {IncomeStatisticsConfig.new_purchase.label} -
-
123
-
- -
-
- {IncomeStatisticsConfig.repurchase.label} -
-
456
-
-
-
-
- - - - - - { - return new Date(value).toLocaleDateString(locale, { - month: 'short', - }); - }} - /> - } - /> - - - } /> - - - - -
-
-
总收入
-
987,654,321
-
-
-
-
-
-
- - - - 用户统计 - - 今日 - 本月 - 总计 - - - - - - - } /> - } /> - - - - - - -
-
-
- {UserStatisticsConfig.register.label} -
-
789
-
- -
-
- {UserStatisticsConfig.new_purchase.label} -
-
123
-
- -
-
- {UserStatisticsConfig.repurchase.label} -
-
456
-
-
-
-
- - - - - - { - return new Date(value).toLocaleDateString(locale, { - month: 'short', - day: 'numeric', - }); - }} - /> - - - - } /> - } /> - - - - -
-
-
- {UserStatisticsConfig.register.label} -
-
789
-
- -
-
- {UserStatisticsConfig.new_purchase.label} -
-
123
-
- -
-
- {UserStatisticsConfig.repurchase.label} -
-
456
-
-
-
-
- - - - - - { - return new Date(value).toLocaleDateString(locale, { - month: 'short', - }); - }} - /> - } - /> - - - - } /> - - - - -
-
-
- {UserStatisticsConfig.register.label} -
-
987,654,321
-
-
-
-
-
-
+ + - 流量排行 + {t('trafficRank')} - 今日 - 昨日 + {t('today')} + {t('yesterday')}
-

{dataType === 'nodes' ? '节点流量' : '用户流量'}

+

+ {dataType === 'nodes' ? t('nodeTraffic') : t('userTraffic')} +

- - - - formatBytes(unitConversion('gbToBytes', value) || 0)} - /> - String(index + 1)} - /> - - dataType === 'nodes' ? `节点: ${label}` : `用户: ${label}` - } - /> - } - /> - - 0 ? ( + + + + formatBytes(unitConversion('gbToBytes', value) || 0)} /> - - - + String(index + 1)} + /> + + dataType === 'nodes' + ? `${t('nodes')}: ${label}` + : `${t('users')}: ${label}` + } + /> + } + /> + + + + + + ) : ( + + )}
diff --git a/apps/admin/components/dashboard/user-statistics-card.tsx b/apps/admin/components/dashboard/user-statistics-card.tsx new file mode 100644 index 0000000..6dc43d0 --- /dev/null +++ b/apps/admin/components/dashboard/user-statistics-card.tsx @@ -0,0 +1,330 @@ +'use client'; + +import { queryUserStatistics } from '@/services/admin/console'; +import { Card, CardContent, CardFooter, CardHeader, CardTitle } from '@shadcn/ui/card'; +import { + ChartContainer, + ChartLegend, + ChartLegendContent, + ChartTooltip, + ChartTooltipContent, +} from '@shadcn/ui/chart'; +import { + Area, + AreaChart, + Bar, + BarChart, + CartesianGrid, + Label, + Pie, + PieChart, + XAxis, +} from '@shadcn/ui/lib/recharts'; +import { Separator } from '@shadcn/ui/separator'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@shadcn/ui/tabs'; +import { useQuery } from '@tanstack/react-query'; +import { useLocale, useTranslations } from 'next-intl'; +import { Empty } from '../empty'; + +const UserStatisticsConfig = { + register: { + label: '注册', + color: 'hsl(var(--chart-1))', + }, + new_purchase: { + label: '新购', + color: 'hsl(var(--chart-2))', + }, + repurchase: { + label: '复购', + color: 'hsl(var(--chart-3))', + }, +}; + +export function UserStatisticsCard() { + const t = useTranslations('index'); + + const UserStatisticsConfig = { + register: { + label: t('register'), + color: 'hsl(var(--chart-1))', + }, + new_purchase: { + label: t('newPurchase'), + color: 'hsl(var(--chart-2))', + }, + repurchase: { + label: t('repurchase'), + color: 'hsl(var(--chart-3))', + }, + }; + const locale = useLocale(); + + const { data: UserStatistics } = useQuery({ + queryKey: ['queryUserStatistics'], + queryFn: async () => { + const { data } = await queryUserStatistics(); + return data.data; + }, + }); + + return ( + + + + {t('userTitle')} + + {t('today')} + {t('month')} + {t('total')} + + + + + + {UserStatistics?.today.register || + UserStatistics?.today.new_order_users || + UserStatistics?.today.renewal_order_users ? ( + + + } /> + } /> + + + + + ) : ( + + )} + + +
+
+
+ {UserStatisticsConfig.register.label} +
+
+ {UserStatistics?.today.register} +
+
+ +
+
+ {UserStatisticsConfig.new_purchase.label} +
+
+ {UserStatistics?.today.new_order_users} +
+
+ +
+
+ {UserStatisticsConfig.repurchase.label} +
+
+ {UserStatistics?.today.renewal_order_users} +
+
+
+
+
+ + + + {UserStatistics?.monthly.list && UserStatistics?.monthly.list.length > 0 ? ( + + ({ + date: item.date, + register: item.register, + new_purchase: item.new_order_users, + repurchase: item.renewal_order_users, + })) || [] + } + > + + { + return new Date(value).toLocaleDateString(locale, { + month: 'short', + day: 'numeric', + }); + }} + /> + + + + } /> + } /> + + + ) : ( + + )} + + +
+
+
+ {UserStatisticsConfig.register.label} +
+
+ {UserStatistics?.monthly.register} +
+
+ +
+
+ {UserStatisticsConfig.new_purchase.label} +
+
+ {UserStatistics?.monthly.new_order_users} +
+
+ +
+
+ {UserStatisticsConfig.repurchase.label} +
+
+ {UserStatistics?.monthly.renewal_order_users} +
+
+
+
+
+ + + + {UserStatistics?.all.list && UserStatistics?.all.list.length > 0 ? ( + + ({ + date: item.date, + register: item.register, + new_purchase: item.new_order_users, + repurchase: item.renewal_order_users, + })) || [] + } + margin={{ + left: 12, + right: 12, + }} + > + + { + return new Date(value).toLocaleDateString(locale, { + month: 'short', + }); + }} + /> + } /> + + + + } /> + + + ) : ( + + )} + + +
+
+
+ {UserStatisticsConfig.register.label} +
+
+ {UserStatistics?.all.register} +
+
+
+
+
+
+
+ ); +} diff --git a/apps/admin/components/empty.tsx b/apps/admin/components/empty.tsx new file mode 100644 index 0000000..db10c99 --- /dev/null +++ b/apps/admin/components/empty.tsx @@ -0,0 +1,18 @@ +'use client'; + +import { default as _Empty } from '@repo/ui/empty'; +import { useTranslations } from 'next-intl'; +import { useEffect, useState } from 'react'; + +export function Empty() { + const t = useTranslations('common'); + + const [description, setDescription] = useState(''); + + useEffect(() => { + const random = Math.floor(Math.random() * 10); + setDescription(t(`empty.${random}`)); + }, [t]); + + return <_Empty description={description} />; +} diff --git a/apps/admin/locales/en-US/index.json b/apps/admin/locales/en-US/index.json index 0967ef4..ec12fce 100644 --- a/apps/admin/locales/en-US/index.json +++ b/apps/admin/locales/en-US/index.json @@ -1 +1,29 @@ -{} +{ + "email": "Email", + "month": "Month", + "monthDownloadTraffic": "This Month's Download Traffic", + "monthUploadTraffic": "This Month's Upload Traffic", + "newPurchase": "New Purchase", + "nodeTraffic": "Node Traffic", + "nodes": "Nodes", + "offlineNodeCount": "Offline Nodes", + "onlineIPCount": "Online IPs", + "onlineNodeCount": "Online Nodes", + "pendingTickets": "Pending Tickets", + "register": "Register", + "repurchase": "Repurchase", + "revenueTitle": "Revenue Statistics", + "selectTypePlaceholder": "Select Type", + "statisticsTitle": "Statistics", + "today": "Today", + "todayDownloadTraffic": "Today's Download Traffic", + "todayUploadTraffic": "Today's Upload Traffic", + "total": "Total", + "totalIncome": "Total Income", + "trafficRank": "Traffic Ranking", + "type": "Type", + "userTitle": "User Statistics", + "userTraffic": "User Traffic", + "users": "Users", + "yesterday": "Yesterday" +} diff --git a/apps/admin/locales/zh-CN/index.json b/apps/admin/locales/zh-CN/index.json index 0967ef4..f9e44c9 100644 --- a/apps/admin/locales/zh-CN/index.json +++ b/apps/admin/locales/zh-CN/index.json @@ -1 +1,29 @@ -{} +{ + "email": "邮箱", + "month": "本月", + "monthDownloadTraffic": "本月下载流量", + "monthUploadTraffic": "本月上传流量", + "newPurchase": "新购", + "nodeTraffic": "节点流量", + "nodes": "节点", + "offlineNodeCount": "离线节点数", + "onlineIPCount": "在线IP数", + "onlineNodeCount": "在线节点数", + "pendingTickets": "待处理工单", + "register": "注册", + "repurchase": "复购", + "revenueTitle": "收入统计", + "selectTypePlaceholder": "选择类型", + "statisticsTitle": "统计", + "today": "今日", + "todayDownloadTraffic": "今日下载流量", + "todayUploadTraffic": "今日上传流量", + "total": "总计", + "totalIncome": "总收入", + "trafficRank": "流量排行", + "type": "类型", + "userTitle": "用户统计", + "userTraffic": "用户流量", + "users": "用户", + "yesterday": "昨日" +} diff --git a/apps/admin/services/admin/console.ts b/apps/admin/services/admin/console.ts new file mode 100644 index 0000000..82db603 --- /dev/null +++ b/apps/admin/services/admin/console.ts @@ -0,0 +1,44 @@ +// @ts-ignore +/* eslint-disable */ +import request from '@/utils/request'; + +/** Query revenue statistics GET /v1/admin/console/revenue */ +export async function queryRevenueStatistics(options?: { [key: string]: any }) { + return request( + '/v1/admin/console/revenue', + { + method: 'GET', + ...(options || {}), + }, + ); +} + +/** Query server total data GET /v1/admin/console/server */ +export async function queryServerTotalData(options?: { [key: string]: any }) { + return request( + '/v1/admin/console/server', + { + method: 'GET', + ...(options || {}), + }, + ); +} + +/** Query ticket wait reply GET /v1/admin/console/ticket */ +export async function queryTicketWaitReply(options?: { [key: string]: any }) { + return request( + '/v1/admin/console/ticket', + { + method: 'GET', + ...(options || {}), + }, + ); +} + +/** Query user statistics GET /v1/admin/console/user */ +export async function queryUserStatistics(options?: { [key: string]: any }) { + return request('/v1/admin/console/user', { + method: 'GET', + ...(options || {}), + }); +} diff --git a/apps/admin/services/admin/index.ts b/apps/admin/services/admin/index.ts index a827234..944988e 100644 --- a/apps/admin/services/admin/index.ts +++ b/apps/admin/services/admin/index.ts @@ -3,6 +3,7 @@ // API 更新时间: // API 唯一标识: import * as announcement from './announcement'; +import * as console from './console'; import * as coupon from './coupon'; import * as document from './document'; import * as order from './order'; @@ -15,6 +16,7 @@ import * as tool from './tool'; import * as user from './user'; export default { announcement, + console, coupon, document, order, diff --git a/apps/admin/services/admin/typings.d.ts b/apps/admin/services/admin/typings.d.ts index fadf025..1ec1abc 100644 --- a/apps/admin/services/admin/typings.d.ts +++ b/apps/admin/services/admin/typings.d.ts @@ -556,6 +556,14 @@ declare namespace API { updated_at: number; }; + type OrdersStatistics = { + date?: string; + amount_total: number; + new_order_amount: number; + renewal_order_amount: number; + list?: OrdersStatistics[]; + }; + type PaymentConfig = { id: number; name: string; @@ -589,6 +597,12 @@ declare namespace API { data?: Record; }; + type RevenueStatisticsResponse = { + today: OrdersStatistics; + monthly: OrdersStatistics; + all: OrdersStatistics; + }; + type SecurityConfig = { sni: string; allow_insecure: boolean; @@ -633,6 +647,28 @@ declare namespace API { updated_at: number; }; + type ServerTotalDataResponse = { + online_user_ips: number; + online_servers: number; + offline_servers: number; + today_upload: number; + today_download: number; + monthly_upload: number; + monthly_download: number; + updated_at: number; + server_traffic_ranking_today: ServerTrafficData[]; + server_traffic_ranking_yesterday: ServerTrafficData[]; + user_traffic_ranking_today: UserTrafficData[]; + user_traffic_ranking_yesterday: UserTrafficData[]; + }; + + type ServerTrafficData = { + server_id: number; + name: string; + upload: number; + download: number; + }; + type Shadowsocks = { method: string; port: number; @@ -719,6 +755,10 @@ declare namespace API { updated_at: number; }; + type TicketWaitRelpyResponse = { + count: number; + }; + type TosConfig = { tos_content: string; }; @@ -942,6 +982,20 @@ declare namespace API { created_at: number; }; + type UserStatistics = { + date?: string; + register: number; + new_order_users: number; + renewal_order_users: number; + list?: UserStatistics[]; + }; + + type UserStatisticsResponse = { + today: UserStatistics; + monthly: UserStatistics; + all: UserStatistics; + }; + type UserSubscribe = { id: number; user_id: number; @@ -959,6 +1013,13 @@ declare namespace API { updated_at: number; }; + type UserTrafficData = { + user_id: number; + email: string; + upload: number; + download: number; + }; + type VerifyConfig = { turnstile_site_key: string; turnstile_secret: string;