refactor: 替换项目中的"yudao"为"AIOTAGRO",并清理相关配置文件

This commit is contained in:
2025-10-04 18:38:56 +08:00
parent 2292615a3b
commit dbccc1078a
130 changed files with 4680 additions and 484 deletions

652
docs/安全文档.md Normal file
View File

@@ -0,0 +1,652 @@
# 安全文档
## 安全概述
AIOTAGRO 管理系统安全文档涵盖系统安全设计、安全配置、安全审计、应急响应等安全相关事项。本文档为开发团队和运维团队提供完整的安全指南。
## 安全架构
### 1. 安全设计原则
#### 最小权限原则
- 每个组件只拥有完成其功能所需的最小权限
- 数据库用户按功能分离权限
- 文件系统权限严格控制
#### 纵深防御
- 多层安全防护机制
- 网络层、应用层、数据层全面防护
- 安全监控和告警机制
#### 安全默认配置
- 默认关闭不必要的服务
- 默认启用安全功能
- 默认使用强加密算法
### 2. 安全组件
#### 前端安全
- CSP (Content Security Policy) 策略
- XSS 防护机制
- CSRF 防护机制
- 安全头配置
#### 后端安全
- 输入验证和过滤
- SQL 注入防护
- 文件上传安全
- 会话安全管理
#### 基础设施安全
- 网络安全配置
- 系统安全加固
- 访问控制机制
- 日志审计系统
## 安全配置
### 1. 前端安全配置
#### CSP 配置
```javascript
// vite.config.js
export default defineConfig({
// CSP 配置
server: {
headers: {
'Content-Security-Policy': `
default-src 'self';
script-src 'self' 'unsafe-inline' 'unsafe-eval';
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
font-src 'self';
connect-src 'self' https://api.aiotagro.com;
frame-ancestors 'none';
base-uri 'self';
form-action 'self'
`.replace(/\s+/g, ' ').trim()
}
}
})
```
#### 安全头配置
```nginx
# Nginx 安全头配置
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
add_header Referrer-Policy "strict-origin-when-cross-origin";
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()";
```
### 2. 应用安全配置
#### 输入验证
```javascript
// 输入验证工具
export const validateInput = {
// 邮箱验证
email: (email) => {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
return regex.test(email)
},
// 手机号验证
phone: (phone) => {
const regex = /^1[3-9]\d{9}$/
return regex.test(phone)
},
// 密码强度验证
password: (password) => {
return password.length >= 8 &&
/[A-Z]/.test(password) &&
/[a-z]/.test(password) &&
/[0-9]/.test(password)
},
// XSS 防护
sanitize: (input) => {
return input.replace(/[<>"'&]/g, (char) => {
const escapeMap = {
'<': '<',
'>': '>',
'"': '"',
"'": '&#x27;',
'&': '&'
}
return escapeMap[char] || char
})
}
}
```
#### 会话安全
```javascript
// 会话管理
export const sessionManager = {
// 生成安全的会话 ID
generateSessionId: () => {
return crypto.randomBytes(32).toString('hex')
},
// 设置安全 Cookie
setSecureCookie: (name, value, options = {}) => {
const defaults = {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict',
maxAge: 24 * 60 * 60 * 1000 // 24小时
}
document.cookie = `${name}=${value}; ${Object.entries({...defaults, ...options})
.map(([key, val]) => `${key}=${val}`)
.join('; ')}`
},
// 验证会话
validateSession: (sessionId) => {
// 验证会话有效性和权限
return true
}
}
```
### 3. 基础设施安全
#### 网络安全配置
```nginx
# 网络安全配置
# 限制请求大小
client_max_body_size 10m;
# 限制请求速率
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
# IP 黑名单
geo $blacklist {
default 0;
192.168.1.100 1;
10.0.0.50 1;
}
server {
# 黑名单处理
if ($blacklist) {
return 403;
}
# API 速率限制
location /api/ {
limit_req zone=api burst=20 nodelay;
# ...
}
# 登录速率限制
location /api/auth/login {
limit_req zone=login burst=5 nodelay;
# ...
}
}
```
#### 系统安全加固
```bash
#!/bin/bash
# system-hardening.sh
echo "开始系统安全加固..."
# 1. 更新系统
sudo apt update && sudo apt upgrade -y
# 2. 配置防火墙
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw --force enable
# 3. 禁用不必要的服务
sudo systemctl disable apache2
sudo systemctl disable mysql
sudo systemctl disable postgresql
# 4. 配置 SSH 安全
sudo sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sudo sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/#MaxAuthTries 6/MaxAuthTries 3/' /etc/ssh/sshd_config
sudo systemctl restart sshd
# 5. 配置文件权限
sudo chmod 600 /etc/ssl/private/aiotagro.key
sudo chmod 644 /etc/ssl/certs/aiotagro.crt
sudo chown -R www-data:www-data /var/www/aiotagro
# 6. 配置日志审计
sudo apt install auditd
sudo auditctl -e 1
sudo systemctl enable auditd
echo "系统安全加固完成"
```
## 安全审计
### 1. 代码安全审计
#### 静态代码分析
```yaml
# .github/workflows/code-scan.yml
name: Code Security Scan
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
schedule:
- cron: '0 2 * * 1' # 每周一凌晨2点
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Run ESLint security rules
run: |
npx eslint . --ext .js,.vue,.ts --config .eslintrc.security.js
- name: Run SAST scan
uses: github/codeql-action/init@v2
with:
languages: javascript
queries: security-extended
- name: Run SAST analysis
uses: github/codeql-action/analyze@v2
- name: Run dependency check
uses: dependency-check/Dependency-Check_Action@main
with:
project: 'AIOTAGRO Frontend'
path: '.'
format: 'HTML'
- name: Upload security report
uses: actions/upload-artifact@v3
with:
name: security-reports
path: reports/
```
#### 安全规则配置
```javascript
// .eslintrc.security.js
module.exports = {
extends: [
'eslint:recommended',
'plugin:security/recommended'
],
plugins: ['security'],
rules: {
'security/detect-object-injection': 'error',
'security/detect-possible-timing-attacks': 'error',
'security/detect-non-literal-require': 'error',
'security/detect-non-literal-fs-filename': 'error',
'security/detect-eval-with-expression': 'error',
'security/detect-pseudoRandomBytes': 'error',
'security/detect-unsafe-regex': 'error'
}
}
```
### 2. 依赖安全审计
#### 依赖安全检查
```json
{
"scripts": {
"security:audit": "npm audit --audit-level moderate",
"security:fix": "npm audit fix",
"security:outdated": "npm outdated",
"security:check": "npx snyk test"
}
}
```
#### 自动化安全更新
```yaml
# .github/workflows/security-update.yml
name: Security Updates
on:
schedule:
- cron: '0 3 * * 0' # 每周日凌晨3点
workflow_dispatch:
jobs:
security-update:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Check for security vulnerabilities
run: npm audit --audit-level moderate
- name: Update dependencies
if: always()
run: |
npm update --save
npm audit fix
- name: Create Pull Request
if: always()
uses: peter-evans/create-pull-request@v4
with:
title: '安全依赖更新'
body: '自动安全依赖更新'
branch: 'security-updates'
commit-message: '更新安全依赖'
```
### 3. 运行时安全监控
#### 安全事件监控
```javascript
// 安全监控工具
export const securityMonitor = {
// 记录安全事件
logSecurityEvent: (event) => {
const securityLog = {
timestamp: new Date().toISOString(),
event: event.type,
severity: event.severity || 'info',
userAgent: navigator.userAgent,
url: window.location.href,
details: event.details
}
// 发送到安全日志服务
fetch('/api/security/log', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(securityLog)
}).catch(console.error)
},
// 检测异常行为
detectAnomalies: () => {
// 检测异常请求模式
// 检测可疑用户行为
// 检测安全策略违规
},
// 实时告警
alert: (message, level = 'warning') => {
console[level](`[安全告警] ${message}`)
// 发送到告警系统
}
}
// 监控全局错误
window.addEventListener('error', (event) => {
securityMonitor.logSecurityEvent({
type: 'javascript_error',
severity: 'error',
details: {
message: event.message,
filename: event.filename,
lineno: event.lineno,
colno: event.colno
}
})
})
// 监控未处理的 Promise 拒绝
window.addEventListener('unhandledrejection', (event) => {
securityMonitor.logSecurityEvent({
type: 'unhandled_promise_rejection',
severity: 'error',
details: {
reason: event.reason
}
})
})
```
## 应急响应
### 1. 安全事件分类
#### 事件严重等级
| 等级 | 描述 | 响应时间 | 处理流程 |
|------|------|----------|----------|
| 紧急 | 系统被入侵,数据泄露 | 立即响应 | 隔离系统,通知管理层 |
| 高危 | 发现严重漏洞 | 2小时内响应 | 修复漏洞,安全审计 |
| 中危 | 发现中等风险漏洞 | 24小时内响应 | 制定修复计划 |
| 低危 | 发现低风险问题 | 72小时内响应 | 定期修复 |
### 2. 应急响应流程
#### 安全事件响应脚本
```bash
#!/bin/bash
# security-incident-response.sh
set -e
INCIDENT_TYPE="$1"
SEVERITY="$2"
echo "开始安全事件应急响应..."
echo "事件类型: $INCIDENT_TYPE"
echo "严重等级: $SEVERITY"
# 记录事件
timestamp=$(date +%Y%m%d_%H%M%S)
echo "[$timestamp] 安全事件: $INCIDENT_TYPE ($SEVERITY)" >> /var/log/security/incidents.log
case $SEVERITY in
"critical")
echo "执行紧急响应流程..."
# 1. 隔离受影响系统
echo "隔离系统..."
sudo systemctl stop nginx
sudo ufw deny http
sudo ufw deny https
# 2. 备份当前状态
echo "备份系统状态..."
tar -czf "/opt/aiotagro/forensics/incident_$timestamp.tar.gz" \
/var/log/nginx \
/var/log/auth.log \
/etc/nginx
# 3. 通知相关人员
echo "通知安全团队..."
# send_email "security@aiotagro.com" "安全事件告警" "发现紧急安全事件"
# 4. 启动取证调查
echo "启动取证调查..."
;;
"high")
echo "执行高危响应流程..."
# 1. 限制访问
echo "限制访问..."
sudo nginx -t && sudo systemctl reload nginx
# 2. 安全审计
echo "执行安全审计..."
npm audit
# 运行安全扫描工具
# 3. 修复漏洞
echo "修复安全漏洞..."
;;
*)
echo "执行标准响应流程..."
;;
esac
echo "安全事件响应完成"
```
### 3. 恢复流程
#### 系统恢复检查清单
```bash
#!/bin/bash
# security-recovery-checklist.sh
echo "=== 安全恢复检查清单 ==="
# 1. 验证系统完整性
echo "1. 验证系统完整性..."
checksum_original="$(sha256sum /opt/aiotagro/frontend/package.json | cut -d' ' -f1)"
checksum_current="$(sha256sum /opt/aiotagro/frontend/package.json | cut -d' ' -f1)"
if [ "$checksum_original" = "$checksum_current" ]; then
echo "✓ 系统文件完整性验证通过"
else
echo "✗ 系统文件可能被篡改"
fi
# 2. 检查安全配置
echo "2. 检查安全配置..."
nginx_test=$(sudo nginx -t 2>&1)
if echo "$nginx_test" | grep -q "test is successful"; then
echo "✓ Nginx 配置验证通过"
else
echo "✗ Nginx 配置存在错误"
fi
# 3. 验证证书状态
echo "3. 验证证书状态..."
if openssl x509 -checkend 86400 -noout -in /etc/ssl/certs/aiotagro.crt; then
echo "✓ SSL 证书有效"
else
echo "✗ SSL 证书即将过期或无效"
fi
# 4. 检查服务状态
echo "4. 检查服务状态..."
services=("nginx" "node-exporter")
for service in "${services[@]}"; do
if systemctl is-active --quiet "$service"; then
echo "✓ $service 服务运行正常"
else
echo "✗ $service 服务异常"
fi
done
# 5. 安全扫描
echo "5. 执行安全扫描..."
# 运行安全扫描工具
echo "安全恢复检查完成"
```
## 安全培训
### 1. 开发安全规范
#### 代码安全规范
```markdown
# AIOTAGRO 开发安全规范
## 1. 输入验证
- 所有用户输入必须验证
- 使用白名单验证策略
- 防范 XSS、SQL 注入等攻击
## 2. 身份认证
- 使用强密码策略
- 实现多因素认证
- 会话超时机制
## 3. 数据保护
- 敏感数据加密存储
- 传输层使用 TLS
- 最小化数据收集
## 4. 错误处理
- 不暴露系统信息
- 记录安全相关错误
- 统一的错误处理机制
## 5. 依赖管理
- 定期更新依赖
- 使用可信的包源
- 扫描依赖的安全漏洞
```
### 2. 运维安全规范
#### 运维安全清单
```markdown
# AIOTAGRO 运维安全清单
## 系统安全
- [ ] 定期系统更新
- [ ] 防火墙配置检查
- [ ] 用户权限审核
- [ ] 日志审计启用
## 应用安全
- [ ] 安全头配置检查
- [ ] SSL/TLS 配置验证
- [ ] 应用漏洞扫描
- [ ] 备份恢复测试
## 网络安全
- [ ] 网络隔离检查
- [ ] 访问控制验证
- [ ] 入侵检测配置
- [ ] DDoS 防护启用
## 数据安全
- [ ] 数据加密验证
- [ ] 访问日志审计
- [ ] 数据备份验证
- [ ] 隐私保护检查
```
通过以上安全配置和流程AIOTAGRO 管理系统可以实现全面的安全防护,确保系统稳定可靠运行。

