1项目架构总览
「易搭衣橱」由三个端构成,共用同一套 Koa 后端与 MySQL 数据库:
- 用户端 easyClothing-plus-front:Vue 3 + Vant 4 的移动端 H5 应用,运行于
http://127.0.0.1:8080,承载商品浏览、穿搭技巧、社区发帖、消息、AI 穿搭助手等全部 C 端功能。 - 管理端 easyClothing-admin:React 19 + TypeScript 的运营后台,运行于
http://127.0.0.1:8081,承载数据概览与用户 / 帖子 / 商品 / 技巧 / 评论 / 反馈 / 公司站点的审核与管理。 - 后端 easyClothing-plus-backend:Koa 2 服务,监听
http://127.0.0.1:3033,提供全部 REST API,数据存储使用 MySQL(库名baijiahao),热点数据走 Redis 缓存。
┌─────────────┐ ┌─────────────┐ ┌──────────────────┐
│ 用户端 H5 │ │ 管理端 │ │ 对外静态站点 │
│ Vue3+Vant4 │ │ React+AntD │ │ 官网 /docs 文档站 │
│ :8080 │ │ :8081 │ │ 后端 public 托管 │
└──────┬──────┘ └──────┬──────┘ └────────┬─────────┘
│ vite proxy │ CORS + token │ 静态托管
▼ ▼ ▼
┌─────────────────────────────────────────────────────┐
│ Koa 2 后端服务 :3033 │
│ 路由 / 鉴权 / 上传 / 业务模型 / AI 多模型调度 │
├──────────────────────┬──────────────────────────────┤
│ MySQL(baijiahao) │ Redis(热点缓存) │
└──────────────────────┴──────────────────────────────┘
2技术栈清单
Vue 3
渐进式前端框架,组合式 API 组织页面逻辑,配合 vue-router 实现 history 路由。
vite.config.ts 配置代理转发后端请求。Vant 4
移动端组件库,提供 Tabbar、NavBar、Popup、Swipe、Search 等开箱即用的移动组件。
React 19 + TypeScript
类型安全的 UI 构建方案,Hooks 管理组件状态,TS 保证接口数据契约。
tsc -b 严格类型检查后构建;api 层集中定义请求函数与参数类型。Ant Design 6
企业级 React 组件库,提供 Table、Form、Modal、Statistic 等后台常用组件与中文 locale。
ConfigProvider 统一主题色(#8a5cf6)与中文语言包。Zustand
轻量状态管理库,基于 Hooks 的 store 订阅模型,配合 persist 中间件做本地持久化。
store/auth.ts 保存登录 token 与用户名,刷新后自动恢复登录态。Tailwind CSS 4
原子化 CSS 框架,通过 @tailwindcss/vite 插件零配置接入,按需生成工具类。
h-screen、flex items-center),其余样式用 antd 主题与内联类。Vite 8
极速前端构建工具,开发服务器带 HMR,生产构建基于 Rolldown 打包。
port 8081 与 Tailwind 插件。Koa 2
轻量 Node.js Web 框架,洋葱模型中间件,配合 koa-router / koa-body / koa-static。
app.js 启动 + 全局异常兜底;src/router 注册全部路由;src/controller 分层处理业务;public 目录托管官网与文档静态站。MySQL 8
关系型数据库,存储用户、商品、帖子、评论、穿搭技巧、反馈等全部业务数据。
mysql 驱动(20 连接),各模块建表语句启动时幂等执行;关键表:cloth / article / comment / cmatch / admin / company_info / team_member。Redis
内存缓存与热点加速,降低数据库压力。
多模型调度
穿搭推荐与文案生成支持 Claude / DeepSeek / 通义千问 / Kimi 多供应商配置,自动降级。
controller/ai.js 按配置顺序尝试各模型,失败即切换下一个;调用日志写入 ai_llm_log 表。3基础地址与响应格式
后端统一基础地址:http://127.0.0.1:3033。所有接口返回统一 JSON 结构:
{ "code": 0, "msg": "success", "data": { ... } }
code = 0:成功,业务数据在data中。code = -1:业务失败,msg为错误提示(HTTP 状态通常仍为 200;管理端未登录返回 HTTP 401)。
列表类接口统一分页参数:page(页码,从 1 开始)、limit(每页条数),返回 { total, list };关键词过滤统一使用 keyword。
4鉴权方式
管理端与用户端均使用自定义 Token 头:
authentication: "<token>" // 注意:值带英文双引号(后端会去除后校验)
- 用户端:登录 / 注册接口返回 token,请求封装在
src/request/axios.js中统一注入。 - 管理端:
POST /admin/login获取 token,存于 localStorage(zustand persist);axios 请求拦截器自动携带;后端重启后 token 失效,前端自动跳转登录页。
5前端 API 封装
用户端(Vue3 + Vant4)
统一封装位于 src/request/axios.js(导出 _service):
- GET 请求第二参数传
{ params: {...} }; - 拦截器判断
res.code === 0为成功,否则提示msg并 reject; - 自动注入
authentication请求头; - 开发环境经 vite proxy 将接口转发到 3033。
import { _service } from "@/request/axios.js";
_service.get("/cloth/index", { params: { page: 1, limit: 10 } }); // 商品列表
_service.post("/user/login", { username, password }); // 登录
管理端(React + TS)
请求封装位于 src/api/http.ts,接口函数位于 src/api/admin.ts:
- axios 实例 baseURL 直连
http://127.0.0.1:3033(后端已开启 CORS); - 响应拦截器在
code === 0时直接返回data;HTTP 401 时清除 token 并跳转登录页; - 请求拦截器读取
localStorage.admin_token并注入authentication头。
import { getUsers, toggleUser } from '../api/admin';
const d = await getUsers({ page: 1, limit: 10, keyword: '' }); // d = { total, list }
await toggleUser(id, 0); // 封禁用户
6用户与关注
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /user/login | 用户登录,body: username/password,返回 token |
| POST | /user/register | 用户注册 |
| POST | /user/follow | 关注用户 |
| POST | /user/unfollow | 取消关注 |
| GET | /user/follow-list | 我的关注列表(支持取关) |
| GET | /user/fans-list | 我的粉丝列表 |
| GET | /user/counts | 关注 / 粉丝 / 作品计数 |
| GET | /user/home | 用户主页:个人信息 + 作品(时间 / 热度排序) |
7商品与穿搭技巧
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /cloth/index | 商品列表(分页 / 分组 / 关键词) |
| GET | /cloth/detail | 商品详情 |
| GET | /cloth/sort | 商品分组(分类)列表 |
| POST | /cloth/save | 保存商品(用户收藏 / 浏览记录) |
| POST | /cloth/search | 商品搜索 |
| GET | /match/tag | 穿搭技巧分组(tab)列表 |
| GET | /match/list | 穿搭技巧列表(支持 group_id 过滤) |
| GET | /match/search | 穿搭技巧搜索(定位到分组) |
| GET | /match/detail | 单条穿搭技巧详情(搜索定位置顶) |
8帖子与互动(社区)
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /article/list | 帖子列表(信息流) |
| GET | /article/detail | 帖子详情(作者 / 评论 / 点赞数据) |
| GET | /article/mine | 我的作品 |
| GET | /article/browse-history | 浏览历史 |
| GET | /article/liked | 我点赞的帖子(喜欢) |
| GET | /article/search | 帖子搜索 |
| GET | /article/comment | 评论列表(二级评论,回填 like_count 点赞数与当前用户 liked 状态) |
| POST | /article/comment/like | 点赞 / 取消点赞评论(body: articleId, replyId;给评论作者发"赞了你的评论"消息,未读去重) |
| POST | /article/publish | 发布帖子(含可选 isAi 标记;is_ai=1 表示含 AI 生成文案/配图,管理端帖子列表展示 AI 标识) |
| POST | /article/draft/save | 保存/新建草稿(自动保存,含 isAi 标记) |
| GET | /post/draft/list | 草稿列表(草稿数量角标) |
| POST | /post/draft/publish | 草稿发布 |
| POST | /post/draft/delete | 删除草稿 |
| POST | /post/like | 点赞 / 取消点赞 |
| POST | /post/forward | 转发 |
| POST | /post/comment | 发表评论(支持回复别人 = 二级评论) |
9AI 穿搭助手 AI
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /ai/recommend | AI 穿搭推荐:读取对话历史 → 多模型调度生成(Claude → DeepSeek → 通义千问 → Kimi 自动降级)→ 保存对话与推荐记录 → 返回商品映射与链接 |
| GET | /ai/recommend/list | 推荐历史列表(含 LLM 用途) |
| GET | /ai/conversation | 读取对话历史 |
| POST | /ai/conversation/remove | 删除对话 |
| POST | /ai/feedback | 推荐结果反馈(有用 / 没用) |
| POST | /ai/copywriter | AI 辅助生成帖子文案(专业 / 温暖 / 幽默风格,返回正文 content 与推荐指数 recommendationScore,多模型自动降级) |
| GET | /ai/copywriter/images | 发帖配图推荐。优先 AI 文生图(通义万相,复用 DashScope Key,图存后端 /images/ai),未配置 Key / 超时 / 失败时自动降级到内部商品库按标签匹配。返回 source(ai / library)与 list[{id,tag,cover,ai}];参数 source=library 可强制走商品库("换一批"免费) |
| GET | /ai/llm-status | LLM 调用状态与日志信息 |
| GET | /ai/products | 推荐结果商品映射列表 |
AI 推荐降级链路
读取对话历史
→ 尝试 Claude ├─ 成功 → 返回(保存对话 / 记录推荐)
→ 尝试 DeepSeek ├─ 失败 → 下一个
→ 尝试通义千问 ├─ 失败 → 下一个
→ 尝试 Kimi ├─ 成功 → 返回
└─ 全部失败 → 返回"全部不可用"错误
(每次调用写入 ai_llm_log 日志表)
10搜索
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /search/hot | 热门搜索词 |
| GET | /search/history | 搜索历史 |
| GET | /search/recom | 搜索联想(附近匹配 / 部分匹配,用于输入辅助) |
| POST | /search/clear | 清空搜索历史 |
搜索页三栏:商品 / 穿搭技巧 / 帖子,分别对接 /cloth/search、/match/search、/article/search。
11消息
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /message/list | 消息列表(回复 / 收到喜欢 / 系统,按时间降序) |
| GET | /message/unread | 未读数 |
| POST | /message/read | 标记单条已读(未读数 -1) |
| POST | /message/read-all | 全部已读 |
12管理端接口 需登录
管理端接口统一前缀 /admin,需在 authentication 头携带管理员 token(POST /admin/login 获取)。
admin/admin123 仅做功能展示——所有写操作(POST/PUT/DELETE)会返回 code=4031,不真正修改数据库;真正可写库的最高管理员账号不对外公开。登录返回值中 role 为 demo/super,demo=true 表示只读演示。
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /admin/login | 管理员登录(返回 token/username/role/demo) |
| GET | /admin/whoami | 当前登录身份(username/role/demo) |
| POST | /admin/cleanup-demo | 一键清理 demo_ 开头的模拟账号及其帖子/评论(仅最高管理员) |
| GET | /admin/dashboard | 数据概览(统计 / 最近用户 / 分组分布 / 反馈分布) |
| GET | /admin/users | 用户列表(搜索 / 分页) |
| POST | /admin/user/toggle | 封禁 / 解封 |
| POST | /admin/user/remove | 删除用户(级联删除帖子 / 评论 / 点赞 / 关注) |
| GET | /admin/articles | 帖子列表(含评论数)。查询参数:keyword(标题/ID/内容)、author(作者名)、status(1展示/0下架)、source(1 AI创作 / 0 原创)、分页 page/limit;列表含 is_ai 字段 |
| POST | /admin/article/toggle | 下架 / 恢复 |
| POST | /admin/article/remove | 删除帖子 |
| GET | /admin/cloths | 商品列表 |
| POST | /admin/cloth/toggle | 上架 / 下架 |
| POST | /admin/cloth/save | 新增 / 编辑商品(body 含 id 时为编辑,字段:tag/goods_id/description/price/discount/likes/nums/cover/group_id/tag_list/is_show) |
| GET | /admin/matches | 穿搭技巧列表(分组筛选) |
| POST | /admin/match/save | 新增 / 编辑技巧 |
| POST | /admin/match/remove | 删除技巧 |
| GET | /admin/groups | 技巧分组列表 |
| POST | /admin/group/save | 新增 / 编辑分组 |
| POST | /admin/group/remove | 删除分组 |
| GET | /admin/comments | 评论列表 |
| POST | /admin/comment/toggle | 隐藏 / 恢复评论 |
| POST | /admin/comment/remove | 删除评论 |
| GET | /admin/suggests | 用户反馈列表 |
| POST | /admin/suggest/status | 标记处理状态 |
| POST | /admin/suggest/remove | 删除反馈 |
| GET | /admin/config | 读取系统配置(站点信息 / 邮件 / 用户协议 / 更新日志 / LLM 配置) |
| POST | /admin/config | 保存系统配置。新增字段:llm_order(JSON 数组,LLM 降级顺序)、llm_balance_threshold(JSON {模型:阈值})、llm_current_balance(JSON {模型:当前额度})、llm_alert_cooldown_hours(同模型两次预警间隔) |
| GET | /admin/llm/keys | 查询各厂商 API Key。仅 super 最高管理员返回明文(visible:true, keys:{...});其他账号返回 visible:false, keys:null,仅含各模型"是否已配置"布尔标记,后端不下发任何密钥 |
| POST | /admin/llm/keys | 一键保存各厂商 API Key 到 llm-config.json(仅 super 可写,演示账号返回 4031)。字段:claude/deepseek/qwen/kimi,留空或 __keep__ 表示保持原密钥不变 |
| GET | /system/agreement / /system/changelog | 公开 用户协议 / 更新日志(从数据库读取,管理端可编辑;v2.0.0 及以前的日志锁定不可改) |
13公司站点与核心团队
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/site/info | 公开 公司介绍(名称 / slogan / 简介 / 产品 / 招聘 / 联系方式),官网页面动态读取 |
| GET | /api/site/team | 公开 核心团队(仅展示中成员,按排序) |
| GET | /admin/site/info | 需登录 读取公司全部配置(编辑回填) |
| POST | /admin/site/info | 需登录 保存公司配置(body: company 对象) |
| GET | /admin/team | 需登录 团队列表(含隐藏) |
| POST | /admin/team/save | 需登录 新增 / 编辑成员 |
| POST | /admin/team/remove | 需登录 删除成员 |
| POST | /admin/team/toggle | 需登录 显示 / 隐藏成员 |
公司信息存储于 company_info(key-value 配置表),团队成员存储于 team_member;官网(/site/)与本文档(/docs/)由后端 koa-static 托管,属于 SEO 友好的静态页面。