snack-mall/admin-snack
Yuhang Wu c9d85b0815 feat(module/seckill): 限时抢购 Redis Lua 防超卖 + 一人一单兜底
- 实体 SeckillActivity、SeckillProduct、SeckillOrder
- 枚举:SeckillActivityStatusEnum(含 calcStatus 时间驱动动态状态)、SeckillResultEnum
- RedisKey 追加 4 个抢购相关 key:SECKILL_STOCK / SECKILL_USER_RECORD / SECKILL_RESULT / SECKILL_WARMUP
- Mapper:decrRemainStock / incrRemainStock(MySQL 兜底)、forceEnd、markAsPaid
- resources/lua/seckill.lua:原子完成"限购校验 + 库存校验 + 扣库存 + 累计已购"
- Service:seckillBuy(核心:Lua 防超卖 → 落库 → 唯一索引兜底 → 落库失败回滚 Redis)
- Service:queryResult(轮询接口,从 Redis 取抢购结果)
- Service:warmupActivity(管理端预热,把库存同步到 Redis)
- Service:forceEnd / deleteActivity(清理 Redis)
- DTO:SeckillBuyReq、SeckillActivitySaveReq、SeckillProductAddReq
- VO:SeckillActivityVO(含动态状态 + 倒计时秒数)、SeckillProductVO(含实时 Redis 库存 + 已售百分比 + 折扣率)、SeckillResultVO
- Controller:用户端(活动列表/详情/抢购/结果查询)+ 管理端(活动 CRUD + 预热 + 强制结束 + 商品管理)
- 一人一单:seckill_order UNIQUE KEY (user_id, activity_id, sku_id) 兜底
- 抢购失败回滚:MySQL 落库异常时 INCRBY Redis 释放库存
feat(common/storage): 文件存储抽象接口 + Local / S3 双实现

- 抽象接口 FileStorage:store / delete / getAccessUrl / parsePathFromUrl
- LocalFileStorage:本地 ./uploads/ 物理存储(默认)
- S3FileStorage:S3 协议实现(RustFS / MinIO / AWS S3 / 阿里云 OSS)
- S3StorageProperties:snack.s3.* 配置类
- @ConditionalOnProperty 自动按 snack.storage.type 切换
- 启动时自动 ensureBucket(headBucket + createBucket)
- DisposableBean 容器关闭时关闭 S3Client 连接池

文件模块:
- 实体 UploadFile(含 storageType / bizType 区分)
- 枚举:FileBizTypeEnum(avatar/admin-avatar/product/sku/category/banner/notice/chat/common)
- Service:upload / uploadWithUploader / deleteFile / deleteByPath
- FileController:/api/file/upload + /api/file/{id}
- 图片类型自动校验(jpg/png/gif/webp)
- URL → path 反查(删除商品时根据 main_image 字段自动清理物理文件)
- application.yml:snack.storage.type / snack.upload.* / snack.s3.* 配置

管理端:
- AdminAvatarController /api/admin/avatar/upload
- CategoryAdminController 加 /api/admin/category/{id}/icon
- 删除分类时同步清理 icon 物理文件
2026-06-05 11:11:19 +08:00
..
public ``` 2026-06-02 10:05:37 +08:00
src feat(module/seckill): 限时抢购 Redis Lua 防超卖 + 一人一单兜底 2026-06-05 11:11:19 +08:00
.env.development feat: 完成商品分类管理功能,优化前后端配置与接口 2026-06-02 23:46:19 +08:00
.env.production ``` 2026-06-02 10:05:37 +08:00
.env.test feat: 完成商品分类管理功能,优化前后端配置与接口 2026-06-02 23:46:19 +08:00
.eslintrc-auto-import.json ``` 2026-06-02 14:25:53 +08:00
.gitignore ``` 2026-06-02 10:05:37 +08:00
.prettierrc.cjs.json ``` 2026-06-02 10:05:37 +08:00
.prettierrc.json ``` 2026-06-02 10:05:37 +08:00
README.md ``` 2026-06-02 10:05:37 +08:00
eslint.config.js ``` 2026-06-02 10:05:37 +08:00
index.html ``` 2026-06-02 10:05:37 +08:00
package-lock.json feat: 完成商品分类管理功能,优化前后端配置与接口 2026-06-02 23:46:19 +08:00
package.json feat: 新增用户与公告管理功能,优化后台菜单系统 2026-06-03 23:40:35 +08:00
pnpm-lock.yaml feat: 新增用户与公告管理功能,优化后台菜单系统 2026-06-03 23:40:35 +08:00
pnpm-workspace.yaml feat: 新增用户与公告管理功能,优化后台菜单系统 2026-06-03 23:40:35 +08:00
tsconfig.json ``` 2026-06-02 10:05:37 +08:00
tsconfig.node.json ``` 2026-06-02 10:05:37 +08:00
uno.config.ts ``` 2026-06-02 14:25:53 +08:00
vite.config.ts feat: 完成商品分类管理功能,优化前后端配置与接口 2026-06-02 23:46:19 +08:00