562
docs/开发文档.md Normal file
View File

@@ -0,0 +1,562 @@
# 开发文档
## 开发环境搭建
### 环境要求
- **Node.js**: 18.0.0 或更高版本
- **pnpm**: 8.0.0 或更高版本
- **Git**: 2.0.0 或更高版本
### 安装步骤
1. **安装 Node.js**
```bash
# 下载并安装 Node.js 18+
# 验证安装
node --version
npm --version
```
2. **安装 pnpm**
```bash
# 使用 npm 安装 pnpm
npm install -g pnpm
# 验证安装
pnpm --version
```
3. **克隆项目**
```bash
git clone https://github.com/vbenjs/vue-vben-admin.git
cd vue-vben-admin
```
4. **安装依赖**
```bash
# 安装项目依赖
pnpm install
```
5. **启动开发服务器**
```bash
# 启动 Ant Design 版本
pnpm dev:antd
# 启动 Element Plus 版本
pnpm dev:ele
# 启动 Naive UI 版本
pnpm dev:naive
```
## 项目结构说明
### 目录结构详解
```
yudao-ui-admin-vben/
├── apps/ # 应用目录
│ ├── web-antd/ # Ant Design 版本
│ │ ├── src/ # 源代码
│ │ │ ├── api/ # API 接口
│ │ │ ├── components/ # 组件
│ │ │ ├── layouts/ # 布局
│ │ │ ├── router/ # 路由
│ │ │ ├── store/ # 状态管理
│ │ │ ├── utils/ # 工具函数
│ │ │ └── views/ # 页面视图
│ │ └── package.json # 应用配置
│ ├── web-ele/ # Element Plus 版本
│ ├── web-naive/ # Naive UI 版本
│ └── backend-mock/ # 后端模拟服务
├── packages/ # 共享包目录
│ ├── @core/ # 核心功能
│ ├── constants/ # 常量定义
│ ├── effects/ # 副作用管理
│ ├── icons/ # 图标库
│ ├── locales/ # 国际化
│ ├── stores/ # 状态管理
│ ├── styles/ # 样式文件
│ ├── types/ # 类型定义
│ └── utils/ # 工具函数
└── internal/ # 内部配置
├── lint-configs/ # 代码规范
├── tailwind-config/ # Tailwind 配置
├── tsconfig/ # TypeScript 配置
└── vite-config/ # Vite 配置
```
### 核心包说明
#### @core 包
- 基础组件封装
- 工具函数集合
- 类型定义扩展
#### stores 包
- 全局状态管理
- 用户信息存储
- 应用配置管理
#### utils 包
- 数据处理工具
- 日期时间工具
- 表单验证工具
## 开发规范
### 代码规范
#### 1. 命名规范
- **文件命名**: 使用 kebab-case (例如: user-info.vue)
- **组件命名**: 使用 PascalCase (例如: UserInfo)
- **变量命名**: 使用 camelCase (例如: userName)
- **常量命名**: 使用 UPPER_SNAKE_CASE (例如: API_BASE_URL)
#### 2. 组件规范
```typescript
// 组件结构示例
<script setup lang="ts">
// 导入
import { ref, computed } from 'vue'
import { useUserStore } from '@/stores/user'
// 类型定义
interface Props {
userId: number
userName: string
}
// Props 定义
const props = defineProps<Props>()
// 状态管理
const userStore = useUserStore()
const loading = ref(false)
// 计算属性
const fullName = computed(() => `${props.userName} (${props.userId})`)
// 方法
const handleSubmit = async () => {
loading.value = true
try {
await userStore.updateUser(props.userId, { name: props.userName })
} finally {
loading.value = false
}
}
</script>
<template>
<div class="user-info">
<h3>{{ fullName }}</h3>
<button :disabled="loading" @click="handleSubmit">
{{ loading ? '保存中...' : '保存' }}
</button>
</div>
</template>
<style scoped>
.user-info {
padding: 16px;
}
</style>
```
#### 3. API 调用规范
```typescript
// api/user.ts
import { request } from '@/utils/request'
export interface User {
id: number
name: string
email: string
}
export const userApi = {
// 获取用户列表
getUsers: (params: { page: number; size: number }) => {
return request.get<{ list: User[]; total: number }>('/api/users', { params })
},
// 创建用户
createUser: (data: Omit<User, 'id'>) => {
return request.post<User>('/api/users', data)
},
// 更新用户
updateUser: (id: number, data: Partial<User>) => {
return request.put<User>(`/api/users/${id}`, data)
},
// 删除用户
deleteUser: (id: number) => {
return request.delete(`/api/users/${id}`)
}
}
```
### 样式规范
#### 1. CSS 类命名
- 使用 BEM 命名规范
- 避免使用全局样式
- 优先使用 Tailwind CSS
```css
/* BEM 示例 */
.user-list {}
.user-list__item {}
.user-list__item--active {}
.user-list__item__avatar {}
```
#### 2. Tailwind CSS 使用
```vue
<template>
<div class="p-4 bg-white rounded-lg shadow-sm">
<h3 class="text-lg font-semibold text-gray-900 mb-4">用户信息</h3>
<div class="space-y-3">
<div class="flex items-center space-x-3">
<span class="text-sm text-gray-500 w-20">姓名:</span>
<span class="text-sm text-gray-900">{{ user.name }}</span>
</div>
</div>
</div>
</template>
```
## 功能开发指南
### 1. 新增页面
#### 步骤 1: 创建页面组件
```bash
# 在 apps/web-antd/src/views/ 下创建页面目录
mkdir -p apps/web-antd/src/views/user-management
```
#### 步骤 2: 创建页面组件
```vue
<!-- apps/web-antd/src/views/user-management/index.vue -->
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { userApi } from '@/api/user'
interface User {
id: number
name: string
email: string
}
const users = ref<User[]>([])
const loading = ref(false)
const loadUsers = async () => {
loading.value = true
try {
const response = await userApi.getUsers({ page: 1, size: 10 })
users.value = response.data.list
} finally {
loading.value = false
}
}
onMounted(() => {
loadUsers()
})
</script>
<template>
<div class="user-management">
<h1>用户管理</h1>
<div v-if="loading">加载中...</div>
<div v-else>
<table>
<thead>
<tr>
<th>ID</th>
<th>姓名</th>
<th>邮箱</th>
</tr>
</thead>
<tbody>
<tr v-for="user in users" :key="user.id">
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.email }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<style scoped>
.user-management {
padding: 20px;
}
</style>
```
#### 步骤 3: 配置路由
```typescript
// apps/web-antd/src/router/routes.ts
import type { RouteRecordRaw } from 'vue-router'
export const routes: RouteRecordRaw[] = [
// ... 其他路由
{
path: '/user-management',
name: 'UserManagement',
component: () => import('@/views/user-management/index.vue'),
meta: {
title: '用户管理',
requiresAuth: true
}
}
]
```
### 2. 新增组件
#### 创建可复用组件
```vue
<!-- apps/web-antd/src/components/UserAvatar.vue -->
<script setup lang="ts">
interface Props {
user: {
name: string
avatar?: string
}
size?: 'small' | 'medium' | 'large'
}
const props = withDefaults(defineProps<Props>(), {
size: 'medium'
})
const sizeMap = {
small: 'w-8 h-8',
medium: 'w-12 h-12',
large: 'w-16 h-16'
}
</script>
<template>
<div class="user-avatar flex items-center space-x-3">
<img
v-if="user.avatar"
:src="user.avatar"
:alt="user.name"
:class="['rounded-full', sizeMap[size]]"
/>
<div
v-else
:class="['bg-gray-200 rounded-full flex items-center justify-center', sizeMap[size]]"
>
<span class="text-gray-600 font-medium">{{ user.name.charAt(0) }}</span>
</div>
<span class="text-gray-900 font-medium">{{ user.name }}</span>
</div>
</template>
<style scoped>
.user-avatar {
display: inline-flex;
align-items: center;
}
</style>
```
## 开发计划
### 第一阶段:基础功能开发 (1-2周)
#### 任务清单
- [x] 项目环境搭建
- [x] 基础架构配置
- [x] 用户登录功能
- [x] 权限管理系统
- [x] 基础布局组件
#### 技术要点
- Vue3 Composition API 使用
- TypeScript 类型定义
- Pinia 状态管理
- Vue Router 路由配置
### 第二阶段:业务功能开发 (2-3周)
#### 任务清单
- [x] 用户管理模块
- [x] 角色管理模块
- [x] 菜单管理模块
- [x] 系统设置模块
- [x] 数据表格组件
#### 技术要点
- 表单验证处理
- 表格数据展示
- 分页查询优化
- 文件上传下载
### 第三阶段:优化完善 (1周)
#### 任务清单
- [x] 性能优化
- [x] 代码重构
- [x] 测试用例编写
- [x] 文档完善
#### 技术要点
- 代码分割优化
- 懒加载实现
- 单元测试覆盖
- 文档自动生成
## 常见问题解决
### 1. 依赖安装问题
**问题**: pnpm install 失败
**解决方案**:
```bash
# 清理缓存
pnpm store prune
# 重新安装
pnpm install --force
```
### 2. 类型检查错误
**问题**: TypeScript 类型错误
**解决方案**:
```bash
# 检查类型错误
pnpm type-check
# 自动修复
pnpm lint:fix
```
### 3. 构建失败
**问题**: 生产构建失败
**解决方案**:
```bash
# 清理构建缓存
pnpm clean
# 重新构建
pnpm build
```
## 测试指南
### 单元测试
```typescript
// __tests__/user.spec.ts
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import UserInfo from '@/components/UserInfo.vue'
describe('UserInfo', () => {
it('renders user name correctly', () => {
const wrapper = mount(UserInfo, {
props: {
user: {
name: '张三',
email: 'zhangsan@example.com'
}
}
})
expect(wrapper.text()).toContain('张三')
})
})
```
### E2E 测试
```typescript
// __tests__/e2e/user.spec.ts
import { test, expect } from '@playwright/test'
test('user login flow', async ({ page }) => {
await page.goto('/login')
await page.fill('[data-testid="username"]', 'admin')
await page.fill('[data-testid="password"]', '123456')
await page.click('[data-testid="login-btn"]')
await expect(page).toHaveURL('/dashboard')
})
```
## 部署指南
### 开发环境部署
```bash
# 启动开发服务器
pnpm dev:antd
# 访问地址
http://localhost:3000
```
### 生产环境部署
```bash
# 构建生产版本
pnpm build:antd
# 部署到服务器
# 将 dist 目录上传到 Web 服务器
```
## 性能优化
### 构建优化
- 代码分割
- 树摇优化
- 压缩资源
- 缓存策略
### 运行时优化
- 虚拟滚动
- 图片懒加载
- 组件懒加载
- 防抖节流
## 安全指南
### 前端安全
- XSS 防护
- CSRF 防护
- 输入验证
- 权限控制
### 代码安全
- 敏感信息加密
- API 密钥保护
- 代码混淆
- 安全审计
## 维护指南
### 日常维护
- 定期更新依赖
- 监控系统性能
- 备份重要数据
- 安全漏洞修复
### 版本管理
- 使用 Git 版本控制
- 遵循语义化版本
- 定期发布版本
- 维护更新日志

View File

