consumer模块完成95%,在和商家端对接聊天购物闭环
This commit is contained in:
155
pages/mall/consumer/doc/CHAT_SHOPPING_SUPABASE_ARCH.md
Normal file
155
pages/mall/consumer/doc/CHAT_SHOPPING_SUPABASE_ARCH.md
Normal file
@@ -0,0 +1,155 @@
|
||||
# 基于 Supabase 实现消费者-商家聊天购物闭环方案
|
||||
|
||||
> **结论:** 是的,仅依赖 Supabase (配合前端逻辑) 完全可以实现“聊天购物闭环”的核心业务流程。 Supabase 提供的 Authentication(身份验证)、Database(数据库)、Realtime(实时订阅)、Storage(存储)以及 Edge Functions(边缘函数)覆盖了即时通讯和订单状态流转所需的所有基础设施。
|
||||
>
|
||||
> *注:实际资金的支付(扣款)通常需要对接微信支付/支付宝/Stripe等第三方支付网关,但 Supabase 可以完美托管支付前后的数据流、状态流和 Webhook 处理。*
|
||||
|
||||
---
|
||||
|
||||
## 1. 核心架构概览
|
||||
|
||||
在不引入额外后端服务(如 Node.js/Java 服务端)的情况下,架构如下:
|
||||
|
||||
* **客户端 (Uni-app / Vue)**: 消费者端消费者 App,商家端管理后台。直接通过 `supabase-js` SDK 与 Supabase 交互。
|
||||
* **身份验证 (Auth)**: 区分消费者(Consumer)和商家(Merchant/Admin)。利用 RLS (Row Level Security) 确保数据隔离。
|
||||
* **实时通讯 (Realtime)**: 监听 `messages` 和 `orders` 表的变动,实现毫秒级消息推送和订单状态更新。
|
||||
* **业务逻辑 (Database + Edge Functions)**: 使用 Postgres 函数处理复杂的原子操作(如创建订单),使用 Edge Functions 处理支付回调。
|
||||
|
||||
---
|
||||
|
||||
## 2. 数据库设计 (Schema)
|
||||
|
||||
为了支持“边聊边买”,我们需要设计能关联聊天与订单的数据结构。
|
||||
|
||||
### 2.1 核心表结构
|
||||
|
||||
**1. 聊天室表 (`chat_rooms`)**
|
||||
| 字段 | 类型 | 说明 |
|
||||
| :--- | :--- | :--- |
|
||||
| `id` | uuid | 主键 |
|
||||
| `consumer_id` | uuid | 关联 `auth.users` (消费者) |
|
||||
| `merchant_id` | uuid | 关联 `auth.users` (商家) |
|
||||
| `last_message` | jsonb | 最后一条消息快照(用于列表展示) |
|
||||
| `updated_at` | timestamp | 排序用 |
|
||||
|
||||
**2. 消息表 (`messages`)**
|
||||
| 字段 | 类型 | 说明 |
|
||||
| :--- | :--- | :--- |
|
||||
| `id` | uuid | 主键 |
|
||||
| `room_id` | uuid | 外键关联 `chat_rooms` |
|
||||
| `sender_id` | uuid | 发送者 ID |
|
||||
| `type` | text | 消息类型: `text`, `image`, `product`, `order`, `system` |
|
||||
| `payload` | jsonb | 消息内容。如果是 `product`,存商品快照;如果是 `order`,存订单摘要 |
|
||||
| `is_read` | boolean | 已读状态 |
|
||||
| `created_at` | timestamp | 发送时间 |
|
||||
|
||||
**3. 订单表 (`orders`)**
|
||||
| 字段 | 类型 | 说明 |
|
||||
| :--- | :--- | :--- |
|
||||
| `id` | uuid | 主键 |
|
||||
| `room_id` | uuid | **关键关联**:该订单属于哪个聊天上下文 |
|
||||
| `consumer_id` | uuid | 买家 |
|
||||
| `merchant_id` | uuid | 卖家 |
|
||||
| `items` | jsonb | 商品列表 |
|
||||
| `total_amount` | numeric | 总金额 |
|
||||
| `status` | text | `pending`, `paid`, `shipped`, `completed`, `cancelled` |
|
||||
| `payment_status`| text | `unpaid`, `success` |
|
||||
|
||||
---
|
||||
|
||||
## 3. “聊天购物”闭环流程详解
|
||||
|
||||
### 场景一:商品咨询与卡片发送
|
||||
1. **场景**: 消费者在商品详情页点击“联系商家”。
|
||||
2. **动作**:
|
||||
* 前端检查 `chat_rooms` 是否存在该(消费者, 商家)的记录,没有则插入(`upsert`)。
|
||||
* 跳转至聊天页。
|
||||
* **特色功能**: 自动发送一条 `type: product` 的消息,包含当前浏览的商品卡片 (`payload: { id, title, price, image }`)。
|
||||
3. **实现 (Supabase)**:
|
||||
* 直接写入 `messages` 表。
|
||||
* 商家端通过 `supabase.channel('messages').on(...)` 实时收到商品卡片,知道用户对什么感兴趣。
|
||||
|
||||
### 场景二:商家发起收款(创建订单)
|
||||
1. **场景**: 双方沟通确认购买意向后,商家点击“发起订单”或“直接改价”。
|
||||
2. **动作**:
|
||||
* 商家选择商品,填写金额,生成预订单。
|
||||
* 向 `orders` 表插入一条状态为 `pending` 的记录。
|
||||
* 向 `messages` 表插入一条 `type: order` 的消息,`payload` 包含 `order_id` 和摘要。
|
||||
3. **表现**: 消费者在聊天流中看到一个“待支付订单卡片”。
|
||||
|
||||
### 场景三:聊天中支付
|
||||
1. **场景**: 消费者点击聊天气泡中的“立即支付”按钮。
|
||||
2. **动作**:
|
||||
* APP 唤起支付(微信/支付宝)。
|
||||
* 支付成功后,支付平台回调 Supabase Edge Function (或通过前端验证)。
|
||||
* 更新 `orders` 表 `status` 为 `paid`。
|
||||
3. **闭环**:
|
||||
* Supabase 监听到 `orders` 表 `status` 变为 `paid`。
|
||||
* **触发器 (Trigger)** 或客户端逻辑自动插入一条 `type: system` 的消息:“订单已支付,等待发货”。
|
||||
* 商家端聊天界面实时更新订单状态为“已支付”。
|
||||
|
||||
---
|
||||
|
||||
## 4. 关键技术实现点
|
||||
|
||||
### 4.1 RLS (行级安全策略)
|
||||
必须配置严格的 RLS,防止用户偷看他人聊天。
|
||||
|
||||
```sql
|
||||
-- 示例:只能查看属于自己的聊天室
|
||||
create policy "Users can view their own rooms"
|
||||
on chat_rooms for select
|
||||
using (auth.uid() = consumer_id or auth.uid() = merchant_id);
|
||||
```
|
||||
|
||||
### 4.2 实时订阅 (Realtime)
|
||||
|
||||
前端代码示例 (Prolog/Vue):
|
||||
|
||||
```typescript
|
||||
// 订阅消息
|
||||
const messageChannel = supabase
|
||||
.channel('chat-room-123')
|
||||
.on(
|
||||
'postgres_changes',
|
||||
{ event: 'INSERT', schema: 'public', table: 'messages', filter: `room_id=eq.${roomId}` },
|
||||
(payload) => {
|
||||
messages.value.push(payload.new)
|
||||
scrollToBottom()
|
||||
}
|
||||
)
|
||||
.subscribe()
|
||||
|
||||
// 订阅订单状态变更 (实现卡片状态自动刷新)
|
||||
const orderChannel = supabase
|
||||
.channel('order-updates')
|
||||
.on(
|
||||
'postgres_changes',
|
||||
{ event: 'UPDATE', schema: 'public', table: 'orders', filter: `room_id=eq.${roomId}` },
|
||||
(payload) => {
|
||||
updateOrderCardStatus(payload.new.id, payload.new.status)
|
||||
}
|
||||
)
|
||||
.subscribe()
|
||||
```
|
||||
|
||||
### 4.3 边缘函数 (Edge Functions) 处理 Webhook
|
||||
由于前端不能直接处理支付回调(不安全),需要使用 Supabase Edge Functions。
|
||||
|
||||
* `functions/payment-webhook/index.ts`: 接收微信支付回调,验证签名,然后使用 Service Role Key 更新 `orders` 表。
|
||||
|
||||
---
|
||||
|
||||
## 5. 总结
|
||||
|
||||
完全依赖 Supabase 实现聊天购物闭环是**可行且高效**的方案。
|
||||
|
||||
* **开发快**: 免去后端 CRUD 接口开发,直接操作 DB。
|
||||
* **实时性**: Realtime 功能天然契合聊天场景。
|
||||
* **成本低**: 无需维护长连接服务器 (WebSocket)。
|
||||
* **闭环体验**: 订单与消息在同一数据流中,用户体验流畅。
|
||||
|
||||
**下一步建议:**
|
||||
1. 在 Supabase 中创建 `chat_rooms`, `messages`, `orders` 表。
|
||||
2. 配置 RLS。
|
||||
3. 开发消息列表 UI,支持多类型消息渲染(特别是商品卡片和订单卡片)。
|
||||
192
pages/mall/consumer/doc/CONSUMER_DB_DOC.md
Normal file
192
pages/mall/consumer/doc/CONSUMER_DB_DOC.md
Normal file
@@ -0,0 +1,192 @@
|
||||
# 消费者端前端数据库文档 (Consumer App DB Schema)
|
||||
|
||||
本文档基于现有消费者前端 (`mall/pages/mall/consumer`) 和 Supabase 服务层 (`mall/utils/supabaseService.uts`) 的调用逻辑生成。旨在协助商家端前端开发进行数据库对接。
|
||||
|
||||
## 1. 核心业务表 (Core Business Tables)
|
||||
|
||||
### 1.1 商品分类表 (`ml_categories`)
|
||||
用于展示商品的一级/二级分类。
|
||||
|
||||
| 字段名 | 类型 | 描述 | 备注 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `id` | UUID | 主键 | |
|
||||
| `name` | Text | 分类名称 | |
|
||||
| `icon_url` | Text | 图标 URL | 前端可能回退到 Emoji |
|
||||
| `description` | Text | 描述 | |
|
||||
| `parent_id` | UUID | 父分类 ID | 用于树形结构 |
|
||||
| `sort_order` | Integer | 排序权重 | |
|
||||
| `is_active` | Boolean | 是否启用 | |
|
||||
|
||||
### 1.2 品牌表 (`ml_brands`)
|
||||
商品所属品牌信息。
|
||||
|
||||
| 字段名 | 类型 | 描述 | 备注 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `id` | UUID | 主键 | |
|
||||
| `name` | Text | 品牌名称 | |
|
||||
| `logo_url` | Text | 品牌 Logo URL | |
|
||||
| `description` | Text | 品牌描述 | |
|
||||
| `country` | Text | 所属国家 | 可选 |
|
||||
| `is_active` | Boolean | 是否启用 | |
|
||||
|
||||
### 1.3 商家/店铺表 (`ml_shops`)
|
||||
商家端主要管理的店铺信息实体。
|
||||
|
||||
| 字段名 | 类型 | 描述 | 备注 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `id` | UUID | 主键 | |
|
||||
| `merchant_id` | UUID | 关联的商户账号 ID | 对应 auth.users 或 merchants 表 |
|
||||
| `shop_name` | Text | 店铺名称 | |
|
||||
| `shop_logo` | Text | 店铺 Logo | |
|
||||
| `shop_banner` | Text | 店铺背景图 | |
|
||||
| `description` | Text | 店铺简介 | |
|
||||
| `contact_name` | Text | 联系人 | |
|
||||
| `contact_phone` | Text | 联系电话 | |
|
||||
| `rating_avg` | Numeric | 平均评分 | |
|
||||
| `total_sales` | Integer | 总销量 | |
|
||||
| `status` | Integer | 状态 | 1: 正常, 0: 停用 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 商品系统 (Product System)
|
||||
|
||||
### 2.1 商品主表 (`ml_products`)
|
||||
商家发布的核心商品数据。
|
||||
|
||||
| 字段名 | 类型 | 描述 | 备注 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `id` | UUID | 主键 | |
|
||||
| `merchant_id` | UUID | 所属商家 ID | |
|
||||
| `category_id` | UUID | 所属分类 ID | |
|
||||
| `brand_id` | UUID | 所属品牌 ID | |
|
||||
| `name` | Text | 商品名称 | |
|
||||
| `subtitle` | Text | 副标题 | 简短描述 |
|
||||
| `description` | Text | 商品详情 | HTML 或 Markdown |
|
||||
| `main_image_url` | Text | 主图 URL | |
|
||||
| `image_urls` | JSON/Array | 轮播图列表 | `['url1', 'url2']` |
|
||||
| `video_urls` | JSON/Array | 视频列表 | |
|
||||
| `base_price` | Numeric | 基础售价 | 列表页展示价格 |
|
||||
| `market_price` | Numeric | 市场价/划线价 | |
|
||||
| `cost_price` | Numeric | 成本价 | 敏感字段,仅商家可见 |
|
||||
| `total_stock` | Integer | 总库存 | |
|
||||
| `status` | Integer | 状态 | 1: 上架, 0: 下架, 2: 审核中 |
|
||||
| `is_hot` | Boolean | 是否热销 | |
|
||||
| `is_new` | Boolean | 是否新品 | |
|
||||
| `is_featured` | Boolean | 是否推荐 | |
|
||||
| `attributes` | JSONB | 商品属性 | `{ "材质": "纯棉", "季节": "夏季" }` |
|
||||
| `tags` | Text[] | 标签 | |
|
||||
| `sale_count` | Integer | 销量 | 统计字段 |
|
||||
|
||||
### 2.2 商品 SKU 表 (`ml_product_skus`)
|
||||
商品的多规格定义(如颜色、尺寸)。
|
||||
|
||||
| 字段名 | 类型 | 描述 | 备注 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `id` | UUID | 主键 | |
|
||||
| `product_id` | UUID | 关联商品 ID | |
|
||||
| `sku_code` | Text | SKU 编码 | 商家自定义编码 |
|
||||
| `specifications` | JSONB | 规格键值对 | `{ "颜色": "红", "尺寸": "L" }` |
|
||||
| `price` | Numeric | SKU 售价 | 特殊规格价格 |
|
||||
| `market_price` | Numeric | SKU 市场价 | |
|
||||
| `stock` | Integer | 当前库存 | |
|
||||
| `image_url` | Text | 规格对应图片 | 如红色款对应红色的图 |
|
||||
| `status` | Integer | 状态 | 1: 启用, 0: 禁用 |
|
||||
|
||||
### 2.3 商品详情视图 (`ml_products_detail_view`)
|
||||
**重要**: 消费者端主要通过此视图查询商品,商家在维护数据时应确保这些关联字段能正确生成。
|
||||
* 该视图通常 `JOIN` 了 `ml_shops` (获取 `shop_name`), `ml_brands` (获取 `brand_name`), `ml_categories` (获取 `category_name`)。
|
||||
* **商家端操作**: 不需要直接操作视图,只需维护上述基础表。
|
||||
|
||||
---
|
||||
|
||||
## 3. 交易系统 (Transaction System)
|
||||
|
||||
### 3.1 购物车 (`ml_shopping_cart`)
|
||||
|
||||
| 字段名 | 类型 | 描述 | 备注 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `id` | UUID | 主键 | |
|
||||
| `user_id` | UUID | 用户 ID | |
|
||||
| `product_id` | UUID | 商品 ID | |
|
||||
| `sku_id` | UUID | SKU ID | 可空(若商品无多规格) |
|
||||
| `quantity` | Integer |数量 | |
|
||||
| `selected` | Boolean | 是否勾选 | 购物车状态 |
|
||||
| `created_at` | Timestamp | 创建时间 | |
|
||||
|
||||
### 3.2 订单主表 (`ml_orders`) (推测结构)
|
||||
商家端处理订单的核心表。
|
||||
|
||||
| 字段名 | 类型 | 描述 | 备注 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `id` | UUID | 主键 | |
|
||||
| `user_id` | UUID | 用户 ID | |
|
||||
| `merchant_id` | UUID | 商家 ID | |
|
||||
| `order_no` | Text | 订单号 | 唯一业务单号 |
|
||||
| `total_amount` | Numeric | 订单总金额 | |
|
||||
| `pay_amount` | Numeric | 实付金额 | |
|
||||
| `status` | Integer | 订单状态 | 0: 待付款, 1: 待发货, 2: 待收货, 3: 已完成, -1: 已取消 |
|
||||
| `address_snapshot` | JSONB | 收货地址快照 | 下单时的地址信息 |
|
||||
| `remark` | Text | 订单备注 | |
|
||||
| `created_at` | Timestamp | 下单时间 | |
|
||||
|
||||
### 3.3 订单项表 (`ml_order_items`) (推测结构)
|
||||
|
||||
| 字段名 | 类型 | 描述 | 备注 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `id` | UUID | 主键 | |
|
||||
| `order_id` | UUID | 订单 ID | |
|
||||
| `product_id` | UUID | 商品 ID | |
|
||||
| `sku_id` | UUID | SKU ID | |
|
||||
| `product_name` | Text | 商品名称快照 | |
|
||||
| `price` | Numeric | 成交单价 | |
|
||||
| `quantity` | Integer | 购买数量 | |
|
||||
| `sku_snapshot` | JSONB | 规格快照 | |
|
||||
|
||||
---
|
||||
|
||||
## 4. 用户相关 (User Relations)
|
||||
|
||||
### 4.1 用户地址 (`ml_user_addresses`)
|
||||
|
||||
| 字段名 | 类型 | 描述 | 备注 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `id` | UUID | 主键 | |
|
||||
| `user_id` | UUID | 用户 ID | |
|
||||
| `recipient_name` | Text | 收货人姓名 | |
|
||||
| `phone` | Text | 手机号 | |
|
||||
| `province` | Text | 省 | |
|
||||
| `city` | Text | 市 | |
|
||||
| `district` | Text | 区 | |
|
||||
| `detail_address` | Text | 详细地址 | |
|
||||
| `is_default` | Boolean | 是否默认地址 | |
|
||||
|
||||
### 4.2 聊天消息 (`ml_chat_messages`)
|
||||
用于客服系统。
|
||||
|
||||
| 字段名 | 类型 | 描述 | 备注 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `id` | UUID | 主键 | |
|
||||
| `session_id` | UUID | 会话 ID | 可选,或通过收发人聚合 |
|
||||
| `sender_id` | UUID | 发送者 ID | |
|
||||
| `receiver_id` | UUID | 接收者 ID | |
|
||||
| `content` | Text | 消息内容 | |
|
||||
| `msg_type` | Text | 消息类型 | 'text', 'image', 'product' |
|
||||
| `is_read` | Boolean | 是否已读 | |
|
||||
| `created_at` | Timestamp | 发送时间 | |
|
||||
|
||||
## 5. 对接建议 (Integration Tips for Merchant Frontend)
|
||||
|
||||
1. **商品管理**:
|
||||
* 在创建商品时,必须先选择 `category_id` 和 `merchant_id`。
|
||||
* 如果有 `specifications` (多规格),请同时向 `ml_product_skus` 插入数据。
|
||||
* 更新库存时,请优先更新 `ml_product_skus` 中的 `stock`,并同步总库存到 `ml_products`.`total_stock`。
|
||||
|
||||
2. **图片处理**:
|
||||
* 消费者端支持 `main_image_url` (字符串) 和 `image_urls` (JSON 数组) 两种格式,请确保都正确填充。
|
||||
|
||||
3. **状态管理**:
|
||||
* 上架商品请将 `status` 设为 `1`。
|
||||
* 如需在首页 "推荐/热销" 板块显示,请设置 `is_featured` 或 `is_hot` 为 `true`。
|
||||
|
||||
4. **Supabase 安全策略 (RLS)**:
|
||||
* 请确保商家端账号有权限写入 `ml_products` 和 `ml_shops` 表,但只能修改 `merchant_id` 等于自己账号的数据。
|
||||
Reference in New Issue
Block a user