zhangyuewww vor 2 Jahren
Commit
4ef2c0f192
100 geänderte Dateien mit 6002 neuen und 0 gelöschten Zeilen
  1. 2 0
      .gitattributes
  2. 78 0
      .gitignore
  3. 145 0
      pom.xml
  4. 22 0
      sendGoodNotPlat.xml
  5. 641 0
      sql/unimall_tmp.sql
  6. 107 0
      unimall-admin-api/pom.xml
  7. 51 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/AdminCheckQuartz.java
  8. 91 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/AuthService.java
  9. 31 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/MyApplicationLisenter.java
  10. 13 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/UnimallAdminApiApplication.java
  11. 79 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/admin/AdminService.java
  12. 248 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/admin/AdminServiceImpl.java
  13. 71 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/advertisement/AdminAdvertisementService.java
  14. 108 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/advertisement/AdminAdvertisementServiceImpl.java
  15. 54 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/config/AdminMerchantConfigService.java
  16. 75 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/config/AdminMerchantConfigServiceImpl.java
  17. 50 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/dict/DictDataService.java
  18. 77 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/dict/DictDataserviceImpl.java
  19. 48 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/dict/DictTypeService.java
  20. 86 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/dict/DictTypeServiceImpl.java
  21. 40 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/log/loginLog/SysLogininforService.java
  22. 87 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/log/loginLog/SysLogininforServiceImpl.java
  23. 40 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/log/operLog/OperLogService.java
  24. 87 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/log/operLog/OperLogServiceImpl.java
  25. 21 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/monitor/online/UserOnlineService.java
  26. 45 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/monitor/online/UserOnlineServiceImpl.java
  27. 11 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/monitor/server/ServerService.java
  28. 22 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/monitor/server/ServerServiceImpl.java
  29. 65 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/role/RoleService.java
  30. 141 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/role/RoleServiceImpl.java
  31. 74 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/tools/gen/GenTableService.java
  32. 179 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/tools/gen/GenTableServiceImpl.java
  33. 62 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/user/AdminUserService.java
  34. 229 0
      unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/user/AdminUserServiceImpl.java
  35. BIN
      unimall-admin-api/src/main/lib/cf-auth-api-token-5.1.5-SNAPSHOT-jar-with-dependencies.jar
  36. BIN
      unimall-admin-api/src/main/lib/dangdang-open-sdk.jar
  37. 1 0
      unimall-admin-api/src/main/resources/application.properties
  38. 17 0
      unimall-admin/.babelrc
  39. 3 0
      unimall-admin/.eslintignore
  40. 185 0
      unimall-admin/.eslintrc.js
  41. 10 0
      unimall-admin/.postcssrc.js
  42. 67 0
      unimall-admin/build/build.js
  43. 64 0
      unimall-admin/build/check-versions.js
  44. BIN
      unimall-admin/build/logo.png
  45. 108 0
      unimall-admin/build/utils.js
  46. 5 0
      unimall-admin/build/vue-loader.conf.js
  47. 107 0
      unimall-admin/build/webpack.base.conf.js
  48. 98 0
      unimall-admin/build/webpack.dev.conf.js
  49. 188 0
      unimall-admin/build/webpack.prod.conf.js
  50. 6 0
      unimall-admin/config/dep.env.js
  51. 8 0
      unimall-admin/config/dev.env.js
  52. 88 0
      unimall-admin/config/index.js
  53. 6 0
      unimall-admin/config/prod.env.js
  54. BIN
      unimall-admin/favicon.ico
  55. 18 0
      unimall-admin/index.html
  56. 18 0
      unimall-admin/src/App.vue
  57. 55 0
      unimall-admin/src/api/admin.js
  58. 23 0
      unimall-admin/src/api/appraise.js
  59. 66 0
      unimall-admin/src/api/category.js
  60. 11 0
      unimall-admin/src/api/dashboard.js
  61. 48 0
      unimall-admin/src/api/log/logininfor.js
  62. 48 0
      unimall-admin/src/api/log/operlog.js
  63. 50 0
      unimall-admin/src/api/login.js
  64. 24 0
      unimall-admin/src/api/merchant.js
  65. 91 0
      unimall-admin/src/api/merchantad.js
  66. 24 0
      unimall-admin/src/api/monitor/online.js
  67. 12 0
      unimall-admin/src/api/monitor/server.js
  68. 12 0
      unimall-admin/src/api/profile.js
  69. 78 0
      unimall-admin/src/api/role.js
  70. 11 0
      unimall-admin/src/api/storage.js
  71. 74 0
      unimall-admin/src/api/sys/dict/data.js
  72. 72 0
      unimall-admin/src/api/sys/dict/type.js
  73. 93 0
      unimall-admin/src/api/tool/gen.js
  74. 58 0
      unimall-admin/src/api/user.js
  75. BIN
      unimall-admin/src/assets/401_images/401.gif
  76. BIN
      unimall-admin/src/assets/404_images/404.png
  77. BIN
      unimall-admin/src/assets/404_images/404_cloud.png
  78. BIN
      unimall-admin/src/assets/avatar.png
  79. BIN
      unimall-admin/src/assets/custom-theme/fonts/element-icons.ttf
  80. BIN
      unimall-admin/src/assets/custom-theme/fonts/element-icons.woff
  81. 0 0
      unimall-admin/src/assets/custom-theme/index.css
  82. 116 0
      unimall-admin/src/components/BackToTop/index.vue
  83. 63 0
      unimall-admin/src/components/Breadcrumb/index.vue
  84. 59 0
      unimall-admin/src/components/Hamburger/index.vue
  85. 40 0
      unimall-admin/src/components/LangSelect/index.vue
  86. 102 0
      unimall-admin/src/components/Pagination/index.vue
  87. 78 0
      unimall-admin/src/components/Screenfull/index.vue
  88. 92 0
      unimall-admin/src/components/ScrollPane/index.vue
  89. 55 0
      unimall-admin/src/components/SizeSelect/index.vue
  90. 43 0
      unimall-admin/src/components/SvgIcon/index.vue
  91. 144 0
      unimall-admin/src/components/ThemePicker/index.vue
  92. 49 0
      unimall-admin/src/directive/clipboard/clipboard.js
  93. 13 0
      unimall-admin/src/directive/clipboard/index.js
  94. 13 0
      unimall-admin/src/directive/permission/index.js
  95. 29 0
      unimall-admin/src/directive/permission/permission.js
  96. 68 0
      unimall-admin/src/filters/index.js
  97. 9 0
      unimall-admin/src/icons/index.js
  98. 1 0
      unimall-admin/src/icons/svg/404.svg
  99. 0 0
      unimall-admin/src/icons/svg/admin.svg
  100. 1 0
      unimall-admin/src/icons/svg/api.svg

+ 2 - 0
.gitattributes

@@ -0,0 +1,2 @@
+*.sql linguist-language=java
+*.html linguist-language=java

+ 78 - 0
.gitignore

@@ -0,0 +1,78 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**
+!**/src/test/**
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+#/build/
+
+### VS Code ###
+.vscode/
+
+### maven ###
+.mvn
+mvnw
+mvnw.cmd
+
+###properties###
+/unimall-launcher/src/main/resources/application-dev.properties
+/unimall-launcher/src/main/resources/application-prd.properties
+
+### target ###
+/target/
+/unimall-admin-api/target/
+/unimall-app-api/target/
+/unimall-biz/target/
+/unimall-data/target/
+/unimall-core/target/
+/unimall-launcher/target/
+/unimall-plugin-core/target/
+/unimall-app/unpackage/dist/
+/unimall-app/unpackage/resources/
+/unimall-app/unpackage/debug/
+/unimall-admin/dist.zip
+
+###node_modules###
+/unimall-admin/node_modules/
+/unimall-app/node_modules/
+
+
+###logs###
+unimall.log
+unimall.log.*.gz
+unimall.log.*.tmp
+
+
+### plugins ###
+/plugins/
+/unimall-app/pages/plugins/
+/unimall-admin/src/views/plugins/
+
+### xcx ###
+.map/
+/unpackage/
+*.wxss
+*.json
+*.wxml
+xiaochengxu/unpackage/

+ 145 - 0
pom.xml

@@ -0,0 +1,145 @@
+<?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>
+	<packaging>pom</packaging>
+	<parent>
+		<groupId>org.springframework.boot</groupId>
+		<artifactId>spring-boot-starter-parent</artifactId>
+		<version>2.1.2.RELEASE</version>
+		<relativePath/> <!-- lookup parent from repository -->
+	</parent>
+	<groupId>com.iotechn</groupId>
+	<artifactId>unimall</artifactId>
+	<version>0.0.1-RELEASE</version>
+	<name>unimall</name>
+	<description>App,MiniProgram</description>
+
+	<properties>
+		<java.version>1.8</java.version>
+	</properties>
+
+	<repositories>
+		<repository>
+			<id>maven-ali</id>
+			<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
+			<releases>
+				<enabled>true</enabled>
+			</releases>
+			<snapshots>
+				<enabled>true</enabled>
+				<updatePolicy>always</updatePolicy>
+				<checksumPolicy>fail</checksumPolicy>
+			</snapshots>
+		</repository>
+	</repositories>
+
+	<modules>
+		<module>unimall-core</module>
+		<module>unimall-data</module>
+		<module>unimall-biz</module>
+		<module>unimall-app-api</module>
+		<module>unimall-admin-api</module>
+		<module>unimall-launcher</module>
+		<module>unimall-plugin-core</module>
+	</modules>
+
+	<dependencyManagement>
+		<dependencies>
+
+			<!-- http客户端 -->
+			<dependency>
+				<groupId>com.squareup.okhttp3</groupId>
+				<artifactId>okhttp</artifactId>
+				<version>3.10.0</version>
+			</dependency>
+
+			<!-- 良心云 sms -->
+			<dependency>
+				<groupId>com.github.qcloudsms</groupId>
+				<artifactId>qcloudsms</artifactId>
+				<version>1.0.5</version>
+			</dependency>
+
+			<!-- 阿里云 SMS -->
+			<dependency>
+				<groupId>com.aliyun</groupId>
+				<artifactId>aliyun-java-sdk-core</artifactId>
+				<version>4.1.1</version>
+			</dependency>
+
+			<!-- 阿里云对象存储 -->
+			<dependency>
+				<groupId>com.aliyun.oss</groupId>
+				<artifactId>aliyun-sdk-oss</artifactId>
+				<version>2.8.3</version>
+			</dependency>
+
+			<!-- mybatis plus 依赖 -->
+			<dependency>
+				<groupId>com.baomidou</groupId>
+				<artifactId>mybatis-plus-boot-starter</artifactId>
+				<version>2.2.0</version>
+			</dependency>
+
+			<dependency>
+				<groupId>com.baomidou</groupId>
+				<artifactId>mybatis-plus-support</artifactId>
+				<version>2.2.0</version>
+			</dependency>
+
+			<!-- mysql -->
+			<dependency>
+				<groupId>mysql</groupId>
+				<artifactId>mysql-connector-java</artifactId>
+				<version>8.0.15</version>
+			</dependency>
+
+			<!-- 阿里巴巴 数据源 Druid -->
+			<dependency>
+				<groupId>com.alibaba</groupId>
+				<artifactId>druid</artifactId>
+				<version>1.1.8</version>
+			</dependency>
+
+			<!-- lombok 工具 -->
+			<dependency>
+				<groupId>org.projectlombok</groupId>
+				<artifactId>lombok</artifactId>
+				<version>1.18.4</version>
+				<scope>provided</scope>
+			</dependency>
+
+			<!-- 阿里巴巴 json 解析 -->
+			<dependency>
+				<groupId>com.alibaba</groupId>
+				<artifactId>fastjson</artifactId>
+				<version>1.2.31</version>
+			</dependency>
+
+			<!-- 微信第三方封装Api -->
+			<dependency>
+				<groupId>com.github.binarywang</groupId>
+				<artifactId>weixin-java-pay</artifactId>
+				<version>3.3.0</version>
+				<exclusions>
+					<exclusion>
+						<artifactId>qrcode-utils</artifactId>
+						<groupId>com.github.binarywang</groupId>
+					</exclusion>
+				</exclusions>
+			</dependency>
+
+		</dependencies>
+	</dependencyManagement>
+
+	<!-- 发布maven私服 -->
+	<!--<distributionManagement>-->
+		<!--<repository>-->
+			<!--<id>iotechn-release</id>-->
+			<!--<name>unimall maven</name>-->
+			<!--<url>http://maven.iotechn.com/repository/maven-releases/</url>-->
+		<!--</repository>-->
+	<!--</distributionManagement>-->
+
+</project>

+ 22 - 0
sendGoodNotPlat.xml

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="GBK"?>
+<request>
+    <functionID>dangdang.order.goods.send</functionID>
+    <time>2022-07-11 09:32:13</time>
+    <OrdersList>
+        <OrderInfo>
+            <orderID>45018706599</orderID>
+            <logisticsName>¼«ÍÃËÙµÝ</logisticsName>
+            <logisticsNameAb>JT</logisticsNameAb>
+            <logisticsTel>400-820-1666</logisticsTel>
+            <logisticsOrderID>JT3007364146966</logisticsOrderID>
+            <SendGoodsList>
+                <ItemInfo>
+                    <itemID>11162110282</itemID>
+                    <sendGoodsCount>1</sendGoodsCount>
+                    <belongProductsPromoID></belongProductsPromoID>
+                    <productItemId>45018706599001</productItemId>
+                </ItemInfo>
+            </SendGoodsList>
+        </OrderInfo>
+    </OrdersList>
+</request>

Datei-Diff unterdrückt, da er zu groß ist
+ 641 - 0
sql/unimall_tmp.sql


+ 107 - 0
unimall-admin-api/pom.xml

@@ -0,0 +1,107 @@
+<?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>
+	<parent>
+		<groupId>com.iotechn</groupId>
+		<artifactId>unimall</artifactId>
+		<version>0.0.1-RELEASE</version>
+	</parent>
+	<groupId>com.iotechn</groupId>
+	<artifactId>unimall-admin-api</artifactId>
+	<version>0.0.1-RELEASE</version>
+	<name>unimall-admin-api</name>
+	<description>后台管理Api</description>
+
+	<properties>
+		<java.version>1.8</java.version>
+	</properties>
+
+	<repositories>
+		<repository>
+			<id>maven-ali</id>
+			<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
+			<releases>
+				<enabled>true</enabled>
+			</releases>
+			<snapshots>
+				<enabled>true</enabled>
+				<updatePolicy>always</updatePolicy>
+				<checksumPolicy>fail</checksumPolicy>
+			</snapshots>
+		</repository>
+		<repository>
+			<id>iotechn-release</id>
+			<name>unimall maven</name>
+			<url>http://maven.iotechn.com/repository/maven-releases/</url>
+		</repository>
+	</repositories>
+
+	<dependencies>
+		<dependency>
+			<groupId>commons-httpclient</groupId>
+			<artifactId>commons-httpclient</artifactId>
+			<version>3.1</version>
+		</dependency>
+		<!-- 引入本地jar -->
+		<dependency>
+			<groupId>com.dangdang.openplatform.openapi</groupId>
+			<artifactId>sdk</artifactId>
+			<version>1.0-SNAPSHOT</version>
+			<scope>system</scope>
+			<systemPath>${project.basedir}/src/main/lib/dangdang-open-sdk.jar</systemPath>
+		</dependency>
+		<dependency>
+			<groupId>com.iotechn</groupId>
+			<artifactId>unimall-core</artifactId>
+			<version>0.0.1-RELEASE</version>
+		</dependency>
+		<!-- 插件核心依赖 勿删 -->
+		<dependency>
+			<groupId>com.iotechn</groupId>
+			<artifactId>unimall-plugin-core</artifactId>
+			<version>0.0.1-RELEASE</version>
+		</dependency>
+
+		<dependency>
+			<groupId>com.iotechn</groupId>
+			<artifactId>unimall-data</artifactId>
+			<version>0.0.1-RELEASE</version>
+		</dependency>
+
+		<dependency>
+			<groupId>com.iotechn</groupId>
+			<artifactId>unimall-biz</artifactId>
+			<version>0.0.1-RELEASE</version>
+		</dependency>
+
+		<!-- 微信第三方封装Api -->
+		<dependency>
+			<groupId>com.github.binarywang</groupId>
+			<artifactId>weixin-java-pay</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>com.baidu.contact-center</groupId>
+			<artifactId>cf-auth-api-token</artifactId>
+			<version>5.1.5-SNAPSHOT</version>
+			<scope>system</scope>
+			<systemPath>${project.basedir}/src/main/lib/cf-auth-api-token-5.1.5-SNAPSHOT-jar-with-dependencies.jar</systemPath>
+		</dependency>
+		<dependency>
+			<groupId>org.projectlombok</groupId>
+			<artifactId>lombok</artifactId>
+			<optional>true</optional>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-test</artifactId>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+
+</project>

+ 51 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/AdminCheckQuartz.java

@@ -0,0 +1,51 @@
+package com.iotechn.unimall.admin;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.stereotype.Component;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * Created by rize on 2019/7/21.
+ */
+@Component
+@EnableScheduling
+public class AdminCheckQuartz {
+
+    private static final Logger logger = LoggerFactory.getLogger(AdminCheckQuartz.class);
+    private static final String ORDER_STATUS_LOCK = "ORDER_STATUS_QUARTZ_LOCK";
+    private static final String GROUP_SHOP_START_LOCK = "GROUP_SHOP_START_LOCK";
+    private static final String GROUP_SHOP_END_LOCK = "GROUP_SHOP_END_LOCK";
+    private static final String GROUP_SHOP_LOCK_LOCK = "GROUP_SHOP_LOCK_LOCK";
+    ExecutorService pool = Executors.newFixedThreadPool(2);
+
+    /**
+     * 订单数据定时轮训处理 每小时执行一次
+     */
+//    @Scheduled(cron = "0 0 7-22 * * ? ")
+    public void task1(){
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+            }
+        }).start();
+    }
+    /**
+     * 订单数据定时轮训处理 每30分钟执行一次
+     */
+//    @Scheduled(cron = "0 0/30 * * * ? ")
+    public void task2(){
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+            }
+        }).start();
+    }
+    public void dealOrder() throws Exception {
+
+    }
+
+
+}

+ 91 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/AuthService.java

@@ -0,0 +1,91 @@
+package com.iotechn.unimall.admin;
+
+/**
+ * @Author:chengchangjiang
+ * @Description:
+ * @Date:Created in 15:59 2022-06-17
+ */
+
+
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 获取token类
+ */
+public class AuthService {
+
+    /**
+     * 获取权限token
+     * @return 返回示例:
+     * {
+     * "access_token": "24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567",
+     * "expires_in": 2592000
+     * }
+     */
+    public static String getAuth() {
+        // 官网获取的 API Key 更新为你注册的
+        String clientId = "346da55bb3c248ea84e39b5913939f05";
+        // 官网获取的 Secret Key 更新为你注册的
+        String clientSecret = "0628356ece284d87935f73017af1c0ce";
+        return getAuth(clientId, clientSecret);
+    }
+
+    /**
+     * 获取API访问token
+     * 该token有一定的有效期,需要自行管理,当失效时需重新获取.
+     * @param ak - 百度云官网获取的 API Key
+     * @param sk - 百度云官网获取的 Securet Key
+     * @return assess_token 示例:
+     * "24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567"
+     */
+    public static String getAuth(String ak, String sk) {
+        // 获取token地址
+        String authHost = "https://aip.baidubce.com/oauth/2.0/token?";
+        String getAccessTokenUrl = authHost
+                // 1. grant_type为固定参数
+                + "grant_type=client_credentials"
+                // 2. 官网获取的 API Key
+                + "&client_id=" + ak
+                // 3. 官网获取的 Secret Key
+                + "&client_secret=" + sk;
+        try {
+            URL realUrl = new URL(getAccessTokenUrl);
+            // 打开和URL之间的连接
+            HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
+            connection.setRequestMethod("GET");
+            connection.connect();
+            // 获取所有响应头字段
+            Map<String, List<String>> map = connection.getHeaderFields();
+            // 遍历所有的响应头字段
+            for (String key : map.keySet()) {
+                System.out.println(key + "--->" + map.get(key));
+            }
+            // 定义 BufferedReader输入流来读取URL的响应
+            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
+            String result = "";
+            String line;
+            while ((line = in.readLine()) != null) {
+                result += line;
+            }
+            /**
+             * 返回结果示例
+             */
+            System.out.println("result:" + result);
+            JSONObject jsonObject = new JSONObject(result);
+            String access_token = jsonObject.getString("access_token");
+            return access_token;
+        } catch (Exception e) {
+            System.err.printf("获取token失败!");
+            e.printStackTrace(System.err);
+        }
+        return null;
+    }
+
+}

+ 31 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/MyApplicationLisenter.java

@@ -0,0 +1,31 @@
+package com.iotechn.unimall.admin;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.stereotype.Component;
+
+/**
+ * @Author:chengchangjiang
+ * @Description:
+ * @Date:Created in 12:34 2022-06-16
+ */
+@Component
+public class MyApplicationLisenter implements ApplicationListener<ContextRefreshedEvent> {
+
+    private static Logger logger = LoggerFactory.getLogger(MyApplicationLisenter.class);
+
+    @Override
+    public void onApplicationEvent(ContextRefreshedEvent e) {
+        logger.info("实现了ApplicationListener的onApplicationEvent方法");
+//        new Thread(new Runnable() {
+//            @Override
+//            public void run() {
+//            }
+//        }).start();
+    }
+
+
+}

+ 13 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/UnimallAdminApiApplication.java

@@ -0,0 +1,13 @@
+package com.iotechn.unimall.admin;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class UnimallAdminApiApplication {
+
+	public static void main(String[] args) {
+		SpringApplication.run(UnimallAdminApiApplication.class, args);
+	}
+
+}

+ 79 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/admin/AdminService.java

@@ -0,0 +1,79 @@
+package com.iotechn.unimall.admin.api.admin;
+
+import com.iotechn.unimall.core.Const;
+import com.iotechn.unimall.core.annotation.HttpMethod;
+import com.iotechn.unimall.core.annotation.HttpOpenApi;
+import com.iotechn.unimall.core.annotation.HttpParam;
+import com.iotechn.unimall.core.annotation.HttpParamType;
+import com.iotechn.unimall.core.annotation.param.NotNull;
+import com.iotechn.unimall.core.exception.ServiceException;
+import com.iotechn.unimall.data.dto.AdminDTO;
+import com.iotechn.unimall.data.model.Page;
+
+/**
+ * Created by rize on 2019/4/8.
+ */
+@HttpOpenApi(group = "admin", description = "管理员服务")
+public interface AdminService {
+
+	@HttpMethod(description = "管理员登录 返回AccessToken")
+	public String login(
+			@NotNull @HttpParam(name = "loginIp", type = HttpParamType.IP, description = "用户登陆IP") String loginIp,
+			@NotNull @HttpParam(name = "browserName", type = HttpParamType.BrowserName, description = "浏览器名称") String browserName,
+			@NotNull @HttpParam(name = "browserVersion", type = HttpParamType.BrowserVersion, description = "浏览器版本") String browserVersion,
+			@NotNull @HttpParam(name = "osName", type = HttpParamType.OsName, description = "系统名称") String osName,
+			@NotNull @HttpParam(name = "username", type = HttpParamType.COMMON, description = "用户名") String username,
+			@NotNull @HttpParam(name = "password", type = HttpParamType.COMMON, description = "密码") String password,
+			@NotNull @HttpParam(name = "verifyCode", type = HttpParamType.COMMON, description = "验证码") String verifyCode)
+			throws ServiceException;
+
+	@HttpMethod(description = "管理员登出")
+	public String logout(
+			@NotNull @HttpParam(name = Const.ADMIN_ACCESS_TOKEN, type = HttpParamType.HEADER, description = "访问Token") String accessToken,
+			@NotNull @HttpParam(name = "adminId", type = HttpParamType.ADMIN_ID, description = "管理员ID") Long adminId)
+			throws ServiceException;
+
+	@HttpMethod(description = "管理员信息")
+	public AdminDTO info(
+			@NotNull @HttpParam(name = "adminId", type = HttpParamType.ADMIN_ID, description = "管理员ID") Long adminId)
+			throws ServiceException;
+
+	@HttpMethod(description = "列表", permission = "admin:admin:list", permissionParentName = "系统管理", permissionName = "管理员")
+	public Page<AdminDTO> list(
+			@HttpParam(name = "username", type = HttpParamType.COMMON, description = "管理员名称搜索") String name,
+			@HttpParam(name = "page", type = HttpParamType.COMMON, description = "页码", valueDef = "1") Integer page,
+			@HttpParam(name = "limit", type = HttpParamType.COMMON, description = "页长度", valueDef = "20") Integer limit,
+			@NotNull @HttpParam(name = "adminId", type = HttpParamType.ADMIN_ID, description = "管理员ID") Long adminId)
+			throws ServiceException;
+
+	@HttpMethod(description = "创建", permission = "admin:admin:create", permissionParentName = "系统管理", permissionName = "管理员")
+	public AdminDTO create(
+			@NotNull @HttpParam(name = "adminDTO", type = HttpParamType.COMMON, description = "欲创建的admin对象JSON") AdminDTO adminDTO,
+			@NotNull @HttpParam(name = "adminId", type = HttpParamType.ADMIN_ID, description = "管理员ID") Long adminId)
+			throws ServiceException;
+
+	@HttpMethod(description = "修改", permission = "admin:admin:update", permissionParentName = "系统管理", permissionName = "管理员")
+	public String update(
+			@NotNull @HttpParam(name = "adminDTO", type = HttpParamType.COMMON, description = "欲修改的admin对象JSON") AdminDTO adminDTO,
+			@NotNull @HttpParam(name = "adminId", type = HttpParamType.ADMIN_ID, description = "管理员ID") Long adminId)
+			throws ServiceException;
+
+	@HttpMethod(description = "删除", permission = "admin:admin:delete", permissionParentName = "系统管理", permissionName = "管理员")
+	public String delete(@NotNull @HttpParam(name = "id", type = HttpParamType.COMMON, description = "目标删除Id") Long id,
+			@NotNull @HttpParam(name = "adminId", type = HttpParamType.ADMIN_ID, description = "管理员ID") Long adminId)
+			throws ServiceException;
+
+	@HttpMethod(description = "更改密码")
+	public String newPassword(
+			@HttpParam(name = Const.ADMIN_ACCESS_TOKEN, type = HttpParamType.HEADER, description = "访问Token") String accessToken,
+			@NotNull @HttpParam(name = "oldPassword", type = HttpParamType.COMMON, description = "老密码") String oldPassword,
+			@NotNull @HttpParam(name = "newPassword", type = HttpParamType.COMMON, description = "新密码") String newPassword,
+			@NotNull @HttpParam(name = "adminId", type = HttpParamType.ADMIN_ID, description = "管理员ID") Long adminId)
+			throws ServiceException;
+
+	@HttpMethod(description = "发送登陆短信")
+	public Boolean sendLoginMsg(
+			@NotNull @HttpParam(name = "username", type = HttpParamType.COMMON, description = "用户名") String username,
+			@NotNull @HttpParam(name = "password", type = HttpParamType.COMMON, description = "密码") String password)
+			throws ServiceException;
+}