@@ -0,0 +1,307 @@
# 数据库设计文档
## 数据库概述
本系统采用前后端分离架构,前端不直接操作数据库,但需要了解后端数据库设计以便进行合理的数据交互和界面设计。
## 数据库选型
### 推荐数据库
- **MySQL 8.0+**: 关系型数据库,事务支持完善
- **PostgreSQL 13+**: 高级特性丰富JSON 支持好
- **MongoDB 5.0+**: 文档数据库,灵活 schema
### 选择建议
- 中小型项目: MySQL
- 大型复杂项目: PostgreSQL
- 快速原型: MongoDB
## 核心表设计
### 1. 用户表 (sys_user)
| 字段名 | 类型 | 长度 | 主键 | 非空 | 默认值 | 说明 |
|--------|------|------|------|------|--------|------|
| id | bigint | 20 | ✅ | ✅ | 自增 | 用户ID |
| username | varchar | 50 | ❌ | ✅ | | 用户名 |
| password | varchar | 100 | ❌ | ✅ | | 密码(加密) |
| nickname | varchar | 50 | ❌ | ❌ | | 昵称 |
| email | varchar | 100 | ❌ | ❌ | | 邮箱 |
| phone | varchar | 20 | ❌ | ❌ | | 手机号 |
| avatar | varchar | 500 | ❌ | ❌ | | 头像 |
| status | tinyint | 1 | ❌ | ✅ | 1 | 状态(0禁用,1启用) |
| create_time | datetime | | ❌ | ✅ | CURRENT_TIMESTAMP | 创建时间 |
| update_time | datetime | | ❌ | ✅ | CURRENT_TIMESTAMP | 更新时间 |
**索引设计:**
- 主键索引: PRIMARY KEY (id)
- 唯一索引: UNIQUE KEY uk_username (username)
- 普通索引: INDEX idx_email (email)
### 2. 角色表 (sys_role)
| 字段名 | 类型 | 长度 | 主键 | 非空 | 默认值 | 说明 |
|--------|------|------|------|------|--------|------|
| id | bigint | 20 | ✅ | ✅ | 自增 | 角色ID |
| name | varchar | 50 | ❌ | ✅ | | 角色名称 |
| code | varchar | 50 | ❌ | ✅ | | 角色编码 |
| description | varchar | 200 | ❌ | ❌ | | 角色描述 |
| status | tinyint | 1 | ❌ | ✅ | 1 | 状态(0禁用,1启用) |
| create_time | datetime | | ❌ | ✅ | CURRENT_TIMESTAMP | 创建时间 |
| update_time | datetime | | ❌ | ✅ | CURRENT_TIMESTAMP | 更新时间 |
**索引设计:**
- 主键索引: PRIMARY KEY (id)
- 唯一索引: UNIQUE KEY uk_code (code)
### 3. 权限表 (sys_permission)
| 字段名 | 类型 | 长度 | 主键 | 非空 | 默认值 | 说明 |
|--------|------|------|------|------|--------|------|
| id | bigint | 20 | ✅ | ✅ | 自增 | 权限ID |
| name | varchar | 50 | ❌ | ✅ | | 权限名称 |
| code | varchar | 100 | ❌ | ✅ | | 权限编码 |
| type | tinyint | 1 | ❌ | ✅ | | 权限类型(1菜单,2按钮) |
| parent_id | bigint | 20 | ❌ | ✅ | 0 | 父级ID |
| path | varchar | 200 | ❌ | ❌ | | 路由路径 |
| component | varchar | 200 | ❌ | ❌ | | 组件路径 |
| icon | varchar | 50 | ❌ | ❌ | | 图标 |
| sort | int | 11 | ❌ | ✅ | 0 | 排序 |
| status | tinyint | 1 | ❌ | ✅ | 1 | 状态(0禁用,1启用) |
| create_time | datetime | | ❌ | ✅ | CURRENT_TIMESTAMP | 创建时间 |
| update_time | datetime | | ❌ | ✅ | CURRENT_TIMESTAMP | 更新时间 |
**索引设计:**
- 主键索引: PRIMARY KEY (id)
- 普通索引: INDEX idx_parent_id (parent_id)
- 普通索引: INDEX idx_type (type)
### 4. 用户角色关联表 (sys_user_role)
| 字段名 | 类型 | 长度 | 主键 | 非空 | 默认值 | 说明 |
|--------|------|------|------|------|--------|------|
| id | bigint | 20 | ✅ | ✅ | 自增 | 关联ID |
| user_id | bigint | 20 | ❌ | ✅ | | 用户ID |
| role_id | bigint | 20 | ❌ | ✅ | | 角色ID |
| create_time | datetime | | ❌ | ✅ | CURRENT_TIMESTAMP | 创建时间 |
**索引设计:**
- 主键索引: PRIMARY KEY (id)
- 唯一索引: UNIQUE KEY uk_user_role (user_id, role_id)
- 普通索引: INDEX idx_user_id (user_id)
- 普通索引: INDEX idx_role_id (role_id)
### 5. 角色权限关联表 (sys_role_permission)
| 字段名 | 类型 | 长度 | 主键 | 非空 | 默认值 | 说明 |
|--------|------|------|------|------|--------|------|
| id | bigint | 20 | ✅ | ✅ | 自增 | 关联ID |
| role_id | bigint | 20 | ❌ | ✅ | | 角色ID |
| permission_id | bigint | 20 | ❌ | ✅ | | 权限ID |
| create_time | datetime | | ❌ | ✅ | CURRENT_TIMESTAMP | 创建时间 |
**索引设计:**
- 主键索引: PRIMARY KEY (id)
- 唯一索引: UNIQUE KEY uk_role_permission (role_id, permission_id)
- 普通索引: INDEX idx_role_id (role_id)
- 普通索引: INDEX idx_permission_id (permission_id)
### 6. 菜单表 (sys_menu)
| 字段名 | 类型 | 长度 | 主键 | 非空 | 默认值 | 说明 |
|--------|------|------|------|------|--------|------|
| id | bigint | 20 | ✅ | ✅ | 自增 | 菜单ID |
| name | varchar | 50 | ❌ | ✅ | | 菜单名称 |
| type | tinyint | 1 | ❌ | ✅ | | 菜单类型(1目录,2菜单,3按钮) |
| parent_id | bigint | 20 | ❌ | ✅ | 0 | 父级ID |
| path | varchar | 200 | ❌ | ❌ | | 路由路径 |
| component | varchar | 200 | ❌ | ❌ | | 组件路径 |
| icon | varchar | 50 | ❌ | ❌ | | 图标 |
| sort | int | 11 | ❌ | ✅ | 0 | 排序 |
| status | tinyint | 1 | ❌ | ✅ | 1 | 状态(0禁用,1启用) |
| create_time | datetime | | ❌ | ✅ | CURRENT_TIMESTAMP | 创建时间 |
| update_time | datetime | | ❌ | ✅ | CURRENT_TIMESTAMP | 更新时间 |
**索引设计:**
- 主键索引: PRIMARY KEY (id)
- 普通索引: INDEX idx_parent_id (parent_id)
## 业务表设计
### 7. 操作日志表 (sys_operation_log)
| 字段名 | 类型 | 长度 | 主键 | 非空 | 默认值 | 说明 |
|--------|------|------|------|------|--------|------|
| id | bigint | 20 | ✅ | ✅ | 自增 | 日志ID |
| user_id | bigint | 20 | ❌ | ✅ | | 用户ID |
| username | varchar | 50 | ❌ | ✅ | | 用户名 |
| operation | varchar | 100 | ❌ | ✅ | | 操作描述 |
| method | varchar | 10 | ❌ | ✅ | | 请求方法 |
| url | varchar | 500 | ❌ | ✅ | | 请求URL |
| ip | varchar | 50 | ❌ | ✅ | | IP地址 |
| user_agent | varchar | 500 | ❌ | ❌ | | 用户代理 |
| params | text | | ❌ | ❌ | | 请求参数 |
| result | text | | ❌ | ❌ | | 返回结果 |
| status | tinyint | 1 | ❌ | ✅ | 1 | 状态(0失败,1成功) |
| error_msg | text | | ❌ | ❌ | | 错误信息 |
| execute_time | int | 11 | ❌ | ✅ | 0 | 执行时间(ms) |
| create_time | datetime | | ❌ | ✅ | CURRENT_TIMESTAMP | 创建时间 |
**索引设计:**
- 主键索引: PRIMARY KEY (id)
- 普通索引: INDEX idx_user_id (user_id)
- 普通索引: INDEX idx_create_time (create_time)
### 8. 字典表 (sys_dict)
| 字段名 | 类型 | 长度 | 主键 | 非空 | 默认值 | 说明 |
|--------|------|------|------|------|--------|------|
| id | bigint | 20 | ✅ | ✅ | 自增 | 字典ID |
| type | varchar | 50 | ❌ | ✅ | | 字典类型 |
| code | varchar | 50 | ❌ | ✅ | | 字典编码 |
| name | varchar | 100 | ❌ | ✅ | | 字典名称 |
| value | varchar | 200 | ❌ | ❌ | | 字典值 |
| sort | int | 11 | ❌ | ✅ | 0 | 排序 |
| status | tinyint | 1 | ❌ | ✅ | 1 | 状态(0禁用,1启用) |
| description | varchar | 200 | ❌ | ❌ | | 描述 |
| create_time | datetime | | ❌ | ✅ | CURRENT_TIMESTAMP | 创建时间 |
| update_time | datetime | | ❌ | ✅ | CURRENT_TIMESTAMP | 更新时间 |
**索引设计:**
- 主键索引: PRIMARY KEY (id)
- 唯一索引: UNIQUE KEY uk_type_code (type, code)
- 普通索引: INDEX idx_type (type)
## 数据库关系图
```mermaid
erDiagram
sys_user ||--o{ sys_user_role : has
sys_role ||--o{ sys_user_role : has
sys_role ||--o{ sys_role_permission : has
sys_permission ||--o{ sys_role_permission : has
sys_permission ||--o{ sys_menu : extends
sys_user {
bigint id PK
varchar username
varchar password
varchar nickname
varchar email
varchar phone
varchar avatar
tinyint status
datetime create_time
datetime update_time
}
sys_role {
bigint id PK
varchar name
varchar code
varchar description
tinyint status
datetime create_time
datetime update_time
}
sys_permission {
bigint id PK
varchar name
varchar code
tinyint type
bigint parent_id
varchar path
varchar component
varchar icon
int sort
tinyint status
datetime create_time
datetime update_time
}
sys_user_role {
bigint id PK
bigint user_id
bigint role_id
datetime create_time
}
sys_role_permission {
bigint id PK
bigint role_id
bigint permission_id
datetime create_time
}
```
## 数据字典
### 状态枚举
| 表名 | 字段名 | 枚举值 | 说明 |
|------|--------|--------|------|
| sys_user | status | 0 | 禁用 |
| sys_user | status | 1 | 启用 |
| sys_role | status | 0 | 禁用 |
| sys_role | status | 1 | 启用 |
| sys_permission | status | 0 | 禁用 |
| sys_permission | status | 1 | 启用 |
| sys_operation_log | status | 0 | 失败 |
| sys_operation_log | status | 1 | 成功 |
### 类型枚举
| 表名 | 字段名 | 枚举值 | 说明 |
|------|--------|--------|------|
| sys_permission | type | 1 | 菜单权限 |
| sys_permission | type | 2 | 按钮权限 |
| sys_menu | type | 1 | 目录 |
| sys_menu | type | 2 | 菜单 |
| sys_menu | type | 3 | 按钮 |
## 数据库优化建议
### 1. 索引优化
- 为常用查询字段建立索引
- 避免过度索引影响写入性能
- 定期分析索引使用情况
### 2. 查询优化
- 使用分页查询避免大数据量
- 避免 SELECT * 查询
- 合理使用 JOIN 查询
### 3. 存储优化
- 合理设置字段长度
- 使用合适的数据类型
- 定期清理历史数据
### 4. 安全优化
- 敏感字段加密存储
- 定期备份数据
- 访问权限控制
## 迁移策略
### 版本管理
- 使用 Flyway 或 Liquibase 进行数据库版本管理
- 每个版本创建对应的迁移脚本
- 测试环境先行验证
### 数据迁移
- 生产环境数据备份
- 灰度发布验证
- 回滚方案准备
## 监控维护
### 性能监控
- 慢查询日志分析
- 连接数监控
- 磁盘空间监控
### 日常维护
- 定期数据备份
- 索引重建优化
- 日志文件清理

551
docs/测试文档.md Normal file
View File

