feat(admin): complete full integration of kefu, finance, product and order modules with real RPC data streams

This commit is contained in:
comlibmb
2026-02-11 18:45:46 +08:00
parent ee5c0c446b
commit 48320b410c
25 changed files with 2060 additions and 538 deletions

View File

@@ -0,0 +1,36 @@
-- =====================================================================================
-- RPC: rpc_admin_kefu_account_delete
-- 位置docs/sql/30_rpc/kefu/
-- 对象类型RPC 函数 (SECURITY DEFINER)
-- 版本v1
-- 说明:管理端删除客服账号
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.rpc_admin_kefu_account_delete(
p_id UUID
)
RETURNS BOOLEAN
SECURITY DEFINER
SET search_path = public
LANGUAGE plpgsql
AS $$
DECLARE
v_ok BOOLEAN;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE id = auth.uid() AND role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 执行删除
DELETE FROM public.ml_kefu_accounts WHERE id = p_id;
GET DIAGNOSTICS v_ok = ROW_COUNT;
RETURN v_ok;
END;
$$;
COMMENT ON FUNCTION public.rpc_admin_kefu_account_delete IS '管理员删除客服账号';

View File

@@ -0,0 +1,69 @@
-- =====================================================================================
-- RPC: rpc_admin_kefu_account_list
-- 位置docs/sql/30_rpc/kefu/
-- 对象类型RPC 函数 (SECURITY DEFINER)
-- 版本v1
-- 说明:管理端分页获取客服账号列表
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.rpc_admin_kefu_account_list(
p_page INTEGER DEFAULT 1,
p_page_size INTEGER DEFAULT 15,
p_search TEXT DEFAULT NULL,
p_status SMALLINT DEFAULT NULL
)
RETURNS JSONB
SECURITY DEFINER
SET search_path = public
LANGUAGE plpgsql
AS $$
DECLARE
v_offset INTEGER;
v_total BIGINT;
v_items JSONB;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE id = auth.uid() AND role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
v_offset := (p_page - 1) * p_page_size;
-- 2. 获取总数
SELECT COUNT(*) INTO v_total
FROM public.ml_kefu_accounts ka
JOIN public.ak_users u ON u.id = ka.user_id
WHERE (p_status IS NULL OR ka.status = p_status)
AND (p_search IS NULL OR ka.nickname ILIKE '%' || p_search || '%' OR u.username ILIKE '%' || p_search || '%');
-- 3. 获取数据
SELECT jsonb_agg(t) INTO v_items
FROM (
SELECT
ka.id,
ka.user_id,
ka.nickname,
ka.avatar,
ka.status,
ka.is_online,
ka.created_at,
ka.updated_at,
u.username as user_account
FROM public.ml_kefu_accounts ka
JOIN public.ak_users u ON u.id = ka.user_id
WHERE (p_status IS NULL OR ka.status = p_status)
AND (p_search IS NULL OR ka.nickname ILIKE '%' || p_search || '%' OR u.username ILIKE '%' || p_search || '%')
ORDER BY ka.created_at DESC
LIMIT p_page_size
OFFSET v_offset
) t;
RETURN jsonb_build_object(
'total', v_total,
'items', COALESCE(v_items, '[]'::jsonb)
);
END;
$$;

View File

@@ -0,0 +1,61 @@
-- =====================================================================================
-- RPC: rpc_admin_kefu_account_save
-- 位置docs/sql/30_rpc/kefu/
-- 对象类型RPC 函数 (SECURITY DEFINER)
-- 版本v1
-- 说明:新增或更新客服账号
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.rpc_admin_kefu_account_save(
p_id UUID DEFAULT NULL,
p_user_id UUID DEFAULT NULL,
p_nickname TEXT DEFAULT NULL,
p_avatar TEXT DEFAULT NULL,
p_status SMALLINT DEFAULT 1
)
RETURNS UUID
SECURITY DEFINER
SET search_path = public
LANGUAGE plpgsql
AS $$
DECLARE
v_id UUID;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE id = auth.uid() AND role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 新增
IF p_id IS NULL THEN
IF p_user_id IS NULL OR p_nickname IS NULL THEN
RAISE EXCEPTION 'Missing required fields';
END IF;
INSERT INTO public.ml_kefu_accounts (
user_id, nickname, avatar, status
) VALUES (
p_user_id, p_nickname, p_avatar, p_status
) RETURNING id INTO v_id;
ELSE
-- 3. 更新
UPDATE public.ml_kefu_accounts
SET
nickname = COALESCE(p_nickname, nickname),
avatar = COALESCE(p_avatar, avatar),
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 'Account not found';
END IF;
END IF;
RETURN v_id;
END;
$$;