README.md

Admin Snack — 零食商城管理后台

基于 Vue 3 + Vite 6 + TypeScript 5 + Element Plus 的现代化电商管理后台。

技术栈

类别 技术
框架 Vue 3.5 (Composition API + <script setup>)
语言 TypeScript 5
构建 Vite 6
路由 Vue Router 4
状态 Pinia 2 + 持久化
UI 库 Element Plus 2.9
工具类 UnoCSS辅助
图表 ECharts 5 + vue-echarts
HTTP Axios
工具 dayjs、lodash-es、mitt、nprogress、VueUse
代码规范 ESLint 9 + Prettier 3
Node 要求 ≥ 20

快速开始

# 1. 安装依赖
npm install

# 2. 启动开发服务器
npm run dev
# 访问 http://localhost:5173

# 3. 生产构建
npm run build:prod

# 4. 类型检查
npm run type-check

# 5. 代码格式化
npm run format

默认账号

用户名admin
密  码123456

目录结构

admin-snack/
├── public/                      # 不经 vite 处理的静态资源
│   └── favicon.svg
├── src/
│   ├── api/                     # 接口请求层(按业务模块划分)
│   │   ├── auth.ts
│   │   ├── dashboard.ts
│   │   ├── product.ts
│   │   ├── order.ts
│   │   └── ...
│   ├── assets/                  # 静态资源
│   ├── components/              # 公共组件
│   │   ├── common/
│   │   └── business/
│   ├── hooks/                   # 组合式函数
│   ├── layouts/                 # 布局
│   │   ├── BasicLayout.vue      # 主框架(侧边栏+顶栏+内容区)
│   │   └── components/
│   │       ├── SideMenu.vue
│   │       └── NavBreadcrumb.vue
│   ├── permission.ts            # 路由守卫
│   ├── router/                  # 路由
│   │   ├── index.ts             # 基础路由
│   │   └── async-routes.ts      # 业务路由(按权限动态挂载)
│   ├── stores/                  # Pinia
│   │   ├── index.ts
│   │   └── modules/
│   │       ├── user.ts          # 用户/管理员
│   │       └── app.ts           # 应用全局
│   ├── styles/                  # 全局样式
│   │   ├── variables.scss       # 设计系统令牌
│   │   ├── reset.scss
│   │   ├── element.scss         # Element Plus 主题覆盖
│   │   ├── transitions.scss
│   │   └── index.scss
│   ├── types/                   # TS 类型
│   │   ├── api.ts
│   │   └── auth.ts
│   ├── utils/                   # 工具
│   │   ├── request.ts           # axios 封装
│   │   ├── date.ts              # dayjs 封装
│   │   ├── dict.ts              # 业务字典
│   │   └── bus.ts               # mitt 事件总线
│   ├── views/                   # 页面
│   │   ├── login/index.vue
│   │   ├── dashboard/index.vue
│   │   ├── product/
│   │   ├── order/
│   │   ├── user/
│   │   ├── coupon/
│   │   ├── seckill/
│   │   ├── notice/
│   │   ├── chat/
│   │   └── error/404.vue
│   ├── App.vue
│   └── main.ts
├── .env.development             # 开发环境变量
├── .env.test                    # 测试环境变量
├── .env.production              # 生产环境变量
├── eslint.config.js
├── .prettierrc.json
├── index.html
├── package.json
├── tsconfig.json
├── tsconfig.node.json
├── uno.config.ts
└── vite.config.ts

设计系统

风格 Minimalism · Data-Dense Dashboard
主色 #1E40AF(深蓝)/ #3B82F6(亮蓝)
辅色 #60A5FA
状态色 success #10B981 / warning #F59E0B / danger #EF4444
字体 系统字体栈PingFang SC / Microsoft YaHei
圆角 卡片 10px、按钮 6px、输入框 10px
阴影 三档sm / md / lg
背景 页面 #F8FAFC、卡片 #FFFFFF

后端联调

.env.development 中配置:

VITE_API_BASE_URL=http://localhost:8080

vite.config.ts 已配置 /api/uploads 路径代理到后端 server-snack 项目。

浏览器支持

现代浏览器 + ES2020Chrome 90+, Edge 90+, Firefox 90+, Safari 14+