@@ -0,0 +1,551 @@
# 测试文档
## 测试概述
AIOTAGRO 管理系统采用全面的测试策略,确保系统质量和稳定性。测试覆盖单元测试、集成测试和端到端测试。
## 测试环境
### 环境要求
- **Node.js**: 18.0.0+
- **pnpm**: 8.0.0+
- **浏览器**: Chrome 90+, Firefox 85+, Safari 14+
### 测试工具栈
| 工具 | 版本 | 用途 |
|------|------|------|
| Vitest | 1.0.0+ | 单元测试框架 |
| Vue Test Utils | 2.4.0+ | Vue 组件测试 |
| Playwright | 1.40.0+ | E2E 测试 |
| Testing Library | 6.0.0+ | 组件测试工具 |
## 单元测试
### 测试配置
```typescript
// vitest.config.ts
import { defineConfig } from 'vitest/config'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
test: {
globals: true,
environment: 'jsdom',
include: ['**/__tests__/**/*.spec.ts'],
coverage: {
reporter: ['text', 'json', 'html'],
exclude: [
'node_modules/',
'dist/',
'**/*.d.ts',
'**/types/**'
]
}
}
})
```
### 组件测试示例
```typescript
// __tests__/components/UserInfo.spec.ts
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import UserInfo from '@/components/UserInfo.vue'
describe('UserInfo', () => {
it('renders user information correctly', () => {
const user = {
id: 1,
name: '张三',
email: 'zhangsan@example.com',
avatar: '/avatar.jpg'
}
const wrapper = mount(UserInfo, {
props: { user }
})
expect(wrapper.text()).toContain('张三')
expect(wrapper.text()).toContain('zhangsan@example.com')
expect(wrapper.find('img').attributes('src')).toBe('/avatar.jpg')
})
it('emits edit event when edit button is clicked', async () => {
const user = {
id: 1,
name: '张三',
email: 'zhangsan@example.com'
}
const wrapper = mount(UserInfo, {
props: { user }
})
await wrapper.find('[data-testid="edit-btn"]').trigger('click')
expect(wrapper.emitted('edit')).toBeTruthy()
})
})
```
### 工具函数测试
```typescript
// __tests__/utils/format.spec.ts
import { describe, it, expect } from 'vitest'
import { formatDate, formatCurrency } from '@/utils/format'
describe('format utils', () => {
describe('formatDate', () => {
it('formats date correctly', () => {
const date = new Date('2023-12-01')
expect(formatDate(date)).toBe('2023-12-01')
})
it('handles invalid date', () => {
expect(formatDate(null)).toBe('')
expect(formatDate(undefined)).toBe('')
})
})
describe('formatCurrency', () => {
it('formats currency correctly', () => {
expect(formatCurrency(1234.56)).toBe('¥1,234.56')
expect(formatCurrency(0)).toBe('¥0.00')
})
})
})
```
## 集成测试
### API 集成测试
```typescript
// __tests__/api/user.spec.ts
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { userApi } from '@/api/user'
import { mockServer } from '../mocks/server'
describe('User API', () => {
beforeEach(() => {
mockServer.listen()
})
afterEach(() => {
mockServer.resetHandlers()
})
afterAll(() => {
mockServer.close()
})
it('fetches user list successfully', async () => {
const response = await userApi.getUsers({ page: 1, size: 10 })
expect(response.status).toBe(200)
expect(response.data.list).toHaveLength(2)
expect(response.data.total).toBe(2)
})
it('handles API errors correctly', async () => {
mockServer.use(
rest.get('/api/users', (req, res, ctx) => {
return res(ctx.status(500), ctx.json({ message: 'Internal Server Error' }))
})
)
await expect(userApi.getUsers({ page: 1, size: 10 })).rejects.toThrow()
})
})
```
### 状态管理测试
```typescript
// __tests__/stores/user.spec.ts
import { describe, it, expect } from 'vitest'
import { setActivePinia, createPinia } from 'pinia'
import { useUserStore } from '@/stores/user'
describe('User Store', () => {
beforeEach(() => {
setActivePinia(createPinia())
})
it('initializes with default values', () => {
const store = useUserStore()
expect(store.user).toBeNull()
expect(store.isLoggedIn).toBe(false)
expect(store.loading).toBe(false)
})
it('sets user correctly', () => {
const store = useUserStore()
const user = { id: 1, name: '张三', email: 'zhangsan@example.com' }
store.setUser(user)
expect(store.user).toEqual(user)
expect(store.isLoggedIn).toBe(true)
})
it('clears user on logout', () => {
const store = useUserStore()
const user = { id: 1, name: '张三', email: 'zhangsan@example.com' }
store.setUser(user)
store.logout()
expect(store.user).toBeNull()
expect(store.isLoggedIn).toBe(false)
})
})
```
## E2E 测试
### 测试配置
```typescript
// playwright.config.ts
import { defineConfig, devices } from '@playwright/test'
export default defineConfig({
testDir: './__tests__/e2e',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: 'html',
use: {
baseURL: 'http://localhost:3000',
trace: 'on-first-retry',
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},
{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
],
webServer: {
command: 'pnpm dev:antd',
url: 'http://localhost:3000',
reuseExistingServer: !process.env.CI,
},
})
```
### 登录流程测试
```typescript
// __tests__/e2e/login.spec.ts
import { test, expect } from '@playwright/test'
test.describe('Login Flow', () => {
test('should login successfully with valid credentials', async ({ page }) => {
await page.goto('/login')
// 填写登录表单
await page.fill('[data-testid="username"]', 'admin')
await page.fill('[data-testid="password"]', '123456')
await page.click('[data-testid="login-btn"]')
// 验证登录成功
await expect(page).toHaveURL('/dashboard')
await expect(page.locator('[data-testid="user-name"]')).toContainText('管理员')
})
test('should show error message with invalid credentials', async ({ page }) => {
await page.goto('/login')
// 填写错误凭证
await page.fill('[data-testid="username"]', 'wronguser')
await page.fill('[data-testid="password"]', 'wrongpass')
await page.click('[data-testid="login-btn"]')
// 验证错误提示
await expect(page.locator('[data-testid="error-message"]')).toBeVisible()
await expect(page).toHaveURL('/login')
})
test('should redirect to login when accessing protected page without authentication', async ({ page }) => {
// 直接访问受保护页面
await page.goto('/user-management')
// 验证重定向到登录页
await expect(page).toHaveURL('/login')
})
})
```
### 用户管理测试
```typescript
// __tests__/e2e/user-management.spec.ts
import { test, expect } from '@playwright/test'
test.describe('User Management', () => {
test.beforeEach(async ({ page }) => {
// 登录
await page.goto('/login')
await page.fill('[data-testid="username"]', 'admin')
await page.fill('[data-testid="password"]', '123456')
await page.click('[data-testid="login-btn"]')
await page.goto('/user-management')
})
test('should display user list', async ({ page }) => {
await expect(page.locator('[data-testid="user-table"]')).toBeVisible()
await expect(page.locator('[data-testid="user-row"]').first()).toBeVisible()
})
test('should create new user', async ({ page }) => {
// 点击新建按钮
await page.click('[data-testid="create-user-btn"]')
// 填写用户信息
await page.fill('[data-testid="user-name"]', '测试用户')
await page.fill('[data-testid="user-email"]', 'test@example.com')
await page.click('[data-testid="save-btn"]')
// 验证创建成功
await expect(page.locator('[data-testid="success-message"]')).toBeVisible()
await expect(page.locator('[data-testid="user-table"]')).toContainText('测试用户')
})
test('should delete user', async ({ page }) => {
// 点击删除按钮
await page.click('[data-testid="delete-user-btn"]').first()
await page.click('[data-testid="confirm-delete-btn"]')
// 验证删除成功
await expect(page.locator('[data-testid="success-message"]')).toBeVisible()
})
})
```
## 性能测试
### 加载性能测试
```typescript
// __tests__/performance/loading.spec.ts
import { test, expect } from '@playwright/test'
test.describe('Performance Tests', () => {
test('should load dashboard within 3 seconds', async ({ page }) => {
const startTime = Date.now()
await page.goto('/dashboard')
const loadTime = Date.now() - startTime
expect(loadTime).toBeLessThan(3000)
})
test('should render user table with 1000 rows efficiently', async ({ page }) => {
await page.goto('/user-management')
// 模拟大量数据
await page.evaluate(() => {
window.performance.mark('table-render-start')
})
// 等待表格渲染完成
await page.waitForSelector('[data-testid="user-table"]')
const renderTime = await page.evaluate(() => {
window.performance.mark('table-render-end')
window.performance.measure('table-render', 'table-render-start', 'table-render-end')
const measure = window.performance.getEntriesByName('table-render')[0]
return measure.duration
})
expect(renderTime).toBeLessThan(1000)
})
})
```
## 安全测试
### XSS 防护测试
```typescript
// __tests__/security/xss.spec.ts
import { test, expect } from '@playwright/test'
test.describe('Security Tests', () => {
test('should sanitize user input to prevent XSS', async ({ page }) => {
await page.goto('/user-management')
// 尝试注入 XSS 代码
const xssPayload = '<script>alert("XSS")</script>'
await page.fill('[data-testid="user-name"]', xssPayload)
await page.click('[data-testid="save-btn"]')
// 验证输入被正确转义
const userNameCell = await page.locator('[data-testid="user-name"]').first()
const innerHTML = await userNameCell.innerHTML()
expect(innerHTML).not.toContain('<script>')
expect(innerHTML).toContain('<script>')
})
})
```
## 测试覆盖率
### 覆盖率配置
```json
{
"coverage": {
"provider": "v8",
"reporter": ["text", "json", "html"],
"reportsDirectory": "./coverage",
"exclude": [
"**/*.d.ts",
"**/types/**",
"**/node_modules/**",
"**/dist/**",
"**/coverage/**"
],
"thresholds": {
"lines": 80,
"functions": 80,
"branches": 70,
"statements": 80
}
}
}
```
### 覆盖率报告
```bash
# 生成覆盖率报告
pnpm test:coverage
# 查看 HTML 报告
open coverage/index.html
```
## 测试执行
### 开发环境测试
```bash
# 运行单元测试
pnpm test:unit
# 运行 E2E 测试
pnpm test:e2e
# 运行所有测试
pnpm test
```
### CI/CD 环境测试
```yaml
# .github/workflows/test.yml
name: Test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
cache: 'pnpm'
- run: pnpm install
- run: pnpm test:unit
- run: pnpm test:e2e
- run: pnpm test:coverage
```
## 测试最佳实践
### 1. 测试命名规范
- 描述性测试名称
- 使用 Given-When-Then 模式
- 避免模糊的测试描述
### 2. 测试数据管理
- 使用测试工厂函数
- 避免硬编码数据
- 清理测试数据
### 3. 测试隔离
- 每个测试独立运行
- 避免测试间依赖
- 使用 beforeEach/afterEach
### 4. 异步测试
- 正确处理异步操作
- 使用适当的等待策略
- 避免不必要的等待
## 故障排除
### 常见问题
#### 1. 测试超时
```typescript
// 增加超时时间
test('slow operation', async ({ page }) => {
test.setTimeout(60000)
// 测试代码
})
```
#### 2. 元素找不到
```typescript
// 使用更稳定的选择器
await page.locator('[data-testid="submit-btn"]').click()
```
#### 3. 网络请求失败
```typescript
// 等待网络请求完成
await page.waitForResponse(response =>
response.url().includes('/api/users') && response.status() === 200
)
```
## 测试报告
### 生成测试报告
```bash
# 生成 JUnit 报告
pnpm test:report
# 生成覆盖率报告
pnpm test:coverage:report
```
### 报告解读
- **测试通过率**: 应保持在 95% 以上
- **代码覆盖率**: 单元测试覆盖率应达到 80% 以上
- **性能指标**: 关键页面加载时间应小于 3 秒
- **安全测试**: 所有安全测试必须通过

246
docs/用户手册-附录.md Normal file
View File

