feat(admin): complete integration of auth, delivery, and system infrastructure modules

This commit is contained in:
comlibmb
2026-02-18 23:30:39 +08:00
parent 7b27694690
commit 5d00e3d74e
37 changed files with 2830 additions and 1075 deletions

View File

@@ -0,0 +1,24 @@
-- =====================================================================================
-- Schema: 系统配置表
-- 位置docs/sql/10_schema/admin/ml_system_configs_v1.sql
-- 对象类型TABLE
-- 版本v1
-- 说明:统一存储系统、应用、维护等模块的 Key-Value 配置项
-- =====================================================================================
CREATE TABLE IF NOT EXISTS public.ml_system_configs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
config_key TEXT UNIQUE NOT NULL,
config_value JSONB NOT NULL DEFAULT '{}'::jsonb,
description TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- 索引
CREATE INDEX IF NOT EXISTS idx_system_configs_key ON public.ml_system_configs (config_key);
-- 注释
COMMENT ON TABLE public.ml_system_configs IS '系统全局配置表';
COMMENT ON COLUMN public.ml_system_configs.config_key IS '配置唯一标识键';
COMMENT ON COLUMN public.ml_system_configs.config_value IS '配置内容 (JSONB)';

View File

@@ -0,0 +1,51 @@
-- =====================================================================================
-- Schema: 物流设置 (Delivery) 核心表
-- 位置docs/sql/10_schema/delivery/ak_delivery_system_v1.sql
-- 对象类型TABLE
-- 版本v1
-- 说明:包含配送员管理表、提货点/核销点管理表
-- =====================================================================================
-- 1. 配送员管理表
CREATE TABLE IF NOT EXISTS public.ml_delivery_staff (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
uid UUID REFERENCES public.ak_users(id) ON DELETE SET NULL, -- 关联用户(可选)
nickname TEXT NOT NULL, -- 配送员名称
avatar TEXT, -- 头像
phone TEXT NOT NULL, -- 手机号
status SMALLINT NOT NULL DEFAULT 1, -- 状态: 1-启用, 0-禁用
is_active BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- 2. 提货点/核销点管理表
CREATE TABLE IF NOT EXISTS public.ml_delivery_stations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL, -- 提货点名称
phone TEXT NOT NULL, -- 联系电话
address TEXT NOT NULL, -- 详细地址
image TEXT, -- 门店图片
lng NUMERIC(10,7), -- 经度
lat NUMERIC(10,7), -- 纬度
status SMALLINT NOT NULL DEFAULT 1, -- 状态: 1-显示, 0-隐藏
sort_order INTEGER DEFAULT 0,
business_hours JSONB, -- 营业时间 (如: {"start": "09:00", "end": "21:00"})
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- 索引
CREATE INDEX IF NOT EXISTS idx_delivery_staff_phone ON public.ml_delivery_staff(phone);
CREATE INDEX IF NOT EXISTS idx_delivery_stations_status ON public.ml_delivery_stations(status);
-- 注释
COMMENT ON TABLE public.ml_delivery_staff IS '配送员信息表';
COMMENT ON TABLE public.ml_delivery_stations IS '提货点/核销点信息表';

View File

@@ -0,0 +1,69 @@
-- =====================================================================================
-- Schema: 权限管理 (RBAC) 核心表
-- 位置docs/sql/10_schema/user/ak_auth_system_v1.sql
-- 对象类型TABLE
-- 版本v1
-- 说明:包含角色表、权限/菜单表及用户角色关联表
-- =====================================================================================
-- 1. 角色表
CREATE TABLE IF NOT EXISTS public.ak_roles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL UNIQUE, -- 角色名称 (如: 超级管理员)
code TEXT NOT NULL UNIQUE, -- 角色编码 (如: super_admin)
description TEXT, -- 角色描述
is_active BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- 2. 权限/菜单表
CREATE TABLE IF NOT EXISTS public.ak_permissions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
parent_id UUID REFERENCES public.ak_permissions(id) ON DELETE CASCADE,
name TEXT NOT NULL, -- 权限/菜单名称
code TEXT NOT NULL UNIQUE, -- 权限编码 (如: order_view)
type TEXT NOT NULL, -- 类型: menu(菜单), button(按钮/接口)
path TEXT, -- 前端路由路径 (仅针对 menu)
icon TEXT, -- 图标
sort_order INTEGER DEFAULT 0, -- 排序
is_visible BOOLEAN DEFAULT TRUE, -- 菜单是否在左侧可见
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- 3. 用户-角色关联表
-- 映射管理员 (ak_users) 与角色
CREATE TABLE IF NOT EXISTS public.ak_admin_roles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES public.ak_users(id) ON DELETE CASCADE,
role_id UUID NOT NULL REFERENCES public.ak_roles(id) ON DELETE CASCADE,
assigned_at TIMESTAMPTZ NOT NULL DEFAULT now(),
assigned_by UUID REFERENCES public.ak_users(id),
UNIQUE(user_id, role_id)
);
-- 4. 角色-权限关联表
CREATE TABLE IF NOT EXISTS public.ak_role_permissions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
role_id UUID NOT NULL REFERENCES public.ak_roles(id) ON DELETE CASCADE,
permission_id UUID NOT NULL REFERENCES public.ak_permissions(id) ON DELETE CASCADE,
UNIQUE(role_id, permission_id)
);
-- 索引
CREATE INDEX IF NOT EXISTS idx_permissions_parent_id ON public.ak_permissions(parent_id);
CREATE INDEX IF NOT EXISTS idx_admin_roles_user_id ON public.ak_admin_roles(user_id);
CREATE INDEX IF NOT EXISTS idx_role_permissions_role_id ON public.ak_role_permissions(role_id);
-- 注释
COMMENT ON TABLE public.ak_roles IS '后台管理角色表';
COMMENT ON TABLE public.ak_permissions IS '功能权限与菜单定义表';
COMMENT ON TABLE public.ak_admin_roles IS '管理员角色分配表';
COMMENT ON TABLE public.ak_role_permissions IS '角色权限映射表';

