hjp 10 mesiacov pred
commit
f9929e0d17
100 zmenil súbory, kde vykonal 6555 pridanie a 0 odobranie
  1. 11 0
      .idea/$PROJECT_FILE$
  2. 5 0
      .idea/.gitignore
  3. 19 0
      .idea/compiler.xml
  4. 7 0
      .idea/encodings.xml
  5. 20 0
      .idea/jarRepositories.xml
  6. 17 0
      .idea/misc.xml
  7. 12 0
      .idea/qaplug_profiles.xml
  8. 8 0
      Order.iml
  9. 128 0
      README.md
  10. 846 0
      db_school_eorder.sql
  11. BIN
      pic/add-cart.png
  12. BIN
      pic/admin-goods-add.png
  13. BIN
      pic/admin-goods-list.png
  14. BIN
      pic/admin-index.png
  15. BIN
      pic/comment.png
  16. BIN
      pic/coupon.png
  17. BIN
      pic/goods-info.png
  18. BIN
      pic/index.png
  19. BIN
      pic/login.png
  20. BIN
      pic/order-info.png
  21. BIN
      pic/search.png
  22. BIN
      pic/功能.drawio.png
  23. BIN
      pic/项目架构图.drawio.png
  24. 210 0
      pom.xml
  25. 23 0
      src/main/java/com/cdu/lys/graduation/Application.java
  26. 17 0
      src/main/java/com/cdu/lys/graduation/admin/bill/bo/BillBO.java
  27. 42 0
      src/main/java/com/cdu/lys/graduation/admin/bill/bo/impl/BillBOImpl.java
  28. 33 0
      src/main/java/com/cdu/lys/graduation/admin/bill/converter/BillConverter.java
  29. 11 0
      src/main/java/com/cdu/lys/graduation/admin/bill/service/BillService.java
  30. 112 0
      src/main/java/com/cdu/lys/graduation/admin/bill/service/impl/BillServiceImpl.java
  31. 38 0
      src/main/java/com/cdu/lys/graduation/admin/comment/bo/AdminCommentBO.java
  32. 133 0
      src/main/java/com/cdu/lys/graduation/admin/comment/bo/impl/AdminCommentBOImpl.java
  33. 20 0
      src/main/java/com/cdu/lys/graduation/admin/comment/service/AdminCommentService.java
  34. 88 0
      src/main/java/com/cdu/lys/graduation/admin/comment/service/impl/AdminCommentServiceImpl.java
  35. 31 0
      src/main/java/com/cdu/lys/graduation/admin/coupon/bo/AdminCouponBO.java
  36. 124 0
      src/main/java/com/cdu/lys/graduation/admin/coupon/bo/impl/AdminCouponBOImpl.java
  37. 19 0
      src/main/java/com/cdu/lys/graduation/admin/coupon/service/AdminCouponService.java
  38. 55 0
      src/main/java/com/cdu/lys/graduation/admin/coupon/service/impl/AdminCouponServiceImpl.java
  39. 81 0
      src/main/java/com/cdu/lys/graduation/admin/goods/bo/AdminGoodsBO.java
  40. 19 0
      src/main/java/com/cdu/lys/graduation/admin/goods/bo/AdminGoodsOptionBO.java
  41. 24 0
      src/main/java/com/cdu/lys/graduation/admin/goods/bo/AdminGoodsTypeBO.java
  42. 171 0
      src/main/java/com/cdu/lys/graduation/admin/goods/bo/impl/AdminGoodsBOImpl.java
  43. 133 0
      src/main/java/com/cdu/lys/graduation/admin/goods/bo/impl/AdminGoodsOptionBOImpl.java
  44. 74 0
      src/main/java/com/cdu/lys/graduation/admin/goods/bo/impl/AdminGoodsTypeBOImpl.java
  45. 49 0
      src/main/java/com/cdu/lys/graduation/admin/goods/convertor/GoodsConverter.java
  46. 19 0
      src/main/java/com/cdu/lys/graduation/admin/goods/service/AdminGoodsOptionService.java
  47. 59 0
      src/main/java/com/cdu/lys/graduation/admin/goods/service/AdminGoodsService.java
  48. 16 0
      src/main/java/com/cdu/lys/graduation/admin/goods/service/AdminGoodsTypeService.java
  49. 55 0
      src/main/java/com/cdu/lys/graduation/admin/goods/service/impl/AdminGoodsOptionServiceImpl.java
  50. 174 0
      src/main/java/com/cdu/lys/graduation/admin/goods/service/impl/AdminGoodsServiceImpl.java
  51. 39 0
      src/main/java/com/cdu/lys/graduation/admin/goods/service/impl/AdminGoodsTypeServiceImpl.java
  52. 17 0
      src/main/java/com/cdu/lys/graduation/admin/login/bo/AdminBO.java
  53. 37 0
      src/main/java/com/cdu/lys/graduation/admin/login/bo/impl/AdminBOImpl.java
  54. 18 0
      src/main/java/com/cdu/lys/graduation/admin/login/service/AdminLoginService.java
  55. 53 0
      src/main/java/com/cdu/lys/graduation/admin/login/service/impl/AdminLoginServiceImpl.java
  56. 25 0
      src/main/java/com/cdu/lys/graduation/admin/merchant/bo/MerchantBO.java
  57. 25 0
      src/main/java/com/cdu/lys/graduation/admin/merchant/bo/MerchantRealPictureBO.java
  58. 43 0
      src/main/java/com/cdu/lys/graduation/admin/merchant/bo/impl/MerchantBOImpl.java
  59. 63 0
      src/main/java/com/cdu/lys/graduation/admin/merchant/bo/impl/MerchantRealPictureBOImpl.java
  60. 41 0
      src/main/java/com/cdu/lys/graduation/admin/merchant/convertor/MerchantConvertor.java
  61. 32 0
      src/main/java/com/cdu/lys/graduation/admin/order/bo/AdminOrderBO.java
  62. 35 0
      src/main/java/com/cdu/lys/graduation/admin/order/bo/AdminOrderFormInfoBO.java
  63. 118 0
      src/main/java/com/cdu/lys/graduation/admin/order/bo/impl/AdminOrderBOImpl.java
  64. 69 0
      src/main/java/com/cdu/lys/graduation/admin/order/bo/impl/AdminOrderFormInfoBOImpl.java
  65. 57 0
      src/main/java/com/cdu/lys/graduation/admin/order/converter/OrderDataConverter.java
  66. 30 0
      src/main/java/com/cdu/lys/graduation/admin/order/converter/OrderInfoDataConverter.java
  67. 25 0
      src/main/java/com/cdu/lys/graduation/admin/order/service/AdminOrderService.java
  68. 150 0
      src/main/java/com/cdu/lys/graduation/admin/order/service/impl/AdminOrderServiceImpl.java
  69. 16 0
      src/main/java/com/cdu/lys/graduation/admin/record/bo/RecordBO.java
  70. 30 0
      src/main/java/com/cdu/lys/graduation/admin/record/bo/impl/RecordBOImpl.java
  71. 40 0
      src/main/java/com/cdu/lys/graduation/admin/record/service/RecordService.java
  72. 156 0
      src/main/java/com/cdu/lys/graduation/admin/record/service/impl/RecordServiceImpl.java
  73. 14 0
      src/main/java/com/cdu/lys/graduation/admin/user/bo/AdminUserBO.java
  74. 51 0
      src/main/java/com/cdu/lys/graduation/admin/user/bo/impl/AdminUserBOImpl.java
  75. 97 0
      src/main/java/com/cdu/lys/graduation/commons/result/ActionResult.java
  76. 91 0
      src/main/java/com/cdu/lys/graduation/commons/result/PageResult.java
  77. 52 0
      src/main/java/com/cdu/lys/graduation/commons/result/UploadFileResponse.java
  78. 31 0
      src/main/java/com/cdu/lys/graduation/commons/utils/BASE64Utils.java
  79. 61 0
      src/main/java/com/cdu/lys/graduation/commons/utils/DateUtils.java
  80. 132 0
      src/main/java/com/cdu/lys/graduation/commons/utils/JWTUtils.java
  81. 55 0
      src/main/java/com/cdu/lys/graduation/config/RedisConfig.java
  82. 78 0
      src/main/java/com/cdu/lys/graduation/config/RestTemplateConfig.java
  83. 21 0
      src/main/java/com/cdu/lys/graduation/config/ScheduleConfig.java
  84. 37 0
      src/main/java/com/cdu/lys/graduation/config/SwaggerConfig.java
  85. 83 0
      src/main/java/com/cdu/lys/graduation/config/WebMvcConfig.java
  86. 90 0
      src/main/java/com/cdu/lys/graduation/controller/admin/AdminBillController.java
  87. 82 0
      src/main/java/com/cdu/lys/graduation/controller/admin/AdminCommentController.java
  88. 120 0
      src/main/java/com/cdu/lys/graduation/controller/admin/AdminCouponController.java
  89. 115 0
      src/main/java/com/cdu/lys/graduation/controller/admin/AdminGoodsController.java
  90. 67 0
      src/main/java/com/cdu/lys/graduation/controller/admin/AdminGoodsOptionController.java
  91. 110 0
      src/main/java/com/cdu/lys/graduation/controller/admin/AdminGoodsTypeController.java
  92. 63 0
      src/main/java/com/cdu/lys/graduation/controller/admin/AdminIndexController.java
  93. 107 0
      src/main/java/com/cdu/lys/graduation/controller/admin/AdminLoginController.java
  94. 71 0
      src/main/java/com/cdu/lys/graduation/controller/admin/AdminMerchantController.java
  95. 117 0
      src/main/java/com/cdu/lys/graduation/controller/admin/AdminOrderController.java
  96. 98 0
      src/main/java/com/cdu/lys/graduation/controller/coupon/CouponController.java
  97. 99 0
      src/main/java/com/cdu/lys/graduation/controller/file/FileController.java
  98. 231 0
      src/main/java/com/cdu/lys/graduation/controller/goods/GoodsController.java
  99. 142 0
      src/main/java/com/cdu/lys/graduation/controller/user/CommentController.java
  100. 218 0
      src/main/java/com/cdu/lys/graduation/controller/user/LoginController.java

+ 11 - 0
.idea/$PROJECT_FILE$

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="AnalysisProjectProfileManager">
+    <option name="PROJECT_PROFILE" />
+    <option name="USE_PROJECT_LEVEL_SETTINGS" value="false" />
+    <list size="0" />
+  </component>
+  <component name="SuppressionsComponent">
+    <option name="suppComments" value="[]" />
+  </component>
+</project>

+ 5 - 0
.idea/.gitignore

@@ -0,0 +1,5 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/

+ 19 - 0
.idea/compiler.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CompilerConfiguration">
+    <annotationProcessing>
+      <profile default="true" name="Default" enabled="true" />
+      <profile name="Maven default annotation processors profile" enabled="true">
+        <sourceOutputDir name="target/generated-sources/annotations" />
+        <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
+        <outputRelativeToContentRoot value="true" />
+        <module name="Order" />
+      </profile>
+    </annotationProcessing>
+  </component>
+  <component name="JavacSettings">
+    <option name="ADDITIONAL_OPTIONS_OVERRIDE">
+      <module name="Order" options="-parameters" />
+    </option>
+  </component>
+</project>

+ 7 - 0
.idea/encodings.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Encoding">
+    <file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
+  </component>
+</project>

+ 20 - 0
.idea/jarRepositories.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="RemoteRepositoriesConfiguration">
+    <remote-repository>
+      <option name="id" value="central" />
+      <option name="name" value="Maven Central repository" />
+      <option name="url" value="https://repo1.maven.org/maven2" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="central" />
+      <option name="name" value="Central Repository" />
+      <option name="url" value="http://maven.aliyun.com/nexus/content/groups/public/" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="jboss.community" />
+      <option name="name" value="JBoss Community repository" />
+      <option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
+    </remote-repository>
+  </component>
+</project>

+ 17 - 0
.idea/misc.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ExternalStorageConfigurationManager" enabled="true" />
+  <component name="MavenProjectsManager">
+    <option name="originalFiles">
+      <list>
+        <option value="$PROJECT_DIR$/pom.xml" />
+      </list>
+    </option>
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/out" />
+  </component>
+  <component name="SuppressionsComponent">
+    <option name="suppComments" value="[]" />
+  </component>
+</project>

+ 12 - 0
.idea/qaplug_profiles.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="AnalysisProjectProfileManager">
+    <option name="PROJECT_PROFILE" value="Project Default" />
+    <option name="USE_PROJECT_LEVEL_SETTINGS" value="false" />
+    <scopes />
+    <profiles>
+      <profile profile_name="Project Default" version="1.0" is_locked="false" />
+    </profiles>
+    <list size="0" />
+  </component>
+</project>

+ 8 - 0
Order.iml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="FacetManager">
+    <facet type="Spring" name="Spring">
+      <configuration />
+    </facet>
+  </component>
+</module>

+ 128 - 0
README.md

