consumer模块完成度95%,实现数据库多端注册登录,优化安卓端小程序bug
This commit is contained in:
102
utils/sapi copy.uts
Normal file
102
utils/sapi copy.uts
Normal file
@@ -0,0 +1,102 @@
|
||||
import supabase, { supaReady } from '@/components/supadb/aksupainstance.uts'
|
||||
import type { UserProfile } from '@/types/mall-types.uts'
|
||||
|
||||
/**
|
||||
* 确保用户资料存在,如果不存在则创建基础资料
|
||||
* @param sessionUser 会话用户对象 (UTSJSONObject)
|
||||
* @returns 创建的用户资料,如果创建失败则返回 null
|
||||
*/
|
||||
export async function ensureUserProfile(sessionUser: UTSJSONObject): Promise<UserProfile | null> {
|
||||
try {
|
||||
await supaReady
|
||||
|
||||
// 从 sessionUser 中获取用户ID和邮箱
|
||||
const userId = sessionUser.getString('id')
|
||||
const email = sessionUser.getString('email') ?? ''
|
||||
|
||||
if (userId == null || userId === '') {
|
||||
console.error('无法获取用户ID')
|
||||
return null
|
||||
}
|
||||
|
||||
// 检查用户是否已存在(ak_users 通过 auth_id 关联 auth.users.id)
|
||||
const checkRes = await supabase.from('ak_users')
|
||||
.select('*', {})
|
||||
.eq('auth_id', userId)
|
||||
.single()
|
||||
.execute()
|
||||
|
||||
console.log('ensureUserProfile check ak_users:', {
|
||||
status: checkRes.status,
|
||||
hasData: checkRes.data != null
|
||||
})
|
||||
|
||||
if (checkRes.status >= 200 && checkRes.status < 300 && checkRes.data != null) {
|
||||
// 用户已存在,返回现有资料(H5 下 checkRes.data 可能是 plain object,不一定是 UTSJSONObject)
|
||||
const data = checkRes.data
|
||||
let existingUser: UTSJSONObject
|
||||
if (data instanceof UTSJSONObject) {
|
||||
existingUser = data
|
||||
} else {
|
||||
existingUser = new UTSJSONObject(data)
|
||||
}
|
||||
return {
|
||||
id: existingUser.getString('id') ?? '',
|
||||
username: existingUser.getString('username') ?? '',
|
||||
email: existingUser.getString('email') ?? email,
|
||||
gender: existingUser.getString('gender'),
|
||||
birthday: existingUser.getString('birthday'),
|
||||
height_cm: existingUser.getNumber('height_cm'),
|
||||
weight_kg: existingUser.getNumber('weight_kg'),
|
||||
bio: existingUser.getString('bio'),
|
||||
avatar_url: existingUser.getString('avatar_url'),
|
||||
preferred_language: existingUser.getString('preferred_language'),
|
||||
role: existingUser.getString('role') ?? 'consumer',
|
||||
created_at: existingUser.getString('created_at'),
|
||||
updated_at: existingUser.getString('updated_at')
|
||||
} as UserProfile
|
||||
}
|
||||
|
||||
// 用户不存在,创建新用户资料
|
||||
const newUserData = new UTSJSONObject()
|
||||
newUserData.set('id', userId)
|
||||
newUserData.set('email', email)
|
||||
newUserData.set('username', email.split('@')[0] ?? 'user') // 默认用户名为邮箱前缀
|
||||
|
||||
const insertRes = await supabase.from('ak_users')
|
||||
.insert(newUserData)
|
||||
.select('*', {})
|
||||
.single()
|
||||
.execute()
|
||||
|
||||
console.log('ensureUserProfile insert ak_users status:', insertRes.status)
|
||||
|
||||
if (insertRes.status >= 200 && insertRes.status < 300 && insertRes.data != null) {
|
||||
const rawData = insertRes.data
|
||||
const newUser = (rawData instanceof UTSJSONObject)
|
||||
? (rawData as UTSJSONObject)
|
||||
: new UTSJSONObject(rawData)
|
||||
return {
|
||||
id: newUser.getString('id') ?? '',
|
||||
username: newUser.getString('username') ?? '',
|
||||
email: newUser.getString('email') ?? email,
|
||||
gender: newUser.getString('gender'),
|
||||
birthday: newUser.getString('birthday'),
|
||||
height_cm: newUser.getNumber('height_cm'),
|
||||
weight_kg: newUser.getNumber('weight_kg'),
|
||||
bio: newUser.getString('bio'),
|
||||
avatar_url: newUser.getString('avatar_url'),
|
||||
preferred_language: newUser.getString('preferred_language'),
|
||||
role: newUser.getString('role') ?? 'consumer',
|
||||
created_at: newUser.getString('created_at'),
|
||||
updated_at: newUser.getString('updated_at')
|
||||
} as UserProfile
|
||||
} else {
|
||||
console.error('创建用户资料失败:', insertRes.status)
|
||||
return null
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('ensureUserProfile 异常:', error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -19,11 +19,10 @@ export async function ensureUserProfile(sessionUser: UTSJSONObject): Promise<Use
|
||||
return null
|
||||
}
|
||||
|
||||
// 检查用户是否已存在(ak_users 通过 auth_id 关联 auth.users.id)
|
||||
// 检查用户是否已存在(ak_users 通过 id 或 auth_id 关联 auth.users.id)
|
||||
const checkRes = await supabase.from('ak_users')
|
||||
.select('*', {})
|
||||
.eq('auth_id', userId)
|
||||
.single()
|
||||
.or('id.eq.' + userId + ',auth_id.eq.' + userId)
|
||||
.execute()
|
||||
|
||||
console.log('ensureUserProfile check ak_users:', {
|
||||
@@ -31,17 +30,53 @@ export async function ensureUserProfile(sessionUser: UTSJSONObject): Promise<Use
|
||||
hasData: checkRes.data != null
|
||||
})
|
||||
|
||||
if (checkRes.status >= 200 && checkRes.status < 300 && checkRes.data != null) {
|
||||
const dataList = checkRes.data
|
||||
if (checkRes.status >= 200 && checkRes.status < 300 && dataList != null && (dataList as any[]).length > 0) {
|
||||
// 用户已存在,返回现有资料(H5 下 checkRes.data 可能是 plain object,不一定是 UTSJSONObject)
|
||||
const data = checkRes.data
|
||||
let existingUser: UTSJSONObject
|
||||
if (data instanceof UTSJSONObject) {
|
||||
existingUser = data
|
||||
const firstItem = (dataList as any[])[0]
|
||||
if (firstItem instanceof UTSJSONObject) {
|
||||
existingUser = firstItem
|
||||
} else {
|
||||
existingUser = new UTSJSONObject(data)
|
||||
existingUser = new UTSJSONObject(firstItem)
|
||||
}
|
||||
|
||||
const currentRole = existingUser.getString('role')
|
||||
const currentAuthId = existingUser.getString('auth_id')
|
||||
|
||||
// 【强力修复逻辑】如果 role 是 student 或者 auth_id 为空,进行 upsert 修复
|
||||
if (currentRole == 'student' || currentAuthId == null || currentAuthId == '') {
|
||||
console.log('检测到旧数据异常,正在修复角色或关联ID...')
|
||||
const updateData = new UTSJSONObject()
|
||||
// updateData.set('id', userId) // update 场景不需要传 ID 在 body 里,通常作为 filter
|
||||
updateData.set('auth_id', userId)
|
||||
updateData.set('role', 'consumer')
|
||||
|
||||
await supabase.from('ak_users')
|
||||
.update(updateData)
|
||||
.eq('id', userId)
|
||||
.execute()
|
||||
|
||||
// 同步 Auth 元数据
|
||||
try {
|
||||
const meta = new UTSJSONObject()
|
||||
meta.set('user_role', 'consumer')
|
||||
await supabase.updateUserMetadata(meta)
|
||||
} catch (e) {
|
||||
console.warn('同步 Auth 元数据失败:', e)
|
||||
}
|
||||
|
||||
// 返回修复后的对象
|
||||
return {
|
||||
id: userId,
|
||||
username: existingUser.getString('username') ?? email.split('@')[0],
|
||||
email: existingUser.getString('email') ?? email,
|
||||
role: 'consumer'
|
||||
} as UserProfile
|
||||
}
|
||||
|
||||
return {
|
||||
id: existingUser.getString('id') ?? '',
|
||||
id: userId, // 始终返回 auth.users.id 作为 Profile ID
|
||||
username: existingUser.getString('username') ?? '',
|
||||
email: existingUser.getString('email') ?? email,
|
||||
gender: existingUser.getString('gender'),
|
||||
@@ -60,25 +95,51 @@ export async function ensureUserProfile(sessionUser: UTSJSONObject): Promise<Use
|
||||
// 用户不存在,创建新用户资料
|
||||
const newUserData = new UTSJSONObject()
|
||||
newUserData.set('id', userId)
|
||||
newUserData.set('auth_id', userId) // 确保 auth_id 被存储,解决登录查不到 Profile 的问题
|
||||
newUserData.set('email', email)
|
||||
newUserData.set('username', email.split('@')[0] ?? 'user') // 默认用户名为邮箱前缀
|
||||
newUserData.set('role', 'consumer') // 强制设置为消费者角色
|
||||
newUserData.set('created_at', new Date().toISOString()) // 手动设置创建时间
|
||||
|
||||
// 尝试同步更新 Auth 元数据,确保以后登录生成的 JWT 中角色也为 consumer
|
||||
try {
|
||||
const meta = new UTSJSONObject()
|
||||
meta.set('user_role', 'consumer')
|
||||
await supabase.updateUserMetadata(meta)
|
||||
} catch (e) {
|
||||
console.warn('同步 Auth 元数据失败 (非致命):', e)
|
||||
}
|
||||
|
||||
console.log('准备插入 ak_users, 目标 ID:', userId)
|
||||
console.log('正在执行 insert 资料:', JSON.stringify(newUserData))
|
||||
const insertRes = await supabase.from('ak_users')
|
||||
.insert(newUserData)
|
||||
.select('*', {})
|
||||
.single()
|
||||
.execute()
|
||||
|
||||
console.log('ensureUserProfile insert ak_users status:', insertRes.status)
|
||||
console.log('ensureUserProfile insert ak_users 完整结果:', JSON.stringify(insertRes))
|
||||
|
||||
if (insertRes.status >= 200 && insertRes.status < 300 && insertRes.data != null) {
|
||||
const rawData = insertRes.data
|
||||
if (insertRes.status >= 200 && insertRes.status < 300) {
|
||||
const dataList = (insertRes.data != null) ? (insertRes.data as any[]) : []
|
||||
const rawData = dataList.length > 0 ? dataList[0] : null
|
||||
|
||||
if (rawData == null) {
|
||||
console.log('ensureUserProfile: 资料插入操作已完成(200),但未返回数据(可能是 RLS 限制)');
|
||||
return {
|
||||
id: userId,
|
||||
username: email.split('@')[0] ?? 'user',
|
||||
email: email,
|
||||
role: 'consumer',
|
||||
created_at: newUserData.getString('created_at')
|
||||
} as UserProfile
|
||||
}
|
||||
|
||||
const newUser = (rawData instanceof UTSJSONObject)
|
||||
? (rawData as UTSJSONObject)
|
||||
: new UTSJSONObject(rawData)
|
||||
return {
|
||||
id: newUser.getString('id') ?? '',
|
||||
username: newUser.getString('username') ?? '',
|
||||
id: newUser.getString('id') ?? userId,
|
||||
username: newUser.getString('username') ?? email.split('@')[0],
|
||||
email: newUser.getString('email') ?? email,
|
||||
gender: newUser.getString('gender'),
|
||||
birthday: newUser.getString('birthday'),
|
||||
|
||||
Reference in New Issue
Block a user