View File

@@ -0,0 +1,17 @@
-- =====================================================================================
-- RLS: 系统配置表安全策略
-- 位置docs/sql/20_rls/admin/ml_system_configs_rls_v1.sql
-- 对象类型RLS 策略
-- 版本v1
-- 说明:允许所有登录用户读取配置;管理端全量操作通过 RPC (SECURITY DEFINER) 执行
-- =====================================================================================
-- 启用 RLS
ALTER TABLE public.ml_system_configs ENABLE ROW LEVEL SECURITY;
-- 1. 允许所有登录用户读取配置 (用于前端业务逻辑判断)
DROP POLICY IF EXISTS system_configs_select_policy ON public.ml_system_configs;
CREATE POLICY system_configs_select_policy ON public.ml_system_configs
FOR SELECT TO authenticated USING (true);
-- 管理端全量管理将通过 SECURITY DEFINER 的 RPC 接口执行,此处不再额外开放直接表操作

View File

@@ -0,0 +1,17 @@
-- =====================================================================================
-- RLS: 权限管理 (Auth) 安全策略
-- 位置docs/sql/20_rls/auth/ak_auth_rls_v1.sql
-- 对象类型RLS 策略
-- 版本v1
-- 说明:角色与权限表默认不对外开放,全量管理通过 SECURITY DEFINER RPC 执行
-- =====================================================================================
-- 启用 RLS
ALTER TABLE public.ak_roles ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.ak_permissions ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.ak_admin_roles ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.ak_role_permissions ENABLE ROW LEVEL SECURITY;
-- 默认策略NO DIRECT ACCESS
-- 所有的查询和修改均建议通过 docs/sql/30_rpc/auth/ 下的专用管理接口完成
-- 这样可以确保鉴权逻辑与 ak_users.role 强制绑定,且具备审计能力

View File

@@ -0,0 +1,24 @@
-- =====================================================================================
-- RLS: 物流设置 (Delivery) 安全策略
-- 位置docs/sql/20_rls/delivery/ak_delivery_rls_v1.sql
-- 对象类型RLS 策略
-- 版本v1
-- 说明:配送员表管理端私有;提货点表消费者端只读
-- =====================================================================================
-- 启用 RLS
ALTER TABLE public.ml_delivery_staff ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.ml_delivery_stations ENABLE ROW LEVEL SECURITY;
-- 1. 配送员表策略:默认不开放直接访问
-- 全量管理通过 docs/sql/30_rpc/delivery/ 下的 RPC 执行
-- 2. 提货点表策略:允许消费者端只读(用于地图展示和下单选择)
DROP POLICY IF EXISTS delivery_stations_select_active ON public.ml_delivery_stations;
CREATE POLICY delivery_stations_select_active
ON public.ml_delivery_stations
FOR SELECT
TO anon, authenticated
USING (status = 1);
-- 管理端全量管理将通过 SECURITY DEFINER 的 RPC 接口执行