+ 248 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/admin/AdminServiceImpl.java

@@ -0,0 +1,248 @@
+package com.iotechn.unimall.admin.api.admin;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.baomidou.mybatisplus.mapper.Wrapper;
+import com.iotechn.unimall.core.Const;
+import com.iotechn.unimall.core.exception.AdminServiceException;
+import com.iotechn.unimall.core.exception.ExceptionDefinition;
+import com.iotechn.unimall.core.exception.ServiceException;
+import com.iotechn.unimall.core.exception.ThirdPartServiceException;
+import com.iotechn.unimall.core.notify.SMSClient;
+import com.iotechn.unimall.core.notify.SMSResult;
+import com.iotechn.unimall.core.util.GeneratorUtil;
+import com.iotechn.unimall.core.util.MD5Util;
+import com.iotechn.unimall.data.component.CacheComponent;
+import com.iotechn.unimall.data.domain.AdminDO;
+import com.iotechn.unimall.data.domain.RoleDO;
+import com.iotechn.unimall.data.domain.RolePermissionDO;
+import com.iotechn.unimall.data.dto.AdminDTO;
+import com.iotechn.unimall.data.enums.AdminStatusType;
+import com.iotechn.unimall.data.enums.RoleStatusType;
+import com.iotechn.unimall.data.mapper.AdminMapper;
+import com.iotechn.unimall.data.mapper.RoleMapper;
+import com.iotechn.unimall.data.mapper.RolePermissionMapper;
+import com.iotechn.unimall.data.model.Page;
+import com.iotechn.unimall.data.util.IpUtils;
+import com.iotechn.unimall.data.util.SessionUtil;
+import org.apache.ibatis.session.RowBounds;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Created by rize on 2019/4/8.
+ */
+@Service
+public class AdminServiceImpl implements AdminService {
+
+	@Autowired
+	private StringRedisTemplate userRedisTemplate;
+
+	@Autowired
+	private AdminMapper adminMapper;
+
+	@Autowired
+	private RoleMapper roleMapper;
+
+	@Autowired
+	private RolePermissionMapper rolePermissionMapper;
+
+	@Autowired
+	private CacheComponent cacheComponent;
+
+	@Autowired
+	private SMSClient smsClient;
+
+	private final static String ADMIN_MSG_CODE = "admin_msg_code_";
+
+	@Override
+	public String login(String loginIp, String browserName, String browserVersion, String osName, String username,
+			String password, String verifyCode) throws ServiceException {
+		String accessToken = generateAccessToken();
+		// 数据库查管理员
+		List<AdminDO> adminDOS = adminMapper.selectList(new EntityWrapper<AdminDO>().eq("username", username));
+		if (CollectionUtils.isEmpty(adminDOS)) {
+			throw new AdminServiceException(ExceptionDefinition.ADMIN_NOT_EXIST);
+		}
+		AdminDO adminDO = adminDOS.get(0);
+		// 短信验证码
+//        String code = cacheComponent.getRaw(ADMIN_MSG_CODE+adminDO.getPhone() );
+//        if(!"guest".equals(username) && (code == null || verifyCode==null || !code.equals(verifyCode))){
+//            throw new AdminServiceException(ExceptionDefinition.ADMIN_VERIFYCODE_ERROR);
+//        }
+
+		if (!MD5Util.verify(password, username, adminDO.getPassword())) {
+			throw new AdminServiceException(ExceptionDefinition.ADMIN_PASSWORD_ERROR);
+		}
+		List<Long> ids = JSONObject.parseArray(adminDO.getRoleIds(), Long.class);
+		if (CollectionUtils.isEmpty(ids)) {
+			throw new AdminServiceException(ExceptionDefinition.ADMIN_ROLE_IS_EMPTY);
+		}
+		List<RoleDO> roleDOList = roleMapper
+				.selectList(new EntityWrapper<RoleDO>().in("id", ids).eq("status", RoleStatusType.ACTIVE.getCode()));
+		List<String> roleNames = new LinkedList<>();
+		roleDOList.forEach(item -> {
+			roleNames.add(item.getName());
+		});
+		AdminDTO adminDTO = new AdminDTO();
+		adminDTO.setRoles(roleNames);
+		BeanUtils.copyProperties(adminDO, adminDTO);
+		adminDTO.setRoleIds(JSONObject.parseArray(adminDO.getRoleIds(), Long.class));
+		adminDTO.setPassword(null);
+		List<RolePermissionDO> rolePermissionDOList = rolePermissionMapper
+				.selectList(new EntityWrapper<RolePermissionDO>().in("role_id", ids).eq("deleted", 0));
+		List<String> permissionNames = new LinkedList<>();
+		rolePermissionDOList.forEach(item -> {
+			permissionNames.add(item.getPermission());
+		});
+		adminDTO.setPerms(permissionNames);
+		JSONObject loginUserInfo = (JSONObject) JSONObject.toJSON(adminDTO);
+		loginUserInfo.put("loginIp", loginIp);
+		loginUserInfo.put("loginTime", new Date());
+		loginUserInfo.put("browser", browserName + "(" + browserVersion + ")");
+		loginUserInfo.put("osName", osName);
+		userRedisTemplate.opsForValue().set(Const.ADMIN_REDIS_PREFIX + accessToken,
+				JSONObject.toJSONString(loginUserInfo), 30, TimeUnit.DAYS);
+		return accessToken;
+	}
+
+	@Override
+	public String logout(String accessToken, Long adminId) throws ServiceException {
+		userRedisTemplate.delete(Const.ADMIN_REDIS_PREFIX + accessToken);
+		return "ok";
+	}
+
+	@Override
+	public AdminDTO info(Long adminId) throws ServiceException {
+		return SessionUtil.getAdmin();
+	}
+
+	@Override
+	public Page<AdminDTO> list(String name, Integer page, Integer limit, Long adminId) throws ServiceException {
+		Wrapper<AdminDO> wrapper = new EntityWrapper<AdminDO>();
+		if (!StringUtils.isEmpty(name)) {
+			wrapper.like("username", name);
+		}
+		wrapper.orderBy("id", false);
+		Integer count = adminMapper.selectCount(wrapper);
+		List<AdminDO> adminDOS = adminMapper.selectPage(new RowBounds((page - 1) * limit, limit), wrapper);
+		List<AdminDTO> adminDTOS = new ArrayList<AdminDTO>(adminDOS.size());
+		for (AdminDO adminDO : adminDOS) {
+			AdminDTO adminDTO = new AdminDTO();
+			BeanUtils.copyProperties(adminDO, adminDTO);
+			adminDTO.setRoleIds(JSONObject.parseArray(adminDO.getRoleIds(), Long.class));
+			adminDTO.setPassword(null);
+			adminDTOS.add(adminDTO);
+		}
+		return new Page<>(adminDTOS, page, limit, count);
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public AdminDTO create(AdminDTO adminDTO, Long adminId) throws ServiceException {
+		AdminDO adminDO = new AdminDO();
+		Integer count = adminMapper.selectCount(new EntityWrapper<AdminDO>().eq("username", adminDTO.getUsername()));
+		if (count > 0) {
+			throw new AdminServiceException(ExceptionDefinition.ADMIN_USER_NAME_REPEAT);
+		}
+		BeanUtils.copyProperties(adminDTO, adminDO);
+		adminDO.setPassword(MD5Util.md5(adminDO.getPassword(), adminDO.getUsername()));
+		adminDO.setRoleIds(JSONObject.toJSONString(adminDTO.getRoleIds()));
+		adminDO.setGmtUpdate(new Date());
+		adminDO.setGmtCreate(adminDO.getGmtUpdate());
+		adminDO.setStatus(AdminStatusType.ACTIVE.getCode());
+		adminDO.setLastLoginIp("0.0.0.0");
+		adminDO.setGmtLastLogin("1997-01-20 00:00:00");
+		if (adminMapper.insert(adminDO) > 0) {
+			adminDTO.setId(adminDO.getId());
+			return adminDTO;
+		}
+		throw new AdminServiceException(ExceptionDefinition.ADMIN_UNKNOWN_EXCEPTION);
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public String update(AdminDTO adminDTO, Long adminId) throws ServiceException {
+		Long id = adminDTO.getId();
+		if (id == null) {
+			throw new AdminServiceException(ExceptionDefinition.ADMIN_UNKNOWN_EXCEPTION);
+		}
+		AdminDO adminDO = new AdminDO();
+		BeanUtils.copyProperties(adminDTO, adminDO);
+		adminDO.setGmtUpdate(new Date());
+		AdminDO adminDOExist = adminMapper.selectById(id);
+		if (!StringUtils.isEmpty(adminDO.getPassword()) && !StringUtils.isEmpty(adminDOExist.getUsername())) {
+			adminDO.setPassword(MD5Util.md5(adminDO.getPassword(), adminDOExist.getUsername()));
+		}
+		adminDO.setUsername(null);
+		if (!CollectionUtils.isEmpty(adminDTO.getRoleIds())) {
+			adminDO.setRoleIds(JSONObject.toJSONString(adminDTO.getRoleIds()));
+		}
+		if (adminMapper.updateById(adminDO) > 0) {
+			return "ok";
+		}
+		throw new AdminServiceException(ExceptionDefinition.ADMIN_UNKNOWN_EXCEPTION);
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public String delete(Long id, Long adminId) throws ServiceException {
+		if (adminMapper.deleteById(id) > 0) {
+			return "ok";
+		}
+		throw new AdminServiceException(ExceptionDefinition.ADMIN_UNKNOWN_EXCEPTION);
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public String newPassword(String accessToken, String oldPassword, String newPassword, Long adminId)
+			throws ServiceException {
+		AdminDO adminDOExist = adminMapper.selectById(adminId);
+		if (!MD5Util.md5(oldPassword, adminDOExist.getUsername()).equals(adminDOExist.getPassword())) {
+			throw new AdminServiceException(ExceptionDefinition.ADMIN_PASSWORD_ERROR);
+		}
+		AdminDO adminDO = new AdminDO();
+		adminDO.setId(adminId);
+		adminDO.setPassword(MD5Util.md5(newPassword, adminDOExist.getUsername()));
+		if (adminMapper.updateById(adminDO) > 0) {
+			// logout(accessToken, adminId);
+			return "ok";
+		}
+		throw new AdminServiceException(ExceptionDefinition.ADMIN_UNKNOWN_EXCEPTION);
+	}
+
+	@Override
+	public Boolean sendLoginMsg(String username, String password) throws ServiceException {
+		if ("guest".equals(username)) {
+			throw new AdminServiceException(ExceptionDefinition.ADMIN_GUEST_NOT_NEED_VERIFY_CODE);
+		}
+		AdminDO adminDO = new AdminDO();
+		adminDO.setUsername(username);
+		adminDO.setPassword(MD5Util.md5(password, username));
+		AdminDO admin = adminMapper.selectOne(adminDO);
+		if (admin == null) {
+			throw new AdminServiceException(ExceptionDefinition.ADMIN_USER_NOT_EXITS);
+		}
+		String code = GeneratorUtil.genSixVerifyCode();
+		cacheComponent.putRaw(ADMIN_MSG_CODE + admin.getPhone(), code, 300);
+		SMSResult smsResult = smsClient.sendAdminLoginVerify(admin.getPhone(), code);
+		if (!smsResult.isSucc()) {
+			throw new ThirdPartServiceException(smsResult.getMsg(),
+					ExceptionDefinition.ADMIN_VERIFY_CODE_SEND_FAIL.getCode());
+		}
+		return true;
+	}
+
+	private String generateAccessToken() {
+		return (UUID.randomUUID().toString().replace("-", ""));
+	}
+
+}

+ 71 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/advertisement/AdminAdvertisementService.java

@@ -0,0 +1,71 @@
+package com.iotechn.unimall.admin.api.advertisement;
+
+import com.iotechn.unimall.core.annotation.HttpMethod;
+import com.iotechn.unimall.core.annotation.HttpOpenApi;
+import com.iotechn.unimall.core.annotation.HttpParam;
+import com.iotechn.unimall.core.annotation.HttpParamType;
+import com.iotechn.unimall.core.annotation.param.NotNull;
+import com.iotechn.unimall.core.annotation.param.Range;
+import com.iotechn.unimall.core.exception.ServiceException;
+import com.iotechn.unimall.data.domain.AdvertisementDO;
+import com.iotechn.unimall.data.enums.StatusType;
+import com.iotechn.unimall.data.model.Page;
+
+import java.util.List;
+
+/**
+ * Created with IntelliJ IDEA.
+ * Description:
+ * User: kbq
+ * Date: 2019-07-08
+ * Time: 下午8:23
+ */
+
+@HttpOpenApi(group = "admin.advertisement", description = "广告推销")
+public interface AdminAdvertisementService {
+
+    @HttpMethod(description = "创建", permission = "promote:advertisement:create", permissionParentName = "推广管理", permissionName = "广告管理")
+    public Boolean addAdvertisement(
+            @NotNull @HttpParam(name = "adminId", type = HttpParamType.ADMIN_ID, description = "管理员ID") Long adminId,
+            @NotNull @HttpParam(name = "adType", type = HttpParamType.COMMON, description = "广告类型") Integer adType,
+            @HttpParam(name = "title", type = HttpParamType.COMMON, description = "广告标题") String title,
+            @NotNull @HttpParam(name = "url", type = HttpParamType.COMMON, description = "广告地址") String url,
+            @NotNull @HttpParam(name = "imgUrl", type = HttpParamType.COMMON, description = "广告图片地址") String imgUrl,
+            @NotNull @HttpParam(name = "status", type = HttpParamType.COMMON, description = "广告状态") Integer status,
+            @NotNull @HttpParam(name = "color", type = HttpParamType.COMMON, description = "广告图片颜色") String color) throws ServiceException;
+
+    @HttpMethod(description = "删除", permission = "promote:advertisement:delete", permissionParentName = "推广管理", permissionName = "广告管理")
+    public Boolean deleteAdvertisement(
+            @NotNull @HttpParam(name = "adminId", type = HttpParamType.ADMIN_ID, description = "管理员ID") Long adminId,
+            @NotNull @HttpParam(name = "adType", type = HttpParamType.COMMON, description = "广告类型") Integer adType,
+            @NotNull @HttpParam(name = "adId", type = HttpParamType.COMMON, description = "广告ID") Long adId) throws ServiceException;
+
+    @HttpMethod(description = "修改", permission = "promote:advertisement:update", permissionParentName = "推广管理", permissionName = "广告管理")
+    public Boolean updateAdvertisement(
+            @NotNull @HttpParam(name = "adminId", type = HttpParamType.ADMIN_ID, description = "管理员ID") Long adminId,
+            @NotNull @HttpParam(name = "adId", type = HttpParamType.COMMON, description = "广告ID") Long adId,
+            @NotNull @HttpParam(name = "adType", type = HttpParamType.COMMON, description = "广告类型") Integer adType,
+            @HttpParam(name = "title", type = HttpParamType.COMMON, description = "广告标题") String title,
+            @HttpParam(name = "url", type = HttpParamType.COMMON, description = "广告地址") String url,
+            @HttpParam(name = "imgUrl", type = HttpParamType.COMMON, description = "广告图片地址") String imgUrl,
+            @HttpParam(name = "status", type = HttpParamType.COMMON, description = "广告状态") Integer status,
+            @HttpParam(name = "color", type = HttpParamType.COMMON, description = "广告图片颜色") String color) throws ServiceException;
+
+
+    @HttpMethod(description = "查询", permission = "promote:advertisement:query", permissionParentName = "推广管理", permissionName = "广告管理")
+    public Page<AdvertisementDO> queryAdvertisement(
+            @NotNull @HttpParam(name = "adminId", type = HttpParamType.ADMIN_ID, description = "管理员ID") Long adminId,
+            @HttpParam(name = "adType", type = HttpParamType.COMMON, description = "广告类型") Integer adType,
+            @Range(min = 1) @HttpParam(name = "pageNo", type = HttpParamType.COMMON, description = "页码", valueDef = "1") Integer pageNo,
+            @Range(min = 1) @HttpParam(name = "limit", type = HttpParamType.COMMON, description = "页面长度", valueDef = "10") Integer limit,
+            @HttpParam(name = "status", type = HttpParamType.COMMON, description = "广告状态") Integer status) throws ServiceException;
+
+    @HttpMethod(description = "查询", permission = "promote:advertisement:query", permissionParentName = "推广管理", permissionName = "广告管理")
+    public Page<AdvertisementDO> queryAllAdvertisement(
+            @NotNull @HttpParam(name = "adminId", type = HttpParamType.ADMIN_ID, description = "管理员ID") Long adminId,
+            @Range(min = 1) @HttpParam(name = "pageNo", type = HttpParamType.COMMON, description = "页码", valueDef = "1") Integer pageNo,
+            @Range(min = 1) @HttpParam(name = "limit", type = HttpParamType.COMMON, description = "页面长度", valueDef = "10") Integer pageSize
+    ) throws ServiceException;
+
+
+}

+ 108 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/advertisement/AdminAdvertisementServiceImpl.java

@@ -0,0 +1,108 @@
+package com.iotechn.unimall.admin.api.advertisement;
+
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.baomidou.mybatisplus.mapper.Wrapper;
+import com.iotechn.unimall.core.exception.AdminServiceException;
+import com.iotechn.unimall.core.exception.ExceptionDefinition;
+import com.iotechn.unimall.core.exception.ServiceException;
+import com.iotechn.unimall.data.component.CacheComponent;
+import com.iotechn.unimall.data.domain.AdvertisementDO;
+import com.iotechn.unimall.data.mapper.AdvertisementMapper;
+import com.iotechn.unimall.data.model.Page;
+import org.apache.ibatis.session.RowBounds;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Created with IntelliJ IDEA.
+ * Description:
+ * User: kbq
+ * Date: 2019-07-08
+ * Time: 下午9:24
+ */
+@Service
+public class AdminAdvertisementServiceImpl implements AdminAdvertisementService {
+
+    @Autowired
+    private AdvertisementMapper advertisementMapper;
+    @Autowired
+    private CacheComponent cacheComponent;
+
+    private  final  static String  ADVERTISEMENT_NAME = "ADVERTISEMENT_TYPE_";
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean addAdvertisement(Long adminId, Integer adType, String title, String url, String imgUrl, Integer status,String color) throws ServiceException {
+
+        Date now = new Date();
+        AdvertisementDO advertisementDO = new AdvertisementDO(adType,title,url,imgUrl,status,color);
+        advertisementDO.setGmtCreate(now);
+        advertisementDO.setGmtUpdate(now);
+
+        if(advertisementMapper.insert(advertisementDO) > 0){
+            cacheComponent.delPrefixKey(ADVERTISEMENT_NAME);
+            return true;
+        }
+        throw new AdminServiceException(ExceptionDefinition.ADVERTISEMENT_SQL_ADD_FAILED);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean deleteAdvertisement(Long adminId,Integer adType, Long adId) throws ServiceException {
+
+        if(advertisementMapper.delete(new EntityWrapper<AdvertisementDO>()
+                .eq("id",adId)
+                .eq("ad_type",adType)) > 0){
+            cacheComponent.delPrefixKey(ADVERTISEMENT_NAME);
+            return true;
+        }
+        throw new AdminServiceException(ExceptionDefinition.ADVERTISEMENT_SQL_DELETE_FAILED);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean updateAdvertisement(Long adminId,Long adId, Integer adType, String title, String url, String imgUrl, Integer status,String color) throws ServiceException {
+        AdvertisementDO advertisementDO = new AdvertisementDO(adType,title,url,imgUrl,status,color);
+        advertisementDO.setId(adId);
+        advertisementDO.setGmtUpdate(new Date());
+        if(advertisementMapper.updateById(advertisementDO)>0){
+            cacheComponent.delPrefixKey(ADVERTISEMENT_NAME);
+            return  true;
+        }
+        throw new AdminServiceException(ExceptionDefinition.ADVERTISEMENT_SQL_UPDATE_FAILED);
+    }
+
+    @Override
+    public Page<AdvertisementDO> queryAdvertisement(Long adminId, Integer adType, Integer pageNo, Integer limit, Integer status) throws ServiceException {
+        Wrapper<AdvertisementDO> wrapper = new EntityWrapper<AdvertisementDO>();
+        if (adType != null) {
+            wrapper.eq("ad_type", adType);
+        }
+        if (status != null) {
+            wrapper.eq("status", status);
+        }
+
+        List<AdvertisementDO> advertisementDOList = advertisementMapper.selectPage(new RowBounds(limit *(pageNo - 1), limit),wrapper);
+        Integer count = advertisementMapper.selectCount(wrapper);
+
+        Page<AdvertisementDO> page = new Page<>(advertisementDOList,pageNo, limit,count);
+
+        return page;
+
+    }
+
+    //冗余,未使用
+    @Override
+    public Page<AdvertisementDO> queryAllAdvertisement(Long adminId,Integer pageNo,Integer pageSize) throws ServiceException {
+
+        List<AdvertisementDO> advertisementDOList = advertisementMapper.getAllAdvertisement(pageSize*(pageNo-1),pageSize);
+        Integer count = advertisementMapper.selectCount(null);
+        Page<AdvertisementDO> page = new Page<>(advertisementDOList,pageNo,pageSize,count);
+        return page;
+
+    }
+}

+ 54 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/config/AdminMerchantConfigService.java

@@ -0,0 +1,54 @@
+package com.iotechn.unimall.admin.api.config;
+
+import com.iotechn.unimall.core.annotation.HttpMethod;
+import com.iotechn.unimall.core.annotation.HttpOpenApi;
+import com.iotechn.unimall.core.annotation.HttpParam;
+import com.iotechn.unimall.core.annotation.HttpParamType;
+import com.iotechn.unimall.core.annotation.param.NotNull;
+import com.iotechn.unimall.core.annotation.param.Range;
+import com.iotechn.unimall.core.exception.ServiceException;
+import com.iotechn.unimall.data.domain.CategoryDO;
+import com.iotechn.unimall.data.domain.ConfigDO;
+import com.iotechn.unimall.data.dto.CategoryTreeNodeDTO;
+import com.iotechn.unimall.data.dto.ConfigDTO;
+import com.iotechn.unimall.data.model.Page;
+
+import java.util.List;
+
+/**
+ * Created with IntelliJ IDEA.
+ * Description:
+ * User: kbq
+ * Date: 2019-07-20
+ * Time: 上午10:18
+ */
+
+@HttpOpenApi(group = "admin.merchant", description = "商铺信息配置")
+public interface AdminMerchantConfigService {
+
+    @HttpMethod(description = "创建", permission = "promote:merchant:create", permissionParentName = "推广管理", permissionName = "商铺信息管理")
+    public boolean addMerchant(
+            @NotNull @HttpParam(name = "adminId", type = HttpParamType.ADMIN_ID, description = "管理员ID") Long adminId,
+            @NotNull @HttpParam(name = "title", type = HttpParamType.COMMON, description = "商铺标题") String title,
+            @HttpParam(name = "logoUrl", type = HttpParamType.COMMON, description = "商铺logo") String logoUrl,
+            @HttpParam(name = "description", type = HttpParamType.COMMON, description = "商铺描述") String description,
+            @HttpParam(name = "address", type = HttpParamType.COMMON, description = "商铺地址") String address,
+            @NotNull @HttpParam(name = "showType", type = HttpParamType.COMMON, description = "展示方式") Integer showType
+    ) throws ServiceException;
+
+    @HttpMethod(description = "修改", permission = "promote:merchant:update", permissionParentName = "推广管理", permissionName = "商铺信息管理")
+    public boolean updateMerchant(
+            @NotNull @HttpParam(name = "adminId", type = HttpParamType.ADMIN_ID, description = "管理员ID") Long adminId,
+            @NotNull @HttpParam(name = "title", type = HttpParamType.COMMON, description = "商铺标题") String title,
+            @HttpParam(name = "logoUrl", type = HttpParamType.COMMON, description = "商铺logo") String logoUrl,
+            @HttpParam(name = "description", type = HttpParamType.COMMON, description = "商铺描述") String description,
+            @HttpParam(name = "address", type = HttpParamType.COMMON, description = "商铺地址") String address,
+            @NotNull @HttpParam(name = "showType", type = HttpParamType.COMMON, description = "展示方式") Integer showType
+    ) throws ServiceException;
+
+    @HttpMethod(description = "查询", permission = "promote:merchant:query", permissionParentName = "推广管理", permissionName = "商铺信息管理")
+    public ConfigDTO getMerchant(
+            @NotNull @HttpParam(name = "adminId", type = HttpParamType.ADMIN_ID, description = "管理员ID") Long adminId) throws ServiceException;
+
+
+}

+ 75 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/config/AdminMerchantConfigServiceImpl.java

@@ -0,0 +1,75 @@
+package com.iotechn.unimall.admin.api.config;
+
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.iotechn.unimall.biz.service.config.ConfigBizService;
+import com.iotechn.unimall.core.exception.ServiceException;
+import com.iotechn.unimall.data.domain.ConfigDO;
+import com.iotechn.unimall.data.dto.ConfigDTO;
+import com.iotechn.unimall.data.mapper.ConfigMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Date;
+
+/**
+ * Created with IntelliJ IDEA.
+ * Description:
+ * User: kbq
+ * Date: 2019-07-20
+ * Time: 上午10:47
+ */
+@Service
+public class AdminMerchantConfigServiceImpl implements AdminMerchantConfigService {
+
+    @Autowired
+    private ConfigMapper configMapper;
+
+    @Autowired
+    private ConfigBizService configBizService;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean addMerchant(Long adminId, String title, String logoUrl, String description, String address, Integer showType) throws ServiceException {
+        Date now = new Date();
+        ConfigDO titleDO = new ConfigDO("title",title);
+            titleDO.setGmtCreate(now);titleDO.setGmtUpdate(now);
+        ConfigDO logoDO = new ConfigDO("logoUrl",logoUrl);
+            logoDO.setGmtCreate(now);logoDO.setGmtUpdate(now);
+        ConfigDO descDO = new ConfigDO("description",description);
+            descDO.setGmtCreate(now);descDO.setGmtUpdate(now);
+        ConfigDO addressDO = new ConfigDO("address",address);
+            addressDO.setGmtCreate(now);addressDO.setGmtUpdate(now);
+        ConfigDO showTypeDO = new ConfigDO("showType",String.valueOf(showType));
+            showTypeDO.setGmtCreate(now);showTypeDO.setGmtUpdate(now);
+        configMapper.insert(titleDO);
+        configMapper.insert(logoDO);
+        configMapper.insert(descDO);
+        configMapper.insert(addressDO);
+        configMapper.insert(showTypeDO);
+        configBizService.clearMerchantConfigCache();
+        return true;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean updateMerchant(Long adminId, String title, String logoUrl, String description, String address, Integer showType) throws ServiceException {
+        configMapper.update(new ConfigDO("title",title), new EntityWrapper<ConfigDO>().eq("key_word","title"));
+
+        configMapper.update(new ConfigDO("logoUrl",logoUrl), new EntityWrapper<ConfigDO>().eq("key_word","logoUrl"));
+
+        configMapper.update(new ConfigDO("description",description), new EntityWrapper<ConfigDO>().eq("key_word","description"));
+
+        configMapper.update(new ConfigDO("address",address), new EntityWrapper<ConfigDO>().eq("key_word","address"));
+
+        configMapper.update(new ConfigDO("showType",String.valueOf(showType)), new EntityWrapper<ConfigDO>().eq("key_word","showType"));
+
+        configBizService.clearMerchantConfigCache();
+        return true;
+    }
+
+    @Override
+    public ConfigDTO getMerchant(Long adminId) throws ServiceException {
+        return configBizService.getMerchantConfig();
+    }
+}

+ 50 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/dict/DictDataService.java

@@ -0,0 +1,50 @@
+package com.iotechn.unimall.admin.api.dict;
+
+import java.util.List;
+
+import com.iotechn.unimall.core.annotation.HttpMethod;
+import com.iotechn.unimall.core.annotation.HttpOpenApi;
+import com.iotechn.unimall.core.annotation.HttpParam;
+import com.iotechn.unimall.core.annotation.HttpParamType;
+import com.iotechn.unimall.core.annotation.param.NotNull;
+import com.iotechn.unimall.core.exception.ServiceException;
+import com.iotechn.unimall.data.domain.sys.dict.SysDictData;
+import com.iotechn.unimall.data.model.Page;
+
+@HttpOpenApi(group = "admin.dictData", description = "字典数据服务")
+public interface DictDataService {
+	@HttpMethod(description = "创建", permission = "admin:dictData:add", permissionParentName = "系统管理", permissionName = "字典管理")
+	public Boolean add(
+			@NotNull @HttpParam(name = "dictData", type = HttpParamType.COMMON, description = "字典信息") SysDictData dictData)
+			throws ServiceException;
+
+	@HttpMethod(description = "列表",  permissionName = "字典管理")
+	public Page<SysDictData> list(
+			@HttpParam(name = "dictType", type = HttpParamType.COMMON, description = "字典类型") String dictType,
+			@HttpParam(name = "dictLabel", type = HttpParamType.COMMON, description = "字典标签") String dictLabel,
+			@HttpParam(name = "status", type = HttpParamType.COMMON, description = "状态") String status,
+			@HttpParam(name = "page", type = HttpParamType.COMMON, description = "页码", valueDef = "1") Integer page,
+			@HttpParam(name = "limit", type = HttpParamType.COMMON, description = "页码长度", valueDef = "20") Integer limit)
+			throws ServiceException;
+
+	@HttpMethod(description = "删除", permission = "admin:dictData:delete", permissionParentName = "系统管理", permissionName = "字典管理")
+	public Boolean delete(
+			@NotNull @HttpParam(name = "dictCodes", type = HttpParamType.COMMON, description = "字典Id") String dictCodes)
+			throws ServiceException;
+
+	@HttpMethod(description = "修改", permission = "admin:dictData:update", permissionParentName = "系统管理", permissionName = "字典管理")
+	public Boolean update(
+			@NotNull @HttpParam(name = "dictData", type = HttpParamType.COMMON, description = "字典信息") SysDictData dictData)
+			throws ServiceException;
+
+	@HttpMethod(description = "查询", permission = "admin:dictData:get", permissionParentName = "系统管理", permissionName = "字典管理")
+	public SysDictData get(
+			@HttpParam(name = "dictCode", type = HttpParamType.COMMON, description = "字典ID") String dictCode)
+			throws ServiceException;
+
+	@HttpMethod(description = "根据字典类型查询所属数据", permission = "admin:dictData:selectDictDataByType", permissionParentName = "系统管理", permissionName = "字典管理")
+	public List<SysDictData> selectDictDataByType(
+			@HttpParam(name = "dictType", type = HttpParamType.COMMON, description = "字典类型") String dictType)
+			throws ServiceException;
+
+}

+ 77 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/dict/DictDataserviceImpl.java

@@ -0,0 +1,77 @@
+package com.iotechn.unimall.admin.api.dict;
+
+import java.util.List;
+
+import org.apache.ibatis.session.RowBounds;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.baomidou.mybatisplus.mapper.Wrapper;
+import com.iotechn.unimall.core.exception.ServiceException;
+import com.iotechn.unimall.data.domain.sys.dict.SysDictData;
+import com.iotechn.unimall.data.mapper.sys.dict.SysDictDataMapper;
+import com.iotechn.unimall.data.model.Page;
+/**
+ * 
+ * @author dyl
+ *
+ */
+@Service
+public class DictDataserviceImpl implements DictDataService{
+
+	@Autowired
+	private SysDictDataMapper dictDataMapper;
+	
+	@Override
+	public Boolean add(SysDictData dictData) throws ServiceException {
+		return dictDataMapper.insert(dictData)>0;
+	}
+
+	@Override
+	public Page<SysDictData> list(String dictType, String dictLabel, String status,Integer page, Integer limit)
+			throws ServiceException {
+		Wrapper<SysDictData> wrapper = new EntityWrapper<SysDictData>();
+		if (!StringUtils.isEmpty(dictType)) {
+			wrapper.eq("dict_type", dictType);
+		}
+		if (!StringUtils.isEmpty(dictType)) {
+			wrapper.like("dict_label", dictLabel);
+		}
+		if (!StringUtils.isEmpty(status)) {
+			wrapper.like("status", status);
+		}
+		List<SysDictData> SysDictDataS = dictDataMapper.selectPage(new RowBounds((page - 1) * limit, limit), wrapper);
+		Integer count = dictDataMapper.selectCount(wrapper);
+		return new Page<SysDictData>(SysDictDataS, page, limit, count);
+	}
+
+	@Override
+	public Boolean delete(String dictCodes) throws ServiceException {
+		String[] ids=dictCodes.split(",");
+		Wrapper<SysDictData> wrapper = new EntityWrapper<SysDictData>();
+		wrapper.in("dict_code", ids);
+		return dictDataMapper.delete(wrapper)>0;
+	}
+
+	@Override
+	public Boolean update(SysDictData dictData) throws ServiceException {
+		return dictDataMapper.updateById(dictData)>0;
+	}
+
+	@Override
+	public SysDictData get(String dictCode) throws ServiceException {
+		return dictDataMapper.selectById(dictCode);
+	}
+
+	@Override
+	public List<SysDictData> selectDictDataByType(String dictType) throws ServiceException {
+		Wrapper<SysDictData> wrapper = new EntityWrapper<SysDictData>();
+        if (!StringUtils.isEmpty(dictType)) {
+            wrapper.eq("dict_type", dictType);
+        }
+		return dictDataMapper.selectList(wrapper);
+	}
+
+}

+ 48 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/dict/DictTypeService.java

@@ -0,0 +1,48 @@
+package com.iotechn.unimall.admin.api.dict;
+
+import java.util.List;
+
+import com.iotechn.unimall.core.annotation.HttpMethod;
+import com.iotechn.unimall.core.annotation.HttpOpenApi;
+import com.iotechn.unimall.core.annotation.HttpParam;
+import com.iotechn.unimall.core.annotation.HttpParamType;
+import com.iotechn.unimall.core.annotation.param.NotNull;
+import com.iotechn.unimall.core.exception.ServiceException;
+import com.iotechn.unimall.data.domain.sys.dict.SysDictType;
+import com.iotechn.unimall.data.model.Page;
+
+@HttpOpenApi(group = "admin.dictType", description = "字典类型服务")
+public interface DictTypeService {
+	@HttpMethod(description = "创建", permission = "admin:dictType:add", permissionParentName = "系统管理", permissionName = "字典管理")
+	public Boolean add(
+			@NotNull @HttpParam(name = "dictType", type = HttpParamType.COMMON, description = "字典信息") SysDictType dictType)
+			throws ServiceException;
+
+	@HttpMethod(description = "列表", permission = "admin:dictType:list", permissionParentName = "系统管理", permissionName = "字典管理")
+	public Page<SysDictType> list(
+			@HttpParam(name = "dictName", type = HttpParamType.COMMON, description = "字典名称") String dictName,
+			@HttpParam(name = "dictType", type = HttpParamType.COMMON, description = "字典类型") String dictType,
+			@HttpParam(name = "page", type = HttpParamType.COMMON, description = "页码", valueDef = "1") Integer page,
+			@HttpParam(name = "limit", type = HttpParamType.COMMON, description = "页码长度", valueDef = "20") Integer limit)
+			throws ServiceException;
+
+	@HttpMethod(description = "删除", permission = "admin:dictType:delete", permissionParentName = "系统管理", permissionName = "字典管理")
+	public Boolean delete(
+			@NotNull @HttpParam(name = "dictIds", type = HttpParamType.COMMON, description = "字典Id") String dictIds)
+			throws ServiceException;
+
+	@HttpMethod(description = "修改", permission = "admin:dictType:update", permissionParentName = "系统管理", permissionName = "字典管理")
+	public Boolean update(
+			@NotNull @HttpParam(name = "dictType", type = HttpParamType.COMMON, description = "字典信息") SysDictType dictType)
+			throws ServiceException;
+
+	@HttpMethod(description = "查询", permission = "admin:dictType:get", permissionParentName = "系统管理", permissionName = "字典管理")
+	public SysDictType get(
+			@HttpParam(name = "dictId", type = HttpParamType.COMMON, description = "字典ID") Long dictId)
+			throws ServiceException;
+
+	@HttpMethod(description = "字典选择框列表", permission = "admin:dictType:optionselect", permissionParentName = "系统管理", permissionName = "字典管理")
+	public List<SysDictType> optionselect()throws ServiceException;
+
+
+}

+ 86 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/dict/DictTypeServiceImpl.java

@@ -0,0 +1,86 @@
+package com.iotechn.unimall.admin.api.dict;
+
+import java.util.List;
+
+import org.apache.ibatis.session.RowBounds;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.baomidou.mybatisplus.mapper.Wrapper;
+import com.iotechn.unimall.core.exception.AdminServiceException;
+import com.iotechn.unimall.core.exception.ExceptionDefinition;
+import com.iotechn.unimall.core.exception.ServiceException;
+import com.iotechn.unimall.data.domain.sys.dict.SysDictType;
+import com.iotechn.unimall.data.mapper.sys.dict.SysDictTypeMapper;
+import com.iotechn.unimall.data.model.Page;
+
+/**
+ * 
+ * @author dyl
+ *
+ */
+@Service
+public class DictTypeServiceImpl implements DictTypeService {
+
+	@Autowired
+	private SysDictTypeMapper typeMapper;
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public Boolean add(SysDictType sysDictType) throws ServiceException {
+		Long dictId;
+		if (sysDictType.getDictId() == null)
+			dictId = -1L;
+		else
+			dictId = sysDictType.getDictId();
+		SysDictType dictType = typeMapper.checkDictTypeUnique(sysDictType);
+		if (dictType != null && dictType.getDictId().longValue() != dictId.longValue()) {
+			throw new AdminServiceException(ExceptionDefinition.DICT_TYPE_HAS_EXISTED);
+		}
+		return typeMapper.insert(sysDictType) > 0;
+	}
+
+	@Override
+	public Page<SysDictType> list(String dictName, String dictType, Integer page, Integer limit)
+			throws ServiceException {
+		Wrapper<SysDictType> wrapper = new EntityWrapper<SysDictType>();
+		if (!StringUtils.isEmpty(dictName)) {
+			wrapper.like("dict_name", dictName);
+		}
+		if (!StringUtils.isEmpty(dictType)) {
+			wrapper.eq("dict_type", dictType);
+		}
+		List<SysDictType> SysDictTypeS = typeMapper.selectPage(new RowBounds((page - 1) * limit, limit), wrapper);
+		Integer count = typeMapper.selectCount(wrapper);
+		return new Page<SysDictType>(SysDictTypeS, page, limit, count);
+	}
+
+	@Override
+	public Boolean delete(String dictIds) throws ServiceException {
+		String[] ids=dictIds.split(",");
+		Wrapper<SysDictType> wrapper = new EntityWrapper<SysDictType>();
+		wrapper.in("dict_id", ids);
+		return typeMapper.delete(wrapper) > 0;
+	}
+
+	@Override
+	public Boolean update(SysDictType dictType) throws ServiceException {
+
+		return typeMapper.updateById(dictType) > 0;
+	}
+
+	@Override
+	public SysDictType get(Long dictId) throws ServiceException {
+		return typeMapper.selectById(dictId);
+	}
+
+	@Override
+	public List<SysDictType> optionselect() throws ServiceException {
+		return typeMapper.selectDictTypeAll();
+	}
+
+
+}

+ 40 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/log/loginLog/SysLogininforService.java

@@ -0,0 +1,40 @@
+package com.iotechn.unimall.admin.api.log.loginLog;
+
+import com.iotechn.unimall.core.annotation.HttpMethod;
+import com.iotechn.unimall.core.annotation.HttpOpenApi;
+import com.iotechn.unimall.core.annotation.HttpParam;
+import com.iotechn.unimall.core.annotation.HttpParamType;
+import com.iotechn.unimall.core.annotation.param.NotNull;
+import com.iotechn.unimall.core.exception.ServiceException;
+import com.iotechn.unimall.data.domain.log.SysLogininfor;
+import com.iotechn.unimall.data.model.Page;
+
+@HttpOpenApi(group = "admin.log.logininfor", description = "登陆日志管理")
+public interface SysLogininforService {
+	@HttpMethod(description = "登陆日志列表", permission = "admin:log:logininfor:list", permissionParentName = "日志管理", permissionName = "登陆日志管理")
+	public Page<SysLogininfor> list(
+			@HttpParam(name = "ipaddr", type = HttpParamType.COMMON, description = "登录地址") String ipaddr,
+			@HttpParam(name = "userName", type = HttpParamType.COMMON, description = "用户名称") String userName,
+			@HttpParam(name = "status", type = HttpParamType.COMMON, description = "状态") String status,
+			@HttpParam(name = "beginTime", type = HttpParamType.COMMON, description = "登陆开始时间") String beginTime,
+			@HttpParam(name = "endTime", type = HttpParamType.COMMON, description = "登陆结束时间") String endTime,
+			@HttpParam(name = "pageNum", type = HttpParamType.COMMON, description = "页码", valueDef = "1") Integer page,
+			@HttpParam(name = "pageSize", type = HttpParamType.COMMON, description = "页码长度", valueDef = "20") Integer limit)
+			throws ServiceException;
+	@HttpMethod(description = "删除登陆日志", permission = "admin:log:logininfor:delete", permissionParentName = "日志管理", permissionName = "登陆日志管理")
+	public Boolean delete(
+			@NotNull @HttpParam(name = "infoIds", type = HttpParamType.COMMON, description = "日志Id") String infoIds)
+			throws ServiceException;
+	
+	@HttpMethod(description = "清空登陆日志", permission = "admin:log:logininfor:clean", permissionParentName = "日志管理", permissionName = "登陆日志管理")
+	public Boolean clean()throws ServiceException;
+	
+	@HttpMethod(description = "导出日志列表", permission = "admin:log:logininfor:export", permissionParentName = "日志管理", permissionName = "登陆日志管理")
+	public String export(
+			@HttpParam(name = "ipaddr", type = HttpParamType.COMMON, description = "登录地址") String ipaddr,
+			@HttpParam(name = "userName", type = HttpParamType.COMMON, description = "用户名称") String userName,
+			@HttpParam(name = "status", type = HttpParamType.COMMON, description = "状态") String status,
+			@HttpParam(name = "beginTime", type = HttpParamType.COMMON, description = "登陆开始时间") String beginTime,
+			@HttpParam(name = "endTime", type = HttpParamType.COMMON, description = "登陆结束时间") String endTime)
+			throws ServiceException;
+}

+ 87 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/log/loginLog/SysLogininforServiceImpl.java

@@ -0,0 +1,87 @@
+package com.iotechn.unimall.admin.api.log.loginLog;
+
+import java.util.List;
+
+import org.apache.ibatis.session.RowBounds;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.baomidou.mybatisplus.mapper.Wrapper;
+import com.iotechn.unimall.core.exception.ServiceException;
+import com.iotechn.unimall.data.domain.log.SysLogininfor;
+import com.iotechn.unimall.data.mapper.log.SysLogininforMapper;
+import com.iotechn.unimall.data.model.Page;
+import com.iotechn.unimall.data.util.ExcelUtil;
+
+/**
+ * 
+ * @author dyl
+ *
+ */
+@Service
+public class SysLogininforServiceImpl implements SysLogininforService {
+
+	@Autowired
+	private SysLogininforMapper logininforMapper;
+
+	@Override
+	public Page<SysLogininfor> list(String ipaddr, String userName, String status, String beginTime, String endTime,
+			Integer page, Integer limit) throws ServiceException {
+		Wrapper<SysLogininfor> wrapper = new EntityWrapper<SysLogininfor>();
+		if (!StringUtils.isEmpty(ipaddr)) {
+			wrapper.like("ipaddr", ipaddr);
+		}
+		if (!StringUtils.isEmpty(userName)) {
+			wrapper.like("user_name", userName);
+		}
+		if (!StringUtils.isEmpty(status)) {
+			wrapper.eq("status", status);
+		}
+		if (!StringUtils.isEmpty(beginTime) && !StringUtils.isEmpty(endTime)) {
+			wrapper.between("login_time", beginTime, endTime);
+		}
+		wrapper.orderBy("info_id", false);
+		List<SysLogininfor> SysOperLogS = logininforMapper.selectPage(new RowBounds((page - 1) * limit, limit), wrapper);
+		Integer count = logininforMapper.selectCount(wrapper);
+		return new Page<SysLogininfor>(SysOperLogS, page, limit, count);
+	}
+
+	@Override
+	public Boolean delete(String infoIds) throws ServiceException {
+		String[] ids = infoIds.split(",");
+		Wrapper<SysLogininfor> wrapper = new EntityWrapper<SysLogininfor>();
+		wrapper.in("info_id", ids);
+		return logininforMapper.delete(wrapper) > 0;
+	}
+
+	@Override
+	public Boolean clean() throws ServiceException {
+		Wrapper<SysLogininfor> wrapper = new EntityWrapper<SysLogininfor>();
+		wrapper.eq("1", 1);
+		return logininforMapper.delete(wrapper) > 0;
+	}
+
+	@Override
+	public String export(String ipaddr, String userName, String status, String beginTime, String endTime)
+			throws ServiceException {
+		Wrapper<SysLogininfor> wrapper = new EntityWrapper<SysLogininfor>();
+		if (!StringUtils.isEmpty(ipaddr)) {
+			wrapper.like("ipaddr", ipaddr);
+		}
+		if (!StringUtils.isEmpty(userName)) {
+			wrapper.like("user_name", userName);
+		}
+		if (!StringUtils.isEmpty(status)) {
+			wrapper.eq("status", status);
+		}
+		if (!StringUtils.isEmpty(beginTime) && !StringUtils.isEmpty(endTime)) {
+			wrapper.between("login_time", beginTime, endTime);
+		}
+		List<SysLogininfor> list = logininforMapper.selectList(wrapper);
+		ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class);
+		return util.exportExcel(list, "操作日志");
+	}
+
+}

+ 40 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/log/operLog/OperLogService.java

@@ -0,0 +1,40 @@
+package com.iotechn.unimall.admin.api.log.operLog;
+
+import com.iotechn.unimall.core.annotation.HttpMethod;
+import com.iotechn.unimall.core.annotation.HttpOpenApi;
+import com.iotechn.unimall.core.annotation.HttpParam;
+import com.iotechn.unimall.core.annotation.HttpParamType;
+import com.iotechn.unimall.core.annotation.param.NotNull;
+import com.iotechn.unimall.core.exception.ServiceException;
+import com.iotechn.unimall.data.domain.log.SysOperLog;
+import com.iotechn.unimall.data.model.Page;
+
+@HttpOpenApi(group = "admin.log.operlog", description = "操作日志管理")
+public interface OperLogService {
+	@HttpMethod(description = "操作日志列表", permission = "admin:log:operlog:list", permissionParentName = "日志管理", permissionName = "操作日志管理")
+	public Page<SysOperLog> list(
+			@HttpParam(name = "title", type = HttpParamType.COMMON, description = "系统模块") String title,
+			@HttpParam(name = "operName", type = HttpParamType.COMMON, description = "操作人员") String operName,
+			@HttpParam(name = "businessType", type = HttpParamType.COMMON, description = "操作类型") String businessType,
+			@HttpParam(name = "beginTime", type = HttpParamType.COMMON, description = "操作开始时间") String beginTime,
+			@HttpParam(name = "endTime", type = HttpParamType.COMMON, description = "操作结束时间") String endTime,
+			@HttpParam(name = "pageNum", type = HttpParamType.COMMON, description = "页码", valueDef = "1") Integer page,
+			@HttpParam(name = "pageSize", type = HttpParamType.COMMON, description = "页码长度", valueDef = "20") Integer limit)
+			throws ServiceException;
+	@HttpMethod(description = "删除操作日志", permission = "admin:log:operlog:delete", permissionParentName = "日志管理", permissionName = "操作日志管理")
+	public Boolean delete(
+			@NotNull @HttpParam(name = "operIds", type = HttpParamType.COMMON, description = "日志Id") String operIds)
+			throws ServiceException;
+	
+	@HttpMethod(description = "清空操作日志", permission = "admin:log:operlog:clean", permissionParentName = "日志管理", permissionName = "操作日志管理")
+	public Boolean clean()throws ServiceException;
+	
+	@HttpMethod(description = "导出日志列表", permission = "admin:log:operlog:export", permissionParentName = "日志管理", permissionName = "操作日志管理")
+	public String export(
+			@HttpParam(name = "title", type = HttpParamType.COMMON, description = "系统模块") String title,
+			@HttpParam(name = "operName", type = HttpParamType.COMMON, description = "操作人员") String operName,
+			@HttpParam(name = "businessType", type = HttpParamType.COMMON, description = "操作类型") String businessType,
+			@HttpParam(name = "beginTime", type = HttpParamType.COMMON, description = "操作开始时间") String beginTime,
+			@HttpParam(name = "endTime", type = HttpParamType.COMMON, description = "操作结束时间") String endTime)
+			throws ServiceException;
+}

+ 87 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/log/operLog/OperLogServiceImpl.java

@@ -0,0 +1,87 @@
+package com.iotechn.unimall.admin.api.log.operLog;
+
+import java.util.List;
+
+import org.apache.ibatis.session.RowBounds;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.baomidou.mybatisplus.mapper.Wrapper;
+import com.iotechn.unimall.core.exception.ServiceException;
+import com.iotechn.unimall.data.domain.log.SysOperLog;
+import com.iotechn.unimall.data.mapper.log.SysOperLogMapper;
+import com.iotechn.unimall.data.model.Page;
+import com.iotechn.unimall.data.util.ExcelUtil;
+
+/**
+ * 
+ * @author dyl
+ *
+ */
+@Service
+public class OperLogServiceImpl implements OperLogService {
+
+	@Autowired
+	private SysOperLogMapper operLogMapper;
+
+	@Override
+	public Page<SysOperLog> list(String title, String operName, String businessType, String beginTime, String endTime,
+			Integer page, Integer limit) throws ServiceException {
+		Wrapper<SysOperLog> wrapper = new EntityWrapper<SysOperLog>();
+		if (!StringUtils.isEmpty(title)) {
+			wrapper.like("title", title);
+		}
+		if (!StringUtils.isEmpty(operName)) {
+			wrapper.like("oper_name", operName);
+		}
+		if (!StringUtils.isEmpty(businessType)) {
+			wrapper.eq("business_type", businessType);
+		}
+		if (!StringUtils.isEmpty(beginTime) && !StringUtils.isEmpty(endTime)) {
+			wrapper.between("oper_time", beginTime, endTime);
+		}
+		wrapper.orderBy("oper_id", false);
+		List<SysOperLog> SysOperLogS = operLogMapper.selectPage(new RowBounds((page - 1) * limit, limit), wrapper);
+		Integer count = operLogMapper.selectCount(wrapper);
+		return new Page<SysOperLog>(SysOperLogS, page, limit, count);
+	}
+
+	@Override
+	public Boolean delete(String operIds) throws ServiceException {
+		String[] ids = operIds.split(",");
+		Wrapper<SysOperLog> wrapper = new EntityWrapper<SysOperLog>();
+		wrapper.in("oper_id", ids);
+		return operLogMapper.delete(wrapper) > 0;
+	}
+
+	@Override
+	public Boolean clean() throws ServiceException {
+		Wrapper<SysOperLog> wrapper = new EntityWrapper<SysOperLog>();
+		wrapper.eq("1", 1);
+		return operLogMapper.delete(wrapper) > 0;
+	}
+
+	@Override
+	public String export(String title, String operName, String businessType, String beginTime, String endTime)
+			throws ServiceException {
+		Wrapper<SysOperLog> wrapper = new EntityWrapper<SysOperLog>();
+		if (!StringUtils.isEmpty(title)) {
+			wrapper.like("title", title);
+		}
+		if (!StringUtils.isEmpty(operName)) {
+			wrapper.like("oper_name", operName);
+		}
+		if (!StringUtils.isEmpty(businessType)) {
+			wrapper.eq("business_type", businessType);
+		}
+		if (!StringUtils.isEmpty(beginTime) && !StringUtils.isEmpty(endTime)) {
+			wrapper.between("oper_time", beginTime, endTime);
+		}
+		List<SysOperLog> list = operLogMapper.selectList(wrapper);
+		ExcelUtil<SysOperLog> util = new ExcelUtil<SysOperLog>(SysOperLog.class);
+		return util.exportExcel(list, "操作日志");
+	}
+
+}

+ 21 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/monitor/online/UserOnlineService.java

@@ -0,0 +1,21 @@
+package com.iotechn.unimall.admin.api.monitor.online;
+
+import java.util.List;
+
+import com.alibaba.fastjson.JSONObject;
+import com.iotechn.unimall.core.annotation.HttpMethod;
+import com.iotechn.unimall.core.annotation.HttpOpenApi;
+import com.iotechn.unimall.core.annotation.HttpParam;
+import com.iotechn.unimall.core.annotation.HttpParamType;
+import com.iotechn.unimall.core.exception.ServiceException;
+
+@HttpOpenApi(group = "admin.monitor.online", description = "在线用户管理")
+public interface UserOnlineService {
+	@HttpMethod(description = "在线用户列表", permission = "admin:monitor:online:list", permissionParentName = "系统管理", permissionName = "在线用户管理")
+	public List<JSONObject> list() throws ServiceException;
+	
+	@HttpMethod(description = "强退用户", permission = "admin:monitor:online:forceLogout", permissionParentName = "系统管理", permissionName = "在线用户管理")
+	public Boolean forceLogout(
+			@HttpParam(name = "tokenId", type = HttpParamType.COMMON, description = "用户token") String tokenId)
+			throws ServiceException;
+}

+ 45 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/monitor/online/UserOnlineServiceImpl.java

@@ -0,0 +1,45 @@
+package com.iotechn.unimall.admin.api.monitor.online;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Service;
+
+import com.alibaba.fastjson.JSONObject;
+import com.iotechn.unimall.core.Const;
+import com.iotechn.unimall.core.exception.ServiceException;
+/**
+ * 
+ * @author dyl
+ *
+ */
+@Service
+public class UserOnlineServiceImpl implements UserOnlineService {
+	@Autowired
+	private StringRedisTemplate userRedisTemplate;
+	
+	@Override
+	public List<JSONObject> list() throws ServiceException {
+		List<JSONObject> loginList=new ArrayList<JSONObject>();
+		Set<String> keys = userRedisTemplate.keys(Const.ADMIN_REDIS_PREFIX+"*");
+		Iterator<String> it1 = keys.iterator();
+		while (it1.hasNext()) {
+			String tokenId=it1.next();
+			JSONObject json = JSONObject.parseObject(userRedisTemplate.opsForValue().get(tokenId));
+			json.put("tokenId", tokenId.split("_")[2]);
+			json.put("expireTime", userRedisTemplate.getExpire(tokenId));
+			loginList.add(json);
+		}
+		return loginList;
+	}
+
+	@Override
+	public Boolean forceLogout(String tokenId) throws ServiceException {
+		return userRedisTemplate.delete(Const.ADMIN_REDIS_PREFIX  + tokenId);
+	}
+
+}

+ 11 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/monitor/server/ServerService.java

@@ -0,0 +1,11 @@
+package com.iotechn.unimall.admin.api.monitor.server;
+
+import com.iotechn.unimall.core.annotation.HttpMethod;
+import com.iotechn.unimall.core.annotation.HttpOpenApi;
+import com.iotechn.unimall.data.domain.monitor.Server;
+
+@HttpOpenApi(group = "admin.monitor.server", description = "服务监控数据")
+public interface ServerService {
+	@HttpMethod(description = "获取服务监控数据", permission = "admin:monitor:server:getInfo", permissionParentName = "系统管理", permissionName = "服务监控数据")
+	public Server getInfo()throws Exception;
+}

+ 22 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/monitor/server/ServerServiceImpl.java

@@ -0,0 +1,22 @@
+package com.iotechn.unimall.admin.api.monitor.server;
+
+import org.springframework.stereotype.Service;
+
+import com.iotechn.unimall.data.domain.monitor.Server;
+
+/**
+ * 
+ * @author dyl
+ *
+ */
+@Service
+public class ServerServiceImpl implements ServerService {
+
+	@Override
+	public Server getInfo() throws Exception {
+		Server server = new Server();
+		server.copyTo();
+		return server;
+	}
+
+}

+ 65 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/role/RoleService.java

@@ -0,0 +1,65 @@
+package com.iotechn.unimall.admin.api.role;
+
+
+import com.iotechn.unimall.core.annotation.HttpMethod;
+import com.iotechn.unimall.core.annotation.HttpOpenApi;
+import com.iotechn.unimall.core.annotation.HttpParam;
+import com.iotechn.unimall.core.annotation.HttpParamType;
+import com.iotechn.unimall.core.annotation.param.NotNull;
+import com.iotechn.unimall.core.exception.ServiceException;
+import com.iotechn.unimall.data.domain.RoleDO;
+import com.iotechn.unimall.data.dto.RoleSetPermissionDTO;
+import com.iotechn.unimall.data.model.Page;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Created by rize on 2019/4/11.
+ */
+@HttpOpenApi(group = "admin.role", description = "角色服务")
+public interface RoleService {
+
+    @HttpMethod(description = "列表", permission = "admin:role:list", permissionParentName = "系统管理", permissionName = "角色管理")
+    public Page<RoleDO> list(
+            @HttpParam(name = "name", type = HttpParamType.COMMON, description = "搜索名称") String name,
+            @HttpParam(name = "page", type = HttpParamType.COMMON, description = "页码", valueDef = "1") Integer page,
+            @HttpParam(name = "limit", type = HttpParamType.COMMON, description = "页码长度", valueDef = "20") Integer limit,
+            @HttpParam(name = "adminId", type = HttpParamType.USER_ID, description = "管理员ID") Long adminId) throws ServiceException;
+
+
+    @HttpMethod(description = "添加", permission = "admin:role:create", permissionParentName = "系统管理", permissionName = "角色管理")
+    public RoleDO create(
+            @NotNull @HttpParam(name = "role", type = HttpParamType.COMMON, description = "角色对象") RoleDO roleDO,
+            @HttpParam(name = "adminId", type = HttpParamType.USER_ID, description = "管理员ID") Long adminId) throws ServiceException;
+
+
+    @HttpMethod(description = "删除", permission = "admin:role:delete", permissionParentName = "系统管理", permissionName = "角色管理")
+    public String delete(
+            @NotNull @HttpParam(name = "roleId", type = HttpParamType.COMMON, description = "角色Id") Long roleId,
+            @HttpParam(name = "adminId", type = HttpParamType.USER_ID, description = "管理员ID") Long adminId) throws ServiceException;
+
+
+    @HttpMethod(description = "更新", permission = "admin:role:update", permissionParentName = "系统管理", permissionName = "角色管理")
+    public RoleDO update(
+            @NotNull @HttpParam(name = "role", type = HttpParamType.COMMON, description = "角色对象") RoleDO roleDO,
+            @HttpParam(name = "adminId", type = HttpParamType.USER_ID, description = "管理员ID") Long adminId) throws ServiceException;
+
+
+    @HttpMethod(description = "角色授权", permission = "admin:role:permissionList",  permissionParentName = "系统管理", permissionName = "角色管理")
+    public String permissionSet(
+            @NotNull @HttpParam(name = "roleSetPermissionDTO", type = HttpParamType.COMMON, description = "设置DTO") RoleSetPermissionDTO roleSetPermissionDTO,
+            @HttpParam(name = "adminId", type = HttpParamType.USER_ID, description = "管理员ID") Long adminId) throws ServiceException;
+
+
+    @HttpMethod(description = "权限列表", permission = "admin:permission:list", permissionParentName = "系统管理", permissionName = "角色管理")
+    public Map<String,Object> permissionList(
+            @NotNull @HttpParam(name = "roleId", type = HttpParamType.COMMON, description = "角色ID") Long roleId,
+            @HttpParam(name = "adminId", type = HttpParamType.USER_ID, description = "管理员ID") Long adminId) throws ServiceException;
+
+
+    @HttpMethod(description = "角色枚举")
+    public List<Map<String,Object>> options(
+            @HttpParam(name = "adminId", type = HttpParamType.USER_ID, description = "管理员ID") Long adminId) throws ServiceException;
+
+}

+ 141 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/role/RoleServiceImpl.java

@@ -0,0 +1,141 @@
+package com.iotechn.unimall.admin.api.role;
+
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.baomidou.mybatisplus.mapper.Wrapper;
+import com.iotechn.unimall.core.exception.AdminServiceException;
+import com.iotechn.unimall.core.exception.ExceptionDefinition;
+import com.iotechn.unimall.core.exception.ServiceException;
+import com.iotechn.unimall.data.domain.RoleDO;
+import com.iotechn.unimall.data.domain.RolePermissionDO;
+import com.iotechn.unimall.data.dto.PermissionPointDTO;
+import com.iotechn.unimall.data.dto.RoleSetPermissionDTO;
+import com.iotechn.unimall.data.enums.RoleStatusType;
+import com.iotechn.unimall.data.mapper.RoleMapper;
+import com.iotechn.unimall.data.mapper.RolePermissionMapper;
+import com.iotechn.unimall.data.model.Page;
+import org.apache.ibatis.session.RowBounds;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+
+import java.util.*;
+
+/**
+ * Created by rize on 2019/4/11.
+ */
+@Service
+public class RoleServiceImpl implements RoleService {
+
+    @Autowired
+    private RoleMapper roleMapper;
+
+    @Autowired
+    private RolePermissionMapper rolePermissionMapper;
+
+    public static List<PermissionPointDTO> permDTOs = new LinkedList<>();
+
+    public static Set<String> allPermPoint = new HashSet<>();
+
+    @Override
+    public Page<RoleDO> list(String name, Integer page, Integer limit, Long adminId) throws ServiceException {
+        Wrapper<RoleDO> wrapper = new EntityWrapper<RoleDO>();
+        if (!StringUtils.isEmpty(name)) {
+            wrapper.like("name", name);
+        }
+        List<RoleDO> roleDOS = roleMapper.selectPage(new RowBounds((page - 1) * limit, limit), wrapper);
+        Integer count = roleMapper.selectCount(wrapper);
+        return new Page<RoleDO>(roleDOS, page, limit, count);
+    }
+
+    @Override
+    public RoleDO create(RoleDO roleDO, Long adminId) throws ServiceException {
+        Date now = new Date();
+        roleDO.setStatus(RoleStatusType.ACTIVE.getCode());
+        roleDO.setGmtUpdate(now);
+        roleDO.setGmtCreate(now);
+        if (roleMapper.insert(roleDO) > 0) {
+            return roleDO;
+        }
+        throw new AdminServiceException(ExceptionDefinition.ADMIN_UNKNOWN_EXCEPTION);
+    }
+
+    @Override
+    public String delete(Long roleId, Long adminId) throws ServiceException {
+        if (roleMapper.deleteById(roleId) > 0) {
+            return "ok";
+        }
+        throw new AdminServiceException(ExceptionDefinition.ADMIN_UNKNOWN_EXCEPTION);
+    }
+
+    @Override
+    public RoleDO update(RoleDO roleDO, Long adminId) throws ServiceException {
+        if (roleMapper.updateById(roleDO) > 0) {
+            return roleDO;
+        }
+        throw new AdminServiceException(ExceptionDefinition.ADMIN_UNKNOWN_EXCEPTION);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public String permissionSet(RoleSetPermissionDTO roleSetPermissionDTO, Long adminId) throws ServiceException {
+        Long roleId = roleSetPermissionDTO.getRoleId();
+        if (roleId == null) {
+            throw new AdminServiceException(ExceptionDefinition.PARAM_CHECK_FAILED);
+        }
+        rolePermissionMapper.delete(new EntityWrapper<RolePermissionDO>().eq("role_id", roleId));
+        //构建插入
+        List<String> permissions = roleSetPermissionDTO.getPermissions();
+        if (!CollectionUtils.isEmpty(permissions)) {
+            Date now = new Date();
+            for (String permission : permissions) {
+                RolePermissionDO rolePermissionDO = new RolePermissionDO();
+                rolePermissionDO.setRoleId(roleId);
+                rolePermissionDO.setDeleted(0);
+                rolePermissionDO.setPermission(permission);
+                rolePermissionDO.setGmtCreate(now);
+                rolePermissionDO.setGmtUpdate(now);
+                rolePermissionMapper.insert(rolePermissionDO);
+            }
+        }
+        return "ok";
+    }
+
+    @Override
+    public Map<String,Object> permissionList(Long roleId, Long adminId) throws ServiceException {
+        List<RolePermissionDO> rolePermissionDOList =
+                rolePermissionMapper.selectList(
+                        new EntityWrapper<RolePermissionDO>()
+                                .eq("role_id", roleId));
+
+        Map<String,Object> map = new HashMap<>();
+        Set<String> permissionPoint = new HashSet<>();
+        for (RolePermissionDO permissionDO : rolePermissionDOList) {
+            if ("*".equals(permissionDO.getPermission())) {
+                //若为超级管理员,则直接push所有权限进去
+                permissionPoint.addAll(allPermPoint);
+                break;
+            } else {
+                permissionPoint.add(permissionDO.getPermission());
+            }
+        }
+        map.put("systemPermissions", permDTOs);
+        map.put("assignedPermissions", permissionPoint);
+        return map;
+    }
+
+    @Override
+    public List<Map<String, Object>> options(Long adminId) throws ServiceException {
+        List<RoleDO> roleDOS = roleMapper.selectList(new EntityWrapper<>());
+        List<Map<String,Object>> list = new LinkedList<>();
+        roleDOS.forEach(item -> {
+            Map<String,Object> map = new HashMap<>();
+            map.put("value", item.getId());
+            map.put("label", item.getName());
+            list.add(map);
+        });
+        return list;
+    }
+
+}

+ 74 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/tools/gen/GenTableService.java

@@ -0,0 +1,74 @@
+package com.iotechn.unimall.admin.api.tools.gen;
+
+import java.util.List;
+
+import com.alibaba.fastjson.JSONObject;
+import com.iotechn.unimall.core.annotation.HttpMethod;
+import com.iotechn.unimall.core.annotation.HttpOpenApi;
+import com.iotechn.unimall.core.annotation.HttpParam;
+import com.iotechn.unimall.core.annotation.HttpParamType;
+import com.iotechn.unimall.core.annotation.param.NotNull;
+import com.iotechn.unimall.core.exception.ServiceException;
+import com.iotechn.unimall.data.domain.tools.gen.GenTable;
+import com.iotechn.unimall.data.domain.tools.gen.GenTableColumn;
+import com.iotechn.unimall.data.model.Page;
+
+/**
+ * 
+ * @author dyl
+ *
+ */
+@HttpOpenApi(group = "admin.tools.gen", description = "代码生成")
+public interface GenTableService {
+	@HttpMethod(description = "代码生成列表", permission = "admin:tools:gen:list", permissionParentName = "系统工具", permissionName = "代码生成")
+	public Page<GenTable> list(
+			@HttpParam(name = "tableName", type = HttpParamType.COMMON, description = "表名称") String tableName,
+			@HttpParam(name = "tableComment", type = HttpParamType.COMMON, description = "表描述") String tableComment,
+			@HttpParam(name = "beginTime", type = HttpParamType.COMMON, description = "开始时间") String beginTime,
+			@HttpParam(name = "endTime", type = HttpParamType.COMMON, description = "结束时间") String endTime,
+			@HttpParam(name = "page", type = HttpParamType.COMMON, description = "页码", valueDef = "1") Integer page,
+			@HttpParam(name = "limit", type = HttpParamType.COMMON, description = "页码长度", valueDef = "20") Integer limit)
+			throws ServiceException;
+
+	@HttpMethod(description = "数据表列表", permission = "admin:tools:gen:dbList", permissionParentName = "系统工具", permissionName = "代码生成")
+	public Page<GenTable> getDbList(
+			@HttpParam(name = "tableName", type = HttpParamType.COMMON, description = "表名称") String tableName,
+			@HttpParam(name = "tableComment", type = HttpParamType.COMMON, description = "表描述") String tableComment,
+			@HttpParam(name = "page", type = HttpParamType.COMMON, description = "页码", valueDef = "1") Integer page,
+			@HttpParam(name = "limit", type = HttpParamType.COMMON, description = "页码长度", valueDef = "20") Integer limit)
+			throws ServiceException;
+
+	@HttpMethod(description = "查询数据表详情", permission = "admin:tools:gen:get", permissionParentName = "系统工具", permissionName = "代码生成")
+	public JSONObject get(@NotNull @HttpParam(name = "id", type = HttpParamType.COMMON, description = "表ID") String id)
+			throws ServiceException;
+
+	@HttpMethod(description = "查询数据表字段详情", permission = "admin:tools:genTable:getColumn", permissionParentName = "系统工具", permissionName = "代码生成")
+	public List<GenTableColumn> getColumn(
+			@HttpParam(name = "talbleId", type = HttpParamType.COMMON, description = "表ID") String talbleId)
+			throws ServiceException;
+
+	@HttpMethod(description = "导入表结构", permission = "admin:tools:gen:import", permissionParentName = "系统工具", permissionName = "代码生成")
+	public Boolean importTableSave(
+			@HttpParam(name = "tables", type = HttpParamType.COMMON, description = "表名") String tables)
+			throws ServiceException;
+
+	@HttpMethod(description = "修改表生成信息", permission = "admin:tools:gen:update", permissionParentName = "系统工具", permissionName = "代码生成")
+	public Boolean update(
+			@NotNull @HttpParam(name = "genTable", type = HttpParamType.COMMON, description = "表信息") GenTable genTable)
+			throws ServiceException;
+
+	@HttpMethod(description = "修改表字段生成信息", permission = "admin:tools:gen:updateColumn", permissionParentName = "系统工具", permissionName = "代码生成")
+	public Boolean updateColumn(
+			@NotNull @HttpParam(name = "genTableColumn", type = HttpParamType.COMMON, description = "表字段信息") GenTableColumn genTableColumn)
+			throws ServiceException;
+
+	@HttpMethod(description = "删除", permission = "admin:tools:gen:delete", permissionParentName = "系统工具", permissionName = "代码生成")
+	public Boolean delete(
+			@NotNull @HttpParam(name = "tableIds", type = HttpParamType.COMMON, description = "表Id") String tableIds)
+			throws ServiceException;
+
+	@HttpMethod(description = "代码预览", permission = "admin:tools:gen:preview", permissionParentName = "系统工具", permissionName = "代码生成")
+	public JSONObject preview(
+			@NotNull @HttpParam(name = "tableId", type = HttpParamType.COMMON, description = "表Id") String tableId)
+			throws ServiceException;
+}

+ 179 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/tools/gen/GenTableServiceImpl.java

@@ -0,0 +1,179 @@
+package com.iotechn.unimall.admin.api.tools.gen;
+
+import java.io.StringWriter;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ibatis.session.RowBounds;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.baomidou.mybatisplus.mapper.Wrapper;
+import com.iotechn.unimall.core.exception.AdminServiceException;
+import com.iotechn.unimall.core.exception.ExceptionDefinition;
+import com.iotechn.unimall.core.exception.ServiceException;
+import com.iotechn.unimall.core.util.StringUtils;
+import com.iotechn.unimall.data.domain.tools.gen.GenTable;
+import com.iotechn.unimall.data.domain.tools.gen.GenTableColumn;
+import com.iotechn.unimall.data.mapper.tools.gen.GenTableColumnMapper;
+import com.iotechn.unimall.data.mapper.tools.gen.GenTableMapper;
+import com.iotechn.unimall.data.model.Page;
+import com.iotechn.unimall.data.util.GenUtils;
+import com.iotechn.unimall.data.util.SessionUtil;
+import com.iotechn.unimall.data.util.VelocityInitializer;
+import com.iotechn.unimall.data.util.VelocityUtils;
+
+/**
+ * 
+ * @author dyl
+ *
+ */
+@Service
+public class GenTableServiceImpl implements GenTableService {
+
+	@Autowired
+	private GenTableMapper tableMapper;
+
+	@Autowired
+	private GenTableColumnMapper tableColumnMapper;
+
+	@Override
+	public Page<GenTable> list(String tableName, String tableComment, String beginTime, String endTime, Integer page,
+			Integer limit) throws ServiceException {
+		Wrapper<GenTable> wrapper = new EntityWrapper<GenTable>();
+		if (!StringUtils.isEmpty(tableName)) {
+			wrapper.eq("table_name", tableName);
+		}
+		if (!StringUtils.isEmpty(tableComment)) {
+			wrapper.like("table_comment", tableComment);
+		}
+		if (!StringUtils.isEmpty(beginTime) && !StringUtils.isEmpty(endTime)) {
+			wrapper.between("create_time", beginTime, endTime);
+		}
+		List<GenTable> GenTableS = tableMapper.selectPage(new RowBounds((page - 1) * limit, limit), wrapper);
+		Integer count = tableMapper.selectCount(wrapper);
+		return new Page<GenTable>(GenTableS, page, limit, count);
+	}
+
+	@Override
+	public Page<GenTable> getDbList(String tableName, String tableComment, Integer page, Integer limit)
+			throws ServiceException {
+		GenTable genTable = new GenTable();
+		genTable.setTableName(tableName);
+		genTable.setTableComment(tableComment);
+		List<GenTable> GenTableS = tableMapper.selectDbTableList(new RowBounds((page - 1) * limit, limit), genTable);
+		Integer count = tableMapper.selectDbTableCount(genTable);
+		return new Page<GenTable>(GenTableS, page, limit, count);
+	}
+
+	@Override
+	public JSONObject get(String id) throws ServiceException {
+		JSONObject result = new JSONObject();
+		Wrapper<GenTableColumn> wrapper = new EntityWrapper<GenTableColumn>();
+		wrapper.eq("table_id", id);
+
+		GenTable table = tableMapper.selectById(id);
+		List<GenTableColumn> list = tableColumnMapper.selectList(wrapper);
+
+		result.put("info", table);
+		result.put("rows", list);
+		return result;
+	}
+
+	@Override
+	public List<GenTableColumn> getColumn(String talbleId) throws ServiceException {
+		Wrapper<GenTableColumn> wrapper = new EntityWrapper<GenTableColumn>();
+		wrapper.eq("table_id", talbleId);
+		List<GenTableColumn> list = tableColumnMapper.selectList(wrapper);
+		return list;
+	}
+
+	@Override
+	public Boolean importTableSave(String tables) throws ServiceException {
+		String[] ids = tables.split(",");
+		List<GenTable> tableList = tableMapper.selectDbTableListByNames(ids);
+		String operName = SessionUtil.getAdmin().getUsername();
+		for (GenTable table : tableList) {
+			try {
+				String tableName = table.getTableName();
+				GenUtils.initTable(table, operName);
+				int row = tableMapper.insert(table);
+				if (row > 0) {
+					// 保存列信息
+					List<GenTableColumn> genTableColumns = tableColumnMapper.selectDbTableColumnsByName(tableName);
+					for (GenTableColumn column : genTableColumns) {
+						GenUtils.initColumnField(column, table);
+						tableColumnMapper.insert(column);
+					}
+				}
+			} catch (Exception e) {
+				e.printStackTrace();
+				throw new AdminServiceException(ExceptionDefinition.TABLE_IMPORT_ERROR);
+			}
+		}
+		return true;
+	}
+
+	@Override
+	public Boolean update(GenTable genTable) throws ServiceException {
+		return tableMapper.updateById(genTable) > 0;
+	}
+
+	@Override
+	public Boolean updateColumn(GenTableColumn genTableColumn) throws ServiceException {
+		return tableColumnMapper.updateById(genTableColumn) > 0;
+	}
+
+	@Override
+	public Boolean delete(String tableIds) throws ServiceException {
+		String[] ids = tableIds.split(",");
+		Wrapper<GenTable> wrapper = new EntityWrapper<GenTable>();
+		wrapper.in("table_id", ids);
+		return tableMapper.delete(wrapper) > 0;
+	}
+
+	@Override
+	public JSONObject preview(String tableId) throws ServiceException {
+		Map<String, String> dataMap = new LinkedHashMap<>();
+		// 查询表信息
+		GenTable table = tableMapper.selectById(tableId);
+		Wrapper<GenTableColumn> wrapper = new EntityWrapper<GenTableColumn>();
+		wrapper.eq("table_id", table.getTableId());
+		// 查询列信息
+		List<GenTableColumn> columns =tableColumnMapper.selectList(wrapper);
+		table.setColumns(columns);
+		setPkColumn(table, columns);
+		VelocityInitializer.initVelocity();
+
+		VelocityContext context = VelocityUtils.prepareContext(table);
+
+		// 获取模板列表
+		List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
+		for (String template : templates) {
+			// 渲染模板
+			StringWriter sw = new StringWriter();
+			Template tpl = Velocity.getTemplate(template, "UTF-8");
+			tpl.merge(context, sw);
+			dataMap.put(template, sw.toString());
+		}
+		return JSONObject.parseObject(JSONObject.toJSONString(dataMap));
+	}
+
+	public void setPkColumn(GenTable table, List<GenTableColumn> columns) {
+		for (GenTableColumn column : columns) {
+			if (column.isPk()) {
+				table.setPkColumn(column);
+				break;
+			}
+		}
+		if (StringUtils.isNull(table.getPkColumn())) {
+			table.setPkColumn(columns.get(0));
+		}
+	}
+}

+ 62 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/user/AdminUserService.java

@@ -0,0 +1,62 @@
+package com.iotechn.unimall.admin.api.user;
+
+import com.iotechn.unimall.core.annotation.HttpMethod;
+import com.iotechn.unimall.core.annotation.HttpOpenApi;
+import com.iotechn.unimall.core.annotation.HttpParam;
+import com.iotechn.unimall.core.annotation.HttpParamType;
+import com.iotechn.unimall.core.annotation.param.NotNull;
+import com.iotechn.unimall.core.annotation.param.Range;
+import com.iotechn.unimall.core.exception.ServiceException;
+import com.iotechn.unimall.data.domain.UserDO;
+import com.iotechn.unimall.data.model.Page;
+
+/**
+ * Created with IntelliJ IDEA.
+ * Description:
+ * User: kbq
+ * Date: 2019-07-11
+ * Time: 下午7:30
+ */
+
+@HttpOpenApi(group = "admin.user", description = "用户管理")
+public interface AdminUserService {
+
+    @HttpMethod(description = "创建", permission = "system:user:create", permissionParentName = "系统管理", permissionName = "用户管理")
+    public Boolean addUser(
+            @NotNull @HttpParam(name = "adminId", type = HttpParamType.ADMIN_ID, description = "管理员ID") Long adminId,
+            @NotNull @HttpParam(name = "user", type = HttpParamType.COMMON, description = "用户信息") UserDO user) throws ServiceException;
+
+    @HttpMethod(description = "删除", permission = "system:user:delete", permissionParentName = "系统管理", permissionName = "用户管理")
+    public Boolean deleteUser(
+            @NotNull @HttpParam(name = "adminId", type = HttpParamType.ADMIN_ID, description = "管理员ID") Long adminId,
+            @NotNull @HttpParam(name = "id", type = HttpParamType.COMMON, description = "用户Id") Long id,
+            @NotNull @HttpParam(name = "nickname", type = HttpParamType.COMMON, description = "用户Id") String nickname) throws ServiceException;
+
+    @HttpMethod(description = "修改", permission = "system:user:update", permissionParentName = "系统管理", permissionName = "用户管理")
+    public Boolean updateUser(
+            @NotNull @HttpParam(name = "adminId", type = HttpParamType.ADMIN_ID, description = "管理员ID") Long adminId,
+            @NotNull @HttpParam(name = "user", type = HttpParamType.COMMON, description = "用户信息") UserDO user) throws ServiceException;
+
+    @HttpMethod(description = "激活冻结", permission = "system:user:update", permissionParentName = "系统管理", permissionName = "用户管理")
+    public Boolean updateStatus(
+            @NotNull @HttpParam(name = "adminId", type = HttpParamType.ADMIN_ID, description = "管理员ID") Long adminId,
+            @NotNull @HttpParam(name = "userId", type = HttpParamType.COMMON, description = "用户信息") Long userId,
+            @NotNull @HttpParam(name = "status", type = HttpParamType.COMMON, description = "用户信息") Integer status) throws ServiceException;
+
+
+    @HttpMethod(description = "查询", permission = "system:user:query", permissionParentName = "系统管理", permissionName = "用户管理")
+    public Page<UserDO> getUser(
+            @NotNull @HttpParam(name = "adminId", type = HttpParamType.ADMIN_ID, description = "管理员ID") Long adminId,
+            @HttpParam(name = "id", type = HttpParamType.COMMON, description = "用户ID") Long id,
+            @HttpParam(name = "nickname", type = HttpParamType.COMMON, description = "用户昵称") String nickname,
+            @HttpParam(name = "level", type = HttpParamType.COMMON, description = "用户等级") Integer level,
+            @HttpParam(name = "gender", type = HttpParamType.COMMON, description = "用户性别") Integer gender,
+            @HttpParam(name = "status", type = HttpParamType.COMMON, description = "用户状态") Integer status,
+            @Range(min = 1) @HttpParam(name = "pageNo", type = HttpParamType.COMMON, description = "当前页码") Integer pageNo,
+            @Range(min = 1) @HttpParam(name = "limit", type = HttpParamType.COMMON, description = "页码长度") Integer limit) throws ServiceException;
+    @HttpMethod(description = "测试")
+    public String test(
+            @HttpParam(name = "param", type = HttpParamType.COMMON, description = "参数") String nickname,
+            @HttpParam(name = "param1", type = HttpParamType.COMMON, description = "参数") String nickname1) throws Exception;
+
+}

+ 229 - 0
unimall-admin-api/src/main/java/com/iotechn/unimall/admin/api/user/AdminUserServiceImpl.java

@@ -0,0 +1,229 @@
+package com.iotechn.unimall.admin.api.user;
+
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.mapper.Wrapper;
+import com.dangdang.openplatform.openapi.sdk.ApiException;
+import com.dangdang.openplatform.openapi.sdk.SdkClient;
+import com.dangdang.openplatform.openapi.sdk.internal.util.FileItem;
+import com.dangdang.openplatform.openapi.sdk.request.order.OrderDetailsGetRequest;
+import com.dangdang.openplatform.openapi.sdk.request.order.OrderGoodsSendRequest;
+import com.dangdang.openplatform.openapi.sdk.request.order.OrdersContentDecryptRequest;
+import com.dangdang.openplatform.openapi.sdk.requestmodel.order.EncryptDTO;
+import com.dangdang.openplatform.openapi.sdk.requestmodel.order.OrderDetailsGet;
+import com.dangdang.openplatform.openapi.sdk.response.order.OrderDetailsGetResponse;
+import com.dangdang.openplatform.openapi.sdk.response.order.OrderGoodsSendResponse;
+import com.dangdang.openplatform.openapi.sdk.response.order.OrdersContentDecryptResponse;
+import com.dangdang.openplatform.openapi.sdk.responsemodel.order.CryptUserInfo;
+import com.dangdang.openplatform.openapi.sdk.responsemodel.order.OrdersContentDecryptDTO;
+import com.google.gson.JsonObject;
+import com.iotechn.unimall.core.util.MD5Util;
+import com.iotechn.unimall.data.util.XMLUtil;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.iotechn.unimall.core.exception.AdminServiceException;
+import com.iotechn.unimall.core.exception.ExceptionDefinition;
+import com.iotechn.unimall.core.exception.ServiceException;
+import com.iotechn.unimall.data.domain.UserDO;
+import com.iotechn.unimall.data.mapper.UserMapper;
+import com.iotechn.unimall.data.model.Page;
+import okhttp3.*;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.codec.digest.Md5Crypt;
+import org.apache.http.HttpStatus;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.BasicCookieStore;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.*;
+import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Created with IntelliJ IDEA.
+ * Description:
+ * User: kbq
+ * Date: 2019-07-11
+ * Time: 下午7:57
+ */
+@Service
+public class AdminUserServiceImpl implements AdminUserService {
+
+    @Autowired
+    private UserMapper userMapper;
+
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean addUser(Long adminId, UserDO user) throws ServiceException {
+        if (user == null) {
+            throw new AdminServiceException(ExceptionDefinition.USER_INFORMATION_MISSING);
+        }
+        if (user.getPhone() == null) {
+            throw new AdminServiceException(ExceptionDefinition.USER_INFORMATION_MISSING);
+        }
+        if (userMapper.selectCount(new EntityWrapper<UserDO>().eq("phone", user.getPhone())) > 0) {
+            throw new AdminServiceException(ExceptionDefinition.USER_PHONE_ALREADY_EXIST);
+        }
+        Date now = new Date();
+        user.setId(null);
+        user.setPassword(Md5Crypt.md5Crypt(user.getPassword().getBytes(), "$1$" + user.getPhone().substring(0, 7)));
+        user.setGmtCreate(now);
+        user.setGmtUpdate(now);
+        return userMapper.insert(user) > 0;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean deleteUser(Long adminId, Long id, String nickname) throws ServiceException {
+        return userMapper.delete(new EntityWrapper<UserDO>()
+                .eq("id", id)
+                .eq("nickname", nickname)) > 0;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean updateUser(Long adminId, UserDO user) throws ServiceException {
+        if (user == null || user.getId() == null) {
+            throw new AdminServiceException(ExceptionDefinition.USER_INFORMATION_MISSING);
+        }
+        if (user.getPhone() == null) {
+            throw new AdminServiceException(ExceptionDefinition.USER_INFORMATION_MISSING);
+        }
+        if (userMapper.selectCount(new EntityWrapper<UserDO>().eq("phone", user.getPhone()).notIn("id", user.getId())) > 0) {
+            throw new AdminServiceException(ExceptionDefinition.USER_PHONE_ALREADY_EXIST);
+        }
+        Date now = new Date();
+        user.setGmtUpdate(now);
+        UserDO userDO = userMapper.selectById(user.getId());
+        if (userDO.getPassword().equals(user.getPassword())) {
+            return userMapper.updateById(user) > 0;
+        }
+        if (user.getPassword() != null) {
+            user.setPassword(Md5Crypt.md5Crypt(user.getPassword().getBytes(), "$1$" + user.getPhone().substring(0, 7)));
+        }
+        return userMapper.updateById(user) > 0;
+    }
+
+    @Override
+    public Boolean updateStatus(Long adminId, Long userId, Integer status) throws ServiceException {
+        if (userId == null || status == null || (status != 0 && status != 1)) {
+            throw new AdminServiceException(ExceptionDefinition.USER_INFORMATION_MISSING);
+        }
+        UserDO userDO = new UserDO();
+        userDO.setId(userId);
+        userDO.setStatus(status);
+        userDO.setGmtUpdate(new Date());
+        if (userMapper.updateById(userDO) > 0) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public Page<UserDO> getUser(Long adminId, Long id, String nickname, Integer level, Integer gender, Integer status, Integer pageNo, Integer limit) throws ServiceException {
+        Integer count = userMapper.countUser(id, nickname, level, gender, status);
+        List<UserDO> userDOList = userMapper.getUserList(id, nickname, level, gender, status, limit * (pageNo - 1), limit);
+        Page<UserDO> page = new Page<UserDO>(userDOList, pageNo, limit, count);
+        return page;
+    }
+
+    @Override
+    public String test(String param, String param1) throws Exception {
+        String url = "https://open-api.ushengyun.com/printer/print";
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+        // 模拟登陆,按实际服务器端要求选用 Post 或 Get 请求方式
+        HttpPost httpPost = new HttpPost(url);
+        SortedMap<Object, Object> params = new TreeMap<Object, Object>();
+        Long now = new Date().getTime();
+        params.put("appid", "10317");
+        params.put("timestamp", now);
+        params.put("deviceid", "70006716");
+        params.put("devicesecret", "y77iba4i");
+        params.put("printdata", "<S2><C>#1 饿了么</C></S2><S1><C>优声科技(成都店)</C></S1><S1><C>--在线支付--</C></S1><S2><C>[预订单]</C></S2>");
+        String sign = createSign(params,"eaf56473cc6cba0d5a8e10d3a35ab51b");
+        params.put("sign", sign);
+        JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(params));
+
+        httpPost.setEntity(new StringEntity(jsonObject.toString(), StandardCharsets.UTF_8));
+        ;
+        // 设置header信息
+        httpPost.setHeader("Content-type", "application/json");
+        CloseableHttpResponse response = httpClient.execute(httpPost);
+        try {
+            // 执行请求操作,并拿到结果(同步阻塞)
+            String body = EntityUtils.toString(response.getEntity());
+            jsonObject = JSONObject.parseObject(body);
+            if (jsonObject.getString("status").equals("1001")) {
+                String token = jsonObject.getJSONObject("result").getString("token");
+                System.out.println("token = " + token);
+                return token;
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            // 释放链接
+            response.close();
+            httpClient.close();
+        }
+
+        return "";
+
+    }
+    /**
+     * 生成签名
+     */
+    public static String createSign(SortedMap<Object,Object> parameters,String key){
+        StringBuffer sbkey = new StringBuffer();
+        //1.将所有参与传参的参数按照accsii排序(升序)
+        Set es = parameters.entrySet();
+        Iterator it = es.iterator();
+        while(it.hasNext()) {
+            Map.Entry entry = (Map.Entry)it.next();
+            String k = (String)entry.getKey();
+            Object v = entry.getValue();
+            //2.空值不传递,不参与签名组串
+            if(null != v && !"".equals(v)) {
+                sbkey.append(k + v );
+            }
+        }
+        sbkey=sbkey.append(key);
+        System.out.println("排序好的顺序为:"+sbkey.toString());
+        //3.MD5加密,结果转换为大写字符
+        String sign = getMD5(sbkey.toString()).toLowerCase();
+        return sign;
+    }
+
+    /**
+     * 对字符串进行MD5加密
+     */
+    public static String getMD5(String str) {
+        MessageDigest digest;
+
+        try {
+            digest = MessageDigest.getInstance("MD5");
+            digest.update(str.getBytes());
+            return new BigInteger(1, digest.digest()).toString(16);
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+}

BIN
unimall-admin-api/src/main/lib/cf-auth-api-token-5.1.5-SNAPSHOT-jar-with-dependencies.jar


BIN
unimall-admin-api/src/main/lib/dangdang-open-sdk.jar


+ 1 - 0
unimall-admin-api/src/main/resources/application.properties

@@ -0,0 +1 @@
+

+ 17 - 0
unimall-admin/.babelrc

@@ -0,0 +1,17 @@
+{
+  "presets": [
+    ["env", {
+      "modules": false,
+      "targets": {
+        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
+      }
+    }],
+    "stage-2"
+  ],
+  "plugins": ["transform-vue-jsx", "transform-runtime"],
+  "env": {
+    "development":{
+      "plugins": ["dynamic-import-node"]
+    }
+  }
+}

+ 3 - 0
unimall-admin/.eslintignore

@@ -0,0 +1,3 @@
+build/*.js
+config/*.js
+src/assets

+ 185 - 0
unimall-admin/.eslintrc.js

@@ -0,0 +1,185 @@
+module.exports = {
+  root: true,
+  parserOptions: {
+    parser: 'babel-eslint',
+    sourceType: 'module'
+  },
+  env: {
+    browser: true,
+    node: true,
+    es6: true,
+  },
+  extends: ['plugin:vue/recommended', 'eslint:recommended'],
+
+  // add your custom rules here
+  //it is base on https://github.com/vuejs/eslint-config-vue
+  rules: {
+    "indent": ["off", 0],
+    "vue/max-attributes-per-line": [2, {
+      "singleline": 10,
+      "multiline": {
+        "max": 1,
+        "allowFirstLine": false
+      }
+    }],
+    "vue/name-property-casing": ["error", "PascalCase"],
+    'accessor-pairs': 2,
+    'arrow-spacing': [2, {
+      'before': true,
+      'after': true
+    }],
+    'block-spacing': [2, 'always'],
+    'brace-style': "off",
+    'camelcase': [0, {
+      'properties': 'always'
+    }],
+    'comma-dangle': [2, 'never'],
+    'comma-spacing': [2, {
+      'before': false,
+      'after': true
+    }],
+    'comma-style': [2, 'last'],
+    'constructor-super': 2,
+    'curly': [2, 'multi-line'],
+    'dot-location': [2, 'property'],
+    'eol-last': 2,
+    'eqeqeq': "off",
+    'generator-star-spacing': [2, {
+      'before': true,
+      'after': true
+    }],
+    'handle-callback-err': [2, '^(err|error)$'],
+    'indent': [2, 2, {
+      'SwitchCase': 1
+    }],
+    'jsx-quotes': [2, 'prefer-single'],
+    'key-spacing': [2, {
+      'beforeColon': false,
+      'afterColon': true
+    }],
+    'keyword-spacing': [2, {
+      'before': true,
+      'after': true
+    }],
+    'new-cap': "off",
+    'new-parens': 2,
+    'no-array-constructor': 2,
+    'no-caller': "off",
+    'no-console': 'off',
+    'no-class-assign': 2,
+    'no-cond-assign': "off",
+    'no-const-assign': 2,
+    'no-constant-condition': "off",
+    'no-control-regex': 0,
+    'no-delete-var': 2,
+    'no-dupe-args': 2,
+    'no-dupe-class-members': 2,
+    'no-dupe-keys': 2,
+    'no-duplicate-case': 2,
+    'no-empty': "off",
+    'no-empty-character-class': "off",
+    'no-empty-pattern': "off",
+    'no-eval': "off",
+    'no-ex-assign': 2,
+    'no-extend-native': 2,
+    'no-extra-bind': 2,
+    'no-extra-boolean-cast': 2,
+    'no-extra-parens': [2, 'functions'],
+    'no-fallthrough': "off",
+    'no-floating-decimal': 2,
+    'no-func-assign': "off",
+    'no-implied-eval': 2,
+    'no-inner-declarations': "off",
+    'no-invalid-regexp': 2,
+    'no-irregular-whitespace': 2,
+    'no-iterator': 2,
+    'no-label-var': 2,
+    'no-labels': [2, {
+      'allowLoop': false,
+      'allowSwitch': false
+    }],
+    'no-lone-blocks': 2,
+    'no-mixed-spaces-and-tabs': 2,
+    'no-multi-spaces': 2,
+    'no-multi-str': 2,
+    'no-multiple-empty-lines': [2, {
+      'max': 1
+    }],
+    'no-native-reassign': 2,
+    'no-negated-in-lhs': 2,
+    'no-new-object': 2,
+    'no-new-require': 2,
+    'no-new-symbol': 2,
+    'no-new-wrappers': 2,
+    'no-obj-calls': 2,
+    'no-octal': 2,
+    'no-octal-escape': 2,
+    'no-path-concat': 2,
+    'no-proto': 2,
+    'no-redeclare': "off",
+    'no-regex-spaces': 2,
+    'no-return-assign': "off",
+    'no-self-assign': 2,
+    'no-self-compare': 2,
+    'no-sequences': "off",
+    'no-shadow-restricted-names': 2,
+    'no-spaced-func': 2,
+    'no-sparse-arrays': 2,
+    'no-this-before-super': 2,
+    'no-throw-literal': "off",
+    'no-trailing-spaces': 2,
+    'no-undef': "off",
+    'no-undef-init': "off",
+    'no-unexpected-multiline': "off",
+    'no-unmodified-loop-condition': "off",
+    'no-unneeded-ternary': "off",
+    'no-unreachable': "off",
+    'no-unsafe-finally': 2,
+    'no-unused-vars': [2, {
+      'vars': 'all',
+      'args': 'none'
+    }],
+    'no-useless-call': 2,
+    'no-useless-computed-key': 2,
+    'no-useless-constructor': 2,
+    'no-useless-escape': 0,
+    'no-whitespace-before-property': 2,
+    'no-with': 2,
+    "no-tabs":"off",
+    'one-var': "off",
+    'operator-linebreak': [2, 'after', {
+      'overrides': {
+        '?': 'before',
+        ':': 'before'
+      }
+    }],
+    'padded-blocks': [2, 'never'],
+    'quotes': [2, 'single', {
+      'avoidEscape': true,
+      'allowTemplateLiterals': true
+    }],
+    'semi': [2, 'never'],
+    'semi-spacing': [2, {
+      'before': false,
+      'after': true
+    }],
+    'space-before-blocks': [2, 'always'],
+    'space-before-function-paren':  0,
+    'spaced-comment': [2, 'always', {
+      'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
+    }],
+    'template-curly-spacing': [2, 'never'],
+    'use-isnan': 2,
+    'valid-typeof': 2,
+    'wrap-iife': [2, 'any'],
+    'yield-star-spacing': [2, 'both'],
+    'yoda': [2, 'never'],
+    'prefer-const': 2,
+    'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
+    'object-curly-spacing': [2, 'always', {
+      objectsInObjects: false
+    }],
+    'array-bracket-spacing': [2, 'never'],
+    "no-unused-vars": "off",
+  }
+}

+ 10 - 0
unimall-admin/.postcssrc.js

@@ -0,0 +1,10 @@
+// https://github.com/michael-ciniawsky/postcss-load-config
+
+module.exports = {
+  "plugins": {
+    "postcss-import": {},
+    "postcss-url": {},
+    // to edit target browsers: use "browserslist" field in package.json
+    "autoprefixer": {}
+  }
+}

+ 67 - 0
unimall-admin/build/build.js

@@ -0,0 +1,67 @@
+'use strict'
+require('./check-versions')()
+
+const ora = require('ora')
+const rm = require('rimraf')
+const path = require('path')
+const chalk = require('chalk')
+const webpack = require('webpack')
+const config = require('../config')
+const webpackConfig = require('./webpack.prod.conf')
+var connect = require('connect')
+var serveStatic = require('serve-static')
+
+const spinner = ora(
+  'building for ' + process.env.env_config + ' environment...'
+)
+spinner.start()
+
+rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
+  if (err) throw err
+  webpack(webpackConfig, (err, stats) => {
+    spinner.stop()
+    if (err) throw err
+    process.stdout.write(
+      stats.toString({
+        colors: true,
+        modules: false,
+        children: false,
+        chunks: false,
+        chunkModules: false
+      }) + '\n\n'
+    )
+
+    if (stats.hasErrors()) {
+      console.log(chalk.red(' Build failed with errors.\n'))
+      process.exit(1)
+    }
+
+    console.log(chalk.cyan(' Build complete.\n'))
+    console.log(
+      chalk.yellow(
+        ' Tip: built files are meant to be served over an HTTP server.\n' +
+          " Opening index.html over file:// won't work.\n"
+      )
+    )
+
+    if (process.env.npm_config_preview) {
+      const port = 9526
+      const host = 'http://localhost:' + port
+      const basePath = config.build.assetsPublicPath
+      const app = connect()
+
+      app.use(
+        basePath,
+        serveStatic('./dist', {
+          index: ['index.html', '/']
+        })
+      )
+
+      app.listen(port, function() {
+        console.log(
+          chalk.green(`> Listening at  http://localhost:${port}${basePath}`)
+        )
+      })
+    }
+  })
+})

+ 64 - 0
unimall-admin/build/check-versions.js

@@ -0,0 +1,64 @@
+'use strict'
+const chalk = require('chalk')
+const semver = require('semver')
+const packageConfig = require('../package.json')
+const shell = require('shelljs')
+
+function exec(cmd) {
+  return require('child_process')
+    .execSync(cmd)
+    .toString()
+    .trim()
+}
+
+const versionRequirements = [
+  {
+    name: 'node',
+    currentVersion: semver.clean(process.version),
+    versionRequirement: packageConfig.engines.node
+  }
+]
+
+if (shell.which('npm')) {
+  versionRequirements.push({
+    name: 'npm',
+    currentVersion: exec('npm --version'),
+    versionRequirement: packageConfig.engines.npm
+  })
+}
+
+module.exports = function() {
+  const warnings = []
+
+  for (let i = 0; i < versionRequirements.length; i++) {
+    const mod = versionRequirements[i]
+
+    if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
+      warnings.push(
+        mod.name +
+          ': ' +
+          chalk.red(mod.currentVersion) +
+          ' should be ' +
+          chalk.green(mod.versionRequirement)
+      )
+    }
+  }
+
+  if (warnings.length) {
+    console.log('')
+    console.log(
+      chalk.yellow(
+        'To use this template, you must update following to modules:'
+      )
+    )
+    console.log()
+
+    for (let i = 0; i < warnings.length; i++) {
+      const warning = warnings[i]
+      console.log('  ' + warning)
+    }
+
+    console.log()
+    process.exit(1)
+  }
+}

BIN
unimall-admin/build/logo.png


+ 108 - 0
unimall-admin/build/utils.js

@@ -0,0 +1,108 @@
+'use strict'
+const path = require('path')
+const config = require('../config')
+const MiniCssExtractPlugin = require('mini-css-extract-plugin')
+const packageConfig = require('../package.json')
+
+exports.assetsPath = function(_path) {
+  const assetsSubDirectory =
+    process.env.NODE_ENV === 'production'
+      ? config.build.assetsSubDirectory
+      : config.dev.assetsSubDirectory
+
+  return path.posix.join(assetsSubDirectory, _path)
+}
+
+exports.cssLoaders = function(options) {
+  options = options || {}
+
+  const cssLoader = {
+    loader: 'css-loader',
+    options: {
+      sourceMap: options.sourceMap
+    }
+  }
+
+  const postcssLoader = {
+    loader: 'postcss-loader',
+    options: {
+      sourceMap: options.sourceMap
+    }
+  }
+
+  // generate loader string to be used with extract text plugin
+  function generateLoaders(loader, loaderOptions) {
+    const loaders = []
+
+    // Extract CSS when that option is specified
+    // (which is the case during production build)
+    if (options.extract) {
+      loaders.push(MiniCssExtractPlugin.loader)
+    } else {
+      loaders.push('vue-style-loader')
+    }
+
+    loaders.push(cssLoader)
+
+    if (options.usePostCSS) {
+      loaders.push(postcssLoader)
+    }
+
+    if (loader) {
+      loaders.push({
+        loader: loader + '-loader',
+        options: Object.assign({}, loaderOptions, {
+          sourceMap: options.sourceMap
+        })
+      })
+    }
+
+    return loaders
+  }
+  // https://vue-loader.vuejs.org/en/configurations/extract-css.html
+  return {
+    css: generateLoaders(),
+    postcss: generateLoaders(),
+    less: generateLoaders('less'),
+    sass: generateLoaders('sass', {
+      indentedSyntax: true
+    }),
+    scss: generateLoaders('sass'),
+    stylus: generateLoaders('stylus'),
+    styl: generateLoaders('stylus')
+  }
+}
+
+// Generate loaders for standalone style files (outside of .vue)
+exports.styleLoaders = function(options) {
+  const output = []
+  const loaders = exports.cssLoaders(options)
+
+  for (const extension in loaders) {
+    const loader = loaders[extension]
+    output.push({
+      test: new RegExp('\\.' + extension + '$'),
+      use: loader
+    })
+  }
+
+  return output
+}
+
+exports.createNotifierCallback = () => {
+  const notifier = require('node-notifier')
+
+  return (severity, errors) => {
+    if (severity !== 'error') return
+
+    const error = errors[0]
+    const filename = error.file && error.file.split('!').pop()
+
+    notifier.notify({
+      title: packageConfig.name,
+      message: severity + ': ' + error.name,
+      subtitle: filename || '',
+      icon: path.join(__dirname, 'logo.png')
+    })
+  }
+}

+ 5 - 0
unimall-admin/build/vue-loader.conf.js

@@ -0,0 +1,5 @@
+'use strict'
+
+module.exports = {
+  //You can set the vue-loader configuration by yourself.
+}

+ 107 - 0
unimall-admin/build/webpack.base.conf.js

@@ -0,0 +1,107 @@
+'use strict'
+const path = require('path')
+const utils = require('./utils')
+const config = require('../config')
+const { VueLoaderPlugin } = require('vue-loader')
+const vueLoaderConfig = require('./vue-loader.conf')
+
+function resolve(dir) {
+  return path.join(__dirname, '..', dir)
+}
+
+const createLintingRule = () => ({
+  test: /\.(js|vue)$/,
+  loader: 'eslint-loader',
+  enforce: 'pre',
+  include: [resolve('src'), resolve('test')],
+  options: {
+    formatter: require('eslint-friendly-formatter'),
+    emitWarning: !config.dev.showEslintErrorsInOverlay
+  }
+})
+
+module.exports = {
+  context: path.resolve(__dirname, '../'),
+  entry: {
+    app: './src/main.js'
+  },
+  output: {
+    path: config.build.assetsRoot,
+    filename: '[name].js',
+    publicPath:
+      process.env.NODE_ENV === 'production'
+        ? config.build.assetsPublicPath
+        : config.dev.assetsPublicPath
+  },
+  resolve: {
+    extensions: ['.js', '.vue', '.json'],
+    alias: {
+      '@': resolve('src')
+    }
+  },
+  module: {
+    rules: [
+      ...(config.dev.useEslint ? [createLintingRule()] : []),
+      {
+        test: /\.vue$/,
+        loader: 'vue-loader',
+        options: vueLoaderConfig
+      },
+      {
+        test: /\.js$/,
+        loader: 'babel-loader?cacheDirectory',
+        include: [
+          resolve('src'),
+          resolve('test'),
+          resolve('node_modules/webpack-dev-server/client')
+        ]
+      },
+      {
+        test: /\.svg$/,
+        loader: 'svg-sprite-loader',
+        include: [resolve('src/icons')],
+        options: {
+          symbolId: 'icon-[name]'
+        }
+      },
+      {
+        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
+        loader: 'url-loader',
+        exclude: [resolve('src/icons')],
+        options: {
+          limit: 10000,
+          name: utils.assetsPath('img/[name].[hash:7].[ext]')
+        }
+      },
+      {
+        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
+        loader: 'url-loader',
+        options: {
+          limit: 10000,
+          name: utils.assetsPath('media/[name].[hash:7].[ext]')
+        }
+      },
+      {
+        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
+        loader: 'url-loader',
+        options: {
+          limit: 10000,
+          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
+        }
+      }
+    ]
+  },
+  plugins: [new VueLoaderPlugin()],
+  node: {
+    // prevent webpack from injecting useless setImmediate polyfill because Vue
+    // source contains it (although only uses it if it's native).
+    setImmediate: false,
+    // prevent webpack from injecting mocks to Node native modules
+    // that does not make sense for the client
+    dgram: 'empty',
+    fs: 'empty',
+    net: 'empty',
+    tls: 'empty',
+    child_process: 'empty'
+  }
+}

+ 98 - 0
unimall-admin/build/webpack.dev.conf.js

@@ -0,0 +1,98 @@
+'use strict'
+const path = require('path')
+const utils = require('./utils')
+const webpack = require('webpack')
+const config = require('../config')
+const merge = require('webpack-merge')
+const baseWebpackConfig = require('./webpack.base.conf')
+const HtmlWebpackPlugin = require('html-webpack-plugin')
+const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
+const portfinder = require('portfinder')
+
+function resolve(dir) {
+  return path.join(__dirname, '..', dir)
+}
+
+const HOST = process.env.HOST
+const PORT = process.env.PORT && Number(process.env.PORT)
+
+const devWebpackConfig = merge(baseWebpackConfig, {
+  mode: 'development',
+  module: {
+    rules: utils.styleLoaders({
+      sourceMap: config.dev.cssSourceMap,
+      usePostCSS: true
+    })
+  },
+  // cheap-module-eval-source-map is faster for development
+  devtool: config.dev.devtool,
+
+  // these devServer options should be customized in /config/index.js
+  devServer: {
+    clientLogLevel: 'warning',
+    historyApiFallback: true,
+    hot: true,
+    compress: true,
+    host: HOST || config.dev.host,
+    port: PORT || config.dev.port,
+    open: config.dev.autoOpenBrowser,
+    overlay: config.dev.errorOverlay
+      ? { warnings: false, errors: true }
+      : false,
+    publicPath: config.dev.assetsPublicPath,
+    proxy: config.dev.proxyTable,
+    quiet: true, // necessary for FriendlyErrorsPlugin
+    watchOptions: {
+      poll: config.dev.poll
+    }
+  },
+  plugins: [
+    new webpack.DefinePlugin({
+      'process.env': require('../config/dev.env')
+    }),
+    new webpack.HotModuleReplacementPlugin(),
+    // https://github.com/ampedandwired/html-webpack-plugin
+    new HtmlWebpackPlugin({
+      filename: 'index.html',
+      template: 'index.html',
+      inject: true,
+      favicon: resolve('favicon.ico'),
+      title: 'vue-element-admin',
+      templateParameters: {
+        BASE_URL: config.dev.assetsPublicPath + config.dev.assetsSubDirectory,
+      },
+    }),
+  ]
+})
+
+module.exports = new Promise((resolve, reject) => {
+  portfinder.basePort = process.env.PORT || config.dev.port
+  portfinder.getPort((err, port) => {
+    if (err) {
+      reject(err)
+    } else {
+      // publish the new Port, necessary for e2e tests
+      process.env.PORT = port
+      // add port to devServer config
+      devWebpackConfig.devServer.port = port
+
+      // Add FriendlyErrorsPlugin
+      devWebpackConfig.plugins.push(
+        new FriendlyErrorsPlugin({
+          compilationSuccessInfo: {
+            messages: [
+              `Your application is running here: http://${
+                devWebpackConfig.devServer.host
+              }:${port}`
+            ]
+          },
+          onErrors: config.dev.notifyOnErrors
+            ? utils.createNotifierCallback()
+            : undefined
+        })
+      )
+
+      resolve(devWebpackConfig)
+    }
+  })
+})

+ 188 - 0
unimall-admin/build/webpack.prod.conf.js

@@ -0,0 +1,188 @@
+'use strict'
+const path = require('path')
+const utils = require('./utils')
+const webpack = require('webpack')
+const config = require('../config')
+const merge = require('webpack-merge')
+const baseWebpackConfig = require('./webpack.base.conf')
+const CopyWebpackPlugin = require('copy-webpack-plugin')
+const HtmlWebpackPlugin = require('html-webpack-plugin')
+const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin')
+const MiniCssExtractPlugin = require('mini-css-extract-plugin')
+const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
+const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
+
+function resolve(dir) {
+  return path.join(__dirname, '..', dir)
+}
+
+const env = require('../config/' + process.env.env_config + '.env')
+
+// For NamedChunksPlugin
+const seen = new Set()
+const nameLength = 4
+
+const webpackConfig = merge(baseWebpackConfig, {
+  mode: 'production',
+  module: {
+    rules: utils.styleLoaders({
+      sourceMap: config.build.productionSourceMap,
+      extract: true,
+      usePostCSS: true
+    })
+  },
+  devtool: config.build.productionSourceMap ? config.build.devtool : false,
+  output: {
+    path: config.build.assetsRoot,
+    filename: utils.assetsPath('js/[name].[chunkhash:8].js'),
+    chunkFilename: utils.assetsPath('js/[name].[chunkhash:8].js')
+  },
+  plugins: [
+    // http://vuejs.github.io/vue-loader/en/workflow/production.html
+    new webpack.DefinePlugin({
+      'process.env': env
+    }),
+    // extract css into its own file
+    new MiniCssExtractPlugin({
+      filename: utils.assetsPath('css/[name].[contenthash:8].css'),
+      chunkFilename: utils.assetsPath('css/[name].[contenthash:8].css')
+    }),
+    // generate dist index.html with correct asset hash for caching.
+    // you can customize output by editing /index.html
+    // see https://github.com/ampedandwired/html-webpack-plugin
+    new HtmlWebpackPlugin({
+      filename: config.build.index,
+      template: 'index.html',
+      inject: true,
+      favicon: resolve('favicon.ico'),
+      title: 'vue-element-admin',
+      templateParameters: {
+        BASE_URL: config.build.assetsPublicPath + config.build.assetsSubDirectory,
+      },
+      minify: {
+        removeComments: true,
+        collapseWhitespace: true,
+        removeAttributeQuotes: true
+        // more options:
+        // https://github.com/kangax/html-minifier#options-quick-reference
+      }
+      // default sort mode uses toposort which cannot handle cyclic deps
+      // in certain cases, and in webpack 4, chunk order in HTML doesn't
+      // matter anyway
+    }),
+    new ScriptExtHtmlWebpackPlugin({
+      //`runtime` must same as runtimeChunk name. default is `runtime`
+      inline: /runtime\..*\.js$/
+    }),
+    // keep chunk.id stable when chunk has no name
+    new webpack.NamedChunksPlugin(chunk => {
+      if (chunk.name) {
+        return chunk.name
+      }
+      const modules = Array.from(chunk.modulesIterable)
+      if (modules.length > 1) {
+        const hash = require('hash-sum')
+        const joinedHash = hash(modules.map(m => m.id).join('_'))
+        let len = nameLength
+        while (seen.has(joinedHash.substr(0, len))) len++
+        seen.add(joinedHash.substr(0, len))
+        return `chunk-${joinedHash.substr(0, len)}`
+      } else {
+        return modules[0].id
+      }
+    }),
+    // keep module.id stable when vender modules does not change
+    new webpack.HashedModuleIdsPlugin(),
+    // copy custom static assets
+    new CopyWebpackPlugin([
+      {
+        from: path.resolve(__dirname, '../static'),
+        to: config.build.assetsSubDirectory,
+        ignore: ['.*']
+      }
+    ])
+  ],
+  optimization: {
+    splitChunks: {
+      chunks: 'all',
+      cacheGroups: {
+        libs: {
+          name: 'chunk-libs',
+          test: /[\\/]node_modules[\\/]/,
+          priority: 10,
+          chunks: 'initial' // 只打包初始时依赖的第三方
+        },
+        elementUI: {
+          name: 'chunk-elementUI', // 单独将 elementUI 拆包
+          priority: 20, // 权重要大于 libs 和 app 不然会被打包进 libs 或者 app
+          test: /[\\/]node_modules[\\/]element-ui[\\/]/
+        },
+        commons: {
+          name: 'chunk-commons',
+          test: resolve('src/components'), // 可自定义拓展你的规则
+          minChunks: 3, // 最小公用次数
+          priority: 5,
+          reuseExistingChunk: true
+        }
+      }
+    },
+    runtimeChunk: 'single',
+    minimizer: [
+      new UglifyJsPlugin({
+        uglifyOptions: {
+          mangle: {
+            safari10: true
+          }
+        },
+        sourceMap: config.build.productionSourceMap,
+        cache: true,
+        parallel: true
+      }),
+      // Compress extracted CSS. We are using this plugin so that possible
+      // duplicated CSS from different components can be deduped.
+      new OptimizeCSSAssetsPlugin()
+    ]
+  }
+})
+
+if (config.build.productionGzip) {
+  const CompressionWebpackPlugin = require('compression-webpack-plugin')
+
+  webpackConfig.plugins.push(
+    new CompressionWebpackPlugin({
+      asset: '[path].gz[query]',
+      algorithm: 'gzip',
+      test: new RegExp(
+        '\\.(' + config.build.productionGzipExtensions.join('|') + ')$'
+      ),
+      threshold: 10240,
+      minRatio: 0.8
+    })
+  )
+}
+
+if (config.build.generateAnalyzerReport || config.build.bundleAnalyzerReport) {
+  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
+    .BundleAnalyzerPlugin
+
+  if (config.build.bundleAnalyzerReport) {
+    webpackConfig.plugins.push(
+      new BundleAnalyzerPlugin({
+        analyzerPort: 8080,
+        generateStatsFile: false
+      })
+    )
+  }
+
+  if (config.build.generateAnalyzerReport) {
+    webpackConfig.plugins.push(
+      new BundleAnalyzerPlugin({
+        analyzerMode: 'static',
+        reportFilename: 'bundle-report.html',
+        openAnalyzer: false
+      })
+    )
+  }
+}
+
+module.exports = webpackConfig

+ 6 - 0
unimall-admin/config/dep.env.js

@@ -0,0 +1,6 @@
+module.exports = {
+	NODE_ENV: '"production"',
+  ENV_CONFIG: '"dep"',
+  HOST: '"http://localhost:8081"',
+  BASE_API: '"http://localhost:8081/m.api"'
+}

+ 8 - 0
unimall-admin/config/dev.env.js

@@ -0,0 +1,8 @@
+module.exports = {
+    NODE_ENV: '"development"',
+    ENV_CONFIG: '"dev"',
+    // HOST: '"http://192.168.110.138:8182"',
+    // BASE_API: '"http://192.168.110.138:8182/m.api"'
+    HOST: '"https://cardapi.eliangeyun.com"',
+    BASE_API: '"https://cardapi.eliangeyun.com/m.api"'
+}

+ 88 - 0
unimall-admin/config/index.js

@@ -0,0 +1,88 @@
+'use strict'
+// Template version: 1.2.6
+// see http://vuejs-templates.github.io/webpack for documentation.
+
+const path = require('path')
+
+module.exports = {
+    dev: {
+        // Paths
+        assetsSubDirectory: 'static',
+        assetsPublicPath: '/',
+        proxyTable: {},
+
+        // Various Dev Server settings
+
+        // can be overwritten by process.env.HOST
+        // if you want dev by ip, please set host: '0.0.0.0'
+        host: '192.168.110.82',
+        port: 9527, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
+        autoOpenBrowser: true,
+        errorOverlay: true,
+        notifyOnErrors: false,
+        poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
+
+        // Use Eslint Loader?
+        // If true, your code will be linted during bundling and
+        // linting errors and warnings will be shown in the console.
+        useEslint: false,
+        // If true, eslint errors and warnings will also be shown in the error overlay
+        // in the browser.
+        showEslintErrorsInOverlay: false,
+
+        /**
+         * Source Maps
+         */
+
+        // https://webpack.js.org/configuration/devtool/#development
+        devtool: 'source-map',
+
+        // CSS Sourcemaps off by default because relative paths are "buggy"
+        // with this option, according to the CSS-Loader README
+        // (https://github.com/webpack/css-loader#sourcemaps)
+        // In our experience, they generally work as expected,
+        // just be aware of this issue when enabling this option.
+        cssSourceMap: false
+    },
+
+    build: {
+        // Template for index.html
+        index: path.resolve(__dirname, '../dist/index.html'),
+
+        // Paths
+        assetsRoot: path.resolve(__dirname, '../dist'),
+        assetsSubDirectory: 'static',
+
+        /**
+         * You can set by youself according to actual condition
+         * You will need to set this if you plan to deploy your site under a sub path,
+         * for example GitHub pages. If you plan to deploy your site to https://foo.github.io/bar/,
+         * then assetsPublicPath should be set to "/bar/".
+         * In most cases please use '/' !!!
+         */
+        assetsPublicPath: '/',
+
+        /**
+         * Source Maps
+         */
+        productionSourceMap: false,
+        // https://webpack.js.org/configuration/devtool/#production
+        devtool: 'source-map',
+
+        // Gzip off by default as many popular static hosts such as
+        // Surge or Netlify already gzip all static assets for you.
+        // Before setting to `true`, make sure to:
+        // npm install --save-dev compression-webpack-plugin
+        productionGzip: false,
+        productionGzipExtensions: ['js', 'css'],
+
+        // Run the build command with an extra argument to
+        // View the bundle analyzer report after build finishes:
+        // `npm run build:prod --report`
+        // Set to `true` or `false` to always turn it on or off
+        bundleAnalyzerReport: process.env.npm_config_report || false,
+
+        // `npm run build:prod --generate_report`
+        generateAnalyzerReport: process.env.npm_config_generate_report || false
+    }
+}

+ 6 - 0
unimall-admin/config/prod.env.js

@@ -0,0 +1,6 @@
+module.exports = {
+	NODE_ENV: '"production"',
+  	ENV_CONFIG: '"prod"',
+    HOST: '"https://cardapi.eliangeyun.com"',
+    BASE_API: '"https://cardapi.eliangeyun.com/m.api"'
+}

BIN
unimall-admin/favicon.ico


+ 18 - 0
unimall-admin/index.html

@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <meta charset="utf-8">
+    <meta name="renderer" content="webkit">
+    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
+    <title>名片后台管理</title>
+</head>
+
+<body>
+    <script src=<%=BASE_URL %>/tinymce4.7.5/tinymce.min.js >
+    </script>
+    <div id="app"></div>
+    <!-- built files will be auto injected -->
+</body>
+
+</html>

+ 18 - 0
unimall-admin/src/App.vue

@@ -0,0 +1,18 @@
+<template>
+  <div id="app">
+    <router-view/>
+  </div>
+</template>
+
+<script>
+export default{
+  name: 'App'
+}
+</script>
+<style>
+.el-upload--picture-card,.el-upload-list--picture-card .el-upload-list__item{
+  width: 70px;
+  height: 70px;
+  line-height: 70px;
+}
+</style>

+ 55 - 0
unimall-admin/src/api/admin.js

@@ -0,0 +1,55 @@
+import request from '@/utils/request'
+import Qs from 'qs'
+
+export function listAdmin(query) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin',
+      _mt: 'list',
+      ...query
+    }
+  })
+}
+
+export function createAdmin(data) {
+  return request({
+    method: 'post',
+    data: Qs.stringify({
+      _gp: 'admin',
+      _mt: 'create',
+      adminDTO: JSON.stringify(data)
+    })
+  })
+}
+
+export function readminAdmin(data) {
+  return request({
+    url: '/admin/readmin',
+    method: 'get',
+    data
+  })
+}
+
+export function updateAdmin(data) {
+  return request({
+    method: 'post',
+    data: Qs.stringify({
+      _gp: 'admin',
+      _mt: 'update',
+      adminDTO: JSON.stringify(data)
+    })
+  })
+}
+
+export function deleteAdmin(id) {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin',
+      _mt: 'delete',
+      id: id
+    }
+  })
+}
+

+ 23 - 0
unimall-admin/src/api/appraise.js

@@ -0,0 +1,23 @@
+import request from '@/utils/request'
+
+export function listAppraise(query) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.appraise',
+      _mt: 'getAppraiseList',
+      ...query
+    }
+  })
+}
+
+export function deleteAppraise(data) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.appraise',
+      _mt: 'deleteAppraise',
+      ...data
+    }
+  })
+}

