Browse Source

Merge remote-tracking branch 'origin/dev' into feature-cloud

guq 6 years ago
parent
commit
1934497240
23 changed files with 282 additions and 21 deletions
  1. 12 2
      applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/listener/AccessControlListener.java
  2. 48 1
      applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/po/AccessControl.java
  3. 10 4
      applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/repository/AccessControlRepository.java
  4. 4 0
      applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/service/AccessControlService.java
  5. 3 1
      applications/device/device-client/src/main/resources/schema.sql
  6. 9 0
      applications/device/device-client/src/main/resources/static/index.html
  7. 1 0
      applications/device/device-client/src/main/resources/static/js/index.js
  8. 12 3
      applications/device/device-sdk-dahua/src/main/java/com/usoftchina/smartschool/device/dahua/service/DahuaDataAnalyzeService.java
  9. 1 1
      applications/device/device-sdk-dahua/src/main/java/com/usoftchina/smartschool/device/dahua/service/DahuaDeviceService.java
  10. 8 0
      applications/device/device-sdk/src/main/java/com/usoftchina/smartschool/device/dto/DeviceInfo.java
  11. 12 1
      applications/device/device-sdk/src/main/java/com/usoftchina/smartschool/device/event/AccessControlEvent.java
  12. 4 0
      applications/device/device-server/src/main/java/com/usoftchina/smartschool/device/service/impl/AccessControlServiceImpl.java
  13. 3 1
      applications/device/device-server/src/main/resources/application.yml
  14. 3 1
      applications/device/device-server/src/main/resources/config/application-docker-cloud.yml
  15. 3 1
      applications/device/device-server/src/main/resources/config/application-docker-prod.yml
  16. 1 1
      frontend/pc-web/app/view/Interaction/homework/Release.js
  17. 1 1
      frontend/pc-web/app/view/Interaction/notice/SchoolNotice.js
  18. 1 1
      frontend/pc-web/app/view/core/form/field/ClassComboBox.js
  19. 23 0
      frontend/pc-web/app/view/setting/msgtemplate/Panel.js
  20. 116 0
      frontend/pc-web/app/view/setting/msgtemplate/PanelController.js
  21. 4 0
      frontend/pc-web/resources/json/navigation.json
  22. 3 2
      frontend/wechat-web/src/modules/hiPages/access-notice/ItemComp.js
  23. BIN
      frontend/wechat-web/src/style/imgs/no_data.png

+ 12 - 2
applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/listener/AccessControlListener.java

@@ -1,6 +1,8 @@
 package com.usoftchina.smartschool.device.client.listener;
 
+import com.usoftchina.smartschool.device.client.po.AccessControl;
 import com.usoftchina.smartschool.device.client.service.AccessControlService;
+import com.usoftchina.smartschool.device.dto.AccessControlInfo;
 import com.usoftchina.smartschool.device.event.AccessControlEvent;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -28,9 +30,17 @@ public class AccessControlListener {
     @Async
     @EventListener(AccessControlEvent.class)
     public void onAccessControlEvent(AccessControlEvent event) {
+        AccessControlInfo info = event.getAccessControlInfo();
+        AccessControl accessControl = accessControlService.findById(event.getDeviceId());
+        // 通过门禁设备绑定的访问类型,来设置本次事件的访问类型
+        if (accessControl.isEntryType()) {
+            info.setEventType(AccessControlInfo.EventType.ENTRY);
+        } else {
+            info.setEventType(AccessControlInfo.EventType.EXIT);
+        }
         if(logger.isDebugEnabled()) {
-            logger.debug(event.getAccessControlInfo().toString());
+            logger.debug(info.toString());
         }
-        accessControlService.saveRecord(event.getAccessControlInfo());
+        accessControlService.saveRecord(info);
     }
 }

+ 48 - 1
applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/po/AccessControl.java

@@ -1,12 +1,15 @@
 package com.usoftchina.smartschool.device.client.po;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.usoftchina.smartschool.device.dto.DeviceInfo;
 