View File

@@ -0,0 +1,59 @@
-- =====================================================================================
-- Admin 统计功能 - 获取全站核心指标概览 RPC
-- 位置docs/sql/30_rpc/admin/rpc_admin_get_overall_stats_v1.sql
-- 对象类型RPC 函数SECURITY DEFINER
-- 版本v1
-- 说明:一次性聚合查询销售、订单、用户及商品的核心统计指标
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.rpc_admin_get_overall_stats()
RETURNS JSONB
SECURITY DEFINER
SET search_path = public
LANGUAGE plpgsql
AS $$
DECLARE
v_stats JSONB;
v_today_start TIMESTAMPTZ := CURRENT_DATE;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE auth_id = auth.uid() AND role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 聚合统计
WITH totals AS (
SELECT
(SELECT COALESCE(SUM(paid_amount), 0) FROM public.ml_orders WHERE paid = 1) as total_sales,
(SELECT COUNT(*) FROM public.ml_orders WHERE paid = 1) as total_orders,
(SELECT COUNT(*) FROM public.ak_users) as total_users,
(SELECT COUNT(*) FROM public.ml_products) as total_products
),
today_stats AS (
SELECT
(SELECT COALESCE(SUM(paid_amount), 0) FROM public.ml_orders WHERE paid = 1 AND created_at >= v_today_start) as today_sales,
(SELECT COUNT(*) FROM public.ml_orders WHERE paid = 1 AND created_at >= v_today_start) as today_orders,
(SELECT COUNT(*) FROM public.ak_users WHERE created_at >= v_today_start) as today_new_users
),
pending_tasks AS (
SELECT
(SELECT COUNT(*) FROM public.ml_orders WHERE paid = 1 AND order_status = 1) as pending_delivery,
(SELECT COUNT(*) FROM public.ml_product_skus WHERE stock <= 10) as stock_warning, -- 假设库存小于10为预警
(SELECT COUNT(*) FROM public.ml_extract WHERE status = 0) as pending_extract
)
SELECT jsonb_build_object(
'totals', (SELECT row_to_json(totals.*) FROM totals),
'today', (SELECT row_to_json(today_stats.*) FROM today_stats),
'pending', (SELECT row_to_json(pending_tasks.*) FROM pending_tasks)
) INTO v_stats;
RETURN v_stats;
END;
$$;
-- 授权
REVOKE ALL ON FUNCTION public.rpc_admin_get_overall_stats() FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_get_overall_stats() TO authenticated;

View File

@@ -0,0 +1,46 @@
-- =====================================================================================
-- Admin 系统维护 - 获取服务器环境信息 RPC
-- 位置docs/sql/30_rpc/admin/rpc_admin_get_system_info_v1.sql
-- 对象类型RPC 函数SECURITY DEFINER
-- 版本v1
-- 说明:获取服务器操作系统、数据库版本及运行环境信息
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.rpc_admin_get_system_info()
RETURNS JSONB
SECURITY DEFINER
SET search_path = public
LANGUAGE plpgsql
AS $$
DECLARE
v_info JSONB;
v_db_version TEXT;
BEGIN
-- 1. 权限检查 (仅管理员)
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE auth_id = auth.uid() AND role = 'admin'
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 获取数据库版本
SELECT version() INTO v_db_version;
-- 3. 构建返回信息
v_info := jsonb_build_object(
'server_os', 'Linux (Simulated)', -- 数据库侧通常难以直接获取完整的宿主系统信息
'web_server', 'Nginx/1.24.0 (Simulated)',
'db_engine', 'PostgreSQL',
'db_version', v_db_version,
'uts_runtime', 'uni-app x (UTS)',
'auth_id', 'ZC2884891' -- 模拟授权码
);
RETURN v_info;
END;
$$;
-- 授权
REVOKE ALL ON FUNCTION public.rpc_admin_get_system_info() FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_get_system_info() TO authenticated;

View File