+ 66 - 0
unimall-admin/src/api/category.js

@@ -0,0 +1,66 @@
+import request from '@/utils/request'
+import Qs from 'qs'
+
+export function categorySecondLevelTree() {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.category',
+      _mt: 'categorySecondLevelTree'
+    }
+  })
+}
+
+export function categoryTree() {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.category',
+      _mt: 'categoryTree'
+    }
+  })
+}
+
+export function listCategory(query) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.category',
+      _mt: 'queryCategory',
+      ...query
+    }
+  })
+}
+
+export function createCategory(data) {
+  return request({
+    method: 'post',
+    data: Qs.stringify({
+      _gp: 'admin.category',
+      _mt: 'addCategory',
+      ...data
+    })
+  })
+}
+
+export function updateCategory(data) {
+  return request({
+    method: 'post',
+    data: Qs.stringify({
+      _gp: 'admin.category',
+      _mt: 'updateCategory',
+      ...data
+    })
+  })
+}
+
+export function deleteCategory(id) {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin.category',
+      _mt: 'deleteCategory',
+      id: id
+    }
+  })
+}

+ 11 - 0
unimall-admin/src/api/dashboard.js

@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+export function info() {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.dashboard',
+      _mt: 'integral'
+    }
+  })
+}

+ 48 - 0
unimall-admin/src/api/log/logininfor.js

