consumer模块完成度95%,实现数据库多端注册登录,优化安卓端小程序bug

This commit is contained in:
cyh666666
2026-03-10 17:08:20 +08:00
parent 2262d1bfd9
commit 5517c93666
1010 changed files with 1688 additions and 4919 deletions

View File

@@ -703,14 +703,17 @@ export class AkSupa {
if (this.apikey == null || this.apikey.trim() === '' || this.apikey === 'your-anon-key') {
throw new Error('Supabase 配置错误:请在 ak/config.uts 中设置 SUPA_KEY当前为占位符');
}
const headers = new UTSJSONObject()
headers.set('apikey', this.apikey)
headers.set('Content-Type', 'application/json')
const reqData = new UTSJSONObject()
reqData.set('email', email)
reqData.set('password', password)
const res = await AkReq.request({
url: this.baseUrl + '/auth/v1/token?grant_type=password',
method: 'POST',
headers: {
apikey: this.apikey,
'Content-Type': 'application/json'
} as UTSJSONObject,
data: { email, password } as UTSJSONObject,
headers: headers,
data: reqData,
contentType: 'application/json'
}, false);
// 如果响应不是 2xx例如 401提取后端错误信息并抛出便于上层显示具体原因
@@ -720,7 +723,14 @@ export class AkSupa {
try {
if (res.data != null) {
const obj = new UTSJSONObject(res.data);
msg = obj.getString('message') ?? obj.getString('error') ?? obj.getString('msg') ?? obj.getString('description') ?? obj.getString('error_description') ?? msg;
const rawMsg = obj.getString('message') ?? obj.getString('error') ?? obj.getString('msg') ?? obj.getString('description') ?? obj.getString('error_description') ?? '';
// 核心修复:在这里拦截英文错误并转换为中文
if (rawMsg.includes('Invalid login credentials')) {
msg = '用户名或密码错误';
} else if (rawMsg != '') {
msg = rawMsg;
}
}
} catch (e) {
// ignore
@@ -763,15 +773,26 @@ export class AkSupa {
};
}
async signUp(email : string, password : string) : Promise<UTSJSONObject> {
async signUp(email : string, password : string, options : UTSJSONObject | null = null) : Promise<UTSJSONObject> {
const headers = new UTSJSONObject()
headers.set('apikey', this.apikey)
headers.set('Content-Type', 'application/json')
const data = new UTSJSONObject()
data.set('email', email)
data.set('password', password)
if (options != null) {
const dataField = options.getJSON('data')
if (dataField != null) {
data.set('data', dataField)
}
}
const res = await AkReq.request({
url: this.baseUrl + '/auth/v1/signup',
method: 'POST',
headers: {
apikey: this.apikey,
'Content-Type': 'application/json'
} as UTSJSONObject,
data: { email, password } as UTSJSONObject,
headers: headers,
data: data,
contentType: 'application/json'
}, false);
return res.data as UTSJSONObject;
@@ -786,11 +807,10 @@ export class AkSupa {
*/
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 headers = new UTSJSONObject()
headers.set('apikey', this.apikey)
headers.set('Content-Type', 'application/json')
headers.set('Authorization', `Bearer ${AkReq.getToken() ?? ''}`)
let params : string[] = [];
if (options != null) {
if (options.columns != null && !(options.columns == "")) params.push('select=' + encodeURIComponent(options.columns ?? ""));
@@ -876,20 +896,17 @@ async select_uts(table : string, filter ?: UTSJSONObject | null, options ?: AkSu
*/
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;
const headers = new UTSJSONObject()
headers.set('apikey', this.apikey)
headers.set('Content-Type', 'application/json')
headers.set('Authorization', `Bearer ${AkReq.getToken() ?? ''}`)
headers.set('Prefer', 'return=representation')
// 如果是数组,直接传递;如果是单个对象,也直接传递
// Supabase REST API 原生支持两种格式
let reqOptions : AkReqOptions = {
url,
method: 'POST',
headers,
data: row, // 可以是单个对象或数组
data: row,
contentType: 'application/json'
};
return await this.requestWithAutoRefresh(reqOptions);
@@ -907,12 +924,11 @@ async update(table : string, filter : string | null, values : UTSJSONObject) : P
if (filter!=null && filter !== "") {
url += '?' + filter;
}
const headers = {
apikey: this.apikey,
'Content-Type': 'application/json',
Authorization: `Bearer ${AkReq.getToken() ?? ''}`,
Prefer: 'return=representation'
} as UTSJSONObject;
const headers = new UTSJSONObject()
headers.set('apikey', this.apikey)
headers.set('Content-Type', 'application/json')
headers.set('Authorization', `Bearer ${AkReq.getToken() ?? ''}`)
headers.set('Prefer', 'return=representation')
let reqOptions : AkReqOptions = {
url,
method: 'PATCH',
@@ -934,12 +950,11 @@ async delete(table : string, filter : string | null) : Promise<AkReqResponse<any
if (filter!=null && filter !== "") {
url += '?' + filter;
}
const headers = {
apikey: this.apikey,
'Content-Type': 'application/json',
Authorization: `Bearer ${AkReq.getToken() ?? ''}`,
Prefer: 'return=representation'
} as UTSJSONObject;
const headers = new UTSJSONObject()
headers.set('apikey', this.apikey)
headers.set('Content-Type', 'application/json')
headers.set('Authorization', `Bearer ${AkReq.getToken() ?? ''}`)
headers.set('Prefer', 'return=representation')
let reqOptions : AkReqOptions = {
url,
method: 'DELETE',
@@ -956,17 +971,16 @@ async delete(table : string, filter : string | null) : Promise<AkReqResponse<any
* @returns AkReqResponse<any>
*/
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;
const url = this.baseUrl + '/rest/v1/rpc/' + functionName;
const headers = new UTSJSONObject()
headers.set('apikey', this.apikey)
headers.set('Content-Type', 'application/json')
headers.set('Authorization', `Bearer ${AkReq.getToken() ?? ''}`)
let reqOptions : AkReqOptions = {
url,
method: 'POST',
headers,
data: params ?? {},
data: params ?? new UTSJSONObject(),
contentType: 'application/json'
};
return await this.requestWithAutoRefresh(reqOptions);
@@ -998,14 +1012,16 @@ async delete(table : string, filter : string | null) : Promise<AkReqResponse<any
async refreshSession() : Promise<boolean> {
if (this.session == null || this.session?.refresh_token == null) return false;
try {
const headers = new UTSJSONObject()
headers.set('apikey', this.apikey)
headers.set('Content-Type', 'application/json')
const data = new UTSJSONObject()
data.set('refresh_token', this.session?.refresh_token)
const res = await AkReq.request({
url: this.baseUrl + '/auth/v1/token?grant_type=refresh_token',
method: 'POST',
headers: {
apikey: this.apikey,
'Content-Type': 'application/json'
} as UTSJSONObject,
data: { refresh_token: this.session?.refresh_token } as UTSJSONObject,
headers: headers,
data: data,
contentType: 'application/json'
}, false);
if (res.status == 200 && (res.data != null)) {
@@ -1034,6 +1050,23 @@ async delete(table : string, filter : string | null) : Promise<AkReqResponse<any
}
}
async updateUserMetadata(metadata: UTSJSONObject): Promise<UTSJSONObject> {
const headers = new UTSJSONObject()
headers.set('apikey', this.apikey)
headers.set('Content-Type', 'application/json')
headers.set('Authorization', `Bearer ${AkReq.getToken() ?? ''}`)
const data = new UTSJSONObject()
data.set('data', metadata)
const res = await AkReq.request({
url: this.baseUrl + '/auth/v1/user',
method: 'PUT',
headers: headers,
data: data,
contentType: 'application/json'
}, false);
return res.data as UTSJSONObject;
}
// AkSupa类内新增自动刷新封装
async requestWithAutoRefresh(reqOptions : AkReqOptions, isRetry = false) : Promise<AkReqResponse<any>> {
let res = await AkReq.request(reqOptions, false);