@@ -0,0 +1,246 @@
# 用户手册 - 附录
## 快捷键列表
### 全局快捷键
| 快捷键 | 功能 | 说明 |
|--------|------|------|
| `Ctrl + K` | 快速搜索 | 打开全局搜索框 |
| `Ctrl + ,` | 打开设置 | 打开系统设置页面 |
| `F1` | 帮助 | 打开帮助文档 |
| `Ctrl + S` | 保存 | 保存当前表单 |
| `Ctrl + Z` | 撤销 | 撤销上一步操作 |
| `Ctrl + Y` | 重做 | 重做撤销的操作 |
### 数据操作快捷键
| 快捷键 | 功能 | 说明 |
|--------|------|------|
| `Ctrl + F` | 查找 | 在当前页面查找 |
| `Ctrl + A` | 全选 | 选择所有数据 |
| `Ctrl + C` | 复制 | 复制选中数据 |
| `Ctrl + V` | 粘贴 | 粘贴数据 |
| `Delete` | 删除 | 删除选中数据 |
| `Enter` | 确认 | 确认操作或保存 |
### 导航快捷键
| 快捷键 | 功能 | 说明 |
|--------|------|------|
| `Alt + 1` | 仪表盘 | 跳转到仪表盘 |
| `Alt + 2` | 用户管理 | 跳转到用户管理 |
| `Alt + 3` | 角色管理 | 跳转到角色管理 |
| `Alt + 4` | 菜单管理 | 跳转到菜单管理 |
| `Alt + 5` | 部门管理 | 跳转到部门管理 |
| `Alt + 6` | 系统设置 | 跳转到系统设置 |
## 错误代码说明
### 系统错误代码
| 错误代码 | 错误描述 | 解决方案 |
|----------|----------|----------|
| 1001 | 系统内部错误 | 联系技术支持 |
| 1002 | 数据库连接失败 | 检查数据库服务 |
| 1003 | 文件系统错误 | 检查磁盘空间和权限 |
| 1004 | 内存不足 | 重启系统或增加内存 |
### 用户错误代码
| 错误代码 | 错误描述 | 解决方案 |
|----------|----------|----------|
| 2001 | 用户未登录 | 重新登录系统 |
| 2002 | 权限不足 | 检查用户权限设置 |
| 2003 | 会话过期 | 重新登录系统 |
| 2004 | 账号被禁用 | 联系管理员启用账号 |
| 2005 | 密码错误 | 检查密码或重置密码 |
### 数据错误代码
| 错误代码 | 错误描述 | 解决方案 |
|----------|----------|----------|
| 3001 | 数据不存在 | 检查数据ID是否正确 |
| 3002 | 数据重复 | 检查数据唯一性约束 |
| 3003 | 数据格式错误 | 检查数据格式要求 |
| 3004 | 数据关联错误 | 检查关联数据是否存在 |
### 网络错误代码
| 错误代码 | 错误描述 | 解决方案 |
|----------|----------|----------|
| 4001 | 网络连接超时 | 检查网络连接 |
| 4002 | 服务器无响应 | 检查服务器状态 |
| 4003 | DNS解析失败 | 检查DNS配置 |
| 4004 | SSL证书错误 | 检查证书有效性 |
## 数据格式规范
### 日期时间格式
| 字段类型 | 格式 | 示例 | 说明 |
|----------|------|------|------|
| 日期 | YYYY-MM-DD | 2024-01-15 | ISO 8601 标准 |
| 时间 | HH:mm:ss | 14:30:00 | 24小时制 |
| 日期时间 | YYYY-MM-DD HH:mm:ss | 2024-01-15 14:30:00 | 完整时间戳 |
### 数字格式
| 字段类型 | 格式 | 示例 | 说明 |
|----------|------|------|------|
| 整数 | 无分隔符 | 12345 | 纯数字 |
| 小数 | 两位小数 | 123.45 | 小数点后两位 |
| 百分比 | 百分比格式 | 12.34% | 自动转换 |
| 货币 | 货币格式 | ¥123.45 | 根据地区设置 |
### 文件格式要求
| 文件类型 | 支持格式 | 大小限制 | 说明 |
|----------|----------|----------|------|
| 图片 | JPG, PNG, GIF, WebP | 5MB | 支持常见图片格式 |
| 文档 | PDF, DOC, DOCX, XLS, XLSX | 10MB | Office文档 |
| 压缩包 | ZIP, RAR | 50MB | 压缩文件 |
| 其他 | TXT, CSV, JSON | 2MB | 文本文件 |
## 系统限制说明
### 数据量限制
| 项目 | 限制 | 说明 |
|------|------|------|
| 单页显示数据 | 100条 | 分页显示大量数据 |
| 导出数据量 | 10000条 | 单次导出最大数量 |
| 导入数据量 | 5000条 | 单次导入最大数量 |
| 文件上传大小 | 100MB | 单个文件最大大小 |
### 操作频率限制
| 操作类型 | 频率限制 | 说明 |
|----------|----------|------|
| 登录尝试 | 5次/分钟 | 防止暴力破解 |
| 数据查询 | 100次/分钟 | 防止过度查询 |
| 数据导出 | 10次/小时 | 防止资源滥用 |
| 邮件发送 | 50封/小时 | 防止垃圾邮件 |
### 存储空间限制
| 用户类型 | 存储空间 | 说明 |
|----------|----------|------|
| 普通用户 | 1GB | 个人文件存储 |
| 管理员 | 10GB | 系统文件存储 |
| 超级管理员 | 无限制 | 系统管理需要 |
## 浏览器兼容性
### 完全支持
| 浏览器 | 最低版本 | 推荐版本 |
|--------|----------|----------|
| Chrome | 90 | 100+ |
| Firefox | 88 | 95+ |
| Safari | 14 | 15+ |
| Edge | 90 | 100+ |
### 部分支持
| 浏览器 | 支持情况 | 限制说明 |
|--------|----------|----------|
| IE 11 | 基本功能 | 部分高级功能不可用 |
| Opera | 大部分功能 | 兼容性良好 |
| 移动端浏览器 | 响应式设计 | 适配移动设备 |
### 不支持的浏览器
| 浏览器 | 原因 | 替代方案 |
|--------|------|----------|
| IE 10及以下 | 技术过时 | 升级到现代浏览器 |
| 老旧移动浏览器 | 功能限制 | 使用主流浏览器 |
## 性能优化建议
### 客户端优化
1. **浏览器设置**
- 启用硬件加速
- 清理浏览器缓存
- 关闭不必要的扩展
2. **网络优化**
- 使用有线网络连接
- 避免同时下载大文件
- 使用CDN加速
### 服务器端优化
1. **资源管理**
- 定期清理临时文件
- 优化数据库查询
- 使用缓存机制
2. **负载均衡**
- 分布式部署
- 负载均衡配置
- 自动扩容机制
## 故障排除指南
### 常见问题解决
#### 页面无法加载
1. 检查网络连接
2. 清除浏览器缓存
3. 尝试其他浏览器
4. 联系技术支持
#### 功能无法使用
1. 检查用户权限
2. 查看错误提示信息
3. 重新登录系统
4. 联系管理员
#### 数据异常
1. 检查数据格式
2. 验证数据完整性
3. 查看操作日志
4. 联系技术支持
### 紧急处理流程
#### 系统无法访问
1. 立即联系技术支持
2. 提供错误现象描述
3. 配合技术排查
4. 等待系统恢复
#### 数据丢失
1. 停止所有操作
2. 立即联系技术支持
3. 提供数据备份信息
4. 等待数据恢复
## 联系方式
### 技术支持
- **电话支持**: 400-xxx-xxxx
- **邮箱支持**: support@aiotagro.com
- **在线客服**: 系统内在线聊天
- **工作时间**: 工作日 9:00-18:00
### 反馈渠道
- **产品建议**: product@aiotagro.com
- **问题反馈**: feedback@aiotagro.com
- **技术合作**: tech@aiotagro.com
- **商务合作**: business@aiotagro.com
### 文档更新
- **最新版本**: 查看系统内版本信息
- **更新日志**: 查看版本更新说明
- **文档下载**: 官网文档中心
- **培训资料**: 联系客户成功团队
---
*本附录会随系统版本更新而更新,请定期查看最新版本。如有任何补充建议,请联系产品团队。*

397
docs/用户手册.md Normal file
View File

@@ -0,0 +1,397 @@
# 用户手册
## 产品概述
AIOTAGRO 管理系统是一个基于 Vue3 + TypeScript 的现代化企业级管理系统,提供丰富的功能模块和优秀的用户体验。本文档为用户提供完整的产品使用指南。
## 快速开始
### 1. 系统访问
#### 访问地址
- 生产环境: https://aiotagro.com
- 测试环境: https://test.aiotagro.com
- 开发环境: http://localhost:3000
#### 浏览器要求
- Chrome 90+ (推荐)
- Firefox 88+
- Safari 14+
- Edge 90+
### 2. 首次登录
#### 账号注册
1. 访问系统登录页面
2. 点击"注册新账号"
3. 填写注册信息(邮箱、手机号、密码)
4. 完成邮箱/手机验证
5. 登录系统
#### 密码要求
- 长度至少8位字符
- 包含大写字母、小写字母、数字
- 建议使用特殊字符增强安全性
## 系统功能
### 1. 仪表盘
#### 功能概述
仪表盘是系统的首页,提供关键业务数据的可视化展示和快速访问入口。
#### 主要功能
- **数据概览**: 显示核心业务指标
- **快捷操作**: 常用功能快速入口
- **消息通知**: 系统消息和待办事项
- **图表展示**: 数据趋势和统计分析
#### 使用指南
1. 登录系统后自动进入仪表盘
2. 点击各个卡片查看详细信息
3. 使用搜索框快速查找功能
4. 自定义仪表盘布局(拖拽调整)
### 2. 用户管理
#### 功能概述
用户管理模块用于管理系统用户账号、权限和角色。
#### 用户列表
- **查看用户**: 显示所有用户信息
- **搜索用户**: 按姓名、邮箱、角色搜索
- **筛选用户**: 按状态、部门、角色筛选
- **批量操作**: 批量启用/禁用用户
#### 添加用户
1. 点击"添加用户"按钮
2. 填写用户基本信息
3. 设置用户角色和权限
4. 发送账号激活邮件
#### 用户编辑
- **基本信息**: 修改姓名、邮箱、电话
- **权限设置**: 调整用户角色和权限
- **状态管理**: 启用/禁用用户账号
- **密码重置**: 重置用户登录密码
### 3. 角色管理
#### 功能概述
角色管理用于定义系统权限组,实现精细化的权限控制。
#### 角色列表
- **查看角色**: 显示所有角色信息
- **角色详情**: 查看角色权限配置
- **角色状态**: 启用/禁用角色
#### 创建角色
1. 点击"创建角色"按钮
2. 输入角色名称和描述
3. 配置角色权限
4. 保存角色配置
#### 权限配置
- **菜单权限**: 控制菜单访问权限
- **操作权限**: 控制功能操作权限
- **数据权限**: 控制数据访问范围
- **API权限**: 控制接口调用权限
### 4. 菜单管理
#### 功能概述
菜单管理用于配置系统导航菜单结构和权限。
#### 菜单树
- **层级结构**: 树形结构展示菜单
- **拖拽排序**: 拖拽调整菜单顺序
- **展开收起**: 展开/收起菜单层级
- **搜索菜单**: 快速查找菜单项
#### 添加菜单
1. 选择父级菜单(可选)
2. 点击"添加菜单"按钮
3. 配置菜单基本信息
4. 设置菜单权限和图标
5. 保存菜单配置
#### 菜单配置项
- **菜单名称**: 显示在导航中的名称
- **菜单路径**: 路由路径或外部链接
- **菜单图标**: 图标标识
- **排序号**: 显示顺序
- **可见性**: 控制菜单是否显示
- **权限控制**: 关联权限配置
### 5. 部门管理
#### 功能概述
部门管理用于组织企业组织架构,实现按部门的数据权限控制。
#### 部门树
- **组织架构**: 树形展示部门结构
- **部门详情**: 查看部门信息和成员
- **部门排序**: 调整部门显示顺序
#### 添加部门
1. 选择父级部门(可选)
2. 点击"添加部门"按钮
3. 填写部门基本信息
4. 设置部门负责人
5. 配置部门权限
#### 部门成员
- **成员列表**: 查看部门所有成员
- **添加成员**: 从用户列表添加成员
- **移除成员**: 从部门移除成员
- **调整角色**: 设置成员在部门中的角色
### 6. 系统设置
#### 功能概述
系统设置模块提供系统级配置和管理功能。
#### 基本设置
- **系统名称**: 设置系统显示名称
- **Logo配置**: 上传系统Logo
- **主题设置**: 配置系统主题颜色
- **语言设置**: 多语言支持配置
#### 安全设置
- **密码策略**: 配置密码复杂度要求
- **登录策略**: 配置登录相关设置
- **会话管理**: 配置会话超时时间
- **审计日志**: 查看系统操作日志
#### 邮件设置
- **SMTP配置**: 配置邮件服务器
- **模板管理**: 管理邮件模板
- **测试发送**: 测试邮件发送功能
## 操作指南
### 1. 数据查询
#### 基本查询
1. 进入相应功能模块
2. 使用搜索框输入关键词
3. 点击搜索按钮或按回车键
4. 查看查询结果
#### 高级查询
1. 点击"高级查询"按钮
2. 选择查询条件字段
3. 设置查询条件和值
4. 添加多个查询条件
5. 执行查询操作
#### 查询技巧
- 使用通配符: * 表示多个字符,? 表示单个字符
- 组合查询: 多个条件同时满足
- 保存查询: 将常用查询保存为模板
### 2. 数据导出
#### 导出当前页
1. 在数据列表页面
2. 点击"导出"按钮
3. 选择导出格式Excel/CSV/PDF
4. 设置导出字段
5. 下载导出文件
#### 导出全部数据
1. 在数据列表页面
2. 点击"导出全部"按钮
3. 选择导出格式
4. 系统后台生成文件
5. 下载导出文件
#### 导出设置
- **字段选择**: 选择需要导出的字段
- **格式设置**: 设置导出文件格式
- **编码设置**: 设置文件编码格式
- **分页设置**: 设置导出数据分页
### 3. 批量操作
#### 批量选择
1. 在数据列表页面
2. 使用复选框选择多个项目
3. 或使用"全选"功能选择所有项目
4. 点击批量操作按钮
#### 批量操作类型
- **批量删除**: 删除选中的项目
- **批量启用**: 启用选中的项目
- **批量禁用**: 禁用选中的项目
- **批量分配**: 分配选中的项目
#### 操作确认
- 系统会显示操作确认对话框
- 确认操作影响的项目数量
- 输入确认信息(如删除确认)
- 执行批量操作
### 4. 数据导入
#### 准备数据文件
1. 下载数据导入模板
2. 按照模板格式填写数据
3. 保存为Excel或CSV格式
4. 检查数据格式是否正确
#### 执行导入
1. 点击"数据导入"按钮
2. 选择数据文件
3. 设置导入选项
4. 预览导入数据
5. 确认并执行导入
#### 导入结果
- **成功导入**: 显示成功导入数量
- **导入失败**: 显示失败原因
- **错误报告**: 下载错误数据报告
- **重新导入**: 修正错误后重新导入
## 常见问题
### 1. 登录问题
#### 忘记密码
1. 在登录页面点击"忘记密码"
2. 输入注册邮箱或手机号
3. 接收验证码
4. 设置新密码
5. 使用新密码登录
#### 账号被锁定
1. 联系系统管理员
2. 提供用户信息验证身份
3. 管理员解锁账号
4. 重新尝试登录
#### 登录失败
- 检查用户名和密码是否正确
- 检查网络连接是否正常
- 清除浏览器缓存和Cookie
- 尝试使用其他浏览器
### 2. 权限问题
#### 功能无法访问
1. 检查当前用户角色权限
2. 联系管理员确认权限配置
3. 申请相应功能权限
4. 重新登录系统生效
#### 数据访问受限
1. 检查数据权限设置
2. 确认部门权限配置
3. 联系管理员调整权限
4. 刷新页面重新加载
### 3. 性能问题
#### 页面加载慢
1. 检查网络连接速度
2. 清理浏览器缓存
3. 关闭不必要的浏览器标签
4. 联系技术支持
#### 操作响应慢
1. 检查系统当前负载
2. 避免同时进行大量操作
3. 分批处理大数据量操作
4. 联系管理员优化系统
## 最佳实践
### 1. 数据管理
#### 定期备份
- 重要数据定期导出备份
- 使用系统提供的备份功能
- 存储备份文件到安全位置
- 测试备份文件可恢复性
#### 数据清理
- 定期清理过期数据
- 归档历史数据
- 删除重复数据
- 优化数据存储结构
### 2. 权限管理
#### 最小权限原则
- 为用户分配最小必要权限
- 定期审核用户权限
- 及时回收不再需要的权限
- 使用角色组管理权限
#### 权限审计
- 定期检查权限配置
- 审核权限使用情况
- 发现异常权限及时处理
- 记录权限变更日志
### 3. 系统使用
#### 操作规范
- 按照标准流程操作系统
- 重要操作前进行确认
- 记录关键操作日志
- 定期检查操作结果
#### 问题反馈
- 发现问题及时反馈
- 提供详细的问题描述
- 附上相关截图和日志
- 跟踪问题处理进度
## 技术支持
### 1. 获取帮助
#### 在线帮助
- 系统内置帮助文档
- 操作提示和向导
- 常见问题解答
- 视频教程链接
#### 技术支持
- 技术支持热线: 400-xxx-xxxx
- 技术支持邮箱: support@aiotagro.com
- 在线客服系统
- 技术社区论坛
### 2. 问题反馈
#### 反馈渠道
- 系统内问题反馈功能
- 邮件反馈: feedback@aiotagro.com
- 电话反馈: 400-xxx-xxxx
- 用户调研问卷
#### 反馈内容
- 问题详细描述
- 操作步骤重现
- 系统环境信息
- 期望解决方案
### 3. 版本更新
#### 更新通知
- 系统内更新公告
- 邮件通知更新信息
- 版本更新说明文档
- 新功能使用指南
#### 更新准备
- 备份重要数据
- 了解更新内容
- 测试新功能
- 培训相关人员
---
*本用户手册会随系统版本更新而更新,请定期查看最新版本。如有任何问题或建议,请联系技术支持团队。*

