Files
medical-mall/mall_sql/docs/FRONTEND_BACKEND_DEBUGGING.md
2026-01-30 16:11:23 +08:00

876 lines
19 KiB
Markdown

# 🔧 前端与后端联调指南
## 📋 目录
1. [联调环境配置](#联调环境配置)
2. [本地开发环境搭建](#本地开发环境搭建)
3. [前端连接后端](#前端连接后端)
4. [调试工具和方法](#调试工具和方法)
5. [常见联调场景](#常见联调场景)
6. [问题排查](#问题排查)
---
## 一、联调环境配置
### 1.1 环境类型
#### 开发环境 (Development)
- **Supabase 本地实例**: Docker Compose 运行在 `192.168.0.150:8080`
- **Supabase 云服务**: 使用开发项目
- **前端**: uni-app-x 开发模式
#### 生产环境 (Production)
- **Supabase 云服务**: 生产项目
- **前端**: 编译后的应用
### 1.2 配置文件位置
#### 前端配置
**文件**: `ak/config.uts`
```typescript
// 开发环境 - 本地 Supabase
export const SUPA_URL: string = 'http://192.168.0.150:8080'
export const SUPA_KEY: string = 'your-anon-key'
// 生产环境 - Supabase 云服务
export const SUPA_URL: string = 'https://ak3.oulog.com'
export const SUPA_KEY: string = 'your-anon-key'
// WebSocket 实时连接
export const WS_URL: string = 'wss://ak3.oulog.com/realtime/v1/websocket'
```
#### 后端配置 (Docker)
**文件**: `doc_chat/supa.env`
```env
# Supabase 本地配置
POSTGRES_HOST=db
POSTGRES_DB=postgres
POSTGRES_PORT=5432
POSTGRES_PASSWORD=your-password
# API 配置
KONG_HTTP_PORT=8000
KONG_HTTPS_PORT=8443
# Auth 配置
API_EXTERNAL_URL=http://localhost:8000
SITE_URL=http://localhost:3000
```
---
## 二、本地开发环境搭建
### 2.1 Supabase 本地实例启动
#### 方式一: Docker Compose (推荐)
```bash
# 1. 进入 Supabase 目录
cd doc_chat
# 2. 启动 Supabase 服务
docker-compose -f supa-docker-compose.yml up -d
# 3. 检查服务状态
docker-compose -f supa-docker-compose.yml ps
# 4. 查看日志
docker-compose -f supa-docker-compose.yml logs -f
```
**服务端口**:
- **API**: `http://localhost:8000``http://192.168.0.150:8080`
- **PostgreSQL**: `localhost:5432`
- **Dashboard**: `http://localhost:3000`
#### 方式二: Supabase CLI
```bash
# 1. 安装 Supabase CLI
npm install -g supabase
# 2. 初始化项目
supabase init
# 3. 启动本地实例
supabase start
# 4. 查看服务信息
supabase status
```
### 2.2 数据库初始化
```bash
# 1. 执行商城数据库脚本
psql -h localhost -U postgres -d postgres -f doc_mall/database/complete_mall_database.sql
# 或使用 Supabase Dashboard SQL Editor
# 1. 打开 http://localhost:3000
# 2. 进入 SQL Editor
# 3. 复制粘贴 complete_mall_database.sql 内容
# 4. 执行脚本
# 2. 插入模拟数据 (可选)
psql -h localhost -U postgres -d postgres -f doc_mall/database/mock_data_insert.sql
# 3. 验证数据库
psql -h localhost -U postgres -d postgres -f doc_mall/database/validation_test.sql
```
### 2.3 前端开发环境
```bash
# 1. 安装依赖 (如果使用 npm)
npm install
# 2. 启动 uni-app-x 开发服务器
# 在 HBuilderX 中:
# - 运行 -> 运行到浏览器/手机模拟器
# - 或使用命令行工具
# 3. 配置开发环境
# 修改 ak/config.uts 中的 SUPA_URL 和 SUPA_KEY
```
---
## 三、前端连接后端
### 3.1 Supabase 客户端初始化
#### 全局单例模式
**文件**: `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
```
#### 在页面中使用
```typescript
// pages/mall/consumer/index.uvue
<script setup lang="uts">
import supa from '@/components/supadb/aksupainstance.uts'
import { ProductType } from '@/types/mall-types.uts'
const products = ref<Array<ProductType>>([])
onMounted(async () => {
// 等待 Supabase 客户端就绪
await supaReady
// 查询商品列表
const res = await supa.select('ml_products', {
status: 1 // 只查询已上架商品
}, {
limit: 20,
order: 'created_at.desc'
})
if (res.success && res.data) {
products.value = res.data as Array<ProductType>
}
})
</script>
```
### 3.2 API 调用方式
#### 3.2.1 查询数据 (SELECT)
```typescript
// 简单查询
const res = await supa.select('ml_products', null, {
limit: 10,
order: 'created_at.desc'
})
// 带过滤条件
const res = await supa.select('ml_products', {
status: 1,
category_id: categoryId
}, {
limit: 20,
order: 'sale_count.desc'
})
// 复杂过滤 (PostgREST 操作符)
const res = await supa.select('ml_products', {
base_price: { gte: 100, lte: 500 },
name: { ilike: '%商品%' },
category_id: { in: [id1, id2, id3] }
}, {
limit: 20
})
// 单条记录
const res = await supa.select('ml_products', { id: productId }, {
single: true
})
// 选择特定字段
const res = await supa.select('ml_products', null, {
columns: 'id,name,base_price,main_image_url',
limit: 20
})
```
#### 3.2.2 插入数据 (INSERT)
```typescript
// 插入订单
const orderRes = await supa.insert('ml_orders', {
user_id: userId,
merchant_id: merchantId,
total_amount: 100.00,
order_status: 1,
payment_status: 1,
shipping_status: 1,
shipping_address: {
receiver_name: '张三',
receiver_phone: '13800138000',
address_detail: '北京市朝阳区xxx'
}
})
// 批量插入
const items = [
{ order_id: orderId, product_id: productId1, quantity: 2 },
{ order_id: orderId, product_id: productId2, quantity: 1 }
]
const itemsRes = await supa.insert('ml_order_items', items)
```
#### 3.2.3 更新数据 (UPDATE)
```typescript
// 更新商品状态
await supa.update('ml_products',
{ id: productId }, // 过滤条件
{
status: 2, // 下架
updated_at: new Date().toISOString()
}
)
// 更新订单状态
await supa.update('ml_orders',
{ id: orderId },
{
order_status: 2, // 待发货
updated_at: new Date().toISOString()
}
)
```
#### 3.2.4 删除数据 (DELETE)
```typescript
// 删除收藏
await supa.delete('ml_user_favorites', { id: favoriteId })
// 删除购物车商品
await supa.delete('ml_shopping_cart', {
user_id: userId,
product_id: productId
})
```
#### 3.2.5 调用数据库函数 (RPC)
```typescript
// 计算购物车总金额
const totalRes = await supa.rpc('calculate_cart_total', {
p_user_id: userId
})
// 生成订单号
const orderNoRes = await supa.rpc('generate_order_no')
// 获取用户默认地址
const addressRes = await supa.rpc('get_user_default_address', {
p_user_id: userId
})
```
### 3.3 链式查询构建器
```typescript
// 使用链式 API
const res = await supa
.from('ml_products')
.eq('status', 1)
.gte('base_price', 100)
.lte('base_price', 500)
.like('name', '%商品%')
.order('created_at', { ascending: false })
.limit(20)
.select()
```
---
## 四、调试工具和方法
### 4.1 浏览器开发者工具
#### 网络请求调试
1. **打开 Chrome DevTools** (F12)
2. **Network 标签页**
- 查看所有 HTTP 请求
- 检查请求 URL、Headers、Body
- 查看响应状态码、数据
3. **Console 标签页**
- 查看 `console.log()` 输出
- 查看错误信息
- 执行调试代码
#### 示例: 检查 API 请求
```typescript
// 在代码中添加日志
console.log('请求商品列表:', {
table: 'ml_products',
filter: { status: 1 },
options: { limit: 20 }
})
const res = await supa.select('ml_products', { status: 1 }, { limit: 20 })
console.log('API 响应:', {
success: res.success,
data: res.data,
error: res.error,
status: res.status
})
```
### 4.2 Supabase Dashboard
#### 实时查看数据
1. **Table Editor**
- 查看表数据
- 手动编辑数据
- 验证数据是否正确
2. **SQL Editor**
- 执行 SQL 查询
- 测试数据库函数
- 验证 RLS 策略
3. **API Logs**
- 查看 API 请求日志
- 检查错误信息
- 分析性能问题
#### 示例: 测试查询
```sql
-- 在 Supabase Dashboard SQL Editor 中执行
SELECT * FROM ml_products
WHERE status = 1
ORDER BY created_at DESC
LIMIT 20;
-- 测试 RLS 策略
SET ROLE authenticated;
SET request.jwt.claim.sub = 'user-uuid-here';
SELECT * FROM ml_user_profiles;
```
### 4.3 Postman / Insomnia
#### 直接测试 Supabase API
```http
#
GET https://your-project.supabase.co/rest/v1/ml_products?status=eq.1&limit=20
Headers:
apikey: your-anon-key
Authorization: Bearer your-jwt-token
Content-Type: application/json
#
POST https://your-project.supabase.co/rest/v1/ml_orders
Headers:
apikey: your-anon-key
Authorization: Bearer your-jwt-token
Content-Type: application/json
Prefer: return=representation
Body:
{
"user_id": "user-uuid",
"merchant_id": "merchant-uuid",
"total_amount": 100.00,
"order_status": 1
}
# RPC
POST https://your-project.supabase.co/rest/v1/rpc/calculate_cart_total
Headers:
apikey: your-anon-key
Authorization: Bearer your-jwt-token
Content-Type: application/json
Body:
{
"p_user_id": "user-uuid"
}
```
### 4.4 数据库客户端工具
#### pgAdmin / DBeaver / DataGrip
```sql
-- 直接连接 PostgreSQL 数据库
-- Host: localhost (或 192.168.0.150)
-- Port: 5432
-- Database: postgres
-- User: postgres
-- Password: (从 supa.env 获取)
-- 查看表结构
SELECT * FROM information_schema.tables
WHERE table_schema = 'public' AND table_name LIKE 'ml_%';
-- 查看数据
SELECT * FROM ml_products LIMIT 10;
-- 查看 RLS 策略
SELECT * FROM pg_policies WHERE tablename = 'ml_products';
```
### 4.5 uni-app-x 调试
#### HBuilderX 调试工具
1. **控制台输出**
- 查看 `console.log()` 输出
- 查看错误堆栈
2. **网络请求监控**
- 查看所有网络请求
- 检查请求参数和响应
3. **断点调试**
- 在代码中设置断点
- 单步执行
- 查看变量值
---
## 五、常见联调场景
### 5.1 场景一: 查询商品列表失败
#### 问题现象
```typescript
// 前端代码
const res = await supa.select('ml_products', null, { limit: 20 })
// res.success = false
// res.error = "relation 'ml_products' does not exist"
```
#### 排查步骤
1. **检查数据库表是否存在**
```sql
SELECT table_name FROM information_schema.tables
WHERE table_schema = 'public' AND table_name = 'ml_products';
```
2. **检查表是否已创建**
- 执行 `complete_mall_database.sql` 脚本
- 验证脚本执行成功
3. **检查连接配置**
```typescript
console.log('Supabase URL:', SUPA_URL)
console.log('Supabase Key:', SUPA_KEY)
```
#### 解决方案
```bash
# 重新执行数据库脚本
psql -h localhost -U postgres -d postgres -f doc_mall/database/complete_mall_database.sql
```
### 5.2 场景二: RLS 策略阻止数据访问
#### 问题现象
```typescript
// 查询用户数据返回空
const res = await supa.select('ml_user_profiles', { user_id: userId })
// res.data = [] 或 null
```
#### 排查步骤
1. **检查用户是否已登录**
```typescript
const session = await supa.getSession()
console.log('当前用户:', session.user)
```
2. **检查 RLS 策略**
```sql
-- 查看表的 RLS 策略
SELECT * FROM pg_policies WHERE tablename = 'ml_user_profiles';
-- 测试 RLS 策略
SET ROLE authenticated;
SET request.jwt.claim.sub = 'auth-user-id';
SELECT * FROM ml_user_profiles;
```
3. **检查 auth_id 关联**
```sql
-- 验证 ak_users.auth_id 是否正确
SELECT id, auth_id FROM ak_users WHERE id = 'user-uuid';
```
#### 解决方案
```typescript
// 确保用户已登录
await supa.signIn('user@example.com', 'password')
// 或检查 Token
const token = AkReq.getToken()
console.log('JWT Token:', token)
```
### 5.3 场景三: 插入数据失败
#### 问题现象
```typescript
// 插入订单失败
const res = await supa.insert('ml_orders', orderData)
// res.success = false
// res.error = "new row violates row-level security policy"
```
#### 排查步骤
1. **检查必填字段**
```typescript
console.log('订单数据:', JSON.stringify(orderData, null, 2))
```
2. **检查外键约束**
```sql
-- 验证 user_id 和 merchant_id 是否存在
SELECT id FROM ak_users WHERE id IN ('user-id', 'merchant-id');
```
3. **检查 RLS INSERT 策略**
```sql
SELECT * FROM pg_policies
WHERE tablename = 'ml_orders' AND cmd = 'INSERT';
```
#### 解决方案
```typescript
// 确保数据完整
const orderData = {
user_id: userId, // 必须存在
merchant_id: merchantId, // 必须存在
total_amount: 100.00,
order_status: 1,
payment_status: 1,
shipping_status: 1,
shipping_address: addressData // 必须提供
}
// 确保用户有权限
await supa.signIn('user@example.com', 'password')
```
### 5.4 场景四: 实时数据同步不工作
#### 问题现象
```typescript
// 订阅订单状态更新,但没有收到推送
supa.realtime.subscribe('ml_orders', {
filter: `id=eq.${orderId}`,
event: 'UPDATE',
callback: (payload) => {
console.log('订单更新:', payload) // 没有触发
}
})
```
#### 排查步骤
1. **检查 WebSocket 连接**
```typescript
console.log('WebSocket URL:', WS_URL)
```
2. **检查表是否启用 Realtime**
```sql
-- 在 Supabase Dashboard 中检查
-- Database -> Replication -> 确保 ml_orders 表已启用
```
3. **检查网络连接**
- 确保 WebSocket 连接没有被防火墙阻止
- 检查浏览器控制台是否有 WebSocket 错误
#### 解决方案
```typescript
// 确保 WebSocket URL 正确
export const WS_URL: string = 'wss://your-project.supabase.co/realtime/v1/websocket'
// 在 Supabase Dashboard 中启用表的 Realtime
// Database -> Replication -> 找到 ml_orders -> 启用
```
### 5.5 场景五: 数据库函数调用失败
#### 问题现象
```typescript
// 调用 RPC 函数失败
const res = await supa.rpc('calculate_cart_total', { p_user_id: userId })
// res.success = false
// res.error = "function calculate_cart_total does not exist"
```
#### 排查步骤
1. **检查函数是否存在**
```sql
SELECT routine_name FROM information_schema.routines
WHERE routine_schema = 'public' AND routine_name = 'calculate_cart_total';
```
2. **检查函数参数**
```sql
-- 查看函数定义
\df calculate_cart_total
```
3. **测试函数**
```sql
SELECT calculate_cart_total('user-uuid-here');
```
#### 解决方案
```bash
# 重新执行数据库脚本,确保函数已创建
psql -h localhost -U postgres -d postgres -f doc_mall/database/complete_mall_database.sql
```
---
## 六、问题排查
### 6.1 排查清单
#### 连接问题
- [ ] Supabase URL 是否正确
- [ ] API Key 是否正确
- [ ] 网络连接是否正常
- [ ] 防火墙是否阻止连接
#### 认证问题
- [ ] 用户是否已登录
- [ ] JWT Token 是否有效
- [ ] Token 是否过期
- [ ] auth_id 是否正确关联
#### 数据问题
- [ ] 表是否存在
- [ ] 字段名是否正确
- [ ] 数据类型是否匹配
- [ ] 外键约束是否满足
#### 权限问题
- [ ] RLS 策略是否正确
- [ ] 用户是否有权限
- [ ] 策略条件是否满足
### 6.2 常用调试命令
#### 前端调试
```typescript
// 打印完整请求信息
console.log('请求详情:', {
url: `${SUPA_URL}/rest/v1/ml_products`,
headers: {
apikey: SUPA_KEY,
Authorization: `Bearer ${token}`
},
filter: filter,
options: options
})
// 打印完整响应
console.log('响应详情:', {
success: res.success,
status: res.status,
data: res.data,
error: res.error,
raw: res
})
```
#### 数据库调试
```sql
-- 查看表结构
\d ml_products
-- 查看索引
\di ml_products*
-- 查看触发器
\d+ ml_products
-- 查看 RLS 策略
SELECT * FROM pg_policies WHERE tablename = 'ml_products';
-- 测试查询性能
EXPLAIN ANALYZE SELECT * FROM ml_products WHERE status = 1;
```
### 6.3 错误码参考
| HTTP 状态码 | 含义 | 常见原因 |
| ----------- | ---------- | ---------------------- |
| 200 | 成功 | - |
| 400 | 请求错误 | 参数错误、数据格式错误 |
| 401 | 未授权 | Token 无效、未登录 |
| 403 | 禁止访问 | RLS 策略阻止 |
| 404 | 未找到 | 表不存在、记录不存在 |
| 500 | 服务器错误 | 数据库错误、函数错误 |
### 6.4 日志收集
#### 前端日志
```typescript
// 创建日志工具
class DebugLogger {
static log(module: string, action: string, data: any) {
console.log(`[${module}] ${action}:`, data)
// 可以发送到日志服务器
}
}
// 使用
DebugLogger.log('MallAPI', '查询商品', { filter, options })
```
#### 后端日志
```sql
-- 启用 PostgreSQL 日志
-- 在 postgresql.conf 中设置
log_statement = 'all'
log_duration = on
log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h '
```
---
## 七、最佳实践
### 7.1 开发环境配置
1. **使用环境变量**
```typescript
// 开发环境
const isDev = process.env.NODE_ENV === 'development'
export const SUPA_URL = isDev
? 'http://192.168.0.150:8080'
: 'https://ak3.oulog.com'
```
2. **统一错误处理**
```typescript
async function safeApiCall<T>(apiCall: () => Promise<AkReqResponse<T>>) {
try {
const res = await apiCall()
if (!res.success) {
console.error('API 调用失败:', res.error)
uni.showToast({ title: '操作失败', icon: 'error' })
}
return res
} catch (error) {
console.error('API 调用异常:', error)
uni.showToast({ title: '网络错误', icon: 'error' })
throw error
}
}
```
3. **请求重试机制**
```typescript
async function retryApiCall<T>(
apiCall: () => Promise<AkReqResponse<T>>,
maxRetries = 3
) {
for (let i = 0; i < maxRetries; i++) {
try {
const res = await apiCall()
if (res.success) return res
} catch (error) {
if (i === maxRetries - 1) throw error
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)))
}
}
}
```
### 7.2 联调流程
1. **数据库准备**
- 执行数据库脚本
- 插入测试数据
- 验证表结构
2. **前端配置**
- 配置 Supabase URL 和 Key
- 测试连接
- 验证认证
3. **功能测试**
- 测试 CRUD 操作
- 测试 RLS 策略
- 测试实时同步
4. **问题排查**
- 查看日志
- 检查网络请求
- 验证数据库数据
---
## 📚 相关文档
- [模块分析报告](./MODULE_ANALYSIS.md)
- [数据库创建报告](./database/database_creation_report.md)
- [完整部署指南](./database/complete_deployment_guide.md)
- [Supabase 官方文档](https://supabase.com/docs)
---
**生成时间**: 2025年1月
**版本**: v1.0
**状态**: ✅ 完整联调指南