From 532bf9633a0169fcd253d9dc6ad3ac26c74e9e97 Mon Sep 17 00:00:00 2001 From: Cxx0822 <1556464090@qq.com> Date: Tue, 24 Jun 2025 20:01:04 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E6=90=AD=E5=BB=BA=E5=B7=A5=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitattributes | 2 + .gitignore | 33 +++ .mvn/wrapper/maven-wrapper.properties | 19 ++ mvnw | 259 ++++++++++++++++++ mvnw.cmd | Bin 0 -> 7936 bytes pom.xml | 41 +++ .../cxx/food/FoodHubServiceApplication.java | 13 + .../cxx/food/controller/FoodController.java | 100 +++++++ .../food/controller/SessionController.java | 28 ++ src/main/java/com/cxx/food/dao/FoodDao.java | 33 +++ .../com/cxx/food/dto/FoodMaterialDto.java | 23 ++ .../java/com/cxx/food/dto/FoodRecipeDto.java | 43 +++ .../java/com/cxx/food/dto/FoodRecordDto.java | 32 +++ .../java/com/cxx/food/dto/FoodStatsDto.java | 19 ++ .../java/com/cxx/food/dto/FoodStepDto.java | 23 ++ .../java/com/cxx/food/dto/FoodSummaryDto.java | 26 ++ src/main/java/com/cxx/food/dto/PlainView.java | 4 + src/main/java/com/cxx/food/dto/ReadView.java | 4 + .../java/com/cxx/food/dto/SessionDto.java | 14 + src/main/java/com/cxx/food/dto/WriteView.java | 4 + .../com/cxx/food/entity/FoodMaterial.java | 24 ++ .../java/com/cxx/food/entity/FoodRecipe.java | 24 ++ .../java/com/cxx/food/entity/FoodRecord.java | 23 ++ .../java/com/cxx/food/entity/FoodStep.java | 24 ++ .../cxx/food/mapper/FoodMaterialMapper.java | 9 + .../com/cxx/food/mapper/FoodRecipeMapper.java | 9 + .../com/cxx/food/mapper/FoodRecordMapper.java | 9 + .../com/cxx/food/mapper/FoodStepMapper.java | 9 + .../com/cxx/food/service/FoodService.java | 37 +++ .../com/cxx/food/service/SessionService.java | 8 + .../food/service/impl/FoodServiceImpl.java | 200 ++++++++++++++ .../food/service/impl/SessionServiceImpl.java | 27 ++ .../java/com/cxx/food/vo/FoodQueryVo.java | 13 + src/main/resources/application-dev.yml | 10 + src/main/resources/application-docker.yml | 9 + src/main/resources/application-prod.yml | 10 + src/main/resources/application.yml | 23 ++ src/main/resources/mapper/FoodMapper.xml | 144 ++++++++++ .../food/FoodHubServiceApplicationTests.java | 13 + 39 files changed, 1345 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .mvn/wrapper/maven-wrapper.properties create mode 100644 mvnw create mode 100644 mvnw.cmd create mode 100644 pom.xml create mode 100644 src/main/java/com/cxx/food/FoodHubServiceApplication.java create mode 100644 src/main/java/com/cxx/food/controller/FoodController.java create mode 100644 src/main/java/com/cxx/food/controller/SessionController.java create mode 100644 src/main/java/com/cxx/food/dao/FoodDao.java create mode 100644 src/main/java/com/cxx/food/dto/FoodMaterialDto.java create mode 100644 src/main/java/com/cxx/food/dto/FoodRecipeDto.java create mode 100644 src/main/java/com/cxx/food/dto/FoodRecordDto.java create mode 100644 src/main/java/com/cxx/food/dto/FoodStatsDto.java create mode 100644 src/main/java/com/cxx/food/dto/FoodStepDto.java create mode 100644 src/main/java/com/cxx/food/dto/FoodSummaryDto.java create mode 100644 src/main/java/com/cxx/food/dto/PlainView.java create mode 100644 src/main/java/com/cxx/food/dto/ReadView.java create mode 100644 src/main/java/com/cxx/food/dto/SessionDto.java create mode 100644 src/main/java/com/cxx/food/dto/WriteView.java create mode 100644 src/main/java/com/cxx/food/entity/FoodMaterial.java create mode 100644 src/main/java/com/cxx/food/entity/FoodRecipe.java create mode 100644 src/main/java/com/cxx/food/entity/FoodRecord.java create mode 100644 src/main/java/com/cxx/food/entity/FoodStep.java create mode 100644 src/main/java/com/cxx/food/mapper/FoodMaterialMapper.java create mode 100644 src/main/java/com/cxx/food/mapper/FoodRecipeMapper.java create mode 100644 src/main/java/com/cxx/food/mapper/FoodRecordMapper.java create mode 100644 src/main/java/com/cxx/food/mapper/FoodStepMapper.java create mode 100644 src/main/java/com/cxx/food/service/FoodService.java create mode 100644 src/main/java/com/cxx/food/service/SessionService.java create mode 100644 src/main/java/com/cxx/food/service/impl/FoodServiceImpl.java create mode 100644 src/main/java/com/cxx/food/service/impl/SessionServiceImpl.java create mode 100644 src/main/java/com/cxx/food/vo/FoodQueryVo.java create mode 100644 src/main/resources/application-dev.yml create mode 100644 src/main/resources/application-docker.yml create mode 100644 src/main/resources/application-prod.yml create mode 100644 src/main/resources/application.yml create mode 100644 src/main/resources/mapper/FoodMapper.xml create mode 100644 src/test/java/com/cxx/food/FoodHubServiceApplicationTests.java 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..2f94e61 --- /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.10/apache-maven-3.9.10-bin.zip 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 0000000000000000000000000000000000000000..affc0ab1464a804492afdd4756fdf2bf5e068222 GIT binary patch literal 7936 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 literal 0 HcmV?d00001 diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..a894b0c --- /dev/null +++ b/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + + com.cxx + starter-parent + 2.0.0 + + + + food-hub-service + 0.0.1-SNAPSHOT + food-hub-service + food-hub-service + + + 17 + 17 + UTF-8 + + + + + com.cxx + starter-web + 2.0.0 + + + com.cxx + starter-jdbc + 2.0.0 + + + com.cxx + starter-logging + 2.0.0 + + + diff --git a/src/main/java/com/cxx/food/FoodHubServiceApplication.java b/src/main/java/com/cxx/food/FoodHubServiceApplication.java new file mode 100644 index 0000000..3626861 --- /dev/null +++ b/src/main/java/com/cxx/food/FoodHubServiceApplication.java @@ -0,0 +1,13 @@ +package com.cxx.food; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class FoodHubServiceApplication { + + public static void main(String[] args) { + SpringApplication.run(FoodHubServiceApplication.class, args); + } + +} diff --git a/src/main/java/com/cxx/food/controller/FoodController.java b/src/main/java/com/cxx/food/controller/FoodController.java new file mode 100644 index 0000000..9f677dd --- /dev/null +++ b/src/main/java/com/cxx/food/controller/FoodController.java @@ -0,0 +1,100 @@ +package com.cxx.food.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.cxx.food.dto.*; +import com.cxx.food.service.FoodService; +import com.cxx.food.vo.FoodQueryVo; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/food") +@Tag(name = "美食记录") +public class FoodController { + @Resource + private FoodService foodService; + + @Operation(summary = "新增美食菜谱") + @PostMapping("/recipe") + public Boolean addFoodRecipe(@RequestBody @JsonView(WriteView.class) @Validated FoodRecipeDto foodRecipeDto) { + return foodService.addFoodRecipe(foodRecipeDto); + } + + @Operation(summary = "更新美食菜谱") + @PutMapping("/recipe/{id}") + public Boolean updateFoodRecipe(@PathVariable("id") long id, + @RequestBody @JsonView(WriteView.class) FoodRecipeDto foodRecipeDto) { + return foodService.updateFoodRecipe(id, foodRecipeDto); + } + + @Operation(summary = "删除美食菜谱") + @DeleteMapping("/recipe/{id}") + public Boolean deleteFoodRecipe(@PathVariable("id") long id) { + return foodService.deleteFoodRecipe(id); + } + + @Operation(summary = "分页查询美食菜谱") + @GetMapping("/recipe/page") + public IPage queryFoodSummary(@RequestParam("currentPage") Integer currentPage, + @RequestParam("pageSize") Integer pageSize, + FoodQueryVo foodQueryVo) { + return foodService.queryFoodSummary(currentPage, pageSize, foodQueryVo); + } + + @Operation(summary = "查询美食") + @GetMapping("/recipe/{id}") + public @JsonView(ReadView.class) FoodRecipeDto queryFoodRecipe(@PathVariable("id") long id) { + return foodService.queryFoodRecipe(id); + } + + @Operation(summary = "查询所有美食名称") + @GetMapping("/recipe/name") + public List queryFoodName() { + return foodService.queryFoodName(); + } + + @Operation(summary = "新增美食成果") + @PostMapping("/record") + public Boolean addFoodRecord(@RequestBody @JsonView(WriteView.class) @Validated FoodRecordDto foodRecordDto) { + return foodService.addFoodRecord(foodRecordDto); + } + + @Operation(summary = "更新美食成果") + @PutMapping("/record/{id}") + public Boolean updateFoodRecord(@PathVariable("id") long id, + @RequestBody @JsonView(WriteView.class) FoodRecordDto foodRecordDto) { + return foodService.updateFoodRecord(id, foodRecordDto); + } + + @Operation(summary = "删除美食成果") + @DeleteMapping("/record/{id}") + public Boolean deleteFoodRecord(@PathVariable("id") long id) { + return foodService.deleteFoodRecord(id); + } + + @Operation(summary = "查询美食记录") + @GetMapping("/record") + public @JsonView(ReadView.class) List queryFoodRecord(@RequestParam("startDate") String startDate, + @RequestParam("endDate") String endDate) { + return foodService.queryFoodRecord(startDate, endDate); + } + + @Operation(summary = "查询美食类别") + @GetMapping("/category") + public List queryFoodCategory() { + return foodService.queryFoodCategory(); + } + + @Operation(summary = "查询美食统计") + @GetMapping("/stats") + public FoodStatsDto queryFoodStats() { + return foodService.queryFoodStats(); + } +} + \ No newline at end of file diff --git a/src/main/java/com/cxx/food/controller/SessionController.java b/src/main/java/com/cxx/food/controller/SessionController.java new file mode 100644 index 0000000..3c97247 --- /dev/null +++ b/src/main/java/com/cxx/food/controller/SessionController.java @@ -0,0 +1,28 @@ +package com.cxx.food.controller; + +import cn.dev33.satoken.annotation.SaIgnore; +import com.cxx.food.dto.SessionDto; +import com.cxx.food.service.SessionService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/session") +@Tag(name = "会话管理") +public class SessionController { + @Resource + private SessionService sessionService; + + @Operation(summary = "创建会话") + @PostMapping("") + @SaIgnore + public SessionDto createSession(@RequestParam("name") String name, + @RequestParam("password") String password) { + return sessionService.create(name, password); + } +} \ No newline at end of file diff --git a/src/main/java/com/cxx/food/dao/FoodDao.java b/src/main/java/com/cxx/food/dao/FoodDao.java new file mode 100644 index 0000000..e197b44 --- /dev/null +++ b/src/main/java/com/cxx/food/dao/FoodDao.java @@ -0,0 +1,33 @@ +package com.cxx.food.dao; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.cxx.food.dto.*; +import com.cxx.food.vo.FoodQueryVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface FoodDao { + FoodRecipeDto queryFoodRecipe(@Param("id") Long id); + + IPage queryFoodSummary(IPage page, + @Param("query") FoodQueryVo foodQueryVo); + + List queryFoodRecordById(@Param("id") Long id); + + List queryFoodRecord(@Param("startDate") String startDate, + @Param("endDate") String endDate); + + FoodStatsDto queryFoodStats(); + + List queryFoodCategory(); + + void insertFoodMaterial(@Param("foodId") Long foodId, + @Param("list") List list); + + void insertFoodStep(@Param("foodId") Long foodId, + @Param("list") List list); + +} diff --git a/src/main/java/com/cxx/food/dto/FoodMaterialDto.java b/src/main/java/com/cxx/food/dto/FoodMaterialDto.java new file mode 100644 index 0000000..12c8d84 --- /dev/null +++ b/src/main/java/com/cxx/food/dto/FoodMaterialDto.java @@ -0,0 +1,23 @@ +package com.cxx.food.dto; + +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@JsonView(PlainView.class) +public class FoodMaterialDto { + @Schema(description = "id") + private Long id; + + @Schema(description = "食材类型") + private String type; + + @Schema(description = "食材名称") + private String name; + + @Schema(description = "食材分量") + private String amount; +} diff --git a/src/main/java/com/cxx/food/dto/FoodRecipeDto.java b/src/main/java/com/cxx/food/dto/FoodRecipeDto.java new file mode 100644 index 0000000..4b2075c --- /dev/null +++ b/src/main/java/com/cxx/food/dto/FoodRecipeDto.java @@ -0,0 +1,43 @@ +package com.cxx.food.dto; + +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.validator.constraints.Range; + +import java.util.List; + +@Getter +@Setter +@JsonView(PlainView.class) +public class FoodRecipeDto { + @Schema(description = "id") + @JsonView(ReadView.class) + private Long id; + + @Schema(description = "美食名称") + @NotBlank(message = "名称不能为空") + private String name; + + @Schema(description = "美食菜系") + private String category; + + @Schema(description = "推荐指数") + @Range(min = 0, max = 5, message = "推荐指数在0-5之间") + private Integer recommendRate; + + @Schema(description = "美食食材") + private List materialList; + + @Schema(description = "美食步骤") + private List stepList; + + @Schema(description = "美食成果") + @JsonView(ReadView.class) + private List recordList; + + @Schema(description = "备注") + private String remark; +} diff --git a/src/main/java/com/cxx/food/dto/FoodRecordDto.java b/src/main/java/com/cxx/food/dto/FoodRecordDto.java new file mode 100644 index 0000000..dc726c6 --- /dev/null +++ b/src/main/java/com/cxx/food/dto/FoodRecordDto.java @@ -0,0 +1,32 @@ +package com.cxx.food.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; + +@Getter +@Setter +@JsonView(PlainView.class) +public class FoodRecordDto { + @Schema(description = "id") + @JsonView(ReadView.class) + private Long id; + + @Schema(description = "名称") + private String name; + + @Schema(description = "分类") + @JsonView(ReadView.class) + private String category; + + @Schema(description = "完成时间") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date date; + + @Schema(description = "成果图片") + private String imageUrl; +} diff --git a/src/main/java/com/cxx/food/dto/FoodStatsDto.java b/src/main/java/com/cxx/food/dto/FoodStatsDto.java new file mode 100644 index 0000000..c97a0cd --- /dev/null +++ b/src/main/java/com/cxx/food/dto/FoodStatsDto.java @@ -0,0 +1,19 @@ +package com.cxx.food.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + + +@Getter +@Setter +public class FoodStatsDto { + @Schema(description = "菜谱总数") + private Integer recipeCount; + + @Schema(description = "菜谱类别") + private Integer categoryCount; + + @Schema(description = "做菜次数") + private Integer workCount; +} diff --git a/src/main/java/com/cxx/food/dto/FoodStepDto.java b/src/main/java/com/cxx/food/dto/FoodStepDto.java new file mode 100644 index 0000000..12a5181 --- /dev/null +++ b/src/main/java/com/cxx/food/dto/FoodStepDto.java @@ -0,0 +1,23 @@ +package com.cxx.food.dto; + +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@JsonView(PlainView.class) +public class FoodStepDto { + @Schema(description = "id") + private Long id; + + @Schema(description = "顺序") + private Integer sort; + + @Schema(description = "步骤内容") + private String content; + + @Schema(description = "步骤图片") + private String imageUrl; +} diff --git a/src/main/java/com/cxx/food/dto/FoodSummaryDto.java b/src/main/java/com/cxx/food/dto/FoodSummaryDto.java new file mode 100644 index 0000000..415b965 --- /dev/null +++ b/src/main/java/com/cxx/food/dto/FoodSummaryDto.java @@ -0,0 +1,26 @@ +package com.cxx.food.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class FoodSummaryDto { + @Schema(description = "id") + private Long id; + + @Schema(description = "美食名称") + private String name; + + @Schema(description = "美食类型") + private String category; + + @Schema(description = "推荐指数") + private Integer recommendRate; + + @Schema(description = "美食记录") + private List recordList; +} diff --git a/src/main/java/com/cxx/food/dto/PlainView.java b/src/main/java/com/cxx/food/dto/PlainView.java new file mode 100644 index 0000000..98ba65c --- /dev/null +++ b/src/main/java/com/cxx/food/dto/PlainView.java @@ -0,0 +1,4 @@ +package com.cxx.food.dto; + +public interface PlainView { +} diff --git a/src/main/java/com/cxx/food/dto/ReadView.java b/src/main/java/com/cxx/food/dto/ReadView.java new file mode 100644 index 0000000..52193aa --- /dev/null +++ b/src/main/java/com/cxx/food/dto/ReadView.java @@ -0,0 +1,4 @@ +package com.cxx.food.dto; + +public interface ReadView extends PlainView { +} diff --git a/src/main/java/com/cxx/food/dto/SessionDto.java b/src/main/java/com/cxx/food/dto/SessionDto.java new file mode 100644 index 0000000..1d33b24 --- /dev/null +++ b/src/main/java/com/cxx/food/dto/SessionDto.java @@ -0,0 +1,14 @@ +package com.cxx.food.dto; + +import cn.dev33.satoken.stp.SaTokenInfo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class SessionDto { + @Schema(description = "令牌") + private SaTokenInfo saToken; +} + diff --git a/src/main/java/com/cxx/food/dto/WriteView.java b/src/main/java/com/cxx/food/dto/WriteView.java new file mode 100644 index 0000000..db46985 --- /dev/null +++ b/src/main/java/com/cxx/food/dto/WriteView.java @@ -0,0 +1,4 @@ +package com.cxx.food.dto; + +public interface WriteView extends PlainView { +} diff --git a/src/main/java/com/cxx/food/entity/FoodMaterial.java b/src/main/java/com/cxx/food/entity/FoodMaterial.java new file mode 100644 index 0000000..586cec0 --- /dev/null +++ b/src/main/java/com/cxx/food/entity/FoodMaterial.java @@ -0,0 +1,24 @@ +package com.cxx.food.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractIdEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("food_material") +public class FoodMaterial extends AbstractIdEntity { + @TableField("food_id") + private Long foodId; + + @TableField("type") + private String type; + + @TableField("name") + private String name; + + @TableField("amount") + private String amount; +} diff --git a/src/main/java/com/cxx/food/entity/FoodRecipe.java b/src/main/java/com/cxx/food/entity/FoodRecipe.java new file mode 100644 index 0000000..4da96a7 --- /dev/null +++ b/src/main/java/com/cxx/food/entity/FoodRecipe.java @@ -0,0 +1,24 @@ +package com.cxx.food.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("food_recipe") +public class FoodRecipe extends AbstractEntity { + @TableField("name") + private String name; + + @TableField("category") + private String category; + + @TableField("recommend_rate") + private Integer recommendRate; + + @TableField("remark") + private String remark; +} diff --git a/src/main/java/com/cxx/food/entity/FoodRecord.java b/src/main/java/com/cxx/food/entity/FoodRecord.java new file mode 100644 index 0000000..09b5846 --- /dev/null +++ b/src/main/java/com/cxx/food/entity/FoodRecord.java @@ -0,0 +1,23 @@ +package com.cxx.food.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractIdEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("food_record") +public class FoodRecord extends AbstractIdEntity { + @TableField("food_id") + private Long foodId; + + @TableField("date") + private Date date; + + @TableField("image_url") + private String imageUrl; +} diff --git a/src/main/java/com/cxx/food/entity/FoodStep.java b/src/main/java/com/cxx/food/entity/FoodStep.java new file mode 100644 index 0000000..7943a7e --- /dev/null +++ b/src/main/java/com/cxx/food/entity/FoodStep.java @@ -0,0 +1,24 @@ +package com.cxx.food.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractIdEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("food_step") +public class FoodStep extends AbstractIdEntity { + @TableField("food_id") + private Long foodId; + + @TableField("sort") + private Integer sort; + + @TableField("content") + private String content; + + @TableField("image_url") + private String imageUrl; +} diff --git a/src/main/java/com/cxx/food/mapper/FoodMaterialMapper.java b/src/main/java/com/cxx/food/mapper/FoodMaterialMapper.java new file mode 100644 index 0000000..4e75817 --- /dev/null +++ b/src/main/java/com/cxx/food/mapper/FoodMaterialMapper.java @@ -0,0 +1,9 @@ +package com.cxx.food.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.food.entity.FoodMaterial; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface FoodMaterialMapper extends BaseMapper { +} \ No newline at end of file diff --git a/src/main/java/com/cxx/food/mapper/FoodRecipeMapper.java b/src/main/java/com/cxx/food/mapper/FoodRecipeMapper.java new file mode 100644 index 0000000..6b326d8 --- /dev/null +++ b/src/main/java/com/cxx/food/mapper/FoodRecipeMapper.java @@ -0,0 +1,9 @@ +package com.cxx.food.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.food.entity.FoodRecipe; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface FoodRecipeMapper extends BaseMapper { +} \ No newline at end of file diff --git a/src/main/java/com/cxx/food/mapper/FoodRecordMapper.java b/src/main/java/com/cxx/food/mapper/FoodRecordMapper.java new file mode 100644 index 0000000..65f27b1 --- /dev/null +++ b/src/main/java/com/cxx/food/mapper/FoodRecordMapper.java @@ -0,0 +1,9 @@ +package com.cxx.food.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.food.entity.FoodRecord; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface FoodRecordMapper extends BaseMapper { +} \ No newline at end of file diff --git a/src/main/java/com/cxx/food/mapper/FoodStepMapper.java b/src/main/java/com/cxx/food/mapper/FoodStepMapper.java new file mode 100644 index 0000000..d603630 --- /dev/null +++ b/src/main/java/com/cxx/food/mapper/FoodStepMapper.java @@ -0,0 +1,9 @@ +package com.cxx.food.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.food.entity.FoodStep; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface FoodStepMapper extends BaseMapper { +} \ No newline at end of file diff --git a/src/main/java/com/cxx/food/service/FoodService.java b/src/main/java/com/cxx/food/service/FoodService.java new file mode 100644 index 0000000..a65de7a --- /dev/null +++ b/src/main/java/com/cxx/food/service/FoodService.java @@ -0,0 +1,37 @@ +package com.cxx.food.service; + + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.cxx.food.dto.FoodRecipeDto; +import com.cxx.food.dto.FoodRecordDto; +import com.cxx.food.dto.FoodStatsDto; +import com.cxx.food.dto.FoodSummaryDto; +import com.cxx.food.vo.FoodQueryVo; + +import java.util.List; + +public interface FoodService { + Boolean addFoodRecipe(FoodRecipeDto foodRecipeDto); + + Boolean updateFoodRecipe(Long id, FoodRecipeDto foodRecipeDto); + + Boolean deleteFoodRecipe(Long id); + + Boolean addFoodRecord(FoodRecordDto foodRecordDto); + + Boolean updateFoodRecord(Long id, FoodRecordDto foodRecordDto); + + Boolean deleteFoodRecord(Long id); + + FoodRecipeDto queryFoodRecipe(Long id); + + IPage queryFoodSummary(Integer currentPage, Integer pageSize, FoodQueryVo foodQueryVo); + + List queryFoodRecord(String startDate, String endDate); + + List queryFoodName(); + + List queryFoodCategory(); + + FoodStatsDto queryFoodStats(); +} diff --git a/src/main/java/com/cxx/food/service/SessionService.java b/src/main/java/com/cxx/food/service/SessionService.java new file mode 100644 index 0000000..4f05d46 --- /dev/null +++ b/src/main/java/com/cxx/food/service/SessionService.java @@ -0,0 +1,8 @@ +package com.cxx.food.service; + + +import com.cxx.food.dto.SessionDto; + +public interface SessionService { + SessionDto create(String name, String password); +} diff --git a/src/main/java/com/cxx/food/service/impl/FoodServiceImpl.java b/src/main/java/com/cxx/food/service/impl/FoodServiceImpl.java new file mode 100644 index 0000000..a0134fd --- /dev/null +++ b/src/main/java/com/cxx/food/service/impl/FoodServiceImpl.java @@ -0,0 +1,200 @@ +package com.cxx.food.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.cxx.food.dao.FoodDao; +import com.cxx.food.dto.*; +import com.cxx.food.entity.FoodMaterial; +import com.cxx.food.entity.FoodRecipe; +import com.cxx.food.entity.FoodRecord; +import com.cxx.food.entity.FoodStep; +import com.cxx.food.mapper.FoodMaterialMapper; +import com.cxx.food.mapper.FoodRecipeMapper; +import com.cxx.food.mapper.FoodRecordMapper; +import com.cxx.food.mapper.FoodStepMapper; +import com.cxx.food.service.FoodService; +import com.cxx.food.vo.FoodQueryVo; +import com.cxx.framework.web.CustomException; +import com.github.yitter.idgen.YitIdHelper; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class FoodServiceImpl implements FoodService { + @Resource + private FoodDao foodDao; + + @Resource + private FoodRecipeMapper foodRecipeMapper; + + @Resource + private FoodMaterialMapper foodMaterialMapper; + + @Resource + private FoodStepMapper foodStepMapper; + + @Resource + private FoodRecordMapper foodRecordMapper; + + @Override + @Transactional + public Boolean addFoodRecipe(FoodRecipeDto foodRecipeDto) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if (foodRecipeMapper.exists(queryWrapper.eq(FoodRecipe::getName, foodRecipeDto.getName()))) { + throw new CustomException("该菜谱已经存在"); + } + + FoodRecipe foodRecipe = new FoodRecipe(); + BeanUtils.copyProperties(foodRecipeDto, foodRecipe); + foodRecipeMapper.insert(foodRecipe); + resetFoodRecipe(foodRecipe.getId(), foodRecipeDto); + + return Boolean.TRUE; + } + + @Override + @Transactional + public Boolean updateFoodRecipe(Long id, FoodRecipeDto foodRecipeDto) { + if (foodRecipeMapper.selectById(id) == null) { + throw new CustomException("该菜谱不存在"); + } + + FoodRecipe foodRecipe = new FoodRecipe(); + BeanUtils.copyProperties(foodRecipeDto, foodRecipe); + foodRecipe.setId(id); + foodRecipeMapper.updateById(foodRecipe); + resetFoodRecipe(foodRecipe.getId(), foodRecipeDto); + + return Boolean.TRUE; + } + + @Override + @Transactional + public Boolean deleteFoodRecipe(Long id) { + foodRecipeMapper.deleteById(id); + foodMaterialMapper.delete(Wrappers.lambdaQuery(FoodMaterial.class).eq(FoodMaterial::getFoodId, id)); + foodStepMapper.delete(Wrappers.lambdaQuery(FoodStep.class).eq(FoodStep::getFoodId, id)); + foodRecordMapper.delete(Wrappers.lambdaQuery(FoodRecord.class).eq(FoodRecord::getFoodId, id)); + + return Boolean.TRUE; + } + + @Override + public Boolean addFoodRecord(FoodRecordDto foodRecordDto) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + FoodRecipe foodRecipe = foodRecipeMapper.selectOne(queryWrapper.eq(FoodRecipe::getName, foodRecordDto.getName())); + if (foodRecipe == null) { + throw new CustomException("该菜谱不存在"); + } + + FoodRecord foodRecord = new FoodRecord(); + foodRecord.setFoodId(foodRecipe.getId()); + BeanUtils.copyProperties(foodRecordDto, foodRecord); + foodRecordMapper.insert(foodRecord); + + return Boolean.TRUE; + } + + @Override + public Boolean updateFoodRecord(Long id, FoodRecordDto foodRecordDto) { + if (foodRecordMapper.selectById(id) == null) { + throw new CustomException("该成果不存在"); + } + + FoodRecord foodRecord = new FoodRecord(); + BeanUtils.copyProperties(foodRecordDto, foodRecord); + foodRecord.setId(id); + foodRecordMapper.updateById(foodRecord); + + return Boolean.TRUE; + } + + @Override + public Boolean deleteFoodRecord(Long id) { + foodRecordMapper.deleteById(id); + + return Boolean.TRUE; + } + + private void resetFoodRecipe(Long id, FoodRecipeDto foodRecipeDto) { + foodMaterialMapper.delete(Wrappers.lambdaQuery(FoodMaterial.class).eq(FoodMaterial::getFoodId, id)); + foodStepMapper.delete(Wrappers.lambdaQuery(FoodStep.class).eq(FoodStep::getFoodId, id)); + + insertFoodMaterial(id, foodRecipeDto.getMaterialList()); + insertFoodStep(id, foodRecipeDto.getStepList()); + } + + private void insertFoodMaterial(Long foodId, List foodMaterialList) { + if (foodMaterialList.isEmpty()) { + return; + } + + foodMaterialList.forEach((item) -> { + item.setId(YitIdHelper.nextId()); + }); + foodDao.insertFoodMaterial(foodId, foodMaterialList); + } + + private void insertFoodStep(Long foodId, List foodStepList) { + if (foodStepList.isEmpty()) { + return; + } + + foodStepList.forEach((item) -> { + item.setId(YitIdHelper.nextId()); + }); + foodDao.insertFoodStep(foodId, foodStepList); + } + + @Override + public FoodRecipeDto queryFoodRecipe(Long id) { + if (foodRecipeMapper.selectById(id) == null) { + throw new CustomException("该美食不存在"); + } + + return foodDao.queryFoodRecipe(id); + } + + @Override + public IPage queryFoodSummary(Integer currentPage, Integer pageSize, FoodQueryVo foodQueryVo) { + // 这里只能先对主表进行分页 然后在查询子表信息 + // 不能使用Left Join关联表查询,因为这里是一对多数据,关联查询会导致数据有重复 + // 从而导致page计算错误(会把重复的数据当成多条记录,实际上只有1条记录) + IPage foodSummaryPage = foodDao.queryFoodSummary(new Page<>(currentPage, pageSize), foodQueryVo); + List foodSummaryList = foodSummaryPage.getRecords(); + for (FoodSummaryDto foodSummary : foodSummaryList) { + foodSummary.setRecordList(foodDao.queryFoodRecordById(foodSummary.getId())); + } + + foodSummaryPage.setRecords(foodSummaryList); + return foodSummaryPage; + } + + @Override + public List queryFoodRecord(String startDate, String endDate) { + return foodDao.queryFoodRecord(startDate, endDate); + } + + @Override + public List queryFoodName() { + return foodRecipeMapper.selectList(null) + .stream().map(FoodRecipe::getName).collect(Collectors.toList()); + } + + @Override + public List queryFoodCategory() { + return foodDao.queryFoodCategory(); + } + + @Override + public FoodStatsDto queryFoodStats() { + return foodDao.queryFoodStats(); + } +} diff --git a/src/main/java/com/cxx/food/service/impl/SessionServiceImpl.java b/src/main/java/com/cxx/food/service/impl/SessionServiceImpl.java new file mode 100644 index 0000000..132d4c7 --- /dev/null +++ b/src/main/java/com/cxx/food/service/impl/SessionServiceImpl.java @@ -0,0 +1,27 @@ +package com.cxx.food.service.impl; + + +import cn.dev33.satoken.secure.BCrypt; +import cn.dev33.satoken.stp.StpUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.cxx.food.dto.SessionDto; +import com.cxx.food.service.SessionService; +import com.cxx.framework.web.CustomException; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + + +@Service +public class SessionServiceImpl implements SessionService { + + @Override + public SessionDto create(String name, String password) { + SessionDto sessionDto = new SessionDto(); + StpUtil.login(name); + sessionDto.setSaToken(StpUtil.getTokenInfo()); + + return sessionDto; + } +} diff --git a/src/main/java/com/cxx/food/vo/FoodQueryVo.java b/src/main/java/com/cxx/food/vo/FoodQueryVo.java new file mode 100644 index 0000000..a3f3156 --- /dev/null +++ b/src/main/java/com/cxx/food/vo/FoodQueryVo.java @@ -0,0 +1,13 @@ + +package com.cxx.food.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class FoodQueryVo { + @Schema(description = "美食类别") + private String category; +} \ No newline at end of file diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml new file mode 100644 index 0000000..82d908c --- /dev/null +++ b/src/main/resources/application-dev.yml @@ -0,0 +1,10 @@ +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://127.0.0.1:3306/sweet_hut?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=false + username: cxx + password: 123456 + +file: + path: D:\\temp\\ + log-path: D:\\temp\\ \ No newline at end of file diff --git a/src/main/resources/application-docker.yml b/src/main/resources/application-docker.yml new file mode 100644 index 0000000..dafb638 --- /dev/null +++ b/src/main/resources/application-docker.yml @@ -0,0 +1,9 @@ +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://mysql:3306/sweet_hut?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=false + username: docker + password: 19940822Cxx + +file: + path: /upload-file/ \ No newline at end of file diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml new file mode 100644 index 0000000..0bdcd3b --- /dev/null +++ b/src/main/resources/application-prod.yml @@ -0,0 +1,10 @@ +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://127.0.0.1:3306/sweet_hut?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=false + username: cxx + password: 19940822Cxx@1213 + +file: + path: /root/docker/upload-file/ + log-path: /root/service/logs/ \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..3bb8bc7 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,23 @@ +server: + port: 8090 + +spring: + application: + name: @project.artifactId@ + version: @project.version@ + profiles: + active: dev + +# mybatis plus mapper路径 +mybatis-plus: + # mybatis plus + mapper-locations: classpath*:/mapper/**/*.xml + configuration: + log-impl: + org.apache.ibatis.logging.stdout.StdOutImpl + +web-starter: + base-package: com.cxx.food + +aes: + secret-key: "sG5p7t9wBdKnPqRsUvYx2D5F8H9JmQ=2" diff --git a/src/main/resources/mapper/FoodMapper.xml b/src/main/resources/mapper/FoodMapper.xml new file mode 100644 index 0000000..e360486 --- /dev/null +++ b/src/main/resources/mapper/FoodMapper.xml @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO food_material (id, food_id, type, name, amount) VALUES + + (#{item.id}, #{foodId}, #{item.type}, #{item.name}, #{item.amount}) + + + + + INSERT INTO food_step (id, food_id, sort, content, image_url) VALUES + + (#{item.id}, #{foodId}, #{item.sort}, #{item.content}, #{item.imageUrl}) + + + diff --git a/src/test/java/com/cxx/food/FoodHubServiceApplicationTests.java b/src/test/java/com/cxx/food/FoodHubServiceApplicationTests.java new file mode 100644 index 0000000..b4c7e17 --- /dev/null +++ b/src/test/java/com/cxx/food/FoodHubServiceApplicationTests.java @@ -0,0 +1,13 @@ +package com.cxx.food; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class FoodHubServiceApplicationTests { + + @Test + void contextLoads() { + } + +}