@@ -0,0 +1,48 @@
+import request from '@/utils/request'
+
+// 查询登录日志列表
+export function list(query) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.log.logininfor',
+      _mt: 'list',
+      ...query
+    }
+  })
+}
+
+// 删除登录日志
+export function delLogininfor(infoId) {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin.log.logininfor',
+      _mt: 'delete',
+      infoIds: infoId
+    }
+  })
+}
+
+// 清空登录日志
+export function cleanLogininfor() {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin.log.logininfor',
+      _mt: 'clean'
+    }
+  })
+}
+
+// 导出登录日志
+export function exportLogininfor(query) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.log.logininfor',
+      _mt: 'export',
+      ...query
+    }
+  })
+}

+ 48 - 0
unimall-admin/src/api/log/operlog.js

@@ -0,0 +1,48 @@
+import request from '@/utils/request'
+
+// 查询操作日志列表
+export function list(query) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.log.operlog',
+      _mt: 'list',
+      ...query
+    }
+  })
+}
+
+// 删除操作日志
+export function delOperlog(operIds) {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin.log.operlog',
+      _mt: 'delete',
+      operIds: operIds
+    }
+  })
+}
+
+// 清空操作日志
+export function cleanOperlog() {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin.log.operlog',
+      _mt: 'clean'
+    }
+  })
+}
+
+// 导出操作日志
+export function exportOperlog(query) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.log.operlog',
+      _mt: 'export',
+      ...query
+    }
+  })
+}

