[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-public-2vquH0pr":3,"public-project-articles-2vquH0pr":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},253,"2vquH0pr",38,"12. 餐桌管理","## 创建数据库表 tables\n\n```sql\nCREATE TABLE `tables` (\n  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',\n  `no` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '餐桌号',\n  `unit` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '规格',\n  `free` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '是否空闲',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='餐桌信息';\n```\n\n## 完成后台的CRUD\n\nTablesController\n\n```java\npackage com.example.controller;\n\nimport com.example.common.Result;\nimport com.example.entity.Tables;\nimport com.example.service.TablesService;\nimport com.github.pagehelper.PageInfo;\nimport jakarta.annotation.Resource;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\n\n@RestController\n@RequestMapping(\"\u002Ftables\")\npublic class TablesController {\n\n    @Resource\n    TablesService tablesService;\n\n    \u002F**\n     * 新增\n     *\u002F\n    @PostMapping(\"\u002Fadd\")\n    public Result add(@RequestBody Tables tables) {\n        tablesService.add(tables);\n        return Result.success();\n    }\n\n    \u002F**\n     * 删除\n     *\u002F\n    @DeleteMapping(\"\u002Fdelete\u002F{id}\")\n    public Result delete(@PathVariable Integer id) {\n        tablesService.deleteById(id);\n        return Result.success();\n    }\n\n    \u002F**\n     * 批量删除\n     *\u002F\n    @DeleteMapping(\"\u002Fdelete\u002Fbatch\")\n    public Result delete(@RequestBody List\u003CInteger> ids) {\n        tablesService.deleteBatch(ids);\n        return Result.success();\n    }\n\n    \u002F**\n     * 新增\n     *\u002F\n    @PutMapping(\"\u002Fupdate\")\n    public Result update(@RequestBody Tables tables) {\n        tablesService.updateById(tables);\n        return Result.success();\n    }\n\n    \u002F**\n     * 查询单个\n     *\u002F\n    @GetMapping(\"\u002FselectById\u002F{id}\")\n    public Result selectById(@PathVariable Integer id) {\n        Tables tables = tablesService.selectById(id);\n        return Result.success(tables);\n    }\n\n    \u002F**\n     * 查询所有\n     *\u002F\n    @GetMapping(\"\u002FselectAll\")\n    public Result selectAll(String name) {\n        List\u003CTables> list = tablesService.selectAll(name);\n        return Result.success(list);\n    }\n\n    \u002F**\n     * 查询所有\n     *\u002F\n    @GetMapping(\"\u002FselectPage\")\n    public Result selectPage(\n            String name,\n            @RequestParam(defaultValue = \"1\") Integer pageNum,\n            @RequestParam(defaultValue = \"10\") Integer pageSize) {\n        PageInfo\u003CTables> pageInfo = tablesService.selectPage(name, pageNum, pageSize);\n        return Result.success(pageInfo);\n    }\n\n}\n\n```\n\nTablesMapper.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.TablesMapper\">\n\n    \u003Cinsert id=\"insert\">\n        insert into tables (no, unit, free)\n        values (#{no}, #{unit}, #{free})\n    \u003C\u002Finsert>\n\n\n    \u003Cupdate id=\"updateById\">\n        update tables\n        \u003Cset>\n            \u003Cif test=\"no != null\">no = #{no},\u003C\u002Fif>\n            \u003Cif test=\"unit != null\">unit = #{unit},\u003C\u002Fif>\n            \u003Cif test=\"free != null\">free = #{free},\u003C\u002Fif>\n        \u003C\u002Fset>\n        where id = #{id}\n    \u003C\u002Fupdate>\n\n    \u003Cdelete id=\"deleteById\">\n        delete\n        from tables\n        where id = #{id}\n    \u003C\u002Fdelete>\n\n    \u003Cselect id=\"selectAll\" resultType=\"com.example.entity.Tables\">\n        select * from tables\n        \u003Cwhere>\n            \u003Cif test=\"no != null\">\n                no like concat('%', #{no}, '%')\n            \u003C\u002Fif>\n        \u003C\u002Fwhere>\n        order by id desc\n    \u003C\u002Fselect>\n\n\n\u003C\u002Fmapper>\n```\n\n## 完成前台页面开发\n\n```vue\n\u003Ctemplate>\n  \u003Cdiv>\n\n    \u003Cdiv class=\"card\" style=\"margin-bottom: 10px;\">\n      \u003Cel-input prefix-icon=\"Search\" style=\"width: 300px; margin-right: 10px\" placeholder=\"请输入餐桌号查询\" v-model=\"data.no\">\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: 10px\">\n      \u003Cdiv style=\"margin-bottom: 10px\">\n        \u003Cel-button type=\"primary\" @click=\"handleAdd\">新增\u003C\u002Fel-button>\n      \u003C\u002Fdiv>\n      \u003Cel-table :data=\"data.tableData\">\n        \u003Cel-table-column prop=\"id\" label=\"序号\" width=\"70\"\u002F>\n        \u003Cel-table-column prop=\"no\" label=\"餐桌号\"\u002F>\n        \u003Cel-table-column prop=\"unit\" label=\"规格\"\u002F>\n        \u003Cel-table-column prop=\"free\" label=\"是否空闲\">\u003C\u002Fel-table-column>\n        \u003Cel-table-column label=\"操作\" width=\"180\">\n          \u003Ctemplate #default=\"scope\">\n            \u003Cel-button type=\"primary\" @click=\"handleEdit(scope.row)\">编辑\u003C\u002Fel-button>\n            \u003Cel-button type=\"danger\" @click=\"del(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\" v-if=\"data.total\">\n      \u003Cel-pagination background layout=\"prev, pager, next\" @current-change=\"load\" :page-size=\"data.pageSize\" v-model:current-page=\"data.pageNum\" :total=\"data.total\"\u002F>\n    \u003C\u002Fdiv>\n\n    \u003Cel-dialog v-model=\"data.formVisible\" title=\"信息\" width=\"40%\" destroy-on-close>\n      \u003Cel-form :model=\"data.form\" label-width=\"100px\" style=\"padding-right: 50px\">\n        \u003Cel-form-item label=\"餐桌号\">\n          \u003Cel-input v-model=\"data.form.no\" autocomplete=\"off\" \u002F>\n        \u003C\u002Fel-form-item>\n        \u003Cel-form-item label=\"规格\">\n          \u003Cel-input v-model=\"data.form.unit\" autocomplete=\"off\" \u002F>\n        \u003C\u002Fel-form-item>\n        \u003Cel-form-item label=\"是否空闲\">\n          \u003Cel-radio-group v-model=\"data.form.free\">\n            \u003Cel-radio label=\"是\">\u003C\u002Fel-radio>\n            \u003Cel-radio label=\"否\">\u003C\u002Fel-radio>\n          \u003C\u002Fel-radio-group>\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 {reactive} from \"vue\"\nimport request from \"@\u002Futils\u002Frequest\";\nimport {ElMessage, ElMessageBox} from \"element-plus\";\n\nconst data = reactive({\n  tableData: [],\n  total: 0,\n  pageNum: 1,  \u002F\u002F 当前的页码\n  pageSize: 5,  \u002F\u002F 每页的个数\n  formVisible: false,\n  form: {},\n  no: '',\n})\n\nconst load = () => {\n  request.get('\u002Ftables\u002FselectPage', {\n    params: {\n      pageNum: data.pageNum,\n      pageSize: data.pageSize,\n      no: data.no\n    }\n  }).then(res => {\n    data.tableData = res.data?.list || []\n    data.total = res.data.total\n  })\n}\n\nload()\n\nconst reset = () => {\n  data.no = null\n  load()\n}\n\nconst handleAdd = () => {\n  data.form = {}  \u002F\u002F 初始化表单\n  data.formVisible = true  \u002F\u002F 打开弹窗\n}\n\n\u002F\u002F 保存数据\nconst save = () => {\n  request.request({\n    method: data.form.id ? 'PUT' : 'POST',\n    url: data.form.id ? '\u002Ftables\u002Fupdate' : '\u002Ftables\u002Fadd',\n    data: data.form\n  }).then(res => {\n    if (res.code === '200') {  \u002F\u002F成功\n      ElMessage.success('操作成功')\n      data.formVisible = false \u002F\u002F 关闭弹窗\n      load()  \u002F\u002F 重新加载表格数据\n    } else {\n      ElMessage.error(res.msg)\n    }\n  })\n}\n\nconst handleEdit = (row) => {\n  data.form = JSON.parse(JSON.stringify(row))\n  data.formVisible = true\n}\n\nconst del = (id) => {\n  ElMessageBox.confirm('删除后数据无法恢复，您确认删除吗？', '确认删除', { type: 'warning' }).then(res => {\n    request.delete('\u002Ftables\u002Fdelete\u002F' + id).then(res => {\n      if (res.code === '200') {  \u002F\u002F成功\n        ElMessage.success('操作成功')\n        load()  \u002F\u002F 重新加载表格数据\n      } else {\n        ElMessage.error(res.msg)\n      }\n    })\n  }).catch(err => {\n    console.log(err)\n  })\n}\n\n\u003C\u002Fscript>\n```\n\n## 完成首页餐桌管理\n\n![餐饮.png](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2024\u002Fpng\u002F751015\u002F1708657307709-f1a7357a-d27a-47e4-8e1f-2b28a76bb9e2.png#averageHue=%23070c2d&clientId=u74a18c44-20b0-4&from=paste&height=160&id=ua8cd180e&originHeight=200&originWidth=246&originalType=binary&ratio=1.25&rotation=0&showTitle=false&size=4485&status=done&style=none&taskId=u737280e5-91ed-4d9b-9bbd-8574f6c7ca8&title=&width=196.8)\n\n新增一个接口 用于点餐\n\n```vue\n@PutMapping(\"\u002FaddOrder\")\npublic Result addOrder(@RequestBody Tables tables) {\n    tablesService.addOrder(tables);\n    return Result.success();\n}\n\npublic void addOrder(Tables tables) {\n    \u002F\u002F 先查询当前的用户有没有占用餐桌\n    Tables dbTables = tablesMapper.selectByUserId(tables.getUserId());\n    if (dbTables != null && !dbTables.getId().equals(tables.getId())) {\n        throw new CustomException(\"您已经预定了其他餐桌\");\n    }\n    this.updateById(tables);\n}\n```\n\n新增一个接口  根据当前的用户ID查询已经订餐的餐桌\n\n```java\n@GetMapping(\"\u002FselectByUserId\u002F{userId}\")\npublic Result selectByUserId(@PathVariable Integer userId) {\n    Tables tables = tablesService.selectByUserId(userId);\n    return Result.success(tables);\n}\n```\n\n新增一个接口，退桌\n\n```java\n@PutMapping(\"\u002FremoveOrder\")\npublic Result removeOrder(@RequestBody Tables tables) {\n    tablesService.removeOrder(tables);\n    return Result.success();\n}\n\npublic void removeOrder(Tables tables) {\n    tablesMapper.removeOrder(tables.getId());\n}\n\n@Update(\"update tables set user_id = null, free = '是' where id = #{id}\")\nvoid removeOrder(Integer id);\n```\n\nOrder.vue\n\n```vue\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003Cdiv class=\"card\">\n      \u003Cdiv v-if=\"data.table.no\">\n        \u003Cdiv style=\"display: flex\">\n          \u003Cdiv style=\"flex: 1\">\n            餐桌号：{{ data.table.no }}  开始点餐\n          \u003C\u002Fdiv>\n          \u003Cel-button type=\"primary\" @click=\"removeOrder\">退桌\u003C\u002Fel-button>\n        \u003C\u002Fdiv>\n\n        \u003Cdiv>\n\u003C!--          展示餐品-->\n        \u003C\u002Fdiv>\n\n      \u003C\u002Fdiv>\n\n\n      \u003Cdiv style=\"color:#666;\" v-else>\n        您还未选餐桌，请先 \u003Ca href=\"\u002Fhome\">选择餐桌\u003C\u002Fa> 再点餐\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport {reactive} from \"vue\";\nimport request from \"@\u002Futils\u002Frequest\";\nimport router from \"@\u002Frouter\";\nimport {ElMessage} from \"element-plus\";\n\nconst data = reactive({\n  table: {},\n  user: JSON.parse(localStorage.getItem('canteen-user') || '{}')\n})\n\nconst loadTable = () => {\n  request.get('\u002Ftables\u002FselectByUserId\u002F' + data.user.id).then(res => {\n    data.table = res.data || {}\n  })\n}\nloadTable()\n\nconst removeOrder = () => {\n  request.put('\u002Ftables\u002FremoveOrder', data.table).then(res => {\n    if (res.code === '200') {\n      ElMessage.success('退桌成功')\n      loadTable()\n    } else {\n      ElMessage.error(res.msg)\n    }\n  })\n}\n\u003C\u002Fscript>\n\n\u003Cstyle scoped>\n\n\u003C\u002Fstyle>\n```\n\n## 管理员编辑餐桌的空闲状态\n\n查询用户名称\n\n```sql\n\u003Cselect id=\"selectAll\" resultType=\"com.example.entity.Tables\">\n    select tables.*, user.name as userName from tables\n    left join user\n    on tables.user_id = user.id\n    \u003Cwhere>\n        \u003Cif test=\"no != null\">\n            tables.no like concat('%', #{no}, '%')\n        \u003C\u002Fif>\n    \u003C\u002Fwhere>\n    order by id desc\n\u003C\u002Fselect>\n```\n\n当管理员设置餐桌状态是空闲的时候，我们就设置user_id = null\n\n```java\npublic void updateById(Tables tables) {\n    if (\"是\".equals(tables.getFree())) {\n        tables.setUserId(null);  \u002F\u002F 清除占用的顾客信息\n    }\n    tablesMapper.updateById(tables);\n}\n```\n\n![image.png](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2024\u002Fpng\u002F751015\u002F1708998543247-612354aa-aeb5-4089-bac2-e0c5cbc799fa.png#averageHue=%23474435&clientId=u44a76b11-ef6b-4&from=paste&height=265&id=ua3a3b278&originHeight=331&originWidth=757&originalType=binary&ratio=1.25&rotation=0&showTitle=false&size=34090&status=done&style=none&taskId=ub0f5ecc3-d828-4bc4-bec5-2e72acd9d14&title=&width=605.6)","coding",1,879,432,"2024-06-03 22:12:16","2026-05-03 22:49:02","SpringBoot3+Vue3的在线点餐系统","online-ordering",{"project":18,"items":19},{"id":6,"title":15,"slug":16},[20,27,34,41,48,55,62,69,76,83,90,97,98,105,112,119],{"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},58,"JOJVoOQd","01. 在线点餐系统介绍",2745,102,"2025-01-09 09:49: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},59,"Tt7tzqbb","02. 脚手架介绍",2364,103,"2025-01-09 09:54:51",{"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},60,"h74qSg8n","03. 开发登录功能",1974,104,"2024-04-16 02:30:00",{"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},61,"uv8MFWZg","04. 开发后台登录接口",1729,105,"2024-04-16 02:29:56",{"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},62,"jd2xjxUG","05. 开发普通用户登录功能",1145,106,"2024-04-16 02:29:27",{"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},63,"TnvWfP4t","06. 开发普通用户注册功能",861,107,"2024-04-16 02:29: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},64,"j9QNZGZU","07. 开发管理员后台接口",873,108,"2024-04-16 02:29:17",{"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},65,"Sle0aiDs","08. 开发管理员管理页面并对接后台接口",821,109,"2024-04-16 02:29:13",{"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},66,"msAf9SFh","09. 开发文件上传功能",659,110,"2024-04-16 02:29:09",{"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},67,"8FBiQ4ue","10. 个人资料管理",736,111,"2024-04-16 02:29:06",{"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},252,"hi7dGSTj","11. 顾客信息管理",643,431,"2024-06-20 15:59:16",{"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":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},254,"F8DqfdBe","13. 开发餐品管理功能.",731,433,"2024-06-03 22:12:43",{"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},275,"G20uzwaW","14. 开发在线点餐功能（一）",768,467,"2024-06-27 12:21:02",{"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},276,"0bl3zvbT","15. 开发在线点餐功能（二）",609,468,"2024-06-27 12:21:30",{"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":14,"project_title":15,"project_slug":16},277,"AUgPvs9x","16. 开发在线点餐功能（三）",716,469,"2024-06-27 12:22:01"]