@@ -1,5 +1,5 @@
-- =====================================================================================
-- Admin 系统功能 - 保存配置项 RPC
-- Admin 系统功能 - 保存/更新配置项 RPC
-- 位置docs/sql/30_rpc/admin/
-- 对象类型RPC 函数SECURITY DEFINER
-- 版本v1
@@ -8,7 +8,8 @@
CREATE OR REPLACE FUNCTION public.rpc_admin_system_config_save(
p_key TEXT,
p_value JSONB
p_value JSONB,
p_description TEXT DEFAULT NULL
)
RETURNS BOOLEAN
SECURITY DEFINER
@@ -24,14 +25,19 @@ BEGIN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 执行保存(存在则更新,不存在则插入)
INSERT INTO public.ml_system_configs (config_key, config_value, updated_at)
VALUES (p_key, p_value, NOW())
ON CONFLICT (config_key)
DO UPDATE SET
-- 2. 插入或更新配置
INSERT INTO public.ml_system_configs (config_key, config_value, description, updated_at)
VALUES (p_key, p_value, p_description, NOW())
ON CONFLICT (config_key) DO UPDATE
SET
config_value = EXCLUDED.config_value,
description = COALESCE(EXCLUDED.description, public.ml_system_configs.description),
updated_at = NOW();
RETURN TRUE;
END;
$$;
$$;
-- 授权
REVOKE ALL ON FUNCTION public.rpc_admin_system_config_save(TEXT, JSONB, TEXT) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_system_config_save(TEXT, JSONB, TEXT) TO authenticated;

View File

@@ -0,0 +1,33 @@
-- RPC: rpc_admin_delete_permission
-- 管理端删除功能权限/菜单
CREATE OR REPLACE FUNCTION public.rpc_admin_delete_permission(
p_id UUID
)
RETURNS BOOLEAN
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
v_ok BOOLEAN;
BEGIN
-- 1. 权限检查 (仅管理员)
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE auth_id = auth.uid() AND role = 'admin'
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 执行级联删除 (外键已配置 ON DELETE CASCADE)
DELETE FROM public.ak_permissions WHERE id = p_id;
GET DIAGNOSTICS v_ok = ROW_COUNT;
RETURN v_ok;
END;
$$;
-- 授权
REVOKE ALL ON FUNCTION public.rpc_admin_delete_permission(UUID) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_delete_permission(UUID) TO authenticated;

View File

@@ -0,0 +1,33 @@
-- RPC: rpc_admin_delete_role
-- 管理端删除角色
CREATE OR REPLACE FUNCTION public.rpc_admin_delete_role(
p_id UUID
)
RETURNS BOOLEAN
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
v_ok BOOLEAN;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE auth_id = auth.uid() AND role = 'admin'
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 执行删除
DELETE FROM public.ak_roles WHERE id = p_id;
GET DIAGNOSTICS v_ok = ROW_COUNT;
RETURN v_ok;
END;
$$;
-- 授权
REVOKE ALL ON FUNCTION public.rpc_admin_delete_role(UUID) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_delete_role(UUID) TO authenticated;

View File

@@ -0,0 +1,70 @@
-- RPC: rpc_admin_get_admin_list
-- 管理端获取管理员列表
-- 筛选 ak_users 表中 role 为 'admin' 或 'analytics' 的用户,并关联显示其角色信息
CREATE OR REPLACE FUNCTION public.rpc_admin_get_admin_list(
p_search TEXT DEFAULT NULL,
p_status SMALLINT DEFAULT NULL,
p_page INTEGER DEFAULT 1,
p_page_size INTEGER DEFAULT 20
)
RETURNS JSONB
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
v_offset INTEGER := (p_page - 1) * p_page_size;
v_total BIGINT;
v_items JSONB;
BEGIN
-- 1. 权限检查 (仅管理员)
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE auth_id = auth.uid() AND role = 'admin'
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 获取总数
SELECT COUNT(*) INTO v_total
FROM public.ak_users u
WHERE u.role IN ('admin', 'analytics')
AND (p_status IS NULL OR u.is_active = (p_status = 1))
AND (p_search IS NULL OR u.username ILIKE '%' || p_search || '%' OR u.real_name ILIKE '%' || p_search || '%');
-- 3. 获取数据列表 (关联角色)
SELECT jsonb_agg(t) INTO v_items
FROM (
SELECT
u.id,
u.username,
u.real_name,
u.role,
u.is_active,
u.last_login_at,
u.last_login_ip,
(
SELECT jsonb_agg(r.name)
FROM public.ak_admin_roles ar
JOIN public.ak_roles r ON r.id = ar.role_id
WHERE ar.user_id = u.id
) as roles
FROM public.ak_users u
WHERE u.role IN ('admin', 'analytics')
AND (p_status IS NULL OR u.is_active = (p_status = 1))
AND (p_search IS NULL OR u.username ILIKE '%' || p_search || '%' OR u.real_name ILIKE '%' || p_search || '%')
ORDER BY u.created_at DESC
LIMIT p_page_size OFFSET v_offset
) t;
RETURN jsonb_build_object(
'total', v_total,
'items', COALESCE(v_items, '[]'::jsonb)
);
END;
$$;
-- 授权
REVOKE ALL ON FUNCTION public.rpc_admin_get_admin_list(TEXT, SMALLINT, INTEGER, INTEGER) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_get_admin_list(TEXT, SMALLINT, INTEGER, INTEGER) TO authenticated;

