一、原生资讯模块数据表拆解
1.1 文章主表(ls_articie)
LikeShop 的资讯模块以 ls_article 表为核心,存储平台发布的文章内容;核心字段包括:
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 文章ID |
| cid | int | 文章分类ID |
| title | varchar | 文章标题 |
| synopsis | varchar | 文字简介 |
| image | varchar | 文章图片/封面图 |
| is_notice | tinyint | 是否公告:1-是,0-否 |
| content | text | 文章内容 |
| visit | int | 浏览人数 |
| is_show | tinyint | 是否显示:0-隐藏,1-显示 |
| sort | int | 排序 |
| create_time | int | 创建时间 |
文章分类通过 ls_article_category 表管理,支持分类名称、分类简介、分类图片、父级ID、排序等字段,后台可维护文章分类,方便文章分类整理;文章列表接口返回字段包括 id,cid,title,image,click_virtual,click_actual,create_time 等。
1.2 原生资讯模块的四个核心局限
局限一:内容生产模式单一。ls_article 表定位为平台官方资讯发布,内容由后台管理员创建,不支持用户(C端消费者)发布内容;表结构中没有 user_id 字段,无法追踪内容创作者。
局限二:无社交互动能力。资讯模块是单向传播------平台发布、用户阅读、不具备点赞、评论、收藏、分享等互动能力;ls_article 表仅有 visit (浏览人数)字段,没有点赞数、评论数、收藏数的统计字段。
局限三:无商品关联能力。资讯内容与商品体系完全割裂;ls_article 表没有任何与 ls_goods 关联的字段或关联表,无法实现"内容种草 → 商品转化"的链路。
局限四:无话题/社区运营能力。资讯以分类(cid)组织,分类结构是树形的一级/二级分类,而种草社区需要的是话题广场模式------一个用户可以自由创建、参与和关注的话题体系,话题具有动态性和社交性。
1.3 二开策略定位
参考 LikeShop 的二开规范,核心原则是"新增能力 > 修改原逻辑,组合扩展 > 覆盖替换";资讯模块的二开策略应当遵循:
- 不修改 ls_article 表结构,保持原生资讯功能不变,避免影响平台官方资讯发布
- 新建独立的笔记体系,与资讯模块并行运行,通过统一的内容聚合层对外提供数据
- 复用原生的文件上传、用户体系、商品体系,通过关联表实现笔记与商品、话题的绑定
- 扩展逻辑封装在独立的 Service 中,不修改核心的 ArticleLogic、UserLogic 等文件
二、数据库扩展设计
2.1 笔记主表(ls_note)
CREATE TABLE `ls_note` (
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` int UNSIGNED NOT NULL COMMENT '发布用户ID',
`title` varchar(100) NOT NULL DEFAULT '' COMMENT '笔记标题',
`content` text COMMENT '笔记内容,最多1000字',
`note_type` tinyint NOT NULL DEFAULT 1 COMMENT '笔记类型:1-图片笔记,2-视频笔记',
`images` text COMMENT '图片列表,JSON数组,最多9张',
`video_url` varchar(500) NOT NULL DEFAULT '' COMMENT '视频地址',
`video_cover` varchar(500) NOT NULL DEFAULT '' COMMENT '视频封面图(前三秒截取)',
`topic_id` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '所属话题ID',
`category_id` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '所属分类ID',
`is_top` tinyint NOT NULL DEFAULT 0 COMMENT '是否置顶:0-否,1-是',
`audit_status` tinyint NOT NULL DEFAULT 0 COMMENT '审核状态:0-待审核,1-已通过,2-已驳回',
`audit_remark` varchar(255) NOT NULL DEFAULT '' COMMENT '审核备注',
`status` tinyint NOT NULL DEFAULT 1 COMMENT '状态:0-隐藏,1-显示',
`like_count` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '点赞数',
`comment_count` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '评论数',
`collect_count` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '收藏数',
`view_count` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '浏览量',
`virtual_like` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '虚拟点赞数',
`create_time` int UNSIGNED NOT NULL DEFAULT 0,
`update_time` int UNSIGNED NOT NULL DEFAULT 0,
`del` tinyint NOT NULL DEFAULT 0 COMMENT '是否删除:0-否,非0为删除时间',
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_topic_id` (`topic_id`),
KEY `idx_category_id` (`category_id`),
KEY `idx_audit_status` (`audit_status`),
KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='种草笔记表';
笔记支持图片笔记(最多9张图片)和视频笔记(上传一个视频,截取前三秒作为封面),笔记下方支持文字说明(1000字内),可以选择关联商品和所属话题。
2.2 话题表(ls_note_topic)
话题是社区内容组织的基本单元;笔记属于话题,话题属于分类,形成"分类 → 话题 → 笔记"的三级结构:
CREATE TABLE `ls_note_topic` (
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL COMMENT '话题名称',
`description` varchar(255) NOT NULL DEFAULT '' COMMENT '话题简介',
`image` varchar(500) NOT NULL DEFAULT '' COMMENT '话题封面图',
`category_id` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '所属分类ID',
`topic_type` tinyint NOT NULL DEFAULT 1 COMMENT '话题类型:1-日常话题,2-有奖征集,3-PK活动',
`note_count` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '笔记数量',
`follow_count` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '关注人数',
`view_count` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '浏览量',
`is_recommend` tinyint NOT NULL DEFAULT 0 COMMENT '是否推荐:0-否,1-是',
`sort` int NOT NULL DEFAULT 0 COMMENT '排序',
`status` tinyint NOT NULL DEFAULT 1 COMMENT '状态:0-禁用,1-启用',
`start_time` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '活动开始时间(有奖活动使用)',
`end_time` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '活动结束时间',
`create_time` int UNSIGNED NOT NULL DEFAULT 0,
`update_time` int UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
KEY `idx_category_id` (`category_id`),
KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='话题表';
话题分类表 ls_note_category 结构参考文章分类表,包含分类名称、简介、图片、父级ID、排序等字段。
2.3 笔记-商品关联表(ls_note_goods)
实现内容到转化的核心表,支持一条笔记关联多个商品:
CREATE TABLE `ls_note_goods` (
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`note_id` int UNSIGNED NOT NULL COMMENT '笔记ID',
`goods_id` int UNSIGNED NOT NULL COMMENT '商品ID',
`item_id` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '规格ID',
`sort` int NOT NULL DEFAULT 0 COMMENT '排序',
`create_time` int UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_note_goods` (`note_id`, `goods_id`),
KEY `idx_goods_id` (`goods_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='笔记商品关联表';
2.4 点赞记录表(ls_note_like)
CREATE TABLE `ls_note_like` (
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`note_id` int UNSIGNED NOT NULL COMMENT '笔记ID',
`user_id` int UNSIGNED NOT NULL COMMENT '用户ID',
`create_time` int UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_note_user` (`note_id`, `user_id`),
KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='笔记点赞记录表';
2.5 评论表(ls_note_comment)
CREATE TABLE `ls_note_comment` (
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`note_id` int UNSIGNED NOT NULL COMMENT '笔记ID',
`user_id` int UNSIGNED NOT NULL COMMENT '评论用户ID',
`parent_id` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '父评论ID,0为一级评论',
`reply_user_id` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '被回复用户ID',
`content` varchar(500) NOT NULL DEFAULT '' COMMENT '评论内容',
`like_count` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '点赞数',
`audit_status` tinyint NOT NULL DEFAULT 0 COMMENT '审核状态:0-待审核,1-已通过,2-已驳回',
`status` tinyint NOT NULL DEFAULT 1 COMMENT '状态:0-隐藏,1-显示',
`create_time` int UNSIGNED NOT NULL DEFAULT 0,
`del` tinyint NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
KEY `idx_note_id` (`note_id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_parent_id` (`parent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='笔记评论表';
2.6 收藏记录表(ls_note_collect)
CREATE TABLE `ls_note_collect` (
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`note_id` int UNSIGNED NOT NULL COMMENT '笔记ID',
`user_id` int UNSIGNED NOT NULL COMMENT '用户ID',
`create_time` int UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_note_user` (`note_id`, `user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='笔记收藏记录表';
2.7 话题关注表(ls_note_topic_follow)
CREATE TABLE `ls_note_topic_follow` (
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`topic_id` int UNSIGNED NOT NULL COMMENT '话题ID',
`user_id` int UNSIGNED NOT NULL COMMENT '用户ID',
`create_time` int UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_topic_user` (`topic_id`, `user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='话题关注表';
三、笔记发布功能实现
3.1 发布接口设计
笔记发布是 UGC 社区的核心入口;发布接口 /api/note/publish 的请求参数:
{
"note_type": 1,
"title": "秋季穿搭分享",
"content": "今天入手了一件超好看的外套...",
"images": ["url1", "url2"],
"video_url": "",
"topic_id": 3,
"goods_ids": [15, 28]
}
3.2 核心发布逻辑
class NoteService
{
/**
* 发布笔记
*/
public function publish($userId, $data)
{
// 1. 校验用户是否被拉黑
if ($this->isUserBlacklisted($userId)) {
throw new Exception('您已被禁止发布笔记');
}
// 2. 内容校验
$this->validateContent($data);
// 3. 敏感词检测
if (SensitiveWordService::check($data['content'])) {
throw new Exception('笔记内容包含敏感词,请修改后提交');
}
// 4. 图片/视频格式校验
if ($data['note_type'] == 1) {
if (empty($data['images']) || count($data['images']) > 9) {
throw new Exception('图片笔记需上传1-9张图片');
}
} elseif ($data['note_type'] == 2) {
if (empty($data['video_url'])) {
throw new Exception('视频笔记需上传视频');
}
}
// 5. 话题校验
if (!empty($data['topic_id'])) {
$topic = NoteTopicModel::where('id', $data['topic_id'])
->where('status', 1)->find();
if (!$topic) {
throw new Exception('话题不存在或已禁用');
}
}
// 6. 写入笔记
Db::startTrans();
try {
$needAudit = ConfigModel::get('note_audit_enable', 1);
$noteId = NoteModel::create([
'user_id' => $userId,
'title' => $data['title'],
'content' => $data['content'],
'note_type' => $data['note_type'],
'images' => json_encode($data['images'] ?? [], JSON_UNESCAPED_UNICODE),
'video_url' => $data['video_url'] ?? '',
'video_cover' => $this->extractVideoCover($data['video_url'] ?? ''),
'topic_id' => $data['topic_id'] ?? 0,
'category_id' => $topic['category_id'] ?? 0,
'audit_status'=> $needAudit ? 0 : 1,
'create_time' => time(),
])->id;
// 7. 关联商品
if (!empty($data['goods_ids'])) {
$this->bindGoods($noteId, $data['goods_ids']);
}
// 8. 更新话题笔记数
if (!empty($data['topic_id'])) {
NoteTopicModel::where('id', $data['topic_id'])
->inc('note_count', 1)->update();
}
Db::commit();
// 9. 触发审核检测
if ($needAudit) {
event('NoteSubmitAudit', ['note_id' => $noteId]);
}
return ['note_id' => $noteId, 'need_audit' => $needAudit];
} catch (\Exception $e) {
Db::rollback();
throw $e;
}
}
/**
* 关联商品到笔记
*/
private function bindGoods($noteId, $goodsIds)
{
$goodsIds = array_unique(array_filter($goodsIds));
if (count($goodsIds) > 10) {
throw new Exception('一条笔记最多关联10个商品');
}
foreach ($goodsIds as $sort => $goodsId) {
// 校验商品是否存在且上架
$goods = GoodsModel::where('id', $goodsId)
->where('status', 1)->where('del', 0)->find();
if (!$goods) continue;
NoteGoodsModel::create([
'note_id' => $noteId,
'goods_id' => $goodsId,
'sort' => $sort,
'create_time' => time(),
]);
}
}
/**
* 视频封面提取(截取前三秒)
*/
private function extractVideoCover($videoUrl)
{
if (empty($videoUrl)) return '';
// 调用 FFmpeg 截取视频前三秒作为封面
// 实际实现中通过队列异步处理
return $videoUrl . '?vframe/jpg/offset/3';
}
}
3.3 内容审核机制
笔记发布后进入审核流程;审核支持两种模式:
模式一:人工审核。笔记写入后 audit_status = 0 (待审核),后台"笔记管理"页面展示待审核列表,管理员逐条审核;审核通过后笔记对外可见,驳回时需填写驳回原因。
模式二:AI 自动审核。可接入百度智能鉴定等第三方内容安全服务,笔记上传后自动触发鉴定,鉴定结果为不合规时自动驳回并记录在案;审核通过的笔记直接对外展示,无需人工介入。
3.4 后台配置
在"应用中心 → 种草社区 → 基础设置"中增加:
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| 笔记审核开关 | 开关 | 开启 | 笔记是否需审核后展示 |
| AI 自动审核 | 开关 | 关闭 | 是否开启第三方内容安全鉴定 |
| 笔记最大图片数 | 数字输入 | 9 | 单条笔记图片上限 |
| 笔记最大字数 | 数字输入 | 1000 | 笔记正文字数上限 |
| 每日发布上限 | 数字输入 | 5 | 用户每日发布笔记上限,0为不限 |
四、话题广场功能实现
4.1 话题广场首页
话题广场是社区内容的流量入口,展示热门话题和最新话题;话题列表接口返回数据包含话题名称、封面图、笔记数量、关注人数,并支持按"推荐""最新""最热"排序:
class NoteTopicService
{
public function getTopicList($sortBy = 'recommend', $categoryId = 0, $page = 1, $size = 20)
{
$query = NoteTopicModel::where('status', 1);
if ($categoryId > 0) {
$query->where('category_id', $categoryId);
}
switch ($sortBy) {
case 'recommend':
$query->where('is_recommend', 1)
->order('sort', 'desc');
break;
case 'newest':
$query->order('create_time', 'desc');
break;
case 'hottest':
$query->order('note_count', 'desc');
break;
}
$list = $query->page($page, $size)->select();
// 批量查询当前用户是否已关注
$userId = request()->userId ?? 0;
if ($userId > 0) {
$topicIds = array_column($list->toArray(), 'id');
$followedIds = NoteTopicFollowModel::where('user_id', $userId)
->whereIn('topic_id', $topicIds)
->column('topic_id');
foreach ($list as &$item) {
$item['is_followed'] = in_array($item['id'], $followedIds) ? 1 : 0;
}
}
return $list;
}
}
4.2 话题关注与取消
public function followTopic($userId, $topicId)
{
$topic = NoteTopicModel::where('id', $topicId)
->where('status', 1)->find();
if (!$topic) {
throw new Exception('话题不存在');
}
// 幂等:已关注则忽略
$exists = NoteTopicFollowModel::where('user_id', $userId)
->where('topic_id', $topicId)->find();
if ($exists) {
throw new Exception('您已关注该话题');
}
Db::startTrans();
try {
NoteTopicFollowModel::create([
'topic_id' => $topicId,
'user_id' => $userId,
'create_time' => time(),
]);
NoteTopicModel::where('id', $topicId)->inc('follow_count', 1)->update();
Db::commit();
} catch (\Exception $e) {
Db::rollback();
throw $e;
}
}
4.3 话题下的笔记流
话题详情页展示该话题下的笔记列表,支持按"最新"和"最热"排序;列表采用瀑布流布局,根据第一张图片的长度比例实现瀑布流效果:
public function getTopicNotes($topicId, $sortBy = 'newest', $page = 1, $size = 10)
{
$query = NoteModel::where('topic_id', $topicId)
->where('audit_status', 1)
->where('status', 1)
->where('del', 0);
if ($sortBy == 'hottest') {
$query->order('like_count', 'desc')->order('create_time', 'desc');
} else {
$query->order('is_top', 'desc')->order('create_time', 'desc');
}
$list = $query->page($page, $size)->select();
// 批量补齐用户信息和商品信息
$this->fillUserInfo($list);
$this->fillGoodsInfo($list);
return $list;
}
4.4 后台配置
在"应用中心 → 种草社区 → 话题管理"中增加话题管理页面,支持话题的增删改查、置顶、推荐、启用/禁用;话题分类在"类目管理"中维护,形成"分类 → 话题 → 笔记"的三级结构。
五、商品挂载与转化链路实现
5.1 笔记详情页的商品展示
笔记详情接口在返回笔记内容的同时,关联查询挂载的商品信息;商品以卡片形式展示在笔记内容下方:
public function getNoteDetail($noteId, $userId = 0)
{
$note = NoteModel::where('id', $noteId)
->where('audit_status', 1)
->where('status', 1)
->where('del', 0)
->find();
if (!$note) {
throw new Exception('笔记不存在或已下架');
}
// 浏览量递增(Redis 原子递增,定时同步到数据库)
Redis::incr("note:view:{$noteId}");
// 查询关联商品
$goodsList = NoteGoodsModel::alias('ng')
->join('goods g', 'ng.goods_id = g.id')
->where('ng.note_id', $noteId)
->where('g.status', 1)
->where('g.del', 0)
->field('g.id, g.name, g.image, g.price, g.market_price, ng.sort')
->order('ng.sort', 'asc')
->select();
// 查询发布者信息
$user = UserModel::field('id, nickname, avatar')->find($note['user_id']);
// 查询当前用户互动状态
$isLiked = 0;
$isCollected = 0;
if ($userId > 0) {
$isLiked = NoteLikeModel::where('note_id', $noteId)
->where('user_id', $userId)->count();
$isCollected = NoteCollectModel::where('note_id', $noteId)
->where('user_id', $userId)->count();
}
return [
'note' => $note,
'goods_list' => $goodsList,
'user' => $user,
'is_liked' => $isLiked ? 1 : 0,
'is_collected' => $isCollected ? 1 : 0,
'like_count' => $note['like_count'] + $note['virtual_like'],
];
}
5.2 商品点击的转化追踪
用户在笔记中点击商品卡片跳转到商品详情页时,记录转化来源:
public function trackGoodsClick($noteId, $goodsId, $userId)
{
// 写入转化追踪记录(可异步写入日志表)
NoteConversionLogModel::create([
'note_id' => $noteId,
'goods_id' => $goodsId,
'user_id' => $userId,
'action' => 'click',
'create_time' => time(),
]);
// 商品浏览量递增
Redis::incr("goods:view:{$goodsId}");
}
5.3 商品挂载的展示规则
- 笔记详情页展示挂载商品时,仅展示状态为上架且未删除的商品
- 商品按 sort 字段排序,运营可在后台调整排序
- 如果挂载的商品已下架,该商品在笔记详情中自动隐藏,不影响笔记本身的展示
- 每条笔记最多关联 10 个商品,后台可配置上限
六、点赞与评论功能实现
6.1 点赞逻辑
点赞采用"记录表 + 计数字段"的双重机制;ls_note_like 表记录每条点赞明细,ls_note 表的 like_count 字段做计数缓存,避免每次查询都去 count 记录表:
public function toggleLike($userId, $noteId)
{
$note = NoteModel::where('id', $noteId)
->where('audit_status', 1)
->where('status', 1)
->find();
if (!$note) {
throw new Exception('笔记不存在');
}
$exists = NoteLikeModel::where('note_id', $noteId)
->where('user_id', $userId)->find();
Db::startTrans();
try {
if ($exists) {
// 取消点赞
NoteLikeModel::where('id', $exists['id'])->delete();
NoteModel::where('id', $noteId)->dec('like_count', 1)->update();
$isLiked = 0;
} else {
// 点赞
NoteLikeModel::create([
'note_id' => $noteId,
'user_id' => $userId,
'create_time' => time(),
]);
NoteModel::where('id', $noteId)->inc('like_count', 1)->update();
$isLiked = 1;
}
Db::commit();
} catch (\Exception $e) {
Db::rollback();
throw $e;
}
return ['is_liked' => $isLiked];
}
点赞数展示时,前端看到的点赞数是实际点赞数加上虚拟点赞数(like_count + virtual_like),后台可修改虚拟点赞数。
6.2 评论逻辑
评论支持一级评论和二级回复(楼中楼),通过 parent_id 和 reply_user_id 实现:
public function addComment($userId, $noteId, $content, $parentId = 0, $replyUserId = 0)
{
if (empty(trim($content))) {
throw new Exception('评论内容不能为空');
}
if (mb_strlen($content) > 500) {
throw new Exception('评论内容不能超过500字');
}
if (SensitiveWordService::check($content)) {
throw new Exception('评论内容包含敏感词');
}
// 校验父评论
if ($parentId > 0) {
$parent = NoteCommentModel::where('id', $parentId)
->where('note_id', $noteId)->find();
if (!$parent) {
throw new Exception('回复的评论不存在');
}
}
$commentId = NoteCommentModel::create([
'note_id' => $noteId,
'user_id' => $userId,
'parent_id' => $parentId,
'reply_user_id'=> $replyUserId,
'content' => $content,
'audit_status' => ConfigModel::get('comment_audit_enable', 0) ? 0 : 1,
'create_time' => time(),
])->id;
// 更新笔记评论数
NoteModel::where('id', $noteId)->inc('comment_count', 1)->update();
// 通知笔记作者和被回复用户
if ($note = NoteModel::find($noteId)) {
if ($note['user_id'] != $userId) {
MessageService::send($note['user_id'], '笔记收到新评论', $content);
}
}
if ($replyUserId > 0 && $replyUserId != $userId) {
MessageService::send($replyUserId, '有人回复了你的评论', $content);
}
return ['comment_id' => $commentId];
}
6.3 举报与拉黑机制
后台支持处理用户举报的笔记或评论,可以隐藏对应的笔记和评论;作者拉黑后无法发布笔记和下单:
CREATE TABLE `ls_note_report` (
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`target_type` tinyint NOT NULL DEFAULT 1 COMMENT '举报对象:1-笔记,2-评论',
`target_id` int UNSIGNED NOT NULL COMMENT '举报对象ID',
`reporter_id` int UNSIGNED NOT NULL COMMENT '举报人ID',
`reason` varchar(255) NOT NULL DEFAULT '' COMMENT '举报原因',
`status` tinyint NOT NULL DEFAULT 0 COMMENT '处理状态:0-待处理,1-已处理',
`handle_remark` varchar(255) NOT NULL DEFAULT '' COMMENT '处理备 注',
`create_time` int UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
KEY `idx_target` (`target_type`, `target_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='举报记录表';
七、完整开发步骤总结
7.1 数据库变更清单
| 操作 | 表名 | 说明 |
|---|---|---|
| CREATE | ls_note | 笔记主表 |
| CREATE | ls_note_topic | 话题表 |
| CREATE | ls_note_category | 话题分类表 |
| CREATE | ls_note_goods | 笔记-商品关联表 |
| CREATE | ls_note_like | 点赞记录表 |
| CREATE | ls_note_comment | 评论表 |
| CREATE | ls_note_collect | 收藏记录表 |
| CREATE | ls_note_topic_follow | 话题关注表 |
| CREATE | ls_note_report | 举报记录表 |
| CREATE | ls_note_conversion_log | 转化追踪日志表 |
7.2 后端开发清单
| 模块 | 文件/类 | 工作内容 |
|---|---|---|
| 数据层 | NoteModel | 笔记主表 Model |
| 数据层 | NoteTopicModel | 话题 Model |
| 数据层 | NoteGoodsModel | 商品关联 Model |
| 数据层 | NoteLikeModel / NoteCommentModel / NoteCollectModel | 互动记录 Model |
| 业务层 | NoteService | 笔记发布、编辑、删除、列表查询 |
| 业务层 | NoteTopicService | 话题创建、关注、列表、笔记流 |
| 业务层 | NoteInteractionService | 点赞、评论、收藏的统一处理 |
| 业务层 | NoteConversionService | 商品点击追踪和转化统计 |
| 业务层 | NoteAuditService | 笔记和评论的审核流程 |
| 接口层 | NoteController | 前台笔记相关接口 |
| 接口层 | NoteTopicController | 前台话题相关接口 |
| 后台接口 | NoteManageController | 后台笔记管理、话题管理、举报处理 |
| 事件 | NoteSubmitAuditEvent | 笔记提交后触发审核 |
| 定时任务 | NoteViewSync | 笔记浏览量从 Redis 同步到数据库 |
7.3 后台前端开发清单
| 页面 | 工作内容 |
|---|---|
| 种草社区 → 笔记管理 | 笔记列表(含审核状态筛选)、审核通过/驳回、置顶/隐藏/删除 |
| 种草社区 → 话题管理 | 话题增删改查、推荐设置、活动配置 |
| 种草社区 → 类目管理 | 话题分类的增删改查 |
| 种草社区 → 作者管理 | 查看作者信息、投稿数、评论数,设置拉黑 |
| 种草社区 → 举报管理 | 举报记录列表、隐藏笔记/评论、标记已处理 |
| 种草社区 → 基础设置 | 审核开关、AI审核开关、发布上限等配置 |
7.4 开发注意事项
二开规范方面:遵循"稳定内核原则",不修改 ls_article 表结构和原生资讯模块的代码;种草社区作为独立模块开发,通过统一的 Controlle 层对外提供接口,通过 Model 层与用户表、商品表做关联;新增能力集中在独立的 Service 中,核心 Logic 文件保持只读。
数据一致性方面:点赞、评论、收藏的计数采用"记录表 + 计数字段"模式,写操作在同一事务中完成;浏览量等高频写操作先走 Redis 原子递增,定时任务批量同步到数据库。
审核性能方面:笔记审核支持批量操作,待审核数量在后台菜单以角标展示;AI 自动审核通过队列异步处理,不阻塞用户发布流程。
内容安全方面:笔记标题、正文、评论均需经过敏感词过滤;图片和视频建议接入第三方内容安全鉴定服务,对不合规内容自动驳回。
性能优化方面:笔记列表的瀑布流查询使用覆盖索引,避免回表;话题笔记数、关注数等统计字段通过 Redis 计数器维护,定时同步;笔记详情页的关联商品查询使用 whereIn 批量查询,避免 N+1 问题。