574
docs/运维文档.md Normal file
View File

@@ -0,0 +1,574 @@
# 运维文档
## 运维概述
AIOTAGRO 管理系统运维文档涵盖系统监控、性能优化、故障处理、安全维护等日常运维工作。本文档为运维团队提供完整的操作指南和最佳实践。
## 系统监控
### 监控指标
#### 1. 应用性能指标
| 指标 | 阈值 | 说明 | 监控工具 |
|------|------|------|----------|
| 响应时间 | < 2秒 | 页面加载时间 | Prometheus |
| 错误率 | < 1% | HTTP 错误率 | Grafana |
| 吞吐量 | > 1000 RPM | 请求处理能力 | New Relic |
| 可用性 | > 99.9% | 系统可用性 | Uptime Robot |
#### 2. 服务器资源指标
| 指标 | 阈值 | 说明 | 监控工具 |
|------|------|------|----------|
| CPU 使用率 | < 80% | CPU 负载 | Node Exporter |
| 内存使用率 | < 85% | 内存使用 | cAdvisor |
| 磁盘使用率 | < 90% | 磁盘空间 | Disk Usage |
| 网络流量 | 无限制 | 网络带宽 | NetData |
### 监控配置
#### 1. Prometheus 配置
```yaml
# prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'aiotagro-frontend'
static_configs:
- targets: ['localhost:3000']
metrics_path: '/metrics'
scrape_interval: 30s
- job_name: 'nginx'
static_configs:
- targets: ['localhost:9113']
scrape_interval: 30s
- job_name: 'node-exporter'
static_configs:
- targets: ['localhost:9100']
scrape_interval: 30s
alerting:
alertmanagers:
- static_configs:
- targets: ['localhost:9093']
rule_files:
- "alerts.yml"
```
#### 2. 告警规则
```yaml
# alerts.yml
groups:
- name: aiotagro-frontend
rules:
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.05
for: 2m
labels:
severity: critical
annotations:
summary: "高错误率警报"
description: "错误率超过 5%,当前值: {{ $value }}"
- alert: HighResponseTime
expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 2
for: 5m
labels:
severity: warning
annotations:
summary: "高响应时间警报"
description: "95% 响应时间超过 2 秒,当前值: {{ $value }}"
- alert: ServiceDown
expr: up{job="aiotagro-frontend"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "服务宕机警报"
description: "AIOTAGRO 前端服务已宕机"
```
### 监控仪表板
#### 1. Grafana 配置
```json
{
"dashboard": {
"title": "AIOTAGRO 监控面板",
"panels": [
{
"title": "响应时间",
"type": "graph",
"targets": [
{
"expr": "histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))",
"legendFormat": "95% 响应时间"
}
]
},
{
"title": "错误率",
"type": "singlestat",
"targets": [
{
"expr": "rate(http_requests_total{status=~\"5..\"}[5m]) / rate(http_requests_total[5m]) * 100",
"format": "percent"
}
]
}
]
}
}
```
## 性能优化
### 1. 前端优化
#### 代码分割配置
```javascript
// vite.config.js
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'vue-router', 'pinia'],
ui: ['ant-design-vue', '@ant-design/icons-vue'],
utils: ['lodash', 'dayjs', 'axios'],
charts: ['echarts']
}
}
}
}
})
```
#### 缓存策略优化
```nginx
# 静态资源缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header Vary Accept-Encoding;
# 启用 Brotli 压缩
brotli_static on;
gzip_static on;
}
# API 响应缓存
location /api/ {
proxy_cache api_cache;
proxy_cache_valid 200 302 5m;
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
add_header X-Cache-Status $upstream_cache_status;
}
```
### 2. 服务器优化
#### Nginx 性能调优
```nginx
# /etc/nginx/nginx.conf
worker_processes auto;
worker_cpu_affinity auto;
worker_rlimit_nofile 100000;
events {
worker_connections 4096;
use epoll;
multi_accept on;
}
http {
# 基础配置
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
keepalive_requests 1000;
# 缓冲区优化
client_body_buffer_size 128k;
client_max_body_size 100m;
client_header_buffer_size 1k;
large_client_header_buffers 4 4k;
output_buffers 1 32k;
postpone_output 1460;
# Gzip 压缩
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_comp_level 6;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss
application/atom+xml
image/svg+xml;
}
```
#### 系统内核优化
```bash
# /etc/sysctl.conf
# 网络优化
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 65536
net.ipv4.tcp_max_syn_backlog = 65536
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 1200
# 内存优化
vm.swappiness = 10
vm.dirty_ratio = 60
vm.dirty_background_ratio = 2
```
## 故障处理
### 1. 常见故障及解决方案
#### 服务不可用
**症状**: 网站无法访问返回 502/503 错误
**解决方案**:
```bash
# 检查服务状态
sudo systemctl status nginx
sudo systemctl status node-exporter
# 检查端口占用
sudo netstat -tlnp | grep :80
sudo netstat -tlnp | grep :3000
# 重启服务
sudo systemctl restart nginx
```
#### 性能下降
**症状**: 响应时间变慢CPU/内存使用率高
**解决方案**:
```bash
# 查看系统资源
top
htop
iotop
# 检查 Nginx 状态
sudo nginx -t
sudo tail -f /var/log/nginx/error.log
# 清理缓存
echo 3 > /proc/sys/vm/drop_caches
```
#### 磁盘空间不足
**症状**: 写入失败系统告警
**解决方案**:
```bash
# 检查磁盘使用
df -h
du -sh /var/log/nginx/
# 清理日志文件
sudo find /var/log/nginx -name "*.log" -mtime +7 -delete
sudo truncate -s 0 /var/log/nginx/error.log
# 清理备份文件
find /opt/aiotagro/backups -name "*.tar.gz" -mtime +30 -delete
```
### 2. 故障排查流程
#### 快速诊断脚本
```bash
#!/bin/bash
# diagnose.sh
echo "=== AIOTAGRO 系统诊断 ==="
echo "检查时间: $(date)"
echo -e "\n1. 系统资源检查"
echo "CPU 使用率: $(top -bn1 | grep "Cpu(s)" | awk '{print $2}')%"
echo "内存使用率: $(free | grep Mem | awk '{printf "%.2f%", $3/$2 * 100}')"
echo "磁盘使用率: $(df -h / | awk 'NR==2 {print $5}')"
echo -e "\n2. 服务状态检查"
services=("nginx" "node-exporter" "prometheus")
for service in "${services[@]}"; do
status=$(systemctl is-active $service)
echo "$service: $status"
done
echo -e "\n3. 端口检查"
ports=("80" "3000" "9100" "9090")
for port in "${ports[@]}"; do
if netstat -tln | grep ":$port " > /dev/null; then
echo "端口 $port: 正常"
else
echo "端口 $port: 异常"
fi
done
echo -e "\n4. 日志检查"
if sudo tail -n 10 /var/log/nginx/error.log | grep -i error; then
echo "发现 Nginx 错误日志"
else
echo "Nginx 错误日志正常"
fi
echo -e "\n诊断完成"
```
## 安全维护
### 1. 安全扫描
#### 漏洞扫描配置
```yaml
# .github/workflows/security-scan.yml
name: Security Scan
on:
schedule:
- cron: '0 2 * * 1' # 每周一凌晨2点
workflow_dispatch:
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Run security audit
run: |
npm audit --audit-level moderate
pnpm audit
- name: Run SAST scan
uses: github/codeql-action/init@v2
with:
languages: javascript
- name: Run SAST analysis
uses: github/codeql-action/analyze@v2
- name: Run dependency check
uses: dependency-check/Dependency-Check_Action@main
with:
project: 'AIOTAGRO Frontend'
path: '.'
format: 'HTML'
- name: Upload report
uses: actions/upload-artifact@v3
with:
name: security-reports
path: reports/
```
### 2. 安全更新
#### 自动更新脚本
```bash
#!/bin/bash
# security-update.sh
set -e
echo "开始安全更新..."
# 更新系统包
sudo apt update
sudo apt upgrade -y
# 更新 Node.js 依赖
pnpm update --latest
# 运行安全审计
pnpm audit
# 修复安全漏洞
if pnpm audit | grep -q "high"; then
echo "发现高危漏洞,尝试修复..."
pnpm audit fix
fi
# 重新构建应用
pnpm build:antd
# 重启服务
sudo systemctl restart nginx
echo "安全更新完成"
```
## 备份和恢复
### 1. 自动化备份
#### 完整备份脚本
```bash
#!/bin/bash
# full-backup.sh
set -e
BACKUP_DIR="/opt/aiotagro/backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="aiotagro_full_backup_$TIMESTAMP.tar.gz"
echo "开始完整备份..."
# 创建备份目录
mkdir -p "$BACKUP_DIR"
# 备份应用代码
echo "备份应用代码..."
tar -czf "$BACKUP_DIR/app_$TIMESTAMP.tar.gz" \
--exclude=node_modules \
--exclude=dist \
--exclude=.git \
/opt/aiotagro/frontend
# 备份配置文件
echo "备份配置文件..."
tar -czf "$BACKUP_DIR/config_$TIMESTAMP.tar.gz" \
/etc/nginx \
/etc/systemd/system/aiotagro.service
# 备份数据库(如果有)
# echo "备份数据库..."
# pg_dump -U postgres aiotagro > "$BACKUP_DIR/db_$TIMESTAMP.sql"
# 创建完整备份包
echo "创建完整备份包..."
tar -czf "$BACKUP_DIR/$BACKUP_FILE" \
"$BACKUP_DIR/app_$TIMESTAMP.tar.gz" \
"$BACKUP_DIR/config_$TIMESTAMP.tar.gz"
# 清理临时文件
rm -f "$BACKUP_DIR/app_$TIMESTAMP.tar.gz" \
"$BACKUP_DIR/config_$TIMESTAMP.tar.gz"
# 上传到云存储(可选)
# echo "上传到云存储..."
# aws s3 cp "$BACKUP_DIR/$BACKUP_FILE" s3://aiotagro-backups/
# 清理旧备份保留最近30天
find "$BACKUP_DIR" -name "aiotagro_full_backup_*.tar.gz" -mtime +30 -delete
echo "备份完成: $BACKUP_DIR/$BACKUP_FILE"
```
### 2. 灾难恢复
#### 恢复流程
```bash
#!/bin/bash
# disaster-recovery.sh
set -e
BACKUP_FILE="$1"
if [ -z "$BACKUP_FILE" ]; then
echo "用法: $0 <备份文件>"
exit 1
fi
echo "开始灾难恢复..."
# 停止服务
sudo systemctl stop nginx
# 解压备份文件
tar -xzf "$BACKUP_FILE" -C /tmp/
# 恢复应用代码
tar -xzf /tmp/app_*.tar.gz -C /
# 恢复配置文件
tar -xzf /tmp/config_*.tar.gz -C /
# 重新加载系统配置
sudo systemctl daemon-reload
# 启动服务
sudo systemctl start nginx
# 验证恢复
sleep 5
if curl -f http://localhost/ > /dev/null 2>&1; then
echo "恢复成功"
else
echo "恢复失败,请检查日志"
exit 1
fi
# 清理临时文件
rm -rf /tmp/app_*.tar.gz /tmp/config_*.tar.gz
echo "灾难恢复完成"
```
## 日常维护
### 1. 维护检查清单
#### 每日检查
- [ ] 系统资源使用情况
- [ ] 服务运行状态
- [ ] 错误日志检查
- [ ] 备份状态验证
- [ ] 安全告警检查
#### 每周检查
- [ ] 性能指标分析
- [ ] 安全漏洞扫描
- [ ] 日志文件清理
- [ ] 备份文件验证
- [ ] 系统更新检查
#### 每月检查
- [ ] 容量规划评估
- [ ] 安全审计
- [ ] 性能优化评估
- [ ] 灾难恢复演练
- [ ] 文档更新
通过以上运维配置和流程AIOTAGRO 管理系统可以实现稳定安全高效的运维管理

