commit 37f2b6f3dd3e1f14dadd9ca0a278d39d9241bbe2 Author: qq1244 <1244154570@qq.com> Date: Wed Jun 18 18:29:40 2025 +0800 beta1.0 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3b41682 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +/mvnw text eol=lf +*.cmd text eol=crlf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..667aaef --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..d58dfb7 --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +wrapperVersion=3.3.2 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip diff --git a/README.md b/README.md new file mode 100644 index 0000000..56139cc --- /dev/null +++ b/README.md @@ -0,0 +1,163 @@ +# 菜品管理系统后端 + +这是一个基于Spring Boot + MyBatis-Plus的菜品管理系统后端API。 + +## 技术栈 + +- **Spring Boot 3.4.6** - Web框架 +- **MyBatis-Plus 3.5.3.1** - 数据持久层框架 +- **MySQL** - 数据库 +- **Lombok** - 简化Java代码 +- **Maven** - 项目管理工具 + +## 项目结构 + +``` +src/ +├── main/ +│ ├── java/com/example/javatest/ +│ │ ├── JavaTestApplication.java # 主启动类 +│ │ ├── config/ +│ │ │ └── MybatisPlusConfig.java # MyBatis-Plus配置 +│ │ ├── controller/ +│ │ │ └── DishController.java # 菜品控制器 +│ │ ├── entity/ +│ │ │ └── Dish.java # 菜品实体类 +│ │ ├── mapper/ +│ │ │ └── DishMapper.java # 菜品Mapper接口 +│ │ └── service/ +│ │ ├── DishService.java # 菜品服务接口 +│ │ └── impl/ +│ │ └── DishServiceImpl.java # 菜品服务实现 +│ └── resources/ +│ ├── application.properties # 应用配置 +│ ├── mapper/ +│ │ └── DishMapper.xml # MyBatis映射文件 +│ └── sql/ +│ └── dishes.sql # 数据库建表脚本 +``` + +## 快速开始 + +### 1. 环境要求 + +- JDK 17+ +- MySQL 8.0+ +- Maven 3.6+ + +### 2. 数据库配置 + +1. 创建MySQL数据库 +2. 执行 `src/main/resources/sql/dishes.sql` 脚本创建表和测试数据 +3. 修改 `application.properties` 中的数据库连接信息: + +```properties +spring.datasource.url=jdbc:mysql://localhost:3306/restaurant_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai +spring.datasource.username=your_username +spring.datasource.password=your_password +``` + +### 3. 运行项目 + +```bash +# 克隆项目 +git clone + +# 进入项目目录 +cd java-test + +# 安装依赖并运行 +mvn spring-boot:run +``` + +项目启动后访问:http://localhost:8080 + +## API接口 + +### 菜品管理接口 + +| 方法 | 路径 | 描述 | +|------|------|------| +| GET | `/api/dishes` | 分页查询菜品列表 | +| GET | `/api/dishes/{id}` | 根据ID查询菜品详情 | +| POST | `/api/dishes` | 添加菜品 | +| PUT | `/api/dishes/{id}` | 更新菜品 | +| DELETE | `/api/dishes/{id}` | 删除菜品 | +| PATCH | `/api/dishes/{id}/status` | 更新菜品状态 | + +### 分页查询参数 + +- `page`: 当前页,默认1 +- `size`: 每页大小,默认10 +- `dishName`: 菜品名称(模糊查询) +- `category`: 分类筛选 +- `status`: 状态筛选 + +### 示例请求 + +```bash +# 查询菜品列表 +curl "http://localhost:8080/api/dishes?page=1&size=10" + +# 根据名称搜索 +curl "http://localhost:8080/api/dishes?dishName=宫保鸡丁" + +# 根据分类筛选 +curl "http://localhost:8080/api/dishes?category=主食" + +# 更新菜品状态 +curl -X PATCH "http://localhost:8080/api/dishes/1/status" \ + -H "Content-Type: application/json" \ + -d '{"status": "停售"}' +``` + +## 数据模型 + +### Dish (菜品) + +| 字段 | 类型 | 说明 | +|------|------|------| +| dishId | Long | 菜品ID (主键) | +| dishName | String | 菜品名称 | +| category | String | 分类 | +| price | BigDecimal | 价格 | +| stock | Integer | 库存 | +| status | String | 状态 (在售/停售) | +| description | String | 描述 | +| imageUrl | String | 图片URL | +| sales | Integer | 销量 | +| tag | String | 标签 | +| isDeleted | Integer | 逻辑删除标记 | +| deletedAt | LocalDateTime | 删除时间 | +| createdAt | LocalDateTime | 创建时间 | +| updatedAt | LocalDateTime | 更新时间 | + +## 功能特性 + +- ✅ CRUD操作 +- ✅ 分页查询 +- ✅ 条件筛选(名称、分类、状态) +- ✅ 逻辑删除 +- ✅ 自动时间戳填充 +- ✅ 跨域支持 +- ✅ 统一响应格式 + +## 前端集成 + +此后端API与Vue3前端菜品管理页面完全兼容,支持: + +- 菜品列表展示 +- 分页显示 +- 搜索筛选 +- 菜品详情查看 +- 菜品编辑 +- 状态切换 +- 菜品删除 + +## 开发说明 + +- 使用MyBatis-Plus简化数据操作 +- 支持逻辑删除,数据安全 +- 自动填充创建时间和更新时间 +- ResponseEntity统一响应格式 +- 完整的异常处理机制 \ No newline at end of file diff --git a/cg.sql b/cg.sql new file mode 100644 index 0000000..0d037ab --- /dev/null +++ b/cg.sql @@ -0,0 +1,191 @@ +/* + Navicat Premium Dump SQL + + Source Server : localhost_3306 + Source Server Type : MySQL + Source Server Version : 90200 (9.2.0) + Source Host : localhost:3306 + Source Schema : cg + + Target Server Type : MySQL + Target Server Version : 90200 (9.2.0) + File Encoding : 65001 + + Date: 18/06/2025 12:47:29 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for account +-- ---------------------------- +DROP TABLE IF EXISTS `account`; +CREATE TABLE `account` ( + `account_id` bigint NOT NULL AUTO_INCREMENT COMMENT '账户ID', + `account_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '账户名称', + `account_password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '账户密码', + `account_phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '手机号码', + `account_type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'customer' COMMENT '账户类型:admin/manager/customer', + `account_img` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '头像图片URL', + `account_gender` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '性别:male/female', + `account_tag` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '账户标签', + `salary` decimal(10, 2) NULL DEFAULT NULL COMMENT '薪资(员工用)', + `is_deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除:0-未删除,1-已删除', + `deleted_at` datetime NULL DEFAULT NULL COMMENT '删除时间', + `created_at` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`account_id`) USING BTREE, + INDEX `idx_account_phone`(`account_phone` ASC) USING BTREE, + INDEX `idx_account_type`(`account_type` ASC) USING BTREE, + INDEX `idx_is_deleted`(`is_deleted` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户账户表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for branch +-- ---------------------------- +DROP TABLE IF EXISTS `branch`; +CREATE TABLE `branch` ( + `branch_id` bigint NOT NULL AUTO_INCREMENT COMMENT '分店ID', + `branch_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '分店名称', + `branch_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '分店地址', + `branch_phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '分店电话', + `branch_start` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '营业开始时间,格式:HH:mm', + `branch_end` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '营业结束时间,格式:HH:mm', + `branch_status` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT 'open' COMMENT '营业状态:open-营业中,closed-已停业', + `branch_boss` bigint NULL DEFAULT NULL COMMENT '负责人ID,关联account表', + `province` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '所属省份', + `latitude` decimal(10, 8) NULL DEFAULT NULL COMMENT '纬度', + `longitude` decimal(11, 8) NULL DEFAULT NULL COMMENT '经度', + `is_deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除:0-未删除,1-已删除', + `deleted_at` datetime NULL DEFAULT NULL COMMENT '删除时间', + `created_at` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`branch_id`) USING BTREE, + INDEX `idx_branch_status`(`branch_status` ASC) USING BTREE, + INDEX `idx_branch_boss`(`branch_boss` ASC) USING BTREE, + INDEX `idx_province`(`province` ASC) USING BTREE, + INDEX `idx_is_deleted`(`is_deleted` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '分店表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for comments +-- ---------------------------- +DROP TABLE IF EXISTS `comments`; +CREATE TABLE `comments` ( + `comment_id` bigint NOT NULL AUTO_INCREMENT COMMENT '评论ID', + `comment_text` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '评论内容', + `comment_dish_id` bigint NOT NULL COMMENT '评论的菜品ID', + `comment_account_id` bigint NOT NULL COMMENT '评论用户ID', + `comment_rating` int NULL DEFAULT 5 COMMENT '评分:1-5分', + `parent_comment_id` bigint NULL DEFAULT NULL COMMENT '父评论ID,用于回复功能', + `is_deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除:0-未删除,1-已删除', + `deleted_at` datetime NULL DEFAULT NULL COMMENT '删除时间', + `created_at` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`comment_id`) USING BTREE, + INDEX `idx_comment_dish_id`(`comment_dish_id` ASC) USING BTREE, + INDEX `idx_comment_account_id`(`comment_account_id` ASC) USING BTREE, + INDEX `idx_parent_comment_id`(`parent_comment_id` ASC) USING BTREE, + INDEX `idx_comment_rating`(`comment_rating` ASC) USING BTREE, + INDEX `idx_is_deleted`(`is_deleted` ASC) USING BTREE, + INDEX `idx_created_at`(`created_at` ASC) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '评论表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for dishes +-- ---------------------------- +DROP TABLE IF EXISTS `dishes`; +CREATE TABLE `dishes` ( + `dish_id` bigint NOT NULL AUTO_INCREMENT COMMENT '菜品ID', + `dish_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '菜品名称', + `category` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '菜品分类', + `price` decimal(10, 2) NOT NULL COMMENT '菜品价格', + `stock` int NULL DEFAULT 0 COMMENT '库存数量', + `status` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT 'available' COMMENT '菜品状态:available-可售,unavailable-停售', + `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '菜品描述', + `image_url` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '菜品图片URL', + `sales` int NULL DEFAULT 0 COMMENT '累计销售数量', + `tag` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '菜品标签', + `is_deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除:0-未删除,1-已删除', + `deleted_at` datetime NULL DEFAULT NULL COMMENT '删除时间', + `created_at` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`dish_id`) USING BTREE, + INDEX `idx_category`(`category` ASC) USING BTREE, + INDEX `idx_status`(`status` ASC) USING BTREE, + INDEX `idx_is_deleted`(`is_deleted` ASC) USING BTREE, + INDEX `idx_dish_name`(`dish_name` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '菜品表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for menu +-- ---------------------------- +DROP TABLE IF EXISTS `menu`; +CREATE TABLE `menu` ( + `menu_id` bigint NOT NULL AUTO_INCREMENT COMMENT '菜单ID', + `branch_id` bigint NOT NULL COMMENT '分店ID', + `dish_id` bigint NOT NULL COMMENT '菜品ID', + `is_available` tinyint(1) NULL DEFAULT 1 COMMENT '该菜品在该分店是否可售', + `branch_price` decimal(10, 2) NULL DEFAULT NULL COMMENT '分店特定价格(如果为空则使用菜品表的价格)', + `created_at` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`menu_id`) USING BTREE, + UNIQUE INDEX `uk_branch_dish`(`branch_id` ASC, `dish_id` ASC) USING BTREE, + INDEX `idx_branch_id`(`branch_id` ASC) USING BTREE, + INDEX `idx_dish_id`(`dish_id` ASC) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '菜单表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for order +-- ---------------------------- +DROP TABLE IF EXISTS `order`; +CREATE TABLE `order` ( + `order_id` bigint NOT NULL AUTO_INCREMENT COMMENT '订单ID', + `account_id` bigint NOT NULL COMMENT '下单用户ID', + `order_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '下单时间', + `branch_id` bigint NOT NULL COMMENT '分店ID', + `order_money` decimal(10, 2) NOT NULL COMMENT '订单总金额', + `order_remarks` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '订单备注', + `order_status` int NULL DEFAULT 1 COMMENT '订单状态:1-待处理,2-已完成,-1-已取消', + `is_deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除:0-未删除,1-已删除', + `deleted_at` datetime NULL DEFAULT NULL COMMENT '删除时间', + `created_at` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`order_id`) USING BTREE, + INDEX `idx_account_id`(`account_id` ASC) USING BTREE, + INDEX `idx_branch_id`(`branch_id` ASC) USING BTREE, + INDEX `idx_order_status`(`order_status` ASC) USING BTREE, + INDEX `idx_order_time`(`order_time` ASC) USING BTREE, + INDEX `idx_is_deleted`(`is_deleted` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '订单表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for order_list +-- ---------------------------- +DROP TABLE IF EXISTS `order_list`; +CREATE TABLE `order_list` ( + `order_list_id` bigint NOT NULL AUTO_INCREMENT COMMENT '订单明细ID', + `order_id` bigint NOT NULL COMMENT '订单ID', + `dish_id` bigint NOT NULL COMMENT '菜品ID', + `number` int NOT NULL DEFAULT 1 COMMENT '数量', + `created_at` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`order_list_id`) USING BTREE, + INDEX `idx_order_id`(`order_id` ASC) USING BTREE, + INDEX `idx_dish_id`(`dish_id` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '订单明细表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- View structure for branch_order_stats +-- ---------------------------- +DROP VIEW IF EXISTS `branch_order_stats`; +CREATE ALGORITHM = UNDEFINED SQL SECURITY DEFINER VIEW `branch_order_stats` AS select `b`.`branch_id` AS `branch_id`,`b`.`branch_name` AS `branch_name`,count(`o`.`order_id`) AS `total_orders`,coalesce(sum(`o`.`order_money`),0) AS `total_revenue`,cast(`o`.`order_time` as date) AS `order_date` from (`branch` `b` left join `order` `o` on(((`b`.`branch_id` = `o`.`branch_id`) and (`o`.`is_deleted` = false)))) where (`b`.`is_deleted` = false) group by `b`.`branch_id`,`b`.`branch_name`,cast(`o`.`order_time` as date); + +-- ---------------------------- +-- View structure for dish_sales_view +-- ---------------------------- +DROP VIEW IF EXISTS `dish_sales_view`; +CREATE ALGORITHM = UNDEFINED SQL SECURITY DEFINER VIEW `dish_sales_view` AS select `d`.`dish_id` AS `dish_id`,`d`.`dish_name` AS `dish_name`,`d`.`category` AS `category`,`d`.`price` AS `price`,coalesce(sum(`ol`.`number`),0) AS `total_sales`,count(distinct `o`.`order_id`) AS `order_count` from ((`dishes` `d` left join `order_list` `ol` on((`d`.`dish_id` = `ol`.`dish_id`))) left join `order` `o` on(((`ol`.`order_id` = `o`.`order_id`) and (`o`.`is_deleted` = false)))) where (`d`.`is_deleted` = false) group by `d`.`dish_id`,`d`.`dish_name`,`d`.`category`,`d`.`price`; + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/mvnw b/mvnw new file mode 100644 index 0000000..19529dd --- /dev/null +++ b/mvnw @@ -0,0 +1,259 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.2 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..249bdf3 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,149 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..e94c26f --- /dev/null +++ b/pom.xml @@ -0,0 +1,124 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.5.0 + + + org.example + CG + 0.0.1-SNAPSHOT + CG + CG + + + + + + + + + + + + + + + 17 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.apache.httpcomponents + httpclient + 4.5.13 + + + com.alibaba + fastjson + 2.0.31 + + + + org.projectlombok + lombok + 1.18.36 + provided + + + + org.springframework.boot + spring-boot-starter-security + + + + + mysql + mysql-connector-java + 8.0.26 + + + + com.baomidou + mybatis-plus-spring-boot3-starter + 3.5.12 + + + + com.baomidou + mybatis-plus-jsqlparser + 3.5.12 + + + + com.alibaba + druid-spring-boot-starter + 1.2.18 + + + + io.jsonwebtoken + jjwt-api + 0.12.6 + + + + io.jsonwebtoken + jjwt-impl + 0.12.6 + + + + io.jsonwebtoken + jjwt-jackson + 0.12.6 + + + org.springframework.boot + spring-boot-starter-webflux + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/src/main/java/com/example/javatest/Controller/admin/AccountController.java b/src/main/java/com/example/javatest/Controller/admin/AccountController.java new file mode 100644 index 0000000..9178a92 --- /dev/null +++ b/src/main/java/com/example/javatest/Controller/admin/AccountController.java @@ -0,0 +1,182 @@ +package com.example.javatest.Controller.admin; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; + +import com.example.javatest.Entity.admin.Account; +import com.example.javatest.Mapper.admin.AccountMapper; +import com.example.javatest.common.Result; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDateTime; + +@RestController +@RequestMapping("/admin/accounts") +public class AccountController { + + @Autowired + private AccountMapper accountMapper; + + // 1. 获取所有账户信息(分页) + @GetMapping + public Result> getAllAccounts( + @RequestParam(defaultValue = "1") int pageNum, + @RequestParam(defaultValue = "10") int pageSize) { + + Page page = new Page<>(pageNum, pageSize); + Page accountPage = accountMapper.selectPage(page, null); + return Result.success(accountPage); + } + + // 2. 根据账户类型查询 + @GetMapping("/byType") + public Result> getAccountsByType( + @RequestParam String accountType, + @RequestParam(defaultValue = "1") int pageNum, + @RequestParam(defaultValue = "10") int pageSize) { + + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(Account::getAccountType, accountType); + + Page page = new Page<>(pageNum, pageSize); + Page resultPage = accountMapper.selectPage(page, queryWrapper); + return Result.success(resultPage); + } + + // 3. 新增账户 + @PostMapping + @Transactional + public Result createAccount(@RequestBody Account account) { + // 设置默认密码 + account.setAccountPassword("123456"); + account.setAccountId(null); + + // 设置创建和更新时间 + LocalDateTime now = LocalDateTime.now(); + account.setCreatedAt(now); + account.setUpdatedAt(now); + + // 设置默认逻辑删除状态 + account.setIsDeleted(0); + + // 执行插入 + int result = accountMapper.insert(account); + if (result > 0) { + return Result.success(account); + } else { + return Result.error("新增账户失败"); + } + } + + // 4. 逻辑删除账户 + @DeleteMapping("/{id}") + @Transactional + public Result deleteAccount(@PathVariable Long id) { + // 直接使用MyBatis Plus的deleteById方法 + int result = accountMapper.deleteById(id); + + if (result > 0) { + return Result.success(); + } else { + // 检查账户是否存在 + Account account = accountMapper.selectById(id); + if (account == null) { + return Result.error("账户不存在"); + } else { + return Result.error("删除账户失败"); + } + } + } + + + // 5. 编辑账户信息 + @PutMapping("/{id}") + @Transactional + public Result updateAccount( + @PathVariable Long id, + @RequestBody Account updatedAccount) { + + // 获取现有账户 + Account account = accountMapper.selectById(id); + if (account == null) { + return Result.error("账户不存在"); + } + + // 更新基本信息(排除密码、图片、创建时间) + account.setAccountName(updatedAccount.getAccountName()); + account.setAccountPhone(updatedAccount.getAccountPhone()); + account.setAccountGender(updatedAccount.getAccountGender()); + account.setAccountType(updatedAccount.getAccountType()); + + // 更新图片URL(如果提供了新URL) + if (updatedAccount.getAccountImg() != null && !updatedAccount.getAccountImg().isEmpty()) { + account.setAccountImg(updatedAccount.getAccountImg()); + } + + // 更新修改时间 + account.setUpdatedAt(LocalDateTime.now()); + + int result = accountMapper.updateById(account); + if (result > 0) { + return Result.success(account); + } else { + return Result.error("更新账户失败"); + } + } + + // 6. 重置密码 + @PutMapping("/{id}/reset-password") + @Transactional + public Result resetPassword(@PathVariable Long id) { + Account account = accountMapper.selectById(id); + if (account == null) { + return Result.error("账户不存在"); + } + + account.setAccountPassword("123456"); + account.setUpdatedAt(LocalDateTime.now()); + + int result = accountMapper.updateById(account); + if (result > 0) { + return Result.success(); + } else { + return Result.error("密码重置失败"); + } + } + + // 7. 条件模糊查询 + @GetMapping("/search") + public Result> searchAccounts( + @RequestParam(required = false) Long id, + @RequestParam(required = false) String accountName, + @RequestParam(required = false) String accountPhone, + @RequestParam(required = false) String accountGender, + @RequestParam(defaultValue = "1") int pageNum, + @RequestParam(defaultValue = "10") int pageSize) { + + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + + // 添加查询条件 + if (id != null) { + queryWrapper.eq(Account::getAccountId, id); + } + if (accountName != null && !accountName.isEmpty()) { + queryWrapper.like(Account::getAccountName, accountName); + } + if (accountPhone != null && !accountPhone.isEmpty()) { + queryWrapper.like(Account::getAccountPhone, accountPhone); + } + if (accountGender != null && !accountGender.isEmpty()) { + queryWrapper.like(Account::getAccountGender, accountGender); + } + + // 排除已删除的账户 + queryWrapper.eq(Account::getIsDeleted, 0); + + Page page = new Page<>(pageNum, pageSize); + Page resultPage = accountMapper.selectPage(page, queryWrapper); + return Result.success(resultPage); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Controller/admin/BranchController.java b/src/main/java/com/example/javatest/Controller/admin/BranchController.java new file mode 100644 index 0000000..4cf35a9 --- /dev/null +++ b/src/main/java/com/example/javatest/Controller/admin/BranchController.java @@ -0,0 +1,326 @@ +package com.example.javatest.Controller.admin; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.example.javatest.Entity.admin.Account; +import com.example.javatest.Entity.admin.Branch; +import com.example.javatest.Mapper.admin.AccountMapper; +import com.example.javatest.Mapper.admin.BranchMapper; +import com.example.javatest.Mapper.admin.OrderMapper; +import com.example.javatest.Entity.admin.Order; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + + +@RestController("adminBranchController") +@RequestMapping("/admin/branch") +public class BranchController { + + @Autowired + private BranchMapper branchMapper; + @Autowired + private AccountMapper accountMapper; + @Autowired + private OrderMapper orderMapper; + + + /** + * 根据省份查询分店信息 + * @param province 省份名称 + * @return 分店列表 + */ + @GetMapping("/province/{province}") + public List getBranchesByProvince(@PathVariable String province) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("province", province); + return branchMapper.selectList(queryWrapper); + } + + /** + * 根据ID逻辑删除分店 + * @param id 分店ID + * @return 删除结果(true表示成功,false表示失败) + */ + @DeleteMapping("/{id}") + public boolean deleteBranch(@PathVariable Long id) { + return branchMapper.deleteById(id) > 0; + } + + // 新增分店接口 + @PostMapping("/add") + public boolean addBranch(@RequestBody Branch branch) { + // 设置默认值 + branch.setBranchId(null); + branch.setBranchStatus("营业中"); + branch.setBranchBoss(null); + branch.setIsDeleted(0); + branch.setCreatedAt(LocalDateTime.now()); + branch.setUpdatedAt(LocalDateTime.now()); + + // 执行插入操作 + return branchMapper.insert(branch) > 0; + } + + + @PutMapping("/{id}") + public boolean updateBranch( + @PathVariable Long id, + @RequestBody Branch branch) { + + // 验证分店是否存在 + Branch existingBranch = branchMapper.selectById(id); + if (existingBranch == null) { + return false; + } + + // 创建更新包装器 + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + updateWrapper.eq("branch_id", id); + + // 设置可更新字段 + if (branch.getBranchName() != null) { + updateWrapper.set("branch_name", branch.getBranchName()); + } + if (branch.getBranchAddress() != null) { + updateWrapper.set("branch_address", branch.getBranchAddress()); + } + if (branch.getBranchPhone() != null) { + updateWrapper.set("branch_phone", branch.getBranchPhone()); + } + if (branch.getBranchStart() != null) { + updateWrapper.set("branch_start", branch.getBranchStart()); + } + if (branch.getBranchEnd() != null) { + updateWrapper.set("branch_end", branch.getBranchEnd()); + } + + // 设置更新时间 + updateWrapper.set("updated_at", LocalDateTime.now()); + + // 执行更新 + return branchMapper.update(null, updateWrapper) > 0; + } + + /** + * 编辑负责人信息 + * @param branchId 分店ID + * @param request 包含更新信息的请求体 + * @return 更新结果 + */ + @PutMapping("/{branchId}/boss-info") + public boolean updateBossInfo( + @PathVariable Long branchId, + @RequestBody BossUpdateRequest request) { + + // 1. 获取分店信息 + Branch branch = branchMapper.selectById(branchId); + if (branch == null) { + return false; // 分店不存在 + } + + // 2. 检查分店是否有店长 + Long bossId = branch.getBranchBoss(); + if (bossId == null) { + return false; // 分店没有店长 + } + + // 3. 获取店长账号信息 + Account bossAccount = accountMapper.selectById(bossId); + if (bossAccount == null) { + return false; // 店长账号不存在 + } + + // 4. 创建更新包装器 + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + updateWrapper.eq("account_id", bossId); + + // 5. 更新字段(仅当请求中有提供值时更新) + if (request.getName() != null && !request.getName().isBlank()) { + updateWrapper.set("account_name", request.getName()); + } + if (request.getGender() != null && !request.getGender().isBlank()) { + updateWrapper.set("account_gender", request.getGender()); + } + if (request.getPhone() != null && !request.getPhone().isBlank()) { + updateWrapper.set("account_phone", request.getPhone()); + } + if (request.getSalary() != null) { + updateWrapper.set("salary", request.getSalary()); + } + + // 6. 执行更新 + return accountMapper.update(null, updateWrapper) > 0; + } + + + /** + * 根据分店ID获取负责人信息 + * @param branchId 分店ID + * @return 负责人Account对象 + */ + @GetMapping("/boss/{branchId}") + public Account getBossInfo(@PathVariable Long branchId) { + Branch branch = branchMapper.selectById(branchId); + if (branch != null && branch.getBranchBoss() != null) { + return accountMapper.selectById(branch.getBranchBoss()); + } else { + return null; + } + } + + /** + * 为分店设置店长 + * @param branchId 分店ID + * @param request 包含店长ID的请求体 + * @return 设置结果(true表示成功,false表示失败) + */ + @PutMapping("/{branchId}/boss") + public boolean setBranchBoss( + @PathVariable Long branchId, + @RequestBody BossRequest request) { + + // 1. 检查分店是否存在 + Branch branch = branchMapper.selectById(branchId); + if (branch == null) { + return false; // 分店不存在 + } + + // 2. 检查分店是否已有店长 + if (branch.getBranchBoss() != null) { + return false; // 分店已有店长 + } + + // 3. 检查店长账号是否存在 + Account account = accountMapper.selectById(request.getBossId()); + if (account == null) { + return false; // 店长账号不存在 + } + + // 4. 更新分店信息 + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + updateWrapper.eq("branch_id", branchId) + .set("branch_boss", request.getBossId()) + .set("updated_at", LocalDateTime.now()); + + return branchMapper.update(null, updateWrapper) > 0; + } + + + // 新增统计方法 + /** + * 根据分店ID统计每日订单数据 + * @param branchId 分店ID + * @return 每日统计结果 + */ + @GetMapping("/{branchId}/dailyStats") + public Map> getDailyStatsByBranch(@PathVariable Long branchId) { + // 查询该分店所有未删除的订单 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("branch_id", branchId) + .eq("is_deleted", 0); + List orders = orderMapper.selectList(queryWrapper); + + // 按日期分组并统计 + return orders.stream() + .collect(Collectors.groupingBy( + order -> order.getOrderTime().toLocalDate().atStartOfDay(), + Collectors.collectingAndThen( + Collectors.toList(), + list -> { + Map stats = new HashMap<>(); + stats.put("date", list.get(0).getOrderTime().toLocalDate()); + stats.put("orderCount", list.size()); + + // 计算总金额 + BigDecimal totalAmount = list.stream() + .map(Order::getOrderMoney) + .reduce(BigDecimal.ZERO, BigDecimal::add); + stats.put("totalAmount", totalAmount); + + return stats; + } + ) + )); + } + + /** + * 根据分店ID查询经纬度信息 + * @param id 分店ID + * @return 包含经纬度信息的Map + */ + @GetMapping("/location/{id}") + public Map getLocationById(@PathVariable Long id) { + Branch branch = branchMapper.selectById(id); + if (branch == null) { + return null; + } + + Map location = new HashMap<>(); + location.put("latitude", BigDecimal.valueOf(branch.getLatitude())); + location.put("longitude", BigDecimal.valueOf(branch.getLongitude())); + return location; + } + + // 内部类用于接收请求体 + static class BossRequest { + private Long bossId; + + // Getter和Setter + public Long getBossId() { + return bossId; + } + + public void setBossId(Long bossId) { + this.bossId = bossId; + } + } + + + // 内部类用于接收请求体 + static class BossUpdateRequest { + private String name; + private String gender; + private String phone; + private BigDecimal salary; + + // Getters and Setters + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getGender() { + return gender; + } + + public void setGender(String gender) { + this.gender = gender; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public BigDecimal getSalary() { + return salary; + } + + public void setSalary(BigDecimal salary) { + this.salary = salary; + } + } +} diff --git a/src/main/java/com/example/javatest/Controller/admin/DishController.java b/src/main/java/com/example/javatest/Controller/admin/DishController.java new file mode 100644 index 0000000..2881f76 --- /dev/null +++ b/src/main/java/com/example/javatest/Controller/admin/DishController.java @@ -0,0 +1,123 @@ +package com.example.javatest.Controller.admin; + + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; + +import com.example.javatest.Entity.admin.Dish; +import com.example.javatest.Mapper.admin.DishMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 菜品管理控制器 + * 提供菜品的增删改查、分类查询、价格区间筛选等RESTful接口 + */ +@RestController("adminDishController") +@RequestMapping("/admin/dishes") +public class DishController { + + @Autowired + @Qualifier("adminDishMapper") + private DishMapper dishMapper; + + /** + * 根据菜品分类分页查询菜品数据 + * @param category 分类名称 + * @param page 当前页码 + * @param size 每页数量 + * @return 分页结果 + */ + @GetMapping("/category/{category}") + public IPage getDishesByCategory( + @PathVariable String category, + @RequestParam(defaultValue = "1") int page, + @RequestParam(defaultValue = "10") int size + ) { + IPage dishPage = new Page<>(page, size); + return dishMapper.selectPage(dishPage, + new LambdaQueryWrapper() + .eq(Dish::getCategory, category) + .orderByDesc(Dish::getCreatedAt)); + } + + /** + * 新增菜品 + * @param dish 菜品对象(需包含name, price, imageUrl, category, status) + * @return 新增的菜品对象 + */ + @PostMapping + public Dish createDish(@RequestBody Dish dish) { + dish.setCreatedAt(LocalDateTime.now()); + dish.setUpdatedAt(LocalDateTime.now()); + dish.setDishId(null); + dishMapper.insert(dish); + return dish; + } + + /** + * 编辑菜品 + * @param id 菜品ID + * @param updatedDish 修改后的菜品数据 + * @return 修改结果(1表示成功) + */ + @PutMapping("/{id}") + public Integer updateDish(@PathVariable Long id, @RequestBody Dish updatedDish) { + updatedDish.setDishId(id); + updatedDish.setUpdatedAt(LocalDateTime.now()); + return dishMapper.updateById(updatedDish); + } + + /** + * 删除菜品 + * @param id 菜品ID + * @return 删除结果(1表示成功) + */ + @DeleteMapping("/{id}") + public Integer deleteDish(@PathVariable Long id) { + return dishMapper.deleteById(id); + } + + /** + * 多条件搜索菜品(支持 ID 精确查询和名称模糊查询) + * @param keyword 查询关键词(可为 ID 或名称) + * @param page 当前页码 + * @param size 每页数量 + * @return 分页结果 + */ + @GetMapping("/search") + public Page searchDishes( + @RequestParam String keyword, + @RequestParam(defaultValue = "1") int page, + @RequestParam(defaultValue = "10") int size + ) { + Page dishPage = new Page<>(page, size); + LambdaQueryWrapper query = new LambdaQueryWrapper<>(); + + try { + // 尝试将 keyword 转换为 Long 类型的 ID + Long id = Long.parseLong(keyword); + query.eq(Dish::getDishId, id); + } catch (NumberFormatException e) { + // 无法转换为 ID 时,执行名称模糊查询 + query.like(Dish::getDishName, keyword); + } + + return dishMapper.selectPage(dishPage, query); + } + + /** + * 获取所有菜品列表(带排序) + * @return 所有菜品列表 + */ + @GetMapping + public List getAllDishes() { + return dishMapper.selectList(new LambdaQueryWrapper() + .orderByDesc(Dish::getCreatedAt)); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Controller/branch/BranchController.java b/src/main/java/com/example/javatest/Controller/branch/BranchController.java new file mode 100644 index 0000000..83fe141 --- /dev/null +++ b/src/main/java/com/example/javatest/Controller/branch/BranchController.java @@ -0,0 +1,282 @@ +package com.example.javatest.Controller.branch; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; + +import com.example.javatest.Entity.branch.Branch; +import com.example.javatest.Service.branch.BranchService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 分店控制器 + */ +@RestController("branchBranchController") +@RequestMapping("/branch/branch") +public class BranchController { + + @Autowired + private BranchService branchService; + + /** + * 分页查询分店列表 + */ + @GetMapping("/page") + public ResponseEntity> getPageList( + @RequestParam(defaultValue = "1") Long current, + @RequestParam(defaultValue = "10") Long size, + @RequestParam(required = false) String keyword, + @RequestParam(required = false) String branchStatus, + @RequestParam(required = false) String branchBoss) { + + try { + Page pageResult = branchService.getPageList(current, size, keyword, branchStatus, branchBoss); + + Map result = new HashMap<>(); + result.put("code", 200); + result.put("message", "查询成功"); + result.put("data", pageResult); + + return ResponseEntity.ok(result); + } catch (Exception e) { + Map result = new HashMap<>(); + result.put("code", 500); + result.put("message", "查询失败:" + e.getMessage()); + return ResponseEntity.ok(result); + } + } + + /** + * 获取分店详情 + */ + @GetMapping("/{branchId}") + public ResponseEntity> getBranchDetail(@PathVariable Long branchId) { + try { + Branch branch = branchService.getBranchDetail(branchId); + + Map result = new HashMap<>(); + if (branch != null) { + result.put("code", 200); + result.put("message", "查询成功"); + result.put("data", branch); + } else { + result.put("code", 404); + result.put("message", "分店不存在"); + } + + return ResponseEntity.ok(result); + } catch (Exception e) { + Map result = new HashMap<>(); + result.put("code", 500); + result.put("message", "查询失败:" + e.getMessage()); + return ResponseEntity.ok(result); + } + } + + /** + * 保存分店基础信息 + */ + @PostMapping("/basic-info") + public ResponseEntity> saveBasicInfo(@RequestBody Branch branch) { + try { + boolean success = branchService.saveBasicInfo(branch); + + Map result = new HashMap<>(); + if (success) { + result.put("code", 200); + result.put("message", "保存成功"); + result.put("data", branch); + } else { + result.put("code", 400); + result.put("message", "保存失败"); + } + + return ResponseEntity.ok(result); + } catch (Exception e) { + Map result = new HashMap<>(); + result.put("code", 500); + result.put("message", "保存失败:" + e.getMessage()); + return ResponseEntity.ok(result); + } + } + + /** + * 更新分店营业信息 + */ + @PutMapping("/{branchId}/business-info") + public ResponseEntity> updateBusinessInfo( + @PathVariable Long branchId, + @RequestBody Map businessInfo) { + + try { + String branchStatus = businessInfo.get("branchStatus"); + String branchStart = businessInfo.get("branchStart"); + String branchEnd = businessInfo.get("branchEnd"); + + boolean success = branchService.updateBusinessInfo(branchId, branchStatus, branchStart, branchEnd); + + Map result = new HashMap<>(); + if (success) { + result.put("code", 200); + result.put("message", "更新成功"); + } else { + result.put("code", 400); + result.put("message", "更新失败"); + } + + return ResponseEntity.ok(result); + } catch (Exception e) { + Map result = new HashMap<>(); + result.put("code", 500); + result.put("message", "更新失败:" + e.getMessage()); + return ResponseEntity.ok(result); + } + } + + /** + * 根据负责人查询分店列表 + */ + @GetMapping("/by-boss/{branchBoss}") + public ResponseEntity> getBranchListByBoss(@PathVariable String branchBoss) { + try { + List branches = branchService.getBranchListByBoss(branchBoss); + + Map result = new HashMap<>(); + result.put("code", 200); + result.put("message", "查询成功"); + result.put("data", branches); + + return ResponseEntity.ok(result); + } catch (Exception e) { + Map result = new HashMap<>(); + result.put("code", 500); + result.put("message", "查询失败:" + e.getMessage()); + return ResponseEntity.ok(result); + } + } + + /** + * 根据状态查询分店列表 + */ + @GetMapping("/by-status/{branchStatus}") + public ResponseEntity> getBranchListByStatus(@PathVariable String branchStatus) { + try { + List branches = branchService.getBranchListByStatus(branchStatus); + + Map result = new HashMap<>(); + result.put("code", 200); + result.put("message", "查询成功"); + result.put("data", branches); + + return ResponseEntity.ok(result); + } catch (Exception e) { + Map result = new HashMap<>(); + result.put("code", 500); + result.put("message", "查询失败:" + e.getMessage()); + return ResponseEntity.ok(result); + } + } + + /** + * 删除分店 + */ + @DeleteMapping("/{branchId}") + public ResponseEntity> deleteBranch(@PathVariable Long branchId) { + try { + boolean success = branchService.deleteBranch(branchId); + + Map result = new HashMap<>(); + if (success) { + result.put("code", 200); + result.put("message", "删除成功"); + } else { + result.put("code", 400); + result.put("message", "删除失败"); + } + + return ResponseEntity.ok(result); + } catch (Exception e) { + Map result = new HashMap<>(); + result.put("code", 500); + result.put("message", "删除失败:" + e.getMessage()); + return ResponseEntity.ok(result); + } + } + + /** + * 批量删除分店 + */ + @DeleteMapping("/batch") + public ResponseEntity> deleteBatchBranch(@RequestBody List branchIds) { + try { + boolean success = branchService.deleteBatchBranch(branchIds); + + Map result = new HashMap<>(); + if (success) { + result.put("code", 200); + result.put("message", "批量删除成功"); + } else { + result.put("code", 400); + result.put("message", "批量删除失败"); + } + + return ResponseEntity.ok(result); + } catch (Exception e) { + Map result = new HashMap<>(); + result.put("code", 500); + result.put("message", "批量删除失败:" + e.getMessage()); + return ResponseEntity.ok(result); + } + } + + /** + * 检查分店名称是否存在 + */ + @GetMapping("/check-name") + public ResponseEntity> checkBranchNameExists( + @RequestParam String branchName, + @RequestParam(required = false) Long branchId) { + + try { + boolean exists = branchService.checkBranchNameExists(branchName, branchId); + + Map result = new HashMap<>(); + result.put("code", 200); + result.put("message", "检查完成"); + result.put("data", exists); + + return ResponseEntity.ok(result); + } catch (Exception e) { + Map result = new HashMap<>(); + result.put("code", 500); + result.put("message", "检查失败:" + e.getMessage()); + return ResponseEntity.ok(result); + } + } + + /** + * 获取所有分店(用于下拉选择等) + */ + @GetMapping("/all") + public ResponseEntity> getAllBranches() { + try { + List branches = branchService.list(); + + Map result = new HashMap<>(); + result.put("code", 200); + result.put("message", "查询成功"); + result.put("data", branches); + + return ResponseEntity.ok(result); + } catch (Exception e) { + Map result = new HashMap<>(); + result.put("code", 500); + result.put("message", "查询失败:" + e.getMessage()); + return ResponseEntity.ok(result); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Controller/branch/CommentController.java b/src/main/java/com/example/javatest/Controller/branch/CommentController.java new file mode 100644 index 0000000..bf11dd6 --- /dev/null +++ b/src/main/java/com/example/javatest/Controller/branch/CommentController.java @@ -0,0 +1,278 @@ +package com.example.javatest.Controller.branch; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.example.javatest.Entity.branch.Comment; +import com.example.javatest.Service.branch.CommentService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 评论控制器 + */ +@RestController("branchCommentController") +@RequestMapping("/branch/comments") +public class CommentController { + + @Autowired + private CommentService commentService; + + /** + * 分页查询评论列表 + */ + @GetMapping + public ResponseEntity> getCommentPage( + @RequestParam(defaultValue = "1") Integer page, + @RequestParam(defaultValue = "10") Integer size, + @RequestParam(required = false) String dishName, + @RequestParam(required = false) String rating, + @RequestParam(required = false) String commentType) { + + try { + IPage commentPage = commentService.getCommentPage(page, size, dishName, rating, commentType); + + Map response = new HashMap<>(); + Map data = new HashMap<>(); + data.put("records", commentPage.getRecords()); + data.put("total", commentPage.getTotal()); + data.put("current", commentPage.getCurrent()); + data.put("size", commentPage.getSize()); + data.put("pages", (int) Math.ceil((double) commentPage.getTotal() / commentPage.getSize())); + + response.put("code", 200); + response.put("msg", "success"); + response.put("data", data); + + return ResponseEntity.ok(response); + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 500); + errorResponse.put("msg", "查询失败:" + e.getMessage()); + return ResponseEntity.status(500).body(errorResponse); + } + } + + /** + * 获取评论详情,包括相关回复 + */ + @GetMapping("/{commentId}/detail") + public ResponseEntity> getCommentDetail(@PathVariable Long commentId) { + try { + Comment comment = commentService.getCommentDetail(commentId); + if (comment == null) { + Map response = new HashMap<>(); + response.put("code", 404); + response.put("msg", "评论不存在"); + return ResponseEntity.status(404).body(response); + } + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("msg", "success"); + response.put("data", comment); + + return ResponseEntity.ok(response); + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 500); + errorResponse.put("msg", "查询失败:" + e.getMessage()); + return ResponseEntity.status(500).body(errorResponse); + } + } + + /** + * 添加回复评论 + */ + @PostMapping("/reply") + public ResponseEntity addReplyComment(@RequestBody Comment comment) { + try { + // 设置当前用户账户ID,实际应用中应从登录用户中获取 + comment.setCommentAccountId(456L); + + boolean success = commentService.addReplyComment(comment); + Map response = new HashMap<>(); + + if (success) { + Map data = new HashMap<>(); + data.put("commentId", comment.getCommentId()); + + response.put("code", 200); + response.put("msg", "回复成功"); + response.put("data", data); + } else { + response.put("code", 500); + response.put("msg", "回复失败"); + } + + return ResponseEntity.ok(response); + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 500); + errorResponse.put("msg", "回复失败:" + e.getMessage()); + return ResponseEntity.status(500).body(errorResponse); + } + } + + /** + * 删除评论(逻辑删除) + */ + @DeleteMapping("/{commentId}") + public ResponseEntity> deleteComment(@PathVariable Long commentId) { + try { + boolean success = commentService.deleteComment(commentId); + Map response = new HashMap<>(); + + if (success) { + response.put("code", 200); + response.put("msg", "删除成功"); + response.put("data", null); + } else { + response.put("code", 500); + response.put("msg", "删除失败"); + } + + return ResponseEntity.ok(response); + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 500); + errorResponse.put("msg", "删除失败:" + e.getMessage()); + return ResponseEntity.status(500).body(errorResponse); + } + } + + /** + * 获取所有主评论及其回复列表 + */ + @GetMapping("/with-replies") + public ResponseEntity> getMainCommentsWithReplies( + @RequestParam(defaultValue = "1") Integer page, + @RequestParam(defaultValue = "10") Integer size, + @RequestParam(required = false) String dishName, + @RequestParam(required = false) String rating) { + + try { + IPage commentPage = commentService.getMainCommentsWithReplies(page, size, dishName, rating); + + Map response = new HashMap<>(); + Map data = new HashMap<>(); + data.put("records", commentPage.getRecords()); + data.put("total", commentPage.getTotal()); + data.put("current", commentPage.getCurrent()); + data.put("size", commentPage.getSize()); + data.put("pages", (int) Math.ceil((double) commentPage.getTotal() / commentPage.getSize())); + + response.put("code", 200); + response.put("msg", "success"); + response.put("data", data); + + return ResponseEntity.ok(response); + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 500); + errorResponse.put("msg", "查询失败:" + e.getMessage()); + return ResponseEntity.status(500).body(errorResponse); + } + } + + /** + * 根据店铺ID分页查询评论列表 + */ + @GetMapping("/branch/{branchId}") + public ResponseEntity> getCommentPageByBranchId( + @PathVariable Long branchId, + @RequestParam(defaultValue = "1") Integer page, + @RequestParam(defaultValue = "10") Integer size, + @RequestParam(required = false) String dishName, + @RequestParam(required = false) String rating, + @RequestParam(required = false) String commentType) { + + try { + IPage commentPage = commentService.getCommentPageByBranchId( + page, size, branchId, dishName, rating, commentType); + + Map response = new HashMap<>(); + Map data = new HashMap<>(); + data.put("records", commentPage.getRecords()); + data.put("total", commentPage.getTotal()); + data.put("current", commentPage.getCurrent()); + data.put("size", commentPage.getSize()); + data.put("pages", (int) Math.ceil((double) commentPage.getTotal() / commentPage.getSize())); + + response.put("code", 200); + response.put("msg", "success"); + response.put("data", data); + + return ResponseEntity.ok(response); + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 500); + errorResponse.put("msg", "查询失败:" + e.getMessage()); + return ResponseEntity.status(500).body(errorResponse); + } + } + + /** + * 根据店铺ID获取所有主评论及其回复列表 + */ + @GetMapping("/branch/{branchId}/with-replies") + public ResponseEntity> getMainCommentsWithRepliesByBranchId( + @PathVariable Long branchId, + @RequestParam(defaultValue = "1") Integer page, + @RequestParam(defaultValue = "10") Integer size, + @RequestParam(required = false) String dishName, + @RequestParam(required = false) String rating) { + + try { + IPage commentPage = commentService.getMainCommentsWithRepliesByBranchId( + page, size, branchId, dishName, rating); + + Map response = new HashMap<>(); + Map data = new HashMap<>(); + data.put("records", commentPage.getRecords()); + data.put("total", commentPage.getTotal()); + data.put("current", commentPage.getCurrent()); + data.put("size", commentPage.getSize()); + data.put("pages", (int) Math.ceil((double) commentPage.getTotal() / commentPage.getSize())); + + response.put("code", 200); + response.put("msg", "success"); + response.put("data", data); + + return ResponseEntity.ok(response); + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 500); + errorResponse.put("msg", "查询失败:" + e.getMessage()); + return ResponseEntity.status(500).body(errorResponse); + } + } + + /** + * 查询指定店铺和菜品的评论 + */ + @GetMapping("/branch/{branchId}/dish/{dishId}") + public ResponseEntity> getCommentsByDishIdAndBranchId( + @PathVariable Long branchId, + @PathVariable Long dishId) { + + try { + List comments = commentService.getCommentsByDishIdAndBranchId(dishId, branchId); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("msg", "success"); + response.put("data", comments); + + return ResponseEntity.ok(response); + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 500); + errorResponse.put("msg", "查询失败:" + e.getMessage()); + return ResponseEntity.status(500).body(errorResponse); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Controller/branch/DishController.java b/src/main/java/com/example/javatest/Controller/branch/DishController.java new file mode 100644 index 0000000..9f99b8c --- /dev/null +++ b/src/main/java/com/example/javatest/Controller/branch/DishController.java @@ -0,0 +1,254 @@ +package com.example.javatest.Controller.branch; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.example.javatest.Entity.branch.Dish; + +import com.example.javatest.Service.branch.DishService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 菜品控制器 + */ +@RestController("branchDishController") +@RequestMapping("/branch/dishes") +public class DishController { + + @Autowired + @Qualifier("branchDishService") + private DishService dishService; + + /** + * 分页查询菜品列表 + */ + @GetMapping + public ResponseEntity> getDishPage( + @RequestParam(defaultValue = "1") Integer page, + @RequestParam(defaultValue = "10") Integer size, + @RequestParam(required = false) String dishName, + @RequestParam(required = false) String category, + @RequestParam(required = false) String status) { + + try { + IPage dishPage = dishService.getDishPage(page, size, dishName, category, status); + + Map response = new HashMap<>(); + Map data = new HashMap<>(); + data.put("records", dishPage.getRecords()); + data.put("total", dishPage.getTotal()); + data.put("current", dishPage.getCurrent()); + data.put("size", dishPage.getSize()); + + response.put("code", 200); + response.put("message", "查询成功"); + response.put("data", data); + + return ResponseEntity.ok(response); + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 500); + errorResponse.put("message", "查询失败:" + e.getMessage()); + return ResponseEntity.status(500).body(errorResponse); + } + } + + /** + * 根据ID查询菜品详情 + */ + @GetMapping("/{id}") + public ResponseEntity> getDishById(@PathVariable Long id) { + try { + Dish dish = dishService.getDishById(id); + if (dish == null) { + Map response = new HashMap<>(); + response.put("code", 404); + response.put("message", "菜品不存在"); + return ResponseEntity.status(404).body(response); + } + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "查询成功"); + response.put("data", dish); + + return ResponseEntity.ok(response); + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 500); + errorResponse.put("message", "查询失败:" + e.getMessage()); + return ResponseEntity.status(500).body(errorResponse); + } + } + + /** + * 添加菜品 + */ + @PostMapping + public ResponseEntity> addDish(@RequestBody Dish dish) { + try { + boolean success = dishService.addDish(dish); + Map response = new HashMap<>(); + + if (success) { + response.put("code", 200); + response.put("message", "添加成功"); + response.put("data", dish); + } else { + response.put("code", 500); + response.put("message", "添加失败"); + } + + return ResponseEntity.ok(response); + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 500); + errorResponse.put("message", "添加失败:" + e.getMessage()); + return ResponseEntity.status(500).body(errorResponse); + } + } + + /** + * 更新菜品 + */ + @PutMapping("/{id}") + public ResponseEntity> updateDish(@PathVariable Long id, @RequestBody Dish dish) { + try { + dish.setDishId(id); + boolean success = dishService.updateDish(dish); + Map response = new HashMap<>(); + + if (success) { + response.put("code", 200); + response.put("message", "更新成功"); + response.put("data", dish); + } else { + response.put("code", 500); + response.put("message", "更新失败"); + } + + return ResponseEntity.ok(response); + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 500); + errorResponse.put("message", "更新失败:" + e.getMessage()); + return ResponseEntity.status(500).body(errorResponse); + } + } + + /** + * 删除菜品 + */ + @DeleteMapping("/{id}") + public ResponseEntity> deleteDish(@PathVariable Long id) { + try { + boolean success = dishService.deleteDish(id); + Map response = new HashMap<>(); + + if (success) { + response.put("code", 200); + response.put("message", "删除成功"); + } else { + response.put("code", 500); + response.put("message", "删除失败"); + } + + return ResponseEntity.ok(response); + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 500); + errorResponse.put("message", "删除失败:" + e.getMessage()); + return ResponseEntity.status(500).body(errorResponse); + } + } + + /** + * 更新菜品状态 + */ + @PatchMapping("/{id}/status") + public ResponseEntity> updateDishStatus( + @PathVariable Long id, + @RequestBody Map statusMap) { + try { + String status = statusMap.get("status"); + boolean success = dishService.updateDishStatus(id, status); + Map response = new HashMap<>(); + + if (success) { + response.put("code", 200); + response.put("message", "状态更新成功"); + } else { + response.put("code", 500); + response.put("message", "状态更新失败"); + } + + return ResponseEntity.ok(response); + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 500); + errorResponse.put("message", "状态更新失败:" + e.getMessage()); + return ResponseEntity.status(500).body(errorResponse); + } + } + + /** + * 根据店铺ID分页查询菜品列表 + */ + @GetMapping("/branch/{branchId}") + public ResponseEntity> getDishByBranchId( + @PathVariable Long branchId, + @RequestParam(defaultValue = "1") Integer page, + @RequestParam(defaultValue = "10") Integer size, + @RequestParam(required = false) String dishName, + @RequestParam(required = false) String category) { + + try { + IPage dishPage = dishService.getDishByBranchId(page, size, branchId, dishName, category); + + Map response = new HashMap<>(); + Map data = new HashMap<>(); + data.put("records", dishPage.getRecords()); + data.put("total", dishPage.getTotal()); + data.put("current", dishPage.getCurrent()); + data.put("size", dishPage.getSize()); + + response.put("code", 200); + response.put("message", "查询成功"); + response.put("data", data); + + return ResponseEntity.ok(response); + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 500); + errorResponse.put("message", "查询失败:" + e.getMessage()); + return ResponseEntity.status(500).body(errorResponse); + } + } + + /** + * 查询指定店铺的所有菜品 + */ + @GetMapping("/branch/{branchId}/all") + public ResponseEntity> getAllDishByBranchId(@PathVariable Long branchId) { + try { + List dishList = dishService.getDishListByBranchId(branchId); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "查询成功"); + response.put("data", dishList); + + return ResponseEntity.ok(response); + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 500); + errorResponse.put("message", "查询失败:" + e.getMessage()); + return ResponseEntity.status(500).body(errorResponse); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Controller/branch/MapController.java b/src/main/java/com/example/javatest/Controller/branch/MapController.java new file mode 100644 index 0000000..68a7114 --- /dev/null +++ b/src/main/java/com/example/javatest/Controller/branch/MapController.java @@ -0,0 +1,41 @@ +package com.example.javatest.Controller.branch; + +import com.example.javatest.Service.branch.MapService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +@RestController("branchMapController") +@RequestMapping("/branch/district") +public class MapController { + + @Autowired + private MapService mapService; + + + /** + * 对外暴露的查询接口 + * @param keywords 查询关键词 + * @return 将高德 API 返回的 JSON 数据直接返回给前端 + */ + @GetMapping + public Mono queryDistrict( + @RequestParam(value = "keywords", defaultValue = "中国") String keywords, + @RequestParam(value = "subdistrict", defaultValue = "1") int subdistrict) + { + + return mapService.getDistrictInfo(keywords, subdistrict) + .map(responseBody -> ResponseEntity.ok() + .contentType(MediaType.APPLICATION_JSON) + .body(responseBody)) + .defaultIfEmpty(ResponseEntity.status(HttpStatus.NOT_FOUND).build()); + } +} + + diff --git a/src/main/java/com/example/javatest/Controller/branch/OrderController.java b/src/main/java/com/example/javatest/Controller/branch/OrderController.java new file mode 100644 index 0000000..70ecc51 --- /dev/null +++ b/src/main/java/com/example/javatest/Controller/branch/OrderController.java @@ -0,0 +1,189 @@ +package com.example.javatest.Controller.branch; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.example.javatest.Entity.branch.Order; +import com.example.javatest.Entity.branch.OrderList; +import com.example.javatest.Service.branch.OrderService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 订单控制器 + */ +@RestController("branchOrderController") +@RequestMapping("/branch/orders") +public class OrderController { + + @Autowired + private OrderService orderService; + + /** + * 分页查询店铺订单列表 + */ + @GetMapping("/branch/{branchId}") + public ResponseEntity> getOrderPageByBranchId( + @PathVariable Long branchId, + @RequestParam(defaultValue = "1") Integer page, + @RequestParam(defaultValue = "10") Integer size, + @RequestParam(required = false) Integer orderStatus, + @RequestParam(required = false) String accountId) { + + try { + IPage orderPage = orderService.getOrderPageByBranchId( + page, size, branchId, orderStatus, accountId); + + Map response = new HashMap<>(); + Map data = new HashMap<>(); + data.put("records", orderPage.getRecords()); + data.put("total", orderPage.getTotal()); + data.put("current", orderPage.getCurrent()); + data.put("size", orderPage.getSize()); + data.put("pages", (int) Math.ceil((double) orderPage.getTotal() / orderPage.getSize())); + + response.put("code", 200); + response.put("message", "查询成功"); + response.put("data", data); + + return ResponseEntity.ok(response); + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 500); + errorResponse.put("message", "查询失败:" + e.getMessage()); + return ResponseEntity.status(500).body(errorResponse); + } + } + + /** + * 查询店铺所有订单 + */ + @GetMapping("/branch/{branchId}/all") + public ResponseEntity> getAllOrdersByBranchId(@PathVariable Long branchId) { + try { + List orders = orderService.getOrdersByBranchId(branchId); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "查询成功"); + response.put("data", orders); + + return ResponseEntity.ok(response); + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 500); + errorResponse.put("message", "查询失败:" + e.getMessage()); + return ResponseEntity.status(500).body(errorResponse); + } + } + + /** + * 根据订单ID查询订单详情 + */ + @GetMapping("/{orderId}") + public ResponseEntity> getOrderDetail(@PathVariable Long orderId) { + try { + Order order = orderService.getOrderDetailById(orderId); + if (order == null) { + Map notFoundResponse = new HashMap<>(); + notFoundResponse.put("code", 404); + notFoundResponse.put("message", "订单不存在"); + return ResponseEntity.status(404).body(notFoundResponse); + } + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "查询成功"); + response.put("data", order); + + return ResponseEntity.ok(response); + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 500); + errorResponse.put("message", "查询失败:" + e.getMessage()); + return ResponseEntity.status(500).body(errorResponse); + } + } + + /** + * 创建订单 + */ + @PostMapping + public ResponseEntity> createOrder(@RequestBody Order order) { + try { + // 获取订单明细 + List orderItems = order.getOrderLists(); + Long orderId = orderService.createOrder(order, orderItems); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "创建成功"); + response.put("data", orderId); + + return ResponseEntity.ok(response); + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 500); + errorResponse.put("message", "创建失败:" + e.getMessage()); + return ResponseEntity.status(500).body(errorResponse); + } + } + + /** + * 更新订单状态 + */ + @PatchMapping("/{orderId}/status") + public ResponseEntity> updateOrderStatus( + @PathVariable Long orderId, + @RequestBody Map statusMap) { + try { + Integer orderStatus = statusMap.get("orderStatus"); + boolean success = orderService.updateOrderStatus(orderId, orderStatus); + + Map response = new HashMap<>(); + if (success) { + response.put("code", 200); + response.put("message", "状态更新成功"); + } else { + response.put("code", 500); + response.put("message", "状态更新失败"); + } + + return ResponseEntity.ok(response); + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 500); + errorResponse.put("message", "状态更新失败:" + e.getMessage()); + return ResponseEntity.status(500).body(errorResponse); + } + } + + /** + * 取消订单 + */ + @DeleteMapping("/{orderId}") + public ResponseEntity> cancelOrder(@PathVariable Long orderId) { + try { + boolean success = orderService.cancelOrder(orderId); + + Map response = new HashMap<>(); + if (success) { + response.put("code", 200); + response.put("message", "订单取消成功"); + } else { + response.put("code", 500); + response.put("message", "订单取消失败"); + } + + return ResponseEntity.ok(response); + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 500); + errorResponse.put("message", "订单取消失败:" + e.getMessage()); + return ResponseEntity.status(500).body(errorResponse); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Controller/user/BranchController.java b/src/main/java/com/example/javatest/Controller/user/BranchController.java new file mode 100644 index 0000000..8991d88 --- /dev/null +++ b/src/main/java/com/example/javatest/Controller/user/BranchController.java @@ -0,0 +1,42 @@ +package com.example.javatest.Controller.user; + + +import com.example.javatest.Entity.user.Branch; +import com.example.javatest.Service.user.BranchService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController("userBranchController") +@RequestMapping("/user/branch") +public class BranchController { + + @Autowired + private BranchService branchService; + + @GetMapping("/list") + public List list() { + return branchService.list(); + } + + @PostMapping("/add") + public int add(@RequestBody Branch branch) { + return branchService.add(branch); + } + + @PutMapping("/update") + public int update(@RequestBody Branch branch) { + return branchService.update(branch); + } + + @DeleteMapping("/delete/{id}") + public int delete(@PathVariable Long id) { + return branchService.delete(id); + } + + @GetMapping("/{id}") + public Branch getById(@PathVariable Long id) { + return branchService.getById(id); + } +} diff --git a/src/main/java/com/example/javatest/Controller/user/CommentController.java b/src/main/java/com/example/javatest/Controller/user/CommentController.java new file mode 100644 index 0000000..bd4f5bc --- /dev/null +++ b/src/main/java/com/example/javatest/Controller/user/CommentController.java @@ -0,0 +1,40 @@ +package com.example.javatest.Controller.user; + + +import com.example.javatest.Entity.user.Comment; +import com.example.javatest.Service.user.CommentService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController("userCommentController") +@RequestMapping("/user/comments") +public class CommentController { + + @Autowired + private CommentService commentService; + + // 获取某个菜品的所有评论 + @GetMapping("/dish/{dishId}") + public List getCommentsByDishId(@PathVariable Long dishId) { + return commentService.getCommentsByDishId(dishId); + } + + // 获取某个用户的评论 + @GetMapping("/user/{accountId}") + public List getCommentsByAccountId(@PathVariable Long accountId) { + return commentService.getCommentsByAccountId(accountId); + } + + // 提交评论 + @PostMapping("/add") + public String addComment(@RequestBody Comment comment) { + boolean saved = commentService.saveComment(comment); + if (saved) { + return "评论提交成功"; + } else { + return "评论提交失败"; + } + } +} diff --git a/src/main/java/com/example/javatest/Controller/user/CustomerController.java b/src/main/java/com/example/javatest/Controller/user/CustomerController.java new file mode 100644 index 0000000..b407c13 --- /dev/null +++ b/src/main/java/com/example/javatest/Controller/user/CustomerController.java @@ -0,0 +1,44 @@ +package com.example.javatest.Controller.user; + + +import com.example.javatest.Entity.user.Customer; +import com.example.javatest.Service.user.CustomerService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/user/customers") +public class CustomerController { + + @Autowired + private CustomerService customerService; + + // 获取客户信息 + @GetMapping("/{accountId}") + public ResponseEntity getCustomer(@PathVariable Long accountId) { + Customer customer = customerService.getCustomerById(accountId); + return customer != null ? ResponseEntity.ok(customer) : ResponseEntity.notFound().build(); + } + + // 根据账户名获取客户信息 + @GetMapping("/name/{accountName}") + public ResponseEntity getCustomerByName(@PathVariable String accountName) { + Customer customer = customerService.getCustomerByName(accountName); + return customer != null ? ResponseEntity.ok(customer) : ResponseEntity.notFound().build(); + } + + // 创建/更新客户信息 + @PostMapping + public ResponseEntity saveCustomer(@RequestBody Customer customer) { + boolean saved = customerService.saveCustomer(customer); + return saved ? ResponseEntity.ok(customer) : ResponseEntity.badRequest().build(); + } + + // 删除客户 + @DeleteMapping("/{accountId}") + public ResponseEntity deleteCustomer(@PathVariable Long accountId) { + boolean deleted = customerService.deleteCustomer(accountId); + return deleted ? ResponseEntity.noContent().build() : ResponseEntity.notFound().build(); + } +} diff --git a/src/main/java/com/example/javatest/Controller/user/DishController.java b/src/main/java/com/example/javatest/Controller/user/DishController.java new file mode 100644 index 0000000..1ccbb69 --- /dev/null +++ b/src/main/java/com/example/javatest/Controller/user/DishController.java @@ -0,0 +1,59 @@ +package com.example.javatest.Controller.user; + +import com.example.javatest.Entity.user.Dish; +import com.example.javatest.Service.user.DishService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController("userDishController") +@RequestMapping("/user/dishes") +public class DishController { + + @Autowired + @Qualifier("userDishService") + private DishService dishService; + + // 根据分类精确查询菜品 + @GetMapping("/category") + public List getDishesByCategoryAndBranch( + @RequestParam String category, + @RequestParam Long branchId + ) { + return dishService.getDishesByCategoryAndBranch(category, branchId); + } + + @GetMapping("/search") + public List searchDishes(@RequestParam String keyword, @RequestParam Long branchId) { + return dishService.searchDishes(keyword, branchId); + } + + // 获取所有菜品分类 + @GetMapping("/categories") + public List getCategories() { + return dishService.getCategories(); + } + // 根据菜品ID查询菜品详情 + @GetMapping("/{id}") + public Dish getDishById(@PathVariable Integer id) { + return dishService.getDishById(id); + } + + @PostMapping("/batch") + public List getDishesByIds(@RequestBody List ids) { + return dishService.getDishesByIds(ids); + } + + @GetMapping("/hot/{branchId}") + public List getTop5PopularDishesByBranch(@PathVariable Long branchId) { + return dishService.getTop5PopularDishesByBranch(branchId); + } + + @GetMapping("/latest/{branchId}") + public List getLatestDishesByBranch(@PathVariable Long branchId) { + return dishService.getLatestDishesByBranch(branchId); + } + +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Controller/user/MapController.java b/src/main/java/com/example/javatest/Controller/user/MapController.java new file mode 100644 index 0000000..243c02c --- /dev/null +++ b/src/main/java/com/example/javatest/Controller/user/MapController.java @@ -0,0 +1,30 @@ +package com.example.javatest.Controller.user; + +import com.example.javatest.Service.user.MapService; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController("userMapController") +@RequestMapping("/user/map") +public class MapController { + + private final MapService mapService; + + public MapController(MapService mapService) { + this.mapService = mapService; + } + /** + * 接收经纬度并转换为地址的API接口 + * @param longitude 经度 + * @param latitude 纬度 + * @return 转换后的地址信息 + */ + @GetMapping("/convert") + public String convertCoordinate(@RequestParam("longitude") double longitude, + @RequestParam("latitude") double latitude) { + return mapService.convertCoordinateToAddress(longitude, latitude); + } + +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Controller/user/OrderController.java b/src/main/java/com/example/javatest/Controller/user/OrderController.java new file mode 100644 index 0000000..cb41533 --- /dev/null +++ b/src/main/java/com/example/javatest/Controller/user/OrderController.java @@ -0,0 +1,62 @@ +package com.example.javatest.Controller.user; + + +import com.example.javatest.Entity.user.Dish; +import com.example.javatest.Entity.user.Order; +import com.example.javatest.Entity.user.OrderList; +import com.example.javatest.Service.user.OrderService; +import lombok.Data; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +@RestController("userOrderController") +@RequestMapping("/user/orders") +public class OrderController { + + @Autowired + private OrderService orderService; + + @PostMapping("/create") + public ResponseEntity createOrder(@RequestBody OrderRequest request) { + if (request.getOrder() == null || request.getItems() == null || request.getItems().isEmpty()) { + return ResponseEntity.badRequest().body("订单或订单项不能为空"); + } + Order order = request.getOrder(); + orderService.createOrder(order, request.getItems()); + // orderId 已经自动生成并赋值到 order 对象了 + return ResponseEntity.ok(Map.of( + "message", "订单创建成功", + "orderId", order.getOrderId() + )); + } + @GetMapping("/{id}") + public Order getOrder(@PathVariable Long id) { + return orderService.getOrderById(id); + } + @GetMapping("/user/{userId}") + public List getOrdersByUserId(@PathVariable Long userId) { + return orderService.getOrdersByUserId(userId); // 使用包含订单项的版本 + } + + @GetMapping("/account/{accountId}") + public List getOrdersByAccount(@PathVariable Long accountId) { + return orderService.getOrdersByAccountId(accountId); + } + + + @GetMapping("/top-dishes/{accountId}") + public List getTopDishesByUser(@PathVariable Long accountId) { + return orderService.getTopDishesByUser(accountId); + } + + @Data + public static class OrderRequest { + private Order order; + private List items; + } +} + diff --git a/src/main/java/com/example/javatest/Entity/admin/Account.java b/src/main/java/com/example/javatest/Entity/admin/Account.java new file mode 100644 index 0000000..6226f33 --- /dev/null +++ b/src/main/java/com/example/javatest/Entity/admin/Account.java @@ -0,0 +1,104 @@ +package com.example.javatest.Entity.admin; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.ibatis.type.Alias; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 用户账户实体类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Alias("AdminAccount") +@TableName("account") +public class Account { + + /** + * 账户ID + */ + @TableId(value = "account_id", type = IdType.AUTO) + private Long accountId; + + /** + * 账户名称 + */ + @TableField("account_name") + private String accountName; + + /** + * 账户密码 + */ + @TableField("account_password") + private String accountPassword; + + /** + * 手机号码 + */ + @TableField("account_phone") + private String accountPhone; + + /** + * 账户类型:admin/manager/customer + */ + @TableField("account_type") + private String accountType; + + /** + * 头像图片URL + */ + @TableField("account_img") + private String accountImg; + + /** + * 性别:male/female + */ + @TableField("account_gender") + private String accountGender; + + /** + * 账户标签 + */ + @TableField("account_tag") + private String accountTag; + + /** + * 薪资(员工用) + */ + @TableField("salary") + private BigDecimal salary; + + /** + * 是否删除:0-未删除,1-已删除 + */ + @TableLogic + @TableField("is_deleted") + private Integer isDeleted; + + /** + * 删除时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField("deleted_at") + private LocalDateTime deletedAt; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Entity/admin/Branch.java b/src/main/java/com/example/javatest/Entity/admin/Branch.java new file mode 100644 index 0000000..a6e0f20 --- /dev/null +++ b/src/main/java/com/example/javatest/Entity/admin/Branch.java @@ -0,0 +1,115 @@ +package com.example.javatest.Entity.admin; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.ibatis.type.Alias; + +import java.time.LocalDateTime; + +/** + * 分店实体类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Alias("AdminBranch") +@TableName("branch") +public class Branch { + + /** + * 分店ID + */ + @TableId(value = "branch_id", type = IdType.AUTO) + private Long branchId; + + /** + * 分店名称 + */ + @TableField("branch_name") + private String branchName; + + /** + * 分店地址 + */ + @TableField("branch_address") + private String branchAddress; + + /** + * 分店电话 + */ + @TableField("branch_phone") + private String branchPhone; + + /** + * 营业开始时间,格式:HH:mm + */ + @TableField("branch_start") + private String branchStart; + + /** + * 营业结束时间,格式:HH:mm + */ + @TableField("branch_end") + private String branchEnd; + + /** + * 营业状态:open-营业中,closed-已停业 + */ + @TableField("branch_status") + private String branchStatus; + + /** + * 负责人ID,关联account表 + */ + @TableField("branch_boss") + private Long branchBoss; + + /** + * 所属省份 + */ + @TableField("province") + private String province; + + /** + * 纬度 + */ + @TableField("latitude") + private Double latitude; + + /** + * 经度 + */ + @TableField("longitude") + private Double longitude; + + /** + * 是否删除:0-未删除,1-已删除 + */ + @TableLogic + @TableField("is_deleted") + private Integer isDeleted; + + /** + * 删除时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField("deleted_at") + private LocalDateTime deletedAt; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Entity/admin/Dish.java b/src/main/java/com/example/javatest/Entity/admin/Dish.java new file mode 100644 index 0000000..bbee282 --- /dev/null +++ b/src/main/java/com/example/javatest/Entity/admin/Dish.java @@ -0,0 +1,110 @@ +package com.example.javatest.Entity.admin; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.ibatis.type.Alias; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 菜品实体类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Alias("AdminDish") +@TableName("dishes") +public class Dish { + + /** + * 菜品ID + */ + @TableId(value = "dish_id", type = IdType.AUTO) + private Long dishId; + + /** + * 菜品名称 + */ + @TableField("dish_name") + private String dishName; + + /** + * 菜品分类 + */ + @TableField("category") + private String category; + + /** + * 菜品价格 + */ + @TableField("price") + private BigDecimal price; + + /** + * 库存数量 + */ + @TableField("stock") + private Integer stock; + + /** + * 菜品状态:available-可售,unavailable-停售 + */ + @TableField("status") + private String status; + + /** + * 菜品描述 + */ + @TableField("description") + private String description; + + /** + * 菜品图片URL + */ + @TableField("image_url") + private String imageUrl; + + /** + * 累计销售数量 + */ + @TableField("sales") + private Integer sales; + + /** + * 菜品标签 + */ + @TableField("tag") + private String tag; + + /** + * 是否删除:0-未删除,1-已删除 + */ + @TableLogic + @TableField("is_deleted") + private Integer isDeleted; + + /** + * 删除时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField("deleted_at") + private LocalDateTime deletedAt; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Entity/admin/Order.java b/src/main/java/com/example/javatest/Entity/admin/Order.java new file mode 100644 index 0000000..97a1a8b --- /dev/null +++ b/src/main/java/com/example/javatest/Entity/admin/Order.java @@ -0,0 +1,93 @@ +package com.example.javatest.Entity.admin; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.ibatis.type.Alias; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 订单实体类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Alias("AdminOrder") +@TableName("`order`") +public class Order { + + /** + * 订单ID + */ + @TableId(value = "order_id", type = IdType.AUTO) + private Long orderId; + + /** + * 下单用户ID + */ + @TableField("account_id") + private Long accountId; + + /** + * 下单时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField("order_time") + private LocalDateTime orderTime; + + /** + * 分店ID + */ + @TableField("branch_id") + private Long branchId; + + /** + * 订单总金额 + */ + @TableField("order_money") + private BigDecimal orderMoney; + + /** + * 订单备注 + */ + @TableField("order_remarks") + private String orderRemarks; + + /** + * 订单状态:1-待处理,2-已完成,-1-已取消 + */ + @TableField("order_status") + private Integer orderStatus; + + /** + * 是否删除:0-未删除,1-已删除 + */ + @TableLogic + @TableField("is_deleted") + private Integer isDeleted; + + /** + * 删除时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField("deleted_at") + private LocalDateTime deletedAt; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Entity/branch/Branch.java b/src/main/java/com/example/javatest/Entity/branch/Branch.java new file mode 100644 index 0000000..0b11d6e --- /dev/null +++ b/src/main/java/com/example/javatest/Entity/branch/Branch.java @@ -0,0 +1,115 @@ +package com.example.javatest.Entity.branch; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.ibatis.type.Alias; + +import java.time.LocalDateTime; + +/** + * 分店实体类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Alias("BranchBranch") +@TableName("branch") +public class Branch { + + /** + * 分店ID + */ + @TableId(value = "branch_id", type = IdType.AUTO) + private Long branchId; + + /** + * 分店名称 + */ + @TableField("branch_name") + private String branchName; + + /** + * 分店地址 + */ + @TableField("branch_address") + private String branchAddress; + + /** + * 分店电话 + */ + @TableField("branch_phone") + private String branchPhone; + + /** + * 营业开始时间,格式:HH:mm + */ + @TableField("branch_start") + private String branchStart; + + /** + * 营业结束时间,格式:HH:mm + */ + @TableField("branch_end") + private String branchEnd; + + /** + * 营业状态:open-营业中,closed-已停业 + */ + @TableField("branch_status") + private String branchStatus; + + /** + * 负责人ID,关联account表 + */ + @TableField("branch_boss") + private Long branchBoss; + + /** + * 所属省份 + */ + @TableField("province") + private String province; + + /** + * 纬度 + */ + @TableField("latitude") + private Double latitude; + + /** + * 经度 + */ + @TableField("longitude") + private Double longitude; + + /** + * 是否删除:0-未删除,1-已删除 + */ + @TableLogic + @TableField("is_deleted") + private Integer isDeleted; + + /** + * 删除时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField("deleted_at") + private LocalDateTime deletedAt; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Entity/branch/Comment.java b/src/main/java/com/example/javatest/Entity/branch/Comment.java new file mode 100644 index 0000000..23a4ac6 --- /dev/null +++ b/src/main/java/com/example/javatest/Entity/branch/Comment.java @@ -0,0 +1,106 @@ +package com.example.javatest.Entity.branch; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.ibatis.type.Alias; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 评论实体类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Alias("BranchComment") +@TableName("comments") +public class Comment { + + /** + * 评论ID + */ + @TableId(value = "comment_id", type = IdType.AUTO) + private Long commentId; + + /** + * 评论内容 + */ + @TableField("comment_text") + private String commentText; + + /** + * 菜品ID + */ + @TableField("comment_dish_id") + private Long commentDishId; + + /** + * 评论用户ID + */ + @TableField("comment_account_id") + private Long commentAccountId; + + /** + * 评论评分 + */ + @TableField("comment_rating") + private Integer commentRating; + + /** + * 父评论ID,用于回复功能 + */ + @TableField("parent_comment_id") + private Long parentCommentId; + + /** + * 是否删除:0-未删除,1-已删除 + */ + @TableLogic + @TableField("is_deleted") + private Integer isDeleted; + + /** + * 删除时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField("deleted_at") + private LocalDateTime deletedAt; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; + + // 非数据库字段 + + /** + * 回复列表 + */ + @TableField(exist = false) + private List replies; + + /** + * 菜品名称 + */ + @TableField(exist = false) + private String dishName; + + /** + * 账户名称 + */ + @TableField(exist = false) + private String accountName; +} diff --git a/src/main/java/com/example/javatest/Entity/branch/Dish.java b/src/main/java/com/example/javatest/Entity/branch/Dish.java new file mode 100644 index 0000000..046e0c9 --- /dev/null +++ b/src/main/java/com/example/javatest/Entity/branch/Dish.java @@ -0,0 +1,110 @@ +package com.example.javatest.Entity.branch; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.ibatis.type.Alias; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 菜品实体类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Alias("BranchDish") +@TableName("dishes") +public class Dish { + + /** + * 菜品ID + */ + @TableId(value = "dish_id", type = IdType.AUTO) + private Long dishId; + + /** + * 菜品名称 + */ + @TableField("dish_name") + private String dishName; + + /** + * 菜品分类 + */ + @TableField("category") + private String category; + + /** + * 菜品价格 + */ + @TableField("price") + private BigDecimal price; + + /** + * 当前库存数量 + */ + @TableField("stock") + private Integer stock; + + /** + * 菜品状态:在售/停售 + */ + @TableField("status") + private String status; + + /** + * 菜品描述 + */ + @TableField("description") + private String description; + + /** + * 菜品图片URL + */ + @TableField("image_url") + private String imageUrl; + + /** + * 累计销售数量 + */ + @TableField("sales") + private Integer sales; + + /** + * 菜品标签 + */ + @TableField("tag") + private String tag; + + /** + * 是否删除:0-未删除,1-已删除 + */ + @TableLogic + @TableField("is_deleted") + private Integer isDeleted; + + /** + * 删除时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField("deleted_at") + private LocalDateTime deletedAt; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Entity/branch/Menu.java b/src/main/java/com/example/javatest/Entity/branch/Menu.java new file mode 100644 index 0000000..6cac60b --- /dev/null +++ b/src/main/java/com/example/javatest/Entity/branch/Menu.java @@ -0,0 +1,63 @@ +package com.example.javatest.Entity.branch; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.ibatis.type.Alias; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 菜单实体类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Alias("BranchMenu") +@TableName("menu") +public class Menu { + + /** + * 菜单ID + */ + @TableId(value = "menu_id", type = IdType.AUTO) + private Long menuId; + + /** + * 分店ID + */ + @TableField("branch_id") + private Long branchId; + + /** + * 菜品ID + */ + @TableField("dish_id") + private Long dishId; + + /** + * 该菜品在该分店是否可售 + */ + @TableField("is_available") + private Boolean isAvailable; + + /** + * 分店特定价格(如果为空则使用菜品表的价格) + */ + @TableField("branch_price") + private BigDecimal branchPrice; + + /** + * 创建时间 + */ + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 更新时间 + */ + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Entity/branch/Order.java b/src/main/java/com/example/javatest/Entity/branch/Order.java new file mode 100644 index 0000000..1cb0d64 --- /dev/null +++ b/src/main/java/com/example/javatest/Entity/branch/Order.java @@ -0,0 +1,106 @@ +package com.example.javatest.Entity.branch; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.ibatis.type.Alias; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +/** + * 订单实体类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Alias("BranchOrder") +@TableName("`order`") +public class Order { + + /** + * 订单ID + */ + @TableId(value = "order_id", type = IdType.AUTO) + private Long orderId; + + /** + * 账户ID + */ + @TableField("account_id") + private Long accountId; + + /** + * 下单时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField("order_time") + private LocalDateTime orderTime; + + /** + * 分店ID + */ + @TableField("branch_id") + private Long branchId; + + /** + * 订单金额 + */ + @TableField("order_money") + private BigDecimal orderMoney; + + /** + * 订单备注 + */ + @TableField("order_remarks") + private String orderRemarks; + + /** + * 订单状态:0-待处理,1-进行中,2-已完成,3-已取消 + */ + @TableField("order_status") + private Integer orderStatus; + + /** + * 是否删除:0-未删除,1-已删除 + */ + @TableLogic + @TableField("is_deleted") + private Integer isDeleted; + + /** + * 删除时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField("deleted_at") + private LocalDateTime deletedAt; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; + + /** + * 订单明细列表 + */ + @TableField(exist = false) + private List orderLists; + + /** + * 分店名称 + */ + @TableField(exist = false) + private String branchName; +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Entity/branch/OrderList.java b/src/main/java/com/example/javatest/Entity/branch/OrderList.java new file mode 100644 index 0000000..f8a051e --- /dev/null +++ b/src/main/java/com/example/javatest/Entity/branch/OrderList.java @@ -0,0 +1,72 @@ +package com.example.javatest.Entity.branch; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.ibatis.type.Alias; + +import java.time.LocalDateTime; + +/** + * 订单明细实体类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Alias("BranchOrderList") +@TableName("order_list") +public class OrderList { + + /** + * 订单明细ID + */ + @TableId(value = "order_list_id", type = IdType.AUTO) + private Long orderListId; + + /** + * 订单ID + */ + @TableField("order_id") + private Long orderId; + + /** + * 菜品ID + */ + @TableField("dish_id") + private Long dishId; + + /** + * 数量 + */ + @TableField("number") + private Integer number; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; + + // 非数据库字段 + /** + * 菜品名称 + */ + @TableField(exist = false) + private String dishName; + + /** + * 价格 + */ + @TableField(exist = false) + private Double price; +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Entity/user/Branch.java b/src/main/java/com/example/javatest/Entity/user/Branch.java new file mode 100644 index 0000000..b84dcdd --- /dev/null +++ b/src/main/java/com/example/javatest/Entity/user/Branch.java @@ -0,0 +1,113 @@ +package com.example.javatest.Entity.user; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.ibatis.type.Alias; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 分店实体类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Alias("UserBranch") +@TableName("branch") +public class Branch { + /** + * 分店ID + */ + @TableId(value = "branch_id", type = IdType.AUTO) + private Long branchId; + + /** + * 分店名称 + */ + @TableField("branch_name") + private String branchName; + + /** + * 分店地址 + */ + @TableField("branch_address") + private String branchAddress; + + /** + * 分店电话 + */ + @TableField("branch_phone") + private String branchPhone; + + /** + * 营业开始时间,格式:HH:mm + */ + @TableField("branch_start") + private String branchStart; + + /** + * 营业结束时间,格式:HH:mm + */ + @TableField("branch_end") + private String branchEnd; + + /** + * 分店状态:营业中/休息中 + */ + @TableField("branch_status") + private String branchStatus; /** + * 分店负责人ID,关联account表 + */ + @TableField("branch_boss") + private Long branchBoss; + + /** + * 所属省份 + */ + @TableField("province") + private String province; + + /** + * 纬度 + */ + @TableField("latitude") + private Double latitude; + + /** + * 经度 + */ + @TableField("longitude") + private Double longitude; + + /** + * 是否删除:0-未删除,1-已删除 + */ + @TableLogic + @TableField("is_deleted") + private Integer isDeleted; + + /** + * 删除时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField("deleted_at") + private LocalDateTime deletedAt; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Entity/user/Comment.java b/src/main/java/com/example/javatest/Entity/user/Comment.java new file mode 100644 index 0000000..6905999 --- /dev/null +++ b/src/main/java/com/example/javatest/Entity/user/Comment.java @@ -0,0 +1,85 @@ +package com.example.javatest.Entity.user; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.ibatis.type.Alias; + +import java.time.LocalDateTime; + +/** + * 评论实体类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Alias("UserComment") +@TableName("comments") +public class Comment { + + /** + * 评论ID + */ + @TableId(value = "comment_id", type = IdType.AUTO) + private Long commentId; + + /** + * 评论内容 + */ + @TableField("comment_text") + private String commentText; + + /** + * 评论的菜品ID + */ + @TableField("comment_dish_id") + private Long commentDishId; + + /** + * 评论用户ID + */ + @TableField("comment_account_id") + private Long commentAccountId; + + /** + * 评分:1-5分 + */ + @TableField("comment_rating") + private Integer commentRating; + + /** + * 父评论ID,用于回复功能 + */ + @TableField("parent_comment_id") + private Long parentCommentId; + + /** + * 是否删除:0-未删除,1-已删除 + */ + @TableLogic + @TableField("is_deleted") + private Integer isDeleted; + + /** + * 删除时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField("deleted_at") + private LocalDateTime deletedAt; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; +} diff --git a/src/main/java/com/example/javatest/Entity/user/Customer.java b/src/main/java/com/example/javatest/Entity/user/Customer.java new file mode 100644 index 0000000..ebcd1f8 --- /dev/null +++ b/src/main/java/com/example/javatest/Entity/user/Customer.java @@ -0,0 +1,104 @@ +package com.example.javatest.Entity.user; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.ibatis.type.Alias; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 用户账户实体类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Alias("UserCustomer") +@TableName("account") +public class Customer { + + /** + * 账户ID + */ + @TableId(value = "account_id", type = IdType.AUTO) + private Long accountId; + + /** + * 账户名称 + */ + @TableField("account_name") + private String accountName; + + /** + * 账户密码 + */ + @TableField("account_password") + private String accountPassword; + + /** + * 手机号码 + */ + @TableField("account_phone") + private String accountPhone; + + /** + * 账户类型:admin/manager/customer + */ + @TableField("account_type") + private String accountType; + + /** + * 头像图片URL + */ + @TableField("account_img") + private String accountImg; + + /** + * 性别:male/female + */ + @TableField("account_gender") + private String accountGender; + + /** + * 账户标签 + */ + @TableField("account_tag") + private String accountTag; + + /** + * 薪资(员工用) + */ + @TableField("salary") + private BigDecimal salary; + + /** + * 是否删除:0-未删除,1-已删除 + */ + @TableLogic + @TableField("is_deleted") + private Integer isDeleted; + + /** + * 删除时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField("deleted_at") + private LocalDateTime deletedAt; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; +} diff --git a/src/main/java/com/example/javatest/Entity/user/Dish.java b/src/main/java/com/example/javatest/Entity/user/Dish.java new file mode 100644 index 0000000..35f0bd9 --- /dev/null +++ b/src/main/java/com/example/javatest/Entity/user/Dish.java @@ -0,0 +1,110 @@ +package com.example.javatest.Entity.user; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.ibatis.type.Alias; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 菜品实体类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Alias("UserDish") +@TableName("dishes") +public class Dish { + + /** + * 菜品ID + */ + @TableId(value = "dish_id", type = IdType.AUTO) + private Integer dishId; + + /** + * 菜品名称 + */ + @TableField("dish_name") + private String dishName; + + /** + * 菜品分类 + */ + @TableField("category") + private String category; + + /** + * 菜品价格 + */ + @TableField("price") + private BigDecimal price; + + /** + * 当前库存数量 + */ + @TableField("stock") + private Integer stock; + + /** + * 菜品状态:在售/停售 + */ + @TableField("status") + private String status; + + /** + * 菜品描述 + */ + @TableField("description") + private String description; + + /** + * 菜品图片URL + */ + @TableField("image_url") + private String imageUrl; + + /** + * 累计销售数量 + */ + @TableField("sales") + private Integer sales; + + /** + * 菜品标签 + */ + @TableField("tag") + private String tag; + + /** + * 是否删除:0-未删除,1-已删除 + */ + @TableLogic + @TableField("is_deleted") + private Integer isDeleted; + + /** + * 删除时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField("deleted_at") + private LocalDateTime deletedAt; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Entity/user/Order.java b/src/main/java/com/example/javatest/Entity/user/Order.java new file mode 100644 index 0000000..62b005b --- /dev/null +++ b/src/main/java/com/example/javatest/Entity/user/Order.java @@ -0,0 +1,93 @@ +package com.example.javatest.Entity.user; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.ibatis.type.Alias; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 订单实体类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Alias("UserOrder") +@TableName("`order`") +public class Order { + + /** + * 订单ID + */ + @TableId(value = "order_id", type = IdType.AUTO) + private Long orderId; + + /** + * 下单用户ID + */ + @TableField("account_id") + private Long accountId; + + /** + * 下单时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField("order_time") + private LocalDateTime orderTime; + + /** + * 分店ID + */ + @TableField("branch_id") + private Long branchId; + + /** + * 订单总金额 + */ + @TableField("order_money") + private BigDecimal orderMoney; + + /** + * 订单备注 + */ + @TableField("order_remarks") + private String orderRemarks; + + /** + * 订单状态:1-待处理,2-已完成,-1-已取消 + */ + @TableField("order_status") + private Integer orderStatus; + + /** + * 是否删除:0-未删除,1-已删除 + */ + @TableLogic + @TableField("is_deleted") + private Integer isDeleted; + + /** + * 删除时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField("deleted_at") + private LocalDateTime deletedAt; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Entity/user/OrderList.java b/src/main/java/com/example/javatest/Entity/user/OrderList.java new file mode 100644 index 0000000..c069a82 --- /dev/null +++ b/src/main/java/com/example/javatest/Entity/user/OrderList.java @@ -0,0 +1,59 @@ +package com.example.javatest.Entity.user; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.ibatis.type.Alias; + +import java.time.LocalDateTime; + +/** + * 订单明细实体类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Alias("UserOrderList") +@TableName("order_list") +public class OrderList { + /** + * 订单明细ID + */ + @TableId(value = "order_list_id", type = IdType.AUTO) + private Long orderListId; + + /** + * 订单ID + */ + @TableField("order_id") + private Long orderId; + + /** + * 菜品ID + */ + @TableField("dish_id") + private Long dishId; + + /** + * 菜品数量 + */ + @TableField("number") + private Integer number; + + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/JavaTestApplication.java b/src/main/java/com/example/javatest/JavaTestApplication.java new file mode 100644 index 0000000..e9da99c --- /dev/null +++ b/src/main/java/com/example/javatest/JavaTestApplication.java @@ -0,0 +1,15 @@ +package com.example.javatest; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@MapperScan("com.example.javatest.Mapper") +public class JavaTestApplication { + + public static void main(String[] args) { + SpringApplication.run(JavaTestApplication.class, args); + } + +} diff --git a/src/main/java/com/example/javatest/Mapper/admin/AccountMapper.java b/src/main/java/com/example/javatest/Mapper/admin/AccountMapper.java new file mode 100644 index 0000000..c42229f --- /dev/null +++ b/src/main/java/com/example/javatest/Mapper/admin/AccountMapper.java @@ -0,0 +1,9 @@ +package com.example.javatest.Mapper.admin; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.javatest.Entity.admin.Account; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface AccountMapper extends BaseMapper { +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Mapper/admin/BranchMapper.java b/src/main/java/com/example/javatest/Mapper/admin/BranchMapper.java new file mode 100644 index 0000000..8433a93 --- /dev/null +++ b/src/main/java/com/example/javatest/Mapper/admin/BranchMapper.java @@ -0,0 +1,10 @@ +package com.example.javatest.Mapper.admin; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.javatest.Entity.admin.Branch; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Component; +@Mapper +@Component("adminBranchMapper") +public interface BranchMapper extends BaseMapper { +} diff --git a/src/main/java/com/example/javatest/Mapper/admin/DishMapper.java b/src/main/java/com/example/javatest/Mapper/admin/DishMapper.java new file mode 100644 index 0000000..436227a --- /dev/null +++ b/src/main/java/com/example/javatest/Mapper/admin/DishMapper.java @@ -0,0 +1,11 @@ +package com.example.javatest.Mapper.admin; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.javatest.Entity.admin.Dish; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Component; + +@Mapper +@Component("adminDishMapper") +public interface DishMapper extends BaseMapper { +} diff --git a/src/main/java/com/example/javatest/Mapper/admin/OrderMapper.java b/src/main/java/com/example/javatest/Mapper/admin/OrderMapper.java new file mode 100644 index 0000000..28d1fa6 --- /dev/null +++ b/src/main/java/com/example/javatest/Mapper/admin/OrderMapper.java @@ -0,0 +1,12 @@ +package com.example.javatest.Mapper.admin; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.javatest.Entity.admin.Order; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Component; + + +@Mapper +@Component("adminOrderMapper") +public interface OrderMapper extends BaseMapper { +} diff --git a/src/main/java/com/example/javatest/Mapper/branch/BranchMapper.java b/src/main/java/com/example/javatest/Mapper/branch/BranchMapper.java new file mode 100644 index 0000000..606c471 --- /dev/null +++ b/src/main/java/com/example/javatest/Mapper/branch/BranchMapper.java @@ -0,0 +1,60 @@ +package com.example.javatest.Mapper.branch; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.javatest.Entity.branch.Branch; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + +/** + * 分店数据访问层 + */ +@Mapper +@Component("branchBranchMapper") +public interface BranchMapper extends BaseMapper { + + /** + * 根据负责人ID查询分店列表 + * @param branchBoss 分店负责人ID + * @return 分店列表 + */ + List selectByBranchBoss(@Param("branchBoss") String branchBoss); + + /** + * 根据分店状态查询分店列表 + * @param branchStatus 分店状态 + * @return 分店列表 + */ + List selectByBranchStatus(@Param("branchStatus") String branchStatus); + + /** + * 模糊查询分店(根据分店名称或地址) + * @param keyword 关键词 + * @return 分店列表 + */ + List selectByKeyword(@Param("keyword") String keyword); + + /** + * 复杂查询:分页查询分店列表(支持多条件) + * @param keyword 关键词 + * @param branchStatus 分店状态 + * @param branchBoss 负责人ID + * @return 分店列表 + */ + List selectPageWithConditions(@Param("keyword") String keyword, @Param("branchStatus") String branchStatus, @Param("branchBoss") String branchBoss); + + /** + * 统计查询:根据状态统计分店数量 + * @return 统计结果 + */ + List> countByStatus(); + + /** + * 统计查询:根据负责人统计分店数量 + * @return 统计结果 + */ + List> countByBoss(); +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Mapper/branch/CommentMapper.java b/src/main/java/com/example/javatest/Mapper/branch/CommentMapper.java new file mode 100644 index 0000000..04dade4 --- /dev/null +++ b/src/main/java/com/example/javatest/Mapper/branch/CommentMapper.java @@ -0,0 +1,83 @@ +package com.example.javatest.Mapper.branch; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.example.javatest.Entity.branch.Comment; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 评论Mapper接口 + */ +@Mapper +@Component("branchCommentMapper") +public interface CommentMapper extends BaseMapper { + + /** + * 分页查询评论列表 + * @param page 分页对象 + * @param dishName 菜品名称(可选) + * @param rating 评分(可选) + * @param commentType 评论类型,main表示主评论,reply表示回复评论(可选) + * @return 分页结果 + */ + IPage selectCommentPage(Page page, + @Param("dishName") String dishName, + @Param("rating") String rating, + @Param("commentType") String commentType); + + /** + * 查询评论详情,包括回复 + * @param commentId 评论ID + * @return 评论详情 + */ + Comment selectCommentDetail(@Param("commentId") Long commentId); + + /** + * 查询评论的回复列表 + * @param commentId 主评论ID + * @return 回复列表 + */ + List selectCommentReplies(@Param("commentId") Long commentId); + + /** + * 根据店铺ID分页查询评论列表 + * @param page 分页对象 + * @param branchId 店铺ID + * @param dishName 菜品名称(可选) + * @param rating 评分(可选) + * @param commentType 评论类型,main表示主评论,reply表示回复评论(可选) + * @return 分页结果 + */ + IPage selectCommentPageByBranchId(Page page, + @Param("branchId") Long branchId, + @Param("dishName") String dishName, + @Param("rating") String rating, + @Param("commentType") String commentType); + + /** + * 根据店铺ID查询所有主评论 + * @param page 分页对象 + * @param branchId 店铺ID + * @param dishName 菜品名称(可选) + * @param rating 评分(可选) + * @return 分页结果 + */ + IPage selectMainCommentsByBranchId(Page page, + @Param("branchId") Long branchId, + @Param("dishName") String dishName, + @Param("rating") String rating); + + /** + * 根据店铺ID和菜品ID查询评论 + * @param dishId 菜品ID + * @param branchId 店铺ID + * @return 评论列表 + */ + List selectCommentsByDishIdAndBranchId(@Param("dishId") Long dishId, + @Param("branchId") Long branchId); +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Mapper/branch/DishMapper.java b/src/main/java/com/example/javatest/Mapper/branch/DishMapper.java new file mode 100644 index 0000000..27e15f9 --- /dev/null +++ b/src/main/java/com/example/javatest/Mapper/branch/DishMapper.java @@ -0,0 +1,52 @@ +package com.example.javatest.Mapper.branch; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.example.javatest.Entity.branch.Dish; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 菜品Mapper接口 + */ +@Mapper +@Component("branchDishMapper") +public interface DishMapper extends BaseMapper { + + /** + * 分页查询菜品列表 + * @param page 分页对象 + * @param dishName 菜品名称(可选) + * @param category 分类(可选) + * @param status 状态(可选) + * @return 分页结果 + */ + IPage selectDishPage(Page page, + @Param("dishName") String dishName, + @Param("category") String category, + @Param("status") String status); + + /** + * 根据店铺ID查询菜品列表 + * @param page 分页对象 + * @param branchId 店铺ID + * @param dishName 菜品名称(可选) + * @param category 分类(可选) + * @return 分页结果 + */ + IPage selectDishByBranchId(Page page, + @Param("branchId") Long branchId, + @Param("dishName") String dishName, + @Param("category") String category); + + /** + * 根据店铺ID查询所有菜品 + * @param branchId 店铺ID + * @return 菜品列表 + */ + List selectDishListByBranchId(@Param("branchId") Long branchId); +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Mapper/branch/OrderListMapper.java b/src/main/java/com/example/javatest/Mapper/branch/OrderListMapper.java new file mode 100644 index 0000000..7d6afb9 --- /dev/null +++ b/src/main/java/com/example/javatest/Mapper/branch/OrderListMapper.java @@ -0,0 +1,31 @@ +package com.example.javatest.Mapper.branch; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.javatest.Entity.branch.OrderList; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 订单明细Mapper接口 + */ +@Mapper +@Component("branchOrderListMapper") +public interface OrderListMapper extends BaseMapper { + + /** + * 根据订单ID查询订单明细列表 + * @param orderId 订单ID + * @return 订单明细列表 + */ + List selectOrderItemsByOrderId(@Param("orderId") Long orderId); + + /** + * 批量插入订单明细 + * @param orderItems 订单明细列表 + * @return 影响行数 + */ + int batchInsert(@Param("list") List orderItems); +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Mapper/branch/OrderMapper.java b/src/main/java/com/example/javatest/Mapper/branch/OrderMapper.java new file mode 100644 index 0000000..d9fad41 --- /dev/null +++ b/src/main/java/com/example/javatest/Mapper/branch/OrderMapper.java @@ -0,0 +1,46 @@ +package com.example.javatest.Mapper.branch; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.example.javatest.Entity.branch.Order; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 订单Mapper接口 + */ +@Mapper +@Component("branchOrderMapper") +public interface OrderMapper extends BaseMapper { + + /** + * 分页查询店铺订单列表 + * @param page 分页对象 + * @param branchId 店铺ID + * @param orderStatus 订单状态(可选) + * @param accountId 账户ID(可选) + * @return 分页结果 + */ + IPage selectOrderPageByBranchId(Page page, + @Param("branchId") Long branchId, + @Param("orderStatus") Integer orderStatus, + @Param("accountId") String accountId); + + /** + * 查询店铺所有订单 + * @param branchId 店铺ID + * @return 订单列表 + */ + List selectOrdersByBranchId(@Param("branchId") Long branchId); + + /** + * 根据订单ID查询订单详情,包含订单明细 + * @param orderId 订单ID + * @return 订单详情 + */ + Order selectOrderDetailById(@Param("orderId") Long orderId); +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Mapper/user/BranchMapper.java b/src/main/java/com/example/javatest/Mapper/user/BranchMapper.java new file mode 100644 index 0000000..9315038 --- /dev/null +++ b/src/main/java/com/example/javatest/Mapper/user/BranchMapper.java @@ -0,0 +1,12 @@ +package com.example.javatest.Mapper.user; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import com.example.javatest.Entity.user.Branch; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Component; + +@Mapper +@Component("userBranchMapper") +public interface BranchMapper extends BaseMapper { +} diff --git a/src/main/java/com/example/javatest/Mapper/user/CommentMapper.java b/src/main/java/com/example/javatest/Mapper/user/CommentMapper.java new file mode 100644 index 0000000..34637aa --- /dev/null +++ b/src/main/java/com/example/javatest/Mapper/user/CommentMapper.java @@ -0,0 +1,23 @@ +package com.example.javatest.Mapper.user; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import com.example.javatest.Entity.user.Comment; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Mapper +@Component("userCommentMapper") +public interface CommentMapper extends BaseMapper { + + @Select("SELECT * FROM comments WHERE comment_dish_id = #{dishId}") + List selectByDishId(@Param("dishId") Long dishId); + + // 获取某个用户的评论 + @Select("SELECT * FROM comments WHERE comment_account_id = #{accountId}") + List selectByAccountId(@Param("accountId") Long accountId); +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Mapper/user/CustomerMapper.java b/src/main/java/com/example/javatest/Mapper/user/CustomerMapper.java new file mode 100644 index 0000000..6e1cda3 --- /dev/null +++ b/src/main/java/com/example/javatest/Mapper/user/CustomerMapper.java @@ -0,0 +1,9 @@ +package com.example.javatest.Mapper.user; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.javatest.Entity.user.Customer; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface CustomerMapper extends BaseMapper { +} diff --git a/src/main/java/com/example/javatest/Mapper/user/DishMapper.java b/src/main/java/com/example/javatest/Mapper/user/DishMapper.java new file mode 100644 index 0000000..11e79aa --- /dev/null +++ b/src/main/java/com/example/javatest/Mapper/user/DishMapper.java @@ -0,0 +1,75 @@ +package com.example.javatest.Mapper.user; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.javatest.Entity.user.Dish; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Mapper +@Component("userDishMapper") +public interface DishMapper extends BaseMapper { + @Select(""" + SELECT d.* FROM dishes d + JOIN menu m ON d.dish_id = m.dish_id + WHERE d.category = #{category} + AND m.branch_id = #{branchId} + AND d.is_deleted = 0 + """) + List selectByCategoryAndBranch(@Param("category") String category, @Param("branchId") Long branchId); + @Select(""" + SELECT d.* + FROM dishes d + JOIN menu m ON d.dish_id = m.dish_id + WHERE m.branch_id = #{branchId} + AND ( + d.dish_name LIKE CONCAT('%', #{keyword}, '%') + OR d.category LIKE CONCAT('%', #{keyword}, '%') + OR d.tag LIKE CONCAT('%', #{keyword}, '%') + ) + """) + List searchByKeyword(@Param("keyword") String keyword, @Param("branchId") Long branchId); + + // 获取所有菜品分类 + @Select("SELECT DISTINCT category FROM dishes WHERE is_deleted = 0") + List selectCategories(); + + // 根据菜品ID查询菜品详情 + @Select("SELECT * FROM dishes WHERE dish_id = #{id} AND is_deleted = 0") + Dish selectById(@Param("id") Integer id); + + // 查询某个分店历史销量最多的前5个菜品 + @Select(""" + SELECT + d.dish_id AS dishId, + d.dish_name AS dishName, + d.price, + d.image_url AS imageUrl + FROM order_list ol + JOIN `order` o ON ol.order_id = o.order_id + JOIN dishes d ON ol.dish_id = d.dish_id + JOIN menu m ON d.dish_id = m.dish_id + WHERE o.is_deleted = 0 + AND d.is_deleted = 0 + AND m.branch_id = #{branchId} + GROUP BY d.dish_id + ORDER BY SUM(ol.number) DESC + LIMIT 5 + """) + List selectTop5PopularDishesByBranch(@Param("branchId") Long branchId); + + @Select(""" + SELECT d.* + FROM dishes d + JOIN menu m ON d.dish_id = m.dish_id + WHERE d.is_deleted = 0 + AND m.branch_id = #{branchId} + ORDER BY d.updated_at DESC + LIMIT 5 + """) + List selectLatestDishesByBranch(@Param("branchId") Long branchId); + +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Mapper/user/OrderListMapper.java b/src/main/java/com/example/javatest/Mapper/user/OrderListMapper.java new file mode 100644 index 0000000..5b8bd29 --- /dev/null +++ b/src/main/java/com/example/javatest/Mapper/user/OrderListMapper.java @@ -0,0 +1,36 @@ +package com.example.javatest.Mapper.user; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import com.example.javatest.Entity.user.Dish; +import com.example.javatest.Entity.user.OrderList; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Mapper +@Component("userOrderListMapper") +public interface OrderListMapper extends BaseMapper { + @Select("SELECT * FROM order_list WHERE order_id = #{orderId}") + List selectByOrderId(@Param("orderId") Long orderId); + + @Select(""" + SELECT + d.dish_id AS dishId, + d.dish_name AS dishName, + d.price, + d.image_url AS imageUrl + FROM order_list ol + JOIN `order` o ON ol.order_id = o.order_id + JOIN dishes d ON ol.dish_id = d.dish_id + WHERE o.account_id = #{accountId} + AND o.is_deleted = 0 + GROUP BY d.dish_id + ORDER BY SUM(ol.number) DESC + LIMIT 5 +""") + List selectTopDishesByUser(@Param("accountId") Long accountId); +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Mapper/user/OrderMapper.java b/src/main/java/com/example/javatest/Mapper/user/OrderMapper.java new file mode 100644 index 0000000..dcb8316 --- /dev/null +++ b/src/main/java/com/example/javatest/Mapper/user/OrderMapper.java @@ -0,0 +1,17 @@ +package com.example.javatest.Mapper.user; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.javatest.Entity.user.Order; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Mapper +@Component("userOrderMapper") +public interface OrderMapper extends BaseMapper { + @Select("SELECT * FROM `order` WHERE account_id = #{userId}") + List selectByUserId(@Param("userId") Long userId); +} diff --git a/src/main/java/com/example/javatest/Service/branch/BranchService.java b/src/main/java/com/example/javatest/Service/branch/BranchService.java new file mode 100644 index 0000000..684aaa7 --- /dev/null +++ b/src/main/java/com/example/javatest/Service/branch/BranchService.java @@ -0,0 +1,85 @@ +package com.example.javatest.Service.branch; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.example.javatest.Entity.branch.Branch; + + +import java.util.List; + +/** + * 分店服务层接口 + */ +public interface BranchService extends IService { + + /** + * 分页查询分店列表 + * @param current 当前页 + * @param size 每页大小 + * @param keyword 搜索关键词(可选) + * @param branchStatus 分店状态(可选) + * @param branchBoss 分店负责人(可选) + * @return 分页结果 + */ + Page getPageList(Long current, Long size, String keyword, String branchStatus, String branchBoss); + + /** + * 根据ID获取分店详情 + * @param branchId 分店ID + * @return 分店信息 + */ + Branch getBranchDetail(Long branchId); + + /** + * 保存分店基础信息 + * @param branch 分店信息 + * @return 是否保存成功 + */ + boolean saveBasicInfo(Branch branch); + + /** + * 更新分店营业信息 + * @param branchId 分店ID + * @param branchStatus 营业状态 + * @param branchStart 营业开始时间 + * @param branchEnd 营业结束时间 + * @return 是否更新成功 + */ + boolean updateBusinessInfo(Long branchId, String branchStatus, String branchStart, String branchEnd); + + /** + * 根据负责人ID查询分店列表 + * @param branchBoss 分店负责人ID + * @return 分店列表 + */ + List getBranchListByBoss(String branchBoss); + + /** + * 根据分店状态查询分店列表 + * @param branchStatus 分店状态 + * @return 分店列表 + */ + List getBranchListByStatus(String branchStatus); + + /** + * 删除分店(逻辑删除) + * @param branchId 分店ID + * @return 是否删除成功 + */ + boolean deleteBranch(Long branchId); + + /** + * 批量删除分店(逻辑删除) + * @param branchIds 分店ID列表 + * @return 是否删除成功 + */ + boolean deleteBatchBranch(List branchIds); + + /** + * 检查分店名称是否重复 + * @param branchName 分店名称 + * @param branchId 分店ID(更新时排除自己) + * @return 是否重复 + */ + boolean checkBranchNameExists(String branchName, Long branchId); +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Service/branch/CommentService.java b/src/main/java/com/example/javatest/Service/branch/CommentService.java new file mode 100644 index 0000000..cc357dd --- /dev/null +++ b/src/main/java/com/example/javatest/Service/branch/CommentService.java @@ -0,0 +1,87 @@ +package com.example.javatest.Service.branch; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.example.javatest.Entity.branch.Comment; + +import java.util.List; + +/** + * 评论服务接口 + */ +public interface CommentService extends IService { + + /** + * 分页查询评论列表 + * @param page 当前页 + * @param size 每页大小 + * @param dishName 菜品名称(可选) + * @param rating 评分(可选) + * @param commentType 评论类型,main表示主评论,reply表示回复评论(可选) + * @return 分页结果 + */ + IPage getCommentPage(Integer page, Integer size, String dishName, String rating, String commentType); + + /** + * 根据ID获取评论详情,包括相关回复 + * @param commentId 评论ID + * @return 评论详情 + */ + Comment getCommentDetail(Long commentId); + + /** + * 添加回复评论 + * @param comment 回复评论信息 + * @return 是否成功 + */ + boolean addReplyComment(Comment comment); + + /** + * 删除评论(逻辑删除) + * @param commentId 评论ID + * @return 是否成功 + */ + boolean deleteComment(Long commentId); + /** + * 获取所有主评论及其回复列表 + * @param page 当前页 + * @param size 每页大小 + * @param dishName 菜品名称(可选) + * @param rating 评分(可选) + * @return 包含回复的主评论列表 + */ + IPage getMainCommentsWithReplies(Integer page, Integer size, String dishName, String rating); + + /** + * 根据店铺ID分页查询评论列表 + * @param page 当前页 + * @param size 每页大小 + * @param branchId 店铺ID + * @param dishName 菜品名称(可选) + * @param rating 评分(可选) + * @param commentType 评论类型,main表示主评论,reply表示回复评论(可选) + * @return 分页结果 + */ + IPage getCommentPageByBranchId(Integer page, Integer size, Long branchId, + String dishName, String rating, String commentType); + + /** + * 根据店铺ID获取所有主评论及其回复列表 + * @param page 当前页 + * @param size 每页大小 + * @param branchId 店铺ID + * @param dishName 菜品名称(可选) + * @param rating 评分(可选) + * @return 包含回复的主评论列表 + */ + IPage getMainCommentsWithRepliesByBranchId(Integer page, Integer size, + Long branchId, String dishName, String rating); + + /** + * 根据店铺ID和菜品ID查询评论 + * @param dishId 菜品ID + * @param branchId 店铺ID + * @return 评论列表 + */ + List getCommentsByDishIdAndBranchId(Long dishId, Long branchId); +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Service/branch/DishService.java b/src/main/java/com/example/javatest/Service/branch/DishService.java new file mode 100644 index 0000000..9436daf --- /dev/null +++ b/src/main/java/com/example/javatest/Service/branch/DishService.java @@ -0,0 +1,78 @@ +package com.example.javatest.Service.branch; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.example.javatest.Entity.branch.Dish; + +import java.util.List; + +/** + * 菜品服务接口 + */ +public interface DishService extends IService { + + /** + * 分页查询菜品列表 + * @param page 当前页 + * @param size 每页大小 + * @param dishName 菜品名称(可选) + * @param category 分类(可选) + * @param status 状态(可选) + * @return 分页结果 + */ + IPage getDishPage(Integer page, Integer size, String dishName, String category, String status); + + /** + * 根据ID获取菜品详情 + * @param dishId 菜品ID + * @return 菜品信息 + */ + Dish getDishById(Long dishId); + + /** + * 添加菜品 + * @param dish 菜品信息 + * @return 是否成功 + */ + boolean addDish(Dish dish); + + /** + * 更新菜品 + * @param dish 菜品信息 + * @return 是否成功 + */ + boolean updateDish(Dish dish); + + /** + * 删除菜品 + * @param dishId 菜品ID + * @return 是否成功 + */ + boolean deleteDish(Long dishId); + + /** + * 更新菜品状态 + * @param dishId 菜品ID + * @param status 新状态 + * @return 是否成功 + */ + boolean updateDishStatus(Long dishId, String status); + + /** + * 根据店铺ID分页查询菜品列表 + * @param page 当前页 + * @param size 每页大小 + * @param branchId 店铺ID + * @param dishName 菜品名称(可选) + * @param category 分类(可选) + * @return 分页结果 + */ + IPage getDishByBranchId(Integer page, Integer size, Long branchId, String dishName, String category); + + /** + * 根据店铺ID查询所有菜品 + * @param branchId 店铺ID + * @return 菜品列表 + */ + List getDishListByBranchId(Long branchId); +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Service/branch/MapService.java b/src/main/java/com/example/javatest/Service/branch/MapService.java new file mode 100644 index 0000000..ef6696d --- /dev/null +++ b/src/main/java/com/example/javatest/Service/branch/MapService.java @@ -0,0 +1,7 @@ +package com.example.javatest.Service.branch; + +import reactor.core.publisher.Mono; + +public interface MapService { + public Mono getDistrictInfo(String keywords, int subdistrict); +} diff --git a/src/main/java/com/example/javatest/Service/branch/OrderService.java b/src/main/java/com/example/javatest/Service/branch/OrderService.java new file mode 100644 index 0000000..0d5747e --- /dev/null +++ b/src/main/java/com/example/javatest/Service/branch/OrderService.java @@ -0,0 +1,63 @@ +package com.example.javatest.Service.branch; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.example.javatest.Entity.branch.Order; +import com.example.javatest.Entity.branch.OrderList; + +import java.util.List; + +/** + * 订单服务接口 + */ +public interface OrderService extends IService { + + /** + * 分页查询店铺订单列表 + * @param page 当前页 + * @param size 每页大小 + * @param branchId 店铺ID + * @param orderStatus 订单状态(可选) + * @param accountId 账户ID(可选) + * @return 分页结果 + */ + IPage getOrderPageByBranchId(Integer page, Integer size, + Long branchId, Integer orderStatus, String accountId); + + /** + * 查询店铺所有订单 + * @param branchId 店铺ID + * @return 订单列表 + */ + List getOrdersByBranchId(Long branchId); + + /** + * 根据订单ID查询订单详情,包含订单明细 + * @param orderId 订单ID + * @return 订单详情 + */ + Order getOrderDetailById(Long orderId); + + /** + * 创建订单 + * @param order 订单信息 + * @param orderItems 订单明细列表 + * @return 订单ID + */ + Long createOrder(Order order, List orderItems); + + /** + * 更新订单状态 + * @param orderId 订单ID + * @param orderStatus 新状态 + * @return 是否成功 + */ + boolean updateOrderStatus(Long orderId, Integer orderStatus); + + /** + * 取消订单 + * @param orderId 订单ID + * @return 是否成功 + */ + boolean cancelOrder(Long orderId); +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Service/branch/impl/BranchServiceImpl.java b/src/main/java/com/example/javatest/Service/branch/impl/BranchServiceImpl.java new file mode 100644 index 0000000..3448d58 --- /dev/null +++ b/src/main/java/com/example/javatest/Service/branch/impl/BranchServiceImpl.java @@ -0,0 +1,147 @@ +package com.example.javatest.Service.branch.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +import com.example.javatest.Entity.branch.Branch; +import com.example.javatest.Mapper.branch.BranchMapper; +import com.example.javatest.Service.branch.BranchService; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +import java.util.List; + +/** + * 分店服务层实现 + */ +@Service("branchBranchService") +public class BranchServiceImpl extends ServiceImpl implements BranchService { + + @Override + public Page getPageList(Long current, Long size, String keyword, String branchStatus, String branchBoss) { + Page page = new Page<>(current, size); + QueryWrapper queryWrapper = new QueryWrapper<>(); + + // 搜索关键词 + if (StringUtils.hasText(keyword)) { + queryWrapper.and(wrapper -> wrapper + .like("branch_name", keyword) + .or() + .like("branch_address", keyword) + .or() + .like("branch_phone", keyword) + ); + } + + // 分店状态 + if (StringUtils.hasText(branchStatus)) { + queryWrapper.eq("branch_status", branchStatus); + } + + // 分店负责人 + if (StringUtils.hasText(branchBoss)) { + queryWrapper.eq("branch_boss", branchBoss); + } + + // 排序:按更新时间倒序 + queryWrapper.orderByDesc("updated_at"); + + return this.page(page, queryWrapper); + } + + @Override + public Branch getBranchDetail(Long branchId) { + if (branchId == null) { + return null; + } + return this.getById(branchId); + } + + @Override + public boolean saveBasicInfo(Branch branch) { + if (branch == null) { + return false; + } + + // 检查分店名称是否重复 + if (checkBranchNameExists(branch.getBranchName(), branch.getBranchId())) { + throw new RuntimeException("分店名称已存在"); + } + + // 新增或更新 + if (branch.getBranchId() == null) { + return this.save(branch); + } else { + return this.updateById(branch); + } + } + + @Override + public boolean updateBusinessInfo(Long branchId, String branchStatus, String branchStart, String branchEnd) { + if (branchId == null) { + return false; + } + + Branch branch = new Branch(); + branch.setBranchId(branchId); + branch.setBranchStatus(branchStatus); + branch.setBranchStart(branchStart); + branch.setBranchEnd(branchEnd); + + return this.updateById(branch); + } + + @Override + public List getBranchListByBoss(String branchBoss) { + if (!StringUtils.hasText(branchBoss)) { + return List.of(); + } + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("branch_boss", branchBoss); + return this.list(queryWrapper); + } + + @Override + public List getBranchListByStatus(String branchStatus) { + if (!StringUtils.hasText(branchStatus)) { + return List.of(); + } + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("branch_status", branchStatus); + return this.list(queryWrapper); + } + + @Override + public boolean deleteBranch(Long branchId) { + if (branchId == null) { + return false; + } + return this.removeById(branchId); + } + + @Override + public boolean deleteBatchBranch(List branchIds) { + if (branchIds == null || branchIds.isEmpty()) { + return false; + } + return this.removeByIds(branchIds); + } + + @Override + public boolean checkBranchNameExists(String branchName, Long branchId) { + if (!StringUtils.hasText(branchName)) { + return false; + } + + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("branch_name", branchName); + + // 更新时排除自己 + if (branchId != null) { + queryWrapper.ne("branch_id", branchId); + } + + return this.count(queryWrapper) > 0; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Service/branch/impl/CommentServiceImpl.java b/src/main/java/com/example/javatest/Service/branch/impl/CommentServiceImpl.java new file mode 100644 index 0000000..470402c --- /dev/null +++ b/src/main/java/com/example/javatest/Service/branch/impl/CommentServiceImpl.java @@ -0,0 +1,136 @@ +package com.example.javatest.Service.branch.impl; + +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.example.javatest.Entity.branch.Comment; +import com.example.javatest.Mapper.branch.CommentMapper; +import com.example.javatest.Service.branch.CommentService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 评论服务实现类 + */ +@Service("branchCommentService") +public class CommentServiceImpl extends ServiceImpl implements CommentService { + + @Autowired + private CommentMapper commentMapper; + + @Override + public IPage getCommentPage(Integer page, Integer size, String dishName, String rating, String commentType) { + Page commentPage = new Page<>(page, size); + return commentMapper.selectCommentPage(commentPage, dishName, rating, commentType); + } + + @Override + public Comment getCommentDetail(Long commentId) { + // 先查询评论基本信息 + Comment comment = commentMapper.selectCommentDetail(commentId); + if (comment == null) { + return null; + } + + // 如果是主评论(parentCommentId为null),则查询所有回复 + if (comment.getParentCommentId() == null) { + List replies = commentMapper.selectCommentReplies(commentId); + // 将回复列表添加到评论对象中 + comment.setReplies(replies); + } + + return comment; + } + + @Override + @Transactional + public boolean addReplyComment(Comment comment) { + // 首先检查被回复的评论是否存在 + Comment parentComment = this.getById(comment.getParentCommentId()); + if (parentComment == null) { + return false; + } + + // 回复评论的评分为0 + comment.setCommentRating(0); + + // 设置默认值 + comment.setIsDeleted(0); + + // 保存回复评论 + return this.save(comment); + } + + @Override + @Transactional + public boolean deleteComment(Long commentId) { + // 先查询评论是否存在 + Comment comment = this.getById(commentId); + if (comment == null) { + return false; + } + + // 设置删除时间 + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(Comment::getCommentId, commentId) + .set(Comment::getDeletedAt, LocalDateTime.now()); + this.update(updateWrapper); + + // 逻辑删除评论 + return this.removeById(commentId); + + // 注意:如果需要同时删除该评论下的所有回复,可以添加以下代码 + // com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper queryWrapper = new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>(); + // queryWrapper.eq(Comment::getParentCommentId, commentId); + // this.remove(queryWrapper); + } + + @Override + public IPage getMainCommentsWithReplies(Integer page, Integer size, String dishName, String rating) { + // 查询主评论列表(parent_comment_id为null的评论) + IPage mainCommentPage = this.getCommentPage(page, size, dishName, rating, "main"); + + // 为每个主评论查询回复列表 + for (Comment mainComment : mainCommentPage.getRecords()) { + List replies = commentMapper.selectCommentReplies(mainComment.getCommentId()); + // 设置回复列表(按创建时间升序排序,已在XML中配置ORDER BY c.created_at ASC) + mainComment.setReplies(replies); + } + + return mainCommentPage; + } + + @Override + public IPage getCommentPageByBranchId(Integer page, Integer size, Long branchId, + String dishName, String rating, String commentType) { + Page commentPage = new Page<>(page, size); + return commentMapper.selectCommentPageByBranchId(commentPage, branchId, dishName, rating, commentType); + } + + @Override + public IPage getMainCommentsWithRepliesByBranchId(Integer page, Integer size, + Long branchId, String dishName, String rating) { + // 查询指定店铺的主评论列表 + Page commentPage = new Page<>(page, size); + IPage mainCommentPage = commentMapper.selectMainCommentsByBranchId(commentPage, branchId, dishName, rating); + + // 为每个主评论查询回复列表 + for (Comment mainComment : mainCommentPage.getRecords()) { + List replies = commentMapper.selectCommentReplies(mainComment.getCommentId()); + // 设置回复列表 + mainComment.setReplies(replies); + } + + return mainCommentPage; + } + + @Override + public List getCommentsByDishIdAndBranchId(Long dishId, Long branchId) { + return commentMapper.selectCommentsByDishIdAndBranchId(dishId, branchId); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Service/branch/impl/DishServiceImpl.java b/src/main/java/com/example/javatest/Service/branch/impl/DishServiceImpl.java new file mode 100644 index 0000000..815c4d1 --- /dev/null +++ b/src/main/java/com/example/javatest/Service/branch/impl/DishServiceImpl.java @@ -0,0 +1,85 @@ +package com.example.javatest.Service.branch.impl; + +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.example.javatest.Entity.branch.Dish; +import com.example.javatest.Mapper.branch.DishMapper; +import com.example.javatest.Service.branch.DishService; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 菜品服务实现类 + */ +@Service("branchDishService") +public class DishServiceImpl extends ServiceImpl implements DishService { + + @Autowired + @Qualifier("branchDishMapper") + private DishMapper dishMapper; + + @Override + public IPage getDishPage(Integer page, Integer size, String dishName, String category, String status) { + Page dishPage = new Page<>(page, size); + return dishMapper.selectDishPage(dishPage, dishName, category, status); + } + + @Override + public Dish getDishById(Long dishId) { + return this.getById(dishId); + } + + @Override + public boolean addDish(Dish dish) { + // 设置默认值 + if (dish.getSales() == null) { + dish.setSales(0); + } + if (dish.getIsDeleted() == null) { + dish.setIsDeleted(0); + } + if (!StringUtils.hasText(dish.getStatus())) { + dish.setStatus("available"); + } + return this.save(dish); + } + + @Override + public boolean updateDish(Dish dish) { + return this.updateById(dish); + } + + @Override + public boolean deleteDish(Long dishId) { + // 逻辑删除 + return this.removeById(dishId); + } + + @Override + public boolean updateDishStatus(Long dishId, String status) { + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(Dish::getDishId, dishId) + .set(Dish::getStatus, status) + .set(Dish::getUpdatedAt, LocalDateTime.now()); + return this.update(updateWrapper); + } + + @Override + public IPage getDishByBranchId(Integer page, Integer size, Long branchId, String dishName, String category) { + Page dishPage = new Page<>(page, size); + return dishMapper.selectDishByBranchId(dishPage, branchId, dishName, category); + } + + @Override + public List getDishListByBranchId(Long branchId) { + return dishMapper.selectDishListByBranchId(branchId); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Service/branch/impl/MapServiceImpl.java b/src/main/java/com/example/javatest/Service/branch/impl/MapServiceImpl.java new file mode 100644 index 0000000..b555a21 --- /dev/null +++ b/src/main/java/com/example/javatest/Service/branch/impl/MapServiceImpl.java @@ -0,0 +1,47 @@ +package com.example.javatest.Service.branch.impl; + + +import com.example.javatest.Service.branch.MapService; +import com.fasterxml.jackson.databind.JsonNode; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +@Service("branchMapService") +public class MapServiceImpl implements MapService { + @Autowired + private WebClient webClient; + // 从 application.yml 中读取高德地图的配置 + @Value("${amap.key}") + private String amapKey; + + @Value("${amap.district.path}") + private String districtPath; + + + /** + * 查询行政区域信息 + * @param keywords 查询关键词,例如 "北京" + * @param subdistrict 返回的下级行政区级数,2 表示返回省、市、县/区三级 + * @return 来自高德 API 的原始 JSON 字符串 Mono + */ + public Mono getDistrictInfo(String keywords, int subdistrict) { + return webClient.get() + .uri(uriBuilder -> uriBuilder + .path(districtPath) + .queryParam("keywords", keywords) + .queryParam("subdistrict", subdistrict) + .queryParam("key", amapKey) + .build()) + .retrieve() + .bodyToMono(JsonNode.class) + .map(jsonNode -> { + // 从高德返回的完整JSON中,我们只关心 districts 数组 + // 高德API成功时 districts 字段一定存在 + return jsonNode.get("districts"); + }); + } +} + diff --git a/src/main/java/com/example/javatest/Service/branch/impl/OrderServiceImpl.java b/src/main/java/com/example/javatest/Service/branch/impl/OrderServiceImpl.java new file mode 100644 index 0000000..026fae9 --- /dev/null +++ b/src/main/java/com/example/javatest/Service/branch/impl/OrderServiceImpl.java @@ -0,0 +1,98 @@ +package com.example.javatest.Service.branch.impl; + +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.example.javatest.Entity.branch.Order; +import com.example.javatest.Entity.branch.OrderList; +import com.example.javatest.Mapper.branch.OrderListMapper; +import com.example.javatest.Mapper.branch.OrderMapper; +import com.example.javatest.Service.branch.OrderService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 订单服务实现类 + */ +@Service("branchOrderService") +public class OrderServiceImpl extends ServiceImpl implements OrderService { + + @Autowired + private OrderMapper orderMapper; + + @Autowired + private OrderListMapper orderListMapper; + + @Override + public IPage getOrderPageByBranchId(Integer page, Integer size, + Long branchId, Integer orderStatus, String accountId) { + Page orderPage = new Page<>(page, size); + return orderMapper.selectOrderPageByBranchId(orderPage, branchId, orderStatus, accountId); + } + + @Override + public List getOrdersByBranchId(Long branchId) { + return orderMapper.selectOrdersByBranchId(branchId); + } + + @Override + public Order getOrderDetailById(Long orderId) { + // 查询订单基本信息 + Order order = orderMapper.selectOrderDetailById(orderId); + if (order == null) { + return null; + } + + // 查询订单明细 + List orderItems = orderListMapper.selectOrderItemsByOrderId(orderId); + order.setOrderLists(orderItems); + + return order; + } + + @Override + @Transactional + public Long createOrder(Order order, List orderItems) { + // 设置订单时间 + order.setOrderTime(LocalDateTime.now()); + // 设置逻辑删除标志 + order.setIsDeleted(0); + + // 保存订单 + this.save(order); + Long orderId = order.getOrderId(); + + // 保存订单明细 + if (orderItems != null && !orderItems.isEmpty()) { + for (OrderList item : orderItems) { + item.setOrderId(orderId); + } + orderListMapper.batchInsert(orderItems); + } + + return orderId; + } + + @Override + @Transactional + public boolean updateOrderStatus(Long orderId, Integer orderStatus) { + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(Order::getOrderId, orderId) + .set(Order::getOrderStatus, orderStatus) + .set(Order::getUpdatedAt, LocalDateTime.now()); + + return this.update(updateWrapper); + } + + @Override + @Transactional + public boolean cancelOrder(Long orderId) { + // 实际业务中可能需要检查订单状态,判断是否允许取消 + return updateOrderStatus(orderId, -1); // 假设-1表示已取消 + } +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Service/user/BranchService.java b/src/main/java/com/example/javatest/Service/user/BranchService.java new file mode 100644 index 0000000..2df8a9d --- /dev/null +++ b/src/main/java/com/example/javatest/Service/user/BranchService.java @@ -0,0 +1,36 @@ +package com.example.javatest.Service.user; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; + +import com.example.javatest.Entity.user.Branch; +import com.example.javatest.Mapper.user.BranchMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; + +@Service("userBranchService") +public class BranchService { + + @Autowired + private BranchMapper branchMapper; public List list() { + return branchMapper.selectList(new QueryWrapper().eq("is_deleted", 0)); + } + + public int add(Branch branch) { + return branchMapper.insert(branch); + } + + public int update(Branch branch) { + return branchMapper.updateById(branch); + } public int delete(Long id) { + Branch branch = new Branch(); + branch.setBranchId(id); + branch.setIsDeleted(1); + branch.setDeletedAt(LocalDateTime.now()); + return branchMapper.updateById(branch); + } public Branch getById(Long id) { + return branchMapper.selectById(id); + } +} diff --git a/src/main/java/com/example/javatest/Service/user/CommentService.java b/src/main/java/com/example/javatest/Service/user/CommentService.java new file mode 100644 index 0000000..cb4b6df --- /dev/null +++ b/src/main/java/com/example/javatest/Service/user/CommentService.java @@ -0,0 +1,28 @@ +package com.example.javatest.Service.user; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +import com.example.javatest.Entity.user.Comment; +import com.example.javatest.Mapper.user.CommentMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service("userCommentService") +public class CommentService extends ServiceImpl { + + @Autowired + private CommentMapper commentMapper; // 根据菜品ID获取评论 + public List getCommentsByDishId(Long dishId) { + return commentMapper.selectByDishId(dishId); + } // 获取某个用户的评论 + public List getCommentsByAccountId(Long accountId) { + return commentMapper.selectByAccountId(accountId); + } + + // 保存评论 + public boolean saveComment(Comment comment) { + return this.save(comment); + } +} diff --git a/src/main/java/com/example/javatest/Service/user/CustomerService.java b/src/main/java/com/example/javatest/Service/user/CustomerService.java new file mode 100644 index 0000000..d568ac0 --- /dev/null +++ b/src/main/java/com/example/javatest/Service/user/CustomerService.java @@ -0,0 +1,31 @@ +package com.example.javatest.Service.user; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +import com.example.javatest.Entity.user.Customer; +import com.example.javatest.Mapper.user.CustomerMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service("userCustomerService") +public class CustomerService extends ServiceImpl { + + @Autowired + private CustomerMapper customerMapper; // 可根据需求编写具体的业务逻辑 + public Customer getCustomerById(Long accountId) { + return customerMapper.selectById(accountId); + } + + // 根据 accountName 查询客户 + public Customer getCustomerByName(String accountName) { + return customerMapper.selectOne(new QueryWrapper().eq("account_name", accountName)); + } + // 保存客户信息 + public boolean saveCustomer(Customer customer) { + return this.save(customer); + } // 删除客户 + public boolean deleteCustomer(Long accountId) { + return this.removeById(accountId); + } +} diff --git a/src/main/java/com/example/javatest/Service/user/DishService.java b/src/main/java/com/example/javatest/Service/user/DishService.java new file mode 100644 index 0000000..1b27900 --- /dev/null +++ b/src/main/java/com/example/javatest/Service/user/DishService.java @@ -0,0 +1,44 @@ +package com.example.javatest.Service.user; + +import com.example.javatest.Entity.user.Dish; +import com.example.javatest.Mapper.user.DishMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.List; + +@Service("userDishService") +public class DishService { + + @Autowired + @Qualifier("userDishMapper") + private DishMapper dishMapper;public List getDishesByCategoryAndBranch(String category, Long branchId) { + return dishMapper.selectByCategoryAndBranch(category, branchId); + } public List searchDishes(String keyword, Long branchId) { + return dishMapper.searchByKeyword(keyword, branchId); + } + + // 获取所有菜品分类 + public List getCategories() { + return dishMapper.selectCategories(); + } + + // 根据菜品 ID 查询菜品 + public Dish getDishById(Integer id) { + return dishMapper.selectById(id); + } public List getDishesByIds(List ids) { + if (ids == null || ids.isEmpty()) { + return Collections.emptyList(); + } + return dishMapper.selectList( + new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper() + .in("dish_id", ids) + ); + }public List getTop5PopularDishesByBranch(Long branchId) { + return dishMapper.selectTop5PopularDishesByBranch(branchId); + } public List getLatestDishesByBranch(Long branchId) { + return dishMapper.selectLatestDishesByBranch(branchId); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Service/user/MapService.java b/src/main/java/com/example/javatest/Service/user/MapService.java new file mode 100644 index 0000000..9473068 --- /dev/null +++ b/src/main/java/com/example/javatest/Service/user/MapService.java @@ -0,0 +1,92 @@ +package com.example.javatest.Service.user; + +import com.alibaba.fastjson.JSONObject; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.ssl.SSLContexts; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +@Service("userMapService") +public class MapService { + private final CloseableHttpClient httpClient; + private static final Logger log = LoggerFactory.getLogger(MapService.class); + + public MapService() { + try { + // 配置超时时间 + RequestConfig config = RequestConfig.custom() + .setConnectTimeout(10000) // 连接超时:10秒 + .setSocketTimeout(30000) // 读取超时:30秒 + .build(); + + // 配置 SSL 连接 + SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory( + SSLContexts.createSystemDefault(), + NoopHostnameVerifier.INSTANCE + ); + + httpClient = HttpClientBuilder.create() + .setDefaultRequestConfig(config) + .setSSLSocketFactory(sslSocketFactory) + .build(); + } catch (Exception e) { + throw new IllegalStateException("Failed to initialize HttpClient", e); + } + } + + public String convertCoordinateToAddress(double longitude, double latitude) { + try { + // 构建请求 + HttpGet request = new HttpGet( + "https://restapi.amap.com/v3/geocode/regeo?" + + "key=808211cfee7c59cdd4268a8262f05f01&" + // 注意:实际使用时替换为真实的 API Key + "location=" + longitude + "," + latitude + ); + request.setHeader("Content-Type", "application/json"); + + // 执行请求 + CloseableHttpResponse response = httpClient.execute(request); + try { + if (response.getStatusLine().getStatusCode() == 200) { + String result = EntityUtils.toString(response.getEntity()); + + // 使用 FastJSON 解析结果,提取 formatted_address + JSONObject jsonObject = JSONObject.parseObject(result); + + // 检查 API 响应状态 + String status = jsonObject.getString("status"); + if ("1".equals(status)) { // 高德 API 返回成功 + JSONObject regeocode = jsonObject.getJSONObject("regeocode"); + if (regeocode != null) { + String formattedAddress = regeocode.getString("formatted_address"); + if (formattedAddress != null) { + return formattedAddress; // 只返回格式化地址 + } + } + } + + // 如果解析失败或API返回错误,记录日志并返回默认信息 + log.error("解析高德API响应失败: {}", result); + return "无法获取格式化地址"; + } else { + throw new RuntimeException("高德API返回错误:" + response.getStatusLine().getStatusCode()); + } + } finally { + response.close(); + } + } catch (Exception e) { + log.error("调用高德API失败", e); + return "获取地址失败"; + } + } + + +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/Service/user/OrderService.java b/src/main/java/com/example/javatest/Service/user/OrderService.java new file mode 100644 index 0000000..5e54f79 --- /dev/null +++ b/src/main/java/com/example/javatest/Service/user/OrderService.java @@ -0,0 +1,46 @@ +package com.example.javatest.Service.user; + + +import com.example.javatest.Entity.user.Dish; +import com.example.javatest.Entity.user.Order; +import com.example.javatest.Entity.user.OrderList; +import com.example.javatest.Mapper.user.OrderListMapper; +import com.example.javatest.Mapper.user.OrderMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; + +@Service("userOrderService") +public class OrderService { + + @Autowired + private OrderMapper orderMapper; + + @Autowired + private OrderListMapper orderListMapper; + + public void createOrder(Order order, List items) { + order.setOrderTime(LocalDateTime.now()); + orderMapper.insert(order); + // 手动设置创建时间 + order.setCreatedAt(LocalDateTime.now()); + order.setUpdatedAt(LocalDateTime.now()); + for (OrderList item : items) { + item.setOrderId(order.getOrderId()); + orderListMapper.insert(item); + } + } public Order getOrderById(Long id) { + return orderMapper.selectById(id); + } public List getOrdersByUserId(Long userId) { + return orderMapper.selectByUserId(userId); + }public List getOrdersByAccountId(Long accountId) { + return orderMapper.selectList( + new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper() + .eq("account_id", accountId) + ); + } public List getTopDishesByUser(Long accountId) { + return orderListMapper.selectTopDishesByUser(accountId); + } +} diff --git a/src/main/java/com/example/javatest/common/Result.java b/src/main/java/com/example/javatest/common/Result.java new file mode 100644 index 0000000..9161dca --- /dev/null +++ b/src/main/java/com/example/javatest/common/Result.java @@ -0,0 +1,29 @@ +package com.example.javatest.common; + +import lombok.Data; + +@Data +public class Result { + private int code; + private String msg; + private T data; + + public static Result success(T data) { + Result result = new Result<>(); + result.setCode(200); + result.setMsg("成功"); + result.setData(data); + return result; + } + + public static Result success() { + return success(null); + } + + public static Result error(String msg) { + Result result = new Result<>(); + result.setCode(500); + result.setMsg(msg); + return result; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/config/CorsConfig.java b/src/main/java/com/example/javatest/config/CorsConfig.java new file mode 100644 index 0000000..ac681f4 --- /dev/null +++ b/src/main/java/com/example/javatest/config/CorsConfig.java @@ -0,0 +1,22 @@ +package com.example.javatest.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * 跨域配置类 + */ +@Configuration +public class CorsConfig implements WebMvcConfigurer { + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOriginPatterns("*") + .allowedMethods("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS") + .allowedHeaders("*") + .allowCredentials(true) + .maxAge(3600); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/config/MybatisPlusConfig.java b/src/main/java/com/example/javatest/config/MybatisPlusConfig.java new file mode 100644 index 0000000..5dbc505 --- /dev/null +++ b/src/main/java/com/example/javatest/config/MybatisPlusConfig.java @@ -0,0 +1,47 @@ +package com.example.javatest.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.apache.ibatis.reflection.MetaObject; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +/** + * MyBatis-Plus配置类 + */ +@Configuration +public class MybatisPlusConfig { + + /** + * 分页插件 + */ + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); + return interceptor; + } + + /** + * 自动填充处理器 + */ + @Component + public static class MyMetaObjectHandler implements MetaObjectHandler { + + @Override + public void insertFill(MetaObject metaObject) { + this.strictInsertFill(metaObject, "createdAt", LocalDateTime.class, LocalDateTime.now()); + this.strictInsertFill(metaObject, "updatedAt", LocalDateTime.class, LocalDateTime.now()); + } + + @Override + public void updateFill(MetaObject metaObject) { + this.strictUpdateFill(metaObject, "updatedAt", LocalDateTime.class, LocalDateTime.now()); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/example/javatest/config/WebClientConfig.java b/src/main/java/com/example/javatest/config/WebClientConfig.java new file mode 100644 index 0000000..86bf454 --- /dev/null +++ b/src/main/java/com/example/javatest/config/WebClientConfig.java @@ -0,0 +1,38 @@ +package com.example.javatest.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.web.reactive.function.client.ExchangeFilterFunction; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +@Configuration +public class WebClientConfig { + + @Value("${amap.base-url}") + private String amapBaseUrl; + + @Bean + public WebClient.Builder webClientBuilder() { + return WebClient.builder() + .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) // 默认请求头 + .defaultHeader("User-Agent", "MySpringBootApp/1.0") + .filter(ExchangeFilterFunction.ofRequestProcessor( + clientRequest -> { + // 可以在这里统一添加认证信息或日志 + System.out.println("Request: " + clientRequest.method() + " " + clientRequest.url()); + return Mono.just(clientRequest); + } + )); + } + + @Bean + public WebClient webClient(WebClient.Builder builder) { + return builder + .baseUrl(amapBaseUrl) // 设置高德地图API基础URL + .build(); + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..1d885db --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,47 @@ +spring: + application: + name: java-test + + # 数据库配置 + datasource: + url: jdbc:mysql://localhost:3306/cg + username: root + password: 123456 + driver-class-name: com.mysql.cj.jdbc.Driver + + # 排除Spring Security自动配置 + autoconfigure: + exclude: + - org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration + - org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration + +# MyBatis-Plus配置 +mybatis-plus: + mapper-locations: classpath:mapper/*.xml + type-aliases-package: com.example.javatest.entity + configuration: + map-underscore-to-camel-case: true + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + global-config: + db-config: + logic-delete-field: isDeleted + logic-delete-value: 1 + logic-not-delete-value: 0 + +# 服务器配置 +server: + port: 8080 + +# 日志配置 +logging: + level: + com.example.javatest.Mapper: debug + +amap: + # 在高德开放平台申请的 Web 服务 Key + key: d92b938ba20e026ced99f8ed9de12821 + # 高德地图API基础URL + base-url: https://restapi.amap.com + district: + # 行政区域查询 API 的路径 + path: /v3/config/district diff --git a/src/main/resources/mapper/BranchMapper.xml b/src/main/resources/mapper/BranchMapper.xml new file mode 100644 index 0000000..e41dabe --- /dev/null +++ b/src/main/resources/mapper/BranchMapper.xml @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + branch_id, branch_name, branch_address, branch_phone, branch_start, + branch_end, branch_status, branch_boss, province, latitude, longitude, + is_deleted, deleted_at, created_at, updated_at + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/CommentMapper.xml b/src/main/resources/mapper/CommentMapper.xml new file mode 100644 index 0000000..5c65434 --- /dev/null +++ b/src/main/resources/mapper/CommentMapper.xml @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/DishMapper.xml b/src/main/resources/mapper/DishMapper.xml new file mode 100644 index 0000000..79cce40 --- /dev/null +++ b/src/main/resources/mapper/DishMapper.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/OrderListMapper.xml b/src/main/resources/mapper/OrderListMapper.xml new file mode 100644 index 0000000..4d411d8 --- /dev/null +++ b/src/main/resources/mapper/OrderListMapper.xml @@ -0,0 +1,31 @@ + + + + + + + + + + INSERT INTO order_list (order_id, number, dish_id) + VALUES + + (#{item.orderId}, #{item.number}, #{item.dishId}) + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/OrderMapper.xml b/src/main/resources/mapper/OrderMapper.xml new file mode 100644 index 0000000..0f4ac61 --- /dev/null +++ b/src/main/resources/mapper/OrderMapper.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/java/com/example/javatest/JavaTestApplicationTests.java b/src/test/java/com/example/javatest/JavaTestApplicationTests.java new file mode 100644 index 0000000..d2a5e12 --- /dev/null +++ b/src/test/java/com/example/javatest/JavaTestApplicationTests.java @@ -0,0 +1,13 @@ +package com.example.javatest; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class JavaTestApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/餐厅管理系统实体类设计文档.md b/餐厅管理系统实体类设计文档.md new file mode 100644 index 0000000..e79649d --- /dev/null +++ b/餐厅管理系统实体类设计文档.md @@ -0,0 +1,341 @@ +# 餐厅管理系统实体类设计文档 + +## 项目概述 + +本项目是一个基于Spring Boot + MyBatis-Plus的餐厅管理系统,采用分层架构设计,支持多角色权限管理。系统主要面向三种用户角色:系统管理员(admin)、分店管理员(branch)和普通用户(user)。 + +## 技术栈 + +- **框架**: Spring Boot +- **ORM**: MyBatis-Plus +- **注解工具**: Lombok +- **JSON序列化**: Jackson +- **数据库**: MySQL + +## 实体类架构设计 + +### 1. 包结构设计 + +实体类按照业务角色进行模块化分包: + +``` +src/main/java/com/example/javatest/Entity/ +├── admin/ # 系统管理员相关实体 +├── branch/ # 分店管理员相关实体 +└── user/ # 普通用户相关实体 +``` + +### 2. 通用注解说明 + +所有实体类都使用了以下通用注解: + +- **`@Data`**: Lombok注解,自动生成getter/setter/toString/equals/hashCode方法 +- **`@NoArgsConstructor`**: 生成无参构造函数 +- **`@AllArgsConstructor`**: 生成全参构造函数 +- **`@Alias`**: MyBatis别名,用于区分不同包下的同名实体 +- **`@TableName`**: 指定数据库表名 +- **`@TableId`**: 标识主键字段,使用AUTO自增策略 +- **`@TableField`**: 映射数据库字段 +- **`@TableLogic`**: 逻辑删除标识 +- **`@JsonFormat`**: JSON序列化时间格式化 +- **`@FieldFill`**: 字段自动填充策略 + +## 核心实体类详解 + +### 1. 账户实体类 (Account/Customer) + +#### 1.1 管理员账户 ([`Account.java`](src/main/java/com/example/javatest/Entity/admin/Account.java:21)) + +**表名**: `account` +**别名**: `AdminAccount` + +| 字段名 | 数据类型 | 数据库字段 | 是否必填 | 说明 | 示例值 | +|--------|----------|------------|----------|------|--------| +| accountId | Long | account_id | ✓ | 账户ID(主键,自增) | 1001 | +| accountName | String | account_name | ✓ | 账户名称 | "张三" | +| accountPassword | String | account_password | ✓ | 账户密码 | "******" | +| accountPhone | String | account_phone | ○ | 手机号码 | "13888888888" | +| accountType | String | account_type | ✓ | 账户类型 | admin/manager/customer | +| accountImg | String | account_img | ○ | 头像图片URL | "https://example.com/avatar.jpg" | +| accountGender | String | account_gender | ○ | 性别 | male/female | +| accountTag | String | account_tag | ○ | 账户标签 | "VIP用户" | +| salary | BigDecimal | salary | ○ | 薪资(员工用) | 5000.00 | +| isDeleted | Integer | is_deleted | ✓ | 逻辑删除标识 | 0-未删除,1-已删除 | +| deletedAt | LocalDateTime | deleted_at | ○ | 删除时间 | 2024-01-01 12:00:00 | +| createdAt | LocalDateTime | created_at | ✓ | 创建时间(自动填充) | 2024-01-01 10:00:00 | +| updatedAt | LocalDateTime | updated_at | ✓ | 更新时间(自动填充) | 2024-01-01 11:00:00 | + +#### 1.2 用户账户 ([`Customer.java`](src/main/java/com/example/javatest/Entity/user/Customer.java:21)) + +**表名**: `account` +**别名**: `UserCustomer` + +用户账户实体与管理员账户实体结构完全相同,字段定义参考上表。区别在于使用不同的别名以区分业务上下文。 + +**设计特点**: +- 统一的账户表设计,通过`account_type`字段区分角色 +- 支持员工薪资管理 +- 完整的用户画像信息(头像、性别、标签) + +### 2. 分店实体类 ([`Branch.java`](src/main/java/com/example/javatest/Entity/branch/Branch.java:20)) + +**表名**: `branch` +**别名**: `BranchBranch` + +| 字段名 | 数据类型 | 数据库字段 | 是否必填 | 说明 | 示例值 | +|--------|----------|------------|----------|------|--------| +| branchId | Long | branch_id | ✓ | 分店ID(主键,自增) | 2001 | +| branchName | String | branch_name | ✓ | 分店名称 | "北京朝阳店" | +| branchAddress | String | branch_address | ✓ | 分店地址 | "北京市朝阳区三里屯路1号" | +| branchPhone | String | branch_phone | ○ | 分店电话 | "010-12345678" | +| branchStart | String | branch_start | ○ | 营业开始时间 | "09:00" | +| branchEnd | String | branch_end | ○ | 营业结束时间 | "22:00" | +| branchStatus | String | branch_status | ✓ | 营业状态 | open-营业中,closed-已停业 | +| branchBoss | Long | branch_boss | ○ | 负责人ID(关联account表) | 1001 | +| province | String | province | ○ | 所属省份 | "北京市" | +| latitude | Double | latitude | ○ | 纬度 | 39.9042 | +| longitude | Double | longitude | ○ | 经度 | 116.4074 | +| isDeleted | Integer | is_deleted | ✓ | 逻辑删除标识 | 0-未删除,1-已删除 | +| deletedAt | LocalDateTime | deleted_at | ○ | 删除时间 | 2024-01-01 12:00:00 | +| createdAt | LocalDateTime | created_at | ✓ | 创建时间(自动填充) | 2024-01-01 10:00:00 | +| updatedAt | LocalDateTime | updated_at | ✓ | 更新时间(自动填充) | 2024-01-01 11:00:00 | + +**设计特点**: +- 支持地理位置信息(经纬度),便于地图功能 +- 灵活的营业时间管理(HH:mm格式) +- 分店负责人关联设计 +- 营业状态动态管理 + +### 3. 菜品实体类 ([`Dish.java`](src/main/java/com/example/javatest/Entity/user/Dish.java:21)) + +**表名**: `dishes` +**别名**: `UserDish` + +| 字段名 | 数据类型 | 数据库字段 | 是否必填 | 说明 | 示例值 | +|--------|----------|------------|----------|------|--------| +| dishId | Integer | dish_id | ✓ | 菜品ID(主键,自增) | 3001 | +| dishName | String | dish_name | ✓ | 菜品名称 | "宫保鸡丁" | +| category | String | category | ○ | 菜品分类 | "川菜" | +| price | BigDecimal | price | ✓ | 菜品价格 | 28.00 | +| stock | Integer | stock | ○ | 当前库存数量 | 50 | +| status | String | status | ✓ | 菜品状态 | "在售"/"停售" | +| description | String | description | ○ | 菜品描述 | "经典川菜,麻辣鲜香" | +| imageUrl | String | image_url | ○ | 菜品图片URL | "https://example.com/dish.jpg" | +| sales | Integer | sales | ○ | 累计销售数量 | 156 | +| tag | String | tag | ○ | 菜品标签 | "招牌菜,辣" | +| isDeleted | Integer | is_deleted | ✓ | 逻辑删除标识 | 0-未删除,1-已删除 | +| deletedAt | LocalDateTime | deleted_at | ○ | 删除时间 | 2024-01-01 12:00:00 | +| createdAt | LocalDateTime | created_at | ✓ | 创建时间(自动填充) | 2024-01-01 10:00:00 | +| updatedAt | LocalDateTime | updated_at | ✓ | 更新时间(自动填充) | 2024-01-01 11:00:00 | + +**设计特点**: +- 完整的商品信息管理(价格、库存、销量) +- 支持图片展示功能 +- 灵活的分类和标签系统 +- 状态管理(在售/停售) + +### 4. 订单实体类 ([`Order.java`](src/main/java/com/example/javatest/Entity/user/Order.java:21)) + +**表名**: `order`(使用反引号处理MySQL保留字) +**别名**: `UserOrder` + +| 字段名 | 数据类型 | 数据库字段 | 是否必填 | 说明 | 示例值 | +|--------|----------|------------|----------|------|--------| +| orderId | Long | order_id | ✓ | 订单ID(主键,自增) | 4001 | +| accountId | Long | account_id | ✓ | 下单用户ID(关联account表) | 1001 | +| orderTime | LocalDateTime | order_time | ✓ | 下单时间 | 2024-01-01 14:30:00 | +| branchId | Long | branch_id | ✓ | 分店ID(关联branch表) | 2001 | +| orderMoney | BigDecimal | order_money | ✓ | 订单总金额 | 86.50 | +| orderRemarks | String | order_remarks | ○ | 订单备注 | "少盐,不要香菜" | +| orderStatus | Integer | order_status | ✓ | 订单状态 | 1-待处理,2-已完成,-1-已取消 | +| isDeleted | Integer | is_deleted | ✓ | 逻辑删除标识 | 0-未删除,1-已删除 | +| deletedAt | LocalDateTime | deleted_at | ○ | 删除时间 | 2024-01-01 12:00:00 | +| createdAt | LocalDateTime | created_at | ✓ | 创建时间(自动填充) | 2024-01-01 10:00:00 | +| updatedAt | LocalDateTime | updated_at | ✓ | 更新时间(自动填充) | 2024-01-01 11:00:00 | + +**设计特点**: +- 关联用户和分店信息 +- 完整的订单流程状态管理 +- 支持订单备注功能 +- 使用反引号处理MySQL保留字`order` + +### 5. 订单明细实体类 ([`OrderList.java`](src/main/java/com/example/javatest/Entity/user/OrderList.java:20)) + +**表名**: `order_list` +**别名**: `UserOrderList` + +| 字段名 | 数据类型 | 数据库字段 | 是否必填 | 说明 | 示例值 | +|--------|----------|------------|----------|------|--------| +| orderListId | Long | order_list_id | ✓ | 订单明细ID(主键,自增) | 5001 | +| orderId | Long | order_id | ✓ | 订单ID(关联order表) | 4001 | +| dishId | Long | dish_id | ✓ | 菜品ID(关联dishes表) | 3001 | +| number | Integer | number | ✓ | 菜品数量 | 2 | +| createdAt | LocalDateTime | created_at | ✓ | 创建时间(自动填充) | 2024-01-01 10:00:00 | +| updatedAt | LocalDateTime | updated_at | ✓ | 更新时间(自动填充) | 2024-01-01 11:00:00 | + +**设计特点**: +- 订单与菜品的多对多关系处理 +- 简洁的明细记录设计 +- 支持同一订单多种菜品 +- 仅包含核心业务字段,无逻辑删除功能 + +### 6. 评论实体类 ([`Comment.java`](src/main/java/com/example/javatest/Entity/user/Comment.java:20)) + +**表名**: `comments` +**别名**: `UserComment` + +| 字段名 | 数据类型 | 数据库字段 | 是否必填 | 说明 | 示例值 | +|--------|----------|------------|----------|------|--------| +| commentId | Long | comment_id | ✓ | 评论ID(主键,自增) | 6001 | +| commentText | String | comment_text | ✓ | 评论内容 | "味道很不错,分量足够" | +| commentDishId | Long | comment_dish_id | ✓ | 评论的菜品ID(关联dishes表) | 3001 | +| commentAccountId | Long | comment_account_id | ✓ | 评论用户ID(关联account表) | 1001 | +| commentRating | Integer | comment_rating | ○ | 评分 | 1-5分(5为最高分) | +| parentCommentId | Long | parent_comment_id | ○ | 父评论ID(用于回复功能) | 6000 | +| isDeleted | Integer | is_deleted | ✓ | 逻辑删除标识 | 0-未删除,1-已删除 | +| deletedAt | LocalDateTime | deleted_at | ○ | 删除时间 | 2024-01-01 12:00:00 | +| createdAt | LocalDateTime | created_at | ✓ | 创建时间(自动填充) | 2024-01-01 10:00:00 | +| updatedAt | LocalDateTime | updated_at | ✓ | 更新时间(自动填充) | 2024-01-01 11:00:00 | + +**设计特点**: +- 支持评分系统(1-5分) +- 嵌套评论功能(回复功能) +- 关联菜品和用户信息 +- 支持评论内容的逻辑删除 + +## 通用字段设计 + +### 1. 逻辑删除机制 + +| 字段名 | 数据类型 | 数据库字段 | 注解 | 说明 | 可选值 | +|--------|----------|------------|------|------|--------| +| isDeleted | Integer | is_deleted | @TableLogic | 逻辑删除标识 | 0-未删除,1-已删除 | +| deletedAt | LocalDateTime | deleted_at | @JsonFormat | 删除时间戳 | 2024-01-01 12:00:00 | + +**特点说明**: +- 使用`@TableLogic`注解实现逻辑删除 +- 删除操作不会物理删除数据,而是更新`is_deleted`字段 +- 查询时自动过滤已删除数据 +- `deletedAt`记录具体删除时间 + +### 2. 时间戳管理 + +| 字段名 | 数据类型 | 数据库字段 | 填充策略 | 说明 | 示例值 | +|--------|----------|------------|----------|------|--------| +| createdAt | LocalDateTime | created_at | FieldFill.INSERT | 创建时间(插入时自动填充) | 2024-01-01 10:00:00 | +| updatedAt | LocalDateTime | updated_at | FieldFill.INSERT_UPDATE | 更新时间(插入和更新时自动填充) | 2024-01-01 11:00:00 | + +**特点说明**: +- 使用MyBatis-Plus自动填充功能 +- `@JsonFormat`统一时间格式化为`yyyy-MM-dd HH:mm:ss` +- 创建时间仅在插入时填充,更新时间在插入和更新时都会填充 +- 时间戳字段为审计功能提供基础支持 + +### 3. 主键设计 + +| 特性 | 说明 | 注解配置 | 示例 | +|------|------|----------|------| +| 主键类型 | 自增长整型 | @TableId(type = IdType.AUTO) | account_id, branch_id | +| 命名规范 | {表名}_id 格式 | @TableId(value = "table_id") | order_id, dish_id | +| 数据类型 | Long (大部分) / Integer (菜品) | private Long/Integer xxxId | 支持大数据量 | + +## 数据库设计规范 + +### 1. 命名规范 + +- **表名**: 使用复数形式或业务名称(如`dishes`、`comments`、`order_list`) +- **字段名**: 使用下划线命名法(如`account_name`、`branch_address`) +- **主键**: 统一使用`{表名}_id`格式(如`account_id`、`branch_id`) + +### 2. 数据类型选择 + +- **主键**: `BIGINT AUTO_INCREMENT` +- **金额**: `DECIMAL`类型,保证精度 +- **时间**: `DATETIME`类型,支持毫秒级精度 +- **状态字段**: `VARCHAR`或`INT`,根据业务需求选择 +- **布尔值**: `TINYINT`,0表示false,1表示true + +### 3. 外键关系 + +| 主表 | 主键字段 | 从表 | 外键字段 | 关系类型 | 业务含义 | +|------|----------|------|----------|----------|----------| +| Account | account_id | Branch | branch_boss | 一对一 | 分店负责人 | +| Account | account_id | Order | account_id | 一对多 | 用户订单 | +| Branch | branch_id | Order | branch_id | 一对多 | 分店订单 | +| Order | order_id | OrderList | order_id | 一对多 | 订单明细 | +| Dish | dish_id | OrderList | dish_id | 一对多 | 菜品订购 | +| Dish | dish_id | Comment | comment_dish_id | 一对多 | 菜品评论 | +| Account | account_id | Comment | comment_account_id | 一对多 | 用户评论 | +| Comment | comment_id | Comment | parent_comment_id | 一对多 | 评论回复 | + +**关系特点**: +- 使用逻辑外键,不设置物理外键约束 +- 通过应用层保证数据一致性 +- 支持分布式数据库部署 +- 便于数据迁移和维护 + +## 业务流程设计 + +### 1. 用户注册登录 + +1. 用户通过[`Customer`](src/main/java/com/example/javatest/Entity/user/Customer.java:21)实体注册账户 +2. 系统根据[`accountType`](src/main/java/com/example/javatest/Entity/admin/Account.java:50)字段分配权限 +3. 支持多种账户类型:admin、manager、customer + +### 2. 分店管理 + +1. 系统管理员创建[`Branch`](src/main/java/com/example/javatest/Entity/branch/Branch.java:20)记录 +2. 指定分店负责人([`branchBoss`](src/main/java/com/example/javatest/Entity/branch/Branch.java:67)字段) +3. 设置营业时间和地理位置信息 + +### 3. 菜品管理 + +1. 分店管理员维护[`Dish`](src/main/java/com/example/javatest/Entity/user/Dish.java:21)信息 +2. 管理库存、价格、状态等 +3. 用户可以浏览菜品并查看评价 + +### 4. 订单流程 + +1. 用户创建[`Order`](src/main/java/com/example/javatest/Entity/user/Order.java:21)记录 +2. 通过[`OrderList`](src/main/java/com/example/javatest/Entity/user/OrderList.java:20)记录订单明细 +3. 订单状态流转:待处理 → 已完成/已取消 + +### 5. 评价系统 + +1. 用户完成订单后可对菜品进行评价 +2. 通过[`Comment`](src/main/java/com/example/javatest/Entity/user/Comment.java:20)实体记录评价信息 +3. 支持评分和文字评价 +4. 支持评论回复功能 + +## 扩展性考虑 + +### 1. 多租户支持 + +当前设计通过分包实现了基础的多角色支持,未来可以考虑: +- 添加租户ID字段 +- 实现数据隔离机制 + +### 2. 缓存策略 + +对于频繁查询的实体(如菜品信息),可以考虑: +- Redis缓存热点数据 +- 实现缓存失效机制 + +### 3. 审计功能 + +当前的时间戳字段为审计功能提供了基础,可以进一步扩展: +- 操作人记录 +- 操作类型记录 +- 详细的变更历史 + +## 总结 + +本餐厅管理系统的实体类设计具有以下特点: + +1. **模块化设计**: 按角色分包,职责清晰 +2. **统一规范**: 使用一致的注解和命名规范 +3. **完整功能**: 覆盖餐厅业务的核心流程 +4. **扩展性好**: 预留了扩展字段和机制 +5. **数据安全**: 实现逻辑删除和时间戳管理 + +这种设计既满足了当前的业务需求,又为未来的功能扩展提供了良好的基础。通过MyBatis-Plus的强大功能,大大简化了数据访问层的开发工作。 \ No newline at end of file