[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-public-8ZlQ12IX":3,"public-project-articles-8ZlQ12IX":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},1003,"8ZlQ12IX",52,"02. 带你开发一个基础的用户管理模块（上）","## 创建一个 user 的数据库表\n\n![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2025\u002Fpng\u002F751015\u002F1762932413361-898c194a-0776-4350-8ccf-334ab4e2243e.png)\n\n```sql\nCREATE TABLE `user` (\n  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID',\n  `username` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '账号',\n  `password` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '密码',\n  `name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '姓名',\n  `avatar` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '头像',\n  `role` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '角色',\n  `account` decimal(10,2) DEFAULT NULL COMMENT '账户',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='普通用户';\n```\n\n## Vue 项目开发的基本方法\n\n1. 创建页面（views）\n2. 创建路由（router\u002Findex.js）\n3. 创建菜单（Manager.vue\u002F el-menu）\n\n通过路由访问页面，例如：[http:\u002F\u002Flocalhost:5173\u002Fmanager\u002Fhome](http:\u002F\u002Flocalhost:5173\u002Fmanager\u002Fhome)\n\n## Element-Plus\n\n[https:\u002F\u002Felement-plus.org\u002Fzh-CN\u002F](https:\u002F\u002Felement-plus.org\u002Fzh-CN\u002F)\n\n## Vue.js\n\n[https:\u002F\u002Fcn.vuejs.org\u002F](https:\u002F\u002Fcn.vuejs.org\u002F)\n\n## 页面设计\n\n基本的增删改查页面分为 4 部分：\n\n1. 搜索区域\n2. 操作区域（新增数据）\n3. 表格区域（展示数据、编辑删除数据）\n4. 分页区域\n\n## 数据绑定\n\n```vue\n\u003Cel-input v-model=\"data.name\" placeholder=\"Type something\" :prefix-icon=\"Search\" \u002F>\n\n\u003Cscript setup>\n  import { reactive } from \"vue\";\n  const data = reactive({\n    name: null\n  })\n\u003C\u002Fscript>\n```\n\n## 导入图标\n\n```vue\nimport { Search } from \"@element-plus\u002Ficons-vue\";\n```\n\n## \u003Cfont style=\"color:rgb(31, 31, 31);\">⭐\u003C\u002Ffont>表格分页展示数据（包括模糊查询）\n\n### 数据库添加数据（造数据）\n\n![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2025\u002Fpng\u002F751015\u002F1762936409661-52ddcec5-1f45-4d72-bffd-3632dce1ff04.png)\n\n### 页面\n\n```vue\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003Cdiv class=\"card\" style=\"margin-bottom: 5px\">\n      \u003Cel-input style=\"width: 300px\" v-model=\"data.name\" placeholder=\"请输入名称查询\" :prefix-icon=\"Search\" \u002F>\n      \u003Cel-button @click=\"load\" type=\"primary\" style=\"margin-left: 10px\">查询\u003C\u002Fel-button>\n      \u003Cel-button @click=\"reset\" type=\"info\">重置\u003C\u002Fel-button>\n    \u003C\u002Fdiv>\n\n    \u003Cdiv class=\"card\" style=\"margin-bottom: 5px\">\n      \u003Cdiv style=\"margin-bottom: 10px\">\n        \u003Cel-button @click=\"reset\" type=\"primary\">新增\u003C\u002Fel-button>\n      \u003C\u002Fdiv>\n      \u003Cdiv>\n        \u003Cel-table :data=\"data.tableData\" stripe style=\"width: 100%\">\n          \u003Cel-table-column prop=\"username\" label=\"账号\" \u002F>\n          \u003Cel-table-column prop=\"name\" label=\"姓名\" \u002F>\n          \u003Cel-table-column prop=\"role\" label=\"角色\" \u002F>\n          \u003Cel-table-column prop=\"account\" label=\"账户余额\" \u002F>\n          \u003Cel-table-column label=\"操作\" width=\"180\" fixed=\"right\" >\n            \u003Cel-button type=\"primary\">编辑\u003C\u002Fel-button>\n            \u003Cel-button type=\"danger\">删除\u003C\u002Fel-button>\n          \u003C\u002Fel-table-column>\n        \u003C\u002Fel-table>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n\n    \u003Cdiv class=\"card\">\n      \u003Cel-pagination background layout=\"total, prev, pager, next\" :total=\"1\" \u002F>\n    \u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport { reactive } from \"vue\";\nimport { Search } from \"@element-plus\u002Ficons-vue\";\n\nconst data = reactive({\n  name: null,\n  tableData: [\n    { username: 'aaa', name: '小张', role: '普通用户', account: 0 }\n  ]\n})\n\n\u002F\u002F 分页查询数据的函数\nconst load = () => {\n\n}\n\nconst reset = () => {\n\n}\n\u003C\u002Fscript>\n```\n\n### 请求数据\n\n```vue\nimport request from \"@\u002Futils\u002Frequest\";\n```\n\n### 后台接口\n\nuser_name    userName\n\n- entity（实体类，跟数据库表对应上，Java 里面的字段是驼峰的风格，数据库里面是下划线）\n- controller（接口层，跟前端交互，前端 vue 通过 axios 插件请求后端接口的数据）\n- service（业务逻辑层，写一下判断的业务逻辑，也会做多个表的数据更新，service 会调用 mapper 层操作数据）\n- mapper（数据接口层，全部都是接口方法，具体的实现在 xml 里面通过 sql 语句来实现）\n- mapper.xml（具体的 sql 的实现，namespace 绑定到 mapper 数据接口层）\n\n### 分页查询使用 pageHelper 插件\n\n```java\n\u002F**\n * 分页查询的方法\n *\u002F\npublic PageInfo\u003CUser> selectPage(Integer pageNum, Integer pageSize) {\n    PageHelper.startPage(pageNum, pageSize);\n    List\u003CUser> list = userMapper.selectAll();\n    return PageInfo.of(list);\n}\n\n```\n\n### 分页模糊查询的 SQL\n\n![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2025\u002Fpng\u002F751015\u002F1762936379928-c5aee284-a5d5-45c8-a432-dafe53b30bde.png)\n\n\n\n## 完整的代码\n\nUser.java\n\n```java\npackage com.example.entity;\n\nimport java.math.BigDecimal;\n\npublic class User {\n    private Integer id;\n    private String username;\n    private String password;\n    private String name;\n    private String role;\n    private BigDecimal account;\n\n    public Integer getId() {\n        return id;\n    }\n\n    public void setId(Integer id) {\n        this.id = id;\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 getPassword() {\n        return password;\n    }\n\n    public void setPassword(String password) {\n        this.password = password;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public String getRole() {\n        return role;\n    }\n\n    public void setRole(String role) {\n        this.role = role;\n    }\n\n    public BigDecimal getAccount() {\n        return account;\n    }\n\n    public void setAccount(BigDecimal account) {\n        this.account = account;\n    }\n}\n\n```\n\n\n\nUserController\n\n```java\npackage com.example.controller;\n\nimport com.example.common.Result;\nimport com.example.entity.User;\nimport com.example.service.UserService;\nimport com.github.pagehelper.PageInfo;\nimport jakarta.annotation.Resource;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\n@RequestMapping(\"\u002Fuser\")\npublic class UserController {\n\n    @Resource\n    private UserService userService;\n\n\n    \u002F**\n     * @param pageNum 当前页码\n     * @param pageSize 每页展示的个数\n     * @return 分页数据\n     * 接口的请求方式：http:\u002F\u002Flocalhost:9090\u002Fuser\u002FselectPage?pageNum=1&pageSize=10\n     *\u002F\n    @GetMapping(\"\u002FselectPage\")\n    public Result selectPage(@RequestParam(defaultValue = \"1\") Integer pageNum,\n                             @RequestParam(defaultValue = \"10\") Integer pageSize,\n                             @RequestParam(required = false) String name) {\n        PageInfo\u003CUser> pageInfo = userService.selectPage(pageNum, pageSize, name);\n        return Result.success(pageInfo);\n    }\n\n}\n\n```\n\n\n\nUserService\n\n```java\npackage com.example.service;\n\nimport com.example.entity.User;\nimport com.example.mapper.UserMapper;\nimport com.github.pagehelper.PageHelper;\nimport com.github.pagehelper.PageInfo;\nimport jakarta.annotation.Resource;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n@Service\npublic class UserService {\n\n    @Resource\n    private UserMapper userMapper;\n\n    \u002F**\n     * 分页查询的方法\n     *\u002F\n    public PageInfo\u003CUser> selectPage(Integer pageNum, Integer pageSize, String name) {\n        PageHelper.startPage(pageNum, pageSize);\n        List\u003CUser> list = userMapper.selectAll(name);\n        return PageInfo.of(list);\n    }\n\n}\n\n\n```\n\n\n\nUserMapper\n\n```java\npackage com.example.mapper;\n\nimport com.example.entity.User;\n\nimport java.util.List;\n\npublic interface UserMapper {\n\n    List\u003CUser> selectAll(String name);\n\n}\n\n\n```\n\n\n\nUserMapper.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.UserMapper\">\n\n    \u003Cselect id=\"selectAll\" resultType=\"com.example.entity.User\">\n        select * from `user`\n        \u003Cwhere>\n            \u003Cif test=\"name != null\">name like concat('%', #{name}, '%')\u003C\u002Fif>\n        \u003C\u002Fwhere>\n    \u003C\u002Fselect>\n\n\u003C\u002Fmapper>\n\n```\n\n\n\nUser.vue\n\n```vue\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003Cdiv class=\"card\" style=\"margin-bottom: 5px\">\n      \u003Cel-input style=\"width: 300px\" v-model=\"data.name\" placeholder=\"请输入名称查询\" :prefix-icon=\"Search\" \u002F>\n      \u003Cel-button @click=\"load\" type=\"primary\" style=\"margin-left: 10px\">查询\u003C\u002Fel-button>\n      \u003Cel-button @click=\"reset\" type=\"info\">重置\u003C\u002Fel-button>\n    \u003C\u002Fdiv>\n\n    \u003Cdiv class=\"card\" style=\"margin-bottom: 5px\">\n      \u003Cdiv style=\"margin-bottom: 10px\">\n        \u003Cel-button @click=\"reset\" type=\"primary\">新增\u003C\u002Fel-button>\n      \u003C\u002Fdiv>\n      \u003Cdiv>\n        \u003Cel-table :data=\"data.tableData\" stripe style=\"width: 100%\">\n          \u003Cel-table-column prop=\"username\" label=\"账号\" \u002F>\n          \u003Cel-table-column prop=\"name\" label=\"姓名\" \u002F>\n          \u003Cel-table-column prop=\"role\" label=\"角色\" \u002F>\n          \u003Cel-table-column prop=\"account\" label=\"账户余额\" \u002F>\n          \u003Cel-table-column label=\"操作\" width=\"180\" fixed=\"right\" >\n            \u003Cel-button type=\"primary\">编辑\u003C\u002Fel-button>\n            \u003Cel-button type=\"danger\">删除\u003C\u002Fel-button>\n          \u003C\u002Fel-table-column>\n        \u003C\u002Fel-table>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n\n    \u003Cdiv class=\"card\">\n      \u003Cel-pagination v-model:current-page=\"data.pageNum\" v-model:page-size=\"data.pageSize\"\n                     @current-change=\"load\" background layout=\"total, prev, pager, next\" :total=\"data.total\" \u002F>\n    \u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport { reactive } from \"vue\";\nimport { Search } from \"@element-plus\u002Ficons-vue\";\nimport request from \"@\u002Futils\u002Frequest\";\nimport {ElMessage} from \"element-plus\";\n\nconst data = reactive({\n  name: null,\n  tableData: [],\n  total: 0,\n  pageNum: 1,\n  pageSize: 5\n})\n\n\u002F\u002F 分页查询数据的函数\nconst load = () => {\n  request.get('\u002Fuser\u002FselectPage', {\n    params: {\n      pageNum: data.pageNum,\n      pageSize: data.pageSize,\n      name: data.name\n    }\n  }).then(res => {\n    if (res.code === '200') {\n      data.tableData = res.data?.list\n      data.total = res.data?.total\n    } else {\n      ElMessage.error(res.msg)\n    }\n  })\n}\nload()\n\nconst reset = () => {\n  data.name = null\n  load()\n}\n\u003C\u002Fscript>\n\n```\n\n## \u003Cfont style=\"color:rgb(31, 31, 31);\">⭐\u003C\u002Ffont>删除数据\n\n### 页面按钮\n\n```vue\n\u003Cel-table-column label=\"操作\" width=\"180\" fixed=\"right\" >\n  \u003Ctemplate #default=\"scope\">\n    \u003Cel-button type=\"danger\" @click=\"del(scope.row.id)\">删除\u003C\u002Fel-button>\n  \u003C\u002Ftemplate>\n\u003C\u002Fel-table-column>\n\nimport {ElMessage, ElMessageBox} from \"element-plus\";\n\nconst del = (id) => {\n  ElMessageBox.confirm('您确定删除吗？', '删除确认', { type: 'warning' }).then(res => {\n    request.delete('\u002Fuser\u002Fdelete\u002F' + id).then(res => {\n      if (res.code === '200') {\n        ElMessage.success('操作成功')\n        load()\n      } else {\n        ElMessage.error(res.msg)\n      }\n    })\n  }).catch(err => {})\n}\n\n```\n\n### 后台接口\n\n删除接口\n\n```java\n\u002F**\n * 删除数据\n * 接口路径：\u002Fuser\u002Fdelete\u002F1\n *\u002F\n@DeleteMapping(\"\u002Fdelete\u002F{id}\")\npublic Result delete(@PathVariable Integer id) {\n    userService.deleteById(id);\n    return Result.success();\n}\n\n```\n\n删除的 sql\n\n```xml\n\u003Cdelete id=\"deleteById\">\n    delete from `user` where id = #{id}\n\u003C\u002Fdelete>\n\n```\n\n","coding",1,12150,1987,"2025-11-12 16:53:01","2026-05-03 22:49:02","青哥带小白做毕设2026所有资料汇总","qingge-code-2026",{"project":18,"items":19},{"id":6,"title":15,"slug":16},[20,27,34,35,42,49,56,63,70,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. 带小白做毕设课程介绍以及脚手架获取",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":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":36,"uuid":37,"project_id":6,"title":38,"type":9,"status":10,"public_enabled":10,"views":39,"sort":40,"created_at":41,"updated_at":14,"project_title":15,"project_slug":16},1006,"6mmUNf9i","03. 带你开发一个基础的用户管理模块（下）",7782,1994,"2025-11-13 16:48:27",{"id":43,"uuid":44,"project_id":6,"title":45,"type":9,"status":10,"public_enabled":10,"views":46,"sort":47,"created_at":48,"updated_at":14,"project_title":15,"project_slug":16},1011,"3XNG04wA","04. 带你开发用户登录、注册、个人信息、修改密码功能",6474,2003,"2025-11-17 17:03:58",{"id":50,"uuid":51,"project_id":6,"title":52,"type":9,"status":10,"public_enabled":10,"views":53,"sort":54,"created_at":55,"updated_at":14,"project_title":15,"project_slug":16},1017,"LnAAYydZ","05. 带你开发商品分类管理功能",5467,2012,"2025-11-24 17:30:23",{"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},1018,"584qohhy","06. 开发商品信息管理功能",4836,2013,"2025-11-24 17:30:12",{"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},1024,"scxsifCZ","07. 开发轮播图信息管理功能",3313,2021,"2025-11-24 17:29:58",{"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},1041,"AjujV8Gq","08. 带你实现前台首页功能",4058,2039,"2025-11-24 17:31:31",{"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. 带你开发用户模拟充值功能",2442,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"]