初始化
This commit is contained in:
869
docs/architecture/api-contracts.md
Normal file
869
docs/architecture/api-contracts.md
Normal file
@@ -0,0 +1,869 @@
|
||||
# API Contracts — Hyperf RESTful API 契约
|
||||
|
||||
> 定义 API 设计规范和端点文档。AI Agent 在生成 Controller 和前端 API 调用时参考本文档。
|
||||
>
|
||||
> **服务对象标注说明**:
|
||||
> - 🟦 `[user]` — 仅用户端(`Case-Database-Frontend-user/`)调用
|
||||
> - 🟧 `[admin]` — 仅管理端(`Case-Database-Frontend-admin/`)调用
|
||||
> - 🟩 `[both]` — 两个前端均可调用
|
||||
|
||||
---
|
||||
|
||||
## 1. 通用规范
|
||||
|
||||
### Base URL
|
||||
```
|
||||
# 管理端 API
|
||||
开发: http://localhost:9501/admin
|
||||
生产: https://api.example.com/admin
|
||||
|
||||
# 用户端 API
|
||||
开发: http://localhost:9501/api
|
||||
生产: https://api.example.com/api
|
||||
```
|
||||
|
||||
### 统一响应格式
|
||||
|
||||
**成功**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "ok",
|
||||
"data": {}
|
||||
}
|
||||
```
|
||||
|
||||
**列表(带分页)**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "ok",
|
||||
"data": {
|
||||
"items": [],
|
||||
"total": 100
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**错误**
|
||||
```json
|
||||
{
|
||||
"code": 422,
|
||||
"message": "Validation failed",
|
||||
"data": {
|
||||
"errors": {
|
||||
"email": ["The email field is required."]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### HTTP 状态码
|
||||
|
||||
| 状态码 | 含义 |
|
||||
|--------|------|
|
||||
| 200 | 成功 |
|
||||
| 201 | 创建成功 |
|
||||
| 400 | 请求参数错误 |
|
||||
| 401 | 未认证 (Token 无效/过期) |
|
||||
| 403 | 无权限 |
|
||||
| 404 | 资源不存在 |
|
||||
| 409 | 资源冲突 (锁定) |
|
||||
| 422 | 验证失败 |
|
||||
| 429 | 请求频率过高 |
|
||||
| 500 | 服务器内部错误 |
|
||||
|
||||
### 认证
|
||||
|
||||
所有需要认证的接口在 Header 中携带:
|
||||
```
|
||||
Authorization: Bearer <access_token>
|
||||
```
|
||||
|
||||
Token 过期返回 `401`,客户端用 Refresh Token 刷新。
|
||||
|
||||
### 分页参数
|
||||
|
||||
| 参数 | 类型 | 默认值 | 说明 |
|
||||
|------|------|--------|------|
|
||||
| `page` | int | 1 | 页码 |
|
||||
| `page_size` | int | 10 | 每页数量 (max: 100) |
|
||||
|
||||
### 排序参数
|
||||
|
||||
```
|
||||
?sort=created_at&order=desc
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 核心 API 端点
|
||||
|
||||
### 2.1 🟦 用户端认证 `[user]` — 16 端点
|
||||
|
||||
| 方法 | 路径 | 说明 | 认证 |
|
||||
|------|------|------|------|
|
||||
| POST | `/api/auth/captcha/challenge` | 获取图形验证码挑战(返回 `captcha_token`, `width`, `target_x`) | 否 |
|
||||
| POST | `/api/auth/captcha/verify` | 校验滑块位置(`captcha_token` + `answer_x`,tolerance=10px) | 否 |
|
||||
| POST | `/api/auth/register` | 用户注册 | 否 |
|
||||
| POST | `/api/auth/login` | 账号密码登录 | 否 |
|
||||
| POST | `/api/auth/sms/send` | 发送短信验证码 | 否 |
|
||||
| POST | `/api/auth/sms/login` | 短信验证码登录 | 否 |
|
||||
| POST | `/api/auth/forgot-password` | 忘记密码(账号/手机号校验后重置) | 否 |
|
||||
| POST | `/api/auth/logout` | 登出 | 是 |
|
||||
| POST | `/api/auth/refresh` | 刷新 Token | 否(需 Refresh Token) |
|
||||
| GET | `/api/auth/profile` | 当前用户信息 | 是 |
|
||||
| PUT | `/api/auth/profile` | 更新个人信息 | 是 |
|
||||
| GET | `/api/auth/sessions` | 获取当前账号会话列表 | 是 |
|
||||
| POST | `/api/auth/sessions/:sessionId/revoke` | 踢出指定会话 | 是 |
|
||||
| GET | `/api/auth/enterprise-sso/redirect` | 企业 SSO 跳转入口 | 否 |
|
||||
| POST | `/api/auth/enterprise-sso/callback` | 企业 SSO 回调登录 | 否 |
|
||||
| POST | `/api/auth/enterprise-sso/direct-login` | 企业平台直达登录(签名票据) | 否 |
|
||||
|
||||
#### 认证请求字段约定
|
||||
|
||||
- `/api/auth/register` 必填字段:`username`, `phone`, `sms_code`, `password`, `password_confirm`, `captcha_token`, `agree`。
|
||||
- `/api/auth/login` 必填字段:`username_or_phone`, `password`, `captcha_token`。
|
||||
- `/api/auth/sms/send` 必填字段:`phone`, `captcha_token`。
|
||||
- `/api/auth/sms/login` 必填字段:`phone`, `code`, `captcha_token`。
|
||||
- `/api/auth/forgot-password` 必填字段:`username_or_phone`, `phone`, `sms_code`, `new_password`, `new_password_confirm`, `captcha_token`。
|
||||
- 协议同意字段:`agree=true`,并由后端记录 `agree_at` 与 `agreement_version`。
|
||||
|
||||
#### 认证限流策略
|
||||
|
||||
| 接口 | 限流规则 |
|
||||
|------|----------|
|
||||
| 登录 `/api/auth/login` | 同 IP 5 次/分钟;同账号 10 次/小时 |
|
||||
| 短信发送 `/api/auth/sms/send` | 同手机号 1 次/分钟,5 次/天 |
|
||||
| 注册 `/api/auth/register` | 同 IP 3 次/小时 |
|
||||
| 找回密码 `/api/auth/forgot-password` | 同账号 3 次/天 |
|
||||
|
||||
#### 第三方登录
|
||||
|
||||
| 方法 | 路径 | 说明 | 认证 |
|
||||
|------|------|------|------|
|
||||
| GET | `/api/auth/oauth/:provider` | OAuth 跳转(provider: wechat / qq) | 否 |
|
||||
| GET | `/api/auth/oauth/:provider/callback` | OAuth 回调 | 否 |
|
||||
|
||||
---
|
||||
|
||||
### 2.2 🟦 用户端案例 `[user]` — 8 端点
|
||||
|
||||
| 方法 | 路径 | 说明 | 认证 |
|
||||
|------|------|------|------|
|
||||
| GET | `/api/cases` | 案例列表(支持多维筛选) | 否 |
|
||||
| GET | `/api/cases/:id` | 案例详情 | 否 |
|
||||
| GET | `/api/cases/:id/comments` | 案例评论列表 | 否 |
|
||||
| POST | `/api/cases/:id/comments` | 发表评论 | 是 |
|
||||
| POST | `/api/cases/:id/favorite` | 收藏 / 取消收藏 (toggle) | 是 |
|
||||
| POST | `/api/cases/:id/like` | 点赞 / 取消点赞 (toggle) | 是 |
|
||||
| GET | `/api/cases/:id/related` | 相关推荐案例 | 否 |
|
||||
| GET | `/api/cases/:id/files` | 案例文件列表(按阶段分组) | 否 |
|
||||
|
||||
#### 案例列表筛选参数
|
||||
|
||||
| 参数 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `category_id` | int | 建筑类型分类 |
|
||||
| `style` | string | 风格标签 slug |
|
||||
| `keyword` | string | 搜索关键词(标题 / 编号) |
|
||||
| `area_min` | number | 最小占地面积 |
|
||||
| `area_max` | number | 最大占地面积 |
|
||||
| `cost_min` | number | 最低造价 |
|
||||
| `cost_max` | number | 最高造价 |
|
||||
| `floors` | int | 层数 |
|
||||
| `bedroom_count` | int | 卧室数量 |
|
||||
| `site_width_min` | number | 最小面宽 |
|
||||
| `site_depth_min` | number | 最小进深 |
|
||||
| `tag_ids` | string | 标签 ID(逗号分隔) |
|
||||
| `is_featured` | boolean | 仅看精选 |
|
||||
| `sort` | string | 排序字段:`created_at` / `view_count` / `like_count` |
|
||||
| `order` | string | `asc` / `desc` |
|
||||
|
||||
---
|
||||
|
||||
### 2.3 🟦 用户端设计师 `[user]` — 4 端点
|
||||
|
||||
| 方法 | 路径 | 说明 | 认证 |
|
||||
|------|------|------|------|
|
||||
| GET | `/api/designers/:id` | 设计师详情 | 否 |
|
||||
| GET | `/api/designers/:id/cases` | 设计师作品集 | 否 |
|
||||
| POST | `/api/designers/:id/follow` | 关注 / 取消关注 (toggle) | 是 |
|
||||
| GET | `/api/designers/:id/awards` | 设计师荣誉奖项 | 否 |
|
||||
|
||||
---
|
||||
|
||||
### 2.4 🟦 用户端内容 `[user]` — 8 端点
|
||||
|
||||
| 方法 | 路径 | 说明 | 认证 |
|
||||
|------|------|------|------|
|
||||
| GET | `/api/banners` | 首页轮播列表 | 否 |
|
||||
| GET | `/api/categories` | 分类列表 | 否 |
|
||||
| GET | `/api/tags` | 标签列表(支持 `?type=style` 筛选) | 否 |
|
||||
| GET | `/api/tags/hot` | 热门标签 | 否 |
|
||||
| GET | `/api/topics` | 专题列表 | 否 |
|
||||
| GET | `/api/topics/:id` | 专题详情(含关联案例列表) | 否 |
|
||||
| POST | `/api/newsletter/subscribe` | 邮箱订阅 | 否 |
|
||||
| GET | `/api/my/favorites` | 我的收藏列表 | 是 |
|
||||
|
||||
---
|
||||
|
||||
### 2.5 🟧 管理端认证 `[admin]` — 4 端点
|
||||
|
||||
| 方法 | 路径 | 说明 | 认证 |
|
||||
|------|------|------|------|
|
||||
| POST | `/admin/auth/login` | 管理员登录 | 否 |
|
||||
| POST | `/admin/auth/logout` | 登出 | 是 |
|
||||
| POST | `/admin/auth/refresh` | 刷新 Token | 否(需 Refresh Token) |
|
||||
| GET | `/admin/auth/info` | 当前管理员信息(含角色权限) | 是 |
|
||||
|
||||
---
|
||||
|
||||
### 2.6 🟧 管理端案例管理 `[admin]` — 9 端点
|
||||
|
||||
| 方法 | 路径 | 说明 | 权限 |
|
||||
|------|------|------|------|
|
||||
| GET | `/admin/cases` | 案例列表(含草稿 / 待审 / 已发布 / 已归档筛选) | `case:list` |
|
||||
| GET | `/admin/cases/:id` | 案例详情 | `case:detail` |
|
||||
| POST | `/admin/cases` | 创建案例 | `case:create` |
|
||||
| PUT | `/admin/cases/:id` | 更新案例 | `case:update` |
|
||||
| DELETE | `/admin/cases/:id` | 删除案例(软删除) | `case:delete` |
|
||||
| PUT | `/admin/cases/:id/status` | 变更案例状态 | `case:status` |
|
||||
| PUT | `/admin/cases/:id/featured` | 精选标记 toggle | `case:feature` |
|
||||
| POST | `/admin/cases/:id/files` | 上传案例文件(分阶段) | `case:upload` |
|
||||
| DELETE | `/admin/cases/:id/files/:fileId` | 删除案例文件 | `case:upload` |
|
||||
|
||||
---
|
||||
|
||||
### 2.7 🟧 管理端轮播管理 `[admin]` — 5 端点
|
||||
|
||||
| 方法 | 路径 | 说明 | 权限 |
|
||||
|------|------|------|------|
|
||||
| GET | `/admin/banners` | 轮播列表 | `banner:list` |
|
||||
| POST | `/admin/banners` | 创建轮播 | `banner:create` |
|
||||
| PUT | `/admin/banners/:id` | 更新轮播 | `banner:update` |
|
||||
| DELETE | `/admin/banners/:id` | 删除轮播 | `banner:delete` |
|
||||
| PUT | `/admin/banners/sort` | 批量排序 | `banner:update` |
|
||||
|
||||
---
|
||||
|
||||
### 2.8 🟧 管理端专题管理 `[admin]` — 6 端点
|
||||
|
||||
| 方法 | 路径 | 说明 | 权限 |
|
||||
|------|------|------|------|
|
||||
| GET | `/admin/topics` | 专题列表 | `topic:list` |
|
||||
| POST | `/admin/topics` | 创建专题 | `topic:create` |
|
||||
| PUT | `/admin/topics/:id` | 更新专题 | `topic:update` |
|
||||
| DELETE | `/admin/topics/:id` | 删除专题 | `topic:delete` |
|
||||
| POST | `/admin/topics/:id/cases` | 关联案例到专题 | `topic:update` |
|
||||
| DELETE | `/admin/topics/:id/cases/:caseId` | 取消关联案例 | `topic:update` |
|
||||
|
||||
---
|
||||
|
||||
### 2.9 🟧 管理端分类标签 `[admin]` — 7 端点
|
||||
|
||||
| 方法 | 路径 | 说明 | 权限 |
|
||||
|------|------|------|------|
|
||||
| GET | `/admin/categories` | 分类列表 | `category:list` |
|
||||
| POST | `/admin/categories` | 创建分类 | `category:create` |
|
||||
| PUT | `/admin/categories/:id` | 更新分类 | `category:update` |
|
||||
| DELETE | `/admin/categories/:id` | 删除分类(需判断无关联案例) | `category:delete` |
|
||||
| GET | `/admin/tags` | 标签列表(支持 `?type=` 筛选) | `tag:list` |
|
||||
| POST | `/admin/tags` | 创建标签 | `tag:create` |
|
||||
| PUT | `/admin/tags/:id` | 更新标签 | `tag:update` |
|
||||
| DELETE | `/admin/tags/:id` | 删除标签 | `tag:delete` |
|
||||
|
||||
---
|
||||
|
||||
### 2.10 🟧 管理端设计师管理 `[admin]` — 5 端点
|
||||
|
||||
| 方法 | 路径 | 说明 | 权限 |
|
||||
|------|------|------|------|
|
||||
| GET | `/admin/designers` | 设计师列表 | `designer:list` |
|
||||
| POST | `/admin/designers` | 创建设计师 | `designer:create` |
|
||||
| PUT | `/admin/designers/:id` | 更新设计师 | `designer:update` |
|
||||
| DELETE | `/admin/designers/:id` | 删除设计师 | `designer:delete` |
|
||||
| PUT | `/admin/designers/:id/active` | 启用/停用设计师 | `designer:update` |
|
||||
|
||||
---
|
||||
|
||||
### 2.11 🟧 管理端评论管理 `[admin]` — 4 端点
|
||||
|
||||
| 方法 | 路径 | 说明 | 权限 |
|
||||
|------|------|------|------|
|
||||
| GET | `/admin/comments` | 评论列表(支持 `?status=pending` 筛选) | `comment:list` |
|
||||
| PUT | `/admin/comments/:id/approve` | 审核通过 | `comment:audit` |
|
||||
| PUT | `/admin/comments/:id/reject` | 审核拒绝 | `comment:audit` |
|
||||
| DELETE | `/admin/comments/:id` | 删除评论 | `comment:delete` |
|
||||
|
||||
---
|
||||
|
||||
### 2.12 🟧 管理端用户与权限 `[admin]` — 8 端点
|
||||
|
||||
| 方法 | 路径 | 说明 | 权限 |
|
||||
|------|------|------|------|
|
||||
| GET | `/admin/users` | 用户列表 | `user:list` |
|
||||
| POST | `/admin/users` | 创建管理员 | `user:create` |
|
||||
| PUT | `/admin/users/:id` | 更新用户 | `user:update` |
|
||||
| PUT | `/admin/users/:id/status` | 启用/禁用用户 | `user:update` |
|
||||
| GET | `/admin/roles` | 角色列表 | `role:list` |
|
||||
| POST | `/admin/roles` | 创建角色(含菜单权限分配) | `role:create` |
|
||||
| PUT | `/admin/roles/:id` | 更新角色 | `role:update` |
|
||||
| GET | `/admin/menus` | 菜单权限树 | `menu:list` |
|
||||
|
||||
---
|
||||
|
||||
### 2.13 🟧 管理端系统配置 `[admin]` — 2 端点
|
||||
|
||||
| 方法 | 路径 | 说明 | 权限 |
|
||||
|------|------|------|------|
|
||||
| GET | `/admin/configs` | 获取系统配置(支持 `?group=site` 筛选) | `config:list` |
|
||||
| PUT | `/admin/configs` | 批量更新系统配置 | `config:update` |
|
||||
|
||||
---
|
||||
|
||||
### 2.14 🟧 管理端数据仪表盘 `[admin]` — 3 端点
|
||||
|
||||
| 方法 | 路径 | 说明 | 权限 |
|
||||
|------|------|------|------|
|
||||
| GET | `/admin/dashboard/overview` | 概览统计(总案例数 / 总用户数 / 今日浏览量等) | `dashboard:view` |
|
||||
| GET | `/admin/dashboard/trends` | 趋势数据(按日/周/月的浏览 / 注册曲线) | `dashboard:view` |
|
||||
| GET | `/admin/dashboard/rankings` | 热门排行(案例浏览 TOP / 下载 TOP / 活跃设计师) | `dashboard:view` |
|
||||
|
||||
---
|
||||
|
||||
### 2.15 🟧 管理端日志 `[admin]` — 2 端点
|
||||
|
||||
| 方法 | 路径 | 说明 | 权限 |
|
||||
|------|------|------|------|
|
||||
| GET | `/admin/logs/operations` | 操作日志列表 | `log:list` |
|
||||
| GET | `/admin/logs/downloads` | 下载日志列表 | `log:list` |
|
||||
|
||||
---
|
||||
|
||||
### 2.16 🟩 通用上传 `[both]` — 1 端点
|
||||
|
||||
| 方法 | 路径 | 说明 | 认证 |
|
||||
|------|------|------|------|
|
||||
| POST | `/api/upload/image` | 上传图片(头像/封面/banner) | 是 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 请求/响应示例
|
||||
|
||||
### 3.1 管理端登录
|
||||
|
||||
```bash
|
||||
POST /admin/auth/login
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"username": "admin",
|
||||
"password": "password123"
|
||||
}
|
||||
|
||||
# Response 200
|
||||
{
|
||||
"code": 200,
|
||||
"message": "ok",
|
||||
"data": {
|
||||
"access_token": "eyJhbGci...",
|
||||
"refresh_token": "eyJhbGci...",
|
||||
"expires_in": 7200,
|
||||
"user": {
|
||||
"id": 1,
|
||||
"username": "admin",
|
||||
"nickname": "超级管理员",
|
||||
"avatar": "https://cdn.example.com/avatars/admin.jpg",
|
||||
"roles": ["super_admin"],
|
||||
"permissions": ["case:*", "banner:*", "topic:*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 用户端登录(账号密码)
|
||||
|
||||
```bash
|
||||
POST /api/auth/login
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"phone": "13800138000",
|
||||
"password": "password123"
|
||||
}
|
||||
|
||||
# Response 200
|
||||
{
|
||||
"code": 200,
|
||||
"message": "ok",
|
||||
"data": {
|
||||
"access_token": "eyJhbGci...",
|
||||
"refresh_token": "eyJhbGci...",
|
||||
"expires_in": 7200,
|
||||
"user": {
|
||||
"id": 42,
|
||||
"nickname": "建筑师小李",
|
||||
"avatar": "https://cdn.example.com/avatars/42.jpg",
|
||||
"phone": "138****8000",
|
||||
"role_label": "Architect"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3 用户端短信登录
|
||||
|
||||
```bash
|
||||
# Step 1: 发送验证码
|
||||
POST /api/auth/sms/send
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"phone": "13800138000"
|
||||
}
|
||||
|
||||
# Response 200
|
||||
{
|
||||
"code": 200,
|
||||
"message": "验证码已发送",
|
||||
"data": {
|
||||
"expires_in": 300
|
||||
}
|
||||
}
|
||||
|
||||
# Step 2: 验证码登录
|
||||
POST /api/auth/sms/login
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"phone": "13800138000",
|
||||
"code": "123456"
|
||||
}
|
||||
|
||||
# Response 200 (同 3.2 登录响应)
|
||||
```
|
||||
|
||||
### 3.4 案例列表(多维筛选)
|
||||
|
||||
```bash
|
||||
GET /api/cases?category_id=1&style=modern&area_min=100&area_max=300&cost_max=60&floors=3&sort=created_at&order=desc&page=1&page_size=12
|
||||
Authorization: Bearer eyJhbGci... (可选)
|
||||
|
||||
# Response 200
|
||||
{
|
||||
"code": 200,
|
||||
"message": "ok",
|
||||
"data": {
|
||||
"items": [
|
||||
{
|
||||
"id": 88,
|
||||
"title": "云端墅 The Cloud Villa",
|
||||
"code": "P-2024-8839",
|
||||
"cover_image": "https://cdn.example.com/cases/88/cover.jpg",
|
||||
"category": {
|
||||
"id": 1,
|
||||
"name": "别墅",
|
||||
"slug": "villa"
|
||||
},
|
||||
"layout": "3室2厅3卫",
|
||||
"floors_above": 3,
|
||||
"site_area": 128.50,
|
||||
"total_building_area": 340.00,
|
||||
"cost_min": 45.00,
|
||||
"cost_max": 55.00,
|
||||
"architecture_style": "现代主义",
|
||||
"is_featured": true,
|
||||
"tags": [
|
||||
{ "id": 1, "name": "现代", "type": "style" },
|
||||
{ "id": 5, "name": "落地窗", "type": "feature" }
|
||||
],
|
||||
"lead_designer": {
|
||||
"id": 12,
|
||||
"name_cn": "张明远",
|
||||
"title_badge": "Lead Architect"
|
||||
},
|
||||
"view_count": 1234,
|
||||
"like_count": 56,
|
||||
"favorite_count": 23,
|
||||
"is_liked": false,
|
||||
"is_favorited": true,
|
||||
"published_at": "2024-12-15T10:00:00Z"
|
||||
}
|
||||
],
|
||||
"total": 156
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.5 案例详情
|
||||
|
||||
```bash
|
||||
GET /api/cases/88
|
||||
Authorization: Bearer eyJhbGci... (可选)
|
||||
|
||||
# Response 200
|
||||
{
|
||||
"code": 200,
|
||||
"message": "ok",
|
||||
"data": {
|
||||
"id": 88,
|
||||
"title": "云端墅 The Cloud Villa",
|
||||
"code": "P-2024-8839",
|
||||
"cover_image": "https://cdn.example.com/cases/88/cover.jpg",
|
||||
"category": { "id": 1, "name": "别墅", "slug": "villa" },
|
||||
"status": "published",
|
||||
"is_featured": true,
|
||||
"layout": "3室2厅3卫",
|
||||
"floor_height": "3.6/3.3/3.3m",
|
||||
|
||||
"dimensions": {
|
||||
"site": {
|
||||
"site_width": "面宽 ≥ 10.5m",
|
||||
"site_depth": "进深 ≥ 12.2m",
|
||||
"site_area": 128.50,
|
||||
"lighting_restriction": "南侧无遮挡",
|
||||
"site_shape": "规则矩形"
|
||||
},
|
||||
"scale": {
|
||||
"floors_above": 3,
|
||||
"floors_below": 1,
|
||||
"cost_min": 45.00,
|
||||
"cost_max": 55.00,
|
||||
"total_building_area": 340.00,
|
||||
"bedroom_count": 5,
|
||||
"bedroom_note": "含1主卧套房"
|
||||
},
|
||||
"function": {
|
||||
"stair_type": "旋转楼梯 + 电梯",
|
||||
"special_space": "地下影音室 / 露台花园",
|
||||
"bedroom_config": "主卧套房含衣帽间",
|
||||
"leisure_space": "屋顶露台 / 下沉式客厅",
|
||||
"kitchen_dining": "开放式西厨 + 独立中厨",
|
||||
"bathroom_config": "5卫 (含2套干湿分离)"
|
||||
},
|
||||
"appearance": {
|
||||
"architecture_style": "现代主义",
|
||||
"roof_type": "平屋顶 + 局部坡屋顶",
|
||||
"facade_material": "白色真石漆 + 深灰铝板"
|
||||
},
|
||||
"structure": {
|
||||
"structure_type": "框架结构",
|
||||
"foundation_type": "筏板基础",
|
||||
"layout_logic": "南北通透 / 动静分区",
|
||||
"wall_thickness": "240mm (外) + 120mm (内)",
|
||||
"seismic_rating": "7度设防",
|
||||
"insulation_type": "外墙外保温 EPS",
|
||||
"roof_structure": "SBS防水 + 挤塑板保温"
|
||||
}
|
||||
},
|
||||
|
||||
"design_concept": "<p>设计理念正文...</p>",
|
||||
"concept_style": "现代主义",
|
||||
"concept_material": "混凝土 / 玻璃 / 石材",
|
||||
"concept_target": "追求品质生活的年轻家庭",
|
||||
"meta": {},
|
||||
|
||||
"images": {
|
||||
"effect": [
|
||||
{ "id": 1, "url": "https://cdn.example.com/cases/88/effect-1.jpg", "thumbnail_url": "..." }
|
||||
],
|
||||
"floor_plan": [
|
||||
{ "id": 2, "url": "https://cdn.example.com/cases/88/plan-1f.jpg", "thumbnail_url": "..." }
|
||||
],
|
||||
"elevation": [
|
||||
{ "id": 3, "url": "https://cdn.example.com/cases/88/elev-south.jpg", "thumbnail_url": "..." }
|
||||
]
|
||||
},
|
||||
|
||||
"files": {
|
||||
"floor_plan": [
|
||||
{ "id": 1, "file_name": "一层平面图.dwg", "file_ext": "dwg", "file_size": 2048000 }
|
||||
],
|
||||
"exterior": [],
|
||||
"construction": [
|
||||
{ "id": 2, "file_name": "施工图全套.pdf", "file_ext": "pdf", "file_size": 15360000 }
|
||||
],
|
||||
"structure": [],
|
||||
"interior": [],
|
||||
"courtyard": []
|
||||
},
|
||||
|
||||
"team": [
|
||||
{
|
||||
"designer": {
|
||||
"id": 12,
|
||||
"name_cn": "张明远",
|
||||
"name_en": "Zhang Mingyuan",
|
||||
"title": "方案主创设计师",
|
||||
"title_badge": "Lead Architect",
|
||||
"portrait": "https://cdn.example.com/designers/12/portrait.jpg"
|
||||
},
|
||||
"role": "scheme",
|
||||
"is_lead": true
|
||||
},
|
||||
{
|
||||
"designer": {
|
||||
"id": 15,
|
||||
"name_cn": "李结构",
|
||||
"title": "结构工程师",
|
||||
"title_badge": "Structural Eng."
|
||||
},
|
||||
"role": "structure",
|
||||
"is_lead": false
|
||||
}
|
||||
],
|
||||
|
||||
"tags": [
|
||||
{ "id": 1, "name": "现代", "type": "style" },
|
||||
{ "id": 5, "name": "落地窗", "type": "feature" }
|
||||
],
|
||||
|
||||
"stats": {
|
||||
"view_count": 1234,
|
||||
"like_count": 56,
|
||||
"favorite_count": 23,
|
||||
"download_count": 8,
|
||||
"comment_count": 12
|
||||
},
|
||||
|
||||
"user_interaction": {
|
||||
"is_liked": false,
|
||||
"is_favorited": true
|
||||
},
|
||||
|
||||
"published_at": "2024-12-15T10:00:00Z",
|
||||
"created_at": "2024-12-10T08:00:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.6 管理端文件上传(分阶段)
|
||||
|
||||
```bash
|
||||
POST /admin/cases/88/files
|
||||
Authorization: Bearer eyJhbGci...
|
||||
Content-Type: multipart/form-data
|
||||
|
||||
# Form Data
|
||||
stage: construction
|
||||
file: (binary) 施工图全套.pdf
|
||||
|
||||
# Response 201
|
||||
{
|
||||
"code": 201,
|
||||
"message": "上传成功",
|
||||
"data": {
|
||||
"id": 156,
|
||||
"case_id": 88,
|
||||
"stage": "construction",
|
||||
"file_name": "施工图全套.pdf",
|
||||
"file_path": "cases/88/construction/施工图全套.pdf",
|
||||
"file_size": 15360000,
|
||||
"file_ext": "pdf",
|
||||
"mime_type": "application/pdf"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.7 管理端创建案例
|
||||
|
||||
```bash
|
||||
POST /admin/cases
|
||||
Authorization: Bearer eyJhbGci...
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"title": "云端墅 The Cloud Villa",
|
||||
"code": "P-2024-8839",
|
||||
"category_id": 1,
|
||||
"cover_image": "https://cdn.example.com/cases/88/cover.jpg",
|
||||
"layout": "3室2厅3卫",
|
||||
"floor_height": "3.6/3.3/3.3m",
|
||||
"site_width": "面宽 ≥ 10.5m",
|
||||
"site_depth": "进深 ≥ 12.2m",
|
||||
"site_area": 128.50,
|
||||
"floors_above": 3,
|
||||
"floors_below": 1,
|
||||
"cost_min": 45.00,
|
||||
"cost_max": 55.00,
|
||||
"total_building_area": 340.00,
|
||||
"bedroom_count": 5,
|
||||
"bedroom_note": "含1主卧套房",
|
||||
"architecture_style": "现代主义",
|
||||
"structure_type": "框架结构",
|
||||
"design_concept": "<p>设计理念正文...</p>",
|
||||
"tag_ids": [1, 5, 12],
|
||||
"team": [
|
||||
{ "designer_id": 12, "role": "scheme", "is_lead": true },
|
||||
{ "designer_id": 15, "role": "structure", "is_lead": false }
|
||||
]
|
||||
}
|
||||
|
||||
# Response 201
|
||||
{
|
||||
"code": 201,
|
||||
"message": "创建成功",
|
||||
"data": {
|
||||
"id": 88,
|
||||
"code": "P-2024-8839",
|
||||
"status": "draft"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.8 管理端案例状态变更
|
||||
|
||||
```bash
|
||||
PUT /admin/cases/88/status
|
||||
Authorization: Bearer eyJhbGci...
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"status": "published"
|
||||
}
|
||||
|
||||
# Response 200
|
||||
{
|
||||
"code": 200,
|
||||
"message": "状态已更新",
|
||||
"data": {
|
||||
"id": 88,
|
||||
"status": "published",
|
||||
"published_at": "2024-12-15T10:00:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.9 设计师详情
|
||||
|
||||
```bash
|
||||
GET /api/designers/12
|
||||
|
||||
# Response 200
|
||||
{
|
||||
"code": 200,
|
||||
"message": "ok",
|
||||
"data": {
|
||||
"id": 12,
|
||||
"name_cn": "张明远",
|
||||
"name_en": "Zhang Mingyuan",
|
||||
"title": "方案主创设计师",
|
||||
"title_badge": "Lead Architect",
|
||||
"company": "ZM 建筑事务所",
|
||||
"city": "上海",
|
||||
"portrait": "https://cdn.example.com/designers/12/portrait.jpg",
|
||||
"portrait_caption": "STUDIO PORTRAIT © 2023",
|
||||
"years_of_experience": 15,
|
||||
"project_count": 42,
|
||||
"design_philosophy_quote": "建筑是凝固的音乐",
|
||||
"design_philosophy": "<p>设计理念详述...</p>",
|
||||
"specialties": [
|
||||
{ "id": 20, "name": "参数化设计" },
|
||||
{ "id": 21, "name": "可持续建筑" }
|
||||
],
|
||||
"awards": [
|
||||
{
|
||||
"year": 2023,
|
||||
"title": "红点设计大奖 Red Dot Award",
|
||||
"description": "最佳室内设计类 - The Cloud Villa"
|
||||
},
|
||||
{
|
||||
"year": 2022,
|
||||
"title": "Architizer A+ Awards",
|
||||
"description": "住宅建筑类 - 山水间"
|
||||
}
|
||||
],
|
||||
"stats": {
|
||||
"follower_count": 326,
|
||||
"view_count": 8920,
|
||||
"project_count": 42
|
||||
},
|
||||
"user_interaction": {
|
||||
"is_followed": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.10 管理端创建轮播
|
||||
|
||||
```bash
|
||||
POST /admin/banners
|
||||
Authorization: Bearer eyJhbGci...
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"title": "云端墅 — 现代都市别墅的极致诠释",
|
||||
"description": "三层框架结构,340㎡ 全功能空间",
|
||||
"image": "https://cdn.example.com/banners/cloud-villa.jpg",
|
||||
"label": "精选项目",
|
||||
"link_type": "case",
|
||||
"link_url": "/cases/88",
|
||||
"sort": 1,
|
||||
"is_active": true
|
||||
}
|
||||
|
||||
# Response 201
|
||||
{
|
||||
"code": 201,
|
||||
"message": "创建成功",
|
||||
"data": {
|
||||
"id": 5,
|
||||
"title": "云端墅 — 现代都市别墅的极致诠释",
|
||||
"sort": 1,
|
||||
"is_active": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.11 管理端仪表盘概览
|
||||
|
||||
```bash
|
||||
GET /admin/dashboard/overview
|
||||
Authorization: Bearer eyJhbGci...
|
||||
|
||||
# Response 200
|
||||
{
|
||||
"code": 200,
|
||||
"message": "ok",
|
||||
"data": {
|
||||
"total_cases": 256,
|
||||
"published_cases": 198,
|
||||
"total_designers": 42,
|
||||
"total_users": 3680,
|
||||
"today_views": 1250,
|
||||
"today_registers": 15,
|
||||
"pending_comments": 8,
|
||||
"pending_cases": 3
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 端点汇总统计
|
||||
|
||||
| 分组 | 服务对象 | 端点数 |
|
||||
|------|----------|--------|
|
||||
| 用户端认证 | 🟦 user | 16 |
|
||||
| 用户端案例 | 🟦 user | 8 |
|
||||
| 用户端设计师 | 🟦 user | 4 |
|
||||
| 用户端内容 | 🟦 user | 8 |
|
||||
| 管理端认证 | 🟧 admin | 4 |
|
||||
| 管理端案例管理 | 🟧 admin | 9 |
|
||||
| 管理端轮播管理 | 🟧 admin | 5 |
|
||||
| 管理端专题管理 | 🟧 admin | 6 |
|
||||
| 管理端分类标签 | 🟧 admin | 8 |
|
||||
| 管理端设计师管理 | 🟧 admin | 5 |
|
||||
| 管理端评论管理 | 🟧 admin | 4 |
|
||||
| 管理端用户权限 | 🟧 admin | 8 |
|
||||
| 管理端系统配置 | 🟧 admin | 2 |
|
||||
| 管理端仪表盘 | 🟧 admin | 3 |
|
||||
| 管理端日志 | 🟧 admin | 2 |
|
||||
| 通用上传 | 🟩 both | 1 |
|
||||
| **合计** | | **93** |
|
||||
|
||||
---
|
||||
|
||||
*最后更新: 2026-02-28*
|
||||
748
docs/architecture/data-model.md
Normal file
748
docs/architecture/data-model.md
Normal file
@@ -0,0 +1,748 @@
|
||||
# Data Model — MySQL 数据建模
|
||||
|
||||
> 定义数据库表结构、关系和设计约定。AI Agent 在生成 Migration 和 Model 时参考本文档。
|
||||
|
||||
---
|
||||
|
||||
## 1. 设计原则
|
||||
|
||||
- 主键统一使用 `BIGINT UNSIGNED AUTO_INCREMENT`
|
||||
- 字符集 `utf8mb4`,排序规则 `utf8mb4_unicode_ci`
|
||||
- 所有表包含 `created_at`, `updated_at`, `deleted_at` (软删除)
|
||||
- 外键字段命名 `<table_singular>_id`,必须有索引
|
||||
- 金额字段使用 `DECIMAL(10,2)`
|
||||
- 状态字段使用 `VARCHAR(20)` 或 `TINYINT`(避免 ENUM)
|
||||
- 时间字段使用 `TIMESTAMP`
|
||||
- 排序字段使用 `INT UNSIGNED DEFAULT 0`
|
||||
|
||||
## 2. 命名规范
|
||||
|
||||
### 2.1 表命名规则
|
||||
|
||||
**表名必须以所属模块名作为前缀**(snake_case),格式:`<module>_<entity_plural>`。
|
||||
|
||||
| 模块 | 前缀 | 说明 |
|
||||
|------|------|------|
|
||||
| 用户与权限 | `auth_` | 用户、角色、菜单、OAuth 等 |
|
||||
| 案例核心 | `case_` | 案例主表、图库、文件、分类等 |
|
||||
| 设计师 | `designer_` | 设计师档案、奖项、标签关联等 |
|
||||
| 运营内容 | `operation_` | 轮播图、专题、标签字典等 |
|
||||
| 用户互动 | `interaction_` | 收藏、点赞、评论、关注、订阅等 |
|
||||
| 日志 | `log_` | 登录日志、操作日志、下载日志等 |
|
||||
| 安全风控 | `security_` | 黑名单、风控事件、会话等 |
|
||||
| 系统配置 | `system_` | 系统参数配置等 |
|
||||
|
||||
> **规则说明**:
|
||||
> - 同一业务域下的所有表使用相同前缀,避免不同模块表名冲突
|
||||
> - 多对多关联表同样需要加模块前缀:`<module>_<a>_belongs_<b>`
|
||||
> - 跨模块关联的中间表,以**主体模块**的前缀命名
|
||||
|
||||
### 2.2 通用命名约定
|
||||
|
||||
| 类型 | 规范 | 示例 |
|
||||
|------|------|------|
|
||||
| 表名 | `<module>_` 前缀 + snake_case 复数 | `case_cases`, `auth_users` |
|
||||
| 字段名 | snake_case | `total_building_area` |
|
||||
| 主键 | `id` | `BIGINT UNSIGNED` |
|
||||
| 外键 | `<singular>_id` | `case_id`, `designer_id` |
|
||||
| 索引 | `idx_<table>_<cols>` | `idx_case_cases_status` |
|
||||
| 唯一索引 | `uk_<table>_<cols>` | `uk_case_cases_code` |
|
||||
| 多对多关联表 | `<module>_<a>_belongs_<b>` | `case_case_belongs_tag` |
|
||||
| 布尔字段 | `is_<adj>` | `is_featured`, `is_active` |
|
||||
| 计数缓存 | `<noun>_count` | `view_count`, `like_count` |
|
||||
|
||||
### 2.3 各模块表名对照
|
||||
|
||||
| 当前表名 | 所属模块 | 规范表名 |
|
||||
|----------|----------|----------|
|
||||
| `users` | 用户与权限 | `auth_users` |
|
||||
| `oauth_bindings` | 用户与权限 | `auth_oauth_bindings` |
|
||||
| `roles` | 用户与权限 | `auth_roles` |
|
||||
| `menus` | 用户与权限 | `auth_menus` |
|
||||
| `user_belongs_role` | 用户与权限 | `auth_user_belongs_role` |
|
||||
| `role_belongs_menu` | 用户与权限 | `auth_role_belongs_menu` |
|
||||
| `categories` | 案例核心 | `case_categories` |
|
||||
| `tags` | 运营内容 | `operation_tags` |
|
||||
| `cases` | 案例核心 | `case_cases` |
|
||||
| `case_images` | 案例核心 | `case_images`(已有前缀) |
|
||||
| `case_files` | 案例核心 | `case_files`(已有前缀) |
|
||||
| `case_belongs_tag` | 案例核心 | `case_belongs_tag`(已有前缀) |
|
||||
| `case_team_members` | 案例核心 | `case_team_members`(已有前缀) |
|
||||
| `designers` | 设计师 | `designer_profiles` |
|
||||
| `designer_awards` | 设计师 | `designer_awards`(已有前缀) |
|
||||
| `designer_belongs_tag` | 设计师 | `designer_belongs_tag`(已有前缀) |
|
||||
| `banners` | 运营内容 | `operation_banners` |
|
||||
| `topics` | 运营内容 | `operation_topics` |
|
||||
| `topic_belongs_case` | 运营内容 | `operation_topic_belongs_case` |
|
||||
| `favorites` | 用户互动 | `interaction_favorites` |
|
||||
| `likes` | 用户互动 | `interaction_likes` |
|
||||
| `comments` | 用户互动 | `interaction_comments` |
|
||||
| `follows` | 用户互动 | `interaction_follows` |
|
||||
| `newsletter_subscriptions` | 用户互动 | `interaction_newsletter_subscriptions` |
|
||||
| `user_login_logs` | 日志 | `log_user_logins` |
|
||||
| `admin_operation_logs` | 日志 | `log_admin_operations` |
|
||||
| `download_logs` | 日志 | `log_downloads` |
|
||||
| `user_sessions` | 安全风控 | `security_user_sessions` |
|
||||
| `security_risk_events` | 安全风控 | `security_risk_events`(已有前缀) |
|
||||
| `security_blacklists` | 安全风控 | `security_blacklists`(已有前缀) |
|
||||
| `system_configs` | 系统配置 | `system_configs`(已有前缀) |
|
||||
|
||||
---
|
||||
|
||||
## 3. ER 关系总览
|
||||
|
||||
```
|
||||
用户与权限
|
||||
─────────
|
||||
users ←→ user_belongs_role ←→ roles
|
||||
│ │
|
||||
└→ oauth_bindings role_belongs_menu ←→ menus
|
||||
|
||||
案例核心
|
||||
────────
|
||||
categories ←── cases ──→ case_images
|
||||
│ └──→ case_files
|
||||
│ └──→ case_belongs_tag ←── tags
|
||||
│ └──→ case_team_members ──→ designers
|
||||
│ │
|
||||
│ └→ designer_awards
|
||||
│ └→ designer_belongs_tag ←── tags
|
||||
│
|
||||
└──→ favorites ←── users
|
||||
└──→ likes ←── users
|
||||
└──→ comments ←── users
|
||||
|
||||
运营内容
|
||||
────────
|
||||
banners (独立)
|
||||
topics ←→ topic_belongs_case ←→ cases
|
||||
|
||||
会话与安全
|
||||
──────────
|
||||
users ──→ user_sessions
|
||||
users ──→ security_risk_events
|
||||
security_blacklists (独立)
|
||||
|
||||
日志与系统
|
||||
──────────
|
||||
user_login_logs
|
||||
admin_operation_logs
|
||||
download_logs
|
||||
system_configs
|
||||
newsletter_subscriptions
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 核心数据表
|
||||
|
||||
### 4.1 用户与权限域
|
||||
|
||||
#### `users` — 统一用户表
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK, AUTO_INCREMENT | |
|
||||
| `user_type` | VARCHAR(20) | NOT NULL, DEFAULT 'user' | user / admin |
|
||||
| `username` | VARCHAR(50) | NULL, UNIQUE | 登录账号 |
|
||||
| `phone` | VARCHAR(20) | NULL, UNIQUE | 手机号 |
|
||||
| `password` | VARCHAR(255) | NULL | bcrypt 哈希 |
|
||||
| `enterprise_user_id` | VARCHAR(100) | NULL, UNIQUE | 企业平台用户唯一标识 |
|
||||
| `source` | VARCHAR(20) | NOT NULL, DEFAULT 'local' | local / enterprise / wechat / qq |
|
||||
| `is_enterprise_linked` | TINYINT | NOT NULL, DEFAULT 0 | 是否已绑定企业账号 |
|
||||
| `nickname` | VARCHAR(50) | NULL | 显示昵称 |
|
||||
| `avatar` | VARCHAR(500) | NULL | 头像 URL |
|
||||
| `role_label` | VARCHAR(50) | NULL | 展示角色标签(如 Architect) |
|
||||
| `previous_password_hash` | VARCHAR(255) | NULL | 上次密码哈希(防重复使用) |
|
||||
| `agree_at` | TIMESTAMP | NULL | 用户同意协议时间 |
|
||||
| `agreement_version` | VARCHAR(30) | NULL | 同意时协议版本 |
|
||||
| `status` | TINYINT | NOT NULL, DEFAULT 1 | 1=启用, 0=禁用 |
|
||||
| `deactivation_requested_at` | TIMESTAMP | NULL | 注销申请时间(冷静期起始) |
|
||||
| `scheduled_deletion_at` | TIMESTAMP | NULL | 计划删除时间(冷静期结束) |
|
||||
| `last_login_at` | TIMESTAMP | NULL | |
|
||||
| `created_at` | TIMESTAMP | | |
|
||||
| `updated_at` | TIMESTAMP | | |
|
||||
| `deleted_at` | TIMESTAMP | NULL | |
|
||||
|
||||
索引:`uk_users_username`, `uk_users_phone`, `uk_users_enterprise_user_id`, `idx_users_user_type`, `idx_users_status`
|
||||
|
||||
#### `oauth_bindings` — 第三方登录绑定
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK | |
|
||||
| `user_id` | BIGINT UNSIGNED | FK → users | |
|
||||
| `provider` | VARCHAR(20) | NOT NULL | wechat / qq / enterprise |
|
||||
| `provider_user_id` | VARCHAR(100) | NOT NULL | 第三方平台用户 ID |
|
||||
| `access_token` | VARCHAR(500) | NULL | |
|
||||
| `refresh_token` | VARCHAR(500) | NULL | |
|
||||
| `expires_at` | TIMESTAMP | NULL | |
|
||||
| `created_at` | TIMESTAMP | | |
|
||||
| `updated_at` | TIMESTAMP | | |
|
||||
|
||||
索引:`uk_oauth_provider_uid (provider, provider_user_id)`, `idx_oauth_user_id`
|
||||
|
||||
#### `roles` — 角色表
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK | |
|
||||
| `name` | VARCHAR(50) | NOT NULL, UNIQUE | 角色标识:super_admin / content_ops / reviewer |
|
||||
| `display_name` | VARCHAR(50) | NOT NULL | 超级管理员 / 内容运营 / 审核员 |
|
||||
| `description` | VARCHAR(200) | NULL | |
|
||||
| `created_at` | TIMESTAMP | | |
|
||||
| `updated_at` | TIMESTAMP | | |
|
||||
|
||||
#### `menus` — 菜单/权限表
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK | |
|
||||
| `parent_id` | BIGINT UNSIGNED | DEFAULT 0 | 树形结构 |
|
||||
| `name` | VARCHAR(50) | NOT NULL | 权限标识 `case:create` |
|
||||
| `display_name` | VARCHAR(50) | NOT NULL | 菜单显示名 |
|
||||
| `type` | VARCHAR(10) | NOT NULL | menu / button |
|
||||
| `path` | VARCHAR(200) | NULL | 前端路由路径 |
|
||||
| `icon` | VARCHAR(50) | NULL | 图标名 |
|
||||
| `sort` | INT UNSIGNED | DEFAULT 0 | |
|
||||
| `is_visible` | TINYINT | DEFAULT 1 | |
|
||||
| `created_at` | TIMESTAMP | | |
|
||||
| `updated_at` | TIMESTAMP | | |
|
||||
|
||||
#### `user_belongs_role` — 用户-角色关联
|
||||
|
||||
| 字段 | 类型 | 约束 |
|
||||
|------|------|------|
|
||||
| `user_id` | BIGINT UNSIGNED | PK(联合), FK → users |
|
||||
| `role_id` | BIGINT UNSIGNED | PK(联合), FK → roles |
|
||||
|
||||
#### `role_belongs_menu` — 角色-菜单关联
|
||||
|
||||
| 字段 | 类型 | 约束 |
|
||||
|------|------|------|
|
||||
| `role_id` | BIGINT UNSIGNED | PK(联合), FK → roles |
|
||||
| `menu_id` | BIGINT UNSIGNED | PK(联合), FK → menus |
|
||||
|
||||
---
|
||||
|
||||
### 4.2 案例核心域
|
||||
|
||||
#### `categories` — 建筑类型分类
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK | |
|
||||
| `name` | VARCHAR(50) | NOT NULL, UNIQUE | 别墅 / 民宿 / 室内 / 景观 / 农村自建房 / 庭院 |
|
||||
| `slug` | VARCHAR(50) | NOT NULL, UNIQUE | villa / homestay / interior / landscape |
|
||||
| `icon` | VARCHAR(50) | NULL | |
|
||||
| `sort` | INT UNSIGNED | DEFAULT 0 | |
|
||||
| `case_count` | INT UNSIGNED | DEFAULT 0 | 缓存引用计数 |
|
||||
| `created_at` | TIMESTAMP | | |
|
||||
| `updated_at` | TIMESTAMP | | |
|
||||
|
||||
#### `tags` — 统一标签字典
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK | |
|
||||
| `type` | VARCHAR(20) | NOT NULL | style / feature / specialty |
|
||||
| `name` | VARCHAR(50) | NOT NULL | 现代 / 落地窗 / 参数化设计 |
|
||||
| `sort` | INT UNSIGNED | DEFAULT 0 | |
|
||||
| `reference_count` | INT UNSIGNED | DEFAULT 0 | 被引用次数 |
|
||||
| `created_at` | TIMESTAMP | | |
|
||||
| `updated_at` | TIMESTAMP | | |
|
||||
|
||||
索引:`uk_tags_type_name (type, name)`, `idx_tags_type`
|
||||
|
||||
#### `cases` — 案例主表
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK | |
|
||||
| `category_id` | BIGINT UNSIGNED | FK → categories | 建筑类型 |
|
||||
| `title` | VARCHAR(200) | NOT NULL | 项目名称 |
|
||||
| `code` | VARCHAR(30) | NOT NULL, UNIQUE | 项目编号 P-2024-8839 |
|
||||
| `cover_image` | VARCHAR(500) | NULL | 封面图 URL |
|
||||
| `status` | VARCHAR(20) | NOT NULL, DEFAULT 'draft' | draft / pending / published / archived |
|
||||
| `is_featured` | TINYINT | DEFAULT 0 | 是否精选 |
|
||||
| `featured_sort` | INT UNSIGNED | DEFAULT 0 | 精选排序 |
|
||||
| — **户型布局** — | | | |
|
||||
| `layout` | VARCHAR(50) | NULL | 3室2厅3卫 |
|
||||
| `floor_height` | VARCHAR(50) | NULL | 3.6/3.3/3.3m |
|
||||
| — **用地条件** — | | | |
|
||||
| `site_width` | VARCHAR(50) | NULL | 面宽 ≥ 10.5m |
|
||||
| `site_depth` | VARCHAR(50) | NULL | 进深 ≥ 12.2m |
|
||||
| `site_area` | DECIMAL(10,2) | NULL | 占地面积 m² |
|
||||
| `lighting_restriction` | VARCHAR(100) | NULL | 采光限制 |
|
||||
| `site_shape` | VARCHAR(50) | NULL | 用地形状 |
|
||||
| — **规模造价** — | | | |
|
||||
| `floors_above` | TINYINT UNSIGNED | NULL | 地上层数 |
|
||||
| `floors_below` | TINYINT UNSIGNED | NULL | 地下层数 |
|
||||
| `cost_min` | DECIMAL(12,2) | NULL | 造价预估下限(万元) |
|
||||
| `cost_max` | DECIMAL(12,2) | NULL | 造价预估上限(万元) |
|
||||
| `total_building_area` | DECIMAL(10,2) | NULL | 建筑总面积 m² |
|
||||
| `bedroom_count` | TINYINT UNSIGNED | NULL | 卧室数量 |
|
||||
| `bedroom_note` | VARCHAR(100) | NULL | 含1主卧套房 |
|
||||
| — **平面功能** — | | | |
|
||||
| `stair_type` | VARCHAR(100) | NULL | 楼梯类型 |
|
||||
| `special_space` | VARCHAR(200) | NULL | 特色空间 / 农村特色 |
|
||||
| `bedroom_config` | VARCHAR(200) | NULL | 卧室配置 |
|
||||
| `leisure_space` | VARCHAR(200) | NULL | 休闲空间 |
|
||||
| `kitchen_dining` | VARCHAR(200) | NULL | 厨房餐厅 |
|
||||
| `bathroom_config` | VARCHAR(100) | NULL | 卫生间配置 |
|
||||
| — **外观风格** — | | | |
|
||||
| `architecture_style` | VARCHAR(100) | NULL | 建筑风格 |
|
||||
| `roof_type` | VARCHAR(100) | NULL | 屋顶形式 |
|
||||
| `facade_material` | VARCHAR(200) | NULL | 外立面材料 |
|
||||
| — **结构与性能** — | | | |
|
||||
| `structure_type` | VARCHAR(100) | NULL | 结构类型 |
|
||||
| `foundation_type` | VARCHAR(100) | NULL | 基础类型 |
|
||||
| `layout_logic` | VARCHAR(200) | NULL | 户型逻辑 |
|
||||
| `wall_thickness` | VARCHAR(100) | NULL | 墙体厚度 |
|
||||
| `seismic_rating` | VARCHAR(100) | NULL | 抗震设防 |
|
||||
| `insulation_type` | VARCHAR(100) | NULL | 保温形式 |
|
||||
| `roof_structure` | VARCHAR(200) | NULL | 屋面构造 |
|
||||
| — **设计理念** — | | | |
|
||||
| `design_concept` | TEXT | NULL | 设计理念富文本 |
|
||||
| `concept_style` | VARCHAR(100) | NULL | 风格提炼 |
|
||||
| `concept_material` | VARCHAR(100) | NULL | 材质提炼 |
|
||||
| `concept_target` | VARCHAR(100) | NULL | 受众提炼 |
|
||||
| — **分类特有扩展** — | | | |
|
||||
| `meta` | JSON | NULL | 分类特有参数(景观面积 / 客房数 / 主材等) |
|
||||
| — **统计计数** — | | | |
|
||||
| `view_count` | INT UNSIGNED | DEFAULT 0 | |
|
||||
| `like_count` | INT UNSIGNED | DEFAULT 0 | |
|
||||
| `favorite_count` | INT UNSIGNED | DEFAULT 0 | |
|
||||
| `download_count` | INT UNSIGNED | DEFAULT 0 | |
|
||||
| `comment_count` | INT UNSIGNED | DEFAULT 0 | |
|
||||
| — **时间** — | | | |
|
||||
| `published_at` | TIMESTAMP | NULL | 发布时间 |
|
||||
| `created_at` | TIMESTAMP | | |
|
||||
| `updated_at` | TIMESTAMP | | |
|
||||
| `deleted_at` | TIMESTAMP | NULL | |
|
||||
|
||||
索引:`uk_cases_code`, `idx_cases_category_id`, `idx_cases_status`, `idx_cases_is_featured`, `idx_cases_status_created (status, created_at)`, `idx_cases_status_featured (status, is_featured, featured_sort)`
|
||||
|
||||
> `meta` JSON 用于存储不同分类的特有参数。例如:
|
||||
> - 景观类案例:`{"landscape_area": 270, "main_vegetation": "黑松/苔藓", "paving_material": "花岗岩/白砂"}`
|
||||
> - 民宿类案例:`{"room_count": 12, "room_note": "12间套房"}`
|
||||
> - 室内类案例:`{"main_material": "微水泥/钢构"}`
|
||||
> - 商业类案例:`{"building_height": "120m", "function_layout": "办公/商业"}`
|
||||
|
||||
#### `case_images` — 案例图库
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK | |
|
||||
| `case_id` | BIGINT UNSIGNED | FK → cases | |
|
||||
| `type` | VARCHAR(20) | NOT NULL | effect / floor_plan / elevation |
|
||||
| `url` | VARCHAR(500) | NOT NULL | 图片 URL |
|
||||
| `thumbnail_url` | VARCHAR(500) | NULL | 缩略图 URL |
|
||||
| `sort` | INT UNSIGNED | DEFAULT 0 | |
|
||||
| `created_at` | TIMESTAMP | | |
|
||||
| `updated_at` | TIMESTAMP | | |
|
||||
|
||||
索引:`idx_case_images_case_type (case_id, type)`
|
||||
|
||||
#### `case_files` — 案例文件资产
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK | |
|
||||
| `case_id` | BIGINT UNSIGNED | FK → cases | |
|
||||
| `stage` | VARCHAR(20) | NOT NULL | floor_plan / exterior / construction / structure / interior / courtyard |
|
||||
| `file_name` | VARCHAR(200) | NOT NULL | 原始文件名 |
|
||||
| `file_path` | VARCHAR(500) | NOT NULL | 存储路径 / OSS key |
|
||||
| `file_size` | BIGINT UNSIGNED | NOT NULL | 字节数 |
|
||||
| `file_ext` | VARCHAR(20) | NOT NULL | dwg / pdf / rvt / jpg / png / zip |
|
||||
| `mime_type` | VARCHAR(100) | NULL | |
|
||||
| `uploader_id` | BIGINT UNSIGNED | FK → users | 上传者 |
|
||||
| `sort` | INT UNSIGNED | DEFAULT 0 | |
|
||||
| `created_at` | TIMESTAMP | | |
|
||||
| `updated_at` | TIMESTAMP | | |
|
||||
|
||||
索引:`idx_case_files_case_stage (case_id, stage)`
|
||||
|
||||
> `stage` 枚举值对应 PRD F5.1 的 6 个设计阶段:
|
||||
> - `floor_plan` — 平面阶段
|
||||
> - `exterior` — 外观阶段
|
||||
> - `construction` — 施工图阶段
|
||||
> - `structure` — 结构阶段
|
||||
> - `interior` — 室内阶段
|
||||
> - `courtyard` — 庭院阶段
|
||||
|
||||
#### `case_belongs_tag` — 案例-标签关联
|
||||
|
||||
| 字段 | 类型 | 约束 |
|
||||
|------|------|------|
|
||||
| `case_id` | BIGINT UNSIGNED | PK(联合), FK → cases |
|
||||
| `tag_id` | BIGINT UNSIGNED | PK(联合), FK → tags |
|
||||
|
||||
#### `case_team_members` — 案例主创团队
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK | |
|
||||
| `case_id` | BIGINT UNSIGNED | FK → cases | |
|
||||
| `designer_id` | BIGINT UNSIGNED | FK → designers | |
|
||||
| `role` | VARCHAR(30) | NOT NULL | scheme / structure / mep (方案/结构/水电) |
|
||||
| `is_lead` | TINYINT | DEFAULT 0 | 是否主创 |
|
||||
| `sort` | INT UNSIGNED | DEFAULT 0 | |
|
||||
| `created_at` | TIMESTAMP | | |
|
||||
|
||||
索引:`uk_case_team_case_designer_role (case_id, designer_id, role)`, `idx_case_team_designer_id`
|
||||
|
||||
---
|
||||
|
||||
### 4.3 设计师域
|
||||
|
||||
#### `designers` — 设计师档案
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK | |
|
||||
| `name_cn` | VARCHAR(50) | NOT NULL | 中文姓名 |
|
||||
| `name_en` | VARCHAR(100) | NULL | 英文姓名 |
|
||||
| `title` | VARCHAR(50) | NULL | 职位:方案主创设计师 |
|
||||
| `title_badge` | VARCHAR(50) | NULL | 职位徽章:Lead Architect |
|
||||
| `company` | VARCHAR(100) | NULL | 所属机构 |
|
||||
| `city` | VARCHAR(50) | NULL | 所在城市 |
|
||||
| `portrait` | VARCHAR(500) | NULL | 个人写真 URL |
|
||||
| `portrait_caption` | VARCHAR(100) | NULL | STUDIO PORTRAIT © 2023 |
|
||||
| `years_of_experience` | TINYINT UNSIGNED | NULL | 从业年限 |
|
||||
| `project_count` | INT UNSIGNED | DEFAULT 0 | 完成项目数 |
|
||||
| `design_philosophy_quote` | TEXT | NULL | 设计理念引用语 |
|
||||
| `design_philosophy` | TEXT | NULL | 设计理念详述(富文本) |
|
||||
| `follower_count` | INT UNSIGNED | DEFAULT 0 | 关注者数量 |
|
||||
| `view_count` | INT UNSIGNED | DEFAULT 0 | 主页浏览量 |
|
||||
| `is_active` | TINYINT | DEFAULT 1 | 是否公开展示 |
|
||||
| `created_at` | TIMESTAMP | | |
|
||||
| `updated_at` | TIMESTAMP | | |
|
||||
| `deleted_at` | TIMESTAMP | NULL | |
|
||||
|
||||
索引:`idx_designers_is_active`
|
||||
|
||||
#### `designer_awards` — 设计师荣誉奖项
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK | |
|
||||
| `designer_id` | BIGINT UNSIGNED | FK → designers | |
|
||||
| `year` | SMALLINT UNSIGNED | NOT NULL | 获奖年份 |
|
||||
| `title` | VARCHAR(200) | NOT NULL | 红点设计大奖 Red Dot Award |
|
||||
| `description` | VARCHAR(300) | NULL | 最佳室内设计类 - The Cloud Villa |
|
||||
| `sort` | INT UNSIGNED | DEFAULT 0 | |
|
||||
| `created_at` | TIMESTAMP | | |
|
||||
| `updated_at` | TIMESTAMP | | |
|
||||
|
||||
索引:`idx_awards_designer_year (designer_id, year DESC)`
|
||||
|
||||
#### `designer_belongs_tag` — 设计师-专长标签
|
||||
|
||||
| 字段 | 类型 | 约束 |
|
||||
|------|------|------|
|
||||
| `designer_id` | BIGINT UNSIGNED | PK(联合), FK → designers |
|
||||
| `tag_id` | BIGINT UNSIGNED | PK(联合), FK → tags (type=specialty) |
|
||||
|
||||
---
|
||||
|
||||
### 4.4 运营内容域
|
||||
|
||||
#### `banners` — 首页轮播
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK | |
|
||||
| `title` | VARCHAR(200) | NOT NULL | 大标题 |
|
||||
| `description` | TEXT | NULL | 描述摘要 |
|
||||
| `image` | VARCHAR(500) | NOT NULL | 背景大图 URL |
|
||||
| `label` | VARCHAR(50) | NULL | 标签文字:精选项目 |
|
||||
| `link_type` | VARCHAR(20) | NOT NULL, DEFAULT 'case' | case / topic / external |
|
||||
| `link_url` | VARCHAR(500) | NOT NULL | 跳转链接 |
|
||||
| `sort` | INT UNSIGNED | DEFAULT 0 | |
|
||||
| `is_active` | TINYINT | DEFAULT 1 | 启用/停用 |
|
||||
| `published_at` | TIMESTAMP | NULL | 展示日期 |
|
||||
| `created_at` | TIMESTAMP | | |
|
||||
| `updated_at` | TIMESTAMP | | |
|
||||
|
||||
索引:`idx_banners_active_sort (is_active, sort)`
|
||||
|
||||
#### `topics` — 专题合集
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK | |
|
||||
| `title` | VARCHAR(200) | NOT NULL | 专题标题 |
|
||||
| `cover_image` | VARCHAR(500) | NULL | 封面图 |
|
||||
| `description` | TEXT | NULL | 富文本描述 |
|
||||
| `status` | VARCHAR(20) | NOT NULL, DEFAULT 'draft' | draft / published |
|
||||
| `case_count` | INT UNSIGNED | DEFAULT 0 | 关联案例数 |
|
||||
| `created_at` | TIMESTAMP | | |
|
||||
| `updated_at` | TIMESTAMP | | |
|
||||
| `deleted_at` | TIMESTAMP | NULL | |
|
||||
|
||||
#### `topic_belongs_case` — 专题-案例关联
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `topic_id` | BIGINT UNSIGNED | PK(联合), FK → topics | |
|
||||
| `case_id` | BIGINT UNSIGNED | PK(联合), FK → cases | |
|
||||
| `sort` | INT UNSIGNED | DEFAULT 0 | 专题内排序 |
|
||||
|
||||
---
|
||||
|
||||
### 4.5 用户互动域
|
||||
|
||||
#### `favorites` — 收藏
|
||||
|
||||
| 字段 | 类型 | 约束 |
|
||||
|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK |
|
||||
| `user_id` | BIGINT UNSIGNED | FK → users |
|
||||
| `case_id` | BIGINT UNSIGNED | FK → cases |
|
||||
| `created_at` | TIMESTAMP | |
|
||||
|
||||
索引:`uk_favorites_user_case (user_id, case_id)`, `idx_favorites_case_id`
|
||||
|
||||
#### `likes` — 点赞
|
||||
|
||||
| 字段 | 类型 | 约束 |
|
||||
|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK |
|
||||
| `user_id` | BIGINT UNSIGNED | FK → users |
|
||||
| `case_id` | BIGINT UNSIGNED | FK → cases |
|
||||
| `created_at` | TIMESTAMP | |
|
||||
|
||||
索引:`uk_likes_user_case (user_id, case_id)`, `idx_likes_case_id`
|
||||
|
||||
#### `comments` — 评论
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK | |
|
||||
| `case_id` | BIGINT UNSIGNED | FK → cases | |
|
||||
| `user_id` | BIGINT UNSIGNED | FK → users | |
|
||||
| `parent_id` | BIGINT UNSIGNED | NULL, FK → comments | 回复嵌套 |
|
||||
| `content` | TEXT | NOT NULL | 评论内容 |
|
||||
| `status` | VARCHAR(20) | DEFAULT 'pending' | pending / approved / rejected |
|
||||
| `created_at` | TIMESTAMP | | |
|
||||
| `updated_at` | TIMESTAMP | | |
|
||||
| `deleted_at` | TIMESTAMP | NULL | |
|
||||
|
||||
索引:`idx_comments_case_status (case_id, status)`, `idx_comments_user_id`, `idx_comments_parent_id`
|
||||
|
||||
#### `follows` — 关注设计师
|
||||
|
||||
| 字段 | 类型 | 约束 |
|
||||
|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK |
|
||||
| `user_id` | BIGINT UNSIGNED | FK → users |
|
||||
| `designer_id` | BIGINT UNSIGNED | FK → designers |
|
||||
| `created_at` | TIMESTAMP | |
|
||||
|
||||
索引:`uk_follows_user_designer (user_id, designer_id)`, `idx_follows_designer_id`
|
||||
|
||||
#### `newsletter_subscriptions` — 邮箱订阅
|
||||
|
||||
| 字段 | 类型 | 约束 |
|
||||
|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK |
|
||||
| `email` | VARCHAR(200) | NOT NULL, UNIQUE |
|
||||
| `created_at` | TIMESTAMP | |
|
||||
|
||||
---
|
||||
|
||||
### 4.6 日志与系统域
|
||||
|
||||
#### `user_login_logs` — 登录日志
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK | |
|
||||
| `user_id` | BIGINT UNSIGNED | FK → users | |
|
||||
| `login_type` | VARCHAR(20) | NOT NULL | password / sms / qr / wechat / qq / enterprise_sso |
|
||||
| `ip` | VARCHAR(45) | NULL | |
|
||||
| `login_location` | VARCHAR(100) | NULL | 登录地理位置(由 IP 库反查填充) |
|
||||
| `device_fingerprint` | VARCHAR(128) | NULL | 设备指纹 |
|
||||
| `risk_level` | VARCHAR(10) | NULL | L1 / L2 / L3 / L4 |
|
||||
| `risk_reason` | VARCHAR(255) | NULL | 命中策略摘要 |
|
||||
| `result` | VARCHAR(20) | NOT NULL, DEFAULT 'success' | success / failed / blocked |
|
||||
| `user_agent` | VARCHAR(500) | NULL | |
|
||||
| `created_at` | TIMESTAMP | | |
|
||||
|
||||
索引:`idx_login_logs_user_created (user_id, created_at)`, `idx_login_logs_ip_created (ip, created_at)`
|
||||
|
||||
#### `user_sessions` — 活跃会话
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK | |
|
||||
| `user_id` | BIGINT UNSIGNED | FK → users | |
|
||||
| `session_token` | VARCHAR(255) | NOT NULL, UNIQUE | Refresh Token 标识(哈希值) |
|
||||
| `device_name` | VARCHAR(100) | NULL | 设备名称(如 Chrome on macOS) |
|
||||
| `device_fingerprint` | VARCHAR(128) | NULL | 设备指纹 |
|
||||
| `ip` | VARCHAR(45) | NULL | 登录 IP |
|
||||
| `login_location` | VARCHAR(100) | NULL | 登录地理位置 |
|
||||
| `is_current` | TINYINT | NOT NULL, DEFAULT 0 | 是否为当前请求会话 |
|
||||
| `last_active_at` | TIMESTAMP | NULL | 最近活跃时间 |
|
||||
| `expires_at` | TIMESTAMP | NOT NULL | 会话过期时间 |
|
||||
| `revoked_at` | TIMESTAMP | NULL | 被踢出/注销时间(非空即失效) |
|
||||
| `created_at` | TIMESTAMP | | |
|
||||
|
||||
索引:`idx_sessions_user_active (user_id, revoked_at, expires_at)`, `uk_sessions_token (session_token)`
|
||||
|
||||
> 活跃会话表用于 F1.9 多端会话管理。创建会话时写入,Token 刷新时更新 `last_active_at`,退出/踢出时设置 `revoked_at`。定期清理过期记录。
|
||||
|
||||
#### `security_risk_events` — 风控事件日志
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK | |
|
||||
| `user_id` | BIGINT UNSIGNED | NULL, FK → users | 可为空(未登录攻击流量) |
|
||||
| `event_type` | VARCHAR(30) | NOT NULL | login / sms_send / register / reset_password / sso_callback |
|
||||
| `risk_level` | VARCHAR(10) | NOT NULL | L1 / L2 / L3 / L4 |
|
||||
| `action` | VARCHAR(30) | NOT NULL | captcha_upgrade / rate_limit / temporary_block / blacklist |
|
||||
| `ip` | VARCHAR(45) | NULL | |
|
||||
| `device_fingerprint` | VARCHAR(128) | NULL | |
|
||||
| `user_agent` | VARCHAR(500) | NULL | |
|
||||
| `payload` | JSON | NULL | 事件上下文 |
|
||||
| `created_at` | TIMESTAMP | | |
|
||||
|
||||
索引:`idx_risk_events_user_created (user_id, created_at)`, `idx_risk_events_level_created (risk_level, created_at)`, `idx_risk_events_ip_created (ip, created_at)`
|
||||
|
||||
> 风控事件日志不可编辑、不可删除,无 `updated_at` 和 `deleted_at`。
|
||||
|
||||
#### `security_blacklists` — 安全黑名单
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK | |
|
||||
| `target_type` | VARCHAR(20) | NOT NULL | ip / device / account |
|
||||
| `target_value` | VARCHAR(255) | NOT NULL | IP、设备指纹或账号标识 |
|
||||
| `reason` | VARCHAR(255) | NULL | 拉黑原因 |
|
||||
| `source` | VARCHAR(20) | NOT NULL, DEFAULT 'system' | system / manual |
|
||||
| `status` | VARCHAR(20) | NOT NULL, DEFAULT 'active' | active / released / expired |
|
||||
| `expire_at` | TIMESTAMP | NULL | 为空表示永久 |
|
||||
| `created_by` | BIGINT UNSIGNED | NULL, FK → users | 手动操作人(系统自动为空) |
|
||||
| `created_at` | TIMESTAMP | | |
|
||||
| `updated_at` | TIMESTAMP | | |
|
||||
|
||||
索引:`uk_blacklists_target (target_type, target_value)`, `idx_blacklists_status_expire (status, expire_at)`
|
||||
|
||||
#### `admin_operation_logs` — 管理端操作日志
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK | |
|
||||
| `user_id` | BIGINT UNSIGNED | FK → users | 操作人 |
|
||||
| `action` | VARCHAR(30) | NOT NULL | create / update / delete / status_change |
|
||||
| `resource_type` | VARCHAR(50) | NOT NULL | case / banner / topic / designer / comment |
|
||||
| `resource_id` | BIGINT UNSIGNED | NOT NULL | 操作对象 ID |
|
||||
| `before_value` | JSON | NULL | 变更前值 |
|
||||
| `after_value` | JSON | NULL | 变更后值 |
|
||||
| `ip` | VARCHAR(45) | NULL | |
|
||||
| `created_at` | TIMESTAMP | | |
|
||||
|
||||
索引:`idx_op_logs_user_created (user_id, created_at)`, `idx_op_logs_resource (resource_type, resource_id)`
|
||||
|
||||
> 操作日志不可编辑、不可删除,无 `updated_at` 和 `deleted_at`。
|
||||
|
||||
#### `download_logs` — 文件下载日志
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK | |
|
||||
| `user_id` | BIGINT UNSIGNED | FK → users | |
|
||||
| `case_id` | BIGINT UNSIGNED | FK → cases | |
|
||||
| `case_file_id` | BIGINT UNSIGNED | FK → case_files | |
|
||||
| `ip` | VARCHAR(45) | NULL | |
|
||||
| `created_at` | TIMESTAMP | | |
|
||||
|
||||
索引:`idx_dl_logs_user_created (user_id, created_at)`, `idx_dl_logs_case_id`
|
||||
|
||||
#### `system_configs` — 系统配置
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGINT UNSIGNED | PK | |
|
||||
| `group` | VARCHAR(50) | NOT NULL | site / seo / upload / comment / watermark / security |
|
||||
| `key` | VARCHAR(100) | NOT NULL | |
|
||||
| `value` | TEXT | NULL | |
|
||||
| `created_at` | TIMESTAMP | | |
|
||||
| `updated_at` | TIMESTAMP | | |
|
||||
|
||||
索引:`uk_configs_group_key (group, key)`
|
||||
|
||||
---
|
||||
|
||||
## 5. 索引策略
|
||||
|
||||
### 必须索引
|
||||
- 所有外键字段
|
||||
- `status` 字段
|
||||
- `created_at` 字段
|
||||
- 唯一业务标识(`cases.code`、`tags.type+name`、`users.phone`)
|
||||
|
||||
### 核心复合索引
|
||||
```sql
|
||||
-- 案例列表查询(分类 + 状态 + 时间)
|
||||
idx_cases_category_status_created (category_id, status, created_at)
|
||||
|
||||
-- 案例精选排序
|
||||
idx_cases_featured_sort (status, is_featured, featured_sort)
|
||||
|
||||
-- 文件按阶段查询
|
||||
idx_case_files_case_stage (case_id, stage)
|
||||
|
||||
-- 评论列表
|
||||
idx_comments_case_status (case_id, status, created_at)
|
||||
```
|
||||
|
||||
### 索引限制
|
||||
- 单表索引不超过 6 个
|
||||
- 避免冗余索引
|
||||
- 定期检查未使用的索引
|
||||
|
||||
---
|
||||
|
||||
## 6. 百万级数据表设计
|
||||
|
||||
### 分页优化
|
||||
```sql
|
||||
-- 游标分页(案例列表推荐使用)
|
||||
SELECT * FROM cases WHERE status = 'published' AND id > :last_id ORDER BY id DESC LIMIT 20;
|
||||
```
|
||||
|
||||
### 大表 COUNT 优化
|
||||
```sql
|
||||
-- 使用 categories.case_count / tags.reference_count 缓存计数
|
||||
-- 使用 cases.view_count / like_count / favorite_count 避免 COUNT JOIN
|
||||
```
|
||||
|
||||
### 分区策略(日志表)
|
||||
```sql
|
||||
-- 管理操作日志
|
||||
ALTER TABLE admin_operation_logs PARTITION BY RANGE (YEAR(created_at) * 100 + MONTH(created_at)) (
|
||||
PARTITION p202601 VALUES LESS THAN (202602),
|
||||
PARTITION p202602 VALUES LESS THAN (202603),
|
||||
PARTITION pmax VALUES LESS THAN MAXVALUE
|
||||
);
|
||||
|
||||
-- 用户登录日志(数据量最大,优先分区)
|
||||
ALTER TABLE user_login_logs PARTITION BY RANGE (YEAR(created_at) * 100 + MONTH(created_at)) (
|
||||
PARTITION p202601 VALUES LESS THAN (202602),
|
||||
PARTITION p202602 VALUES LESS THAN (202603),
|
||||
PARTITION pmax VALUES LESS THAN MAXVALUE
|
||||
);
|
||||
|
||||
-- 风控事件日志
|
||||
ALTER TABLE security_risk_events PARTITION BY RANGE (YEAR(created_at) * 100 + MONTH(created_at)) (
|
||||
PARTITION p202601 VALUES LESS THAN (202602),
|
||||
PARTITION p202602 VALUES LESS THAN (202603),
|
||||
PARTITION pmax VALUES LESS THAN MAXVALUE
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*最后更新: 2026-02-28*
|
||||
76
docs/architecture/decisions/_template.md
Normal file
76
docs/architecture/decisions/_template.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# ADR-XXX: [决策标题]
|
||||
|
||||
> Architecture Decision Record (架构决策记录)
|
||||
|
||||
## 状态
|
||||
|
||||
**[提议中 | 已接受 | 已废弃 | 已取代 → ADR-YYY]**
|
||||
|
||||
## 日期
|
||||
|
||||
YYYY-MM-DD
|
||||
|
||||
## 上下文
|
||||
|
||||
描述促使此决策的背景、问题或需求。
|
||||
|
||||
**问题陈述**:
|
||||
我们需要解决 [什么问题]...
|
||||
|
||||
**约束条件**:
|
||||
- 约束1
|
||||
- 约束2
|
||||
|
||||
## 决策
|
||||
|
||||
我们决定采用 [方案]。
|
||||
|
||||
**选定方案的详细描述**:
|
||||
...
|
||||
|
||||
## 考虑的备选方案
|
||||
|
||||
### 方案 A: [名称]
|
||||
**描述**: ...
|
||||
**优点**:
|
||||
- 优点1
|
||||
- 优点2
|
||||
|
||||
**缺点**:
|
||||
- 缺点1
|
||||
- 缺点2
|
||||
|
||||
### 方案 B: [名称]
|
||||
**描述**: ...
|
||||
**优点**:
|
||||
- 优点1
|
||||
|
||||
**缺点**:
|
||||
- 缺点1
|
||||
|
||||
## 为什么选择此方案
|
||||
|
||||
解释选择该方案而非其他方案的理由。
|
||||
|
||||
## 影响
|
||||
|
||||
### 正面影响
|
||||
- 影响1
|
||||
- 影响2
|
||||
|
||||
### 负面影响/权衡
|
||||
- 权衡1
|
||||
|
||||
### 需要的后续行动
|
||||
- [ ] 行动1
|
||||
- [ ] 行动2
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [系统架构](../system-design.md)
|
||||
- [相关 ADR](./xxx.md)
|
||||
|
||||
---
|
||||
|
||||
*记录人: [姓名]*
|
||||
*审核人: [姓名]*
|
||||
128
docs/architecture/frontend-strategy.md
Normal file
128
docs/architecture/frontend-strategy.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# 🖥️ 双前端架构策略
|
||||
|
||||
> AI Agent 在生成前端代码时必须先阅读本文档,明确目标前端的职责边界、技术约束和设计原则。
|
||||
|
||||
---
|
||||
|
||||
## 1. 整体架构
|
||||
|
||||
本项目采用「一后端 + 双前端 + 共享层」架构:
|
||||
|
||||
```
|
||||
vibe-cursor-pro/(Cursor 工作区)
|
||||
├── Case-Database-Backend/ ← PHP Hyperf + Swoole 后端(统一 API 服务)
|
||||
├── Case-Database-Frontend-user/ ← Vue 3 用户端(面向终端用户)
|
||||
├── Case-Database-Frontend-admin/ ← Vue 3 管理端(面向运营/管理人员)
|
||||
└── Case-Database-Frontend-shared/ ← 共享类型定义、工具函数、API 契约常量
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 前端职责边界
|
||||
|
||||
### Case-Database-Frontend-user/(用户端)
|
||||
|
||||
| 维度 | 说明 |
|
||||
|---|---|
|
||||
| **目标用户** | 普通终端用户(公开访问 + 登录用户) |
|
||||
| **核心体验** | 性能优先、流畅交互、移动端友好 |
|
||||
| **设计风格** | 品牌化、轻量、视觉吸引力强 |
|
||||
| **页面规模** | 中小型页面,单页功能聚焦 |
|
||||
| **权限模型** | 简单(登录/未登录、会员等级) |
|
||||
| **SEO 需求** | 有(落地页、详情页考虑 SSG/SSR) |
|
||||
| **API 前缀** | `/api/`(用户端接口) |
|
||||
|
||||
**典型页面**:首页、商品详情、购物车、个人中心、订单查询
|
||||
|
||||
### Case-Database-Frontend-admin/(管理端)
|
||||
|
||||
| 维度 | 说明 |
|
||||
|---|---|
|
||||
| **目标用户** | 内部运营人员、管理员 |
|
||||
| **核心体验** | 功能完整、信息密度高、操作高效 |
|
||||
| **设计风格** | 专业、实用、Element Plus 标准组件优先(仅管理端) |
|
||||
| **页面规模** | 复杂页面(多 Tab、嵌套表单、数据大表格) |
|
||||
| **权限模型** | 精细(RBAC:角色、菜单、按钮级权限) |
|
||||
| **SEO 需求** | 无(内部系统,登录后访问) |
|
||||
| **API 前缀** | `/admin/`(管理端接口) |
|
||||
|
||||
**典型页面**:数据看板、订单管理、用户管理、权限配置、系统设置
|
||||
|
||||
---
|
||||
|
||||
## 3. 共享层(Case-Database-Frontend-shared/)
|
||||
|
||||
仅包含**纯 TypeScript**内容(配合 JSDoc 类型注释),不引入任何 UI 框架:
|
||||
|
||||
```
|
||||
Case-Database-Frontend-shared/
|
||||
├── constants/ ← 业务枚举(订单状态、权限码等)
|
||||
├── utils/ ← 纯函数工具(日期格式化、金额计算等)
|
||||
└── api-schema/ ← API 请求/响应的 JSDoc 类型定义
|
||||
```
|
||||
|
||||
> **规则**:Case-Database-Frontend-shared/ 中的代码必须可被两个前端同时使用,不得包含平台特定代码。
|
||||
|
||||
---
|
||||
|
||||
## 4. 技术差异对比
|
||||
|
||||
| 技术点 | Case-Database-Frontend-user/ | Case-Database-Frontend-admin/ |
|
||||
|---|---|---|
|
||||
| **UI 框架** | 自定义组件 + Tailwind | Element Plus(优先使用标准组件) |
|
||||
| **响应式** | 移动优先(xs → xl) | 桌面优先(≥ 1280px 为主) |
|
||||
| **路由** | Vue Router(History 模式) | Vue Router(History 模式 + 权限守卫) |
|
||||
| **状态管理** | Pinia(轻量 Store) | Pinia(含权限 Store、菜单 Store) |
|
||||
| **打包优化** | 激进代码分割、图片优化、SSG 评估 | 按需分割(菜单级懒加载) |
|
||||
| **错误处理** | 用户友好提示(Toast) | 详细错误码 + 日志上报 |
|
||||
| **主题** | 品牌色(见 ui-specs-user.md) | 专业蓝灰(见 ui-specs-admin.md) |
|
||||
|
||||
---
|
||||
|
||||
## 5. AI Agent 工作约定
|
||||
|
||||
### 目录前缀约定
|
||||
|
||||
**每次前端相关任务,必须在 prompt 中明确指定目标目录**:
|
||||
|
||||
```
|
||||
✅ 正确:在 Case-Database-Frontend-user/ 中创建商品详情页
|
||||
✅ 正确:在 Case-Database-Frontend-admin/ 中创建订单管理页
|
||||
❌ 错误:创建商品详情页(未指定前端)
|
||||
```
|
||||
|
||||
### 设计原则差异
|
||||
|
||||
当 Agent 在 `Case-Database-Frontend-user/` 工作时:
|
||||
- 移动端优先(先写 xs 断点,再扩展到 lg)
|
||||
- 组件必须考虑骨架屏 / 懒加载
|
||||
- 图片必须有 alt 属性、考虑 WebP 格式
|
||||
- 交互反馈必须流畅(避免页面跳动)
|
||||
|
||||
当 Agent 在 `Case-Database-Frontend-admin/` 工作时:
|
||||
- 桌面端优先(以 1280px 为基准设计)
|
||||
- 优先使用 Element Plus 标准组件(`el-table`、`el-form`、`el-dialog` 等)
|
||||
- 页面操作必须有权限守卫(`v-permission` 指令 或 `hasPermission()` 检查)
|
||||
- 数据操作必须有二次确认(删除、批量操作等危险操作)
|
||||
|
||||
### 共享代码优先
|
||||
|
||||
在生成 API 调用代码时:
|
||||
1. 先检查 `Case-Database-Frontend-shared/constants/` 是否已有对应枚举或常量
|
||||
2. 先检查 `Case-Database-Frontend-shared/api-schema/` 是否已有接口契约
|
||||
3. 有则复用,无则在 Case-Database-Frontend-shared/ 中新建后再引用
|
||||
|
||||
---
|
||||
|
||||
## 6. 部署架构
|
||||
|
||||
```
|
||||
用户端: https://www.example.com → Nginx → Case-Database-Frontend-user/dist/
|
||||
管理端: https://admin.example.com → Nginx → Case-Database-Frontend-admin/dist/
|
||||
API: https://api.example.com → Nginx → Hyperf (9501)
|
||||
WebSocket: wss://api.example.com/ws → Nginx → Swoole (9502)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*最后更新: 2026-02-26*
|
||||
133
docs/architecture/system-design.md
Normal file
133
docs/architecture/system-design.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# 🏗️ System Design — 百万级并发企业数字化平台
|
||||
|
||||
> 填写本文档,为 AI Agent 提供系统架构上下文。
|
||||
|
||||
---
|
||||
|
||||
## 1. 技术栈
|
||||
|
||||
| 层级 | 技术 | 版本 |
|
||||
|------|------|------|
|
||||
| 前端框架 | Vue 3 + Vite | 3.5+ / 7.x |
|
||||
| UI 库 (管理端) | Element Plus + Tailwind CSS | 2.x / 4.x |
|
||||
| UI 库 (用户端) | Headless UI + Tailwind CSS | 1.x / 4.x |
|
||||
| 状态管理 | Pinia | 3.x |
|
||||
| 路由 | Vue Router | 4.x |
|
||||
| HTTP 客户端 | Axios | 1.x |
|
||||
| 后端框架 | Hyperf | 3.1 |
|
||||
| 协程引擎 | Swoole | 5.0+ |
|
||||
| 编程语言 | PHP | 8.1+ |
|
||||
| 数据库 | MySQL | 8.1 |
|
||||
| 缓存 | Redis | 7.x |
|
||||
| 反向代理 | Nginx | 1.25+ |
|
||||
| 容器化 | Docker + Docker Compose | - |
|
||||
|
||||
## 2. 架构总览
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 用户层 │
|
||||
│ PC 浏览器 │ 移动端 (响应式) │ 平板 │ 管理后台 │
|
||||
└───────────────────────────┬─────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────────────────────────────────────────┐
|
||||
│ CDN + WAF (可选) │
|
||||
└───────────────────────────┬───────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────────────────────────────────────────┐
|
||||
│ Nginx 集群 (负载均衡 + SSL + 静态资源) │
|
||||
│ - upstream hyperf_cluster │
|
||||
│ - WebSocket proxy │
|
||||
└───────────────────────────┬───────────────────────────────────────┘
|
||||
│
|
||||
┌─────────────┼─────────────┐
|
||||
▼ ▼ ▼
|
||||
┌──────────┐ ┌──────────┐ ┌──────────┐
|
||||
│ Hyperf-1 │ │ Hyperf-2 │ │ Hyperf-N │ (水平扩展)
|
||||
│ HTTP:9501│ │ HTTP:9501│ │ HTTP:9501│
|
||||
│ WS:9502 │ │ WS:9502 │ │ WS:9502 │
|
||||
└────┬─────┘ └────┬─────┘ └────┬─────┘
|
||||
│ │ │
|
||||
└──────┬───────┴──────┬───────┘
|
||||
│ │
|
||||
┌──────┴──────┐ ┌────┴────────┐
|
||||
│ Redis │ │ MySQL │
|
||||
│ Sentinel/ │ │ Master │
|
||||
│ Cluster │ │ ├─Slave 1 │
|
||||
│ │ │ └─Slave 2 │
|
||||
└─────────────┘ └─────────────┘
|
||||
```
|
||||
|
||||
## 3. 分层架构
|
||||
|
||||
```
|
||||
请求 → Nginx → Hyperf HTTP Server → 中间件链 → Controller
|
||||
│
|
||||
▼
|
||||
Service 层
|
||||
│
|
||||
┌───────────────┼───────────────┐
|
||||
▼ ▼ ▼
|
||||
Repository Redis Cache Event Bus
|
||||
│ │
|
||||
▼ ▼
|
||||
MySQL Async Queue
|
||||
```
|
||||
|
||||
## 4. 核心模块
|
||||
|
||||
<!-- 根据实际项目填写 -->
|
||||
|
||||
| 模块 | 说明 | 关键接口 |
|
||||
|------|------|---------|
|
||||
| 用户认证 | JWT + RBAC 权限 | `/admin/auth/login`, `/admin/auth/refresh` |
|
||||
| 权限管理 | 用户/角色/菜单/数据权限 | `/admin/users`, `/admin/roles`, `/admin/menus` |
|
||||
| 生产管理 | 订单/子订单/发货/收款 | `/admin/production-orders`, `/admin/sub-orders` |
|
||||
| 工作流 | 审批流程定义与执行 | `/admin/workflows`, `/admin/tasks` |
|
||||
| 通知中心 | WebSocket + 站内消息 + 短信 | `/admin/notifications`, `ws://9502` |
|
||||
| 客户管理 | 客户/平台/店铺 | `/admin/customers`, `/admin/platforms` |
|
||||
|
||||
## 5. 并发设计要点
|
||||
|
||||
| 设计要点 | 实现方式 |
|
||||
|---------|---------|
|
||||
| 无状态服务 | Session/Token 存 Redis,文件存对象存储 |
|
||||
| 数据库高可用 | MySQL 主从 + 读写分离 + 连接池 |
|
||||
| 缓存策略 | Cache-Aside + 穿透/击穿/雪崩防护 |
|
||||
| 异步削峰 | Hyperf AsyncQueue (Redis 驱动) |
|
||||
| 分布式锁 | Redis SET NX + Lua 脚本 |
|
||||
| 限流 | 令牌桶 (API) + 滑动窗口 (用户) |
|
||||
| 实时通信 | Swoole WebSocket + Redis Pub/Sub |
|
||||
| 水平扩展 | Docker Compose → K8s HPA |
|
||||
|
||||
## 6. 部署拓扑
|
||||
|
||||
<!-- 根据实际部署环境填写 -->
|
||||
|
||||
### 开发环境
|
||||
- 单机 Docker Compose (Nginx + Hyperf + MySQL + Redis)
|
||||
|
||||
### 生产环境
|
||||
- Nginx 集群 (2+ 节点)
|
||||
- Hyperf 应用 (4+ 实例)
|
||||
- MySQL 主从 (1 写 + 2 读)
|
||||
- Redis Sentinel (3 节点)
|
||||
|
||||
## 7. 决策记录
|
||||
|
||||
<!-- 重要架构决策记录在 docs/architecture/decisions/ -->
|
||||
|
||||
| 决策 | 选择 | 原因 |
|
||||
|------|------|------|
|
||||
| 后端框架 | Hyperf + Swoole | 协程高性能,连接池,与旧项目技术栈一致 |
|
||||
| 数据库 | MySQL 8.1 | 成熟稳定,JSON 支持,与旧项目一致 |
|
||||
| 缓存 | Redis 7 | 数据结构丰富,连接池,队列支持 |
|
||||
| 前端框架 | Vue 3 + Vite | 生态成熟,与旧项目一致,Composition API |
|
||||
| UI 库 | 管理端 Element Plus + Tailwind / 用户端 Headless UI + Tailwind | 管理端企业级组件 + 用户端轻量交互 |
|
||||
| 部署 | Docker Compose → K8s | 渐进式扩展 |
|
||||
|
||||
---
|
||||
|
||||
*最后更新: YYYY-MM-DD*
|
||||
Reference in New Issue
Block a user