+import java.util.Arrays;
+
 /**
  * @author yingp
  * @date 2019/3/11
  */
-public class AccessControl implements DeviceInfo{
+public class AccessControl implements DeviceInfo {
     private String id;
     /**
      * 名称
@@ -21,6 +24,11 @@ public class AccessControl implements DeviceInfo{
 
     private String password;
 
+    /**
+     * 闸机头绑定访问类型 1 进入 / 2 出去
+     */
+    private int accessType;
+
     public String getName() {
         return name;
     }
@@ -29,6 +37,7 @@ public class AccessControl implements DeviceInfo{
         this.name = name;
     }
 
+    @Override
     public String getId() {
         return id;
     }
@@ -72,4 +81,42 @@ public class AccessControl implements DeviceInfo{
     public void setPassword(String password) {
         this.password = password;
     }
+
+    public int getAccessType() {
+        return accessType;
+    }
+
+    public void setAccessType(int accessType) {
+        this.accessType = accessType;
+    }
+
+    /**
+     * 是否进门类型
+     *
+     * @return
+     */
+    @JsonIgnore
+    public boolean isEntryType() {
+        return AccessType.of(accessType) == AccessType.ENTRY;
+    }
+
+    public enum AccessType {
+        ENTRY(1),
+        EXIT(2);
+
+        private final int code;
+
+        AccessType(int code) {
+            this.code = code;
+        }
+
+        public static AccessType of(int code) {
+            for (AccessType type : values()) {
+                if (type.code == code) {
+                    return type;
+                }
+            }
+            return ENTRY;
+        }
+    }
 }

+ 10 - 4
applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/repository/AccessControlRepository.java

@@ -2,6 +2,8 @@ package com.usoftchina.smartschool.device.client.repository;
 
 import com.usoftchina.smartschool.device.client.po.AccessControl;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
 import org.springframework.dao.EmptyResultDataAccessException;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
@@ -38,6 +40,7 @@ public class AccessControlRepository {
         }
     }
 
+    @Cacheable(value = "accessControl", key = "#id")
     public AccessControl findById(String id) {
         try {
             return jdbcTemplate.queryForObject("select * from access_control where id=?",
@@ -47,20 +50,23 @@ public class AccessControlRepository {
         }
     }
 
+    @CacheEvict(value = "accessControl", key = "#accessControl.id")
     public boolean save(AccessControl accessControl) {
-        int ret = jdbcTemplate.update("insert into access_control(id, name,ip,port,username,password) values " +
+        int ret = jdbcTemplate.update("insert into access_control(id, name,ip,port,username,password,accessType) values " +
                         "(?,?,?,?,?,?)", accessControl.getId(), accessControl.getName(), accessControl.getIp(), accessControl.getPort(),
-                accessControl.getUsername(), accessControl.getPassword());
+                accessControl.getUsername(), accessControl.getPassword(), accessControl.getAccessType());
         return ret > 0;
     }
 
+    @CacheEvict(value = "accessControl", key = "#accessControl.id")
     public boolean update(AccessControl accessControl) {
-        int ret = jdbcTemplate.update("update access_control set name=?,ip=?,port=?,username=?,password=? where " +
+        int ret = jdbcTemplate.update("update access_control set name=?,ip=?,port=?,username=?,password=?,accessType=? where " +
                         "id=?", accessControl.getName(), accessControl.getIp(), accessControl.getPort(),
-                accessControl.getUsername(), accessControl.getPassword(), accessControl.getId());
+                accessControl.getUsername(), accessControl.getPassword(), accessControl.getAccessType(), accessControl.getId());
         return ret > 0;
     }
 
+    @CacheEvict(value = "accessControl", key = "#id")
     public boolean delete(String id) {
         return jdbcTemplate.update("delete from access_control where id=?", id) > 0;
     }

+ 4 - 0
applications/device/device-client/src/main/java/com/usoftchina/smartschool/device/client/service/AccessControlService.java

@@ -94,6 +94,10 @@ public class AccessControlService {
         }
     }
 
+    public AccessControl findById(String id) {
+        return accessControlRepository.findById(id);
+    }
+
     /**
      * 远程保存门禁记录
      *

+ 3 - 1
applications/device/device-client/src/main/resources/schema.sql

@@ -22,4 +22,6 @@ port int not null,
 username varchar(30) not null,
 password varchar(50) not null,
 databaseName varchar(30) not null
-);
+);
+
+alter table access_control add column if not exists accessType int default 1;

+ 9 - 0
applications/device/device-client/src/main/resources/static/index.html

@@ -68,6 +68,13 @@
                         <input type="password" class="form-control" id="passwordInput" name="password"
                                required aria-describedby="passwordHelp" placeholder="登录密码">
                     </div>
+                    <div class="form-group">
+                        <label for="accessTypeInput">访问类型</label>
+                        <select class="form-control" id="accessTypeInput" name="accessType">
+                            <option value="1">进门</option>
+                            <option value="2">出门</option>
+                        </select>
+                    </div>
                 </form>
             </div>
             <div class="modal-footer">
@@ -83,6 +90,7 @@
         <th scope="col">名称</th>
         <th scope="col">IP</th>
         <th scope="col">端口</th>
+        <th scope="col">访问类型</th>
         <th scope="col">操作</th>
     </tr>
     </thead>
@@ -95,6 +103,7 @@
         <td><%=data[i].name%></td>
         <td><%=data[i].ip%></td>
         <td><%=data[i].port%></td>
+        <td><%=data[i].accessType == 1 ? '进门' : '出门'%></td>
         <td>
             <button type="button" class="btn btn-link btn-edit" data-index="<%=i%>" title="编辑"
                     data-toggle="modal" data-target="#formModal">

+ 1 - 0
applications/device/device-client/src/main/resources/static/js/index.js

@@ -21,6 +21,7 @@ $(document).ready(function () {
                                 $('#portInput').val(accessControl.port);
                                 $('#usernameInput').val(accessControl.username);
                                 $('#passwordInput').val(accessControl.password);
+                                $('#accessTypeInput').val(accessControl.accessType);
                             });
                             $('.btn-delete').click(function(){
                                 var index = $(this).data('index'),

+ 12 - 3
applications/device/device-sdk-dahua/src/main/java/com/usoftchina/smartschool/device/dahua/service/DahuaDataAnalyzeService.java

@@ -39,13 +39,15 @@ public class DahuaDataAnalyzeService {
     /**
      * 启动智能数据监听
      *
+     * @param deviceId 门禁设备ID
      * @param loginHandle 登录句柄
      */
-    public void startListen(NativeLong loginHandle) {
+    public void startListen(String deviceId, NativeLong loginHandle) {
         long key = loginHandle.longValue();
         if (key != 0 && !analyzerHandles.containsKey(key)) {
             NativeLong lAnalyzerHandle = sdk.getInstance().CLIENT_RealLoadPictureEx(loginHandle, 0,
-                    DahuaEvents.EVENT_IVS_ALL, true, new AnalyzerDataCallBack(), new NativeLong(), null);
+                    DahuaEvents.EVENT_IVS_ALL, true, new AnalyzerDataCallBack(deviceId),
+                    new NativeLong(), null);
             analyzerHandles.put(key, lAnalyzerHandle);
         }
     }
@@ -54,6 +56,13 @@ public class DahuaDataAnalyzeService {
      * 智能分析数据回调
      */
     class AnalyzerDataCallBack implements fAnalyzerDataCallBack {
+        private final String deviceId;
+
+        public AnalyzerDataCallBack(String deviceId) {
+            super();
+            this.deviceId = deviceId;
+        }
+
         @Override
         public void invoke(NativeLong lAnalyzerHandle, int dwAlarmType, Pointer pAlarmInfo, Pointer pBuffer,
                            int dwBufSize, NativeLong dwUser, int nSequence, Pointer reserved) {
@@ -75,7 +84,7 @@ public class DahuaDataAnalyzeService {
                     accessControlInfo.setOpenMethod(convertOpenMethod(info.emOpenMethod));
                     accessControlInfo.setEventTime(info.UTC.toDate());
                     SpringContextHolder.getContext().publishEvent(new AccessControlEvent(this,
-                            accessControlInfo));
+                            deviceId, accessControlInfo));
                     // 其他地方可通过监听 AccessControlEvent 来扩展
                     break;
                 /**

+ 1 - 1
applications/device/device-sdk-dahua/src/main/java/com/usoftchina/smartschool/device/dahua/service/DahuaDeviceService.java

@@ -44,7 +44,7 @@ public class DahuaDeviceService implements DeviceApi {
             NativeLong loginHandle = login(info.getIp(), info.getPort(), info.getUsername(), info.getPassword());
             loginHandles.put(id, loginHandle);
             // 开启智能事件监听
-            dataAnalyzeService.startListen(loginHandle);
+            dataAnalyzeService.startListen(info.getId(), loginHandle);
         }
     }
 

+ 8 - 0
applications/device/device-sdk/src/main/java/com/usoftchina/smartschool/device/dto/DeviceInfo.java

@@ -7,6 +7,14 @@ package com.usoftchina.smartschool.device.dto;
  * @date 2019/3/8
  */
 public interface DeviceInfo {
+
+    /**
+     * ID
+     *
+     * @return
+     */
+    String getId();
+
     /**
      * ip
      *

+ 12 - 1
applications/device/device-sdk/src/main/java/com/usoftchina/smartschool/device/event/AccessControlEvent.java

@@ -11,13 +11,24 @@ import org.springframework.context.ApplicationEvent;
  */
 public class AccessControlEvent extends ApplicationEvent {
 
+    private final String deviceId;
     private final AccessControlInfo accessControlInfo;
 
-    public AccessControlEvent(Object source, AccessControlInfo accessControlInfo) {
+    public AccessControlEvent(Object source, String deviceId, AccessControlInfo accessControlInfo) {
         super(source);
+        this.deviceId = deviceId;
         this.accessControlInfo = accessControlInfo;
     }
 
+    /**
+     * 产生事件的门禁设备ID
+     *
+     * @return
+     */
+    public String getDeviceId() {
+        return deviceId;
+    }
+
     public AccessControlInfo getAccessControlInfo() {
         return accessControlInfo;
     }

+ 4 - 0
applications/device/device-server/src/main/java/com/usoftchina/smartschool/device/service/impl/AccessControlServiceImpl.java

@@ -49,6 +49,9 @@ public class AccessControlServiceImpl implements AccessControlService{
     @Value("${wechat.template.accesscontrol}")
     private String accessControlTemplateId;
 
+    @Value("${smartschool.domain.wechat}")
+    private String wechatBaseUrl;
+
     @Override
     public void onAccessControlEvent(AccessControlInfo info) {
         String filePath = null;
@@ -102,6 +105,7 @@ public class AccessControlServiceImpl implements AccessControlService{
          * 3、推送消息到消息服务器(微信服务监听此消息发送微信消息)
          */
         MessageInfoDTO msg = new MessageInfoDTO();
+        msg.setUrl(wechatBaseUrl + "/accessnoticedetail/" + record.getRecord_id());
         msg.setAppId(studentInfo.getAppId());
         msg.setSecret(studentInfo.getSecret());
         msg.setTouser(studentInfo.getOpenId());

+ 3 - 1
applications/device/device-server/src/main/resources/application.yml

@@ -76,4 +76,6 @@ mybatis:
   mapper-locations: classpath:mapper/*.xml
 smartschool:
   wechat:
-    pushUrl: https://school-api.ubtob.com/api/wechat/send/Messages
+    pushUrl: https://school-api.ubtob.com/api/wechat/send/Messages
+  domain:
+    wechat: https://school-wechat.ubtob.com

+ 3 - 1
applications/device/device-server/src/main/resources/config/application-docker-cloud.yml

@@ -23,4 +23,6 @@ spring:
         connection-timeout: 30000
 smartschool:
   wechat:
-    pushUrl: https://school-api.ydyhz.com/api/wechat/send/Messages
+    pushUrl: https://school-api.ydyhz.com/api/wechat/send/Messages
+  domain:
+    wechat: https://school-wechat.ydyhz.com

+ 3 - 1
applications/device/device-server/src/main/resources/config/application-docker-prod.yml

@@ -15,4 +15,6 @@ spring:
     port: 6379
 smartschool:
   wechat:
-    pushUrl: https://school-api.ubtob.com/api/wechat/send/Messages
+    pushUrl: https://school-api.ubtob.com/api/wechat/send/Messages
+  domain:
+    wechat: https://school-wechat.ubtob.com

+ 1 - 1
frontend/pc-web/app/view/Interaction/homework/Release.js

@@ -29,7 +29,7 @@ Ext.define('school.view.interaction.homework.Release', {
                 xtype: "textfield",
                 name: "task_creator",
                 fieldLabel: "发布人id",
-                defaultValue: school.util.BaseUtil.getCurrentUser().id,
+                defaultValue: school.util.BaseUtil.getCurrentUser().teacher_id,
                 hidden: true
             }, {
                 xtype: "textfield",

+ 1 - 1
frontend/pc-web/app/view/Interaction/notice/SchoolNotice.js

@@ -29,7 +29,7 @@ Ext.define('school.view.interaction.notice.SchoolNotice', {
                 name: "notify_creator",
                 fieldLabel: "发布人id",
                 columnWidth: 0.5,
-                defaultValue: school.util.BaseUtil.getCurrentUser().id,
+                defaultValue: school.util.BaseUtil.getCurrentUser().teacher_id,
                 hidden: true
             }, {
                 xtype: "textfield",

+ 1 - 1
frontend/pc-web/app/view/core/form/field/ClassComboBox.js

@@ -20,7 +20,7 @@ Ext.define('school.view.core.form.field.ClassComboBox', {
     // template for the content inside text field
     displayTpl: Ext.create('Ext.XTemplate',
         '<tpl for=".">',
-        '{clazz_name} | {clazz_grade}',
+        '{clazz_name}',
         '</tpl>'
     ),
 

+ 23 - 0
frontend/pc-web/app/view/setting/msgtemplate/Panel.js

@@ -0,0 +1,23 @@
+Ext.define('school.view.setting.msgtemplate.Panel', {
+    extend: 'Ext.form.Panel',
+    xtype: 'setting-msgtemplate-panel',
+
+    controller: 'setting-msgtemplate-panel',
+
+    layout: 'column',
+    autoScroll: true,
+    bodyPadding: '8 12 8 12',
+
+    fieldDefaults: {
+        margin: '0 0 10 0',
+        labelAlign: 'right',
+        labelWidth: 90,
+        columnWidth: 1,
+    },
+
+    items: [],
+
+    listeners: {
+        afterrender: 'afterrender'
+    }
+});

+ 116 - 0
frontend/pc-web/app/view/setting/msgtemplate/PanelController.js

@@ -0,0 +1,116 @@
+Ext.define('school.view.setting.msgtemplate.PanelController', {
+    extend: 'Ext.app.ViewController',
+    alias: 'controller.setting-msgtemplate-panel',
+    
+    afterrender: function() {
+        let me = this,
+        view = me.getView();
+
+        view.setLoading(true);
+        school.util.BaseUtil.request({
+            // url: 'http://10.1.80.47:9520/api/school/template/list'
+            url: '/api/school/template/list'
+        }).then(function(res) {
+            view.setLoading(false);
+            let data = res.data.list.map(function(l) {
+                return {
+                    id: l.st_id,
+                    title: l.st_name,
+                    templateId: l.st_templateid
+                }
+            })
+            if(data.length > 0) {
+                me.addTemplate(data);
+            }else {
+                me.addEmptyText();
+            }
+        }).catch(function(e) {
+            view.setLoading(false);
+            me.addEmptyText();
+            school.util.BaseUtil.showErrorToast(e.message);
+        });
+    },
+
+    update: function(btn) {
+        let container = btn.up('fieldcontainer'),
+        items = container.items.items,
+        valueField = items[0],
+        titleField = items[1],
+        templateIdField = items[2],
+        id = valueField.value,
+        title = titleField.value,
+        templateId = templateIdField.value;
+
+        if(!templateIdField.isDirty()) {
+            school.util.BaseUtil.showErrorToast('数据无修改');
+            return;
+        }
+
+        container.setLoading(true);
+        school.util.BaseUtil.request({
+            // url: 'http://10.1.80.47:9520/api/school/template/save',
+            url: '/api/school/template/save',
+            method: 'POST',
+            params: JSON.stringify({
+                st_id: id,
+                st_name: title,
+                st_templateid: templateId
+            })
+        }).then(function(res) {
+            container.setLoading(false);
+            templateIdField.originalValue = templateId;
+            school.util.BaseUtil.showSuccessToast('更新成功');
+        }).catch(function(e) {
+            container.setLoading(false);
+            school.util.BaseUtil.showErrorToast('更新失败: ' + e.message);
+        });
+    },
+
+    addTemplate: function(datas) {
+        let me = this,
+        view = me.getView();
+
+        if(datas.length > 0) {
+            Ext.Array.each(datas, function(data) {
+                view.add(me.applyTemplate(data));
+            });
+        }
+    },
+
+    addEmptyText: function() {
+        let me = this,
+        view = me.getView();
+
+        view.setHtml('暂无数据');
+    },
+
+    applyTemplate: function(data) {
+        let template = {
+            xtype: 'fieldcontainer',
+            layout: 'hbox',
+            items: [{
+                xtype: 'hidden',
+                fieldLabel: 'ID',
+                name: 'id',
+                value: data.id
+            }, {
+                xtype: 'displayfield',
+                fieldLabel: '模板标题',
+                name: 'title',
+                value: data.title
+            }, {
+                xtype: 'textfield',
+                fieldLabel: '模板ID',
+                name: 'templateId',
+                value: data.templateId
+            }, {
+                xtype: 'button',
+                text: '保存',
+                handler: 'update'
+            }] 
+        };
+
+        return template;
+    }
+
+});

+ 4 - 0
frontend/pc-web/resources/json/navigation.json

@@ -54,6 +54,10 @@
     "text": "系统设置",
     "iconCls": "x-ss ss-nav-setting",
     "items": [{
+        "id": "setting-msgtemplate-panel",
+        "text": "消息模板设置",
+        "view": "setting-msgtemplate-panel"
+    }, {
         "id": "setting-device-list",
         "text": "设备参数",
         "view": "setting-device-list"

+ 3 - 2
frontend/wechat-web/src/modules/hiPages/access-notice/ItemComp.js

@@ -15,7 +15,8 @@ export default class ItemComp extends Component{
    constructor(props){
         super(props);
         this.state = {
-            showTime1:(this.props.itemdata.inDate==''||this.props.itemdata.inDate==null) ? this.props.itemdata.outDate : this.props.itemdata.inDate,
+            // showTime1:(this.props.itemdata.inDate==''||this.props.itemdata.inDate==null) ? this.props.itemdata.outDate : this.props.itemdata.inDate,
+            showTime1:this.props.itemdata.recordDate
         }
     }
      render(){
@@ -28,7 +29,7 @@ export default class ItemComp extends Component{
                          style={{height: '100%', justifyContent: 'center', alignItems: 'center'}}>
                         {this.props.isFirst ? <div style={{flex: 1}}></div>
                             : <div style={{background: '#E9E9E9', flex: '1', width: '2px'}}></div>}
-                        {(this.props.itemdata.inDate==''||this.props.itemdata.inDate==null) ?
+                        { this.props.itemdata.recordType == 1  ?
                             <div className="item_in_out in">进</div> :
                             <div className="item_in_out out">出</div>
                         }

BIN
frontend/wechat-web/src/style/imgs/no_data.png