260 lines
5.3 KiB
Markdown
260 lines
5.3 KiB
Markdown
# 直接使用 AkSupa 链式调用指南
|
||
|
||
**优势:** 无需 API 包装层,直接使用 `supaClient` 链式调用,代码更简洁高效!
|
||
|
||
## 基本用法
|
||
|
||
### 1. 导入 supaClient
|
||
```typescript
|
||
import supaClient from '@/components/supadb/aksupainstance.uts'
|
||
```
|
||
|
||
### 2. 基本 CRUD 操作
|
||
|
||
#### 查询数据
|
||
```typescript
|
||
// 获取所有项目
|
||
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()
|
||
```
|
||
|
||
#### 插入数据
|
||
```typescript
|
||
// 创建新记录
|
||
const result = await supaClient
|
||
.from('ak_training_records')
|
||
.insert({
|
||
title: '晨跑训练',
|
||
duration: 30,
|
||
calories: 200,
|
||
student_id: 'user123',
|
||
created_at: new Date().toISOString()
|
||
})
|
||
.single()
|
||
.execute()
|
||
```
|
||
|
||
#### 更新数据
|
||
```typescript
|
||
// 更新记录
|
||
const result = await supaClient
|
||
.from('ak_assignments')
|
||
.update({
|
||
status: 'completed',
|
||
completed_at: new Date().toISOString(),
|
||
score: 95
|
||
})
|
||
.eq('id', assignmentId)
|
||
.single()
|
||
.execute()
|
||
```
|
||
|
||
#### 删除数据
|
||
```typescript
|
||
// 删除记录
|
||
const result = await supaClient
|
||
.from('ak_training_records')
|
||
.delete()
|
||
.eq('id', recordId)
|
||
.execute()
|
||
```
|
||
|
||
### 3. 高级查询
|
||
|
||
#### 复杂筛选
|
||
```typescript
|
||
// 多条件筛选
|
||
const result = await supaClient
|
||
.from('ak_training_projects')
|
||
.select('*')
|
||
.eq('category', '体能训练')
|
||
.gte('difficulty', 3)
|
||
.lte('difficulty', 5)
|
||
.eq('is_active', true)
|
||
.ilike('name', '%跑步%')
|
||
.execute()
|
||
```
|
||
|
||
#### 分页查询
|
||
```typescript
|
||
// 分页获取数据
|
||
const result = await supaClient
|
||
.from('ak_assignments')
|
||
.select('*')
|
||
.range(0, 19) // 获取前20条
|
||
.order('created_at', { ascending: false })
|
||
.execute()
|
||
```
|
||
|
||
#### 聚合查询
|
||
```typescript
|
||
// 统计查询
|
||
const result = await supaClient
|
||
.from('ak_training_records')
|
||
.select('*', { count: 'exact' })
|
||
.eq('student_id', studentId)
|
||
.execute()
|
||
|
||
// result.count 包含总数
|
||
```
|
||
|
||
### 4. 实时订阅
|
||
|
||
```typescript
|
||
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. 文件上传
|
||
|
||
```typescript
|
||
// 上传文件到 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. 认证操作
|
||
|
||
```typescript
|
||
// 登录
|
||
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
|
||
}
|
||
```
|
||
|
||
## 错误处理
|
||
|
||
```typescript
|
||
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` 中的安全访问函数:
|
||
|
||
```typescript
|
||
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` 链式调用让代码更加简洁、直观和高效!
|