@@ -0,0 +1,128 @@
+# EOrder
+
+#### 1. 介绍
+​		使用微信小程序开发的在线点餐平台。项目包括微信小程序、Web 商户端和 Java 服务端。功能上分为登录注册模块、商品模块、优惠模块、订单 模块、评论模块、搜索及热搜。  采用 B/S 架构、前后端分离模式进行设计与开发。前端使用微信小程序与 LayUI 开发,Java 服务端使用 SpringBoot、SpringMVC、Mybatis、MySQL、Redis 等技术。 
+
+​		未登录用户(游客)可以使用小程序进行浏览、选择加入购物车、查看评论和查看优惠券等功能,进行下单 时提示用户登录。登录用户可以使用除游客以外的下单、领取使用优惠券和查看个人信息等功能。商户端需使用管理权限才能登录使用。 
+
+本项目分为3部分,包括微信小程序、Web商户管理系统和Java服务器。
+
+| 目录         | 说明         |
+| ------------ | ------------ |
+| Eorder       | Java项目代码 |
+| eorder-admin | Web管理系统  |
+| eorder-mini  | 微信小程序   |
+| pic          | 图片         |
+
+#### 2. 功能概览
+系统总体功能下图所示。
+
+![项目功能概览.drawio](./pic/功能.drawio.png)
+
+
+
+#### 3. 系统环境
+
+##### 3.1 环境
+
+1. Java环境:JDK8、MySQL5.7、Maven、Redis、Docker。
+2. 小程序环境:微信小程序。
+3. Web端使用layUI开发。
+
+##### 3.2 技术栈
+
+Java技术栈:
+
+1.  Spring Boot
+2.  Spring MVC
+3.  Mybatis/Mybatis Generator
+4.  Mysql
+5.  Redis
+6.  Swagger
+7.  Maven
+
+#### 4. 使用说明
+
+##### 4.0 使用前务必确认
+
+1. MySQL是否导入(目录下的sql文件)
+2. redis是否配置正确
+3. **后台跨域是否配置正确(跨域配置:order-start > com.xxxx.config.WebMvcConfig)**[跨域资源共享 CORS 详解 - 阮一峰的网络日志](https://www.ruanyifeng.com/blog/2016/04/cors.html)
+4. 管理员账号
+   - 92024109936,exR4HT7jzh7QPeRx
+
+##### 4.1 Java端使用说明
+
+1. MySQL数据库导入:建立db_school_eorder数据库将EOrder根目录下的db_school_eorder.sql文件导入。
+2. redis数据库:修改yml文件的host和port正确即可。
+3. 启动Application.java
+4. 启动后,项目接口文档地址:http://localhost:8080/swagger-ui.html#/
+
+##### 4.2 微信小程序使用说明
+
+1. 导入项目至微信开发助手使用
+
+##### 4.3 Web管理系统使用说明
+
+1. 部署到Web服务器使用
+
+#### 5. 项目展示
+
+##### 5.1 微信小程序
+
+###### **登录**
+
+![](./pic/login.png)
+
+###### **主页**
+
+![](./pic/index.png)
+
+###### **详情**
+
+![](./pic/goods-info.png)
+
+###### **加入购物车**
+
+![](./pic/add-cart.png)
+
+
+
+###### **订单详情**
+
+![](./pic/order-info.png)
+
+
+
+###### **评论**
+
+![](./pic/comment.png)
+
+###### **优惠券**
+
+![](./pic/coupon.png)
+
+###### **搜索**
+
+![](./pic/search.png)
+
+##### 5.2 Web管理系统
+
+###### **主页**
+
+![](./pic/admin-index.png)
+
+###### **系统列表实例**
+
+![](./pic/admin-goods-list.png)
+
+###### **添加商品**
+
+![](./pic/admin-goods-add.png)
+
+#### 6. 参与贡献
+
+1.  Fork 本仓库
+2.  新建 Feat_xxx 分支
+3.  提交代码
+4.  新建 Pull Request

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 846 - 0
db_school_eorder.sql


BIN
pic/add-cart.png


BIN
pic/admin-goods-add.png


BIN
pic/admin-goods-list.png


BIN
pic/admin-index.png


BIN
pic/comment.png


BIN
pic/coupon.png


BIN
pic/goods-info.png


BIN
pic/index.png


BIN
pic/login.png


BIN
pic/order-info.png


BIN
pic/search.png


BIN
pic/功能.drawio.png


BIN
pic/项目架构图.drawio.png


+ 210 - 0
pom.xml

@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.cdu.lys.graduation</groupId>
+    <artifactId>EOrder</artifactId>
+    <packaging>jar</packaging>
+    <version>1.0-SNAPSHOT</version>
+
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.5.6</version>
+        <relativePath/>
+    </parent>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <junit.version>4.10</junit.version>
+        <log4j.version>1.2.12</log4j.version>
+        <lombok.version>1.16.18</lombok.version>
+        <mysql.version>8.0.33</mysql.version>
+        <druid.version>1.1.16</druid.version>
+        <mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
+        <fastjson.version>1.2.75</fastjson.version>
+        <swagger.version>2.9.2</swagger.version>
+    </properties>
+
+    <dependencies>
+        <!--spring boot 2.2.2-->
+        <!--<dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-dependencies</artifactId>
+            <version>2.5.6</version>
+            <type>pom</type>
+            <scope>import</scope>
+        </dependency>-->
+        <!--<dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+        </dependency>-->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>${mysql.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid</artifactId>
+            <version>${druid.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.mybatis.spring.boot</groupId>
+            <artifactId>mybatis-spring-boot-starter</artifactId>
+            <version>${mybatis.spring.boot.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>${junit.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+            <version>${log4j.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>${lombok.version}</version>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>${fastjson.version}</version>
+        </dependency>
+
+        <!-- swagger -->
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+            <version>${swagger.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger-ui</artifactId>
+            <version>${swagger.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>3.9</version>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>2.8.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper-spring-boot-starter</artifactId>
+            <version>1.3.0</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.mybatis.spring.boot</groupId>
+                    <artifactId>mybatis-spring-boot-starter</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!-- <dependency>
+             <groupId>commons-fileupload</groupId>
+             <artifactId>commons-fileupload</artifactId>
+             <version>1.3.3</version>
+         </dependency>-->
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>easyexcel</artifactId>
+            <version>2.2.7</version>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+            <version>0.9.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.auth0</groupId>
+            <artifactId>java-jwt</artifactId>
+            <version>3.4.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.mybatis.generator</groupId>
+            <artifactId>mybatis-generator-core</artifactId>
+            <version>1.3.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <version>2.5.6</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+            <version>2.5.6</version>
+        </dependency>
+        <dependency>
+            <groupId>org.mindrot</groupId>
+            <artifactId>jbcrypt</artifactId>
+            <version>0.4</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid-spring-boot-starter</artifactId>
+            <version>1.1.10</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+            <version>5.3.12</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+            <version>2.5.6</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>${project.artifactId}</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <!--                    <fork>true</fork> &lt;!&ndash; 如果没有该配置,devtools不会生效 &ndash;&gt;-->
+                </configuration>
+            </plugin>
+        </plugins>
+       <!-- <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+                &lt;!&ndash;                <includes>&ndash;&gt;
+                &lt;!&ndash;                    <include>application.yml</include>&ndash;&gt;
+                &lt;!&ndash;                    <include>application-${spring.profiles.active}.yml</include>&ndash;&gt;
+                &lt;!&ndash;                    <include>**/*.xml</include>&ndash;&gt;
+                &lt;!&ndash;                </includes>&ndash;&gt;
+            </resource>
+        </resources>-->
+    </build>
+</project>

+ 23 - 0
src/main/java/com/cdu/lys/graduation/Application.java

@@ -0,0 +1,23 @@
+package com.cdu.lys.graduation;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+/**
+ * @author liyinsong
+ * @date 2022/1/3 14:09
+ */
+@SpringBootApplication
+@ComponentScan(basePackages = "com.cdu.lys")
+@MapperScan("com.cdu.lys.graduation.repository.dao")
+@EnableScheduling
+@EnableCaching
+public class Application {
+    public static void main(String[] args) {
+        SpringApplication.run(Application.class, args);
+    }
+}

+ 17 - 0
src/main/java/com/cdu/lys/graduation/admin/bill/bo/BillBO.java

@@ -0,0 +1,17 @@
+package com.cdu.lys.graduation.admin.bill.bo;
+
+import com.cdu.lys.graduation.repository.entity.BillDO;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/4/6 16:36
+ */
+public interface BillBO {
+
+    List<BillDO> getAll();
+
+    List<BillDO> getByDate(Date date);
+}

+ 42 - 0
src/main/java/com/cdu/lys/graduation/admin/bill/bo/impl/BillBOImpl.java

@@ -0,0 +1,42 @@
+package com.cdu.lys.graduation.admin.bill.bo.impl;
+
+import com.cdu.lys.graduation.admin.bill.bo.BillBO;
+import com.cdu.lys.graduation.repository.dao.BillDOMapper;
+import com.cdu.lys.graduation.repository.entity.BillDO;
+import com.cdu.lys.graduation.repository.entity.BillDOExample;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * @author liyinsong
+ * @date 2022/4/6 16:37
+ */
+@Service
+public class BillBOImpl implements BillBO {
+
+    @Autowired
+    private BillDOMapper billDOMapper;
+
+    @Override
+    public List<BillDO> getAll() {
+        BillDOExample example = new BillDOExample();
+        example.setOrderByClause("bill_date desc");
+        return billDOMapper.selectByExample(example);
+    }
+
+    @Override
+    public List<BillDO> getByDate(Date date) {
+        BillDOExample example = new BillDOExample();
+        example.setOrderByClause("bill_date desc");
+        if (Objects.nonNull(date)) {
+            example.createCriteria()
+                    .andBillDateEqualTo(date);
+        }
+        return billDOMapper.selectByExample(example);
+    }
+
+}

+ 33 - 0
src/main/java/com/cdu/lys/graduation/admin/bill/converter/BillConverter.java

@@ -0,0 +1,33 @@
+package com.cdu.lys.graduation.admin.bill.converter;
+
+import com.cdu.lys.graduation.domain.admin.vo.BillVO;
+import com.cdu.lys.graduation.repository.entity.BillDO;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/4/6 16:50
+ */
+@Component
+public class BillConverter {
+
+    public List<BillVO> convert2VOList(List<BillDO> allBill) {
+
+        if (CollectionUtils.isEmpty(allBill)) {
+            return null;
+        }
+        List<BillVO> res = new ArrayList<>();
+        allBill.forEach(billDO -> {
+            BillVO billVO = new BillVO();
+            BeanUtils.copyProperties(billDO, billVO);
+            res.add(billVO);
+        });
+
+        return res;
+    }
+}

+ 11 - 0
src/main/java/com/cdu/lys/graduation/admin/bill/service/BillService.java

@@ -0,0 +1,11 @@
+package com.cdu.lys.graduation.admin.bill.service;
+
+/**
+ * @author liyinsong
+ * @date 2022/4/6 17:38
+ */
+public interface BillService {
+
+    void billTask();
+
+}

+ 112 - 0
src/main/java/com/cdu/lys/graduation/admin/bill/service/impl/BillServiceImpl.java

@@ -0,0 +1,112 @@
+package com.cdu.lys.graduation.admin.bill.service.impl;
+
+import com.cdu.lys.graduation.admin.bill.service.BillService;
+import com.cdu.lys.graduation.commons.utils.DateUtils;
+import com.cdu.lys.graduation.repository.dao.BillDOMapper;
+import com.cdu.lys.graduation.repository.dao.GoodsDOMapper;
+import com.cdu.lys.graduation.repository.dao.OrderFormDOMapper;
+import com.cdu.lys.graduation.repository.dao.OrderFormInfoDOMapper;
+import com.cdu.lys.graduation.repository.entity.*;
+import com.cdu.lys.graduation.types.payment.TradeStatus;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author liyinsong
+ * @date 2022/4/6 17:38
+ */
+@Service
+public class BillServiceImpl implements BillService {
+
+    @Autowired
+    private OrderFormDOMapper orderFormDOMapper;
+
+    @Autowired
+    private OrderFormInfoDOMapper orderFormInfoDOMapper;
+
+    @Autowired
+    private GoodsDOMapper goodsDOMapper;
+
+    @Autowired
+    private BillDOMapper billDOMapper;
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void billTask() {
+        Date today = DateUtils.getToday();
+
+        OrderFormDOExample example = new OrderFormDOExample();
+        example.createCriteria()
+                .andCreateTimeGreaterThanOrEqualTo(today);
+
+        //当天所有订单
+        List<OrderFormDO> orderFormDOList = orderFormDOMapper.selectByExample(example);
+
+        double totalOrderAmount = 0;
+        double totalActualAmount = 0;
+        double totalCost = 0;
+
+        List<OrderFormDO> collect = orderFormDOList.stream().
+                filter(orderFormDO -> orderFormDO.getTradeStatus().equals(TradeStatus.FINISHED.getCode())
+                        || orderFormDO.getTradeStatus().equals(TradeStatus.NOT_DELIVERY.getCode()))
+                .collect(Collectors.toList());
+
+        for (OrderFormDO orderFormDO : collect) {
+
+            totalOrderAmount += orderFormDO.getOrderAmount();
+            totalActualAmount += orderFormDO.getPayAmount();
+            totalCost += this.getCost(orderFormDO);
+        }
+
+        BillDOExample billDOExample = new BillDOExample();
+        billDOExample.createCriteria()
+                .andBillDateEqualTo(today);
+
+        List<BillDO> billDOS = billDOMapper.selectByExample(billDOExample);
+
+        BillDO billDO = new BillDO();
+        billDO.setTotalOrderAmount(totalOrderAmount);
+        billDO.setTotalActualAmount(totalActualAmount);
+        billDO.setTotalCost(totalCost);
+        billDO.setNetIncome(totalActualAmount - totalCost);
+        billDO.setTotalNumber(orderFormDOList.size());
+        billDO.setCancelNumber(orderFormDOList.size() - collect.size());
+        billDO.setBillDate(today);
+
+        if (CollectionUtils.isEmpty(billDOS)) {
+            billDOMapper.insertSelective(billDO);
+        }else {
+            billDO.setId(billDOS.get(0).getId());
+            billDOMapper.updateByPrimaryKeySelective(billDO);
+        }
+
+    }
+
+    /**
+     * 计算成本
+     * @param orderFormDO 订单
+     * @return 成本
+     */
+    private double getCost(OrderFormDO orderFormDO) {
+        OrderFormInfoDOExample example = new OrderFormInfoDOExample();
+        example.createCriteria()
+                .andOrderNumEqualTo(orderFormDO.getOrderNum());
+
+        double cost = 0;
+        List<OrderFormInfoDO> orderFormInfoDOS = orderFormInfoDOMapper.selectByExample(example);
+        for (OrderFormInfoDO orderFormInfoDO : orderFormInfoDOS) {
+            Integer goodsId = orderFormInfoDO.getGoodsId();
+            GoodsDO goodsDO = goodsDOMapper.selectByPrimaryKey(goodsId);
+            cost += goodsDO.getCost();
+        }
+
+        return cost;
+    }
+
+}

+ 38 - 0
src/main/java/com/cdu/lys/graduation/admin/comment/bo/AdminCommentBO.java

@@ -0,0 +1,38 @@
+package com.cdu.lys.graduation.admin.comment.bo;
+
+import com.cdu.lys.graduation.domain.admin.dto.CommentSearchDTO;
+import com.cdu.lys.graduation.domain.comment.dto.CommentDTO;
+import com.cdu.lys.graduation.repository.entity.CommentDO;
+import com.cdu.lys.graduation.types.admin.comment.CommentReplyQuery;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/4/2 11:01
+ */
+public interface AdminCommentBO {
+
+    /**
+     * 得到过去date到现在的评论
+     *
+     * @param date 时间
+     * @return 评分
+     */
+    List<CommentDO> getCommentBeforeDate(Date date);
+
+    /**
+     * 根据条件搜索
+     *
+     * @param query 条件
+     * @return 结果
+     */
+    List<CommentDTO> search(CommentSearchDTO query);
+
+    boolean reply(CommentReplyQuery query);
+
+    boolean delete(Integer id);
+
+    int autoReply(String replyContent);
+}

+ 133 - 0
src/main/java/com/cdu/lys/graduation/admin/comment/bo/impl/AdminCommentBOImpl.java

@@ -0,0 +1,133 @@
+package com.cdu.lys.graduation.admin.comment.bo.impl;
+
+import com.cdu.lys.graduation.admin.comment.bo.AdminCommentBO;
+import com.cdu.lys.graduation.admin.user.bo.AdminUserBO;
+import com.cdu.lys.graduation.domain.admin.dto.CommentSearchDTO;
+import com.cdu.lys.graduation.domain.comment.dto.CommentDTO;
+import com.cdu.lys.graduation.repository.dao.CommentDOMapper;
+import com.cdu.lys.graduation.repository.dao.UserDOMapper;
+import com.cdu.lys.graduation.repository.entity.CommentDO;
+import com.cdu.lys.graduation.repository.entity.CommentDOExample;
+import com.cdu.lys.graduation.repository.entity.UserDO;
+import com.cdu.lys.graduation.types.ExpireTypeEnum;
+import com.cdu.lys.graduation.types.admin.comment.CommentReplyQuery;
+import com.cdu.lys.graduation.types.admin.comment.CommentType;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * @author liyinsong
+ * @date 2022/4/2 11:01
+ */
+@Service
+public class AdminCommentBOImpl implements AdminCommentBO {
+
+    @Autowired
+    private CommentDOMapper commentDOMapper;
+
+    @Autowired
+    private UserDOMapper userDOMapper;
+
+    @Autowired
+    private AdminUserBO adminUserBO;
+
+    @Override
+    public List<CommentDO> getCommentBeforeDate(Date date) {
+        CommentDOExample example = new CommentDOExample();
+        example.createCriteria()
+                .andCreateTimeGreaterThan(date)
+                .andIsDeleteEqualTo("n");
+
+        return commentDOMapper.selectByExample(example);
+    }
+
+    @Override
+    public List<CommentDTO> search(CommentSearchDTO query) {
+        CommentDOExample example = new CommentDOExample();
+        CommentDOExample.Criteria criteria = example.createCriteria();
+
+        UserDO userDO = null;
+        if (StringUtils.hasLength(query.getUsername())) {
+            userDO = adminUserBO.getByUsername(query.getUsername());
+            if(Objects.nonNull(userDO))
+                criteria.andUserIdEqualTo(userDO.getId());
+        }
+
+        //好评、差评
+        Integer commentType = query.getCommentType();
+        if (Objects.nonNull(commentType) && CommentType.isCommentType(commentType)) {
+            if (CommentType.BAD_COMMENT.getType().equals(commentType)) {
+                criteria.andTasteScoreLessThan(3)
+                        .andEnvironmentScoreLessThan(3)
+                        .andServiceScoreLessThan(3);
+            }else {
+                criteria.andTasteScoreGreaterThanOrEqualTo(3)
+                        .andEnvironmentScoreGreaterThanOrEqualTo(3)
+                        .andServiceScoreGreaterThanOrEqualTo(3);
+            }
+        }
+        criteria.andIsDeleteEqualTo("n");
+        List<CommentDO> commentDOS = commentDOMapper.selectByExample(example);
+
+        List<CommentDTO> result = new ArrayList<>();
+        for (CommentDO commentDO : commentDOS) {
+            CommentDTO commentDTO = new CommentDTO();
+            BeanUtils.copyProperties(commentDO, commentDTO);
+            if (Objects.nonNull(userDO)) {
+                BeanUtils.copyProperties(userDO, commentDTO);
+            }
+            result.add(commentDTO);
+        }
+
+        return result;
+    }
+
+    @Override
+    public boolean reply(CommentReplyQuery query) {
+        Date replyTime = new Date();
+        CommentDO commentDO = new CommentDO();
+        BeanUtils.copyProperties(query, commentDO);
+        commentDO.setIsReply(ExpireTypeEnum.YES.getType());
+        commentDO.setReplyTime(replyTime);
+        commentDO.setUpdateTime(replyTime);
+
+        return commentDOMapper.updateByPrimaryKeySelective(commentDO) > 0;
+    }
+
+    @Override
+    public boolean delete(Integer id) {
+        CommentDOExample example = new CommentDOExample();
+        example.createCriteria()
+                .andIdEqualTo(id)
+                .andIsDeleteEqualTo(ExpireTypeEnum.NO.getType());
+        CommentDO commentDO = new CommentDO();
+        commentDO.setIsDelete(ExpireTypeEnum.YES.getType());
+        commentDO.setUpdateTime(new Date());
+
+        return commentDOMapper.updateByExampleSelective(commentDO, example) > 0;
+    }
+
+    @Override
+    public int autoReply(String replyContent) {
+        CommentDOExample example = new CommentDOExample();
+        example.createCriteria()
+                .andIsReplyEqualTo(ExpireTypeEnum.NO.getType())
+                .andServiceScoreGreaterThanOrEqualTo(3)
+                .andTasteScoreGreaterThanOrEqualTo(3)
+                .andEnvironmentScoreGreaterThanOrEqualTo(3);
+
+        CommentDO record = new CommentDO();
+        record.setReply(replyContent);
+        record.setReplyTime(new Date());
+        record.setIsReply(ExpireTypeEnum.YES.getType());
+        return commentDOMapper.updateByExampleSelective(record, example);
+    }
+
+}

+ 20 - 0
src/main/java/com/cdu/lys/graduation/admin/comment/service/AdminCommentService.java

@@ -0,0 +1,20 @@
+package com.cdu.lys.graduation.admin.comment.service;
+
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.domain.comment.dto.CommentDTO;
+import com.cdu.lys.graduation.types.admin.comment.CommentSearchQuery;
+
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/4/2 11:15
+ */
+public interface AdminCommentService {
+
+    PageResult<List<CommentDTO>> search(CommentSearchQuery query);
+
+    int autoReply();
+
+    int calculateCommentScore();
+}

+ 88 - 0
src/main/java/com/cdu/lys/graduation/admin/comment/service/impl/AdminCommentServiceImpl.java

@@ -0,0 +1,88 @@
+package com.cdu.lys.graduation.admin.comment.service.impl;
+
+import com.cdu.lys.graduation.admin.comment.bo.AdminCommentBO;
+import com.cdu.lys.graduation.admin.comment.service.AdminCommentService;
+import com.cdu.lys.graduation.admin.merchant.bo.MerchantBO;
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.commons.utils.DateUtils;
+import com.cdu.lys.graduation.domain.admin.dto.CommentSearchDTO;
+import com.cdu.lys.graduation.domain.comment.dto.CommentDTO;
+import com.cdu.lys.graduation.repository.entity.CommentDO;
+import com.cdu.lys.graduation.repository.entity.MerchantDO;
+import com.cdu.lys.graduation.types.SwitchTypeEnum;
+import com.cdu.lys.graduation.types.admin.comment.CommentSearchQuery;
+import com.github.pagehelper.Page;
+import com.github.pagehelper.PageHelper;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.text.DecimalFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/4/2 11:15
+ */
+@Service
+public class AdminCommentServiceImpl implements AdminCommentService {
+
+    @Autowired
+    private AdminCommentBO adminCommentBO;
+
+    @Autowired
+    private MerchantBO merchantBO;
+
+    @Override
+    public PageResult<List<CommentDTO>> search(CommentSearchQuery query) {
+        Page<Object> page = PageHelper.startPage(query.getPageNo(), query.getPageSize());
+        CommentSearchDTO commentSearchDTO = new CommentSearchDTO();
+        BeanUtils.copyProperties(query, commentSearchDTO);
+        List<CommentDTO> commentDTOList = adminCommentBO.search(commentSearchDTO);
+
+        PageResult<List<CommentDTO>> pageResult = new PageResult<>(commentDTOList);
+        pageResult.setPageNum(page.getPageNum());
+        pageResult.setPageSize(page.getPageSize());
+        pageResult.setTotal(page.getTotal());
+        pageResult.setPages(page.getPages());
+
+        return pageResult;
+    }
+
+    @Override
+    public int autoReply() {
+        MerchantDO merchantDO = merchantBO.get();
+        String isAutoReply = merchantDO.getIsAutoReply();
+
+        //开启自动回复
+        if (SwitchTypeEnum.ON.getContent().equals(isAutoReply)) {
+            return adminCommentBO.autoReply(merchantDO.getAutoReplyContent());
+        }
+        return 0;
+    }
+
+    @Override
+    public int calculateCommentScore() {
+        Date monthBefore = DateUtils.add(new Date(), Calendar.MONTH, -1);
+        List<CommentDO> commentDOList = adminCommentBO.getCommentBeforeDate(monthBefore);
+
+        //(总星/订单数*15)*5
+        double rate = 5.0;
+        if (!CollectionUtils.isEmpty(commentDOList)) {
+            int scores = 0;
+            for (CommentDO commentDO : commentDOList) {
+                scores += (commentDO.getTasteScore() + commentDO.getServiceScore() + commentDO.getEnvironmentScore());
+            }
+            rate = (scores * 1.0 / (commentDOList.size() * 15)) * 5;
+        }
+
+        DecimalFormat format = new DecimalFormat("0.0");
+
+        MerchantDO merchantDO = new MerchantDO();
+        merchantDO.setScore(Double.valueOf(format.format(rate)));
+        return merchantBO.update(merchantDO);
+    }
+}

+ 31 - 0
src/main/java/com/cdu/lys/graduation/admin/coupon/bo/AdminCouponBO.java

@@ -0,0 +1,31 @@
+package com.cdu.lys.graduation.admin.coupon.bo;
+
+import com.cdu.lys.graduation.repository.entity.CouponDO;
+import com.cdu.lys.graduation.types.admin.coupon.CouponQuery;
+import com.cdu.lys.graduation.types.admin.coupon.CouponSearchQuery;
+import com.cdu.lys.graduation.types.admin.coupon.CouponUpdateQuery;
+
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/20 17:04
+ */
+public interface AdminCouponBO {
+
+    List<CouponDO> selectCoupons();
+
+    CouponDO getCouponById(Integer couponId);
+
+    int updateCoupon(CouponUpdateQuery coupon);
+
+    int deleteCoupon(Integer couponId);
+
+    int addCoupon(CouponQuery query);
+
+    List<CouponDO> search(CouponSearchQuery query);
+
+    List<CouponDO> searchByUserType(Integer userType);
+
+    List<CouponDO> searchByName(String couponName);
+}

+ 124 - 0
src/main/java/com/cdu/lys/graduation/admin/coupon/bo/impl/AdminCouponBOImpl.java

@@ -0,0 +1,124 @@
+package com.cdu.lys.graduation.admin.coupon.bo.impl;
+
+import com.cdu.lys.graduation.admin.coupon.bo.AdminCouponBO;
+import com.cdu.lys.graduation.repository.dao.CouponDOMapper;
+import com.cdu.lys.graduation.repository.entity.CouponDO;
+import com.cdu.lys.graduation.repository.entity.CouponDOExample;
+import com.cdu.lys.graduation.types.admin.coupon.CouponQuery;
+import com.cdu.lys.graduation.types.admin.coupon.CouponSearchQuery;
+import com.cdu.lys.graduation.types.admin.coupon.CouponUpdateQuery;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/20 17:04
+ */
+@Service
+public class AdminCouponBOImpl implements AdminCouponBO {
+
+    @Autowired
+    private CouponDOMapper couponDOMapper;
+
+    @Override
+    public List<CouponDO> selectCoupons() {
+        CouponDOExample example = new CouponDOExample();
+        example.createCriteria()
+                .andDeadlineGreaterThan(new Date())
+                .andNumberGreaterThan(0)
+                .andIsDeleteEqualTo("n");
+
+        return couponDOMapper.selectByExample(example);
+    }
+
+    @Override
+    public CouponDO getCouponById(Integer couponId) {
+        CouponDOExample example = new CouponDOExample();
+        example.createCriteria()
+                .andIdEqualTo(couponId)
+                .andIsDeleteEqualTo("n");
+
+        return couponDOMapper.selectByExample(example).get(0);
+    }
+
+    @Override
+    public int updateCoupon(CouponUpdateQuery coupon) {
+        CouponDO couponDO = new CouponDO();
+        BeanUtils.copyProperties(coupon, couponDO);
+        couponDO.setUpdateTime(new Date());
+
+        return couponDOMapper.updateByPrimaryKeySelective(couponDO);
+    }
+
+    @Override
+    public int deleteCoupon(Integer couponId) {
+        CouponDO couponDO = new CouponDO();
+        couponDO.setId(couponId);
+        couponDO.setUpdateTime(new Date());
+        couponDO.setIsDelete("y");
+
+        return couponDOMapper.updateByPrimaryKeySelective(couponDO);
+    }
+
+    @Override
+    public int addCoupon(CouponQuery query) {
+        CouponDO couponDO = new CouponDO();
+        BeanUtils.copyProperties(query, couponDO);
+        couponDO.setCreateTime(new Date());
+        int i=couponDOMapper.insertSelective(couponDO);
+        return i;
+    }
+
+    @Override
+    public List<CouponDO> search(CouponSearchQuery query) {
+        CouponDOExample example = new CouponDOExample();
+        CouponDOExample.Criteria criteria = example.createCriteria();
+
+        String couponName = query.getCouponName();
+        Integer userType = query.getUserType();
+
+        if (StringUtils.hasText(couponName)) {
+            criteria.andCouponNameLike("%"+couponName+"%");
+        }
+
+        if (userType != null) {
+            criteria.andUserTypeEqualTo(userType);
+        }
+
+        criteria.andDeadlineGreaterThan(new Date())
+                .andNumberGreaterThan(0)
+                .andIsDeleteEqualTo("n");
+
+        return couponDOMapper.selectByExample(example);
+    }
+
+    @Override
+    public List<CouponDO> searchByUserType(Integer userType) {
+        CouponDOExample example = new CouponDOExample();
+        example.createCriteria()
+                .andUserTypeEqualTo(userType)
+                .andDeadlineGreaterThan(new Date())
+                .andNumberGreaterThan(0)
+                .andIsDeleteEqualTo("n");
+
+        return couponDOMapper.selectByExample(example);
+    }
+
+    @Override
+    public List<CouponDO> searchByName(String couponName) {
+        CouponDOExample example = new CouponDOExample();
+        example.createCriteria()
+                .andCouponNameEqualTo(couponName)
+                .andDeadlineGreaterThan(new Date())
+                .andNumberGreaterThan(0)
+                .andIsDeleteEqualTo("n");
+
+        return couponDOMapper.selectByExample(example);
+    }
+
+}

+ 19 - 0
src/main/java/com/cdu/lys/graduation/admin/coupon/service/AdminCouponService.java

@@ -0,0 +1,19 @@
+package com.cdu.lys.graduation.admin.coupon.service;
+
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.repository.entity.CouponDO;
+import com.cdu.lys.graduation.types.PageQuery;
+import com.cdu.lys.graduation.types.admin.coupon.CouponSearchQuery;
+
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/20 17:00
+ */
+public interface AdminCouponService {
+
+    PageResult<List<CouponDO>> getCouponList(PageQuery query);
+
+    PageResult<List<CouponDO>> searchCoupon(CouponSearchQuery query);
+}

+ 55 - 0
src/main/java/com/cdu/lys/graduation/admin/coupon/service/impl/AdminCouponServiceImpl.java

@@ -0,0 +1,55 @@
+package com.cdu.lys.graduation.admin.coupon.service.impl;
+
+import com.cdu.lys.graduation.admin.coupon.bo.AdminCouponBO;
+import com.cdu.lys.graduation.admin.coupon.service.AdminCouponService;
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.repository.entity.CouponDO;
+import com.cdu.lys.graduation.types.PageQuery;
+import com.cdu.lys.graduation.types.admin.coupon.CouponSearchQuery;
+import com.github.pagehelper.Page;
+import com.github.pagehelper.PageHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/20 17:01
+ */
+@Service
+public class AdminCouponServiceImpl implements AdminCouponService {
+
+    @Autowired
+    private AdminCouponBO adminCouponBO;
+
+    @Override
+    public PageResult<List<CouponDO>> getCouponList(PageQuery query) {
+        Page<Object> page = PageHelper.startPage(query.getPageNo(), query.getPageSize());
+
+        List<CouponDO> couponDOS = adminCouponBO.selectCoupons();
+
+        PageResult<List<CouponDO>> pageResult = new PageResult<>(couponDOS);
+        pageResult.setPageNum(page.getPageNum());
+        pageResult.setPageSize(page.getPageSize());
+        pageResult.setTotal(page.getTotal());
+        pageResult.setPages(page.getPages());
+
+        return pageResult;
+    }
+
+    @Override
+    public PageResult<List<CouponDO>> searchCoupon(CouponSearchQuery query) {
+        Page<Object> page = PageHelper.startPage(query.getPageNo(), query.getPageSize());
+
+        List<CouponDO> couponDOS = adminCouponBO.search(query);
+
+        PageResult<List<CouponDO>> pageResult = new PageResult<>(couponDOS);
+        pageResult.setPageNum(page.getPageNum());
+        pageResult.setPageSize(page.getPageSize());
+        pageResult.setTotal(page.getTotal());
+        pageResult.setPages(page.getPages());
+
+        return pageResult;
+    }
+}

+ 81 - 0
src/main/java/com/cdu/lys/graduation/admin/goods/bo/AdminGoodsBO.java

@@ -0,0 +1,81 @@
+package com.cdu.lys.graduation.admin.goods.bo;
+
+import com.cdu.lys.graduation.repository.entity.GoodsDO;
+import com.cdu.lys.graduation.repository.entity.GoodsPictureDO;
+import com.cdu.lys.graduation.types.admin.goods.GoodsQuery;
+import com.cdu.lys.graduation.types.admin.goods.Picture;
+import com.cdu.lys.graduation.types.admin.goods.UpdateGoodsQuery;
+import com.cdu.lys.graduation.types.admin.goods.type.GoodsSearchQuery;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/19 11:36
+ */
+public interface AdminGoodsBO {
+
+    /**
+     * 查询所有商品
+     * @return 商品列表
+     */
+    List<GoodsDO> selectGoods();
+
+    /**
+     * 查询商品图片
+     * @param goodsId 商品id
+     * @return 图片
+     */
+    List<GoodsPictureDO> getGoodsPicturesById(Integer goodsId);
+
+    /**
+     * 删除商品(修改is_delete)
+     * @param goodsId 商品id
+     * @return rows
+     */
+    int deleteGoodsByGoodsId(Integer goodsId);
+
+    /**
+     * 添加商品
+     * @param goods 商品
+     * @return i
+     */
+    int addGoods(GoodsQuery goods);
+
+    /**
+     * 添加商品图片图片
+     * @param pictures 图片
+     * @param goodsId 商品id
+     * @return 0
+     */
+    int addGoodsPictures(List<Picture> pictures, Integer goodsId);
+
+    /**
+     * 删除商品所有的图片
+     * @param goodsId 商品id
+     * @return i
+     */
+    int deleteGoodsPictures(Integer goodsId);
+
+    /**
+     * 修改商品
+     * @param goods
+     * @return
+     */
+    int updateGoods(UpdateGoodsQuery goods);
+
+    /**
+     * 搜索
+     * @param query 条件
+     * @return 商品集合
+     */
+    List<GoodsDO> search(GoodsSearchQuery query);
+
+    /**
+     * 根据goodsId更新评分
+     * @param scores k:goodsId,v:score
+     * @return i
+     */
+    int updateGoodsScore(Map<Integer,Double> scores);
+}

+ 19 - 0
src/main/java/com/cdu/lys/graduation/admin/goods/bo/AdminGoodsOptionBO.java

@@ -0,0 +1,19 @@
+package com.cdu.lys.graduation.admin.goods.bo;
+
+import com.cdu.lys.graduation.domain.admin.vo.AdminGoodsOption;
+import com.cdu.lys.graduation.types.admin.goods.option.GoodsOptionQuery;
+
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/26 19:26
+ */
+public interface AdminGoodsOptionBO {
+
+    List<AdminGoodsOption> selectAll();
+
+    List<AdminGoodsOption> search(String goodsName);
+
+    int addGoodsOption(GoodsOptionQuery query);
+}

+ 24 - 0
src/main/java/com/cdu/lys/graduation/admin/goods/bo/AdminGoodsTypeBO.java

@@ -0,0 +1,24 @@
+package com.cdu.lys.graduation.admin.goods.bo;
+
+import com.cdu.lys.graduation.repository.entity.GoodsTypeDO;
+import com.cdu.lys.graduation.types.admin.goods.type.GoodsTypeQuery;
+import com.cdu.lys.graduation.types.admin.goods.type.GoodsTypeUpdateQuery;
+
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/24 23:11
+ */
+public interface AdminGoodsTypeBO {
+
+    List<GoodsTypeDO> getAll();
+
+    int updateById(GoodsTypeUpdateQuery query);
+
+    int add(GoodsTypeQuery query);
+
+    int delete(Integer id);
+
+    List<GoodsTypeDO> searchByType(String type);
+}

+ 171 - 0
src/main/java/com/cdu/lys/graduation/admin/goods/bo/impl/AdminGoodsBOImpl.java

@@ -0,0 +1,171 @@
+package com.cdu.lys.graduation.admin.goods.bo.impl;
+
+import com.cdu.lys.graduation.admin.goods.bo.AdminGoodsBO;
+import com.cdu.lys.graduation.repository.dao.GoodsDOMapper;
+import com.cdu.lys.graduation.repository.dao.GoodsPictureDOMapper;
+import com.cdu.lys.graduation.repository.dao.ext.GoodsMapperExt;
+import com.cdu.lys.graduation.repository.entity.GoodsDO;
+import com.cdu.lys.graduation.repository.entity.GoodsDOExample;
+import com.cdu.lys.graduation.repository.entity.GoodsPictureDO;
+import com.cdu.lys.graduation.repository.entity.GoodsPictureDOExample;
+import com.cdu.lys.graduation.types.ExpireTypeEnum;
+import com.cdu.lys.graduation.types.admin.goods.GoodsQuery;
+import com.cdu.lys.graduation.types.admin.goods.Picture;
+import com.cdu.lys.graduation.types.admin.goods.UpdateGoodsQuery;
+import com.cdu.lys.graduation.types.admin.goods.type.GoodsSearchQuery;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/19 11:37
+ */
+@Service
+public class AdminGoodsBOImpl implements AdminGoodsBO {
+
+    @Autowired
+    private GoodsDOMapper goodsDOMapper;
+
+    @Autowired
+    private GoodsPictureDOMapper goodsPictureDOMapper;
+
+    @Autowired
+    private GoodsMapperExt goodsMapperExt;
+
+    @Override
+    public List<GoodsDO> selectGoods() {
+        GoodsDOExample example = new GoodsDOExample();
+        example.createCriteria()
+                .andIsDeleteEqualTo("n");
+
+        return goodsDOMapper.selectByExample(example);
+    }
+
+    @Override
+    public List<GoodsPictureDO> getGoodsPicturesById(Integer goodsId) {
+        GoodsPictureDOExample example = new GoodsPictureDOExample();
+        example.createCriteria()
+                .andGoodsIdEqualTo(goodsId)
+                .andIsDeleteEqualTo("n");
+
+        return goodsPictureDOMapper.selectByExample(example);
+    }
+
+    @Override
+    public int deleteGoodsByGoodsId(Integer goodsId) {
+        GoodsDOExample example = new GoodsDOExample();
+        example.createCriteria()
+                .andIdEqualTo(goodsId)
+                .andIsDeleteEqualTo("n");
+
+        GoodsDO goodsDO = new GoodsDO();
+        goodsDO.setUpdateTime(new Date());
+        goodsDO.setIsDelete("y");
+
+        return goodsDOMapper.updateByExampleSelective(goodsDO, example);
+    }
+
+    @Override
+    public int addGoods(GoodsQuery goods) {
+        Date createTime = new Date();
+
+        GoodsDO goodsDO = new GoodsDO();
+        BeanUtils.copyProperties(goods, goodsDO);
+        goodsDO.setCreateTime(createTime);
+        goodsDO.setUpdateTime(createTime);
+
+        goodsDOMapper.insertSelective(goodsDO);
+        return goodsDO.getId();
+    }
+
+    @Override
+    public int addGoodsPictures(List<Picture> pictures, Integer goodsId) {
+        if (CollectionUtils.isEmpty(pictures)) {
+            return 0;
+        }
+        Date createTime = new Date();
+        pictures.forEach(picture -> {
+            GoodsPictureDO goodsPictureDO = new GoodsPictureDO();
+            BeanUtils.copyProperties(picture, goodsPictureDO);
+            goodsPictureDO.setGoodsId(goodsId);
+            goodsPictureDO.setCreateTime(createTime);
+            goodsPictureDO.setUpdateTime(createTime);
+            goodsPictureDOMapper.insertSelective(goodsPictureDO);
+        });
+        return 0;
+    }
+
+    @Override
+    public int deleteGoodsPictures(Integer goodsId) {
+        GoodsPictureDOExample example = new GoodsPictureDOExample();
+        example.createCriteria()
+                .andGoodsIdEqualTo(goodsId);
+        GoodsPictureDO goodsPictureDO = new GoodsPictureDO();
+        goodsPictureDO.setIsDelete(ExpireTypeEnum.YES.getType());
+        goodsPictureDO.setUpdateTime(new Date());
+        return goodsPictureDOMapper.updateByExampleSelective(goodsPictureDO, example);
+    }
+
+    @Override
+    public int updateGoods(UpdateGoodsQuery goods) {
+        GoodsDO goodsDO = new GoodsDO();
+        BeanUtils.copyProperties(goods, goodsDO);
+        goodsDO.setUpdateTime(new Date());
+
+        return goodsDOMapper.updateByPrimaryKeySelective(goodsDO);
+    }
+
+    @Override
+    public List<GoodsDO> search(GoodsSearchQuery query) {
+        GoodsDOExample example = new GoodsDOExample();
+        GoodsDOExample.Criteria criteria = example.createCriteria();
+
+        if (StringUtils.hasLength(query.getGoodsName())) {
+            criteria.andGoodsNameEqualTo(query.getGoodsName());
+        }
+
+        if (StringUtils.hasLength(query.getTaste())) {
+            criteria.andTasteLike("%" + query.getTaste() + "%");
+        }
+
+        if (Objects.nonNull(query.getGoodsType())) {
+            criteria.andGoodsTypeEqualTo(query.getGoodsType());
+        }
+
+        if (Objects.nonNull(query.getMinPrice())) {
+            criteria.andPriceGreaterThan(query.getMinPrice());
+        }
+
+        if (Objects.nonNull(query.getMaxPrice())) {
+            criteria.andPriceLessThan(query.getMaxPrice());
+        }
+
+        if (Objects.nonNull(query.getMinCost())) {
+            criteria.andCostGreaterThan(query.getMinCost());
+        }
+
+        if (Objects.nonNull(query.getMaxCost())) {
+            criteria.andCostLessThanOrEqualTo(query.getMaxCost());
+        }
+
+        criteria.andIsDeleteEqualTo("n");
+        return goodsDOMapper.selectByExample(example);
+    }
+
+    @Override
+    public int updateGoodsScore(Map<Integer, Double> scores) {
+        if (CollectionUtils.isEmpty(scores)) {
+            return 0;
+        }
+        return goodsMapperExt.updateScoreByGoodsIds(scores);
+    }
+
+}

+ 133 - 0
src/main/java/com/cdu/lys/graduation/admin/goods/bo/impl/AdminGoodsOptionBOImpl.java

@@ -0,0 +1,133 @@
+package com.cdu.lys.graduation.admin.goods.bo.impl;
+
+import com.cdu.lys.graduation.admin.goods.bo.AdminGoodsOptionBO;
+import com.cdu.lys.graduation.domain.admin.vo.AdminGoodsOption;
+import com.cdu.lys.graduation.repository.dao.GoodsDOMapper;
+import com.cdu.lys.graduation.repository.dao.GoodsOptionDOMapper;
+import com.cdu.lys.graduation.repository.dao.GoodsOptionItemDOMapper;
+import com.cdu.lys.graduation.repository.entity.*;
+import com.cdu.lys.graduation.types.admin.goods.option.GoodsOptionQuery;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/26 19:27
+ */
+@Service
+public class AdminGoodsOptionBOImpl implements AdminGoodsOptionBO {
+
+    @Autowired
+    private GoodsOptionDOMapper goodsOptionDOMapper;
+
+    @Autowired
+    private GoodsOptionItemDOMapper goodsOptionItemDOMapper;
+
+    @Autowired
+    private GoodsDOMapper goodsDOMapper;
+
+    @Override
+    public List<AdminGoodsOption> selectAll() {
+
+        GoodsDOExample example = new GoodsDOExample();
+        example.createCriteria()
+                .andIsDeleteEqualTo("n");
+
+
+        List<GoodsDO> goodsDOS = goodsDOMapper.selectByExample(example);
+
+        return this.getResult(goodsDOS);
+    }
+
+    @Override
+    public List<AdminGoodsOption> search(String goodsName) {
+        GoodsDOExample example = new GoodsDOExample();
+        example.createCriteria()
+                .andGoodsNameEqualTo(goodsName)
+                .andIsDeleteEqualTo("n");
+
+        List<GoodsDO> goodsDOS = goodsDOMapper.selectByExample(example);
+
+        return this.getResult(goodsDOS);
+    }
+
+    /**
+     * 得到结果
+     * @param goodsDOS 商品列表
+     * @return 结果
+     */
+    private List<AdminGoodsOption> getResult(List<GoodsDO> goodsDOS) {
+        if (CollectionUtils.isEmpty(goodsDOS)) {
+            return null;
+        }
+        List<AdminGoodsOption> result = new ArrayList<>();
+
+        goodsDOS.forEach(goodsDO -> {
+            AdminGoodsOption adminGoodsOption = new AdminGoodsOption();
+
+            GoodsOptionDOExample optionDOExample = new GoodsOptionDOExample();
+            GoodsOptionDOExample.Criteria criteria = optionDOExample.createCriteria();
+            criteria.andGoodsIdEqualTo(goodsDO.getId())
+                    .andIsDeleteEqualTo("n");
+
+            BeanUtils.copyProperties(goodsDO, adminGoodsOption);
+            List<GoodsOptionDO> goodsOptionDOS = goodsOptionDOMapper.selectByExample(optionDOExample);
+            adminGoodsOption.setGoodsId(goodsDO.getId());
+            adminGoodsOption.setGoodsOptionText(this.getOptionText(goodsOptionDOS));
+
+            result.add(adminGoodsOption);
+        });
+        return result;
+    }
+
+    @Override
+    public int addGoodsOption(GoodsOptionQuery query) {
+
+        GoodsOptionDO goodsOptionDO = new GoodsOptionDO();
+        goodsOptionDO.setGoodsId(query.getGoodsId());
+        goodsOptionDO.setOptionName(query.getOptionName());
+        Date createTime = new Date();
+        goodsOptionDO.setCreateTime(createTime);
+        goodsOptionDO.setUpdateTime(createTime);
+
+        int i = goodsOptionDOMapper.insertSelective(goodsOptionDO);
+
+        query.getOptionItems().forEach(item->{
+            GoodsOptionItemDO record = new GoodsOptionItemDO();
+            record.setOptionId(goodsOptionDO.getId());
+            if (item.getExtraPrice() != null) {
+                record.setExtraPrice(item.getExtraPrice());
+            }
+            if (StringUtils.hasLength(item.getOptionItem())) {
+                record.setOptionItem(item.getOptionItem());
+                record.setCreateTime(createTime);
+                record.setUpdateTime(createTime);
+                goodsOptionItemDOMapper.insertSelective(record);
+            }
+        });
+
+        return i;
+    }
+
+    private String getOptionText(List<GoodsOptionDO> goodsOptionDOS) {
+
+        StringBuilder sb = new StringBuilder();
+
+        for (GoodsOptionDO goodsOptionDO : goodsOptionDOS) {
+            sb.append(goodsOptionDO.getOptionName());
+            sb.append(",");
+        }
+        if (sb.length() > 0) {
+            sb.deleteCharAt(sb.length() - 1);
+        }
+        return sb.toString();
+    }
+
+}

+ 74 - 0
src/main/java/com/cdu/lys/graduation/admin/goods/bo/impl/AdminGoodsTypeBOImpl.java

@@ -0,0 +1,74 @@
+package com.cdu.lys.graduation.admin.goods.bo.impl;
+
+import com.cdu.lys.graduation.admin.goods.bo.AdminGoodsTypeBO;
+import com.cdu.lys.graduation.repository.dao.GoodsTypeDOMapper;
+import com.cdu.lys.graduation.repository.entity.GoodsTypeDO;
+import com.cdu.lys.graduation.repository.entity.GoodsTypeDOExample;
+import com.cdu.lys.graduation.types.admin.goods.type.GoodsTypeQuery;
+import com.cdu.lys.graduation.types.admin.goods.type.GoodsTypeUpdateQuery;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/24 23:11
+ */
+@Service
+public class AdminGoodsTypeBOImpl implements AdminGoodsTypeBO {
+
+    @Autowired
+    private GoodsTypeDOMapper goodsTypeDOMapper;
+
+    @Override
+    public List<GoodsTypeDO> getAll() {
+        GoodsTypeDOExample example = new GoodsTypeDOExample();
+        example.createCriteria()
+                .andIsDeleteEqualTo("n");
+
+        return goodsTypeDOMapper.selectByExample(example);
+    }
+
+    @Override
+    public int updateById(GoodsTypeUpdateQuery query) {
+        GoodsTypeDO goodsTypeDO = new GoodsTypeDO();
+        goodsTypeDO.setId(query.getId());
+        goodsTypeDO.setUpdateTime(new Date());
+        goodsTypeDO.setType(query.getType());
+
+        return goodsTypeDOMapper.updateByPrimaryKeySelective(goodsTypeDO);
+    }
+
+    @Override
+    public int add(GoodsTypeQuery query) {
+        GoodsTypeDO goodsTypeDO = new GoodsTypeDO();
+        goodsTypeDO.setCreateTime(new Date());
+        goodsTypeDO.setType(query.getType());
+
+        return goodsTypeDOMapper.insertSelective(goodsTypeDO);
+    }
+
+    @Override
+    public int delete(Integer id) {
+        GoodsTypeDOExample example = new GoodsTypeDOExample();
+        example.createCriteria()
+                .andIdEqualTo(id);
+        GoodsTypeDO goodsTypeDO = new GoodsTypeDO();
+        goodsTypeDO.setUpdateTime(new Date());
+        goodsTypeDO.setIsDelete("y");
+
+        return goodsTypeDOMapper.updateByExampleSelective(goodsTypeDO, example);
+    }
+
+    @Override
+    public List<GoodsTypeDO> searchByType(String type) {
+        GoodsTypeDOExample example = new GoodsTypeDOExample();
+        example.createCriteria()
+                .andTypeEqualTo(type);
+
+        return goodsTypeDOMapper.selectByExample(example);
+    }
+
+}

+ 49 - 0
src/main/java/com/cdu/lys/graduation/admin/goods/convertor/GoodsConverter.java

@@ -0,0 +1,49 @@
+package com.cdu.lys.graduation.admin.goods.convertor;
+
+import com.cdu.lys.graduation.admin.goods.bo.AdminGoodsTypeBO;
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.domain.admin.vo.AdminGoodsVO;
+import com.cdu.lys.graduation.repository.entity.GoodsDO;
+import com.cdu.lys.graduation.repository.entity.GoodsTypeDO;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/26 16:41
+ */
+@Component
+public class GoodsConverter {
+
+    @Autowired
+    private AdminGoodsTypeBO adminGoodsTypeBO;
+
+    public PageResult<List<AdminGoodsVO>> convert2GoodsPageVo(PageResult<List<GoodsDO>> pageResult) {
+        PageResult<List<AdminGoodsVO>> result = new PageResult<>();
+        List<AdminGoodsVO> goodsVOS = new ArrayList<>();
+
+        List<GoodsTypeDO> types = adminGoodsTypeBO.getAll();
+        List<GoodsDO> goods = pageResult.getData();
+        goods.forEach(goodsDO -> {
+            AdminGoodsVO adminGoodsVO = new AdminGoodsVO();
+            BeanUtils.copyProperties(goodsDO, adminGoodsVO);
+            List<GoodsTypeDO> collect = types.stream()
+                    .filter(goodsTypeDO -> goodsTypeDO.getId().equals(goodsDO.getGoodsType()))
+                    .collect(Collectors.toList());
+            if (!CollectionUtils.isEmpty(collect)) {
+                adminGoodsVO.setGoodsType(collect.get(0).getType());
+            }
+            goodsVOS.add(adminGoodsVO);
+        });
+
+        BeanUtils.copyProperties(pageResult, result);
+        result.setData(goodsVOS);
+        return result;
+    }
+}

+ 19 - 0
src/main/java/com/cdu/lys/graduation/admin/goods/service/AdminGoodsOptionService.java

@@ -0,0 +1,19 @@
+package com.cdu.lys.graduation.admin.goods.service;
+
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.domain.admin.vo.AdminGoodsOption;
+import com.cdu.lys.graduation.types.PageQuery;
+import com.cdu.lys.graduation.types.admin.goods.option.GoodsOptionSearchQuery;
+
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/26 19:20
+ */
+public interface AdminGoodsOptionService {
+
+    PageResult<List<AdminGoodsOption>> getAllOptions(PageQuery query);
+
+    PageResult<List<AdminGoodsOption>> search(GoodsOptionSearchQuery query);
+}

+ 59 - 0
src/main/java/com/cdu/lys/graduation/admin/goods/service/AdminGoodsService.java

@@ -0,0 +1,59 @@
+package com.cdu.lys.graduation.admin.goods.service;
+
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.repository.entity.GoodsDO;
+import com.cdu.lys.graduation.types.PageQuery;
+import com.cdu.lys.graduation.types.admin.goods.GoodsQuery;
+import com.cdu.lys.graduation.types.admin.goods.UpdateGoodsQuery;
+import com.cdu.lys.graduation.types.admin.goods.type.GoodsSearchQuery;
+
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/19 11:32
+ */
+public interface AdminGoodsService {
+
+    /**
+     * 商品列表分页查询
+     *
+     * @param query 分页请求
+     * @return 分页数据
+     */
+    PageResult<List<GoodsDO>> getGoodsList(PageQuery query);
+
+    /**
+     * 删除商品
+     * @param goodsId 商品id
+     * @return 结果
+     */
+    boolean deleteGoods(Integer goodsId);
+
+    /**
+     * 添加商品
+     * @param goods 商品
+     * @return id
+     */
+    int addGoods(GoodsQuery goods);
+
+    /**
+     * 修改商品
+     * @param goods 商品
+     * @return i
+     */
+    int updateGoods(UpdateGoodsQuery goods);
+
+    /**
+     * 搜索
+     * @param query 条件
+     * @return 商品
+     */
+    PageResult<List<GoodsDO>> search(GoodsSearchQuery query);
+
+    /**
+     * 计算商品评分
+     * @return i
+     */
+    int calculateGoodsScore();
+}

+ 16 - 0
src/main/java/com/cdu/lys/graduation/admin/goods/service/AdminGoodsTypeService.java

@@ -0,0 +1,16 @@
+package com.cdu.lys.graduation.admin.goods.service;
+
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.repository.entity.GoodsTypeDO;
+import com.cdu.lys.graduation.types.PageQuery;
+
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/24 23:14
+ */
+public interface AdminGoodsTypeService {
+
+    PageResult<List<GoodsTypeDO>> getGoodsTypeList(PageQuery query);
+}

+ 55 - 0
src/main/java/com/cdu/lys/graduation/admin/goods/service/impl/AdminGoodsOptionServiceImpl.java

@@ -0,0 +1,55 @@
+package com.cdu.lys.graduation.admin.goods.service.impl;
+
+import com.cdu.lys.graduation.admin.goods.bo.AdminGoodsOptionBO;
+import com.cdu.lys.graduation.admin.goods.service.AdminGoodsOptionService;
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.domain.admin.vo.AdminGoodsOption;
+import com.cdu.lys.graduation.types.PageQuery;
+import com.cdu.lys.graduation.types.admin.goods.option.GoodsOptionSearchQuery;
+import com.github.pagehelper.Page;
+import com.github.pagehelper.PageHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/26 19:20
+ */
+@Service
+public class AdminGoodsOptionServiceImpl implements AdminGoodsOptionService {
+
+    @Autowired
+    private AdminGoodsOptionBO adminGoodsOptionBO;
+
+    @Override
+    public PageResult<List<AdminGoodsOption>> getAllOptions(PageQuery query) {
+        Page<Object> page = PageHelper.startPage(query.getPageNo(), query.getPageSize());
+
+        List<AdminGoodsOption> adminGoodsOptions = adminGoodsOptionBO.selectAll();
+
+        PageResult<List<AdminGoodsOption>> pageResult = new PageResult<>(adminGoodsOptions);
+        pageResult.setPageNum(page.getPageNum());
+        pageResult.setPageSize(page.getPageSize());
+        pageResult.setTotal(page.getTotal());
+        pageResult.setPages(page.getPages());
+
+        return pageResult;
+    }
+
+    @Override
+    public PageResult<List<AdminGoodsOption>> search(GoodsOptionSearchQuery query) {
+        Page<Object> page = PageHelper.startPage(query.getPageNo(), query.getPageSize());
+
+        List<AdminGoodsOption> adminGoodsOptions = adminGoodsOptionBO.search(query.getGoodsName());
+
+        PageResult<List<AdminGoodsOption>> pageResult = new PageResult<>(adminGoodsOptions);
+        pageResult.setPageNum(page.getPageNum());
+        pageResult.setPageSize(page.getPageSize());
+        pageResult.setTotal(page.getTotal());
+        pageResult.setPages(page.getPages());
+
+        return pageResult;
+    }
+}

+ 174 - 0
src/main/java/com/cdu/lys/graduation/admin/goods/service/impl/AdminGoodsServiceImpl.java

@@ -0,0 +1,174 @@
+package com.cdu.lys.graduation.admin.goods.service.impl;
+
+import com.cdu.lys.graduation.admin.comment.bo.AdminCommentBO;
+import com.cdu.lys.graduation.admin.goods.bo.AdminGoodsBO;
+import com.cdu.lys.graduation.admin.goods.service.AdminGoodsService;
+import com.cdu.lys.graduation.admin.order.bo.AdminOrderBO;
+import com.cdu.lys.graduation.admin.order.bo.AdminOrderFormInfoBO;
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.commons.utils.DateUtils;
+import com.cdu.lys.graduation.repository.entity.CommentDO;
+import com.cdu.lys.graduation.repository.entity.GoodsDO;
+import com.cdu.lys.graduation.repository.entity.OrderFormDO;
+import com.cdu.lys.graduation.repository.entity.OrderFormInfoDO;
+import com.cdu.lys.graduation.types.ExpireTypeEnum;
+import com.cdu.lys.graduation.types.PageQuery;
+import com.cdu.lys.graduation.types.admin.goods.GoodsQuery;
+import com.cdu.lys.graduation.types.admin.goods.Picture;
+import com.cdu.lys.graduation.types.admin.goods.UpdateGoodsQuery;
+import com.cdu.lys.graduation.types.admin.goods.type.GoodsSearchQuery;
+import com.github.pagehelper.Page;
+import com.github.pagehelper.PageHelper;
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.text.DecimalFormat;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/19 11:33
+ */
+@Service
+public class AdminGoodsServiceImpl implements AdminGoodsService {
+
+    @Autowired
+    private AdminGoodsBO adminGoodsBO;
+
+    @Autowired
+    private AdminOrderFormInfoBO adminOrderFormInfoBO;
+
+    @Autowired
+    private AdminCommentBO adminCommentBO;
+
+    @Autowired
+    private AdminOrderBO adminOrderBO;
+
+    @Override
+    public PageResult<List<GoodsDO>> getGoodsList(PageQuery query) {
+        Page<Object> page = PageHelper.startPage(query.getPageNo(), query.getPageSize());
+
+        List<GoodsDO> goodsDOS = adminGoodsBO.selectGoods();
+
+        PageResult<List<GoodsDO>> pageResult = new PageResult<>(goodsDOS);
+        pageResult.setPageNum(page.getPageNum());
+        pageResult.setPageSize(page.getPageSize());
+        pageResult.setTotal(page.getTotal());
+        pageResult.setPages(page.getPages());
+
+        return pageResult;
+    }
+
+    @Override
+    public boolean deleteGoods(Integer goodsId) {
+        int i = adminGoodsBO.deleteGoodsByGoodsId(goodsId);
+        adminGoodsBO.deleteGoodsPictures(goodsId);
+        return true;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public int addGoods(GoodsQuery goods) {
+
+        int goodsId = adminGoodsBO.addGoods(goods);
+
+        List<Picture> pictures = goods.getPictures();
+        //插入图片
+        adminGoodsBO.addGoodsPictures(pictures, goodsId);
+
+        return goodsId;
+    }
+
+    @Override
+    public int updateGoods(UpdateGoodsQuery goods) {
+        int i = adminGoodsBO.updateGoods(goods);
+        List<Picture> pictures = goods.getPictures();
+        if (!CollectionUtils.isEmpty(pictures)) {
+            //更新图片
+            Integer goodsId = goods.getId();
+            adminGoodsBO.deleteGoodsPictures(goodsId);
+            adminGoodsBO.addGoodsPictures(pictures, goodsId);
+        }
+        return i;
+    }
+
+    @Override
+    public PageResult<List<GoodsDO>> search(GoodsSearchQuery query) {
+        Page<Object> page = PageHelper.startPage(query.getPageNo(), query.getPageSize());
+
+        List<GoodsDO> goodsDOS = adminGoodsBO.search(query);
+
+        PageResult<List<GoodsDO>> pageResult = new PageResult<>(goodsDOS);
+        pageResult.setPageNum(page.getPageNum());
+        pageResult.setPageSize(page.getPageSize());
+        pageResult.setTotal(page.getTotal());
+        pageResult.setPages(page.getPages());
+
+        return pageResult;
+    }
+
+    @Override
+    public int calculateGoodsScore() {
+        Date monthBefore = DateUtils.add(new Date(), Calendar.MONTH, -1);
+        List<CommentDO> commentDOList = adminCommentBO.getCommentBeforeDate(monthBefore);
+        List<OrderFormDO> orderBeforeMonth = adminOrderBO.getOrderBeforeDate(monthBefore);
+        //得到已经评论的订单的订单号集合
+        List<String> collect = orderBeforeMonth.stream()
+                .filter(orderFormDO -> ExpireTypeEnum.YES.getType().equals(orderFormDO.getIsComment()))
+                .map(OrderFormDO::getOrderNum).collect(Collectors.toList());
+        //已评论订单的订单详情
+        List<OrderFormInfoDO> orderInfoList = adminOrderFormInfoBO.getOrderInfoOrderNumIn(collect);
+
+        //计算每个订单评论的总分,key: orderNum, v: sum(score)
+        Map<String, Integer> commentMap = commentDOList.stream()
+                .collect(Collectors.toMap(
+                        CommentDO::getOrderNum,
+                        commentDO -> commentDO.getServiceScore() + commentDO.getTasteScore() + commentDO.getEnvironmentScore()
+                ));
+
+        //统计每个商品的总评分,k:goodsId,v:sum(score),cnt
+        Map<Integer, Count> goodsScoreMap = new HashMap<>();
+        orderInfoList.forEach(orderFormInfoDO -> {
+            Integer goodsId = orderFormInfoDO.getGoodsId();
+            int score = commentMap.get(orderFormInfoDO.getOrderNum()) == null ? 0 : commentMap.get(orderFormInfoDO.getOrderNum());
+
+            Count temp;
+            if ((temp = goodsScoreMap.get(goodsId)) != null) {
+                temp.setCounts(temp.getCounts() + 1);
+                temp.setScore(temp.getScore() + score);
+            } else {
+                temp = new Count();
+                temp.setCounts(1);
+                temp.setScore(score);
+            }
+            goodsScoreMap.put(goodsId, temp);
+        });
+
+        DecimalFormat format = new DecimalFormat("0.0");
+        for (Map.Entry<Integer, Count> entry : goodsScoreMap.entrySet()) {
+            Count value = entry.getValue();
+            //评分转换成5分制
+            double rate = (value.getScore() * 1.0 / (value.getCounts() * 15)) * 5;
+            value.setRate(Double.parseDouble(format.format(rate)));
+        }
+
+        Map<Integer, Double> scoreMap = new HashMap<>();
+        goodsScoreMap.forEach((k, v) -> scoreMap.put(k, v.getRate()));
+        //修改商品评分
+        return adminGoodsBO.updateGoodsScore(scoreMap);
+    }
+}
+
+@Data
+class Count {
+
+    private int score;
+
+    private int counts;
+
+    private double rate;
+}

+ 39 - 0
src/main/java/com/cdu/lys/graduation/admin/goods/service/impl/AdminGoodsTypeServiceImpl.java

@@ -0,0 +1,39 @@
+package com.cdu.lys.graduation.admin.goods.service.impl;
+
+import com.cdu.lys.graduation.admin.goods.bo.AdminGoodsTypeBO;
+import com.cdu.lys.graduation.admin.goods.service.AdminGoodsTypeService;
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.repository.entity.GoodsTypeDO;
+import com.cdu.lys.graduation.types.PageQuery;
+import com.github.pagehelper.Page;
+import com.github.pagehelper.PageHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/24 23:15
+ */
+@Service
+public class AdminGoodsTypeServiceImpl implements AdminGoodsTypeService {
+
+    @Autowired
+    private AdminGoodsTypeBO adminGoodsTypeBO;
+
+    @Override
+    public PageResult<List<GoodsTypeDO>> getGoodsTypeList(PageQuery query) {
+        Page<Object> page = PageHelper.startPage(query.getPageNo(), query.getPageSize());
+
+        List<GoodsTypeDO> goodsTypeDOList = adminGoodsTypeBO.getAll();
+
+        PageResult<List<GoodsTypeDO>> pageResult = new PageResult<>(goodsTypeDOList);
+        pageResult.setPageNum(page.getPageNum());
+        pageResult.setPageSize(page.getPageSize());
+        pageResult.setTotal(page.getTotal());
+        pageResult.setPages(page.getPages());
+
+        return pageResult;
+    }
+}

+ 17 - 0
src/main/java/com/cdu/lys/graduation/admin/login/bo/AdminBO.java

@@ -0,0 +1,17 @@
+package com.cdu.lys.graduation.admin.login.bo;
+
+import com.cdu.lys.graduation.repository.entity.UserDO;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/16 18:58
+ */
+public interface AdminBO {
+
+    /**
+     * 查询管理员用户
+     * @param username 用户名
+     * @return 管理员用户
+     */
+    UserDO selectAdminUserByName(String username);
+}

+ 37 - 0
src/main/java/com/cdu/lys/graduation/admin/login/bo/impl/AdminBOImpl.java

@@ -0,0 +1,37 @@
+package com.cdu.lys.graduation.admin.login.bo.impl;
+
+import com.cdu.lys.graduation.admin.login.bo.AdminBO;
+import com.cdu.lys.graduation.repository.dao.UserDOMapper;
+import com.cdu.lys.graduation.repository.entity.UserDO;
+import com.cdu.lys.graduation.repository.entity.UserDOExample;
+import com.cdu.lys.graduation.types.user.UserTypeEnum;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/16 18:58
+ */
+@Service
+public class AdminBOImpl implements AdminBO {
+
+    @Autowired
+    private UserDOMapper userDOMapper;
+
+    @Override
+    public UserDO selectAdminUserByName(String username) {
+        UserDOExample example = new UserDOExample();
+        example.createCriteria()
+                .andUsernameEqualTo(username)
+                .andTypeEqualTo(UserTypeEnum.ADMIN_USER.getCode())
+                .andIsDeleteEqualTo("n");
+
+        List<UserDO> userDOList = userDOMapper.selectByExample(example);
+
+        return CollectionUtils.isEmpty(userDOList) ? null : userDOList.get(0);
+    }
+
+}

+ 18 - 0
src/main/java/com/cdu/lys/graduation/admin/login/service/AdminLoginService.java

@@ -0,0 +1,18 @@
+package com.cdu.lys.graduation.admin.login.service;
+
+import com.cdu.lys.graduation.domain.user.dto.UserDTO;
+import com.cdu.lys.graduation.types.user.LoginQuery;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/16 18:37
+ */
+public interface AdminLoginService {
+
+    /**
+     * 管理系统登录
+     * @param query
+     * @return 登录结果
+     */
+    UserDTO login(LoginQuery query);
+}

+ 53 - 0
src/main/java/com/cdu/lys/graduation/admin/login/service/impl/AdminLoginServiceImpl.java

@@ -0,0 +1,53 @@
+package com.cdu.lys.graduation.admin.login.service.impl;
+
+import com.cdu.lys.graduation.admin.login.bo.AdminBO;
+import com.cdu.lys.graduation.admin.login.service.AdminLoginService;
+import com.cdu.lys.graduation.domain.user.dto.UserDTO;
+import com.cdu.lys.graduation.repository.entity.UserDO;
+import com.cdu.lys.graduation.types.user.LoginQuery;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/16 18:38
+ */
+@Service
+public class AdminLoginServiceImpl implements AdminLoginService {
+
+    @Autowired
+    private AdminBO adminBO;
+
+    @Override
+    public UserDTO login(LoginQuery query) {
+        UserDO userDO = adminBO.selectAdminUserByName(query.getUsername());
+
+        //没有该管理员
+        if (userDO == null) {
+            return null;
+        }
+        String encryptedPassword = encryptPassword(query.getPassword(), userDO.getSalt());
+        //密码错误
+        if (!encryptedPassword.equals(userDO.getPassword())) {
+            return null;
+        }
+        UserDTO userDTO = new UserDTO();
+        BeanUtils.copyProperties(userDO, userDTO);
+
+        return userDTO;
+    }
+
+    /**
+     * 密码加密
+     *
+     * @param password 密码
+     * @return 加密后密码
+     */
+    private String encryptPassword(String password, String salt) {
+        String saltPassword = DigestUtils.md5Hex(salt + password);
+
+        return saltPassword;
+    }
+}

+ 25 - 0
src/main/java/com/cdu/lys/graduation/admin/merchant/bo/MerchantBO.java

@@ -0,0 +1,25 @@
+package com.cdu.lys.graduation.admin.merchant.bo;
+
+import com.cdu.lys.graduation.repository.entity.MerchantDO;
+
+/**
+ * @author liyinsong
+ * @date 2022/4/14 21:37
+ */
+public interface MerchantBO {
+
+    /**
+     * 得到商户信息
+     *
+     * @return 商户信息
+     */
+    MerchantDO get();
+
+    /**
+     * 修改商户信息
+     *
+     * @param merchantDO 商户
+     * @return 行数
+     */
+    int update(MerchantDO merchantDO);
+}

+ 25 - 0
src/main/java/com/cdu/lys/graduation/admin/merchant/bo/MerchantRealPictureBO.java

@@ -0,0 +1,25 @@
+package com.cdu.lys.graduation.admin.merchant.bo;
+
+import com.cdu.lys.graduation.repository.entity.MerchantRealPictureDO;
+
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/4/17 20:56
+ */
+public interface MerchantRealPictureBO {
+
+    /**
+     * 得到商户实景图片
+     * @return 图片
+     */
+    List<MerchantRealPictureDO> get();
+
+    /**
+     * 更新商家实体图片
+     * @param merchantRealPictureDO 图片
+     * @return i
+     */
+    int update(List<MerchantRealPictureDO> merchantRealPictureDO);
+}

+ 43 - 0
src/main/java/com/cdu/lys/graduation/admin/merchant/bo/impl/MerchantBOImpl.java

@@ -0,0 +1,43 @@
+package com.cdu.lys.graduation.admin.merchant.bo.impl;
+
+import com.cdu.lys.graduation.admin.merchant.bo.MerchantBO;
+import com.cdu.lys.graduation.repository.dao.MerchantDOMapper;
+import com.cdu.lys.graduation.repository.entity.MerchantDO;
+import com.cdu.lys.graduation.repository.entity.MerchantDOExample;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/4/14 21:38
+ */
+@Service
+public class MerchantBOImpl implements MerchantBO {
+
+    @Autowired
+    private MerchantDOMapper merchantDOMapper;
+
+    @Override
+    public MerchantDO get() {
+        MerchantDOExample example = new MerchantDOExample();
+        List<MerchantDO> merchantDOS = merchantDOMapper.selectByExample(example);
+
+        if (CollectionUtils.isEmpty(merchantDOS)) {
+            return null;
+        }
+        return merchantDOS.get(0);
+    }
+
+    @Override
+    public int update(MerchantDO merchantDO) {
+        MerchantDO old = this.get();
+        if (old == null) {
+            return merchantDOMapper.insertSelective(merchantDO);
+        }
+        merchantDO.setId(old.getId());
+        return merchantDOMapper.updateByPrimaryKeySelective(merchantDO);
+    }
+}

+ 63 - 0
src/main/java/com/cdu/lys/graduation/admin/merchant/bo/impl/MerchantRealPictureBOImpl.java

@@ -0,0 +1,63 @@
+package com.cdu.lys.graduation.admin.merchant.bo.impl;
+
+import com.cdu.lys.graduation.admin.merchant.bo.MerchantBO;
+import com.cdu.lys.graduation.admin.merchant.bo.MerchantRealPictureBO;
+import com.cdu.lys.graduation.repository.dao.MerchantRealPictureDOMapper;
+import com.cdu.lys.graduation.repository.entity.MerchantDO;
+import com.cdu.lys.graduation.repository.entity.MerchantRealPictureDO;
+import com.cdu.lys.graduation.repository.entity.MerchantRealPictureDOExample;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/4/17 20:57
+ */
+@Service
+public class MerchantRealPictureBOImpl implements MerchantRealPictureBO {
+
+    @Autowired
+    private MerchantRealPictureDOMapper merchantRealPictureDOMapper;
+
+    @Autowired
+    private MerchantBO merchantBO;
+
+    @Override
+    public List<MerchantRealPictureDO> get() {
+        MerchantDO merchantDO = merchantBO.get();
+        if (merchantDO == null) {
+            return null;
+        }
+
+        MerchantRealPictureDOExample example = new MerchantRealPictureDOExample();
+        example.createCriteria()
+                .andMerchantIdEqualTo(merchantDO.getId());
+
+        return merchantRealPictureDOMapper.selectByExample(example);
+    }
+
+    @Override
+    public int update(List<MerchantRealPictureDO> merchantRealPictureDO) {
+        if (CollectionUtils.isEmpty(merchantRealPictureDO)) {
+            return 0;
+        }
+        MerchantDO merchantDO = merchantBO.get();
+
+        MerchantRealPictureDOExample example = new MerchantRealPictureDOExample();
+
+        if (merchantDO != null) {
+            Integer merchantId = merchantDO.getId();
+            example.createCriteria()
+                    .andMerchantIdEqualTo(merchantId);
+            merchantRealPictureDOMapper.deleteByExample(example);
+            for (MerchantRealPictureDO realPictureDO : merchantRealPictureDO) {
+                realPictureDO.setMerchantId(merchantId);
+                merchantRealPictureDOMapper.insert(realPictureDO);
+            }
+        }
+        return 1;
+    }
+}

+ 41 - 0
src/main/java/com/cdu/lys/graduation/admin/merchant/convertor/MerchantConvertor.java

@@ -0,0 +1,41 @@
+package com.cdu.lys.graduation.admin.merchant.convertor;
+
+import com.cdu.lys.graduation.repository.entity.MerchantRealPictureDO;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author liyinsong
+ * @date 2022/4/17 21:12
+ */
+@Component
+public class MerchantConvertor {
+
+    public List<String> convert2MerchantRealPictureVO(List<MerchantRealPictureDO> merchantRealPictureDOS) {
+        return merchantRealPictureDOS.stream()
+                .map(MerchantRealPictureDO::getPicUrl).collect(Collectors.toList());
+    }
+
+    public List<MerchantRealPictureDO> convert2PictureDO(List<String> picUrls) {
+        if (CollectionUtils.isEmpty(picUrls)) {
+            return null;
+        }
+        List<MerchantRealPictureDO> res = new ArrayList<>();
+        Date createTime = new Date();
+        for (String url : picUrls) {
+            MerchantRealPictureDO pictureDO = new MerchantRealPictureDO();
+            pictureDO.setPicUrl(url);
+            pictureDO.setCreateTime(createTime);
+            pictureDO.setUpdateTime(createTime);
+            res.add(pictureDO);
+        }
+
+        return res;
+    }
+
+}

+ 32 - 0
src/main/java/com/cdu/lys/graduation/admin/order/bo/AdminOrderBO.java

@@ -0,0 +1,32 @@
+package com.cdu.lys.graduation.admin.order.bo;
+
+import com.cdu.lys.graduation.repository.entity.OrderFormDO;
+import com.cdu.lys.graduation.types.PageQuery;
+import com.cdu.lys.graduation.types.admin.order.OrderSearchQuery;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/20 17:39
+ */
+public interface AdminOrderBO {
+
+    List<OrderFormDO> getAllOrders(PageQuery query);
+
+    List<OrderFormDO> getUndoneOrders(PageQuery query);
+
+    int updateOrderFormByOrderNum(String orderNum, OrderFormDO orderFormDO);
+
+    List<OrderFormDO> getByOrderNum(String orderNum);
+
+    List<OrderFormDO> search(OrderSearchQuery query);
+
+    /**
+     * 指定时间前的订单
+     * @param date 时间
+     * @return 订单list
+     */
+    List<OrderFormDO> getOrderBeforeDate(Date date);
+}

+ 35 - 0
src/main/java/com/cdu/lys/graduation/admin/order/bo/AdminOrderFormInfoBO.java

@@ -0,0 +1,35 @@
+package com.cdu.lys.graduation.admin.order.bo;
+
+import com.cdu.lys.graduation.repository.entity.OrderFormInfoDO;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/22 22:39
+ */
+public interface AdminOrderFormInfoBO {
+
+    OrderFormInfoDO getById(Integer id);
+
+    List<OrderFormInfoDO> getByOrderNum(String orderNum);
+
+    int updateByIdSelective(OrderFormInfoDO orderFormInfoDO);
+
+    int updateByOrderNumSelective(String orderNum, OrderFormInfoDO orderFormInfoDO);
+
+    /**
+     * 得到过去date至今的订单详情
+     * @param date 时间
+     * @return 订单详情
+     */
+    List<OrderFormInfoDO> getOrderInfoBeforeDate(Date date);
+
+    /**
+     * 得到订单集合的订单详情
+     * @param orderNumList 订单集合
+     * @return 订单详情
+     */
+    List<OrderFormInfoDO> getOrderInfoOrderNumIn(List<String> orderNumList);
+}

+ 118 - 0
src/main/java/com/cdu/lys/graduation/admin/order/bo/impl/AdminOrderBOImpl.java

@@ -0,0 +1,118 @@
+package com.cdu.lys.graduation.admin.order.bo.impl;
+
+import com.cdu.lys.graduation.admin.order.bo.AdminOrderBO;
+import com.cdu.lys.graduation.mini.user.bo.UserBO;
+import com.cdu.lys.graduation.repository.dao.OrderFormDOMapper;
+import com.cdu.lys.graduation.repository.entity.OrderFormDO;
+import com.cdu.lys.graduation.repository.entity.OrderFormDOExample;
+import com.cdu.lys.graduation.repository.entity.UserDO;
+import com.cdu.lys.graduation.types.PageQuery;
+import com.cdu.lys.graduation.types.admin.order.OrderSearchQuery;
+import com.cdu.lys.graduation.types.payment.TradeStatus;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/20 17:39
+ */
+@Service
+public class AdminOrderBOImpl implements AdminOrderBO {
+
+    @Autowired
+    private OrderFormDOMapper orderFormDOMapper;
+
+    @Autowired
+    private UserBO userBO;
+
+    @Override
+    public List<OrderFormDO> getAllOrders(PageQuery query) {
+        OrderFormDOExample example = new OrderFormDOExample();
+        example.setOrderByClause("create_time desc,id desc");
+        example.createCriteria();
+
+        return orderFormDOMapper.selectByExample(example);
+    }
+
+    @Override
+    public List<OrderFormDO> getUndoneOrders(PageQuery query) {
+        OrderFormDOExample example = new OrderFormDOExample();
+        //按照创建时间(天)倒序,排队号升序
+        example.setOrderByClause("DATE_FORMAT(create_time,'%y-%m-%d') DESC, queue_num");
+        example.createCriteria()
+                .andTradeStatusEqualTo(TradeStatus.NOT_DELIVERY.getCode());
+
+        return orderFormDOMapper.selectByExample(example);
+    }
+
+    @Override
+    public int updateOrderFormByOrderNum(String orderNum, OrderFormDO orderFormDO) {
+        OrderFormDOExample example = new OrderFormDOExample();
+        example.createCriteria()
+                .andOrderNumEqualTo(orderNum);
+
+        return orderFormDOMapper.updateByExampleSelective(orderFormDO, example);
+    }
+
+    @Override
+    public List<OrderFormDO> getByOrderNum(String orderNum) {
+        OrderFormDOExample example = new OrderFormDOExample();
+        example.createCriteria()
+                .andOrderNumEqualTo(orderNum);
+
+        return orderFormDOMapper.selectByExample(example);
+    }
+
+    @Override
+    public List<OrderFormDO> search(OrderSearchQuery query) {
+        OrderFormDOExample example = new OrderFormDOExample();
+        example.setOrderByClause("create_time desc,id desc");
+        OrderFormDOExample.Criteria criteria = example.createCriteria();
+
+        //精确搜索订单号
+        if (StringUtils.hasLength(query.getOrderNum())) {
+            criteria.andOrderNumEqualTo(query.getOrderNum());
+            return orderFormDOMapper.selectByExample(example);
+        }
+
+        //根据用户名查找
+        if (StringUtils.hasLength(query.getUsername())) {
+            UserDO userDO = userBO.getUserByUsername(query.getUsername());
+            if (userDO != null) {
+                criteria.andUserIdEqualTo(userDO.getId());
+            }
+        }
+
+        //交易状态
+        Integer tradeStatus = query.getTradeStatus();
+        if (query.getIsUndone().equals(true)) {
+            criteria.andTradeStatusEqualTo(TradeStatus.NOT_DELIVERY.getCode());
+        }else if (Objects.nonNull(tradeStatus)) {
+            criteria.andTradeStatusEqualTo(tradeStatus);
+        }
+
+        if (StringUtils.hasLength(query.getQueueNum())) {
+            criteria.andQueueNumEqualTo(query.getQueueNum());
+        }
+
+        if (Objects.nonNull(query.getDeliveryStatus())) {
+            criteria.andDeliveryStatusEqualTo(query.getDeliveryStatus());
+        }
+
+        return orderFormDOMapper.selectByExample(example);
+    }
+
+    @Override
+    public List<OrderFormDO> getOrderBeforeDate(Date date) {
+        OrderFormDOExample example = new OrderFormDOExample();
+        example.createCriteria()
+                .andCreateTimeGreaterThanOrEqualTo(date);
+
+        return orderFormDOMapper.selectByExample(example);
+    }
+}

+ 69 - 0
src/main/java/com/cdu/lys/graduation/admin/order/bo/impl/AdminOrderFormInfoBOImpl.java

@@ -0,0 +1,69 @@
+package com.cdu.lys.graduation.admin.order.bo.impl;
+
+import com.cdu.lys.graduation.admin.order.bo.AdminOrderFormInfoBO;
+import com.cdu.lys.graduation.repository.dao.OrderFormInfoDOMapper;
+import com.cdu.lys.graduation.repository.entity.OrderFormInfoDO;
+import com.cdu.lys.graduation.repository.entity.OrderFormInfoDOExample;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/22 22:39
+ */
+@Service
+public class AdminOrderFormInfoBOImpl implements AdminOrderFormInfoBO {
+
+    @Autowired
+    private OrderFormInfoDOMapper orderFormInfoDOMapper;
+
+    @Override
+    public OrderFormInfoDO getById(Integer id) {
+        return orderFormInfoDOMapper.selectByPrimaryKey(id);
+    }
+
+    @Override
+    public List<OrderFormInfoDO> getByOrderNum(String orderNum) {
+        OrderFormInfoDOExample example = new OrderFormInfoDOExample();
+        example.createCriteria()
+                .andOrderNumEqualTo(orderNum);
+
+        return orderFormInfoDOMapper.selectByExample(example);
+    }
+
+    @Override
+    public int updateByIdSelective(OrderFormInfoDO orderFormInfoDO) {
+        return orderFormInfoDOMapper.updateByPrimaryKeySelective(orderFormInfoDO);
+    }
+
+    @Override
+    public int updateByOrderNumSelective(String orderNum, OrderFormInfoDO orderFormInfoDO) {
+        OrderFormInfoDOExample example = new OrderFormInfoDOExample();
+        example.createCriteria()
+                .andOrderNumEqualTo(orderNum);
+        orderFormInfoDO.setUpdateTime(new Date());
+        return orderFormInfoDOMapper.updateByExampleSelective(orderFormInfoDO, example);
+    }
+
+    @Override
+    public List<OrderFormInfoDO> getOrderInfoBeforeDate(Date date) {
+        OrderFormInfoDOExample example = new OrderFormInfoDOExample();
+        example.createCriteria()
+                .andCreateTimeGreaterThan(date);
+
+        return orderFormInfoDOMapper.selectByExample(example);
+    }
+
+    @Override
+    public List<OrderFormInfoDO> getOrderInfoOrderNumIn(List<String> orderNumList) {
+        OrderFormInfoDOExample example = new OrderFormInfoDOExample();
+        example.createCriteria()
+                .andOrderNumIn(orderNumList);
+
+        return orderFormInfoDOMapper.selectByExample(example);
+    }
+
+}

+ 57 - 0
src/main/java/com/cdu/lys/graduation/admin/order/converter/OrderDataConverter.java

@@ -0,0 +1,57 @@
+package com.cdu.lys.graduation.admin.order.converter;
+
+import com.cdu.lys.graduation.admin.user.bo.AdminUserBO;
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.domain.admin.vo.OrderFormVO;
+import com.cdu.lys.graduation.repository.entity.OrderFormDO;
+import com.cdu.lys.graduation.repository.entity.UserDO;
+import com.cdu.lys.graduation.types.payment.DeliveryStatus;
+import com.cdu.lys.graduation.types.payment.PayStatus;
+import com.cdu.lys.graduation.types.payment.TradeStatus;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 数据格式转换类
+ *
+ * @author liyinsong
+ * @date 2022/3/21 19:49
+ */
+@Component
+public class OrderDataConverter {
+
+    @Autowired
+    private AdminUserBO adminUserBO;
+
+    public PageResult<List<OrderFormVO>> convertOrderPageDO2VO(PageResult<List<OrderFormDO>> pageResult) {
+
+        List<OrderFormDO> data = pageResult.getData();
+        List<OrderFormVO> orderFormVOS = new ArrayList<>();
+        data.forEach(orderFormDO -> {
+            OrderFormVO orderFormVO = this.convertOrderFormDO2VO(orderFormDO);
+            UserDO userDO = adminUserBO.getById(orderFormDO.getUserId());
+            orderFormVO.setUsername(userDO.getUsername());
+            orderFormVOS.add(orderFormVO);
+        });
+        PageResult<List<OrderFormVO>> result = new PageResult<>();
+        BeanUtils.copyProperties(pageResult, result);
+        result.setData(orderFormVOS);
+
+        return result;
+    }
+
+    public OrderFormVO convertOrderFormDO2VO(OrderFormDO orderFormDO) {
+
+        OrderFormVO orderFormVO = new OrderFormVO();
+        BeanUtils.copyProperties(orderFormDO, orderFormVO);
+        orderFormVO.setTradeStatus(TradeStatus.getMsgByCode(orderFormDO.getTradeStatus()));
+        orderFormVO.setPayStatus(PayStatus.getMsgByCode(orderFormDO.getPayStatus()));
+        orderFormVO.setDeliveryStatus(DeliveryStatus.getMsgByCode(orderFormDO.getDeliveryStatus()));
+
+        return orderFormVO;
+    }
+}

+ 30 - 0
src/main/java/com/cdu/lys/graduation/admin/order/converter/OrderInfoDataConverter.java

@@ -0,0 +1,30 @@
+package com.cdu.lys.graduation.admin.order.converter;
+
+import com.cdu.lys.graduation.domain.admin.vo.OrderFormInfoVO;
+import com.cdu.lys.graduation.repository.entity.OrderFormInfoDO;
+import com.cdu.lys.graduation.types.payment.DeliveryStatus;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/22 23:38
+ */
+@Component
+public class OrderInfoDataConverter {
+
+    public List<OrderFormInfoVO> convertOrderInfoDO2VO(List<OrderFormInfoDO> orderFormInfoDOS) {
+        List<OrderFormInfoVO> res = new ArrayList<>();
+        orderFormInfoDOS.forEach(orderFormInfoDO -> {
+            OrderFormInfoVO orderFormInfoVO = new OrderFormInfoVO();
+            BeanUtils.copyProperties(orderFormInfoDO, orderFormInfoVO);
+            orderFormInfoVO.setDeliveryStatus(DeliveryStatus.getMsgByCode(orderFormInfoDO.getDeliveryStatus()));
+            res.add(orderFormInfoVO);
+        });
+
+        return res;
+    }
+}

+ 25 - 0
src/main/java/com/cdu/lys/graduation/admin/order/service/AdminOrderService.java

@@ -0,0 +1,25 @@
+package com.cdu.lys.graduation.admin.order.service;
+
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.repository.entity.OrderFormDO;
+import com.cdu.lys.graduation.types.PageQuery;
+import com.cdu.lys.graduation.types.admin.order.OrderSearchQuery;
+
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/20 17:38
+ */
+public interface AdminOrderService {
+
+    PageResult<List<OrderFormDO>> getAllOrders(PageQuery query);
+
+    PageResult<List<OrderFormDO>> getUndoneOrders(PageQuery query);
+
+    boolean deliveryOne(Integer orderInfoId);
+
+    boolean deliveryAll(String orderNum);
+
+    PageResult<List<OrderFormDO>> search(OrderSearchQuery query);
+}

+ 150 - 0
src/main/java/com/cdu/lys/graduation/admin/order/service/impl/AdminOrderServiceImpl.java

@@ -0,0 +1,150 @@
+package com.cdu.lys.graduation.admin.order.service.impl;
+
+import com.cdu.lys.graduation.admin.order.bo.AdminOrderBO;
+import com.cdu.lys.graduation.admin.order.bo.AdminOrderFormInfoBO;
+import com.cdu.lys.graduation.admin.order.service.AdminOrderService;
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.repository.entity.OrderFormDO;
+import com.cdu.lys.graduation.repository.entity.OrderFormInfoDO;
+import com.cdu.lys.graduation.types.PageQuery;
+import com.cdu.lys.graduation.types.admin.order.OrderSearchQuery;
+import com.cdu.lys.graduation.types.exception.BusinessException;
+import com.cdu.lys.graduation.types.exception.ErrorType;
+import com.cdu.lys.graduation.types.payment.DeliveryStatus;
+import com.cdu.lys.graduation.types.payment.TradeStatus;
+import com.github.pagehelper.Page;
+import com.github.pagehelper.PageHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/20 17:38
+ */
+@Service
+public class AdminOrderServiceImpl implements AdminOrderService {
+
+    @Autowired
+    private AdminOrderBO adminOrderBO;
+
+    @Autowired
+    private AdminOrderFormInfoBO adminOrderFormInfoBO;
+
+    @Override
+    public PageResult<List<OrderFormDO>> getAllOrders(PageQuery query) {
+        Page<Object> page = PageHelper.startPage(query.getPageNo(), query.getPageSize());
+
+        List<OrderFormDO> orders = adminOrderBO.getAllOrders(query);
+
+        PageResult<List<OrderFormDO>> pageResult = new PageResult<>(orders);
+        pageResult.setPageNum(page.getPageNum());
+        pageResult.setPageSize(page.getPageSize());
+        pageResult.setTotal(page.getTotal());
+        pageResult.setPages(page.getPages());
+
+        return pageResult;
+    }
+
+    @Override
+    public PageResult<List<OrderFormDO>> getUndoneOrders(PageQuery query) {
+        Page<Object> page = PageHelper.startPage(query.getPageNo(), query.getPageSize());
+        List<OrderFormDO> orders = adminOrderBO.getUndoneOrders(query);
+
+        PageResult<List<OrderFormDO>> pageResult = new PageResult<>(orders);
+        pageResult.setPageNum(page.getPageNum());
+        pageResult.setPageSize(page.getPageSize());
+        pageResult.setTotal(page.getTotal());
+        pageResult.setPages(page.getPages());
+        return pageResult;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public boolean deliveryOne(Integer orderInfoId) {
+        OrderFormInfoDO orderFormInfo = adminOrderFormInfoBO.getById(orderInfoId);
+        if (orderFormInfo.getDeliveryStatus().equals(DeliveryStatus.DELIVERED.getCode())) {
+            return false;
+        }
+        String orderNum = orderFormInfo.getOrderNum();
+        OrderFormDO order = adminOrderBO.getByOrderNum(orderNum).get(0);
+        //订单不是待配送状态
+        if (!order.getTradeStatus().equals(TradeStatus.NOT_DELIVERY.getCode())) {
+            return false;
+        }
+
+        OrderFormInfoDO orderFormInfoDO = new OrderFormInfoDO();
+        orderFormInfoDO.setId(orderInfoId);
+        orderFormInfoDO.setDeliveryStatus(DeliveryStatus.DELIVERED.getCode());
+        int i = adminOrderFormInfoBO.updateByIdSelective(orderFormInfoDO);
+
+        //是否全部已配送
+        List<OrderFormInfoDO> orderFormInfoDOS = adminOrderFormInfoBO.getByOrderNum(orderNum);
+        boolean allDelivery = orderFormInfoDOS.stream()
+                .allMatch(o -> o.getDeliveryStatus().equals(DeliveryStatus.DELIVERED.getCode()));
+
+        if (allDelivery) {
+            //更新订单表
+            this.setOrderFormDelivery(orderNum);
+        }
+
+        return i > 0;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public boolean deliveryAll(String orderNum) {
+        List<OrderFormDO> orders = adminOrderBO.getByOrderNum(orderNum);
+        if (CollectionUtils.isEmpty(orders)) {
+            throw new BusinessException(ErrorType.PARAM_ERROR, "没有该订单");
+        }
+
+        OrderFormDO order = orders.get(0);
+        Integer tradeStatus = order.getTradeStatus();
+        //订单不是待配送状态
+        if (!tradeStatus.equals(TradeStatus.NOT_DELIVERY.getCode())) {
+            return false;
+        }
+
+        //修改订单表
+        boolean formDelivery = this.setOrderFormDelivery(orderNum);
+
+        //订单详情表
+        OrderFormInfoDO orderFormInfoDO = new OrderFormInfoDO();
+        orderFormInfoDO.setDeliveryStatus(DeliveryStatus.DELIVERED.getCode());
+        int i = adminOrderFormInfoBO.updateByOrderNumSelective(orderNum, orderFormInfoDO);
+
+        return i > 0 && formDelivery;
+    }
+
+    @Override
+    public PageResult<List<OrderFormDO>> search(OrderSearchQuery query) {
+        Page<Object> page = PageHelper.startPage(query.getPageNo(), query.getPageSize());
+
+        List<OrderFormDO> orders = adminOrderBO.search(query);
+
+        PageResult<List<OrderFormDO>> pageResult = new PageResult<>(orders);
+        pageResult.setPageNum(page.getPageNum());
+        pageResult.setPageSize(page.getPageSize());
+        pageResult.setTotal(page.getTotal());
+        pageResult.setPages(page.getPages());
+
+        return pageResult;
+    }
+
+    private boolean setOrderFormDelivery(String orderNum) {
+        //修改订单表
+        OrderFormDO orderFormDO = new OrderFormDO();
+        orderFormDO.setDeliveryStatus(DeliveryStatus.DELIVERED.getCode());
+        orderFormDO.setTradeStatus(TradeStatus.FINISHED.getCode());
+        orderFormDO.setCloseTime(new Date());
+
+        int i = adminOrderBO.updateOrderFormByOrderNum(orderNum, orderFormDO);
+
+        return i > 0;
+    }
+}

+ 16 - 0
src/main/java/com/cdu/lys/graduation/admin/record/bo/RecordBO.java

@@ -0,0 +1,16 @@
+package com.cdu.lys.graduation.admin.record.bo;
+
+import com.cdu.lys.graduation.repository.entity.SystemRecordDO;
+
+/**
+ * @author liyinsong
+ * @date 2022/4/13 19:53
+ */
+public interface RecordBO {
+
+    /**
+     * 得到昨天记录
+     * @return 昨天记录
+     */
+    SystemRecordDO getYesterdayRecord();
+}

+ 30 - 0
src/main/java/com/cdu/lys/graduation/admin/record/bo/impl/RecordBOImpl.java

@@ -0,0 +1,30 @@
+package com.cdu.lys.graduation.admin.record.bo.impl;
+
+import com.cdu.lys.graduation.admin.record.bo.RecordBO;
+import com.cdu.lys.graduation.repository.dao.SystemRecordDOMapper;
+import com.cdu.lys.graduation.repository.entity.SystemRecordDO;
+import com.cdu.lys.graduation.repository.entity.SystemRecordDOExample;
+import com.github.pagehelper.PageHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author liyinsong
+ * @date 2022/4/13 19:53
+ */
+@Service
+public class RecordBOImpl implements RecordBO {
+
+    @Autowired
+    private SystemRecordDOMapper systemRecordDOMapper;
+
+    @Cacheable(value = "YesterdayRecord")
+    @Override
+    public SystemRecordDO getYesterdayRecord() {
+        SystemRecordDOExample example = new SystemRecordDOExample();
+        example.setOrderByClause("record_date desc");
+        PageHelper.startPage(1, 1);
+        return systemRecordDOMapper.selectByExample(example).get(0);
+    }
+}

+ 40 - 0
src/main/java/com/cdu/lys/graduation/admin/record/service/RecordService.java

@@ -0,0 +1,40 @@
+package com.cdu.lys.graduation.admin.record.service;
+
+import com.cdu.lys.graduation.domain.admin.vo.RecordVO;
+
+/**
+ * @author liyinsong
+ * @date 2022/4/13 15:27
+ */
+public interface RecordService {
+
+    /**
+     * 日访问量
+     * @return 日访问量
+     */
+    RecordVO getDailyVisit();
+
+    /**
+     * 日销量
+     * @return 日销量
+     */
+    RecordVO getDailySales();
+
+    /**
+     * 日收入
+     * @return 日收入
+     */
+    RecordVO getDailyIncome();
+
+    /**
+     * 日评论量
+     * @return 日评论量
+     */
+    RecordVO getDailyCommentNum();
+
+    /**
+     * 持久化每日数据
+     * @return 影响行数
+     */
+    int recordTask();
+}

+ 156 - 0
src/main/java/com/cdu/lys/graduation/admin/record/service/impl/RecordServiceImpl.java

@@ -0,0 +1,156 @@
+package com.cdu.lys.graduation.admin.record.service.impl;
+
+import com.cdu.lys.graduation.admin.record.bo.RecordBO;
+import com.cdu.lys.graduation.admin.record.service.RecordService;
+import com.cdu.lys.graduation.commons.utils.DateUtils;
+import com.cdu.lys.graduation.domain.admin.vo.RecordVO;
+import com.cdu.lys.graduation.redis.RedisService;
+import com.cdu.lys.graduation.repository.dao.SystemRecordDOMapper;
+import com.cdu.lys.graduation.repository.entity.SystemRecordDO;
+import com.cdu.lys.graduation.repository.entity.SystemRecordDOExample;
+import com.cdu.lys.graduation.types.SystemConstant;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+
+import java.text.DecimalFormat;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/4/13 15:27
+ */
+@Service
+public class RecordServiceImpl implements RecordService {
+
+    @Autowired
+    private RedisService redisService;
+
+    @Autowired
+    private SystemRecordDOMapper systemRecordDOMapper;
+
+    @Autowired
+    private RecordBO recordBO;
+
+    @Override
+    public RecordVO getDailyVisit() {
+        String visit = redisService.getKey(SystemConstant.DAILY_VISIT_NUM_KEY);
+
+        SystemRecordDO recordDO = recordBO.getYesterdayRecord();
+        if (!StringUtils.hasLength(visit)) {
+            visit = "0";
+        }
+        String rate = this.calculateRate(recordDO.getVisitNum(), Integer.parseInt(visit));
+        return new RecordVO(visit, rate);
+    }
+
+    @Override
+    public RecordVO getDailySales() {
+        String sales = redisService.getKey(SystemConstant.DAILY_SALES_KEY);
+
+        SystemRecordDO recordDO = recordBO.getYesterdayRecord();
+        if (!StringUtils.hasLength(sales)) {
+            sales = "0";
+        }
+        String rate = this.calculateRate(recordDO.getSales(), Integer.parseInt(sales));
+        return new RecordVO(sales, rate);
+    }
+
+    @Override
+    public RecordVO getDailyIncome() {
+        String income = redisService.getKey(SystemConstant.DAILY_INCOME_KEY);
+
+        SystemRecordDO recordDO = recordBO.getYesterdayRecord();
+        if (!StringUtils.hasLength(income)) {
+            income = "0";
+        }
+        String rate = this.calculateRate(recordDO.getDailyIncome(), Double.parseDouble(income));
+        return new RecordVO(income, rate);
+    }
+
+    @Override
+    public RecordVO getDailyCommentNum() {
+        String comment = redisService.getKey(SystemConstant.DAILY_COMMENT_NUM_KEY);
+
+        SystemRecordDO recordDO = recordBO.getYesterdayRecord();
+        if (!StringUtils.hasLength(comment)) {
+            comment = "0";
+        }
+        String rate = this.calculateRate(recordDO.getDailyCommentNum(), Integer.parseInt(comment));
+        return new RecordVO(comment, rate);
+    }
+
+    @Override
+    public int recordTask() {
+        String visit = redisService.getKey(SystemConstant.DAILY_VISIT_NUM_KEY);
+        String sales = redisService.getKey(SystemConstant.DAILY_SALES_KEY);
+        String income = redisService.getKey(SystemConstant.DAILY_INCOME_KEY);
+        String comment = redisService.getKey(SystemConstant.DAILY_COMMENT_NUM_KEY);
+
+        SystemRecordDO recordDO = new SystemRecordDO();
+        Date today = DateUtils.getToday();
+        recordDO.setRecordDate(today);
+        if (StringUtils.hasLength(comment)) {
+            recordDO.setDailyCommentNum(Integer.parseInt(comment));
+        }
+        if (StringUtils.hasLength(income)) {
+            recordDO.setDailyIncome(Double.parseDouble(income));
+        }
+        if (StringUtils.hasLength(sales)) {
+            recordDO.setSales(Integer.parseInt(sales));
+        }
+        if (StringUtils.hasLength(visit)) {
+            recordDO.setVisitNum(Integer.parseInt(visit));
+        }
+
+        SystemRecordDOExample example = new SystemRecordDOExample();
+        example.createCriteria()
+                .andRecordDateEqualTo(today);
+        List<SystemRecordDO> recordDOS = systemRecordDOMapper.selectByExample(example);
+
+        if (CollectionUtils.isEmpty(recordDOS)) {
+            return systemRecordDOMapper.insertSelective(recordDO);
+        }else {
+            recordDO.setId(recordDOS.get(0).getId());
+            return systemRecordDOMapper.updateByPrimaryKeySelective(recordDO);
+        }
+
+    }
+
+    /**
+     * 计算百分比
+     * @param num1
+     * @param num2
+     * @return num2相对于num1的百分比
+     */
+    private String calculateRate(int num1, int num2) {
+
+        DecimalFormat fmt = new DecimalFormat("#.##%");
+        double rate = 1;
+
+        if (num1 != 0) {
+            rate = (num2 - num1) * 1.0 / num1;
+        }
+
+        return fmt.format(rate);
+    }
+
+    /**
+     * 计算百分比
+     * @param num1
+     * @param num2
+     * @return
+     */
+    private String calculateRate(double num1, double num2) {
+
+        DecimalFormat fmt = new DecimalFormat("#.##%");
+        double rate = 1;
+
+        if (num1 != 0) {
+            rate = (num2 - num1) / num1;
+        }
+        return fmt.format(rate);
+    }
+}

+ 14 - 0
src/main/java/com/cdu/lys/graduation/admin/user/bo/AdminUserBO.java

@@ -0,0 +1,14 @@
+package com.cdu.lys.graduation.admin.user.bo;
+
+import com.cdu.lys.graduation.repository.entity.UserDO;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/21 20:37
+ */
+public interface AdminUserBO {
+
+    UserDO getById(Integer userId);
+
+    UserDO getByUsername(String username);
+}

+ 51 - 0
src/main/java/com/cdu/lys/graduation/admin/user/bo/impl/AdminUserBOImpl.java

@@ -0,0 +1,51 @@
+package com.cdu.lys.graduation.admin.user.bo.impl;
+
+import com.cdu.lys.graduation.admin.user.bo.AdminUserBO;
+import com.cdu.lys.graduation.repository.dao.UserDOMapper;
+import com.cdu.lys.graduation.repository.entity.UserDO;
+import com.cdu.lys.graduation.repository.entity.UserDOExample;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/21 20:37
+ */
+@Service
+public class AdminUserBOImpl implements AdminUserBO {
+
+    @Autowired
+    private UserDOMapper userDOMapper;
+
+    @Override
+    public UserDO getById(Integer userId) {
+        UserDOExample example = new UserDOExample();
+        example.createCriteria()
+                .andIdEqualTo(userId)
+                .andIsDeleteEqualTo("n");
+
+        List<UserDO> userDOS = userDOMapper.selectByExample(example);
+        if (CollectionUtils.isEmpty(userDOS)) {
+            return null;
+        }
+        return userDOS.get(0);
+    }
+
+    @Override
+    public UserDO getByUsername(String username) {
+        UserDOExample example = new UserDOExample();
+        example.createCriteria()
+                .andUsernameEqualTo(username)
+                .andIsDeleteEqualTo("n");
+
+        List<UserDO> userDOS = userDOMapper.selectByExample(example);
+        if (CollectionUtils.isEmpty(userDOS)) {
+            return null;
+        }
+        return userDOS.get(0);
+    }
+
+}

+ 97 - 0
src/main/java/com/cdu/lys/graduation/commons/result/ActionResult.java

@@ -0,0 +1,97 @@
+package com.cdu.lys.graduation.commons.result;
+
+import java.io.Serializable;
+
+/**
+ * @author liyinsong
+ * @date 2022/1/8 10:19
+ */
+public class ActionResult<T> implements Serializable {
+    private String code;
+    private String message;
+    private boolean success;
+    private T data;
+
+    public ActionResult() {
+    }
+
+    public ActionResult(String code, String message, boolean success, T data) {
+        this.code = code;
+        this.message = message;
+        this.success = success;
+        this.data = data;
+    }
+
+    public static <T> ActionResult<T> getSuccessResult(String message) {
+        return new ActionResult<>("0000", message, true, null);
+    }
+    public static <T> ActionResult<T> getSuccessResult(T data){
+        return new ActionResult<>("0000", "成功", true, data);
+    }
+
+    public static <T> ActionResult<T> getSuccessResult(String message, T data) {
+        return new ActionResult<>("0000", message, true, data);
+    }
+
+    public static <T> ActionResult<T> getSuccessResult(String code, String message, T data) {
+        return new ActionResult<>(code, message, true, data);
+    }
+
+    public static <T> ActionResult<T> getErrorResult(String code, String message) {
+        return new ActionResult<>(code, message, false, null);
+    }
+
+    public static <T> ActionResult<T> getErrorResult(String code, String message, T data) {
+        return new ActionResult<>(code, message, false, data);
+    }
+
+    public static <T> ActionResult<T> getErrorResult(String message, T data) {
+        return new ActionResult<>("9999", message, false, data);
+    }
+
+    public static <T> ActionResult<T> getErrorResult(String message) {
+        return new ActionResult<>("9999", message, false, null);
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public T getData() {
+        return data;
+    }
+
+    public void setData(T data) {
+        this.data = data;
+    }
+
+    public boolean isSuccess() {
+        return success;
+    }
+
+    public void setSuccess(boolean success) {
+        this.success = success;
+    }
+
+    @Override
+    public String toString() {
+        return "ActionResult{" +
+                "code='" + code + '\'' +
+                ", message='" + message + '\'' +
+                ", success=" + success +
+                ", data=" + data +
+                '}';
+    }
+}

+ 91 - 0
src/main/java/com/cdu/lys/graduation/commons/result/PageResult.java

@@ -0,0 +1,91 @@
+package com.cdu.lys.graduation.commons.result;
+
+/**
+ * @author liyinsong
+ * @date 2022/2/8 11:32
+ */
+public class PageResult<T> {
+
+    /**
+     * 页数
+     */
+    private int pageNum;
+
+    /**
+     * 页面大小
+     */
+    private int pageSize;
+
+    /**
+     * 数据总数
+     */
+    private long total;
+
+    /**
+     * 总页数
+     */
+    private int pages;
+
+    /**
+     * 页面数据
+     */
+    private T data;
+
+    public PageResult() {
+    }
+
+    public PageResult(T data) {
+        this.data = data;
+    }
+
+    public int getPageNum() {
+        return pageNum;
+    }
+
+    public void setPageNum(int pageNum) {
+        this.pageNum = pageNum;
+    }
+
+    public int getPageSize() {
+        return pageSize;
+    }
+
+    public void setPageSize(int pageSize) {
+        this.pageSize = pageSize;
+    }
+
+    public long getTotal() {
+        return total;
+    }
+
+    public void setTotal(long total) {
+        this.total = total;
+    }
+
+    public T getData() {
+        return data;
+    }
+
+    public void setData(T data) {
+        this.data = data;
+    }
+
+    public int getPages() {
+        return pages;
+    }
+
+    public void setPages(int pages) {
+        this.pages = pages;
+    }
+
+    @Override
+    public String toString() {
+        return "PageResult{" +
+                "pageNum=" + pageNum +
+                ", pageSize=" + pageSize +
+                ", total=" + total +
+                ", pages=" + pages +
+                ", data=" + data +
+                '}';
+    }
+}

+ 52 - 0
src/main/java/com/cdu/lys/graduation/commons/result/UploadFileResponse.java

@@ -0,0 +1,52 @@
+package com.cdu.lys.graduation.commons.result;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/28 22:49
+ */
+public class UploadFileResponse {
+
+    private String fileName;
+    private String fileDownloadUri;
+    private String fileType;
+    private long size;
+
+    public UploadFileResponse(String fileName, String fileDownloadUri, String fileType, long size) {
+        this.fileName = fileName;
+        this.fileDownloadUri = fileDownloadUri;
+        this.fileType = fileType;
+        this.size = size;
+    }
+
+    public String getFileName() {
+        return fileName;
+    }
+
+    public void setFileName(String fileName) {
+        this.fileName = fileName;
+    }
+
+    public String getFileDownloadUri() {
+        return fileDownloadUri;
+    }
+
+    public void setFileDownloadUri(String fileDownloadUri) {
+        this.fileDownloadUri = fileDownloadUri;
+    }
+
+    public String getFileType() {
+        return fileType;
+    }
+
+    public void setFileType(String fileType) {
+        this.fileType = fileType;
+    }
+
+    public long getSize() {
+        return size;
+    }
+
+    public void setSize(long size) {
+        this.size = size;
+    }
+}

+ 31 - 0
src/main/java/com/cdu/lys/graduation/commons/utils/BASE64Utils.java

@@ -0,0 +1,31 @@
+package com.cdu.lys.graduation.commons.utils;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+
+/**
+ * BASE64 系统密文转换工具类,仅在配置文件读取时使用
+ * @author liyinsong
+ * @date 2022/1/13 22:36
+ */
+public class BASE64Utils {
+
+    public static String encodeBase64(String msg) {
+        byte[] encode = Base64.getEncoder().encode(msg.getBytes(StandardCharsets.UTF_8));
+
+        return new String(encode,StandardCharsets.UTF_8);
+    }
+
+    public static String parseBase64(String msg) {
+        byte[] decode = Base64.getDecoder().decode(msg);
+
+        return new String(decode, StandardCharsets.UTF_8);
+    }
+
+    public static void main(String[] args) {
+        String base64 = encodeBase64("qDGU*8ZLDP");
+        System.out.println("加密后:"+base64);
+        System.out.println("解密后:"+parseBase64(base64));
+
+    }
+}

+ 61 - 0
src/main/java/com/cdu/lys/graduation/commons/utils/DateUtils.java

@@ -0,0 +1,61 @@
+package com.cdu.lys.graduation.commons.utils;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Objects;
+
+/**
+ * @author liyinsong
+ * @date 2022/2/28 16:25
+ */
+public class DateUtils {
+
+    /**
+     * 查询指定日期前后指定的天数
+     * @param date 指定日期
+     * @param day 天数
+     * @return 日期对象
+     */
+    public static Date add(Date date, int day) {
+
+        if (Objects.isNull(date)) {
+            return null;
+        }
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.add(Calendar.DATE, day);
+
+        return calendar.getTime();
+    }
+
+    /**
+     * 得到指定日期后的指定时间
+     * @param date 指定日期
+     * @param type 按type增加,使用Calendar类中的常量
+     * @param amount 数量
+     * @return 日期
+     */
+    public static Date add(Date date, int type, int amount) {
+        if (Objects.isNull(date)) {
+            return null;
+        }
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.add(type, amount);
+
+        return calendar.getTime();
+    }
+
+    /**
+     * 得到今天凌晨时间
+     * @return 时间
+     */
+    public static Date getToday() {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+        return calendar.getTime();
+    }
+}

+ 132 - 0
src/main/java/com/cdu/lys/graduation/commons/utils/JWTUtils.java

@@ -0,0 +1,132 @@
+package com.cdu.lys.graduation.commons.utils;
+
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.JwtBuilder;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import org.apache.commons.codec.binary.Base64;
+
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import java.util.Date;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * JWT生成工具类
+ * @author liyinsong
+ * @date 2022/1/9 19:26
+ */
+public class JWTUtils {
+
+    /**
+     * 生成jwt
+     * @param subject   代表这个JWT的主体,即它的所有人,这个是一个json格式的字符串,可以存放什么userid,roldid之类的,作为什么用户的唯一标志。
+     * @param ttlMillis 过期时间
+     * @param claims    创建payload的私有声明(根据特定的业务需要添加,如果要拿这个做验证,一般是需要和jwt的接收方提前沟通好验证方式的)
+     * @param secretKey 秘钥
+     * @return jwt
+     */
+    public static String createJWT(String subject, long ttlMillis, Map<String, Object> claims,String secretKey) {
+        SignatureAlgorithm hs256 = SignatureAlgorithm.HS256;
+        long nowMillis = System.currentTimeMillis();
+        Date now = new Date(nowMillis);
+
+        SecretKey key = generalKey(secretKey);
+
+        JwtBuilder builder = Jwts.builder()
+                .setClaims(claims)
+                .setId(UUID.randomUUID().toString())
+                .setIssuedAt(now)
+                .setSubject(subject)
+                .signWith(hs256, key);
+
+        if (ttlMillis >= 0) {
+            long expMillis = nowMillis + ttlMillis;
+            Date exp = new Date(expMillis);
+            builder.setExpiration(exp);     //设置过期时间
+        }
+
+        return builder.compact();
+    }
+
+    /**
+     * 生成jwt字符串,payload中不带参数
+     * @param secretKey 秘钥,不能泄露,泄露后用户就能自由签发jwt
+     * @return jwt
+     */
+    public static String createJWT(String secretKey) {
+        SignatureAlgorithm hs256 = SignatureAlgorithm.HS256;
+        long nowMillis = System.currentTimeMillis();
+        Date now = new Date(nowMillis);
+
+        SecretKey key = generalKey(secretKey);
+
+        JwtBuilder builder = Jwts.builder()
+                .setId(UUID.randomUUID().toString())
+                .setIssuedAt(now)
+                .signWith(hs256, key);
+
+        return builder.compact();
+    }
+
+    /**
+     * 生成秘钥key
+     * @param secretKey BASE64格式的key,即是秘钥
+     * @return key
+     */
+    private static SecretKey generalKey(String secretKey) {
+
+        //本地的密码解码
+        byte[] encodedKey = Base64.decodeBase64(secretKey);
+
+        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");// 根据给定的字节数组使用AES加密算法构造一个密钥,使用 encodedKey中的始于且包含 0 到前 leng 个字节这是当然是所有。
+        return key;
+    }
+
+
+    /**
+     * 解析jwt字符串
+     * @param jwt jwt字符串
+     * @return 返回jwt payload
+     */
+    public static Claims parseJWT(String jwt,String key) {
+        SecretKey secretKey = generalKey(key);
+
+        return Jwts.parser()
+                .setSigningKey(secretKey)
+                .parseClaimsJws(jwt).getBody();
+    }
+
+    //完成最终版本后删除
+    /*public static void main(String[] args) {
+        System.out.println("========test01========");
+
+        Map<String, Object> map = new HashMap<>();
+        map.put("username", "test");
+        String key = Base64.encodeBase64String("123".getBytes(StandardCharsets.UTF_8));
+
+        String jwt = JWTUtils.createJWT( "a1", System.currentTimeMillis(), map, key);
+        System.out.println(jwt);
+        System.out.println("start parse");
+
+
+        Claims x = parseJWT(jwt,key);
+        System.out.println(x);
+        System.out.println("audience="+x.getAudience());
+        System.out.println("subject="+x.getSubject());
+        System.out.println("expire="+x.getExpiration());
+        System.out.println("id="+x.getId());
+        System.out.println("iss="+x.getIssuedAt());
+        System.out.println("issuser="+x.getIssuer());
+        System.out.println("notbefor="+x.getNotBefore());
+        System.out.println("username="+x.get("username"));
+
+        System.out.println("========test02========");
+        String jwt1 = JWTUtils.createJWT(key);
+        System.out.println("jwt="+jwt1);
+        System.out.println(JWTUtils.parseJWT(jwt1, key));
+
+    }*/
+
+}

+ 55 - 0
src/main/java/com/cdu/lys/graduation/config/RedisConfig.java

@@ -0,0 +1,55 @@
+package com.cdu.lys.graduation.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.cache.RedisCacheConfiguration;
+import org.springframework.data.redis.cache.RedisCacheManager;
+import org.springframework.data.redis.cache.RedisCacheWriter;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.*;
+
+import java.time.Duration;
+
+/**
+ * @author liyinsong
+ * @date 2022/1/8 21:59
+ */
+@Configuration
+public class RedisConfig {
+
+    @Bean
+    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
+        RedisTemplate<String,Object> redisTemplate=new RedisTemplate<>();
+        redisTemplate.setConnectionFactory(redisConnectionFactory);
+
+        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
+        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
+        redisTemplate.setKeySerializer(new StringRedisSerializer());
+
+        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
+        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
+        redisTemplate.afterPropertiesSet();
+
+        return redisTemplate;
+    }
+
+    /**
+     * 基于SpringBoot2 对 RedisCacheManager 的自定义配置
+     */
+    @Bean
+    public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
+        //初始化一个RedisCacheWriter
+        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
+        //设置CacheManager的值序列化方式为json序列化
+        RedisSerializer<Object> jsonSerializer = new GenericJackson2JsonRedisSerializer();
+        RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(jsonSerializer);
+        RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig()
+                .serializeValuesWith(pair)
+                .entryTtl(Duration.ofDays(1))//设置默认超过时期是1天
+                .prefixCacheNameWith("EORDER:CACHE:");
+
+        //初始化RedisCacheManager
+        return new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
+    }
+}

+ 78 - 0
src/main/java/com/cdu/lys/graduation/config/RestTemplateConfig.java

@@ -0,0 +1,78 @@
+package com.cdu.lys.graduation.config;
+
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.client.ClientHttpRequestFactory;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * RestTemplate配置类
+ * @author liyinsong
+ * @date 2022/1/14 10:15
+ */
+@Configuration
+public class RestTemplateConfig {
+    @Value("${http_pool.max_total}")
+    private int maxTotal;
+
+    @Value("${http_pool.default_max_per_route}")
+    private int maxPerRoute;
+
+    @Value("${http_pool.connect_timeout}")
+    private int connTimeOut;
+
+    @Value("${http_pool.connection_request_timeout}")
+    private int connReqTimeOut;
+
+    @Value("${http_pool.socket_timeout}")
+    private int socketTimeout;
+
+    @Value("${http_pool.validate_after_inactivity}")
+    private int inactivity;
+
+    @Bean
+    public RestTemplate restTemplate() {
+        return new RestTemplate(httpRequestFactory());
+    }
+
+    @Bean
+    public ClientHttpRequestFactory httpRequestFactory() {
+        return new HttpComponentsClientHttpRequestFactory(httpClient());
+    }
+
+    @Bean
+    public HttpClient httpClient() {
+        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
+                .register("http", PlainConnectionSocketFactory.getSocketFactory())
+                .register("https", SSLConnectionSocketFactory.getSocketFactory())
+                .build();
+        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
+        connectionManager.setMaxTotal(maxTotal);
+        connectionManager.setDefaultMaxPerRoute(maxPerRoute);
+        connectionManager.setValidateAfterInactivity(inactivity);
+        RequestConfig requestConfig = RequestConfig.custom()
+                //服务器返回数据(response)的时间,超过抛出read timeout
+                .setSocketTimeout(socketTimeout)
+                //连接上服务器(握手成功)的时间,超出抛出connect timeout
+                .setConnectTimeout(connTimeOut)
+                //从连接池中获取连接的超时时间,超时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
+                .setConnectionRequestTimeout(connReqTimeOut)
+                .build();
+
+        return HttpClientBuilder.create()
+                .setDefaultRequestConfig(requestConfig)
+                .setConnectionManager(connectionManager)
+                .build();
+    }
+}

+ 21 - 0
src/main/java/com/cdu/lys/graduation/config/ScheduleConfig.java

@@ -0,0 +1,21 @@
+package com.cdu.lys.graduation.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.SchedulingConfigurer;
+import org.springframework.scheduling.config.ScheduledTaskRegistrar;
+
+import java.util.concurrent.Executors;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/15 14:16
+ */
+@Configuration
+public class ScheduleConfig implements SchedulingConfigurer {
+
+    @Override
+    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
+
+        taskRegistrar.setScheduler(Executors.newScheduledThreadPool(3));
+    }
+}

+ 37 - 0
src/main/java/com/cdu/lys/graduation/config/SwaggerConfig.java

@@ -0,0 +1,37 @@
+package com.cdu.lys.graduation.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+/**
+ * swagger 配置
+ * @author liyinsong
+ * @date 2022/1/4 21:40
+ */
+@Configuration
+@EnableSwagger2
+public class SwaggerConfig {
+    @Bean
+    public Docket createRestApi(){
+        return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
+                .select()
+                .apis(RequestHandlerSelectors.any())
+                .paths(PathSelectors.any()).build();
+    }
+
+    private ApiInfo apiInfo(){
+        return new ApiInfoBuilder()
+                .title("EOrder接口文档")
+                .description("这是后台系统的接口文档")
+                .version("1.0")
+                .build();
+    }
+
+}

+ 83 - 0
src/main/java/com/cdu/lys/graduation/config/WebMvcConfig.java

@@ -0,0 +1,83 @@
+package com.cdu.lys.graduation.config;
+
+import com.cdu.lys.graduation.interceptor.AdminLoginInterceptor;
+import com.cdu.lys.graduation.interceptor.FileInterceptor;
+import com.cdu.lys.graduation.interceptor.LoginInterceptor;
+import com.cdu.lys.graduation.interceptor.SystemInterceptor;
+import com.cdu.lys.graduation.types.SystemConstant;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * 拦截器配置
+ *
+ * @author liyinsong
+ * @date 2022/1/8 15:14
+ */
+@Configuration
+public class WebMvcConfig implements WebMvcConfigurer {
+
+    @Autowired
+    private LoginInterceptor loginInterceptor;
+
+    @Autowired
+    private SystemInterceptor systemInterceptor;
+
+    @Autowired
+    private AdminLoginInterceptor adminLoginInterceptor;
+
+    @Autowired
+    private FileInterceptor fileInterceptor;
+
+    /**
+     * 跨域方法
+     */
+    private static final String[] ORIGINS = new String[]{"GET", "POST", "PUT", "DELETE"};
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+
+        /*系统所有请求拦截器*/
+        registry.addInterceptor(systemInterceptor)
+                .addPathPatterns("/**")
+                .excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**",
+                        "/swagger-ui.html/**",
+                        "/test/**",
+                        "/favicon.ico",
+                        "/error",
+                        "/csrf",
+                        "/");
+
+        /*用户登录拦截器*/
+        registry.addInterceptor(loginInterceptor)
+                .addPathPatterns(SystemConstant.SYSTEM_API_ROOT);
+
+        /*管理系统登录拦截器*/
+        registry.addInterceptor(adminLoginInterceptor)
+                .addPathPatterns(SystemConstant.SYSTEM_MANAGE_PATH);
+
+        /*文件上传接口拦截*/
+        registry.addInterceptor(fileInterceptor)
+                .addPathPatterns(SystemConstant.SYSTEM_FILE_UPLOAD_PATH);
+    }
+
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry) {
+
+        registry.addResourceHandler(SystemConstant.SYSTEM_STATIC_PATH)
+                .addResourceLocations("classpath:/static/");
+    }
+
+    @Override
+    public void addCorsMappings(CorsRegistry registry) {
+        registry.addMapping("/**")
+                .allowedOrigins("http://localhost:7999")
+                .allowCredentials(true)
+                .allowedMethods(ORIGINS)
+                .maxAge(3600);
+    }
+}

+ 90 - 0
src/main/java/com/cdu/lys/graduation/controller/admin/AdminBillController.java

@@ -0,0 +1,90 @@
+package com.cdu.lys.graduation.controller.admin;
+
+import com.alibaba.excel.EasyExcel;
+import com.cdu.lys.graduation.admin.bill.bo.BillBO;
+import com.cdu.lys.graduation.admin.bill.converter.BillConverter;
+import com.cdu.lys.graduation.commons.result.ActionResult;
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.domain.admin.vo.BillVO;
+import com.cdu.lys.graduation.repository.entity.BillDO;
+import com.cdu.lys.graduation.types.PageQuery;
+import com.cdu.lys.graduation.types.admin.bill.BillSearchQuery;
+import com.github.pagehelper.Page;
+import com.github.pagehelper.PageHelper;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/4/6 16:33
+ */
+@RestController
+@RequestMapping(value = "/eorder/admin")
+@Api(tags = "管理系统账单接口")
+@Slf4j
+public class AdminBillController {
+
+    @Autowired
+    private BillBO billBO;
+
+    @Autowired
+    private BillConverter converter;
+
+    @ApiOperation("账单列表")
+    @PostMapping(value = "/bill/list", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> list(@RequestBody @Valid PageQuery query) {
+        Page<Object> page = PageHelper.startPage(query.getPageNo(), query.getPageSize());
+        List<BillDO> allBill = billBO.getAll();
+
+        List<BillVO> billVOS = converter.convert2VOList(allBill);
+        PageResult<List<BillVO>> pageResult = new PageResult<>(billVOS);
+        pageResult.setPageNum(page.getPageNum());
+        pageResult.setPageSize(page.getPageSize());
+        pageResult.setTotal(page.getTotal());
+        pageResult.setPages(page.getPages());
+
+        log.info("Admin select bill success");
+        return ActionResult.getSuccessResult(pageResult);
+    }
+
+    @ApiOperation("导出所有账单")
+    @GetMapping(value = "/bill/excel")
+    public void excelAllBill(HttpServletResponse response) throws IOException {
+        List<BillDO> allBill = billBO.getAll();
+
+        List<BillVO> billVOS = converter.convert2VOList(allBill);
+
+        response.setContentType("application/vnd.ms-excel");
+        response.setCharacterEncoding("utf-8");
+        response.setHeader("Content-disposition", "attachment;filename=bill.xlsx");
+        response.setHeader("Set-Cookie", "fileDownload=true; path=/");
+        EasyExcel.write(response.getOutputStream(), BillVO.class).sheet("全部").doWrite(billVOS);
+        log.info("Admin excel bill success");
+    }
+
+    @ApiOperation("搜索")
+    @PostMapping(value = "/bill/search", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> search(@RequestBody @Valid BillSearchQuery query) {
+        Page<Object> page = PageHelper.startPage(query.getPageNo(), query.getPageSize());
+        List<BillDO> byDate = billBO.getByDate(query.getBillDate());
+
+        List<BillVO> billVOS = converter.convert2VOList(byDate);
+        PageResult<List<BillVO>> pageResult = new PageResult<>(billVOS);
+        pageResult.setPageNum(page.getPageNum());
+        pageResult.setPageSize(page.getPageSize());
+        pageResult.setTotal(page.getTotal());
+        pageResult.setPages(page.getPages());
+
+        log.info("Admin search bill success");
+        return ActionResult.getSuccessResult(pageResult);
+    }
+}

+ 82 - 0
src/main/java/com/cdu/lys/graduation/controller/admin/AdminCommentController.java

@@ -0,0 +1,82 @@
+package com.cdu.lys.graduation.controller.admin;
+
+import com.cdu.lys.graduation.admin.comment.bo.AdminCommentBO;
+import com.cdu.lys.graduation.admin.comment.service.AdminCommentService;
+import com.cdu.lys.graduation.commons.result.ActionResult;
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.domain.comment.dto.CommentDTO;
+import com.cdu.lys.graduation.mini.user.service.CommentService;
+import com.cdu.lys.graduation.types.PageQuery;
+import com.cdu.lys.graduation.types.admin.comment.CommentReplyQuery;
+import com.cdu.lys.graduation.types.admin.comment.CommentSearchQuery;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/4/2 10:27
+ */
+@RestController
+@RequestMapping(value = "/eorder/admin")
+@Api(tags = "管理系统评论接口")
+@Validated
+@Slf4j
+public class AdminCommentController {
+
+    @Autowired
+    private CommentService commentService;
+
+    @Autowired
+    private AdminCommentService adminCommentService;
+
+    @Autowired
+    private AdminCommentBO adminCommentBO;
+
+    @ApiOperation("获取用户评论列表")
+    @PostMapping(value = "/comment/list", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> commentList(@RequestBody @Valid PageQuery query) {
+        PageResult<List<CommentDTO>> pageResult = commentService.commentList(query);
+
+        log.info("Admin select all comment list success");
+        return ActionResult.getSuccessResult(pageResult);
+    }
+
+    @ApiOperation("按用户账号搜索")
+    @PostMapping(value = "/comment/search", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> search(@RequestBody @Valid CommentSearchQuery query) {
+        PageResult<List<CommentDTO>> pageResult = adminCommentService.search(query);
+
+        log.info("Admin search user:{} comment list success", query.getUsername());
+        return ActionResult.getSuccessResult(pageResult);
+    }
+
+    @ApiOperation("回复")
+    @PostMapping(value = "/comment/reply", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> reply(@RequestBody @Valid CommentReplyQuery query) {
+        boolean reply = adminCommentBO.reply(query);
+        if (!reply) {
+            return ActionResult.getErrorResult("回复失败");
+        }
+        return ActionResult.getSuccessResult("回复成功");
+    }
+
+    @ApiOperation("删除评论")
+    @GetMapping(value = "/comment/delete", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> delete(@NotNull(message = "id不能为空") Integer id) {
+        boolean delete = adminCommentBO.delete(id);
+        if (!delete) {
+            return ActionResult.getErrorResult("删除失败");
+        }
+        return ActionResult.getSuccessResult("删除成功");
+    }
+
+}

+ 120 - 0
src/main/java/com/cdu/lys/graduation/controller/admin/AdminCouponController.java

@@ -0,0 +1,120 @@
+package com.cdu.lys.graduation.controller.admin;
+
+import com.cdu.lys.graduation.admin.coupon.bo.AdminCouponBO;
+import com.cdu.lys.graduation.admin.coupon.service.AdminCouponService;
+import com.cdu.lys.graduation.commons.result.ActionResult;
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.domain.admin.vo.CouponVO;
+import com.cdu.lys.graduation.repository.entity.CouponDO;
+import com.cdu.lys.graduation.types.PageQuery;
+import com.cdu.lys.graduation.types.admin.coupon.CouponQuery;
+import com.cdu.lys.graduation.types.admin.coupon.CouponSearchQuery;
+import com.cdu.lys.graduation.types.admin.coupon.CouponUpdateQuery;
+import com.cdu.lys.graduation.types.coupon.UserGroupEnum;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/21 21:56
+ */
+@RestController
+@RequestMapping(value = "/eorder/admin")
+@Api(tags = "管理系统优惠券接口")
+@Slf4j
+@Validated
+public class AdminCouponController {
+
+    @Autowired
+    private AdminCouponService adminCouponService;
+
+    @Autowired
+    private AdminCouponBO adminCouponBO;
+
+    @ApiOperation("优惠券列表")
+    @PostMapping(value = "/coupon/list", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> getCouponList(@RequestBody @Valid PageQuery query) {
+        PageResult<List<CouponDO>> pageResult = adminCouponService.getCouponList(query);
+
+        List<CouponDO> data = pageResult.getData();
+        List<CouponVO> couponVOS = new ArrayList<>();
+
+        data.forEach(couponDO -> {
+            CouponVO couponVO = new CouponVO();
+            BeanUtils.copyProperties(couponDO, couponVO);
+            couponVO.setUserType(UserGroupEnum.getMsgByCode(couponDO.getUserType()));
+            couponVOS.add(couponVO);
+        });
+        PageResult<List<CouponVO>> result = new PageResult<>();
+        BeanUtils.copyProperties(pageResult, result);
+        result.setData(couponVOS);
+        log.info("Admin select coupon list success, pageNo:{}, pageSize:{}", query.getPageNo(), query.getPageSize());
+        return ActionResult.getSuccessResult(result);
+    }
+
+    @ApiOperation("根据id获取优惠券")
+    @GetMapping(value = "/coupon/get", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<CouponDO> getCouponById(Integer couponId) {
+        CouponDO coupon = adminCouponBO.getCouponById(couponId);
+        log.info("Admin select coupon success, id:{}", couponId);
+        return ActionResult.getSuccessResult(coupon);
+    }
+
+    @ApiOperation("更新优惠券")
+    @PostMapping(value = "/coupon/update", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Boolean> updateCoupon(@RequestBody @Valid CouponUpdateQuery couponUpdateQuery) {
+
+        int i = adminCouponBO.updateCoupon(couponUpdateQuery);
+        log.info("Admin update coupon success, rows:{}", i);
+        return ActionResult.getSuccessResult("更新成功");
+    }
+
+    @ApiOperation("删除优惠券")
+    @GetMapping(value = "/coupon/delete", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> deleteCoupon(@NotNull Integer couponId) {
+        int i = adminCouponBO.deleteCoupon(couponId);
+        log.info("Admin delete coupon success, rows:{}", i);
+        return ActionResult.getSuccessResult("删除成功");
+    }
+
+    @ApiOperation("添加优惠券")
+    @PostMapping(value = "/coupon/add", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> addCoupon(@RequestBody @Valid CouponQuery query) {
+        int i = adminCouponBO.addCoupon(query);
+        log.info("Admin add coupon success, rows:{}", i);
+        return ActionResult.getSuccessResult("添加成功");
+    }
+
+    @ApiOperation("搜索")
+    @PostMapping(value = "/coupon/search", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<PageResult<List<CouponVO>>> searchCoupon(@RequestBody CouponSearchQuery query) {
+        PageResult<List<CouponDO>> pageResult = adminCouponService.searchCoupon(query);
+
+        List<CouponDO> data = pageResult.getData();
+        List<CouponVO> couponVOS = new ArrayList<>();
+
+        data.forEach(couponDO -> {
+            CouponVO couponVO = new CouponVO();
+            BeanUtils.copyProperties(couponDO, couponVO);
+            couponVO.setUserType(UserGroupEnum.getMsgByCode(couponDO.getUserType()));
+            couponVOS.add(couponVO);
+        });
+        PageResult<List<CouponVO>> result = new PageResult<>();
+        BeanUtils.copyProperties(pageResult, result);
+        result.setData(couponVOS);
+
+        log.info("Admin search coupon list success, pageNo:{}, pageSize:{}, couponName:{}, userType:{}", query.getPageNo(), query.getPageSize(), query.getCouponName(), query.getUserType());
+        return ActionResult.getSuccessResult(result);
+    }
+}

+ 115 - 0
src/main/java/com/cdu/lys/graduation/controller/admin/AdminGoodsController.java

@@ -0,0 +1,115 @@
+package com.cdu.lys.graduation.controller.admin;
+
+import com.cdu.lys.graduation.admin.goods.bo.AdminGoodsBO;
+import com.cdu.lys.graduation.admin.goods.convertor.GoodsConverter;
+import com.cdu.lys.graduation.admin.goods.service.AdminGoodsService;
+import com.cdu.lys.graduation.commons.result.ActionResult;
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.domain.admin.vo.AdminGoodsPictureVO;
+import com.cdu.lys.graduation.domain.admin.vo.AdminGoodsVO;
+import com.cdu.lys.graduation.repository.entity.GoodsDO;
+import com.cdu.lys.graduation.repository.entity.GoodsPictureDO;
+import com.cdu.lys.graduation.types.PageQuery;
+import com.cdu.lys.graduation.types.admin.goods.GoodsQuery;
+import com.cdu.lys.graduation.types.admin.goods.UpdateGoodsQuery;
+import com.cdu.lys.graduation.types.admin.goods.type.GoodsSearchQuery;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/21 21:58
+ */
+@RestController
+@RequestMapping(value = "/eorder/admin")
+@Api(tags = "管理系统商品接口")
+@Slf4j
+public class AdminGoodsController {
+
+    @Autowired
+    private AdminGoodsService adminGoodsService;
+
+    @Autowired
+    private AdminGoodsBO adminGoodsBO;
+
+    @Autowired
+    private GoodsConverter goodsConverter;
+
+    @ApiOperation(value = "商品列表")
+    @PostMapping(value = "/goods/list", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> getGoodsList(@RequestBody @Valid PageQuery query) {
+        PageResult<List<GoodsDO>> pageResult = adminGoodsService.getGoodsList(query);
+
+        PageResult<List<AdminGoodsVO>> result = goodsConverter.convert2GoodsPageVo(pageResult);
+        log.info("Admin select goods list success, pageNo:{}, pageSize:{}", query.getPageNo(), query.getPageSize());
+        return ActionResult.getSuccessResult(result);
+    }
+
+    @ApiOperation(value = "删除商品")
+    @GetMapping(value = "/goods/delete", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> deleteGoods(Integer goodsId) {
+        boolean res = adminGoodsService.deleteGoods(goodsId);
+
+        log.info("Admin delete goods:[{}] success", goodsId);
+        return ActionResult.getSuccessResult("删除成功");
+    }
+
+    @ApiOperation(value = "添加商品")
+    @PostMapping(value = "/goods/add", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Integer> addGoods(@RequestBody @Valid GoodsQuery goods) {
+        int id = adminGoodsService.addGoods(goods);
+        log.info("Admin add goods success,id:{}", id);
+        return ActionResult.getSuccessResult("添加成功");
+    }
+
+    @PostMapping(value = "/goods/upload", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> upload() {
+        log.info("11111111111111");
+        return ActionResult.getSuccessResult("成功");
+    }
+
+    @ApiOperation(value = "修改商品")
+    @PostMapping(value = "/goods/update", produces = MediaType.APPLICATION_JSON_VALUE)
+    @CacheEvict(value = "Goods:ID", key = "#goods.id")
+    public ActionResult<Object> updateGoods(@RequestBody @Valid UpdateGoodsQuery goods) {
+        int i = adminGoodsService.updateGoods(goods);
+        log.info("Admin update goods success, rows:{}", i);
+        return ActionResult.getSuccessResult("更新成功");
+    }
+
+    @ApiOperation("搜索")
+    @PostMapping(value = "/goods/search", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<PageResult<List<AdminGoodsVO>>> search(@RequestBody @Valid GoodsSearchQuery query) {
+        PageResult<List<GoodsDO>> search = adminGoodsService.search(query);
+
+        PageResult<List<AdminGoodsVO>> result = goodsConverter.convert2GoodsPageVo(search);
+        log.info("Admin search goods list success, pageNo:{}, pageSize:{}", query.getPageNo(), query.getPageSize());
+        return ActionResult.getSuccessResult(result);
+    }
+
+    @ApiOperation("获取商品图片")
+    @GetMapping(value = "/goods/picture/get", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> getGoodsPictures(@NotNull(message = "商品id不能为空") Integer goodsId) {
+        List<GoodsPictureDO> goodsPictures = adminGoodsBO.getGoodsPicturesById(goodsId);
+
+        List<AdminGoodsPictureVO> goodsPictureVOS = new ArrayList<>();
+        goodsPictures.forEach(goodsPictureDO -> {
+            AdminGoodsPictureVO goodsPictureVO = new AdminGoodsPictureVO();
+            BeanUtils.copyProperties(goodsPictureDO, goodsPictureVO);
+            goodsPictureVOS.add(goodsPictureVO);
+        });
+        log.info("Admin get goods picture success");
+        return ActionResult.getSuccessResult(goodsPictureVOS);
+    }
+}

+ 67 - 0
src/main/java/com/cdu/lys/graduation/controller/admin/AdminGoodsOptionController.java

@@ -0,0 +1,67 @@
+package com.cdu.lys.graduation.controller.admin;
+
+import com.cdu.lys.graduation.admin.goods.bo.AdminGoodsOptionBO;
+import com.cdu.lys.graduation.admin.goods.service.AdminGoodsOptionService;
+import com.cdu.lys.graduation.commons.result.ActionResult;
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.domain.admin.vo.AdminGoodsOption;
+import com.cdu.lys.graduation.types.PageQuery;
+import com.cdu.lys.graduation.types.admin.goods.option.GoodsOptionQuery;
+import com.cdu.lys.graduation.types.admin.goods.option.GoodsOptionSearchQuery;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+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 javax.validation.Valid;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/26 19:15
+ */
+@RestController
+@RequestMapping(value = "/eorder/admin")
+@Api(tags = "管理系统商品规格接口")
+@Slf4j
+public class AdminGoodsOptionController {
+
+
+    @Autowired
+    private AdminGoodsOptionService adminGoodsOptionService;
+
+    @Autowired
+    private AdminGoodsOptionBO adminGoodsOptionBO;
+
+    @PostMapping(value = "/goods/option/list", produces = MediaType.APPLICATION_JSON_VALUE)
+    @ApiOperation("得到规格列表")
+    public ActionResult<Object> getOptionsList(@RequestBody @Valid PageQuery query) {
+        PageResult<List<AdminGoodsOption>> options = adminGoodsOptionService.getAllOptions(query);
+
+        log.info("Admin select goodsOption success");
+        return ActionResult.getSuccessResult(options);
+    }
+
+    @ApiOperation("搜索")
+    @PostMapping(value = "/goods/option/search", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<PageResult<List<AdminGoodsOption>>> search(@RequestBody @Valid GoodsOptionSearchQuery query) {
+        PageResult<List<AdminGoodsOption>> options = adminGoodsOptionService.search(query);
+
+        log.info("Admin select goodsOption success");
+        return ActionResult.getSuccessResult(options);
+    }
+
+    @ApiOperation("添加选规格")
+    @PostMapping(value = "/goods/option/add", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> addGoodsOption(@RequestBody @Valid GoodsOptionQuery query) {
+
+        int i = adminGoodsOptionBO.addGoodsOption(query);
+        log.info("Admin add goods type success");
+        return ActionResult.getSuccessResult("成功");
+    }
+}

+ 110 - 0
src/main/java/com/cdu/lys/graduation/controller/admin/AdminGoodsTypeController.java

@@ -0,0 +1,110 @@
+package com.cdu.lys.graduation.controller.admin;
+
+import com.cdu.lys.graduation.admin.goods.bo.AdminGoodsTypeBO;
+import com.cdu.lys.graduation.admin.goods.service.AdminGoodsTypeService;
+import com.cdu.lys.graduation.commons.result.ActionResult;
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.repository.entity.GoodsTypeDO;
+import com.cdu.lys.graduation.types.PageQuery;
+import com.cdu.lys.graduation.types.admin.goods.type.GoodsTypeQuery;
+import com.cdu.lys.graduation.types.admin.goods.type.GoodsTypeSearchQuery;
+import com.cdu.lys.graduation.types.admin.goods.type.GoodsTypeUpdateQuery;
+import com.github.pagehelper.Page;
+import com.github.pagehelper.PageHelper;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/24 23:08
+ */
+@RestController
+@RequestMapping(value = "/eorder/admin")
+@Api(tags = "管理系统商品类型接口")
+@Slf4j
+public class AdminGoodsTypeController {
+
+
+    @Autowired
+    private AdminGoodsTypeService adminGoodsTypeService;
+
+    @Autowired
+    private AdminGoodsTypeBO adminGoodsTypeBO;
+
+    @ApiOperation("得到所有商品类型")
+    @GetMapping(value = "/goods/type", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<List<GoodsTypeDO>> getGoodsType() {
+        List<GoodsTypeDO> goodsTypes = adminGoodsTypeBO.getAll();
+        log.info("Admin select goods types success");
+        return ActionResult.getSuccessResult(goodsTypes);
+    }
+
+    @ApiOperation("得到商品类型分页数据")
+    @PostMapping(value = "/goods/type/page", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> getGoodsType(@RequestBody @Valid PageQuery query) {
+        PageResult<List<GoodsTypeDO>> goodsTypeList = adminGoodsTypeService.getGoodsTypeList(query);
+
+        log.info("Admin select goods types success");
+        return ActionResult.getSuccessResult(goodsTypeList);
+    }
+
+    @ApiOperation("更新商品类型")
+    @PostMapping(value = "/goods/type/update", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> updateGoodsType(@RequestBody @Valid GoodsTypeUpdateQuery query) {
+        int i = adminGoodsTypeBO.updateById(query);
+        if (i > 0) {
+            log.info("Admin update goods types success");
+            return ActionResult.getSuccessResult("更新成功");
+        }
+        log.info("Admin update goods types failed");
+        return ActionResult.getErrorResult("更新失败");
+    }
+
+    @ApiOperation("添加商品类型")
+    @PostMapping(value = "/goods/type/add", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> addGoodsType(@RequestBody @Valid GoodsTypeQuery query) {
+        int i = adminGoodsTypeBO.add(query);
+        if (i > 0) {
+            log.info("Admin add goods types success");
+            return ActionResult.getSuccessResult("添加成功");
+        }
+        log.info("Admin add goods types failed");
+        return ActionResult.getErrorResult("添加失败");
+    }
+
+    @ApiOperation("删除商品类型")
+    @GetMapping(value = "/goods/type/delete", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> deleteGoodsType(@NotNull(message = "id不能为null") Integer id) {
+        int i = adminGoodsTypeBO.delete(id);
+        if (i > 0) {
+            log.info("Admin delete goods types success");
+            return ActionResult.getSuccessResult("删除成功");
+        }
+        log.info("Admin delete goods types failed");
+        return ActionResult.getErrorResult("删除失败");
+    }
+
+    @ApiOperation("搜索商品")
+    @PostMapping(value = "/goods/type/search", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> searchGoodsType(@RequestBody @Valid GoodsTypeSearchQuery query) {
+
+        Page<Object> page = PageHelper.startPage(query.getPageNo(), query.getPageSize());
+        List<GoodsTypeDO> search = adminGoodsTypeBO.searchByType(query.getType());
+        PageResult<List<GoodsTypeDO>> pageResult = new PageResult<>(search);
+        pageResult.setPageNum(page.getPageNum());
+        pageResult.setPageSize(page.getPageSize());
+        pageResult.setTotal(page.getTotal());
+        pageResult.setPages(page.getPages());
+
+        log.info("Admin search goodsType success");
+        return ActionResult.getSuccessResult(pageResult);
+    }
+}

+ 63 - 0
src/main/java/com/cdu/lys/graduation/controller/admin/AdminIndexController.java

@@ -0,0 +1,63 @@
+package com.cdu.lys.graduation.controller.admin;
+
+import com.cdu.lys.graduation.admin.record.service.RecordService;
+import com.cdu.lys.graduation.commons.result.ActionResult;
+import com.cdu.lys.graduation.domain.admin.vo.RecordVO;
+import com.cdu.lys.graduation.redis.RedisService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author liyinsong
+ * @date 2022/4/13 10:07
+ */
+@RestController
+@RequestMapping(value = "/eorder/admin")
+@Api(tags = "管理系统主页接口")
+@Slf4j
+public class AdminIndexController {
+
+    @Autowired
+    private RedisService redisService;
+
+    @Autowired
+    private RecordService recordService;
+
+    @GetMapping(value = "/index/visit", produces = MediaType.APPLICATION_JSON_VALUE)
+    @ApiOperation("获取日访问量")
+    public ActionResult<Object> getDailyVisit() {
+        RecordVO dailyVisit = recordService.getDailyVisit();
+        log.info("Admin get daily visit number success");
+        return ActionResult.getSuccessResult("成功", dailyVisit);
+    }
+
+    @GetMapping(value = "/index/sale", produces = MediaType.APPLICATION_JSON_VALUE)
+    @ApiOperation("获取日销量")
+    public ActionResult<Object> getDailySale() {
+        RecordVO dailySales = recordService.getDailySales();
+        log.info("Admin get daily sales success");
+        return ActionResult.getSuccessResult("成功", dailySales);
+    }
+
+    @GetMapping(value = "/index/income", produces = MediaType.APPLICATION_JSON_VALUE)
+    @ApiOperation("获取日收入")
+    public ActionResult<Object> getDailyIncome() {
+        RecordVO dailyIncome = recordService.getDailyIncome();
+        log.info("Admin get daily sales success");
+        return ActionResult.getSuccessResult("成功", dailyIncome);
+    }
+
+    @GetMapping(value = "/index/comment", produces = MediaType.APPLICATION_JSON_VALUE)
+    @ApiOperation("获取日评论")
+    public ActionResult<Object> getDailyComment() {
+        RecordVO commentNum = recordService.getDailyCommentNum();
+        log.info("Admin get daily comment success");
+        return ActionResult.getSuccessResult("成功", commentNum);
+    }
+}

+ 107 - 0
src/main/java/com/cdu/lys/graduation/controller/admin/AdminLoginController.java

@@ -0,0 +1,107 @@
+package com.cdu.lys.graduation.controller.admin;
+
+import com.cdu.lys.graduation.admin.login.service.AdminLoginService;
+import com.cdu.lys.graduation.commons.result.ActionResult;
+import com.cdu.lys.graduation.commons.utils.JWTUtils;
+import com.cdu.lys.graduation.domain.admin.TokenValue;
+import com.cdu.lys.graduation.domain.user.dto.UserDTO;
+import com.cdu.lys.graduation.domain.user.vo.AdminUserLoginVO;
+import com.cdu.lys.graduation.redis.RedisService;
+import com.cdu.lys.graduation.types.SystemConstant;
+import com.cdu.lys.graduation.types.user.LoginQuery;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 管理系统接口
+ *
+ * @author liyinsong
+ * @date 2022/3/16 17:25
+ */
+@RestController
+@RequestMapping(value = "/eorder/admin")
+@Api(tags = "管理系统登录接口")
+@Slf4j
+public class AdminLoginController {
+
+    @Autowired
+    private AdminLoginService adminLoginService;
+
+    @Autowired
+    private RedisService redisService;
+
+    @Autowired
+    private RedisTemplate<String,Object> redisTemplate;
+
+    @Value("${system.order.secretKey}")
+    private String secretKey;
+
+
+    @PostMapping(value = "/login", produces = MediaType.APPLICATION_JSON_VALUE)
+    @ApiOperation("管理系统登录")
+    public ActionResult<Object> login(@RequestBody @Valid LoginQuery query) {
+        UserDTO userDTO = adminLoginService.login(query);
+//        JWT.create().withAudience(query.getUsername()).sign(Algorithm.HMAC256(query.getPassword()));
+
+        if (userDTO == null) {
+            log.info("Admin login failed, username:{}", query.getUsername());
+            return ActionResult.getErrorResult("登录失败");
+        }
+        Map<String, Object> claims = new HashMap<>();
+        claims.put("username", query.getUsername());
+        String token = JWTUtils.createJWT("admin", TimeUnit.DAYS.toMillis(1), claims, secretKey);
+
+        //存入redis FIXME 可能不用存入redis
+        redisTemplate.opsForValue().set(SystemConstant.ADMIN_LOGIN_TOKEN_KEY + query.getUsername(), new TokenValue(token), SystemConstant.SYSTEM_LOGIN_TIMEOUT, TimeUnit.DAYS);
+
+        AdminUserLoginVO loginVO = new AdminUserLoginVO();
+        BeanUtils.copyProperties(userDTO, loginVO);
+        loginVO.setToken(token);
+
+        log.info("Admin login success, username:{}", query.getUsername());
+        return ActionResult.getSuccessResult("登录成功", loginVO);
+    }
+
+    @ApiOperation("注销登录")
+    @GetMapping(value = "/logout", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> wxLogout(@RequestHeader String token) {
+        String username = (String) JWTUtils.parseJWT(token, secretKey).get("username");
+
+        String key = SystemConstant.ADMIN_LOGIN_TOKEN_KEY + username;
+        Boolean delete = redisTemplate.delete(key);
+
+        if (delete) {
+            log.info("Admin delete key [{}] success", key);
+            return ActionResult.getSuccessResult("注销成功");
+        } else {
+            log.info("Admin delete key [{}] fail", token);
+            return ActionResult.getErrorResult("注销成功");
+        }
+    }
+
+    @GetMapping(value = "/token/check", produces = MediaType.APPLICATION_JSON_VALUE)
+    @ApiOperation("校验登录token是否失效")
+    public ActionResult<Object> checkSessionExpire(@RequestHeader("token") String token) {
+
+        boolean valid = redisService.checkAdminTokenValid(token);
+        if (!valid) {
+            log.warn("token is invalid");
+            return ActionResult.getErrorResult("不合法token");
+        }
+        log.info("token is valid");
+        return ActionResult.getSuccessResult("合法token");
+    }
+
+}

+ 71 - 0
src/main/java/com/cdu/lys/graduation/controller/admin/AdminMerchantController.java

@@ -0,0 +1,71 @@
+package com.cdu.lys.graduation.controller.admin;
+
+import com.cdu.lys.graduation.admin.merchant.bo.MerchantBO;
+import com.cdu.lys.graduation.admin.merchant.bo.MerchantRealPictureBO;
+import com.cdu.lys.graduation.admin.merchant.convertor.MerchantConvertor;
+import com.cdu.lys.graduation.commons.result.ActionResult;
+import com.cdu.lys.graduation.domain.admin.vo.AdminMerchantVO;
+import com.cdu.lys.graduation.repository.entity.MerchantDO;
+import com.cdu.lys.graduation.repository.entity.MerchantRealPictureDO;
+import com.cdu.lys.graduation.types.admin.merchant.MerchantQuery;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/4/14 21:36
+ */
+@RestController
+@RequestMapping(value = "/eorder/admin")
+@Api(tags = "管理系统商家设置接口")
+@Slf4j
+public class AdminMerchantController {
+
+    @Autowired
+    private MerchantBO merchantBO;
+
+    @Autowired
+    private MerchantRealPictureBO merchantRealPictureBO;
+
+    @Autowired
+    private MerchantConvertor convertor;
+
+    @ApiOperation("获取商户信息")
+    @GetMapping(value = "/merchant/get", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<AdminMerchantVO> getMerchantInfo() {
+        MerchantDO merchantDO = merchantBO.get();
+        AdminMerchantVO adminMerchantVO = new AdminMerchantVO();
+
+        List<MerchantRealPictureDO> merchantRealPictureDOS = merchantRealPictureBO.get();
+        BeanUtils.copyProperties(merchantDO, adminMerchantVO);
+        adminMerchantVO.setRealPictureUrl(convertor.convert2MerchantRealPictureVO(merchantRealPictureDOS));
+
+        log.info("Admin get merchant info success");
+        return ActionResult.getSuccessResult(adminMerchantVO);
+    }
+
+    @ApiOperation("修改商户信息")
+    @PostMapping(value = "/merchant/update", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> modifyMerchant(@RequestBody @Valid MerchantQuery query) {
+        MerchantDO merchantDO = new MerchantDO();
+        BeanUtils.copyProperties(query, merchantDO);
+        int i = merchantBO.update(merchantDO);
+        merchantRealPictureBO.update(convertor.convert2PictureDO(query.getRealPictures()));
+
+        if (i > 0) {
+            log.info("Admin update merchant info success");
+            return ActionResult.getSuccessResult("更新成功");
+        }
+        log.warn("Admin update merchant info fail");
+        return ActionResult.getSuccessResult("更新失败");
+    }
+
+}

+ 117 - 0
src/main/java/com/cdu/lys/graduation/controller/admin/AdminOrderController.java

@@ -0,0 +1,117 @@
+package com.cdu.lys.graduation.controller.admin;
+
+import com.cdu.lys.graduation.admin.order.bo.AdminOrderFormInfoBO;
+import com.cdu.lys.graduation.admin.order.converter.OrderDataConverter;
+import com.cdu.lys.graduation.admin.order.converter.OrderInfoDataConverter;
+import com.cdu.lys.graduation.admin.order.service.AdminOrderService;
+import com.cdu.lys.graduation.commons.result.ActionResult;
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.domain.admin.vo.OrderFormInfoVO;
+import com.cdu.lys.graduation.domain.admin.vo.OrderFormVO;
+import com.cdu.lys.graduation.repository.entity.OrderFormDO;
+import com.cdu.lys.graduation.repository.entity.OrderFormInfoDO;
+import com.cdu.lys.graduation.types.PageQuery;
+import com.cdu.lys.graduation.types.admin.order.OrderSearchQuery;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/21 21:59
+ */
+@RestController
+@RequestMapping(value = "/eorder/admin")
+@Api(tags = "管理系统订单接口")
+@Validated
+@Slf4j
+public class AdminOrderController {
+
+    @Autowired
+    private OrderDataConverter orderDataConverter;
+
+    @Autowired
+    private AdminOrderService adminOrderService;
+
+    @Autowired
+    private AdminOrderFormInfoBO adminOrderFormInfoBO;
+
+    @Autowired
+    private OrderInfoDataConverter orderInfoDataConverter;
+
+    @ApiOperation("所有订单列表")
+    @PostMapping(value = "/order/list/all", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> getOrderList(@RequestBody @Valid PageQuery query) {
+        PageResult<List<OrderFormDO>> pageResult = adminOrderService.getAllOrders(query);
+
+        PageResult<List<OrderFormVO>> result = orderDataConverter.convertOrderPageDO2VO(pageResult);
+
+        log.info("Admin select order list success, pageNo:{}, pageSize:{}", query.getPageNo(), query.getPageSize());
+        return ActionResult.getSuccessResult(result);
+    }
+
+    @ApiOperation("未完成订单")
+    @PostMapping(value = "/order/list/undone", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<PageResult<List<OrderFormVO>>> getUndoneOrder(@RequestBody @Valid PageQuery query) {
+        PageResult<List<OrderFormDO>> pageResult = adminOrderService.getUndoneOrders(query);
+
+        PageResult<List<OrderFormVO>> result = orderDataConverter.convertOrderPageDO2VO(pageResult);
+
+        log.info("Admin select order list success, pageNo:{}, pageSize:{}", query.getPageNo(), query.getPageSize());
+        return ActionResult.getSuccessResult(result);
+    }
+
+    @ApiOperation("订单详情")
+    @GetMapping(value = "/order/detail", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> getOrderDetailByOrderNum(@NotBlank String orderNum) {
+        List<OrderFormInfoDO> orderFormInfoDOS = adminOrderFormInfoBO.getByOrderNum(orderNum);
+        List<OrderFormInfoVO> orderFormInfoVOS = orderInfoDataConverter.convertOrderInfoDO2VO(orderFormInfoDOS);
+
+        log.info("Admin select order detail success, orderNum:{}", orderNum);
+        return ActionResult.getSuccessResult(orderFormInfoVOS);
+    }
+
+    @ApiOperation("配送单个商品")
+    @GetMapping(value = "/order/delivery/one", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> deliveryOne(@NotNull Integer orderInfoId) {
+        boolean res = adminOrderService.deliveryOne(orderInfoId);
+        if (!res) {
+            log.info("Admin delivery one failed, orderFormInfoId:{}", orderInfoId);
+            return ActionResult.getErrorResult("配送失败");
+        }
+        log.info("Admin delivery one success, orderFormInfoId:{}", orderInfoId);
+        return ActionResult.getSuccessResult("配送成功");
+    }
+
+    @ApiOperation("配送所有商品")
+    @GetMapping(value = "/order/delivery/all")
+    public ActionResult<Object> deliveryAll(@NotBlank(message = "订单号不能为空") String orderNum) {
+        boolean res = adminOrderService.deliveryAll(orderNum);
+        if (!res) {
+            log.info("Admin delivery order failed, orderNum:{}", orderNum);
+            return ActionResult.getErrorResult("配送失败");
+        }
+        log.info("Admin delivery order success, orderNum:{}", orderNum);
+        return ActionResult.getSuccessResult("配送成功");
+    }
+
+    @ApiOperation("搜索")
+    @PostMapping(value = "/order/search", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> search(@RequestBody @Valid OrderSearchQuery query) {
+        PageResult<List<OrderFormDO>> pageResult = adminOrderService.search(query);
+
+        PageResult<List<OrderFormVO>> result = orderDataConverter.convertOrderPageDO2VO(pageResult);
+
+        log.info("Admin search order list success, pageNo:{}, pageSize:{}", query.getPageNo(), query.getPageSize());
+        return ActionResult.getSuccessResult(result);
+    }
+}

+ 98 - 0
src/main/java/com/cdu/lys/graduation/controller/coupon/CouponController.java

@@ -0,0 +1,98 @@
+package com.cdu.lys.graduation.controller.coupon;
+
+import com.cdu.lys.graduation.commons.result.ActionResult;
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.domain.coupon.dto.CouponDTO;
+import com.cdu.lys.graduation.domain.coupon.vo.CouponVO;
+import com.cdu.lys.graduation.domain.user.wx.LoginUser;
+import com.cdu.lys.graduation.mini.coupon.service.CouponService;
+import com.cdu.lys.graduation.redis.RedisService;
+import com.cdu.lys.graduation.types.PageQuery;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/2/28 14:21
+ */
+@RestController
+@RequestMapping(value = "/eorder/app/coupon")
+@Api(tags = "coupon接口")
+@Slf4j
+public class CouponController {
+
+    @Autowired
+    private CouponService couponService;
+
+    @Autowired
+    private RedisService redisService;
+
+    /**
+     * 登录用户获取优惠券
+     *
+     * @param token 登录状态
+     * @return 优惠券列表
+     */
+    @PostMapping(value = "/get", produces = MediaType.APPLICATION_JSON_VALUE)
+    @ApiOperation("查询优惠券")
+    public ActionResult<PageResult<List<CouponVO>>> getCoupon(@RequestBody @Valid PageQuery query, @RequestHeader("token") String token) {
+        LoginUser loginValue = redisService.getLoginValue(token);
+        Integer userId = loginValue.getId();
+
+        PageResult<List<CouponDTO>> pageResult = couponService.getCoupons(query, userId);
+        PageResult<List<CouponVO>> result = convertPageDTO2PageVO(pageResult);
+
+        log.info("select coupons success");
+        return ActionResult.getSuccessResult(result);
+    }
+
+    /**
+     * 未登录用户获取优惠券
+     *
+     * @return 优惠券
+     */
+    @PostMapping(value = "/visit/get", produces = MediaType.APPLICATION_JSON_VALUE)
+    @ApiOperation("访客查询优惠券")
+    public ActionResult<Object> getVisitorCoupon(@RequestBody PageQuery query) {
+        PageResult<List<CouponDTO>> pageResult = couponService.getVisitorCoupons(query);
+        PageResult<List<CouponVO>> result = convertPageDTO2PageVO(pageResult);
+
+        log.info("select visitor coupon success");
+        return ActionResult.getSuccessResult(result);
+    }
+
+
+    /**
+     * 将DTO转为VO
+     * @param pageResult DTO
+     * @return VO
+     */
+    private PageResult<List<CouponVO>> convertPageDTO2PageVO(PageResult<List<CouponDTO>> pageResult) {
+        List<CouponDTO> couponDTOList = pageResult.getData();
+
+        List<CouponVO> couponVOList = new ArrayList<>();
+        if (!CollectionUtils.isEmpty(couponDTOList)) {
+            couponDTOList.forEach(couponDTO -> {
+                CouponVO couponVO = new CouponVO();
+                BeanUtils.copyProperties(couponDTO, couponVO);
+                couponVOList.add(couponVO);
+            });
+        }
+
+        PageResult<List<CouponVO>> result = new PageResult<>(couponVOList);
+        BeanUtils.copyProperties(pageResult, result);
+        result.setData(couponVOList);
+
+        return result;
+    }
+}

+ 99 - 0
src/main/java/com/cdu/lys/graduation/controller/file/FileController.java

@@ -0,0 +1,99 @@
+package com.cdu.lys.graduation.controller.file;
+
+import com.cdu.lys.graduation.commons.result.ActionResult;
+import com.cdu.lys.graduation.commons.result.UploadFileResponse;
+import com.cdu.lys.graduation.file.FileService;
+import com.cdu.lys.graduation.types.SystemConstant;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.Resource;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.constraints.NotNull;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/28 21:59
+ */
+@Api(tags = "文件接口")
+@RestController
+@RequestMapping("/eorder/file")
+@Slf4j
+@Validated
+public class FileController {
+
+    @Autowired
+    private FileService fileService;
+
+    @ApiOperation("图片上传")
+    @PostMapping(value = "/upload", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<UploadFileResponse> uploadFile(@NotNull(message = "文件不能为空") MultipartFile file) {
+
+        String fileName = fileService.storeFile(file);
+//        String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
+//                .path(SystemConstant.SYSTEM_DOWNLOAD_PATH)
+//                .path(fileName)
+//                .toUriString();
+
+        String fileDownloadUri = SystemConstant.SYSTEM_DOWNLOAD_PATH + fileName;
+        UploadFileResponse response = new UploadFileResponse(fileName, fileDownloadUri,
+                file.getContentType(), file.getSize());
+        return ActionResult.getSuccessResult(response);
+    }
+
+//    @PostMapping("/uploadMultipleFiles")
+    public ActionResult<List<UploadFileResponse>> uploadMultipleFiles(@RequestParam("files") MultipartFile[] files) {
+
+        List<UploadFileResponse> responses = new ArrayList<>();
+
+        UriComponentsBuilder path = ServletUriComponentsBuilder.fromCurrentContextPath()
+                .path(SystemConstant.SYSTEM_DOWNLOAD_PATH);
+        Arrays.stream(files).forEach(file->{
+            String filename = fileService.storeFile(file);
+            UploadFileResponse response = new UploadFileResponse(filename, path.path(filename).toUriString(),
+                    file.getContentType(), file.getSize());
+            responses.add(response);
+        });
+
+        return ActionResult.getSuccessResult(responses);
+    }
+
+    @ApiOperation("文件下载")
+    @GetMapping("/download/{fileName:.+}")
+    public ResponseEntity<Resource> downloadFile(@PathVariable String fileName, HttpServletRequest request) {
+        // Load file as Resource
+        Resource resource = fileService.loadFileAsResource(fileName);
+
+        // Try to determine file's content type
+        String contentType = null;
+        try {
+            contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
+        } catch (IOException ex) {
+            log.warn("Could not determine file type.");
+        }
+
+        // Fallback to the default content type if type could not be determined
+        if(contentType == null) {
+            contentType = "application/octet-stream";
+        }
+
+        return ResponseEntity.ok()
+                .contentType(MediaType.parseMediaType(contentType))
+                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
+                .body(resource);
+    }
+}

+ 231 - 0
src/main/java/com/cdu/lys/graduation/controller/goods/GoodsController.java

@@ -0,0 +1,231 @@
+package com.cdu.lys.graduation.controller.goods;
+
+import com.cdu.lys.graduation.commons.result.ActionResult;
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.domain.goods.dto.GoodsDTO;
+import com.cdu.lys.graduation.domain.goods.dto.GoodsListDTO;
+import com.cdu.lys.graduation.domain.goods.dto.GoodsOptionDTO;
+import com.cdu.lys.graduation.domain.goods.dto.GoodsTypeDTO;
+import com.cdu.lys.graduation.domain.goods.vo.*;
+import com.cdu.lys.graduation.mini.goods.service.GoodsService;
+import com.cdu.lys.graduation.redis.RedisService;
+import com.cdu.lys.graduation.types.PageQuery;
+import com.cdu.lys.graduation.types.exception.ErrorType;
+import com.cdu.lys.graduation.types.exception.ParamException;
+import com.cdu.lys.graduation.types.goods.GoodsListQuery;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.http.MediaType;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotBlank;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author liyinsong
+ * @date 2022/2/8 11:49
+ */
+@RestController
+@Api(tags = "Goods接口")
+@RequestMapping("/eorder/app/goods")
+@Validated
+@Slf4j
+public class GoodsController {
+
+    @Autowired
+    private GoodsService goodsService;
+
+    @Autowired
+    private RedisService redisService;
+
+    @ApiOperation("查询商品列表list")
+    @PostMapping(value = "/list", produces = MediaType.APPLICATION_JSON_VALUE)
+    @Cacheable(value = "Goods:List", key = "#pageQuery.pageNo+''+#pageQuery.pageSize")
+    public ActionResult<PageResult<List<GoodsListVO>>> selectGoodsList(@RequestBody @Valid PageQuery pageQuery) {
+        PageResult<List<GoodsListDTO>> goodsList = goodsService.selectGoodsList(pageQuery.getPageNo(), pageQuery.getPageSize());
+        PageResult<List<GoodsListVO>> result = this.getGoodsListPageVO(goodsList);
+
+        log.info("select goods list success, PageQuery:[ {} ]", pageQuery);
+        return ActionResult.getSuccessResult(result);
+    }
+
+    @ApiOperation("查询所有商品类型")
+    @GetMapping(value = "/type/list", produces = MediaType.APPLICATION_JSON_VALUE)
+    @Cacheable(value = "Goods:Types")
+    public ActionResult<List<GoodsTypeVO>> selectGoodsTypes() {
+        List<GoodsTypeDTO> goodsTypeDTOS = goodsService.selectGoodsTypes();
+
+        List<GoodsTypeVO> goodsTypeVOS = new ArrayList<>();
+        goodsTypeDTOS.forEach(goodsTypeDTO -> {
+            GoodsTypeVO goodsTypeVO = new GoodsTypeVO();
+            BeanUtils.copyProperties(goodsTypeDTO, goodsTypeVO);
+            goodsTypeVOS.add(goodsTypeVO);
+        });
+        log.info("select all goods type success");
+
+        return ActionResult.getSuccessResult(goodsTypeVOS);
+    }
+
+    @ApiOperation("根据Query查询GoodsList")
+    @PostMapping(value = "/listByType", produces = MediaType.APPLICATION_JSON_VALUE)
+    @Cacheable(value = "Goods:List:Type", key = "#query.pageNo+''+#query.pageSize+''+#query.goodsType")
+    public ActionResult<PageResult<List<GoodsListVO>>> selectGoodsListByType(@RequestBody @Valid GoodsListQuery query) {
+        PageResult<List<GoodsListDTO>> goodsList = goodsService.selectGoodsListByType(query.getPageNo(), query.getPageSize(), query.getGoodsType());
+        PageResult<List<GoodsListVO>> result = this.getGoodsListPageVO(goodsList);
+
+        log.info("select goods list by goodsType success, query is[ {} ]", query);
+        return ActionResult.getSuccessResult(result);
+    }
+
+    @ApiOperation("查询热门商品list")
+    @PostMapping(value = "/list/hot", produces = MediaType.APPLICATION_JSON_VALUE)
+    @Cacheable(value = "Goods:List:Hot", key = "#query.pageNo+''+#query.pageSize")
+    public ActionResult<PageResult<List<GoodsListVO>>> getHotGoodsList(@RequestBody @Valid PageQuery query) {
+        PageResult<List<GoodsListDTO>> goodsList = goodsService.selectHotGoodsList(query);
+        PageResult<List<GoodsListVO>> result = this.getGoodsListPageVO(goodsList);
+
+        log.info("select hot goods list success, query is[ {} ]", query);
+        return ActionResult.getSuccessResult(result);
+    }
+
+    @GetMapping(value = "/getGoods", produces = MediaType.APPLICATION_JSON_VALUE)
+    @ApiOperation("根据id查询goods")
+    @Cacheable(value = "Goods:ID", key = "#goodsId")
+    public ActionResult<GoodsVO> selectGoodsInfo(Integer goodsId) {
+        GoodsDTO goodsDTO = goodsService.selectGoodsById(goodsId);
+        log.info("select Goods by id success, goods_id is:{}", goodsId);
+        GoodsVO goodsVO = convertGoodsDTO2GoodsVO(goodsDTO);
+        return ActionResult.getSuccessResult(goodsVO);
+    }
+
+    @GetMapping(value = "/search", produces = MediaType.APPLICATION_JSON_VALUE)
+    @ApiOperation("商品搜索")
+    public ActionResult<List<GoodsVO>> searchGoods(@NotBlank(message = "搜索词不能为空") String inputValue) {
+
+        String input = inputValue.trim();
+
+        //添加到热搜list
+        redisService.increaseHotSearchList(input);
+        //查询
+        List<GoodsDTO> goodsDTOS = goodsService.searchGoods(input);
+        List<GoodsVO> goods = new ArrayList<>();
+
+        goodsDTOS.forEach(goodsDTO -> {
+            GoodsVO goodsVO = convertGoodsDTO2GoodsVO(goodsDTO);
+            goods.add(goodsVO);
+        });
+
+        log.info("search goods success");
+        return ActionResult.getSuccessResult(goods);
+    }
+
+    @GetMapping(value = "/search/top/{num}")
+    @ApiOperation("获取前num个热搜词")
+    public ActionResult<Set<String>> getTopSearch(@PathVariable("num") int top) {
+        if (top <= 0) {
+            throw new ParamException(ErrorType.PARAM_ERROR, "top 必须大于0");
+        }
+        Set<String> topList = redisService.getHotSearchTopList(top);
+        log.info("get top search list success");
+
+        return ActionResult.getSuccessResult(topList);
+    }
+
+    /**
+     * 得到商品list page vo对象
+     *
+     * @param goodsList 商品page
+     * @return vo
+     */
+    private PageResult<List<GoodsListVO>> getGoodsListPageVO(PageResult<List<GoodsListDTO>> goodsList) {
+        List<GoodsListVO> goodsListVOS = new ArrayList<>();
+
+        goodsList.getData().forEach(goodsListDTO -> {
+            GoodsListVO goodsListVO = convertGoodsListDTO2VO(goodsListDTO);
+            goodsListVOS.add(goodsListVO);
+        });
+        PageResult<List<GoodsListVO>> pageResult = new PageResult<>();
+        BeanUtils.copyProperties(goodsList, pageResult);
+        pageResult.setData(goodsListVOS);
+        return pageResult;
+    }
+
+    /**
+     * 将GoodsListDTO转为GoodsListVO
+     *
+     * @param goodsListDTO dto
+     * @return vo
+     */
+    private GoodsListVO convertGoodsListDTO2VO(GoodsListDTO goodsListDTO) {
+        GoodsListVO goodsListVO = new GoodsListVO();
+        BeanUtils.copyProperties(goodsListDTO, goodsListVO);
+
+        List<GoodsVO> goodsVOS = new ArrayList<>();
+        goodsListDTO.getGoods().forEach(goodsDTO -> {
+            goodsVOS.add(convertGoodsDTO2GoodsVO(goodsDTO));
+        });
+
+        goodsListVO.setGoods(goodsVOS);
+        return goodsListVO;
+    }
+
+    /**
+     * 将GoodsDTO转换为GoodsVO
+     *
+     * @param goodsDTO dto
+     * @return vo
+     */
+    private GoodsVO convertGoodsDTO2GoodsVO(GoodsDTO goodsDTO) {
+        GoodsVO goodsVO = new GoodsVO();
+        BeanUtils.copyProperties(goodsDTO, goodsVO);
+
+        List<GoodsPictureVO> pictureVOS = new ArrayList<>();
+        List<GoodsOptionVO> goodsOptionVOS = new ArrayList<>();
+
+        goodsDTO.getPictures().forEach(pictureDTO -> {
+            GoodsPictureVO pictureVO = new GoodsPictureVO();
+            BeanUtils.copyProperties(pictureDTO, pictureVO);
+            pictureVOS.add(pictureVO);
+        });
+
+        goodsDTO.getGoodsOptions().forEach(goodsOptionDTO -> {
+            GoodsOptionVO goodsOptionVO = convertGoodsOptionDTO2VO(goodsOptionDTO);
+            goodsOptionVOS.add(goodsOptionVO);
+        });
+
+        goodsVO.setPictures(pictureVOS);
+        goodsVO.setGoodsOptions(goodsOptionVOS);
+
+        return goodsVO;
+    }
+
+    /**
+     * 将GoodsOptionDTO转化为GoodsOptionVO
+     *
+     * @param goodsOptionDTO dto
+     * @return vo
+     */
+    private GoodsOptionVO convertGoodsOptionDTO2VO(GoodsOptionDTO goodsOptionDTO) {
+        GoodsOptionVO goodsOptionVO = new GoodsOptionVO();
+        BeanUtils.copyProperties(goodsOptionDTO, goodsOptionVO);
+        List<GoodsOptionItemVO> goodsOptionItemVOS = new ArrayList<>();
+
+        goodsOptionDTO.getGoodsOptionItems().forEach(goodsOptionItemDTO -> {
+            GoodsOptionItemVO goodsOptionItemVO = new GoodsOptionItemVO();
+            BeanUtils.copyProperties(goodsOptionItemDTO, goodsOptionItemVO);
+            goodsOptionItemVOS.add(goodsOptionItemVO);
+        });
+
+        goodsOptionVO.setGoodsOptionItems(goodsOptionItemVOS);
+        return goodsOptionVO;
+    }
+
+}

+ 142 - 0
src/main/java/com/cdu/lys/graduation/controller/user/CommentController.java

@@ -0,0 +1,142 @@
+package com.cdu.lys.graduation.controller.user;
+
+import com.cdu.lys.graduation.commons.result.ActionResult;
+import com.cdu.lys.graduation.commons.result.PageResult;
+import com.cdu.lys.graduation.domain.comment.dto.CommentDTO;
+import com.cdu.lys.graduation.domain.comment.dto.CommentPictureDTO;
+import com.cdu.lys.graduation.domain.comment.vo.CommentPictureVO;
+import com.cdu.lys.graduation.domain.comment.vo.CommentVO;
+import com.cdu.lys.graduation.domain.user.wx.LoginUser;
+import com.cdu.lys.graduation.mini.user.service.CommentService;
+import com.cdu.lys.graduation.redis.RedisService;
+import com.cdu.lys.graduation.types.PageQuery;
+import com.cdu.lys.graduation.types.user.CommentQuery;
+import com.cdu.lys.graduation.types.user.CommentTypeQuery;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author liyinsong
+ * @date 2022/3/29 19:32
+ */
+@Api(tags = "User评论接口")
+@RestController
+@RequestMapping("/eorder/app/user")
+@Slf4j
+public class CommentController {
+
+    @Autowired
+    private CommentService commentService;
+
+    @Autowired
+    private RedisService redisService;
+
+    @ApiOperation("用户评论")
+    @PostMapping(value = "/comment", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> comment(@RequestBody @Valid CommentQuery query, @RequestHeader("token") String token) {
+        //获取用户session_key
+        LoginUser loginUser = redisService.getLoginValue(token);
+
+        boolean result = commentService.comment(query, loginUser.getId());
+
+        if (!result) {
+            log.info("user comment error");
+            return ActionResult.getErrorResult("评论失败");
+        }
+        redisService.incrDailyComment();
+        log.info("user comment success");
+        return ActionResult.getSuccessResult("评论成功");
+    }
+
+    @ApiOperation("评论列表")
+    @PostMapping(value = "/comment/visit/list", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> commentList(@RequestBody @Valid PageQuery query) {
+
+        PageResult<List<CommentDTO>> pageResult = commentService.commentList(query);
+        PageResult<List<CommentVO>> result = this.convert2CommentPageVO(pageResult);
+
+        log.info("select all comment list success");
+        return ActionResult.getSuccessResult(result);
+    }
+
+    @ApiOperation("获取用户评论列表")
+    @PostMapping(value = "/comment/list", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<PageResult<List<CommentVO>>> getUserCommentList(@RequestBody @Valid PageQuery query, @RequestHeader("token") String token) {
+        //获取用户session_key
+        LoginUser loginUser = redisService.getLoginValue(token);
+        PageResult<List<CommentDTO>> pageResult = commentService.getUserCommentList(query, loginUser.getId());
+
+        PageResult<List<CommentVO>> result = this.convert2CommentPageVO(pageResult);
+
+        log.info("select user comment list success");
+        return ActionResult.getSuccessResult(result);
+    }
+
+    @ApiOperation("评论分类搜索")
+    @PostMapping(value = "/comment/visit/search", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> getCommentListByType(@RequestBody @Valid CommentTypeQuery query) {
+
+        PageResult<List<CommentDTO>> pageResult = commentService.commentListByType(query);
+        PageResult<List<CommentVO>> result = this.convert2CommentPageVO(pageResult);
+
+        log.info("select comment list by type[{}] success", query.getType());
+        return ActionResult.getSuccessResult(result);
+    }
+
+    /**
+     * 转为VO
+     * @param pageResult DTO
+     * @return VO
+     */
+    private PageResult<List<CommentVO>> convert2CommentPageVO(PageResult<List<CommentDTO>> pageResult) {
+
+        PageResult<List<CommentVO>> result = new PageResult<>();
+        List<CommentVO> commentVOS = new ArrayList<>();
+
+        BeanUtils.copyProperties(pageResult, result);
+
+        List<CommentDTO> data = pageResult.getData();
+        if (CollectionUtils.isEmpty(data)) {
+            return result;
+        }
+
+        data.forEach(commentDTO -> {
+            CommentVO commentVO = new CommentVO();
+            BeanUtils.copyProperties(commentDTO, commentVO);
+            commentVO.setPicUrls(this.convert2PictureVO(commentDTO.getPicUrls()));
+            commentVOS.add(commentVO);
+        });
+        result.setData(commentVOS);
+
+        return result;
+    }
+
+    /**
+     * 转为为vo List
+     * @param commentPictureDTOS
+     * @return
+     */
+    private List<CommentPictureVO> convert2PictureVO(List<CommentPictureDTO> commentPictureDTOS) {
+
+        if (CollectionUtils.isEmpty(commentPictureDTOS)) {
+            return null;
+        }
+        List<CommentPictureVO> res = new ArrayList<>();
+        commentPictureDTOS.forEach(commentPictureDTO -> {
+            CommentPictureVO commentPictureVO = new CommentPictureVO();
+            commentPictureVO.setPicUrl(commentPictureDTO.getPicUrl());
+            res.add(commentPictureVO);
+        });
+        return res;
+    }
+}

+ 218 - 0
src/main/java/com/cdu/lys/graduation/controller/user/LoginController.java

@@ -0,0 +1,218 @@
+package com.cdu.lys.graduation.controller.user;
+
+import com.alibaba.fastjson.JSONObject;
+import com.cdu.lys.graduation.commons.result.ActionResult;
+import com.cdu.lys.graduation.commons.utils.JWTUtils;
+import com.cdu.lys.graduation.domain.user.dto.WxUserDTO;
+import com.cdu.lys.graduation.domain.user.vo.LoginVO;
+import com.cdu.lys.graduation.domain.user.vo.UserVO;
+import com.cdu.lys.graduation.domain.user.wx.LoginUser;
+import com.cdu.lys.graduation.mini.user.bo.UserBO;
+import com.cdu.lys.graduation.mini.user.service.LoginService;
+import com.cdu.lys.graduation.redis.RedisService;
+import com.cdu.lys.graduation.repository.entity.UserDO;
+import com.cdu.lys.graduation.types.SystemConstant;
+import com.cdu.lys.graduation.types.user.LoginQuery;
+import com.cdu.lys.graduation.types.user.UserQuery;
+import com.cdu.lys.graduation.types.user.WxLoginQuery;
+import com.cdu.lys.graduation.types.user.WxUserProfile;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.http.MediaType;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 用户接口
+ *
+ * @author liyinsong
+ * @date 2022/1/8 15:27
+ */
+@Api(tags = "User登录接口")
+@RestController
+@RequestMapping("/eorder/app/user")
+@Slf4j
+@Validated
+public class LoginController {
+
+    @Autowired
+    private LoginService loginService;
+
+    @Autowired
+    private RedisService redisService;
+
+    @Autowired
+    private RedisTemplate<String,Object> redisTemplate;
+
+    @Value("${system.order.secretKey}")
+    private String secretKey;
+
+    @Autowired
+    private UserBO userBO;
+
+    /**
+     * 系统登录
+     *
+     * @param loginQuery 用户输入
+     * @return 登录结果
+     */
+    @ApiOperation("系统登录逻辑")
+    @PostMapping(value = "/login", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> login(@RequestBody @Valid LoginQuery loginQuery) {
+        ActionResult<Object> result = loginService.systemLogin(loginQuery);
+        if (!result.isSuccess()) {
+            log.warn("user[{}] login failed, err msg: {}", loginQuery.getUsername(), result.getMessage());
+            return result;
+        }
+        //生成登录状态jwt token
+        String token = JWTUtils.createJWT(secretKey);
+
+        //存入redis设置失效时间,3天 FIXME 这里可能不应该存redis,token设置cookie就行了
+        Object data = result.getData();
+        redisTemplate.opsForValue().set(SystemConstant.LOGIN_TOKEN_KEY + token, data, SystemConstant.SYSTEM_LOGIN_TIMEOUT, TimeUnit.DAYS);
+
+        UserVO userVO = new UserVO();
+        LoginVO loginVO = new LoginVO();
+
+        BeanUtils.copyProperties(data, userVO);
+        loginVO.setToken(token);
+        loginVO.setUserInfo(userVO);
+
+        log.info("user[{}] login success.", loginQuery.getUsername());
+        return ActionResult.getSuccessResult(result.getMessage(), loginVO);
+    }
+
+    /**
+     * 微信登录
+     * @param loginQuery 用户登录凭证
+     * @return 登录
+     */
+    @ApiOperation("微信登录逻辑")
+    @PostMapping(value = "/wx/login", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> wxLogin(@RequestBody @Valid WxLoginQuery loginQuery) {
+        log.info("UserController#wxLogin, data: {}", loginQuery);
+
+        ActionResult<Object> loginResult = loginService.wxLogin(loginQuery.getCode());
+
+        //登录失败
+        if (!loginResult.isSuccess()) {
+            log.error("UserController#wxLogin fail, error msg:{}", loginResult.getMessage());
+            return loginResult;
+        }
+
+        //生成登录状态jwt token
+        String token = JWTUtils.createJWT(secretKey);
+
+        //存入redis设置失效时间,3天
+        redisTemplate.opsForValue().set(SystemConstant.LOGIN_TOKEN_KEY + token, loginResult.getData(), SystemConstant.SYSTEM_LOGIN_TIMEOUT, TimeUnit.DAYS);
+        WxUserDTO wxUserDTO = new WxUserDTO();
+        JSONObject jsonObject = (JSONObject) JSONObject.toJSON(loginResult.getData());
+        wxUserDTO.setOpenId(jsonObject.getString("openid"));
+        loginService.registryWxUserInfo(wxUserDTO);
+
+
+        //将token,返回前端
+        LoginVO wxLoginVO=new LoginVO();
+        wxLoginVO.setToken(token);
+
+        log.info("UserController#wxLogin success, generated token is [{}]", token);
+        return ActionResult.getSuccessResult("登录成功", wxLoginVO);
+    }
+
+    @ApiOperation("注册微信用户,插入数据")
+    @PostMapping(value = "/wx/insert", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> insertWxUser(@RequestBody WxUserProfile user, @RequestHeader("token") String token) {
+        //获取用户session_key
+        LoginUser loginUser = redisService.getLoginValue(token);
+        String sessionKey = loginUser.getSession_key();
+        //校验用户数据是否被修改
+        boolean isChanged = loginService.checkWxUser(user.getRawData(), user.getSignature(), sessionKey);
+        if (!isChanged) {
+            log.info("user data has changes, check user failed");
+            return ActionResult.getErrorResult("用户数据被篡改");
+        }
+        log.info("user data no changes, check user success");
+
+        WxUserDTO wxUserDTO = null;
+
+        try {
+            //解密用户数据
+            wxUserDTO = loginService.decryptWxUserInfo(user.getEncryptedData(), user.getIv(), sessionKey);
+            log.info("WeChat UserInfo decrypt success");
+        } catch (Exception e) {
+            log.error("WeChat UserInfo decrypt failed", e);
+            return ActionResult.getErrorResult("用户数据解密失败");
+        }
+
+        //插入数据库
+        wxUserDTO.setOpenId(loginUser.getOpenid());
+        loginService.registryWxUserInfo(wxUserDTO);
+
+        return ActionResult.getSuccessResult("用户数据插入成功");
+    }
+
+    @ApiOperation("注销登录")
+    @GetMapping(value = "/logout", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> wxLogout(@RequestHeader String token) {
+        Boolean delete = redisTemplate.delete(SystemConstant.LOGIN_TOKEN_KEY + token);
+
+        if (delete) {
+            log.info("delete key [{}] success", token);
+            return ActionResult.getSuccessResult("注销成功");
+        } else {
+            log.info("delete key [{}] fail", token);
+            return ActionResult.getErrorResult("注销成功");
+        }
+    }
+
+    @ApiOperation("获取微信用户手机号")
+    @GetMapping(value = "/wx/getPhoneNumber")
+    public void wxGetWxPhoneNumber(String code){
+        loginService.getWxUserPhoneNumber(code);
+
+    }
+
+    @GetMapping(value = "/token/check")
+    @ApiOperation("校验登录token是否失效")
+    public ActionResult<Object> checkSessionExpire(@RequestHeader("token") String token){
+        boolean valid = redisService.checkTokenValid(token);
+        if (!valid) {
+            log.warn("token is invalid");
+            return ActionResult.getErrorResult("不合法token");
+        }
+        log.info("token is valid");
+        return ActionResult.getSuccessResult("合法token");
+    }
+
+    @ApiOperation("修改用户信息")
+    @PostMapping(value = "/update", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<Object> modifyUser(@RequestBody @Valid UserQuery query, @RequestHeader("token") String token) {
+        LoginUser loginUser = redisService.getLoginValue(token);
+
+        int i = userBO.updateUser(query, loginUser.getId());
+
+        log.info("user modify userInfo success");
+        return ActionResult.getSuccessResult("保存成功");
+    }
+
+    @ApiOperation("获取用户信息")
+    @PostMapping(value = "/get", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ActionResult<UserVO> getUserInfo(@RequestHeader("token") String token) {
+        LoginUser loginUser = redisService.getLoginValue(token);
+
+        UserDO userDO = userBO.getUserById(loginUser.getId());
+        UserVO userVO = new UserVO();
+
+        BeanUtils.copyProperties(userDO, userVO);
+        log.info("select userInfo success");
+        return ActionResult.getSuccessResult(userVO);
+    }
+}

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov