diff --git a/apps/web/.gitignore b/apps/web/.gitignore index 5ef6a52..79faae4 100644 --- a/apps/web/.gitignore +++ b/apps/web/.gitignore @@ -13,6 +13,13 @@ # testing /coverage +# playwright e2e +/e2e/.auth +/e2e/.report +/e2e/.artifacts +/playwright-report +/test-results + # next.js /.next/ /out/ diff --git a/apps/web/e2e/apps.spec.ts b/apps/web/e2e/apps.spec.ts new file mode 100644 index 0000000..be385c7 --- /dev/null +++ b/apps/web/e2e/apps.spec.ts @@ -0,0 +1,103 @@ +import { test, expect, type Page } from "@playwright/test"; +import { + chatExamples, + agentExamples, + completionExamples, + workflowExamples, +} from "./examples"; + +/** 断言结果容器中渲染了实质内容(markdown 文本长度足够)。 */ +async function expectNonEmptyAnswer(locator: ReturnType) { + await expect(locator).toBeVisible({ timeout: 90_000 }); + await expect + .poll(async () => (await locator.innerText()).trim().length, { timeout: 90_000 }) + .toBeGreaterThan(15); +} + +test.describe("对话型 / 智能体型应用(textarea + 发送)", () => { + for (const app of [...chatExamples, ...agentExamples]) { + test(`${app.name} (${app.slug})`, async ({ page }) => { + await page.goto(`/chat/${app.slug}`); + + const textarea = page.getByPlaceholder(/输入消息/); + await expect(textarea).toBeVisible({ timeout: 30_000 }); + await textarea.fill(app.input); + + const busy = app.kind === "agent" ? /思考中/ : /生成中/; + await page.getByRole("button", { name: /发送/ }).click(); + + // 等待回复结束(发送按钮文本从 busy 恢复为“发送”)。 + await expect(page.getByRole("button", { name: busy })).toBeVisible({ timeout: 30_000 }); + await expect(page.getByRole("button", { name: /发送/ })).toBeVisible({ timeout: 90_000 }); + + // 最后一条 AI 回复(justify-start 容器)应有非空内容。 + const lastAiReply = page.locator("div.justify-start").last(); + await expectNonEmptyAnswer(lastAiReply); + }); + } +}); + +test.describe("补全型应用(textarea + 生成)", () => { + for (const app of completionExamples) { + test(`${app.name} (${app.slug})`, async ({ page }) => { + await page.goto(`/chat/${app.slug}`); + + const textarea = page.getByPlaceholder(/请输入|在此输入/).first(); + await expect(textarea).toBeVisible({ timeout: 30_000 }); + await textarea.fill(app.input); + + await page.getByRole("button", { name: /^生成$/ }).click(); + + // 生成中 -> 生成 恢复。 + await expect(page.getByRole("button", { name: /生成中/ })).toBeVisible({ timeout: 30_000 }); + await expect(page.getByRole("button", { name: /^生成$/ })).toBeVisible({ timeout: 90_000 }); + + // 输出结果卡片(emerald 主题)渲染非空。 + const output = page.locator(".bg-emerald-50\\/30").last(); + await expectNonEmptyAnswer(output); + }); + } +}); + +test.describe("工作流型应用(多步表单 + 运行)", () => { + for (const app of workflowExamples) { + test(`${app.name} (${app.slug})`, async ({ page }) => { + await page.goto(`/chat/${app.slug}`); + + // 等待第一步表单渲染。 + await expect(page.getByRole("heading", { name: /步骤 1/ })).toBeVisible({ + timeout: 30_000, + }); + + for (let i = 0; i < app.steps.length; i++) { + const step = app.steps[i]; + const isLast = i === app.steps.length - 1; + + if (step.type === "select") { + await page.getByRole("button", { name: step.value, exact: true }).click(); + } else { + const ta = page.locator("textarea"); + await expect(ta).toBeVisible(); + await ta.fill(step.value); + } + + if (isLast) { + await page.getByRole("button", { name: /运行/ }).click(); + } else { + await page.getByRole("button", { name: /下一步/ }).click(); + // 等待进入下一步。 + await expect( + page.getByRole("heading", { name: new RegExp(`步骤 ${i + 2}`) }), + ).toBeVisible({ timeout: 15_000 }); + } + } + + // 运行后等待“处理结果”出现并渲染非空内容。 + await expect(page.getByRole("heading", { name: /处理结果/ })).toBeVisible({ + timeout: 90_000, + }); + const result = page.locator(".bg-emerald-50\\/30").last(); + await expectNonEmptyAnswer(result); + }); + } +}); \ No newline at end of file diff --git a/apps/web/e2e/auth.setup.ts b/apps/web/e2e/auth.setup.ts new file mode 100644 index 0000000..899fc2f --- /dev/null +++ b/apps/web/e2e/auth.setup.ts @@ -0,0 +1,26 @@ +import { test as setup, expect } from "@playwright/test"; +import fs from "fs"; +import path from "path"; + +const AUTH_FILE = path.join(__dirname, ".auth", "state.json"); + +setup("登录法制日报账号并保存会话", async ({ page }) => { + fs.mkdirSync(path.dirname(AUTH_FILE), { recursive: true }); + + await page.goto("/login"); + + await expect(page.locator("#org")).toBeVisible({ timeout: 30_000 }); + + await page.locator("#org").selectOption("a0000000-0000-0000-0000-00000000000a"); + await page.fill("#email", "fazhiribao@govai.gov.cn"); + await page.fill("#password", "admin123"); + + await page.getByRole("button", { name: /登\s*录/ }).click(); + + await page.waitForURL(/\/store/, { timeout: 30_000 }); + + const token = await page.evaluate(() => localStorage.getItem("token")); + expect(token, "登录后应在 localStorage 写入 token").toBeTruthy(); + + await page.context().storageState({ path: AUTH_FILE }); +}); \ No newline at end of file diff --git a/apps/web/e2e/examples.ts b/apps/web/e2e/examples.ts new file mode 100644 index 0000000..b1759f3 --- /dev/null +++ b/apps/web/e2e/examples.ts @@ -0,0 +1,168 @@ +/** + * 法制日报 15 个应用的示例输入数据。 + * 类型与 slug 对应 server/migrations/seed_fazhiribao.sql。 + * workflow 的 steps 顺序与字段 key 严格对应 app_config.steps。 + */ + +export interface ChatExample { + slug: string; + name: string; + kind: "chatbot" | "agent"; + input: string; +} + +export interface CompletionExample { + slug: string; + name: string; + kind: "completion"; + input: string; +} + +export interface WorkflowStepInput { + label: string; + type: "text" | "textarea" | "select"; + value: string; +} + +export interface WorkflowExample { + slug: string; + name: string; + kind: "workflow"; + steps: WorkflowStepInput[]; +} + +export type AppExample = ChatExample | CompletionExample | WorkflowExample; + +export const chatExamples: ChatExample[] = [ + { + slug: "law-news-summary", + name: "法治新闻摘要", + kind: "chatbot", + input: + "请为以下新闻生成摘要:某市中级人民法院今日对一起特大电信网络诈骗案作出一审宣判,主犯王某因诈骗罪、组织领导犯罪集团罪被判处有期徒刑十五年,并处罚金。该犯罪集团两年间骗取全国受害人共计三千余万元。", + }, + { + slug: "case-analysis-law", + name: "典型案例解读", + kind: "chatbot", + input: + "请解读这起案例:一名外卖骑手深夜送餐途中,发现路边有人持刀抢劫,遂上前制止并将抢劫者打伤。法院认定骑手的行为构成正当防卫,不负刑事责任。请分析裁判要旨与法律适用。", + }, + { + slug: "law-provision-qa", + name: "法规条文查询", + kind: "chatbot", + input: "《中华人民共和国民法典》关于合同解除的法定情形有哪些?请列出相关条文。", + }, + { + slug: "legal-public-opinion", + name: "法治舆情监测", + kind: "chatbot", + input: + "请研判以下舆情:某地一起医患纠纷视频在网络流传,患者家属情绪激动冲击医院,引发网友对医疗纠纷处理机制的广泛讨论,部分声音质疑医院责任,也有观点呼吁理性维权。请分析舆论走向并给出引导建议。", + }, + { + slug: "law-writing-polish", + name: "法治写作润色", + kind: "chatbot", + input: + "请润色以下评论片段,使其更专业有说服力:现在网络谣言太多了,很多人随便转发,造成很坏的影响,应该严厉打击,让造谣的人付出代价。", + }, +]; + +export const completionExamples: CompletionExample[] = [ + { + slug: "case-report-gen", + name: "案件报道生成", + kind: "completion", + input: + "案件类型:刑事案件\n案件概要:被告人李某利用职务便利,挪用公司资金二百万元用于个人炒股,案发后已全部退还\n审理法院与时间:某区人民法院,2024年3月\n当事人情况:李某,男,38岁,某公司财务经理\n审理结果与法律依据:以挪用资金罪判处有期徒刑两年,缓刑三年,依据《刑法》第二百七十二条", + }, + { + slug: "law-propaganda-gen", + name: "法治宣传文案", + kind: "completion", + input: + "普法主题:防范养老诈骗\n目标受众:老年人\n宣传形式偏好:社区宣传栏海报 + 短视频\n重点强调内容:识别以高额返利、免费体检为名的常见诈骗套路", + }, + { + slug: "interview-outline-gen", + name: "采访提纲生成", + kind: "completion", + input: + "采访主题:未成年人网络保护立法进展\n受访对象:参与立法调研的法学专家\n采访目的:了解立法重点与难点\n重点关注的问题方向:平台责任、家长监护、个人信息保护", + }, + { + slug: "law-comment-gen", + name: "法治评论撰写", + kind: "completion", + input: + "评论对象:高空抛物入刑后的治理成效\n事件概要:刑法修正案(十一)将高空抛物罪入刑以来,多地宣判典型案例,居民安全意识提升\n立场倾向:肯定立法成效,同时呼吁源头治理\n字数要求:1000字左右", + }, +]; + +export const workflowExamples: WorkflowExample[] = [ + { + slug: "topic-planning", + name: "选题策划助手", + kind: "workflow", + steps: [ + { label: "选题方向", type: "text", value: "未成年人网络保护" }, + { label: "选题由头", type: "textarea", value: "近期多起未成年人巨额游戏充值、网络打赏纠纷引发社会关注,相关立法正在推进" }, + { label: "目标受众", type: "select", value: "普通公众" }, + { label: "报道形式", type: "select", value: "深度报道" }, + { label: "特殊要求", type: "textarea", value: "配合普法宣传月,突出平台责任与家长监护双重视角" }, + ], + }, + { + slug: "omnichannel-publish", + name: "法治意识调查报告", + kind: "workflow", + steps: [ + { label: "调查区域与样本", type: "text", value: "示范市,样本量2000人,覆盖城乡各年龄段" }, + { label: "调查维度", type: "textarea", value: "法律知晓度、维权意识、守法行为、司法信任、普法需求" }, + { label: "调查数据", type: "textarea", value: "法律知晓度68%,主动维权意愿55%,司法信任度72%,普法需求最高的是劳动权益与消费维权" }, + { label: "对比基准", type: "select", value: "与上年数据对比" }, + { label: "重点关注", type: "textarea", value: "重点分析青年群体维权意识与老年群体防诈骗意识" }, + ], + }, + { + slug: "special-report", + name: "专题报道框架", + kind: "workflow", + steps: [ + { label: "专题主题", type: "text", value: "民法典实施三周年观察" }, + { label: "专题背景", type: "textarea", value: "民法典施行三年,在婚姻家庭、合同、物权等领域产生广泛影响,多项配套司法解释陆续出台" }, + { label: "报道周期", type: "select", value: "一周系列" }, + { label: "切入角度", type: "textarea", value: "从典型案例切入,展现民法典如何走进百姓生活" }, + { label: "媒介形式", type: "select", value: "图文+视频" }, + ], + }, + { + slug: "legal-topic-plan", + name: "法律专题策划", + kind: "workflow", + steps: [ + { label: "法律领域", type: "text", value: "个人信息保护法" }, + { label: "普法目标", type: "textarea", value: "让公众了解个人信息权益与维权途径,提升企业合规意识" }, + { label: "目标人群", type: "select", value: "全体公众" }, + { label: "传播渠道", type: "textarea", value: "报纸、客户端、抖音短视频、社区线下活动" }, + { label: "策划周期", type: "text", value: "国家宪法日宣传周" }, + ], + }, +]; + +export const agentExamples: ChatExample[] = [ + { + slug: "topic-intel-agent", + name: "法治选题智能助手", + kind: "agent", + input: "围绕电信网络诈骗治理,请追踪相关立法动态、分析舆情态势,并推荐3个值得报道的选题角度。", + }, + { + slug: "content-creation-agent", + name: "法治内容创作助手", + kind: "agent", + input: "请围绕高空抛物治理,查找相关法条与典型案例,创作一篇面向社区居民的普法报道,并做润色。", + }, +]; \ No newline at end of file diff --git a/apps/web/package-lock.json b/apps/web/package-lock.json index 10ec9de..e39c55a 100644 --- a/apps/web/package-lock.json +++ b/apps/web/package-lock.json @@ -29,6 +29,7 @@ }, "devDependencies": { "@eslint/js": "^9.0.0", + "@playwright/test": "^1.61.1", "@tailwindcss/postcss": "^4", "@types/node": "^20", "@types/react": "^19", @@ -1975,6 +1976,22 @@ "url": "https://opencollective.com/pkgr" } }, + "node_modules/@playwright/test": { + "version": "1.61.1", + "resolved": "https://registry.npmmirror.com/@playwright/test/-/test-1.61.1.tgz", + "integrity": "sha512-8nKv6+0RJSL9FE4jYOEGXnPeM/Hg12qZpmqzZjRh3qM0Y7c3z1mrOTfFLids72RDQYVh9WpLEfR5WdpNX4fkig==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.61.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@radix-ui/primitive": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", @@ -5960,6 +5977,20 @@ "node": ">=14.14" } }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -9470,6 +9501,38 @@ "node": ">=16.20.0" } }, + "node_modules/playwright": { + "version": "1.61.1", + "resolved": "https://registry.npmmirror.com/playwright/-/playwright-1.61.1.tgz", + "integrity": "sha512-DWnY5o3YbLWK4GovuAVwpqL+1VwGNdUGrRr++8j8PtQQzvAVZUIMjKQ90fY689sEJZJBbZVw1rXaOKSTitkzPQ==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.61.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.61.1", + "resolved": "https://registry.npmmirror.com/playwright-core/-/playwright-core-1.61.1.tgz", + "integrity": "sha512-h7Qlt6m4REp25qvIdvbDtVmD4LqVXfpRxhORv9L0jzETM05p4fuPJ3dKyuSXQxDSbXnmS79HAgi9589lGSpLkg==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", diff --git a/apps/web/package.json b/apps/web/package.json index c97b7c8..8c2da70 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -6,7 +6,10 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "eslint" + "lint": "eslint", + "test:e2e": "playwright test", + "test:e2e:ui": "playwright test --ui", + "test:e2e:report": "playwright show-report e2e/.report" }, "dependencies": { "@base-ui/react": "^1.4.1", @@ -30,6 +33,7 @@ }, "devDependencies": { "@eslint/js": "^9.0.0", + "@playwright/test": "^1.61.1", "@tailwindcss/postcss": "^4", "@types/node": "^20", "@types/react": "^19", diff --git a/apps/web/playwright.config.ts b/apps/web/playwright.config.ts new file mode 100644 index 0000000..27010c9 --- /dev/null +++ b/apps/web/playwright.config.ts @@ -0,0 +1,36 @@ +import { defineConfig, devices } from "@playwright/test"; + +const BASE_URL = process.env.E2E_BASE_URL || "http://localhost:3000"; + +export default defineConfig({ + testDir: "./e2e", + outputDir: "./e2e/.artifacts", + fullyParallel: false, + forbidOnly: !!process.env.CI, + retries: 0, + workers: 2, + reporter: [["list"], ["html", { outputFolder: "./e2e/.report", open: "never" }]], + timeout: 120_000, + expect: { timeout: 90_000 }, + use: { + baseURL: BASE_URL, + trace: "retain-on-failure", + screenshot: "only-on-failure", + actionTimeout: 30_000, + locale: "zh-CN", + }, + projects: [ + { + name: "setup", + testMatch: /auth\.setup\.ts/, + }, + { + name: "apps", + use: { + ...devices["Desktop Chrome"], + storageState: "./e2e/.auth/state.json", + }, + dependencies: ["setup"], + }, + ], +}); \ No newline at end of file diff --git a/apps/web/src/app/(auth)/login/page.tsx b/apps/web/src/app/(auth)/login/page.tsx index ec8d727..304b063 100644 --- a/apps/web/src/app/(auth)/login/page.tsx +++ b/apps/web/src/app/(auth)/login/page.tsx @@ -20,7 +20,7 @@ import { } from "lucide-react"; export default function LoginPage() { - const [email, setEmail] = useState("kj-admin@govai.gov.cn"); + const [email, setEmail] = useState("fazhiribao@govai.gov.cn"); const [password, setPassword] = useState("admin123"); const [loading, setLoading] = useState(false); const [errorMsg, setErrorMsg] = useState(""); diff --git a/server/migrations/seed_fazhiribao.sql b/server/migrations/seed_fazhiribao.sql new file mode 100644 index 0000000..a7a6d89 --- /dev/null +++ b/server/migrations/seed_fazhiribao.sql @@ -0,0 +1,290 @@ +-- 法制日报(法制网)应用种子数据:分类 + 15个应用 +-- 依赖:seed_fazhiribao_users.sql(机构与用户) +-- 可重复执行(ON CONFLICT DO NOTHING) + +DO $$ +DECLARE + creator_id UUID; + fazhi_org UUID := 'a0000000-0000-0000-0000-00000000000a'; + cat_news UUID; + cat_law UUID; + cat_publicity UUID; + cat_commentary UUID; +BEGIN + SELECT id INTO creator_id FROM users WHERE email = 'fazhibian@govai.gov.cn'; + + -- ========== 分类数据 ========== + INSERT INTO categories (name, slug, icon, sort_order, org_id) VALUES + ('法治新闻采编', 'fazhi-news', 'newspaper', 1, fazhi_org), + ('法律法规解读', 'fazhi-law', 'scale', 2, fazhi_org), + ('普法宣传', 'fazhi-publicity', 'megaphone', 3, fazhi_org), + ('法治评论', 'fazhi-commentary', 'message-square', 4, fazhi_org) + ON CONFLICT (slug) DO NOTHING; + + SELECT id INTO cat_news FROM categories WHERE slug = 'fazhi-news'; + SELECT id INTO cat_law FROM categories WHERE slug = 'fazhi-law'; + SELECT id INTO cat_publicity FROM categories WHERE slug = 'fazhi-publicity'; + SELECT id INTO cat_commentary FROM categories WHERE slug = 'fazhi-commentary'; + + -- ========== 对话型应用(5个)========== + + -- 1. 法治新闻摘要 + INSERT INTO applications (id, name, slug, description, long_description, icon_url, category_id, creator_id, org_id, + dify_app_type, status, visibility, is_featured, usage_count, avg_rating, rating_count, version, + app_config, welcome_message, suggested_prompts, published_at) + VALUES ( + 'e0000000-0000-0000-0000-000000000001', + '法治新闻摘要', 'law-news-summary', + '快速提炼法治新闻核心要点,生成规范的新闻摘要', + E'## 功能介绍\n\n面向法治新闻编辑的智能摘要工具:\n\n- 提取法治新闻核心事实\n- 梳理事件时间线与关键人物\n- 标注涉及的法律法规\n- 生成不同字数版本的摘要\n\n## 使用方法\n\n粘贴法治新闻原文,即可获得结构化摘要。', + '📰', cat_news, creator_id, fazhi_org, + 'chatbot', 'approved', 'public', true, 386, 4.7, 52, '1.0', + '{"system_prompt": "你是法治日报的资深新闻编辑,擅长提炼法治新闻要点。请对用户提供的新闻进行摘要,输出包括:核心事实、关键人物、涉及法律、事件意义。语言简洁、客观、准确。", "model": "qwen-plus", "temperature": 0.3, "max_tokens": 3000}', + '您好,我是法治新闻摘要助手。请粘贴新闻原文,我来为您提炼核心要点。', + '["请为这则关于网络诈骗案宣判的新闻生成摘要", "提炼这篇民法典普法报道的要点", "总结这起行政诉讼案件的关键信息"]', + NOW() + ) ON CONFLICT (id) DO NOTHING; + + -- 2. 典型案例解读 + INSERT INTO applications (id, name, slug, description, long_description, icon_url, category_id, creator_id, org_id, + dify_app_type, status, visibility, is_featured, usage_count, avg_rating, rating_count, version, + app_config, welcome_message, suggested_prompts, published_at) + VALUES ( + 'e0000000-0000-0000-0000-000000000002', + '典型案例解读', 'case-analysis-law', + '深度解读典型司法案例,提炼裁判要旨与法律启示', + E'## 功能介绍\n\n面向法治报道的案例解读工具:\n\n- 梳理案件事实与争议焦点\n- 解读裁判要旨与法律适用\n- 提炼案例的指导意义\n- 输出通俗版与专业版双版本\n\n## 使用方法\n\n输入案件信息或判决书内容,获取专业解读。', + '⚖️', cat_law, creator_id, fazhi_org, + 'chatbot', 'approved', 'public', true, 512, 4.8, 68, '1.0', + '{"system_prompt": "你是法治日报的法律专家兼普法工作者。请对用户提供的典型案例进行解读,输出两部分:①专业分析(争议焦点、裁判要旨、法律适用、指导意义);②通俗解读(面向普通读者的白话版)。引用法条使用《法律名》第X条格式。所有解读末尾附:本解读仅供参考,具体以司法机关裁判为准。", "model": "qwen-plus", "temperature": 0.3, "max_tokens": 5000}', + '您好,我是典型案例解读助手。请提供案件信息或判决书内容,我来为您深度解读。', + '["解读最高法发布的正当防卫典型案例", "分析这起高空抛物入刑案件的裁判要旨", "解读一起个人信息保护民事公益诉讼案"]', + NOW() + ) ON CONFLICT (id) DO NOTHING; + + -- 3. 法规条文查询 + INSERT INTO applications (id, name, slug, description, long_description, icon_url, category_id, creator_id, org_id, + dify_app_type, status, visibility, is_featured, usage_count, avg_rating, rating_count, version, + app_config, welcome_message, suggested_prompts, published_at) + VALUES ( + 'e0000000-0000-0000-0000-000000000003', + '法规条文查询', 'law-provision-qa', + '精准检索法律法规、司法解释条文,支持法条关联与时效提示', + E'## 功能介绍\n\n法律法规智能检索工具:\n\n- 精准检索现行法律法规条文\n- 查询司法解释与指导案例\n- 法条关联与新旧版本对比\n- 时效性提示(生效/修订/废止)\n\n## 使用方法\n\n输入法律问题或法条关键词,获取精准检索结果。', + '🔍', cat_law, creator_id, fazhi_org, + 'chatbot', 'approved', 'public', false, 478, 4.6, 61, '1.0', + '{"system_prompt": "你是法律法规检索专家,熟悉中国现行法律法规、司法解释。请精准检索并解读相关条文,引用格式:《法律名》第X条。注明法规的生效日期和最新修订版本。如涉及多个法规,按法律层级排列(宪法>法律>行政法规>部门规章)。", "model": "qwen-plus", "temperature": 0.2, "max_tokens": 4000}', + '您好,我是法规条文查询助手。请输入您要检索的法律问题或法条关键词。', + '["《民法典》关于合同解除的条款有哪些?", "正当防卫的法律规定及司法解释", "刑法修正案(十一)新增了哪些罪名?"]', + NOW() + ) ON CONFLICT (id) DO NOTHING; + + -- 4. 法治舆情监测 + INSERT INTO applications (id, name, slug, description, long_description, icon_url, category_id, creator_id, org_id, + dify_app_type, status, visibility, is_featured, usage_count, avg_rating, rating_count, version, + app_config, welcome_message, suggested_prompts, published_at) + VALUES ( + 'e0000000-0000-0000-0000-000000000004', + '法治舆情监测', 'legal-public-opinion', + '监测分析法治领域热点舆情,研判走向并提供应对建议', + E'## 功能介绍\n\n法治舆情智能研判工具:\n\n- 分析法治热点事件舆论走向\n- 梳理各方观点与争议焦点\n- 评估社会影响与传播态势\n- 提供舆论引导建议\n\n## 使用方法\n\n描述舆情事件,获取专业研判分析。', + '📡', cat_news, creator_id, fazhi_org, + 'chatbot', 'approved', 'public', false, 234, 4.5, 32, '1.0', + '{"system_prompt": "你是法治舆情分析专家,服务于法治日报舆情研判工作。请对用户描述的舆情事件进行分析,输出:事件概述、舆论走向、各方观点、法治视角研判、引导建议。分析应客观理性,注重法治价值导向。", "model": "qwen-plus", "temperature": 0.4, "max_tokens": 4000}', + '您好,我是法治舆情监测助手。请描述您关注的舆情事件,我来为您研判分析。', + '["分析某明星偷逃税事件的舆论走向", "研判一起医患纠纷引发的网络热议", "某地城管执法争议的舆情态势分析"]', + NOW() + ) ON CONFLICT (id) DO NOTHING; + + -- 5. 法治写作润色 + INSERT INTO applications (id, name, slug, description, long_description, icon_url, category_id, creator_id, org_id, + dify_app_type, status, visibility, is_featured, usage_count, avg_rating, rating_count, version, + app_config, welcome_message, suggested_prompts, published_at) + VALUES ( + 'e0000000-0000-0000-0000-000000000005', + '法治写作润色', 'law-writing-polish', + '对法治类文章、稿件进行专业润色,提升表达质量', + E'## 功能介绍\n\n法治文稿专业润色工具:\n\n- 优化语言表达与逻辑结构\n- 规范法律术语使用\n- 校正法条引用格式\n- 调整文风以适配不同栏目\n\n## 使用方法\n\n粘贴稿件内容,说明润色要求,获取优化版本。', + '✒️', cat_commentary, creator_id, fazhi_org, + 'chatbot', 'approved', 'public', false, 312, 4.6, 44, '1.0', + '{"system_prompt": "你是法治日报的资深文字编辑,擅长法治类文稿润色。请对用户提供的稿件进行润色,包括:语言表达优化、逻辑结构调整、法律术语规范、法条引用校正。保持原意不变,提升专业性与可读性。如有事实或法律错误请指出。", "model": "qwen-plus", "temperature": 0.4, "max_tokens": 5000}', + '您好,我是法治写作润色助手。请粘贴您的稿件,并说明润色要求。', + '["润色这篇法治评论,使其更有说服力", "优化这篇普法文章的表达,让普通读者易懂", "校正这篇报道中的法律术语和法条引用"]', + NOW() + ) ON CONFLICT (id) DO NOTHING; + + -- ========== 补全型应用(4个)========== + + -- 6. 案件报道生成 + INSERT INTO applications (id, name, slug, description, long_description, icon_url, category_id, creator_id, org_id, + dify_app_type, status, visibility, is_featured, usage_count, avg_rating, rating_count, version, + app_config, welcome_message, published_at) + VALUES ( + 'e0000000-0000-0000-0000-000000000006', + '案件报道生成', 'case-report-gen', + '输入案件要素,生成结构完整、规范客观的法治案件报道', + E'## 功能介绍\n\n法治案件报道智能生成:\n\n- 根据案件要素生成新闻报道\n- 自动组织导语、主体、背景\n- 规范法律术语与法条引用\n- 客观中立,符合法治报道规范\n\n## 使用方法\n\n填写案件要素,一键生成报道初稿。', + '📝', cat_news, creator_id, fazhi_org, + 'completion', 'approved', 'public', true, 423, 4.7, 56, '1.0', + '{"system_prompt": "你是法治日报记者,请根据用户提供的案件要素,生成一篇结构完整、语言规范的法治新闻报道,包括:标题、导语、主体(事实经过、审理结果、法律依据)、背景链接。坚持客观中立,准确使用法律术语。涉及未决案件时使用审慎表述。", "input_label": "案件要素", "output_label": "案件报道", "input_placeholder": "请输入案件要素:\n1. 案件类型(刑事/民事/行政)\n2. 案件概要\n3. 审理法院与时间\n4. 当事人情况\n5. 审理结果与法律依据"}', + NULL, + NOW() + ) ON CONFLICT (id) DO NOTHING; + + -- 7. 法治宣传文案 + INSERT INTO applications (id, name, slug, description, long_description, icon_url, category_id, creator_id, org_id, + dify_app_type, status, visibility, is_featured, usage_count, avg_rating, rating_count, version, + app_config, welcome_message, published_at) + VALUES ( + 'e0000000-0000-0000-0000-000000000007', + '法治宣传文案', 'law-propaganda-gen', + '输入普法主题,生成多形式普法宣传文案', + E'## 功能介绍\n\n普法宣传文案智能生成:\n\n- 生成公众号推文、海报标语、口播稿\n- 针对不同受众定制表达\n- 通俗易懂,便于传播\n- 一次输出多种形式\n\n## 使用方法\n\n输入普法主题与受众要求,生成宣传文案。', + '📢', cat_publicity, creator_id, fazhi_org, + 'completion', 'approved', 'public', true, 389, 4.6, 51, '1.0', + '{"system_prompt": "你是普法宣传专家,请根据用户提供的主题,生成多形式普法宣传文案,包括:①微信公众号推文(800-1200字);②宣传标语(10条);③短视频口播稿(1分钟版)。语言通俗易懂、生动有趣,贴近群众生活,善用案例。", "input_label": "普法主题", "output_label": "宣传文案", "input_placeholder": "请输入普法主题与要求:\n1. 普法主题(如:防范养老诈骗)\n2. 目标受众(如:老年人)\n3. 宣传形式偏好\n4. 重点强调内容"}', + NULL, + NOW() + ) ON CONFLICT (id) DO NOTHING; + + -- 8. 采访提纲生成 + INSERT INTO applications (id, name, slug, description, long_description, icon_url, category_id, creator_id, org_id, + dify_app_type, status, visibility, is_featured, usage_count, avg_rating, rating_count, version, + app_config, welcome_message, published_at) + VALUES ( + 'e0000000-0000-0000-0000-000000000008', + '采访提纲生成', 'interview-outline-gen', + '根据采访主题与对象,生成结构化采访提纲', + E'## 功能介绍\n\n法治采访提纲智能生成:\n\n- 根据选题生成采访问题\n- 设计核心问题与追问策略\n- 分析受访对象特点\n- 提示采访注意事项\n\n## 使用方法\n\n输入采访主题与对象信息,生成提纲。', + '🎤', cat_news, creator_id, fazhi_org, + 'completion', 'approved', 'public', false, 267, 4.5, 35, '1.0', + '{"system_prompt": "你是资深法治记者,请根据用户提供的采访主题和对象,生成结构化采访提纲,包括:①受访对象分析;②采访目标;③核心问题(按逻辑分组,每组3-5问);④追问策略;⑤注意事项。问题应有深度、有针对性。", "input_label": "采访信息", "output_label": "采访提纲", "input_placeholder": "请输入采访信息:\n1. 采访主题\n2. 受访对象(身份/职务)\n3. 采访目的\n4. 重点关注的问题方向"}', + NULL, + NOW() + ) ON CONFLICT (id) DO NOTHING; + + -- 9. 法治评论撰写 + INSERT INTO applications (id, name, slug, description, long_description, icon_url, category_id, creator_id, org_id, + dify_app_type, status, visibility, is_featured, usage_count, avg_rating, rating_count, version, + app_config, welcome_message, published_at) + VALUES ( + 'e0000000-0000-0000-0000-000000000009', + '法治评论撰写', 'law-comment-gen', + '针对法治热点,生成观点鲜明、论据充分的评论文章', + E'## 功能介绍\n\n法治评论文章智能生成:\n\n- 针对热点事件提炼评论角度\n- 组织论点论据,逻辑严密\n- 体现法治价值导向\n- 适配评论栏目文风\n\n## 使用方法\n\n输入评论对象与立场倾向,生成评论文章。', + '💬', cat_commentary, creator_id, fazhi_org, + 'completion', 'approved', 'public', false, 298, 4.7, 41, '1.0', + '{"system_prompt": "你是法治日报评论员,请根据用户提供的热点事件,撰写一篇法治评论文章,包括:标题、引出话题、核心论点、论据论证、结论升华。观点鲜明、逻辑严密、论据充分,体现法治精神与社会责任。字数1000-1500字。", "input_label": "评论素材", "output_label": "评论文章", "input_placeholder": "请输入评论素材:\n1. 评论对象(事件/现象/案件)\n2. 事件概要\n3. 立场倾向或想强调的观点\n4. 字数要求"}', + NULL, + NOW() + ) ON CONFLICT (id) DO NOTHING; + + -- ========== 工作流型应用(4个)========== + + -- 10. 选题策划助手 + INSERT INTO applications (id, name, slug, description, long_description, icon_url, category_id, creator_id, org_id, + dify_app_type, status, visibility, is_featured, usage_count, avg_rating, rating_count, version, + app_config, welcome_message, published_at) + VALUES ( + 'e0000000-0000-0000-0000-00000000000a', + '选题策划助手', 'topic-planning', + '分步引导完成法治报道选题策划,生成完整策划方案', + E'## 功能介绍\n\n法治报道选题策划工具:\n\n- 分步收集选题要素\n- 评估新闻价值与报道角度\n- 生成完整策划方案\n- 提供资源与时间规划建议\n\n## 适用场景\n\n适用于法治新闻选题论证与策划。', + '💡', cat_news, creator_id, fazhi_org, + 'workflow', 'approved', 'public', true, 198, 4.6, 27, '1.0', + '{"system_prompt": "你是法治新闻策划专家,请根据用户分步提供的信息,生成完整的选题策划方案,包括:选题背景与新闻价值、报道角度、内容框架、呈现形式、采访对象建议、时间节点、传播策略。", "app_type": "workflow", "model": "qwen-plus", "temperature": 0.5, "max_tokens": 5000, "steps": [{"key": "topic", "label": "选题方向", "type": "text", "placeholder": "如:未成年人网络保护", "required": true}, {"key": "trigger", "label": "选题由头", "type": "textarea", "placeholder": "近期相关事件、政策或热点", "required": true}, {"key": "audience", "label": "目标受众", "type": "select", "options": ["普通公众", "法律从业者", "青少年", "企业经营者", "基层执法人员"], "required": true}, {"key": "format", "label": "报道形式", "type": "select", "options": ["深度报道", "系列报道", "图文专题", "短视频", "图文+视频融媒体"], "required": true}, {"key": "requirement", "label": "特殊要求", "type": "textarea", "placeholder": "如:配合普法宣传月、突出某个角度等"}]}', + '请填写选题信息,我将为您生成完整的选题策划方案。', + NOW() + ) ON CONFLICT (id) DO NOTHING; + + -- 11. 全民法治意识调查报告 + INSERT INTO applications (id, name, slug, description, long_description, icon_url, category_id, creator_id, org_id, + dify_app_type, status, visibility, is_featured, usage_count, avg_rating, rating_count, version, + app_config, welcome_message, published_at) + VALUES ( + 'e0000000-0000-0000-0000-00000000000b', + '法治意识调查报告', 'omnichannel-publish', + '分步输入调查数据,生成全民法治意识调查报告', + E'## 功能介绍\n\n法治意识调查报告生成:\n\n- 分步收集调查数据\n- 多维度分析法治意识水平\n- 对比研判趋势变化\n- 生成专业调查报告\n\n## 适用场景\n\n适用于普法效果评估与法治宣传调研。', + '📊', cat_publicity, creator_id, fazhi_org, + 'workflow', 'approved', 'public', false, 134, 4.5, 18, '1.0', + '{"system_prompt": "你是法治调研专家,请根据用户分步提供的调查数据,生成专业的全民法治意识调查报告,包括:调查概况、数据分析(分维度)、趋势对比、问题发现、原因分析、对策建议。报告应数据翔实、分析深入。", "app_type": "workflow", "model": "qwen-plus", "temperature": 0.3, "max_tokens": 6000, "steps": [{"key": "region", "label": "调查区域与样本", "type": "text", "placeholder": "如:XX市,样本量2000人", "required": true}, {"key": "dimensions", "label": "调查维度", "type": "textarea", "placeholder": "法律知晓度、维权意识、守法行为、司法信任、普法需求等", "required": true}, {"key": "data", "label": "调查数据", "type": "textarea", "placeholder": "请粘贴问卷统计结果或关键数据", "required": true}, {"key": "baseline", "label": "对比基准", "type": "select", "options": ["与上年数据对比", "与全国数据对比", "与其他地区对比", "无对比"], "required": true}, {"key": "focus", "label": "重点关注", "type": "textarea", "placeholder": "需重点分析的问题或群体"}]}', + '请填写调查信息,我将为您生成法治意识调查报告。', + NOW() + ) ON CONFLICT (id) DO NOTHING; + + -- 12. 专题报道框架 + INSERT INTO applications (id, name, slug, description, long_description, icon_url, category_id, creator_id, org_id, + dify_app_type, status, visibility, is_featured, usage_count, avg_rating, rating_count, version, + app_config, welcome_message, published_at) + VALUES ( + 'e0000000-0000-0000-0000-00000000000c', + '专题报道框架', 'special-report', + '分步输入专题信息,生成结构化的专题报道框架', + E'## 功能介绍\n\n法治专题报道框架生成:\n\n- 分步梳理专题脉络\n- 规划分集内容结构\n- 设计呈现形式\n- 生成完整报道框架\n\n## 适用场景\n\n适用于重大法治专题报道的前期规划。', + '📋', cat_news, creator_id, fazhi_org, + 'workflow', 'approved', 'public', true, 167, 4.7, 23, '1.0', + '{"system_prompt": "你是法治专题报道策划专家,请根据用户分步提供的信息,生成结构化的专题报道框架,包括:专题主旨、分集规划(5-8篇)、每篇核心内容与角度、呈现形式、采访资源、推进时间表。", "app_type": "workflow", "model": "qwen-plus", "temperature": 0.4, "max_tokens": 6000, "steps": [{"key": "subject", "label": "专题主题", "type": "text", "placeholder": "如:民法典实施三周年观察", "required": true}, {"key": "background", "label": "专题背景", "type": "textarea", "placeholder": "策划该专题的背景与意义", "required": true}, {"key": "duration", "label": "报道周期", "type": "select", "options": ["单期专题", "一周系列", "一月系列", "长期跟踪"], "required": true}, {"key": "angle", "label": "切入角度", "type": "textarea", "placeholder": "希望突出的角度或重点", "required": true}, {"key": "media", "label": "媒介形式", "type": "select", "options": ["纯图文", "图文+视频", "全媒体融合", "H5互动"], "required": true}]}', + '请填写专题信息,我将为您生成专题报道框架。', + NOW() + ) ON CONFLICT (id) DO NOTHING; + + -- 13. 法律专题策划 + INSERT INTO applications (id, name, slug, description, long_description, icon_url, category_id, creator_id, org_id, + dify_app_type, status, visibility, is_featured, usage_count, avg_rating, rating_count, version, + app_config, welcome_message, published_at) + VALUES ( + 'e0000000-0000-0000-0000-00000000000d', + '法律专题策划', 'legal-topic-plan', + '围绕特定法律领域,生成深度普法专题策划方案', + E'## 功能介绍\n\n法律专题深度策划工具:\n\n- 围绕法律领域系统策划\n- 整合法规、案例、解读\n- 设计普法传播路径\n- 生成完整专题方案\n\n## 适用场景\n\n适用于围绕某部法律或法律议题的深度普法策划。', + '⚖️', cat_publicity, creator_id, fazhi_org, + 'workflow', 'approved', 'public', false, 112, 4.6, 15, '1.0', + '{"system_prompt": "你是法律普法专题策划专家,请根据用户分步提供的信息,生成深度普法专题策划方案,包括:专题定位、核心法律点梳理、典型案例选取建议、内容产品规划(图文/视频/问答)、传播渠道与节奏、效果评估指标。", "app_type": "workflow", "model": "qwen-plus", "temperature": 0.4, "max_tokens": 6000, "steps": [{"key": "law_area", "label": "法律领域", "type": "text", "placeholder": "如:个人信息保护法", "required": true}, {"key": "goal", "label": "普法目标", "type": "textarea", "placeholder": "希望达到的普法效果", "required": true}, {"key": "target", "label": "目标人群", "type": "select", "options": ["全体公众", "特定行业从业者", "青少年群体", "老年群体", "企业经营者"], "required": true}, {"key": "channel", "label": "传播渠道", "type": "textarea", "placeholder": "如:报纸、客户端、抖音、社区活动等", "required": true}, {"key": "period", "label": "策划周期", "type": "text", "placeholder": "如:国家宪法日宣传周"}]}', + '请填写专题信息,我将为您生成法律专题策划方案。', + NOW() + ) ON CONFLICT (id) DO NOTHING; + + -- ========== 智能体型应用(2个)========== + + -- 14. 法治选题智能助手 + INSERT INTO applications (id, name, slug, description, long_description, icon_url, category_id, creator_id, org_id, + dify_app_type, status, visibility, is_featured, usage_count, avg_rating, rating_count, version, + app_config, welcome_message, suggested_prompts, published_at) + VALUES ( + 'e0000000-0000-0000-0000-00000000000e', + '法治选题智能助手', 'topic-intel-agent', + '多工具联动:追踪热点、检索法条、分析价值、生成选题建议', + E'## 功能介绍\n\n法治选题智能体,集成多种能力辅助选题决策:\n\n- 立法动态追踪:关注最新立法与政策\n- 舆情数据分析:研判热点传播态势\n- 法条检索:匹配相关法律法规\n- 选题建议:评估价值、推荐角度\n\n## 使用方法\n\n描述关注领域或事件,助手自动调用工具综合分析并推荐选题。', + '🧭', cat_news, creator_id, fazhi_org, + 'agent', 'approved', 'public', true, 156, 4.7, 21, '1.0', + '{"system_prompt": "你是法治选题智能助手,服务于法治日报编辑部选题工作。你具备以下能力:\n1. **立法动态追踪**:关注最新立法、修法与政策动向\n2. **舆情数据分析**:研判法治热点的传播态势\n3. **法条检索**:匹配事件相关的法律法规\n4. **选题建议**:评估新闻价值,推荐报道角度\n\n使用某能力时用 [工具调用: 工具名] 和 [工具结果: 工具名] 标记。输出选题建议时给出价值评估与角度推荐。", "tools": ["立法动态追踪", "舆情数据分析", "法条检索", "选题建议"]}', + '您好,我是法治选题智能助手。我可以追踪立法动态、分析舆情、检索法条并推荐选题。请描述您关注的领域或事件。', + '["最近有哪些值得报道的立法动态?", "围绕电信诈骗治理推荐3个选题角度", "分析未成年人保护领域的报道机会"]', + NOW() + ) ON CONFLICT (id) DO NOTHING; + + -- 15. 法治内容创作助手 + INSERT INTO applications (id, name, slug, description, long_description, icon_url, category_id, creator_id, org_id, + dify_app_type, status, visibility, is_featured, usage_count, avg_rating, rating_count, version, + app_config, welcome_message, suggested_prompts, published_at) + VALUES ( + 'e0000000-0000-0000-0000-00000000000f', + '法治内容创作助手', 'content-creation-agent', + '多工具联动:查法条、写报道、配案例、润色审稿一站完成', + E'## 功能介绍\n\n法治内容创作智能体,端到端辅助内容生产:\n\n- 法条检索:查询相关法律依据\n- 案例匹配:检索关联典型案例\n- 内容创作:撰写报道、评论、普法稿\n- 润色审稿:优化表达、校正引用\n\n## 使用方法\n\n描述创作需求,助手自动调用工具完成从素材到成稿的全流程。', + '✨', cat_commentary, creator_id, fazhi_org, + 'agent', 'approved', 'public', true, 189, 4.8, 26, '1.0', + '{"system_prompt": "你是法治内容创作智能助手,服务于法治日报内容生产。你具备以下能力:\n1. **法条检索**:查询相关法律依据\n2. **案例匹配**:检索关联典型案例\n3. **内容创作**:撰写报道、评论、普法稿件\n4. **润色审稿**:优化表达、规范术语、校正法条引用\n\n使用某能力时用 [工具调用: 工具名] 和 [工具结果: 工具名] 标记。坚持客观准确、法治导向。涉及具体案件时审慎表述。", "tools": ["法条检索", "案例匹配", "内容创作", "润色审稿"]}', + '您好,我是法治内容创作助手。我可以查法条、配案例、写稿件、做润色。请描述您的创作需求。', + '["写一篇关于高空抛物治理的普法报道,配相关法条和案例", "围绕个人信息保护写一篇评论并润色", "帮我创作一篇消费者维权的普法文章"]', + NOW() + ) ON CONFLICT (id) DO NOTHING; + + -- ========== 设置发布时间 ========== + UPDATE applications SET published_at = NOW() + WHERE org_id = fazhi_org AND status = 'approved' AND published_at IS NULL; + +END $$; + +SELECT '法制日报应用种子数据插入成功!共15个应用、4个分类。' as status; \ No newline at end of file diff --git a/server/migrations/seed_fazhiribao_knowledge.sql b/server/migrations/seed_fazhiribao_knowledge.sql new file mode 100644 index 0000000..e8a4148 --- /dev/null +++ b/server/migrations/seed_fazhiribao_knowledge.sql @@ -0,0 +1,150 @@ +-- 法制日报(法制网)知识库种子数据:2个知识库 + 10篇文档 +-- 依赖:seed_fazhiribao_users.sql、seed_fazhiribao.sql +-- 可重复执行(ON CONFLICT DO NOTHING) + +DO $$ +DECLARE + creator_id UUID; + fazhi_org UUID := 'a0000000-0000-0000-0000-00000000000a'; + kb_lib_id UUID := 'e1000000-0000-0000-0000-000000000001'; + kb_norm_id UUID := 'e1000000-0000-0000-0000-000000000002'; +BEGIN + SELECT id INTO creator_id FROM users WHERE email = 'fazhibian@govai.gov.cn'; + + -- ========== 知识库 ========== + + -- 1. 法治日报精选文库 + INSERT INTO knowledge_bases (id, name, description, owner_id, org_id, visibility, doc_count, total_chars, status) + VALUES ( + kb_lib_id, + '法治日报精选文库', + '收录宪法、民法典、刑法等核心法律条文及新法速递、典型案例汇编,服务法规检索与案例解读', + creator_id, fazhi_org, 'department', 5, 28000, 'active' + ) ON CONFLICT (id) DO NOTHING; + + -- 2. 法治新闻报道规范 + INSERT INTO knowledge_bases (id, name, description, owner_id, org_id, visibility, doc_count, total_chars, status) + VALUES ( + kb_norm_id, + '法治新闻报道规范', + '收录法治新闻写作规范、法律术语使用指南、敏感信息处理规则、法条引述格式标准及优秀报道点评', + creator_id, fazhi_org, 'department', 5, 22000, 'active' + ) ON CONFLICT (id) DO NOTHING; + + -- ========== 精选文库文档 ========== + + -- 文档1:宪法条文精选 + INSERT INTO knowledge_documents (id, kb_id, name, file_type, char_count, indexing_status, uploader_id, content) + VALUES ( + 'e2000000-0000-0000-0000-000000000001', kb_lib_id, + '宪法条文精选', 'txt', 5000, 'completed', creator_id, + E'中华人民共和国宪法(节选)\n\n第一章 总纲\n\n第五条 中华人民共和国实行依法治国,建设社会主义法治国家。\n国家维护社会主义法制的统一和尊严。\n一切法律、行政法规和地方性法规都不得同宪法相抵触。\n一切国家机关和武装力量、各政党和各社会团体、各企业事业组织都必须遵守宪法和法律。一切违反宪法和法律的行为,必须予以追究。\n任何组织或者个人都不得有超越宪法和法律的特权。\n\n第二章 公民的基本权利和义务\n\n第三十三条 凡具有中华人民共和国国籍的人都是中华人民共和国公民。\n中华人民共和国公民在法律面前一律平等。\n国家尊重和保障人权。\n任何公民享有宪法和法律规定的权利,同时必须履行宪法和法律规定的义务。\n\n第三十五条 中华人民共和国公民有言论、出版、集会、结社、游行、示威的自由。\n\n第三十七条 中华人民共和国公民的人身自由不受侵犯。\n任何公民,非经人民检察院批准或者决定或者人民法院决定,并由公安机关执行,不受逮捕。\n禁止非法拘禁和以其他方法非法剥夺或者限制公民的人身自由,禁止非法搜查公民的身体。\n\n第三十八条 中华人民共和国公民的人格尊严不受侵犯。禁止用任何方法对公民进行侮辱、诽谤和诬告陷害。\n\n第四十一条 中华人民共和国公民对于任何国家机关和国家工作人员,有提出批评和建议的权利;对于任何国家机关和国家工作人员的违法失职行为,有向有关国家机关提出申诉、控告或者检举的权利。' + ) ON CONFLICT (id) DO NOTHING; + + -- 文档2:民法典重点条款 + INSERT INTO knowledge_documents (id, kb_id, name, file_type, char_count, indexing_status, uploader_id, content) + VALUES ( + 'e2000000-0000-0000-0000-000000000002', kb_lib_id, + '民法典重点条款', 'txt', 6000, 'completed', creator_id, + E'中华人民共和国民法典(重点条款摘录,2021年1月1日施行)\n\n第一编 总则\n\n第一条 为了保护民事主体的合法权益,调整民事关系,维护社会和经济秩序,适应中国特色社会主义发展要求,弘扬社会主义核心价值观,根据宪法,制定本法。\n\n第三条 民事主体的人身权利、财产权利以及其他合法权益受法律保护,任何组织或者个人不得侵犯。\n\n第一百一十条 自然人享有生命权、身体权、健康权、姓名权、肖像权、名誉权、荣誉权、隐私权、婚姻自主权等权利。\n\n第一编 总则·民事法律行为\n\n第一百四十三条 具备下列条件的民事法律行为有效:(一)行为人具有相应的民事行为能力;(二)意思表示真实;(三)不违反法律、行政法规的强制性规定,不违背公序良俗。\n\n第四编 人格权\n\n第一千零三十二条 自然人享有隐私权。任何组织或者个人不得以刺探、侵扰、泄露、公开等方式侵害他人的隐私权。\n隐私是自然人的私人生活安宁和不愿为他人知晓的私密空间、私密活动、私密信息。\n\n第一千零三十四条 自然人的个人信息受法律保护。\n个人信息是以电子或者其他方式记录的能够单独或者与其他信息结合识别特定自然人的各种信息。\n\n第六编 合同·合同的解除\n\n第五百六十三条 有下列情形之一的,当事人可以解除合同:(一)因不可抗力致使不能实现合同目的;(二)在履行期限届满前,当事人一方明确表示或者以自己的行为表明不履行主要债务;(三)当事人一方迟延履行主要债务,经催告后在合理期限内仍未履行;(四)当事人一方迟延履行债务或者有其他违约行为致使不能实现合同目的;(五)法律规定的其他情形。\n\n第七编 侵权责任·高空抛物\n\n第一千二百五十四条 禁止从建筑物中抛掷物品。从建筑物中抛掷物品或者从建筑物上坠落的物品造成他人损害的,由侵权人依法承担侵权责任;经调查难以确定具体侵权人的,除能够证明自己不是侵权人的外,由可能加害的建筑物使用人给予补偿。' + ) ON CONFLICT (id) DO NOTHING; + + -- 文档3:刑法修正案对比 + INSERT INTO knowledge_documents (id, kb_id, name, file_type, char_count, indexing_status, uploader_id, content) + VALUES ( + 'e2000000-0000-0000-0000-000000000003', kb_lib_id, + '刑法修正案对比', 'txt', 5500, 'completed', creator_id, + E'刑法修正案(十一)重点修订对比(2021年3月1日施行)\n\n一、刑事责任年龄调整\n修订前:已满十四周岁不满十六周岁的人,仅对八类严重犯罪负刑事责任。\n修订后:已满十二周岁不满十四周岁的人,犯故意杀人、故意伤害罪,致人死亡或者以特别残忍手段致人重伤造成严重残疾,情节恶劣,经最高人民检察院核准追诉的,应当负刑事责任。\n意义:回应低龄未成年人恶性犯罪的社会关切,有限度下调刑事责任年龄。\n\n二、高空抛物入刑\n新增第二百九十一条之二:从建筑物或者其他高空抛掷物品,情节严重的,处一年以下有期徒刑、拘役或者管制,并处或者单处罚金。\n意义:将"头顶上的安全"纳入刑法保护,明确高空抛物的刑事责任。\n\n三、冒名顶替入刑\n新增第二百八十条之二:盗用、冒用他人身份,顶替他人取得的高等学历教育入学资格、公务员录用资格、就业安置待遇的,处三年以下有期徒刑、拘役或者管制,并处罚金。\n意义:回应"冒名顶替上大学"等事件,维护教育公平和社会公正。\n\n四、催收非法债务罪\n新增第二百九十三条之一:有下列情形之一,催收高利放贷等产生的非法债务,情节严重的,处三年以下有期徒刑、拘役或者管制,并处或者单处罚金:(一)使用暴力、胁迫方法的;(二)限制他人人身自由或者侵入他人住宅的;(三)恐吓、跟踪、骚扰他人的。\n意义:针对"套路贷"暴力催收行为,强化对公民人身权利的保护。\n\n五、药品领域犯罪\n修订妨害药品管理罪,加大对生产销售假药劣药行为的打击力度,回应人民群众用药安全关切。' + ) ON CONFLICT (id) DO NOTHING; + + -- 文档4:新法速递解读 + INSERT INTO knowledge_documents (id, kb_id, name, file_type, char_count, indexing_status, uploader_id, content) + VALUES ( + 'e2000000-0000-0000-0000-000000000004', kb_lib_id, + '新法速递解读', 'txt', 5500, 'completed', creator_id, + E'近年重要新法速递解读\n\n一、《个人信息保护法》(2021年11月1日施行)\n核心要点:\n1. 确立个人信息处理的"告知—同意"规则\n2. 单独同意:处理敏感个人信息、向第三方提供、公开个人信息需取得单独同意\n3. 大型平台义务:建立合规制度、定期发布社会责任报告\n4. "大数据杀熟"禁止:自动化决策不得对个人在交易价格等方面实行不合理差别待遇\n5. 个人权利:知情权、决定权、查阅复制权、可携带权、删除权\n违法后果:最高可处五千万元或上一年度营业额百分之五的罚款。\n\n二、《反电信网络诈骗法》(2022年12月1日施行)\n核心要点:\n1. 电话卡、银行卡实名制与数量限制\n2. 金融机构尽职调查义务\n3. 涉诈资金紧急止付、快速冻结、及时返还制度\n4. 对涉诈人员的惩戒措施\n5. 反诈宣传教育责任\n\n三、《家庭教育促进法》(2022年1月1日施行)\n核心要点:\n1. "依法带娃":明确父母或其他监护人的家庭教育主体责任\n2. 国家与社会支持家庭教育\n3. 公检法可对失职监护人发出家庭教育指导令\n意义:将家庭教育从"家事"上升为"国事"。\n\n四、《妇女权益保障法》(2023年1月1日修订施行)\n核心要点:\n1. 完善性骚扰防治机制\n2. 强化就业性别歧视的法律责任\n3. 加强人身安全保护,完善人身安全保护令\n4. 保障农村妇女土地权益' + ) ON CONFLICT (id) DO NOTHING; + + -- 文档5:典型案例汇编 + INSERT INTO knowledge_documents (id, kb_id, name, file_type, char_count, indexing_status, uploader_id, content) + VALUES ( + 'e2000000-0000-0000-0000-000000000005', kb_lib_id, + '典型案例汇编', 'txt', 6000, 'completed', creator_id, + E'法治典型案例汇编\n\n案例一:正当防卫认定——"昆山反杀案"\n基本案情:刘某酒后驾车,与骑车的于某发生争执,刘某持砍刀攻击于某,砍刀脱手后被于某捡起,于某反击致刘某死亡。\n处理结果:检察机关认定于某的行为属于正当防卫,不负刑事责任。\n指导意义:明确正当防卫的认定标准,"法不能向不法让步",鼓励公民勇于同不法侵害作斗争。\n\n案例二:高空抛物——某小区高空抛物损害责任案\n基本案情:某小区一住户从高层抛下杂物,砸坏楼下停放车辆,经调查锁定具体侵权人。\n处理结果:侵权人依法承担全部赔偿责任,情节严重的依高空抛物罪追究刑事责任。\n指导意义:警示高空抛物的法律后果,保护"头顶上的安全"。\n\n案例三:个人信息保护——APP违法收集个人信息案\n基本案情:某APP在用户不知情情况下超范围收集个人信息并提供给第三方。\n处理结果:监管部门责令整改并处罚款,受害用户提起民事公益诉讼获支持。\n指导意义:明确APP运营者的个人信息保护义务,落实"告知—同意"规则。\n\n案例四:消费者权益——"知假买假"惩罚性赔偿案\n基本案情:消费者购买到不符合食品安全标准的食品,主张十倍赔偿。\n处理结果:法院支持消费者的惩罚性赔偿请求。\n指导意义:明确食品安全领域惩罚性赔偿规则,保护消费者合法权益。\n\n案例五:网络谣言——编造传播疫情谣言案\n基本案情:行为人在网络上编造虚假疫情信息并大量传播,造成社会恐慌。\n处理结果:依据治安管理处罚法予以行政拘留,情节严重的追究刑事责任。\n指导意义:警示网络不是法外之地,编造传播谣言要承担法律责任。' + ) ON CONFLICT (id) DO NOTHING; + +END $$; + +-- ========== 报道规范文库文档 + 应用关联 ========== +DO $$ +DECLARE + creator_id UUID; + fazhi_org UUID := 'a0000000-0000-0000-0000-00000000000a'; + kb_lib_id UUID := 'e1000000-0000-0000-0000-000000000001'; + kb_norm_id UUID := 'e1000000-0000-0000-0000-000000000002'; +BEGIN + SELECT id INTO creator_id FROM users WHERE email = 'fazhibian@govai.gov.cn'; + + -- 文档6:法治新闻写作规范 + INSERT INTO knowledge_documents (id, kb_id, name, file_type, char_count, indexing_status, uploader_id, content) + VALUES ( + 'e2000000-0000-0000-0000-000000000006', kb_norm_id, + '法治新闻写作规范', 'txt', 4500, 'completed', creator_id, + E'法治新闻写作规范\n\n一、基本原则\n1. 客观真实:以事实为依据,不夸大、不渲染、不臆测\n2. 准确严谨:准确使用法律术语,正确表述法律关系\n3. 平衡报道:兼顾各方立场,避免"舆论审判"\n4. 法治导向:传播法治理念,引导依法办事\n\n二、案件报道注意事项\n1. 未决案件:使用"涉嫌""犯罪嫌疑人""被告人"等审慎表述,不得提前定性\n2. 罪与非罪:未经法院判决,不得称当事人为"罪犯"\n3. 隐私保护:依法保护当事人隐私,未成年人、性侵案件被害人信息须隐去\n4. 程序表述:准确区分"立案侦查""提起公诉""一审判决""终审"等不同诉讼阶段\n\n三、结构要素\n1. 标题:客观准确,不做"标题党"\n2. 导语:概括核心事实(何时、何地、何人、何事、何因、何果)\n3. 主体:按逻辑展开事实经过、处理结果、法律依据\n4. 背景:补充相关法律法规、类似案例、专家解读\n\n四、常见错误\n1. 混淆"逮捕"与"拘留""刑事拘留"与"行政拘留"\n2. 将"判处有期徒刑X年"误写为"判刑X年"\n3. 将民事案件的"被告"误写为刑事案件的"被告人"\n4. 法条引用不规范,未注明法律全称与条款序号' + ) ON CONFLICT (id) DO NOTHING; + + -- 文档7:法律术语使用指南 + INSERT INTO knowledge_documents (id, kb_id, name, file_type, char_count, indexing_status, uploader_id, content) + VALUES ( + 'e2000000-0000-0000-0000-000000000007', kb_norm_id, + '法律术语使用指南', 'txt', 4500, 'completed', creator_id, + E'法律术语使用指南\n\n一、刑事诉讼术语\n- 犯罪嫌疑人:侦查、审查起诉阶段的称谓\n- 被告人:审判阶段的称谓\n- 罪犯/服刑人员:判决生效后的称谓\n- 刑事拘留:侦查阶段的强制措施(公安机关)\n- 逮捕:需经检察院批准或法院决定\n- 提起公诉:检察机关向法院起诉\n- 不起诉:检察机关决定不向法院起诉\n\n二、民事诉讼术语\n- 原告/被告:民事案件双方当事人\n- 起诉/应诉:提起诉讼与应对诉讼\n- 一审/二审/再审:审级表述\n- 调解/判决:纠纷解决方式\n- 执行:判决生效后的强制履行\n\n三、行政诉讼术语\n- 行政相对人:行政行为的对象\n- 行政复议:向上级行政机关申请审查\n- 行政诉讼:"民告官"\n\n四、易混淆术语辨析\n1. "定金"vs"订金":定金有担保性质,适用定金罚则;订金一般可退\n2. "拘役"vs"拘留":拘役是刑罚;拘留是强制措施或行政处罚\n3. "假释"vs"缓刑":假释是服刑后附条件提前释放;缓刑是暂缓执行\n4. "无期徒刑"vs"死缓":性质不同的刑罚\n5. "罚款"vs"罚金":罚款是行政处罚;罚金是刑罚' + ) ON CONFLICT (id) DO NOTHING; + + -- 文档8:敏感信息处理规则 + INSERT INTO knowledge_documents (id, kb_id, name, file_type, char_count, indexing_status, uploader_id, content) + VALUES ( + 'e2000000-0000-0000-0000-000000000008', kb_norm_id, + '敏感信息处理规则', 'txt', 4000, 'completed', creator_id, + E'法治报道敏感信息处理规则\n\n一、必须隐去或处理的信息\n1. 未成年人:涉案未成年人的姓名、住所、就读学校、照片等可能推断其身份的信息\n2. 性侵案件被害人:姓名、住所、工作单位等身份信息\n3. 隐私信息:与案件无关的个人隐私、家庭住址、联系方式\n4. 国家秘密:涉及国家安全、军事、外交等保密信息\n5. 商业秘密:涉案企业的商业秘密\n\n二、案件细节处理\n1. 犯罪手法:避免详细描述作案手段、制毒制爆等技术细节\n2. 自杀案件:避免详细描述自杀方式,应附心理援助信息\n3. 血腥暴力:避免渲染血腥、暴力、恐怖细节\n\n三、特殊主体报道\n1. 涉及党政机关、领导干部:依规依纪报道,把握分寸\n2. 涉外、涉港澳台、涉民族宗教:严格遵守相关报道纪律\n3. 重大敏感案件:以权威部门发布的信息为准\n\n四、信息来源核实\n1. 优先采用司法机关、政府部门发布的权威信息\n2. 多方核实,避免单一信源\n3. 不传播未经证实的小道消息和网络传言\n4. 引用裁判文书须核对原文,确保准确' + ) ON CONFLICT (id) DO NOTHING; + + -- 文档9:法条引述格式标准 + INSERT INTO knowledge_documents (id, kb_id, name, file_type, char_count, indexing_status, uploader_id, content) + VALUES ( + 'e2000000-0000-0000-0000-000000000009', kb_norm_id, + '法条引述格式标准', 'txt', 4000, 'completed', creator_id, + E'法条引述格式标准\n\n一、基本格式\n标准格式:《法律名称》第X条第X款第X项\n示例:《中华人民共和国民法典》第一千二百五十四条第一款\n\n二、首次引用与简称\n1. 首次引用使用全称:《中华人民共和国刑法》\n2. 后文可用简称:《刑法》\n3. 通行简称:民法典、刑法、刑诉法、民诉法、行政诉讼法\n\n三、法律层级与引用顺序\n按效力层级由高到低排列:\n宪法 > 法律 > 行政法规 > 地方性法规 > 部门规章 > 地方政府规章\n引用多个法条时,按此顺序排列。\n\n四、条款项目的规范表述\n- 条:第一条、第二条……(用汉字)\n- 款:第一款、第二款……(同一条下的自然段)\n- 项:第(一)项、第(二)项……\n- 示例:第二百六十四条第一款第(三)项\n\n五、司法解释引用\n格式:《最高人民法院关于……的解释》第X条\n示例:《最高人民法院关于审理民间借贷案件适用法律若干问题的规定》第二十五条\n\n六、注意事项\n1. 注明法律的施行或修订日期(涉及新旧法对比时)\n2. 引用已废止法律须特别说明\n3. 核对条款序号,避免张冠李戴\n4. 引用原文须与正式文本一致,不得节略改动原意' + ) ON CONFLICT (id) DO NOTHING; + + -- 文档10:优秀报道案例点评 + INSERT INTO knowledge_documents (id, kb_id, name, file_type, char_count, indexing_status, uploader_id, content) + VALUES ( + 'e2000000-0000-0000-0000-000000000010', kb_norm_id, + '优秀报道案例点评', 'txt', 4500, 'completed', creator_id, + E'优秀法治报道案例点评\n\n范例一:深度调查类\n《某地"套路贷"黑产业链调查》\n亮点:\n1. 选题敏锐,聚焦民生痛点\n2. 调查扎实,证据链完整\n3. 法律分析到位,引用法条准确\n4. 警示性强,兼具普法价值\n点评:深度报道的典范,体现了法治媒体的舆论监督功能。\n\n范例二:案例解读类\n《从"昆山反杀案"看正当防卫的边界》\n亮点:\n1. 借热点案例普及法律知识\n2. 专家解读权威,深入浅出\n3. 厘清"正当防卫"认定标准\n4. 引导公众正确认识"法不能向不法让步"\n点评:成功将专业法律问题转化为公众易懂的内容。\n\n范例三:普法宣传类\n《民法典里的"小美好"》系列\n亮点:\n1. 以小见大,贴近生活\n2. 故事化表达,可读性强\n3. 系列化策划,形成传播声势\n4. 融媒体呈现,多平台分发\n点评:普法宣传创新的优秀样本,让法律"活"起来。\n\n范例四:舆论引导类\n《理性看待网络热点事件中的法律问题》\n亮点:\n1. 及时回应社会关切\n2. 以法治视角引导舆论\n3. 平衡报道,避免"舆论审判"\n4. 传播法治理性\n点评:在舆论场中发挥了"压舱石"作用。\n\n共性经验:\n1. 坚持正确导向,传播法治理念\n2. 内容专业准确,经得起检验\n3. 表达通俗生动,贴近受众\n4. 创新形式手段,增强传播力' + ) ON CONFLICT (id) DO NOTHING; + + -- ========== 应用关联知识库 ========== + -- 精选文库:典型案例解读、法规条文查询、典型案例分析、法治评论撰写、法治选题智能助手 + UPDATE applications SET knowledge_base_id = kb_lib_id + WHERE id IN ( + 'e0000000-0000-0000-0000-000000000002', -- 典型案例解读 + 'e0000000-0000-0000-0000-000000000003', -- 法规条文查询 + 'e0000000-0000-0000-0000-000000000009', -- 法治评论撰写 + 'e0000000-0000-0000-0000-00000000000e' -- 法治选题智能助手 + ); + + -- 报道规范:法治新闻摘要、案件报道生成、法治写作润色、采访提纲生成、法治内容创作助手 + UPDATE applications SET knowledge_base_id = kb_norm_id + WHERE id IN ( + 'e0000000-0000-0000-0000-000000000001', -- 法治新闻摘要 + 'e0000000-0000-0000-0000-000000000006', -- 案件报道生成 + 'e0000000-0000-0000-0000-000000000005', -- 法治写作润色 + 'e0000000-0000-0000-0000-000000000008', -- 采访提纲生成 + 'e0000000-0000-0000-0000-00000000000f' -- 法治内容创作助手 + ); + +END $$; + +SELECT '法制日报知识库种子数据插入成功!共2个知识库、10篇文档。' as status; \ No newline at end of file diff --git a/server/migrations/seed_fazhiribao_users.sql b/server/migrations/seed_fazhiribao_users.sql new file mode 100644 index 0000000..21f171e --- /dev/null +++ b/server/migrations/seed_fazhiribao_users.sql @@ -0,0 +1,39 @@ +-- 法制日报(法制网)机构用户种子数据 +-- 密码统一为 admin123 +-- 可重复执行(ON CONFLICT DO NOTHING) + +DO $$ +DECLARE + pwd_hash TEXT; + fazhi_org UUID := 'a0000000-0000-0000-0000-00000000000a'; +BEGIN + -- 获取已有用户的密码hash(admin123) + SELECT password_hash INTO pwd_hash FROM users WHERE email = 'admin@govai.gov.cn'; + + -- 法制日报机构管理员(排序第一位,作为登录页默认账号) + INSERT INTO organizations (id, name, slug, short_name, description, sort_order, is_active) VALUES + (fazhi_org, '法制日报', 'fazhiribao', '法制网', + '法治日报社官方平台,提供法治资讯、政策解读、法律服务与智能应用', + 1, true) + ON CONFLICT (id) DO NOTHING; + + -- 显式重排所有机构,确保法制日报稳定排在第一位、其余机构顺延(幂等) + UPDATE organizations SET sort_order = 1 WHERE slug = 'fazhiribao'; + UPDATE organizations SET sort_order = 2 WHERE slug = 'keji'; + UPDATE organizations SET sort_order = 3 WHERE slug = 'gongan'; + UPDATE organizations SET sort_order = 4 WHERE slug = 'fagai'; + UPDATE organizations SET sort_order = 5 WHERE slug = 'jiaoyu'; + UPDATE organizations SET sort_order = 6 WHERE slug = 'renshe'; + UPDATE organizations SET sort_order = 7 WHERE slug = 'caizheng'; + UPDATE organizations SET sort_order = 8 WHERE slug = 'zhujian'; + UPDATE organizations SET sort_order = 9 WHERE slug = 'shijianju'; + UPDATE organizations SET sort_order = 10 WHERE slug = 'lvsuo'; + + -- 法制日报机构用户 + INSERT INTO users (id, name, email, password_hash, role, status, org_id) VALUES + (gen_random_uuid(), '法制日报管理员', 'fazhiribao@govai.gov.cn', pwd_hash, 'admin', 'active', fazhi_org), + (gen_random_uuid(), '法制网编辑', 'fazhibian@govai.gov.cn', pwd_hash, 'creator', 'active', fazhi_org), + (gen_random_uuid(), '法制日报记者', 'fazhijizhe@govai.gov.cn', pwd_hash, 'user', 'active', fazhi_org) + ON CONFLICT (email) DO NOTHING; + +END $$; \ No newline at end of file