修改cms_content表结构和查询逻辑以支持多个分类ID

1. 将category_id字段改为category_ids字符串字段,支持逗号分隔的多个分类ID
2. 修改CmsContent实体类,添加类型转换支持,可接收数组格式的categoryIds
3. 更新CmsContentMapper.xml,修改查询逻辑为AND条件,要求内容包含所有指定分类
4. 修改CmsContentDto,添加categoryIdList字段支持数组格式的分类ID查询
5. 更新create_tables.sql和alter_cms_content.sql文件以反映字段变更
6. 重新生成init_cms_category.sql文件,包含新的分类结构

此修改解决了内容多分类查询的问题,现在可以通过单个或多个分类ID进行查询,且要求返回的内容包含所有指定分类
This commit is contained in:
wangzhiwei 2026-01-28 10:57:28 +08:00
parent 3f59744aab
commit e5f01458a1
7 changed files with 153 additions and 96 deletions

View File

@ -149,7 +149,7 @@ CREATE TABLE `cms_content` (
`title` varchar(255) NOT NULL COMMENT '标题', `title` varchar(255) NOT NULL COMMENT '标题',
`subtitle` varchar(255) DEFAULT NULL COMMENT '副标题', `subtitle` varchar(255) DEFAULT NULL COMMENT '副标题',
`content_type` tinyint(1) NOT NULL COMMENT '内容类型1文章2视频3图片', `content_type` tinyint(1) NOT NULL COMMENT '内容类型1文章2视频3图片',
`category_id` bigint(20) DEFAULT NULL COMMENT '分类ID', `category_ids` varchar(255) DEFAULT NULL COMMENT '分类ID列表,逗号分隔',
`summary` varchar(500) DEFAULT NULL COMMENT '内容摘要', `summary` varchar(500) DEFAULT NULL COMMENT '内容摘要',
`content` longtext DEFAULT NULL COMMENT '内容详情', `content` longtext DEFAULT NULL COMMENT '内容详情',
`cover_image` varchar(255) DEFAULT NULL COMMENT '封面图片', `cover_image` varchar(255) DEFAULT NULL COMMENT '封面图片',
@ -175,7 +175,6 @@ CREATE TABLE `cms_content` (
`update_by` varchar(50) DEFAULT NULL COMMENT '更新人', `update_by` varchar(50) DEFAULT NULL COMMENT '更新人',
`delete_flag` tinyint(1) DEFAULT '0' COMMENT '是否删除 0 未删除1已删除', `delete_flag` tinyint(1) DEFAULT '0' COMMENT '是否删除 0 未删除1已删除',
PRIMARY KEY (`content_id`), PRIMARY KEY (`content_id`),
KEY `idx_category_id` (`category_id`),
KEY `idx_author_id` (`author_id`), KEY `idx_author_id` (`author_id`),
KEY `idx_audit_status` (`audit_status`), KEY `idx_audit_status` (`audit_status`),
KEY `idx_publish_status` (`publish_status`), KEY `idx_publish_status` (`publish_status`),

View File

@ -2,10 +2,12 @@ package com.kexue.skills.entity;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
import java.util.List;
import java.io.Serializable; import java.io.Serializable;
import com.kexue.skills.entity.base.BaseEntity; import com.kexue.skills.entity.base.BaseEntity;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@ -28,8 +30,8 @@ public class CmsContent extends BaseEntity implements Serializable {
@Schema(description ="是否是官方0否1是") @Schema(description ="是否是官方0否1是")
private Boolean isOfficial; private Boolean isOfficial;
@Schema(description ="分类ID") @Schema(description ="分类ID列表,逗号分隔")
private Long categoryId; private String categoryIds;
@Schema(description ="图标") @Schema(description ="图标")
private String icon; private String icon;
@ -59,9 +61,6 @@ public class CmsContent extends BaseEntity implements Serializable {
@Schema(description ="内容类型1文章2视频3图片") @Schema(description ="内容类型1文章2视频3图片")
private Integer contentType; private Integer contentType;
@Schema(description ="父分类ID")
private Long parentCategoryId;
@Schema(description ="内容详情") @Schema(description ="内容详情")
private String content; private String content;
@ -130,4 +129,24 @@ public class CmsContent extends BaseEntity implements Serializable {
@Schema(description ="副标题") @Schema(description ="副标题")
private String subtitle; private String subtitle;
// 用于接收前端发送的分类ID数组
@JsonProperty("categoryIds")
public void setCategoryIdsFromArray(List<Long> categoryIdList) {
if (categoryIdList != null && !categoryIdList.isEmpty()) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < categoryIdList.size(); i++) {
sb.append(categoryIdList.get(i));
if (i < categoryIdList.size() - 1) {
sb.append(",");
}
}
this.categoryIds = sb.toString();
}
}
// 用于接收前端发送的分类ID字符串
public void setCategoryIds(String categoryIds) {
this.categoryIds = categoryIds;
}
} }

View File

@ -3,6 +3,8 @@ package com.kexue.skills.entity.dto;
import com.kexue.skills.entity.base.BaseQueryDto; import com.kexue.skills.entity.base.BaseQueryDto;
import lombok.Data; import lombok.Data;
import java.util.List;
/** /**
* (CmsContent)查询DTO类 * (CmsContent)查询DTO类
* *
@ -18,9 +20,11 @@ public class CmsContentDto extends BaseQueryDto {
private Integer contentType; private Integer contentType;
private String categoryIds;
private Long categoryId; private Long categoryId;
private Long parentCategoryId; private List<String> categoryIdList;
private Boolean isOfficial; private Boolean isOfficial;

View File

@ -46,7 +46,7 @@ sa-token:
# 验证码配置 # 验证码配置
captcha: captcha:
# 是否启用验证码验证 # 是否启用验证码验证
enabled: false enabled: true
# 验证码有效期(秒) # 验证码有效期(秒)
expire-time: 300 expire-time: 300
# 验证码长度 # 验证码长度

View File

@ -7,13 +7,7 @@
<result property="title" column="title" jdbcType="VARCHAR"/> <result property="title" column="title" jdbcType="VARCHAR"/>
<result property="subtitle" column="subtitle" jdbcType="VARCHAR"/> <result property="subtitle" column="subtitle" jdbcType="VARCHAR"/>
<result property="contentType" column="content_type" jdbcType="INTEGER"/> <result property="contentType" column="content_type" jdbcType="INTEGER"/>
<result property="categoryId" column="category_id" jdbcType="BIGINT"/> <result property="categoryIds" column="category_ids" jdbcType="VARCHAR"/>
<result property="parentCategoryId" column="parent_category_id" jdbcType="BIGINT"/>
<result property="isOfficial" column="is_official" jdbcType="BIT"/>
<result property="shareCount" column="share_count" jdbcType="INTEGER"/>
<result property="fileUrl" column="file_url" jdbcType="VARCHAR"/>
<result property="icon" column="icon" jdbcType="VARCHAR"/>
<result property="background" column="background" jdbcType="VARCHAR"/>
<result property="summary" column="summary" jdbcType="VARCHAR"/> <result property="summary" column="summary" jdbcType="VARCHAR"/>
<result property="content" column="content" jdbcType="LONGVARCHAR"/> <result property="content" column="content" jdbcType="LONGVARCHAR"/>
<result property="coverImage" column="cover_image" jdbcType="VARCHAR"/> <result property="coverImage" column="cover_image" jdbcType="VARCHAR"/>
@ -29,19 +23,28 @@
<result property="likeCount" column="like_count" jdbcType="INTEGER"/> <result property="likeCount" column="like_count" jdbcType="INTEGER"/>
<result property="commentCount" column="comment_count" jdbcType="INTEGER"/> <result property="commentCount" column="comment_count" jdbcType="INTEGER"/>
<result property="sort" column="sort" jdbcType="INTEGER"/> <result property="sort" column="sort" jdbcType="INTEGER"/>
<result property="isPaid" column="is_paid" jdbcType="BIT"/>
<result property="price" column="price" jdbcType="DECIMAL"/>
<result property="requiredPoints" column="required_points" jdbcType="INTEGER"/>
<result property="supportPointsPay" column="support_points_pay" jdbcType="BIT"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/> <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/> <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
<result property="createBy" column="create_by" jdbcType="VARCHAR"/> <result property="createBy" column="create_by" jdbcType="VARCHAR"/>
<result property="updateBy" column="update_by" jdbcType="VARCHAR"/> <result property="updateBy" column="update_by" jdbcType="VARCHAR"/>
<result property="deleteFlag" column="delete_flag" jdbcType="INTEGER"/> <result property="deleteFlag" column="delete_flag" jdbcType="INTEGER"/>
<result property="isOfficial" column="is_official" jdbcType="BIT"/>
<result property="shareCount" column="share_count" jdbcType="INTEGER"/>
<result property="fileUrl" column="file_url" jdbcType="VARCHAR"/>
<result property="icon" column="icon" jdbcType="VARCHAR"/>
<result property="background" column="background" jdbcType="VARCHAR"/>
</resultMap> </resultMap>
<!--查询单个--> <!--查询单个-->
<select id="queryById" resultMap="CmsContentMap"> <select id="queryById" resultMap="CmsContentMap">
select select
content_id, title, subtitle, content_type, category_id, parent_category_id, is_official, share_count, file_url, icon, background, summary, content, cover_image, author_id, author_name, content_id, title, subtitle, content_type, category_ids, summary, content, cover_image, author_id, author_name,
reviewer_id, reviewer_name, audit_status, audit_comment, publish_status, publish_time, reviewer_id, reviewer_name, audit_status, audit_comment, publish_status, publish_time,
view_count, like_count, comment_count, sort, create_time, update_time, create_by, update_by, delete_flag view_count, like_count, comment_count, sort, is_paid, price, required_points, support_points_pay, is_official, share_count, file_url, icon, background, create_time, update_time, create_by, update_by, delete_flag
from cms_content from cms_content
where content_id = #{contentId} where content_id = #{contentId}
</select> </select>
@ -49,9 +52,9 @@
<!--查询分页列表--> <!--查询分页列表-->
<select id="getPageList" resultMap="CmsContentMap"> <select id="getPageList" resultMap="CmsContentMap">
select select
content_id, title, subtitle, content_type, category_id, parent_category_id, is_official, share_count, file_url, icon, background, summary, content, cover_image, author_id, author_name, content_id, title, subtitle, content_type, category_ids, summary, content, cover_image, author_id, author_name,
reviewer_id, reviewer_name, audit_status, audit_comment, publish_status, publish_time, reviewer_id, reviewer_name, audit_status, audit_comment, publish_status, publish_time,
view_count, like_count, comment_count, sort, create_time, update_time, create_by, update_by, delete_flag view_count, like_count, comment_count, sort, is_paid, price, required_points, support_points_pay, is_official, share_count, file_url, icon, background, create_time, update_time, create_by, update_by, delete_flag
from cms_content from cms_content
<where> <where>
<if test="contentId != null"> <if test="contentId != null">
@ -64,13 +67,17 @@
and content_type = #{contentType} and content_type = #{contentType}
</if> </if>
<if test="categoryId != null"> <if test="categoryId != null">
and category_id = #{categoryId} and find_in_set(#{categoryId}, category_ids)
</if> </if>
<if test="parentCategoryId != null"> <if test="categoryIds != null and categoryIds != ''">
and parent_category_id = #{parentCategoryId} <foreach collection="categoryIds.split(',')" item="catId" separator="and" open="and " close="">
find_in_set(#{catId}, category_ids)
</foreach>
</if> </if>
<if test="isOfficial != null"> <if test="categoryIdList != null and categoryIdList.size() > 0">
and is_official = #{isOfficial} <foreach collection="categoryIdList" item="catId" separator="and" open="and " close="">
find_in_set(#{catId}, category_ids)
</foreach>
</if> </if>
<if test="authorId != null"> <if test="authorId != null">
and author_id = #{authorId} and author_id = #{authorId}
@ -97,9 +104,9 @@
<!--查询列表--> <!--查询列表-->
<select id="getList" resultMap="CmsContentMap"> <select id="getList" resultMap="CmsContentMap">
select select
content_id, title, subtitle, content_type, category_id, parent_category_id, is_official, share_count, file_url, icon, background, summary, content, cover_image, author_id, author_name, content_id, title, subtitle, content_type, category_ids, summary, content, cover_image, author_id, author_name,
reviewer_id, reviewer_name, audit_status, audit_comment, publish_status, publish_time, reviewer_id, reviewer_name, audit_status, audit_comment, publish_status, publish_time,
view_count, like_count, comment_count, sort, create_time, update_time, create_by, update_by, delete_flag view_count, like_count, comment_count, sort, is_paid, price, required_points, support_points_pay, is_official, share_count, file_url, icon, background, create_time, update_time, create_by, update_by, delete_flag
from cms_content from cms_content
<where> <where>
<if test="contentId != null"> <if test="contentId != null">
@ -112,7 +119,17 @@
and content_type = #{contentType} and content_type = #{contentType}
</if> </if>
<if test="categoryId != null"> <if test="categoryId != null">
and category_id = #{categoryId} and find_in_set(#{categoryId}, category_ids)
</if>
<if test="categoryIds != null and categoryIds != ''">
<foreach collection="categoryIds.split(',')" item="catId" separator="and" open="and " close="">
find_in_set(#{catId}, category_ids)
</foreach>
</if>
<if test="categoryIdList != null and categoryIdList.size() > 0">
<foreach collection="categoryIdList" item="catId" separator="and" open="and " close="">
find_in_set(#{catId}, category_ids)
</foreach>
</if> </if>
<if test="authorId != null"> <if test="authorId != null">
and author_id = #{authorId} and author_id = #{authorId}
@ -132,12 +149,12 @@
<!--新增所有列--> <!--新增所有列-->
<insert id="insert" keyProperty="contentId" useGeneratedKeys="true"> <insert id="insert" keyProperty="contentId" useGeneratedKeys="true">
insert into cms_content(title, subtitle, content_type, category_id, parent_category_id, is_official, share_count, file_url, icon, background, summary, content, cover_image, author_id, author_name, insert into cms_content(title, subtitle, content_type, category_ids, summary, content, cover_image, author_id, author_name,
reviewer_id, reviewer_name, audit_status, audit_comment, publish_status, publish_time, reviewer_id, reviewer_name, audit_status, audit_comment, publish_status, publish_time,
view_count, like_count, comment_count, sort, create_time, update_time, create_by, update_by, delete_flag) view_count, like_count, comment_count, sort, is_paid, price, required_points, support_points_pay, is_official, share_count, file_url, icon, background, create_time, update_time, create_by, update_by, delete_flag)
values (#{title}, #{subtitle}, #{contentType}, #{categoryId}, #{parentCategoryId}, #{isOfficial}, #{shareCount}, #{fileUrl}, #{icon}, #{background}, #{summary}, #{content}, #{coverImage}, #{authorId}, #{authorName}, values (#{title}, #{subtitle}, #{contentType}, #{categoryIds}, #{summary}, #{content}, #{coverImage}, #{authorId}, #{authorName},
#{reviewerId}, #{reviewerName}, #{auditStatus}, #{auditComment}, #{publishStatus}, #{publishTime}, #{reviewerId}, #{reviewerName}, #{auditStatus}, #{auditComment}, #{publishStatus}, #{publishTime},
#{viewCount}, #{likeCount}, #{commentCount}, #{sort}, #{createTime}, #{updateTime}, #{createBy}, #{updateBy}, #{deleteFlag}) #{viewCount}, #{likeCount}, #{commentCount}, #{sort}, #{isPaid}, #{price}, #{requiredPoints}, #{supportPointsPay}, #{isOfficial}, #{shareCount}, #{fileUrl}, #{icon}, #{background}, #{createTime}, #{updateTime}, #{createBy}, #{updateBy}, #{deleteFlag})
</insert> </insert>
<!--通过主键修改数据--> <!--通过主键修改数据-->
@ -153,26 +170,8 @@
<if test="contentType != null"> <if test="contentType != null">
content_type = #{contentType}, content_type = #{contentType},
</if> </if>
<if test="categoryId != null"> <if test="categoryIds != null and categoryIds != ''">
category_id = #{categoryId}, category_ids = #{categoryIds},
</if>
<if test="parentCategoryId != null">
parent_category_id = #{parentCategoryId},
</if>
<if test="isOfficial != null">
is_official = #{isOfficial},
</if>
<if test="shareCount != null">
share_count = #{shareCount},
</if>
<if test="fileUrl != null">
file_url = #{fileUrl},
</if>
<if test="icon != null">
icon = #{icon},
</if>
<if test="background != null">
background = #{background},
</if> </if>
<if test="summary != null"> <if test="summary != null">
summary = #{summary}, summary = #{summary},
@ -219,6 +218,33 @@
<if test="sort != null"> <if test="sort != null">
sort = #{sort}, sort = #{sort},
</if> </if>
<if test="isPaid != null">
is_paid = #{isPaid},
</if>
<if test="price != null">
price = #{price},
</if>
<if test="requiredPoints != null">
required_points = #{requiredPoints},
</if>
<if test="supportPointsPay != null">
support_points_pay = #{supportPointsPay},
</if>
<if test="isOfficial != null">
is_official = #{isOfficial},
</if>
<if test="shareCount != null">
share_count = #{shareCount},
</if>
<if test="fileUrl != null">
file_url = #{fileUrl},
</if>
<if test="icon != null">
icon = #{icon},
</if>
<if test="background != null">
background = #{background},
</if>
<if test="updateTime != null"> <if test="updateTime != null">
update_time = #{updateTime}, update_time = #{updateTime},
</if> </if>

View File

@ -1,9 +1,14 @@
-- 修改cms_content表添加新字段 -- 修改cms_content表添加新字段并修改分类ID字段
ALTER TABLE cms_content ALTER TABLE cms_content
-- 修改分类ID字段为分类ID列表
MODIFY COLUMN category_id VARCHAR(255) COMMENT '分类ID列表逗号分隔',
-- 添加新字段 -- 添加新字段
ADD COLUMN parent_category_id BIGINT COMMENT '父分类ID',
ADD COLUMN is_official BIT(1) DEFAULT 0 COMMENT '是否是官方0否1是', ADD COLUMN is_official BIT(1) DEFAULT 0 COMMENT '是否是官方0否1是',
ADD COLUMN share_count INT DEFAULT 0 COMMENT '分享数量', ADD COLUMN share_count INT DEFAULT 0 COMMENT '分享数量',
ADD COLUMN file_url VARCHAR(255) COMMENT '文件URL', ADD COLUMN file_url VARCHAR(255) COMMENT '文件URL',
ADD COLUMN icon VARCHAR(255) COMMENT '图标', ADD COLUMN icon VARCHAR(255) COMMENT '图标',
ADD COLUMN background VARCHAR(255) COMMENT '背景'; ADD COLUMN background VARCHAR(255) COMMENT '背景';
-- 重命名字段名
ALTER TABLE cms_content
CHANGE COLUMN category_id category_ids VARCHAR(255) COMMENT '分类ID列表逗号分隔';

View File

@ -1,47 +1,51 @@
-- AI相关分类初始化数据 -- CMS分类初始化数据
-- 先清空现有数据
TRUNCATE TABLE cms_category;
-- 一级分类 -- 一级分类
INSERT INTO cms_category (category_name, parent_id, level, sort, status, delete_flag, create_time, update_time, create_by, update_by) VALUES INSERT INTO cms_category (category_name, parent_id, level, sort, status, delete_flag, create_time, update_time, create_by, update_by) VALUES
('AI技术', NULL, 1, 1, 1, 0, NOW(), NOW(), 'admin', 'admin'), ('官方', 0, 1, 1, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('AI应用', NULL, 1, 2, 1, 0, NOW(), NOW(), 'admin', 'admin'), ('coze', 0, 1, 2, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('AI工具', NULL, 1, 3, 1, 0, NOW(), NOW(), 'admin', 'admin'), ('用户发布', 0, 1, 3, 1, 0, NOW(), NOW(), 'admin', 'admin');
('AI伦理', NULL, 1, 4, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('AI新闻', NULL, 1, 5, 1, 0, NOW(), NOW(), 'admin', 'admin');
-- 二级分类 - AI技术 -- 二级分类 - 官方
INSERT INTO cms_category (category_name, parent_id, level, sort, status, delete_flag, create_time, update_time, create_by, update_by) VALUES INSERT INTO cms_category (category_name, parent_id, level, sort, status, delete_flag, create_time, update_time, create_by, update_by) VALUES
('机器学习', 1, 2, 1, 1, 0, NOW(), NOW(), 'admin', 'admin'), ('工具', 1, 2, 1, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('深度学习', 1, 2, 2, 1, 0, NOW(), NOW(), 'admin', 'admin'), ('编程', 1, 2, 2, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('自然语言处理', 1, 2, 3, 1, 0, NOW(), NOW(), 'admin', 'admin'), ('设计', 1, 2, 3, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('计算机视觉', 1, 2, 4, 1, 0, NOW(), NOW(), 'admin', 'admin'), ('前端', 1, 2, 4, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('语音识别', 1, 2, 5, 1, 0, NOW(), NOW(), 'admin', 'admin'), ('测试', 1, 2, 5, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('强化学习', 1, 2, 6, 1, 0, NOW(), NOW(), 'admin', 'admin'), ('AI', 1, 2, 6, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('AI大模型', 1, 2, 7, 1, 0, NOW(), NOW(), 'admin', 'admin'); ('数据分析', 1, 2, 7, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('写作', 1, 2, 8, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('管理', 1, 2, 9, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('内容', 1, 2, 10, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('自动化', 1, 2, 11, 1, 0, NOW(), NOW(), 'admin', 'admin');
-- 二级分类 - AI应用 -- 二级分类 - coze
INSERT INTO cms_category (category_name, parent_id, level, sort, status, delete_flag, create_time, update_time, create_by, update_by) VALUES INSERT INTO cms_category (category_name, parent_id, level, sort, status, delete_flag, create_time, update_time, create_by, update_by) VALUES
('ChatGPT应用', 2, 2, 1, 1, 0, NOW(), NOW(), 'admin', 'admin'), ('工具', 2, 2, 1, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('AI绘画', 2, 2, 2, 1, 0, NOW(), NOW(), 'admin', 'admin'), ('编程', 2, 2, 2, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('AI写作', 2, 2, 3, 1, 0, NOW(), NOW(), 'admin', 'admin'), ('设计', 2, 2, 3, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('AI编程', 2, 2, 4, 1, 0, NOW(), NOW(), 'admin', 'admin'), ('前端', 2, 2, 4, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('AI教育', 2, 2, 5, 1, 0, NOW(), NOW(), 'admin', 'admin'), ('测试', 2, 2, 5, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('AI医疗', 2, 2, 6, 1, 0, NOW(), NOW(), 'admin', 'admin'), ('AI', 2, 2, 6, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('AI金融', 2, 2, 7, 1, 0, NOW(), NOW(), 'admin', 'admin'); ('数据分析', 2, 2, 7, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('写作', 2, 2, 8, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('管理', 2, 2, 9, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('内容', 2, 2, 10, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('自动化', 2, 2, 11, 1, 0, NOW(), NOW(), 'admin', 'admin');
-- 二级分类 - AI工具 -- 二级分类 - 用户发布
INSERT INTO cms_category (category_name, parent_id, level, sort, status, delete_flag, create_time, update_time, create_by, update_by) VALUES INSERT INTO cms_category (category_name, parent_id, level, sort, status, delete_flag, create_time, update_time, create_by, update_by) VALUES
('AI生成工具', 3, 2, 1, 1, 0, NOW(), NOW(), 'admin', 'admin'), ('工具', 3, 2, 1, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('AI数据分析工具', 3, 2, 2, 1, 0, NOW(), NOW(), 'admin', 'admin'), ('编程', 3, 2, 2, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('AI开发框架', 3, 2, 3, 1, 0, NOW(), NOW(), 'admin', 'admin'), ('设计', 3, 2, 3, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('AI部署工具', 3, 2, 4, 1, 0, NOW(), NOW(), 'admin', 'admin'); ('前端', 3, 2, 4, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('测试', 3, 2, 5, 1, 0, NOW(), NOW(), 'admin', 'admin'),
-- 二级分类 - AI伦理 ('AI', 3, 2, 6, 1, 0, NOW(), NOW(), 'admin', 'admin'),
INSERT INTO cms_category (category_name, parent_id, level, sort, status, delete_flag, create_time, update_time, create_by, update_by) VALUES ('数据分析', 3, 2, 7, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('AI隐私', 4, 2, 1, 1, 0, NOW(), NOW(), 'admin', 'admin'), ('写作', 3, 2, 8, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('AI偏见', 4, 2, 2, 1, 0, NOW(), NOW(), 'admin', 'admin'), ('管理', 3, 2, 9, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('AI安全', 4, 2, 3, 1, 0, NOW(), NOW(), 'admin', 'admin'); ('内容', 3, 2, 10, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('自动化', 3, 2, 11, 1, 0, NOW(), NOW(), 'admin', 'admin');
-- 二级分类 - AI新闻
INSERT INTO cms_category (category_name, parent_id, level, sort, status, delete_flag, create_time, update_time, create_by, update_by) VALUES
('AI行业动态', 5, 2, 1, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('AI企业新闻', 5, 2, 2, 1, 0, NOW(), NOW(), 'admin', 'admin'),
('AI技术进展', 5, 2, 3, 1, 0, NOW(), NOW(), 'admin', 'admin');