View File

@@ -0,0 +1,38 @@
-- RPC: rpc_admin_get_permission_list
-- 管理端获取全量权限/菜单列表 (供前端构建树形结构)
CREATE OR REPLACE FUNCTION public.rpc_admin_get_permission_list()
RETURNS JSONB
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
v_items JSONB;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE auth_id = auth.uid() AND role = 'admin'
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 获取全量数据
SELECT jsonb_agg(t) INTO v_items
FROM (
SELECT
id, parent_id, name, code, type,
path, icon, sort_order, is_visible,
created_at, updated_at
FROM public.ak_permissions
ORDER BY sort_order ASC, created_at ASC
) t;
RETURN COALESCE(v_items, '[]'::jsonb);
END;
$$;
-- 授权
REVOKE ALL ON FUNCTION public.rpc_admin_get_permission_list() FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_get_permission_list() TO authenticated;

View File

@@ -0,0 +1,53 @@
-- RPC: rpc_admin_get_role_list
-- 管理端获取角色分页列表
CREATE OR REPLACE FUNCTION public.rpc_admin_get_role_list(
p_search TEXT DEFAULT NULL,
p_page INTEGER DEFAULT 1,
p_page_size INTEGER DEFAULT 20
)
RETURNS JSONB
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
v_offset INTEGER := (p_page - 1) * p_page_size;
v_total BIGINT;
v_items JSONB;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE auth_id = auth.uid() AND role = 'admin'
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 获取总数
SELECT COUNT(*) INTO v_total
FROM public.ak_roles
WHERE (p_search IS NULL OR p_search = '' OR name ILIKE '%' || p_search || '%' OR code ILIKE '%' || p_search || '%');
-- 3. 获取明细
SELECT jsonb_agg(t) INTO v_items
FROM (
SELECT
id, name, code, description, is_active,
created_at, updated_at
FROM public.ak_roles
WHERE (p_search IS NULL OR p_search = '' OR name ILIKE '%' || p_search || '%' OR code ILIKE '%' || p_search || '%')
ORDER BY created_at DESC
LIMIT p_page_size OFFSET v_offset
) t;
RETURN jsonb_build_object(
'total', v_total,
'items', COALESCE(v_items, '[]'::jsonb)
);
END;
$$;
-- 授权
REVOKE ALL ON FUNCTION public.rpc_admin_get_role_list(TEXT, INTEGER, INTEGER) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_get_role_list(TEXT, INTEGER, INTEGER) TO authenticated;

View File

