25 KiB
25 KiB
数据库 Skills
数据库信息
- 数据库名:
rent_platform - 字符集:
utf8mb4 - 排序规则:
utf8mb4_unicode_ci - 时区:
+08:00
表结构总览
| 表名 | 说明 | 核心字段 |
|---|---|---|
| admins | 平台管理员表 | id, username, name, role, status |
| users | 用户表 | id, phone, nickname, status |
| user_oauth | 第三方账号绑定 | user_id, provider, openid |
| sellers | 商家账户表 | id, phone, password, contact_name, status |
| merchants | 商家表 | seller_id, shop_name, status, rating |
| rooms | 房源表 | merchant_id, name, type, price, status, audit_status |
| room_calendar | 房量房价日历 | room_id, date, price, stock, status |
| room_calendar_logs | 房态变更日志 | room_id, operator_id, change_type |
| orders | 订单表 | order_no, user_id, merchant_id, room_id, pay_amount, service_fee, merchant_income, status |
| reviews | 评价表 | order_id, user_id, rating, content |
| favorites | 收藏表 | user_id, room_id |
| coupons | 优惠券模板 | name, type, value, scope |
| user_coupons | 用户优惠券 | user_id, coupon_id, status |
| promotions | 促销活动 | merchant_id, name, type, rules |
| member_levels | 会员等级 | level, name, min_points, discount |
| user_members | 用户会员信息 | user_id, level_id, points, growth_value |
| settlements | 结算对账单 | merchant_id, settlement_no, period_start, period_end, status |
| settlement_items | 对账单明细 | settlement_id, order_id, order_no, order_amount |
| withdrawals | 提现记录 | merchant_id, settlement_ids, amount, status |
| notifications | 消息通知 | user_id, type, title, content |
| advertisements | 广告位 | position, image, link_type |
| platform_configs | 平台配置 | config_key, config_value |
| operation_logs | 操作日志 | user_id, module, action, detail |
| mkt_activities | 营销活动总表 | name, type, enabled, config |
| mkt_invitations | 邀请关系 | activity_id, inviter_id, invitee_id, invite_code |
| mkt_cashbacks | 返现记录 | activity_id, inviter_id, order_id, amount, status |
| mkt_user_invite_stats | 用户邀请统计 | activity_id, user_id, invite_code, available_balance |
| mkt_invite_withdrawals | 邀请提现申请 | activity_id, user_id, amount, status |
核心关系
users (1) ──── (n) orders
│
└── (n) ──── (n) coupons (user_coupons)
│
└── (n) ──── (n) rooms (favorites)
sellers (1) ──── (1) merchants ──── (n) rooms ──── (n) room_calendar
│
└── (n) orders
orders (1) ──── (1) reviews
orders (1) ──── (1) settlements
状态枚举
管理员状态 (admins.status)
active- 正常frozen- 冻结
管理员角色 (admins.role)
super_admin- 超级管理员admin- 管理员operator- 运营人员
用户状态 (users.status)
active- 正常frozen- 冻结deleted- 已注销
商家账户状态 (sellers.status)
active- 正常frozen- 冻结deleted- 已注销
商家状态 (merchants.status)
pending- 待审核approved- 已通过rejected- 已拒绝frozen- 已冻结
订单状态 (orders.status)
pending_pay- 待支付pending_confirm- 待确认pending_checkin- 待入住checked_in- 已入住completed- 已完成cancelled- 已取消refunding- 退款中refunded- 已退款
订单状态流转
待支付 ──支付成功──> 待确认 ──商家确认──> 待入住 ──入住──> 已入住 ──离店──> 已完成
│ │ │
└──超时/取消──> 已取消 └──商家拒绝──> 已取消 └──用户退款──> 退款中
│
├──商家通过──> 已退款(恢复房量)
└──商家拒绝──> 已取消
待确认 ──用户退款──> 退款中 ──商家通过──> 已退款(恢复房量)
订单取消/退款规则
| 操作 | 适用状态 | 说明 |
|---|---|---|
| 用户取消 | pending_pay | 直接取消,无退款 |
| 用户取消 | pending_confirm | 取消并退款,恢复房量 |
| 用户退款申请 | pending_confirm, pending_checkin | 状态变为 refunding,等待商家审核 |
| 商家通过退款 | refunding | 状态变为 refunded,恢复房量日历库存 |
| 商家拒绝退款 | refunding | 状态变为 cancelled |
房源状态 (rooms.status)
on_sale- 在售off_sale- 已下架
房源审核状态 (rooms.audit_status)
pending- 待审核approved- 已通过rejected- 已拒绝
房源类型 (rooms.type)
hotel- 酒店homestay- 民宿apartment- 公寓hostel- 青旅
优惠券类型 (coupons.type)
fixed- 固定金额percent- 百分比折扣
关键索引
-- 高频查询索引
idx_users_phone (phone)
idx_sellers_phone (phone)
idx_merchants_status (status)
idx_merchants_city (city)
idx_rooms_merchant_id (merchant_id)
idx_rooms_status_price (status, price)
idx_rooms_audit_status (audit_status)
idx_orders_user_id (user_id)
idx_orders_merchant_id (merchant_id)
idx_orders_status (status)
idx_orders_check_in (check_in_date)
idx_room_calendar_room_date (room_id, date)
查询示例
获取在售房源(含商家信息)
SELECT r.*, m.shop_name, m.city, m.rating as merchant_rating
FROM rooms r
JOIN merchants m ON r.merchant_id = m.id
WHERE r.status = 'on_sale' AND m.status = 'approved'
ORDER BY r.rating DESC
LIMIT 10;
获取房源日历
SELECT * FROM room_calendar
WHERE room_id = ? AND date BETWEEN ? AND ?
ORDER BY date;
批量更新房量房价
INSERT INTO room_calendar (room_id, date, price, stock, status)
VALUES (?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE price = VALUES(price), stock = VALUES(stock), status = VALUES(status);
获取用户订单
SELECT o.*, r.name as room_name, m.shop_name
FROM orders o
JOIN rooms r ON o.room_id = r.id
JOIN merchants m ON o.merchant_id = m.id
WHERE o.user_id = ?
ORDER BY o.created_at DESC;
更新房量(预订成功)
UPDATE room_calendar
SET sold = sold + 1, stock = stock - 1
WHERE room_id = ? AND date = ? AND stock > 0;
数据迁移
# 初始化数据库
mysql -u root -p < database/migrations/001_init_schema.sql
# 导入种子数据
mysql -u root -p rent_platform < database/seeds/001_init_data.sql
注意事项
- 用户手机号、身份证号需加密存储(AES-256)
- 密码使用 bcrypt 哈希存储
- 金额字段使用 DECIMAL(10,2) 避免精度丢失
- JSON 字段用于存储数组/对象(如设施列表、活动规则)
- 所有表都有 created_at 字段,核心表有 updated_at
- 敏感操作需记录到 operation_logs 表
平台配置表 (platform_configs)
| 配置键 | 默认值 | 说明 |
|---|---|---|
| commission_rate | 0.10 | 默认平台佣金比例 |
| service_fee_rate | 0.05 | 软件服务费比例(可配置) |
| min_deposit | 5000 | 最低保证金金额 |
| auto_cancel_minutes | 30 | 未支付订单自动取消时间 |
| auto_complete_hours | 24 | 入住后自动完成订单时间 |
| sms_enabled | true | 是否启用短信通知 |
| max_images_per_room | 20 | 每个房源最大图片数 |
| max_images_per_review | 9 | 每条评价最大图片数 |
服务费计算:
- 软件服务费 = 实付金额 × service_fee_rate
- 商家预计收入 = 实付金额 - 软件服务费
- 配置可通过平台管理后台「系统设置」页面调整
商家入驻流程
流程概述
用户点击商家入驻 → 商家注册/登录页面 → 注册商家账户 → 创建店铺 → 提交审核 → 审核通过 → 开始营业
账户体系说明
| 账户类型 | 表名 | Token存储 | 路由前缀 |
|---|---|---|---|
| C端用户 | users | token / userInfo |
/rooms, /orders, /user |
| 商家账户 | sellers | sellerToken / sellerInfo |
/merchant/* |
| 平台管理员 | admins | 管理后台独立存储 | /admin/* |
注意: 用户和商家是独立的账户体系,一个用户可以同时是商家。
商家注册接口
| 接口 | 路径 | 说明 |
|---|---|---|
| 发送验证码 | POST /api/seller-auth/send-code | 发送商家验证码(6位数字) |
| 商家注册 | POST /api/seller-auth/register | 手机号+验证码注册 |
| 商家登录 | POST /api/seller-auth/login | 手机号+验证码或密码登录 |
| 刷新令牌 | POST /api/seller-auth/refresh | 使用refreshToken刷新 |
| 获取商家信息 | GET /api/seller-auth/profile | 需Bearer Token |
商家注册参数
interface SellerRegisterParams {
phone: string; // 手机号(必填,正则:/^1[3-9]\d{9}$/)
code: string; // 验证码(必填,6位数字)
contactName: string; // 联系人姓名(必填,2-50字)
email?: string; // 邮箱(选填,需验证格式)
password?: string; // 密码(选填,6-20位,便于密码登录)
}
商家登录参数
interface SellerLoginParams {
phone: string; // 手机号(必填)
code?: string; // 验证码(可选,6位数字)
password?: string; // 密码(可选,6-20位)
}
// 注:验证码和密码至少填写一种
商家注册响应
interface SellerLoginResult {
accessToken: string;
refreshToken: string;
sellerInfo: {
id: number;
phone: string;
contactName: string;
email?: string;
status: "active" | "frozen" | "deleted";
merchantId?: number; // 有值表示已创建店铺
merchantStatus?: string; // 店铺状态
};
}
商家入驻状态判断
| sellerInfo.merchantId | sellerInfo.merchantStatus | 状态说明 |
|---|---|---|
| 无/undefined | - | 未创建店铺,需引导创建 |
| 有值 | pending | 店铺审核中 |
| 有值 | approved | 已通过审核,可营业 |
| 有值 | rejected | 已拒绝,显示原因 |
| 有值 | frozen | 店铺已冻结 |
小程序页面路由
| 页面 | 路径 | 说明 |
|---|---|---|
| 个人中心 | /pages/mine/index | 入口:商家中心、商家入驻按钮 |
| 商家注册/登录 | /pages/seller-register/index | 商家账号注册登录 |
| 商家中心 | /pages/seller/home | 商家管理入口 |
| 商家订单列表 | /pages/seller/orders | 商家订单管理 |
| 商家订单详情 | /pages/seller/order-detail | 商家订单详情 |
| 创建店铺 | /pages/shop-create/index | 填写店铺信息提交审核 |
| 修改店铺 | /pages/shop-edit/index | 修改店铺信息重新审核 |
Store设计
// useSellerStore (apps/miniapp/src/store/seller.ts)
const sellerToken = ref(uni.getStorageSync("sellerToken") || "");
const sellerInfo = ref<SellerInfo | null>(
uni.getStorageSync("sellerInfo") || null,
);
// 判断方法
isSellerLoggedIn(); // 是否登录商家账号
hasMerchant(); // 是否已创建店铺
店铺创建功能
创建店铺接口
| 接口 | 路径 | 说明 |
|---|---|---|
| 申请创建店铺 | POST /api/merchant/apply | 需商家Token,创建后状态为pending |
| 获取我的店铺 | GET /api/merchant/mine | 需商家Token |
| 更新店铺信息 | PUT /api/merchant/update | 需商家Token,审核通过/拒绝后修改会重置为pending |
创建店铺参数 (ApplyMerchantDto)
| 字段 | 类型 | 必填 | 校验规则 |
|---|---|---|---|
| shopName | string | 是 | 2-100字 |
| phone | string | 是 | 联系电话不能为空 |
| province | string | 否 | 省 |
| city | string | 否 | 市 |
| district | string | 否 | 区 |
| address | string | 否 | 详细地址 |
| businessLicense | string | 是 | 营业执照图片URL |
| licenseNo | string | 否 | 营业执照编号 |
| legalPerson | string | 否 | 法人姓名 |
| description | string | 否 | 店铺描述 |
创建店铺流程
商家中心 → 点击"创建店铺" → 填写表单 → 提交申请
→ 调用 POST /merchant/apply
→ 更新 sellerInfo.merchantId 和 merchantStatus
→ 跳转商家中心显示审核中状态
前端 API 模块
文件: apps/miniapp/src/api/merchant.ts
applyMerchant(data); // 申请创建店铺
getMyMerchant(); // 获取我的店铺信息
updateMerchant(data); // 更新店铺信息
getMerchantById(id); // 获取商家详情(公开)
店铺审核状态展示
状态枚举与显示
| status | 显示文本 | 颜色 | 说明 |
|---|---|---|---|
| pending | 审核中 | 橙色 | 等待平台审核,不可修改 |
| approved | 营业中 | 绿色 | 审核通过,可正常营业 |
| rejected | 已拒绝 | 红色 | 审核拒绝,显示原因,可修改重新提交 |
| frozen | 已冻结 | 灰色 | 店铺被冻结,联系客服 |
商家中心页面状态展示逻辑
审核中 (pending):
- 显示状态标签"审核中"
- 显示提示"店铺信息审核中,暂不可修改"
- 不显示修改按钮
- 不显示数据概览和功能菜单
审核通过 (approved):
- 显示状态标签"营业中"
- 显示店铺信息卡片(电话、地址等)
- 显示数据概览(订单、房源、收入、评分)
- 显示"修改店铺信息"按钮
- 显示功能菜单(订单管理、房源管理)
审核拒绝 (rejected):
- 显示状态标签"已拒绝"
- 显示拒绝原因区块(红色背景,包含拒绝原因)
- 显示店铺信息卡片
- 显示"修改店铺信息"按钮
- 不显示数据概览和功能菜单
店铺冻结 (frozen):
- 显示状态标签"已冻结"
- 显示提示"店铺已被冻结,请联系平台客服"
- 不显示修改按钮
- 不显示数据概览和功能菜单
修改店铺重新审核逻辑
后端逻辑 (merchant.service.ts):
async update(id, dto) {
const merchant = await this.findById(id);
// 审核通过或拒绝后修改,重置为pending
if (merchant.status === 'approved' || merchant.status === 'rejected') {
await this.merchantRepo.update(id, { ...dto, status: 'pending', rejectReason: null });
} else {
await this.merchantRepo.update(id, dto);
}
return this.findById(id);
}
修改流程:
点击"修改店铺信息" → 填写表单 → 提交修改
→ 调用 PUT /merchant/update
→ 后端自动将 status 重置为 pending,清空 rejectReason
→ 跳转商家中心显示"审核中"状态
后续迭代事项
- 商家管理后台集成: 商家后台跳转入口
- 商家实名认证: 身份证上传、银行卡绑定
- 图片上传接口: 营业执照真实上传功能
三端分离开发规范
三端定义
| 端 | 说明 | 前端项目 | API路由前缀 |
|---|---|---|---|
| 用户端 | C端普通用户 | 小程序用户页面 (pages/*) |
/xxx (无前缀) |
| 商家端 | B端商家 | 小程序商家页面 (pages/seller/*) + 商家管理后台 (merchant-admin) |
/seller/xxx |
| 平台端 | 平台管理员 | 平台管理后台 (platform-admin) |
/admin/xxx |
后端 Controller 文件命名规范
每个模块的控制器按端拆分为独立文件,命名格式:{module}-{端}.controller.ts
modules/merchant/
├── merchant-public.controller.ts # 用户端 @Controller('merchants')
├── merchant-seller.controller.ts # 商家端 @Controller('seller/merchant')
├── merchant-admin.controller.ts # 管理端 @Controller('admin/merchants')
├── merchant.service.ts # 共享 Service
├── merchant.module.ts # 模块定义
└── dto/
命名对照:
*-public.controller.ts→ 用户端(公开接口,无Guard或JwtAuthGuard)*-seller.controller.ts→ 商家端(SellerJwtAuthGuard)*-user.controller.ts→ 用户端(需登录,JwtAuthGuard)*-admin.controller.ts→ 管理端(JwtAuthGuard + RolesGuard + @Roles('admin'))
小程序 API 文件目录规范
apps/miniapp/src/api/
├── user/ # 用户端 API
│ ├── auth.ts # /auth/*, /user/profile
│ ├── merchant.ts # /merchants/* (公开)
│ ├── room.ts # /rooms/* (公开)
│ ├── order.ts # /orders/*
│ ├── review.ts # /reviews/*
│ └── invite.ts # /user/activity/invite/*
└── seller/ # 商家端 API
├── auth.ts # /seller/auth/*
├── merchant.ts # /seller/merchant/*
├── room.ts # /seller/rooms/*
├── room-calendar.ts # /seller/room-calendar/*
└── order.ts # /seller/orders/*
Guard 使用对照
| 端 | Guard | Token | 装饰器 |
|---|---|---|---|
| 用户端(公开) | 无 | 无 | 无 |
| 用户端(需登录) | JwtAuthGuard | Bearer Token | @CurrentUser('sub') |
| 商家端 | SellerJwtAuthGuard | Bearer sellerToken | @CurrentSeller('sub') |
| 管理端 | JwtAuthGuard + RolesGuard | Bearer adminToken | @CurrentUser('sub') + @Roles('admin') |
新增模块开发清单
新增业务模块时,按以下步骤操作:
- 创建
modules/{module}/目录 - 创建
dto/{module}.dto.ts - 创建
{module}.service.ts - 按需创建控制器文件:
{module}-public.controller.ts、{module}-seller.controller.ts、{module}-admin.controller.ts - 创建
{module}.module.ts,引用所有控制器和共享 Service - 在
app.module.ts中注册新模块 - 小程序端按端创建 API 文件:
api/user/{module}.ts或api/seller/{module}.ts - 商家管理后台/平台管理后台按需添加 API 文件
商家订单管理
商家订单接口
| 接口 | 路径 | 说明 |
|---|---|---|
| 订单列表 | GET /api/seller/orders | 支持状态筛选、订单号搜索 |
| 订单详情 | GET /api/seller/orders/:id | 获取订单详情 |
| 确认订单 | PUT /api/seller/orders/:id/confirm | pending_confirm → pending_checkin |
| 拒绝订单 | PUT /api/seller/orders/:id/reject | pending_confirm → cancelled |
| 办理入住 | PUT /api/seller/orders/:id/checkin | pending_checkin → checked_in |
| 通过退款 | PUT /api/seller/orders/:id/approve-refund | refunding → refunded,恢复房量 |
| 拒绝退款 | PUT /api/seller/orders/:id/reject-refund | refunding → cancelled |
商家订单状态Tab
| Tab名称 | 对应状态 |
|---|---|
| 全部 | 所有状态 |
| 待确认 | pending_confirm |
| 待入住 | pending_checkin |
| 已入住 | checked_in |
| 已完成 | completed |
| 已取消 | cancelled |
| 已退款 | refunded, refunding |
商家订单操作权限
| 状态 | 可操作 |
|---|---|
| pending_confirm | 确认、拒绝 |
| pending_checkin | 办理入住 |
| refunding | 通过退款、拒绝退款 |
| 其他状态 | 无操作 |
文件上传服务
上传接口
| 接口 | 路径 | 说明 |
|---|---|---|
| 用户上传 | POST /api/upload | 需用户Token |
| 商家上传 | POST /api/seller/upload | 需商家Token |
| 管理员上传 | POST /api/admin/upload | 需管理员Token |
存储配置
存储方式通过 platform_configs 表配置,支持:
| 配置键 | 说明 |
|---|---|
| storage_provider | 存储方式:local / tencent_cos / aliyun_oss |
| storage_local_path | 本地存储路径(默认 ./uploads) |
| storage_cos_bucket | 腾讯云COS Bucket |
| storage_cos_region | 腾讯云COS Region |
| storage_cos_secret_id | 腾讯云SecretId |
| storage_cos_secret_key | 腾讯云SecretKey |
| storage_oss_bucket | 阿里云OSS Bucket |
| storage_oss_region | 阿里云OSS Region |
| storage_oss_access_key_id | 阿里云AccessKeyId |
| storage_oss_access_key_secret | 阿里云AccessKeySecret |
存储配置接口
| 接口 | 路径 | 说明 |
|---|---|---|
| 获取存储配置 | GET /api/admin/config/storage | 需管理员Token |
| 更新存储配置 | PUT /api/admin/config/storage | 需管理员Token |
小程序上传工具
文件: apps/miniapp/src/utils/upload.ts
import { chooseAndUpload, uploadFile } from '@/utils/upload';
// 选择并上传图片
const urls = await chooseAndUpload({ count: 1, useSellerToken: true });
// 直接上传文件
const url = await uploadFile(filePath, { useSellerToken: true });
后端上传模块
文件位置: apps/server/src/modules/upload/
upload.service.ts— 核心上传逻辑,策略模式支持本地/腾讯云/阿里云upload.controller.ts— 上传接口控制器upload.module.ts— 模块定义
静态文件访问
本地上传的文件通过 /uploads/ 路径访问,例如:
- 上传返回:
{ url: "/uploads/abc123.jpg" } - 访问地址:
http://localhost:3000/uploads/abc123.jpg
OSS SDK 安装
使用腾讯云COS或阿里云OSS时,需安装对应SDK:
# 腾讯云COS
pnpm --filter @rent/server add cos-nodejs-sdk-v5
# 阿里云OSS
pnpm --filter @rent/server add ali-oss