Browse Source

Merge branch 'dev' of ssh://10.10.100.21/source/smartschool-platform into dev

# Conflicts:
#	applications/device/device-client/src/main/resources/application.yml
guq 7 years ago
parent
commit
bd49dcdde9
42 changed files with 1299 additions and 46 deletions
  1. 10 0
      applications/device/device-client/pom.xml
  2. 4 6
      applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/DeviceClientApplication.java
  3. 51 0
      applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/config/GlobalExceptionHandler.java
  4. 91 0
      applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/config/RestTemplateConfig.java
  5. 1 0
      applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/config/WebMvcConfig.java
  6. 6 0
      applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/controller/AccessControlController.java
  7. 44 0
      applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/controller/IcCardController.java
  8. 41 0
      applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/controller/SchoolController.java
  9. 5 1
      applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/init/AccessControlInitializer.java
  10. 4 0
      applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/jdbc/DynamicDataSourceRegister.java
  11. 132 0
      applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/po/AccTransDetail.java
  12. 174 0
      applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/po/MessageInfo.java
  13. 49 0
      applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/po/Transaction.java
  14. 1 1
      applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/repository/SchoolRepository.java
  15. 21 11
      applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/service/AccessControlService.java
  16. 127 7
      applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/service/IcCardService.java
  17. 51 0
      applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/utils/HmacUtils.java
  18. 3 0
      applications/device/device-client/src/main/resources/application.yml
  19. 25 0
      applications/device/device-client/src/main/resources/static/css/iconfont.css
  20. BIN
      applications/device/device-client/src/main/resources/static/css/iconfont.eot
  21. 32 0
      applications/device/device-client/src/main/resources/static/css/iconfont.svg
  22. BIN
      applications/device/device-client/src/main/resources/static/css/iconfont.ttf
  23. BIN
      applications/device/device-client/src/main/resources/static/css/iconfont.woff
  24. 41 1
      applications/device/device-client/src/main/resources/static/iccard.html
  25. 18 3
      applications/device/device-client/src/main/resources/static/index.html
  26. 47 0
      applications/device/device-client/src/main/resources/static/js/iccard.js
  27. 0 0
      applications/device/device-client/src/main/resources/static/js/iconfont.js
  28. 36 11
      applications/device/device-client/src/main/resources/static/js/index.js
  29. 42 0
      applications/device/device-client/src/main/resources/static/js/school.js
  30. 44 0
      applications/device/device-client/src/main/resources/static/school.html
  31. 20 0
      applications/device/device-core/src/main/java/com/usoftchina/smartschool/device/base/Result.java
  32. 40 0
      applications/device/device-core/src/main/java/com/usoftchina/smartschool/device/crypto/Hex.java
  33. 96 0
      applications/device/device-core/src/main/java/com/usoftchina/smartschool/device/crypto/HmacEncoder.java
  34. 9 0
      applications/device/device-core/src/main/java/com/usoftchina/smartschool/device/crypto/HmacSHA256Encoder.java
  35. 5 0
      applications/school/school-server/src/main/java/com/usoftchina/smartschool/school/basic/controller/ClassController.java
  36. 2 0
      applications/school/school-server/src/main/java/com/usoftchina/smartschool/school/basic/service/ClassService.java
  37. 12 1
      applications/school/school-server/src/main/java/com/usoftchina/smartschool/school/basic/service/impl/ClassServiceImpl.java
  38. 5 0
      applications/school/school-server/src/main/java/com/usoftchina/smartschool/school/basic/service/impl/TeacherServiceImpl.java
  39. 2 0
      applications/school/school-server/src/main/java/com/usoftchina/smartschool/school/mapper/SysTeacherMapper.java
  40. 3 3
      applications/school/school-server/src/main/resources/mapper/CurriculumMapper.xml
  41. 1 1
      applications/school/school-server/src/main/resources/mapper/SysStudentMapper.xml
  42. 4 0
      applications/school/school-server/src/main/resources/mapper/SysTeacherMapper.xml

+ 10 - 0
applications/device/device-client/pom.xml

@@ -37,6 +37,16 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-jdbc</artifactId>
         </dependency>
+        <!-- JSON -->
+        <dependency>
+          <groupId>com.alibaba</groupId>
+          <artifactId>fastjson</artifactId>
+        </dependency>
+        <!-- httpClient -->
+        <dependency>
+          <groupId>org.apache.httpcomponents</groupId>
+          <artifactId>httpclient</artifactId>
+        </dependency>
     </dependencies>
 
 </project>

+ 4 - 6
applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/DeviceClientApplication.java

@@ -4,9 +4,10 @@ import com.usoftchina.smartschool.device.client.config.DeviceServerProperties;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.Bean;
 import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
 import org.springframework.web.client.RestTemplate;
+import org.springframework.scheduling.annotation.EnableScheduling;
 
 /**
  * @author yingp
@@ -14,14 +15,11 @@ import org.springframework.web.client.RestTemplate;
  */
 @SpringBootApplication
 @EnableAsync
+@EnableTransactionManagement
 @EnableConfigurationProperties(DeviceServerProperties.class)
+@EnableScheduling
 public class DeviceClientApplication {
     public static void main(String[] args) {
         SpringApplication.run(DeviceClientApplication.class, args);
     }
-
-    @Bean
-    public RestTemplate restTemplate() {
-        return new RestTemplate();
-    }
 }

+ 51 - 0
applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/config/GlobalExceptionHandler.java

@@ -0,0 +1,51 @@
+package com.usoftchina.smartschool.device.client.config;
+
+import com.usoftchina.smartschool.device.base.Result;
+import com.usoftchina.smartschool.device.exception.BizException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * @author yingp
+ * @date 2018/10/16
+ */
+@ControllerAdvice
+public class GlobalExceptionHandler {
+
+    private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
+
+    /**
+     * 默认异常处理
+     *
+     * @param request
+     * @param e
+     * @return
+     * @throws Exception
+     */
+    @ExceptionHandler(value = Exception.class)
+    @ResponseBody
+    public Result defaultHandler(HttpServletRequest request, Exception e) throws Exception{
+        logger.error(request.getRequestURI(), e);
+        return Result.throwable(e);
+    }
+
+    /**
+     * 业务异常
+     *
+     * @param request
+     * @param e
+     * @return
+     * @throws Exception
+     */
+    @ExceptionHandler(value = BizException.class)
+    @ResponseBody
+    public Result bizHandler(HttpServletRequest request, BizException e) throws Exception{
+        logger.error(request.getRequestURI(), e);
+        return Result.error(e);
+    }
+}

+ 91 - 0
applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/config/RestTemplateConfig.java

@@ -0,0 +1,91 @@
+package com.usoftchina.smartschool.device.client.config;
+
+import org.apache.http.client.HttpClient;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.apache.http.ssl.TrustStrategy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.StringHttpMessageConverter;
+import org.springframework.web.client.RestTemplate;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+import java.nio.charset.Charset;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+/**
+ * @Author chenwei
+ * @Date 2019/03/07
+ */
+@Configuration
+public class RestTemplateConfig {
+
+    private static final Logger logger = LoggerFactory.getLogger(RestTemplateConfig.class);
+
+    @Bean
+    public RestTemplate restTemplate(){
+        RestTemplate restTemplate = new RestTemplate();
+        List<HttpMessageConverter<?>> converterList = restTemplate.getMessageConverters();
+        converterList.add(0, responseBodyConverter());
+        restTemplate.setRequestFactory(httpRequestFactory());
+        return restTemplate;
+    }
+
+    @Bean
+    public HttpMessageConverter<String> responseBodyConverter() {
+        StringHttpMessageConverter converter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
+        return converter;
+    }
+
+    @Bean
+    public HttpComponentsClientHttpRequestFactory httpRequestFactory(){
+        try {
+            HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
+            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
+                public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
+                    return true;
+                }
+            }).build();
+            httpClientBuilder.setSSLContext(sslContext);
+            HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
+            SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
+            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
+                    .register("http", PlainConnectionSocketFactory.getSocketFactory())
+                    .register("https", sslConnectionSocketFactory).build();// 注册http和https请求
+            // 开始设置连接池
+            PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
+            poolingHttpClientConnectionManager.setMaxTotal(500); // 最大连接数500
+            poolingHttpClientConnectionManager.setDefaultMaxPerRoute(100); // 同路由并发数100
+            httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);
+            httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3, true)); // 重试次数
+            HttpClient httpClient = httpClientBuilder.build();
+            HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); // httpClient连接配置
+            clientHttpRequestFactory.setConnectTimeout(20000);              // 连接超时
+            clientHttpRequestFactory.setReadTimeout(30000);                 // 数据读取超时时间
+            clientHttpRequestFactory.setConnectionRequestTimeout(20000);    // 连接不够用的等待时间
+            return clientHttpRequestFactory;
+        }catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e){
+            logger.info("初始化HTTP连接池出错, message={}", e);
+        }
+        return null;
+    }
+
+}

