# 🔨 doc_mall 模块技术实现拆解

## 📋 目录
1. [整体架构](#整体架构)
2. [数据库层实现](#数据库层实现)
3. [后端/API层实现](#后端api层实现)
4. [前端实现](#前端实现)
5. [数据流机制](#数据流机制)
6. [业务逻辑实现](#业务逻辑实现)
7. [安全机制](#安全机制)
8. [性能优化](#性能优化)

---

## 一、整体架构

### 1.1 技术栈架构图

```
┌─────────────────────────────────────────────────────────┐
│                     前端层 (uni-app-x)                    │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌─────────┐ │
│  │ 消费者端  │  │ 商家端   │  │ 配送端   │  │ 管理端  │ │
│  └──────────┘  └──────────┘  └──────────┘  └─────────┘ │
│         │              │              │            │     │
│         └──────────────┴──────────────┴────────────┘     │
│                          │                                │
│              ┌───────────▼───────────┐                   │
│              │  Supabase 客户端封装   │                   │
│              │   (AkSupa.uts)        │                   │
│              └───────────┬───────────┘                   │
└──────────────────────────┼──────────────────────────────┘
                            │ HTTPS REST API
┌───────────────────────────▼──────────────────────────────┐
│                  API 层 (PostgREST)                       │
│  ┌──────────────────────────────────────────────────┐   │
│  │  自动生成 REST API                               │   │
│  │  - GET /rest/v1/ml_products                      │   │
│  │  - POST /rest/v1/ml_orders                       │   │
│  │  - RPC /rest/v1/rpc/calculate_cart_total         │   │
│  └──────────────────────────────────────────────────┘   │
└───────────────────────────┬──────────────────────────────┘
                            │
┌───────────────────────────▼──────────────────────────────┐
│              认证层 (Supabase Auth)                       │
│  ┌──────────────────────────────────────────────────┐   │
│  │  JWT Token 认证                                  │   │
│  │  - 用户登录/注册                                 │   │
│  │  - Token 刷新                                    │   │
│  │  - 权限验证                                      │   │
│  └──────────────────────────────────────────────────┘   │
└───────────────────────────┬──────────────────────────────┘
                            │
┌───────────────────────────▼──────────────────────────────┐
│              权限层 (RLS - Row Level Security)            │
│  ┌──────────────────────────────────────────────────┐   │
│  │  行级安全策略                                     │   │
│  │  - 用户数据隔离                                   │   │
│  │  - 商家权限控制                                   │   │
│  │  - 公开数据访问                                   │   │
│  └──────────────────────────────────────────────────┘   │
└───────────────────────────┬──────────────────────────────┘
                            │
┌───────────────────────────▼──────────────────────────────┐
│              数据库层 (PostgreSQL)                        │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌─────────┐ │
│  │ 表结构   │  │ 触发器   │  │ 函数     │  │ 视图    │ │
│  │ 索引     │  │ RLS策略  │  │ 序列     │  │ 扩展    │ │
│  └──────────┘  └──────────┘  └──────────┘  └─────────┘ │
└─────────────────────────────────────────────────────────┘
```

### 1.2 核心设计模式

#### BaaS (Backend as a Service) 模式
- **特点**: 使用 Supabase 作为后端服务，无需自建后端服务器
- **优势**: 
  - 自动生成 REST API
  - 内置认证和权限系统
  - 实时数据同步
  - 减少后端开发工作量

#### 数据库优先 (Database-First) 模式
- **流程**: 数据库设计 → 自动生成 API → 前端调用
- **实现**: 
  1. 设计数据库表结构
  2. PostgREST 自动生成 REST API
  3. 前端通过 Supabase 客户端调用

#### 类型驱动开发 (Type-Driven Development)
- **实现**: TypeScript/UTS 类型定义
- **文件**: `types/mall-types.uts`
- **优势**: 类型安全、代码提示、减少错误

---

## 二、数据库层实现

### 2.1 表结构设计

#### 2.1.1 核心表结构

**用户扩展表** (`ml_user_profiles`)
```sql
CREATE TABLE public.ml_user_profiles (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    user_id UUID UNIQUE NOT NULL REFERENCES public.ak_users(id) ON DELETE CASCADE,
    status INTEGER DEFAULT 1,                    -- 1:正常 2:冻结 3:注销 4:待审核
    real_name VARCHAR(100),                       -- 真实姓名
    id_card VARCHAR(32),                          -- 身份证号
    credit_score INTEGER DEFAULT 100,             -- 信用分数 0-1000
    verification_status INTEGER DEFAULT 0,        -- 认证状态
    verification_data JSONB DEFAULT '{}',         -- 认证相关数据
    preferences JSONB DEFAULT '{}',               -- 用户偏好设置
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
```

**商品表** (`ml_products`)
```sql
CREATE TABLE public.ml_products (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    cid SERIAL UNIQUE NOT NULL,                  -- SEO友好的自增ID
    merchant_id UUID NOT NULL REFERENCES public.ak_users(id),
    category_id UUID NOT NULL REFERENCES public.ml_categories(id),
    brand_id UUID REFERENCES public.ml_brands(id),
    product_code VARCHAR(100) UNIQUE NOT NULL,
    name VARCHAR(500) NOT NULL,
    description TEXT,
    main_image_url TEXT,
    image_urls JSONB DEFAULT '[]',               -- 商品图片数组
    base_price DECIMAL(12,2) NOT NULL,
    total_stock INTEGER DEFAULT 0,
    available_stock INTEGER DEFAULT 0,
    status INTEGER DEFAULT 1,                    -- 1:上架 2:下架 3:草稿 4:删除
    view_count INTEGER DEFAULT 0,
    sale_count INTEGER DEFAULT 0,
    rating_avg DECIMAL(3,2) DEFAULT 0.00,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
```

**订单表** (`ml_orders`)
```sql
CREATE TABLE public.ml_orders (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    cid SERIAL UNIQUE NOT NULL,
    order_no VARCHAR(50) UNIQUE NOT NULL,
    user_id UUID NOT NULL REFERENCES public.ak_users(id),
    merchant_id UUID NOT NULL REFERENCES public.ak_users(id),
    product_amount DECIMAL(12,2) NOT NULL DEFAULT 0,
    discount_amount DECIMAL(12,2) DEFAULT 0,
    shipping_fee DECIMAL(12,2) DEFAULT 0,
    total_amount DECIMAL(12,2) NOT NULL,
    shipping_address JSONB NOT NULL,             -- 收货地址JSON
    order_status INTEGER DEFAULT 1,              -- 1:待支付 2:待发货 3:待收货 4:已完成
    payment_status INTEGER DEFAULT 1,           -- 1:未支付 2:已支付 3:部分退款 4:全额退款
    shipping_status INTEGER DEFAULT 1,          -- 1:未发货 2:已发货 3:运输中 4:已送达
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
```

### 2.2 索引设计

#### 2.2.1 性能优化索引

```sql
-- 商品表索引
CREATE INDEX idx_ml_products_merchant ON public.ml_products(merchant_id);
CREATE INDEX idx_ml_products_category ON public.ml_products(category_id);
CREATE INDEX idx_ml_products_status ON public.ml_products(status);
CREATE INDEX idx_ml_products_cid ON public.ml_products(cid);           -- SEO查询
CREATE INDEX idx_ml_products_created ON public.ml_products(created_at DESC);

-- 订单表索引
CREATE INDEX idx_ml_orders_user ON public.ml_orders(user_id);
CREATE INDEX idx_ml_orders_merchant ON public.ml_orders(merchant_id);
CREATE INDEX idx_ml_orders_status ON public.ml_orders(order_status);
CREATE INDEX idx_ml_orders_created ON public.ml_orders(created_at DESC);

-- JSONB GIN索引（用于JSON字段查询）
CREATE INDEX idx_ml_products_images_gin ON public.ml_products USING GIN(image_urls);
CREATE INDEX idx_ml_orders_address_gin ON public.ml_orders USING GIN(shipping_address);
```

### 2.3 触发器实现

#### 2.3.1 自动更新时间戳

```sql
-- 触发器函数
CREATE OR REPLACE FUNCTION public.update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- 应用到表
CREATE TRIGGER trigger_ml_user_profiles_updated_at
    BEFORE UPDATE ON public.ml_user_profiles
    FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column();
```

#### 2.3.2 确保唯一默认地址

```sql
CREATE OR REPLACE FUNCTION public.ensure_single_default_address()
RETURNS TRIGGER AS $$
BEGIN
    IF NEW.is_default = TRUE THEN
        UPDATE public.ml_user_addresses
        SET is_default = FALSE
        WHERE user_id = NEW.user_id AND id != NEW.id;
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_ensure_single_default_address
    BEFORE INSERT OR UPDATE ON public.ml_user_addresses
    FOR EACH ROW EXECUTE FUNCTION public.ensure_single_default_address();
```

#### 2.3.3 自动更新商品库存

```sql
CREATE OR REPLACE FUNCTION public.update_product_stock()
RETURNS TRIGGER AS $$
BEGIN
    IF TG_OP = 'INSERT' THEN
        -- 插入订单商品时，减少库存
        UPDATE public.ml_products
        SET available_stock = available_stock - NEW.quantity
        WHERE id = NEW.product_id;
    ELSIF TG_OP = 'DELETE' THEN
        -- 删除订单商品时，恢复库存
        UPDATE public.ml_products
        SET available_stock = available_stock + OLD.quantity
        WHERE id = OLD.product_id;
    END IF;
    RETURN NULL;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_update_product_stock
    AFTER INSERT OR DELETE ON public.ml_order_items
    FOR EACH ROW EXECUTE FUNCTION public.update_product_stock();
```

### 2.4 数据库函数实现

#### 2.4.1 业务函数

**生成订单号**
```sql
CREATE OR REPLACE FUNCTION public.generate_order_no()
RETURNS TEXT AS $$
DECLARE
    order_no TEXT;
BEGIN
    order_no := 'ML' || TO_CHAR(NOW(), 'YYYYMMDD') || 
                LPAD(NEXTVAL('ml_order_seq')::TEXT, 6, '0');
    RETURN order_no;
END;
$$ LANGUAGE plpgsql;
```

**计算购物车总金额**
```sql
CREATE OR REPLACE FUNCTION public.calculate_cart_total(p_user_id UUID)
RETURNS DECIMAL AS $$
DECLARE
    total_amount DECIMAL(12,2) := 0;
BEGIN
    SELECT COALESCE(SUM(
        CASE 
            WHEN c.sku_id IS NOT NULL THEN s.price * c.quantity
            ELSE p.base_price * c.quantity
        END
    ), 0) INTO total_amount
    FROM public.ml_shopping_cart c
    LEFT JOIN public.ml_product_skus s ON c.sku_id = s.id
    LEFT JOIN public.ml_products p ON c.product_id = p.id
    WHERE c.user_id = p_user_id 
      AND c.selected = TRUE
      AND p.status = 1 
      AND (s.id IS NULL OR s.status = 1);
    
    RETURN total_amount;
END;
$$ LANGUAGE plpgsql;
```

**获取用户默认地址**
```sql
CREATE OR REPLACE FUNCTION public.get_user_default_address(p_user_id UUID)
RETURNS TABLE (
    id UUID,
    receiver_name VARCHAR,
    receiver_phone VARCHAR,
    address_detail TEXT
) AS $$
BEGIN
    RETURN QUERY
    SELECT 
        a.id,
        a.receiver_name,
        a.receiver_phone,
        a.address_detail
    FROM public.ml_user_addresses a
    WHERE a.user_id = p_user_id 
      AND a.is_default = TRUE 
      AND a.status = 1
    LIMIT 1;
END;
$$ LANGUAGE plpgsql;
```

### 2.5 RLS 行级安全策略

#### 2.5.1 用户数据隔离

```sql
-- 用户只能访问自己的数据
CREATE POLICY ml_user_profiles_select_policy ON public.ml_user_profiles
    FOR SELECT USING (
        auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = user_id)
    );

CREATE POLICY ml_user_profiles_update_policy ON public.ml_user_profiles
    FOR UPDATE USING (
        auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = user_id)
    );
```

#### 2.5.2 商品权限控制

```sql
-- 所有人可查看已上架商品
CREATE POLICY ml_products_select_policy ON public.ml_products
    FOR SELECT USING (status = 1);

-- 商家只能管理自己的商品
CREATE POLICY ml_products_insert_policy ON public.ml_products
    FOR INSERT WITH CHECK (
        auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = merchant_id)
    );

CREATE POLICY ml_products_update_policy ON public.ml_products
    FOR UPDATE USING (
        auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = merchant_id)
    );
```

#### 2.5.3 订单权限控制

```sql
-- 用户和商家都可查看相关订单
CREATE POLICY ml_orders_select_policy ON public.ml_orders
    FOR SELECT USING (
        auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = user_id)
        OR
        auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = merchant_id)
    );

-- 只有用户能创建订单
CREATE POLICY ml_orders_insert_policy ON public.ml_orders
    FOR INSERT WITH CHECK (
        auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = user_id)
    );
```

---

## 三、后端/API层实现

### 3.1 PostgREST 自动生成 API

#### 3.1.1 REST API 自动生成机制

Supabase 基于 PostgREST 自动为每个表生成 REST API：

**查询 API**
```
GET /rest/v1/ml_products
GET /rest/v1/ml_products?id=eq.{uuid}
GET /rest/v1/ml_products?status=eq.1&limit=20
GET /rest/v1/ml_products?base_price=gte.100&base_price=lte.500
```

**插入 API**
```
POST /rest/v1/ml_orders
Content-Type: application/json
{
  "user_id": "uuid",
  "merchant_id": "uuid",
  "total_amount": 100.00
}
```

**更新 API**
```
PATCH /rest/v1/ml_products?id=eq.{uuid}
Content-Type: application/json
{
  "status": 2
}
```

**删除 API**
```
DELETE /rest/v1/ml_user_favorites?id=eq.{uuid}
```

**RPC 函数调用**
```
POST /rest/v1/rpc/calculate_cart_total
Content-Type: application/json
{
  "p_user_id": "uuid"
}
```

### 3.2 查询操作符支持

PostgREST 支持丰富的查询操作符：

```typescript
// 等于
?status=eq.1

// 不等于
?status=neq.2

// 大于/小于
?base_price=gte.100&base_price=lte.500

// 模糊查询
?name=ilike.%商品%

// IN 查询
?category_id=in.(id1,id2,id3)

// IS NULL
?deleted_at=is.null

// JSONB 查询
?preferences->theme=eq.dark
```

### 3.3 分页和排序

```typescript
// 分页
?limit=20&offset=0
// 或使用 Range 头
Range: 0-19

// 排序
?order=created_at.desc
?order=base_price.asc,created_at.desc

// 计数
Prefer: count=exact
```

---

## 四、前端实现

### 4.1 项目结构

```
pages/mall/
├── consumer/              # 消费者端
│   ├── index.uvue        # 首页
│   ├── product-detail.uvue # 商品详情
│   ├── cart.uvue         # 购物车
│   ├── checkout.uvue     # 结算页
│   ├── orders.uvue       # 订单列表
│   └── subscription/     # 订阅相关
├── merchant/             # 商家端
│   ├── index.uvue        # 商家首页
│   └── product-detail.uvue
├── delivery/             # 配送端
├── admin/                # 管理端
└── service/              # 客服端

components/supadb/
├── aksupa.uts            # Supabase 客户端封装
├── aksupainstance.uts    # 全局单例
└── aksuparealtime.uts    # 实时订阅

types/
└── mall-types.uts       # 类型定义
```

### 4.2 Supabase 客户端封装

#### 4.2.1 客户端初始化

**文件**: `components/supadb/aksupainstance.uts`

```typescript
import AkSupa from './aksupa.uts'
import { SUPA_URL, SUPA_KEY } from '@/ak/config.uts'

// 创建全局 Supabase 客户端实例
const supa = new AkSupa(SUPA_URL, SUPA_KEY)

// 自动登录 (开发环境)
const supaReady: Promise<boolean> = (async () => {
    try {
        await supa.signIn('test@example.com', 'password')
        return true
    } catch (err) {
        console.error('Supabase auto sign-in failed', err)
        return false
    }
})()

export { supaReady }
export default supa
```

#### 4.2.2 API 调用封装

**文件**: `components/supadb/aksupa.uts`

```typescript
export class AkSupa {
    baseUrl: string
    apikey: string

    constructor(baseUrl: string, apikey: string) {
        this.baseUrl = baseUrl
        this.apikey = apikey
    }

    // 查询数据
    async select(
        table: string, 
        filter?: string | null, 
        options?: AkSupaSelectOptions
    ): Promise<AkReqResponse<any>> {
        let url = this.baseUrl + '/rest/v1/' + table
        let headers = {
            apikey: this.apikey,
            'Content-Type': 'application/json',
            Authorization: `Bearer ${AkReq.getToken() ?? ''}`
        } as UTSJSONObject
        
        // 构建查询参数
        let params: string[] = []
        if (options?.limit) params.push(`limit=${options.limit}`)
        if (options?.order) params.push(`order=${encodeURIComponent(options.order)}`)
        if (filter) params.push(filter)
        
        if (params.length > 0) {
            url += '?' + params.join('&')
        }
        
        return await this.requestWithAutoRefresh({
            url,
            method: 'GET',
            headers
        })
    }

    // 插入数据
    async insert(
        table: string, 
        row: UTSJSONObject | Array<UTSJSONObject>
    ): Promise<AkReqResponse<any>> {
        const url = this.baseUrl + '/rest/v1/' + table
        const headers = {
            apikey: this.apikey,
            'Content-Type': 'application/json',
            Authorization: `Bearer ${AkReq.getToken() ?? ''}`,
            Prefer: 'return=representation'
        } as UTSJSONObject
        
        return await this.requestWithAutoRefresh({
            url,
            method: 'POST',
            headers,
            data: row
        })
    }

    // 更新数据
    async update(
        table: string,
        filter: UTSJSONObject,
        data: UTSJSONObject
    ): Promise<AkReqResponse<any>> {
        const filterStr = buildSupabaseFilterQuery(filter)
        const url = this.baseUrl + '/rest/v1/' + table + '?' + filterStr
        const headers = {
            apikey: this.apikey,
            'Content-Type': 'application/json',
            Authorization: `Bearer ${AkReq.getToken() ?? ''}`,
            Prefer: 'return=representation'
        } as UTSJSONObject
        
        return await this.requestWithAutoRefresh({
            url,
            method: 'PATCH',
            headers,
            data
        })
    }

    // 调用 RPC 函数
    async rpc(
        functionName: string,
        params: UTSJSONObject
    ): Promise<AkReqResponse<any>> {
        const url = `${this.baseUrl}/rest/v1/rpc/${functionName}`
        const headers = {
            apikey: this.apikey,
            'Content-Type': 'application/json',
            Authorization: `Bearer ${AkReq.getToken() ?? ''}`
        } as UTSJSONObject
        
        return await this.requestWithAutoRefresh({
            url,
            method: 'POST',
            headers,
            data: params
        })
    }
}
```

### 4.3 页面实现示例

#### 4.3.1 商品列表页面

**文件**: `pages/mall/consumer/index.uvue`

```typescript
<script setup lang="uts">
import { ref, onMounted } from 'vue'
import type { ProductType } from '@/types/mall-types.uts'
import supa from '@/components/supadb/aksupainstance.uts'

const productList = ref<Array<ProductType>>([])
const isLoading = ref<boolean>(false)
const page = ref<number>(1)
const pageSize = ref<number>(20)

// 加载商品列表
const loadProducts = async (loadMore: boolean = false) => {
    if (isLoading.value) return
    
    isLoading.value = true
    
    try {
        const currentPage = loadMore ? page.value + 1 : 1
        
        // 使用链式查询构建器
        const res = await supa
            .from('ml_products')
            .select('*')
            .eq('status', 1)
            .order('created_at', { ascending: false })
            .range((currentPage - 1) * pageSize.value, currentPage * pageSize.value - 1)
        
        if (res.success && res.data) {
            const newProducts = res.data as Array<ProductType>
            
            if (loadMore) {
                productList.value.push(...newProducts)
            } else {
                productList.value = newProducts
            }
            
            page.value = currentPage
        }
    } catch (err) {
        console.error('加载商品失败:', err)
    } finally {
        isLoading.value = false
    }
}

onMounted(() => {
    loadProducts()
})
</script>
```

#### 4.3.2 商品详情页面

```typescript
// 加载商品详情
const loadProductDetail = async (productId: string) => {
    try {
        // 查询商品信息
        const productRes = await supa.select('ml_products', 
            `id=eq.${productId}`, 
            { single: true }
        )
        
        if (productRes.success && productRes.data) {
            product.value = productRes.data as ProductType
        }
        
        // 查询商品SKU
        const skuRes = await supa.select('ml_product_skus', {
            product_id: productId
        })
        
        if (skuRes.success && skuRes.data) {
            productSkus.value = skuRes.data as Array<ProductSkuType>
        }
        
        // 查询商家信息
        const merchantRes = await supa.select('ml_shops', {
            merchant_id: product.value.merchant_id
        }, { single: true })
        
        if (merchantRes.success && merchantRes.data) {
            merchant.value = merchantRes.data as MerchantType
        }
    } catch (err) {
        console.error('加载商品详情失败:', err)
    }
}
```

#### 4.3.3 购物车操作

```typescript
// 添加到购物车
const addToCart = async (product: ProductType, skuId?: string, quantity: number = 1) => {
    try {
        const userId = getCurrentUserId()
        if (!userId) {
            uni.showToast({ title: '请先登录', icon: 'error' })
            return
        }
        
        // 检查购物车中是否已存在
        const existingRes = await supa.select('ml_shopping_cart', {
            user_id: userId,
            product_id: product.id,
            sku_id: skuId || null
        }, { single: true })
        
        if (existingRes.success && existingRes.data) {
            // 更新数量
            await supa.update('ml_shopping_cart', 
                { id: existingRes.data.id },
                { quantity: existingRes.data.quantity + quantity }
            )
        } else {
            // 新增购物车项
            await supa.insert('ml_shopping_cart', {
                user_id: userId,
                product_id: product.id,
                sku_id: skuId || null,
                quantity: quantity,
                selected: true
            })
        }
        
        uni.showToast({ title: '已添加到购物车', icon: 'success' })
        loadCartCount()
    } catch (err) {
        console.error('添加到购物车失败:', err)
        uni.showToast({ title: '操作失败', icon: 'error' })
    }
}
```

#### 4.3.4 创建订单

```typescript
// 创建订单
const createOrder = async (cartItems: Array<CartItemType>, address: UserAddressType) => {
    try {
        // 1. 计算订单总金额（使用数据库函数）
        const totalRes = await supa.rpc('calculate_cart_total', {
            p_user_id: getCurrentUserId()
        })
        
        if (!totalRes.success) {
            throw new Error('计算订单金额失败')
        }
        
        const totalAmount = totalRes.data as number
        
        // 2. 生成订单号
        const orderNoRes = await supa.rpc('generate_order_no')
        if (!orderNoRes.success) {
            throw new Error('生成订单号失败')
        }
        const orderNo = orderNoRes.data as string
        
        // 3. 创建订单
        const orderRes = await supa.insert('ml_orders', {
            order_no: orderNo,
            user_id: getCurrentUserId(),
            merchant_id: cartItems[0].product.merchant_id,
            product_amount: totalAmount,
            discount_amount: 0,
            shipping_fee: 0,
            total_amount: totalAmount,
            shipping_address: {
                receiver_name: address.receiver_name,
                receiver_phone: address.receiver_phone,
                province: address.province,
                city: address.city,
                district: address.district,
                address_detail: address.address_detail
            },
            order_status: 1,  // 待支付
            payment_status: 1,
            shipping_status: 1
        })
        
        if (!orderRes.success) {
            throw new Error('创建订单失败')
        }
        
        const orderId = orderRes.data.id
        
        // 4. 创建订单商品项
        const orderItems = cartItems.map(item => ({
            order_id: orderId,
            product_id: item.product_id,
            sku_id: item.sku_id || null,
            product_name: item.product.name,
            price: item.sku?.price || item.product.price,
            quantity: item.quantity,
            total_amount: (item.sku?.price || item.product.price) * item.quantity
        }))
        
        await supa.insert('ml_order_items', orderItems)
        
        // 5. 清空购物车
        for (const item of cartItems) {
            await supa.delete('ml_shopping_cart', { id: item.id })
        }
        
        uni.showToast({ title: '订单创建成功', icon: 'success' })
        
        // 跳转到订单详情
        uni.navigateTo({
            url: `/pages/mall/consumer/order-detail?orderId=${orderId}`
        })
    } catch (err) {
        console.error('创建订单失败:', err)
        uni.showToast({ title: '创建订单失败', icon: 'error' })
    }
}
```

### 4.4 实时数据同步

#### 4.4.1 订阅订单状态更新

```typescript
import { AkSupaRealtime } from '@/components/supadb/aksuparealtime.uts'

// 订阅订单状态更新
const subscribeOrderStatus = (orderId: string, callback: (payload: any) => void) => {
    const realtime = new AkSupaRealtime(WS_URL, SUPA_KEY)
    
    realtime.subscribe('ml_orders', {
        filter: `id=eq.${orderId}`,
        event: 'UPDATE',
        callback: (payload) => {
            console.log('订单状态更新:', payload)
            callback(payload)
        }
    })
}

// 使用
onMounted(() => {
    subscribeOrderStatus(orderId, (payload) => {
        // 更新订单状态
        order.value.order_status = payload.new.order_status
    })
})
```

---

## 五、数据流机制

### 5.1 数据流向图

```
用户操作
   │
   ▼
前端页面 (uni-app-x)
   │
   ▼
Supabase 客户端 (AkSupa)
   │
   ▼ HTTP Request
   │
   ├─ Headers: apikey, Authorization (JWT Token)
   │
   ▼
PostgREST API
   │
   ├─ 解析请求
   ├─ 验证 JWT Token
   ├─ 应用 RLS 策略
   │
   ▼
PostgreSQL 数据库
   │
   ├─ 执行 SQL 查询
   ├─ 触发触发器
   ├─ 执行函数
   │
   ▼
返回数据
   │
   ▼
PostgREST 格式化响应
   │
   ▼ HTTP Response
   │
   ├─ JSON 数据
   ├─ 状态码
   │
   ▼
Supabase 客户端处理
   │
   ├─ 解析响应
   ├─ 错误处理
   │
   ▼
前端页面更新 UI
```

### 5.2 认证流程

```
1. 用户登录
   │
   ▼
2. Supabase Auth 验证
   │
   ├─ 验证邮箱/密码
   ├─ 生成 JWT Token
   │
   ▼
3. 存储 Token
   │
   ├─ 本地存储 (uni.setStorageSync)
   │
   ▼
4. 后续请求自动携带 Token
   │
   ├─ Authorization: Bearer <token>
   │
   ▼
5. PostgREST 验证 Token
   │
   ├─ 解析 JWT
   ├─ 获取 auth.uid()
   │
   ▼
6. RLS 策略应用
   │
   ├─ 根据 auth.uid() 过滤数据
```

### 5.3 权限控制流程

```
请求到达 PostgREST
   │
   ▼
解析 JWT Token
   │
   ├─ 获取 auth.uid()
   │
   ▼
查找 RLS 策略
   │
   ├─ SELECT 策略 → USING 子句
   ├─ INSERT 策略 → WITH CHECK 子句
   ├─ UPDATE 策略 → USING + WITH CHECK
   ├─ DELETE 策略 → USING 子句
   │
   ▼
应用策略条件
   │
   ├─ 用户只能访问自己的数据
   ├─ 商家只能管理自己的商品
   ├─ 公开数据所有人可查看
   │
   ▼
执行 SQL 查询
   │
   ├─ 自动添加 WHERE 条件
   │
   ▼
返回过滤后的数据
```

---

## 六、业务逻辑实现

### 6.1 商品管理流程

#### 6.1.1 商品上架流程

```typescript
// 商家上架商品
const publishProduct = async (productData: any) => {
    // 1. 验证商家权限
    const merchantRes = await supa.select('ml_user_profiles', {
        user_id: getCurrentUserId(),
        user_type: 2,  // 商家
        verification_status: 1  // 已认证
    }, { single: true })
    
    if (!merchantRes.success || !merchantRes.data) {
        throw new Error('您还不是认证商家')
    }
    
    // 2. 创建商品
    const productRes = await supa.insert('ml_products', {
        merchant_id: getCurrentUserId(),
        category_id: productData.category_id,
        name: productData.name,
        description: productData.description,
        base_price: productData.price,
        total_stock: productData.stock,
        available_stock: productData.stock,
        status: 1,  // 上架
        ...productData
    })
    
    // 3. 创建商品SKU
    if (productData.skus && productData.skus.length > 0) {
        const skus = productData.skus.map((sku: any) => ({
            product_id: productRes.data.id,
            sku_code: sku.sku_code,
            specifications: sku.specifications,
            price: sku.price,
            stock: sku.stock
        }))
        
        await supa.insert('ml_product_skus', skus)
    }
    
    return productRes.data
}
```

### 6.2 订单处理流程

#### 6.2.1 订单状态流转

```typescript
// 订单状态枚举
const ORDER_STATUS = {
    PENDING_PAYMENT: 1,    // 待支付
    PAID: 2,               // 已支付
    SHIPPED: 3,            // 已发货
    DELIVERED: 4,          // 已送达
    COMPLETED: 5,          // 已完成
    CANCELLED: 6,          // 已取消
    REFUNDING: 7,          // 退款中
    REFUNDED: 8            // 已退款
}

// 更新订单状态
const updateOrderStatus = async (orderId: string, newStatus: number) => {
    const updateData: any = {
        order_status: newStatus,
        updated_at: new Date().toISOString()
    }
    
    // 根据状态设置相应时间戳
    switch (newStatus) {
        case ORDER_STATUS.PAID:
            updateData.paid_at = new Date().toISOString()
            updateData.payment_status = 2  // 已支付
            break
        case ORDER_STATUS.SHIPPED:
            updateData.shipped_at = new Date().toISOString()
            updateData.shipping_status = 2  // 已发货
            break
        case ORDER_STATUS.DELIVERED:
            updateData.delivered_at = new Date().toISOString()
            updateData.shipping_status = 4  // 已送达
            break
        case ORDER_STATUS.COMPLETED:
            updateData.completed_at = new Date().toISOString()
            break
    }
    
    await supa.update('ml_orders', { id: orderId }, updateData)
}
```

### 6.3 库存管理机制

#### 6.3.1 库存扣减流程

```typescript
// 下单时扣减库存
const deductStock = async (orderItems: Array<any>) => {
    for (const item of orderItems) {
        if (item.sku_id) {
            // 扣减 SKU 库存
            const skuRes = await supa.select('ml_product_skus', {
                id: item.sku_id
            }, { single: true })
            
            if (skuRes.data.stock < item.quantity) {
                throw new Error(`商品 ${item.product_name} 库存不足`)
            }
            
            await supa.update('ml_product_skus', 
                { id: item.sku_id },
                { stock: skuRes.data.stock - item.quantity }
            )
        } else {
            // 扣减商品总库存
            const productRes = await supa.select('ml_products', {
                id: item.product_id
            }, { single: true })
            
            if (productRes.data.available_stock < item.quantity) {
                throw new Error(`商品 ${item.product_name} 库存不足`)
            }
            
            await supa.update('ml_products',
                { id: item.product_id },
                { 
                    available_stock: productRes.data.available_stock - item.quantity,
                    sale_count: productRes.data.sale_count + item.quantity
                }
            )
        }
    }
}
```

---

## 七、安全机制

### 7.1 多层安全防护

```
┌─────────────────────────────────────┐
│  1. 网络层安全                        │
│  - HTTPS 加密传输                    │
│  - SSL/TLS 证书                      │
└─────────────────────────────────────┘
           │
           ▼
┌─────────────────────────────────────┐
│  2. 认证层安全                        │
│  - JWT Token 验证                    │
│  - Token 过期机制                    │
│  - 自动刷新 Token                    │
└─────────────────────────────────────┘
           │
           ▼
┌─────────────────────────────────────┐
│  3. 权限层安全 (RLS)                 │
│  - 行级安全策略                       │
│  - 基于用户角色的权限控制             │
│  - 数据隔离                          │
└─────────────────────────────────────┘
           │
           ▼
┌─────────────────────────────────────┐
│  4. 应用层安全                        │
│  - 前端数据验证                       │
│  - 输入过滤和转义                     │
│  - 防止 SQL 注入                     │
└─────────────────────────────────────┘
```

### 7.2 数据验证机制

#### 7.2.1 数据库约束

```sql
-- CHECK 约束
CONSTRAINT chk_ml_product_status CHECK (status IN (1,2,3,4))
CONSTRAINT chk_ml_order_status CHECK (order_status IN (1,2,3,4,5,6,7))
CONSTRAINT chk_ml_credit_score CHECK (credit_score >= 0 AND credit_score <= 1000)

-- 外键约束
REFERENCES public.ak_users(id) ON DELETE CASCADE
REFERENCES public.ml_products(id) ON DELETE CASCADE

-- 唯一约束
UNIQUE(product_code)
UNIQUE(order_no)
UNIQUE(user_id, product_id, sku_id)  -- 购物车唯一性
```

#### 7.2.2 前端验证

```typescript
// 表单验证
const validateOrderData = (orderData: any): boolean => {
    if (!orderData.user_id) {
        uni.showToast({ title: '用户ID不能为空', icon: 'error' })
        return false
    }
    
    if (!orderData.total_amount || orderData.total_amount <= 0) {
        uni.showToast({ title: '订单金额无效', icon: 'error' })
        return false
    }
    
    if (!orderData.shipping_address) {
        uni.showToast({ title: '请选择收货地址', icon: 'error' })
        return false
    }
    
    return true
}
```

---

## 八、性能优化

### 8.1 数据库优化

#### 8.1.1 索引优化

```sql
-- 复合索引（针对常用查询组合）
CREATE INDEX idx_ml_products_status_created 
ON ml_products(status, created_at DESC);

CREATE INDEX idx_ml_orders_user_status 
ON ml_orders(user_id, order_status);

-- 部分索引（只索引活跃数据）
CREATE INDEX idx_ml_products_active 
ON ml_products(merchant_id, category_id) 
WHERE status = 1;
```

#### 8.1.2 查询优化

```typescript
// 只查询需要的字段
const res = await supa.select('ml_products', null, {
    columns: 'id,name,base_price,main_image_url',  // 只查询必要字段
    limit: 20
})

// 使用视图简化复杂查询
const res = await supa.select('ml_products_detail_view', {
    status: 1
}, {
    limit: 20
})
```

### 8.2 前端优化

#### 8.2.1 分页加载

```typescript
// 分页加载商品列表
const loadProducts = async (loadMore: boolean = false) => {
    const currentPage = loadMore ? page.value + 1 : 1
    
    const res = await supa
        .from('ml_products')
        .select('*')
        .eq('status', 1)
        .order('created_at', { ascending: false })
        .range((currentPage - 1) * pageSize.value, currentPage * pageSize.value - 1)
    
    // 追加或替换数据
    if (loadMore) {
        productList.value.push(...res.data)
    } else {
        productList.value = res.data
    }
}
```

#### 8.2.2 数据缓存

```typescript
// 使用本地缓存减少请求
const getCachedProducts = async (categoryId: string) => {
    const cacheKey = `products_${categoryId}`
    const cached = uni.getStorageSync(cacheKey)
    
    if (cached && Date.now() - cached.timestamp < 5 * 60 * 1000) {
        // 5分钟内使用缓存
        return cached.data
    }
    
    // 从服务器获取
    const res = await supa.select('ml_products', {
        category_id: categoryId,
        status: 1
    })
    
    // 更新缓存
    uni.setStorageSync(cacheKey, {
        data: res.data,
        timestamp: Date.now()
    })
    
    return res.data
}
```

### 8.3 实时同步优化

```typescript
// 只订阅必要的数据变更
const subscribeOrderUpdates = (orderId: string) => {
    realtime.subscribe('ml_orders', {
        filter: `id=eq.${orderId}`,  // 只订阅特定订单
        event: 'UPDATE',              // 只监听更新事件
        callback: handleOrderUpdate
    })
}

// 及时取消订阅
onUnmounted(() => {
    realtime.unsubscribe('ml_orders')
})
```

---

## 九、开发工作流

### 9.1 开发流程

```
1. 数据库设计
   │
   ├─ 设计表结构
   ├─ 设计索引
   ├─ 设计 RLS 策略
   ├─ 设计触发器
   └─ 设计函数
   │
   ▼
2. 执行数据库脚本
   │
   ├─ complete_mall_database.sql
   │
   ▼
3. 定义类型
   │
   ├─ types/mall-types.uts
   │
   ▼
4. 开发前端页面
   │
   ├─ 页面组件
   ├─ API 调用
   └─ 业务逻辑
   │
   ▼
5. 测试验证
   │
   ├─ 功能测试
   ├─ 权限测试
   └─ 性能测试
```

### 9.2 调试技巧

```typescript
// 1. 启用详细日志
console.log('请求参数:', {
    table: 'ml_products',
    filter: filter,
    options: options
})

// 2. 检查响应
console.log('API 响应:', {
    success: res.success,
    status: res.status,
    data: res.data,
    error: res.error
})

// 3. 验证权限
const session = await supa.getSession()
console.log('当前用户:', session.user)
console.log('JWT Token:', AkReq.getToken())
```

---

## 📚 相关文档

- [模块分析报告](./MODULE_ANALYSIS.md)
- [前后端联调指南](./FRONTEND_BACKEND_DEBUGGING.md)
- [数据库创建报告](./database/database_creation_report.md)
- [完整部署指南](./database/complete_deployment_guide.md)

---

**生成时间**: 2025年1月  
**版本**: v1.0  
**状态**: ✅ 完整技术实现拆解
