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 { 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 通过 id 或 auth_id 关联 auth.users.id) const checkRes = await supabase.from('ak_users') .select('*', {}) .or('id.eq.' + userId + ',auth_id.eq.' + userId) .execute() console.log('ensureUserProfile check ak_users:', { status: checkRes.status, hasData: 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) let existingUser: UTSJSONObject const firstItem = (dataList as any[])[0] if (firstItem instanceof UTSJSONObject) { existingUser = firstItem } else { 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: userId, // 始终返回 auth.users.id 作为 Profile 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 } // 用户不存在,创建新用户资料 // 权威字段映射:ak_users.auth_id = auth.uid(),业务主键 id 由数据库自动生成 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') // 默认用户名为邮箱前缀 //hzb newUserData.set('role', 'consumer') // 获取注册时带入的 meta_data 角色信息,在这个端(商家端/管理端)找不到则默认为 merchant let userRole = 'merchant' const metadata = sessionUser.getJSON('user_metadata') ?? sessionUser.getJSON('raw_user_meta_data') if (metadata != null) { const metaRole = metadata.getString('user_role') if (metaRole != null && metaRole.trim() !== '') { userRole = metaRole } } newUserData.set('role', userRole) //cyh // 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('*', {}) .execute() console.log('ensureUserProfile insert ak_users 完整结果:', JSON.stringify(insertRes)) 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') ?? userId, username: newUser.getString('username') ?? email.split('@')[0], 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') ?? userRole, 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 } }