[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-public-7YABYvbd":3,"public-project-articles-7YABYvbd":17},{"id":4,"uuid":5,"project_id":6,"title":7,"content":8,"type":9,"status":10,"public_enabled":10,"views":11,"sort":12,"created_at":13,"updated_at":14,"project_title":15,"project_slug":16},1203,"7YABYvbd",54,"13. 开发论坛帖子点赞和评论功能","\u003C!-- 这是一张图片，ocr 内容为： -->\n![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2026\u002Fpng\u002F751015\u002F1768810733475-fdae0d97-dc55-467c-9ef5-85ca7b18bfc8.png)\u003C!-- 这是一张图片，ocr 内容为： -->\n![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2026\u002Fpng\u002F751015\u002F1768810733476-9fccb617-12a2-4b42-9205-b4b112eb5d72.png)\n\n## SQL\n\n```sql\nCREATE TABLE `likes` (\n  `id` int NOT NULL AUTO_INCREMENT COMMENT 'ID',\n  `user_id` int DEFAULT NULL COMMENT '用户ID',\n  `article_id` int DEFAULT NULL COMMENT '帖子ID',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='点赞信息';\n```\n\n## 开发后端接口\n\n### Likes\n\n```java\npackage com.example.entity;\n\npublic class Likes {\n    private Integer id;\n    private Integer userId;\n    private Integer articleId;\n\n    public Integer getId() {\n        return id;\n    }\n\n    public void setId(Integer id) {\n        this.id = id;\n    }\n\n    public Integer getUserId() {\n        return userId;\n    }\n\n    public void setUserId(Integer userId) {\n        this.userId = userId;\n    }\n\n    public Integer getArticleId() {\n        return articleId;\n    }\n\n    public void setArticleId(Integer articleId) {\n        this.articleId = articleId;\n    }\n}\n\n```\n\n### LikesMapper\n\n```xml\n\u003C?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\u003C!DOCTYPE mapper\n        PUBLIC \"-\u002F\u002Fmybatis.org\u002F\u002FDTD Mapper 3.0\u002F\u002FEN\"\n        \"http:\u002F\u002Fmybatis.org\u002Fdtd\u002Fmybatis-3-mapper.dtd\">\n\u003Cmapper namespace=\"com.example.mapper.LikesMapper\">\n\n    \u003Cselect id=\"selectAll\" resultType=\"com.example.entity.Likes\">\n        select * from `likes`\n        \u003Cwhere>\n            \u003Cif test=\"userId != null\"> and likes.user_id = #{userId}\u003C\u002Fif>\n            \u003Cif test=\"articleId != null\"> and likes.article_id = #{articleId}\u003C\u002Fif>\n        \u003C\u002Fwhere>\n        order by id desc\n    \u003C\u002Fselect>\n\n    \u003Cinsert id=\"insert\" parameterType=\"com.example.entity.Likes\" useGeneratedKeys=\"true\">\n        insert into `likes`\n        \u003Ctrim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n            \u003Cif test=\"id != null\">id,\u003C\u002Fif>\n            \u003Cif test=\"userId != null\">user_id,\u003C\u002Fif>\n            \u003Cif test=\"articleId != null\">article_id,\u003C\u002Fif>\n        \u003C\u002Ftrim>\n        values\n        \u003Ctrim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n            \u003Cif test=\"id != null\">#{id},\u003C\u002Fif>\n            \u003Cif test=\"userId != null\">#{userId},\u003C\u002Fif>\n            \u003Cif test=\"articleId != null\">#{articleId},\u003C\u002Fif>\n        \u003C\u002Ftrim>\n    \u003C\u002Finsert>\n\n    \u003Cupdate id=\"updateById\" parameterType=\"com.example.entity.Likes\">\n        update `likes`\n        \u003Cset>\n            \u003Cif test=\"id != null\">\n                id = #{id},\n            \u003C\u002Fif>\n            \u003Cif test=\"userId != null\">\n                user_id = #{userId},\n            \u003C\u002Fif>\n            \u003Cif test=\"articleId != null\">\n                article_id = #{articleId},\n            \u003C\u002Fif>\n        \u003C\u002Fset>\n        where id = #{id}\n    \u003C\u002Fupdate>\n\n\u003C\u002Fmapper>\n```\n\n## 详情页面\n\n```vue\n\u003Ctemplate>\n  \u003Cdiv class=\"card\" style=\"width: 60%; margin:  0 auto; padding: 50px; position: relative\">\n    \u003Cel-button @click=\"router.back()\" style=\"position: absolute; top: 10px; left: 10px\">返回论坛列表\u003C\u002Fel-button>\n    \u003Cdiv style=\"position: absolute; top: 10px; right: 10px; width: fit-content; cursor: pointer\">\n      \u003Cimg src=\"@\u002Fassets\u002Fimgs\u002F赞-1.png\" alt=\"\" style=\"width: 30px\" v-if=\"!data.likes?.id\" @click=\"addLike\">\n      \u003Cimg src=\"@\u002Fassets\u002Fimgs\u002F赞.png\" alt=\"\" style=\"width: 30px\" v-if=\"data.likes?.id\"  @click=\"removeLike\">\n    \u003C\u002Fdiv>\n    \u003Cdiv style=\"font-size: 28px; font-weight: bold; text-align: center; margin-bottom: 15px\">{{ data.article.title }}\u003C\u002Fdiv>\n    \u003Cdiv style=\"font-size: 14px; color: #666; text-align: center; margin-bottom: 30px\">发布人：{{ data.article.userName }}   \u003Cspan style=\"margin-left: 20px\">发布时间：{{ data.article.time }}\u003C\u002Fspan>\u003C\u002Fdiv>\n    \u003Cdiv v-html=\"data.article.content\">\u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport { reactive } from \"vue\";\nimport request from \"@\u002Futils\u002Frequest\";\nimport router from \"@\u002Frouter\";\nimport {ElMessage} from \"element-plus\";\n\nconst data = reactive({\n  user: JSON.parse(localStorage.getItem('system-user') || '{}'),\n  id: router.currentRoute.value.query.id,\n  article: {},\n  likes: {}\n})\n\nrequest.get('\u002Farticle\u002FselectById\u002F' + data.id).then(res => {\n  data.article = res.data\n})\n\nconst loadLikes = () => {\n  request.get('\u002Flikes\u002FselectAll', {\n    params: {\n      articleId: data.id,\n      userId: data.user.id\n    }\n  }).then(res => {\n    data.likes = res.data.length ? res.data[0] : {}\n  })\n}\nloadLikes()\n\n\nconst addLike = () => {\n  request.post('\u002Flikes\u002Fadd', { userId : data.user.id, articleId: data.id }).then(res => {\n    ElMessage.success('操作成功')\n    loadLikes()\n  })\n}\n\u003C\u002Fscript>\n```\n\n## 评论表\n\n```sql\nCREATE TABLE `comments` (\n  `id` int NOT NULL AUTO_INCREMENT COMMENT 'ID',\n  `user_id` int DEFAULT NULL COMMENT '用户ID',\n  `article_id` int DEFAULT NULL COMMENT '帖子ID',\n  `content` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '内容',\n  `time` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '时间',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='评论信息';\n```\n\n\n\n## 后端接口\n\nComments\n\n```java\npackage com.example.entity;\n\npublic class Comments {\n\n    \u002F**ID *\u002F\n    private Integer id;\n    \u002F**用户ID *\u002F\n    private Integer userId;\n    private String userName;\n    \u002F**帖子ID *\u002F\n    private Integer articleId;\n    private String articleTitle;\n    private String avatar;\n    \u002F**内容 *\u002F\n    private String content;\n    private String time;\n\n    public String getTime() {\n        return time;\n    }\n\n    public void setTime(String time) {\n        this.time = time;\n    }\n\n    public String getAvatar() {\n        return avatar;\n    }\n\n    public void setAvatar(String avatar) {\n        this.avatar = avatar;\n    }\n\n    public String getUserName() {\n        return userName;\n    }\n\n    public void setUserName(String userName) {\n        this.userName = userName;\n    }\n\n    public String getArticleTitle() {\n        return articleTitle;\n    }\n\n    public void setArticleTitle(String articleTitle) {\n        this.articleTitle = articleTitle;\n    }\n\n    public Integer getId() {\n        return id;\n    }\n\n    public void setId(Integer id) {\n        this.id = id;\n    }\n\n    public Integer getUserId() {\n        return userId;\n    }\n\n    public void setUserId(Integer userId) {\n        this.userId = userId;\n    }\n\n    public Integer getArticleId() {\n        return articleId;\n    }\n\n    public void setArticleId(Integer articleId) {\n        this.articleId = articleId;\n    }\n\n    public String getContent() {\n        return content;\n    }\n\n    public void setContent(String content) {\n        this.content = content;\n    }\n}\n\n```\n\nCommentsMapper.xml\n\n```xml\n\u003C?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\u003C!DOCTYPE mapper\n        PUBLIC \"-\u002F\u002Fmybatis.org\u002F\u002FDTD Mapper 3.0\u002F\u002FEN\"\n        \"http:\u002F\u002Fmybatis.org\u002Fdtd\u002Fmybatis-3-mapper.dtd\">\n\u003Cmapper namespace=\"com.example.mapper.CommentsMapper\">\n\n    \u003Cselect id=\"selectAll\" resultType=\"com.example.entity.Comments\">\n        select comments.*, user.name as userName, user.avatar, article.title as articleTitle from `comments`\n        left join user on comments.user_id = user.id\n        left join article on comments.article_id = article.id\n        \u003Cwhere>\n            \u003Cif test=\"userId != null\"> and comments.user_id = #{userId}\u003C\u002Fif>\n            \u003Cif test=\"articleId != null\"> and comments.article_id = #{articleId}\u003C\u002Fif>\n        \u003C\u002Fwhere>\n        order by comments.id desc\n    \u003C\u002Fselect>\n\n    \u003Cinsert id=\"insert\" parameterType=\"com.example.entity.Comments\" useGeneratedKeys=\"true\">\n        insert into `comments`\n        \u003Ctrim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n            \u003Cif test=\"id != null\">id,\u003C\u002Fif>\n            \u003Cif test=\"userId != null\">user_id,\u003C\u002Fif>\n            \u003Cif test=\"articleId != null\">article_id,\u003C\u002Fif>\n            \u003Cif test=\"content != null\">content,\u003C\u002Fif>\n            \u003Cif test=\"time != null\">time,\u003C\u002Fif>\n        \u003C\u002Ftrim>\n        values\n        \u003Ctrim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n            \u003Cif test=\"id != null\">#{id},\u003C\u002Fif>\n            \u003Cif test=\"userId != null\">#{userId},\u003C\u002Fif>\n            \u003Cif test=\"articleId != null\">#{articleId},\u003C\u002Fif>\n            \u003Cif test=\"content != null\">#{content},\u003C\u002Fif>\n            \u003Cif test=\"time != null\">#{time},\u003C\u002Fif>\n        \u003C\u002Ftrim>\n    \u003C\u002Finsert>\n\n    \u003Cupdate id=\"updateById\" parameterType=\"com.example.entity.Comments\">\n        update `comments`\n        \u003Cset>\n            \u003Cif test=\"id != null\">\n                id = #{id},\n            \u003C\u002Fif>\n            \u003Cif test=\"userId != null\">\n                user_id = #{userId},\n            \u003C\u002Fif>\n            \u003Cif test=\"articleId != null\">\n                article_id = #{articleId},\n            \u003C\u002Fif>\n            \u003Cif test=\"content != null\">\n                content = #{content},\n            \u003C\u002Fif>\n            \u003Cif test=\"time != null\">\n                time = #{time},\n            \u003C\u002Fif>\n        \u003C\u002Fset>\n        where id = #{id}\n    \u003C\u002Fupdate>\n\n\u003C\u002Fmapper>\n```\n\n\n\n管理页面\n\n```vue\n\u003Ctemplate>\n  \u003Cdiv>\n\n    \u003Cdiv class=\"card\" style=\"margin-bottom: 5px;\">\n      \u003Cel-input v-model=\"data.articleTitle\" style=\"width: 300px; margin-right: 10px\" placeholder=\"请输入帖子标题查询\">\u003C\u002Fel-input>\n      \u003Cel-button type=\"primary\" @click=\"load\">查询\u003C\u002Fel-button>\n      \u003Cel-button type=\"info\" style=\"margin: 0 10px\" @click=\"reset\">重置\u003C\u002Fel-button>\n    \u003C\u002Fdiv>\n\n    \u003Cdiv class=\"card\" style=\"margin-bottom: 5px\">\n      \u003Cel-table :data=\"data.tableData\" stripe>\n        \u003Cel-table-column prop=\"articleTitle\" label=\"帖子标题\">\u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"content\" label=\"内容\" show-overflow-tooltip>\u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"userName\" label=\"发布人\">\u003C\u002Fel-table-column>\n        \u003Cel-table-column label=\"操作\" align=\"center\" width=\"160\">\n          \u003Ctemplate #default=\"scope\">\n            \u003Cel-button type=\"primary\" @click=\"handleEdit(scope.row)\" v-if=\"data.user.role === '普通用户'\">编辑\u003C\u002Fel-button>\n            \u003Cel-button type=\"danger\" @click=\"handleDelete(scope.row.id)\">删除\u003C\u002Fel-button>\n          \u003C\u002Ftemplate>\n        \u003C\u002Fel-table-column>\n      \u003C\u002Fel-table>\n    \u003C\u002Fdiv>\n\n    \u003Cdiv class=\"card\">\n      \u003Cel-pagination @current-change=\"load\" background layout=\"total, prev, pager, next\" v-model:page-size=\"data.pageSize\" v-model:current-page=\"data.pageNum\" :total=\"data.total\"\u002F>\n    \u003C\u002Fdiv>\n\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport request from \"@\u002Futils\u002Frequest\";\nimport {reactive, ref} from \"vue\";\nimport {ElMessageBox, ElMessage} from \"element-plus\";\n\nconst formRef = ref()\nconst data = reactive({\n  user: JSON.parse(localStorage.getItem('system-user') || '{}'),\n  pageNum: 1,\n  pageSize: 10,\n  total: 0,\n  formVisible: false,\n  form: {},\n  tableData: [],\n  articleTitle: null,\n})\n\n\u002F\u002F 分页查询\nconst load = () => {\n  request.get('\u002Fcomments\u002FselectPage', {\n    params: {\n      pageNum: data.pageNum,\n      pageSize: data.pageSize,\n      articleTitle: data.articleTitle,\n      userId: data.user.role === '管理员' ? null : data.user.id,\n    }\n  }).then(res => {\n    data.tableData = res.data?.list\n    data.total = res.data?.total\n  })\n}\n\n\u002F\u002F 新增\nconst handleAdd = () => {\n  data.form = {}\n  data.formVisible = true\n}\n\n\u002F\u002F 编辑\nconst handleEdit = (row) => {\n  data.form = JSON.parse(JSON.stringify(row))\n  data.formVisible = true\n}\n\n\u002F\u002F 新增保存\nconst add = () => {\n  request.post('\u002Fcomments\u002Fadd', data.form).then(res => {\n    if (res.code === '200') {\n      load()\n      ElMessage.success('操作成功')\n      data.formVisible = false\n    } else {\n      ElMessage.error(res.msg)\n    }\n  })\n}\n\n\u002F\u002F 编辑保存\nconst update = () => {\n  request.put('\u002Fcomments\u002Fupdate', data.form).then(res => {\n    if (res.code === '200') {\n      load()\n      ElMessage.success('操作成功')\n      data.formVisible = false\n    } else {\n      ElMessage.error(res.msg)\n    }\n  })\n}\n\n\u002F\u002F 弹窗保存\nconst save = () => {\n  formRef.value.validate(valid => {\n    if (valid) {\n      \u002F\u002F data.form有id就是更新，没有就是新增\n      data.form.id ? update() : add()\n    }\n  })\n}\n\n\u002F\u002F 删除\nconst handleDelete = (id) => {\n  ElMessageBox.confirm('删除后数据无法恢复，您确定删除吗?', '删除确认', { type: 'warning' }).then(res => {\n    request.delete('\u002Fcomments\u002Fdelete\u002F' + id).then(res => {\n      if (res.code === '200') {\n        load()\n        ElMessage.success('操作成功')\n      } else {\n        ElMessage.error(res.msg)\n      }\n    })\n  }).catch(err => {})\n}\n\n\u002F\u002F 重置\nconst reset = () => {\n  data.articleTitle = null\n  load()\n}\n\nload()\n\u003C\u002Fscript>\n```\n\n\n\n详情页 \n\n```vue\n\u003Ctemplate>\n  \u003Cdiv style=\"width: 60%; margin:  0 auto;\">\n    \u003Cdiv class=\"card\" style=\"padding: 50px; position: relative; margin-bottom: 20px\">\n      \u003Cel-button @click=\"router.back()\" style=\"position: absolute; top: 10px; left: 10px\">返回论坛列表\u003C\u002Fel-button>\n      \u003Cdiv style=\"position: absolute; top: 10px; right: 10px; width: fit-content; cursor: pointer\">\n        \u003Cimg src=\"@\u002Fassets\u002Fimgs\u002F赞-1.png\" alt=\"\" style=\"width: 30px\" v-if=\"!data.likes?.id\" @click=\"addLike\">\n        \u003Cimg src=\"@\u002Fassets\u002Fimgs\u002F赞.png\" alt=\"\" style=\"width: 30px\" v-if=\"data.likes?.id\"  @click=\"removeLike\">\n      \u003C\u002Fdiv>\n      \u003Cdiv style=\"font-size: 28px; font-weight: bold; text-align: center; margin-bottom: 15px\">{{ data.article.title }}\u003C\u002Fdiv>\n      \u003Cdiv style=\"font-size: 14px; color: #666; text-align: center; margin-bottom: 30px\">发布人：{{ data.article.userName }}   \u003Cspan style=\"margin-left: 20px\">发布时间：{{ data.article.time }}\u003C\u002Fspan>\u003C\u002Fdiv>\n      \u003Cdiv v-html=\"data.article.content\">\u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n\n    \u003Cdiv class=\"card\" style=\"padding: 20px\">\n      \u003Cdiv style=\"font-size: 20px; margin-bottom: 15px; font-weight: bold\">评论列表（{{ data.total }}）\u003C\u002Fdiv>\n      \u003Cdiv style=\"margin-bottom: 20px\">\n        \u003Cel-input type=\"textarea\" :maxlength=\"200\" v-model=\"data.content\" placeholder=\"请输入评论内容，限200字\" :rows=\"3\">\u003C\u002Fel-input>\n        \u003Cdiv style=\"text-align: right\">\n          \u003Cel-button style=\"margin-top: 5px;\" type=\"primary\" @click=\"addComment\">发布评论\u003C\u002Fel-button>\n        \u003C\u002Fdiv>\n      \u003C\u002Fdiv>\n\n      \u003Cdiv v-for=\"item in data.commentList\" :key=\"item.id\" style=\"display: flex; gap: 10px; margin-bottom: 20px\">\n        \u003Cimg :src=\"item.avatar\" alt=\"\" style=\"width: 50px; height: 50px; border-radius: 50%\">\n        \u003Cdiv style=\"flex: 1; padding-bottom: 10px; border-bottom: 1px solid #ddd; \">\n          \u003Cdiv style=\"margin-bottom: 10px\">{{ item.userName }} \u003Cspan style=\"margin-left: 10px; color: #666; font-size: 13px\">{{ item.time }}\u003C\u002Fspan>\u003C\u002Fdiv>\n          \u003Cdiv style=\"color: #666\">{{ item.content }}\u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n      \u003C\u002Fdiv>\n\n      \u003Cdiv style=\"margin-top: 20px\">\n        \u003Cel-pagination @current-change=\"loadComment\" layout=\"total, prev, pager, next\" v-model:page-size=\"data.pageSize\" v-model:current-page=\"data.pageNum\" :total=\"data.total\"\u002F>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport { reactive } from \"vue\";\nimport request from \"@\u002Futils\u002Frequest\";\nimport router from \"@\u002Frouter\";\nimport {ElMessage} from \"element-plus\";\n\nconst data = reactive({\n  user: JSON.parse(localStorage.getItem('system-user') || '{}'),\n  id: router.currentRoute.value.query.id,\n  article: {},\n  likes: {},\n  pageNum: 1,\n  pageSize: 5,\n  total: 0,\n  content: null,\n  commentList: []\n})\n\nrequest.get('\u002Farticle\u002FselectById\u002F' + data.id).then(res => {\n  data.article = res.data\n})\n\nconst loadLikes = () => {\n  request.get('\u002Flikes\u002FselectAll', {\n    params: {\n      articleId: data.id,\n      userId: data.user.id\n    }\n  }).then(res => {\n    data.likes = res.data.length ? res.data[0] : {}\n  })\n}\nloadLikes()\n\n\nconst addLike = () => {\n  request.post('\u002Flikes\u002Fadd', { userId : data.user.id, articleId: data.id }).then(res => {\n    ElMessage.success('操作成功')\n    loadLikes()\n  })\n}\n\n\u002F\u002F 分页查询\nconst loadComment = () => {\n  request.get('\u002Fcomments\u002FselectPage', {\n    params: {\n      pageNum: data.pageNum,\n      pageSize: data.pageSize,\n      articleId: data.id\n    }\n  }).then(res => {\n    data.commentList = res.data?.list\n    data.total = res.data?.total\n  })\n}\nloadComment()\n\nconst addComment = () => {\n  request.post('\u002Fcomments\u002Fadd', { userId : data.user.id, articleId: data.id, content: data.content}).then(res => {\n    ElMessage.success('评论成功')\n    data.content = null  \u002F\u002F 清空旧评论\n    loadComment()\n  })\n}\n\u003C\u002Fscript>\n```\n\n","coding",1,239,2340,"2026-01-19 17:04:37","2026-05-03 22:49:02","基于SpringBoot3+Vue3的校园物品分享系统","campus-item-sharing",{"project":18,"items":19},{"id":6,"title":15,"slug":16},[20,27,34,41,48,56,63,70,77,84,91,98,105],{"id":21,"uuid":22,"project_id":6,"title":23,"type":9,"status":10,"public_enabled":10,"views":24,"sort":25,"created_at":26,"updated_at":14,"project_title":15,"project_slug":16},1085,"bKvz3GMB","01. 校园物品分享系统介绍",1584,2118,"2026-04-01 22:12:21",{"id":28,"uuid":29,"project_id":6,"title":30,"type":9,"status":10,"public_enabled":10,"views":31,"sort":32,"created_at":33,"updated_at":14,"project_title":15,"project_slug":16},1086,"G7CRiFiL","02. 导入并运行项目脚手架",670,2119,"2025-12-09 16:59:49",{"id":35,"uuid":36,"project_id":6,"title":37,"type":9,"status":10,"public_enabled":10,"views":38,"sort":39,"created_at":40,"updated_at":14,"project_title":15,"project_slug":16},1087,"pgDLuOpz","03. 开发普通用户信息管理功能",544,2121,"2025-12-09 16:59:38",{"id":42,"uuid":43,"project_id":6,"title":44,"type":9,"status":10,"public_enabled":10,"views":45,"sort":46,"created_at":47,"updated_at":14,"project_title":15,"project_slug":16},1090,"2l7FVzgx","04. 开发普通用户登录、注册、个人信息、修改密码功能",365,2131,"2025-12-10 16:11:48",{"id":49,"uuid":50,"project_id":6,"title":51,"type":9,"status":10,"public_enabled":10,"views":52,"sort":53,"created_at":54,"updated_at":55,"project_title":15,"project_slug":16},1091,"l5SB4JYK","05. 开发系统公告管理功能",417,2132,"2025-12-10 16:12:08","2026-05-07 15:36:12.649662+00",{"id":57,"uuid":58,"project_id":6,"title":59,"type":9,"status":10,"public_enabled":10,"views":60,"sort":61,"created_at":62,"updated_at":14,"project_title":15,"project_slug":16},1098,"mXLOXdBC","06. 开发物品分类信息管理功能",297,2143,"2025-12-11 16:37:57",{"id":64,"uuid":65,"project_id":6,"title":66,"type":9,"status":10,"public_enabled":10,"views":67,"sort":68,"created_at":69,"updated_at":14,"project_title":15,"project_slug":16},1099,"nj87VT4L","07. 开发物品信息管理功能",406,2144,"2025-12-11 16:38:16",{"id":71,"uuid":72,"project_id":6,"title":73,"type":9,"status":10,"public_enabled":10,"views":74,"sort":75,"created_at":76,"updated_at":14,"project_title":15,"project_slug":16},1107,"nGHKfpf4","08. 开发用户端物品展示功能",329,2162,"2025-12-15 17:27:07",{"id":78,"uuid":79,"project_id":6,"title":80,"type":9,"status":10,"public_enabled":10,"views":81,"sort":82,"created_at":83,"updated_at":14,"project_title":15,"project_slug":16},1123,"A6caJxFd","09. 开发物品申请交换功能",322,2196,"2025-12-19 16:16:03",{"id":85,"uuid":86,"project_id":6,"title":87,"type":9,"status":10,"public_enabled":10,"views":88,"sort":89,"created_at":90,"updated_at":14,"project_title":15,"project_slug":16},1135,"s5I1gomY","10. 开发物品收藏功能",285,2223,"2025-12-23 17:38:15",{"id":92,"uuid":93,"project_id":6,"title":94,"type":9,"status":10,"public_enabled":10,"views":95,"sort":96,"created_at":97,"updated_at":14,"project_title":15,"project_slug":16},1159,"qadunvVA","11. 开发论坛帖子管理功能",263,2266,"2025-12-30 16:08:47",{"id":99,"uuid":100,"project_id":6,"title":101,"type":9,"status":10,"public_enabled":10,"views":102,"sort":103,"created_at":104,"updated_at":14,"project_title":15,"project_slug":16},1202,"CpPqHdiT","12. 开发论坛帖子展示功能",220,2339,"2026-01-19 17:04:21",{"id":4,"uuid":5,"project_id":6,"title":7,"type":9,"status":10,"public_enabled":10,"views":11,"sort":12,"created_at":13,"updated_at":14,"project_title":15,"project_slug":16}]