Initial commit of akmon project

This commit is contained in:
2026-01-20 08:04:15 +08:00
commit 77a2bab985
1309 changed files with 343305 additions and 0 deletions

View File

@@ -0,0 +1,287 @@
-- ====================================================================
-- 角色字段统一升级脚本 - Role Field Unification Upgrade
-- ====================================================================
-- 目的:将所有表的 user_type (INTEGER) 字段统一为 role (TEXT) 字段
-- 兼容性Supabase + PostgreSQL 14+
-- 执行顺序:在现有数据库基础上执行
-- ====================================================================
BEGIN;
-- ====================================================================
-- 1. 统一 ml_user_profiles 表的角色字段
-- ====================================================================
-- 1.1 添加新的 role 字段
ALTER TABLE public.ml_user_profiles
ADD COLUMN IF NOT EXISTS role TEXT DEFAULT 'customer';
-- 1.2 将现有 user_type 数据迁移到 role 字段
UPDATE public.ml_user_profiles
SET role = CASE
WHEN user_type = 1 THEN 'customer' -- 消费者
WHEN user_type = 2 THEN 'merchant' -- 商家
WHEN user_type = 3 THEN 'delivery' -- 配送员
WHEN user_type = 4 THEN 'service' -- 客服
WHEN user_type = 5 THEN 'admin' -- 管理员
ELSE 'customer'
END
WHERE role IS NULL OR role = 'customer';
-- 1.3 设置 role 字段约束
ALTER TABLE public.ml_user_profiles
ALTER COLUMN role SET NOT NULL;
ALTER TABLE public.ml_user_profiles
ADD CONSTRAINT IF NOT EXISTS chk_ml_user_role
CHECK (role IN ('customer', 'merchant', 'delivery', 'service', 'admin'));
-- 1.4 更新索引
DROP INDEX IF EXISTS idx_ml_user_profiles_type;
CREATE INDEX IF NOT EXISTS idx_ml_user_profiles_role ON public.ml_user_profiles(role);
-- 1.5 删除旧的 user_type 字段和约束(可选,建议在测试确认后执行)
-- ALTER TABLE public.ml_user_profiles DROP CONSTRAINT IF EXISTS chk_ml_user_type;
-- ALTER TABLE public.ml_user_profiles DROP COLUMN IF EXISTS user_type;
-- ====================================================================
-- 2. 更新相关函数中的字段引用
-- ====================================================================
-- 2.1 更新商家验证函数
CREATE OR REPLACE FUNCTION public.is_verified_merchant(user_uuid UUID)
RETURNS BOOLEAN
LANGUAGE plpgsql
SECURITY DEFINER
AS $$
DECLARE
result BOOLEAN := FALSE;
BEGIN
SELECT (role = 'merchant' AND verification_status = 1) INTO result
FROM public.ml_user_profiles
WHERE user_id = user_uuid;
RETURN COALESCE(result, FALSE);
END;
$$;
-- 2.2 更新用户信息视图
CREATE OR REPLACE VIEW public.vw_user_info AS
SELECT
u.id as user_id,
u.email,
u.username,
u.role as user_role,
u.status as user_status,
u.created_at as user_created_at,
p.cid as profile_cid,
p.role as profile_role,
p.status as profile_status,
p.real_name,
p.avatar_url,
p.phone,
p.credit_score,
p.verification_status,
p.created_at as profile_created_at,
CASE
WHEN p.role = 'customer' THEN '消费者'
WHEN p.role = 'merchant' THEN '商家'
WHEN p.role = 'delivery' THEN '配送员'
WHEN p.role = 'service' THEN '客服'
WHEN p.role = 'admin' THEN '管理员'
ELSE '未知'
END as role_name
FROM public.ak_users u
LEFT JOIN public.ml_user_profiles p ON u.id = p.user_id;
-- ====================================================================
-- 3. 更新 RLS 策略中的角色检查
-- ====================================================================
-- 3.1 更新商品相关策略
DROP POLICY IF EXISTS "商家管理自己的商品" ON public.ml_products;
CREATE POLICY "商家管理自己的商品"
ON public.ml_products
FOR ALL
TO authenticated
USING (
merchant_id = auth.uid()
OR EXISTS (
SELECT 1 FROM public.ml_user_profiles p
WHERE p.user_id = auth.uid()
AND p.role IN ('admin', 'service')
)
);
-- 3.2 更新订单相关策略
DROP POLICY IF EXISTS "配送员查看分配的订单" ON public.ml_orders;
CREATE POLICY "配送员查看分配的订单"
ON public.ml_orders
FOR SELECT
TO authenticated
USING (
delivery_id = auth.uid()
OR EXISTS (
SELECT 1 FROM public.ml_user_profiles p
WHERE p.user_id = auth.uid()
AND p.role IN ('admin', 'service')
)
);
-- 3.3 更新用户资料策略
DROP POLICY IF EXISTS "用户管理自己的资料" ON public.ml_user_profiles;
CREATE POLICY "用户管理自己的资料"
ON public.ml_user_profiles
FOR ALL
TO authenticated
USING (
user_id = auth.uid()
OR EXISTS (
SELECT 1 FROM public.ml_user_profiles p
WHERE p.user_id = auth.uid()
AND p.role IN ('admin', 'service')
)
);
-- ====================================================================
-- 4. 更新字段注释
-- ====================================================================
COMMENT ON COLUMN public.ml_user_profiles.role IS '用户角色customer消费者, merchant商家, delivery配送员, service客服, admin管理员';
-- ====================================================================
-- 5. 创建角色辅助函数
-- ====================================================================
-- 5.1 获取用户角色函数
CREATE OR REPLACE FUNCTION public.get_user_role(user_uuid UUID)
RETURNS TEXT
LANGUAGE plpgsql
SECURITY DEFINER
AS $$
DECLARE
user_role TEXT;
BEGIN
SELECT role INTO user_role
FROM public.ml_user_profiles
WHERE user_id = user_uuid;
RETURN COALESCE(user_role, 'customer');
END;
$$;
-- 5.2 检查用户权限函数
CREATE OR REPLACE FUNCTION public.check_user_permission(user_uuid UUID, required_roles TEXT[])
RETURNS BOOLEAN
LANGUAGE plpgsql
SECURITY DEFINER
AS $$
DECLARE
user_role TEXT;
BEGIN
SELECT role INTO user_role
FROM public.ml_user_profiles
WHERE user_id = user_uuid;
RETURN user_role = ANY(required_roles);
END;
$$;
-- 5.3 角色升级函数(将用户提升为商家等)
CREATE OR REPLACE FUNCTION public.upgrade_user_role(user_uuid UUID, new_role TEXT)
RETURNS BOOLEAN
LANGUAGE plpgsql
SECURITY DEFINER
AS $$
BEGIN
-- 检查新角色是否有效
IF new_role NOT IN ('customer', 'merchant', 'delivery', 'service', 'admin') THEN
RAISE EXCEPTION '无效的角色类型: %', new_role;
END IF;
-- 更新用户角色
UPDATE public.ml_user_profiles
SET role = new_role,
updated_at = CURRENT_TIMESTAMP
WHERE user_id = user_uuid;
-- 同步更新 ak_users 表的 role 字段
UPDATE public.ak_users
SET role = new_role,
updated_at = CURRENT_TIMESTAMP
WHERE id = user_uuid;
RETURN FOUND;
END;
$$;
-- ====================================================================
-- 6. 数据一致性检查
-- ====================================================================
-- 6.1 检查角色字段一致性
DO $$
DECLARE
inconsistent_count INTEGER;
BEGIN
SELECT COUNT(*) INTO inconsistent_count
FROM public.ak_users u
JOIN public.ml_user_profiles p ON u.id = p.user_id
WHERE u.role != p.role;
IF inconsistent_count > 0 THEN
RAISE NOTICE '发现 % 条记录的角色字段不一致,正在同步...', inconsistent_count;
-- 以 ml_user_profiles.role 为准同步到 ak_users.role
UPDATE public.ak_users
SET role = p.role,
updated_at = CURRENT_TIMESTAMP
FROM public.ml_user_profiles p
WHERE ak_users.id = p.user_id
AND ak_users.role != p.role;
RAISE NOTICE '角色字段同步完成';
ELSE
RAISE NOTICE '角色字段一致性检查通过';
END IF;
END;
$$;
-- ====================================================================
-- 7. 创建角色统计视图
-- ====================================================================
CREATE OR REPLACE VIEW public.vw_role_statistics AS
SELECT
role,
COUNT(*) as user_count,
COUNT(*) * 100.0 / SUM(COUNT(*)) OVER() as percentage
FROM public.ml_user_profiles
GROUP BY role
ORDER BY user_count DESC;
COMMIT;
-- ====================================================================
-- 执行验证
-- ====================================================================
-- 检查角色分布
SELECT '角色分布统计:' as info;
SELECT * FROM public.vw_role_statistics;
-- 检查索引
SELECT '索引检查:' as info;
SELECT indexname, indexdef
FROM pg_indexes
WHERE tablename = 'ml_user_profiles'
AND indexname LIKE '%role%';
-- 检查约束
SELECT '约束检查:' as info;
SELECT conname, pg_get_constraintdef(oid) as definition
FROM pg_constraint
WHERE conrelid = 'public.ml_user_profiles'::regclass
AND conname LIKE '%role%';
SELECT '角色字段统一升级完成!' as result;