[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-public-AjujV8Gq":3,"public-project-articles-AjujV8Gq":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},1041,"AjujV8Gq",52,"08. 带你实现前台首页功能","## 轮播图\n\n[https:\u002F\u002Felement-plus.org\u002Fzh-CN\u002Fcomponent\u002Fcarousel](https:\u002F\u002Felement-plus.org\u002Fzh-CN\u002Fcomponent\u002Fcarousel)\n\n\n\n![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2025\u002Fpng\u002F751015\u002F1763971026020-0af08d12-6b12-4cd4-99ed-190db3ac73c4.png)![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2025\u002Fpng\u002F751015\u002F1763971351442-797f16f1-0e03-41c3-9b7a-01b5eee7f6ec.png)![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2025\u002Fpng\u002F751015\u002F1763973356523-67ff715f-19f6-4ea2-b721-ff6f6197326e.png)\n\n图标网站：[https:\u002F\u002Fwww.iconfont.cn\u002F](https:\u002F\u002Fwww.iconfont.cn\u002F)\n\n## 查询上架的商品\n\n![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2025\u002Fpng\u002F751015\u002F1763971488225-2655fdf1-5f9b-45ac-84f6-57e17832346f.png)\n\n## CSS 文本多行省略\n\n```css\n.line1 {\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n}\n.line2 {\n  word-break: break-all;\n  text-overflow: ellipsis;\n  display: -webkit-box;\n  -webkit-box-orient: vertical;\n  -webkit-line-clamp: 2; \u002F* 超出几行省略 *\u002F\n  overflow: hidden;\n}\n```\n\n## 页脚\n\n1. 创建 components 文件夹，放入一个 Footer.vue 的文件\n2. 写入页脚的内容\n3. 在 Front.vue 里面引入\n\n```vue\n\u003CFooter \u002F>\n```\n\n```vue\nimport Footer from \"@\u002Fcomponents\u002FFooter.vue\";\n```\n\n## 商品表加上推荐的字段\n\n```sql\nCREATE TABLE `goods` (\n  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID',\n  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '名称',\n  `img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '图片',\n  `price` decimal(10,2) DEFAULT NULL COMMENT '价格',\n  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '简介',\n  `content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '详情',\n  `store` int DEFAULT '0' COMMENT '库存',\n  `category_id` int DEFAULT NULL COMMENT '分类ID',\n  `status` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '上架状态',\n  `views` int DEFAULT NULL COMMENT '浏览量',\n  `sale_count` int DEFAULT NULL COMMENT '销量',\n  `time` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '创建时间',\n  `recommend` 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\nSQL 注意改一下\n\n```xml\n\u003Cinsert id=\"insert\" parameterType=\"com.example.entity.Goods\" useGeneratedKeys=\"true\">\n        insert into `goods`\n        \u003Ctrim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n            \u003Cif test=\"id != null\">id,\u003C\u002Fif>\n            \u003Cif test=\"name != null\">name,\u003C\u002Fif>\n            \u003Cif test=\"img != null\">img,\u003C\u002Fif>\n            \u003Cif test=\"price != null\">price,\u003C\u002Fif>\n            \u003Cif test=\"description != null\">description,\u003C\u002Fif>\n            \u003Cif test=\"content != null\">content,\u003C\u002Fif>\n            \u003Cif test=\"store != null\">store,\u003C\u002Fif>\n            \u003Cif test=\"categoryId != null\">category_id,\u003C\u002Fif>\n            \u003Cif test=\"status != null\">status,\u003C\u002Fif>\n            \u003Cif test=\"views != null\">views,\u003C\u002Fif>\n            \u003Cif test=\"saleCount != null\">sale_count,\u003C\u002Fif>\n            \u003Cif test=\"time != null\">time,\u003C\u002Fif>\n            \u003Cif test=\"recommend != null\">recommend,\u003C\u002Fif>\n        \u003C\u002Ftrim>\n        values\n        \u003Ctrim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n            \u003Cif test=\"id != null\">#{id},\u003C\u002Fif>\n            \u003Cif test=\"name != null\">#{name},\u003C\u002Fif>\n            \u003Cif test=\"img != null\">#{img},\u003C\u002Fif>\n            \u003Cif test=\"price != null\">#{price},\u003C\u002Fif>\n            \u003Cif test=\"description != null\">#{description},\u003C\u002Fif>\n            \u003Cif test=\"content != null\">#{content},\u003C\u002Fif>\n            \u003Cif test=\"store != null\">#{store},\u003C\u002Fif>\n            \u003Cif test=\"categoryId != null\">#{categoryId},\u003C\u002Fif>\n            \u003Cif test=\"status != null\">#{status},\u003C\u002Fif>\n            \u003Cif test=\"views != null\">#{views},\u003C\u002Fif>\n            \u003Cif test=\"saleCount != null\">#{saleCount},\u003C\u002Fif>\n            \u003Cif test=\"time != null\">#{time},\u003C\u002Fif>\n            \u003Cif test=\"recommend != null\">#{recommend},\u003C\u002Fif>\n        \u003C\u002Ftrim>\n    \u003C\u002Finsert>\n\n    \u003Cupdate id=\"updateById\" parameterType=\"com.example.entity.Goods\">\n        update `goods`\n        \u003Cset>\n            \u003Cif test=\"id != null\">\n                id = #{id},\n            \u003C\u002Fif>\n            \u003Cif test=\"name != null\">\n                name = #{name},\n            \u003C\u002Fif>\n            \u003Cif test=\"img != null\">\n                img = #{img},\n            \u003C\u002Fif>\n            \u003Cif test=\"price != null\">\n                price = #{price},\n            \u003C\u002Fif>\n            \u003Cif test=\"description != null\">\n                description = #{description},\n            \u003C\u002Fif>\n            \u003Cif test=\"content != null\">\n                content = #{content},\n            \u003C\u002Fif>\n            \u003Cif test=\"store != null\">\n                store = #{store},\n            \u003C\u002Fif>\n            \u003Cif test=\"categoryId != null\">\n                category_id = #{categoryId},\n            \u003C\u002Fif>\n            \u003Cif test=\"status != null\">\n                status = #{status},\n            \u003C\u002Fif>\n            \u003Cif test=\"views != null\">\n                views = #{views},\n            \u003C\u002Fif>\n            \u003Cif test=\"saleCount != null\">\n                sale_count = #{saleCount},\n            \u003C\u002Fif>\n            \u003Cif test=\"time != null\">\n                time = #{time},\n            \u003C\u002Fif>\n            \u003Cif test=\"recommend != null\">\n                recommend = #{recommend},\n            \u003C\u002Fif>\n        \u003C\u002Fset>\n        where id = #{id}\n    \u003C\u002Fupdate>\n```\n\n改一下数据库商品表的数据，recommend 设置为否\n\n![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2025\u002Fpng\u002F751015\u002F1763974943662-1e833dd2-e586-427f-a81a-98d955ef6058.png)\n\n## Home.vue\n\n```vue\n\u003Ctemplate>\n  \u003Cdiv class=\"front-container\">\n    \u003C!--  第一行开始 -->\n    \u003Cdiv style=\"display: flex; grid-gap: 20px; margin-bottom: 10px\">\n      \u003Cdiv style=\"flex: 1\">\n        \u003Cel-carousel height=\"450px\">\n          \u003Cel-carousel-item v-for=\"item in data.carouselList\" :key=\"item.id\">\n            \u003Cimg @click=\"router.push('\u002Ffront\u002FgoodsDetail?id=' + item.goodsId)\" :src=\"item.img\" alt=\"\" style=\"width: 100%; height: 450px; cursor: pointer\">\n          \u003C\u002Fel-carousel-item>\n        \u003C\u002Fel-carousel>\n      \u003C\u002Fdiv>\n      \u003Cdiv class=\"card\" style=\"width: 260px\">\n        \u003Cdiv style=\"display: flex; align-items: center; padding-bottom: 5px; border-bottom: 1px solid red\">\n          \u003Cimg src=\"@\u002Fassets\u002Fimgs\u002Flove.png\" alt=\"\" style=\"width: 25px\">\n          \u003Cdiv style=\"color: red; font-weight: bold; font-size: 20px; margin-left: 2px\">为您推荐\u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n        \u003Cdiv style=\"padding: 20px 0\">\n          \u003Cdiv class=\"top-item\" @click=\"router.push('\u002Ffront\u002FgoodsDetail?id=' + item.id)\" style=\"cursor: pointer; display: flex; grid-gap: 10px; margin-bottom: 20px\" v-for=\"item in data.recommendGoods\" :key=\"item.id\">\n            \u003Cimg style=\"width: 65px; height: 65px\" :src=\"item.img\" alt=\"\">\n            \u003Cdiv>\n              \u003Cdiv class=\"line2\" style=\"margin-bottom: 5px\">{{ item.name }}\u003C\u002Fdiv>\n              \u003Cdiv style=\"color: red\">\u003Cspan>￥\u003C\u002Fspan>\u003Cb>{{ item.price }}\u003C\u002Fb>\u003C\u002Fdiv>\n            \u003C\u002Fdiv>\n\n          \u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n    \u003C!--  第一行结束 -->\n\n\n    \u003Cdiv class=\"card\" style=\"padding: 20px;\">\n      \u003C!--  第二行开始 -->\n      \u003Cdiv style=\"display: flex; align-items: flex-end; padding-bottom: 5px; border-bottom: 1px solid red; margin-bottom: 10px\">\n        \u003Cdiv style=\"flex: 1; display: flex; align-items: center\">\n          \u003Cimg src=\"@\u002Fassets\u002Fimgs\u002Fhot.png\" alt=\"\" style=\"width: 25px\">\n          \u003Cdiv style=\"color: red; font-weight: bold; font-size: 20px; margin-left: 2px\">热销商品\u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n        \u003Cdiv @click=\"router.push('\u002Ffront\u002Fgoods')\" style=\"cursor: pointer; font-size: 13px\">查看更多\u003C\u002Fdiv>\n      \u003C\u002Fdiv>\n      \u003Cdiv style=\"margin-bottom: 40px\">\n        \u003Cel-row :gutter=\"20\">\n         \u003Cel-col :span=\"6\" v-for=\"item in data.hotGoods\" :key=\"item.id\">\n           \u003Cdiv @click=\"router.push('\u002Ffront\u002FgoodsDetail?id=' + item.id)\" class=\"item\" style=\"width: 100%; border-radius: 5px; height: 350px\">\n             \u003Cimg :src=\"item.img\" alt=\"\" style=\"width: 100%; height: 260px; border-radius: 5px 5px 0 0\">\n             \u003Cdiv style=\"padding: 5px\">\n               \u003Cdiv class=\"line1\" style=\"font-size: 16px;\">{{ item.name }}\u003C\u002Fdiv>\n               \u003Cdiv>\n                 \u003Cspan style=\"color: red\">￥\u003C\u002Fspan>\u003Cb style=\"color: red; font-size: 20px\">{{ item.price }}\u003C\u002Fb>\n                 \u003Cspan style=\"margin-left: 10px; color: #666\">销量：{{ item.saleCount }}\u003C\u002Fspan>\n               \u003C\u002Fdiv>\n             \u003C\u002Fdiv>\n           \u003C\u002Fdiv>\n         \u003C\u002Fel-col>\n        \u003C\u002Fel-row>\n      \u003C\u002Fdiv>\n      \u003C!--  第二行结束 -->\n\n      \u003C!--  第三行开始 -->\n      \u003Cdiv style=\"display: flex; align-items: flex-end; padding-bottom: 5px; border-bottom: 1px solid red; margin-bottom: 10px\">\n        \u003Cdiv style=\"flex: 1; display: flex; align-items: center\">\n          \u003Cimg src=\"@\u002Fassets\u002Fimgs\u002Fnew.png\" alt=\"\" style=\"width: 25px\">\n          \u003Cdiv style=\"color: red; font-weight: bold; font-size: 20px; margin-left: 2px\">最新上架\u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n        \u003Cdiv @click=\"router.push('\u002Ffront\u002Fgoods')\" style=\"cursor: pointer; font-size: 13px\">查看更多\u003C\u002Fdiv>\n      \u003C\u002Fdiv>\n      \u003Cdiv>\n        \u003Cel-row :gutter=\"20\">\n          \u003Cel-col :span=\"6\" v-for=\"item in data.newGoods\" :key=\"item.id\">\n            \u003Cdiv @click=\"router.push('\u002Ffront\u002FgoodsDetail?id=' + item.id)\" class=\"item\" style=\"width: 100%; border-radius: 5px; height: 350px\">\n              \u003Cimg :src=\"item.img\" alt=\"\" style=\"width: 100%; height: 260px; border-radius: 5px 5px 0 0\">\n              \u003Cdiv style=\"padding: 5px\">\n                \u003Cdiv class=\"line1\" style=\"font-size: 16px\">{{ item.name }}\u003C\u002Fdiv>\n                \u003Cdiv>\n                  \u003Cspan style=\"color: red\">￥\u003C\u002Fspan>\u003Cb style=\"color: red; font-size: 20px\">{{ item.price }}\u003C\u002Fb>\n                  \u003Cspan style=\"margin-left: 10px; color: #666\">销量：{{ item.saleCount }}\u003C\u002Fspan>\n                \u003C\u002Fdiv>\n              \u003C\u002Fdiv>\n            \u003C\u002Fdiv>\n          \u003C\u002Fel-col>\n        \u003C\u002Fel-row>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n    \u003C!--  第三行结束 -->\n\n\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport { reactive } from \"vue\";\nimport request from \"@\u002Futils\u002Frequest\";\nimport router from \"@\u002Frouter\";\n\nconst data = reactive({\n  carouselList: [],\n  hotGoods: [],\n  newGoods: [],\n  recommendGoods: [],\n})\n\nrequest.get('\u002Fcarousel\u002FselectAll').then(res => {\n  data.carouselList = res.data\n})\n\nrequest.get('\u002Fgoods\u002FselectAll', {\n  params: {\n    status: '上架'\n  }\n}).then(res => {\n  data.hotGoods = res.data.sort((v1, v2) => v2.saleCount - v1.saleCount).splice(0, 4)\n})\n\nrequest.get('\u002Fgoods\u002FselectAll', {\n  params: {\n    status: '上架'\n  }\n}).then(res => {\n  data.newGoods = res.data.splice(0, 4)\n})\n\nrequest.get('\u002Fgoods\u002FselectAll', {\n  params: {\n    status: '上架'\n  }\n}).then(res => {\n  data.recommendGoods = res.data.filter(v => v.recommend === '是').splice(0, 5)\n})\n\u003C\u002Fscript>\n\n\u003Cstyle>\n.item {\n  cursor: pointer;\n}\n.item:hover {\n  border: 1px solid red\n}\n.top-item:hover {\n  color: red;\n}\n\u003C\u002Fstyle>\n```\n\n## Goods.vue\n\n```vue\n\u003Ctemplate>\n  \u003Cdiv>\n\n    \u003Cdiv class=\"card\" style=\"margin-bottom: 5px;\">\n      \u003Cel-input v-model=\"data.name\" style=\"width: 300px; margin-right: 10px\" placeholder=\"请输入名称查询\">\u003C\u002Fel-input>\n      \u003Cel-select style=\"width: 300px; margin-right: 10px\" v-model=\"data.categoryId\" placeholder=\"请选择商品分类\">\n        \u003Cel-option v-for=\"item in data.categoryList\" :key=\"item.id\" :value=\"item.id\" :label=\"item.name\">\u003C\u002Fel-option>\n      \u003C\u002Fel-select>\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      \u003Cdiv style=\"margin-bottom: 10px\">\n        \u003Cel-button type=\"primary\" @click=\"handleAdd\">新增\u003C\u002Fel-button>\n      \u003C\u002Fdiv>\n      \u003Cel-table tooltip-effect=\"dark myEff\" :data=\"data.tableData\" stripe>\n        \u003Cel-table-column prop=\"name\" label=\"名称\" show-overflow-tooltip>\u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"img\" label=\"图片\">\n          \u003Ctemplate #default=\"scope\">\n            \u003Cel-image v-if=\"scope.row.img\" :src=\"scope.row.img\" :preview-src-list=\"[scope.row.img]\" preview-teleported style=\"width: 100px; height: 100px;\">\u003C\u002Fel-image>\n          \u003C\u002Ftemplate>\n        \u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"price\" label=\"价格\">\u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"description\" label=\"简介\" show-overflow-tooltip>\u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"content\" label=\"详情\">\n          \u003Ctemplate #default=\"scope\">\n            \u003Cel-button type=\"primary\" @click=\"view(scope.row.content)\">查看详情\u003C\u002Fel-button>\n          \u003C\u002Ftemplate>\n        \u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"store\" label=\"库存\">\u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"categoryName\" label=\"分类名称\">\u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"status\" label=\"上架状态\">\u003C\u002Fel-table-column>\n        \u003Cel-table-column label=\"推荐\">\n          \u003Ctemplate #default=\"scope\">\n            \u003Cel-switch @change=\"updateRecommend(scope.row)\" style=\"--el-switch-on-color: #13ce66;\" v-model=\"scope.row.recommendActive\"\n                       active-text=\"是\" inactive-text=\"否\">\u003C\u002Fel-switch>\n          \u003C\u002Ftemplate>\n        \u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"views\" label=\"浏览量\">\u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"saleCount\" label=\"销量\">\u003C\u002Fel-table-column>\n        \u003Cel-table-column prop=\"time\" label=\"创建时间\">\u003C\u002Fel-table-column>\n\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=\"50%\" 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 prop=\"name\" label=\"名称\">\n          \u003Cel-input v-model=\"data.form.name\" placeholder=\"请输入名称\">\u003C\u002Fel-input>\n        \u003C\u002Fel-form-item>\n        \u003Cel-form-item prop=\"img\" label=\"图片\">\n          \u003Cel-upload :action=\"uploadUrl\" list-type=\"picture\" :on-success=\"handleImgSuccess\">\n            \u003Cel-button type=\"primary\">上传图片\u003C\u002Fel-button>\n          \u003C\u002Fel-upload>\n        \u003C\u002Fel-form-item>\n        \u003Cel-form-item prop=\"price\" label=\"价格\">\n          \u003Cel-input-number :min=\"0\" v-model=\"data.form.price\" placeholder=\"请输入价格\">\u003C\u002Fel-input-number>\n        \u003C\u002Fel-form-item>\n        \u003Cel-form-item prop=\"description\" label=\"简介\">\n          \u003Cel-input type=\"textarea\" :rows=\"3\" v-model=\"data.form.description\" placeholder=\"请输入简介\">\u003C\u002Fel-input>\n        \u003C\u002Fel-form-item>\n\n        \u003Cel-form-item prop=\"store\" label=\"库存\">\n          \u003Cel-input v-model=\"data.form.store\" placeholder=\"请输入库存\">\u003C\u002Fel-input>\n        \u003C\u002Fel-form-item>\n        \u003Cel-form-item prop=\"categoryId\" label=\"分类\">\n          \u003Cel-select style=\"width: 100%\" v-model=\"data.form.categoryId\">\n            \u003Cel-option v-for=\"item in data.categoryList\" :key=\"item.id\" :value=\"item.id\" :label=\"item.name\">\u003C\u002Fel-option>\n          \u003C\u002Fel-select>\n        \u003C\u002Fel-form-item>\n        \u003Cel-form-item prop=\"status\" label=\"上架状态\">\n          \u003Cel-radio-group v-model=\"data.form.status\">\n            \u003Cel-radio-button label=\"上架\" value=\"上架\">\u003C\u002Fel-radio-button>\n            \u003Cel-radio-button label=\"下架\" value=\"下架\">\u003C\u002Fel-radio-button>\n          \u003C\u002Fel-radio-group>\n        \u003C\u002Fel-form-item>\n        \u003Cel-form-item prop=\"content\" label=\"详情\">\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.content\"\n                :mode=\"mode\"\n                :defaultConfig=\"editorConfig\"\n                @onCreated=\"handleCreated\"\n            \u002F>\n          \u003C\u002Fdiv>\n        \u003C\u002Fel-form-item>\n\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    \u003Cel-dialog title=\"商品详情\" v-model=\"data.viewVisible\" width=\"50%\" :close-on-click-modal=\"false\" destroy-on-close>\n      \u003Cdiv class=\"editor-content-view\" style=\"padding: 20px\" v-html=\"data.content\">\u003C\u002Fdiv>\n      \u003Ctemplate #footer>\n    \u003Cspan class=\"dialog-footer\">\n      \u003Cel-button @click=\"data.viewVisible = false\">关 闭\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\";\nimport '@wangeditor\u002Feditor\u002Fdist\u002Fcss\u002Fstyle.css' \u002F\u002F 引入 css\nimport {onBeforeUnmount, shallowRef} from \"vue\";\nimport { Editor, Toolbar } from '@wangeditor\u002Feditor-for-vue'\n\nconst uploadUrl = import.meta.env.VITE_BASE_URL + '\u002Ffiles\u002Fupload'\nconst formRef = ref()\nconst data = reactive({\n  pageNum: 1,\n  pageSize: 5,\n  total: 0,\n  formVisible: false,\n  form: {},\n  tableData: [],\n  categoryList: [],\n  name: null,\n  categoryId: null,\n  viewVisible: false,\n  content: null,\n  rules: {\n    name: [\n      { required: true, message: '请输入名称', trigger: 'blur' }\n    ],\n    img: [\n      { required: true, message: '请输入图片', trigger: 'blur' }\n    ],\n    price: [\n      { required: true, message: '请输入价格', trigger: 'blur' }\n    ],\n    description: [\n      { required: true, message: '请输入简介', trigger: 'blur' }\n    ],\n    content: [\n      { required: true, message: '请输入详情', trigger: 'blur' }\n    ],\n    store: [\n      { required: true, message: '请输入库存', trigger: 'blur' }\n    ],\n    categoryId: [\n      { required: true, message: '请输入分类ID', trigger: 'change' }\n    ]\n  }\n})\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 view = (content) => {\n  data.content = content\n  data.viewVisible = true\n}\n\n\u002F\u002F 处理文件上传的钩子\nconst handleImgSuccess = (res) => {\n  data.form.img = res.data  \u002F\u002F res.data就是文件上传返回的文件路径，获取到路径后赋值表单的属性\n}\n\nrequest.get('\u002Fcategory\u002FselectAll').then(res => {\n  data.categoryList = res.data\n})\n\n\n\u002F\u002F 分页查询\nconst load = () => {\n  request.get('\u002Fgoods\u002FselectPage', {\n    params: {\n      pageNum: data.pageNum,\n      pageSize: data.pageSize,\n      name: data.name,\n      categoryId: data.categoryId\n    }\n  }).then(res => {\n    data.tableData = res.data?.list\n    data.tableData.forEach(v => {\n      v.recommendActive = v.recommend === '是'\n    })\n    data.total = res.data?.total\n  })\n}\nload()\n\n\u002F\u002F 新增\nconst handleAdd = () => {\n  data.form = { status: '上架', price: 0, recommend: '否' }\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('\u002Fgoods\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\nconst updateRecommend = (row) => {\n  data.form.id = row.id\n  data.form.recommend = row.recommendActive ? '是' : '否'\n  update()\n}\n\n\u002F\u002F 编辑保存\nconst update = () => {\n  request.put('\u002Fgoods\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('\u002Fgoods\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.name = null\n  data.categoryId = null\n  load()\n}\n\u003C\u002Fscript>\n```\n\n","coding",1,4058,2039,"2025-11-24 17:31:31","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,77,84,91,98,105,112,119,127,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. 带小白做毕设课程介绍以及脚手架获取",32063,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":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":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},1045,"p6yD8ZxS","09. 带你实现商品搜索、商品分类检索功能",3005,2048,"2025-11-25 16:35:45",{"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},1050,"7gHUek7z","10. 带你实现商品详情页功能",2622,2053,"2025-11-26 17:22:20",{"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},1059,"aX7rviTw","11. 带你实现商品收藏功能",2667,2067,"2025-11-28 17:00:21",{"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},1060,"xcmGXr9E","12. 带你开发用户模拟充值功能",2443,2068,"2026-02-02 14:24:37",{"id":106,"uuid":107,"project_id":6,"title":108,"type":9,"status":10,"public_enabled":10,"views":109,"sort":110,"created_at":111,"updated_at":14,"project_title":15,"project_slug":16},1065,"z8IN0tX8","13. 带你实现购物车功能",2461,2078,"2025-12-01 17:16:05",{"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},1069,"NfBIfhVx","14. 带你实现商品下单功能",3131,2086,"2025-12-02 16:57:21",{"id":120,"uuid":121,"project_id":6,"title":122,"type":9,"status":10,"public_enabled":10,"views":123,"sort":124,"created_at":125,"updated_at":126,"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":128,"uuid":129,"project_id":6,"title":130,"type":9,"status":10,"public_enabled":10,"views":131,"sort":132,"created_at":133,"updated_at":14,"project_title":15,"project_slug":16},1075,"RYH15Bfu","15. 带你实现订单评价功能",2507,2103,"2025-12-04 17:10:47",{"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"]