# warmpet **Repository Path**: alfalee_admin/warmpet ## Basic Information - **Project Name**: warmpet - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-22 - **Last Updated**: 2026-10-30 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 暖宠同城 · 宠物信任生态平台(uni-app + Web + Java 全栈版) 商业计划书与软件思维导图落地的完整工程:**uni-app(Vue3) 混合 App/H5/微信小程序 + Vue3 管理后台(供货商 + 平台 PC)+ Spring Boot 后端**。 一句话职责划分:**C 端买、团长端卖、供货商端供、平台端审与分账,后端统一记账**。 --- ## 一、目录结构 ``` warmpet/ ├── uniapp/ 【原始迁移版】uni-app(Vue3+JS) 小程序工程(保留作对照) ├── uniapp-app/ 【推荐】官方 uni-app Vue3 脚手架重建的工程(混合 App+H5+微信小程序) │ ├── package.json @dcloudio/uni-app + vite(scripts: dev:h5 / dev:mp-weixin / dev:app / build:*) │ ├── vite.config.js H5 代理 /api → 8080(并剥离 Origin,避免开发期 CORS) │ ├── index.html │ └── src/ │ ├── main.js / App.vue App.vue 仅 onLaunch 调 store.login(),无全局登录弹窗 │ ├── pages.json 页面路由(含 /pages/login/index 独立登录页) │ ├── manifest.json mp-weixin(调试 localhost) / app-plus / h5 SDK 配置 │ ├── api/ config / request(含单飞刷新+401 统一跳转)/ index / modules/* │ ├── store/ index.js(登录态、openLogin、requireLogin、刷新) │ ├── utils/ platform.js(端判断)、wx-login.js、toast 等 │ ├── components/login/ 微信/账号密码/短信/绑定 登录面板 │ └── pages/ 业务页面(社区/商城/团长/公益/我的 等) ├── web-vue/ 【推荐】Vue3 + Vite + Pinia 管理后台(供货商 + 平台运营) │ ├── package.json vite dev 默认 5173(建议与 uniapp 错开端口,避免抢占) │ ├── vite.config.js /api 代理到 8080,并剥离 Origin │ └── src/ │ ├── api/ request.js(ApiError+单飞刷新)/ auth.js / index.js │ ├── stores/auth.js 登录态、homePath、fetchMe、refresh │ ├── router/index.js meta.roles 角色路由守卫 + redirect 回跳 │ └── views/ │ ├── LoginView.vue 账号密码 / 微信扫码 / 短信登录 三合一 │ ├── login/ WxQrPanel / PasswordPanel / SmsPanel / BindPanel │ ├── admin/ 平台总后台 │ └── supplier/ 供货商后台 ├── web/ 【旧版】静态 HTML 管理端(已去演示化,仅作对照,建议迁移到 web-vue) ├── server/ Spring Boot 2.7.18 + MyBatis-Plus(Java 8) │ ├── pom.xml │ ├── db/mysql-init.sql MySQL 一键初始化(建库建表 + 种子数据) │ └── src/main/ │ ├── java/com/warmpet/ │ │ ├── common/ R 统一响应、ErrorCode、异常、PasswordUtil(BCrypt+明文兼容) │ │ ├── security/ JwtUtil(access+refresh claims)、@RequireRole、LoginUser、AuthInterceptor │ │ ├── config/ WebConfig(CORS)、MyBatisPlusConfig │ │ ├── entity/ RefreshToken(t_refresh_token)等 18+ 张表 │ │ ├── service/ AuthService / WxQrLoginService / Order / Admin / Supplier / Product ... │ │ └── controller/ Auth / Home / Product / Order / Commission / Leader / │ │ Community / Activity / Charity / Member / Supplier / Admin │ └── resources/ │ ├── application.yml 默认 profile = mysql │ └── application-mysql.yml MySQL 连接(运行库) └── docs/ ├── 三端功能与系统设计.md └── uni-app迁移与后端接入.md ``` --- ## 二、鉴权与 Token 方案(统一处理) 全栈统一两套令牌 + 单飞刷新,前后端一致。 ### 1. 令牌 | 令牌 | 形态 | 时效 | 存储 | | --- | --- | --- | --- | | accessToken | JWT(HS256,claims: `sub`/`role`/`jti`/`ver`) | 2h | Web `localStorage.sessionStorage['wp_at']`;小程序/App `uni.setStorageSync('wp_at')` | | refreshToken | 不透明串(SHA-256 入库 `t_refresh_token`,`ver` 用于旋转失效) | 30d 滑动 | `wp_rt`(持久);删除即全部下线 | ### 2. 请求层统一行为(web-vue 与 uniapp-app 一致) - 每次请求在 Header 注入 `Authorization: Bearer `(无 token 则跳过,公开接口照常)。 - 收到 **401** → 进入刷新流程:`POST /auth/refresh`(携带 refreshToken),**单飞(single-flight)** 并发请求排队,刷新成功用新 token 重放;刷新失败(refreshToken 过期/失效)则清空登录态并跳登录页(带当前页 `redirect`)。 - 收到 **403** 区分两类:后端业务包体(`"角色无权"` 等原样提示);非包体网关/CORS 拦截(`"请求被服务器拒绝(HTTP 403):请检查后端 CORS 白名单或代理配置"`)。 - **密码安全**:登录密码 BCrypt 存储;历史明文密码首次登录时 `PasswordUtil.needsUpgrade` 自动升级为 BCrypt(`- {bcrypt}` 前缀)。 ### 3. 登录方式 | 方式 | 入口 | 接口 | 说明 | | --- | --- | --- | --- | | 微信登录 | 小程序/App 静默;PC 扫码 | `POST /auth/wx-login`(body `code`,`client`) | `client` 按端分流小程序 jscode2session / 开放平台移动应用 / 公众号;PC 用 `GET /auth/wx/qrcode` 轮询 `GET /auth/wx/qrcode/{ticket}/status` | | 账号密码 | Web 登录页 / 小程序登录页 | `POST /auth/login`(body `account`,`password`,`client`) | 返回 `token`+`refreshToken`+`user` | | 短信登录 | Web/小程序登录页(预留) | `POST /auth/sms/send`、`POST /auth/sms/login` | 验证码接口已落地,前端面板已挂接 | **登录成功路由**:Web 按 `user.role` 跳转 `/admin`(平台运营)或 `/supplier`(供货商);角色不符(宠主/团长)明确提示「该账号角色为「团长」,仅供货商与平台运营可登录后台」。小程序/App 未登录访问受保护接口时调 `openLogin()` 跳 `/pages/login/index`(带 `redirect` 当前页),同一页面只自动跳一次,避免 onShow 循环。 ### 4. 后端环境配置(必须) | 变量 | 用途 | 默认/说明 | | --- | --- | --- | | `WARMPET_JWT_SECRET` | JWT 签名密钥 | 必填,≥ 32 位;不配会启动失败 | | `WARMPET_WX_MINI_APPID/SECRET` | 微信小程序登录 | 未配回退 `openid-demo`(仅联调) | | `WARMPET_WX_APP_APPID/SECRET` | 开放平台移动应用(App 登录 + App 支付) | | | `WARMPET_WX_WEB_APPID/SECRET` | 网站应用(PC 扫码) | | | `WARMPET_WX_H5_APPID/SECRET` | 公众号网页授权(H5 内) | | | `WARMPET_PAY_WX_APP_APPID` | App 支付商户 AppId | | | `WARMPET_CORS_ORIGINS` | CORS 允许来源 | 默认 `http://localhost:[*],http://127.0.0.1:[*]`;生产务必显式配置真实域名(**禁止保留 `*`**) | > 开发期 Vite 代理已剥离 `Origin`,因此本地换端口(5174/5180…)或用 `127.0.0.1` 访问都不会触发 CORS 403;只有**直接跨域请求后端(不走代理)**时才依赖上面的白名单。 --- ## 三、启动方式 ### 1. 后端(先启动,端口 8080) > **⚠️ 必须用 Java 8(JDK 1.8)。** 本项目 Spring Boot 2.7.18 + MyBatis-Plus 3.5.3.2,不支持 Java 9+。IDEA 启动请把 SDK 与 Run/Debug 的 JRE 都改成 JDK 1.8(本机 `D:\Program Files\Java\jdk1.8.0_231`)。 ```bash cd server # 1) 导入 MySQL(建库 warmpet + 18 张表 + 模拟数据),务必指定 utf8 mysql --default-character-set=utf8 -uroot -p < db/mysql-init.sql # 2) 额外建表:刷新令牌(迁移脚本未含,在 MySQL 客户端执行下列 SQL 一次) ``` ```sql CREATE TABLE IF NOT EXISTS t_refresh_token ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL, token_hash CHAR(64) NOT NULL, ver INT NOT NULL DEFAULT 1, device VARCHAR(64), expires_at DATETIME NOT NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_token_hash (token_hash), KEY idx_user (user_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; # 3) 启动(默认 mysql profile,注入必要环境变量) set WARMPET_JWT_SECRET=请改成至少32位随机串 mvn spring-boot:run # 或打包运行 mvn -DskipTests package java -Dfile.encoding=UTF-8 -jar target/warmpet-server-1.0.0.jar ``` - 健康检查:`GET http://localhost:8080/api/v1/home` - 冒烟测试:`mvn test`(H2 内存库,跑通「下单→支付→发货→收货→佣金结算」及后台审核、登录与刷新链路) ### 2. 小程序 / 混合 App(uniapp-app) ```bash cd uniapp-app npm install # 真机/微信联调需把后端地址写进 .env.local(局域网 IP,不能用 localhost) # VITE_API_BASE=http://192.168.x.x:8080 npm run dev:h5 # 浏览器预览(默认 5173) npm run dev:mp-weixin # 产物 dist/dev/mp-weixin,用微信开发者工具导入 npm run dev:app # 自定义基座真机调试 npm run build:mp-weixin # 生产构建 ``` - 微信开发者工具导入目录:`uniapp-app/dist/dev/mp-weixin` - `manifest.json → mp-weixin.setting.urlCheck = false` 已设,可直接请求 `http://localhost:8080` - 已为 App / H5 / 微信三端分别处理:凭证按端拆分、支付按端选 `JSAPI/APP/NATIVE`、地址选择回调用 `uni.$emit` 双通道兼容 ### 3. 管理后台(web-vue,推荐) ```bash cd web-vue npm install npm run dev -- --port 5180 --strictPort # 建议与 uniapp 错开端口 # 或默认 5173 npm run build # 产物 dist/ ``` - 登录页支持 **账号密码 / 微信扫码 / 短信登录** 三种方式;登录后按角色进入 `/admin` 或 `/supplier`。 - 无 token 或 401 → 自动跳登录页;角色不符 → 明确提示实际角色。 > 旧版 `web/` 静态 HTML 仅作对照,建议统一迁移到 `web-vue`。 ### 4. 演示账号 | 角色 | 账号 | 密码 | 用途 | | --- | --- | --- | --- | | 平台运营 | `admin` | `123456` | 平台 PC 后台(web-vue `/admin`) | | 供货商 | `supplier` | `123456` | 供货商后台(web-vue `/supplier`) | | 团长/宠主 | 小程序/App 内微信静默登录 | — | demo 账号「团子妈」(多群团长 40%) | --- ## 四、后端接口一览(`/api/v1`) ### 认证(Auth) | 接口 | 权限 | 说明 | | --- | --- | --- | | `POST /auth/wx-login` | 公开 | 微信登录,`{code, client}`;client 决定端(mini/app/h5) | | `POST /auth/login` | 公开 | 账号密码登录 `{account, password, client}` | | `POST /auth/refresh` | refreshToken | 旋转刷新,返回新 access/refresh | | `POST /auth/logout` | refreshToken | 注销当前刷新令牌 | | `GET /auth/me` | 登录 | 当前用户信息(含 role) | | `GET /auth/wx/qrcode` | 公开 | 生成 PC 扫码登录 ticket | | `GET /auth/wx/qrcode/{ticket}/status` | 公开 | 轮询扫码状态 | | `POST /auth/wx/qrcode/{ticket}/confirm` | 微信端 | 手机端确认登录 | | `POST /auth/sms/send` | 公开 | 发送短信验证码 | | `POST /auth/sms/login` | 公开 | 短信验证码登录 | ### 业务 | 模块 | 接口 | 角色 | | --- | --- | --- | | 首页 | `GET /home` | 公开 | | 商品 | `GET /products?cat&sort&keyword`、`GET /products/{id}`、`GET /products/categories` | 公开 | | 订单 | `POST /orders`、`GET /orders?status`、`GET /orders/{id}`、`POST /orders/{id}/pay`、`/confirm`、`/cancel`、`/aftersale`、`GET /orders/{id}/logistics` | 宠主/团长 | | 分佣 | `GET /commission/summary`、`GET /commission/records`、`POST /withdraw` | 宠主/团长 | | 团长 | `GET /promote/profile`、`POST /leader/apply`、`GET /leader/sop` | 宠主/团长 | | 宠友圈 | `GET /posts?board`、`GET /posts/{id}`、`POST /posts`、`POST /posts/{id}/like`、`/collect`、`/report`、`GET/POST /posts/{id}/comments` | 公开 / 登录 | | 活动 | `GET /activities?type`、`GET /activities/{id}`、`POST /activities/{id}/signup` | 公开 / 登录 | | 公益 | `GET /charity?type` | 公开 | | 会员 | `GET/POST /pets`、`GET /messages`、`POST /messages/{id}/read`、`/messages/read-all` | 登录 | | 供货商 | `GET /supplier/profile`、`/qualification`、`/orders`、`POST /supplier/orders/{id}/ship`、`GET/POST /supplier/products`、`POST /supplier/qc`、`GET /supplier/aftersales`、`POST /supplier/aftersales/{id}/handle`、`GET /supplier/finance`、`/finance/summary` | 供货商 | | 后台 | `GET /admin/dashboard`、`GET /admin/products/pending`、`POST /admin/products/{id}/audit`、`GET /admin/suppliers`、`GET /admin/leaders`、`POST /admin/leaders/{id}/verify`、`GET/PUT /admin/leaders/rules`、`GET /admin/orders`、`POST /admin/orders/{no}/arbitrate`、`GET /admin/aftersales`、`GET /admin/posts`、`POST /admin/posts/{id}/audit`、`POST /admin/posts/batch-pass`、`GET/POST /admin/activities`、`GET /admin/finance/splits`、`/finance/summary`、`GET /admin/users`、`POST /admin/users/{id}/toggle` | 运营 | 统一响应:`{ "code": 0, "message": "ok", "data": ... }`;未登录返回 HTTP **401**(触发刷新/跳登录),角色不符返回 **403**。 --- ## 五、数据落库与业务规则 - **下单即记账**:创建订单时同时写入 `t_order`、`t_order_item`、`t_commission`(待结算),按 `金额 × 等级比例` 预计算佣金、按 10% 预计算平台服务费。 - **确认收货结算佣金**:订单置 `done`,佣金转 `SETTLED` 并累加进 `t_user.commission`,同时写站内消息。 - **发货**:供货商录入快递公司与单号 → 订单转 `shipped`,物流节点同步给用户。 - **商品双重审核**:供货商提交 → `AUDIT`;运营通过置 `ON + qc=PASS`,驳回置 `OFF + qc=REJECT`,全程写 `t_audit_log`。 - **内容先审后发**:发布即 `PENDING`,仅审核通过进入信息流;举报累计 3 次自动 `REJECT`。 - **团长等级**:只按活跃社群规模定级(0 → 20%,≥1 → 30%,≥10 → 40%),不收任何费用、不做多层级。 - **分账明细**:后台按订单实时拆成「平台服务费 / 团长佣金 / 供货商货款」三份,退款单直接归零。 --- ## 六、迁移与验证情况 | 项 | 结果 | | --- | --- | | 页面数 | uniapp-app 与原生小程序 1:1 | | 模板转换 | WXML → Vue3 语法,无 `wx:`/`bindtap` 残留 | | 构建 | `uniapp-app` 的 `build:h5` / `build:mp-weixin` / `build:app` 均通过;`web-vue` `npm run build` 通过 | | 后端编译 | `mvn package` 通过(Java 8 / Spring Boot 2.7.18) | | 后端用例 | `mvn test` 覆盖建表+种子+交易链路+后台审核+登录/刷新/密码升级+微信按端分流 | | 真实浏览器 E2E(web-vue) | admin/123456 → `/admin` 数据看板;supplier/123456 → `/supplier`;团长 → 明确角色提示;密码错误 → 「账号或密码错误」 | > uniapp-app 已移除本地演示数据兜底,必须连接真实后端;任何接口异常如实暴露。 --- ## 七、后续可继续做的事 1. 支付:接入微信支付「电商收付通」,把 `POST /orders/{id}/pay` 换成 `jsapi` 预下单,分账比例按 `t_split_rule` 下发(App 端已支持 APP 支付)。 2. 物流:把 `OrderService#logistics` 换成快递 100 / 快递鸟查询。 3. 文件存储:商品图与帖子图接对象存储,`img` 字段改为 URL。 4. 短信:生产接入真实短信服务商(当前 `/auth/sms/send` 走 Mock)。 5. 后台补齐分页与导出(当前演示数据量小,直接全量返回)。 6. 生产部署:设置 `WARMPET_JWT_SECRET`、`WARMPET_CORS_ORIGINS`(真实域名)、四组微信凭证;`t_user.openid` 建唯一索引。