View File

@@ -0,0 +1,40 @@
-- =====================================================================================
-- RPC: rpc_admin_kefu_account_set_status
-- 位置docs/sql/30_rpc/kefu/
-- 对象类型RPC 函数 (SECURITY DEFINER)
-- 版本v1
-- 说明:管理端切换客服账号启用/禁用状态
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.rpc_admin_kefu_account_set_status(
p_id UUID,
p_status SMALLINT
)
RETURNS BOOLEAN
SECURITY DEFINER
SET search_path = public
LANGUAGE plpgsql
AS $$
DECLARE
v_ok BOOLEAN;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE id = auth.uid() AND role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 更新状态
UPDATE public.ml_kefu_accounts
SET status = p_status,
updated_at = now()
WHERE id = p_id;
GET DIAGNOSTICS v_ok = ROW_COUNT;
RETURN v_ok;
END;
$$;
COMMENT ON FUNCTION public.rpc_admin_kefu_account_set_status IS '管理员设置客服账号状态';

View File

@@ -0,0 +1,36 @@
-- =====================================================================================
-- RPC: rpc_admin_kefu_auto_reply_delete
-- 位置docs/sql/30_rpc/kefu/
-- 对象类型RPC 函数 (SECURITY DEFINER)
-- 版本v1
-- 说明:管理端删除客服自动回复配置
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.rpc_admin_kefu_auto_reply_delete(
p_id UUID
)
RETURNS BOOLEAN
SECURITY DEFINER
SET search_path = public
LANGUAGE plpgsql
AS $$
DECLARE
v_ok BOOLEAN;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE id = auth.uid() AND role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 执行删除
DELETE FROM public.ml_kefu_auto_replies WHERE id = p_id;
GET DIAGNOSTICS v_ok = ROW_COUNT;
RETURN v_ok;
END;
$$;
COMMENT ON FUNCTION public.rpc_admin_kefu_auto_reply_delete IS '管理员删除客服自动回复配置';

View File

