From 525e305f1d86bba1a879d13543223da4b328a0a1 Mon Sep 17 00:00:00 2001 From: speakeloudest Date: Fri, 15 Aug 2025 09:16:02 -0700 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BF=AE=E6=94=B9=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/admin/.env.prod | 17 +++ apps/user/.env.prod | 32 ++++++ .../app/(main)/(content)/(user)/Header.tsx | 4 +- .../(content)/(user)/dashboard/content.tsx | 4 +- .../app/(main)/(content)/(user)/layout.tsx | 4 +- .../(user)/profile/notify-settings.tsx | 12 ++ .../(user)/wallet/components/Table/Table.tsx | 60 ++++++++++ .../components/WalletDialog/WalletDialog.tsx | 106 ++++++++++++++++++ .../(main)/(content)/(user)/wallet/page.tsx | 56 ++------- apps/user/components/language-switch.tsx | 2 +- apps/user/components/subscribe/purchase.tsx | 1 - apps/user/locales/en-US/wallet.json | 1 + apps/user/locales/zh-CN/wallet.json | 1 + apps/user/services/user/user.ts | 8 +- apps/user/utils/request.ts | 1 - scripts/publish-dev.sh | 8 +- scripts/publish.sh | 2 +- 17 files changed, 256 insertions(+), 63 deletions(-) create mode 100644 apps/admin/.env.prod create mode 100644 apps/user/.env.prod create mode 100644 apps/user/app/(main)/(content)/(user)/wallet/components/Table/Table.tsx create mode 100644 apps/user/app/(main)/(content)/(user)/wallet/components/WalletDialog/WalletDialog.tsx diff --git a/apps/admin/.env.prod b/apps/admin/.env.prod new file mode 100644 index 0000000..7640a79 --- /dev/null +++ b/apps/admin/.env.prod @@ -0,0 +1,17 @@ +# Default Language +NEXT_PUBLIC_DEFAULT_LANGUAGE=zh-CN + +# Site URL and API URL +NEXT_PUBLIC_SITE_URL=https://admin.ppanel.dev +NEXT_PUBLIC_API_URL=https://api.airoport.co + +# Default Login User +NEXT_PUBLIC_DEFAULT_USER_EMAIL= +NEXT_PUBLIC_DEFAULT_USER_PASSWORD= + +# Please put in the .env file, otherwise the i18n command will not work +# OpenAI API key and proxy URL required for i18n command (optional) +OPENAI_API_KEY= +OPENAI_PROXY_URL= + + diff --git a/apps/user/.env.prod b/apps/user/.env.prod new file mode 100644 index 0000000..ea73e02 --- /dev/null +++ b/apps/user/.env.prod @@ -0,0 +1,32 @@ +# Default Language +NEXT_PUBLIC_DEFAULT_LANGUAGE=zh-CN + +# Site URL and API URL +NEXT_PUBLIC_SITE_URL=https://user.ppanel.dev +NEXT_PUBLIC_API_URL=https://api.airoport.co +NEXT_PUBLIC_CDN_URL=https://cdn.jsdelivr.net + +# Home Page Settings +NEXT_PUBLIC_HOME_USER_COUNT=999 +NEXT_PUBLIC_HOME_SERVER_COUNT=999 +NEXT_PUBLIC_HOME_LOCATION_COUNT=999 + +# Contact Email +NEXT_PUBLIC_EMAIL=support@ppanel.dev +# Community Links +NEXT_PUBLIC_TELEGRAM_LINK=https://t.me/ppanel +NEXT_PUBLIC_TWITTER_LINK=https://github.com/perfect-panel/ppanel-web +NEXT_PUBLIC_DISCORD_LINK=https://github.com/perfect-panel/ppanel-web +NEXT_PUBLIC_INSTAGRAM_LINK=https://github.com/perfect-panel/ppanel-web +NEXT_PUBLIC_LINKEDIN_LINK=https://github.com/perfect-panel/ppanel-web +NEXT_PUBLIC_FACEBOOK_LINK=https://github.com/perfect-panel/ppanel-web +NEXT_PUBLIC_GITHUB_LINK=https://github.com/perfect-panel/ppanel-web + +# Default Login User +NEXT_PUBLIC_DEFAULT_USER_EMAIL= +NEXT_PUBLIC_DEFAULT_USER_PASSWORD= + +# Please put in the .env file, otherwise the i18n command will not work +# OpenAI API key and proxy URL required for i18n command (optional) +OPENAI_API_KEY= +OPENAI_PROXY_URL= diff --git a/apps/user/app/(main)/(content)/(user)/Header.tsx b/apps/user/app/(main)/(content)/(user)/Header.tsx index f464658..07984aa 100644 --- a/apps/user/app/(main)/(content)/(user)/Header.tsx +++ b/apps/user/app/(main)/(content)/(user)/Header.tsx @@ -18,8 +18,8 @@ export function Header() { const pathname = usePathname(); const items = useMemo(() => findNavByUrl(pathname), [pathname]); return ( -
- +
+ {items.map((item, index) => { diff --git a/apps/user/app/(main)/(content)/(user)/dashboard/content.tsx b/apps/user/app/(main)/(content)/(user)/dashboard/content.tsx index 2c50920..4928e69 100644 --- a/apps/user/app/(main)/(content)/(user)/dashboard/content.tsx +++ b/apps/user/app/(main)/(content)/(user)/dashboard/content.tsx @@ -75,8 +75,8 @@ export default function Content() { const { data: orderData } = useQuery({ queryKey: ['orderData'], queryFn: async () => { - const { data } = await queryOrderList({ status: 5, page: 1, size: 10 }); - return data?.[0] ?? {}; + const { data } = await queryOrderList({ status: 5, page: 1, size: 1 }); + return data?.data?.list?.[0] ?? {}; }, }); diff --git a/apps/user/app/(main)/(content)/(user)/layout.tsx b/apps/user/app/(main)/(content)/(user)/layout.tsx index 6672193..5267ee4 100644 --- a/apps/user/app/(main)/(content)/(user)/layout.tsx +++ b/apps/user/app/(main)/(content)/(user)/layout.tsx @@ -13,8 +13,8 @@ export default async function DashboardLayout({ children }: { children: React.Re {/**/} -
-
+
+
{children}
diff --git a/apps/user/app/(main)/(content)/(user)/profile/notify-settings.tsx b/apps/user/app/(main)/(content)/(user)/profile/notify-settings.tsx index efc0aa2..4eebfb9 100644 --- a/apps/user/app/(main)/(content)/(user)/profile/notify-settings.tsx +++ b/apps/user/app/(main)/(content)/(user)/profile/notify-settings.tsx @@ -5,6 +5,7 @@ import { updateUserNotify } from '@/services/user/user'; import { zodResolver } from '@hookform/resolvers/zod'; import { Button } from '@workspace/airo-ui/components/button'; import { Card } from '@workspace/airo-ui/components/card'; +import { useEffect } from 'react'; import { AiroButton } from '@workspace/airo-ui/components/AiroButton'; import { @@ -39,6 +40,17 @@ export default function NotifySettings() { enable_trade_notify: user?.enable_trade_notify ?? false, }, }); + // 监听 user 变化,更新表单 + useEffect(() => { + if (user) { + form.reset({ + enable_balance_notify: user.enable_balance_notify ?? false, + enable_login_notify: user.enable_login_notify ?? false, + enable_subscribe_notify: user.enable_subscribe_notify ?? false, + enable_trade_notify: user.enable_trade_notify ?? false, + }); + } + }, [user, form]); async function onSubmit(data: z.infer) { await updateUserNotify(data); diff --git a/apps/user/app/(main)/(content)/(user)/wallet/components/Table/Table.tsx b/apps/user/app/(main)/(content)/(user)/wallet/components/Table/Table.tsx new file mode 100644 index 0000000..7cd8b6d --- /dev/null +++ b/apps/user/app/(main)/(content)/(user)/wallet/components/Table/Table.tsx @@ -0,0 +1,60 @@ +import { Display } from '@/components/display'; +import { Empty } from '@/components/empty'; +import { ProList, ProListActions } from '@/components/pro-list'; +import { queryUserBalanceLog } from '@/services/user/user'; +import { Card, CardContent } from '@workspace/airo-ui/components/card'; +import { formatDate } from '@workspace/airo-ui/utils'; +import { useTranslations } from 'next-intl'; +import { useRef } from 'react'; + +const Table: React.FC<{}> = () => { + const ref = useRef(null); + const t = useTranslations('wallet'); + + return ( + > + action={ref} + request={async (pagination, filter) => { + const response = await queryUserBalanceLog({ ...pagination, ...filter }); + return { + list: response.data.data?.list || [], + total: response.data.data?.total || 0, + }; + }} + renderItem={(item) => { + return ( + + +
    +
  • + {t('createdAt')} + +
  • +
  • + {t('type.0')} + {t(`type.${item.type}`)} +
  • +
  • + {t('amount')} + + + +
  • + +
  • + {t('balance')} + + + +
  • +
+
+
+ ); + }} + empty={} + /> + ); +}; + +export default Table; diff --git a/apps/user/app/(main)/(content)/(user)/wallet/components/WalletDialog/WalletDialog.tsx b/apps/user/app/(main)/(content)/(user)/wallet/components/WalletDialog/WalletDialog.tsx new file mode 100644 index 0000000..44d7caf --- /dev/null +++ b/apps/user/app/(main)/(content)/(user)/wallet/components/WalletDialog/WalletDialog.tsx @@ -0,0 +1,106 @@ +import { queryUserBalanceLog } from '@/services/user/user'; +import { useQuery } from '@tanstack/react-query'; +import { AiroButton } from '@workspace/airo-ui/components/AiroButton'; +import { Card, CardContent } from '@workspace/airo-ui/components/card'; +import { + DialogContent, + DialogHeader, + DialogTitle, + DialogTrigger, +} from '@workspace/airo-ui/components/dialog'; +import { default as Airo_Empty } from '@workspace/airo-ui/custom-components/empty'; +import { formatDate } from '@workspace/airo-ui/utils'; +import { Dialog } from '@workspace/ui/components/dialog'; +import { useTranslations } from 'next-intl'; +import { useState } from 'react'; + +import { Display } from '@/components/display'; +import Table from '../Table/Table'; + +const WalletDialog: React.FC<{}> = () => { + const [open, setOpen] = useState(false); + const t = useTranslations('affiliate'); + const tWallet = useTranslations('wallet'); + + const { data } = useQuery({ + queryKey: ['walletDialogList'], + queryFn: async () => { + const data = await queryUserBalanceLog({ + page: 1, + size: 4, + } as API.QueryUserAffiliateListRequest); + console.log('data', data?.data.data); + return data?.data?.data?.list || []; + }, + }); + + return ( + +
+

{tWallet('title')}

+ + + + {t('more')} + + + + + + {tWallet('title')} + + + + + + + +
+ {data?.length ? ( +
+
+ {data?.map((item) => { + return ( + + +
    +
  • + {tWallet('createdAt')} + +
  • +
  • + {tWallet('type.0')} + {tWallet(`type.${item.type}`)} +
  • +
  • + {tWallet('amount')} + + + +
  • + +
  • + {tWallet('balance')} + + + +
  • +
+
+
+ ); + })} +
+ ) : ( + + )} +
+ + ); +}; + +export default WalletDialog; diff --git a/apps/user/app/(main)/(content)/(user)/wallet/page.tsx b/apps/user/app/(main)/(content)/(user)/wallet/page.tsx index 5f16da2..ddeae16 100644 --- a/apps/user/app/(main)/(content)/(user)/wallet/page.tsx +++ b/apps/user/app/(main)/(content)/(user)/wallet/page.tsx @@ -1,27 +1,23 @@ 'use client'; import { Display } from '@/components/display'; -import { ProList, ProListActions } from '@/components/pro-list'; import useGlobalStore from '@/config/use-global'; -import { queryUserBalanceLog } from '@/services/user/user'; import { Card, CardContent } from '@workspace/airo-ui/components/card'; import { useTranslations } from 'next-intl'; -import { useRef } from 'react'; -import { Empty } from '@/components/empty'; import Recharge from '@/components/subscribe/recharge'; import SvgIcon from '@/components/SvgIcon'; import { Button } from '@workspace/airo-ui/components/button'; -import { formatDate } from '@workspace/airo-ui/utils'; import Link from 'next/link'; import { CopyToClipboard } from 'react-copy-to-clipboard'; import { toast } from 'sonner'; +import Table from './components/Table/Table'; +import WalletDialog from './components/WalletDialog/WalletDialog'; export default function Page() { const t = useTranslations('wallet'); const dashboardT = useTranslations('dashboard'); const { user } = useGlobalStore(); - const ref = useRef(null); const totalAssets = (user?.balance || 0) + (user?.commission || 0) + (user?.gift_amount || 0); return ( <> @@ -92,48 +88,12 @@ export default function Page() { - > - action={ref} - request={async (pagination, filter) => { - const response = await queryUserBalanceLog({ ...pagination, ...filter }); - return { - list: response.data.data?.list || [], - total: response.data.data?.total || 0, - }; - }} - renderItem={(item) => { - return ( - - -
    -
  • - {t('createdAt')} - -
  • -
  • - {t('type.0')} - {t(`type.${item.type}`)} -
  • -
  • - {t('amount')} - - - -
  • - -
  • - {t('balance')} - - - -
  • -
-
-
- ); - }} - empty={} - /> +
+
+ +
+ +
); } diff --git a/apps/user/components/language-switch.tsx b/apps/user/components/language-switch.tsx index 69899f8..d6dfacf 100644 --- a/apps/user/components/language-switch.tsx +++ b/apps/user/components/language-switch.tsx @@ -56,7 +56,7 @@ export default function LanguageSwitch() { }} > {languages[locale as keyof typeof languages]} diff --git a/apps/user/components/subscribe/purchase.tsx b/apps/user/components/subscribe/purchase.tsx index 8d75985..59d5482 100644 --- a/apps/user/components/subscribe/purchase.tsx +++ b/apps/user/components/subscribe/purchase.tsx @@ -75,7 +75,6 @@ const Purchase = forwardRef((props, ref) => { queryKey: ['preCreateOrder', subscribe?.id, params.quantity], queryFn: async () => { try { - console.log('123123', subscribe); const { data } = await preCreateOrder({ ...params, subscribe_id: subscribe?.id as number, diff --git a/apps/user/locales/en-US/wallet.json b/apps/user/locales/en-US/wallet.json index 707895f..bf74ee3 100644 --- a/apps/user/locales/en-US/wallet.json +++ b/apps/user/locales/en-US/wallet.json @@ -8,6 +8,7 @@ "giftAmount": "Girt Amount", "referralCode": "Referral Code", "referralDetails": "Referral Details", + "title": "Invite Records", "totalAssets": "Total Assets", "type": { "0": "Type", diff --git a/apps/user/locales/zh-CN/wallet.json b/apps/user/locales/zh-CN/wallet.json index 53df643..b8d0e86 100644 --- a/apps/user/locales/zh-CN/wallet.json +++ b/apps/user/locales/zh-CN/wallet.json @@ -8,6 +8,7 @@ "giftAmount": "赠送金额", "referralCode": "返佣邀请码", "referralDetails": "返佣详情", + "title": "邀请记录", "totalAssets": "资产概览", "type": { "0": "类型", diff --git a/apps/user/services/user/user.ts b/apps/user/services/user/user.ts index 6033aaa..f6f5d46 100644 --- a/apps/user/services/user/user.ts +++ b/apps/user/services/user/user.ts @@ -32,11 +32,17 @@ export async function queryUserAffiliateList( } /** Query User Balance Log GET /v1/public/user/balance_log */ -export async function queryUserBalanceLog(options?: { [key: string]: any }) { +export async function queryUserBalanceLog( + params: API.QueryUserAffiliateListParams, + options?: { [key: string]: any }, +) { return request( '/v1/public/user/balance_log', { method: 'GET', + params: { + ...params, + }, ...(options || {}), }, ); diff --git a/apps/user/utils/request.ts b/apps/user/utils/request.ts index f56d6ad..91c6461 100644 --- a/apps/user/utils/request.ts +++ b/apps/user/utils/request.ts @@ -7,7 +7,6 @@ import { getAuthorization, Logout } from './common'; async function handleError(response: any) { const code = response.data?.code; - console.log(1111111, code); if ([40002, 40003, 40004, 40005].includes(code)) { if (isBrowser()) { const t = await getTranslations('common'); diff --git a/scripts/publish-dev.sh b/scripts/publish-dev.sh index 4b38195..576df9b 100755 --- a/scripts/publish-dev.sh +++ b/scripts/publish-dev.sh @@ -14,10 +14,10 @@ PROJECTS=( ) # Step 1: Install dependencies -#bun install || { -# echo "Dependency installation failed" -# exit 1 -#} +bun install || { + echo "Dependency installation failed" + exit 1 +} # Step 2: Build each project using Turbo for ITEM in "${PROJECTS[@]}"; do diff --git a/scripts/publish.sh b/scripts/publish.sh index 747543f..09e57e9 100755 --- a/scripts/publish.sh +++ b/scripts/publish.sh @@ -33,7 +33,7 @@ for ITEM in "${PROJECTS[@]}"; do cp -r $PROJECT_PATH/.next/static $PROJECT_BUILD_DIR/$PROJECT_PATH/.next/ cp -r $PROJECT_PATH/public $PROJECT_BUILD_DIR/$PROJECT_PATH/ cp -r $PROJECT_PATH/.env.template $PROJECT_BUILD_DIR/$PROJECT_PATH/.env.template - cp -r $PROJECT_PATH/.env $PROJECT_BUILD_DIR/$PROJECT_PATH/.env + cp -f $PROJECT_PATH/.env.prod $PROJECT_BUILD_DIR/$PROJECT_PATH/.env # Generate ecosystem.config.js for the project ECOSYSTEM_CONFIG="$PROJECT_BUILD_DIR/ecosystem.config.js"