Commit dc0610f26c1d3ff3011a597b3423254f87580816
1 parent
4e11baf1
添加登入,登出查询功能
Showing
16 changed files
with
891 additions
and
0 deletions
src/main/java/com/bsth/WebAppConfiguration.java
| 1 | 1 | package com.bsth; |
| 2 | 2 | |
| 3 | 3 | import com.bsth.filter.ResourceFilter; |
| 4 | +import com.bsth.listener.UserLogoutSessionListener; | |
| 4 | 5 | import com.bsth.websocket.WebSocketHandshakeInterceptor; |
| 5 | 6 | import com.bsth.websocket.handler.RealControlSocketHandler; |
| 6 | 7 | import org.slf4j.Logger; |
| 7 | 8 | import org.slf4j.LoggerFactory; |
| 8 | 9 | import org.springframework.boot.context.embedded.FilterRegistrationBean; |
| 10 | +import org.springframework.boot.context.embedded.ServletListenerRegistrationBean; | |
| 9 | 11 | import org.springframework.context.annotation.Bean; |
| 10 | 12 | import org.springframework.context.annotation.ComponentScan; |
| 11 | 13 | import org.springframework.context.annotation.Configuration; |
| ... | ... | @@ -89,4 +91,17 @@ public class WebAppConfiguration extends WebMvcConfigurerAdapter implements WebS |
| 89 | 91 | logger.info("Websocket factory returned"); |
| 90 | 92 | return container; |
| 91 | 93 | } |
| 94 | + | |
| 95 | + //--------------------- 配置listener ---------------------// | |
| 96 | + @Bean | |
| 97 | + public ServletListenerRegistrationBean<UserLogoutSessionListener> UserLogoutSessionListenerRegistrationBean() { | |
| 98 | + ServletListenerRegistrationBean<UserLogoutSessionListener> userLogoutSessionListenerRegistrationBean = | |
| 99 | + new ServletListenerRegistrationBean<>(); | |
| 100 | + userLogoutSessionListenerRegistrationBean.setListener(userLogoutSessionListenerBean()); | |
| 101 | + return userLogoutSessionListenerRegistrationBean; | |
| 102 | + } | |
| 103 | + @Bean | |
| 104 | + public UserLogoutSessionListener userLogoutSessionListenerBean() { | |
| 105 | + return new UserLogoutSessionListener(); | |
| 106 | + } | |
| 92 | 107 | } | ... | ... |
src/main/java/com/bsth/controller/logger/UserSignController.java
0 → 100644
| 1 | +package com.bsth.controller.logger; | |
| 2 | + | |
| 3 | +import com.bsth.controller.schedule.BController; | |
| 4 | +import com.bsth.entity.logger.UserSign; | |
| 5 | +import org.springframework.web.bind.annotation.RequestMapping; | |
| 6 | +import org.springframework.web.bind.annotation.RestController; | |
| 7 | + | |
| 8 | +@RestController | |
| 9 | +@RequestMapping("logger_user_sign") | |
| 10 | +public class UserSignController extends BController<UserSign, Long> { | |
| 11 | + | |
| 12 | +} | ... | ... |
src/main/java/com/bsth/controller/sys/UserController.java
| ... | ... | @@ -8,6 +8,7 @@ import com.bsth.controller.sys.util.RSAUtils; |
| 8 | 8 | import com.bsth.entity.sys.CompanyAuthority; |
| 9 | 9 | import com.bsth.entity.sys.SysUser; |
| 10 | 10 | import com.bsth.security.util.SecurityUtils; |
| 11 | +import com.bsth.service.logger.UserSignService; | |
| 11 | 12 | import com.bsth.service.sys.CompanyAuthorityService; |
| 12 | 13 | import com.bsth.service.sys.SysUserService; |
| 13 | 14 | import com.google.common.collect.ArrayListMultimap; |
| ... | ... | @@ -39,6 +40,9 @@ public class UserController extends BaseController<SysUser, Integer> { |
| 39 | 40 | @Autowired |
| 40 | 41 | CompanyAuthorityService companyAuthorityService; |
| 41 | 42 | |
| 43 | + @Autowired | |
| 44 | + UserSignService userLogInoutService; | |
| 45 | + | |
| 42 | 46 | @RequestMapping(value = "/login/jCryptionKey") |
| 43 | 47 | public Map<String, Object> jCryptionKey(HttpServletRequest request) { |
| 44 | 48 | //公匙返回页面 |
| ... | ... | @@ -112,6 +116,9 @@ public class UserController extends BaseController<SysUser, Integer> { |
| 112 | 116 | |
| 113 | 117 | captchaMap.remove(userName); |
| 114 | 118 | rs.put("status", ResponseCode.SUCCESS); |
| 119 | + | |
| 120 | + // 记录登录日志 | |
| 121 | + userLogInoutService.userLogIn(user.getUserName(), session.getId(), new Date()); | |
| 115 | 122 | } catch (Exception e) { |
| 116 | 123 | logger.error("", e); |
| 117 | 124 | rs.put("msg", "服务器出现异常,请联系管理员"); | ... | ... |
src/main/java/com/bsth/entity/logger/UserSign.java
0 → 100644
| 1 | +package com.bsth.entity.logger; | |
| 2 | + | |
| 3 | +import javax.persistence.*; | |
| 4 | +import java.util.Date; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * 用户的登录登出日志。 | |
| 8 | + */ | |
| 9 | +@Entity | |
| 10 | +@Table(name = "logger_user_sign") | |
| 11 | +public class UserSign { | |
| 12 | + @Id | |
| 13 | + @GeneratedValue | |
| 14 | + private Long id; | |
| 15 | + | |
| 16 | + /** sessionId */ | |
| 17 | + @Column(nullable = false, unique = true) | |
| 18 | + private String sessionId; | |
| 19 | + | |
| 20 | + /** 登录用户名 */ | |
| 21 | + private String logName; | |
| 22 | + /** 实际用户名 */ | |
| 23 | + private String realName; | |
| 24 | + | |
| 25 | + /** 登录时间(包含日期和具体时刻)*/ | |
| 26 | + @Temporal(TemporalType.TIMESTAMP) | |
| 27 | + private Date logInDateTime; | |
| 28 | + /** 登录时间(只包含日期) */ | |
| 29 | + @Temporal(TemporalType.DATE) | |
| 30 | + private Date logInDate; | |
| 31 | + | |
| 32 | + /** 登出时间(包含日期和具体时刻)*/ | |
| 33 | + @Temporal(TemporalType.TIMESTAMP) | |
| 34 | + private Date logOutDateTime; | |
| 35 | + /** 登录时间(只包含日期) */ | |
| 36 | + @Temporal(TemporalType.DATE) | |
| 37 | + private Date logOutDate; | |
| 38 | + | |
| 39 | + @Version | |
| 40 | + private int version; | |
| 41 | + | |
| 42 | + public Long getId() { | |
| 43 | + return id; | |
| 44 | + } | |
| 45 | + | |
| 46 | + public void setId(Long id) { | |
| 47 | + this.id = id; | |
| 48 | + } | |
| 49 | + | |
| 50 | + public String getSessionId() { | |
| 51 | + return sessionId; | |
| 52 | + } | |
| 53 | + | |
| 54 | + public void setSessionId(String sessionId) { | |
| 55 | + this.sessionId = sessionId; | |
| 56 | + } | |
| 57 | + | |
| 58 | + public String getLogName() { | |
| 59 | + return logName; | |
| 60 | + } | |
| 61 | + | |
| 62 | + public void setLogName(String logName) { | |
| 63 | + this.logName = logName; | |
| 64 | + } | |
| 65 | + | |
| 66 | + public String getRealName() { | |
| 67 | + return realName; | |
| 68 | + } | |
| 69 | + | |
| 70 | + public void setRealName(String realName) { | |
| 71 | + this.realName = realName; | |
| 72 | + } | |
| 73 | + | |
| 74 | + public Date getLogInDateTime() { | |
| 75 | + return logInDateTime; | |
| 76 | + } | |
| 77 | + | |
| 78 | + public void setLogInDateTime(Date logInDateTime) { | |
| 79 | + this.logInDateTime = logInDateTime; | |
| 80 | + } | |
| 81 | + | |
| 82 | + public Date getLogInDate() { | |
| 83 | + return logInDate; | |
| 84 | + } | |
| 85 | + | |
| 86 | + public void setLogInDate(Date logInDate) { | |
| 87 | + this.logInDate = logInDate; | |
| 88 | + } | |
| 89 | + | |
| 90 | + public Date getLogOutDateTime() { | |
| 91 | + return logOutDateTime; | |
| 92 | + } | |
| 93 | + | |
| 94 | + public void setLogOutDateTime(Date logOutDateTime) { | |
| 95 | + this.logOutDateTime = logOutDateTime; | |
| 96 | + } | |
| 97 | + | |
| 98 | + public Date getLogOutDate() { | |
| 99 | + return logOutDate; | |
| 100 | + } | |
| 101 | + | |
| 102 | + public void setLogOutDate(Date logOutDate) { | |
| 103 | + this.logOutDate = logOutDate; | |
| 104 | + } | |
| 105 | + | |
| 106 | + public int getVersion() { | |
| 107 | + return version; | |
| 108 | + } | |
| 109 | + | |
| 110 | + public void setVersion(int version) { | |
| 111 | + this.version = version; | |
| 112 | + } | |
| 113 | +} | ... | ... |
src/main/java/com/bsth/listener/UserLogoutSessionListener.java
0 → 100644
| 1 | +package com.bsth.listener; | |
| 2 | + | |
| 3 | +import com.bsth.common.Constants; | |
| 4 | +import com.bsth.service.logger.UserSignService; | |
| 5 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 6 | + | |
| 7 | +import javax.servlet.http.HttpSession; | |
| 8 | +import javax.servlet.http.HttpSessionEvent; | |
| 9 | +import javax.servlet.http.HttpSessionListener; | |
| 10 | +import java.util.Date; | |
| 11 | + | |
| 12 | +public class UserLogoutSessionListener implements HttpSessionListener { | |
| 13 | + @Autowired | |
| 14 | + private UserSignService userLogInoutService; | |
| 15 | + | |
| 16 | + @Override | |
| 17 | + public void sessionCreated(HttpSessionEvent se) { | |
| 18 | + | |
| 19 | + } | |
| 20 | + | |
| 21 | + @Override | |
| 22 | + public void sessionDestroyed(HttpSessionEvent se) { | |
| 23 | + HttpSession httpSession = se.getSession(); | |
| 24 | + String userName = String.valueOf(httpSession.getAttribute(Constants.SESSION_USERNAME)); | |
| 25 | + String sessionId = httpSession.getId(); | |
| 26 | + | |
| 27 | + userLogInoutService.userLogOut(userName, sessionId, new Date()); | |
| 28 | + } | |
| 29 | +} | ... | ... |
src/main/java/com/bsth/repository/logger/UserSignRepository.java
0 → 100644
| 1 | +package com.bsth.repository.logger; | |
| 2 | + | |
| 3 | +import com.bsth.entity.logger.UserSign; | |
| 4 | +import com.bsth.repository.BaseRepository; | |
| 5 | +import org.springframework.stereotype.Repository; | |
| 6 | + | |
| 7 | +@Repository | |
| 8 | +public interface UserSignRepository extends BaseRepository<UserSign, Long> { | |
| 9 | + UserSign findBySessionId(String sessionId); | |
| 10 | +} | ... | ... |
src/main/java/com/bsth/service/logger/UserSignService.java
0 → 100644
| 1 | +package com.bsth.service.logger; | |
| 2 | + | |
| 3 | +import com.bsth.entity.logger.UserSign; | |
| 4 | +import com.bsth.service.schedule.BService; | |
| 5 | + | |
| 6 | +import java.util.Date; | |
| 7 | + | |
| 8 | +public interface UserSignService extends BService<UserSign, Long> { | |
| 9 | + | |
| 10 | + /** | |
| 11 | + * 用户登录日志。 | |
| 12 | + * @param userName 登录用户名 | |
| 13 | + * @param sessionId sessionId | |
| 14 | + * @param logInDate 登入时间 | |
| 15 | + */ | |
| 16 | + void userLogIn(String userName, String sessionId, Date logInDate); | |
| 17 | + | |
| 18 | + /** | |
| 19 | + * 用户登出日志。 | |
| 20 | + * @param userName 登录用户名 | |
| 21 | + * @param sessionId sessionId | |
| 22 | + * @param logOutDate 登出时间 | |
| 23 | + */ | |
| 24 | + void userLogOut(String userName, String sessionId, Date logOutDate); | |
| 25 | +} | ... | ... |
src/main/java/com/bsth/service/logger/impl/UserSignServiceImpl.java
0 → 100644
| 1 | +package com.bsth.service.logger.impl; | |
| 2 | + | |
| 3 | +import com.bsth.entity.logger.UserSign; | |
| 4 | +import com.bsth.entity.sys.SysUser; | |
| 5 | +import com.bsth.repository.logger.UserSignRepository; | |
| 6 | +import com.bsth.service.logger.UserSignService; | |
| 7 | +import com.bsth.service.schedule.exception.ScheduleException; | |
| 8 | +import com.bsth.service.schedule.impl.BServiceImpl; | |
| 9 | +import com.bsth.service.schedule.utils.DataToolsFile; | |
| 10 | +import com.bsth.service.sys.SysUserService; | |
| 11 | +import org.joda.time.DateTime; | |
| 12 | +import org.slf4j.Logger; | |
| 13 | +import org.slf4j.LoggerFactory; | |
| 14 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 15 | +import org.springframework.stereotype.Service; | |
| 16 | +import org.springframework.transaction.annotation.Isolation; | |
| 17 | +import org.springframework.transaction.annotation.Propagation; | |
| 18 | +import org.springframework.transaction.annotation.Transactional; | |
| 19 | + | |
| 20 | +import java.io.File; | |
| 21 | +import java.util.Date; | |
| 22 | +import java.util.List; | |
| 23 | +import java.util.Map; | |
| 24 | + | |
| 25 | +@Service | |
| 26 | +public class UserSignServiceImpl extends BServiceImpl<UserSign, Long> implements UserSignService { | |
| 27 | + /** 日志记录器 */ | |
| 28 | + private final static Logger LOG = LoggerFactory.getLogger(UserSignServiceImpl.class); | |
| 29 | + | |
| 30 | + @Autowired | |
| 31 | + private UserSignRepository userLogInoutRepository; | |
| 32 | + @Autowired | |
| 33 | + private SysUserService sysUserService; | |
| 34 | + | |
| 35 | + @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED) | |
| 36 | + @Override | |
| 37 | + public void userLogIn(String userName, String sessionId, Date logInDate) { | |
| 38 | + try { | |
| 39 | + SysUser user = sysUserService.findByUserName(userName); | |
| 40 | + if (user == null) { | |
| 41 | + LOG.warn("用户{}不存在!", userName); | |
| 42 | + return; | |
| 43 | + } | |
| 44 | + if (!user.isEnabled()) { | |
| 45 | + LOG.warn("用户{}被锁定!", userName); | |
| 46 | + } | |
| 47 | + | |
| 48 | + // joda日期转换 | |
| 49 | + DateTime _jodaDT = new DateTime(logInDate.getTime()); | |
| 50 | + | |
| 51 | + UserSign userLogInout = new UserSign(); | |
| 52 | + userLogInout.setLogName(userName); | |
| 53 | + userLogInout.setRealName(user.getName()); | |
| 54 | + userLogInout.setSessionId(sessionId); | |
| 55 | + userLogInout.setLogInDate(_jodaDT.dayOfWeek().roundFloorCopy().toDate()); // 登录时间(不带时分秒) | |
| 56 | + userLogInout.setLogInDateTime(_jodaDT.toDate()); // 登录时间(带时分秒) | |
| 57 | + | |
| 58 | + userLogInoutRepository.save(userLogInout); | |
| 59 | + | |
| 60 | + } catch (Exception exp) { | |
| 61 | + LOG.error("用户登录日志异常!", exp); | |
| 62 | + } | |
| 63 | + } | |
| 64 | + | |
| 65 | + @Override | |
| 66 | + public void userLogOut(String userName, String sessionId, Date logOutDate) { | |
| 67 | + try { | |
| 68 | + SysUser user = sysUserService.findByUserName(userName); | |
| 69 | + if (user == null) { | |
| 70 | + LOG.warn("用户{}不存在!", userName); | |
| 71 | + return; | |
| 72 | + } | |
| 73 | + if (!user.isEnabled()) { | |
| 74 | + LOG.warn("用户{}被锁定!", userName); | |
| 75 | + } | |
| 76 | + | |
| 77 | + // 根据sessionId查找对应的登录日志 | |
| 78 | + UserSign userLogInout = userLogInoutRepository.findBySessionId(sessionId); | |
| 79 | + | |
| 80 | + // joda日期转换 | |
| 81 | + DateTime _jodaDT = new DateTime(logOutDate.getTime()); | |
| 82 | + | |
| 83 | + if (userLogInout == null) { // 说明之前登录的操作没有记录日志 | |
| 84 | + userLogInout = new UserSign(); | |
| 85 | + userLogInout.setLogName(userName); | |
| 86 | + userLogInout.setRealName(user.getName()); | |
| 87 | + userLogInout.setSessionId(sessionId); | |
| 88 | + userLogInout.setLogOutDate(_jodaDT.dayOfWeek().roundFloorCopy().toDate()); // 登出时间(不带时分秒) | |
| 89 | + userLogInout.setLogOutDateTime(_jodaDT.toDate()); // 登出时间(带时分秒) | |
| 90 | + } else { | |
| 91 | + userLogInout.setLogOutDate(_jodaDT.dayOfWeek().roundFloorCopy().toDate()); // 登出时间(不带时分秒) | |
| 92 | + userLogInout.setLogOutDateTime(_jodaDT.toDate()); // 登出时间(带时分秒) | |
| 93 | + } | |
| 94 | + | |
| 95 | + userLogInoutRepository.save(userLogInout); | |
| 96 | + | |
| 97 | + } catch (Exception exp) { | |
| 98 | + LOG.error("用户登出日志异常!", exp); | |
| 99 | + } | |
| 100 | + } | |
| 101 | + | |
| 102 | + @Override | |
| 103 | + public UserSign save(UserSign userLogInout) { | |
| 104 | + throw new RuntimeException("不支持save方法!"); | |
| 105 | + } | |
| 106 | + | |
| 107 | + @Override | |
| 108 | + public <S extends UserSign> List<S> bulkSave(List<S> entities) { | |
| 109 | + throw new RuntimeException("不支持bulkSave方法!"); | |
| 110 | + } | |
| 111 | + | |
| 112 | + @Override | |
| 113 | + public void delete(Long aLong) throws ScheduleException { | |
| 114 | + throw new RuntimeException("不支持delete方法!"); | |
| 115 | + } | |
| 116 | + | |
| 117 | + @Override | |
| 118 | + public DataToolsFile uploadFile(String filename, byte[] filedata) throws ScheduleException { | |
| 119 | + throw new RuntimeException("不支持uploadFile方法!"); | |
| 120 | + } | |
| 121 | + | |
| 122 | + @Override | |
| 123 | + public void importData(File file, Map<String, Object> params) throws ScheduleException { | |
| 124 | + throw new RuntimeException("不支持importData方法!"); | |
| 125 | + } | |
| 126 | +} | ... | ... |
src/main/resources/static/pages/scheduleApp/Gruntfile.js
| ... | ... | @@ -117,6 +117,7 @@ module.exports = function (grunt) { |
| 117 | 117 | 'module/core/scheduleRuleManage/route.js', // 排班规则管理模块 |
| 118 | 118 | 'module/core/ttInfoManage/route.js', // 时刻表管理模块 |
| 119 | 119 | 'module/core/ttInfoManage/detailedit/route.js', // 时刻表明细管理模块 |
| 120 | + "module/sys/userSignManage/route.js", // 用户登录日志管理模块 | |
| 120 | 121 | 'module/core/ttInfoManage2/route.js' // 智能时刻表管理模块 |
| 121 | 122 | ], |
| 122 | 123 | dest: 'module/common/prj-common-ui-route-state.js' |
| ... | ... | @@ -137,6 +138,7 @@ module.exports = function (grunt) { |
| 137 | 138 | 'module/core/schedulePlanManage/service.js', // 排班计划管理service |
| 138 | 139 | 'module/core/scheduleRuleManage/service.js', // 排班规则管理service |
| 139 | 140 | 'module/core/ttInfoManage/service.js', // 时刻表管理service |
| 141 | + "module/sys/userSignManage/service.js", // 用户登录日志管理service | |
| 140 | 142 | 'module/common/prj-common-globalservice-legacy.js' // 其他用service |
| 141 | 143 | ], |
| 142 | 144 | dest: 'module/common/prj-common-globalservice.js' | ... | ... |
src/main/resources/static/pages/scheduleApp/module/common/prj-common-globalservice.js
| ... | ... | @@ -885,6 +885,53 @@ angular.module('ScheduleApp').factory( |
| 885 | 885 | |
| 886 | 886 | ] |
| 887 | 887 | ); |
| 888 | +// 用户登录日志service | |
| 889 | +angular.module('ScheduleApp').factory( | |
| 890 | + "UserSignManageService_g", | |
| 891 | + [ | |
| 892 | + '$resource', | |
| 893 | + function($resource) { | |
| 894 | + return { | |
| 895 | + rest: $resource( | |
| 896 | + "/logger_user_sign/:id", | |
| 897 | + {id: '@id'}, | |
| 898 | + { | |
| 899 | + list: { | |
| 900 | + method: 'GET', | |
| 901 | + params: { | |
| 902 | + page: 0 | |
| 903 | + }, | |
| 904 | + transformResponse: function(rs) { | |
| 905 | + var dst = angular.fromJson(rs); | |
| 906 | + if (dst.status == 'SUCCESS') { | |
| 907 | + return dst.data; | |
| 908 | + } else { | |
| 909 | + return dst; // 业务错误留给控制器处理 | |
| 910 | + } | |
| 911 | + } | |
| 912 | + } | |
| 913 | + } | |
| 914 | + ), | |
| 915 | + dataTools: $resource( | |
| 916 | + '/logger_user_sign/:type', | |
| 917 | + {}, | |
| 918 | + { | |
| 919 | + dataExport: { | |
| 920 | + method: 'GET', | |
| 921 | + responseType: "arraybuffer", | |
| 922 | + params: { | |
| 923 | + type: "exportFile" | |
| 924 | + }, | |
| 925 | + transformResponse: function(data, headers){ | |
| 926 | + return {data : data}; | |
| 927 | + } | |
| 928 | + } | |
| 929 | + } | |
| 930 | + ) | |
| 931 | + }; | |
| 932 | + } | |
| 933 | + ] | |
| 934 | +); | |
| 888 | 935 | // 项目通用的全局service服务,供不同的controller使用,自定义指令不使用 |
| 889 | 936 | |
| 890 | 937 | // 文件下载服务 | ... | ... |
src/main/resources/static/pages/scheduleApp/module/common/prj-common-ui-route-state.js
| ... | ... | @@ -1288,6 +1288,42 @@ ScheduleApp.config([ |
| 1288 | 1288 | |
| 1289 | 1289 | } |
| 1290 | 1290 | ]); |
| 1291 | +// ui route 配置 | |
| 1292 | + | |
| 1293 | +/** 用户登录日志模块配置route */ | |
| 1294 | +ScheduleApp.config([ | |
| 1295 | + '$stateProvider', | |
| 1296 | + '$urlRouterProvider', | |
| 1297 | + function($stateProvider, $urlRouterProvider) { | |
| 1298 | + $stateProvider | |
| 1299 | + .state("userSignManage", { // index页面 | |
| 1300 | + url: "/userSignManage", | |
| 1301 | + views: { | |
| 1302 | + "": { | |
| 1303 | + templateUrl: "pages/scheduleApp/module/sys/userSignManage/index.html" | |
| 1304 | + }, | |
| 1305 | + "userSignManage_list@userSignManage": { | |
| 1306 | + templateUrl: "pages/scheduleApp/module/sys/userSignManage/list.html" | |
| 1307 | + } | |
| 1308 | + }, | |
| 1309 | + | |
| 1310 | + resolve: { | |
| 1311 | + deps: ["$ocLazyLoad", function($ocLazyLoad) { | |
| 1312 | + return $ocLazyLoad.load({ | |
| 1313 | + name: 'userSignManage_module', | |
| 1314 | + insertBefore: '#ng_load_plugins_before', // 动态载入模块时放置的位置 | |
| 1315 | + files: [ | |
| 1316 | + "assets/bower_components/angular-ui-select/dist/select.min.css", | |
| 1317 | + "assets/bower_components/angular-ui-select/dist/select.min.js", | |
| 1318 | + "assets/bower_components/angular-file-upload/dist/angular-file-upload.min.js", | |
| 1319 | + "pages/scheduleApp/module/sys/userSignManage/module.js" | |
| 1320 | + ] | |
| 1321 | + }); | |
| 1322 | + }] | |
| 1323 | + } | |
| 1324 | + }) | |
| 1325 | + } | |
| 1326 | +]); | |
| 1291 | 1327 | // ui route 配置 |
| 1292 | 1328 | |
| 1293 | 1329 | /** 时刻表管理配置route */ | ... | ... |
src/main/resources/static/pages/scheduleApp/module/sys/userSignManage/index.html
0 → 100644
| 1 | +<div class="page-head"> | |
| 2 | + <div class="page-title"> | |
| 3 | + <h1>用户登录日志管理</h1> | |
| 4 | + </div> | |
| 5 | +</div> | |
| 6 | + | |
| 7 | +<ul class="page-breadcrumb breadcrumb"> | |
| 8 | + <li> | |
| 9 | + <a href="/pages/home.html" data-pjax>首页</a> | |
| 10 | + <i class="fa fa-circle"></i> | |
| 11 | + </li> | |
| 12 | + <li> | |
| 13 | + <span class="active">权限管理</span> | |
| 14 | + <i class="fa fa-circle"></i> | |
| 15 | + </li> | |
| 16 | + <li> | |
| 17 | + <span class="active">用户登录日志管理</span> | |
| 18 | + </li> | |
| 19 | +</ul> | |
| 20 | + | |
| 21 | +<div class="row"> | |
| 22 | + <div class="col-md-12" ng-controller="UserSignManageCtrl as ctrl"> | |
| 23 | + <style> | |
| 24 | + .dropdown-menu { | |
| 25 | + border-color: #32c5d2; | |
| 26 | + } | |
| 27 | + .btn-group > .dropdown-menu:before { | |
| 28 | + border-bottom-color: #32c5d2; | |
| 29 | + } | |
| 30 | + </style> | |
| 31 | + | |
| 32 | + <div class="portlet light bordered"> | |
| 33 | + <div class="portlet-title"> | |
| 34 | + <div class="caption font-dark"> | |
| 35 | + <i class="fa fa-database font-dark"></i> | |
| 36 | + <span class="caption-subject bold uppercase">用户登录日志</span> | |
| 37 | + </div> | |
| 38 | + <div class="actions"> | |
| 39 | + | |
| 40 | + <div class="btn-group"> | |
| 41 | + <a href="javascript:" class="btn red btn-outline" data-toggle="dropdown"> | |
| 42 | + <i class="fa fa-share"></i> | |
| 43 | + <span>数据工具</span> | |
| 44 | + <i class="fa fa-angle-down"></i> | |
| 45 | + </a> | |
| 46 | + <ul class="dropdown-menu pull-right"> | |
| 47 | + | |
| 48 | + <li> | |
| 49 | + <a href="javascript:" class="tool-action" ng-click="ctrl.exportData()"> | |
| 50 | + <i class="fa fa-file-excel-o"></i> | |
| 51 | + 导出excel | |
| 52 | + </a> | |
| 53 | + </li> | |
| 54 | + | |
| 55 | + </ul> | |
| 56 | + </div> | |
| 57 | + </div> | |
| 58 | + </div> | |
| 59 | + | |
| 60 | + <div class="portlet-body"> | |
| 61 | + <div ui-view="userSignManage_list"></div> | |
| 62 | + </div> | |
| 63 | + </div> | |
| 64 | + </div> | |
| 65 | +</div> | |
| 0 | 66 | \ No newline at end of file | ... | ... |
src/main/resources/static/pages/scheduleApp/module/sys/userSignManage/list.html
0 → 100644
| 1 | +<!-- ui-route userLoginManage_list --> | |
| 2 | +<div ng-controller="UserSignManageListCtrl as ctrl"> | |
| 3 | + <div class="fixDiv"> | |
| 4 | + <table class="table fixTable table-striped table-bordered table-hover table-checkable order-column"> | |
| 5 | + <thead> | |
| 6 | + <tr role="row" class="heading"> | |
| 7 | + <th style="width:70px;">序号</th> | |
| 8 | + <th style="width: 150px;">登录用户名</th> | |
| 9 | + <th style="width: 150px;">实际用户名</th> | |
| 10 | + <th style="width: 450px;">登入/登出时间</th> | |
| 11 | + <th >操作</th> | |
| 12 | + </tr> | |
| 13 | + <tr role="row" class="filter"> | |
| 14 | + <td></td> | |
| 15 | + <td> | |
| 16 | + <input type="text" class="form-control form-filter input-sm" ng-model="ctrl.searchCondition().logName_like" placeholder="输入登录用户名..."/> | |
| 17 | + </td> | |
| 18 | + <td> | |
| 19 | + <input type="text" class="form-control form-filter input-sm" ng-model="ctrl.searchCondition().realName_like" placeholder="输入实际用户名..."/> | |
| 20 | + </td> | |
| 21 | + | |
| 22 | + <td> | |
| 23 | + <div class="input-group" style="width:220px;"> | |
| 24 | + <input type="text" class="form-control input-sm" | |
| 25 | + name="statFromDateTime" placeholder="选择日期..." | |
| 26 | + uib-datepicker-popup="yyyy-MM-dd" | |
| 27 | + is-open="ctrl.statFromDateTime_open" | |
| 28 | + ng-model="ctrl.statFromDateWithConditionGetSetFun" | |
| 29 | + ng-model-options="{ getterSetter: true }" readonly/> | |
| 30 | + <span class="input-group-btn"> | |
| 31 | + <button type="button" class="btn btn-default btn-sm" ng-click="ctrl.statFromDateTime_open_fun()"> | |
| 32 | + <i class="glyphicon glyphicon-calendar"></i> | |
| 33 | + </button> | |
| 34 | + </span> | |
| 35 | + </div> | |
| 36 | + | |
| 37 | + </td> | |
| 38 | + | |
| 39 | + <td> | |
| 40 | + <button class="btn btn-sm green btn-outline filter-submit margin-bottom" style="margin-right: 0;" | |
| 41 | + ng-click="ctrl.doPage()"> | |
| 42 | + <i class="fa fa-search"></i> | |
| 43 | + 搜索 | |
| 44 | + </button> | |
| 45 | + | |
| 46 | + <button class="btn btn-sm red btn-outline filter-cancel" | |
| 47 | + ng-click="ctrl.reset()"> | |
| 48 | + <i class="fa fa-times"></i> | |
| 49 | + 重置 | |
| 50 | + </button> | |
| 51 | + | |
| 52 | + </td> | |
| 53 | + | |
| 54 | + </tr> | |
| 55 | + </thead> | |
| 56 | + <tbody> | |
| 57 | + <tr ng-repeat="info in ctrl.page()['content']" class="odd gradeX"> | |
| 58 | + <td> | |
| 59 | + <div> | |
| 60 | + <a href="#"> | |
| 61 | + <i class="fa fa-list-ol" aria-hidden="true"></i> | |
| 62 | + {{$index + ctrl.page().number * 10 + 1}} | |
| 63 | + </a> | |
| 64 | + </div> | |
| 65 | + </td> | |
| 66 | + <td> | |
| 67 | + <span ng-bind="info.logName"></span> | |
| 68 | + </td> | |
| 69 | + <td> | |
| 70 | + <span ng-bind="info.realName"></span> | |
| 71 | + </td> | |
| 72 | + <td> | |
| 73 | + <div style="float: left; width:200px; padding-right: 20px;"> | |
| 74 | + <a href="#"> | |
| 75 | + <i class="fa fa-sign-in" aria-hidden="true"></i> | |
| 76 | + 登入 <span ng-bind="info.logInDateTime | date: 'yyyy-MM-dd HH:mm:ss'"></span> | |
| 77 | + </a> | |
| 78 | + </div> | |
| 79 | + <div style="float: left;"> | |
| 80 | + <a href="#"> | |
| 81 | + <i class="fa fa-sign-out" aria-hidden="true"></i> | |
| 82 | + 登出 <span ng-bind="info.logOutDateTime | date: 'yyyy-MM-dd HH:mm:ss'"></span> | |
| 83 | + </a> | |
| 84 | + </div> | |
| 85 | + </td> | |
| 86 | + | |
| 87 | + <td></td> | |
| 88 | + </tr> | |
| 89 | + </tbody> | |
| 90 | + </table> | |
| 91 | + </div> | |
| 92 | + | |
| 93 | + <div class="pageBar"> | |
| 94 | + <div class="pageBarLeft"> | |
| 95 | + {{'显示从' + ctrl.page()['uiFromRecord'] + '到' + ctrl.page()['uiToRecord'] + ' 共' + ctrl.page()['totalElements'] + '条' + ' 每页显示10条'}} | |
| 96 | + </div> | |
| 97 | + | |
| 98 | + <div class="pageBarRight"> | |
| 99 | + <uib-pagination total-items="ctrl.page()['totalElements']" | |
| 100 | + ng-model="ctrl.page()['uiNumber']" | |
| 101 | + ng-change="ctrl.doPage()" | |
| 102 | + rotate="false" | |
| 103 | + max-size="10" | |
| 104 | + boundary-links="true" | |
| 105 | + first-text="首页" | |
| 106 | + previous-text="上一页" | |
| 107 | + next-text="下一页" | |
| 108 | + last-text="尾页"> | |
| 109 | + </uib-pagination> | |
| 110 | + </div> | |
| 111 | + </div> | |
| 112 | + | |
| 113 | +</div> | ... | ... |
src/main/resources/static/pages/scheduleApp/module/sys/userSignManage/module.js
0 → 100644
| 1 | +// 用户登录日志管理 | |
| 2 | + | |
| 3 | +angular.module('ScheduleApp').factory( | |
| 4 | + 'UserSignManageService', | |
| 5 | + [ | |
| 6 | + 'UserSignManageService_g', | |
| 7 | + function(service) { | |
| 8 | + /** 当前的查询条件信息 */ | |
| 9 | + var currentSearchCondition = { | |
| 10 | + page: 0, | |
| 11 | + "logName_like" : "", | |
| 12 | + "realName_like" : "" | |
| 13 | + }; | |
| 14 | + // 当前查询返回的信息 | |
| 15 | + var currentPage = { // 后台spring data返回的格式 | |
| 16 | + totalElements: 0, | |
| 17 | + number: 0, // 后台返回的页码,spring返回从0开始 | |
| 18 | + content: [], | |
| 19 | + | |
| 20 | + uiNumber: 1, // 页面绑定的页码 | |
| 21 | + uiFromRecord: 0, // 页面绑定,当前页第几条记录 | |
| 22 | + uiToRecord: 0 // 页面绑定,当前页到第几条记录 | |
| 23 | + }; | |
| 24 | + | |
| 25 | + // 查询对象 | |
| 26 | + var queryClass = service.rest; | |
| 27 | + | |
| 28 | + return { | |
| 29 | + getQueryClass: function() { | |
| 30 | + return queryClass; | |
| 31 | + }, | |
| 32 | + /** | |
| 33 | + * 获取查询条件信息, | |
| 34 | + * 用于给controller用来和页面数据绑定。 | |
| 35 | + */ | |
| 36 | + getSearchCondition: function() { | |
| 37 | + currentSearchCondition.page = currentPage.uiNumber - 1; | |
| 38 | + return currentSearchCondition; | |
| 39 | + }, | |
| 40 | + /** | |
| 41 | + * 组装查询参数,返回一个promise查询结果。 | |
| 42 | + * @param params 查询参数 | |
| 43 | + * @return 返回一个 promise | |
| 44 | + */ | |
| 45 | + getPage: function(page) { | |
| 46 | + if (page) { | |
| 47 | + currentPage.totalElements = page.totalElements; | |
| 48 | + currentPage.number = page.number; | |
| 49 | + currentPage.content = page.content; | |
| 50 | + | |
| 51 | + // 计算当前页开始记录,结束记录 | |
| 52 | + if (page.numberOfElements && page.numberOfElements > 0) { | |
| 53 | + currentPage.uiFromRecord = page.number * 10 + 1; | |
| 54 | + currentPage.uiToRecord = page.number * 10 + page.numberOfElements; | |
| 55 | + } | |
| 56 | + } | |
| 57 | + return currentPage; | |
| 58 | + }, | |
| 59 | + resetStatus: function() { | |
| 60 | + currentSearchCondition = {page: 0}; | |
| 61 | + currentPage = { | |
| 62 | + totalElements: 0, | |
| 63 | + number: 0, | |
| 64 | + content: [], | |
| 65 | + uiNumber: 1, | |
| 66 | + uiFromRecord: 0, | |
| 67 | + uiToRecord: 0 | |
| 68 | + }; | |
| 69 | + }, | |
| 70 | + | |
| 71 | + /** | |
| 72 | + * 数据导出。 | |
| 73 | + * @returns {*|Function|promise|n} | |
| 74 | + */ | |
| 75 | + dataExport: function(query) { | |
| 76 | + if (UserPrincipal.getGsStrsQuery().length > 0) { | |
| 77 | + return service.dataTools.dataExport( | |
| 78 | + {'QUERY': query} | |
| 79 | + ).$promise; | |
| 80 | + } else { | |
| 81 | + return null; | |
| 82 | + } | |
| 83 | + } | |
| 84 | + }; | |
| 85 | + } | |
| 86 | + ] | |
| 87 | +); | |
| 88 | + | |
| 89 | +// index.html控制器 | |
| 90 | +angular.module('ScheduleApp').controller( | |
| 91 | + 'UserSignManageCtrl', | |
| 92 | + [ | |
| 93 | + 'UserSignManageService', | |
| 94 | + '$state', | |
| 95 | + 'FileDownload_g', | |
| 96 | + function(busInfoManageService, $state, fileDownload) { | |
| 97 | + var self = this; | |
| 98 | + | |
| 99 | + // 导出excel | |
| 100 | + self.exportData = function() { | |
| 101 | + // 组装查询条件 | |
| 102 | + var QUERY = []; | |
| 103 | + var key_map = { | |
| 104 | + "logName": "logName_like", | |
| 105 | + "realName": "realName_like" | |
| 106 | + }; | |
| 107 | + | |
| 108 | + var key; | |
| 109 | + var value; | |
| 110 | + var field; | |
| 111 | + var condition = busInfoManageService.getSearchCondition(); | |
| 112 | + for (key in key_map) { | |
| 113 | + value = condition[key_map[key]]; | |
| 114 | + if (value !== undefined && value !== "") { | |
| 115 | + field = key; | |
| 116 | + QUERY.push(field + " = " + "'" + value + "'"); | |
| 117 | + } | |
| 118 | + } | |
| 119 | + | |
| 120 | + var p = busInfoManageService.dataExport(QUERY.join(" and ")); | |
| 121 | + if (p) { | |
| 122 | + p.then( | |
| 123 | + function(result) { | |
| 124 | + fileDownload.downloadFile(result.data, "application/octet-stream", "用户登录日志.xls"); | |
| 125 | + }, | |
| 126 | + function(result) { | |
| 127 | + console.log("exportData failed:" + result); | |
| 128 | + } | |
| 129 | + ); | |
| 130 | + } | |
| 131 | + | |
| 132 | + }; | |
| 133 | + } | |
| 134 | + ] | |
| 135 | +); | |
| 136 | + | |
| 137 | +// list.html控制器 | |
| 138 | +angular.module('ScheduleApp').controller( | |
| 139 | + 'UserSignManageListCtrl', | |
| 140 | + [ | |
| 141 | + 'UserSignManageService', | |
| 142 | + function(service) { | |
| 143 | + var self = this; | |
| 144 | + | |
| 145 | + // 日期 日期控件开关 | |
| 146 | + self.statFromDateTime_open = false; | |
| 147 | + self.statFromDateTime_open_fun = function() { | |
| 148 | + self.statFromDateTime_open = true; | |
| 149 | + }; | |
| 150 | + self.statFromDateTime = null; | |
| 151 | + self.statFromDateWithConditionGetSetFun = function(value) { | |
| 152 | + if (arguments.length == 0) { // 作为get方法 | |
| 153 | + return self.statFromDateTime; | |
| 154 | + } else { | |
| 155 | + self.statFromDateTime = value; | |
| 156 | + if (value) { | |
| 157 | + // 计算条件,当前日期添加一天组成范围查询 | |
| 158 | + var _date = moment(self.statFromDateTime); | |
| 159 | + var _date_plus_day_1 = moment(self.statFromDateTime).add(1, 'd'); | |
| 160 | + service.getSearchCondition()['logInDateTime_ge'] = _date.toDate(); | |
| 161 | + service.getSearchCondition()['logInDateTime_le'] = _date_plus_day_1.toDate(); | |
| 162 | + } | |
| 163 | + | |
| 164 | + } | |
| 165 | + }; | |
| 166 | + | |
| 167 | + var UserLogInOut = service.getQueryClass(); | |
| 168 | + | |
| 169 | + self.page = function() { | |
| 170 | + return service.getPage(); | |
| 171 | + }; | |
| 172 | + | |
| 173 | + self.searchCondition = function() { | |
| 174 | + return service.getSearchCondition(); | |
| 175 | + }; | |
| 176 | + | |
| 177 | + self.doPage = function() { | |
| 178 | + var result = UserLogInOut.list(self.searchCondition(), function() { | |
| 179 | + if (!result.status) { | |
| 180 | + service.getPage(result); | |
| 181 | + } | |
| 182 | + }); | |
| 183 | + }; | |
| 184 | + self.reset = function() { | |
| 185 | + service.resetStatus(); | |
| 186 | + self.statFromDateWithConditionGetSetFun(null); | |
| 187 | + var result = UserLogInOut.list(self.searchCondition(), function() { | |
| 188 | + if (!result.status) { | |
| 189 | + service.getPage(result); | |
| 190 | + } | |
| 191 | + }); | |
| 192 | + }; | |
| 193 | + | |
| 194 | + self.doPage(); | |
| 195 | + | |
| 196 | + } | |
| 197 | + ] | |
| 198 | +); | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | ... | ... |
src/main/resources/static/pages/scheduleApp/module/sys/userSignManage/route.js
0 → 100644
| 1 | +// ui route 配置 | |
| 2 | + | |
| 3 | +/** 用户登录日志模块配置route */ | |
| 4 | +ScheduleApp.config([ | |
| 5 | + '$stateProvider', | |
| 6 | + '$urlRouterProvider', | |
| 7 | + function($stateProvider, $urlRouterProvider) { | |
| 8 | + $stateProvider | |
| 9 | + .state("userSignManage", { // index页面 | |
| 10 | + url: "/userSignManage", | |
| 11 | + views: { | |
| 12 | + "": { | |
| 13 | + templateUrl: "pages/scheduleApp/module/sys/userSignManage/index.html" | |
| 14 | + }, | |
| 15 | + "userSignManage_list@userSignManage": { | |
| 16 | + templateUrl: "pages/scheduleApp/module/sys/userSignManage/list.html" | |
| 17 | + } | |
| 18 | + }, | |
| 19 | + | |
| 20 | + resolve: { | |
| 21 | + deps: ["$ocLazyLoad", function($ocLazyLoad) { | |
| 22 | + return $ocLazyLoad.load({ | |
| 23 | + name: 'userSignManage_module', | |
| 24 | + insertBefore: '#ng_load_plugins_before', // 动态载入模块时放置的位置 | |
| 25 | + files: [ | |
| 26 | + "assets/bower_components/angular-ui-select/dist/select.min.css", | |
| 27 | + "assets/bower_components/angular-ui-select/dist/select.min.js", | |
| 28 | + "assets/bower_components/angular-file-upload/dist/angular-file-upload.min.js", | |
| 29 | + "pages/scheduleApp/module/sys/userSignManage/module.js" | |
| 30 | + ] | |
| 31 | + }); | |
| 32 | + }] | |
| 33 | + } | |
| 34 | + }) | |
| 35 | + } | |
| 36 | +]); | |
| 0 | 37 | \ No newline at end of file | ... | ... |
src/main/resources/static/pages/scheduleApp/module/sys/userSignManage/service.js
0 → 100644
| 1 | +// 用户登录日志service | |
| 2 | +angular.module('ScheduleApp').factory( | |
| 3 | + "UserSignManageService_g", | |
| 4 | + [ | |
| 5 | + '$resource', | |
| 6 | + function($resource) { | |
| 7 | + return { | |
| 8 | + rest: $resource( | |
| 9 | + "/logger_user_sign/:id", | |
| 10 | + {id: '@id'}, | |
| 11 | + { | |
| 12 | + list: { | |
| 13 | + method: 'GET', | |
| 14 | + params: { | |
| 15 | + page: 0 | |
| 16 | + }, | |
| 17 | + transformResponse: function(rs) { | |
| 18 | + var dst = angular.fromJson(rs); | |
| 19 | + if (dst.status == 'SUCCESS') { | |
| 20 | + return dst.data; | |
| 21 | + } else { | |
| 22 | + return dst; // 业务错误留给控制器处理 | |
| 23 | + } | |
| 24 | + } | |
| 25 | + } | |
| 26 | + } | |
| 27 | + ), | |
| 28 | + dataTools: $resource( | |
| 29 | + '/logger_user_sign/:type', | |
| 30 | + {}, | |
| 31 | + { | |
| 32 | + dataExport: { | |
| 33 | + method: 'GET', | |
| 34 | + responseType: "arraybuffer", | |
| 35 | + params: { | |
| 36 | + type: "exportFile" | |
| 37 | + }, | |
| 38 | + transformResponse: function(data, headers){ | |
| 39 | + return {data : data}; | |
| 40 | + } | |
| 41 | + } | |
| 42 | + } | |
| 43 | + ) | |
| 44 | + }; | |
| 45 | + } | |
| 46 | + ] | |
| 47 | +); | |
| 0 | 48 | \ No newline at end of file | ... | ... |