+ 50 - 0
unimall-admin/src/api/login.js

@@ -0,0 +1,50 @@
+import request from '@/utils/request'
+import Qs from 'qs'
+
+export function loginByUsername(username, password, verifyCode) {
+  const data = {
+    username,
+    password,
+    verifyCode
+  }
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin',
+      _mt: 'login',
+      ...data
+    }
+  })
+}
+
+export function sendMsg(data) {
+  return request({
+    method: 'post',
+    data: Qs.stringify({
+      _gp: 'admin',
+      _mt: 'sendLoginMsg',
+      ...data
+    })
+  })
+}
+
+export function logout() {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin',
+      _mt: 'logout'
+    }
+  })
+}
+
+export function getUserInfo() {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin',
+      _mt: 'info'
+    }
+  })
+}
+

+ 24 - 0
unimall-admin/src/api/merchant.js

@@ -0,0 +1,24 @@
+import request from '@/utils/request'
+import Qs from 'qs'
+
+export function listMerchant(query) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.merchant',
+      _mt: 'getMerchant',
+      ...query
+    }
+  })
+}
+
+export function updateMerchant(data) {
+  return request({
+    method: 'post',
+    data: Qs.stringify({
+      _gp: 'admin.merchant',
+      _mt: 'updateMerchant',
+      ...data
+    })
+  })
+}

