mall数据库文件

This commit is contained in:
comlibmb
2026-01-30 16:11:23 +08:00
parent b53d2376ff
commit cfec4a16c0
71 changed files with 11786 additions and 1009 deletions

View File

@@ -0,0 +1,22 @@
# SupaDB 文档更新记录
## 2026-01-30
### AkSupa从本地持久化 token 恢复 user/session
- **文件**`components/supadb/aksupa.uts`
- **位置**`export class AkSupa` -> `constructor(baseUrl: string, apikey: string)`,以及新增方法 `hydrateSessionFromStorage()`
- **定位标记**:在代码中搜索 `// [CHANGE][2026-01-30]`
#### 修改了什么
-`AkSupa` 构造时,会尝试基于本地已持久化的 token`AkReq.setToken` 写入 storage恢复登录态。
- 新增 `hydrateSessionFromStorage()`
- 通过 `AkReq.getToken()` 读取本地 access token
- 若 token 存在,则请求 `GET {baseUrl}/auth/v1/user`
- 将返回的 user 写入 `this.user`
-`this.session` 为空,则补齐一个最小 session 对象,使 `getSession()` 在「重启 App / 刷新页面」后仍能正确反映登录状态
#### 为什么要改
此前 `AkReq` 会把 token 持久化到本地,但 `AkSupa` 启动时不会自动恢复 `this.user` / `this.session`,导致即使 token 仍有效,`getSession()` 也可能返回 `{ session: null, user: null }`,从而使依赖登录态的页面判断失败。

View File

@@ -0,0 +1,155 @@
# AkSupa 简化API指南
## 概述
AkSupa 现在采用了**简化的单一方法**设计:只提供 `executeAs<T>()` 方法进行类型安全的数据访问,移除了所有冗余的类型转换方法。
## 重要变化
### 🚫 已移除的方法
- `selectAs<T>()`
- `insertAs<T>()`
- `updateAs<T>()`
- `deleteAs<T>()`
- `rpcAs<T>()`
### ✅ 统一的方法
- `executeAs<T>()` - 唯一的类型转换方法
## 设计理念
### 简洁性原则
- **一个方法解决所有问题**:所有查询操作最终都要调用 `execute()``executeAs<T>()` 是其类型安全版本
- **减少API复杂性**:不需要记住多个不同的方法名
- **保持一致性**:无论是查询、插入、更新还是删除,都使用相同的方法
### 链式友好
```typescript
// 所有操作都遵循相同的模式
const result = await supa
.from('table')
.operation() // select(), insert(), update(), delete(), rpc()
.conditions() // eq(), gt(), like(), etc.
.executeAs<T>(); // 统一的类型转换方法
```
## 使用示例
### 查询数据
```typescript
// 多条记录
const users = await supa
.from('users')
.select('*')
.eq('status', 'active')
.executeAs<User[]>();
// 单条记录
const user = await supa
.from('users')
.select('*')
.eq('id', 1)
.single()
.executeAs<User>();
```
### 插入数据
```typescript
const newUser = await supa
.from('users')
.insert({
name: 'John',
email: 'john@example.com'
})
.executeAs<User>();
```
### 更新数据
```typescript
const updatedUser = await supa
.from('users')
.update({ name: 'Jane' })
.eq('id', 1)
.executeAs<User>();
```
### 删除数据
```typescript
const deletedUser = await supa
.from('users')
.delete()
.eq('id', 1)
.executeAs<User>();
```
### RPC调用
```typescript
const result = await supa
.from('any_table')
.rpc('my_function', { param1: 'value1' })
.executeAs<ResultType>();
```
## 平台兼容性
| 平台 | 类型转换机制 | 说明 |
|------|-------------|------|
| Android | `UTSJSONObject.parse<T>()` | 真正的类型转换 |
| HarmonyOS | `UTSJSONObject.parse<T>()` | 真正的类型转换 |
| Web/iOS | `as T` | 类型断言 |
## 从旧版本迁移
### 旧代码
```typescript
// 旧方式 - 多个方法
const users = await supa.selectAs<User[]>('users', null, { limit: 10 });
const newUser = await supa.insertAs<User>('users', userData);
const updated = await supa.updateAs<User>('users', filter, updateData);
```
### 新代码
```typescript
// 新方式 - 统一方法
const users = await supa
.from('users')
.select('*')
.limit(10)
.executeAs<User[]>();
const newUser = await supa
.from('users')
.insert(userData)
.executeAs<User>();
const updated = await supa
.from('users')
.update(updateData)
.eq('id', userId)
.executeAs<User>();
```
## 优势
1. **API简洁**:只需要记住一个方法
2. **类型安全**TypeScript 编译时检查
3. **平台兼容**Android/HarmonyOS 使用真正的类型转换
4. **链式友好**:与现有的链式方法无缝集成
5. **维护性强**:单一方法,减少维护成本
## 注意事项
1. **泛型类型**:确保传入正确的类型参数 `<T>`
2. **错误处理**:检查 `result.error``result.data` 的有效性
3. **性能考虑**Android 平台的类型转换有轻微性能开销
4. **调试模式**:开发时会有转换过程的控制台输出
## 总结
通过采用单一的 `executeAs<T>()` 方法AkSupa 现在提供了:
- 更简洁的API
- 更好的类型安全
- 更一致的使用体验
- 更容易维护的代码
这个设计遵循了"简单就是美"的原则让开发者能够更专注于业务逻辑而不是API的复杂性。