+ 1 - 0
applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/config/WebMvcConfig.java

@@ -17,5 +17,6 @@ public class WebMvcConfig implements WebMvcConfigurer {
         registry.addViewController("/").setViewName("index.html");
         registry.addViewController("/login").setViewName("/login.html");
         registry.addViewController("/iccard").setViewName("/iccard.html");
+        registry.addViewController("/school").setViewName("/school.html");
     }
 }

+ 6 - 0
applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/controller/AccessControlController.java

@@ -40,4 +40,10 @@ public class AccessControlController {
         accessControlService.save(accessControl);
         return Result.success();
     }
+
+    @DeleteMapping("/{id}")
+    public Result delete(@PathVariable("id") String id) {
+        accessControlService.delete(id);
+        return Result.success();
+    }
 }

+ 44 - 0
applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/controller/IcCardController.java

@@ -0,0 +1,44 @@
+package com.usoftchina.smartschool.device.client.controller;
+
+import com.usoftchina.smartschool.device.base.Result;
+import com.usoftchina.smartschool.device.client.po.IcCard;
+import com.usoftchina.smartschool.device.client.service.IcCardService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author yingp
+ * @date 2019/3/11
+ */
+@RestController
+@RequestMapping("/api/iccard")
+public class IcCardController {
+
+    @Autowired
+    private IcCardService icCardService;
+
+    /**
+     * 查询消费卡配置
+     *
+     * @return
+     */
+    @GetMapping
+    public Result<IcCard> find() {
+        return Result.success(icCardService.find());
+    }
+
+    /**
+     * 保存消费卡配置
+     *
+     * @param icCard
+     * @return
+     */
+    @PostMapping
+    public Result save(IcCard icCard) {
+        icCardService.save(icCard);
+        return Result.success();
+    }
+}

+ 41 - 0
applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/controller/SchoolController.java

@@ -0,0 +1,41 @@
+package com.usoftchina.smartschool.device.client.controller;
+
+import com.usoftchina.smartschool.device.base.Result;
+import com.usoftchina.smartschool.device.client.po.School;
+import com.usoftchina.smartschool.device.client.service.SchoolService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * @author yingp
+ * @date 2019/3/11
+ */
+@RestController
+@RequestMapping("/api/school")
+public class SchoolController {
+
+    @Autowired
+    private SchoolService schoolService;
+
+    /**
+     * 查询学校信息
+     *
+     * @return
+     */
+    @GetMapping
+    public Result<School> find() {
+        return Result.success(schoolService.find());
+    }
+
+    /**
+     * 保存学校信息
+     *
+     * @param school
+     * @return
+     */
+    @PostMapping
+    public Result save(School school) {
+        schoolService.save(school);
+        return Result.success();
+    }
+}

+ 5 - 1
applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/init/AccessControlInitializer.java