@@ -0,0 +1,69 @@
-- RPC: rpc_admin_save_permission
-- 管理端新增或更新功能权限/菜单
CREATE OR REPLACE FUNCTION public.rpc_admin_save_permission(
p_id UUID DEFAULT NULL,
p_parent_id UUID DEFAULT NULL,
p_name TEXT DEFAULT NULL,
p_code TEXT DEFAULT NULL,
p_type TEXT DEFAULT 'menu',
p_path TEXT DEFAULT NULL,
p_icon TEXT DEFAULT NULL,
p_sort_order INTEGER DEFAULT 0,
p_is_visible BOOLEAN DEFAULT TRUE
)
RETURNS UUID
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
v_id UUID;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE auth_id = auth.uid() AND role = 'admin'
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 新增
IF p_id IS NULL THEN
IF p_name IS NULL OR p_code IS NULL THEN
RAISE EXCEPTION 'Missing required fields: name or code';
END IF;
INSERT INTO public.ak_permissions (
parent_id, name, code, type, path, icon, sort_order, is_visible
) VALUES (
p_parent_id, p_name, p_code, p_type, p_path, p_icon, p_sort_order, p_is_visible
) RETURNING id INTO v_id;
ELSE
-- 3. 更新
UPDATE public.ak_permissions
SET
parent_id = COALESCE(p_parent_id, parent_id),
name = COALESCE(p_name, name),
code = COALESCE(p_code, code),
type = COALESCE(p_type, type),
path = COALESCE(p_path, path),
icon = COALESCE(p_icon, icon),
sort_order = COALESCE(p_sort_order, sort_order),
is_visible = COALESCE(p_is_visible, is_visible),
updated_at = now()
WHERE id = p_id
RETURNING id INTO v_id;
IF v_id IS NULL THEN
RAISE EXCEPTION 'Permission item not found';
END IF;
END IF;
RETURN v_id;
END;
$$;
-- 授权
REVOKE ALL ON FUNCTION public.rpc_admin_save_permission(UUID, UUID, TEXT, TEXT, TEXT, TEXT, TEXT, INTEGER, BOOLEAN) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_save_permission(UUID, UUID, TEXT, TEXT, TEXT, TEXT, TEXT, INTEGER, BOOLEAN) TO authenticated;

View File

@@ -0,0 +1,61 @@
-- RPC: rpc_admin_save_role
-- 管理端新增或更新角色
CREATE OR REPLACE FUNCTION public.rpc_admin_save_role(
p_id UUID DEFAULT NULL,
p_name TEXT DEFAULT NULL,
p_code TEXT DEFAULT NULL,
p_description TEXT DEFAULT NULL,
p_is_active BOOLEAN DEFAULT TRUE
)
RETURNS UUID
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
v_id UUID;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE auth_id = auth.uid() AND role = 'admin'
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 新增
IF p_id IS NULL THEN
IF p_name IS NULL OR p_code IS NULL THEN
RAISE EXCEPTION 'Missing required fields: name or code';
END IF;
INSERT INTO public.ak_roles (
name, code, description, is_active
) VALUES (
p_name, p_code, p_description, p_is_active
) RETURNING id INTO v_id;
ELSE
-- 3. 更新
UPDATE public.ak_roles
SET
name = COALESCE(p_name, name),
code = COALESCE(p_code, code),
description = COALESCE(p_description, description),
is_active = COALESCE(p_is_active, is_active),
updated_at = now()
WHERE id = p_id
RETURNING id INTO v_id;
IF v_id IS NULL THEN
RAISE EXCEPTION 'Role not found';
END IF;
END IF;
RETURN v_id;
END;
$$;
-- 授权
REVOKE ALL ON FUNCTION public.rpc_admin_save_role(UUID, TEXT, TEXT, TEXT, BOOLEAN) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_save_role(UUID, TEXT, TEXT, TEXT, BOOLEAN) TO authenticated;

View File

@@ -0,0 +1,33 @@
-- RPC: rpc_admin_delete_delivery_staff
-- 管理端删除配送员
CREATE OR REPLACE FUNCTION public.rpc_admin_delete_delivery_staff(
p_id UUID
)
RETURNS BOOLEAN
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
v_ok BOOLEAN;
BEGIN
-- 1. 权限检查 (仅管理员)
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE auth_id = auth.uid() AND role = 'admin'
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 执行删除
DELETE FROM public.ml_delivery_staff WHERE id = p_id;
GET DIAGNOSTICS v_ok = ROW_COUNT;
RETURN v_ok;
END;
$$;
-- 授权
REVOKE ALL ON FUNCTION public.rpc_admin_delete_delivery_staff(UUID) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_delete_delivery_staff(UUID) TO authenticated;

View File

@@ -0,0 +1,33 @@
-- RPC: rpc_admin_delete_delivery_station
-- 管理端删除提货点/核销点
CREATE OR REPLACE FUNCTION public.rpc_admin_delete_delivery_station(
p_id UUID
)
RETURNS BOOLEAN
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
v_ok BOOLEAN;
BEGIN
-- 1. 权限检查 (仅管理员)
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE auth_id = auth.uid() AND role = 'admin'
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 执行删除
DELETE FROM public.ml_delivery_stations WHERE id = p_id;
GET DIAGNOSTICS v_ok = ROW_COUNT;
RETURN v_ok;
END;
$$;
-- 授权
REVOKE ALL ON FUNCTION public.rpc_admin_delete_delivery_station(UUID) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_delete_delivery_station(UUID) TO authenticated;

