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,357 @@
-- 修复 Analytics RPC 函数权限问题
-- 解决无法访问 RPC 函数的问题
-- 1. 首先检查当前函数是否存在
SELECT
routine_name,
routine_type,
data_type,
security_type,
routine_definition
FROM information_schema.routines
WHERE routine_schema = 'public'
AND routine_name IN ('get_teacher_analytics', 'get_top_performers', 'get_chart_data', 'get_recent_activities');
-- 2. 检查当前权限设置
SELECT
routine_name,
grantor,
grantee,
privilege_type,
is_grantable
FROM information_schema.routine_privileges
WHERE routine_schema = 'public'
AND routine_name IN ('get_teacher_analytics', 'get_top_performers', 'get_chart_data', 'get_recent_activities');
-- 3. 删除现有函数(如果存在权限问题)
DROP FUNCTION IF EXISTS public.get_teacher_analytics CASCADE;
DROP FUNCTION IF EXISTS public.get_top_performers CASCADE;
DROP FUNCTION IF EXISTS public.get_chart_data CASCADE;
DROP FUNCTION IF EXISTS public.get_recent_activities CASCADE;
-- 4. 重新创建 get_teacher_analytics 函数(带完整权限)
CREATE OR REPLACE FUNCTION public.get_teacher_analytics(
teacher_id_param uuid DEFAULT NULL,
start_date_param text DEFAULT NULL,
end_date_param text DEFAULT NULL
)
RETURNS jsonb
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
result_data jsonb;
BEGIN
-- 返回模拟统计数据
result_data := jsonb_build_object(
'total_students', 28,
'total_assignments', 12,
'completion_rate', 87.5,
'average_score', 82.3,
'active_classes', 4,
'total_submissions', 285,
'pending_reviews', 15,
'graded_submissions', 270,
'teacher_id', COALESCE(teacher_id_param::text, 'default'),
'date_range', jsonb_build_object(
'start_date', COALESCE(start_date_param, '2024-06-01'),
'end_date', COALESCE(end_date_param, '2024-06-12')
),
'generated_at', now()::text
);
RETURN result_data;
EXCEPTION WHEN OTHERS THEN
RETURN jsonb_build_object(
'error', true,
'message', 'Function execution failed: ' || SQLERRM,
'code', SQLSTATE
);
END;
$$;
-- 5. 重新创建 get_top_performers 函数
CREATE OR REPLACE FUNCTION public.get_top_performers(
teacher_id_param uuid DEFAULT NULL,
start_date_param text DEFAULT NULL,
end_date_param text DEFAULT NULL,
limit_param integer DEFAULT 10
)
RETURNS jsonb
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
result_data jsonb;
BEGIN
-- 返回模拟的优秀学员数据
result_data := jsonb_build_array(
jsonb_build_object(
'student_id', '550e8400-e29b-41d4-a716-446655440001',
'name', '王小明',
'username', 'wangxiaoming',
'avatar_url', null,
'score', 96.8,
'submission_count', 12,
'completion_rate', 100.0,
'class_name', '高三(1)班',
'rank_position', 1
),
jsonb_build_object(
'student_id', '550e8400-e29b-41d4-a716-446655440002',
'name', '张丽华',
'username', 'zhanglihua',
'avatar_url', null,
'score', 94.2,
'submission_count', 11,
'completion_rate', 91.7,
'class_name', '高三(2)班',
'rank_position', 2
),
jsonb_build_object(
'student_id', '550e8400-e29b-41d4-a716-446655440003',
'name', '李强',
'username', 'liqiang',
'avatar_url', null,
'score', 92.5,
'submission_count', 10,
'completion_rate', 83.3,
'class_name', '高三(1)班',
'rank_position', 3
)
);
RETURN result_data;
EXCEPTION WHEN OTHERS THEN
RETURN jsonb_build_object(
'error', true,
'message', 'Function execution failed: ' || SQLERRM,
'code', SQLSTATE
);
END;
$$;
-- 6. 重新创建 get_chart_data 函数
CREATE OR REPLACE FUNCTION public.get_chart_data(
teacher_id_param uuid DEFAULT NULL,
start_date_param text DEFAULT NULL,
end_date_param text DEFAULT NULL,
type_param text DEFAULT 'completion_rate'
)
RETURNS jsonb
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
result_data jsonb;
chart_type text;
BEGIN
chart_type := COALESCE(type_param, 'completion_rate');
-- 根据类型返回不同的图表数据
IF chart_type = 'completion_rate' THEN
result_data := jsonb_build_array(
jsonb_build_object('date_key', '2024-06-01', 'value', 75.5, 'label', '完成率', 'count', 15),
jsonb_build_object('date_key', '2024-06-02', 'value', 82.3, 'label', '完成率', 'count', 18),
jsonb_build_object('date_key', '2024-06-03', 'value', 88.1, 'label', '完成率', 'count', 22),
jsonb_build_object('date_key', '2024-06-04', 'value', 90.5, 'label', '完成率', 'count', 25),
jsonb_build_object('date_key', '2024-06-05', 'value', 87.2, 'label', '完成率', 'count', 23),
jsonb_build_object('date_key', '2024-06-06', 'value', 92.8, 'label', '完成率', 'count', 28),
jsonb_build_object('date_key', '2024-06-07', 'value', 85.6, 'label', '完成率', 'count', 21)
);
ELSIF chart_type = 'score_distribution' THEN
result_data := jsonb_build_array(
jsonb_build_object('range', '90-100', 'label', '优秀', 'count', 25, 'percentage', 18.7),
jsonb_build_object('range', '80-89', 'label', '良好', 'count', 45, 'percentage', 33.6),
jsonb_build_object('range', '70-79', 'label', '中等', 'count', 35, 'percentage', 26.1),
jsonb_build_object('range', '60-69', 'label', '及格', 'count', 20, 'percentage', 14.9),
jsonb_build_object('range', '60以下', 'label', '不及格', 'count', 8, 'percentage', 6.0)
);
ELSIF chart_type = 'submission_trend' THEN
result_data := jsonb_build_array(
jsonb_build_object('date_key', '2024-06-01', 'value', 12, 'label', '提交数量', 'count', 12),
jsonb_build_object('date_key', '2024-06-02', 'value', 15, 'label', '提交数量', 'count', 15),
jsonb_build_object('date_key', '2024-06-03', 'value', 18, 'label', '提交数量', 'count', 18),
jsonb_build_object('date_key', '2024-06-04', 'value', 22, 'label', '提交数量', 'count', 22),
jsonb_build_object('date_key', '2024-06-05', 'value', 19, 'label', '提交数量', 'count', 19),
jsonb_build_object('date_key', '2024-06-06', 'value', 25, 'label', '提交数量', 'count', 25),
jsonb_build_object('date_key', '2024-06-07', 'value', 16, 'label', '提交数量', 'count', 16)
);
ELSE
result_data := '[]'::jsonb;
END IF;
RETURN result_data;
EXCEPTION WHEN OTHERS THEN
RETURN jsonb_build_object(
'error', true,
'message', 'Function execution failed: ' || SQLERRM,
'code', SQLSTATE,
'chart_type', chart_type
);
END;
$$;
-- 7. 重新创建 get_recent_activities 函数
CREATE OR REPLACE FUNCTION public.get_recent_activities(
teacher_id_param uuid DEFAULT NULL,
limit_param integer DEFAULT 20
)
RETURNS jsonb
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
result_data jsonb;
BEGIN
-- 返回模拟的近期活动数据
result_data := jsonb_build_array(
jsonb_build_object(
'activity_id', '550e8400-e29b-41d4-a716-446655440001',
'activity_type', 'assignment_submitted',
'title', '王小明提交了跑步训练作业',
'description', '完成了5公里跑步训练用时25分钟',
'student_name', '王小明',
'assignment_title', '跑步训练',
'activity_time', '2024-06-12T08:30:00Z',
'time_ago', '2小时前'
),
jsonb_build_object(
'activity_id', '550e8400-e29b-41d4-a716-446655440002',
'activity_type', 'assignment_submitted',
'title', '张丽华提交了力量训练作业',
'description', '完成了器械训练,表现优秀',
'student_name', '张丽华',
'assignment_title', '力量训练',
'activity_time', '2024-06-12T07:15:00Z',
'time_ago', '3小时前'
),
jsonb_build_object(
'activity_id', '550e8400-e29b-41d4-a716-446655440003',
'activity_type', 'project_completed',
'title', '李强完成了体能测试项目',
'description', '各项指标达到优秀标准',
'student_name', '李强',
'assignment_title', '体能测试',
'activity_time', '2024-06-12T06:45:00Z',
'time_ago', '4小时前'
)
);
RETURN result_data;
EXCEPTION WHEN OTHERS THEN
RETURN jsonb_build_object(
'error', true,
'message', 'Function execution failed: ' || SQLERRM,
'code', SQLSTATE
);
END;
$$;
-- 8. 设置完整的权限 - 关键步骤!
-- 授权给 authenticated 角色
GRANT EXECUTE ON FUNCTION public.get_teacher_analytics TO authenticated;
GRANT EXECUTE ON FUNCTION public.get_top_performers TO authenticated;
GRANT EXECUTE ON FUNCTION public.get_chart_data TO authenticated;
GRANT EXECUTE ON FUNCTION public.get_recent_activities TO authenticated;
-- 授权给 anon 角色(匿名用户)
GRANT EXECUTE ON FUNCTION public.get_teacher_analytics TO anon;
GRANT EXECUTE ON FUNCTION public.get_top_performers TO anon;
GRANT EXECUTE ON FUNCTION public.get_chart_data TO anon;
GRANT EXECUTE ON FUNCTION public.get_recent_activities TO anon;
-- 授权给 service_role 角色(服务角色)
GRANT EXECUTE ON FUNCTION public.get_teacher_analytics TO service_role;
GRANT EXECUTE ON FUNCTION public.get_top_performers TO service_role;
GRANT EXECUTE ON FUNCTION public.get_chart_data TO service_role;
GRANT EXECUTE ON FUNCTION public.get_recent_activities TO service_role;
-- 9. 确保函数可以被 RPC 调用 - 非常重要!
-- 在 Supabase 中RPC 函数需要特定的权限设置
ALTER FUNCTION public.get_teacher_analytics OWNER TO postgres;
ALTER FUNCTION public.get_top_performers OWNER TO postgres;
ALTER FUNCTION public.get_chart_data OWNER TO postgres;
ALTER FUNCTION public.get_recent_activities OWNER TO postgres;
-- 10. 创建一个测试用户权限的函数
CREATE OR REPLACE FUNCTION public.test_rpc_access()
RETURNS jsonb
LANGUAGE plpgsql
SECURITY DEFINER
AS $$
BEGIN
RETURN jsonb_build_object(
'current_user', current_user,
'session_user', session_user,
'current_role', current_setting('role', true),
'current_database', current_database(),
'current_schema', current_schema(),
'timestamp', now(),
'message', 'RPC access test successful'
);
END;
$$;
-- 授权测试函数
GRANT EXECUTE ON FUNCTION public.test_rpc_access TO authenticated;
GRANT EXECUTE ON FUNCTION public.test_rpc_access TO anon;
GRANT EXECUTE ON FUNCTION public.test_rpc_access TO service_role;
-- 11. 验证所有函数和权限
SELECT
r.routine_name,
r.routine_type,
r.data_type,
r.security_type,
COALESCE(
(SELECT string_agg(p.grantee, ', ')
FROM information_schema.routine_privileges p
WHERE p.routine_name = r.routine_name
AND p.routine_schema = r.routine_schema),
'No explicit grants'
) as granted_to
FROM information_schema.routines r
WHERE r.routine_schema = 'public'
AND r.routine_name IN ('get_teacher_analytics', 'get_top_performers', 'get_chart_data', 'get_recent_activities', 'test_rpc_access')
ORDER BY r.routine_name;
-- 12. 测试函数调用
DO $$
DECLARE
test_result jsonb;
BEGIN
-- 测试权限检查函数
SELECT public.test_rpc_access() INTO test_result;
RAISE NOTICE '✅ test_rpc_access 结果: %', test_result;
-- 测试 get_teacher_analytics
SELECT public.get_teacher_analytics() INTO test_result;
RAISE NOTICE '✅ get_teacher_analytics 测试: %', (test_result->>'total_students');
-- 测试 get_top_performers
SELECT public.get_top_performers() INTO test_result;
RAISE NOTICE '✅ get_top_performers 测试: % 条记录', jsonb_array_length(test_result);
-- 测试 get_chart_data
SELECT public.get_chart_data() INTO test_result;
RAISE NOTICE '✅ get_chart_data 测试: % 条记录', jsonb_array_length(test_result);
-- 测试 get_recent_activities
SELECT public.get_recent_activities() INTO test_result;
RAISE NOTICE '✅ get_recent_activities 测试: % 条记录', jsonb_array_length(test_result);
RAISE NOTICE '🎉 所有函数权限设置完成并测试通过!';
END;
$$;
-- 13. 显示完成信息
SELECT
'🎉 Analytics RPC Functions with Full Permissions Deployed!' as status,
'Functions are now accessible via RPC calls' as message,
'authenticated, anon, service_role roles have access' as permissions,
now() as deployed_at;