+ 91 - 0
unimall-admin/src/api/merchantad.js

@@ -0,0 +1,91 @@
+import request from '@/utils/request'
+import Qs from 'qs'
+
+export function listAd(query) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.advertisement',
+      _mt: 'queryAdvertisement',
+      ...query
+    }
+  })
+}
+
+export function createAd(data) {
+  return request({
+    method: 'post',
+    data: Qs.stringify({
+      _gp: 'admin.advertisement',
+      _mt: 'addAdvertisement',
+      ...data
+    })
+  })
+}
+
+// export function readAd(data) {
+//   return request({
+//     url: '/ad/read',
+//     method: 'get',
+//     data
+//   })
+// }
+
+export function updateAd(data) {
+  return request({
+    method: 'post',
+    data: Qs.stringify({
+      _gp: 'admin.advertisement',
+      _mt: 'updateAdvertisement',
+      ...data,
+      adId: data.id
+    })
+  })
+}
+
+export function deleteAd(id, adType) {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin.advertisement',
+      _mt: 'deleteAdvertisement',
+      adId: id,
+      adType: adType
+    }
+  })
+}
+
+export function getImageColor(canvas, img) {
+  canvas.width = img.width
+  canvas.height = img.height
+
+  var context = canvas.getContext('2d')
+
+  context.drawImage(img, 0, 0)
+
+  // 获取像素数据
+  var data = context.getImageData(0, 0, img.width, img.height).data
+
+  var r, g, b
+  r = g = b = 0
+  // 取所有像素的平均值
+  for (var row = 0; row < img.height; row++) {
+    for (var col = 0; col < img.width; col++) {
+      r += data[((img.width * row) + col) * 4]
+      g += data[((img.width * row) + col) * 4 + 1]
+      b += data[((img.width * row) + col) * 4 + 2]
+    }
+  }
+  // 求取平均值
+  r /= (img.width * img.height)
+  g /= (img.width * img.height)
+  b /= (img.width * img.height)
+
+  // 将最终的值取整
+  r = Math.round(r)
+  g = Math.round(g)
+  b = Math.round(b)
+
+  return 'rgb(' + r + ',' + g + ',' + b + ')'
+}
+

