snack-mall/AGENTS.md

9.3 KiB
Raw Blame History

AGENTS.md

This file provides guidance to Codex (Codex.ai/code) when working with code in this repository.

项目概览

零食商城(毕业设计)— 前后端分离的电商平台,SpringBoot 4 + Vue 3 单体多模块仓库:

目录 角色 技术栈
server-snack/ 后端 API Spring Boot 4.0.6、Java 21、MyBatis-Plus 3.5、Sa-Token 1.45、Redis、MySQL 8、Knife4j 4.6
admin-snack/ 管理后台前端 Vue 3.5 + Vite 6 + TypeScript 5 + Element Plus 2.9 + Pinia 2 + ECharts 5
db/ 数据库脚本与设计文档 schema.sql(建库 + 21 张表 DDLseed.sql(演示数据)、BUSINESS_DESIGN.md
功能设计文档.md 完整功能与接口设计(仓库根) v1.2,覆盖用户端/管理端/客服/公告/优惠券/抢购 6 大模块

用户端 web-snack 模块当前未在本仓库中(设计文档中描述),当前实际前端仅有 admin-snack 管理端。

常用命令

后端(server-snack/

# 构建(首次会下载依赖,可能需要较长时间)
mvn clean package

# 跳过测试运行
mvn spring-boot:run

# 单独跑测试
mvn test
mvn test -Dtest=类名#方法名   # 单个测试方法

# 开发工具热重启
mvn spring-boot:run -Dspring-boot.run.fork=true
  • 启动类:com.snack.server.ServerSnackApplication
  • 监听端口:8080
  • 接口文档Knife4jhttp://localhost:8080/doc.html
  • MySQL 默认连接:jdbc:mysql://localhost:3306/snack_mall(账号 root / 123456,见 application.yml
  • Redis 默认:localhost:6379
  • 本地上传文件 存储到 server-snack/uploads/,通过 /uploads/** 暴露为静态资源

数据库(db/

mysql -u root -p < schema.sql   # 建库 + 21 张表
mysql -u root -p < seed.sql     # 演示数据(管理员 admin/123456user001~user005/123456

管理端(admin-snack/

# 要求 Node ≥ 20
npm install
npm run dev                # 开发服务器http://localhost:5173已配置 /api 和 /uploads 代理到 8080
npm run build              # 类型检查 + 生产构建(默认 mode
npm run build:test         # 测试环境构建
npm run build:prod         # 生产环境构建
npm run type-check         # vue-tsc 类型检查
npm run lint               # ESLint --fix
npm run format             # Prettier 格式化

仓库内 pnpm-lock.yaml 已存在,但 package.json 脚本未区分包管理器;如本机用 pnpm命令相同pnpm dev 等)。 项目内默认账号 admin / 123456(管理端登录页 + 数据库 seed 同步)。

架构与约定

后端分层

每个业务模块位于 server-snack/src/main/java/com/snack/server/module/<name>/,统一包结构:

module/<name>/
├── controller/   # @RestController按"用户端 / 管理端"分文件(如 ProductPublicController / ProductAdminController
├── service/      # 业务接口
│   └── impl/     # 业务实现
├── mapper/       # MyBatis-Plus BaseMapper
├── entity/       # 数据库表实体(含 createTime / updateTime会被 MetaObjectHandler 自动填充)
├── dto/req       # 入参(带 jakarta.validation 注解)
├── vo/           # 出参(视图对象)
├── enums/        # 模块内枚举
└── constant/     # 模块内常量

跨模块共享放在 com.snack.server.{common,config,constant,exception,handler,utils,enums,websocket}

关键技术点

  1. 认证 — Sa-Token注意不是 JWT

    • 用户端与管理端走两套登录体系LoginType.USER / LoginType.ADMIN),通过 SaRouter.match 区分
    • Token 通过 Authorization 请求头传递(前端 Bearer ${token}
    • 拦截器在 config/SaTokenConfig.java 集中维护,按 URL 模式做登录校验
    • 业务异常401/403GlobalExceptionHandler 统一转 Result<Void>
  2. 统一响应 — Result<T>

    • 结构:{ code, message, data },封装在 common/Result.java
    • 业务码集中在 common/ResultCode.java200/400/401/403/404/500 + 1xxx 业务码)
    • 前端 axios 拦截器在 code === 200 时直接返回 datautils/request.ts)— 这是已解包约定,调用方拿到的就是业务数据
  3. MyBatis-Plus 约定

    • 逻辑删除字段:deleted0 未删 / 1 已删),全局生效
    • 主键自增:id-type: auto
    • 实体类继承 com.baomidou.mybatisplus.annotation.*,自动填充 createTime / updateTimeMybatisPlusMetaObjectHandler
    • 复杂 SQL 走 XMLsrc/main/resources/com/snack/server/module/<name>/mapper/*.xml
    • 建表 DDL 与 entity 字段必须保持一致,新增字段要同步两边
  4. Redis 键命名constant/RedisKey.java

    • 抢购库存:seckill:stock:{activityId}:{productId}
    • 用户抢购记录(限购):seckill:user:{userId}:{activityId}:{productId}
    • 客服在线用户集合:chat:online:users
    • 会话未读数:chat:unread:{sessionId}
    • 验证码:captcha:{uuid}
  5. WebSocket 客服模块websocket/ 当前为占位 gitkeepBUSINESS_DESIGN.md 有详细方案)

    • Spring WebSocket + STOMP握手时验证 JWT
    • 消息全部落库 chat_message,离线消息不丢
    • 用户端用 stomp.js;管理端会话页在 views/chat/
  6. 防超卖(抢购核心)

    • Redis DECR 原子扣减库存 → 失败直接返回"已抢完"
    • 写入异步队列 → 消费端落 MySQL详见 功能设计文档.md 3.6.2
  7. 接口规范

    • 用户端路径:/api/<资源>(例:/api/cart/api/orders/{id}/pay
    • 管理端路径:/api/admin/**(登录、验证码、文件上传除外)
    • RESTful列表 GET、创建 POST、详情 GET {id}、删除 DELETE {id}

前端约定(admin-snack/

  1. 路径别名@src/Vite + tsconfig 双侧配置)

  2. 自动导入unplugin-auto-import + unplugin-vue-components

    • 自动导入 Vue / Vue Router / Pinia API、Element Plus 组件
    • 类型声明由插件生成到 src/types/auto-imports.d.tssrc/types/components.d.ts
    • 业务文件中不要手动 import { ref, computed } from 'vue' — 插件已处理
  3. 状态管理 — Pinia + 持久化

    • stores/modules/user.ts 持久化 key 为 snack-admin-user
    • 用 Composition API 写法(defineStore('user', () => { ... })),不是 Options API
  4. 请求层utils/request.ts

    • axios 实例baseURL 取 VITE_API_BASE_URL.env.development 默认 http://localhost:8080
    • 响应拦截器已解包code === 200 时直接 return data,调用方拿到的就是业务数据
    • 401 自动清空登录态并跳 /login
    • 所有 API 文件(api/*.ts)用 request<T>(config) 二次封装
  5. 路由router/

    • index.ts基础路由login、404、仪表盘占位
    • async-routes.ts:业务路由清单(与 index.ts 同步维护,权限动态挂载用)
    • 路由守卫在 src/permission.ts,白名单 ['/login', '/404']
    • 默认页签布局:layouts/BasicLayout.vue(侧栏 + 顶栏 + TabsNav
  6. 样式

    • SCSS 全局变量由 vite.config.tsadditionalData 自动注入 @use "@/styles/variables.scss" as *;
    • 业务组件中直接使用变量即可,不要重新 import
    • 设计令牌:主色 #1E40AF / #3B82F6,圆角 6/10px背景 #F8FAFC(详见 admin-snack/README.md
  7. Mock

    • src/mock/index.ts 启动时拦截 API 返回本地假数据(基于 mockjs + axios-mock-adapter
    • 联调后端时注释掉 main.ts 里的 import './mock' 即可关闭
  8. 设计系统Minimalism · Data-Dense Dashboard状态色 success #10B981 / warning #F59E0B / danger #EF4444,圆角与阴影三档(admin-snack/README.md 有完整表)

全局约定

  • 不要 commit 真实密钥.env.*.localserver-snack/application-local.yml*.pem/*.key/*.crt 已被 .gitignore 排除
  • Java 版本21<java.version>21</java.version>
  • Node 版本:≥ 20
  • 包管理器:管理端 pnpm-lock.yaml 已存在
  • Maven 仓库:内置了华为云、阿里云镜像加速
  • 不需要写 README、通用开发规范、显而易见的"添加注释"等指令

关键文档

文档 路径 何时读
功能设计总览 功能设计文档.md 任何新模块开发前
业务核心设计WebSocket + 防超卖) db/BUSINESS_DESIGN.md 客服/抢购相关开发前
数据库表结构 db/schema.sql + db/README.md 新增/修改实体前
管理端技术栈与命令 admin-snack/README.md 前端环境问题排查

调试与排错

  • 后端启动失败:先检查 MySQL/Redis 是否启动、端口是否被占用、knife4j 文档能否打开
  • 前端 401 风暴:检查 VITE_API_BASE_URL、浏览器是否带了 Authorization 头、Sa-Token 拦截器路径配置
  • 抢购超卖:先看 Redis 中 seckill:stock:* 键值,再用 BUSINESS_DESIGN.md 对照流程
  • 类型错误:运行 npm run type-check(管理端),不要绕过 vue-tsc 直接 build
  • 本地上传文件访问不到:确认 WebMvcConfig.addResourceHandlers/uploads/**file:./uploads/ 配置,并查看 snack.upload.domain 是否正确