Files
akmon/pages/sport/SUPACLINET_GUIDE.md
2026-01-20 08:04:15 +08:00

5.3 KiB
Raw Permalink Blame History

直接使用 AkSupa 链式调用指南

优势: 无需 API 包装层,直接使用 supaClient 链式调用,代码更简洁高效!

基本用法

1. 导入 supaClient

import supaClient from '@/components/supadb/aksupainstance.uts'

2. 基本 CRUD 操作

查询数据

// 获取所有项目
const result = await supaClient
  .from('ak_training_projects')
  .select('*')
  .execute()

// 带条件查询
const result = await supaClient
  .from('ak_assignments')
  .select('*, ak_training_projects(*)')
  .eq('student_id', studentId)
  .eq('status', 'pending')
  .order('created_at', { ascending: false })
  .limit(20)
  .execute()

// 单条记录查询
const result = await supaClient
  .from('ak_training_projects')
  .select('*')
  .eq('id', projectId)
  .single()
  .execute()

插入数据

// 创建新记录
const result = await supaClient
  .from('ak_training_records')
  .insert({
    title: '晨跑训练',
    duration: 30,
    calories: 200,
    student_id: 'user123',
    created_at: new Date().toISOString()
  })
  .single()
  .execute()

更新数据

// 更新记录
const result = await supaClient
  .from('ak_assignments')
  .update({
    status: 'completed',
    completed_at: new Date().toISOString(),
    score: 95
  })
  .eq('id', assignmentId)
  .single()
  .execute()

删除数据

// 删除记录
const result = await supaClient
  .from('ak_training_records')
  .delete()
  .eq('id', recordId)
  .execute()

3. 高级查询

复杂筛选

// 多条件筛选
const result = await supaClient
  .from('ak_training_projects')
  .select('*')
  .eq('category', '体能训练')
  .gte('difficulty', 3)
  .lte('difficulty', 5)
  .eq('is_active', true)
  .ilike('name', '%跑步%')
  .execute()

分页查询

// 分页获取数据
const result = await supaClient
  .from('ak_assignments')
  .select('*')
  .range(0, 19) // 获取前20条
  .order('created_at', { ascending: false })
  .execute()

聚合查询

// 统计查询
const result = await supaClient
  .from('ak_training_records')
  .select('*', { count: 'exact' })
  .eq('student_id', studentId)
  .execute()

// result.count 包含总数

4. 实时订阅

export default {
  data() {
    return {
      subscription: null
    }
  },
  
  onLoad() {
    this.setupRealtimeSubscription()
  },
  
  onUnload() {
    if (this.subscription) {
      this.subscription.unsubscribe()
    }
  },
  
  methods: {
    setupRealtimeSubscription() {
      this.subscription = supaClient
        .from('ak_assignments')
        .on('INSERT', (payload) => {
          console.log('新作业:', payload.new)
          // 更新本地数据
          this.assignments.push(payload.new)
        })
        .on('UPDATE', (payload) => {
          console.log('作业更新:', payload.new)
          // 更新本地数据
          this.updateLocalAssignment(payload.new)
        })
        .on('DELETE', (payload) => {
          console.log('作业删除:', payload.old)
          // 从本地数据中移除
          this.removeLocalAssignment(payload.old.id)
        })
        .subscribe()
    }
  }
}

5. 文件上传

// 上传文件到 Supabase Storage
const result = await supaClient
  .storage
  .from('training-files')
  .upload(`${Date.now()}_${fileName}`, filePath)
  .execute()

if (result.success) {
  const fileUrl = supaClient.storage
    .from('training-files')
    .getPublicUrl(result.data.path)
  
  console.log('文件URL', fileUrl)
}

6. 认证操作

// 登录
const result = await supaClient.signInWithPassword(email, password)

// 登出
await supaClient.signOut()

// 获取当前会话
const session = supaClient.getSession()

// 获取当前用户
if (session && session.user) {
  const userId = session.user.id
  const userEmail = session.user.email
}

错误处理

try {
  const result = await supaClient
    .from('ak_training_projects')
    .select('*')
    .execute()
  
  if (result.success) {
    // 处理成功结果
    this.projects = result.data
  } else {
    // 处理错误
    uni.showToast({
      title: result.message || '操作失败',
      icon: 'none'
    })
  }
} catch (error) {
  console.error('请求失败:', error)
  uni.showToast({
    title: '网络错误',
    icon: 'none'
  })
}

数据安全访问

使用 types.uts 中的安全访问函数:

import { safeGet } from '../types.uts'

// 安全获取数据
const projectId = safeGet(project, 'id', '') as string
const projectName = safeGet(project, 'name', '未命名项目') as string
const difficulty = safeGet(project, 'difficulty', 1) as number

最佳实践

  1. 统一错误处理 - 使用 try-catch 包装所有数据库操作
  2. 数据验证 - 在插入/更新前验证数据有效性
  3. 实时订阅管理 - 在页面卸载时记得取消订阅
  4. 安全访问 - 始终使用 safeGet 等安全函数访问数据
  5. 性能优化 - 合理使用 limit() 和分页查询

示例页面

参考 pages/sport/student/simple-records.uvue 查看完整的实现示例。


总结: 删除了 api.uts 包装层后,直接使用 supaClient 链式调用让代码更加简洁、直观和高效!