767
docs/部署文档.md Normal file
View File

@@ -0,0 +1,767 @@
# 部署文档
## 部署概述
AIOTAGRO 管理系统支持多种部署方式,包括开发环境部署、测试环境部署和生产环境部署。本文档详细说明各种部署场景的配置和步骤。
## 环境要求
### 服务器要求
| 环境 | CPU | 内存 | 磁盘 | 网络 |
|------|-----|------|------|------|
| 开发环境 | 2核 | 4GB | 20GB | 10Mbps |
| 测试环境 | 4核 | 8GB | 50GB | 50Mbps |
| 生产环境 | 8核 | 16GB | 100GB | 100Mbps |
### 软件要求
| 软件 | 版本 | 说明 |
|------|------|------|
| Node.js | 18.0.0+ | JavaScript 运行时 |
| pnpm | 8.0.0+ | 包管理器 |
| Nginx | 1.20.0+ | Web 服务器 |
| Git | 2.30.0+ | 版本控制 |
## 开发环境部署
### 本地开发环境
#### 1. 环境准备
```bash
# 安装 Node.js
# 访问 https://nodejs.org/ 下载安装包
# 安装 pnpm
npm install -g pnpm
# 验证安装
node --version
pnpm --version
```
#### 2. 项目初始化
```bash
# 克隆项目
git clone https://github.com/aiotagro/yudao-ui-admin-vben.git
cd yudao-ui-admin-vben
# 安装依赖
pnpm install
# 启动开发服务器
pnpm dev:antd
```
#### 3. 访问应用
打开浏览器访问: http://localhost:3000
### Docker 开发环境
#### 1. Dockerfile 配置
```dockerfile
# Dockerfile.dev
FROM node:18-alpine
WORKDIR /app
# 复制 package.json 和 pnpm-lock.yaml
COPY package.json pnpm-lock.yaml ./
# 安装依赖
RUN npm install -g pnpm && pnpm install
# 复制源代码
COPY . .
# 暴露端口
EXPOSE 3000
# 启动开发服务器
CMD ["pnpm", "dev:antd"]
```
#### 2. docker-compose 配置
```yaml
# docker-compose.dev.yml
version: '3.8'
services:
frontend:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
volumes:
- .:/app
- /app/node_modules
environment:
- NODE_ENV=development
```
#### 3. 启动服务
```bash
# 构建并启动服务
docker-compose -f docker-compose.dev.yml up --build
# 后台运行
docker-compose -f docker-compose.dev.yml up -d
```
## 测试环境部署
### 手动部署
#### 1. 服务器准备
```bash
# 登录服务器
ssh user@test-server
# 创建项目目录
mkdir -p /opt/aiotagro/frontend
cd /opt/aiotagro/frontend
# 克隆代码
git clone https://github.com/aiotagro/yudao-ui-admin-vben.git .
```
#### 2. 环境配置
```bash
# 安装 Node.js
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
# 安装 pnpm
npm install -g pnpm
# 安装依赖
pnpm install
```
#### 3. 构建应用
```bash
# 构建生产版本
pnpm build:antd
# 检查构建结果
ls -la dist/
```
#### 4. 配置 Nginx
```nginx
# /etc/nginx/sites-available/aiotagro-test
server {
listen 80;
server_name test.aiotagro.com;
root /opt/aiotagro/frontend/dist;
index index.html;
# Gzip 压缩
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# 静态资源缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# SPA 路由支持
location / {
try_files $uri $uri/ /index.html;
}
# API 代理
location /api/ {
proxy_pass http://backend-server:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
```
#### 5. 启用站点
```bash
# 创建符号链接
sudo ln -s /etc/nginx/sites-available/aiotagro-test /etc/nginx/sites-enabled/
# 测试配置
sudo nginx -t
# 重启 Nginx
sudo systemctl restart nginx
```
### 自动化部署脚本
```bash
#!/bin/bash
# deploy-test.sh
set -e
# 配置变量
PROJECT_DIR="/opt/aiotagro/frontend"
BACKUP_DIR="/opt/aiotagro/backups"
BRANCH="test"
echo "开始部署 AIOTAGRO 测试环境..."
# 备份当前版本
if [ -d "$PROJECT_DIR" ]; then
echo "备份当前版本..."
timestamp=$(date +%Y%m%d_%H%M%S)
tar -czf "$BACKUP_DIR/frontend_$timestamp.tar.gz" -C "$PROJECT_DIR" .
fi
# 更新代码
cd "$PROJECT_DIR"
git fetch origin
git checkout "$BRANCH"
git pull origin "$BRANCH"
# 安装依赖
echo "安装依赖..."
pnpm install
# 构建应用
echo "构建应用..."
pnpm build:antd
# 重启服务
echo "重启服务..."
sudo systemctl restart nginx
echo "部署完成!"
```
## 生产环境部署
### 高可用架构
#### 1. 负载均衡配置
```nginx
# /etc/nginx/nginx.conf
upstream aiogatro_backend {
server 10.0.1.10:8080 weight=3;
server 10.0.1.11:8080 weight=2;
server 10.0.1.12:8080 weight=2;
keepalive 32;
}
server {
listen 80;
server_name aiotagro.com www.aiotagro.com;
# 重定向到 HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name aiotagro.com www.aiotagro.com;
# SSL 配置
ssl_certificate /etc/ssl/certs/aiotagro.crt;
ssl_certificate_key /etc/ssl/private/aiotagro.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
root /var/www/aiotagro/dist;
index index.html;
# 安全头
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
# 静态资源
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header Vary Accept-Encoding;
}
# API 代理
location /api/ {
proxy_pass http://aiogatro_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
# SPA 路由
location / {
try_files $uri $uri/ /index.html;
}
}
```
### 容器化部署
#### 1. Docker 生产配置
```dockerfile
# Dockerfile.prod
FROM node:18-alpine AS builder
WORKDIR /app
# 复制依赖文件
COPY package.json pnpm-lock.yaml ./
RUN npm install -g pnpm && pnpm install --frozen-lockfile
# 复制源代码
COPY . .
# 构建应用
RUN pnpm build:antd
# 生产阶段
FROM nginx:alpine
# 复制构建结果
COPY --from=builder /app/dist /usr/share/nginx/html
# 复制 Nginx 配置
COPY nginx.conf /etc/nginx/nginx.conf
# 暴露端口
EXPOSE 80
# 启动 Nginx
CMD ["nginx", "-g", "daemon off;"]
```
#### 2. Kubernetes 部署
```yaml
# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: aiotagro-frontend
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: aiotagro-frontend
template:
metadata:
labels:
app: aiotagro-frontend
spec:
containers:
- name: frontend
image: aiotagro/frontend:latest
ports:
- containerPort: 80
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: aiotagro-frontend-service
namespace: production
spec:
selector:
app: aiotagro-frontend
ports:
- port: 80
targetPort: 80
type: LoadBalancer
```
### 自动化部署流程
#### 1. CI/CD 配置
```yaml
# .github/workflows/deploy.yml
name: Deploy to Production
on:
push:
branches: [ main ]
workflow_dispatch:
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'pnpm'
- name: Install dependencies
run: pnpm install
- name: Run tests
run: pnpm test
- name: Build application
run: pnpm build:antd
- name: Build Docker image
run: |
docker build -t $REGISTRY/$IMAGE_NAME:${{ github.sha }} .
- name: Push Docker image
run: |
echo ${{ secrets.GITHUB_TOKEN }} | docker login $REGISTRY -u ${{ github.actor }} --password-stdin
docker push $REGISTRY/$IMAGE_NAME:${{ github.sha }}
- name: Deploy to production
run: |
# 部署到生产环境
ssh deploy@production-server << EOF
docker pull $REGISTRY/$IMAGE_NAME:${{ github.sha }}
docker stop aiotagro-frontend || true
docker rm aiotagro-frontend || true
docker run -d --name aiotagro-frontend -p 80:80 $REGISTRY/$IMAGE_NAME:${{ github.sha }}
EOF
```
## 监控和日志
### 1. 应用监控配置
```javascript
// src/utils/monitoring.js
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals'
export const initMonitoring = () => {
// 性能监控
getCLS(console.log)
getFID(console.log)
getFCP(console.log)
getLCP(console.log)
getTTFB(console.log)
// 错误监控
window.addEventListener('error', (event) => {
console.error('JavaScript Error:', event.error)
// 发送到监控服务
sendToMonitoringService({
type: 'error',
message: event.error.message,
stack: event.error.stack,
timestamp: new Date().toISOString()
})
})
// 未处理的 Promise 拒绝
window.addEventListener('unhandledrejection', (event) => {
console.error('Unhandled Promise Rejection:', event.reason)
sendToMonitoringService({
type: 'promise_rejection',
reason: event.reason,
timestamp: new Date().toISOString()
})
})
}
const sendToMonitoringService = (data) => {
// 发送到监控服务
fetch('/api/monitoring', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
}).catch(console.error)
}
```
### 2. 日志配置
```nginx
# Nginx 日志配置
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'rt=$request_time uct="$upstream_connect_time" '
'uht="$upstream_header_time" urt="$upstream_response_time"';
access_log /var/log/nginx/aiotagro-access.log main;
error_log /var/log/nginx/aiotagro-error.log warn;
```
## 备份和恢复
### 1. 备份策略
```bash
#!/bin/bash
# backup.sh
set -e
BACKUP_DIR="/opt/aiotagro/backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="aiotagro_backup_$TIMESTAMP.tar.gz"
echo "开始备份 AIOTAGRO 系统..."
# 备份应用代码
tar -czf "$BACKUP_DIR/$BACKUP_FILE" \
--exclude=node_modules \
--exclude=dist \
--exclude=.git \
/opt/aiotagro/frontend
# 备份 Nginx 配置
tar -czf "$BACKUP_DIR/nginx_config_$TIMESTAMP.tar.gz" /etc/nginx
# 清理旧备份保留最近7天
find "$BACKUP_DIR" -name "aiotagro_backup_*.tar.gz" -mtime +7 -delete
find "$BACKUP_DIR" -name "nginx_config_*.tar.gz" -mtime +7 -delete
echo "备份完成: $BACKUP_DIR/$BACKUP_FILE"
```
### 2. 恢复策略
```bash
#!/bin/bash
# restore.sh
set -e
BACKUP_FILE="$1"
if [ -z "$BACKUP_FILE" ]; then
echo "Usage: $0 <backup_file>"
exit 1
fi
echo "开始恢复 AIOTAGRO 系统..."
# 停止服务
sudo systemctl stop nginx
# 恢复应用代码
tar -xzf "$BACKUP_FILE" -C /
# 恢复 Nginx 配置(可选)
# tar -xzf "nginx_config_*.tar.gz" -C /
# 启动服务
sudo systemctl start nginx
echo "恢复完成"
```
## 故障排除
### 常见问题
#### 1. 构建失败
**问题**: pnpm build 失败
**解决方案**:
```bash
# 清理缓存
pnpm clean
# 重新安装依赖
pnpm install --force
# 重新构建
pnpm build:antd
```
#### 2. Nginx 配置错误
**问题**: Nginx 启动失败
**解决方案**:
```bash
# 检查配置
sudo nginx -t
# 查看错误日志
sudo tail -f /var/log/nginx/error.log
```
#### 3. 证书问题
**问题**: SSL 证书错误
**解决方案**:
```bash
# 检查证书权限
sudo chmod 600 /etc/ssl/private/aiotagro.key
# 重新加载 Nginx
sudo systemctl reload nginx
```
## 性能优化
### 1. 构建优化
```javascript
// vite.config.js
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'vue-router', 'pinia'],
ui: ['ant-design-vue', '@ant-design/icons-vue'],
utils: ['lodash', 'dayjs', 'axios']
}
}
}
}
})
```
### 2. 缓存策略
```nginx
# 静态资源缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header Vary Accept-Encoding;
}
# API 缓存
location /api/ {
proxy_cache api_cache;
proxy_cache_valid 200 302 5m;
proxy_cache_valid 404 1m;
add_header X-Cache-Status $upstream_cache_status;
}
```
## 安全配置
### 1. 安全头设置
```nginx
# 安全头配置
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'";
```
### 2. 访问控制
```nginx
# IP 限制
location /admin/ {
allow 192.168.1.0/24;
allow 10.0.0.0/8;
deny all;
}
# 速率限制
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
location /api/ {
limit_req zone=api burst=20 nodelay;
}
```
## 更新和维护
### 1. 定期更新
```bash
#!/bin/bash
# update.sh
set -e
echo "开始更新 AIOTAGRO 系统..."
# 更新代码
cd /opt/aiotagro/frontend
git pull origin main
# 更新依赖
pnpm install
# 构建应用
pnpm build:antd
# 重启服务
sudo systemctl restart nginx
echo "更新完成"
```
### 2. 健康检查
```bash
#!/bin/bash
# health-check.sh
set -e
URL="https://aiotagro.com"
TIMEOUT=10
response=$(curl -s -o /dev/null -w "%{http_code}" --max-time $TIMEOUT $URL)
if [ "$response" -eq 200 ]; then
echo "健康检查通过: $URL"
exit 0
else
echo "健康检查失败: $URL (状态码: $response)"
exit 1
fi
```
通过以上配置和脚本AIOTAGRO 管理系统可以实现稳定、安全、高效的部署和运维。

