diff --git a/frontend/admin-web/.dockerignore b/frontend/admin-web/.dockerignore new file mode 100644 index 0000000..fe67d7c --- /dev/null +++ b/frontend/admin-web/.dockerignore @@ -0,0 +1,54 @@ +# 依赖目录 +node_modules +.pnp +.pnp.js + +# 构建产物 +.next +out +build +dist + +# 测试 +coverage +.nyc_output + +# 开发环境 +.env.local +.env.development +.env.development.local +.env.test.local + +# 编辑器和IDE +.idea +.vscode +*.swp +*.swo +*~ + +# 系统文件 +.DS_Store +Thumbs.db + +# Git +.git +.gitignore + +# Docker +Dockerfile +docker-compose*.yml +.dockerignore + +# 日志 +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# 文档 +README.md +CHANGELOG.md +docs + +# 其他 +.claude diff --git a/frontend/admin-web/.gitignore b/frontend/admin-web/.gitignore new file mode 100644 index 0000000..33ec8cb --- /dev/null +++ b/frontend/admin-web/.gitignore @@ -0,0 +1,47 @@ +# dependencies +/node_modules +/.pnp +.pnp.js +.yarn/install-state.gz + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local +.env.local + +# Claude Code +.claude/ + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + +# IDE +.idea/ +.vscode/ +*.swp +*.swo + +# OS +Thumbs.db diff --git a/frontend/admin-web/next.config.ts b/frontend/admin-web/next.config.ts new file mode 100644 index 0000000..c0ea6e9 --- /dev/null +++ b/frontend/admin-web/next.config.ts @@ -0,0 +1,25 @@ +import type { NextConfig } from 'next'; + +const nextConfig: NextConfig = { + output: 'standalone', + reactStrictMode: true, + images: { + remotePatterns: [ + { + protocol: 'https', + hostname: '**', + }, + ], + }, + async redirects() { + return [ + { + source: '/', + destination: '/dashboard', + permanent: false, + }, + ]; + }, +}; + +export default nextConfig; diff --git a/frontend/admin-web/package.json b/frontend/admin-web/package.json new file mode 100644 index 0000000..4f173fe --- /dev/null +++ b/frontend/admin-web/package.json @@ -0,0 +1,39 @@ +{ + "name": "genex-admin-web", + "version": "1.0.0", + "private": true, + "description": "Genex 券金融平台管理后台 - Admin Web", + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "lint:fix": "next lint --fix", + "format": "prettier --write \"src/**/*.{ts,tsx,css,json}\"", + "format:check": "prettier --check \"src/**/*.{ts,tsx,css,json}\"", + "type-check": "tsc --noEmit" + }, + "dependencies": { + "@reduxjs/toolkit": "^2.3.0", + "@tanstack/react-query": "^5.62.16", + "@tanstack/react-table": "^8.20.0", + "axios": "^1.7.9", + "clsx": "^2.1.1", + "dayjs": "^1.11.13", + "next": "15.1.11", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-redux": "^9.2.0", + "recharts": "^2.15.0", + "zustand": "^5.0.3" + }, + "devDependencies": { + "@types/node": "^22.10.7", + "@types/react": "^18.3.18", + "@types/react-dom": "^18.3.5", + "eslint": "^9.18.0", + "eslint-config-next": "^15.1.6", + "prettier": "^3.4.2", + "typescript": "5.9.3" + } +} diff --git a/frontend/admin-web/public/favicon.ico b/frontend/admin-web/public/favicon.ico new file mode 100644 index 0000000..e69de29 diff --git a/frontend/admin-web/src/app/api/health/route.ts b/frontend/admin-web/src/app/api/health/route.ts new file mode 100644 index 0000000..f02d9ad --- /dev/null +++ b/frontend/admin-web/src/app/api/health/route.ts @@ -0,0 +1,15 @@ +import { NextResponse } from 'next/server'; + +/** + * 健康检查 API + * + * Docker healthcheck 和负载均衡器使用 + * GET /api/health + */ +export async function GET() { + return NextResponse.json({ + status: 'ok', + service: 'genex-admin-web', + timestamp: new Date().toISOString(), + }); +} diff --git a/frontend/admin-web/src/app/globals.css b/frontend/admin-web/src/app/globals.css new file mode 100644 index 0000000..d2a0f2c --- /dev/null +++ b/frontend/admin-web/src/app/globals.css @@ -0,0 +1,50 @@ +@import '../styles/design-tokens.css'; + +*, +*::before, +*::after { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +html { + font-family: var(--font-family); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +body { + background: var(--color-bg); + color: var(--color-text-primary); + min-height: 100vh; +} + +a { + color: var(--color-text-link); + text-decoration: none; +} + +::selection { + background: var(--color-primary-container); + color: var(--color-primary-dark); +} + +/* Scrollbar */ +::-webkit-scrollbar { + width: 6px; + height: 6px; +} + +::-webkit-scrollbar-track { + background: transparent; +} + +::-webkit-scrollbar-thumb { + background: var(--color-gray-300); + border-radius: var(--radius-full); +} + +::-webkit-scrollbar-thumb:hover { + background: var(--color-gray-400); +} diff --git a/frontend/admin-web/src/app/layout.tsx b/frontend/admin-web/src/app/layout.tsx new file mode 100644 index 0000000..a00989d --- /dev/null +++ b/frontend/admin-web/src/app/layout.tsx @@ -0,0 +1,25 @@ +import type { Metadata } from 'next'; +import { Providers } from './providers'; +import './globals.css'; + +export const metadata: Metadata = { + title: 'Genex Admin - 券金融平台管理后台', + description: 'Genex 券金融平台运营管理系统', + icons: { + icon: '/favicon.ico', + }, +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + + {children} + + + ); +} diff --git a/frontend/admin-web/src/app/page.tsx b/frontend/admin-web/src/app/page.tsx new file mode 100644 index 0000000..63562ed --- /dev/null +++ b/frontend/admin-web/src/app/page.tsx @@ -0,0 +1,7 @@ +/** + * 根页面 - 自动重定向到 /dashboard + * 重定向逻辑在 next.config.ts 中配置 + */ +export default function Home() { + return null; +} diff --git a/frontend/admin-web/src/app/providers.tsx b/frontend/admin-web/src/app/providers.tsx new file mode 100644 index 0000000..792b2ab --- /dev/null +++ b/frontend/admin-web/src/app/providers.tsx @@ -0,0 +1,16 @@ +'use client'; + +import React from 'react'; + +/** + * 全局 Providers 包装 + * + * 后续在此添加: + * - Redux Provider (RTK) + * - React Query Provider + * - Theme Provider + * - Auth Provider + */ +export function Providers({ children }: { children: React.ReactNode }) { + return <>{children}; +} diff --git a/frontend/admin-web/tsconfig.json b/frontend/admin-web/tsconfig.json new file mode 100644 index 0000000..84fdd20 --- /dev/null +++ b/frontend/admin-web/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [{ "name": "next" }], + "paths": { + "@/*": ["./src/*"] + }, + "baseUrl": ".", + "target": "ES2017" + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +}