[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-public-gjsxuriJ":3,"public-project-articles-gjsxuriJ":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},425,"gjsxuriJ",46,"14. 开发电影评论功能","![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2024\u002Fpng\u002F751015\u002F1725500599312-ede1d631-1f93-4e75-9d7b-3d73c4ed2293.png)\n\n## 筛选短评和长评的分页数据\n\n在 sql 这里加一个 type 的条件和 filmId 条件\n\n![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2024\u002Fpng\u002F751015\u002F1725501882849-89ed1b1a-9077-47b0-b074-4df96309e370.png)\n\n在前端页面这里加一个 type 的参数和filmId 参数\n\n![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2024\u002Fpng\u002F751015\u002F1725501901034-85c4d2f0-4f8c-47e7-af22-a6ad9146b898.png)\n\n## 富文本\n\n官网\n\n[https:\u002F\u002Fwww.wangeditor.com\u002F](https:\u002F\u002Fwww.wangeditor.com\u002F)\n\n安装\n\n```javascript\nnpm install @wangeditor\u002Feditor --save\nnpm install @wangeditor\u002Feditor-for-vue@next --save\n```\n\n引入\n\n```javascript\nimport '@wangeditor\u002Feditor\u002Fdist\u002Fcss\u002Fstyle.css' \u002F\u002F 引入 css\nimport {onBeforeUnmount, ref, shallowRef} from \"vue\";\nimport { Editor, Toolbar } from '@wangeditor\u002Feditor-for-vue'\n```\n\n初始化（表单中）\n\nwangEditor 5 富文本字段可以直接和form中的字段使用v-model进行绑定\n\n```html\n\u003Cel-form-item label=\"项目介绍\" prop=\"content\">\n  \u003Cdiv style=\"border: 1px solid #ccc; width: 100%\">\n    \u003CToolbar\n        style=\"border-bottom: 1px solid #ccc\"\n        :editor=\"editorRef\"\n        :mode=\"mode\"\n    \u002F>\n    \u003CEditor\n        style=\"height: 500px; overflow-y: hidden;\"\n        v-model=\"data.form.comment\"\n        :mode=\"mode\"\n      \t:defaultConfig=\"editorConfig\"\n        @onCreated=\"handleCreated\"\n    \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Fel-form-item>\n```\n\n```javascript\n\u002F* wangEditor5 初始化开始 *\u002F\nconst baseUrl = import.meta.env.VITE_BASE_URL\nconst editorRef = shallowRef()  \u002F\u002F 编辑器实例，必须用 shallowRef\nconst mode = 'default' \nconst editorConfig = { MENU_CONF: {} }\n\u002F\u002F 图片上传配置\neditorConfig.MENU_CONF['uploadImage'] = {\n  server: baseUrl + '\u002Ffiles\u002Fwang\u002Fupload',  \u002F\u002F 服务端图片上传接口\n  fieldName: 'file'  \u002F\u002F 服务端图片上传接口参数\n}\n\u002F\u002F 组件销毁时，也及时销毁编辑器，否则可能会造成内存泄漏\nonBeforeUnmount(() => {\n  const editor = editorRef.value\n  if (editor == null) return\n  editor.destroy()\n})\n\u002F\u002F 记录 editor 实例，重要！\nconst handleCreated = (editor) => {\n  editorRef.value = editor \n}\n\u002F* wangEditor5 初始化结束 *\u002F\n```\n\n## 从外面引入的图片无法显示怎么办？\n\n![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2024\u002Fpng\u002F751015\u002F1725503482472-71626af8-adc3-4abf-bf9a-98add0bb9b0d.png)\n\n\n\n在 index.html 里面加一个标签即可\n\n```html\n\u003Cmeta name=\"referrer\" content=\"never\">\n```\n\n## 本节课源码\n\n```vue\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003Cdiv style=\"display: flex; align-items: flex-start; grid-gap: 10px\">\n      \u003Cdiv style=\"flex: 1; width: 0\">\n        \u003Cdiv class=\"card\" style=\"padding: 20px; margin-bottom: 10px\">\n          \u003Cdiv style=\"display: flex; align-items: center;\">\n            \u003Cdiv style=\"font-weight: bold; font-size: 18px; flex: 1\">{{ data.film.name }}\u003C\u002Fdiv>\n            \u003Cdiv>\n              \u003Cel-button type=\"primary\" plain @click=\"addComment('短评')\">写短评\u003C\u002Fel-button>\n              \u003Cel-button type=\"success\" plain @click=\"addComment('长评')\">写长评\u003C\u002Fel-button>\n            \u003C\u002Fdiv>\n          \u003C\u002Fdiv>\n          \u003Cdiv style=\"margin-bottom: 20px\">\n            \u003Cel-rate v-model=\"data.film.score\" disabled allow-half show-score>\u003C\u002Fel-rate>\n          \u003C\u002Fdiv>\n\n          \u003Cdiv style=\"display: flex; grid-gap: 20px; margin-bottom: 20px\">\n            \u003Cimg :src=\"data.film.cover\" alt=\"\" style=\"width: 200px; height: 270px; border-radius: 5px\">\n            \u003Cdiv style=\"flex: 1; color: #666\">\n              \u003Cdiv style=\"margin-bottom: 10px\">\u003Cstrong>导演：\u003C\u002Fstrong>{{ data.film.director }}\u003C\u002Fdiv>\n              \u003Cdiv style=\"margin-bottom: 10px\">\u003Cstrong>主演：\u003C\u002Fstrong>{{ data.film.actors }}\u003C\u002Fdiv>\n              \u003Cdiv style=\"margin-bottom: 10px\">\u003Cstrong>类型：\u003C\u002Fstrong>{{ data.film.categoryName }}\u003C\u002Fdiv>\n              \u003Cdiv style=\"margin-bottom: 10px\">\u003Cstrong>制片国家\u002F地区：\u003C\u002Fstrong>{{ data.film.country }}\u003C\u002Fdiv>\n              \u003Cdiv style=\"margin-bottom: 10px\">\u003Cstrong>语言：\u003C\u002Fstrong>{{ data.film.language }}\u003C\u002Fdiv>\n              \u003Cdiv style=\"margin-bottom: 10px\">\u003Cstrong>上映日期：\u003C\u002Fstrong>{{ data.film.date }}\u003C\u002Fdiv>\n              \u003Cdiv style=\"margin-bottom: 10px\">\u003Cstrong>片长：\u003C\u002Fstrong>{{ data.film.duration }}\u003C\u002Fdiv>\n              \u003Cdiv style=\"margin-bottom: 10px\">\u003Cstrong>IMDb：\u003C\u002Fstrong>{{ data.film.imdb }}\u003C\u002Fdiv>\n            \u003C\u002Fdiv>\n          \u003C\u002Fdiv>\n\n          \u003Cdiv style=\"font-size: 20px; color: #1967e3; margin-bottom: 10px\">{{ data.film.name }} 的剧情简介\u003C\u002Fdiv>\n          \u003Cdiv style=\"color: #666; line-height: 24px; text-align: justify\">{{ data.film.descr }}\u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n\n        \u003Cdiv class=\"card\" style=\"padding: 20px; margin-bottom: 10px\">\n          \u003Cdiv style=\"font-size: 20px; color: #239113; margin-bottom: 10px\">{{ data.film.name }} 的短评 \u003Cspan style=\"font-size: 14px; color: #333\">...(全部{{ data.totalShort }}条)\u003C\u002Fspan>\u003C\u002Fdiv>\n          \u003Cdiv style=\"border-bottom: 1px solid #eee; padding: 20px 0\" v-for=\"item in data.commentShortList\" :key=\"item.id\">\n            \u003Cdiv style=\"display: flex; align-items: center; margin-bottom: 5px\">\n              \u003Cspan>{{ item.userName }}\u003C\u002Fspan>\n              \u003Cel-rate style=\"margin: 0 10px\" v-model=\"item.score\" disabled allow-half>\u003C\u002Fel-rate>\n              \u003Cspan style=\"color: #666\">{{ item.time }}\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n            \u003Cdiv style=\"line-height: 24px; color:  #666;\">{{ item.comment }}\u003C\u002Fdiv>\n          \u003C\u002Fdiv>\n          \u003Cel-pagination layout=\"total, prev, pager, next\" v-model:current-page=\"data.pageNumShort\" v-model:page-size=\"data.pageSizeShort\"\n                         :total=\"data.totalShort\" @current-change=\"loadShortComment\" \u002F>\n        \u003C\u002Fdiv>\n\n        \u003Cdiv class=\"card\" style=\"padding: 20px\">\n          \u003Cdiv style=\"font-size: 20px; color: orange; margin-bottom: 10px\">{{ data.film.name }} 的长评 \u003Cspan style=\"font-size: 14px; color: #333\">...(全部{{ data.totalLong }}条)\u003C\u002Fspan>\u003C\u002Fdiv>\n          \u003Cdiv style=\"border-bottom: 1px solid #eee; padding: 20px 0\" v-for=\"item in data.commentLongList\" :key=\"item.id\">\n            \u003Cdiv style=\"display: flex; align-items: center; margin-bottom: 5px\">\n              \u003Cspan>{{ item.userName }}\u003C\u002Fspan>\n              \u003Cel-rate style=\"margin: 0 10px\" v-model=\"item.score\" disabled allow-half>\u003C\u002Fel-rate>\n              \u003Cspan style=\"color: #666\">{{ item.time }}\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n            \u003Cdiv style=\"line-height: 24px; color:  #666; margin-bottom: 5px\" class=\"line3\" v-html=\"item.comment\">\u003C\u002Fdiv>\n            \u003Cdiv>\u003Cspan style=\"color: #1967e3; cursor: pointer\" @click=\"viewLongComment(item.comment)\">查看更多...\u003C\u002Fspan>\u003C\u002Fdiv>\n          \u003C\u002Fdiv>\n          \u003Cel-pagination layout=\"total, prev, pager, next\" v-model:current-page=\"data.pageNumLong\" v-model:page-size=\"data.pageSizeLong\"\n                         :total=\"data.totalLong\" @current-change=\"loadLongComment\" \u002F>\n        \u003C\u002Fdiv>\n      \u003C\u002Fdiv>\n\n      \u003Cdiv style=\"width: 300px; padding: 20px\" class=\"card\">\n        \u003Cdiv style=\"font-size: 20px; margin-bottom: 20px\">推荐电影\u003C\u002Fdiv>\n        \u003Cdiv style=\"margin-bottom: 20px; cursor: pointer\" v-for=\"item in data.recommendList\" :key=\"item.id\" @click=\"goDetail(item.id)\">\n          \u003Cimg :src=\"item.cover\" alt=\"\" style=\"width: 100%; margin-bottom: 5px\">\n          \u003Cdiv style=\"font-size: 18px\">{{ item.name }}\u003C\u002Fdiv>\n          \u003Cdiv>\n            \u003Cel-rate v-model=\"item.score\" disabled allow-half show-score>\u003C\u002Fel-rate>\n          \u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n\n    \u003Cel-dialog v-model=\"data.formVisible\" title=\"评论信息\" width=\"50%\">\n      \u003Cel-form :model=\"data.form\" label-width=\"80px\" style=\"padding-right: 20px\">\n        \u003Cel-form-item label=\"打分\">\n          \u003Cel-rate v-model=\"data.form.score\" allow-half show-score>\u003C\u002Fel-rate>\n        \u003C\u002Fel-form-item>\n        \u003Cel-form-item label=\"内容\" v-if=\"data.form.type === '短评'\">\n          \u003Cel-input :rows=\"5\" type=\"textarea\" v-model=\"data.form.comment\" autocomplete=\"off\" placeholder=\"请输入内容\" \u002F>\n        \u003C\u002Fel-form-item>\n        \u003Cel-form-item label=\"内容\" prop=\"comment\" v-if=\"data.form.type === '长评'\">\n          \u003Cdiv style=\"border: 1px solid #ccc; width: 100%\">\n            \u003CToolbar\n                style=\"border-bottom: 1px solid #ccc\"\n                :editor=\"editorRef\"\n                :mode=\"mode\"\n            \u002F>\n            \u003CEditor\n                style=\"height: 500px; overflow-y: hidden;\"\n                v-model=\"data.form.comment\"\n                :mode=\"mode\"\n                :defaultConfig=\"editorConfig\"\n                @onCreated=\"handleCreated\"\n            \u002F>\n          \u003C\u002Fdiv>\n        \u003C\u002Fel-form-item>\n      \u003C\u002Fel-form>\n      \u003Ctemplate #footer>\n        \u003Cdiv class=\"dialog-footer\">\n          \u003Cel-button @click=\"data.formVisible = false\">取 消\u003C\u002Fel-button>\n          \u003Cel-button type=\"primary\" @click=\"save\">保 存\u003C\u002Fel-button>\n        \u003C\u002Fdiv>\n      \u003C\u002Ftemplate>\n    \u003C\u002Fel-dialog>\n\n    \u003Cel-dialog v-model=\"data.formVisibleView\" title=\"长评\" width=\"50%\">\n      \u003Cdiv style=\"line-height: 24px\">\n        \u003Cdiv class=\"longComment\" v-html=\"data.comment\">\u003C\u002Fdiv>\n      \u003C\u002Fdiv>\n      \u003Ctemplate #footer>\n        \u003Cdiv class=\"dialog-footer\">\n          \u003Cel-button @click=\"data.formVisibleView = false\">关闭\u003C\u002Fel-button>\n        \u003C\u002Fdiv>\n      \u003C\u002Ftemplate>\n    \u003C\u002Fel-dialog>\n\n\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport { reactive } from \"vue\";\nimport router from \"@\u002Frouter\";\nimport request from \"@\u002Futils\u002Frequest\";\nimport {ElMessage} from \"element-plus\";\nimport '@wangeditor\u002Feditor\u002Fdist\u002Fcss\u002Fstyle.css' \u002F\u002F 引入 css\nimport {onBeforeUnmount, ref, shallowRef} from \"vue\";\nimport { Editor, Toolbar } from '@wangeditor\u002Feditor-for-vue'\n\nconst data = reactive({\n  id: router.currentRoute.value.query.id,\n  film: {},\n  recommendList: [],\n  formVisible: false,\n  form: {},\n  pageNumShort: 1,\n  pageSizeShort: 3,\n  totalShort: 0,\n  commentShortList: [],\n  user: JSON.parse(localStorage.getItem('system-user') || '{}'),\n  pageNumLong: 1,\n  pageSizeLong: 3,\n  totalLong: 0,\n  commentLongList: [],\n  formVisibleView: false,\n  comment: null\n})\n\n\u002F* wangEditor5 初始化开始 *\u002F\nconst baseUrl = import.meta.env.VITE_BASE_URL\nconst editorRef = shallowRef()  \u002F\u002F 编辑器实例，必须用 shallowRef\nconst mode = 'default'\nconst editorConfig = { MENU_CONF: {} }\n\u002F\u002F 图片上传配置\neditorConfig.MENU_CONF['uploadImage'] = {\n  server: baseUrl + '\u002Ffiles\u002Fwang\u002Fupload',  \u002F\u002F 服务端图片上传接口\n  fieldName: 'file'  \u002F\u002F 服务端图片上传接口参数\n}\n\u002F\u002F 组件销毁时，也及时销毁编辑器，否则可能会造成内存泄漏\nonBeforeUnmount(() => {\n  const editor = editorRef.value\n  if (editor == null) return\n  editor.destroy()\n})\n\u002F\u002F 记录 editor 实例，重要！\nconst handleCreated = (editor) => {\n  editorRef.value = editor\n}\n\u002F* wangEditor5 初始化结束 *\u002F\n\nconst viewLongComment = (comment) => {\n  data.comment = comment\n  data.formVisibleView = true\n}\n\nconst addComment = (type) => {\n  data.form = { type: type }\n  data.formVisible = true\n}\n\n\u002F\u002F 新增评论的方法\nconst save = () => {\n  data.form.filmId = data.id\n  data.form.userId = data.user.id\n  request.post('\u002Fcomment\u002Fadd', data.form).then(res => {\n    if (res.code === '200') {\n      data.formVisible = false\n      ElMessage.success('评论成功')\n      loadShortComment()\n      loadLongComment()\n    } else {\n      ElMessage.success(res.msg)\n    }\n  })\n}\n\nconst loadShortComment = () => {\n  request.get('\u002Fcomment\u002FselectPage', {\n    params: {\n      pageNum: data.pageNumShort,\n      pageSize: data.pageSizeShort,\n      filmId: data.id,\n      type: '短评'\n    }\n  }).then(res => {\n    data.commentShortList = res.data.list\n    data.totalShort = res.data.total\n  })\n}\nloadShortComment()\n\nconst loadLongComment = () => {\n  request.get('\u002Fcomment\u002FselectPage', {\n    params: {\n      pageNum: data.pageNumShort,\n      pageSize: data.pageSizeShort,\n      filmId: data.id,\n      type: '长评'\n    }\n  }).then(res => {\n    data.commentLongList = res.data.list\n    data.totalLong = res.data.total\n  })\n}\nloadLongComment()\n\nrequest.get('\u002Ffilm\u002FselectById\u002F' + data.id).then(res => {\n  data.film = res.data\n})\n\nrequest.get('\u002Ffilm\u002FselectRecommend\u002F' + data.id).then(res => {\n  data.recommendList = res.data\n})\n\nconst goDetail = (id) => {\n  location.href = '\u002FfilmDetail?id=' + id\n}\n\u003C\u002Fscript>\n\n\u003Cstyle>\n.longComment img {\n  width: 100% !important;\n}\n\u003C\u002Fstyle>\n```\n\n","coding",1,1501,810,"2024-09-05 11:44:17","2026-05-03 22:49:02","SpringBoot3+Vue3的电影评论系统","movie-review",{"project":18,"items":19},{"id":6,"title":15,"slug":16},[20,27,34,41,48,55,62,69,76,83,90,97,104,111,112],{"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},292,"kCgjr7mm","01. 电影评论系统介绍",4823,638,"2025-01-09 09:33:06",{"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},293,"BlmKufUR","02. 导入并运行脚手架",3530,639,"2024-07-29 10:54:55",{"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},294,"06Pduwwf","03. 开发系统公告功能（1）",2477,640,"2024-07-29 12:10:44",{"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},295,"Fdq2YYG6","04. 开发系统公告功能（2）",1703,647,"2024-07-30 11:50:26",{"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":14,"project_title":15,"project_slug":16},296,"GCaoVbnp","05. 开发系统公告功能（3）",1380,648,"2024-07-30 11:51:01",{"id":56,"uuid":57,"project_id":6,"title":58,"type":9,"status":10,"public_enabled":10,"views":59,"sort":60,"created_at":61,"updated_at":14,"project_title":15,"project_slug":16},297,"RSJvf6Eg","06. 开发系统公告功能（4）",1361,649,"2024-07-30 11:52:11",{"id":63,"uuid":64,"project_id":6,"title":65,"type":9,"status":10,"public_enabled":10,"views":66,"sort":67,"created_at":68,"updated_at":14,"project_title":15,"project_slug":16},298,"joADRMpg","07. 开发首页展示公告功能（时间线）",1332,650,"2024-07-30 11:52:49",{"id":70,"uuid":71,"project_id":6,"title":72,"type":9,"status":10,"public_enabled":10,"views":73,"sort":74,"created_at":75,"updated_at":14,"project_title":15,"project_slug":16},419,"Qus99gUh","08. 开发电影分类管理功能",1607,800,"2024-09-03 10:35:12",{"id":77,"uuid":78,"project_id":6,"title":79,"type":9,"status":10,"public_enabled":10,"views":80,"sort":81,"created_at":82,"updated_at":14,"project_title":15,"project_slug":16},420,"vkbZ8lMM","09. 开发电影信息管理",1761,801,"2024-09-03 10:35:48",{"id":84,"uuid":85,"project_id":6,"title":86,"type":9,"status":10,"public_enabled":10,"views":87,"sort":88,"created_at":89,"updated_at":14,"project_title":15,"project_slug":16},421,"ZwFHi9Ao","10. 开发电影评论管理功能",1514,802,"2024-09-03 11:39:45",{"id":91,"uuid":92,"project_id":6,"title":93,"type":9,"status":10,"public_enabled":10,"views":94,"sort":95,"created_at":96,"updated_at":14,"project_title":15,"project_slug":16},422,"DmVqZCwN","11. 开发用户管理功能",1171,806,"2024-09-04 11:01:37",{"id":98,"uuid":99,"project_id":6,"title":100,"type":9,"status":10,"public_enabled":10,"views":101,"sort":102,"created_at":103,"updated_at":14,"project_title":15,"project_slug":16},423,"rrMIV8oS","12. 开发用户视角的电影列表",1331,807,"2024-09-04 11:02:08",{"id":105,"uuid":106,"project_id":6,"title":107,"type":9,"status":10,"public_enabled":10,"views":108,"sort":109,"created_at":110,"updated_at":14,"project_title":15,"project_slug":16},424,"Q6ApfoCa","13. 开发电影详情页",1254,808,"2024-09-04 11:53:18",{"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},{"id":113,"uuid":114,"project_id":6,"title":115,"type":9,"status":10,"public_enabled":10,"views":116,"sort":117,"created_at":118,"updated_at":14,"project_title":15,"project_slug":16},426,"nCDmvc9n","15. 开发电影评分排行榜功能",1051,811,"2024-09-05 11:44:44"]