286
docs/项目架构文档.md Normal file
View File

@@ -0,0 +1,286 @@
# 项目架构文档
## 系统架构概述
yudao-ui-admin-vben 采用现代化的前端架构设计,基于 Vue3 + TypeScript + Monorepo 技术栈,提供可扩展、高性能的企业级管理系统解决方案。
## 整体架构
### 架构图
```mermaid
graph TB
A[用户界面] --> B[应用层]
B --> C[业务逻辑层]
C --> D[数据访问层]
D --> E[后端API]
F[构建工具] --> G[打包优化]
G --> H[部署发布]
I[开发工具] --> J[代码检查]
J --> K[测试验证]
```
### 技术栈分层
| 层级 | 技术栈 | 说明 |
|------|--------|------|
| 表现层 | Vue3 + TypeScript | 用户界面渲染 |
| 应用层 | Vue Router + Pinia | 路由和状态管理 |
| 工具层 | Vite + ESLint | 构建和代码检查 |
| 基础设施 | Node.js + pnpm | 运行环境和包管理 |
## Monorepo 架构设计
### 项目结构
```
yudao-ui-admin-vben/
├── apps/ # 应用目录
│ ├── web-antd/ # Ant Design 版本应用
│ ├── web-ele/ # Element Plus 版本应用
│ ├── web-naive/ # Naive UI 版本应用
│ └── backend-mock/ # 后端模拟服务
├── packages/ # 共享包目录
│ ├── @core/ # 核心功能包
│ ├── constants/ # 常量定义包
│ ├── effects/ # 副作用管理包
│ ├── icons/ # 图标库包
│ ├── locales/ # 国际化资源包
│ ├── stores/ # 状态管理包
│ ├── styles/ # 样式文件包
│ ├── types/ # 类型定义包
│ └── utils/ # 工具函数包
├── internal/ # 内部配置目录
│ ├── lint-configs/ # 代码规范配置
│ ├── tailwind-config/ # Tailwind 配置
│ ├── tsconfig/ # TypeScript 配置
│ └── vite-config/ # Vite 配置
└── scripts/ # 脚本工具目录
```
### 包依赖关系
```mermaid
graph LR
A[apps/web-antd] --> B[packages/@core]
A --> C[packages/stores]
A --> D[packages/utils]
B --> E[packages/types]
C --> E
D --> E
F[apps/web-ele] --> B
F --> C
F --> D
G[apps/web-naive] --> B
G --> C
G --> D
```
## 核心模块设计
### 1. 应用模块 (apps/)
#### 功能特性
- **多主题支持**: 同一套业务逻辑,不同 UI 表现
- **独立部署**: 每个应用可独立构建部署
- **共享代码**: 通过 packages 共享公共逻辑
#### 技术实现
- Vue3 Composition API
- TypeScript 类型安全
- Vite 快速构建
- 热重载开发体验
### 2. 核心包模块 (packages/@core)
#### 基础功能
- 基础组件封装
- 工具函数集合
- 类型定义扩展
- 配置管理
#### 设计原则
- 单一职责原则
- 依赖倒置原则
- 接口隔离原则
- 开闭原则
### 3. 状态管理模块 (packages/stores)
#### 状态分类
- 用户状态 (用户信息、权限)
- 应用状态 (主题、语言、布局)
- 业务状态 (页面数据、表单状态)
#### 技术实现
- Pinia 状态管理
- 持久化存储
- 类型安全的状态访问
### 4. 工具模块 (packages/utils)
#### 工具分类
- 数据处理工具
- 日期时间工具
- 表单验证工具
- 网络请求工具
## 数据流设计
### 单向数据流
```
用户操作 → 组件事件 → Action → Mutation → State → 组件更新
```
### 异步数据流
```
组件挂载 → 发起请求 → 加载状态 → 数据处理 → 更新状态 → 界面渲染
```
## 路由设计
### 路由结构
```
/ # 首页
/login # 登录页
/dashboard # 仪表板
/system # 系统管理
/system/user # 用户管理
/system/role # 角色管理
/system/menu # 菜单管理
```
### 路由守卫
- 登录状态验证
- 权限验证
- 路由拦截
- 页面标题设置
## 权限设计
### RBAC 权限模型
- 用户 (User)
- 角色 (Role)
- 权限 (Permission)
- 菜单 (Menu)
### 权限控制级别
- 页面级权限
- 按钮级权限
- 数据级权限
- 功能级权限
## 构建部署架构
### 开发环境
- Vite 开发服务器
- 热重载支持
- Source Map 调试
### 生产环境
- Vite 生产构建
- 代码分割优化
- 资源压缩处理
- CDN 部署支持
### 部署策略
- 静态资源部署
- 多环境配置
- 版本控制
- 回滚机制
## 性能优化策略
### 构建优化
- 代码分割
- 树摇优化
- 懒加载
- 预加载
### 运行时优化
- 虚拟滚动
- 防抖节流
- 缓存策略
- 图片优化
## 安全架构
### 前端安全
- XSS 防护
- CSRF 防护
- 数据加密
- 输入验证
### 权限安全
- JWT 令牌
- 路由守卫
- API 权限验证
- 数据权限控制
## 扩展性设计
### 插件系统
- 组件插件化
- 功能模块化
- 配置可扩展
- 主题可定制
### 微前端支持
- 模块联邦
- 独立部署
- 技术栈无关
- 团队协作
## 监控运维
### 性能监控
- 页面加载时间
- 接口响应时间
- 错误监控
- 用户行为分析
### 日志系统
- 操作日志
- 错误日志
- 性能日志
- 安全日志
## 技术选型理由
### Vue3 优势
- 更好的性能
- 更好的 TypeScript 支持
- 更小的包体积
- 更好的开发体验
### Monorepo 优势
- 代码共享方便
- 版本管理统一
- 构建优化明显
- 团队协作高效
### Vite 优势
- 极速的冷启动
- 快速的热更新
- 丰富的插件生态
- 优化的生产构建
## 架构演进规划
### 短期目标
- 完善现有功能
- 优化性能体验
- 丰富文档体系
### 长期目标
- 微前端架构支持
- 低代码平台集成
- AI 辅助开发
- 云原生部署

143
docs/项目需求文档.md Normal file
View File

@@ -0,0 +1,143 @@
# 项目需求文档
## 项目概述
yudao-ui-admin-vben 是一个基于 Vue3 + TypeScript 的企业级管理系统框架,旨在为开发者提供快速构建现代化管理后台的完整解决方案。
## 业务需求
### 核心功能需求
#### 1. 用户管理
- ✅ 用户登录/注册
- ✅ 用户信息管理
- ✅ 权限控制
- ✅ 角色管理
#### 2. 系统管理
- ✅ 菜单管理
- ✅ 权限配置
- ✅ 系统设置
- ✅ 日志管理
#### 3. 数据管理
- ✅ 数据表格展示
- ✅ 数据增删改查
- ✅ 数据导入导出
- ✅ 数据筛选排序
#### 4. 界面管理
- ✅ 多主题切换
- ✅ 响应式布局
- ✅ 国际化支持
- ✅ 自定义配置
### 技术需求
#### 1. 前端技术栈
- ✅ Vue3 + TypeScript
- ✅ Vite 构建工具
- ✅ Pinia 状态管理
- ✅ Vue Router 路由管理
#### 2. UI 组件库
- ✅ Ant Design Vue
- ✅ Element Plus
- ✅ Naive UI
#### 3. 开发工具
- ✅ ESLint 代码检查
- ✅ Prettier 代码格式化
- ✅ TypeScript 类型检查
- ✅ 单元测试支持
## 非功能性需求
### 性能需求
- 页面加载时间 < 3秒
- 首屏渲染时间 < 1秒
- 支持 1000+ 数据量展示
### 安全性需求
- XSS 攻击防护
- CSRF 攻击防护
- 数据加密传输
- 权限验证机制
### 兼容性需求
- 支持 Chrome 80+
- 支持 Firefox 75+
- 支持 Safari 13+
- 支持 Edge 80+
## 项目范围
### 包含功能
- 基础管理系统框架
- 多主题 UI 组件
- 完整的权限系统
- 开发工具链配置
- 文档系统
### 不包含功能
- 具体业务逻辑实现
- 后端 API 服务
- 数据库设计
- 部署运维服务
## 项目里程碑
### 第一阶段:基础框架
- [x] 项目初始化
- [x] 基础架构搭建
- [x] 核心功能开发
### 第二阶段:功能完善
- [x] 多主题支持
- [x] 权限系统
- [x] 国际化支持
### 第三阶段:优化发布
- [x] 性能优化
- [x] 文档完善
- [x] 版本发布
## 验收标准
### 功能验收
- 所有核心功能正常运行
- 界面交互流畅无卡顿
- 权限控制准确无误
- 多主题切换正常
### 技术验收
- 代码符合规范标准
- 类型检查无错误
- 测试覆盖率达标
- 构建部署成功
## 风险分析
### 技术风险
- 新技术栈学习成本
- 浏览器兼容性问题
- 性能优化挑战
### 管理风险
- 项目进度控制
- 需求变更管理
- 团队协作效率
## 附录
### 术语表
- **Monorepo**: 单一代码仓库管理多个项目
- **Vite**: 下一代前端构建工具
- **Pinia**: Vue 状态管理库
- **TypeScript**: JavaScript 的超集添加类型系统
### 参考资料
- Vue3 官方文档
- TypeScript 官方文档
- Vite 官方文档
- UI 组件库文档