View File

@@ -0,0 +1,58 @@
-- RPC: rpc_admin_get_delivery_staff_list
-- 管理端获取配送员分页列表
-- 支持按姓名或手机号搜索
CREATE OR REPLACE FUNCTION public.rpc_admin_get_delivery_staff_list(
p_search TEXT DEFAULT NULL,
p_status SMALLINT DEFAULT NULL,
p_page INTEGER DEFAULT 1,
p_page_size INTEGER DEFAULT 20
)
RETURNS JSONB
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
v_offset INTEGER := (p_page - 1) * p_page_size;
v_total BIGINT;
v_items JSONB;
BEGIN
-- 1. 权限检查 (仅管理员)
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE auth_id = auth.uid() AND role = 'admin'
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 获取总数
SELECT COUNT(*) INTO v_total
FROM public.ml_delivery_staff
WHERE (p_status IS NULL OR status = p_status)
AND (p_search IS NULL OR p_search = '' OR nickname ILIKE '%' || p_search || '%' OR phone ILIKE '%' || p_search || '%');
-- 3. 获取明细
SELECT jsonb_agg(t) INTO v_items
FROM (
SELECT
id, uid, nickname, avatar, phone, status, is_active,
created_at, updated_at
FROM public.ml_delivery_staff
WHERE (p_status IS NULL OR status = p_status)
AND (p_search IS NULL OR p_search = '' OR nickname ILIKE '%' || p_search || '%' OR phone ILIKE '%' || p_search || '%')
ORDER BY created_at DESC
LIMIT p_page_size OFFSET v_offset
) t;
-- 4. 返回结果
RETURN jsonb_build_object(
'total', v_total,
'items', COALESCE(v_items, '[]'::jsonb)
);
END;
$$;
-- 授权
REVOKE ALL ON FUNCTION public.rpc_admin_get_delivery_staff_list(TEXT, SMALLINT, INTEGER, INTEGER) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_get_delivery_staff_list(TEXT, SMALLINT, INTEGER, INTEGER) TO authenticated;

View File

@@ -0,0 +1,65 @@
-- RPC: rpc_admin_get_delivery_station_list
-- 管理端获取提货点/核销点分页列表
-- 支持按名称、地址或手机号搜索
CREATE OR REPLACE FUNCTION public.rpc_admin_get_delivery_station_list(
p_search TEXT DEFAULT NULL,
p_status SMALLINT DEFAULT NULL,
p_page INTEGER DEFAULT 1,
p_page_size INTEGER DEFAULT 20
)
RETURNS JSONB
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
v_offset INTEGER := (p_page - 1) * p_page_size;
v_total BIGINT;
v_items JSONB;
BEGIN
-- 1. 权限检查 (仅管理员)
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE auth_id = auth.uid() AND role = 'admin'
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 获取总数
SELECT COUNT(*) INTO v_total
FROM public.ml_delivery_stations
WHERE (p_status IS NULL OR status = p_status)
AND (p_search IS NULL OR p_search = ''
OR name ILIKE '%' || p_search || '%'
OR address ILIKE '%' || p_search || '%'
OR phone ILIKE '%' || p_search || '%');
-- 3. 获取明细
SELECT jsonb_agg(t) INTO v_items
FROM (
SELECT
id, name, phone, address, image,
lng, lat, status, sort_order, business_hours,
created_at, updated_at
FROM public.ml_delivery_stations
WHERE (p_status IS NULL OR status = p_status)
AND (p_search IS NULL OR p_search = ''
OR name ILIKE '%' || p_search || '%'
OR address ILIKE '%' || p_search || '%'
OR phone ILIKE '%' || p_search || '%')
ORDER BY sort_order ASC, created_at DESC
LIMIT p_page_size OFFSET v_offset
) t;
-- 4. 返回结果
RETURN jsonb_build_object(
'total', v_total,
'items', COALESCE(v_items, '[]'::jsonb)
);
END;
$$;
-- 授权
REVOKE ALL ON FUNCTION public.rpc_admin_get_delivery_station_list(TEXT, SMALLINT, INTEGER, INTEGER) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_get_delivery_station_list(TEXT, SMALLINT, INTEGER, INTEGER) TO authenticated;

View File