@@ -35,7 +35,11 @@ public class AccessControlInitializer implements CommandLineRunner {
     public void run(String... args) throws Exception {
         List<AccessControl> accessControls = accessControlService.findAll();
         if (!CollectionUtils.isEmpty(accessControls)) {
-            accessControls.forEach(deviceApi::add);
+            try {
+                accessControls.forEach(deviceApi::add);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
         }
     }
 }

+ 4 - 0
applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/jdbc/DynamicDataSourceRegister.java

@@ -20,6 +20,10 @@ public class DynamicDataSourceRegister {
         this.dynamicDataSource = dynamicDataSource;
     }
 
+    public boolean contains(Connectable connectable) {
+        return dynamicDataSource.containsDataSource(connectable.qualifier());
+    }
+
     public void createDataSource(Connectable connectable) {
         if (!dynamicDataSource.containsDataSource(connectable.qualifier())) {
             logger.info("connectable:" + connectable);

+ 132 - 0
applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/po/AccTransDetail.java

@@ -0,0 +1,132 @@
+package com.usoftchina.smartschool.device.client.po;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @Description 交易记录
+ * @Author chenwei
+ * @Date 2019/03/07
+ */
+public class AccTransDetail implements Serializable {
+    /**
+     * 交易ID
+     */
+    private String guid;
+    /**
+     * 用户ID
+     */
+    private String empSysID;
+    /**
+     * 学号
+     */
+    private String empNo;
+    /**
+     * 姓名
+     */
+    private String empName;
+    /**
+     * 账户
+     */
+    private String accNo;
+    /**
+     * 交易类型
+     */
+    private String accTransType;
+    /**
+     * 交易日期
+     */
+    private Date accTransDay;
+    /**
+     * 收入
+     */
+    private Double iMoneyValue;
+    /**
+     * 支出
+     */
+    private Double oMoneyValue;
+    /**
+     * 余额
+     */
+    private Double cardMoneyValue;
+
+    public String getGuid() {
+        return guid;
+    }
+
+    public void setGuid(String guid) {
+        this.guid = guid;
+    }
+
+    public String getEmpSysID() {
+        return empSysID;
+    }
+
+    public void setEmpSysID(String empSysID) {
+        this.empSysID = empSysID;
+    }
+
+    public String getEmpNo() {
+        return empNo;
+    }
+
+    public void setEmpNo(String empNo) {
+        this.empNo = empNo;
+    }
+
+    public String getEmpName() {
+        return empName;
+    }
+
+    public void setEmpName(String empName) {
+        this.empName = empName;
+    }
+
+    public String getAccNo() {
+        return accNo;
+    }
+
+    public void setAccNo(String accNo) {
+        this.accNo = accNo;
+    }
+
+    public String getAccTransType() {
+        return accTransType;
+    }
+
+    public void setAccTransType(String accTransType) {
+        this.accTransType = accTransType;
+    }
+
+    public Date getAccTransDay() {
+        return accTransDay;
+    }
+
+    public void setAccTransDay(Date accTransDay) {
+        this.accTransDay = accTransDay;
+    }
+
+    public Double getiMoneyValue() {
+        return iMoneyValue;
+    }
+
+    public void setiMoneyValue(Double iMoneyValue) {
+        this.iMoneyValue = iMoneyValue;
+    }
+
+    public Double getoMoneyValue() {
+        return oMoneyValue;
+    }
+
+    public void setoMoneyValue(Double oMoneyValue) {
+        this.oMoneyValue = oMoneyValue;
+    }
+
+    public Double getCardMoneyValue() {
+        return cardMoneyValue;
+    }
+
+    public void setCardMoneyValue(Double cardMoneyValue) {
+        this.cardMoneyValue = cardMoneyValue;
+    }
+}

+ 174 - 0
applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/po/MessageInfo.java

@@ -0,0 +1,174 @@
+package com.usoftchina.smartschool.device.client.po;
+
+import java.io.Serializable;
+
+/**
+ * @Author chenwei
+ * @Date 2019/03/08
+ */
+public class MessageInfo implements Serializable {
+
+    private String msgId;
+    /**
+     * 公众号id
+     */
+    private String appId;
+
+    /**
+     * 公众号密钥
+     */
+    private String secret;
+
+    /*
+     * 推送人微信标识
+     */
+    private String touser;
+
+    /**
+     * 微信模板id
+     */
+    private String templateId;
+
+    private String title;
+
+    private String keyword1;
+
+    private String keyword2;
+
+    private String keyword3;
+
+    private String keyword4;
+
+    private String keyword5;
+
+    private String keyword6;
+
+    private int userType;
+
+    private String remark;
+
+    private String url;
+
+    public String getAppId() {
+        return appId;
+    }
+
+    public void setAppId(String appId) {
+        this.appId = appId;
+    }
+
+    public String getSecret() {
+        return secret;
+    }
+
+    public void setSecret(String secret) {
+        this.secret = secret;
+    }
+
+    public String getTouser() {
+        return touser;
+    }
+
+    public void setTouser(String touser) {
+        this.touser = touser;
+    }
+
+    public String getTemplateId() {
+        return templateId;
+    }
+
+    public void setTemplateId(String templateId) {
+        this.templateId = templateId;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getKeyword1() {
+        return keyword1;
+    }
+
+    public void setKeyword1(String keyword1) {
+        this.keyword1 = keyword1;
+    }
+
+    public String getKeyword2() {
+        return keyword2;
+    }
+
+    public void setKeyword2(String keyword2) {
+        this.keyword2 = keyword2;
+    }
+
+    public String getKeyword3() {
+        return keyword3;
+    }
+
+    public void setKeyword3(String keyword3) {
+        this.keyword3 = keyword3;
+    }
+
+    public String getKeyword4() {
+        return keyword4;
+    }
+
+    public void setKeyword4(String keyword4) {
+        this.keyword4 = keyword4;
+    }
+
+    public String getKeyword6() {
+        return keyword6;
+    }
+
+    public void setKeyword6(String keyword6) {
+        this.keyword6 = keyword6;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public String getKeyword5() {
+        return keyword5;
+    }
+
+    public void setKeyword5(String keyword5) {
+        this.keyword5 = keyword5;
+    }
+
+    public int getUserType() {
+        return userType;
+    }
+
+    public void setUserType(int userType) {
+        this.userType = userType;
+    }
+
+    public String getMsgId() {
+        return msgId;
+    }
+
+    public void setMsgId(String msgId) {
+        this.msgId = msgId;
+    }
+
+
+
+}

+ 49 - 0
applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/po/Transaction.java

@@ -0,0 +1,49 @@
+package com.usoftchina.smartschool.device.client.po;
+
+public enum Transaction {
+
+    AUTO_RECHARGE("自动充值", "10"),
+    HAND_RECHARGE("手动充值", "11"),
+    TRANSFER_RECHARGE("转账充值", "12"),
+    SUPPLEMENT__RECHARGE("补账充值", "13"),
+    TRAPS_RECHARGE("圈存充值", "14"),
+
+    CONSUMPTION_PAY("消费支出", "20"),
+    REFUND("退款", "21"),
+    CLOSE_ACCOUNT("销户", "22"),
+    TRANSFER_PAY("转账支出", "23"),
+    SUPPLEMENT_PAY("补账支出", "24");
+
+    private String name;
+    private String code;
+
+    Transaction(String name, String code) {
+        this.name = name;
+        this.code = code;
+    }
+
+    public static String getName(String code){
+        for (Transaction transaction : Transaction.values()) {
+            if (transaction.getCode().equals(code)) {
+                return transaction.name;
+            }
+        }
+        return null;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}

+ 1 - 1
applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/repository/SchoolRepository.java

@@ -19,7 +19,7 @@ public class SchoolRepository{
 
     public School find() {
         try {
-            return jdbcTemplate.queryForObject("select * from iccard",
+            return jdbcTemplate.queryForObject("select * from school",
                     new BeanPropertyRowMapper<>(School.class));
         } catch (EmptyResultDataAccessException e) {
             return null;

+ 21 - 11
applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/service/AccessControlService.java

@@ -12,6 +12,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
 import org.springframework.web.client.RestTemplate;
 
@@ -44,33 +45,42 @@ public class AccessControlService {
      *
      * @param accessControl
      */
+    @Transactional(rollbackFor = Exception.class)
     public void save(AccessControl accessControl) {
         AccessControl oldOne = accessControlRepository.findByIpAndPort(accessControl.getIp(),
                 accessControl.getPort());
+        boolean isNew = StringUtils.isEmpty(accessControl.getId());
         if (null != oldOne) {
-            if (StringUtils.isEmpty(accessControl.getId())) {
+            if (isNew) {
                 accessControl.setId(oldOne.getId());
             } else if (!accessControl.getId().equals(oldOne.getId())) {
                 ExceptionCode.ERROR_IP_PORT_EXIST.occur();
             }
-            accessControlRepository.update(accessControl);
+        } else {
+            if (isNew) {
+                accessControl.setId(RandomUtils.randomString());
+            }
+        }
+
+        if (isNew) {
+            // 调用设备接口监听
+            deviceApi.add(accessControl);
+            accessControlRepository.save(accessControl);
+        } else {
+            oldOne = accessControlRepository.findById(accessControl.getId());
             if (!oldOne.getIp().equals(accessControl.getIp()) || oldOne.getPort() != accessControl.getPort() ||
                     !oldOne.getUsername().equals(accessControl.getUsername()) ||
-                            !oldOne.getPassword().equals(accessControl.getPassword())) {
-                // 先调用设备接口停止监听
-                deviceApi.remove(accessControl);
+                    !oldOne.getPassword().equals(accessControl.getPassword())) {
                 // 调用设备接口监听
                 deviceApi.add(accessControl);
+                // 调用设备接口停止监听
+                deviceApi.remove(oldOne);
             }
-
-        } else {
-            accessControl.setId(RandomUtils.randomString());
-            accessControlRepository.save(accessControl);
-            // 调用设备接口监听
-            deviceApi.add(accessControl);
+            accessControlRepository.update(accessControl);
         }
     }
 
+    @Transactional(rollbackFor = Exception.class)
     public void delete(String id) {
         AccessControl oldOne = accessControlRepository.findById(id);
         if (null != oldOne) {

+ 127 - 7
applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/service/IcCardService.java

@@ -1,11 +1,30 @@
 package com.usoftchina.smartschool.device.client.service;
 
+import com.alibaba.fastjson.JSON;
+import com.usoftchina.smartschool.device.base.Result;
 import com.usoftchina.smartschool.device.client.jdbc.DynamicDataSourceContextHolder;
 import com.usoftchina.smartschool.device.client.jdbc.DynamicDataSourceRegister;
-import com.usoftchina.smartschool.device.client.po.IcCard;
+import com.usoftchina.smartschool.device.client.po.*;
 import com.usoftchina.smartschool.device.client.repository.IcCardRepository;
+import com.usoftchina.smartschool.device.client.utils.HmacUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.*;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.util.StringUtils;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.DefaultUriBuilderFactory;
+
+import java.net.URI;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * @author yingp
@@ -17,13 +36,37 @@ public class IcCardService {
     @Autowired
     private IcCardRepository icCardRepository;
 
+    @Autowired
+    private SchoolService schoolService;
+
     @Autowired
     private DynamicDataSourceRegister dynamicDataSourceRegister;
 
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    @Autowired
+    private RestTemplate restTemplate;
+
+    @Value("${device.icCard.icCardUrl}")
+    private String targetURL;
+
+    //SQL语句
+    private static final String insertSql = "INSERT INTO XF_AccTransDetail_push(GUID,AccNo,AccTransDay,AccTransType,IMoneyValue,OMoneyValue,CardUseNum,CardMoneyValue,DevID,DevOwner,OprtNo,Remark,XFDataSysID,XFPosMoneyByCredit,SendStatus,CreateTime) "
+            + " SELECT SOURCE.GUID,SOURCE.AccNo,SOURCE.AccTransDay,SOURCE.AccTransType,SOURCE.IMoneyValue,SOURCE.OMoneyValue,SOURCE.CardUseNum,SOURCE.CardMoneyValue,SOURCE.DevID,SOURCE.DevOwner,SOURCE.OprtNo,SOURCE.Remark,SOURCE.XFDataSysID,SOURCE.XFPosMoneyByCredit,'待上传',GETDATE() "
+            + " FROM XF_AccTransDetail SOURCE WHERE NOT EXISTS (SELECT 1 FROM XF_AccTransDetail_push TARGET WHERE SOURCE.GUID = TARGET.GUID)";
+
+    private static final String getDataSql = "select top 100 XF_AccTransDetail_push.GUID,RS_EMP.EmpSysID,RS_EMP.EmpNo,RS_EMP.EmpName,XF_AccHead.AccNo, XF_AccTransDetail_push.AccTransType,XF_AccTransDetail_push.AccTransDay,XF_AccTransDetail_push.IMoneyValue,XF_AccTransDetail_push.OMoneyValue,XF_AccTransDetail_push.CardMoneyValue "
+            + "from XF_AccTransDetail_push left join XF_AccHead on XF_AccTransDetail_push.AccNo=XF_AccHead.AccNo left join Tx_EmpCard on Tx_EmpCard.CardID=XF_AccHead.CardID "
+            + "left join RS_EMP ON RS_EMP.EmpSysID=XF_AccHead.EmpSysID where XF_AccTransDetail_push.SendStatus=? order by AccTransDay desc";
+
+    private static final String updateSql = "update XF_AccTransDetail_push set SendStatus = ? where GUID in (?)";
+
     public IcCard find() {
         return icCardRepository.find();
     }
 
+    @Transactional(rollbackFor = Exception.class)
     public void save(IcCard card) {
         IcCard oldOne = find();
         if (null != oldOne) {
@@ -35,13 +78,90 @@ public class IcCardService {
         dynamicDataSourceRegister.createDataSource(card);
     }
 
-    public void startListen() {
+    @Scheduled(fixedRate = 1000 * 60, initialDelay = 5000)
+    public void dataTask() {
         IcCard card = find();
-        DynamicDataSourceContextHolder.set(card);
-        try {
-            // TODO
-        } finally {
-            DynamicDataSourceContextHolder.clear();
+        School school = schoolService.find();
+        if (null != card && dynamicDataSourceRegister.contains(card) && null != school) {
+            DynamicDataSourceContextHolder.set(card);
+            try {
+                doTask();
+            } finally {
+                DynamicDataSourceContextHolder.clear();
+            }
+        }
+    }
+
+    private void doTask(){
+        //1.准备本次需要传输的数据->转移至中间表
+        jdbcTemplate.execute(insertSql);
+        //2.获取本次传输的数据
+        List<AccTransDetail> resultList = jdbcTemplate.query(getDataSql, new BeanPropertyRowMapper<>(AccTransDetail.class), "待上传");
+        List<MessageInfo> messageInfoList = new ArrayList<MessageInfo>();
+        StringBuilder sb = new StringBuilder();
+        resultList.forEach(accTransDetail -> {
+            sb.append(accTransDetail.getGuid() + ",");
+            String oldType = accTransDetail.getAccTransType();
+            accTransDetail.setAccTransType(Transaction.getName(accTransDetail.getAccTransType()));
+            //构造messageInfo对象
+            MessageInfo messageInfo = new MessageInfo();
+            messageInfo.setMsgId(accTransDetail.getGuid());
+            messageInfo.setTouser(accTransDetail.getEmpNo());
+            //messageInfo.setTouser("o8lZ9uNXXY7VSfNM6be-7VZNkcOw");
+            messageInfo.setTouser(accTransDetail.getEmpName());
+            messageInfo.setUserType(2);
+            messageInfo.setTemplateId("FhtdzLdpzLLp4eJGtgvH4SUfIpSIF0kWwIpsWsSBp6c");
+            String accNo = accTransDetail.getAccNo();
+            String cardNo = StringUtils.isEmpty(accNo) ? null : accNo.substring(accTransDetail.getAccNo().length() - 4);
+            String header = "您好,您的小孩" + accTransDetail.getEmpName() + "在校的校园卡(卡号:*** " + cardNo + ")发生如下交易";
+            messageInfo.setTitle(header);
+            messageInfo.setKeyword1(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(accTransDetail.getAccTransDay()));
+            if (Integer.parseInt(oldType) > 15) {
+                messageInfo.setKeyword2(String.format("%.2f", accTransDetail.getoMoneyValue()));
+            }else {
+                messageInfo.setKeyword2(String.format("%.2f", accTransDetail.getiMoneyValue()));
+            }
+            messageInfo.setKeyword3(accTransDetail.getAccTransType());
+            messageInfo.setKeyword4(String.format("%.2f", accTransDetail.getCardMoneyValue()));
+            messageInfo.setRemark("感谢您使用");
+            messageInfoList.add(messageInfo);
+        });
+        //3.传输
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+        MultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<>();
+        requestEntity.add("data", JSON.toJSONString(messageInfoList));
+        HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(requestEntity, headers);
+        //禁止对该url进行encode操作
+        DefaultUriBuilderFactory defaultUriBuilderFactory = new DefaultUriBuilderFactory();
+        defaultUriBuilderFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE);
+        restTemplate.setUriTemplateHandler(defaultUriBuilderFactory);
+        ResponseEntity<String> responseEntity = restTemplate.postForEntity(getURI(targetURL, "/send"), httpEntity, String.class);
+        //4.完成后,将传输的成功的数据状态更新为"已上传"
+        if (responseEntity.getStatusCode().equals(HttpStatus.OK)) {
+            Result result = JSON.parseObject(responseEntity.getBody(), Result.class);
+            if (result.isSuccess()) {
+                String ids = "'" + sb.substring(0, sb.length() - 1).replaceAll(",", "','") + "'";
+                jdbcTemplate.update(updateSql, "已上传", ids);
+            }
         }
     }
+
+    private String getURI(String url, String subIndexOf, Object... vars){
+        StringBuilder accessUrl = new StringBuilder(url);
+        accessUrl.append(url.contains("?") ? "&" : "?");
+        // 身份ID
+        accessUrl.append("school=").append(schoolService.find().getName());
+        //时间戳
+        accessUrl.append("&_timestamp=").append(System.currentTimeMillis());
+        RestTemplate restTemplate = new RestTemplate();
+        URI uri = restTemplate.getUriTemplateHandler().expand(accessUrl.toString(), vars);
+        url = uri.toString();
+        /*if (StringUtils.isEmpty(accessSecretKey)) {
+            return url + "&_signature=" + HmacUtils.encode(url.substring(url.indexOf(subIndexOf)));
+        }else {
+            return url + "&_signature=" + HmacUtils.encode(url.substring(url.indexOf(subIndexOf)), accessSecretKey);
+        }*/
+        return url + "&_signature=" + HmacUtils.encode(url.substring(url.indexOf(subIndexOf)));
+    }
 }

+ 51 - 0
applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/utils/HmacUtils.java

@@ -0,0 +1,51 @@
+package com.usoftchina.smartschool.device.client.utils;
+
+
+import com.usoftchina.smartschool.device.crypto.Hex;
+import com.usoftchina.smartschool.device.crypto.HmacEncoder;
+import com.usoftchina.smartschool.device.crypto.HmacSHA256Encoder;
+
+/**
+ * Hmac加密工具
+ * 
+ * @author yingp
+ *
+ */
+public class HmacUtils {
+
+	private static HmacEncoder hmacEncoder;
+
+	// 默认约定密钥
+	private final static byte[] key = { 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 117, 98, 116, 111, 98, 46, 99, 111, 109, 47,
+			101, 114, 112, 47, 115, 97, 108, 101, 47, 111, 114, 100, 101, 114, 115, 63, 115, 111, 109, 101, 116, 104, 105, 110, 103 };
+
+	static {
+		// default algorithm: HmacSHA256
+		hmacEncoder = new HmacSHA256Encoder();
+	}
+
+	/**
+	 * 
+	 * @param message
+	 *            明文
+	 * @return 16进制密文
+	 */
+	public static String encode(Object message) {
+		byte[] encodeData = hmacEncoder.encode(String.valueOf(message).getBytes(), key);
+		return new String(Hex.encode(encodeData));
+	}
+
+	/**
+	 * 
+	 * @param message
+	 *            明文
+	 * @param key
+	 *            密钥
+	 * @return 16进制密文
+	 */
+	public static String encode(Object message, String key) {
+		byte[] encodeData = hmacEncoder.encode(String.valueOf(message).getBytes(), key.getBytes());
+		return new String(Hex.encode(encodeData));
+	}
+
+}

+ 3 - 0
applications/device/device-client/src/main/resources/application.yml

@@ -5,6 +5,9 @@ device:
   server:
   # 门禁事件的服务端接口
     accessControlEvent: https://school-api.ydyhz.com/api/device/accesscontrol/event
+  # IC卡传输的服务端接口
+  icCard:
+    icCardUrl: https://school-api.ubtob.com/api/wechat/send/Messages
 server:
   tomcat:
     uri-encoding: UTF-8

+ 25 - 0
applications/device/device-client/src/main/resources/static/css/iconfont.css

@@ -0,0 +1,25 @@
+@font-face {font-family: "iconfont";
+  src: url('iconfont.eot?t=1552353178223'); /* IE9 */
+  src: url('iconfont.eot?t=1552353178223#iefix') format('embedded-opentype'), /* IE6-IE8 */
+  url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAOMAAsAAAAACEAAAAM/AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDBgqEKIM+ATYCJAMMCwgABCAFhG0HNxsFBxHVm3PIfiTGtmjyzpmhr6KJ9maCB6rzfbMzSfcbqOSkpG/2iTr+JgBMmnPARkVNluQsevQP99BympHPczluPQ9sfstymmPZsrJF8QEFtDceRVYgAXnD2JUX8RwCsMafWERpeW0rdBTGOgGIQf37dkdPmVE1tQIdgbHkqEIswYCuzdVuAYv974svJAsdNAwS46XGPmW9KHx/94OHNFlMdJJmTOM5AXYKJBALKBBdSt3tkGE6Fom1olb1pUYUAm2smMWCL1a1xpX+8TQQRoxqWwAioVHjpCQ2HwI+eIighvM/BUZAB04ANyDDlaRC+QbZ2fn6OrkOtj/1wN9g3j9/L8q018Zh/n6Ratxwr6v1PPf8VdYu0zV3RcM+834bm4LVpx3H/Kg8u3avaU+/eftEv749NonU+A33Uh1H3bX5YYYD9jv2eKq1e8Ocdo88qo0qv7Lb6vMefVeb3d1XzXPtteKAa6uxbntNkeHtZ0Jb7djl03b9YY++++dbCkyt9UJ7J18ne9dtj70vSs3UW7f5/8527c219vPtkNn2XdGch8Fv8lzmR14Ifpi0NE1tr/bFXQ8SM8n/6Wc1e0v4ktn6MX+ab5Jv43l1TJ4vDAdE3UamjCzf8vnlv9b7JnT8FvattCmqKbh+b/M8z9pQWfKq5tX4jk1f0idEpSW0iBjf4jzc2elzc7oBYLkit8hCnDUpIc3/9Tf0WZW6satD7j/dRgHw7GDkOiht5wX9rj0C/mKTAiwWJbjMsEgli22x7pF0TgTRAAq5hn9XD+DMm/5at9bVINBxi6HRDD9IdEIpihELAzakwohOAayJoeK0DS6MQCKUFRDNTACBI4ehYc9lSBy5TVGM1zDgzjcYcRQS1rQRLlfaoO5F3B0ZSmBJ/ymarnWWTXZB7Q3+XStOynzWCzzGGOVJls1d0YLH2DF+fCHiyHHX0AW8hrruqOeuhJEkiPSHNHVlb0pM10x2HBlKYAn9J6LpWueOl13u8zf4d624pqMi+AKPcXIiJyFrQbmq21Yd10Jm/PgCEUc47hriApyozXRH9OWLShhJCD2S/YEU9XJt1cn82ub5EgBrjDul0IQUilUv1BAsYKNMJgA=') format('woff2'),
+  url('iconfont.woff?t=1552353178223') format('woff'),
+  url('iconfont.ttf?t=1552353178223') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
+  url('iconfont.svg?t=1552353178223#iconfont') format('svg'); /* iOS 4.1- */
+}
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.icon-delete:before {
+  content: "\e6cf";
+}
+
+.icon-edit:before {
+  content: "\e717";
+}
+

BIN
applications/device/device-client/src/main/resources/static/css/iconfont.eot


+ 32 - 0
applications/device/device-client/src/main/resources/static/css/iconfont.svg

@@ -0,0 +1,32 @@
+<?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" >
+<!--
+2013-9-30: Created.
+-->
+<svg>
+<metadata>
+Created by iconfont
+</metadata>
+<defs>
+
+<font id="iconfont" horiz-adv-x="1024" >
+  <font-face
+    font-family="iconfont"
+    font-weight="500"
+    font-stretch="normal"
+    units-per-em="1024"
+    ascent="896"
+    descent="-128"
+  />
+    <missing-glyph />
+    
+    <glyph glyph-name="delete" unicode="&#59087;" d="M768-64H256c-52.8 0-96 43.2-96 96V608c0 17.6 14.4 32 32 32s32-14.4 32-32v-576c0-17.6 14.4-32 32-32h512c17.6 0 32 14.4 32 32V608c0 17.6 14.4 32 32 32s32-14.4 32-32v-576c0-52.8-43.2-96-96-96zM896 704H672c-8 0-16 3.2-22.4 9.6l-44.8 44.8c-6.4 6.4-14.4 9.6-24 9.6h-139.2c-8 0-16-3.2-22.4-9.6l-44.8-44.8c-6.4-6.4-14.4-9.6-22.4-9.6H128c-17.6 0-32 14.4-32 32s14.4 32 32 32h211.2l35.2 35.2C392 822.4 417.6 832 443.2 832h139.2c25.6 0 49.6-9.6 67.2-28.8L684.8 768H896c17.6 0 32-14.4 32-32s-14.4-32-32-32zM400 64c-17.6 0-32 14.4-32 32V608c0 17.6 14.4 32 32 32s32-14.4 32-32v-512c0-17.6-14.4-32-32-32zM624 64c-17.6 0-32 14.4-32 32V608c0 17.6 14.4 32 32 32s32-14.4 32-32v-512c0-17.6-14.4-32-32-32z"  horiz-adv-x="1024" />
+
+    
+    <glyph glyph-name="edit" unicode="&#59159;" d="M1006.592-29.39392c0-54.311936-44.859392-98.60608-100.196352-98.60608H100.196352C45.207552-128 0-83.994624 0-29.710336V660.494336C0 714.807296 45.125632 758.784 100.79232 758.784h539.76576v-49.265664H100.79232c-27.92448 0-50.46272-21.972992-50.46272-49.024v-690.204672c0-26.954752 22.550528-49.024 49.866752-49.024h806.199296c27.416576 0 49.866752 22.116352 49.866752 49.340416v626.944H1006.592v-626.944z m0 0c0-54.311936-44.859392-98.60608-100.196352-98.60608H100.196352C45.207552-128 0-83.994624 0-29.710336V660.494336C0 714.807296 45.125632 758.784 100.79232 758.784h539.76576v-49.265664H100.79232c-27.92448 0-50.46272-21.972992-50.46272-49.024v-690.204672c0-26.954752 22.550528-49.024 49.866752-49.024h806.199296c27.416576 0 49.866752 22.116352 49.866752 49.340416v626.944H1006.592v-626.944zM516.465664 378.235904c19.206144 6.542336 50.36032 24.948736 64.864256 38.288384l378.635264 348.248064c19.523584 17.956864 19.503104 47.152128-0.088064 65.272832l-5.225472 4.83328c-20.186112 18.670592-52.790272 18.783232-72.92928 0.260096L503.044096 486.852608c-13.686784-12.589056-31.880192-40.728576-37.430272-57.837568l-24.835072-76.560384 75.685888 25.781248zM989.96224 868.345856l5.225472-4.83328c39.458816-36.49536 39.602176-95.865856-0.011264-132.3008L616.539136 382.96576c-19.570688-18.000896-56.854528-40.067072-82.895872-48.93696l-123.001856-41.897984c-26.315776-8.964096-40.638464 4.017152-32.60416 28.78464l39.502848 121.772032c7.969792 24.57088 30.553088 59.567104 50.295808 77.725696L846.512128 868.698112c39.836672 36.63872 103.842816 36.28032 143.449088-0.352256z"  horiz-adv-x="1024" />
+
+    
+
+
+  </font>
+</defs></svg>

BIN
applications/device/device-client/src/main/resources/static/css/iconfont.ttf


BIN
applications/device/device-client/src/main/resources/static/css/iconfont.woff


+ 41 - 1
applications/device/device-client/src/main/resources/static/iccard.html

@@ -8,7 +8,7 @@
 </head>
 <body>
 <nav class="navbar navbar-expand-lg navbar-light bg-light">
-    <a class="navbar-brand" href="#">设备监听管理</a>
+    <a class="navbar-brand" href="#">智慧校园设备监听管理</a>
 
     <div class="collapse navbar-collapse">
         <ul class="navbar-nav mr-auto">
@@ -18,7 +18,47 @@
             <li class="nav-item active">
                 <a class="nav-link" href="#">消费卡</a>
             </li>
+            <li class="nav-item">
+                <a class="nav-link" href="/school">学校</a>
+            </li>
         </ul>
     </div>
 </nav>
+<div class="container">
+    <div class="row justify-content-md-center">
+        <div class="col-lg-auto" style="width: 500px">
+            <form id="form">
+                <div class="form-group">
+                    <label for="ipInput">IP</label>
+                    <input type="text" class="form-control" id="ipInput" name="ip" required
+                           aria-describedby="ipHelp" placeholder="ip地址,例如192.168.1.100">
+                </div>
+                <div class="form-group">
+                    <label for="portInput">端口</label>
+                    <input type="text" class="form-control" id="portInput" name="port" required
+                           aria-describedby="portHelp" placeholder="tcp端口,例如37777">
+                </div>
+                <div class="form-group">
+                    <label for="usernameInput">账号</label>
+                    <input type="text" class="form-control" id="usernameInput" name="username"
+                           value="admin" required aria-describedby="usernameHelp" placeholder="数据库账号,例如sa">
+                </div>
+                <div class="form-group">
+                    <label for="passwordInput">密码</label>
+                    <input type="password" class="form-control" id="passwordInput" name="password"
+                           required aria-describedby="passwordHelp" placeholder="数据库密码">
+                </div>
+                <div class="form-group">
+                    <label for="databaseNameInput">数据库</label>
+                    <input type="text" class="form-control" id="databaseNameInput" name="databaseName"
+                           required aria-describedby="databaseNameHelp" placeholder="数据库名称">
+                </div>
+                <button type="button" class="btn btn-primary btn-save">保存</button>
+            </form>
+        </div>
+    </div>
+</div>
+<script src="/js/jquery.min.js"></script>
+<script src="/js/bootstrap.min.js"></script>
+<script src="/js/iccard.js"></script>
 </body>

+ 18 - 3
applications/device/device-client/src/main/resources/static/index.html

@@ -5,10 +5,11 @@
     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
     <title>智慧校园 - 设备监听管理</title>
     <link rel="stylesheet" href="/css/bootstrap.min.css">
+    <link rel="stylesheet" href="/css/iconfont.css">
 </head>
 <body>
 <nav class="navbar navbar-expand-lg navbar-light bg-light">
-    <a class="navbar-brand" href="#">设备监听管理</a>
+    <a class="navbar-brand" href="#">智慧校园设备监听管理</a>
 
     <div class="collapse navbar-collapse">
         <ul class="navbar-nav mr-auto">
@@ -18,6 +19,9 @@
             <li class="nav-item">
                 <a class="nav-link" href="/iccard">消费卡</a>
             </li>
+            <li class="nav-item">
+                <a class="nav-link" href="/school">学校</a>
+            </li>
         </ul>
     </div>
 
@@ -31,13 +35,14 @@
     <div class="modal-dialog modal-dialog-scrollable" role="document">
         <div class="modal-content">
             <div class="modal-header">
-                <h5 class="modal-title" id="formModalTitle">添加门禁设备</h5>
+                <h5 class="modal-title" id="formModalTitle">门禁设备信息</h5>
                 <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                     <span aria-hidden="true">&times;</span>
                 </button>
             </div>
             <div class="modal-body">
                 <form id="form">
+                    <input type="hidden" id="idInput" name="id">
                     <div class="form-group">
                         <label for="nameInput">名称</label>
                         <input type="text" class="form-control" id="nameInput" name="name" required
@@ -67,7 +72,7 @@
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
-                <button type="button" class="btn btn-primary" id="saveBtn">保存</button>
+                <button type="button" class="btn btn-primary btn-save">保存</button>
             </div>
         </div>
     </div>
@@ -78,6 +83,7 @@
         <th scope="col">名称</th>
         <th scope="col">IP</th>
         <th scope="col">端口</th>
+        <th scope="col">操作</th>
     </tr>
     </thead>
     <tbody>
@@ -89,6 +95,15 @@
         <td><%=data[i].name%></td>
         <td><%=data[i].ip%></td>
         <td><%=data[i].port%></td>
+        <td>
+            <button type="button" class="btn btn-link btn-edit" data-index="<%=i%>" title="编辑"
+                    data-toggle="modal" data-target="#formModal">
+                <span class="iconfont icon-edit"></span>
+            </button>
+            <button type="button" class="btn btn-link btn-delete" data-index="<%=i%>" title="删除">
+                <span class="iconfont icon-delete"></span>
+            </button>
+        </td>
     </tr>
     <%}%>
 </script>

+ 47 - 0
applications/device/device-client/src/main/resources/static/js/iccard.js

@@ -0,0 +1,47 @@
+$(document).ready(function () {
+    var app = {
+        methods: {
+            get: function () {
+                $.ajax({
+                    url: '/api/iccard',
+                    method: 'GET',
+                    success: function (content) {
+                        if (content.success) {
+                            var card = content.data;
+                            $('#ipInput').val(card.ip);
+                            $('#portInput').val(card.port);
+                            $('#usernameInput').val(card.username);
+                            $('#passwordInput').val(card.password);
+                            $('#databaseNameInput').val(card.databaseName);
+                        } else {
+                            alert(content.message);
+                        }
+                    }
+                });
+            },
+            save: function () {
+                $.ajax({
+                    url: '/api/iccard',
+                    method: 'POST',
+                    data: $('#form').serialize(),
+                    success: function (content) {
+                        if (content.success) {
+                            window.location.reload();
+                        } else {
+                            alert(content.message);
+                        }
+                    }
+                });
+            }
+        },
+        init: function () {
+            $('.btn-save').click(function(){
+                app.methods.save();
+            });
+
+            app.methods.get();
+        }
+    };
+
+    app.init();
+});

File diff suppressed because it is too large
+ 0 - 0
applications/device/device-client/src/main/resources/static/js/iconfont.js


+ 36 - 11
applications/device/device-client/src/main/resources/static/js/index.js

@@ -12,6 +12,21 @@ $(document).ready(function () {
                         if (content.success) {
                             app.data.accessControls = content.data;
                             $('.table tbody').html(template($('#template-html').text(), content));
+                            $('.btn-edit').click(function(){
+                                var index = $(this).data('index'),
+                                    accessControl = app.data.accessControls[index];
+                                $('#idInput').val(accessControl.id);
+                                $('#nameInput').val(accessControl.name);
+                                $('#ipInput').val(accessControl.ip);
+                                $('#portInput').val(accessControl.port);
+                                $('#usernameInput').val(accessControl.username);
+                                $('#passwordInput').val(accessControl.password);
+                            });
+                            $('.btn-delete').click(function(){
+                                var index = $(this).data('index'),
+                                    accessControl = app.data.accessControls[index];
+                                app.methods.remove(accessControl.id);
+                            });
                         } else {
                             alert(content.message);
                         }
@@ -19,28 +34,38 @@ $(document).ready(function () {
                 });
             },
             save: function () {
-                // var name = $('#nameInput').val(),
-                //     ip = $('#ipInput').val(),
-                //     port = $('#portInput').val(),
-                //     username = $('usernameInput').val(),
-                //     password = $('passwordInput').val();
                 $.ajax({
                     url: '/api/accesscontrol',
                     method: 'POST',
                     data: $('#form').serialize(),
-                    success: function () {
-                        window.location.reload();
-                    },
-                    error: function () {
-
+                    success: function (content) {
+                        if (content.success) {
+                            window.location.reload();
+                        } else {
+                            alert(content.message);
+                        }
+                    }
+                });
+            },
+            remove: function (id) {
+                $.ajax({
+                    url: '/api/accesscontrol/' + id,
+                    method: 'DELETE',
+                    success: function (content) {
+                        if (content.success) {
+                            window.location.reload();
+                        } else {
+                            alert(content.message);
+                        }
                     }
                 });
             }
         },
         init: function () {
-            $('#saveBtn').click(function () {
+            $('.btn-save').click(function(){
                 app.methods.save();
             });
+
             app.methods.getList();
         }
     };

+ 42 - 0
applications/device/device-client/src/main/resources/static/js/school.js

@@ -0,0 +1,42 @@
+$(document).ready(function () {
+    var app = {
+        methods: {
+            get: function () {
+                $.ajax({
+                    url: '/api/school',
+                    method: 'GET',
+                    success: function (content) {
+                        if (content.success) {
+                            $('#nameInput').val(content.data.name);
+                        } else {
+                            alert(content.message);
+                        }
+                    }
+                });
+            },
+            save: function () {
+                $.ajax({
+                    url: '/api/school',
+                    method: 'POST',
+                    data: $('#form').serialize(),
+                    success: function (content) {
+                        if (content.success) {
+                            window.location.reload();
+                        } else {
+                            alert(content.message);
+                        }
+                    }
+                });
+            }
+        },
+        init: function () {
+            $('.btn-save').click(function(){
+                app.methods.save();
+            });
+
+            app.methods.get();
+        }
+    };
+
+    app.init();
+});

+ 44 - 0
applications/device/device-client/src/main/resources/static/school.html

@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html lang="zh-CN">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+    <title>智慧校园 - 设备监听管理</title>
+    <link rel="stylesheet" href="/css/bootstrap.min.css">
+</head>
+<body>
+<nav class="navbar navbar-expand-lg navbar-light bg-light">
+    <a class="navbar-brand" href="#">智慧校园设备监听管理</a>
+
+    <div class="collapse navbar-collapse">
+        <ul class="navbar-nav mr-auto">
+            <li class="nav-item">
+                <a class="nav-link" href="/">门禁设备</a>
+            </li>
+            <li class="nav-item">
+                <a class="nav-link" href="/iccard">消费卡</a>
+            </li>
+            <li class="nav-item active">
+                <a class="nav-link" href="#">学校</a>
+            </li>
+        </ul>
+    </div>
+</nav>
+<div class="container">
+    <div class="row justify-content-md-center">
+        <div class="col-lg-auto" style="width: 500px">
+            <form id="form">
+                <div class="form-group">
+                    <label for="nameInput">名称</label>
+                    <input type="text" class="form-control" id="nameInput" name="name" required
+                           aria-describedby="nameHelp" placeholder="学校名称">
+                </div>
+                <button type="button" class="btn btn-primary btn-save">保存</button>
+            </form>
+        </div>
+    </div>
+</div>
+<script src="/js/jquery.min.js"></script>
+<script src="/js/bootstrap.min.js"></script>
+<script src="/js/school.js"></script>
+</body>

+ 20 - 0
applications/device/device-core/src/main/java/com/usoftchina/smartschool/device/base/Result.java

@@ -1,5 +1,8 @@
 package com.usoftchina.smartschool.device.base;
 
+import com.usoftchina.smartschool.device.exception.BaseException;
+import com.usoftchina.smartschool.device.exception.ExceptionCode;
+
 import java.io.Serializable;
 
 /**
@@ -102,4 +105,21 @@ public class Result<T> implements Serializable {
         result.setMessage(String.format(message, args));
         return result;
     }
+
+    public static Result error(BaseException e) {
+        Result result = error();
+        result.setCode(e.getCode());
+        result.setMessage(e.getMessage());
+        return result;
+    }
+
+    public static Result throwable(Throwable e) {
+        Result result = error();
+        if (e instanceof BaseException) {
+            return error((BaseException) e);
+        }
+        result.setCode(ExceptionCode.ERROR_UNKNOWN.getCode());
+        result.setMessage(e.getMessage());
+        return result;
+    }
 }

+ 40 - 0
applications/device/device-core/src/main/java/com/usoftchina/smartschool/device/crypto/Hex.java

@@ -0,0 +1,40 @@
+package com.usoftchina.smartschool.device.crypto;
+
+public final class Hex {
+	private static final char[] HEX = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+
+	public static char[] encode(byte[] bytes) {
+		int nBytes = bytes.length;
+		char[] result = new char[2 * nBytes];
+
+		int j = 0;
+		for (int i = 0; i < nBytes; ++i) {
+			result[(j++)] = HEX[((0xF0 & bytes[i]) >>> 4)];
+
+			result[(j++)] = HEX[(0xF & bytes[i])];
+		}
+
+		return result;
+	}
+
+	public static byte[] decode(CharSequence s) {
+		int nChars = s.length();
+
+		if (nChars % 2 != 0) {
+			throw new IllegalArgumentException("Hex-encoded string must have an even number of characters");
+		}
+
+		byte[] result = new byte[nChars / 2];
+
+		for (int i = 0; i < nChars; i += 2) {
+			int msb = Character.digit(s.charAt(i), 16);
+			int lsb = Character.digit(s.charAt(i + 1), 16);
+
+			if ((msb < 0) || (lsb < 0)) {
+				throw new IllegalArgumentException("Non-hex character in input: " + s);
+			}
+			result[(i / 2)] = (byte) (msb << 4 | lsb);
+		}
+		return result;
+	}
+}

+ 96 - 0
applications/device/device-core/src/main/java/com/usoftchina/smartschool/device/crypto/HmacEncoder.java

@@ -0,0 +1,96 @@
+package com.usoftchina.smartschool.device.crypto;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * Hash-based message authentication code,利用哈希算法,以一个密钥和一个消息为输入,生成一个消息摘要作为输出
+ * 
+ * @author yingp
+ *
+ */
+public class HmacEncoder {
+
+	private final String algorithm;
+
+	public HmacEncoder(String algorithm) {
+		this.algorithm = algorithm;
+	}
+
+	/**
+	 * 根据给定密钥生成算法创建密钥
+	 * @return 密钥
+	 * @throws RuntimeException
+	 *             当 {@link NoSuchAlgorithmException} 发生时
+	 */
+	public byte[] getKey() {
+		// 初始化KeyGenerator
+		KeyGenerator keyGenerator = null;
+		try {
+			keyGenerator = KeyGenerator.getInstance(algorithm);
+		} catch (NoSuchAlgorithmException e) {
+			throw new RuntimeException(e.getMessage());
+		}
+		// 产生密钥
+		SecretKey secretKey = keyGenerator.generateKey();
+		// 获得密钥
+		return secretKey.getEncoded();
+	}
+
+	/**
+	 * 转换密钥
+	 * 
+	 * @param key
+	 *            二进制密钥
+	 * @param algorithm
+	 *            密钥算法
+	 * @return 密钥
+	 */
+	private static Key toKey(byte[] key, String algorithm) {
+		// 生成密钥
+		return new SecretKeySpec(key, algorithm);
+	}
+
+	/**
+	 * 使用指定消息摘要算法计算消息摘要
+	 * 
+	 * @param data
+	 *            做消息摘要的数据
+	 * @param key
+	 *            密钥
+	 * @return 消息摘要(长度为16的字节数组)
+	 */
+	public byte[] encode(byte[] data, Key key) {
+		Mac mac = null;
+		try {
+			mac = Mac.getInstance(algorithm);
+			mac.init(key);
+		} catch (NoSuchAlgorithmException e) {
+			e.printStackTrace();
+			return new byte[0];
+		} catch (InvalidKeyException e) {
+			e.printStackTrace();
+			return new byte[0];
+		}
+		return mac.doFinal(data);
+	}
+
+	/**
+	 * 使用指定消息摘要算法计算消息摘要
+	 * 
+	 * @param data
+	 *            做消息摘要的数据
+	 * @param key
+	 *            密钥
+	 * @return 消息摘要(长度为16的字节数组)
+	 */
+	public byte[] encode(byte[] data, byte[] key) {
+		return encode(data, toKey(key, algorithm));
+	}
+
+}

+ 9 - 0
applications/device/device-core/src/main/java/com/usoftchina/smartschool/device/crypto/HmacSHA256Encoder.java

@@ -0,0 +1,9 @@
+package com.usoftchina.smartschool.device.crypto;
+
+public class HmacSHA256Encoder extends HmacEncoder {
+
+	public HmacSHA256Encoder() {
+		super("HmacSHA256");
+	}
+
+}

+ 5 - 0
applications/school/school-server/src/main/java/com/usoftchina/smartschool/school/basic/controller/ClassController.java

@@ -36,4 +36,9 @@ public class ClassController {
         return Result.success();
     }
 
+    @PostMapping("/deleteDetail/{id}")
+    public Result deleteDetail(@PathVariable("id") Long id) {
+        classService.deleteDetail(id);
+        return Result.success();
+    }
 }

+ 2 - 0
applications/school/school-server/src/main/java/com/usoftchina/smartschool/school/basic/service/ClassService.java

@@ -9,4 +9,6 @@ public interface ClassService {
     DocBaseDTO saveFormData(ClassForm form);
 
     void delete(Long id);
+
+    void deleteDetail(Long id);
 }

+ 12 - 1
applications/school/school-server/src/main/java/com/usoftchina/smartschool/school/basic/service/impl/ClassServiceImpl.java

@@ -7,7 +7,11 @@ import com.usoftchina.smartschool.school.dto.DocBaseDTO;
 import com.usoftchina.smartschool.school.exception.BizExceptionCode;
 import com.usoftchina.smartschool.school.mapper.SysClazzMapper;
 import com.usoftchina.smartschool.school.mapper.SysStudentMapper;
-import com.usoftchina.smartschool.school.po.*;
+import com.usoftchina.smartschool.school.mapper.SysTeacherMapper;
+import com.usoftchina.smartschool.school.po.ClassForm;
+import com.usoftchina.smartschool.school.po.SysClazz;
+import com.usoftchina.smartschool.school.po.SysStudent;
+import com.usoftchina.smartschool.school.po.SysTeacherClazz;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.StringUtils;
@@ -26,6 +30,8 @@ public class ClassServiceImpl implements ClassService{
     private SysClazzMapper sysClazzMapper;
     @Autowired
     private SysStudentMapper sysStudentMapper;
+    @Autowired
+    private SysTeacherMapper sysTeacherMapper;
 
     @Override
     public ClassForm getFormdata(Long id) {
@@ -125,4 +131,9 @@ public class ClassServiceImpl implements ClassService{
         sysClazzMapper.deleteByPrimaryKey(id);
         sysStudentMapper.deleteTeacher(id);
     }
+
+    @Override
+    public void deleteDetail(Long id) {
+        sysTeacherMapper.deleteDetail(id);
+    }
 }

+ 5 - 0
applications/school/school-server/src/main/java/com/usoftchina/smartschool/school/basic/service/impl/TeacherServiceImpl.java

@@ -155,6 +155,11 @@ public class TeacherServiceImpl implements TeacherService{
                     teacher = JSONObject.parseObject(json.toJSONString(), SysTeacher.class);
                     teacher.setSchool_id(schoolId);
                     teacher.setTeacher_status(1);
+                    //新增账户,并更新教师表UserId字段
+                    if (!StringUtils.isEmpty(teacher.getTeacher_phone())) {
+                        Long userId = createAccount(teacher);
+                        teacher.setUser_id(userId);
+                    }
                     sysTeacherMapper.insertSelective(teacher);
                     teachers.add(teacher);
                     //年纪存在、需要更新

+ 2 - 0
applications/school/school-server/src/main/java/com/usoftchina/smartschool/school/mapper/SysTeacherMapper.java

@@ -42,4 +42,6 @@ public interface SysTeacherMapper {
     int checkTeacher(@Param("teacher_id") Long teacher_id);
 
     Integer checkTeacherSubjects(@Param("clazz_id") Long clazz_id);
+
+    void deleteDetail(@Param("teacher_clazz_id") Long teacher_clazz_id);
 }

+ 3 - 3
applications/school/school-server/src/main/resources/mapper/CurriculumMapper.xml

@@ -264,10 +264,10 @@
   </select>
 
   <update id="updateByPublish" parameterType="java.lang.Long">
-    update clazz_main_curriculum
-    set mcur_status = 1 ,
+    update clazz_main_curriculum,clazz_curriculum
+    set clazz_main_curriculum.mcur_status = 1 ,clazz_curriculum.cur_status = 1 ,
       createTime = now()
-    where id = #{id,jdbcType=BIGINT}
+    where id = #{id,jdbcType=BIGINT} and clazz_curriculum.cur_id=id
   </update>
 
   <update id="updateByRepublish" parameterType="java.lang.Long">

+ 1 - 1
applications/school/school-server/src/main/resources/mapper/SysStudentMapper.xml

@@ -486,6 +486,6 @@
   </select>
 
   <select id="selectIdByClazzId" resultType="string" parameterType="long">
-    SELECT stu_id FROM student WHERE clazz_id = #{clazzId}
+    SELECT stu_id FROM sys_student WHERE clazz_id = #{clazzId}
   </select>
 </mapper>

+ 4 - 0
applications/school/school-server/src/main/resources/mapper/SysTeacherMapper.xml

@@ -402,4 +402,8 @@ where sys_teacher_clazz.teacher_id=#{id}
   <select id="checkTeacherSubjects" parameterType="long" resultType="Integer">
     select count(*) from sys_teacher_clazz where  clazz_id= #{clazz_id}
   </select>
+
+  <delete id="deleteDetail">
+    DELETE FROM sys_teacher_clazz where teacher_clazz_id = #{teacher_clazz_id}
+  </delete>
 </mapper>

Some files were not shown because too many files changed in this diff