View File

@@ -0,0 +1,194 @@
# AkSupa executeAs<T>() 类型转换功能
## 概述
AkSupa 现在提供简洁的 `executeAs<T>()` 方法,支持链式请求的类型转换功能,可以直接返回指定的类型而不仅仅是 `UTSJSONObject`
## 设计理念
遵循 **简洁性原则**,只提供一个 `executeAs<T>()` 方法来处理所有类型转换需求,因为:
1. **统一API**:所有操作最终都通过 `execute()` 处理,`executeAs<T>()` 是其类型安全版本
2. **链式友好**:可以与所有现有的链式方法无缝组合
3. **易于理解**:只需记住一个方法,降低学习成本
4. **功能完整**覆盖查询、插入、更新、删除、RPC 等所有操作
## 平台兼容性
| 平台 | 支持方式 | 说明 |
|------|----------|------|
| Android (uni-app x 3.90+) | `UTSJSONObject.parse()` | 真正的类型转换 |
| Web | `as T` | 类型断言,编译时类型提示 |
| iOS | `as T` | 类型断言,编译时类型提示 |
| HarmonyOS (4.61+) | `UTSJSONObject.parse()` | 真正的类型转换 |
## 方法签名
```typescript
async executeAs<T>() : Promise<AkReqResponse<T>>
```
## 使用示例
### 1. 定义数据类型
```typescript
export type User = {
id: number;
name: string;
email: string;
created_at: string;
avatar_url?: string;
}
```
### 2. 查询操作
```typescript
// 查询多条记录
const usersResult = await supa
.from('users')
.select('*')
.eq('status', 'active')
.limit(10)
.executeAs<User[]>();
// 查询单条记录
const userResult = await supa
.from('users')
.select('*')
.eq('id', 1)
.single()
.executeAs<User>();
// 复杂查询
const complexQuery = await supa
.from('posts')
.select('*, users!posts_user_id_fkey(*)')
.eq('status', 'published')
.gt('created_at', '2024-01-01')
.order('created_at', { ascending: false })
.limit(20)
.executeAs<Post[]>();
```
### 3. 插入操作
```typescript
const newUser = {
name: '新用户',
email: 'newuser@example.com'
} as UTSJSONObject;
const insertResult = await supa
.from('users')
.insert(newUser)
.executeAs<User[]>();
```
### 4. 更新操作
```typescript
const updateResult = await supa
.from('users')
.update({ name: '更新的名称' } as UTSJSONObject)
.eq('id', 1)
.executeAs<User[]>();
```
### 5. 删除操作
```typescript
const deleteResult = await supa
.from('users')
.delete()
.eq('id', 1)
.executeAs<User[]>();
```
### 6. RPC 调用
```typescript
const rpcResult = await supa
.from('') // RPC 不需要 table
.rpc('get_user_stats', { user_id: 1 } as UTSJSONObject)
.executeAs<{ total_posts: number; total_likes: number }>();
```
## 错误处理
```typescript
try {
const result = await supa
.from('users')
.select('*')
.executeAs<User[]>();
if (result.error) {
console.error('查询失败:', result.error);
return;
}
// 使用类型化的数据
const users = result.data;
if (users != null) {
users.forEach(user => {
// 现在有完整的类型提示
console.log(user.name, user.email);
});
}
} catch (error) {
console.error('请求异常:', error);
}
```
## 向后兼容性
- 原有的 `execute()` 方法依然保持不变,返回 `UTSJSONObject`
- 所有原有的链式方法都继续正常工作
- `executeAs<T>()` 是附加功能,不影响现有代码
## 对比旧版本
### 旧版本(多方法)
```typescript
// 需要记住多个方法
const users = await supa.selectAs<User[]>('users', filter, options);
const inserted = await supa.insertAs<User>('users', data);
const updated = await supa.updateAs<User[]>('users', filter, values);
const deleted = await supa.deleteAs<User[]>('users', filter);
const rpcResult = await supa.rpcAs<Stats>('func_name', params);
```
### 新版本(统一方法)
```typescript
// 只需记住一个 executeAs<T>() 方法
const users = await supa.from('users').select('*').executeAs<User[]>();
const inserted = await supa.from('users').insert(data).executeAs<User>();
const updated = await supa.from('users').update(values).eq('id', 1).executeAs<User[]>();
const deleted = await supa.from('users').delete().eq('id', 1).executeAs<User[]>();
const rpcResult = await supa.from('').rpc('func_name', params).executeAs<Stats>();
```
## 优势
1. **API 简洁**:只需要记住一个 `executeAs<T>()` 方法
2. **链式友好**:与所有现有方法完美组合
3. **类型安全**:编译时检查 + 运行时转换Android
4. **易于维护**:减少重复代码,统一处理逻辑
5. **学习成本低**:从 `execute()``executeAs<T>()` 自然过渡
## 注意事项
1. `UTSJSONObject.parse()` 仅在 Android 3.90+ 和 HarmonyOS 4.61+ 平台支持
2. 其他平台使用类型断言,主要提供编译时类型检查
3. 类型转换失败时会 fallback 到原始数据
4. 建议在生产环境中进行充分的测试
## 技术实现
`executeAs<T>()` 内部:
1. 调用原有的 `execute()` 方法获取结果
2. 在 Android 平台使用 `UTSJSONObject.parse()` 进行类型转换
3. 在其他平台使用类型断言提供类型提示
4. 返回类型化的 `AkReqResponse<T>` 结果

