commit 9c71055e85d214f6efcc748be1cc031b462f1965 Author: wucongxing8150 <815046773@qq.com> Date: Mon May 12 13:28:44 2025 +0800 1 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..28316e7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,47 @@ +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/ +/logs +*.log +*.class +*.ctxt +.mtj.tmp/ +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar +hs_err_pid* +replay_pid* \ No newline at end of file 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/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b4a15ce --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +# 基础镜像 +FROM openjdk:17-jdk-alpine +LABEL authors="wucongxing" + +# 工作目录 +WORKDIR /app + +# 复制jar包 +COPY target/caseData.jar /app/app.jar + +# 暴露端口 +EXPOSE 8080 + +# 启动命令 +ENTRYPOINT ["java", "-jar", "/app/app.jar"] \ No newline at end of file diff --git a/mvnw b/mvnw new file mode 100755 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..9cab10f --- /dev/null +++ b/pom.xml @@ -0,0 +1,163 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.4.3 + + + com.example + caseData + 0.0.1-SNAPSHOT + war + caseData + 病例库 + + + + + + + + + + + + + + + 23 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.projectlombok + lombok + 1.18.30 + provided + + + + org.jetbrains + annotations + 13.0 + compile + + + + + mysql + mysql-connector-java + 8.0.33 + + + + + com.baomidou + mybatis-plus-spring-boot3-starter + 3.5.7 + + + com.baomidou + mybatis-plus-generator + 3.5.3.1 + + + org.freemarker + freemarker + 2.3.33 + + + + + org.springframework.boot + spring-boot-starter-validation + + + + + com.aliyun.oss + aliyun-sdk-oss + 3.17.4 + + + + + io.jsonwebtoken + jjwt + 0.9.1 + + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + + org.springframework.boot + spring-boot-starter-freemarker + + + + + com.github.binarywang + weixin-java-miniapp + 4.7.0 + + + + + cn.hutool + hutool-all + 5.8.24 + + + + + com.fasterxml.jackson.core + jackson-databind + 2.16.1 + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + 2.16.1 + + + + + p6spy + p6spy + 3.9.1 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/src/main/.DS_Store b/src/main/.DS_Store new file mode 100644 index 0000000..58bc5be Binary files /dev/null and b/src/main/.DS_Store differ diff --git a/src/main/java/.DS_Store b/src/main/java/.DS_Store new file mode 100644 index 0000000..4e895f7 Binary files /dev/null and b/src/main/java/.DS_Store differ diff --git a/src/main/java/com/.DS_Store b/src/main/java/com/.DS_Store new file mode 100644 index 0000000..9c233c0 Binary files /dev/null and b/src/main/java/com/.DS_Store differ diff --git a/src/main/java/com/example/.DS_Store b/src/main/java/com/example/.DS_Store new file mode 100644 index 0000000..ed9017d Binary files /dev/null and b/src/main/java/com/example/.DS_Store differ diff --git a/src/main/java/com/example/caseData/CaseDataApplication.java b/src/main/java/com/example/caseData/CaseDataApplication.java new file mode 100644 index 0000000..9d55f2d --- /dev/null +++ b/src/main/java/com/example/caseData/CaseDataApplication.java @@ -0,0 +1,15 @@ +package com.example.caseData; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@MapperScan("com.example.caseData.dao") +public class CaseDataApplication { + + public static void main(String[] args) { + SpringApplication.run(CaseDataApplication.class, args); + } + +} diff --git a/src/main/java/com/example/caseData/ServletInitializer.java b/src/main/java/com/example/caseData/ServletInitializer.java new file mode 100644 index 0000000..c19c7a6 --- /dev/null +++ b/src/main/java/com/example/caseData/ServletInitializer.java @@ -0,0 +1,13 @@ +package com.example.caseData; + +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +public class ServletInitializer extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(CaseDataApplication.class); + } + +} diff --git a/src/main/java/com/example/caseData/common/Response.java b/src/main/java/com/example/caseData/common/Response.java new file mode 100644 index 0000000..64cea5d --- /dev/null +++ b/src/main/java/com/example/caseData/common/Response.java @@ -0,0 +1,61 @@ +package com.example.caseData.common; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.HashMap; +import java.util.Map; + +/** + * 返回方法 + * @param + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Response { + private static final int SUCCESS_CODE = 200; + private static final int ERROR_CODE = -1; + + private int code; // 状态码 + private T data; // 返回数据 + private String message; // 消息 + + public static Response success() { + return new Response<>(SUCCESS_CODE, null, "成功"); + } + + public static Response success(String message) { + return new Response<>(SUCCESS_CODE, null, message); + } + + public static Response success(T data) { + return new Response<>(SUCCESS_CODE, data, "成功"); + } + + public static Response success(T data, String message) { + return new Response<>(SUCCESS_CODE, data, message); + } + + public static Response success(int code, T data, String message) { + return new Response<>(code, data, message); + } + + public static Response error() { + return new Response<>(ERROR_CODE, null, "失败"); + } + + public static Response error(String message) { + return new Response<>(ERROR_CODE, null, message); + } + + public static Response error(T data, String message) { + return new Response<>(ERROR_CODE, data, message); + } + + public static Response error(int code, T data, String message) { + return new Response<>(code, data, message); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/config/AppConfig.java b/src/main/java/com/example/caseData/config/AppConfig.java new file mode 100644 index 0000000..4bd16d4 --- /dev/null +++ b/src/main/java/com/example/caseData/config/AppConfig.java @@ -0,0 +1,21 @@ +package com.example.caseData.config; + +import lombok.Getter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +@Getter +public class AppConfig { + @Value("${app.apiUrl}") + private String apiUrl; + + @Value("${app.secretKey}") + private String secretKey; + + @Value("${app.imagePrefix}") + private String imagePrefix; + + @Value("${app.platform}") + private String platform; +} diff --git a/src/main/java/com/example/caseData/config/EnvConfig.java b/src/main/java/com/example/caseData/config/EnvConfig.java new file mode 100644 index 0000000..d97cebe --- /dev/null +++ b/src/main/java/com/example/caseData/config/EnvConfig.java @@ -0,0 +1,12 @@ +package com.example.caseData.config; + +import lombok.Getter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +@Getter +public class EnvConfig { + @Value("${spring.profiles.active}") + private String active; +} diff --git a/src/main/java/com/example/caseData/config/JwtConfig.java b/src/main/java/com/example/caseData/config/JwtConfig.java new file mode 100644 index 0000000..dc203e3 --- /dev/null +++ b/src/main/java/com/example/caseData/config/JwtConfig.java @@ -0,0 +1,18 @@ +package com.example.caseData.config; + +import lombok.Getter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +@Getter +public class JwtConfig { + @Value("${jwt.sign-key}") + private String signKey; + + @Value("${jwt.ttl}") + private Integer ttl; + + @Value("${jwt.algo}") + private String algo; +} diff --git a/src/main/java/com/example/caseData/config/OssConfig.java b/src/main/java/com/example/caseData/config/OssConfig.java new file mode 100644 index 0000000..a63bdca --- /dev/null +++ b/src/main/java/com/example/caseData/config/OssConfig.java @@ -0,0 +1,25 @@ +package com.example.caseData.config; + +import lombok.Getter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +@Getter +public class OssConfig { + @Value("${oss.access-key}") + private String accessKey; + + @Value("${oss.access-key-secret}") + private String accessKeySecret; + + @Value("${oss.bucket}") + private String bucket; + + @Value("${oss.endpoint}") + private String endpoint; + + @Value("${oss.custom-domain-name}") + private String customDomainName; + +} diff --git a/src/main/java/com/example/caseData/config/WxMaConfig.java b/src/main/java/com/example/caseData/config/WxMaConfig.java new file mode 100644 index 0000000..10615a9 --- /dev/null +++ b/src/main/java/com/example/caseData/config/WxMaConfig.java @@ -0,0 +1,15 @@ +package com.example.caseData.config; + +import lombok.Getter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +@Getter +public class WxMaConfig { + @Value("${wechat.miniapp.appid}") + private String appid; + + @Value("${wechat.miniapp.secret}") + private String secret; +} diff --git a/src/main/java/com/example/caseData/controller/BaseController.java b/src/main/java/com/example/caseData/controller/BaseController.java new file mode 100644 index 0000000..af6b76a --- /dev/null +++ b/src/main/java/com/example/caseData/controller/BaseController.java @@ -0,0 +1,12 @@ +package com.example.caseData.controller; + +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +public abstract class BaseController { + @Resource + protected HttpServletRequest request; +} diff --git a/src/main/java/com/example/caseData/controller/CaseClinicalArticleController.java b/src/main/java/com/example/caseData/controller/CaseClinicalArticleController.java new file mode 100644 index 0000000..d7925e1 --- /dev/null +++ b/src/main/java/com/example/caseData/controller/CaseClinicalArticleController.java @@ -0,0 +1,76 @@ +package com.example.caseData.controller; + +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.caseData.common.Response; +import com.example.caseData.dao.*; +import com.example.caseData.dto.basicHospital.BasicHospitalDto; +import com.example.caseData.dto.caseClinicalArticle.CaseClinicalArticleDto; +import com.example.caseData.dto.statsCaseClinicalHospital.StatsCaseClinicalHospitalDto; +import com.example.caseData.model.BasicHospitalModel; +import com.example.caseData.model.CaseClinicalArticleAuthorModel; +import com.example.caseData.model.CaseClinicalArticleModel; +import com.example.caseData.model.CaseClinicalDoctorModel; +import com.example.caseData.request.clinicalRequest.getClinicalHospitalSearchPage; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@RestController +@RequestMapping("/api") +public class CaseClinicalArticleController { + @Resource + private CaseClinicalArticleDao caseClinicalArticleDao; + + @Resource + private CaseClinicalArticleAuthorDao caseClinicalArticleAuthorDao; + + @Resource + private StatsCaseClinicalDoctorDao statsCaseClinicalDoctorDao; + + @Resource + private CaseClinicalDoctorDao caseClinicalDoctorDao; + + @Resource + private BasicHospitalDao basicHospitalDao; + + /** + * 临床病例库-文章-详情 + */ + @GetMapping("/clinical/article/{article_id}") + public Response getClinicalHospitalSearchPage( + @PathVariable("article_id") String articleId + ) { + + // 获取文章数据 + CaseClinicalArticleModel article = caseClinicalArticleDao.selectById(articleId); + if (article == null) { + return Response.error("非法文章"); + } + + // 查找作者 + LambdaQueryWrapper authorQueryWrapper = new LambdaQueryWrapper<>(); + authorQueryWrapper.eq(CaseClinicalArticleAuthorModel::getArticleId, article.getArticleId()); + List caseClinicalArticleAuthors = caseClinicalArticleAuthorDao.selectList(authorQueryWrapper); + for (CaseClinicalArticleAuthorModel author : caseClinicalArticleAuthors) { + // 查询医生 + CaseClinicalDoctorModel caseClinicalDoctor = caseClinicalDoctorDao.selectById(author.getDoctorId()); + + // 查询医生所属医院 + BasicHospitalModel basicHospital = basicHospitalDao.selectById(caseClinicalDoctor.getHospitalId()); + caseClinicalDoctor.setBasicHospital(basicHospital); + + author.setCaseClinicalDoctor(caseClinicalDoctor); + } + + article.setAuthor(caseClinicalArticleAuthors); + + CaseClinicalArticleDto g = CaseClinicalArticleDto.GetDto(article); + return Response.success(g); + } +} diff --git a/src/main/java/com/example/caseData/controller/CaseClinicalVideoController.java b/src/main/java/com/example/caseData/controller/CaseClinicalVideoController.java new file mode 100644 index 0000000..a6b1223 --- /dev/null +++ b/src/main/java/com/example/caseData/controller/CaseClinicalVideoController.java @@ -0,0 +1,70 @@ +package com.example.caseData.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.example.caseData.common.Response; +import com.example.caseData.dao.*; +import com.example.caseData.dto.caseClinicalVideo.CaseClinicalVideoDto; +import com.example.caseData.model.BasicHospitalModel; +import com.example.caseData.model.CaseClinicalVideoAuthorModel; +import com.example.caseData.model.CaseClinicalVideoModel; +import com.example.caseData.model.CaseClinicalDoctorModel; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +@RequestMapping("/api") +public class CaseClinicalVideoController { + @Resource + private CaseClinicalVideoDao caseClinicalVideoDao; + + @Resource + private CaseClinicalVideoAuthorDao caseClinicalVideoAuthorDao; + + @Resource + private StatsCaseClinicalDoctorDao statsCaseClinicalDoctorDao; + + @Resource + private CaseClinicalDoctorDao caseClinicalDoctorDao; + + @Resource + private BasicHospitalDao basicHospitalDao; + + /** + * 临床病例库-视频-详情 + */ + @GetMapping("/clinical/video/{video_id}") + public Response getClinicalHospitalSearchPage( + @PathVariable("video_id") String videoId + ) { + // 获取视频数据 + CaseClinicalVideoModel article = caseClinicalVideoDao.selectById(videoId); + if (article == null) { + return Response.error("非法视频"); + } + + // 查找作者 + LambdaQueryWrapper authorQueryWrapper = new LambdaQueryWrapper<>(); + authorQueryWrapper.eq(CaseClinicalVideoAuthorModel::getVideoId, article.getVideoId()); + List caseClinicalVideoAuthors = caseClinicalVideoAuthorDao.selectList(authorQueryWrapper); + for (CaseClinicalVideoAuthorModel author : caseClinicalVideoAuthors) { + // 查询医生 + CaseClinicalDoctorModel caseClinicalDoctor = caseClinicalDoctorDao.selectById(author.getDoctorId()); + + // 查询医生所属医院 + BasicHospitalModel basicHospital = basicHospitalDao.selectById(caseClinicalDoctor.getHospitalId()); + caseClinicalDoctor.setBasicHospital(basicHospital); + + author.setCaseClinicalDoctor(caseClinicalDoctor); + } + + article.setAuthor(caseClinicalVideoAuthors); + + CaseClinicalVideoDto g = CaseClinicalVideoDto.GetDto(article); + return Response.success(g); + } +} diff --git a/src/main/java/com/example/caseData/controller/ClinicalController.java b/src/main/java/com/example/caseData/controller/ClinicalController.java new file mode 100644 index 0000000..9d84e16 --- /dev/null +++ b/src/main/java/com/example/caseData/controller/ClinicalController.java @@ -0,0 +1,218 @@ +package com.example.caseData.controller; + +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.caseData.common.Response; +import com.example.caseData.dao.*; +import com.example.caseData.dto.basicHospital.BasicHospitalDto; +import com.example.caseData.dto.caseClinicalArticle.CaseClinicalArticleDto; +import com.example.caseData.dto.caseClinicalArticleAuthor.CaseClinicalArticleAuthorDto; +import com.example.caseData.dto.caseClinicalDoctor.CaseClinicalDoctorDto; +import com.example.caseData.dto.caseClinicalVideo.CaseClinicalVideoDto; +import com.example.caseData.dto.caseClinicalVideoAuthor.CaseClinicalVideoAuthorDto; +import com.example.caseData.dto.statsCaseClinicalDoctor.StatsCaseClinicalDoctorDto; +import com.example.caseData.dto.statsCaseClinicalHospital.StatsCaseClinicalHospitalDto; +import com.example.caseData.model.BasicHospitalModel; +import com.example.caseData.model.CaseClinicalArticleAuthorModel; +import com.example.caseData.model.CaseClinicalDoctorModel; +import com.example.caseData.model.CaseClinicalVideoAuthorModel; +import com.example.caseData.request.clinicalRequest.getClinicalDoctorSearchPage; +import com.example.caseData.request.clinicalRequest.getClinicalHospitalSearchPage; +import com.example.caseData.request.clinicalRequest.getClinicalSearchPage; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@RestController +@RequestMapping("/api") +public class ClinicalController extends BaseController { + @Resource + private CaseClinicalArticleDao caseClinicalArticleDao; + + @Resource + private CaseClinicalArticleAuthorDao caseClinicalArticleAuthorDao; + + @Resource + private CaseClinicalVideoDao caseClinicalVideoDao; + + @Resource + private CaseClinicalVideoAuthorDao caseClinicalVideoAuthorDao; + + @Resource + private StatsCaseClinicalDao statsCaseClinicalDao; + + @Resource + private StatsCaseClinicalHospitalDao statsCaseClinicalHospitalDao; + + @Resource + private StatsCaseClinicalDoctorDao statsCaseClinicalDoctorDao; + + @Resource + private CaseClinicalDoctorDao caseClinicalDoctorDao; + + @Resource + private BasicHospitalDao basicHospitalDao; + + /** + * 临床病例库-搜索 + */ + @PostMapping("/clinical/search") + public Response> getClinicalSearchPage( + @Validated({getClinicalSearchPage.class}) + @RequestBody getClinicalSearchPage request + ) { + request.validateForPage(); + + Map resultMap = new HashMap<>(); + + if (request.getType() == 1){ + Page page = new Page<>(request.getPage(), request.getPageSize()); + + // 获取文章数据 + IPage resultPage = caseClinicalArticleDao.getCaseClinicalArticleSearchPage( + page, + request.getTitle(), + request.getDoctorName(), + request.getLabelName(), + request.getHospitalId(), + request.getDoctorId(), + request.handleOrder() + ); + + for (CaseClinicalArticleDto dto : resultPage.getRecords()) { + // 查找作者 + LambdaQueryWrapper authorQueryWrapper = new LambdaQueryWrapper<>(); + authorQueryWrapper.eq(CaseClinicalArticleAuthorModel::getArticleId, dto.getArticleId()); + List caseClinicalArticleAuthors = caseClinicalArticleAuthorDao.selectList(authorQueryWrapper); + for (CaseClinicalArticleAuthorModel author : caseClinicalArticleAuthors) { + // 查询医生 + CaseClinicalDoctorModel caseClinicalDoctor = caseClinicalDoctorDao.selectById(author.getDoctorId()); + author.setCaseClinicalDoctor(caseClinicalDoctor); + } + + List caseClinicalArticleAuthorListDto = CaseClinicalArticleAuthorDto.GetListDto(caseClinicalArticleAuthors); + dto.setAuthor(caseClinicalArticleAuthorListDto); + } + + resultMap.put("page", resultPage.getCurrent()); + resultMap.put("pageSize", resultPage.getSize()); + resultMap.put("total", resultPage.getTotal()); + resultMap.put("data", resultPage.getRecords()); + } else if (request.getType() == 2) { + Page page = new Page<>(request.getPage(), request.getPageSize()); + + // 获取视频数据 + IPage resultPage = caseClinicalVideoDao.getCaseClinicalVideoSearchPage( + page, + request.getTitle(), + request.getDoctorName(), + request.getLabelName(), + request.handleOrder() + ); + + for (CaseClinicalVideoDto dto : resultPage.getRecords()) { + // 查找作者 + LambdaQueryWrapper authorQueryWrapper = new LambdaQueryWrapper<>(); + authorQueryWrapper.eq(CaseClinicalVideoAuthorModel::getVideoId, dto.getVideoId()); + List caseClinicalVideoAuthors = caseClinicalVideoAuthorDao.selectList(authorQueryWrapper); + for (CaseClinicalVideoAuthorModel author : caseClinicalVideoAuthors) { + // 查询医生 + CaseClinicalDoctorModel caseClinicalDoctor = caseClinicalDoctorDao.selectById(author.getDoctorId()); + author.setCaseClinicalDoctor(caseClinicalDoctor); + } + + List caseClinicalVideoAuthorListDto = CaseClinicalVideoAuthorDto.GetListDto(caseClinicalVideoAuthors); + dto.setAuthor(caseClinicalVideoAuthorListDto); + } + + resultMap.put("page", resultPage.getCurrent()); + resultMap.put("pageSize", resultPage.getSize()); + resultMap.put("total", resultPage.getTotal()); + resultMap.put("data", resultPage.getRecords()); + } + + return Response.success(resultMap); + } + + /** + * 临床病例库-医院-搜索 + */ + @PostMapping("/clinical/hospital/search") + public Response> getClinicalHospitalSearchPage( + @Validated() + @RequestBody getClinicalHospitalSearchPage request + ) { + request.validateForPage(); + + Page page = new Page<>(request.getPage(), request.getPageSize()); + + // 获取医院数据 + IPage resultPage = statsCaseClinicalHospitalDao.getStatsCaseClinicalHospitalSearchPage( + page, + request.getHospitalName(), + request.handleOrder() + ); + + for (StatsCaseClinicalHospitalDto dto : resultPage.getRecords()) { + // 查询医院基础数据 + BasicHospitalModel basicHospital = basicHospitalDao.selectById(dto.getHospitalId()); + BasicHospitalDto basicHospitalDto = BasicHospitalDto.GetDto(basicHospital); + dto.setBasicHospital(basicHospitalDto); + } + + Map resultMap = new HashMap<>(); + resultMap.put("page", resultPage.getCurrent()); + resultMap.put("pageSize", resultPage.getSize()); + resultMap.put("total", resultPage.getTotal()); + resultMap.put("data", resultPage.getRecords()); + return Response.success(resultMap); + } + + /** + * 临床病例库-医生-搜索 + */ + @PostMapping("/clinical/doctor/search") + public Response> getClinicalDoctorSearchPage( + @Validated() + @RequestBody getClinicalDoctorSearchPage request + ) { + request.validateForPage(); + + Page page = new Page<>(request.getPage(), request.getPageSize()); + + // 获取医生数据 + IPage resultPage = statsCaseClinicalDoctorDao.getStatsCaseClinicalDoctorSearchPage( + page, + request.getDoctorName(), + request.handleOrder() + ); + + for (StatsCaseClinicalDoctorDto dto : resultPage.getRecords()) { + // 查询医生数据 + CaseClinicalDoctorModel caseClinicalDoctor = caseClinicalDoctorDao.selectById(dto.getDoctorId()); + + // 查询医生所属医院 + BasicHospitalModel basicHospital = basicHospitalDao.selectById(caseClinicalDoctor.getHospitalId()); + caseClinicalDoctor.setBasicHospital(basicHospital); + + CaseClinicalDoctorDto caseClinicalDoctorDto = CaseClinicalDoctorDto.GetDto(caseClinicalDoctor); + + dto.setCaseClinicalDoctor(caseClinicalDoctorDto); + } + + Map resultMap = new HashMap<>(); + resultMap.put("page", resultPage.getCurrent()); + resultMap.put("pageSize", resultPage.getSize()); + resultMap.put("total", resultPage.getTotal()); + resultMap.put("data", resultPage.getRecords()); + return Response.success(resultMap); + } +} diff --git a/src/main/java/com/example/caseData/controller/IndexController.java b/src/main/java/com/example/caseData/controller/IndexController.java new file mode 100644 index 0000000..15b729f --- /dev/null +++ b/src/main/java/com/example/caseData/controller/IndexController.java @@ -0,0 +1,23 @@ +package com.example.caseData.controller; + +import com.example.caseData.common.Response; +import com.example.caseData.dto.index.GetIndexClinicalDto; +import com.example.caseData.service.IndexService; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api") +public class IndexController extends BaseController { + @Resource + private IndexService indexService; + + // 首页-临床病例库 + @GetMapping("/index/clinical") + public Response getIndexClinical() { + return Response.success(indexService.GetIndexClinical()); + } + +} diff --git a/src/main/java/com/example/caseData/controller/PublicController.java b/src/main/java/com/example/caseData/controller/PublicController.java new file mode 100644 index 0000000..655a472 --- /dev/null +++ b/src/main/java/com/example/caseData/controller/PublicController.java @@ -0,0 +1,39 @@ +package com.example.caseData.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.example.caseData.common.Response; +import com.example.caseData.dao.UserDao; +import com.example.caseData.dto.PublicDto; +import com.example.caseData.model.BasicHospitalModel; +import com.example.caseData.model.UserModel; +import com.example.caseData.request.PublicRequest; +import com.example.caseData.request.UserRequest; +import com.example.caseData.service.UserService; +import jakarta.annotation.Resource; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/api") +public class PublicController { + @Resource + private UserService userService; + + // 登陆 + @PostMapping("/login/wechat/mobile") + public Response login(@Validated({PublicRequest.Login.class}) @ModelAttribute PublicRequest request) { + // 微信手机号授权登录 + // 获取手机号 + // 获取用户openid + + // 临时测试使用 + String phone = "18221234167"; + + // 用户登陆 + PublicDto g = userService.UserLogin(phone); + + return Response.success(g); + } +} diff --git a/src/main/java/com/example/caseData/controller/StatsCaseClinicalController.java b/src/main/java/com/example/caseData/controller/StatsCaseClinicalController.java new file mode 100644 index 0000000..3d844af --- /dev/null +++ b/src/main/java/com/example/caseData/controller/StatsCaseClinicalController.java @@ -0,0 +1,75 @@ +package com.example.caseData.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.example.caseData.common.Response; +import com.example.caseData.dao.StatsCaseClinicalDao; +import com.example.caseData.dao.StatsCaseClinicalDoctorDao; +import com.example.caseData.dao.StatsCaseClinicalHospitalDao; +import com.example.caseData.dto.statsCaseClinical.StatsCaseClinicalDto; +import com.example.caseData.dto.statsCaseClinicalDoctor.StatsCaseClinicalDoctorDto; +import com.example.caseData.dto.statsCaseClinicalHospital.StatsCaseClinicalHospitalDto; +import com.example.caseData.model.*; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/api") +public class StatsCaseClinicalController extends BaseController { + @Resource + private StatsCaseClinicalDao statsCaseClinicalDao; + + @Resource + private StatsCaseClinicalHospitalDao statsCaseClinicalHospitalDao; + + @Resource + private StatsCaseClinicalDoctorDao statsCaseClinicalDoctorDao; + + /** + * 临床病例库-统计 + */ + @GetMapping("/clinical/stats") + public Response getClinicalStats(){ + // 统计表-病例库-临床 + LambdaQueryWrapper statsCaseClinicalQueryWrapper = new LambdaQueryWrapper<>(); + StatsCaseClinicalModel statsCaseClinical = statsCaseClinicalDao.selectOne(statsCaseClinicalQueryWrapper); + + StatsCaseClinicalDto g = StatsCaseClinicalDto.GetDto(statsCaseClinical); + + return Response.success(g); + } + + /** + * 临床病例库-统计-医院 + */ + @GetMapping("/clinical/stats/hospital/{hospital_id}") + public Response getClinicalStatsHospital( + @PathVariable("hospital_id") String hospitalId + ){ + + // 统计表-病例库-临床 + LambdaQueryWrapper statsCaseClinicalHospitalQueryWrapper = new LambdaQueryWrapper<>(); + statsCaseClinicalHospitalQueryWrapper.eq(StatsCaseClinicalHospitalModel::getHospitalId, hospitalId); + StatsCaseClinicalHospitalModel statsCaseClinicalHospital = statsCaseClinicalHospitalDao.selectOne(statsCaseClinicalHospitalQueryWrapper); + + StatsCaseClinicalHospitalDto g = StatsCaseClinicalHospitalDto.GetDto(statsCaseClinicalHospital); + + return Response.success(g); + } + + /** + * 临床病例库-统计-医生 + */ + @GetMapping("/clinical/stats/doctor/{doctor_id}") + public Response getClinicalStatsDoctor( + @PathVariable("doctor_id") String doctorId + ){ + // 统计表-病例库-临床 + LambdaQueryWrapper statsCaseClinicalDoctorQueryWrapper = new LambdaQueryWrapper<>(); + statsCaseClinicalDoctorQueryWrapper.eq(StatsCaseClinicalDoctorModel::getDoctorId, doctorId); + StatsCaseClinicalDoctorModel statsCaseClinicalDoctor = statsCaseClinicalDoctorDao.selectOne(statsCaseClinicalDoctorQueryWrapper); + + StatsCaseClinicalDoctorDto g = StatsCaseClinicalDoctorDto.GetDto(statsCaseClinicalDoctor); + + return Response.success(g); + } +} diff --git a/src/main/java/com/example/caseData/controller/UserController.java b/src/main/java/com/example/caseData/controller/UserController.java new file mode 100644 index 0000000..d9896b0 --- /dev/null +++ b/src/main/java/com/example/caseData/controller/UserController.java @@ -0,0 +1,52 @@ +package com.example.caseData.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.example.caseData.common.Response; +import com.example.caseData.dao.UserDao; +import com.example.caseData.dto.UserDto; +import com.example.caseData.model.UserModel; +import com.example.caseData.request.UserRequest; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@RestController +@RequestMapping("/api") +public class UserController extends BaseController { + @Resource + private UserDao userDao; + + // 查询所有用户 + @GetMapping("/users") + public Response> getUserPage(@Validated({UserRequest.Page.class}) @ModelAttribute UserRequest request) { + request.validateForPage(); // 确保分页参数有默认值 + + Page page = new Page<>(request.getPage(), request.getPageSize()); // 创建分页对象 + + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.like("user_id", "吴"); + + // 执行分页查询 + Page resultPage = userDao.selectPage(page, queryWrapper); + + // 返回 + List userDtoList = UserDto.getUserListDto(resultPage.getRecords()); + + // 组装分页结果 + Map resultMap = new HashMap<>(); + resultMap.put("page", resultPage.getCurrent()); + resultMap.put("pageSize", resultPage.getSize()); + resultMap.put("total", resultPage.getTotal()); + resultMap.put("data", userDtoList); + + return Response.success(resultMap); + } +} diff --git a/src/main/java/com/example/caseData/core/CorsConfig.java b/src/main/java/com/example/caseData/core/CorsConfig.java new file mode 100644 index 0000000..0cffcbd --- /dev/null +++ b/src/main/java/com/example/caseData/core/CorsConfig.java @@ -0,0 +1,28 @@ +package com.example.caseData.core; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.lang.NonNull; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class CorsConfig { + + @Bean + public WebMvcConfigurer corsConfigurer() { + return new WebMvcConfigurer() { + @Override + public void addCorsMappings(@NonNull CorsRegistry registry) { + registry.addMapping("/**") // 允许所有路径 + .allowedOriginPatterns("*") // 允许所有来源(Spring 2.4+ 用 `allowedOriginPatterns`) + .allowedMethods("POST", "GET", "OPTIONS", "PUT", "DELETE", "UPDATE") // 允许的 HTTP 方法 + .allowedHeaders("Origin", "X-Requested-With", "Content-Type", "Accept", "Authorization") // 允许的请求头 + .exposedHeaders("Content-Length", "Access-Control-Allow-Origin", + "Access-Control-Allow-Headers", "Cache-Control", + "Content-Language", "Content-Type") // 允许前端访问的响应头 + .allowCredentials(false); // 是否允许携带 Cookie + } + }; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/core/JacksonConfig.java b/src/main/java/com/example/caseData/core/JacksonConfig.java new file mode 100644 index 0000000..8a309ca --- /dev/null +++ b/src/main/java/com/example/caseData/core/JacksonConfig.java @@ -0,0 +1,57 @@ +package com.example.caseData.core; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; + +/** + * 统一全局时间格式配置 + */ +@Configuration +public class JacksonConfig { + + private static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss"; + private static final String DATE_PATTERN = "yyyy-MM-dd"; + private static final String TIME_PATTERN = "HH:mm:ss"; + + @Bean + public ObjectMapper objectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + + JavaTimeModule javaTimeModule = new JavaTimeModule(); + + // 配置序列化器 + javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_TIME_PATTERN))); + javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DATE_PATTERN))); + javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(TIME_PATTERN))); + + // 配置反序列化器 + javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DATE_TIME_PATTERN))); + javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DATE_PATTERN))); + javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(TIME_PATTERN))); + + objectMapper.registerModule(javaTimeModule); + + // 禁用时间戳 + objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + + // 空字段不返回(根据需要,可加可不加) + objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS); + + return objectMapper; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/core/MyBatisPlusConfig.java b/src/main/java/com/example/caseData/core/MyBatisPlusConfig.java new file mode 100644 index 0000000..8162107 --- /dev/null +++ b/src/main/java/com/example/caseData/core/MyBatisPlusConfig.java @@ -0,0 +1,16 @@ +package com.example.caseData.core; + +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class MyBatisPlusConfig { + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); // 添加分页拦截器 + return interceptor; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/core/MyMetaObjectHandler.java b/src/main/java/com/example/caseData/core/MyMetaObjectHandler.java new file mode 100644 index 0000000..14639fc --- /dev/null +++ b/src/main/java/com/example/caseData/core/MyMetaObjectHandler.java @@ -0,0 +1,22 @@ +package com.example.caseData.core; + +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import org.apache.ibatis.reflection.MetaObject; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +@Component +public 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/caseData/core/RedisConfig.java b/src/main/java/com/example/caseData/core/RedisConfig.java new file mode 100644 index 0000000..7e368f8 --- /dev/null +++ b/src/main/java/com/example/caseData/core/RedisConfig.java @@ -0,0 +1,26 @@ +package com.example.caseData.core; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.serializer.StringRedisSerializer; + + +@Configuration +public class RedisConfig { + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(connectionFactory); + + // 使用String序列化方式 + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + template.setKeySerializer(stringRedisSerializer); + template.setValueSerializer(stringRedisSerializer); + template.setHashKeySerializer(stringRedisSerializer); + template.setHashValueSerializer(stringRedisSerializer); + + return template; + } +} diff --git a/src/main/java/com/example/caseData/core/WebConfig.java b/src/main/java/com/example/caseData/core/WebConfig.java new file mode 100644 index 0000000..a6d88d8 --- /dev/null +++ b/src/main/java/com/example/caseData/core/WebConfig.java @@ -0,0 +1,40 @@ +package com.example.caseData.core; + +import com.example.caseData.middlewares.AuthInterceptor; +import com.example.caseData.middlewares.JwtInterceptor; +import com.example.caseData.middlewares.LogRequestInterceptor; +import jakarta.annotation.Resource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + @Resource + private LogRequestInterceptor logRequestInterceptor; + + @Resource + private JwtInterceptor jwtInterceptor; + + @Resource + private AuthInterceptor authInterceptor; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + // 注册日志拦截器 + registry.addInterceptor(logRequestInterceptor) + .addPathPatterns("/**"); // 对所有路径生效 + + // 注册JWT认证拦截器 + registry.addInterceptor(jwtInterceptor) + .addPathPatterns("/**"); // 对所有路径生效 +// .addPathPatterns("/api/**") // 适用于/api下的所有路径 +// .excludePathPatterns("/api/user/1", "/api/register"); // 排除不需要认证的路径 + + // 注册用户权限拦截器 + registry.addInterceptor(authInterceptor) + .addPathPatterns("/**"); // 对所有路径生效 +// .addPathPatterns("/api/secure/**"); // 适用于需要权限验证的路径 + } +} diff --git a/src/main/java/com/example/caseData/dao/BasicHospitalDao.java b/src/main/java/com/example/caseData/dao/BasicHospitalDao.java new file mode 100644 index 0000000..0ecf688 --- /dev/null +++ b/src/main/java/com/example/caseData/dao/BasicHospitalDao.java @@ -0,0 +1,7 @@ +package com.example.caseData.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.caseData.model.BasicHospitalModel; + +public interface BasicHospitalDao extends BaseMapper { +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dao/BasicSensitiveWordDao.java b/src/main/java/com/example/caseData/dao/BasicSensitiveWordDao.java new file mode 100644 index 0000000..ae8c495 --- /dev/null +++ b/src/main/java/com/example/caseData/dao/BasicSensitiveWordDao.java @@ -0,0 +1,7 @@ +package com.example.caseData.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.caseData.model.BasicSensitiveWordModel; + +public interface BasicSensitiveWordDao extends BaseMapper { +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dao/CaseClinicalArticleAuthorDao.java b/src/main/java/com/example/caseData/dao/CaseClinicalArticleAuthorDao.java new file mode 100644 index 0000000..6cb5040 --- /dev/null +++ b/src/main/java/com/example/caseData/dao/CaseClinicalArticleAuthorDao.java @@ -0,0 +1,7 @@ +package com.example.caseData.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.caseData.model.CaseClinicalArticleAuthorModel; + +public interface CaseClinicalArticleAuthorDao extends BaseMapper { +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dao/CaseClinicalArticleDao.java b/src/main/java/com/example/caseData/dao/CaseClinicalArticleDao.java new file mode 100644 index 0000000..350fa75 --- /dev/null +++ b/src/main/java/com/example/caseData/dao/CaseClinicalArticleDao.java @@ -0,0 +1,31 @@ +package com.example.caseData.dao; + +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.caseData.dto.caseClinicalArticle.CaseClinicalArticleDto; +import com.example.caseData.model.CaseClinicalArticleModel; +import org.apache.ibatis.annotations.*; + +import java.util.Map; + +@Mapper +public interface CaseClinicalArticleDao extends BaseMapper { + /** + * 临床病例库-搜索 + * @param page 分页数据 + * @param title 标题 + * @param doctorName 医生名称 + * @param labelName 标签名称 + * @param order 排序 + */ + IPage getCaseClinicalArticleSearchPage( + Page page, + @Param("title") String title, + @Param("doctorName") String doctorName, + @Param("labelName") String labelName, + @Param("hospital_id") String hospitalId, + @Param("doctor_id") String doctorId, + @Param("order") Map order + ); +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dao/CaseClinicalArticleLabelDao.java b/src/main/java/com/example/caseData/dao/CaseClinicalArticleLabelDao.java new file mode 100644 index 0000000..9fbfa9e --- /dev/null +++ b/src/main/java/com/example/caseData/dao/CaseClinicalArticleLabelDao.java @@ -0,0 +1,7 @@ +package com.example.caseData.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.caseData.model.CaseClinicalArticleLabelModel; + +public interface CaseClinicalArticleLabelDao extends BaseMapper { +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dao/CaseClinicalDoctorDao.java b/src/main/java/com/example/caseData/dao/CaseClinicalDoctorDao.java new file mode 100644 index 0000000..46e315e --- /dev/null +++ b/src/main/java/com/example/caseData/dao/CaseClinicalDoctorDao.java @@ -0,0 +1,8 @@ +package com.example.caseData.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.caseData.model.CaseClinicalDoctorModel; + +public interface CaseClinicalDoctorDao extends BaseMapper { + +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dao/CaseClinicalVideoAuthorDao.java b/src/main/java/com/example/caseData/dao/CaseClinicalVideoAuthorDao.java new file mode 100644 index 0000000..49e6987 --- /dev/null +++ b/src/main/java/com/example/caseData/dao/CaseClinicalVideoAuthorDao.java @@ -0,0 +1,7 @@ +package com.example.caseData.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.caseData.model.CaseClinicalVideoAuthorModel; + +public interface CaseClinicalVideoAuthorDao extends BaseMapper { +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dao/CaseClinicalVideoDao.java b/src/main/java/com/example/caseData/dao/CaseClinicalVideoDao.java new file mode 100644 index 0000000..db02e66 --- /dev/null +++ b/src/main/java/com/example/caseData/dao/CaseClinicalVideoDao.java @@ -0,0 +1,31 @@ +package com.example.caseData.dao; + +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.caseData.dto.caseClinicalArticle.CaseClinicalArticleDto; +import com.example.caseData.dto.caseClinicalVideo.CaseClinicalVideoDto; +import com.example.caseData.model.CaseClinicalVideoModel; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.Map; + +@Mapper +public interface CaseClinicalVideoDao extends BaseMapper { + /** + * 临床病例库-搜索 + * @param page 分页数据 + * @param title 标题 + * @param doctorName 医生名称 + * @param labelName 标签名称 + * @param order 排序 + */ + IPage getCaseClinicalVideoSearchPage( + Page page, + @Param("title") String title, + @Param("doctorName") String doctorName, + @Param("labelName") String labelName, + @Param("order") Map order + ); +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dao/CaseClinicalVideoLabelDao.java b/src/main/java/com/example/caseData/dao/CaseClinicalVideoLabelDao.java new file mode 100644 index 0000000..2ed826a --- /dev/null +++ b/src/main/java/com/example/caseData/dao/CaseClinicalVideoLabelDao.java @@ -0,0 +1,7 @@ +package com.example.caseData.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.caseData.model.CaseClinicalVideoLabelModel; + +public interface CaseClinicalVideoLabelDao extends BaseMapper { +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dao/StatsCaseClinicalDao.java b/src/main/java/com/example/caseData/dao/StatsCaseClinicalDao.java new file mode 100644 index 0000000..8dcc8f2 --- /dev/null +++ b/src/main/java/com/example/caseData/dao/StatsCaseClinicalDao.java @@ -0,0 +1,7 @@ +package com.example.caseData.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.caseData.model.StatsCaseClinicalModel; + +public interface StatsCaseClinicalDao extends BaseMapper { +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dao/StatsCaseClinicalDoctorDao.java b/src/main/java/com/example/caseData/dao/StatsCaseClinicalDoctorDao.java new file mode 100644 index 0000000..ace59c5 --- /dev/null +++ b/src/main/java/com/example/caseData/dao/StatsCaseClinicalDoctorDao.java @@ -0,0 +1,25 @@ +package com.example.caseData.dao; + +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.caseData.dto.statsCaseClinicalDoctor.StatsCaseClinicalDoctorDto; +import com.example.caseData.dto.statsCaseClinicalHospital.StatsCaseClinicalHospitalDto; +import com.example.caseData.model.StatsCaseClinicalDoctorModel; +import org.apache.ibatis.annotations.Param; + +import java.util.Map; + +public interface StatsCaseClinicalDoctorDao extends BaseMapper { + /** + * 医院病例库推荐-搜索 + * @param page 分页数据 + * @param doctorName 医生名称 + * @param order 排序 + */ + IPage getStatsCaseClinicalDoctorSearchPage( + Page page, + @Param("doctor_name") String doctorName, + @Param("order") Map order + ); +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dao/StatsCaseClinicalHospitalDao.java b/src/main/java/com/example/caseData/dao/StatsCaseClinicalHospitalDao.java new file mode 100644 index 0000000..6b7218e --- /dev/null +++ b/src/main/java/com/example/caseData/dao/StatsCaseClinicalHospitalDao.java @@ -0,0 +1,25 @@ +package com.example.caseData.dao; + +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.caseData.dto.statsCaseClinicalHospital.StatsCaseClinicalHospitalDto; +import com.example.caseData.model.StatsCaseClinicalHospitalModel; +import org.apache.ibatis.annotations.Param; +import org.checkerframework.checker.units.qual.N; + +import java.util.Map; + +public interface StatsCaseClinicalHospitalDao extends BaseMapper { + /** + * 医院病例库推荐-搜索 + * @param page 分页数据 + * @param hospitalName 医院名称 + * @param order 排序 + */ + IPage getStatsCaseClinicalHospitalSearchPage( + Page page, + @Param("hospital_name") String hospitalName, + @Param("order") Map order + ); +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dao/UserCollectClinicalArticleDao.java b/src/main/java/com/example/caseData/dao/UserCollectClinicalArticleDao.java new file mode 100644 index 0000000..ffa34ad --- /dev/null +++ b/src/main/java/com/example/caseData/dao/UserCollectClinicalArticleDao.java @@ -0,0 +1,7 @@ +package com.example.caseData.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.caseData.model.UserCollectClinicalArticleModel; + +public interface UserCollectClinicalArticleDao extends BaseMapper { +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dao/UserCollectClinicalVideoDao.java b/src/main/java/com/example/caseData/dao/UserCollectClinicalVideoDao.java new file mode 100644 index 0000000..c062fdc --- /dev/null +++ b/src/main/java/com/example/caseData/dao/UserCollectClinicalVideoDao.java @@ -0,0 +1,7 @@ +package com.example.caseData.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.caseData.model.UserCollectClinicalVideoModel; + +public interface UserCollectClinicalVideoDao extends BaseMapper { +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dao/UserCommentClinicalArticleDao.java b/src/main/java/com/example/caseData/dao/UserCommentClinicalArticleDao.java new file mode 100644 index 0000000..9cc475e --- /dev/null +++ b/src/main/java/com/example/caseData/dao/UserCommentClinicalArticleDao.java @@ -0,0 +1,7 @@ +package com.example.caseData.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.caseData.model.UserCommentClinicalArticleModel; + +public interface UserCommentClinicalArticleDao extends BaseMapper { +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dao/UserCommentClinicalVideoDao.java b/src/main/java/com/example/caseData/dao/UserCommentClinicalVideoDao.java new file mode 100644 index 0000000..d4aef2f --- /dev/null +++ b/src/main/java/com/example/caseData/dao/UserCommentClinicalVideoDao.java @@ -0,0 +1,7 @@ +package com.example.caseData.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.caseData.model.UserCommentClinicalVideoModel; + +public interface UserCommentClinicalVideoDao extends BaseMapper { +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dao/UserDao.java b/src/main/java/com/example/caseData/dao/UserDao.java new file mode 100644 index 0000000..0503889 --- /dev/null +++ b/src/main/java/com/example/caseData/dao/UserDao.java @@ -0,0 +1,7 @@ +package com.example.caseData.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.caseData.model.UserModel; + +public interface UserDao extends BaseMapper { +} diff --git a/src/main/java/com/example/caseData/dto/PublicDto.java b/src/main/java/com/example/caseData/dto/PublicDto.java new file mode 100644 index 0000000..178bffe --- /dev/null +++ b/src/main/java/com/example/caseData/dto/PublicDto.java @@ -0,0 +1,20 @@ +package com.example.caseData.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class PublicDto { + @JsonProperty("user_id") + private String userId; // 主键id + + @JsonProperty("user_name") + private String userName; // 用户名称 + + private String avatar; // 头像 + private String token; // token +} diff --git a/src/main/java/com/example/caseData/dto/T.java b/src/main/java/com/example/caseData/dto/T.java new file mode 100644 index 0000000..8983621 --- /dev/null +++ b/src/main/java/com/example/caseData/dto/T.java @@ -0,0 +1,145 @@ +package com.example.caseData.dto; + +import cn.hutool.core.bean.BeanUtil; +import com.example.caseData.dto.caseClinicalArticle.CaseClinicalArticleDto; +import com.example.caseData.dto.caseClinicalArticleAuthor.CaseClinicalArticleAuthorDto; +import com.example.caseData.model.CaseClinicalArticleModel; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +// 示例 +public class T { + /** + * 主键id + */ + @JsonProperty("article_id") + private String articleId; + + /** + * 标题 + */ + @JsonProperty("article_title") + private String articleTitle; + + /** + * 状态(1:正常 2:禁用) + */ + @JsonProperty("article_status") + private Integer articleStatus; + + /** + * 阅读量 + */ + @JsonProperty("read_num") + private Integer readNum; + + /** + * 收藏量 + */ + @JsonProperty("collect_num") + private Integer collectNum; + + /** + * 发表时间 + */ + @JsonProperty("push_date") + private LocalDateTime pushDate; + + /** + * 内容 + */ + @JsonProperty("article_content") + private String articleContent; + + /** + * 创建时间 + */ + @JsonProperty("created_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @JsonProperty("updated_at") + private LocalDateTime updatedAt; + + /** + * 作者 + */ + @JsonProperty("author") + private List author; + + /** + * 将文章实体类列表转换为 DTO 列表,只映射字段,不处理嵌套字段(如作者等) + */ + public static List listDto1(List models) { + if (models == null || models.isEmpty()) { + return Collections.emptyList(); + } + + return models.stream() + .map(v -> BeanUtil.copyProperties(v, CaseClinicalArticleDto.class)) + .collect(Collectors.toList()); + } + + /** + * 单个对象转换,只做字段映射 + */ + public static CaseClinicalArticleDto dto1(CaseClinicalArticleModel model) { + if (model == null) { + return null; + } + + return BeanUtil.copyProperties(model, CaseClinicalArticleDto.class); + } + + + /** + * 将文章实体类列表转换为 DTO 列表,只映射字段,不处理嵌套字段(如作者等) + * 如果字段类型不同(如 Long -> String),可在此处手动处理 + */ + public static List listDto2(List models) { + if (models == null || models.isEmpty()) { + return Collections.emptyList(); + } + + return models.stream() + .map(model -> { + CaseClinicalArticleDto dto = BeanUtil.copyProperties(model, CaseClinicalArticleDto.class); + + // 示例:手动处理字段类型不一致 + if (model.getArticleId() != null) { + dto.setArticleId(String.valueOf(model.getArticleId())); // Long -> String + } + + if (model.getPushDate() != null) { + dto.setPushDate(model.getPushDate()); // 这里类型一致,其实可以不用写,仅作示范 + } + + return dto; + }) + .collect(Collectors.toList()); + } + + /** + * 将单个实体类转换为 DTO,只映射字段,不处理嵌套字段 + */ + public static CaseClinicalArticleDto dto2(CaseClinicalArticleModel model) { + if (model == null) { + return null; + } + + CaseClinicalArticleDto dto = BeanUtil.copyProperties(model, CaseClinicalArticleDto.class); + + // 类型转换示例 + if (model.getArticleId() != null) { + dto.setArticleId(String.valueOf(model.getArticleId())); // Long -> String + } + + return dto; + } +} diff --git a/src/main/java/com/example/caseData/dto/UserDto.java b/src/main/java/com/example/caseData/dto/UserDto.java new file mode 100644 index 0000000..6bf8381 --- /dev/null +++ b/src/main/java/com/example/caseData/dto/UserDto.java @@ -0,0 +1,75 @@ +package com.example.caseData.dto; + +import com.example.caseData.model.UserModel; +import com.example.caseData.utils.Replace; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class UserDto { + private String userId; // 主键id + private String userIden; // 第三方平台唯一标识 + private String userName; // 用户名称 + private String userMobile; // 手机号 + private Integer status; // 状态(0:禁用 1:正常 2:删除) + private Integer registerSource;// 注册来源(1:未知 2:app用户 3:佳动例) + private String openId; // 用户微信标识 + private String unionId; // 微信开放平台标识 + private Integer sex; // 性别(0:未知 1:男 2:女) + private String avatar; // 头像 + private Integer title; // 医生职称 + private String departmentName; // 科室名称 + private String hospitalId; // 所属医院id + private LocalDateTime createdAt; // 创建时间 + private LocalDateTime updatedAt; // 修改时间 + + public static UserDto getUserDto(UserModel userModel) { + if (userModel == null) { + return null; + } + + UserDto dto = new UserDto(); + dto.setUserId(userModel.getUserId().toString()); + dto.setUserIden(userModel.getUserIden()); + dto.setUserName(userModel.getUserName()); + dto.setUserMobile(userModel.getUserMobile()); + dto.setStatus(userModel.getStatus()); + dto.setRegisterSource(userModel.getRegisterSource()); + dto.setOpenId(userModel.getOpenId()); + dto.setUnionId(userModel.getUnionId()); + dto.setSex(userModel.getSex()); + dto.setAvatar(userModel.getAvatar()); + dto.setTitle(userModel.getTitle()); + dto.setDepartmentName(userModel.getDepartmentName()); + dto.setHospitalId(userModel.getHospitalId().toString()); + dto.setCreatedAt(userModel.getCreatedAt()); + dto.setUpdatedAt(userModel.getUpdatedAt()); + return dto; + } + + + public static List getUserListDto(List userModels) { + List userDtoList = new ArrayList<>(); + + for (UserModel userModel : userModels) { + UserDto dto = getUserDto(userModel); + + // 在这里对字段做一些操作(暂时不做任何处理) + // 例如: dto.setUserName(dto.getUserName().toUpperCase()); + + userDtoList.add(dto); + } + + return userDtoList; + } +} diff --git a/src/main/java/com/example/caseData/dto/basicHospital/BasicHospitalDto.java b/src/main/java/com/example/caseData/dto/basicHospital/BasicHospitalDto.java new file mode 100644 index 0000000..7266743 --- /dev/null +++ b/src/main/java/com/example/caseData/dto/basicHospital/BasicHospitalDto.java @@ -0,0 +1,150 @@ +package com.example.caseData.dto.basicHospital; + +import cn.hutool.core.bean.BeanUtil; +import com.example.caseData.model.BasicHospitalModel; +import com.example.caseData.model.BasicHospitalModel; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +@Data +public class BasicHospitalDto { + /** + * 主键id + */ + @JsonProperty("hospital_id") + private String hospitalId; + + /** + * app唯一标识 + */ + @JsonProperty("hospital_iden") + private String hospitalIden; + + /** + * 医院名称 + */ + @JsonProperty("hospital_name") + private String hospitalName; + + /** + * 来源(2:肝胆相照 3:佳动例) + */ + @JsonProperty("source") + private Integer source; + + /** + * 医院等级(0:未知 1:三级甲等 2:三级乙等 3:三级丙等 4:二级甲等 5:二级乙等 6:二级丙等 7:一级甲等 8:一级乙等 9:一级丙等) + */ + @JsonProperty("hospital_level") + private String hospitalLevel; + + /** + * 医院性质(0:未知 1:公立 2:私立) + */ + @JsonProperty("hospital_nature") + private Integer hospitalNature; + + /** + * 医生数量 + */ + @JsonProperty("doctor_number") + private Integer doctorNumber; + + /** + * 省份 + */ + @JsonProperty("province") + private String province; + + /** + * 城市 + */ + @JsonProperty("city") + private String city; + + /** + * 区县 + */ + @JsonProperty("county") + private String county; + + /** + * 医院地址 + */ + @JsonProperty("hospital_address") + private String hospitalAddress; + + /** + * 医院简介 + */ + @JsonProperty("hospital_intro") + private String hospitalIntro; + + /** + * 医院logo + */ + @JsonProperty("hospital_logo") + private String hospitalLogo; + + /** + * 状态(0:禁用 1:正常) + */ + @JsonProperty("status") + private Integer status; + + /** + * 创建时间 + */ + @JsonProperty("created_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @JsonProperty("updated_at") + private LocalDateTime updatedAt; + + /** + * 列表 + */ + public static List GetListDto(List models) { + if (models == null || models.isEmpty()) { + return Collections.emptyList(); + } + + return models.stream() + .map(model -> { + BasicHospitalDto dto = BeanUtil.copyProperties(model, BasicHospitalDto.class); + + // 示例:手动处理字段类型不一致 + if (model.getHospitalId() != null) { + dto.setHospitalId(String.valueOf(model.getHospitalId())); // Long -> String + } + + return dto; + }) + .collect(Collectors.toList()); + } + + /** + * 详情 + */ + public static BasicHospitalDto GetDto(BasicHospitalModel model) { + if (model == null) { + return null; + } + + BasicHospitalDto dto = BeanUtil.copyProperties(model, BasicHospitalDto.class); + + // 示例:手动处理字段类型不一致 + if (model.getHospitalId() != null) { + dto.setHospitalId(String.valueOf(model.getHospitalId())); // Long -> String + } + + return dto; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dto/basicSensitiveWord/BasicSensitiveWordDto.java b/src/main/java/com/example/caseData/dto/basicSensitiveWord/BasicSensitiveWordDto.java new file mode 100644 index 0000000..e7ffa5f --- /dev/null +++ b/src/main/java/com/example/caseData/dto/basicSensitiveWord/BasicSensitiveWordDto.java @@ -0,0 +1,38 @@ +package com.example.caseData.dto.basicSensitiveWord; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import java.time.LocalDateTime; + +@Data +public class BasicSensitiveWordDto { + /** + * 主键id + */ + @JsonProperty("id") + private Long id; + + /** + * 敏感词 + */ + @JsonProperty("word") + private String word; + + /** + * 状态(0:禁用 1:正常) + */ + @JsonProperty("status") + private Integer status; + + /** + * 创建时间 + */ + @JsonProperty("created_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @JsonProperty("updated_at") + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dto/caseClinicalArticle/CaseClinicalArticleDto.java b/src/main/java/com/example/caseData/dto/caseClinicalArticle/CaseClinicalArticleDto.java new file mode 100644 index 0000000..fe30b1f --- /dev/null +++ b/src/main/java/com/example/caseData/dto/caseClinicalArticle/CaseClinicalArticleDto.java @@ -0,0 +1,129 @@ +package com.example.caseData.dto.caseClinicalArticle; + +import cn.hutool.core.bean.BeanUtil; +import com.example.caseData.dto.caseClinicalArticleAuthor.CaseClinicalArticleAuthorDto; +import com.example.caseData.model.CaseClinicalArticleModel; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +@Data +public class CaseClinicalArticleDto { + /** + * 主键id + */ + @JsonProperty("article_id") + private String articleId; + + /** + * 标题 + */ + @JsonProperty("article_title") + private String articleTitle; + + /** + * 状态(1:正常 2:禁用) + */ + @JsonProperty("article_status") + private Integer articleStatus; + + /** + * 阅读量 + */ + @JsonProperty("read_num") + private Integer readNum; + + /** + * 收藏量 + */ + @JsonProperty("collect_num") + private Integer collectNum; + + /** + * 发表时间 + */ + @JsonProperty("push_date") +// @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime pushDate; + + /** + * 内容 + */ + @JsonProperty("article_content") + private String articleContent; + + /** + * 创建时间 + */ + @JsonProperty("created_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @JsonProperty("updated_at") + private LocalDateTime updatedAt; + + /** + * 作者 + */ + @JsonProperty("author") + private List author; + + /** + * 列表 + */ + public static List GetListDto(List models) { + if (models == null || models.isEmpty()) { + return Collections.emptyList(); + } + + return models.stream() + .map(model -> { + CaseClinicalArticleDto dto = BeanUtil.copyProperties(model, CaseClinicalArticleDto.class); + + // 示例:手动处理字段类型不一致 + if (model.getArticleId() != null) { + dto.setArticleId(String.valueOf(model.getArticleId())); // Long -> String + } + + // 作者 + if (model.getAuthor() != null && !model.getAuthor().isEmpty()) { + List caseClinicalArticleAuthorListDto = CaseClinicalArticleAuthorDto.GetListDto(model.getAuthor()); + dto.setAuthor(caseClinicalArticleAuthorListDto); + } + + dto.setArticleContent(""); + return dto; + }) + .collect(Collectors.toList()); + } + + /** + * 详情 + */ + public static CaseClinicalArticleDto GetDto(CaseClinicalArticleModel model) { + if (model == null) { + return null; + } + + CaseClinicalArticleDto dto = BeanUtil.copyProperties(model, CaseClinicalArticleDto.class); + + // 类型转换示例 + if (model.getArticleId() != null) { + dto.setArticleId(String.valueOf(model.getArticleId())); // Long -> String + } + + // 作者 + if (model.getAuthor() != null && !model.getAuthor().isEmpty()) { + List caseClinicalArticleAuthorListDto = CaseClinicalArticleAuthorDto.GetListDto(model.getAuthor()); + dto.setAuthor(caseClinicalArticleAuthorListDto); + } + + return dto; + } +} diff --git a/src/main/java/com/example/caseData/dto/caseClinicalArticleAuthor/CaseClinicalArticleAuthorDto.java b/src/main/java/com/example/caseData/dto/caseClinicalArticleAuthor/CaseClinicalArticleAuthorDto.java new file mode 100644 index 0000000..b96854a --- /dev/null +++ b/src/main/java/com/example/caseData/dto/caseClinicalArticleAuthor/CaseClinicalArticleAuthorDto.java @@ -0,0 +1,112 @@ +package com.example.caseData.dto.caseClinicalArticleAuthor; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.example.caseData.dto.caseClinicalDoctor.CaseClinicalDoctorDto; +import com.example.caseData.model.CaseClinicalArticleAuthorModel; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +@Data +public class CaseClinicalArticleAuthorDto { + /** + * 主键id + */ + @JsonProperty("author_id") + private String authorId; + + /** + * 临床文章id + */ + @JsonProperty("article_id") + private String articleId; + + /** + * 医生id + */ + @JsonProperty("doctor_id") + private String doctorId; + + /** + * 医院名称 + */ + @JsonProperty("doctor_name") + private String doctorName; + + /** + * 医院名称 + */ + @JsonProperty("hospital_name") + private String hospitalName; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @JsonProperty("created_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @JsonProperty("updated_at") + private LocalDateTime updatedAt; + + /** + * 列表 + */ + public static List GetListDto(List models) { + if (models == null || models.isEmpty()) { + return Collections.emptyList(); + } + + return models.stream() + .map(model -> { + CaseClinicalArticleAuthorDto dto = BeanUtil.copyProperties(model, CaseClinicalArticleAuthorDto.class); + + // 示例:手动处理字段类型不一致 + if (model.getAuthorId() != null) { + dto.setAuthorId(String.valueOf(model.getAuthorId())); // Long -> String + } + + if (model.getCaseClinicalDoctor() != null) { + CaseClinicalDoctorDto caseClinicalDoctorDto = CaseClinicalDoctorDto.GetDto(model.getCaseClinicalDoctor()); + dto.setDoctorName(caseClinicalDoctorDto.getDoctorName()); + dto.setHospitalName(caseClinicalDoctorDto.getHospitalName()); + } + + return dto; + }) + .collect(Collectors.toList()); + } + + /** + * 详情 + */ + public static CaseClinicalArticleAuthorDto GetDto(CaseClinicalArticleAuthorModel model) { + if (model == null) { + return null; + } + + CaseClinicalArticleAuthorDto dto = BeanUtil.copyProperties(model, CaseClinicalArticleAuthorDto.class); + + // 类型转换示例 + if (model.getAuthorId() != null) { + dto.setAuthorId(String.valueOf(model.getAuthorId())); // Long -> String + } + + if (model.getCaseClinicalDoctor() != null) { + CaseClinicalDoctorDto caseClinicalDoctorDto = CaseClinicalDoctorDto.GetDto(model.getCaseClinicalDoctor()); + dto.setDoctorName(caseClinicalDoctorDto.getDoctorName()); + } + + return dto; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dto/caseClinicalArticleLabel/CaseClinicalArticleLabelDto.java b/src/main/java/com/example/caseData/dto/caseClinicalArticleLabel/CaseClinicalArticleLabelDto.java new file mode 100644 index 0000000..a0fafca --- /dev/null +++ b/src/main/java/com/example/caseData/dto/caseClinicalArticleLabel/CaseClinicalArticleLabelDto.java @@ -0,0 +1,44 @@ +package com.example.caseData.dto.caseClinicalArticleLabel; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import java.time.LocalDateTime; + +@Data +public class CaseClinicalArticleLabelDto { + /** + * 主键id + */ + @JsonProperty("article_label_id") + private Long articleLabelId; + + /** + * 临床文章id + */ + @JsonProperty("article_id") + private Long articleId; + + /** + * app唯一标识 + */ + @JsonProperty("app_iden") + private String appIden; + + /** + * 标签名称 + */ + @JsonProperty("label_name") + private String labelName; + + /** + * 创建时间 + */ + @JsonProperty("created_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @JsonProperty("updated_at") + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dto/caseClinicalDoctor/CaseClinicalDoctorDto.java b/src/main/java/com/example/caseData/dto/caseClinicalDoctor/CaseClinicalDoctorDto.java new file mode 100644 index 0000000..463e1f9 --- /dev/null +++ b/src/main/java/com/example/caseData/dto/caseClinicalDoctor/CaseClinicalDoctorDto.java @@ -0,0 +1,128 @@ +package com.example.caseData.dto.caseClinicalDoctor; + +import cn.hutool.core.bean.BeanUtil; +import com.example.caseData.model.CaseClinicalDoctorModel; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +@Data +public class CaseClinicalDoctorDto { + + /** + * 主键id + */ + @JsonProperty("doctor_id") + private String doctorId; + + /** + * app唯一标识(存在即表示为注册用户) + */ + @JsonProperty("doctor_iden") + private String doctorIden; + + /** + * 医生名称 + */ + @JsonProperty("doctor_name") + private String doctorName; + + /** + * 所属医院id + */ + @JsonProperty("hospital_id") + private String hospitalId; + + /** + * 状态(1:正常 2:禁用) + */ + @JsonProperty("status") + private Integer status; + + /** + * 头像 + */ + @JsonProperty("avatar") + private String avatar; + + /** + * 创建时间 + */ + @JsonProperty("created_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @JsonProperty("updated_at") + private LocalDateTime updatedAt; + + /** + * 医院名称 + */ + @JsonProperty("hospital_name") + private String hospitalName; + + + /** + * 列表 + */ + public static List GetListDto(List models) { + if (models == null || models.isEmpty()) { + return Collections.emptyList(); + } + + return models.stream() + .map(model -> { + CaseClinicalDoctorDto dto = BeanUtil.copyProperties(model, CaseClinicalDoctorDto.class); + + // 示例:手动处理字段类型不一致 + if (model.getDoctorId() != null) { + dto.setDoctorId(String.valueOf(model.getDoctorId())); // Long -> String + } + + if (model.getHospitalId() != null) { + dto.setHospitalId(String.valueOf(model.getHospitalId())); // Long -> String + } + + // 医院名称 + if (model.getBasicHospital() != null) { + dto.setHospitalName(model.getBasicHospital().getHospitalName()); + } + + return dto; + }) + .collect(Collectors.toList()); + } + + /** + * 详情 + */ + public static CaseClinicalDoctorDto GetDto(CaseClinicalDoctorModel model) { + if (model == null) { + return null; + } + + CaseClinicalDoctorDto dto = BeanUtil.copyProperties(model, CaseClinicalDoctorDto.class); + + // 示例:手动处理字段类型不一致 + if (model.getDoctorId() != null) { + dto.setDoctorId(String.valueOf(model.getDoctorId())); // Long -> String + } + + if (model.getHospitalId() != null) { + dto.setHospitalId(String.valueOf(model.getHospitalId())); // Long -> String + } + + // 医院名称 + if (model.getBasicHospital() != null) { + dto.setHospitalName(model.getBasicHospital().getHospitalName()); + } + + return dto; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dto/caseClinicalVideo/CaseClinicalVideoDto.java b/src/main/java/com/example/caseData/dto/caseClinicalVideo/CaseClinicalVideoDto.java new file mode 100644 index 0000000..2495f16 --- /dev/null +++ b/src/main/java/com/example/caseData/dto/caseClinicalVideo/CaseClinicalVideoDto.java @@ -0,0 +1,133 @@ +package com.example.caseData.dto.caseClinicalVideo; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.example.caseData.dto.caseClinicalVideo.CaseClinicalVideoDto; +import com.example.caseData.dto.caseClinicalVideoAuthor.CaseClinicalVideoAuthorDto; +import com.example.caseData.dto.caseClinicalVideoAuthor.CaseClinicalVideoAuthorDto; +import com.example.caseData.model.CaseClinicalVideoModel; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +@Data +public class CaseClinicalVideoDto { + /** + * 主键id + */ + @JsonProperty("video_id") + private String videoId; + + /** + * 标题 + */ + @JsonProperty("video_title") + private String videoTitle; + + /** + * 状态(1:正常 2:禁用) + */ + @JsonProperty("video_status") + private Integer videoStatus; + + /** + * 阅读量 + */ + @JsonProperty("read_num") + private Integer readNum; + + /** + * 收藏量 + */ + @JsonProperty("collect_num") + private Integer collectNum; + + /** + * 视频编号(保利) + */ + @JsonProperty("video_no") + private String videoNo; + + /** + * 发表时间 + */ + @JsonProperty("push_date") + private LocalDateTime pushDate; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @JsonProperty("created_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @JsonProperty("updated_at") + private LocalDateTime updatedAt; + + /** + * 作者 + */ + @JsonProperty("author") + private List author; + + /** + * 列表 + */ + public static List GetListDto(List models) { + if (models == null || models.isEmpty()) { + return Collections.emptyList(); + } + + return models.stream() + .map(model -> { + CaseClinicalVideoDto dto = BeanUtil.copyProperties(model, CaseClinicalVideoDto.class); + + // 示例:手动处理字段类型不一致 + if (model.getVideoId() != null) { + dto.setVideoId(String.valueOf(model.getVideoId())); // Long -> String + } + + // 作者 + if (model.getAuthor() != null && !model.getAuthor().isEmpty()) { + List caseClinicalVideoAuthorListDto = CaseClinicalVideoAuthorDto.GetListDto(model.getAuthor()); + dto.setAuthor(caseClinicalVideoAuthorListDto); + } + + dto.setVideoNo(""); + return dto; + }) + .collect(Collectors.toList()); + } + + /** + * 详情 + */ + public static CaseClinicalVideoDto GetDto(CaseClinicalVideoModel model) { + if (model == null) { + return null; + } + + CaseClinicalVideoDto dto = BeanUtil.copyProperties(model, CaseClinicalVideoDto.class); + + // 类型转换示例 + if (model.getVideoId() != null) { + dto.setVideoId(String.valueOf(model.getVideoId())); // Long -> String + } + + // 作者 + if (model.getAuthor() != null && !model.getAuthor().isEmpty()) { + List caseClinicalVideoAuthorListDto = CaseClinicalVideoAuthorDto.GetListDto(model.getAuthor()); + dto.setAuthor(caseClinicalVideoAuthorListDto); + } + + return dto; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dto/caseClinicalVideoAuthor/CaseClinicalVideoAuthorDto.java b/src/main/java/com/example/caseData/dto/caseClinicalVideoAuthor/CaseClinicalVideoAuthorDto.java new file mode 100644 index 0000000..f5481dc --- /dev/null +++ b/src/main/java/com/example/caseData/dto/caseClinicalVideoAuthor/CaseClinicalVideoAuthorDto.java @@ -0,0 +1,107 @@ +package com.example.caseData.dto.caseClinicalVideoAuthor; + +import cn.hutool.core.bean.BeanUtil; +import com.example.caseData.dto.caseClinicalVideoAuthor.CaseClinicalVideoAuthorDto; +import com.example.caseData.dto.caseClinicalDoctor.CaseClinicalDoctorDto; +import com.example.caseData.model.CaseClinicalVideoAuthorModel; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +@Data +public class CaseClinicalVideoAuthorDto { + /** + * 主键id(可选) + */ + @JsonProperty("author_id") + private String authorId; + + /** + * 临床视频id(作为主键) + */ + @JsonProperty("video_id") + private String videoId; + + /** + * 医生id + */ + @JsonProperty("doctor_id") + private String doctorId; + + /** + * 医院名称 + */ + @JsonProperty("doctor_name") + private String doctorName; + + /** + * 医院名称 + */ + @JsonProperty("hospital_name") + private String hospitalName; + + /** + * 创建时间 + */ + @JsonProperty("created_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @JsonProperty("updated_at") + private LocalDateTime updatedAt; + + /** + * 列表 + */ + public static List GetListDto(List models) { + if (models == null || models.isEmpty()) { + return Collections.emptyList(); + } + + return models.stream() + .map(model -> { + CaseClinicalVideoAuthorDto dto = BeanUtil.copyProperties(model, CaseClinicalVideoAuthorDto.class); + + // 示例:手动处理字段类型不一致 + if (model.getAuthorId() != null) { + dto.setAuthorId(String.valueOf(model.getAuthorId())); // Long -> String + } + + if (model.getCaseClinicalDoctor() != null) { + CaseClinicalDoctorDto caseClinicalDoctorDto = CaseClinicalDoctorDto.GetDto(model.getCaseClinicalDoctor()); + dto.setDoctorName(caseClinicalDoctorDto.getDoctorName()); + } + + return dto; + }) + .collect(Collectors.toList()); + } + + /** + * 详情 + */ + public static CaseClinicalVideoAuthorDto GetDto(CaseClinicalVideoAuthorModel model) { + if (model == null) { + return null; + } + + CaseClinicalVideoAuthorDto dto = BeanUtil.copyProperties(model, CaseClinicalVideoAuthorDto.class); + + // 类型转换示例 + if (model.getAuthorId() != null) { + dto.setAuthorId(String.valueOf(model.getAuthorId())); // Long -> String + } + + if (model.getCaseClinicalDoctor() != null) { + CaseClinicalDoctorDto caseClinicalDoctorDto = CaseClinicalDoctorDto.GetDto(model.getCaseClinicalDoctor()); + dto.setDoctorName(caseClinicalDoctorDto.getDoctorName()); + } + + return dto; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dto/caseClinicalVideoLabel/CaseClinicalVideoLabelDto.java b/src/main/java/com/example/caseData/dto/caseClinicalVideoLabel/CaseClinicalVideoLabelDto.java new file mode 100644 index 0000000..77dcbf3 --- /dev/null +++ b/src/main/java/com/example/caseData/dto/caseClinicalVideoLabel/CaseClinicalVideoLabelDto.java @@ -0,0 +1,44 @@ +package com.example.caseData.dto.caseClinicalVideoLabel; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import java.time.LocalDateTime; + +@Data +public class CaseClinicalVideoLabelDto { + /** + * 主键id + */ + @JsonProperty("video_label_id") + private Long videoLabelId; + + /** + * 临床视频id + */ + @JsonProperty("video_id") + private Long videoId; + + /** + * app唯一标识 + */ + @JsonProperty("app_iden") + private String appIden; + + /** + * 标签名称 + */ + @JsonProperty("label_name") + private String labelName; + + /** + * 创建时间 + */ + @JsonProperty("created_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @JsonProperty("updated_at") + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dto/index/GetIndexClinicalDto.java b/src/main/java/com/example/caseData/dto/index/GetIndexClinicalDto.java new file mode 100644 index 0000000..a3bc613 --- /dev/null +++ b/src/main/java/com/example/caseData/dto/index/GetIndexClinicalDto.java @@ -0,0 +1,26 @@ +package com.example.caseData.dto.index; + +import com.example.caseData.dto.caseClinicalArticle.CaseClinicalArticleDto; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class GetIndexClinicalDto { + @JsonProperty("new_articles") + private List newArticles; // 最新上线 + + @JsonProperty("most_read_articles") + private List mostReadArticles; // 最多阅读 + + @JsonProperty("recommend_hospital") + private List recommendHospital; // 医院病例库推荐 + + @JsonProperty("recommend_doctor") + private List recommendDoctor; // 医生病例库推荐 +} diff --git a/src/main/java/com/example/caseData/dto/index/RecommendDoctorDto.java b/src/main/java/com/example/caseData/dto/index/RecommendDoctorDto.java new file mode 100644 index 0000000..cd5c978 --- /dev/null +++ b/src/main/java/com/example/caseData/dto/index/RecommendDoctorDto.java @@ -0,0 +1,86 @@ +package com.example.caseData.dto.index; + +import cn.hutool.core.bean.BeanUtil; +import com.example.caseData.model.StatsCaseClinicalDoctorModel; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 医生病例库推荐 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class RecommendDoctorDto { + @JsonProperty("doctor_id") + private String doctorId; // 医生id + + @JsonProperty("doctor_name") + private String doctorName; // 医生名称 + + @JsonProperty("hospital_name") + private String hospitalName; // 医院名称 + + /** + * 列表 + */ + public static List GetListDto(List models) { + if (models == null || models.isEmpty()) { + return Collections.emptyList(); + } + + return models.stream() + .map(model -> { + RecommendDoctorDto dto = BeanUtil.copyProperties(model, RecommendDoctorDto.class); + + // 类型转换示例 + if (model.getDoctorId() != null) { + dto.setDoctorId(String.valueOf(model.getDoctorId())); + } + + if (model.getCaseClinicalDoctor() != null) { + dto.setDoctorName(model.getCaseClinicalDoctor().getDoctorName()); + + if (model.getCaseClinicalDoctor().getBasicHospital() != null) { + dto.setHospitalName(model.getCaseClinicalDoctor().getBasicHospital().getHospitalName()); + } + } + + return dto; + }) + .collect(Collectors.toList()); + } + + /** + * 详情 + */ + public static RecommendDoctorDto GetDto(StatsCaseClinicalDoctorModel model) { + if (model == null) { + return null; + } + + RecommendDoctorDto dto = BeanUtil.copyProperties(model, RecommendDoctorDto.class); + + // 类型转换示例 + if (model.getDoctorId() != null) { + dto.setDoctorId(String.valueOf(model.getDoctorId())); + } + + if (model.getCaseClinicalDoctor() != null) { + dto.setDoctorName(model.getCaseClinicalDoctor().getDoctorName()); + + if (model.getCaseClinicalDoctor().getBasicHospital() != null) { + dto.setHospitalName(model.getCaseClinicalDoctor().getBasicHospital().getHospitalName()); + } + } + + return dto; + } + +} diff --git a/src/main/java/com/example/caseData/dto/index/RecommendHospitalDto.java b/src/main/java/com/example/caseData/dto/index/RecommendHospitalDto.java new file mode 100644 index 0000000..634f098 --- /dev/null +++ b/src/main/java/com/example/caseData/dto/index/RecommendHospitalDto.java @@ -0,0 +1,74 @@ +package com.example.caseData.dto.index; + +import cn.hutool.core.bean.BeanUtil; +import com.example.caseData.model.StatsCaseClinicalHospitalModel; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 医院病例库推荐 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class RecommendHospitalDto { + @JsonProperty("hospital_id") + private String hospitalId; // 医院id + + @JsonProperty("hospital_name") + private String hospitalName; // 医院名称 + + /** + * 列表 + */ + public static List GetListDto(List models) { + if (models == null || models.isEmpty()) { + return Collections.emptyList(); + } + + return models.stream() + .map(model -> { + RecommendHospitalDto dto = BeanUtil.copyProperties(model, RecommendHospitalDto.class); + + // 类型转换示例 + if (model.getHospitalId() != null) { + dto.setHospitalId(String.valueOf(model.getHospitalId())); + } + + if (model.getBasicHospital() != null) { + dto.setHospitalName(model.getBasicHospital().getHospitalName()); + } + + return dto; + }) + .collect(Collectors.toList()); + } + + /** + * 详情 + */ + public static RecommendHospitalDto GetDto(StatsCaseClinicalHospitalModel model) { + if (model == null) { + return null; + } + + RecommendHospitalDto dto = BeanUtil.copyProperties(model, RecommendHospitalDto.class); + + // 类型转换示例 + if (model.getHospitalId() != null) { + dto.setHospitalId(String.valueOf(model.getHospitalId())); + } + + if (model.getBasicHospital() != null) { + dto.setHospitalName(model.getBasicHospital().getHospitalName()); + } + + return dto; + } +} diff --git a/src/main/java/com/example/caseData/dto/statsCaseClinical/StatsCaseClinicalDto.java b/src/main/java/com/example/caseData/dto/statsCaseClinical/StatsCaseClinicalDto.java new file mode 100644 index 0000000..bfd475a --- /dev/null +++ b/src/main/java/com/example/caseData/dto/statsCaseClinical/StatsCaseClinicalDto.java @@ -0,0 +1,95 @@ +package com.example.caseData.dto.statsCaseClinical; + +import cn.hutool.core.bean.BeanUtil; +import com.example.caseData.model.StatsCaseClinicalModel; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +@Data +public class StatsCaseClinicalDto { + /** + * 主键id + */ + @JsonProperty("stats_id") + private String statsId; + + /** + * 总阅读量-文章 + */ + @JsonProperty("article_read_num") + private Integer articleReadNum; + + /** + * 总收藏量-文章 + */ + @JsonProperty("article_collect_num") + private Integer articleCollectNum; + + /** + * 总阅读量-视频 + */ + @JsonProperty("video_read_num") + private Integer videoReadNum; + + /** + * 总收藏量-视频 + */ + @JsonProperty("video_collect_num") + private Integer videoCollectNum; + + /** + * 创建时间 + */ + @JsonProperty("created_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @JsonProperty("updated_at") + private LocalDateTime updatedAt; + + /** + * 列表 + */ + public static List GetListDto(List models) { + if (models == null || models.isEmpty()) { + return Collections.emptyList(); + } + + return models.stream() + .map(model -> { + StatsCaseClinicalDto dto = BeanUtil.copyProperties(model, StatsCaseClinicalDto.class); + + // 示例:手动处理字段类型不一致 + if (model.getStatsId() != null) { + dto.setStatsId(String.valueOf(model.getStatsId())); // Long -> String + } + + return dto; + }) + .collect(Collectors.toList()); + } + + /** + * 详情 + */ + public static StatsCaseClinicalDto GetDto(StatsCaseClinicalModel model) { + if (model == null) { + return null; + } + + StatsCaseClinicalDto dto = BeanUtil.copyProperties(model, StatsCaseClinicalDto.class); + + // 示例:手动处理字段类型不一致 + if (model.getStatsId() != null) { + dto.setStatsId(String.valueOf(model.getStatsId())); // Long -> String + } + + return dto; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dto/statsCaseClinicalDoctor/StatsCaseClinicalDoctorDto.java b/src/main/java/com/example/caseData/dto/statsCaseClinicalDoctor/StatsCaseClinicalDoctorDto.java new file mode 100644 index 0000000..74883c8 --- /dev/null +++ b/src/main/java/com/example/caseData/dto/statsCaseClinicalDoctor/StatsCaseClinicalDoctorDto.java @@ -0,0 +1,148 @@ +package com.example.caseData.dto.statsCaseClinicalDoctor; + +import cn.hutool.core.bean.BeanUtil; +import com.example.caseData.dto.basicHospital.BasicHospitalDto; +import com.example.caseData.dto.caseClinicalDoctor.CaseClinicalDoctorDto; +import com.example.caseData.model.StatsCaseClinicalDoctorModel; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +@Data +public class StatsCaseClinicalDoctorDto { + /** + * 主键id + */ + @JsonProperty("stats_id") + private String statsId; + + /** + * 医院id + */ + @JsonProperty("doctor_id") + private String doctorId; + + /** + * 数量-文章 + */ + @JsonProperty("article_num") + private Integer articleNum; + + /** + * 总阅读量-文章 + */ + @JsonProperty("article_read_num") + private Integer articleReadNum; + + /** + * 总收藏量-文章 + */ + @JsonProperty("article_collect_num") + private Integer articleCollectNum; + + /** + * 最后一篇文章发表时间 + */ + @JsonProperty("last_push_date") + private LocalDateTime lastPushDate; + + /** + * 数量-视频 + */ + @JsonProperty("video_num") + private Integer videoNum; + + /** + * 总阅读量-视频 + */ + @JsonProperty("video_read_num") + private Integer videoReadNum; + + /** + * 总收藏量-视频 + */ + @JsonProperty("video_collect_num") + private Integer videoCollectNum; + + /** + * 创建时间 + */ + @JsonProperty("created_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @JsonProperty("updated_at") + private LocalDateTime updatedAt; + + /** + * 基础数据-医生 + */ + @JsonProperty("case_clinical_doctor") + private CaseClinicalDoctorDto caseClinicalDoctor; + + /** + * 列表 + */ + public static List GetListDto(List models) { + if (models == null || models.isEmpty()) { + return Collections.emptyList(); + } + + return models.stream() + .map(model -> { + com.example.caseData.dto.statsCaseClinicalDoctor.StatsCaseClinicalDoctorDto dto = BeanUtil.copyProperties(model, com.example.caseData.dto.statsCaseClinicalDoctor.StatsCaseClinicalDoctorDto.class); + + // 示例:手动处理字段类型不一致 + if (model.getStatsId() != null) { + dto.setStatsId(String.valueOf(model.getStatsId())); // Long -> String + } + + if (model.getDoctorId() != null) { + dto.setDoctorId(String.valueOf(model.getDoctorId())); // Long -> String + } + + // 基础数据-医生 + if (model.getCaseClinicalDoctor() != null) { + CaseClinicalDoctorDto caseClinicalDoctorDto = CaseClinicalDoctorDto.GetDto(model.getCaseClinicalDoctor()); + dto.setCaseClinicalDoctor(caseClinicalDoctorDto); + } + + return dto; + }) + .collect(Collectors.toList()); + } + + /** + * 详情 + */ + public static com.example.caseData.dto.statsCaseClinicalDoctor.StatsCaseClinicalDoctorDto GetDto(StatsCaseClinicalDoctorModel model) { + if (model == null) { + return null; + } + + com.example.caseData.dto.statsCaseClinicalDoctor.StatsCaseClinicalDoctorDto dto = BeanUtil.copyProperties(model, com.example.caseData.dto.statsCaseClinicalDoctor.StatsCaseClinicalDoctorDto.class); + + // 示例:手动处理字段类型不一致 + if (model.getStatsId() != null) { + dto.setStatsId(String.valueOf(model.getStatsId())); // Long -> String + } + + if (model.getDoctorId() != null) { + dto.setDoctorId(String.valueOf(model.getDoctorId())); // Long -> String + } + + // 基础数据-医生 + if (model.getCaseClinicalDoctor() != null) { + CaseClinicalDoctorDto caseClinicalDoctorDto = CaseClinicalDoctorDto.GetDto(model.getCaseClinicalDoctor()); + dto.setCaseClinicalDoctor(caseClinicalDoctorDto); + } + + return dto; + } +} diff --git a/src/main/java/com/example/caseData/dto/statsCaseClinicalHospital/StatsCaseClinicalHospitalDto.java b/src/main/java/com/example/caseData/dto/statsCaseClinicalHospital/StatsCaseClinicalHospitalDto.java new file mode 100644 index 0000000..fb4273d --- /dev/null +++ b/src/main/java/com/example/caseData/dto/statsCaseClinicalHospital/StatsCaseClinicalHospitalDto.java @@ -0,0 +1,145 @@ +package com.example.caseData.dto.statsCaseClinicalHospital; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.annotation.TableField; +import com.example.caseData.dto.basicHospital.BasicHospitalDto; +import com.example.caseData.model.StatsCaseClinicalHospitalModel; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +//@JsonInclude(JsonInclude.Include.ALWAYS) // 这行是关键,强制序列化 null 值 +@Data +public class StatsCaseClinicalHospitalDto { + /** + * 主键id + */ + @JsonProperty("stats_id") + private String statsId; + + /** + * 医院id + */ + @JsonProperty("hospital_id") + private String hospitalId; + + /** + * 数量-文章 + */ + @JsonProperty("article_num") + private Integer articleNum; + + /** + * 总阅读量-文章 + */ + @JsonProperty("article_read_num") + private Integer articleReadNum; + + /** + * 总收藏量-文章 + */ + @JsonProperty("article_collect_num") + private Integer articleCollectNum; + + /** + * 最后一篇文章发表时间 + */ + @JsonProperty("last_push_date") + private LocalDateTime lastPushDate; + + /** + * 数量-视频 + */ + @JsonProperty("video_num") + private Integer videoNum; + + /** + * 总阅读量-视频 + */ + @JsonProperty("video_read_num") + private Integer videoReadNum; + + /** + * 总收藏量-视频 + */ + @JsonProperty("video_collect_num") + private Integer videoCollectNum; + + /** + * 创建时间 + */ + @JsonProperty("created_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @JsonProperty("updated_at") + private LocalDateTime updatedAt; + + /** + * 基础数据-医院 + */ + @JsonProperty("basic_hospital") + private BasicHospitalDto basicHospital; + + /** + * 列表 + */ + public static List GetListDto(List models) { + if (models == null || models.isEmpty()) { + return Collections.emptyList(); + } + + return models.stream() + .map(model -> { + StatsCaseClinicalHospitalDto dto = BeanUtil.copyProperties(model, StatsCaseClinicalHospitalDto.class); + + // 示例:手动处理字段类型不一致 + if (model.getStatsId() != null) { + dto.setStatsId(String.valueOf(model.getStatsId())); // Long -> String + } + + // 基础数据-医院 + if (model.getBasicHospital() != null) { + BasicHospitalDto basicHospitalListDto = BasicHospitalDto.GetDto(model.getBasicHospital()); + dto.setBasicHospital(basicHospitalListDto); + } + + return dto; + }) + .collect(Collectors.toList()); + } + + /** + * 详情 + */ + public static StatsCaseClinicalHospitalDto GetDto(StatsCaseClinicalHospitalModel model) { + if (model == null) { + return null; + } + + StatsCaseClinicalHospitalDto dto = BeanUtil.copyProperties(model, StatsCaseClinicalHospitalDto.class); + + // 示例:手动处理字段类型不一致 + if (model.getStatsId() != null) { + dto.setStatsId(String.valueOf(model.getStatsId())); // Long -> String + } + + if (model.getHospitalId() != null) { + dto.setHospitalId(String.valueOf(model.getHospitalId())); // Long -> String + } + + // 基础数据-医院 + if (model.getBasicHospital() != null) { + BasicHospitalDto basicHospitalListDto = BasicHospitalDto.GetDto(model.getBasicHospital()); + dto.setBasicHospital(basicHospitalListDto); + } + + return dto; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dto/userCollectClinicalArticle/UserCollectClinicalArticleDto.java b/src/main/java/com/example/caseData/dto/userCollectClinicalArticle/UserCollectClinicalArticleDto.java new file mode 100644 index 0000000..3454442 --- /dev/null +++ b/src/main/java/com/example/caseData/dto/userCollectClinicalArticle/UserCollectClinicalArticleDto.java @@ -0,0 +1,38 @@ +package com.example.caseData.dto.userCollectClinicalArticle; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import java.time.LocalDateTime; + +@Data +public class UserCollectClinicalArticleDto { + /** + * 主键id + */ + @JsonProperty("collect_id") + private Long collectId; + + /** + * 用户id + */ + @JsonProperty("user_id") + private Long userId; + + /** + * 临床文章id + */ + @JsonProperty("article_id") + private Long articleId; + + /** + * 创建时间 + */ + @JsonProperty("created_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @JsonProperty("updated_at") + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dto/userCollectClinicalVideo/UserCollectClinicalVideoDto.java b/src/main/java/com/example/caseData/dto/userCollectClinicalVideo/UserCollectClinicalVideoDto.java new file mode 100644 index 0000000..aec0e73 --- /dev/null +++ b/src/main/java/com/example/caseData/dto/userCollectClinicalVideo/UserCollectClinicalVideoDto.java @@ -0,0 +1,38 @@ +package com.example.caseData.dto.userCollectClinicalVideo; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import java.time.LocalDateTime; + +@Data +public class UserCollectClinicalVideoDto { + /** + * 主键id + */ + @JsonProperty("collect_id") + private Long collectId; + + /** + * 用户id + */ + @JsonProperty("user_id") + private Long userId; + + /** + * 临床视频id + */ + @JsonProperty("video_id") + private Long videoId; + + /** + * 创建时间 + */ + @JsonProperty("created_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @JsonProperty("updated_at") + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dto/userCommentClinicalArticle/UserCommentClinicalArticleDto.java b/src/main/java/com/example/caseData/dto/userCommentClinicalArticle/UserCommentClinicalArticleDto.java new file mode 100644 index 0000000..75096af --- /dev/null +++ b/src/main/java/com/example/caseData/dto/userCommentClinicalArticle/UserCommentClinicalArticleDto.java @@ -0,0 +1,86 @@ +package com.example.caseData.dto.userCommentClinicalArticle; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import java.time.LocalDateTime; + +@Data +public class UserCommentClinicalArticleDto { + /** + * 主键id + */ + @JsonProperty("comment_id") + private Long commentId; + + /** + * 用户id + */ + @JsonProperty("user_id") + private Long userId; + + /** + * 临床文章id + */ + @JsonProperty("article_id") + private Long articleId; + + /** + * 父级id,一级评论为null + */ + @JsonProperty("parent_id") + private Long parentId; + + /** + * 根评论id,一级评论时为null。其余为一级评论id + */ + @JsonProperty("root_id") + private Long rootId; + + /** + * 评论状态(0:禁用 1:正常) + */ + @JsonProperty("status") + private Integer status; + + /** + * 是否存在敏感词(0:否 1:是) + */ + @JsonProperty("is_sensitive") + private Integer isSensitive; + + /** + * 是否优质留言(0:否 1:是) + */ + @JsonProperty("is_high_quality") + private Integer isHighQuality; + + /** + * 点赞数量 + */ + @JsonProperty("like_num") + private Integer likeNum; + + /** + * 评论内容 + */ + @JsonProperty("content") + private String content; + + /** + * 评论内容(原版) + */ + @JsonProperty("content_word") + private String contentWord; + + /** + * 创建时间 + */ + @JsonProperty("created_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @JsonProperty("updated_at") + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/dto/userCommentClinicalVideo/UserCommentClinicalVideoDto.java b/src/main/java/com/example/caseData/dto/userCommentClinicalVideo/UserCommentClinicalVideoDto.java new file mode 100644 index 0000000..0398e68 --- /dev/null +++ b/src/main/java/com/example/caseData/dto/userCommentClinicalVideo/UserCommentClinicalVideoDto.java @@ -0,0 +1,86 @@ +package com.example.caseData.dto.userCommentClinicalVideo; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import java.time.LocalDateTime; + +@Data +public class UserCommentClinicalVideoDto { + /** + * 主键id + */ + @JsonProperty("comment_id") + private Long commentId; + + /** + * 用户id + */ + @JsonProperty("user_id") + private Long userId; + + /** + * 临床视频id + */ + @JsonProperty("video_id") + private Long videoId; + + /** + * 父级id,一级评论为null + */ + @JsonProperty("parent_id") + private Long parentId; + + /** + * 根评论id,一级评论时为null。其余为一级评论id + */ + @JsonProperty("root_id") + private Long rootId; + + /** + * 评论状态(0:禁用 1:正常) + */ + @JsonProperty("status") + private Integer status; + + /** + * 是否存在敏感词(0:否 1:是) + */ + @JsonProperty("is_sensitive") + private Integer isSensitive; + + /** + * 是否优质留言(0:否 1:是) + */ + @JsonProperty("is_high_quality") + private Integer isHighQuality; + + /** + * 点赞数量 + */ + @JsonProperty("like_num") + private Integer likeNum; + + /** + * 评论内容 + */ + @JsonProperty("content") + private String content; + + /** + * 评论内容(原版) + */ + @JsonProperty("content_word") + private String contentWord; + + /** + * 创建时间 + */ + @JsonProperty("created_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @JsonProperty("updated_at") + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/exception/BusinessException.java b/src/main/java/com/example/caseData/exception/BusinessException.java new file mode 100644 index 0000000..2a28ece --- /dev/null +++ b/src/main/java/com/example/caseData/exception/BusinessException.java @@ -0,0 +1,55 @@ +package com.example.caseData.exception; + +import com.example.caseData.config.EnvConfig; +import com.example.caseData.config.OssConfig; +import com.example.caseData.utils.EnvUtil; +import jakarta.annotation.Resource; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +import java.util.Objects; + +@Slf4j +@Getter +public class BusinessException extends RuntimeException { + /** + * 错误码 + */ + private final String code; + + /** + * 错误信息 + */ + private final String message; + + /** + * 构造函数 + * @param code 错误码 + * @param message 错误信息 + */ + public BusinessException(String code, String message) { + super(message); + this.code = code; + this.message = message; + } + + /** + * 构造函数 + * @param message 错误信息 + */ + public BusinessException(String message) { + this("500", message); + } + + /** + * 构造函数 + * @param code 错误码 + * @param message 错误信息 + * @param cause 原始异常 + */ + public BusinessException(String code, String message, Throwable cause) { + super(message, cause); + this.code = code; + this.message = message; + } +} diff --git a/src/main/java/com/example/caseData/exception/GlobalExceptionHandler.java b/src/main/java/com/example/caseData/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..8db4101 --- /dev/null +++ b/src/main/java/com/example/caseData/exception/GlobalExceptionHandler.java @@ -0,0 +1,95 @@ +package com.example.caseData.exception; + +import com.example.caseData.common.Response; +import com.example.caseData.utils.EnvUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.apache.ibatis.binding.BindingException; +import org.apache.ibatis.exceptions.PersistenceException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.FieldError; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.apache.ibatis.exceptions.PersistenceException; + +import java.sql.SQLSyntaxErrorException; +import java.util.HashMap; +import java.util.Map; + +/** + * 全局异常类 + */ +@Slf4j +@ControllerAdvice +public class GlobalExceptionHandler { + // 处理所有未捕获的异常 + @ExceptionHandler(Exception.class) + public ResponseEntity> handleGlobalException(Exception ex) { + System.out.print(ExceptionUtils.getStackTrace(ex)); + Map errorResponse = new HashMap<>(); + + String message = ExceptionUtils.getStackTrace(ex); + if (EnvUtil.isProd()) { + log.error("error:{}", message); + message = "内部错误"; + } + + errorResponse.put("message", "异常"); + errorResponse.put("data", null); + errorResponse.put("code", HttpStatus.INTERNAL_SERVER_ERROR.value()); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse); + } + + // 处理 404 请求(接口不存在) + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + @ResponseStatus(HttpStatus.NOT_FOUND) + public ResponseEntity> handleNotFoundException(HttpRequestMethodNotSupportedException ex) { + Map errorResponse = new HashMap<>(); + errorResponse.put("message", "接口不存在"); + errorResponse.put("code", 404); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(errorResponse); + } + + // 处理参数校验异常 + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity> handleValidationException(MethodArgumentNotValidException ex) { + // 记录的错误 +// Map errors = new HashMap<>(); +// ex.getBindingResult().getFieldErrors().forEach(error -> +// errors.put(error.getField(), error.getDefaultMessage())); + +// Map errorResponse = new HashMap<>(); +// errorResponse.put("code", HttpStatus.BAD_REQUEST.value()); +// errorResponse.put("message", "错误请求"); + + + Map errorResponse = new HashMap<>(); + // 获取第一个字段错误 + FieldError fieldError = ex.getBindingResult().getFieldErrors().stream().findFirst().orElse(null); + + if (fieldError != null) { + // 返回第一个字段的错误信息 + errorResponse.put("code", HttpStatus.BAD_REQUEST.value()); + errorResponse.put("message", fieldError.getDefaultMessage()); + } else { + // 如果没有具体错误信息 + errorResponse.put("code", HttpStatus.BAD_REQUEST.value()); + errorResponse.put("message", "错误请求"); + } + + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorResponse); + } + + // 处理业务异常 + @ExceptionHandler(BusinessException.class) + public ResponseEntity> handleBusinessException(BusinessException ex) { + Map errorResponse = new HashMap<>(); + errorResponse.put("message", ex.getMessage()); + errorResponse.put("code", ex.getCode()); + return ResponseEntity.ok(errorResponse); + } +} diff --git a/src/main/java/com/example/caseData/extend/app/Base.java b/src/main/java/com/example/caseData/extend/app/Base.java new file mode 100644 index 0000000..9dce823 --- /dev/null +++ b/src/main/java/com/example/caseData/extend/app/Base.java @@ -0,0 +1,122 @@ +package com.example.caseData.extend.app; + +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.*; + +@Slf4j +public class Base { + private static final ObjectMapper objectMapper = new ObjectMapper(); + + /** + * 生成签名 + * @param params 需要签名的参数(支持嵌套 Map) + * @param secretKey 密钥 + * @return 签名字符串 + */ + public static String genSignature(Map params, String secretKey) { + try { + // Step 1: 对 Map 进行递归排序 + Map sortedMap = sortMapRecursively(params); + + // Step 2: 转为 JSON 字符串 + String json = objectMapper.writeValueAsString(sortedMap); + + // Step 3: 使用 HMAC-SHA256 签名 + return hmacSha256(json, secretKey); + } catch (JsonProcessingException e) { + return null; + } + } + + /** + * 对 Map 进行递归排序(key 排序),支持嵌套 Map 和 List + */ + public static Map sortMapRecursively(Map data) { + Map sortedMap = new TreeMap<>(); // TreeMap 会自动按 key 排序 + + for (Map.Entry entry : data.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + + if (value instanceof Map) { + // 如果是嵌套 map,递归排序 + @SuppressWarnings("unchecked") + Map nestedMap = (Map) value; + sortedMap.put(key, sortMapRecursively(nestedMap)); + } else if (value instanceof List) { + // 如果是列表,检查每一项是否是 map,如果是则排序 + @SuppressWarnings("unchecked") + List list = (List) value; + List sortedList = new ArrayList<>(); + for (Object item : list) { + if (item instanceof Map) { + @SuppressWarnings("unchecked") + Map nestedItemMap = (Map) item; + sortedList.add(sortMapRecursively(nestedItemMap)); + } else { + sortedList.add(item); + } + } + sortedMap.put(key, sortedList); + } else { + // 普通字段,直接插入 + sortedMap.put(key, value); + } + } + + return sortedMap; + } + + /** + * HMAC-SHA256 加密 + */ + private static String hmacSha256(String data, String key) { + try { + Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); + SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); + sha256_HMAC.init(secretKeySpec); + byte[] result = sha256_HMAC.doFinal(data.getBytes(StandardCharsets.UTF_8)); + + // 转为 16 进制字符串 + StringBuilder hexString = new StringBuilder(); + for (byte b : result) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) hexString.append('0'); + hexString.append(hex); + } + return hexString.toString(); + } catch (Exception e) { + return null; + } + } + + /** + * 发送 POST JSON 请求 + * @param url 请求地址 + * @param jsonData JSON 字符串 + * @param headers 请求头 + * @return 响应字符串 + */ + public String postJson(String url, String jsonData, Map headers) { + HttpRequest request = HttpRequest.post(url) + .body(jsonData) + .header("Content-Type", "application/json"); + + if (headers != null) { + headers.forEach(request::header); + } + + try (HttpResponse response = request.execute()) { + return response.body(); + } + } +} diff --git a/src/main/java/com/example/caseData/extend/app/Hospital/GetHospitalByUuidResponse.java b/src/main/java/com/example/caseData/extend/app/Hospital/GetHospitalByUuidResponse.java new file mode 100644 index 0000000..97d554d --- /dev/null +++ b/src/main/java/com/example/caseData/extend/app/Hospital/GetHospitalByUuidResponse.java @@ -0,0 +1,46 @@ +package com.example.caseData.extend.app.Hospital; + +import com.example.caseData.extend.app.UserInfo.GetUserInfoByMobileResponse; +import lombok.Data; + +@Data +public class GetHospitalByUuidResponse +{ + /** 接口调用状态。200:正常;其它值:调用出错 */ + private int code; + + /** 结果说明。如果接口调用出错,那么返回错误描述。成功则返回 ok */ + private String msg; + + /** 接口返回的用户信息数据 */ + private GetHospitalByUuidData data; + + /** 接口是否调用成功 */ + private boolean success; + + /** 错误信息或提示信息 */ + private String message; + + + /** + * 根据手机号获取医生信息 - 详细数据 + */ + @Data + public static class GetHospitalByUuidData { + + /** 医院唯一标识 */ + private String uuid; + + /** 科室 */ + private String name; + + /** 等级 */ + private String level; + + /** 省份 */ + private String prov_name; + + /** 医生数量 */ + private Integer expert_num; + } +} diff --git a/src/main/java/com/example/caseData/extend/app/Hospital/Hospital.java b/src/main/java/com/example/caseData/extend/app/Hospital/Hospital.java new file mode 100644 index 0000000..0ef8228 --- /dev/null +++ b/src/main/java/com/example/caseData/extend/app/Hospital/Hospital.java @@ -0,0 +1,68 @@ +package com.example.caseData.extend.app.Hospital; + +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import cn.hutool.json.JSONUtil; +import com.example.caseData.config.AppConfig; +import com.example.caseData.exception.BusinessException; +import com.example.caseData.extend.app.Base; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +@Slf4j +@Component +public class Hospital extends Base { + @Resource + private AppConfig appConfig; + + // 根据医院唯一标识获取医院数据 + public GetHospitalByUuidResponse getHospitalByUuid(String hospitalIden) throws BusinessException { + String timestamp = String.valueOf(System.currentTimeMillis() / 1000); + + // 处理参数 + Map requestData = new HashMap<>(); + requestData.put("hospital_uuid", hospitalIden); + requestData.put("platform", appConfig.getPlatform()); + requestData.put("timestamp", timestamp); + + // 生成签名 + String sign = genSignature(requestData,appConfig.getSecretKey()); + + String url = appConfig.getApiUrl() + "/expert-api/getHospitalByUuid"; + String jsonBody = JSONUtil.toJsonStr(requestData); + log.info("获取app数据参数:{}",jsonBody); + + try(HttpResponse response = HttpRequest.post(url) + .header("Content-Type", "application/json") + .header("sign", sign) + .body(jsonBody) + .execute()){ + + if (response.getStatus() != 200) { + throw new BusinessException("失败"); + } + + // 反序列化 JSON + GetHospitalByUuidResponse result = JSONUtil.toBean(response.body(), GetHospitalByUuidResponse.class); + log.info("获取app数据返回:{}",result); + if (result.getCode() != 200){ + if (!Objects.equals(result.getMsg(), "")){ + throw new BusinessException(result.getMsg()); + }else{ + throw new BusinessException("失败"); + } + } + + if (result.getData() == null){ + throw new BusinessException("失败"); + } + + return result; + } + } +} diff --git a/src/main/java/com/example/caseData/extend/app/UserInfo/GetUserInfoByMobileResponse.java b/src/main/java/com/example/caseData/extend/app/UserInfo/GetUserInfoByMobileResponse.java new file mode 100644 index 0000000..da1262e --- /dev/null +++ b/src/main/java/com/example/caseData/extend/app/UserInfo/GetUserInfoByMobileResponse.java @@ -0,0 +1,56 @@ +package com.example.caseData.extend.app.UserInfo; + +import lombok.Data; + +@Data +public class GetUserInfoByMobileResponse { + /** 接口调用状态。200:正常;其它值:调用出错 */ + private int code; + + /** 结果说明。如果接口调用出错,那么返回错误描述。成功则返回 ok */ + private String msg; + + /** 接口返回的用户信息数据 */ + private GetUserInfoByMobileData data; + + /** 接口是否调用成功 */ + private boolean success; + + /** 错误信息或提示信息 */ + private String message; + + + /** + * 根据手机号获取医生信息 - 详细数据 + */ + @Data + public static class GetUserInfoByMobileData { + + /** app唯一标识 */ + private String uuid; + + /** 科室 */ + private String officeName; + + /** 姓名 */ + private String realname; + + /** 医院唯一标识 */ + private String hospitalUuid; + + /** 手机号 */ + private String mobile; + + /** 头像地址 */ + private String photo; + + /** 创建时间 */ + private String createDate; + + /** 职称 */ + private String positionName; + + /** 省份 */ + private String provName; + } +} diff --git a/src/main/java/com/example/caseData/extend/app/UserInfo/UserInfo.java b/src/main/java/com/example/caseData/extend/app/UserInfo/UserInfo.java new file mode 100644 index 0000000..e830a48 --- /dev/null +++ b/src/main/java/com/example/caseData/extend/app/UserInfo/UserInfo.java @@ -0,0 +1,68 @@ +package com.example.caseData.extend.app.UserInfo; + +import cn.hutool.json.JSONUtil; +import com.example.caseData.config.AppConfig; +import com.example.caseData.exception.BusinessException; +import com.example.caseData.extend.app.Base; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +@Slf4j +@Component +public class UserInfo extends Base { + @Resource + private AppConfig appConfig; + + // 根据手机号获取信息V3 + public GetUserInfoByMobileResponse getUserInfoByMobile(String mobile) throws BusinessException { + String timestamp = String.valueOf(System.currentTimeMillis() / 1000); + + // 处理参数 + Map requestData = new HashMap<>(); + requestData.put("mobile", mobile); + requestData.put("platform", appConfig.getPlatform()); + requestData.put("timestamp", timestamp); + + // 生成签名 + String sign = genSignature(requestData,appConfig.getSecretKey()); + + String url = appConfig.getApiUrl() + "/expert-api/getInfoByMobileV3"; + String jsonBody = JSONUtil.toJsonStr(requestData); + log.info("获取app数据参数:{}",jsonBody); + + try(HttpResponse response = HttpRequest.post(url) + .header("Content-Type", "application/json") + .header("sign", sign) + .body(jsonBody) + .execute()){ + + if (response.getStatus() != 200) { + throw new BusinessException("失败"); + } + + // 反序列化 JSON + GetUserInfoByMobileResponse result = JSONUtil.toBean(response.body(), GetUserInfoByMobileResponse.class); + log.info("获取app数据返回:{}",result); + if (result.getCode() != 200){ + if (!Objects.equals(result.getMsg(), "")){ + throw new BusinessException(result.getMsg()); + }else{ + throw new BusinessException("失败"); + } + } + + if (result.getData() == null){ + throw new BusinessException("失败"); + } + + return result; + } + } +} diff --git a/src/main/java/com/example/caseData/extend/weChat/WxMaRedisConfig.java b/src/main/java/com/example/caseData/extend/weChat/WxMaRedisConfig.java new file mode 100644 index 0000000..37410b1 --- /dev/null +++ b/src/main/java/com/example/caseData/extend/weChat/WxMaRedisConfig.java @@ -0,0 +1,47 @@ +package com.example.caseData.extend.weChat; + + +import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.StringRedisTemplate; + +import java.util.concurrent.TimeUnit; + +@Slf4j +public class WxMaRedisConfig extends WxMaDefaultConfigImpl { + + private final StringRedisTemplate redisTemplate; + + public WxMaRedisConfig(StringRedisTemplate redisTemplate) { + this.redisTemplate = redisTemplate; + } + + @Override + public String getAccessToken() { + String redisKey = "wx:ma:access_token:" + this.getAppid(); + String token = redisTemplate.opsForValue().get(redisKey); + if (token != null) { + return token; + } + + synchronized (this) { + token = redisTemplate.opsForValue().get(redisKey); + if (token != null) return token; + + try { + String newToken = super.getAccessToken(); // 强制刷新 + redisTemplate.opsForValue().set(redisKey, newToken, this.getExpiresTime() - 200L, TimeUnit.SECONDS); + return newToken; + } catch (Exception e) { + log.error("获取access_token失败", e); + throw new RuntimeException("获取access_token失败", e); + } + } + } + + @Override + public void updateAccessToken(String accessToken, int expiresInSeconds) { + String redisKey = "wx:ma:access_token:" + this.getAppid(); + redisTemplate.opsForValue().set(redisKey, accessToken, expiresInSeconds - 200L, TimeUnit.SECONDS); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/extend/weChat/WxMaServiceConfig.java b/src/main/java/com/example/caseData/extend/weChat/WxMaServiceConfig.java new file mode 100644 index 0000000..c2ffc40 --- /dev/null +++ b/src/main/java/com/example/caseData/extend/weChat/WxMaServiceConfig.java @@ -0,0 +1,22 @@ +package com.example.caseData.extend.weChat; + +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl; +import com.example.caseData.config.WxMaConfig; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.core.StringRedisTemplate; + +@Configuration +public class WxMaServiceConfig { + @Bean + public WxMaService wxMaService(WxMaConfig config, StringRedisTemplate redisTemplate) { + WxMaRedisConfig redisConfig = new WxMaRedisConfig(redisTemplate); + redisConfig.setAppid(config.getAppid()); + redisConfig.setSecret(config.getSecret()); + + WxMaServiceImpl service = new WxMaServiceImpl(); + service.setWxMaConfig(redisConfig); + return service; + } +} diff --git a/src/main/java/com/example/caseData/extend/weChat/WxMaServiceUtils.java b/src/main/java/com/example/caseData/extend/weChat/WxMaServiceUtils.java new file mode 100644 index 0000000..848fd8c --- /dev/null +++ b/src/main/java/com/example/caseData/extend/weChat/WxMaServiceUtils.java @@ -0,0 +1,53 @@ +package com.example.caseData.extend.weChat; + + +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; +import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +@RequiredArgsConstructor +public class WxMaServiceUtils { + private final WxMaService wxMaService; + + /** + * 通过 code 换取 session 信息(openid/unionid) + */ + public WxMaJscode2SessionResult getSessionInfo(String code) { + try { + return wxMaService.getUserService().getSessionInfo(code); + } catch (WxErrorException e) { + log.error("获取 session 失败", e); + throw new RuntimeException("微信 session 获取失败", e); + } + } + + /** + * 解密手机号信息 + */ + public WxMaPhoneNumberInfo getPhoneNumber(String code) { + try { + return wxMaService.getUserService().getPhoneNumber(code); // 注意:此方法为新版本推荐方法 + } catch (WxErrorException e) { + log.error("获取手机号失败", e); + throw new RuntimeException("微信手机号获取失败", e); + } + } + + /** + * 获取当前 access_token(仅调试或日志用) + */ + public String getAccessToken() { + try { + return wxMaService.getAccessToken(); + } catch (WxErrorException e) { + log.error("获取 access_token 失败", e); + throw new RuntimeException("获取 access_token 失败", e); + } + } +} diff --git a/src/main/java/com/example/caseData/middlewares/AuthInterceptor.java b/src/main/java/com/example/caseData/middlewares/AuthInterceptor.java new file mode 100644 index 0000000..28849c3 --- /dev/null +++ b/src/main/java/com/example/caseData/middlewares/AuthInterceptor.java @@ -0,0 +1,49 @@ +package com.example.caseData.middlewares; + +import com.example.caseData.dao.UserDao; +import com.example.caseData.exception.BusinessException; +import com.example.caseData.model.UserModel; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.jetbrains.annotations.NotNull; +import org.springframework.stereotype.Component; + +@Component +public class AuthInterceptor extends BaseInterceptor { + private final UserDao userDao; + + public AuthInterceptor(UserDao userDao) { + this.userDao = userDao; + } + + @Override + public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws Exception { + + // 放行白名单路径 + if (isWhiteListed(request)) { + return true; + } + + String userId = (String) request.getAttribute("userId"); + + if (userId == null) { + throw new BusinessException("-1","错误"); + } + + // 获取用户数据 + UserModel user = userDao.selectById(userId); + if (user == null) { + throw new BusinessException("-1","用户数据错误"); + } + + if (user.getStatus() == 0){ + throw new BusinessException("-1","用户已禁用"); + } + + if (user.getStatus() == 2){ + throw new BusinessException("-1","用户已禁用"); + } + + return true; // 如果权限验证通过,则继续处理请求 + } +} diff --git a/src/main/java/com/example/caseData/middlewares/BaseInterceptor.java b/src/main/java/com/example/caseData/middlewares/BaseInterceptor.java new file mode 100644 index 0000000..ef83361 --- /dev/null +++ b/src/main/java/com/example/caseData/middlewares/BaseInterceptor.java @@ -0,0 +1,41 @@ +package com.example.caseData.middlewares; + +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.web.servlet.HandlerInterceptor; + +import java.util.List; + +public abstract class BaseInterceptor implements HandlerInterceptor { + + // 请求白名单(格式:请求方式:路径正则) + private final List whiteList = List.of( +// "GET:/api/user/\\d+", // GET 请求,匹配 /api/user/123 +// "POST:/api/public/.*", // POST 请求,匹配 /api/public/xx +// "GET:/api/users" , // GET 请求,匹配具体路径 + "POST:/api/login/wechat/mobile", // 登陆 + "GET:/api/index/clinical" // 首页-临床病例库 + ); + + /** + * 判断当前请求是否在白名单中 + * @param request 请求对象 + * @return 是否放行 + */ + public boolean isWhiteListed(HttpServletRequest request) { + String uri = request.getRequestURI(); + String method = request.getMethod().toUpperCase(); + + for (String rule : whiteList) { + String[] parts = rule.split(":", 2); + if (parts.length == 2) { + String ruleMethod = parts[0]; + String rulePattern = parts[1]; + + if (method.equals(ruleMethod) && uri.matches(rulePattern)) { + return true; + } + } + } + return false; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/middlewares/JwtInterceptor.java b/src/main/java/com/example/caseData/middlewares/JwtInterceptor.java new file mode 100644 index 0000000..2d4c817 --- /dev/null +++ b/src/main/java/com/example/caseData/middlewares/JwtInterceptor.java @@ -0,0 +1,52 @@ +package com.example.caseData.middlewares; + +import com.example.caseData.config.AppConfig; +import com.example.caseData.config.JwtConfig; +import com.example.caseData.exception.BusinessException; +import com.example.caseData.utils.EnvUtil; +import com.example.caseData.utils.JwtUtil; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.Jwts; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.jetbrains.annotations.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Base64; + +@Component +public class JwtInterceptor extends BaseInterceptor { + @Resource + private JwtUtil jwtUtil; + + @Override + public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws Exception { + // 放行白名单路径 + if (isWhiteListed(request)) { + return true; + } + + String token = request.getHeader("Authorization"); + + if (token != null && token.startsWith("Bearer ")) { + try { + token = token.substring(7); // 去除 "Bearer " 前缀 + Claims claims = jwtUtil.verifyToken(token); + + // 将解析出来的数据放入请求属性中供后续使用 + request.setAttribute("userId", claims.get("user_id")); + + return true; + } catch (ExpiredJwtException e) { + throw new BusinessException("406","token过期"); + } catch (Exception e) { + throw new BusinessException("405","token错误"); + } + } else { + throw new BusinessException("405","请求未授权"); + } + } +} diff --git a/src/main/java/com/example/caseData/middlewares/LogRequestInterceptor.java b/src/main/java/com/example/caseData/middlewares/LogRequestInterceptor.java new file mode 100644 index 0000000..09e9ab0 --- /dev/null +++ b/src/main/java/com/example/caseData/middlewares/LogRequestInterceptor.java @@ -0,0 +1,78 @@ +package com.example.caseData.middlewares; + +import com.example.caseData.utils.Fmt; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import org.springframework.util.StreamUtils; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.util.ContentCachingRequestWrapper; + +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +@Slf4j +@Component +public class LogRequestInterceptor implements HandlerInterceptor { + + private static final Logger logger = LoggerFactory.getLogger(LogRequestInterceptor.class); + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws Exception { + ContentCachingRequestWrapper requestWrapper; + if (request instanceof ContentCachingRequestWrapper) { + requestWrapper = (ContentCachingRequestWrapper) request; + } else { + requestWrapper = new ContentCachingRequestWrapper(request); + } + + String url = requestWrapper.getRequestURL().toString(); + String ip = requestWrapper.getRemoteAddr(); + String method = requestWrapper.getMethod(); + String contentType = requestWrapper.getContentType() == null ? "" : requestWrapper.getContentType(); + + final Map paramMap = new HashMap<>(); + + try { + if (Objects.equals(method, "GET")){ + requestWrapper.getParameterMap().forEach((key, values) -> { + paramMap.put(key, values[0]); + }); + }else{ + if (contentType.contains("application/json")){ + // 先触发请求体的读取,将内容缓存起来 + Map a = requestWrapper.getParameterMap(); + + // 从缓存中获取请求体 + String body = new String(requestWrapper.getContentAsByteArray(), StandardCharsets.UTF_8); + if (!body.isEmpty()) { + Map jsonBody = objectMapper.readValue(body, new TypeReference>() {}); + paramMap.putAll(jsonBody); + } + } + + if (contentType.contains("application/x-www-form-urlencoded") || contentType.contains("multipart/form-data")){ + requestWrapper.getParameterMap().forEach((key, values) -> { + paramMap.put(key, values[0]); + }); + } + } + } catch (Exception e) { + paramMap.put("error", "读取参数失败: " + e.getMessage()); + } + + logger.info("uri: {}, ip: {}, method: {}, params: {}", url, ip, method, paramMap); + + return true; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/model/BasicHospitalModel.java b/src/main/java/com/example/caseData/model/BasicHospitalModel.java new file mode 100644 index 0000000..cb4b095 --- /dev/null +++ b/src/main/java/com/example/caseData/model/BasicHospitalModel.java @@ -0,0 +1,77 @@ +package com.example.caseData.model; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +@TableName("`basic_hospital`") +public class BasicHospitalModel { + /** + * 主键id + */ + @TableId(type = IdType.ASSIGN_ID) // 使用MyBatis-Plus的ID生成策略 + private Long hospitalId; + + /** + * app唯一标识 + */ + @TableField("hospital_iden") + private String hospitalIden; + + /** + * 医院名称 + */ + @TableField("hospital_name") + private String hospitalName; + + /** + * 来源(2:肝胆相照 3:佳动例) + */ + private Integer source; + + /** + * 医院等级 + */ + @TableField("hospital_level") + private String hospitalLevel; + + /** + * 医生数量 + */ + @TableField("doctor_number") + private Integer doctorNumber; + + /** + * 省份 + */ + private String province; + + /** + * 城市 + */ + private String city; + + /** + * 区县 + */ + private String county; + + /** + * 地址 + */ + private String address; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; +} diff --git a/src/main/java/com/example/caseData/model/BasicSensitiveWordModel.java b/src/main/java/com/example/caseData/model/BasicSensitiveWordModel.java new file mode 100644 index 0000000..053289a --- /dev/null +++ b/src/main/java/com/example/caseData/model/BasicSensitiveWordModel.java @@ -0,0 +1,40 @@ +package com.example.caseData.model; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data // Lombok注解,用于自动生成getter/setter方法等 +@TableName("`basic_sensitive_word`") // 指定数据库表名 +public class BasicSensitiveWordModel { + /** + * 主键id + */ + @TableId(type = IdType.ASSIGN_ID) // 使用MyBatis-Plus的ID生成策略 + private Long id; + + /** + * 敏感词 + */ + @TableField("word") + private String word; + + /** + * 状态(0:禁用 1:正常) + */ + @TableField("status") + private Integer status; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/model/CaseClinicalArticleAuthorModel.java b/src/main/java/com/example/caseData/model/CaseClinicalArticleAuthorModel.java new file mode 100644 index 0000000..60ccec8 --- /dev/null +++ b/src/main/java/com/example/caseData/model/CaseClinicalArticleAuthorModel.java @@ -0,0 +1,47 @@ +package com.example.caseData.model; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data // Lombok注解,用于自动生成getter/setter方法等 +@TableName("`case_clinical_article_author`") // 指定数据库表名 +public class CaseClinicalArticleAuthorModel { + /** + * 主键id + */ + @TableId(type = IdType.ASSIGN_ID) + private Long authorId; + + /** + * 临床文章id + */ + @TableField("article_id") + private Long articleId; + + /** + * 医生id + */ + @TableField("doctor_id") + private String doctorId; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @JsonProperty("updated_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @JsonProperty("updated_at") + private LocalDateTime updatedAt; + + // 医生 + @TableField(exist = false) + private CaseClinicalDoctorModel caseClinicalDoctor; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/model/CaseClinicalArticleLabelModel.java b/src/main/java/com/example/caseData/model/CaseClinicalArticleLabelModel.java new file mode 100644 index 0000000..b341b13 --- /dev/null +++ b/src/main/java/com/example/caseData/model/CaseClinicalArticleLabelModel.java @@ -0,0 +1,45 @@ +package com.example.caseData.model; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.time.LocalDateTime; +@Data // Lombok注解,用于自动生成getter/setter方法等 +@TableName("`case_clinical_article_label`") // 指定数据库表名 +public class CaseClinicalArticleLabelModel { + /** + * 主键id + */ + @TableId(type = IdType.ASSIGN_ID) // 使用MyBatis-Plus的ID生成策略 + private Long articleLabelId; + + /** + * 临床文章id + */ + @TableField("article_id") + private Long articleId; + + /** + * app唯一标识 + */ + @TableField("app_iden") + private String appIden; + + /** + * 标签名称 + */ + @TableField("label_name") + private String labelName; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/model/CaseClinicalArticleModel.java b/src/main/java/com/example/caseData/model/CaseClinicalArticleModel.java new file mode 100644 index 0000000..a254032 --- /dev/null +++ b/src/main/java/com/example/caseData/model/CaseClinicalArticleModel.java @@ -0,0 +1,69 @@ +package com.example.caseData.model; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +@Data +@TableName("`case_clinical_article`") +public class CaseClinicalArticleModel { + @TableId(type = IdType.ASSIGN_ID) // 主键策略 + private Long articleId; // 主键id + + /** + * 标题 + */ + @TableField("article_title") + private String articleTitle; + + /** + * 状态(1:正常 2:禁用) + */ + @TableField("article_status") + private Integer articleStatus; + + /** + * 阅读量 + */ + @TableField("read_num") + private Integer readNum; + + /** + * 收藏量 + */ + @TableField("collect_num") + private Integer collectNum; + + /** + * 发表时间 + */ + @TableField("push_date") + private LocalDateTime pushDate; + + /** + * 内容 + */ + @TableField("article_content") + private String articleContent; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @JsonProperty("updated_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @JsonProperty("updated_at") + private LocalDateTime updatedAt; + + // 作者 + @TableField(exist = false) + private List author; +} diff --git a/src/main/java/com/example/caseData/model/CaseClinicalDoctorModel.java b/src/main/java/com/example/caseData/model/CaseClinicalDoctorModel.java new file mode 100644 index 0000000..d0f076b --- /dev/null +++ b/src/main/java/com/example/caseData/model/CaseClinicalDoctorModel.java @@ -0,0 +1,68 @@ +package com.example.caseData.model; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 医生表实体类 + */ +@Data // Lombok注解,用于自动生成getter/setter方法等 +@TableName("`case_clinical_doctor`") // 指定数据库表名 +public class CaseClinicalDoctorModel { + /** + * 主键id + */ + @TableId(type = IdType.ASSIGN_ID) // 使用MyBatis-Plus的ID生成策略 + private Long doctorId; + + /** + * app唯一标识(存在即表示为注册用户) + */ + @TableField("doctor_iden") + private String doctorIden; + + /** + * 医生名称 + */ + @TableField("doctor_name") + private String doctorName; + + /** + * 所属医院id + */ + @TableField("hospital_id") + private Long hospitalId; + + /** + * 状态(1:正常 2:禁用) + */ + @TableField("status") + private Integer status; + + /** + * 头像 + */ + @TableField("avatar") + private String avatar; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @JsonProperty("updated_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @JsonProperty("updated_at") + private LocalDateTime updatedAt; + + // 医院 + @TableField(exist = false) + private BasicHospitalModel basicHospital; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/model/CaseClinicalVideoAuthorModel.java b/src/main/java/com/example/caseData/model/CaseClinicalVideoAuthorModel.java new file mode 100644 index 0000000..a31a381 --- /dev/null +++ b/src/main/java/com/example/caseData/model/CaseClinicalVideoAuthorModel.java @@ -0,0 +1,47 @@ +package com.example.caseData.model; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data // Lombok注解,用于自动生成getter/setter方法等 +@TableName("`case_clinical_video_author`") // 指定数据库表名 +public class CaseClinicalVideoAuthorModel { + /** + * 主键id(可选) + */ + @TableId(type = IdType.ASSIGN_ID) + private Long authorId; + + /** + * 临床视频id(作为主键) + */ + @TableField("video_id") + private Long videoId; + + /** + * 医生id + */ + @TableField("doctor_id") + private String doctorId; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @JsonProperty("created_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @JsonProperty("updated_at") + private LocalDateTime updatedAt; + + // 医生 + @TableField(exist = false) + private CaseClinicalDoctorModel caseClinicalDoctor; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/model/CaseClinicalVideoLabelModel.java b/src/main/java/com/example/caseData/model/CaseClinicalVideoLabelModel.java new file mode 100644 index 0000000..c6da9c1 --- /dev/null +++ b/src/main/java/com/example/caseData/model/CaseClinicalVideoLabelModel.java @@ -0,0 +1,49 @@ +package com.example.caseData.model; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data // Lombok注解,用于自动生成getter/setter方法等 +@TableName("`case_clinical_video_label`") // 指定数据库表名 +public class CaseClinicalVideoLabelModel { + /** + * 主键id + */ + @TableId(type = IdType.ASSIGN_ID) // 使用MyBatis-Plus的ID生成策略 + private Long videoLabelId; + + /** + * 临床视频id + */ + @TableField("video_id") + private Long videoId; + + /** + * app唯一标识 + */ + @TableField("app_iden") + private String appIden; + + /** + * 标签名称 + */ + @TableField("label_name") + private String labelName; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @JsonProperty("updated_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @JsonProperty("updated_at") + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/model/CaseClinicalVideoModel.java b/src/main/java/com/example/caseData/model/CaseClinicalVideoModel.java new file mode 100644 index 0000000..fc289a3 --- /dev/null +++ b/src/main/java/com/example/caseData/model/CaseClinicalVideoModel.java @@ -0,0 +1,72 @@ +package com.example.caseData.model; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +@Data // Lombok注解,用于自动生成getter/setter方法等 +@TableName("`case_clinical_video`") // 指定数据库表名 +public class CaseClinicalVideoModel { + /** + * 主键id + */ + @TableId(type = IdType.ASSIGN_ID) // 使用MyBatis-Plus的ID生成策略 + private Long videoId; + + /** + * 标题 + */ + @TableField("video_title") + private String videoTitle; + + /** + * 状态(1:正常 2:禁用) + */ + @TableField("video_status") + private Integer videoStatus; + + /** + * 阅读量 + */ + @TableField("read_num") + private Integer readNum; + + /** + * 收藏量 + */ + @TableField("collect_num") + private Integer collectNum; + + /** + * 视频编号(保利) + */ + @TableField("video_no") + private String videoNo; + + /** + * 发表时间 + */ + @TableField("push_date") + private LocalDateTime pushDate; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @JsonProperty("updated_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @JsonProperty("updated_at") + private LocalDateTime updatedAt; + + // 作者 + @TableField(exist = false) + private List author; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/model/StatsCaseClinicalDoctorModel.java b/src/main/java/com/example/caseData/model/StatsCaseClinicalDoctorModel.java new file mode 100644 index 0000000..b976e27 --- /dev/null +++ b/src/main/java/com/example/caseData/model/StatsCaseClinicalDoctorModel.java @@ -0,0 +1,79 @@ +package com.example.caseData.model; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 统计表-病例库-临床-用户实体类 + */ +@Data // Lombok注解,用于自动生成getter/setter方法等 +@TableName("`stats_case_clinical_doctor`") // 指定数据库表名 +public class StatsCaseClinicalDoctorModel { + /** + * 主键id + */ + @TableId(type = IdType.ASSIGN_ID) + private Long statsId; + + /** + * 医生id + */ + @TableField("doctor_id") + private Long doctorId; + + /** + * 数量-文章 + */ + @TableField("article_num") + private Integer articleNum; + + /** + * 总阅读量-文章 + */ + @TableField("article_read_num") + private Integer articleReadNum; + + /** + * 总收藏量-文章 + */ + @TableField("article_collect_num") + private Integer articleCollectNum; + + /** + * 数量-视频 + */ + @TableField("video_num") + private Integer videoNum; + + /** + * 总阅读量-视频 + */ + @TableField("video_read_num") + private Integer videoReadNum; + + /** + * 总收藏量-视频 + */ + @TableField("video_collect_num") + private Integer videoCollectNum; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; + + /** + * 医生 + */ + @TableField(exist = false) + private CaseClinicalDoctorModel caseClinicalDoctor; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/model/StatsCaseClinicalHospitalModel.java b/src/main/java/com/example/caseData/model/StatsCaseClinicalHospitalModel.java new file mode 100644 index 0000000..875c619 --- /dev/null +++ b/src/main/java/com/example/caseData/model/StatsCaseClinicalHospitalModel.java @@ -0,0 +1,83 @@ +package com.example.caseData.model; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data // Lombok注解,用于自动生成getter/setter方法等 +@TableName("`stats_case_clinical_hospital`") // 指定数据库表名 +public class StatsCaseClinicalHospitalModel { + /** + * 主键id + */ + @TableId(type = IdType.ASSIGN_ID) // 使用MyBatis-Plus的ID生成策略 + private Long statsId; + + /** + * 医院id + */ + @TableField("hospital_id") + private Long hospitalId; + + /** + * 数量-文章 + */ + @TableField("article_num") + private Integer articleNum; + + /** + * 总阅读量-文章 + */ + @TableField("article_read_num") + private Integer articleReadNum; + + /** + * 总收藏量-文章 + */ + @TableField("article_collect_num") + private Integer articleCollectNum; + + /** + * 最后一篇文章发表时间 + */ + @TableField("last_push_date") + private LocalDateTime lastPushDate; + + /** + * 数量-视频 + */ + @TableField("video_num") + private Integer videoNum; + + /** + * 总阅读量-视频 + */ + @TableField("video_read_num") + private Integer videoReadNum; + + /** + * 总收藏量-视频 + */ + @TableField("video_collect_num") + private Integer videoCollectNum; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @JsonProperty("updated_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @JsonProperty("updated_at") + private LocalDateTime updatedAt; + + // 医院 + @TableField(exist = false) + private BasicHospitalModel basicHospital; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/model/StatsCaseClinicalModel.java b/src/main/java/com/example/caseData/model/StatsCaseClinicalModel.java new file mode 100644 index 0000000..6dd9e62 --- /dev/null +++ b/src/main/java/com/example/caseData/model/StatsCaseClinicalModel.java @@ -0,0 +1,52 @@ +package com.example.caseData.model; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data // Lombok注解,用于自动生成getter/setter方法等 +@TableName("`stats_case_clinical`") // 指定数据库表名 +public class StatsCaseClinicalModel { + /** + * 主键id + */ + @TableId(type = IdType.ASSIGN_ID) // 使用MyBatis-Plus的ID生成策略 + private Long statsId; + + /** + * 总阅读量-文章 + */ + @TableField("article_read_num") + private Integer articleReadNum; + + /** + * 总收藏量-文章 + */ + @TableField("article_collect_num") + private Integer articleCollectNum; + + /** + * 总阅读量-视频 + */ + @TableField("video_read_num") + private Integer videoReadNum; + + /** + * 总收藏量-视频 + */ + @TableField("video_collect_num") + private Integer videoCollectNum; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/model/UserCollectClinicalArticleModel.java b/src/main/java/com/example/caseData/model/UserCollectClinicalArticleModel.java new file mode 100644 index 0000000..2fbe624 --- /dev/null +++ b/src/main/java/com/example/caseData/model/UserCollectClinicalArticleModel.java @@ -0,0 +1,40 @@ +package com.example.caseData.model; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data // Lombok注解,用于自动生成getter/setter方法等 +@TableName("`user_collect_clinical_article`") // 指定数据库表名 +public class UserCollectClinicalArticleModel { + /** + * 主键id + */ + @TableId(type = IdType.ASSIGN_ID) // 使用MyBatis-Plus的ID生成策略 + private Long collectId; + + /** + * 用户id + */ + @TableField("user_id") + private Long userId; + + /** + * 临床文章id + */ + @TableField("article_id") + private Long articleId; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/model/UserCollectClinicalVideoModel.java b/src/main/java/com/example/caseData/model/UserCollectClinicalVideoModel.java new file mode 100644 index 0000000..ef96de8 --- /dev/null +++ b/src/main/java/com/example/caseData/model/UserCollectClinicalVideoModel.java @@ -0,0 +1,40 @@ +package com.example.caseData.model; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data // Lombok注解,用于自动生成getter/setter方法等 +@TableName("`user_collect_clinical_video`") // 指定数据库表名 +public class UserCollectClinicalVideoModel { + /** + * 主键id + */ + @TableId(type = IdType.ASSIGN_ID) // 使用MyBatis-Plus的ID生成策略 + private Long collectId; + + /** + * 用户id + */ + @TableField("user_id") + private Long userId; + + /** + * 临床视频id + */ + @TableField("video_id") + private Long videoId; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/model/UserCommentClinicalArticleModel.java b/src/main/java/com/example/caseData/model/UserCommentClinicalArticleModel.java new file mode 100644 index 0000000..781f134 --- /dev/null +++ b/src/main/java/com/example/caseData/model/UserCommentClinicalArticleModel.java @@ -0,0 +1,88 @@ +package com.example.caseData.model; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data // Lombok注解,用于自动生成getter/setter方法等 +@TableName("`user_comment_clinical_article`") // 指定数据库表名 +public class UserCommentClinicalArticleModel { + /** + * 主键id + */ + @TableId(type = IdType.ASSIGN_ID) // 使用MyBatis-Plus的ID生成策略 + private Long commentId; + + /** + * 用户id + */ + @TableField("user_id") + private Long userId; + + /** + * 临床文章id + */ + @TableField("article_id") + private Long articleId; + + /** + * 父级id,一级评论为null + */ + @TableField("parent_id") + private Long parentId; + + /** + * 根评论id,一级评论时为null。其余为一级评论id + */ + @TableField("root_id") + private Long rootId; + + /** + * 评论状态(0:禁用 1:正常) + */ + @TableField("status") + private Integer status; + + /** + * 是否存在敏感词(0:否 1:是) + */ + @TableField("is_sensitive") + private Integer isSensitive; + + /** + * 是否优质留言(0:否 1:是) + */ + @TableField("is_high_quality") + private Integer isHighQuality; + + /** + * 点赞数量 + */ + @TableField("like_num") + private Integer likeNum; + + /** + * 评论内容 + */ + @TableField("content") + private String content; + + /** + * 评论内容(原版) + */ + @TableField("content_word") + private String contentWord; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/model/UserCommentClinicalVideoModel.java b/src/main/java/com/example/caseData/model/UserCommentClinicalVideoModel.java new file mode 100644 index 0000000..64bd3fa --- /dev/null +++ b/src/main/java/com/example/caseData/model/UserCommentClinicalVideoModel.java @@ -0,0 +1,88 @@ +package com.example.caseData.model; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data // Lombok注解,用于自动生成getter/setter方法等 +@TableName("`user_comment_clinical_video`") // 指定数据库表名 +public class UserCommentClinicalVideoModel { + /** + * 主键id + */ + @TableId(type = IdType.ASSIGN_ID) // 使用MyBatis-Plus的ID生成策略 + private Long commentId; + + /** + * 用户id + */ + @TableField("user_id") + private Long userId; + + /** + * 临床视频id + */ + @TableField("video_id") + private Long videoId; + + /** + * 父级id,一级评论为null + */ + @TableField("parent_id") + private Long parentId; + + /** + * 根评论id,一级评论时为null。其余为一级评论id + */ + @TableField("root_id") + private Long rootId; + + /** + * 评论状态(0:禁用 1:正常) + */ + @TableField("status") + private Integer status; + + /** + * 是否存在敏感词(0:否 1:是) + */ + @TableField("is_sensitive") + private Integer isSensitive; + + /** + * 是否优质留言(0:否 1:是) + */ + @TableField("is_high_quality") + private Integer isHighQuality; + + /** + * 点赞数量 + */ + @TableField("like_num") + private Integer likeNum; + + /** + * 评论内容 + */ + @TableField("content") + private String content; + + /** + * 评论内容(原版) + */ + @TableField("content_word") + private String contentWord; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/model/UserModel.java b/src/main/java/com/example/caseData/model/UserModel.java new file mode 100644 index 0000000..37f39a0 --- /dev/null +++ b/src/main/java/com/example/caseData/model/UserModel.java @@ -0,0 +1,112 @@ +package com.example.caseData.model; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +@TableName("`user`") +public class UserModel { + /* + 主键id + */ + @TableId(type = IdType.ASSIGN_ID) + private Long userId; + + /** + * 第三方平台唯一标识 + */ + @TableField("user_iden") + private String userIden; + + /** + * 用户名称 + */ + @TableField("user_name") + private String userName; + + /** + * 手机号(第三方平台时可能为空) + */ + @TableField("user_mobile") + private String userMobile; + + /** + * 手机号加密 + */ + @TableField("mobile_encryption") + private String mobileEncryption; + + /** + * 状态(0:禁用 1:正常 2:删除) + */ + @TableField("status") + private Integer status; + + /** + * 注册来源(1:未知 2:app用户 3:佳动例) + */ + @TableField("register_source") + private Integer registerSource; + + /** + * 用户微信标识 + */ + @TableField("open_id") + private String openId; + + /** + * 微信开放平台标识 + */ + @TableField("union_id") + private String unionId; + + /** + * 性别(0:未知 1:男 2:女) + */ + @TableField("sex") + private Integer sex; + + /** + * 头像 + */ + @TableField("avatar") + private String avatar; + + /** + * 医生职称(0:未知 1:主任医师 2:主任中医师 3:副主任医师 4:副主任中医师 5:主治医师 6:住院医师) + */ + @TableField("title") + private Integer title; + + /** + * 科室名称 + */ + @TableField("department_name") + private String departmentName; + + /** + * 所属医院id + */ + @TableField("hospital_id") + private Long hospitalId; + + /** + * 医生地址 + */ + @TableField("address") + private String address; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/request/ClinicalHospitalRequest.java b/src/main/java/com/example/caseData/request/ClinicalHospitalRequest.java new file mode 100644 index 0000000..17013ba --- /dev/null +++ b/src/main/java/com/example/caseData/request/ClinicalHospitalRequest.java @@ -0,0 +1,17 @@ +package com.example.caseData.request; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; + +import java.util.HashMap; +import java.util.Map; + +@Data +public class ClinicalHospitalRequest { + +} diff --git a/src/main/java/com/example/caseData/request/PublicRequest.java b/src/main/java/com/example/caseData/request/PublicRequest.java new file mode 100644 index 0000000..be3150e --- /dev/null +++ b/src/main/java/com/example/caseData/request/PublicRequest.java @@ -0,0 +1,16 @@ +package com.example.caseData.request; + +import jakarta.validation.constraints.*; +import lombok.Data; + +@Data +public class PublicRequest { + // ✅ 自定义校验分组 + public interface Login {} + + @NotEmpty(message = "错误请求1", groups = {Login.class}) + private String phone_code; + + @NotEmpty(message = "错误请求2", groups = {Login.class}) + private String wx_code; +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/request/TestRequest.java b/src/main/java/com/example/caseData/request/TestRequest.java new file mode 100644 index 0000000..4bcde12 --- /dev/null +++ b/src/main/java/com/example/caseData/request/TestRequest.java @@ -0,0 +1,60 @@ +package com.example.caseData.request; + +import lombok.Data; +import jakarta.validation.constraints.*; + +import java.util.List; + +@Data +public class TestRequest { + /** + * 项目ID,不能为空 + * 适用于 Long 等对象类型 + */ + @NotNull(message = "项目ID不能为空") + private Long projectId; + + /** + * 开始时间,不能为空字符串,不能为 null 或空格 + */ + @NotBlank(message = "开始时间不能为空") + private String startTime; + + /** + * 结束时间,不能为空字符串,不能为 null 或空格 + */ + @NotBlank(message = "结束时间不能为空") + private String endTime; + + /** + * 用户名,不能为 null 或空字符串 + */ + @NotEmpty(message = "用户名不能为空") + private String username; + + /** + * 手机号,必须符合正则表达式格式 + */ + @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确") + private String phone; + + /** + * 年龄,最小为1,最大为100 + */ + @Min(value = 1, message = "年龄必须大于等于1岁") + @Max(value = 100, message = "年龄不能超过100岁") + private Integer age; + + /** + * 密码长度限制,最短6位,最长20位 + */ + @Size(min = 6, max = 20, message = "密码长度必须在6到20之间") + private String password; + + /** + * 选项列表,不能为空且至少包含一个元素 + */ + @NotEmpty(message = "选项列表不能为空") + @Size(min = 1, message = "请至少选择一个选项") + private List options; +} diff --git a/src/main/java/com/example/caseData/request/UserRequest.java b/src/main/java/com/example/caseData/request/UserRequest.java new file mode 100644 index 0000000..f8812e1 --- /dev/null +++ b/src/main/java/com/example/caseData/request/UserRequest.java @@ -0,0 +1,47 @@ +package com.example.caseData.request; + +import jakarta.validation.constraints.*; +import lombok.Data; + +@Data +public class UserRequest { + // ✅ 自定义校验分组 + public interface Create {} + public interface Update {} + public interface Page {} + + // ✅ 统一定义所有用户相关的参数 + // ✅ 分页参数 + @Min(value = 1, groups = Page.class, message = "页码最小为 1") + private Integer page = 1; + + @Min(value = 1, groups = Page.class, message = "每页个数最小为 1") + private Integer pageSize = 20; + + @NotNull(message = "ID 不能为空", groups = {Update.class}) + private Long id; + + @NotBlank(message = "用户名不能为空", groups = {Create.class, Update.class}) + @Size(min = 3, max = 20, message = "用户名长度必须在 3 到 20 之间", groups = {Create.class, Update.class}) + private String username; + + @NotNull(message = "年龄不能为空", groups = {Create.class}) + @Min(value = 18, message = "年龄必须大于或等于 18", groups = {Create.class, Update.class}) + @Max(value = 60, message = "年龄必须小于或等于 60", groups = {Create.class, Update.class}) + private Integer age; + + @Email(message = "邮箱格式不正确", groups = {Create.class, Update.class}) + private String email; + + // ✅ 校验分页参数 + public void validateForPage() { + // 如果 page 为空,设为默认值 1 + if (page == null) { + page = 1; + } + + if (pageSize == null) { + pageSize = 20; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/request/clinicalRequest/getClinicalDoctorSearchPage.java b/src/main/java/com/example/caseData/request/clinicalRequest/getClinicalDoctorSearchPage.java new file mode 100644 index 0000000..5c14f7f --- /dev/null +++ b/src/main/java/com/example/caseData/request/clinicalRequest/getClinicalDoctorSearchPage.java @@ -0,0 +1,79 @@ +package com.example.caseData.request.clinicalRequest; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.Min; +import lombok.Data; +import org.springframework.util.StringUtils; + +import java.util.HashMap; +import java.util.Map; + +@Data +public class getClinicalDoctorSearchPage { + // ✅ 分页参数 + @Min(value = 1, message = "页码最小为 1") + private Integer page = 1; + + @JsonProperty("page_size") + @Min(value = 1, message = "每页个数最小为 1") + private Integer pageSize = 20; + + // 作者名称 + @JsonProperty("doctor_name") + private String doctorName; + + // 排序字段 + private OrderRequest order; + + /** + * 排序字段嵌套结构体 + */ + @Data + public static class OrderRequest { + private String updatedAt; // 更新时间排序 + private String doctorName; // 医生名称 + private String articleNum; // 数量-文章 + + + public Map toMap() { + Map map = new HashMap<>(); + if (StringUtils.hasText(updatedAt)) { + map.put("a.updated_at", updatedAt); + } + + if (StringUtils.hasText(doctorName)) { + map.put("b.doctor_name", doctorName); + } + + if (StringUtils.hasText(articleNum)) { + map.put("a.article_num", articleNum); + } + + // 默认排序(如果用户未传递任何排序字段) + if (map.isEmpty()) { + map.put("a.updated_at", "desc"); + } + + return map; + } + } + + /** + * 获取排序字段,若无用户输入则使用默认排序 + */ + public Map handleOrder() { + return order != null ? order.toMap() : new OrderRequest().toMap(); + } + + // ✅ 校验分页参数 + public void validateForPage() { + // 如果 page 为空,设为默认值 1 + if (page == null) { + page = 1; + } + + if (pageSize == null) { + pageSize = 20; + } + } +} diff --git a/src/main/java/com/example/caseData/request/clinicalRequest/getClinicalHospitalSearchPage.java b/src/main/java/com/example/caseData/request/clinicalRequest/getClinicalHospitalSearchPage.java new file mode 100644 index 0000000..fcbc8e2 --- /dev/null +++ b/src/main/java/com/example/caseData/request/clinicalRequest/getClinicalHospitalSearchPage.java @@ -0,0 +1,80 @@ +package com.example.caseData.request.clinicalRequest; + +import com.example.caseData.request.ClinicalHospitalRequest; +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.Min; +import lombok.Data; +import org.springframework.util.StringUtils; + +import java.util.HashMap; +import java.util.Map; + +@Data +public class getClinicalHospitalSearchPage { + // ✅ 分页参数 + @Min(value = 1, message = "页码最小为 1") + private Integer page = 1; + + @JsonProperty("page_size") + @Min(value = 1, message = "每页个数最小为 1") + private Integer pageSize = 20; + + // 医院名称 + @JsonProperty("hospital_name") + private String hospitalName; + + // 排序字段 + private OrderRequest order; + + /** + * 排序字段嵌套结构体 + */ + @Data + public static class OrderRequest { + private String updatedAt; // 更新时间排序 + private String hospitalName; // 医院名称 + private String articleNum; // 数量-文章 + + + public Map toMap() { + Map map = new HashMap<>(); + if (StringUtils.hasText(updatedAt)) { + map.put("a.updated_at", updatedAt); + } + + if (StringUtils.hasText(hospitalName)) { + map.put("b.hospital_name", hospitalName); + } + + if (StringUtils.hasText(articleNum)) { + map.put("a.article_num", articleNum); + } + + // 默认排序(如果用户未传递任何排序字段) + if (map.isEmpty()) { + map.put("a.updated_at", "desc"); + } + + return map; + } + } + + /** + * 获取排序字段,若无用户输入则使用默认排序 + */ + public Map handleOrder() { + return order != null ? order.toMap() : new OrderRequest().toMap(); + } + + // ✅ 校验分页参数 + public void validateForPage() { + // 如果 page 为空,设为默认值 1 + if (page == null) { + page = 1; + } + + if (pageSize == null) { + pageSize = 20; + } + } +} diff --git a/src/main/java/com/example/caseData/request/clinicalRequest/getClinicalSearchPage.java b/src/main/java/com/example/caseData/request/clinicalRequest/getClinicalSearchPage.java new file mode 100644 index 0000000..bad7698 --- /dev/null +++ b/src/main/java/com/example/caseData/request/clinicalRequest/getClinicalSearchPage.java @@ -0,0 +1,103 @@ +package com.example.caseData.request.clinicalRequest; + + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.springframework.util.StringUtils; + +import java.util.HashMap; +import java.util.Map; + +@Data +public class getClinicalSearchPage { + // ✅ 分页参数 + @Min(value = 1,message = "页码最小为 1") + private Integer page = 1; + + @JsonProperty("page_size") + @Min(value = 1, message = "每页个数最小为 1") + private Integer pageSize = 20; + + // 标题 + @JsonProperty("title") + private String title; + + // 作者名称 + @JsonProperty("doctor_name") + private String doctorName; + + // 标签名称 + @JsonProperty("label_name") + private String labelName; + + // 医院id + @JsonProperty("hospital_id") + private String hospitalId; + + // 医生id + @JsonProperty("doctor_id") + private String doctorId; + + // 类型(1:文章 2:视频) + @NotNull(message = "类型不能为空") + @Min(value = 1, message = "入参错误") + @Max(value = 2, message = "入参错误") + private Integer type; + + // 排序字段 + private OrderRequest order; + + /** + * 排序字段嵌套结构体 + */ + @Data + public static class OrderRequest { + private String createdAt; // 创建时间 + private String readNum; // 阅读量-文章 + private String pushDate; // 发表时间 + + public Map toMap() { + Map map = new HashMap<>(); + if (StringUtils.hasText(createdAt)) { + map.put("a.created_at", createdAt); + } + + if (StringUtils.hasText(readNum)) { + map.put("a.read_num", readNum); + } + + if (StringUtils.hasText(pushDate)) { + map.put("a.push_date", pushDate); + } + + // 默认排序(如果用户未传递任何排序字段) + if (map.isEmpty()) { + map.put("a.updated_at", "desc"); + } + + return map; + } + } + + /** + * 获取排序字段,若无用户输入则使用默认排序 + */ + public Map handleOrder() { + return order != null ? order.toMap() : new OrderRequest().toMap(); + } + + // ✅ 校验分页参数 + public void validateForPage() { + // 如果 page 为空,设为默认值 1 + if (page == null) { + page = 1; + } + + if (pageSize == null) { + pageSize = 20; + } + } +} diff --git a/src/main/java/com/example/caseData/service/IndexService.java b/src/main/java/com/example/caseData/service/IndexService.java new file mode 100644 index 0000000..f8019c4 --- /dev/null +++ b/src/main/java/com/example/caseData/service/IndexService.java @@ -0,0 +1,142 @@ +package com.example.caseData.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.example.caseData.dao.*; +import com.example.caseData.dto.caseClinicalArticle.CaseClinicalArticleDto; +import com.example.caseData.dto.index.GetIndexClinicalDto; +import com.example.caseData.dto.index.RecommendDoctorDto; +import com.example.caseData.dto.index.RecommendHospitalDto; +import com.example.caseData.model.*; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class IndexService { + @Resource + private CaseClinicalArticleDao caseClinicalArticleDao; + + @Resource + private CaseClinicalArticleAuthorDao caseClinicalArticleAuthorDao; + + @Resource + private CaseClinicalVideoDao caseClinicalVideoDao; + + @Resource + private StatsCaseClinicalDao statsCaseClinicalDao; + + @Resource + private StatsCaseClinicalHospitalDao statsCaseClinicalHospitalDao; + + @Resource + private StatsCaseClinicalDoctorDao statsCaseClinicalDoctorDao; + + @Resource + private CaseClinicalDoctorDao caseClinicalDoctorDao; + + @Resource + private BasicHospitalDao basicHospitalDao; + + /** + * 获取首页数据-临床病例库 + */ + public GetIndexClinicalDto GetIndexClinical(){ + // 最新上线-2条 + LambdaQueryWrapper caseClinicalArticleQueryWrapper = new LambdaQueryWrapper<>(); + caseClinicalArticleQueryWrapper.eq(CaseClinicalArticleModel::getArticleStatus, 1) // 上线状态 + .orderByDesc(CaseClinicalArticleModel::getCreatedAt) // 按发布时间倒序 + .last("LIMIT 2"); // 只取2条记录 + List latestArticles = caseClinicalArticleDao.selectList(caseClinicalArticleQueryWrapper); + for (CaseClinicalArticleModel article : latestArticles) { + // 查找作者 + LambdaQueryWrapper authorQueryWrapper = new LambdaQueryWrapper<>(); + authorQueryWrapper.eq(CaseClinicalArticleAuthorModel::getArticleId, article.getArticleId()); + List caseClinicalArticleAuthors = caseClinicalArticleAuthorDao.selectList(authorQueryWrapper); + for (CaseClinicalArticleAuthorModel author : caseClinicalArticleAuthors) { + // 查询医生 + CaseClinicalDoctorModel caseClinicalDoctor = caseClinicalDoctorDao.selectById(author.getDoctorId()); + + // 查询医生所属医院 + BasicHospitalModel basicHospital = basicHospitalDao.selectById(caseClinicalDoctor.getHospitalId()); + caseClinicalDoctor.setBasicHospital(basicHospital); + + author.setCaseClinicalDoctor(caseClinicalDoctor); + } + + article.setAuthor(caseClinicalArticleAuthors); + } + + + // 最多阅读-2条 + caseClinicalArticleQueryWrapper = new LambdaQueryWrapper<>(); + caseClinicalArticleQueryWrapper.eq(CaseClinicalArticleModel::getArticleStatus, 1) // 上线状态 + .orderByDesc(CaseClinicalArticleModel::getReadNum) // 按阅读量倒序 + .last("LIMIT 2"); // 只取2条记录 + List mostReadArticles = caseClinicalArticleDao.selectList(caseClinicalArticleQueryWrapper); + for (CaseClinicalArticleModel article : mostReadArticles) { + // 根据文章ID查找作者 + LambdaQueryWrapper authorQueryWrapper = new LambdaQueryWrapper<>(); + authorQueryWrapper.eq(CaseClinicalArticleAuthorModel::getArticleId, article.getArticleId()); + List caseClinicalArticleAuthors = caseClinicalArticleAuthorDao.selectList(authorQueryWrapper); + for (CaseClinicalArticleAuthorModel author : caseClinicalArticleAuthors) { + // 查询医生 + CaseClinicalDoctorModel caseClinicalDoctor = caseClinicalDoctorDao.selectById(author.getDoctorId()); + + // 查询医生所属医院 + BasicHospitalModel basicHospital = basicHospitalDao.selectById(caseClinicalDoctor.getHospitalId()); + caseClinicalDoctor.setBasicHospital(basicHospital); + + author.setCaseClinicalDoctor(caseClinicalDoctor); + } + + article.setAuthor(caseClinicalArticleAuthors); + + // 删除内容字段 + article.setArticleContent(""); + } + + // 医院病例库推荐-2条 + LambdaQueryWrapper statsCaseClinicalHospitalModelQueryWrapper = new LambdaQueryWrapper<>(); + statsCaseClinicalHospitalModelQueryWrapper.orderByDesc(StatsCaseClinicalHospitalModel::getArticleNum) // 按文章数量倒序 + .last("LIMIT 2"); // 只取2条记录 + List statsCaseClinicalHospitals = statsCaseClinicalHospitalDao.selectList(statsCaseClinicalHospitalModelQueryWrapper); + for (StatsCaseClinicalHospitalModel hospital : statsCaseClinicalHospitals) { + // 查询医院基础数据 + BasicHospitalModel basicHospital = basicHospitalDao.selectById(hospital.getHospitalId()); + hospital.setBasicHospital(basicHospital); + } + + // 医生病例库推荐-2条 + LambdaQueryWrapper statsCaseClinicalDoctorModelQueryWrapper = new LambdaQueryWrapper<>(); + statsCaseClinicalDoctorModelQueryWrapper.orderByDesc(StatsCaseClinicalDoctorModel::getArticleNum) // 按文章数量倒序 + .last("LIMIT 2"); // 只取2条记录 + List statsCaseClinicalDoctors = statsCaseClinicalDoctorDao.selectList(statsCaseClinicalDoctorModelQueryWrapper); + for (StatsCaseClinicalDoctorModel doctor : statsCaseClinicalDoctors) { + // 查询医生数据 + CaseClinicalDoctorModel caseClinicalDoctor = caseClinicalDoctorDao.selectById(doctor.getDoctorId()); + + // 查询医生所属医院 + BasicHospitalModel basicHospital = basicHospitalDao.selectById(caseClinicalDoctor.getHospitalId()); + caseClinicalDoctor.setBasicHospital(basicHospital); + + doctor.setCaseClinicalDoctor(caseClinicalDoctor); + } + + // 处理返回值 + GetIndexClinicalDto g = new GetIndexClinicalDto(); + + // 最新上线-2条 + g.setNewArticles(CaseClinicalArticleDto.GetListDto(latestArticles)); + + // 最多阅读-2条 + g.setMostReadArticles(CaseClinicalArticleDto.GetListDto(mostReadArticles)); + + // 医院病例库推荐-2条 + g.setRecommendHospital(RecommendHospitalDto.GetListDto(statsCaseClinicalHospitals)); + + // 医生病例库推荐-2条 + g.setRecommendDoctor(RecommendDoctorDto.GetListDto(statsCaseClinicalDoctors)); + return g; + } +} diff --git a/src/main/java/com/example/caseData/service/UserService.java b/src/main/java/com/example/caseData/service/UserService.java new file mode 100644 index 0000000..cf84ef4 --- /dev/null +++ b/src/main/java/com/example/caseData/service/UserService.java @@ -0,0 +1,168 @@ +package com.example.caseData.service; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.crypto.SecureUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.example.caseData.dao.BasicHospitalDao; +import com.example.caseData.dao.UserDao; +import com.example.caseData.dto.PublicDto; +import com.example.caseData.exception.BusinessException; +import com.example.caseData.extend.app.Hospital.GetHospitalByUuidResponse; +import com.example.caseData.extend.app.Hospital.Hospital; +import com.example.caseData.extend.app.UserInfo.GetUserInfoByMobileResponse; +import com.example.caseData.extend.app.UserInfo.UserInfo; +import com.example.caseData.model.BasicHospitalModel; +import com.example.caseData.model.UserModel; +import com.example.caseData.utils.JwtUtil; +import com.example.caseData.utils.Replace; +import com.example.caseData.utils.StringToInt; +import jakarta.annotation.Resource; +import org.apache.el.parser.Token; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import static com.baomidou.mybatisplus.extension.toolkit.Db.save; + +@Service +public class UserService { + @Resource + private UserDao userDao; + + @Resource + private UserInfo userInfo; + + @Resource + private BasicHospitalDao basicHospitalDao; + + @Resource + private Hospital hospital; + + @Resource + private JwtUtil jwtUtil; + + /** + * 用户登陆 + * @return UserModel + */ + @Transactional + public PublicDto UserLogin(String phone) throws BusinessException { + // 获取app用户数据 + UserModel user = GetAppUserInfoByPhone(phone); + + // 生成jwt + String token = jwtUtil.createToken(String.valueOf(user.getUserId())); + + // 处理返回值 + PublicDto publicDto = new PublicDto(); + publicDto.setUserId(String.valueOf(user.getUserId())); + publicDto.setUserName(user.getUserName()); + publicDto.setAvatar(Replace.addOssDomain(user.getAvatar())); + publicDto.setToken(token); + return publicDto; + } + + /** + * 获取app用户数据 + * @param phone 手机号 + * @return UserModel + */ + public UserModel GetAppUserInfoByPhone(String phone) throws BusinessException { + // 请求接口获取数据 + GetUserInfoByMobileResponse result = userInfo.getUserInfoByMobile(phone); + GetUserInfoByMobileResponse.GetUserInfoByMobileData data = result.getData(); + + // 查询数据库用户信息 + LambdaQueryWrapper userModelWrapper = new LambdaQueryWrapper<>(); + userModelWrapper.eq(UserModel::getUserIden, result.getData().getUuid()); + UserModel user = userDao.selectOne(userModelWrapper); + if (user == null){ + // 构造 UserModel 对象 + user = new UserModel(); + user.setUserIden(data.getUuid()); + user.setUserName(data.getRealname()); + user.setUserMobile(data.getMobile()); + user.setMobileEncryption(SecureUtil.md5(data.getMobile())); + user.setStatus(1); + user.setRegisterSource(2); + user.setOpenId(""); + user.setUnionId(""); + user.setSex(0); + user.setAvatar(data.getPhoto()); + user.setDepartmentName(data.getOfficeName()); + user.setTitle(StringToInt.DoctorTitleToInt(data.getPositionName())); + user.setAddress(data.getProvName()); + save(user); + }else{ + if (!Objects.equals(user.getUserName(), data.getRealname())){ + user.setUserName(data.getRealname()); + } + + if (!Objects.equals(user.getUserMobile(), data.getMobile())){ + user.setUserMobile(data.getMobile()); + user.setMobileEncryption(SecureUtil.md5(data.getMobile())); + } + + if (!Objects.equals(user.getTitle(), StringToInt.DoctorTitleToInt(data.getOfficeName()))){ + user.setTitle(StringToInt.DoctorTitleToInt(data.getOfficeName())); + } + + if (!Objects.equals(user.getDepartmentName(), data.getOfficeName())){ + user.setDepartmentName(data.getOfficeName()); + } + + if (!Objects.equals(user.getAddress(), data.getProvName())){ + user.setAddress(data.getProvName()); + } + + userDao.updateById(user); + } + + // 获取app医院数据 + BasicHospitalModel basicHospital = GetAppHospital(data.getHospitalUuid()); + + // 修改用户所属医院 + if (!Objects.equals(user.getHospitalId(), basicHospital.getHospitalId())){ + UserModel updateUser = new UserModel(); + updateUser.setUserId(user.getUserId()); + updateUser.setHospitalId(basicHospital.getHospitalId()); + userDao.updateById(updateUser); + } + + return user; + } + + /** + * 获取app医院数据 + * @param hospitalIden app医院唯一标识 + * @return BasicHospitalModel + */ + public BasicHospitalModel GetAppHospital(String hospitalIden) throws BusinessException { + // 查询数据库医院信息 + LambdaQueryWrapper basicHospitalWrapper = new LambdaQueryWrapper<>(); + basicHospitalWrapper.eq(BasicHospitalModel::getHospitalIden, hospitalIden); + BasicHospitalModel basicHospital = basicHospitalDao.selectOne(basicHospitalWrapper); + if (basicHospital == null){ + // 请求接口获取数据 + GetHospitalByUuidResponse result = hospital.getHospitalByUuid(hospitalIden); + GetHospitalByUuidResponse.GetHospitalByUuidData data = result.getData(); + + // 构造 UserModel 对象 + basicHospital = new BasicHospitalModel(); + basicHospital.setHospitalIden(hospitalIden); + basicHospital.setHospitalName(data.getName()); + basicHospital.setSource(2); + basicHospital.setHospitalLevel(data.getLevel()); + basicHospital.setDoctorNumber(data.getExpert_num()); + basicHospital.setProvince(data.getProv_name()); + save(basicHospital); + } + + return basicHospital; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/utils/EnvUtil.java b/src/main/java/com/example/caseData/utils/EnvUtil.java new file mode 100644 index 0000000..07542c6 --- /dev/null +++ b/src/main/java/com/example/caseData/utils/EnvUtil.java @@ -0,0 +1,41 @@ +package com.example.caseData.utils; + +import com.example.caseData.config.EnvConfig; +import com.example.caseData.config.JwtConfig; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class EnvUtil { + private static EnvConfig envConfig; + + public EnvUtil(EnvConfig envConfig ){ + EnvUtil.envConfig = envConfig; + } + +// private static String activeProfile; + +// @Value("${spring.profiles.active:default}") +// private String active; +// +// @PostConstruct +// public void init() { +// activeProfile = active; +// } + + /** + * 判断是否为正式环境 + */ + public static boolean isProd() { + return "prod".equalsIgnoreCase(envConfig.getActive()); + } + + /** + * 判断是否为测试环境 + */ + public static boolean isDev() { + return "dev".equalsIgnoreCase(envConfig.getActive()) || "test".equalsIgnoreCase(envConfig.getActive()); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/utils/Fmt.java b/src/main/java/com/example/caseData/utils/Fmt.java new file mode 100644 index 0000000..636a644 --- /dev/null +++ b/src/main/java/com/example/caseData/utils/Fmt.java @@ -0,0 +1,7 @@ +package com.example.caseData.utils; + +public class Fmt { + public static void PrintLn(Object obj) { + System.out.println(">>> " + obj); + } +} diff --git a/src/main/java/com/example/caseData/utils/JwtUtil.java b/src/main/java/com/example/caseData/utils/JwtUtil.java new file mode 100644 index 0000000..3d73239 --- /dev/null +++ b/src/main/java/com/example/caseData/utils/JwtUtil.java @@ -0,0 +1,50 @@ +package com.example.caseData.utils; + +import cn.hutool.jwt.JWT; +import cn.hutool.jwt.JWTUtil; +import cn.hutool.jwt.JWTValidator; +import cn.hutool.jwt.RegisteredPayload; +import com.example.caseData.config.EnvConfig; +import com.example.caseData.config.JwtConfig; +import com.example.caseData.exception.BusinessException; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.Jwts; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Component; + +import java.util.Base64; +import java.util.Date; + +@Component +public class JwtUtil { + private static JwtConfig jwtConfig; + + public JwtUtil(JwtConfig jwtConfig ){ + JwtUtil.jwtConfig = jwtConfig; + } + + // 创建 + public String createToken(String userId) { + // 过期时间 + long expireMillis = System.currentTimeMillis() + jwtConfig.getTtl() * 60 * 60 * 1000L; + Date expiresAt = new Date(expireMillis); + + Date now = new Date(); + JWT jwt = JWT.create() + .setKey(jwtConfig.getSignKey().getBytes()) // 设置密钥 + .setPayload("user_id", userId) + .setPayload(RegisteredPayload.ISSUED_AT, now) // 发行时间 + .setPayload(RegisteredPayload.EXPIRES_AT, expiresAt) // 过期时间 + .setPayload(RegisteredPayload.NOT_BEFORE, now); // 生效时间 + + return jwt.sign(); // 签名并生成JWT字符串 + } + + // 解析 + public Claims verifyToken(String token) { + return Jwts.parser() + .setSigningKey(Base64.getEncoder().encodeToString(jwtConfig.getSignKey().getBytes())) + .parseClaimsJws(token).getBody(); + } +} diff --git a/src/main/java/com/example/caseData/utils/RedisUtils.java b/src/main/java/com/example/caseData/utils/RedisUtils.java new file mode 100644 index 0000000..10e02da --- /dev/null +++ b/src/main/java/com/example/caseData/utils/RedisUtils.java @@ -0,0 +1,43 @@ +package com.example.caseData.utils; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Component; + +@Component +public class RedisUtils { + private final StringRedisTemplate redisTemplate; + + @Autowired + public RedisUtils(StringRedisTemplate redisTemplate) { + this.redisTemplate = redisTemplate; + } + + /** + * 设置字符串值 + */ + public void set(String key, String value) { + redisTemplate.opsForValue().set(key, value); + } + + /** + * 获取字符串值 + */ + public String get(String key) { + return redisTemplate.opsForValue().get(key); + } + + /** + * 删除键 + */ + public void delete(String key) { + redisTemplate.delete(key); + } + + /** + * 判断 key 是否存在 + */ + public boolean hasKey(String key) { + return Boolean.TRUE.equals(redisTemplate.hasKey(key)); + } +} diff --git a/src/main/java/com/example/caseData/utils/Replace.java b/src/main/java/com/example/caseData/utils/Replace.java new file mode 100644 index 0000000..cd89750 --- /dev/null +++ b/src/main/java/com/example/caseData/utils/Replace.java @@ -0,0 +1,30 @@ +package com.example.caseData.utils; + +import jakarta.annotation.Resource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.RequestMapping; +import com.example.caseData.config.OssConfig; + +@Component +@RequestMapping("/config") +public class Replace { + private static OssConfig ossConfig; + + @Autowired + public Replace(OssConfig ossConfig) { + Replace.ossConfig = ossConfig; + } + + /** + * 增加oss地址中的前缀 + * @param url 原始URL + * @return 添加了域名前缀的URL + */ + public static String addOssDomain(String url) { + if (url == null || url.isEmpty()) { + return ""; + } + return ossConfig.getCustomDomainName() + url; + } +} diff --git a/src/main/java/com/example/caseData/utils/StringToInt.java b/src/main/java/com/example/caseData/utils/StringToInt.java new file mode 100644 index 0000000..6cfb9e8 --- /dev/null +++ b/src/main/java/com/example/caseData/utils/StringToInt.java @@ -0,0 +1,25 @@ +package com.example.caseData.utils; + +public class StringToInt { + + /** + * 将医生职称转换为整数。 + * + * @param title 医生职称字符串 + * @return 职称对应的整数值(0:未知 1:主任医师 2:主任中医师 3:副主任医师 4:副主任中医师 5:主治医师 6:住院医师) + */ + public static int DoctorTitleToInt(String title) { + if (title == null) { + return 0; + } + return switch (title.trim()) { + case "主任医师" -> 1; + case "主任中医师" -> 2; + case "副主任医师" -> 3; + case "副主任中医师" -> 4; + case "主治医师" -> 5; + case "住院医师" -> 6; + default -> 0; + }; + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..0e24453 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,70 @@ +server: + port: 5477 + +# DataSource Config +spring: + application: + name: caseData + profiles: + active: dev + datasource: + driver-class-name: com.p6spy.engine.spy.P6SpyDriver + url: jdbc:p6spy:mysql://42.193.16.243:30001/case_data?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8 + username: root + password: gdxz123456^%$d + data: + redis: + host: '139.155.127.177' + port: 30002 + password: gdxz2022&dj. + database: 9 + timeout: 3000 + jackson: + time-zone: Asia/Shanghai + default-property-inclusion: always + +# MyBatis-Plus 配置 +mybatis-plus: + configuration: + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 开启 SQL 日志 + map-underscore-to-camel-case: true + mapper-locations: "classpath:mapper/*.xml" + global-config: + worker-id: 1 + datacenter-id: 1 + +# oss配置 +oss: + access-key: LTAI5tKmFrVCghcxX7yHyGhm + access-key-secret: q1aiIZCJJuf92YbKk2cSXnPES4zx26 + bucket: caseplatform + endpoint: oss-cn-beijing.aliyuncs.com + custom-domain-name: https://caseplatform.oss-cn-beijing.aliyuncs.com + +# jwt配置 +jwt: + sign-key: 123456899 # 私钥 + ttl: 720 # 过期时间 小时 + algo: HS256 # 加密方式 + +# 日志 +logging: + level: + root: info # 全局日志级别 + file: + name: logs/app.log # 自定义日志文件路径 + pattern: + file: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" + +# 微信 +wechat: + miniapp: + appid: wxc83296720404aa7b + secret: 817665d3763637fe66d56548f8484622 + +# [app] +app: + apiUrl: https://dev-wx.igandan.com + secretKey: nmBCF@hEK6eN&h03dYUin@AU3%bMf%$O + imagePrefix: https://dev-doc.igandan.com/app + platform: case-storge diff --git a/src/main/resources/mapper/BasicHospitalMapper.xml b/src/main/resources/mapper/BasicHospitalMapper.xml new file mode 100644 index 0000000..ad93bfa --- /dev/null +++ b/src/main/resources/mapper/BasicHospitalMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/resources/mapper/BasicSensitiveWordMapper.xml b/src/main/resources/mapper/BasicSensitiveWordMapper.xml new file mode 100644 index 0000000..ae74797 --- /dev/null +++ b/src/main/resources/mapper/BasicSensitiveWordMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/CaseClinicalArticleAuthorMapper.xml b/src/main/resources/mapper/CaseClinicalArticleAuthorMapper.xml new file mode 100644 index 0000000..5691740 --- /dev/null +++ b/src/main/resources/mapper/CaseClinicalArticleAuthorMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/CaseClinicalArticleLabelMapper.xml b/src/main/resources/mapper/CaseClinicalArticleLabelMapper.xml new file mode 100644 index 0000000..eba6373 --- /dev/null +++ b/src/main/resources/mapper/CaseClinicalArticleLabelMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/CaseClinicalArticleMapper.xml b/src/main/resources/mapper/CaseClinicalArticleMapper.xml new file mode 100644 index 0000000..1267cfa --- /dev/null +++ b/src/main/resources/mapper/CaseClinicalArticleMapper.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/CaseClinicalVideoAuthorMapper.xml b/src/main/resources/mapper/CaseClinicalVideoAuthorMapper.xml new file mode 100644 index 0000000..68fdd4b --- /dev/null +++ b/src/main/resources/mapper/CaseClinicalVideoAuthorMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/CaseClinicalVideoLabelMapper.xml b/src/main/resources/mapper/CaseClinicalVideoLabelMapper.xml new file mode 100644 index 0000000..761728b --- /dev/null +++ b/src/main/resources/mapper/CaseClinicalVideoLabelMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/CaseClinicalVideoMapper.xml b/src/main/resources/mapper/CaseClinicalVideoMapper.xml new file mode 100644 index 0000000..950667a --- /dev/null +++ b/src/main/resources/mapper/CaseClinicalVideoMapper.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/StatsCaseClinicalDoctorMapper.xml b/src/main/resources/mapper/StatsCaseClinicalDoctorMapper.xml new file mode 100644 index 0000000..e0ad916 --- /dev/null +++ b/src/main/resources/mapper/StatsCaseClinicalDoctorMapper.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/StatsCaseClinicalHospitalMapper.xml b/src/main/resources/mapper/StatsCaseClinicalHospitalMapper.xml new file mode 100644 index 0000000..d41b79a --- /dev/null +++ b/src/main/resources/mapper/StatsCaseClinicalHospitalMapper.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/StatsCaseClinicalMapper.xml b/src/main/resources/mapper/StatsCaseClinicalMapper.xml new file mode 100644 index 0000000..2ff86eb --- /dev/null +++ b/src/main/resources/mapper/StatsCaseClinicalMapper.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/UserCollectClinicalArticleMapper.xml b/src/main/resources/mapper/UserCollectClinicalArticleMapper.xml new file mode 100644 index 0000000..f88a863 --- /dev/null +++ b/src/main/resources/mapper/UserCollectClinicalArticleMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/UserCollectClinicalVideoMapper.xml b/src/main/resources/mapper/UserCollectClinicalVideoMapper.xml new file mode 100644 index 0000000..5d6f310 --- /dev/null +++ b/src/main/resources/mapper/UserCollectClinicalVideoMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/UserCommentClinicalArticleMapper.xml b/src/main/resources/mapper/UserCommentClinicalArticleMapper.xml new file mode 100644 index 0000000..c461664 --- /dev/null +++ b/src/main/resources/mapper/UserCommentClinicalArticleMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/UserCommentClinicalVideoMapper.xml b/src/main/resources/mapper/UserCommentClinicalVideoMapper.xml new file mode 100644 index 0000000..8acd138 --- /dev/null +++ b/src/main/resources/mapper/UserCommentClinicalVideoMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/UserMapper.xml b/src/main/resources/mapper/UserMapper.xml new file mode 100644 index 0000000..d364c53 --- /dev/null +++ b/src/main/resources/mapper/UserMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/resources/spy.properties b/src/main/resources/spy.properties new file mode 100644 index 0000000..c9d2903 --- /dev/null +++ b/src/main/resources/spy.properties @@ -0,0 +1,19 @@ +# ???????? +#appender=com.p6spy.engine.spy.appender.StdoutLogger +appender=com.p6spy.engine.spy.appender.Slf4JLogger + +# ????????????????? +logMessageFormat=com.p6spy.engine.spy.appender.SingleLineFormat + +# ???????? +outagedetection=false + +# ?????????????????? +# logfile=spy.log + +# ??? SQL???????? +excludecategories=info,debug,result,resultset,batch + + +# ???????????? +executionThreshold=0 \ No newline at end of file diff --git a/src/test/java/com/example/caseData/CaseDataApplicationTests.java b/src/test/java/com/example/caseData/CaseDataApplicationTests.java new file mode 100644 index 0000000..f158f61 --- /dev/null +++ b/src/test/java/com/example/caseData/CaseDataApplicationTests.java @@ -0,0 +1,13 @@ +package com.example.caseData; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class CaseDataApplicationTests { + + @Test + void contextLoads() { + } + +}