+ 24 - 0
unimall-admin/src/api/monitor/online.js

@@ -0,0 +1,24 @@
+import request from '@/utils/request'
+
+// 查询在线用户列表
+export function list() {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.monitor.online',
+      _mt: 'list'
+    }
+  })
+}
+
+// 强退用户
+export function forceLogout(tokenId) {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin.monitor.online',
+      _mt: 'forceLogout',
+      tokenId: tokenId
+    }
+  })
+}

+ 12 - 0
unimall-admin/src/api/monitor/server.js

@@ -0,0 +1,12 @@
+import request from '@/utils/request'
+
+// 查询服务器详细
+export function getServer() {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.monitor.server',
+      _mt: 'getInfo'
+    }
+  })
+}

+ 12 - 0
unimall-admin/src/api/profile.js

@@ -0,0 +1,12 @@
+import request from '@/utils/request'
+
+export function changePassword(data) {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin',
+      _mt: 'newPassword',
+      ...data
+    }
+  })
+}

+ 78 - 0
unimall-admin/src/api/role.js

@@ -0,0 +1,78 @@
+import request from '@/utils/request'
+import Qs from 'qs'
+
+export function listRole(query) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.role',
+      _mt: 'list',
+      ...query
+    }
+  })
+}
+
+export function createRole(data) {
+  return request({
+    method: 'post',
+    data: Qs.stringify({
+      _gp: 'admin.role',
+      _mt: 'create',
+      role: JSON.stringify(data)
+    })
+  })
+}
+
+export function updateRole(data) {
+  return request({
+    method: 'post',
+    data: Qs.stringify({
+      _gp: 'admin.role',
+      _mt: 'update',
+      role: JSON.stringify(data)
+    })
+  })
+}
+
+export function deleteRole(id) {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin.role',
+      _mt: 'delete',
+      roleId: id
+    }
+  })
+}
+
+export function getPermission(query) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.role',
+      _mt: 'permissionList',
+      ...query
+    }
+  })
+}
+
+export function updatePermission(data) {
+  return request({
+    method: 'post',
+    data: Qs.stringify({
+      _gp: 'admin.role',
+      _mt: 'permissionSet',
+      roleSetPermissionDTO: JSON.stringify(data)
+    })
+  })
+}
+
+export function roleOptions(query) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.role',
+      _mt: 'options'
+    }
+  })
+}

+ 11 - 0
unimall-admin/src/api/storage.js

@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+const uploadPath = process.env.HOST + '/upload/admin'
+export { uploadPath }
+
+export function createStorage(data) {
+  return request({
+    url: uploadPath,
+    method: 'post',
+    data
+  })
+}

+ 74 - 0
unimall-admin/src/api/sys/dict/data.js

@@ -0,0 +1,74 @@
+import request from '@/utils/request'
+
+// 查询字典数据列表
+export function listData(query) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.dictData',
+      _mt: 'list',
+      ...query
+    }
+  })
+}
+
+// 查询字典数据详细
+export function getData(dictCode) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.dictData',
+      _mt: 'get',
+      dictCode: dictCode
+    }
+  })
+}
+
+// 根据字典类型查询字典数据信息
+export function getDicts(dictType) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.dictData',
+      _mt: 'selectDictDataByType',
+      dictType: dictType
+    }
+  })
+}
+
+// 新增字典数据
+export function addData(data) {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin.dictData',
+      _mt: 'add',
+      dictData: data
+    }
+  })
+}
+
+// 修改字典数据
+export function updateData(data) {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin.dictData',
+      _mt: 'update',
+      dictData: data
+    }
+  })
+}
+
+// 删除字典数据
+export function delData(dictCodes) {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin.dictData',
+      _mt: 'delete',
+      dictCodes: dictCodes
+    }
+  })
+}
+

+ 72 - 0
unimall-admin/src/api/sys/dict/type.js

@@ -0,0 +1,72 @@
+import request from '@/utils/request'
+
+// 查询字典类型列表
+export function listType(query) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.dictType',
+      _mt: 'list',
+      ...query
+    }
+  })
+}
+
+// 查询字典类型详细
+export function getType(dictId) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.dictType',
+      _mt: 'get',
+      dictId: dictId
+    }
+  })
+}
+
+// 新增字典类型
+export function addType(data) {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin.dictType',
+      _mt: 'add',
+      dictType: JSON.stringify(data)
+    }
+  })
+}
+
+// 修改字典类型
+export function updateType(data) {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin.dictType',
+      _mt: 'update',
+      dictType: JSON.stringify(data)
+    }
+  })
+}
+
+// 删除字典类型
+export function delType(dictIds) {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin.dictType',
+      _mt: 'delete',
+      dictIds: dictIds
+    }
+  })
+}
+
+// 获取字典选择框列表
+export function optionselect() {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.dictType',
+      _mt: 'optionselect'
+    }
+  })
+}

+ 93 - 0
unimall-admin/src/api/tool/gen.js

@@ -0,0 +1,93 @@
+import request from '@/utils/request'
+
+// 查询生成表数据
+export function listTable(query) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.tools.gen',
+      _mt: 'list',
+      ...query
+    }
+  })
+}
+// 查询db数据库列表
+export function listDbTable(query) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.tools.gen',
+      _mt: 'getDbList',
+      ...query
+    }
+  })
+}
+
+// 查询表详细信息
+export function getGenTable(tableId) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.tools.gen',
+      _mt: 'get',
+      id: tableId
+    }
+  })
+}
+
+// 修改代码生成信息
+export function updateGenTable(data) {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin.tools.gen',
+      _mt: 'update',
+      genTable: data
+    }
+  })
+}
+// 修改代码生成字段信息
+export function updateGenTableColumns(data) {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin.tools.gen',
+      _mt: 'updateColumn',
+      genTableColumn: data
+    }
+  })
+}
+// 导入表
+export function importTable(data) {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin.tools.gen',
+      _mt: 'importTableSave',
+      ...data
+    }
+  })
+}
+// 预览生成代码
+export function previewTable(tableId) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.tools.gen',
+      _mt: 'preview',
+      tableId: tableId
+    }
+  })
+}
+// 删除表数据
+export function delTable(tableIds) {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin.tools.gen',
+      _mt: 'delete',
+      tableIds: tableIds
+    }
+  })
+}
+

+ 58 - 0
unimall-admin/src/api/user.js

@@ -0,0 +1,58 @@
+import request from '@/utils/request'
+
+export function fetchList(query) {
+  return request({
+    method: 'get',
+    params: {
+      _gp: 'admin.user',
+      _mt: 'getUser',
+      ...query
+    }
+  })
+}
+
+export function activeUser(data) {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin.user',
+      _mt: 'updateStatus',
+      userId: data.id,
+      status: data.status
+    }
+  })
+}
+
+export function createUser(data) {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin.user',
+      _mt: 'addUser',
+      user: JSON.stringify(data)
+    }
+  })
+}
+
+export function updateUser(data) {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin.user',
+      _mt: 'updateUser',
+      user: JSON.stringify(data)
+    }
+  })
+}
+
+export function deleteUser(id, nickname) {
+  return request({
+    method: 'post',
+    params: {
+      _gp: 'admin.user',
+      _mt: 'deleteUser',
+      id: id,
+      nickname: nickname
+    }
+  })
+}

BIN
unimall-admin/src/assets/401_images/401.gif


BIN
unimall-admin/src/assets/404_images/404.png


BIN
unimall-admin/src/assets/404_images/404_cloud.png


BIN
unimall-admin/src/assets/avatar.png


BIN
unimall-admin/src/assets/custom-theme/fonts/element-icons.ttf


BIN
unimall-admin/src/assets/custom-theme/fonts/element-icons.woff


Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
unimall-admin/src/assets/custom-theme/index.css


+ 116 - 0
unimall-admin/src/components/BackToTop/index.vue

@@ -0,0 +1,116 @@
+<template>
+  <transition :name="transitionName">
+    <div v-show="visible" :style="customStyle" class="back-to-ceiling" @click="backToTop">
+      <svg width="16" height="16" viewBox="0 0 17 17" xmlns="http://www.w3.org/2000/svg" class="Icon Icon--backToTopArrow" aria-hidden="true" style="height: 16px; width: 16px;">
+        <title>回到顶部</title>
+        <g>
+          <path d="M12.036 15.59c0 .55-.453.995-.997.995H5.032c-.55 0-.997-.445-.997-.996V8.584H1.03c-1.1 0-1.36-.633-.578-1.416L7.33.29c.39-.39 1.026-.385 1.412 0l6.878 6.88c.782.78.523 1.415-.58 1.415h-3.004v7.004z" fill-rule="evenodd"/>
+        </g>
+      </svg>
+    </div>
+  </transition>
+</template>
+
+<script>
+export default {
+  name: 'BackToTop',
+  props: {
+    visibilityHeight: {
+      type: Number,
+      default: 400
+    },
+    backPosition: {
+      type: Number,
+      default: 0
+    },
+    customStyle: {
+      type: Object,
+      default: function() {
+        return {
+          right: '50px',
+          bottom: '50px',
+          width: '40px',
+          height: '40px',
+          'border-radius': '4px',
+          'line-height': '45px',
+          background: '#e7eaf1'
+        }
+      }
+    },
+    transitionName: {
+      type: String,
+      default: 'fade'
+    }
+  },
+  data() {
+    return {
+      visible: false,
+      interval: null,
+      isMoving: false
+    }
+  },
+  mounted() {
+    window.addEventListener('scroll', this.handleScroll)
+  },
+  beforeDestroy() {
+    window.removeEventListener('scroll', this.handleScroll)
+    if (this.interval) {
+      clearInterval(this.interval)
+    }
+  },
+  methods: {
+    handleScroll() {
+      this.visible = window.pageYOffset > this.visibilityHeight
+    },
+    backToTop() {
+      if (this.isMoving) return
+      const start = window.pageYOffset
+      let i = 0
+      this.isMoving = true
+      this.interval = setInterval(() => {
+        const next = Math.floor(this.easeInOutQuad(10 * i, start, -start, 500))
+        if (next <= this.backPosition) {
+          window.scrollTo(0, this.backPosition)
+          clearInterval(this.interval)
+          this.isMoving = false
+        } else {
+          window.scrollTo(0, next)
+        }
+        i++
+      }, 16.7)
+    },
+    easeInOutQuad(t, b, c, d) {
+      if ((t /= d / 2) < 1) return c / 2 * t * t + b
+      return -c / 2 * (--t * (t - 2) - 1) + b
+    }
+  }
+}
+</script>
+
+<style scoped>
+  .back-to-ceiling {
+    position: fixed;
+    display: inline-block;
+    text-align: center;
+    cursor: pointer;
+  }
+
+  .back-to-ceiling:hover {
+    background: #d5dbe7;
+  }
+
+  .fade-enter-active,
+  .fade-leave-active {
+    transition: opacity .5s;
+  }
+
+  .fade-enter,
+  .fade-leave-to {
+    opacity: 0
+  }
+
+  .back-to-ceiling .Icon {
+    fill: #9aaabf;
+    background: none;
+  }
+</style>

+ 63 - 0
unimall-admin/src/components/Breadcrumb/index.vue

@@ -0,0 +1,63 @@
+<template>
+  <el-breadcrumb class="app-breadcrumb" separator="/">
+    <transition-group name="breadcrumb">
+      <el-breadcrumb-item v-for="(item,index) in levelList" v-if="item.meta.title" :key="item.path">
+        <span v-if="item.redirect==='noredirect'||index==levelList.length-1" class="no-redirect">{{ generateTitle(item.meta.title) }}</span>
+        <router-link v-else :to="item.redirect||item.path">{{ generateTitle(item.meta.title) }}</router-link>
+      </el-breadcrumb-item>
+    </transition-group>
+  </el-breadcrumb>
+</template>
+
+<script>
+import { generateTitle } from '@/utils/i18n'
+import pathToRegexp from 'path-to-regexp'
+
+export default {
+  data() {
+    return {
+      levelList: null
+    }
+  },
+  watch: {
+    $route() {
+      this.getBreadcrumb()
+    }
+  },
+  created() {
+    this.getBreadcrumb()
+  },
+  methods: {
+    generateTitle,
+    getBreadcrumb() {
+      const { params } = this.$route
+      let matched = this.$route.matched.filter(item => {
+        if (item.name) {
+          // To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
+          var toPath = pathToRegexp.compile(item.path)
+          item.path = toPath(params)
+          return true
+        }
+      })
+      const first = matched[0]
+      if (first && first.name.trim().toLocaleLowerCase() !== 'Dashboard'.toLocaleLowerCase()) {
+        matched = [{ path: '/dashboard', meta: { title: 'dashboard' }}].concat(matched)
+      }
+      this.levelList = matched
+    }
+  }
+}
+</script>
+
+<style rel="stylesheet/scss" lang="scss" scoped>
+  .app-breadcrumb.el-breadcrumb {
+    display: inline-block;
+    font-size: 14px;
+    line-height: 50px;
+    margin-left: 10px;
+    .no-redirect {
+      color: #97a8be;
+      cursor: text;
+    }
+  }
+</style>

+ 59 - 0
unimall-admin/src/components/Hamburger/index.vue

@@ -0,0 +1,59 @@
+<template>
+  <div>
+    <svg
+      :class="{'is-active':isActive}"
+      t="1492500959545"
+      class="hamburger"
+      style=""
+      viewBox="0 0 1024 1024"
+      version="1.1"
+      xmlns="http://www.w3.org/2000/svg"
+      p-id="1691"
+      xmlns:xlink="http://www.w3.org/1999/xlink"
+      width="64"
+      height="64"
+      @click="toggleClick">
+      <path
+        d="M966.8023 568.849776 57.196677 568.849776c-31.397081 0-56.850799-25.452695-56.850799-56.850799l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 543.397081 998.200404 568.849776 966.8023 568.849776z"
+        p-id="1692"/>
+      <path
+        d="M966.8023 881.527125 57.196677 881.527125c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 856.07443 998.200404 881.527125 966.8023 881.527125z"
+        p-id="1693"/>
+      <path
+        d="M966.8023 256.17345 57.196677 256.17345c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.850799 56.850799-56.850799l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.850799l0 0C1023.653099 230.720755 998.200404 256.17345 966.8023 256.17345z"
+        p-id="1694"/>
+    </svg>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'Hamburger',
+  props: {
+    isActive: {
+      type: Boolean,
+      default: false
+    },
+    toggleClick: {
+      type: Function,
+      default: null
+    }
+  }
+}
+</script>
+
+<style scoped>
+.hamburger {
+  display: inline-block;
+  cursor: pointer;
+  width: 20px;
+  height: 20px;
+  transform: rotate(90deg);
+  transition: .38s;
+  transform-origin: 50% 50%;
+}
+
+.hamburger.is-active {
+  transform: rotate(0deg);
+}
+</style>

+ 40 - 0
unimall-admin/src/components/LangSelect/index.vue

@@ -0,0 +1,40 @@
+<template>
+  <el-dropdown trigger="click" class="international" @command="handleSetLanguage">
+    <div>
+      <svg-icon class-name="international-icon" icon-class="language" />
+    </div>
+    <el-dropdown-menu slot="dropdown">
+      <el-dropdown-item :disabled="language==='zh'" command="zh">中文</el-dropdown-item>
+      <el-dropdown-item :disabled="language==='en'" command="en">English</el-dropdown-item>
+    </el-dropdown-menu>
+  </el-dropdown>
+</template>
+
+<script>
+export default {
+  computed: {
+    language() {
+      return this.$store.getters.language
+    }
+  },
+  methods: {
+    handleSetLanguage(lang) {
+      this.$i18n.locale = lang
+      this.$store.dispatch('setLanguage', lang)
+      this.$message({
+        message: 'Switch Language Success',
+        type: 'success'
+      })
+    }
+  }
+}
+</script>
+
+<style scoped>
+.international-icon {
+  font-size: 20px;
+  cursor: pointer;
+  vertical-align: -5px!important;
+}
+</style>
+