View File

@@ -0,0 +1,126 @@
# AkSupa 类型转换错误修复总结
## 问题描述
在实现 `executeAs<T>()` 和相关类型转换方法时,遇到了以下 UTS 编译错误:
1. **泛型类型参数错误**`Cannot use 'T' as reified type parameter`
2. **类型推断错误**`推断类型是T?可为空的T但预期的是Any`
3. **方法参数错误**`Too many arguments for public open fun select`
4. **属性访问错误**`Unresolved reference: data`
## 修复方案
### 1. 移除泛型类型参数
**问题**UTS 不支持 `UTSJSONObject.parse<T>()` 这种带泛型参数的调用方式。
**解决方案**
-`item.parse<T>()` 改为 `item.parse()`
-`result.data.parse<T>()` 改为 `result.data.parse()`
- 使用类型断言 `as T` 来提供类型提示
```typescript
// 修复前
convertedData = result.data.parse<T>();
// 修复后
convertedData = result.data.parse();
```
### 2. 简化方法签名
**问题**`_convertResponse<T>()` 方法的泛型签名在 UTS 中无法正确处理。
**解决方案**
-`_convertResponse<T>()` 改为 `_convertResponse()`
- 返回类型改为 `AkReqResponse<any>`
- 在调用处使用类型断言 `as AkReqResponse<T>`
```typescript
// 修复前
private _convertResponse<T>(result: AkReqResponse<any>): AkReqResponse<T>
// 修复后
private _convertResponse(result: AkReqResponse<any>): AkReqResponse<any>
```
### 3. 统一类型处理
**问题**:不同平台的类型处理逻辑不一致。
**解决方案**
- Android 平台:使用 `UTSJSONObject.parse()` 进行真正的类型转换
- 其他平台:直接返回原始结果,通过类型断言提供类型提示
```typescript
// Android 平台
convertedData = result.data.parse();
// 其他平台
return result; // 直接返回原始结果
```
### 4. 空值处理优化
**问题**`parse()` 方法可能返回 `null`,需要安全处理。
**解决方案**
- 增加 `null` 检查:`parsed != null ? parsed : item`
- 保持原始数据作为 fallback
```typescript
const parsed = item.parse();
convertedArray.push(parsed != null ? parsed : item);
```
## 修复的方法列表
### AkSupaQueryBuilder 类
-`executeAs<T>()` - 链式查询的类型转换执行
### AkSupa 类
-`selectAs<T>()` - 查询并类型转换
-`insertAs<T>()` - 插入并类型转换
-`updateAs<T>()` - 更新并类型转换
-`deleteAs<T>()` - 删除并类型转换
-`rpcAs<T>()` - RPC调用并类型转换
-`_convertResponse()` - 私有类型转换方法
## 平台兼容性
| 平台 | 处理方式 | 效果 |
|------|----------|------|
| Android | `UTSJSONObject.parse()` | 真正的类型转换 |
| iOS | 类型断言 `as T` | 编译时类型检查 |
| Web | 类型断言 `as T` | 编译时类型检查 |
| HarmonyOS | `UTSJSONObject.parse()` | 真正的类型转换 |
## 使用示例
```typescript
// 现在可以正常使用了
const users = await supa
.from('users')
.select('*')
.executeAs<User[]>();
// 类型安全的访问
users.data?.forEach(user => {
console.log(user.name); // 有完整的类型提示
});
// 直接方法调用
const result = await supa.selectAs<User[]>('users');
```
## 技术要点
1. **UTS 限制**:不支持泛型的 reified 类型参数
2. **类型安全**:通过编译时类型断言提供类型提示
3. **运行时转换**:在支持的平台上进行真正的类型转换
4. **向后兼容**:原有的 `.execute()` 方法保持不变
## 总结
修复后的代码在保持类型安全的同时,完全兼容 UTS 的编译要求。在 Android 和 HarmonyOS 平台上提供真正的类型转换,在其他平台上提供编译时类型检查,为开发者提供了更好的开发体验。

