[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-public-RYH15Bfu":3,"public-project-articles-RYH15Bfu":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},1075,"RYH15Bfu",52,"15. 带你实现订单评价功能","## 评价表 SQL\n\n```sql\nCREATE TABLE `comment` (\n  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID',\n  `score` double(10,1) DEFAULT NULL COMMENT '评分',\n  `content` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '评价内容',\n  `user_id` int DEFAULT NULL COMMENT '评价人',\n  `time` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '时间',\n  `order_id` int DEFAULT NULL COMMENT '订单ID',\n  `goods_id` int DEFAULT NULL COMMENT '商品ID',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='订单评价';\n```\n\n## 开发评价的后端接口\n\nComment.java\n\n```java\npackage com.example.entity;\n\npublic class Comment {\n\n    \u002F**主键ID *\u002F\n    private Integer id;\n    \u002F**评分 *\u002F\n    private Double score;\n    \u002F**评价内容 *\u002F\n    private String content;\n    \u002F**评价人 *\u002F\n    private Integer userId;\n    private String userName;\n    private String userAvatar;\n    \u002F**时间 *\u002F\n    private String time;\n    \u002F**订单ID *\u002F\n    private Integer orderId;\n    private String orderNo;\n    \u002F**商品ID *\u002F\n    private Integer goodsId;\n    private String goodsName;\n    private String goodsImg;\n\n    public String getUserAvatar() {\n        return userAvatar;\n    }\n\n    public void setUserAvatar(String userAvatar) {\n        this.userAvatar = userAvatar;\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 Double getScore() {\n        return score;\n    }\n\n    public void setScore(Double score) {\n        this.score = score;\n    }\n\n    public String getContent() {\n        return content;\n    }\n\n    public void setContent(String content) {\n        this.content = content;\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 String getUserName() {\n        return userName;\n    }\n\n    public void setUserName(String userName) {\n        this.userName = userName;\n    }\n\n    public String getTime() {\n        return time;\n    }\n\n    public void setTime(String time) {\n        this.time = time;\n    }\n\n    public Integer getOrderId() {\n        return orderId;\n    }\n\n    public void setOrderId(Integer orderId) {\n        this.orderId = orderId;\n    }\n\n    public String getOrderNo() {\n        return orderNo;\n    }\n\n    public void setOrderNo(String orderNo) {\n        this.orderNo = orderNo;\n    }\n\n    public Integer getGoodsId() {\n        return goodsId;\n    }\n\n    public void setGoodsId(Integer goodsId) {\n        this.goodsId = goodsId;\n    }\n\n    public String getGoodsName() {\n        return goodsName;\n    }\n\n    public void setGoodsName(String goodsName) {\n        this.goodsName = goodsName;\n    }\n\n    public String getGoodsImg() {\n        return goodsImg;\n    }\n\n    public void setGoodsImg(String goodsImg) {\n        this.goodsImg = goodsImg;\n    }\n}\n\n```\n\n\n\nCommentMapper.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.CommentMapper\">\n\n    \u003Cselect id=\"selectAll\" resultType=\"com.example.entity.Comment\">\n        select `comment`.*, user.name as userName, user.avatar as userAvatar, orders.order_no as orderNo, goods.name as goodsName, goods.img as goodsImg\n            from `comment`\n            left join user on `comment`.user_id = user.id\n            left join orders on `comment`.order_id = orders.id\n            left join goods on `comment`.goods_id = goods.id\n        \u003Cwhere>\n            \u003Cif test=\"content != null\"> and `comment`.content like concat('%', #{content}, '%')\u003C\u002Fif>\n            \u003Cif test=\"userId != null\"> and `comment`.user_id = #{userId}\u003C\u002Fif>\n            \u003Cif test=\"goodsId != null\"> and `comment`.goods_id = #{goodsId}\u003C\u002Fif>\n            \u003Cif test=\"orderId != null\"> and `comment`.order_id = #{orderId}\u003C\u002Fif>\n            \u003Cif test=\"goodsName != null\"> and goods.name like concat('%', #{goodsName}, '%')\u003C\u002Fif>\n        \u003C\u002Fwhere>\n        order by `comment`.id desc\n    \u003C\u002Fselect>\n\n    \u003Cselect id=\"selectById\" resultType=\"com.example.entity.Comment\">\n        select * from `comment` where id = #{id}\n    \u003C\u002Fselect>\n\n    \u003Cdelete id=\"deleteById\">\n        delete from `comment` where id = #{id}\n    \u003C\u002Fdelete>\n\n    \u003Cinsert id=\"insert\" parameterType=\"com.example.entity.Comment\" useGeneratedKeys=\"true\">\n        insert into `comment`\n        \u003Ctrim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n            \u003Cif test=\"id != null\">id,\u003C\u002Fif>\n            \u003Cif test=\"score != null\">score,\u003C\u002Fif>\n            \u003Cif test=\"content != null\">content,\u003C\u002Fif>\n            \u003Cif test=\"userId != null\">user_id,\u003C\u002Fif>\n            \u003Cif test=\"time != null\">time,\u003C\u002Fif>\n            \u003Cif test=\"orderId != null\">order_id,\u003C\u002Fif>\n            \u003Cif test=\"goodsId != null\">goods_id,\u003C\u002Fif>\n        \u003C\u002Ftrim>\n        values\n        \u003Ctrim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n            \u003Cif test=\"id != null\">#{id},\u003C\u002Fif>\n            \u003Cif test=\"score != null\">#{score},\u003C\u002Fif>\n            \u003Cif test=\"content != null\">#{content},\u003C\u002Fif>\n            \u003Cif test=\"userId != null\">#{userId},\u003C\u002Fif>\n            \u003Cif test=\"time != null\">#{time},\u003C\u002Fif>\n            \u003Cif test=\"orderId != null\">#{orderId},\u003C\u002Fif>\n            \u003Cif test=\"goodsId != null\">#{goodsId},\u003C\u002Fif>\n        \u003C\u002Ftrim>\n    \u003C\u002Finsert>\n\n    \u003Cupdate id=\"updateById\" parameterType=\"com.example.entity.Comment\">\n        update `comment`\n        \u003Cset>\n            \u003Cif test=\"id != null\">\n                id = #{id},\n            \u003C\u002Fif>\n            \u003Cif test=\"score != null\">\n                score = #{score},\n            \u003C\u002Fif>\n            \u003Cif test=\"content != null\">\n                content = #{content},\n            \u003C\u002Fif>\n            \u003Cif test=\"userId != null\">\n                user_id = #{userId},\n            \u003C\u002Fif>\n            \u003Cif test=\"time != null\">\n                time = #{time},\n            \u003C\u002Fif>\n            \u003Cif test=\"orderId != null\">\n                order_id = #{orderId},\n            \u003C\u002Fif>\n            \u003Cif test=\"goodsId != null\">\n                goods_id = #{goodsId},\n            \u003C\u002Fif>\n        \u003C\u002Fset>\n        where id = #{id}\n    \u003C\u002Fupdate>\n\n\u003C\u002Fmapper>\n```\n\n\n\n## 开发前端页面\n\n### Comment.vue\n\n```vue\n\u003Ctemplate>\n  \u003Cdiv>\n\n    \u003Cdiv class=\"card\" style=\"margin-bottom: 5px;\">\n      \u003Cel-input v-model=\"data.content\" style=\"width: 300px; margin-right: 10px\" placeholder=\"请输入评价内容查询\">\u003C\u002Fel-input>\n      \u003Cel-input v-model=\"data.goodsName\" 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=\"goodsImg\" label=\"商品图片\">\n          \u003Ctemplate #default=\"scope\">\n            \u003Cel-image style=\"width: 50px; height: 50px; display: block; border-radius: 5px\" :src=\"scope.row.goodsImg\" :preview-src-list=\"[scope.row.goodsImg]\" preview-teleported>\u003C\u002Fel-image>\n          \u003C\u002Ftemplate>\n        \u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"goodsName\" label=\"商品名称\">\u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"orderNo\" label=\"订单编号\">\u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"score\" label=\"评分\" width=\"200\">\n          \u003Ctemplate #default=\"scope\">\n            \u003Cel-rate disabled allow-half show-score v-model=\"scope.row.score\" \u002F>\n          \u003C\u002Ftemplate>\n        \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 prop=\"time\" label=\"时间\">\u003C\u002Fel-table-column>\n        \u003Cel-table-column label=\"操作\" align=\"center\" width=\"160\">\n          \u003Ctemplate #default=\"scope\">\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\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  pageNum: 1,\n  pageSize: 10,\n  total: 0,\n  formVisible: false,\n  form: {},\n  tableData: [],\n  content: null,\n  goodsName: null,\n  rules: {\n    name: [\n      { required: true, message: '请输入名称', trigger: 'blur' },\n    ]\n  }\n})\n\n\u002F\u002F 分页查询\nconst load = () => {\n  request.get('\u002Fcomment\u002FselectPage', {\n    params: {\n      pageNum: data.pageNum,\n      pageSize: data.pageSize,\n      content: data.content,\n      goodsName: data.goodsName,\n    }\n  }).then(res => {\n    data.tableData = res.data?.list\n    data.total = res.data?.total\n  })\n}\nload()\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('\u002Fcomment\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('\u002Fcomment\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('\u002Fcomment\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.content = null\n  data.goodsName = null\n  load()\n}\n\u003C\u002Fscript>\n```\n\n \n\n### UserComment.vue\n\n```vue\n\u003Ctemplate>\n  \u003Cdiv class=\"front-container\">\n\n    \u003Cdiv class=\"card\" style=\"margin-bottom: 5px;\">\n      \u003Cel-input v-model=\"data.content\" style=\"width: 300px; margin-right: 10px\" placeholder=\"请输入评价内容查询\">\u003C\u002Fel-input>\n      \u003Cel-input v-model=\"data.goodsName\" 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=\"goodsImg\" label=\"商品图片\">\n          \u003Ctemplate #default=\"scope\">\n            \u003Cel-image style=\"width: 50px; height: 50px; display: block; border-radius: 5px\" :src=\"scope.row.goodsImg\" :preview-src-list=\"[scope.row.goodsImg]\" preview-teleported>\u003C\u002Fel-image>\n          \u003C\u002Ftemplate>\n        \u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"goodsName\" label=\"商品名称\">\n          \u003Ctemplate #default=\"scope\">\n            \u003Ca :href=\"'\u002Ffront\u002FgoodsDetail?id=' + scope.row.goodsId\">{{ scope.row.goodsName }}\u003C\u002Fa>\n          \u003C\u002Ftemplate>\n        \u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"orderNo\" label=\"订单编号\">\u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"score\" label=\"评分\" width=\"200\">\n          \u003Ctemplate #default=\"scope\">\n            \u003Cel-rate disabled allow-half show-score v-model=\"scope.row.score\" \u002F>\n          \u003C\u002Ftemplate>\n        \u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"content\" label=\"评价内容\" width=\"200\" show-overflow-tooltip>\u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"time\" 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)\">编辑\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    \u003Cel-dialog title=\"评价信息\" width=\"30%\" v-model=\"data.formVisible\" :close-on-click-modal=\"false\" destroy-on-close>\n      \u003Cel-form ref=\"formRef\" :model=\"data.form\" :rules=\"data.rules\" label-width=\"80px\" style=\"padding-right: 30px; padding-top: 20px\">\n        \u003Cel-form-item label=\"评分\" prop=\"score\">\n          \u003Cel-rate show-score allow-half v-model=\"data.form.score\">\u003C\u002Fel-rate>\n        \u003C\u002Fel-form-item>\n        \u003Cel-form-item label=\"内容\" prop=\"content\">\n          \u003Cel-input type=\"textarea\" :rows=\"3\" v-model=\"data.form.content\" autocomplete=\"off\" placeholder=\"请输入评价内容\" \u002F>\n        \u003C\u002Fel-form-item>\n      \u003C\u002Fel-form>\n      \u003Ctemplate #footer>\n      \u003Cspan 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\u002Fspan>\n      \u003C\u002Ftemplate>\n    \u003C\u002Fel-dialog>\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  content: null,\n  goodsName: null,\n  rules: {\n    score: [\n      { required: true, message: '请输入评分', trigger: 'change' },\n    ],\n    content: [\n      { required: true, message: '请输入内容', trigger: 'blur' },\n    ],\n  }\n})\n\n\u002F\u002F 分页查询\nconst load = () => {\n  request.get('\u002Fcomment\u002FselectPage', {\n    params: {\n      pageNum: data.pageNum,\n      pageSize: data.pageSize,\n      content: data.content,\n      goodsName: data.goodsName,\n      userId: data.user.id,\n    }\n  }).then(res => {\n    data.tableData = res.data?.list\n    data.total = res.data?.total\n  })\n}\nload()\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('\u002Fcomment\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('\u002Fcomment\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('\u002Fcomment\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.content = null\n  data.goodsName = null\n  load()\n}\n\u003C\u002Fscript>\n```\n\n### UserOrders.vue\n\n```vue\n\u003Ctemplate>\n  \u003Cdiv class=\"front-container\" style=\"width: 80%\">\n    \u003Cdiv style=\"margin-bottom: 10px;\">\n      \u003Cel-input clearable @clear=\"load\" v-model=\"data.orderNo\" style=\"width: 400px; height: 40px; margin-right: 10px\" placeholder=\"请输入订单编号查询\">\u003C\u002Fel-input>\n      \u003Cel-input clearable @clear=\"load\" v-model=\"data.goodsName\" style=\"width: 400px; height: 40px; margin-right: 10px\" placeholder=\"请输入商品名称查询\">\u003C\u002Fel-input>\n      \u003Cel-button style=\"height: 40px\" type=\"primary\" @click=\"load\">查 询\u003C\u002Fel-button>\n    \u003C\u002Fdiv>\n\n    \u003Cdiv class=\"card\">\n      \u003Cel-table :data=\"data.tableData\" stripe :cell-style=\"{'backgroundColor': '#e8efff'}\" default-expand-all>\n        \u003Cel-table-column type=\"expand\">\n          \u003Ctemplate #default=\"props\">\n            \u003Cdiv style=\"padding: 10px\">\n              \u003Cel-table :data=\"props.row.orderDetailList\" border>\n                \u003Cel-table-column label=\"商品图片\" prop=\"goodsImg\" width=\"100\">\n                  \u003Ctemplate #default=\"scope\">\n                    \u003Cimg :src=\"scope.row.goodsImg\" alt=\"\" style=\"width: 50px; height: 50px\">\n                  \u003C\u002Ftemplate>\n                \u003C\u002Fel-table-column>\n                \u003Cel-table-column label=\"商品名称\" prop=\"goodsName\" show-overflow-tooltip>\u003C\u002Fel-table-column>\n                \u003Cel-table-column label=\"商品单价\" prop=\"goodsPrice\" width=\"100\">\u003C\u002Fel-table-column>\n                \u003Cel-table-column label=\"数量\" prop=\"num\" width=\"100\">\n                  \u003Ctemplate #default=\"scope\">\n                    X {{ scope.row.num }}\n                  \u003C\u002Ftemplate>\n                \u003C\u002Fel-table-column>\n                \u003Cel-table-column label=\"小计\" width=\"150\">\n                  \u003Ctemplate #default=\"scope\">\n                    \u003Cb style=\"color: red\">{{ (scope.row.goodsPrice * scope.row.num).toFixed(2) }} 元\u003C\u002Fb>\n                  \u003C\u002Ftemplate>\n                \u003C\u002Fel-table-column>\n                \u003Cel-table-column label=\"操作\" width=\"120\">\n                  \u003Ctemplate #default=\"scope\">\n                    \u003Cel-button @click=\"handleAddComment(scope.row)\" type=\"success\" v-if=\"props.row.status === '已完成'\">评价\u003C\u002Fel-button>\n                  \u003C\u002Ftemplate>\n                \u003C\u002Fel-table-column>\n              \u003C\u002Fel-table>\n            \u003C\u002Fdiv>\n          \u003C\u002Ftemplate>\n        \u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"orderNo\" label=\"订单编号\" width=\"240\">\n          \u003Ctemplate #default=\"scope\">\n            \u003Cb style=\"color: #333\">{{ scope.row.orderNo }}\u003C\u002Fb>\n          \u003C\u002Ftemplate>\n        \u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"total\" label=\"总价格\">\n          \u003Ctemplate #default=\"scope\">\n            \u003Cb style=\"color: red\">{{ scope.row.total }}元\u003C\u002Fb>\n          \u003C\u002Ftemplate>\n        \u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"deliverType\" label=\"配送类型\">\u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"status\" label=\"状态\">\n          \u003Ctemplate #default=\"scope\">\n            \u003Cel-tag type=\"danger\" v-if=\"scope.row.status === '已取消'\">已取消\u003C\u002Fel-tag>\n            \u003Cel-tag type=\"warning\" v-if=\"scope.row.status === '待接单'\">待接单\u003C\u002Fel-tag>\n            \u003Cel-tag type=\"primary\" v-if=\"scope.row.status === '已配送'\">已配送\u003C\u002Fel-tag>\n            \u003Cel-tag type=\"primary\" v-if=\"scope.row.status === '已出货'\">已出货\u003C\u002Fel-tag>\n            \u003Cel-tag type=\"success\" v-if=\"scope.row.status === '已完成'\">已完成\u003C\u002Fel-tag>\n          \u003C\u002Ftemplate>\n        \u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"time\" label=\"下单时间\">\u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"address\" label=\"地址\" width=\"300\">\u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"deliver\" label=\"配送信息\" width=\"300\">\u003C\u002Fel-table-column>\n        \u003Cel-table-column label=\"订单操作\" align=\"center\" width=\"120\">\n          \u003Ctemplate #default=\"scope\">\n            \u003Cel-button @click=\"cancel(scope.row)\"  type=\"danger\" v-if=\"scope.row.status === '待接单'\">取消\u003C\u002Fel-button>\n            \u003Cel-button @click=\"done(scope.row)\" type=\"primary\" v-if=\"scope.row.status === '已出货' || scope.row.status === '已配送'\">确认收货\u003C\u002Fel-button>\n          \u003C\u002Ftemplate>\n        \u003C\u002Fel-table-column>\n      \u003C\u002Fel-table>\n\n      \u003Cdiv style=\"margin-top: 20px\">\n        \u003Cel-pagination @current-change=\"load\" 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\n    \u003Cel-dialog title=\"评价信息\" width=\"30%\" v-model=\"data.formVisible\" :close-on-click-modal=\"false\" destroy-on-close>\n      \u003Cel-form ref=\"formRef\" :model=\"data.form\" :rules=\"data.rules\" label-width=\"80px\" style=\"padding-right: 30px; padding-top: 20px\">\n        \u003Cel-form-item label=\"评分\" prop=\"score\">\n          \u003Cel-rate show-score allow-half v-model=\"data.form.score\">\u003C\u002Fel-rate>\n        \u003C\u002Fel-form-item>\n        \u003Cel-form-item label=\"内容\" prop=\"content\">\n          \u003Cel-input type=\"textarea\" :rows=\"3\" v-model=\"data.form.content\" autocomplete=\"off\" placeholder=\"请输入评价内容\" \u002F>\n        \u003C\u002Fel-form-item>\n      \u003C\u002Fel-form>\n      \u003Ctemplate #footer>\n      \u003Cspan 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\u002Fspan>\n      \u003C\u002Ftemplate>\n    \u003C\u002Fel-dialog>\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: 3,\n  total: 0,\n  formVisible: false,\n  form: {},\n  tableData: [],\n  orderNo: null,\n  goodsName: null,\n  rules: {\n    score: [\n      { required: true, message: '请输入评分', trigger: 'change' },\n    ],\n    content: [\n      { required: true, message: '请输入内容', trigger: 'blur' },\n    ],\n  }\n})\n\n\u002F\u002F 分页查询\nconst load = () => {\n  request.get('\u002Forders\u002FselectPage', {\n    params: {\n      pageNum: data.pageNum,\n      pageSize: data.pageSize,\n      orderNo: data.orderNo,\n      goodsName: data.goodsName,\n      userId: data.user.id\n    }\n  }).then(res => {\n    data.tableData = res.data?.list\n    data.total = res.data?.total\n  })\n}\nload()\n\nconst cancel = (row) => {\n  ElMessageBox.confirm('您确认取消订单吗?', '二次确认', { type: 'warning' }).then(res => {\n    data.form = row\n    data.form.status = '已取消'\n    updateOrder()\n  }).catch(err => {})\n}\n\nconst done = (row) => {\n  ElMessageBox.confirm('您确认订单货物已经收到了吗?', '二次确认', { type: 'warning' }).then(res => {\n    data.form = row\n    data.form.status = '已完成'\n    updateOrder()\n  }).catch(err => {})\n}\n\n\u002F\u002F 编辑保存\nconst updateOrder = () => {\n  request.put('\u002Forders\u002Fupdate', data.form).then(res => {\n    if (res.code === '200') {\n      load()\n      ElMessage.success('操作成功')\n    } else {\n      ElMessage.error(res.msg)\n    }\n  })\n}\n\n\u002F\u002F 新增\nconst handleAddComment = (row) => {\n  request.get('\u002Fcomment\u002FselectAll', {\n    params: {\n      orderId: row.orderId,\n      goodsId: row.goodsId\n    }\n  }).then(res => {\n    \u002F\u002F 返回的是数组\n    data.form = res.data?.length > 0 ? res.data[0] : { orderId: row.orderId, goodsId: row.goodsId, userId: data.user.id }\n    data.formVisible = true\n  })\n}\n\n\u002F\u002F 新增保存\nconst addComment = () => {\n  request.post('\u002Fcomment\u002Fadd', data.form).then(res => {\n    if (res.code === '200') {\n      ElMessage.success('操作成功')\n      data.formVisible = false\n    } else {\n      ElMessage.error(res.msg)\n    }\n  })\n}\n\n\u002F\u002F 编辑保存\nconst updateComment = () => {\n  request.put('\u002Fcomment\u002Fupdate', data.form).then(res => {\n    if (res.code === '200') {\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 ? updateComment() : addComment()\n    }\n  })\n}\n\n\u002F\u002F 删除\nconst handleDelete = (id) => {\n  ElMessageBox.confirm('删除后数据无法恢复，您确定删除吗?', '删除确认', { type: 'warning' }).then(res => {\n    request.delete('\u002Forders\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.orderNo = null\n  data.goodsName = null\n  load()\n}\n\u003C\u002Fscript>\n\n\u003Cstyle scoped>\n.el-tag {\n  font-weight: bold;\n}\n.el-tag--warning {\n  color: orange;\n  background-color: #fff2de;\n}\n\u003C\u002Fstyle>\n```\n\n### GoodsDetail.vue\n\n```vue\n\u003Ctemplate>\n  \u003Cdiv class=\"front-container\" style=\"width: 50%\">\n    \u003Cdiv class=\"card\" style=\"padding: 20px; display: flex; grid-gap: 20px; margin-bottom: 10px\">\n      \u003Cimg :src=\"data.goods.img\" alt=\"\" style=\"width: 300px; height: 300px\">\n      \u003Cdiv style=\"flex: 1\">\n        \u003Cdiv style=\"display: flex; align-items: flex-start; grid-gap: 20px; margin-bottom: 10px\">\n          \u003Cdiv style=\"font-size: 22px; font-weight: bold; line-height: 25px; flex: 1\">\n            \u003Cel-tag style=\"margin-right: 5px; float: left; background-color: red; color: white\" type=\"danger\" v-if=\"data.goods.recommend === '是'\">推荐\u003C\u002Fel-tag>\n            {{ data.goods.name }}\n          \u003C\u002Fdiv>\n          \u003Cdiv style=\"width: 60px; cursor: pointer; color: #666\" @click=\"addCollect\" v-if=\"!data.userCollect?.id\">\n            \u003Cel-icon style=\"position: relative; top: 3px\" size=\"18\">\u003CStar \u002F>\u003C\u002Fel-icon>收藏\n          \u003C\u002Fdiv>\n          \u003Cdiv style=\"width: 100px; cursor: pointer; color: orange\" @click=\"removeCollect\" v-if=\"data.userCollect?.id\">\n            \u003Cel-icon style=\"position: relative; top: 3px\" size=\"18\">\u003CStarFilled \u002F>\u003C\u002Fel-icon>取消收藏\n          \u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n        \u003Cdiv style=\"margin-bottom: 20px\">\n          \u003Cspan style=\"color: red; font-size: 18px\">￥\u003C\u002Fspan>\u003Cb style=\"color: red; font-size: 30px\">{{ data.goods.price }}\u003C\u002Fb>\n          \u003Cspan style=\"color: #666; margin-left: 20px\">累计销量 {{ data.goods.saleCount }}\u003C\u002Fspan>\n          \u003Cspan style=\"color: #666; margin-left: 20px\">剩余库存 {{ data.goods.store }}\u003C\u002Fspan>\n        \u003C\u002Fdiv>\n        \u003Cdiv style=\"margin-bottom: 20px; padding: 10px; border-radius: 5px; background-color: #e8e4e4; line-height: 25px; text-align: justify\">{{ data.goods.description }}\u003C\u002Fdiv>\n        \u003Cdiv>\n          \u003Cel-input-number style=\"width: 150px; height: 40px\" :min=\"1\" v-model=\"data.num\">\u003C\u002Fel-input-number>\n          \u003Cel-button @click=\"addCart\" style=\"height: 40px; margin-left: 5px\" type=\"danger\">加入购物车\u003C\u002Fel-button>\n          \u003Cel-button @click=\"handleAddOrder\" style=\"height: 40px; margin-left: 5px\" type=\"danger\">立即购买\u003C\u002Fel-button>\n        \u003C\u002Fdiv>\n        \u003Cdiv style=\"margin-top: 10px; color: #666\">校园小卖部销售并发货的商品，由小卖部提供发票和相应的售后服务。请您放心购买！\u003C\u002Fdiv>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n\n    \u003Cdiv class=\"card\" style=\"padding: 20px; margin-bottom: 50px\">\n      \u003Cdiv style=\"font-size: 20px; padding-bottom: 10px; border-bottom: 1px solid #ddd\">\n        \u003Cspan @click=\"changeTab('商品详情')\" style=\"cursor: pointer\" :class=\"{'current-active': data.current === '商品详情' }\">商品详情\u003C\u002Fspan>\n        \u003Cspan @click=\"changeTab('商品评价')\" :class=\"{'current-active': data.current === '商品评价' }\" style=\"cursor: pointer; margin-left: 20px\">商品评价\u003C\u002Fspan>\n      \u003C\u002Fdiv>\n      \u003Cdiv v-if=\"data.current === '商品详情'\" style=\"padding: 10px\" v-html=\"data.goods.content\">\u003C\u002Fdiv>\n      \u003Cdiv v-if=\"data.current === '商品评价'\" style=\"min-height: 700px\">\n        \u003Cdiv v-if=\"data.commentList.length === 0\" style=\"padding: 50px; text-align: center; color: #666\">暂无评价...\u003C\u002Fdiv>\n        \u003Cdiv v-if=\"data.commentList.length > 0\" style=\"padding: 20px;\">\n\u003C!--          显示评论列表-->\n          \u003Cdiv v-for=\"(item, index) in data.commentList\" :key=\"item.id\" style=\"display: flex; grid-gap: 10px; padding: 10px 0;\n            border-bottom: 1px solid #ddd\" :style=\"{ 'borderWidth': index === data.commentList.length - 1 ? 0 : '1px' }\">\n            \u003Cimg :src=\"item.userAvatar\" alt=\"\" style=\"width: 50px; height: 50px; border-radius: 50%\">\n            \u003Cdiv style=\"flex: 1\">\n              \u003Cdiv>\u003Cspan>{{ item.userName }}\u003C\u002Fspan>\n                \u003Cspan style=\"color: #666; font-size: 13px; margin-left: 10px\">{{ item.time }}\u003C\u002Fspan>\n              \u003C\u002Fdiv>\n              \u003Cdiv style=\"margin-bottom: 5px\"> \u003Cel-rate v-model=\"item.score\" show-score allow-half disabled>\u003C\u002Fel-rate>\u003C\u002Fdiv>\n              \u003Cdiv>{{ item.content }}\u003C\u002Fdiv>\n            \u003C\u002Fdiv>\n          \u003C\u002Fdiv>\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\u002Fdiv>\n\n    \u003Cel-dialog title=\"下单信息\" width=\"30%\" v-model=\"data.formVisible\" :close-on-click-modal=\"false\" destroy-on-close>\n      \u003Cel-form ref=\"formRef\" :model=\"data.form\" :rules=\"data.rules\" label-width=\"100px\" style=\"padding-right: 30px\">\n        \u003Cel-form-item label=\"配送类型\" prop=\"deliverType\">\n          \u003Cel-radio-group v-model=\"data.form.deliverType\">\n            \u003Cel-radio-button value=\"自提\" label=\"自提\">\u003C\u002Fel-radio-button>\n            \u003Cel-radio-button value=\"外送\" label=\"外送\">\u003C\u002Fel-radio-button>\n          \u003C\u002Fel-radio-group>\n        \u003C\u002Fel-form-item>\n        \u003Cel-form-item label=\"收货地址\" prop=\"address\" v-if=\"data.form.deliverType === '外送'\">\n          \u003Cel-input v-model=\"data.form.address\" type=\"textarea\" :rows=\"3\" placeholder=\"请输入外送的接收地址，包括联系人、联系电话、地址信息\">\u003C\u002Fel-input>\n        \u003C\u002Fel-form-item>\n      \u003C\u002Fel-form>\n      \u003Ctemplate #footer>\n      \u003Cspan class=\"dialog-footer\">\n        \u003Cel-button @click=\"data.formVisible = false\">取 消\u003C\u002Fel-button>\n        \u003Cel-button type=\"primary\" @click=\"addOrder\">确 认\u003C\u002Fel-button>\n      \u003C\u002Fspan>\n      \u003C\u002Ftemplate>\n    \u003C\u002Fel-dialog>\n\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport { reactive, ref } from \"vue\";\nimport router from \"@\u002Frouter\";\nimport request from \"@\u002Futils\u002Frequest\";\nimport {ElMessage} from \"element-plus\";\n\nconst formRef = ref()\nconst data = reactive({\n  user: JSON.parse(localStorage.getItem('system-user') || '{}'),\n  id: router.currentRoute.value.query.id,\n  goods: {},\n  num: 1,\n  current: '商品详情',\n  commentList: [],\n  pageNum: 1,\n  pageSize: 5,\n  total: 0,\n  userCollect: {},\n  form: {},\n  formVisible: false,\n  rules: {\n    deliverType: [\n      { required: true, message: '请选择配送类型', trigger: 'change' }\n    ],\n    address: [\n      { required: true, message: '请输入配送地址', trigger: 'blur' }\n    ]\n  }\n})\n\nconst loadComment = () => {\n  request.get('\u002Fcomment\u002FselectPage', {\n    params: {\n      pageNum: data.pageNum,\n      pageSize: data.pageSize,\n      goodsId: data.id\n    }\n  }).then(res => {\n    data.commentList = res.data?.list\n    data.total = res.data?.total\n  })\n}\nloadComment()\n\nconst handleAddOrder = () => {\n  data.form = {}\n  data.formVisible = true\n}\n\nconst addOrder = () => {\n  formRef.value.validate(valid => {\n    if (valid) {\n      data.form.userId = data.user.id\n      data.form.cartList = [ {goodsId: data.id, num: data.num } ]\n      request.post('\u002Forders\u002Fadd', data.form).then(res => {\n        if (res.code === '200') {\n          ElMessage.success('下单成功')\n          load()\n          data.formVisible = false\n        } else {\n          ElMessage.error(res.msg)\n        }\n      })\n    }\n  })\n}\n\nconst addCart = () => {\n  request.post('\u002Fcart\u002Fadd', { goodsId: data.id, num: data.num, userId: data.user.id }).then(res => {\n    if (res.code === '200') {\n      ElMessage.success('加入购物车成功')\n    } else {\n      ElMessage.error(res.msg)\n    }\n  })\n}\n\n\u002F\u002F 当前的商品是否被当前登录的用户收藏过\nconst loadCollect = () => {\n  request.get('\u002Fcollect\u002FselectAll', {\n    params:{\n      goodsId: data.id,\n      userId: data.user.id\n    }\n  }).then(res => {\n    if (res.data?.length > 0) {  \u002F\u002F 查询到数据了 表示用户收藏过了\n      data.userCollect = res.data[0]\n    } else {\n      data.userCollect = {}\n    }\n  })\n}\nloadCollect()\n\n\u002F\u002F 取消收藏\nconst removeCollect = () => {\n  request.delete('\u002Fcollect\u002Fdelete\u002F' + data.userCollect.id).then(res => {\n    if (res.code === '200') {\n      ElMessage.success('操作成功')\n      loadCollect()\n    } else {\n      ElMessage.error(res.msg)\n    }\n  })\n}\n\nconst addCollect = () => {\n  request.post('\u002Fcollect\u002Fadd', { goodsId: data.id, userId: data.user.id }).then(res => {\n    if (res.code === '200') {\n      ElMessage.success('操作成功')\n      loadCollect()\n    } else {\n      ElMessage.error(res.msg)\n    }\n  })\n}\n\nconst changeTab = (tabName) => {\n  data.current = tabName\n}\n\nconst load = () => {\n  request.get('\u002Fgoods\u002FselectById\u002F' + data.id).then(res => {\n    data.goods = res.data\n  })\n}\nload()\n\u003C\u002Fscript>\n\n\u003Cstyle>\n.current-active {\n  color: red;\n  border-bottom: 2px solid red;\n  padding-bottom: 10px\n}\n\u003C\u002Fstyle>\n```\n\n","coding",1,2507,2103,"2025-12-04 17:10:47","2026-05-03 22:49:02","青哥带小白做毕设2026所有资料汇总","qingge-code-2026",{"project":18,"items":19},{"id":6,"title":15,"slug":16},[20,27,34,41,48,55,62,69,76,83,90,97,104,111,118,125,133,134],{"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},993,"mgoFKmGT","00. 带小白做毕设课程介绍以及脚手架获取",32061,1966,"2026-03-29 19:37:39",{"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},998,"1kCk1d2E","01. 导入并运行项目脚手架",14398,1974,"2025-11-11 16:24:50",{"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},1003,"8ZlQ12IX","02. 带你开发一个基础的用户管理模块（上）",12150,1987,"2025-11-12 16:53:01",{"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},1006,"6mmUNf9i","03. 带你开发一个基础的用户管理模块（下）",7782,1994,"2025-11-13 16:48:27",{"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},1011,"3XNG04wA","04. 带你开发用户登录、注册、个人信息、修改密码功能",6474,2003,"2025-11-17 17:03:58",{"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},1017,"LnAAYydZ","05. 带你开发商品分类管理功能",5467,2012,"2025-11-24 17:30:23",{"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},1018,"584qohhy","06. 开发商品信息管理功能",4836,2013,"2025-11-24 17:30:12",{"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},1024,"scxsifCZ","07. 开发轮播图信息管理功能",3313,2021,"2025-11-24 17:29:58",{"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},1041,"AjujV8Gq","08. 带你实现前台首页功能",4058,2039,"2025-11-24 17:31:31",{"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},1045,"p6yD8ZxS","09. 带你实现商品搜索、商品分类检索功能",3005,2048,"2025-11-25 16:35: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},1050,"7gHUek7z","10. 带你实现商品详情页功能",2622,2053,"2025-11-26 17:22:20",{"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},1059,"aX7rviTw","11. 带你实现商品收藏功能",2667,2067,"2025-11-28 17:00:21",{"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},1060,"xcmGXr9E","12. 带你开发用户模拟充值功能",2442,2068,"2026-02-02 14:24:37",{"id":112,"uuid":113,"project_id":6,"title":114,"type":9,"status":10,"public_enabled":10,"views":115,"sort":116,"created_at":117,"updated_at":14,"project_title":15,"project_slug":16},1065,"z8IN0tX8","13. 带你实现购物车功能",2461,2078,"2025-12-01 17:16:05",{"id":119,"uuid":120,"project_id":6,"title":121,"type":9,"status":10,"public_enabled":10,"views":122,"sort":123,"created_at":124,"updated_at":14,"project_title":15,"project_slug":16},1069,"NfBIfhVx","14. 带你实现商品下单功能",3131,2086,"2025-12-02 16:57:21",{"id":126,"uuid":127,"project_id":6,"title":128,"type":9,"status":10,"public_enabled":10,"views":129,"sort":130,"created_at":131,"updated_at":132,"project_title":15,"project_slug":16},1072,"PDQdczrn","14.1 带你实现订单配送功能",2772,2097,"2025-12-03 16:10:40","2026-05-07 15:36:12.649662+00",{"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":135,"uuid":136,"project_id":6,"title":137,"type":9,"status":10,"public_enabled":10,"views":138,"sort":139,"created_at":140,"updated_at":14,"project_title":15,"project_slug":16},1079,"iUdzrNPu","16. 带你实现后台数据统计功能",2991,2107,"2025-12-05 17:37:57"]