LikeShop 种草社区模块二开:笔记发布、话题广场与商品挂载实现

一、原生资讯模块数据表拆解

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 的二开规范,核心原则是"新增能力 > 修改原逻辑,组合扩展 > 覆盖替换";资讯模块的二开策略应当遵循:

  1. 不修改 ls_article 表结构,保持原生资讯功能不变,避免影响平台官方资讯发布
  2. 新建独立的笔记体系,与资讯模块并行运行,通过统一的内容聚合层对外提供数据
  3. 复用原生的文件上传、用户体系、商品体系,通过关联表实现笔记与商品、话题的绑定
  4. 扩展逻辑封装在独立的 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 问题。

相关推荐
IvorySQL1 小时前
PostgreSQL 日报| PostgreSQL JDBC 安全更新(10 月 10 日)
数据库·postgresql·区块链
一棵树73511 小时前
数据结构闲聊
数据结构·算法
bro_Java6661 小时前
《二叉树的基础知识、操作方法与代码示例》
java·数据结构·算法·广度优先
晚风叙码1 小时前
MySQL 增删改查(CRUD)完全指南:从入门到面试
数据库·mysql·面试
dishugj2 小时前
HANA集群计划内切换与维护操作
java·linux·数据库
IvorySQL11 小时前
PostgreSQL 日报|修复截断 zstd 备份检测(10 月 9 日)
数据库·postgresql
刘胡子大叔11 小时前
SQL 脚本的导入顺序
数据库·sql
代码什么用12 小时前
Spring对IoC的实现
数据库·spring
hz5678914 小时前
涉密视频会议设备配置指南:终端、音视频采集与配套设施选型
服务器·网络·数据库·安全·实时音视频·信息与通信·智能硬件