+ 102 - 0
unimall-admin/src/components/Pagination/index.vue

@@ -0,0 +1,102 @@
+<template>
+  <div :class="{'hidden':hidden}" class="pagination-container">
+    <el-pagination
+      :background="background"
+      :current-page.sync="currentPage"
+      :page-size.sync="pageSize"
+      :layout="layout"
+      :total="total"
+      v-bind="$attrs"
+      @size-change="handleSizeChange"
+      @current-change="handleCurrentChange"/>
+  </div>
+</template>
+
+<script>
+import { scrollTo } from '@/utils/scrollTo'
+
+export default {
+  name: 'Pagination',
+  props: {
+    total: {
+      required: true,
+      type: Number
+    },
+    page: {
+      type: Number,
+      default: 1
+    },
+    limit: {
+      type: Number,
+      default: 20
+    },
+    pageSizes: {
+      type: Array,
+      default() {
+        return [10, 20, 30, 50]
+      }
+    },
+    layout: {
+      type: String,
+      default: 'total, sizes, prev, pager, next, jumper'
+    },
+    background: {
+      type: Boolean,
+      default: true
+    },
+    autoScroll: {
+      type: Boolean,
+      default: true
+    },
+    hidden: {
+      type: Boolean,
+      default: false
+    }
+  },
+  computed: {
+    currentPage: {
+      get() {
+        return this.page
+      },
+      set(val) {
+        this.$emit('update:page', val)
+      }
+    },
+    pageSize: {
+      get() {
+        return this.limit
+      },
+      set(val) {
+        this.$emit('update:limit', val)
+      }
+    }
+  },
+  methods: {
+    handleSizeChange(val) {
+      this.$emit('pagination', { page: this.currentPage, limit: val })
+      if (this.autoScroll) {
+        scrollTo(0, 800)
+      }
+    },
+    handleCurrentChange(val) {
+      this.$emit('pagination', { page: val, limit: this.pageSize })
+      if (this.autoScroll) {
+        scrollTo(0, 800)
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+.pagination-container {
+  background: #fff;
+  padding: 32px 16px;
+}
+.pagination-container.hidden {
+  display: none;
+}
+.pagination-container {
+    text-align: right;
+}
+</style>

+ 78 - 0
unimall-admin/src/components/Screenfull/index.vue

@@ -0,0 +1,78 @@
+<template>
+  <div>
+    <svg
+      t="1508738709248"
+      class="screenfull-svg"
+      viewBox="0 0 1024 1024"
+      version="1.1"
+      xmlns="http://www.w3.org/2000/svg"
+      p-id="2069"
+      xmlns:xlink="http://www.w3.org/1999/xlink"
+      width="32"
+      height="32"
+      @click="click">
+      <path
+        d="M333.493443 428.647617 428.322206 333.832158 262.572184 168.045297 366.707916 64.444754 64.09683 64.444754 63.853283 366.570793 167.283957 262.460644Z"
+        p-id="2070"/>
+      <path
+        d="M854.845439 760.133334 688.61037 593.95864 593.805144 688.764889 759.554142 854.56096 655.44604 958.161503 958.055079 958.161503 958.274066 656.035464Z"
+        p-id="2071"/>
+      <path
+        d="M688.535669 428.550403 854.31025 262.801405 957.935352 366.921787 957.935352 64.34754 655.809313 64.081481 759.919463 167.535691 593.70793 333.731874Z"
+        p-id="2072"/>
+      <path
+        d="M333.590658 594.033341 167.8171 759.804852 64.218604 655.67219 64.218604 958.270996 366.342596 958.502263 262.234493 855.071589 428.421466 688.86108Z"
+        p-id="2073"/>
+    </svg>
+  </div>
+</template>
+
+<script>
+import screenfull from 'screenfull'
+
+export default {
+  name: 'Screenfull',
+  props: {
+    width: {
+      type: Number,
+      default: 22
+    },
+    height: {
+      type: Number,
+      default: 22
+    },
+    fill: {
+      type: String,
+      default: '#48576a'
+    }
+  },
+  data() {
+    return {
+      isFullscreen: false
+    }
+  },
+  methods: {
+    click() {
+      if (!screenfull.enabled) {
+        this.$message({
+          message: 'you browser can not work',
+          type: 'warning'
+        })
+        return false
+      }
+      screenfull.toggle()
+    }
+  }
+}
+</script>
+
+<style scoped>
+.screenfull-svg {
+  display: inline-block;
+  cursor: pointer;
+  fill: #5a5e66;;
+  width: 20px;
+  height: 20px;
+  vertical-align: 10px;
+}
+</style>

+ 92 - 0
unimall-admin/src/components/ScrollPane/index.vue

@@ -0,0 +1,92 @@
+<template>
+  <el-scrollbar ref="scrollContainer" :vertical="false" class="scroll-container" @wheel.native.prevent="handleScroll">
+    <slot/>
+  </el-scrollbar>
+</template>
+
+<script>
+const tagAndTagSpacing = 4 // tagAndTagSpacing
+
+export default {
+  name: 'ScrollPane',
+  data() {
+    return {
+      left: 0
+    }
+  },
+  methods: {
+    handleScroll(e) {
+      const eventDelta = e.wheelDelta || -e.deltaY * 40
+      const $scrollWrapper = this.$refs.scrollContainer.$refs.wrap
+      $scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4
+    },
+    moveToTarget(currentTag) {
+      const $container = this.$refs.scrollContainer.$el
+      const $containerWidth = $container.offsetWidth
+      const $scrollWrapper = this.$refs.scrollContainer.$refs.wrap
+      const tagList = this.$parent.$refs.tag
+
+      let firstTag = null
+      let lastTag = null
+      let prevTag = null
+      let nextTag = null
+
+      // find first tag and last tag
+      if (tagList.length > 0) {
+        firstTag = tagList[0]
+        lastTag = tagList[tagList.length - 1]
+      }
+
+      // find preTag and nextTag
+      for (let i = 0; i < tagList.length; i++) {
+        if (tagList[i] === currentTag) {
+          if (i === 0) {
+            nextTag = tagList[i].length > 1 && tagList[i + 1]
+          } else if (i === tagList.length - 1) {
+            prevTag = tagList[i].length > 1 && tagList[i - 1]
+          } else {
+            prevTag = tagList[i - 1]
+            nextTag = tagList[i + 1]
+          }
+          break
+        }
+      }
+
+      if (firstTag === currentTag) {
+        $scrollWrapper.scrollLeft = 0
+      } else if (lastTag === currentTag) {
+        $scrollWrapper.scrollLeft = $scrollWrapper.scrollWidth - $containerWidth
+      } else {
+        // the tag's offsetLeft after of nextTag
+        const afterNextTagOffsetLeft = nextTag.$el.offsetLeft + nextTag.$el.offsetWidth + tagAndTagSpacing
+
+        // the tag's offsetLeft before of prevTag
+        const beforePrevTagOffsetLeft = prevTag.$el.offsetLeft - tagAndTagSpacing
+
+        if (afterNextTagOffsetLeft > $scrollWrapper.scrollLeft + $containerWidth) {
+          $scrollWrapper.scrollLeft = afterNextTagOffsetLeft - $containerWidth
+        } else if (beforePrevTagOffsetLeft < $scrollWrapper.scrollLeft) {
+          $scrollWrapper.scrollLeft = beforePrevTagOffsetLeft
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style rel="stylesheet/scss" lang="scss" scoped>
+.scroll-container {
+  white-space: nowrap;
+  position: relative;
+  overflow: hidden;
+  width: 100%;
+  /deep/ {
+    .el-scrollbar__bar {
+      bottom: 0px;
+    }
+    .el-scrollbar__wrap {
+      height: 49px;
+    }
+  }
+}
+</style>

+ 55 - 0
unimall-admin/src/components/SizeSelect/index.vue

@@ -0,0 +1,55 @@
+<template>
+  <el-dropdown trigger="click" @command="handleSetSize">
+    <div>
+      <svg-icon class-name="size-icon" icon-class="size" />
+    </div>
+    <el-dropdown-menu slot="dropdown">
+      <el-dropdown-item :disabled="size==='medium'" command="medium">Medium</el-dropdown-item>
+      <el-dropdown-item :disabled="size==='small'" command="small">Small</el-dropdown-item>
+      <el-dropdown-item :disabled="size==='mini'" command="mini">Mini</el-dropdown-item>
+    </el-dropdown-menu>
+  </el-dropdown>
+</template>
+
+<script>
+export default {
+  computed: {
+    size() {
+      return this.$store.getters.size
+    }
+  },
+  methods: {
+    handleSetSize(size) {
+      this.$ELEMENT.size = size
+      this.$store.dispatch('setSize', size)
+      this.refreshView()
+      this.$message({
+        message: 'Switch Size Success',
+        type: 'success'
+      })
+    },
+    refreshView() {
+      // In order to make the cached page re-rendered
+      this.$store.dispatch('delAllCachedViews', this.$route)
+
+      const { fullPath } = this.$route
+
+      this.$nextTick(() => {
+        this.$router.replace({
+          path: '/redirect' + fullPath
+        })
+      })
+    }
+  }
+
+}
+</script>
+
+<style scoped>
+.size-icon {
+  font-size: 20px;
+  cursor: pointer;
+  vertical-align: -4px!important;
+}
+</style>
+

+ 43 - 0
unimall-admin/src/components/SvgIcon/index.vue

@@ -0,0 +1,43 @@
+<template>
+  <svg :class="svgClass" aria-hidden="true">
+    <use :xlink:href="iconName"/>
+  </svg>
+</template>
+
+<script>
+export default {
+  name: 'SvgIcon',
+  props: {
+    iconClass: {
+      type: String,
+      required: true
+    },
+    className: {
+      type: String,
+      default: ''
+    }
+  },
+  computed: {
+    iconName() {
+      return `#icon-${this.iconClass}`
+    },
+    svgClass() {
+      if (this.className) {
+        return 'svg-icon ' + this.className
+      } else {
+        return 'svg-icon'
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+.svg-icon {
+  width: 1em;
+  height: 1em;
+  vertical-align: -0.15em;
+  fill: currentColor;
+  overflow: hidden;
+}
+</style>

+ 144 - 0
unimall-admin/src/components/ThemePicker/index.vue

@@ -0,0 +1,144 @@
+<template>
+  <el-color-picker
+    v-model="theme"
+    class="theme-picker"
+    popper-class="theme-picker-dropdown"/>
+</template>
+
+<script>
+
+const version = require('element-ui/package.json').version // element-ui version from node_modules
+const ORIGINAL_THEME = '#409EFF' // default color
+
+export default {
+  data() {
+    return {
+      chalk: '', // content of theme-chalk css
+      theme: ORIGINAL_THEME
+    }
+  },
+  watch: {
+    theme(val, oldVal) {
+      if (typeof val !== 'string') return
+      const themeCluster = this.getThemeCluster(val.replace('#', ''))
+      const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
+      console.log(themeCluster, originalCluster)
+      const getHandler = (variable, id) => {
+        return () => {
+          const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', ''))
+          const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster)
+
+          let styleTag = document.getElementById(id)
+          if (!styleTag) {
+            styleTag = document.createElement('style')
+            styleTag.setAttribute('id', id)
+            document.head.appendChild(styleTag)
+          }
+          styleTag.innerText = newStyle
+        }
+      }
+
+      const chalkHandler = getHandler('chalk', 'chalk-style')
+
+      if (!this.chalk) {
+        const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`
+        this.getCSSString(url, chalkHandler, 'chalk')
+      } else {
+        chalkHandler()
+      }
+
+      const styles = [].slice.call(document.querySelectorAll('style'))
+        .filter(style => {
+          const text = style.innerText
+          return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text)
+        })
+      styles.forEach(style => {
+        const { innerText } = style
+        if (typeof innerText !== 'string') return
+        style.innerText = this.updateStyle(innerText, originalCluster, themeCluster)
+      })
+      this.$message({
+        message: '换肤成功',
+        type: 'success'
+      })
+    }
+  },
+
+  methods: {
+    updateStyle(style, oldCluster, newCluster) {
+      let newStyle = style
+      oldCluster.forEach((color, index) => {
+        newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
+      })
+      return newStyle
+    },
+
+    getCSSString(url, callback, variable) {
+      const xhr = new XMLHttpRequest()
+      xhr.onreadystatechange = () => {
+        if (xhr.readyState === 4 && xhr.status === 200) {
+          this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '')
+          callback()
+        }
+      }
+      xhr.open('GET', url)
+      xhr.send()
+    },
+
+    getThemeCluster(theme) {
+      const tintColor = (color, tint) => {
+        let red = parseInt(color.slice(0, 2), 16)
+        let green = parseInt(color.slice(2, 4), 16)
+        let blue = parseInt(color.slice(4, 6), 16)
+
+        if (tint === 0) { // when primary color is in its rgb space
+          return [red, green, blue].join(',')
+        } else {
+          red += Math.round(tint * (255 - red))
+          green += Math.round(tint * (255 - green))
+          blue += Math.round(tint * (255 - blue))
+
+          red = red.toString(16)
+          green = green.toString(16)
+          blue = blue.toString(16)
+
+          return `#${red}${green}${blue}`
+        }
+      }
+
+      const shadeColor = (color, shade) => {
+        let red = parseInt(color.slice(0, 2), 16)
+        let green = parseInt(color.slice(2, 4), 16)
+        let blue = parseInt(color.slice(4, 6), 16)
+
+        red = Math.round((1 - shade) * red)
+        green = Math.round((1 - shade) * green)
+        blue = Math.round((1 - shade) * blue)
+
+        red = red.toString(16)
+        green = green.toString(16)
+        blue = blue.toString(16)
+
+        return `#${red}${green}${blue}`
+      }
+
+      const clusters = [theme]
+      for (let i = 0; i <= 9; i++) {
+        clusters.push(tintColor(theme, Number((i / 10).toFixed(2))))
+      }
+      clusters.push(shadeColor(theme, 0.1))
+      return clusters
+    }
+  }
+}
+</script>
+
+<style>
+.theme-picker .el-color-picker__trigger {
+  vertical-align: middle;
+}
+
+.theme-picker-dropdown .el-color-dropdown__link-btn {
+  display: none;
+}
+</style>

+ 49 - 0
unimall-admin/src/directive/clipboard/clipboard.js

@@ -0,0 +1,49 @@
+// Inspired by https://github.com/Inndy/vue-clipboard2
+const Clipboard = require('clipboard')
+if (!Clipboard) {
+  throw new Error('you should npm install `clipboard` --save at first ')
+}
+
+export default {
+  bind(el, binding) {
+    if (binding.arg === 'success') {
+      el._v_clipboard_success = binding.value
+    } else if (binding.arg === 'error') {
+      el._v_clipboard_error = binding.value
+    } else {
+      const clipboard = new Clipboard(el, {
+        text() { return binding.value },
+        action() { return binding.arg === 'cut' ? 'cut' : 'copy' }
+      })
+      clipboard.on('success', e => {
+        const callback = el._v_clipboard_success
+        callback && callback(e) // eslint-disable-line
+      })
+      clipboard.on('error', e => {
+        const callback = el._v_clipboard_error
+        callback && callback(e) // eslint-disable-line
+      })
+      el._v_clipboard = clipboard
+    }
+  },
+  update(el, binding) {
+    if (binding.arg === 'success') {
+      el._v_clipboard_success = binding.value
+    } else if (binding.arg === 'error') {
+      el._v_clipboard_error = binding.value
+    } else {
+      el._v_clipboard.text = function() { return binding.value }
+      el._v_clipboard.action = function() { return binding.arg === 'cut' ? 'cut' : 'copy' }
+    }
+  },
+  unbind(el, binding) {
+    if (binding.arg === 'success') {
+      delete el._v_clipboard_success
+    } else if (binding.arg === 'error') {
+      delete el._v_clipboard_error
+    } else {
+      el._v_clipboard.destroy()
+      delete el._v_clipboard
+    }
+  }
+}

+ 13 - 0
unimall-admin/src/directive/clipboard/index.js

@@ -0,0 +1,13 @@
+import Clipboard from './clipboard'
+
+const install = function(Vue) {
+  Vue.directive('Clipboard', Clipboard)
+}
+
+if (window.Vue) {
+  window.clipboard = Clipboard
+  Vue.use(install); // eslint-disable-line
+}
+
+Clipboard.install = install
+export default Clipboard

+ 13 - 0
unimall-admin/src/directive/permission/index.js

@@ -0,0 +1,13 @@
+import permission from './permission'
+
+const install = function(Vue) {
+  Vue.directive('permission', permission)
+}
+
+if (window.Vue) {
+  window['permission'] = permission
+  Vue.use(install); // eslint-disable-line
+}
+
+permission.install = install
+export default permission

+ 29 - 0
unimall-admin/src/directive/permission/permission.js

@@ -0,0 +1,29 @@
+
+import store from '@/store'
+
+export default{
+  inserted(el, binding, vnode) {
+    const { value } = binding
+    const perms = store.getters && store.getters.perms
+
+    if (value && value instanceof Array && value.length > 0) {
+      const permissions = value
+
+      var hasPermission = false
+
+      if (perms.indexOf('*') >= 0) {
+        hasPermission = true
+      } else {
+        hasPermission = perms.some(perm => {
+          return permissions.includes(perm)
+        })
+      }
+
+      if (!hasPermission) {
+        el.parentNode && el.parentNode.removeChild(el)
+      }
+    } else {
+      throw new Error(`need perms! Like v-permission="['GET /aaa','POST /bbb']"`)
+    }
+  }
+}

+ 68 - 0
unimall-admin/src/filters/index.js

@@ -0,0 +1,68 @@
+// set function parseTime,formatTime to filter
+export { parseTime, formatTime, formatGmt } from '@/utils'
+
+function pluralize(time, label) {
+  if (time === 1) {
+    return time + label
+  }
+  return time + label + 's'
+}
+
+export function timeAgo(time) {
+  const between = Date.now() / 1000 - Number(time)
+  if (between < 3600) {
+    return pluralize(~~(between / 60), ' minute')
+  } else if (between < 86400) {
+    return pluralize(~~(between / 3600), ' hour')
+  } else {
+    return pluralize(~~(between / 86400), ' day')
+  }
+}
+
+/* 数字 格式化*/
+export function numberFormatter(num, digits) {
+  const si = [
+    { value: 1E18, symbol: 'E' },
+    { value: 1E15, symbol: 'P' },
+    { value: 1E12, symbol: 'T' },
+    { value: 1E9, symbol: 'G' },
+    { value: 1E6, symbol: 'M' },
+    { value: 1E3, symbol: 'k' }
+  ]
+  for (let i = 0; i < si.length; i++) {
+    if (num >= si[i].value) {
+      return (num / si[i].value + 0.1).toFixed(digits).replace(/\.0+$|(\.[0-9]*[1-9])0+$/, '$1') + si[i].symbol
+    }
+  }
+  return num.toString()
+}
+
+export function toThousandFilter(num) {
+  return (+num || 0).toString().replace(/^-?\d+/g, m => m.replace(/(?=(?!\b)(\d{3})+$)/g, ','))
+}
+
+export function formatDate(time) {
+  if (time != null && time !== '') {
+    var date = new Date(time)
+    var year = date.getFullYear()
+    var month = date.getMonth() + 1
+    var day = date.getDate()
+    return year + '-' + month + '-' + day
+  } else {
+    return ''
+  }
+}
+export function formatDateAndTime(time) {
+  if (time != null || time !== '') {
+    var date = new Date(time)
+    var year = date.getFullYear()
+    var month = date.getMonth() + 1
+    var day = date.getDate()
+    var hour = date.getHours()
+    var minute = date.getMinutes()
+    var second = date.getSeconds()
+    return year + '-' + month + '-' + day + '\n' + hour + ':' + minute + ':' + second
+  } else {
+    return ''
+  }
+}

+ 9 - 0
unimall-admin/src/icons/index.js

@@ -0,0 +1,9 @@
+import Vue from 'vue'
+import SvgIcon from '@/components/SvgIcon'// svg组件
+
+// register globally
+Vue.component('svg-icon', SvgIcon)
+
+const req = require.context('./svg', false, /\.svg$/)
+const requireAll = requireContext => requireContext.keys().map(requireContext)
+requireAll(req)

+ 1 - 0
unimall-admin/src/icons/svg/404.svg

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M121.718 73.272v9.953c3.957-7.584 6.199-16.05 6.199-24.995C127.917 26.079 99.273 0 63.958 0 28.644 0 0 26.079 0 58.23c0 .403.028.806.028 1.21l22.97-25.953h13.34l-19.76 27.187h6.42V53.77l13.728-19.477v49.361H22.998V73.272H2.158c5.951 20.284 23.608 36.208 45.998 41.399-1.44 3.3-5.618 11.263-12.565 12.674-8.607 1.764 23.358.428 46.163-13.178 17.519-4.611 31.938-15.849 39.77-30.513h-13.506V73.272H85.02V59.464l22.998-25.977h13.008l-19.429 27.187h6.421v-7.433l13.727-19.402v39.433h-.027zm-78.24 2.822a10.516 10.516 0 0 1-.996-4.535V44.548c0-1.613.332-3.124.996-4.535a11.66 11.66 0 0 1 2.713-3.68c1.134-1.032 2.49-1.864 4.04-2.468 1.55-.605 3.21-.908 4.982-.908h11.292c1.77 0 3.431.303 4.981.908 1.522.604 2.85 1.41 3.986 2.418l-12.26 16.303v-2.898a1.96 1.96 0 0 0-.665-1.512c-.443-.403-.996-.604-1.66-.604-.665 0-1.218.201-1.661.604a1.96 1.96 0 0 0-.664 1.512v9.071L44.364 77.606a10.556 10.556 0 0 1-.886-1.512zm35.73-4.535c0 1.613-.332 3.124-.997 4.535a11.66 11.66 0 0 1-2.712 3.68c-1.134 1.032-2.49 1.864-4.04 2.469-1.55.604-3.21.907-4.982.907H55.185c-1.77 0-3.431-.303-4.981-.907-1.55-.605-2.906-1.437-4.041-2.47a12.49 12.49 0 0 1-1.384-1.512l13.727-18.217v6.375c0 .605.222 1.109.665 1.512.442.403.996.604 1.66.604.664 0 1.218-.201 1.66-.604a1.96 1.96 0 0 0 .665-1.512V53.87L75.97 36.838c.913.932 1.66 1.99 2.214 3.175.664 1.41.996 2.922.996 4.535v27.011h.028z"/></svg>

Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
unimall-admin/src/icons/svg/admin.svg


+ 1 - 0
unimall-admin/src/icons/svg/api.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1576683781815" class="icon" viewBox="0 0 1170 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8054" xmlns:xlink="http://www.w3.org/1999/xlink" width="36.5625" height="32"><defs><style type="text/css"></style></defs><path d="M1042.285714 1024H128c-71.314286 0-128-56.685714-128-128V128c0-71.314286 56.685714-128 128-128h914.285714c71.314286 0 128 56.685714 128 128v768c0 71.314286-56.685714 128-128 128zM128 73.142857C96.914286 73.142857 73.142857 96.914286 73.142857 128v768c0 31.085714 23.771429 54.857143 54.857143 54.857143h914.285714c31.085714 0 54.857143-23.771429 54.857143-54.857143V128c0-31.085714-23.771429-54.857143-54.857143-54.857143H128z" fill="" p-id="8055"></path><path d="M18.285714 201.142857h1115.428572v73.142857H18.285714z" fill="" p-id="8056"></path><path d="M362.057143 405.942857L522.971429 822.857143h-67.657143l-38.4-107.885714H237.714286L195.657143 822.857143H128l160.914286-416.914286h73.142857z m32.914286 256l-69.485715-188.342857h-1.828571l-69.485714 188.342857h140.8zM736.914286 405.942857c98.742857 0 149.942857 42.057143 149.942857 126.171429 0 85.942857-51.2 128-149.942857 128h-107.885715V822.857143h-64V405.942857h171.885715z m-109.714286 199.314286H731.428571c31.085714 0 54.857143-5.485714 69.485715-18.285714 14.628571-10.971429 21.942857-31.085714 21.942857-56.685715 0-25.6-7.314286-43.885714-21.942857-54.857143-14.628571-10.971429-36.571429-18.285714-67.657143-18.285714h-104.228572v148.114286zM1009.371429 405.942857V822.857143h-64V405.942857h64z" fill="" p-id="8057"></path></svg>

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.