探讨
This commit is contained in:
8
.eslintrc.json
Normal file
8
.eslintrc.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"extends": "next/core-web-vitals",
|
||||||
|
"rules": {
|
||||||
|
"@typescript-eslint/no-unused-vars": "warn",
|
||||||
|
"@typescript-eslint/no-explicit-any": "warn"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
140
README.md
140
README.md
@@ -1,3 +1,137 @@
|
|||||||
# yanshi2
|
# 智能农业测试平台
|
||||||
|
|
||||||
yanshi2
|
基于 Next.js 14 (App Router) 和 PostgreSQL 的测试管理平台。
|
||||||
|
|
||||||
|
## 技术栈
|
||||||
|
|
||||||
|
- **前端框架**: Next.js 14+ (App Router)
|
||||||
|
- **语言**: TypeScript
|
||||||
|
- **样式**: Tailwind CSS
|
||||||
|
- **数据库**: PostgreSQL
|
||||||
|
- **ORM**: Prisma
|
||||||
|
- **认证**: NextAuth.js
|
||||||
|
- **表单**: React Hook Form + Zod
|
||||||
|
- **状态管理**: Zustand
|
||||||
|
|
||||||
|
## 项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
hm-smart-agri-test-platform/
|
||||||
|
├── src/ # 源代码目录
|
||||||
|
│ ├── app/ # Next.js App Router
|
||||||
|
│ │ ├── api/ # API 路由
|
||||||
|
│ │ ├── auth/ # 认证相关页面
|
||||||
|
│ │ ├── dashboard/ # 仪表板页面
|
||||||
|
│ │ ├── layout.tsx # 根布局
|
||||||
|
│ │ └── page.tsx # 首页
|
||||||
|
│ ├── components/ # 可复用组件
|
||||||
|
│ │ ├── ui/ # 基础 UI 组件
|
||||||
|
│ │ ├── forms/ # 表单组件
|
||||||
|
│ │ └── layout/ # 布局组件
|
||||||
|
│ ├── lib/ # 工具库
|
||||||
|
│ │ ├── db/ # 数据库配置
|
||||||
|
│ │ ├── utils/ # 工具函数
|
||||||
|
│ │ ├── services/ # 服务层
|
||||||
|
│ │ ├── middleware/ # 中间件
|
||||||
|
│ │ ├── auth/ # 认证相关
|
||||||
|
│ │ └── constants/ # 常量定义
|
||||||
|
│ ├── hooks/ # 自定义 Hooks
|
||||||
|
│ ├── types/ # TypeScript 类型定义
|
||||||
|
│ └── middleware.ts # Next.js 中间件
|
||||||
|
├── prisma/ # Prisma 相关
|
||||||
|
│ └── schema.prisma # 数据库模型
|
||||||
|
├── scripts/ # 脚本文件
|
||||||
|
├── tests/ # 测试文件
|
||||||
|
├── docs/ # 文档目录
|
||||||
|
└── public/ # 静态资源
|
||||||
|
```
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
### 1. 安装依赖
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
# 或
|
||||||
|
yarn install
|
||||||
|
# 或
|
||||||
|
pnpm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 配置环境变量
|
||||||
|
|
||||||
|
复制 `.env.example` 为 `.env.local` 并填写相应的配置:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env.local
|
||||||
|
```
|
||||||
|
|
||||||
|
编辑 `.env.local` 文件,配置数据库连接和其他环境变量。
|
||||||
|
|
||||||
|
### 3. 设置数据库
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 生成 Prisma Client
|
||||||
|
npm run db:generate
|
||||||
|
|
||||||
|
# 推送数据库模式(开发环境)
|
||||||
|
npm run db:push
|
||||||
|
|
||||||
|
# 或使用迁移(生产环境推荐)
|
||||||
|
npm run db:migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 启动开发服务器
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
打开 [http://localhost:3000](http://localhost:3000) 查看应用。
|
||||||
|
|
||||||
|
## 可用脚本
|
||||||
|
|
||||||
|
- `npm run dev` - 启动开发服务器
|
||||||
|
- `npm run build` - 构建生产版本
|
||||||
|
- `npm run start` - 启动生产服务器
|
||||||
|
- `npm run lint` - 运行 ESLint
|
||||||
|
- `npm run format` - 格式化代码
|
||||||
|
- `npm run type-check` - TypeScript 类型检查
|
||||||
|
- `npm run db:generate` - 生成 Prisma Client
|
||||||
|
- `npm run db:push` - 推送数据库模式
|
||||||
|
- `npm run db:migrate` - 运行数据库迁移
|
||||||
|
- `npm run db:studio` - 打开 Prisma Studio
|
||||||
|
|
||||||
|
## 数据库设计
|
||||||
|
|
||||||
|
### 核心表
|
||||||
|
|
||||||
|
- **Users** - 用户表
|
||||||
|
- **Projects** - 项目表
|
||||||
|
- **ProjectMembers** - 项目成员表
|
||||||
|
- **TestCases** - 测试用例表
|
||||||
|
- **TestRuns** - 测试执行表
|
||||||
|
- **TestResults** - 测试结果表
|
||||||
|
|
||||||
|
详细设计请查看 `prisma/schema.prisma` 文件。
|
||||||
|
|
||||||
|
## 开发规范
|
||||||
|
|
||||||
|
- 使用 TypeScript 严格模式
|
||||||
|
- 遵循 ESLint 规则
|
||||||
|
- 使用 Prettier 格式化代码
|
||||||
|
- 组件使用 PascalCase
|
||||||
|
- 函数/变量使用 camelCase
|
||||||
|
- 常量使用 UPPER_SNAKE_CASE
|
||||||
|
|
||||||
|
## 下一步
|
||||||
|
|
||||||
|
1. 配置数据库连接
|
||||||
|
2. 运行数据库迁移
|
||||||
|
3. 实现用户认证功能
|
||||||
|
4. 开发核心业务功能
|
||||||
|
|
||||||
|
## 许可证
|
||||||
|
|
||||||
|
MIT
|
||||||
|
|
||||||
|
|||||||
28
middleware.ts
Normal file
28
middleware.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { NextResponse } from 'next/server'
|
||||||
|
import type { NextRequest } from 'next/server'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 中间件:主要用于 API 路由的认证检查
|
||||||
|
* 客户端的 token 验证在页面组件中处理(因为 middleware 无法访问 localStorage)
|
||||||
|
*/
|
||||||
|
export function middleware(request: NextRequest) {
|
||||||
|
const { pathname } = request.nextUrl
|
||||||
|
|
||||||
|
// API 路由的认证检查在各自的 route.ts 中处理
|
||||||
|
// 页面路由的认证检查在客户端组件中处理(使用 useAuth hook)
|
||||||
|
|
||||||
|
return NextResponse.next()
|
||||||
|
}
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
matcher: [
|
||||||
|
/*
|
||||||
|
* Match all request paths except for the ones starting with:
|
||||||
|
* - api (API routes)
|
||||||
|
* - _next/static (static files)
|
||||||
|
* - _next/image (image optimization files)
|
||||||
|
* - favicon.ico (favicon file)
|
||||||
|
*/
|
||||||
|
'/((?!api|_next/static|_next/image|favicon.ico).*)',
|
||||||
|
],
|
||||||
|
}
|
||||||
6
next-env.d.ts
vendored
Normal file
6
next-env.d.ts
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/// <reference types="next" />
|
||||||
|
/// <reference types="next/image-types/global" />
|
||||||
|
import "./.next/dev/types/routes.d.ts";
|
||||||
|
|
||||||
|
// NOTE: This file should not be edited
|
||||||
|
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||||
20
next.config.ts
Normal file
20
next.config.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import type { NextConfig } from 'next'
|
||||||
|
|
||||||
|
const nextConfig: NextConfig = {
|
||||||
|
reactStrictMode: true,
|
||||||
|
poweredByHeader: false,
|
||||||
|
images: {
|
||||||
|
unoptimized: false,
|
||||||
|
},
|
||||||
|
async rewrites() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
source: '/openapi.json',
|
||||||
|
destination: '/api/openapi',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default nextConfig
|
||||||
|
|
||||||
1
openapi.json
Normal file
1
openapi.json
Normal file
File diff suppressed because one or more lines are too long
10152
package-lock.json
generated
Normal file
10152
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
64
package.json
Normal file
64
package.json
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
{
|
||||||
|
"name": "hm-smart-agri-test-platform",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "next lint",
|
||||||
|
"db:generate": "prisma generate",
|
||||||
|
"db:push": "prisma db push",
|
||||||
|
"db:migrate": "prisma migrate dev",
|
||||||
|
"db:studio": "prisma studio",
|
||||||
|
"db:seed": "tsx prisma/seed.ts",
|
||||||
|
"format": "prettier --write .",
|
||||||
|
"type-check": "tsc --noEmit"
|
||||||
|
},
|
||||||
|
"prisma": {
|
||||||
|
"seed": "tsx prisma/seed.ts"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@dnd-kit/core": "^6.3.1",
|
||||||
|
"@dnd-kit/sortable": "^10.0.0",
|
||||||
|
"@dnd-kit/utilities": "^3.2.2",
|
||||||
|
"@hookform/resolvers": "^3.3.4",
|
||||||
|
"@prisma/client": "^5.16.0",
|
||||||
|
"@types/jsonwebtoken": "^9.0.10",
|
||||||
|
"bcryptjs": "^2.4.3",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"date-fns": "^3.6.0",
|
||||||
|
"jsonwebtoken": "^9.0.3",
|
||||||
|
"next": "^16.0.10",
|
||||||
|
"next-auth": "^4.24.0",
|
||||||
|
"next-themes": "^0.4.6",
|
||||||
|
"prisma": "^5.16.0",
|
||||||
|
"react": "^19.2.3",
|
||||||
|
"react-dom": "^19.2.3",
|
||||||
|
"react-hook-form": "^7.51.0",
|
||||||
|
"recharts": "^3.6.0",
|
||||||
|
"redis": "^5.10.0",
|
||||||
|
"swagger-parser": "^10.0.3",
|
||||||
|
"swagger-ui-react": "^5.31.0",
|
||||||
|
"tailwind-merge": "^2.4.0",
|
||||||
|
"xlsx": "^0.18.5",
|
||||||
|
"zod": "^3.23.0",
|
||||||
|
"zustand": "^4.5.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@tailwindcss/forms": "^0.5.7",
|
||||||
|
"@types/bcryptjs": "^2.4.6",
|
||||||
|
"@types/node": "^20.19.25",
|
||||||
|
"@types/react": "^19",
|
||||||
|
"@types/react-dom": "^19",
|
||||||
|
"@types/xlsx": "^0.0.35",
|
||||||
|
"autoprefixer": "^10.4.20",
|
||||||
|
"eslint": "^9",
|
||||||
|
"eslint-config-next": "^16.0.6",
|
||||||
|
"postcss": "^8.4.40",
|
||||||
|
"prettier": "^3.3.0",
|
||||||
|
"tailwindcss": "^3.4.0",
|
||||||
|
"tsx": "^4.21.0",
|
||||||
|
"typescript": "^5"
|
||||||
|
}
|
||||||
|
}
|
||||||
20
tailwind.config.ts
Normal file
20
tailwind.config.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import type { Config } from 'tailwindcss'
|
||||||
|
|
||||||
|
const config: Config = {
|
||||||
|
darkMode: 'class',
|
||||||
|
content: [
|
||||||
|
'./src/pages/**/*.{js,ts,jsx,tsx,mdx}',
|
||||||
|
'./src/components/**/*.{js,ts,jsx,tsx,mdx}',
|
||||||
|
'./src/app/**/*.{js,ts,jsx,tsx,mdx}',
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
background: 'var(--background)',
|
||||||
|
foreground: 'var(--foreground)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [require('@tailwindcss/forms')],
|
||||||
|
}
|
||||||
|
export default config
|
||||||
35
tsconfig.json
Normal file
35
tsconfig.json
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2020",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"incremental": true,
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "next"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"next-env.d.ts",
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx",
|
||||||
|
".next/types/**/*.ts",
|
||||||
|
".next/dev/types/**/*.ts",
|
||||||
|
"**/*.mts"
|
||||||
|
],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user