# 多端用户注册与身份识别实现指南 (Multi-Terminal Registration Guide) 本档说明了如何在当前的 Supabase 架构下实现“消费者端”、“商家端”及“管理端”的统一注册逻辑,并确保用户身份(Role)在入库时能够自动、准确地被识别。 ## 1. 核心架构原理 系统采用 **“前端声明意图 + 后端自动触发”** 的模式: 1. **前端 App**:在调用接口注册时,通过 `raw_user_meta_data` 声明用户的目标角色(如 `consumer` 或 `merchant`)。 2. **Supabase Auth**:接收并存储这些元数据。 3. **数据库触发器 (Trigger)**:在 `auth.users` 产生新记录的一瞬间,由数据库自动读取元数据,并将用户信息连带其正确的角色属性同步到业务表 `ak_users` 中。 --- ## 2. 前端实现步骤 (代码参考) 在各端 App 的注册逻辑中,需在调用 `signUp` 接口时传递 `options.data`。 ### 消费者端 (Consumer App) 在 `pages/user/register.uvue` 中: ```typescript const options = new UTSJSONObject() const metaData = new UTSJSONObject() metaData.set('user_role', 'consumer') // 核心:声明为消费者 options.set('data', metaData) const result = await supa.signUp(email, password, options) ``` ### 商家端 (Merchant App) 在商家端的注册页面中,只需修改 `user_role` 的值: ```typescript metaData.set('user_role', 'merchant') // 核心:声明为商家 ``` --- ## 3. 数据库实现步骤 (SQL 设置) 为了让数据库能够“看碟下菜”,必须在 Supabase SQL Editor 中运行以下脚本,安装/更新智能触发器: ```sql -- 1. 创建或更新处理函数 CREATE OR REPLACE FUNCTION public.handle_new_user() RETURNS trigger AS $$ BEGIN -- 向业务表插入数据,并智能识别角色 INSERT INTO public.ak_users (id, auth_id, email, role, nickname, status) VALUES ( NEW.id, NEW.id, -- 统一使用 Auth ID NEW.email, -- 核心逻辑:读取 metadata 中的 user_role,如果没有传则默认为 'consumer' COALESCE(NEW.raw_user_meta_data->>'user_role', 'consumer'), -- 默认昵称取邮箱前缀 split_part(NEW.email, '@', 1), 1 -- 默认激活状态 ); RETURN NEW; END; $$ LANGUAGE plpgsql SECURITY DEFINER; -- 2. 绑定触发器 DROP TRIGGER IF EXISTS on_auth_user_created ON auth.users; CREATE TRIGGER on_auth_user_created AFTER INSERT ON auth.users FOR EACH ROW EXECUTE FUNCTION public.handle_new_user(); ``` --- ## 4. 三端互不干扰的优势 * **全自动入库**:一旦 SQL 触发器设置完成,前端不再需要手动调用 `ensureUserProfile` 或 `insert` 接口,减少了网络请求和前端报错几率。 * **物理隔离与 RLS 安全**:通过 `ak_users` 表的 RLS 策略(`auth.uid() = id`),确保即使用户通过 API 尝试修改他人数据,也会被数据库直接拦截。 * **统一维护**:所有端的注册逻辑在数据库层面是统一的,未来若需增加新角色(如 `admin_manager`),只需修改触发器逻辑即可,无需大规模重构代码。 --- ## 5. 开发建议 * **强制校验**:在生产环境下,可以在触发器内增加校验逻辑,防止普通用户通过伪造元数据获得 `admin` 角色。 * **日志排查**:如果新用户注册后 `ak_users` 表没有数据,请检查 Supabase 控制台的 `Database -> Logs`,查看触发器执行是否有报错(通常是唯一索引冲突导致)。 --- *最后更新时间:2026-03-10*