feat: Add news information management module with API and database support
- Introduced new API endpoints for querying and managing news information in the CMS. - Implemented data model for NewsInfo and NewsInfoQuery with validation. - Created NewsInfoMapper for database interactions and corresponding XML mappings. - Developed INewsInfoService interface and its implementation for business logic. - Added RichTextSanitizer utility for cleaning HTML content to prevent XSS attacks. - Created unit tests for RichTextSanitizer to ensure proper functionality. - Updated database schema with news_info table and necessary fields, including status and module. - Added migration scripts for setting up the news information module in the database. - Integrated jsoup library for HTML sanitization.
This commit is contained in:
20
sql/migration_add_job_status_and_key_populations.sql
Normal file
20
sql/migration_add_job_status_and_key_populations.sql
Normal file
@@ -0,0 +1,20 @@
|
||||
-- 岗位上下架状态、是否重点人群及重点人群类型字段。
|
||||
-- 执行目标:对应环境 HighGo 数据库的 shz schema。
|
||||
-- 可重复执行:字段使用 IF NOT EXISTS,列注释可重复设置。
|
||||
-- 字段定义与测试库 shz.job 保持一致:允许为空且不设置默认值。
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE "shz"."job"
|
||||
ADD COLUMN IF NOT EXISTS "job_status" VARCHAR(2),
|
||||
ADD COLUMN IF NOT EXISTS "is_key_populations" VARCHAR(2),
|
||||
ADD COLUMN IF NOT EXISTS "key_populations" VARCHAR(20);
|
||||
|
||||
COMMENT ON COLUMN "shz"."job"."job_status"
|
||||
IS '是否下架(0上架,1下架)';
|
||||
COMMENT ON COLUMN "shz"."job"."is_key_populations"
|
||||
IS '是否重点人群';
|
||||
COMMENT ON COLUMN "shz"."job"."key_populations"
|
||||
IS '重点人群(1农民工、2团场职工、3失业人员、4零就业家庭、5零工人员、6退役军人)';
|
||||
|
||||
COMMIT;
|
||||
212
sql/news_info.sql
Normal file
212
sql/news_info.sql
Normal file
@@ -0,0 +1,212 @@
|
||||
-- 新闻资讯:数据表、业务字典与 CMS 菜单权限。
|
||||
-- 执行目标:测试/生产 HighGo 数据库的 shz schema。
|
||||
-- 可重复执行:表/索引、字典类型/字典项、菜单/按钮均做幂等处理。
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- 显式创建序列以兼容生产 HighGo(生产环境不识别 BIGSERIAL 类型别名)。
|
||||
CREATE SEQUENCE IF NOT EXISTS "shz"."news_info_id_seq"
|
||||
START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "shz"."news_info" (
|
||||
"id" BIGINT NOT NULL DEFAULT nextval('shz.news_info_id_seq'::regclass) PRIMARY KEY,
|
||||
"module" VARCHAR(100) NOT NULL,
|
||||
"title" VARCHAR(200) NOT NULL,
|
||||
"content" TEXT NOT NULL,
|
||||
"status" CHAR(1) NOT NULL DEFAULT '1',
|
||||
"create_by" VARCHAR(64) NOT NULL DEFAULT '',
|
||||
"create_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"update_by" VARCHAR(64) NOT NULL DEFAULT '',
|
||||
"update_time" TIMESTAMP,
|
||||
"del_flag" CHAR(1) NOT NULL DEFAULT '0',
|
||||
"remark" VARCHAR(500) NOT NULL DEFAULT '',
|
||||
CONSTRAINT "chk_news_info_status" CHECK ("status" IN ('0', '1')),
|
||||
CONSTRAINT "chk_news_info_del_flag" CHECK ("del_flag" IN ('0', '2'))
|
||||
);
|
||||
|
||||
COMMENT ON TABLE "shz"."news_info" IS '新闻资讯表';
|
||||
COMMENT ON COLUMN "shz"."news_info"."id" IS '新闻资讯ID';
|
||||
COMMENT ON COLUMN "shz"."news_info"."module" IS '资讯模块,对应业务字典 news_module 的 dict_value';
|
||||
COMMENT ON COLUMN "shz"."news_info"."title" IS '标题';
|
||||
COMMENT ON COLUMN "shz"."news_info"."content" IS '富文本正文(经过服务端白名单清理的HTML)';
|
||||
COMMENT ON COLUMN "shz"."news_info"."status" IS '上下架状态(0上架 1下架)';
|
||||
COMMENT ON COLUMN "shz"."news_info"."create_by" IS '创建者';
|
||||
COMMENT ON COLUMN "shz"."news_info"."create_time" IS '创建时间';
|
||||
COMMENT ON COLUMN "shz"."news_info"."update_by" IS '更新者';
|
||||
COMMENT ON COLUMN "shz"."news_info"."update_time" IS '更新时间';
|
||||
COMMENT ON COLUMN "shz"."news_info"."del_flag" IS '删除标志(0存在 2删除)';
|
||||
COMMENT ON COLUMN "shz"."news_info"."remark" IS '备注';
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "idx_news_info_module"
|
||||
ON "shz"."news_info" ("module");
|
||||
CREATE INDEX IF NOT EXISTS "idx_news_info_status_created"
|
||||
ON "shz"."news_info" ("status", "create_time" DESC)
|
||||
WHERE "del_flag" = '0';
|
||||
|
||||
-- 资讯模块使用“业务字典”,资讯表只保存 dict_value;管理员可在现有业务字典页面继续添加模块项。
|
||||
INSERT INTO "shz"."bussiness_dict_type" (
|
||||
"dict_id", "dict_name", "dict_type", "status", "create_by", "create_time", "remark"
|
||||
)
|
||||
SELECT
|
||||
(SELECT COALESCE(MAX("dict_id"), 0) + 1 FROM "shz"."bussiness_dict_type"),
|
||||
'新闻资讯模块',
|
||||
'news_module',
|
||||
'0',
|
||||
'system',
|
||||
CURRENT_TIMESTAMP,
|
||||
'新闻资讯模块,资讯表保存 dict_value,可在业务字典中扩展'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM "shz"."bussiness_dict_type"
|
||||
WHERE "dict_type" = 'news_module'
|
||||
);
|
||||
|
||||
WITH seed("dict_sort", "dict_label", "dict_value", "list_class", "is_default") AS (
|
||||
VALUES
|
||||
(1, '求职资讯', 'job_information', 'primary', 'Y'),
|
||||
(2, '面试技巧', 'interview_tips', 'success', 'N'),
|
||||
(3, '简历指南', 'resume_guide', 'warning', 'N'),
|
||||
(4, '行业指南', 'industry_guide', 'info', 'N'),
|
||||
(5, '政策法规', 'policy_regulations', 'danger', 'N')
|
||||
),
|
||||
new_rows AS (
|
||||
SELECT
|
||||
ROW_NUMBER() OVER (ORDER BY seed."dict_sort") AS rn,
|
||||
seed.*
|
||||
FROM seed
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM "shz"."bussiness_dict_data" data
|
||||
WHERE data."dict_type" = 'news_module'
|
||||
AND data."dict_value" = seed."dict_value"
|
||||
)
|
||||
),
|
||||
base AS (
|
||||
SELECT COALESCE(MAX("dict_code"), 0) AS max_code
|
||||
FROM "shz"."bussiness_dict_data"
|
||||
)
|
||||
INSERT INTO "shz"."bussiness_dict_data" (
|
||||
"dict_code", "dict_sort", "dict_label", "dict_value", "dict_type",
|
||||
"css_class", "list_class", "is_default", "status", "create_by", "create_time", "remark"
|
||||
)
|
||||
SELECT
|
||||
base.max_code + new_rows.rn,
|
||||
new_rows."dict_sort",
|
||||
new_rows."dict_label",
|
||||
new_rows."dict_value",
|
||||
'news_module',
|
||||
NULL,
|
||||
new_rows."list_class",
|
||||
new_rows."is_default",
|
||||
'0',
|
||||
'system',
|
||||
CURRENT_TIMESTAMP,
|
||||
'新闻资讯模块'
|
||||
FROM new_rows
|
||||
CROSS JOIN base;
|
||||
|
||||
-- CMS 一级目录。
|
||||
INSERT INTO "shz"."sys_menu" (
|
||||
"menu_name", "parent_id", "order_num", "path", "component", "query", "route_name",
|
||||
"is_frame", "is_cache", "menu_type", "visible", "status", "perms", "icon",
|
||||
"create_by", "create_time", "update_by", "update_time", "remark", "menu_id"
|
||||
)
|
||||
SELECT
|
||||
'新闻资讯', 0, 8, 'news-information', '', '', 'NewsInformation',
|
||||
1, 0, 'M', '0', '0', '', 'ReadOutlined',
|
||||
'system', CURRENT_TIMESTAMP, '', NULL, '新闻资讯管理目录', ids."menu_id"
|
||||
FROM (
|
||||
SELECT COALESCE(MAX("menu_id"), 0) + 1 AS "menu_id"
|
||||
FROM "shz"."sys_menu"
|
||||
) ids
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM "shz"."sys_menu"
|
||||
WHERE "parent_id" = 0 AND "path" = 'news-information'
|
||||
);
|
||||
|
||||
-- CMS 资讯管理页面;页面权限同时作为列表权限。
|
||||
INSERT INTO "shz"."sys_menu" (
|
||||
"menu_name", "parent_id", "order_num", "path", "component", "query", "route_name",
|
||||
"is_frame", "is_cache", "menu_type", "visible", "status", "perms", "icon",
|
||||
"create_by", "create_time", "update_by", "update_time", "remark", "menu_id"
|
||||
)
|
||||
SELECT
|
||||
'资讯管理', parent."menu_id", 1, 'news-info', 'NewsInfo/index', '', 'NewsInfo',
|
||||
1, 0, 'C', '0', '0', 'cms:newsInfo:list', 'ProfileOutlined',
|
||||
'system', CURRENT_TIMESTAMP, '', NULL, '新闻资讯管理页面', ids."menu_id"
|
||||
FROM (
|
||||
SELECT "menu_id"
|
||||
FROM "shz"."sys_menu"
|
||||
WHERE "parent_id" = 0 AND "path" = 'news-information'
|
||||
ORDER BY "menu_id"
|
||||
LIMIT 1
|
||||
) parent
|
||||
CROSS JOIN (
|
||||
SELECT COALESCE(MAX("menu_id"), 0) + 1 AS "menu_id"
|
||||
FROM "shz"."sys_menu"
|
||||
) ids
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM "shz"."sys_menu"
|
||||
WHERE "perms" = 'cms:newsInfo:list'
|
||||
);
|
||||
|
||||
-- 页面按钮权限。
|
||||
WITH parent AS (
|
||||
SELECT "menu_id"
|
||||
FROM "shz"."sys_menu"
|
||||
WHERE "perms" = 'cms:newsInfo:list'
|
||||
ORDER BY "menu_id"
|
||||
LIMIT 1
|
||||
),
|
||||
seed("order_num", "menu_name", "perms", "remark") AS (
|
||||
VALUES
|
||||
(1, '新闻资讯查询', 'cms:newsInfo:query', '查询新闻资讯详情'),
|
||||
(2, '新闻资讯新增', 'cms:newsInfo:add', '新增新闻资讯'),
|
||||
(3, '新闻资讯修改', 'cms:newsInfo:edit', '修改新闻资讯'),
|
||||
(4, '新闻资讯删除', 'cms:newsInfo:remove', '删除新闻资讯'),
|
||||
(5, '新闻资讯上下架', 'cms:newsInfo:status', '新闻资讯上架或下架')
|
||||
),
|
||||
new_rows AS (
|
||||
SELECT
|
||||
ROW_NUMBER() OVER (ORDER BY seed."order_num") AS rn,
|
||||
seed.*
|
||||
FROM seed
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM "shz"."sys_menu" existing
|
||||
WHERE existing."perms" = seed."perms"
|
||||
)
|
||||
),
|
||||
base AS (
|
||||
SELECT COALESCE(MAX("menu_id"), 0) AS max_id
|
||||
FROM "shz"."sys_menu"
|
||||
)
|
||||
INSERT INTO "shz"."sys_menu" (
|
||||
"menu_id", "menu_name", "parent_id", "order_num", "path", "component", "query", "route_name",
|
||||
"is_frame", "is_cache", "menu_type", "visible", "status", "perms", "icon",
|
||||
"create_by", "create_time", "update_by", "update_time", "remark"
|
||||
)
|
||||
SELECT
|
||||
base.max_id + new_rows.rn,
|
||||
new_rows."menu_name",
|
||||
parent."menu_id",
|
||||
new_rows."order_num",
|
||||
'', '', '', '',
|
||||
1, 0, 'F', '0', '0', new_rows."perms", '#',
|
||||
'system', CURRENT_TIMESTAMP, '', NULL, new_rows."remark"
|
||||
FROM new_rows
|
||||
CROSS JOIN parent
|
||||
CROSS JOIN base;
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- 说明:管理员角色通过 *:*:* 自动拥有全部权限;其他角色请在 CMS“角色管理”中按需分配“新闻资讯”。
|
||||
-- 验证:
|
||||
-- SELECT column_name, data_type FROM information_schema.columns
|
||||
-- WHERE table_schema = 'shz' AND table_name = 'news_info' ORDER BY ordinal_position;
|
||||
-- SELECT dict_label, dict_value FROM shz.bussiness_dict_data
|
||||
-- WHERE dict_type = 'news_module' ORDER BY dict_sort;
|
||||
-- SELECT menu_id, menu_name, parent_id, menu_type, perms FROM shz.sys_menu
|
||||
-- WHERE path = 'news-information' OR perms LIKE 'cms:newsInfo:%' ORDER BY menu_id;
|
||||
Reference in New Issue
Block a user