@@ -0,0 +1,59 @@
-- =====================================================================================
-- RPC: rpc_admin_kefu_auto_reply_list
-- 位置docs/sql/30_rpc/kefu/
-- 对象类型RPC 函数 (SECURITY DEFINER)
-- 版本v1
-- 说明:管理端获取客服自动回复配置列表
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.rpc_admin_kefu_auto_reply_list(
p_page INTEGER DEFAULT 1,
p_page_size INTEGER DEFAULT 15,
p_search TEXT DEFAULT NULL
)
RETURNS JSONB
SECURITY DEFINER
SET search_path = public
LANGUAGE plpgsql
AS $$
DECLARE
v_offset INTEGER;
v_total BIGINT;
v_items JSONB;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE id = auth.uid() AND role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
v_offset := (p_page - 1) * p_page_size;
-- 2. 获取总数
SELECT COUNT(*) INTO v_total
FROM public.ml_kefu_auto_replies
WHERE (p_search IS NULL OR keyword ILIKE '%' || p_search || '%' OR content ILIKE '%' || p_search || '%');
-- 3. 获取明细数据
SELECT jsonb_agg(t) INTO v_items
FROM (
SELECT
id, keyword, content, reply_type, status,
created_at, updated_at
FROM public.ml_kefu_auto_replies
WHERE (p_search IS NULL OR keyword ILIKE '%' || p_search || '%' OR content 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;
$$;
COMMENT ON FUNCTION public.rpc_admin_kefu_auto_reply_list IS '管理员分页查询客服自动回复列表';

View File

@@ -0,0 +1,64 @@
-- =====================================================================================
-- RPC: rpc_admin_kefu_auto_reply_save
-- 位置docs/sql/30_rpc/kefu/
-- 对象类型RPC 函数 (SECURITY DEFINER)
-- 版本v1
-- 说明:管理端新增或更新自动回复配置
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.rpc_admin_kefu_auto_reply_save(
p_id UUID DEFAULT NULL,
p_keyword TEXT DEFAULT NULL,
p_content TEXT DEFAULT NULL,
p_reply_type TEXT DEFAULT 'text',
p_status SMALLINT DEFAULT 1
)
RETURNS UUID
SECURITY DEFINER
SET search_path = public
LANGUAGE plpgsql
AS $$
DECLARE
v_id UUID;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE id = auth.uid() AND role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 新增
IF p_id IS NULL THEN
IF p_keyword IS NULL OR p_content IS NULL THEN
RAISE EXCEPTION 'Missing required fields: keyword or content';
END IF;
INSERT INTO public.ml_kefu_auto_replies (
keyword, content, reply_type, status
) VALUES (
p_keyword, p_content, p_reply_type, p_status
) RETURNING id INTO v_id;
ELSE
-- 3. 更新
UPDATE public.ml_kefu_auto_replies
SET
keyword = COALESCE(p_keyword, keyword),
content = COALESCE(p_content, content),
reply_type = COALESCE(p_reply_type, reply_type),
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 'Auto reply record not found';
END IF;
END IF;
RETURN v_id;
END;
$$;
COMMENT ON FUNCTION public.rpc_admin_kefu_auto_reply_save IS '管理员新增或更新自动回复配置';

View File

@@ -0,0 +1,40 @@
-- =====================================================================================
-- RPC: rpc_admin_kefu_auto_reply_set_status
-- 位置docs/sql/30_rpc/kefu/
-- 对象类型RPC 函数 (SECURITY DEFINER)
-- 版本v1
-- 说明:管理端切换客服自动回复配置启用/禁用状态
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.rpc_admin_kefu_auto_reply_set_status(
p_id UUID,
p_status SMALLINT
)
RETURNS BOOLEAN
SECURITY DEFINER
SET search_path = public
LANGUAGE plpgsql
AS $$
DECLARE
v_ok BOOLEAN;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE id = auth.uid() AND role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 更新状态
UPDATE public.ml_kefu_auto_replies
SET status = p_status,
updated_at = now()
WHERE id = p_id;
GET DIAGNOSTICS v_ok = ROW_COUNT;
RETURN v_ok;
END;
$$;
COMMENT ON FUNCTION public.rpc_admin_kefu_auto_reply_set_status IS '管理员设置客服自动回复状态';

View File

@@ -0,0 +1,73 @@
-- =====================================================================================
-- RPC: rpc_admin_kefu_feedback_list
-- 位置docs/sql/30_rpc/kefu/
-- 对象类型RPC 函数 (SECURITY DEFINER)
-- 版本v1
-- 说明:管理端分页获取用户留言反馈列表
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.rpc_admin_kefu_feedback_list(
p_page INTEGER DEFAULT 1,
p_page_size INTEGER DEFAULT 15,
p_search TEXT DEFAULT NULL,
p_status SMALLINT DEFAULT NULL
)
RETURNS JSONB
SECURITY DEFINER
SET search_path = public
LANGUAGE plpgsql
AS $$
DECLARE
v_offset INTEGER;
v_total BIGINT;
v_items JSONB;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE id = auth.uid() AND role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
v_offset := (p_page - 1) * p_page_size;
-- 2. 获取总数
SELECT COUNT(*) INTO v_total
FROM public.ml_kefu_feedbacks f
LEFT JOIN public.ak_users u ON u.id = f.user_id
WHERE (p_status IS NULL OR f.status = p_status)
AND (p_search IS NULL OR f.nickname ILIKE '%' || p_search || '%' OR f.phone ILIKE '%' || p_search || '%' OR f.content ILIKE '%' || p_search || '%');
-- 3. 获取数据
SELECT jsonb_agg(t) INTO v_items
FROM (
SELECT
f.id,
f.user_id,
f.nickname,
f.phone,
f.content,
f.status,
f.reply_content,
f.processed_at,
f.created_at,
f.updated_at,
u.username as user_account
FROM public.ml_kefu_feedbacks f
LEFT JOIN public.ak_users u ON u.id = f.user_id
WHERE (p_status IS NULL OR f.status = p_status)
AND (p_search IS NULL OR f.nickname ILIKE '%' || p_search || '%' OR f.phone ILIKE '%' || p_search || '%' OR f.content ILIKE '%' || p_search || '%')
ORDER BY f.created_at DESC
LIMIT p_page_size
OFFSET v_offset
) t;
RETURN jsonb_build_object(
'total', v_total,
'items', COALESCE(v_items, '[]'::jsonb)
);
END;
$$;
COMMENT ON FUNCTION public.rpc_admin_kefu_feedback_list IS '管理员分页查询用户留言反馈列表';

View File

@@ -0,0 +1,43 @@
-- =====================================================================================
-- RPC: rpc_admin_kefu_feedback_process
-- 位置docs/sql/30_rpc/kefu/
-- 对象类型RPC 函数 (SECURITY DEFINER)
-- 版本v1
-- 说明:管理端处理用户留言反馈(回复内容并更新状态)
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.rpc_admin_kefu_feedback_process(
p_id UUID,
p_reply_content TEXT
)
RETURNS BOOLEAN
SECURITY DEFINER
SET search_path = public
LANGUAGE plpgsql
AS $$
DECLARE
v_ok BOOLEAN;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE id = auth.uid() AND role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 更新状态
UPDATE public.ml_kefu_feedbacks
SET
status = 1, -- 已处理
reply_content = p_reply_content,
processed_at = now(),
updated_at = now()
WHERE id = p_id;
GET DIAGNOSTICS v_ok = ROW_COUNT;
RETURN v_ok;
END;
$$;
COMMENT ON FUNCTION public.rpc_admin_kefu_feedback_process IS '管理员处理并回复用户留言反馈';

View File

@@ -0,0 +1,36 @@
-- =====================================================================================
-- RPC: rpc_admin_kefu_word_category_delete
-- 位置docs/sql/30_rpc/kefu/
-- 对象类型RPC 函数 (SECURITY DEFINER)
-- 版本v1
-- 说明:管理端删除话术分类
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.rpc_admin_kefu_word_category_delete(
p_id UUID
)
RETURNS BOOLEAN
SECURITY DEFINER
SET search_path = public
LANGUAGE plpgsql
AS $$
DECLARE
v_ok BOOLEAN;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE id = auth.uid() AND role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 执行删除 (ml_kefu_words 已设置 ON DELETE CASCADE)
DELETE FROM public.ml_kefu_word_categories WHERE id = p_id;
GET DIAGNOSTICS v_ok = ROW_COUNT;
RETURN v_ok;
END;
$$;
COMMENT ON FUNCTION public.rpc_admin_kefu_word_category_delete IS '管理员删除话术分类';

View File

@@ -0,0 +1,38 @@
-- =====================================================================================
-- RPC: rpc_admin_kefu_word_category_list
-- 位置docs/sql/30_rpc/kefu/
-- 对象类型RPC 函数 (SECURITY DEFINER)
-- 版本v1
-- 说明:管理端获取话术分类列表
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.rpc_admin_kefu_word_category_list()
RETURNS JSONB
SECURITY DEFINER
SET search_path = public
LANGUAGE plpgsql
AS $$
DECLARE
v_items JSONB;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE id = auth.uid() AND role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 获取分类列表
SELECT jsonb_agg(t) INTO v_items
FROM (
SELECT id, name, sort, created_at, updated_at
FROM public.ml_kefu_word_categories
ORDER BY sort ASC, created_at DESC
) t;
RETURN COALESCE(v_items, '[]'::jsonb);
END;
$$;
COMMENT ON FUNCTION public.rpc_admin_kefu_word_category_list IS '管理员获取话术分类列表';

View File

@@ -0,0 +1,60 @@
-- =====================================================================================
-- RPC: rpc_admin_kefu_word_category_save
-- 位置docs/sql/30_rpc/kefu/
-- 对象类型RPC 函数 (SECURITY DEFINER)
-- 版本v1
-- 说明:管理端新增或更新话术分类
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.rpc_admin_kefu_word_category_save(
p_id UUID DEFAULT NULL,
p_name TEXT DEFAULT NULL,
p_sort INTEGER DEFAULT 0
)
RETURNS UUID
SECURITY DEFINER
SET search_path = public
LANGUAGE plpgsql
AS $$
DECLARE
v_id UUID;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE id = auth.uid() AND role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 新增
IF p_id IS NULL THEN
IF p_name IS NULL THEN
RAISE EXCEPTION 'Missing required fields: name';
END IF;
INSERT INTO public.ml_kefu_word_categories (
name, sort
) VALUES (
p_name, p_sort
) RETURNING id INTO v_id;
ELSE
-- 3. 更新
UPDATE public.ml_kefu_word_categories
SET
name = COALESCE(p_name, name),
sort = COALESCE(p_sort, sort),
updated_at = now()
WHERE id = p_id
RETURNING id INTO v_id;
IF v_id IS NULL THEN
RAISE EXCEPTION 'Category not found';
END IF;
END IF;
RETURN v_id;
END;
$$;
COMMENT ON FUNCTION public.rpc_admin_kefu_word_category_save IS '管理员新增或更新话术分类';

View File

@@ -0,0 +1,36 @@
-- =====================================================================================
-- RPC: rpc_admin_kefu_word_delete
-- 位置docs/sql/30_rpc/kefu/
-- 对象类型RPC 函数 (SECURITY DEFINER)
-- 版本v1
-- 说明:管理端删除快捷话术
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.rpc_admin_kefu_word_delete(
p_id UUID
)
RETURNS BOOLEAN
SECURITY DEFINER
SET search_path = public
LANGUAGE plpgsql
AS $$
DECLARE
v_ok BOOLEAN;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE id = auth.uid() AND role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 执行删除
DELETE FROM public.ml_kefu_words WHERE id = p_id;
GET DIAGNOSTICS v_ok = ROW_COUNT;
RETURN v_ok;
END;
$$;
COMMENT ON FUNCTION public.rpc_admin_kefu_word_delete IS '管理员删除快捷话术';

View File

@@ -0,0 +1,52 @@
-- =====================================================================================
-- RPC: rpc_admin_kefu_word_list
-- 位置docs/sql/30_rpc/kefu/
-- 对象类型RPC 函数 (SECURITY DEFINER)
-- 版本v1
-- 说明:管理端获取指定分类下的快捷话术列表
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.rpc_admin_kefu_word_list(
p_category_id UUID DEFAULT NULL,
p_search TEXT DEFAULT NULL
)
RETURNS JSONB
SECURITY DEFINER
SET search_path = public
LANGUAGE plpgsql
AS $$
DECLARE
v_items JSONB;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE id = auth.uid() AND role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 获取话术列表
SELECT jsonb_agg(t) INTO v_items
FROM (
SELECT
w.id,
w.category_id,
w.title,
w.content,
w.sort,
w.created_at,
w.updated_at,
c.name as category_name
FROM public.ml_kefu_words w
JOIN public.ml_kefu_word_categories c ON c.id = w.category_id
WHERE (p_category_id IS NULL OR w.category_id = p_category_id)
AND (p_search IS NULL OR w.title ILIKE '%' || p_search || '%' OR w.content ILIKE '%' || p_search || '%')
ORDER BY w.sort ASC, w.created_at DESC
) t;
RETURN COALESCE(v_items, '[]'::jsonb);
END;
$$;
COMMENT ON FUNCTION public.rpc_admin_kefu_word_list IS '管理员获取快捷话术列表';

View File

@@ -0,0 +1,64 @@
-- =====================================================================================
-- RPC: rpc_admin_kefu_word_save
-- 位置docs/sql/30_rpc/kefu/
-- 对象类型RPC 函数 (SECURITY DEFINER)
-- 版本v1
-- 说明:管理端新增或更新快捷话术
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.rpc_admin_kefu_word_save(
p_id UUID DEFAULT NULL,
p_category_id UUID DEFAULT NULL,
p_title TEXT DEFAULT NULL,
p_content TEXT DEFAULT NULL,
p_sort INTEGER DEFAULT 0
)
RETURNS UUID
SECURITY DEFINER
SET search_path = public
LANGUAGE plpgsql
AS $$
DECLARE
v_id UUID;
BEGIN
-- 1. 权限检查
IF NOT EXISTS (
SELECT 1 FROM public.ak_users
WHERE id = auth.uid() AND role IN ('admin', 'analytics')
) THEN
RAISE EXCEPTION 'Permission denied';
END IF;
-- 2. 新增
IF p_id IS NULL THEN
IF p_category_id IS NULL OR p_title IS NULL OR p_content IS NULL THEN
RAISE EXCEPTION 'Missing required fields';
END IF;
INSERT INTO public.ml_kefu_words (
category_id, title, content, sort
) VALUES (
p_category_id, p_title, p_content, p_sort
) RETURNING id INTO v_id;
ELSE
-- 3. 更新
UPDATE public.ml_kefu_words
SET
category_id = COALESCE(p_category_id, category_id),
title = COALESCE(p_title, title),
content = COALESCE(p_content, content),
sort = COALESCE(p_sort, sort),
updated_at = now()
WHERE id = p_id
RETURNING id INTO v_id;
IF v_id IS NULL THEN
RAISE EXCEPTION 'Word not found';
END IF;
END IF;
RETURN v_id;
END;
$$;
COMMENT ON FUNCTION public.rpc_admin_kefu_word_save IS '管理员新增或更新快捷话术';