View File

@@ -0,0 +1,56 @@
GET wss://ak3.oulog.com/realtime/v1/websocket?apikey=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q&vsn=1.0.0 HTTP/1.1
Host: ak3.oulog.com
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1
Upgrade: websocket
Origin: http://localhost:5174
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: zh-CN,zh;q=0.9
Sec-WebSocket-Key: dJtuVuI1PWGVjC2E/qCDbQ==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
HTTP/1.1 101 Switching Protocols
Server: nginx
Date: Thu, 03 Jul 2025 04:03:55 GMT
Connection: upgrade
cache-control: max-age=0, private, must-revalidate
sec-websocket-accept: XzR5+Z20bTKH4Ytm23KUTpQmDKE=
upgrade: websocket
Access-Control-Allow-Origin: *
X-Kong-Upstream-Latency: 1
X-Kong-Proxy-Latency: 0
Via: kong/2.8.1
GET wss://ak3.oulog.com/realtime/v1/websocket?apikey=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q&vsn=1.0.0 HTTP/1.1
Host: ak3.oulog.com
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1
Upgrade: websocket
Origin: http://localhost:5173
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: zh-CN,zh;q=0.9
Sec-WebSocket-Key: ZNkWHFYshDAoPrErr9EY9w==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
HTTP/1.1 101 Switching Protocols
Server: nginx
Date: Thu, 03 Jul 2025 07:05:31 GMT
Connection: upgrade
cache-control: max-age=0, private, must-revalidate
sec-websocket-accept: SV8HQ/NAJvS8eQcHVMmIdMRWcb4=
upgrade: websocket
Access-Control-Allow-Origin: *
X-Kong-Upstream-Latency: 3
X-Kong-Proxy-Latency: 1
Via: kong/2.8.1