@@ -0,0 +1,61 @@
-- RPC: rpc_admin_save_delivery_staff
-- 管理端新增或更新配送员信息
CREATE OR REPLACE FUNCTION public.rpc_admin_save_delivery_staff(
p_id UUID DEFAULT NULL,
p_nickname TEXT DEFAULT NULL,
p_avatar TEXT DEFAULT NULL,
p_phone TEXT DEFAULT NULL,
p_status SMALLINT DEFAULT 1
)
RETURNS UUID
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
v_id UUID;
BEGIN
-- 1. 权限检查 (仅管理员)
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE auth_id = auth.uid() AND role = 'admin'
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 参数校验
IF p_nickname IS NULL OR p_phone IS NULL THEN
RAISE EXCEPTION 'Missing required fields: nickname or phone';
END IF;
-- 3. 新增或更新
IF p_id IS NULL THEN
INSERT INTO public.ml_delivery_staff (
nickname, avatar, phone, status
) VALUES (
p_nickname, p_avatar, p_phone, p_status
) RETURNING id INTO v_id;
ELSE
UPDATE public.ml_delivery_staff
SET
nickname = COALESCE(p_nickname, nickname),
avatar = COALESCE(p_avatar, avatar),
phone = COALESCE(p_phone, phone),
status = COALESCE(p_status, status),
updated_at = now()
WHERE id = p_id
RETURNING id INTO v_id;
IF v_id IS NULL THEN
RAISE EXCEPTION 'Delivery staff not found';
END IF;
END IF;
RETURN v_id;
END;
$$;
-- 授权
REVOKE ALL ON FUNCTION public.rpc_admin_save_delivery_staff(UUID, TEXT, TEXT, TEXT, SMALLINT) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_save_delivery_staff(UUID, TEXT, TEXT, TEXT, SMALLINT) TO authenticated;

View File

@@ -0,0 +1,71 @@
-- RPC: rpc_admin_save_delivery_station
-- 管理端新增或更新提货点/核销点信息
CREATE OR REPLACE FUNCTION public.rpc_admin_save_delivery_station(
p_id UUID DEFAULT NULL,
p_name TEXT DEFAULT NULL,
p_phone TEXT DEFAULT NULL,
p_address TEXT DEFAULT NULL,
p_image TEXT DEFAULT NULL,
p_lng NUMERIC DEFAULT NULL,
p_lat NUMERIC DEFAULT NULL,
p_status SMALLINT DEFAULT 1,
p_sort_order INTEGER DEFAULT 0,
p_business_hours JSONB DEFAULT NULL
)
RETURNS UUID
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
v_id UUID;
BEGIN
-- 1. 权限检查 (仅管理员)
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE auth_id = auth.uid() AND role = 'admin'
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 参数校验
IF p_name IS NULL OR p_phone IS NULL OR p_address IS NULL THEN
RAISE EXCEPTION 'Missing required fields: name, phone or address';
END IF;
-- 3. 新增或更新
IF p_id IS NULL THEN
INSERT INTO public.ml_delivery_stations (
name, phone, address, image, lng, lat, status, sort_order, business_hours
) VALUES (
p_name, p_phone, p_address, p_image, p_lng, p_lat, p_status, p_sort_order, p_business_hours
) RETURNING id INTO v_id;
ELSE
UPDATE public.ml_delivery_stations
SET
name = COALESCE(p_name, name),
phone = COALESCE(p_phone, phone),
address = COALESCE(p_address, address),
image = COALESCE(p_image, image),
lng = COALESCE(p_lng, lng),
lat = COALESCE(p_lat, lat),
status = COALESCE(p_status, status),
sort_order = COALESCE(p_sort_order, sort_order),
business_hours = COALESCE(p_business_hours, business_hours),
updated_at = now()
WHERE id = p_id
RETURNING id INTO v_id;
IF v_id IS NULL THEN
RAISE EXCEPTION 'Station not found';
END IF;
END IF;
RETURN v_id;
END;
$$;
-- 授权
REVOKE ALL ON FUNCTION public.rpc_admin_save_delivery_station(UUID, TEXT, TEXT, TEXT, TEXT, NUMERIC, NUMERIC, SMALLINT, INTEGER, JSONB) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_save_delivery_station(UUID, TEXT, TEXT, TEXT, TEXT, NUMERIC, NUMERIC, SMALLINT, INTEGER, JSONB) TO authenticated;