Files
akmon/doc_news/ai_multilingual_topic.sql
2026-01-20 08:04:15 +08:00

382 lines
16 KiB
PL/PgSQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- ===================================================================
-- ak_topics 多语言支持扩展
-- ===================================================================
-- 专题多语言翻译表
CREATE TABLE IF NOT EXISTS public.ak_topic_translations (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
topic_id uuid NOT NULL REFERENCES public.ak_topics(id) ON DELETE CASCADE,
language_code VARCHAR(10) NOT NULL, -- 如 'zh-CN', 'en', 'ja', 'zh-TW'
title VARCHAR(255) NOT NULL,
description TEXT,
meta_description TEXT,
meta_keywords TEXT[],
translation_method VARCHAR(32) DEFAULT 'ai', -- 'ai', 'human', 'hybrid'
ai_provider VARCHAR(32), -- 'openai', 'google', 'baidu', 'custom'
quality_score FLOAT,
ai_confidence FLOAT,
human_verified BOOLEAN DEFAULT false,
human_verified_by uuid, -- 参考 ak_users 表
human_verified_at TIMESTAMP WITH TIME ZONE,
tokens_used INTEGER,
processing_time_ms INTEGER,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
UNIQUE(topic_id, language_code)
);
-- 专题翻译索引
CREATE INDEX IF NOT EXISTS idx_topic_translations_topic ON public.ak_topic_translations(topic_id);
CREATE INDEX IF NOT EXISTS idx_topic_translations_language ON public.ak_topic_translations(language_code);
CREATE INDEX IF NOT EXISTS idx_topic_translations_method ON public.ak_topic_translations(translation_method);
CREATE INDEX IF NOT EXISTS idx_topic_translations_quality ON public.ak_topic_translations(quality_score DESC);
CREATE INDEX IF NOT EXISTS idx_topic_translations_verified ON public.ak_topic_translations(human_verified);
COMMENT ON TABLE public.ak_topic_translations IS '专题多语言翻译表';
COMMENT ON COLUMN public.ak_topic_translations.language_code IS '语言代码如zh-CN、en、ja、zh-TW';
COMMENT ON COLUMN public.ak_topic_translations.translation_method IS '翻译方式ai=AI翻译human=人工翻译hybrid=混合翻译';
COMMENT ON COLUMN public.ak_topic_translations.quality_score IS '翻译质量评分(0-1)';
-- ===================================================================
-- ak_topic_contents 多语言支持扩展
-- ===================================================================
-- 专题内容关联多语言翻译表
CREATE TABLE IF NOT EXISTS public.ak_topic_content_translations (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
topic_content_id uuid NOT NULL REFERENCES public.ak_topic_contents(id) ON DELETE CASCADE,
language_code VARCHAR(10) NOT NULL,
editor_note TEXT, -- 多语言编辑说明
translation_method VARCHAR(32) DEFAULT 'ai',
ai_provider VARCHAR(32),
quality_score FLOAT,
human_verified BOOLEAN DEFAULT false,
human_verified_by uuid,
human_verified_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
UNIQUE(topic_content_id, language_code)
);
-- 专题内容翻译索引
CREATE INDEX IF NOT EXISTS idx_topic_content_translations_content ON public.ak_topic_content_translations(topic_content_id);
CREATE INDEX IF NOT EXISTS idx_topic_content_translations_language ON public.ak_topic_content_translations(language_code);
CREATE INDEX IF NOT EXISTS idx_topic_content_translations_quality ON public.ak_topic_content_translations(quality_score DESC);
COMMENT ON TABLE public.ak_topic_content_translations IS '专题内容关联多语言翻译表';
-- ===================================================================
-- 多语言专题视图和函数
-- ===================================================================
-- 多语言专题视图
CREATE OR REPLACE VIEW public.vw_multilingual_topics AS
SELECT
t.id,
t.title as original_title,
t.description as original_description,
t.topic_type,
t.status,
t.cover_image_url,
t.creator_id,
t.content_count,
t.view_count,
t.like_count,
t.share_count,
t.comment_count,
t.subscriber_count,
t.priority_level,
t.tags,
t.created_at,
t.updated_at,
-- 聚合翻译信息
COALESCE(
json_agg(
json_build_object(
'language_code', tt.language_code,
'title', tt.title,
'description', tt.description,
'meta_description', tt.meta_description,
'meta_keywords', tt.meta_keywords,
'quality_score', tt.quality_score,
'translation_method', tt.translation_method,
'human_verified', tt.human_verified
)
) FILTER (WHERE tt.id IS NOT NULL),
'[]'::json
) as translations
FROM public.ak_topics t
LEFT JOIN public.ak_topic_translations tt ON t.id = tt.topic_id
WHERE t.status IN ('active', 'featured')
GROUP BY t.id, t.title, t.description, t.topic_type, t.status, t.cover_image_url,
t.creator_id, t.content_count, t.view_count, t.like_count, t.share_count,
t.comment_count, t.subscriber_count, t.priority_level, t.tags,
t.created_at, t.updated_at;
COMMENT ON VIEW public.vw_multilingual_topics IS '多语言专题聚合视图';
-- 获取指定语言的专题列表函数
CREATE OR REPLACE FUNCTION public.get_topics_by_language(
p_language_code VARCHAR(10) DEFAULT 'zh-CN',
p_topic_type VARCHAR(32) DEFAULT NULL,
p_status VARCHAR(32) DEFAULT 'active',
p_limit INTEGER DEFAULT 20,
p_offset INTEGER DEFAULT 0
)
RETURNS TABLE (
topic_id uuid,
title VARCHAR(255),
description TEXT,
topic_type VARCHAR(32),
status VARCHAR(32),
cover_image_url TEXT,
content_count INTEGER,
view_count INTEGER,
like_count INTEGER,
share_count INTEGER,
comment_count INTEGER,
subscriber_count INTEGER,
priority_level INTEGER,
tags TEXT[],
translation_quality FLOAT,
created_at TIMESTAMP WITH TIME ZONE,
updated_at TIMESTAMP WITH TIME ZONE
) AS $$
BEGIN
RETURN QUERY
SELECT
t.id,
COALESCE(tt.title, t.title) as title,
COALESCE(tt.description, t.description) as description,
t.topic_type,
t.status,
t.cover_image_url,
t.content_count,
t.view_count,
t.like_count,
t.share_count,
t.comment_count,
t.subscriber_count,
t.priority_level,
t.tags,
tt.quality_score as translation_quality,
t.created_at,
t.updated_at
FROM public.ak_topics t
LEFT JOIN public.ak_topic_translations tt ON t.id = tt.topic_id
AND tt.language_code = p_language_code
WHERE (p_topic_type IS NULL OR t.topic_type = p_topic_type)
AND (p_status IS NULL OR t.status = p_status)
ORDER BY t.priority_level DESC, t.updated_at DESC
LIMIT p_limit OFFSET p_offset;
END;
$$ LANGUAGE plpgsql;
COMMENT ON FUNCTION public.get_topics_by_language IS '获取指定语言的专题列表';
-- 获取专题详情(多语言)函数
CREATE OR REPLACE FUNCTION public.get_topic_detail(
p_topic_id uuid,
p_language_code VARCHAR(10) DEFAULT 'zh-CN'
)
RETURNS TABLE (
topic_id uuid,
title VARCHAR(255),
description TEXT,
meta_description TEXT,
meta_keywords TEXT[],
topic_type VARCHAR(32),
status VARCHAR(32),
cover_image_url TEXT,
creator_id uuid,
editor_id uuid,
content_count INTEGER,
view_count INTEGER,
like_count INTEGER,
share_count INTEGER,
comment_count INTEGER,
subscriber_count INTEGER,
priority_level INTEGER,
tags TEXT[],
seo_slug VARCHAR(255),
translation_quality FLOAT,
is_translated BOOLEAN,
created_at TIMESTAMP WITH TIME ZONE,
updated_at TIMESTAMP WITH TIME ZONE,
contents JSON
) AS $$
BEGIN
RETURN QUERY
SELECT
t.id,
COALESCE(tt.title, t.title) as title,
COALESCE(tt.description, t.description) as description,
COALESCE(tt.meta_description, t.meta_description) as meta_description,
COALESCE(tt.meta_keywords, t.meta_keywords) as meta_keywords,
t.topic_type,
t.status,
t.cover_image_url,
t.creator_id,
t.editor_id,
t.content_count,
t.view_count,
t.like_count,
t.share_count,
t.comment_count,
t.subscriber_count,
t.priority_level,
t.tags,
t.seo_slug,
tt.quality_score as translation_quality,
(tt.id IS NOT NULL) as is_translated,
t.created_at,
t.updated_at,
-- 聚合该专题下的内容
COALESCE(
(SELECT json_agg(
json_build_object(
'content_id', tc.content_id,
'display_order', tc.display_order,
'editor_note', COALESCE(tct.editor_note, tc.editor_note),
'is_featured', tc.is_featured,
'added_at', tc.added_at
)
ORDER BY tc.display_order, tc.added_at
)
FROM public.ak_topic_contents tc
LEFT JOIN public.ak_topic_content_translations tct
ON tc.id = tct.topic_content_id AND tct.language_code = p_language_code
WHERE tc.topic_id = t.id),
'[]'::json
) as contents
FROM public.ak_topics t
LEFT JOIN public.ak_topic_translations tt ON t.id = tt.topic_id
AND tt.language_code = p_language_code
WHERE t.id = p_topic_id;
END;
$$ LANGUAGE plpgsql;
COMMENT ON FUNCTION public.get_topic_detail IS '获取专题详情(多语言支持)';
-- ===================================================================
-- 初始化示例数据
-- ===================================================================
-- 创建示例专题(如果不存在)
INSERT INTO public.ak_topics (title, description, topic_type, status, priority_level, tags)
VALUES
('人工智能发展趋势', '探讨2024年人工智能技术的最新发展趋势和应用前景', 'analysis', 'active', 5, ARRAY['AI', '人工智能', '技术趋势']),
('科技创新专题', '汇聚最新的科技创新成果和突破性技术', 'series', 'featured', 8, ARRAY['科技', '创新', '技术']),
('数字化转型指南', '企业数字化转型的完整指导和最佳实践', 'guide', 'active', 6, ARRAY['数字化', '转型', '企业'])
ON CONFLICT DO NOTHING;
-- 为示例专题添加多语言翻译
INSERT INTO public.ak_topic_translations (topic_id, language_code, title, description, translation_method, quality_score)
SELECT
t.id,
'en',
CASE
WHEN t.title = '人工智能发展趋势' THEN 'AI Development Trends'
WHEN t.title = '科技创新专题' THEN 'Technology Innovation Topics'
WHEN t.title = '数字化转型指南' THEN 'Digital Transformation Guide'
ELSE t.title
END,
CASE
WHEN t.description LIKE '%人工智能%' THEN 'Exploring the latest AI technology trends and application prospects in 2024'
WHEN t.description LIKE '%科技创新%' THEN 'Gathering the latest technological innovations and breakthrough technologies'
WHEN t.description LIKE '%数字化转型%' THEN 'Complete guidance and best practices for enterprise digital transformation'
ELSE t.description
END,
'ai',
0.85
FROM public.ak_topics t
WHERE t.title IN ('人工智能发展趋势', '科技创新专题', '数字化转型指南')
ON CONFLICT (topic_id, language_code) DO NOTHING;
-- 添加日文翻译
INSERT INTO public.ak_topic_translations (topic_id, language_code, title, description, translation_method, quality_score)
SELECT
t.id,
'ja',
CASE
WHEN t.title = '人工智能发展趋势' THEN 'AI発展トレンド'
WHEN t.title = '科技创新专题' THEN 'テクノロジーイノベーション特集'
WHEN t.title = '数字化转型指南' THEN 'デジタル変革ガイド'
ELSE t.title
END,
CASE
WHEN t.description LIKE '%人工智能%' THEN '2024年のAI技術の最新発展トレンドと応用展望を探る'
WHEN t.description LIKE '%科技创新%' THEN '最新の技術革新成果と画期的技術を集約'
WHEN t.description LIKE '%数字化转型%' THEN '企業のデジタル変革の完全ガイドとベストプラクティス'
ELSE t.description
END,
'ai',
0.80
FROM public.ak_topics t
WHERE t.title IN ('人工智能发展趋势', '科技创新专题', '数字化转型指南')
ON CONFLICT (topic_id, language_code) DO NOTHING;
-- ===================================================================
-- 更新现有ak_languages表以支持专题翻译
-- ===================================================================
-- 为专题翻译启用RLS策略
ALTER TABLE public.ak_topic_translations ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.ak_topic_content_translations ENABLE ROW LEVEL SECURITY;
-- 专题翻译访问策略(所有人可读)
DROP POLICY IF EXISTS "topic_translations_select_policy" ON public.ak_topic_translations;
CREATE POLICY "topic_translations_select_policy" ON public.ak_topic_translations
FOR SELECT USING (true);
-- 专题翻译插入策略(认证用户可插入)
DROP POLICY IF EXISTS "topic_translations_insert_policy" ON public.ak_topic_translations;
CREATE POLICY "topic_translations_insert_policy" ON public.ak_topic_translations
FOR INSERT WITH CHECK (auth.uid() IS NOT NULL);
-- 专题内容翻译访问策略
DROP POLICY IF EXISTS "topic_content_translations_select_policy" ON public.ak_topic_content_translations;
CREATE POLICY "topic_content_translations_select_policy" ON public.ak_topic_content_translations
FOR SELECT USING (true);
DROP POLICY IF EXISTS "topic_content_translations_insert_policy" ON public.ak_topic_content_translations;
CREATE POLICY "topic_content_translations_insert_policy" ON public.ak_topic_content_translations
FOR INSERT WITH CHECK (auth.uid() IS NOT NULL);
-- ===================================================================
-- 完成信息
-- ===================================================================
DO $$
BEGIN
RAISE NOTICE '===================================================================';
RAISE NOTICE 'ak_topics 多语言支持扩展完成!';
RAISE NOTICE '===================================================================';
RAISE NOTICE '新增表:';
RAISE NOTICE '- ak_topic_translations: 专题多语言翻译表';
RAISE NOTICE '- ak_topic_content_translations: 专题内容关联多语言翻译表';
RAISE NOTICE '===================================================================';
RAISE NOTICE '新增函数:';
RAISE NOTICE '- get_topics_by_language(): 获取指定语言的专题列表';
RAISE NOTICE '- get_topic_detail(): 获取专题详情(多语言支持)';
RAISE NOTICE '===================================================================';
RAISE NOTICE '新增视图:';
RAISE NOTICE '- vw_multilingual_topics: 多语言专题聚合视图';
RAISE NOTICE '===================================================================';
RAISE NOTICE '特性支持:';
RAISE NOTICE '- 专题标题和描述多语言翻译';
RAISE NOTICE '- 专题内容编辑说明多语言支持';
RAISE NOTICE '- AI和人工翻译质量评分';
RAISE NOTICE '- SEO元数据多语言支持';
RAISE NOTICE '- 翻译质量追踪和审核机制';
RAISE NOTICE '- 与现有ak_content_translations架构一致';
RAISE NOTICE '===================================================================';
END
$$;
ALTER TABLE public.ak_contents
ADD COLUMN cid BIGSERIAL UNIQUE;
-- 或更推荐PostgreSQL 10+,标准写法):
-- ALTER TABLE public.ak_contents
-- ADD COLUMN cid BIGINT GENERATED ALWAYS AS IDENTITY