Selaa lähdekoodia

!11 优化踢出用户
打包压缩js、css资源文件;
优化踢出用户;

Aron 6 vuotta sitten
vanhempi
commit
a48002641e

+ 67 - 3
pom.xml

@@ -33,13 +33,25 @@
 		<qiniu.version>[7.0.0, 7.2.99]</qiniu.version>
 		<oltu.version>1.0.2</oltu.version>
 		<jwt.version>0.6.0</jwt.version>
-		<lomboc.version>1.16.14</lomboc.version>
 		<docker.registry>127.0.0.1:5000</docker.registry>
 		<spotify.version>0.4.10</spotify.version>
-
 	</properties>
 
 	<build>
+		<resources>
+			<resource>
+				<directory>src/main/resources</directory>
+				<filtering>false</filtering>
+			</resource>
+			<resource>
+				<directory>src/main/resources</directory>
+				<filtering>true</filtering>
+				<includes>
+					<include>application.yml</include>
+				</includes>
+			</resource>
+		</resources>
+		
 		<plugins>
 			<plugin>
 				<groupId>org.springframework.boot</groupId>
@@ -69,6 +81,59 @@
 
 		</plugins>
 	</build>
+	<profiles>
+		<profile>
+			<id>dev</id>
+			<properties>
+				<activatedProperties>dev</activatedProperties>
+			</properties>
+			<activation>
+				<activeByDefault>true</activeByDefault>
+			</activation>
+		</profile>
+		<profile>
+			<id>prod</id>
+			<properties>
+				<activatedProperties>prod</activatedProperties>
+			</properties>
+			<build>
+				<plugins>
+					<plugin>
+						<groupId>net.alchim31.maven</groupId>
+						<artifactId>yuicompressor-maven-plugin</artifactId>
+						<version>1.3.0</version>
+						<executions>
+							<execution>
+								<id>cpjscs</id>
+								<phase>prepare-package</phase>
+								<goals>
+									<goal>compress</goal>
+								</goals>
+							</execution>
+						</executions>
+						<configuration>
+							<includes>
+								<include>js/appjs/**/*.js</include>
+								<include>css/*.css</include>
+								<include>css/blog/*.css</include>
+							</includes>
+							<excludes>
+								<exclude>js/appjs/common/generator/edit.js</exclude>
+							</excludes>
+							<encoding>utf8</encoding>
+							<failOnWarning>false</failOnWarning>
+							<force>false</force>
+							<nosuffix>true</nosuffix>
+							<linebreakpos>-1</linebreakpos>
+							<sourceDirectory>src/main/resources/static</sourceDirectory>
+							<outputDirectory>target/classes/static</outputDirectory>
+							<jswarn>false</jswarn>
+						</configuration>
+					</plugin>
+				</plugins>
+			</build>
+		</profile>
+	</profiles>
 	<repositories>
 		<repository>
 			<id>public</id>
@@ -102,7 +167,6 @@
 		<dependency>
 			<groupId>org.projectlombok</groupId>
 			<artifactId>lombok</artifactId>
-			<version>${lomboc.version}</version>
 		</dependency>
 
 		<!-- poi S -->

+ 39 - 24
src/main/java/com/ifast/common/aspect/LogAspect.java

@@ -1,5 +1,6 @@
 package com.ifast.common.aspect;
 
+import com.ifast.api.util.JWTUtil;
 import com.ifast.common.annotation.Log;
 import com.ifast.common.base.BaseDO;
 import com.ifast.common.dao.LogDao;
@@ -96,29 +97,43 @@ public class LogAspect {
     @Around("logMapper()")
     public Object mapper(ProceedingJoinPoint point) throws Throwable {
     	String methodName = point.getSignature().getName();
-    	try {
-	    	Subject subject = SecurityUtils.getSubject();
-	    	if(subject.isAuthenticated()) {
-	    		switch(methodName) {
-	    		case "insert":
-	    		case "insertAllColumn":
-	    			Object insert = point.getArgs()[0];
-	    			if(insert instanceof BaseDO) {
-	    				((BaseDO)insert).setCreateBy(ShiroUtils.getUserId());
-	    			}
-	    			break;
-	    		case "update":
-	    		case "updateById":
-	    		case "updateAllColumnById":
-	    			Object update = point.getArgs()[0];
-	    			if(update instanceof BaseDO) {
-	    				((BaseDO)update).setUpdateBy(ShiroUtils.getUserId());
-	    			}
-	    			break;
-	    		}
-	    	}
-    	}catch(Exception ignore) {}
-    	log.info("call {}.{}{}", point.getTarget().getClass().getSimpleName(), methodName, Arrays.toString(point.getArgs()));
+    	boolean insertBy = false, updateBy = false;
+    	switch(methodName) {
+    	case "insert":
+    	case "insertAllColumn":
+    		insertBy = true;
+    		break;
+    	case "update":
+    	case "updateById":
+    	case "updateAllColumnById":
+    		updateBy = true;
+    		break;
+    	}
+    	if(insertBy || updateBy) {
+    		Object arg0 = point.getArgs()[0];
+    		if(arg0 instanceof BaseDO) {
+    			try {
+    				Subject subject = SecurityUtils.getSubject();
+    				if(subject.isAuthenticated()) {
+    					Object principal = subject.getPrincipal();
+    					Long userId = null;
+    					if(principal instanceof String) {
+    						userId = Long.valueOf(JWTUtil.getUserId((String)principal));
+    					}else if(principal instanceof UserDO) {
+    						userId = ((UserDO)principal).getId();
+    					}
+    					BaseDO baseDO = (BaseDO)arg0;
+    					if(insertBy) {
+    						baseDO.setCreateBy(userId);
+    					}
+    					else if(updateBy) {
+    						baseDO.setUpdateBy(userId);
+    					}
+    				}
+    			}catch(Exception ignore) {}
+    			log.info("call {}.{}{}", point.getTarget().getClass().getSimpleName(), methodName, Arrays.toString(point.getArgs()));
+    		}
+    	}
     	
     	long beginTime = System.currentTimeMillis();
     	Object result = point.proceed();
@@ -150,7 +165,7 @@ public class LogAspect {
         String methodName = signature.getName();
         sysLog.setMethod(className + "." + methodName + "()");
         // 请求的参数
-        Object[] args = joinPoint.getArgs();
+        // Object[] args = joinPoint.getArgs();
         Map<String, String[]> parameterMap = HttpContextUtils.getHttpServletRequest().getParameterMap();
         try {
             String params = JSONUtils.beanToJson(parameterMap);

+ 63 - 62
src/main/java/com/ifast/sys/controller/SessionController.java

@@ -1,62 +1,63 @@
-package com.ifast.sys.controller;
-
-import com.ifast.common.annotation.Log;
-import com.ifast.common.utils.Result;
-import com.ifast.sys.domain.UserOnline;
-import com.ifast.sys.service.SessionService;
-import org.apache.shiro.session.Session;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.ResponseBody;
-import org.springframework.web.servlet.mvc.support.RedirectAttributes;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * <pre>
- * </pre>
- * <small> 2018323日 | Aron</small>
- */
-@RequestMapping("/sys/online")
-@Controller
-public class SessionController {
-	@Autowired
-	SessionService sessionService;
-	
-	@Log("进入在线用户列表页面")
-	@GetMapping()
-	public String online() {
-		return "sys/online/online";
-	}
-	
-	@Log("查询在线用户列表数据")
-	@ResponseBody
-	@RequestMapping("/list")
-	public List<UserOnline> list() {
-		return sessionService.list();
-	}
-	
-	@Log("根据sessionId强踢用户下线")
-	@ResponseBody
-	@RequestMapping("/forceLogout/{sessionId}")
-	public Result<String> forceLogout(@PathVariable("sessionId") String sessionId, RedirectAttributes redirectAttributes) {
-		try {
-			sessionService.forceLogout(sessionId);
-			return Result.ok();
-		} catch (Exception e) {
-			e.printStackTrace();
-			return Result.fail();
-		}
-	}
-	
-	@Log("查询在线用户数据列表")
-	@ResponseBody
-	@RequestMapping("/sessionList")
-	public Collection<Session> sessionList() {
-		return sessionService.sessionList();
-	}
-}
+package com.ifast.sys.controller;
+
+import com.ifast.common.annotation.Log;
+import com.ifast.common.utils.Result;
+import com.ifast.sys.domain.UserOnline;
+import com.ifast.sys.service.SessionService;
+import org.apache.shiro.session.Session;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.servlet.mvc.support.RedirectAttributes;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * <pre>
+ * </pre>
+ * <small> 2018323日 | Aron</small>
+ */
+@RequestMapping("/sys/online")
+@Controller
+public class SessionController {
+	@Autowired
+	SessionService sessionService;
+	
+	@Log("进入在线用户列表页面")
+	@GetMapping()
+	public String online() {
+		return "sys/online/online";
+	}
+	
+	@Log("查询在线用户列表数据")
+	@ResponseBody
+	@RequestMapping("/list")
+	public List<UserOnline> list(@RequestParam(required=false) String name) {
+		return sessionService.list(name);
+	}
+	
+	@Log("根据sessionId强踢用户下线")
+	@ResponseBody
+	@RequestMapping("/forceLogout/{sessionId}")
+	public Result<String> forceLogout(@PathVariable("sessionId") String sessionId, RedirectAttributes redirectAttributes) {
+		try {
+			sessionService.forceLogout(sessionId);
+			return Result.ok();
+		} catch (Exception e) {
+			e.printStackTrace();
+			return Result.fail();
+		}
+	}
+	
+	@Log("查询在线用户数据列表")
+	@ResponseBody
+	@RequestMapping("/sessionList")
+	public Collection<Session> sessionList() {
+		return sessionService.sessionList();
+	}
+}

+ 23 - 23
src/main/java/com/ifast/sys/service/SessionService.java

@@ -1,23 +1,23 @@
-package com.ifast.sys.service;
-
-import java.util.Collection;
-import java.util.List;
-
-import org.apache.shiro.session.Session;
-import org.springframework.stereotype.Service;
-
-import com.ifast.sys.domain.UserOnline;
-
-/**
- * <pre>
- * </pre>
- * <small> 2018323日 | Aron</small>
- */
-@Service
-public interface SessionService {
-	List<UserOnline> list();
-
-	Collection<Session> sessionList();
-	
-	boolean forceLogout(String sessionId);
-}
+package com.ifast.sys.service;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.shiro.session.Session;
+import org.springframework.stereotype.Service;
+
+import com.ifast.sys.domain.UserOnline;
+
+/**
+ * <pre>
+ * </pre>
+ * <small> 2018323日 | Aron</small>
+ */
+@Service
+public interface SessionService {
+	List<UserOnline> list(String name);
+
+	Collection<Session> sessionList();
+	
+	boolean forceLogout(String sessionId);
+}

+ 67 - 65
src/main/java/com/ifast/sys/service/impl/SessionServiceImpl.java

@@ -1,65 +1,67 @@
-package com.ifast.sys.service.impl;
-
-import org.apache.shiro.session.Session;
-import org.apache.shiro.session.mgt.eis.SessionDAO;
-import org.apache.shiro.subject.SimplePrincipalCollection;
-import org.apache.shiro.subject.support.DefaultSubjectContext;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import com.ifast.sys.domain.UserDO;
-import com.ifast.sys.domain.UserOnline;
-import com.ifast.sys.service.SessionService;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * <pre>
- * </pre>
- * <small> 2018323日 | Aron</small>
- */
-@Service
-public class SessionServiceImpl implements SessionService {
-	@Autowired
-	private SessionDAO sessionDAO;
-
-	@Override
-	public List<UserOnline> list() {
-		List<UserOnline> list = new ArrayList<>();
-		Collection<Session> sessions = sessionDAO.getActiveSessions();
-		for (Session session : sessions) {
-			UserOnline userOnline = new UserOnline();
-			UserDO userDO = new UserDO();
-			SimplePrincipalCollection principalCollection = new SimplePrincipalCollection();
-			if (session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY) == null) {
-				continue;
-			} else {
-				principalCollection = (SimplePrincipalCollection) session
-						.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
-				userDO = (UserDO) principalCollection.getPrimaryPrincipal();
-				userOnline.setUsername(userDO.getUsername());
-			}
-			userOnline.setId((String) session.getId());
-			userOnline.setHost(session.getHost());
-			userOnline.setStartTimestamp(session.getStartTimestamp());
-			userOnline.setLastAccessTime(session.getLastAccessTime());
-			userOnline.setTimeout(session.getTimeout());
-			list.add(userOnline);
-		}
-		return list;
-	}
-
-	@Override
-	public Collection<Session> sessionList() {
-		return sessionDAO.getActiveSessions();
-	}
-
-	@Override
-	public boolean forceLogout(String sessionId) {
-		Session session = sessionDAO.readSession(sessionId);
-		session.setTimeout(0);
-		return true;
-	}
-}
+package com.ifast.sys.service.impl;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.session.mgt.eis.SessionDAO;
+import org.apache.shiro.subject.SimplePrincipalCollection;
+import org.apache.shiro.subject.support.DefaultSubjectContext;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.ifast.sys.domain.UserDO;
+import com.ifast.sys.domain.UserOnline;
+import com.ifast.sys.service.SessionService;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * <pre>
+ * </pre>
+ * <small> 2018323日 | Aron</small>
+ */
+@Service
+public class SessionServiceImpl implements SessionService {
+	@Autowired
+	private SessionDAO sessionDAO;
+
+	@Override
+	public List<UserOnline> list(String name) {
+		List<UserOnline> list = new ArrayList<>();
+		Collection<Session> sessions = sessionDAO.getActiveSessions();
+		for (Session session : sessions) {
+			if(session==null) continue;
+			UserOnline userOnline = new UserOnline();
+			UserDO userDO = new UserDO();
+			SimplePrincipalCollection principalCollection = new SimplePrincipalCollection();
+			if (session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY) == null) {
+				continue;
+			} else {
+				principalCollection = (SimplePrincipalCollection) session
+						.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
+				userDO = (UserDO) principalCollection.getPrimaryPrincipal();
+				userOnline.setUsername(userDO.getUsername());
+			}
+			userOnline.setId((String) session.getId());
+			userOnline.setHost(session.getHost());
+			userOnline.setStartTimestamp(session.getStartTimestamp());
+			userOnline.setLastAccessTime(session.getLastAccessTime());
+			userOnline.setTimeout(session.getTimeout());
+			if(StringUtils.isBlank(name) || userOnline.getUsername().contains(name)) list.add(userOnline);
+		}
+		return list;
+	}
+
+	@Override
+	public Collection<Session> sessionList() {
+		return sessionDAO.getActiveSessions();
+	}
+
+	@Override
+	public boolean forceLogout(String sessionId) {
+		Session session = sessionDAO.readSession(sessionId);
+		sessionDAO.delete(session);
+		return true;
+	}
+}

+ 1 - 1
src/main/resources/application.yml

@@ -22,7 +22,7 @@ spring:
     generator:
       WRITE_NUMBERS_AS_STRINGS: true    
   profiles:
-    active: dev
+    active: @activatedProperties@
   http:
     multipart:
       max-file-size: 30Mb

+ 220 - 220
src/main/resources/static/js/appjs/sys/online/online.js

@@ -1,221 +1,221 @@
-var prefix = "/sys/online"
-$(function() {
-	load();
-});
-
-function load() {
-	$('#exampleTable')
-			.bootstrapTable(
-					{
-						method : 'get', // 服务器数据的请求方式 get or post
-						url : prefix + "/list", // 服务器数据的加载地址
-						// showRefresh : true,
-						// showToggle : true,
-						// showColumns : true,
-						iconSize : 'outline',
-						toolbar : '#exampleToolbar',
-						striped : true, // 设置为true会有隔行变色效果
-						dataType : "json", // 服务器返回的数据类型
-						pagination : true, // 设置为true会在底部显示分页条
-						// queryParamsType : "limit",
-						// //设置为limit则会发送符合RESTFull格式的参数
-						singleSelect : false, // 设置为true将禁止多选
-						// contentType : "application/x-www-form-urlencoded",
-						// //发送到服务器的数据编码类型
-						pageSize : 10, // 如果设置了分页,每页数据条数
-						pageNumber : 1, // 如果设置了分布,首页页码
-						// search : true, // 是否显示搜索框
-						showColumns : false, // 是否显示内容下拉框(选择显示的列)
-						sidePagination : "client", // 设置在哪里进行分页,可选值为"client" 或者
-						// "server"
-						queryParams : function(params) {
-							return {
-								// 说明:传入后台的参数包括offset开始索引,limit步长,sort排序列,order:desc或者,以及所有列的键值对
-								limit : params.limit,
-								offset : params.offset,
-								name : $('#searchName').val()
-							};
-						},
-						// //请求服务器数据时,你可以通过重写参数的方式添加一些额外的参数,例如 toolbar 中的参数 如果
-						// queryParamsType = 'limit' ,返回参数必须包含
-						// limit, offset, search, sort, order 否则, 需要包含:
-						// pageSize, pageNumber, searchText, sortName,
-						// sortOrder.
-						// 返回false将会终止请求
-						columns : [
-								{
-									checkbox : true
-								},
-								{
-									field : 'id', // 列字段名
-									title : '序号' // 列标题
-								},
-								{
-									field : 'username',
-									title : '用户名'
-								},
-								{
-									field : 'host',
-									title : '主机'
-								},
-								{
-									field : 'startTimestamp',
-									title : '登录时间'
-								},
-								{
-									field : 'lastAccessTime',
-									title : '最后访问时间'
-								},
-								{
-									field : 'timeout',
-									title : '过期时间'
-								},
-								{
-									field : 'status',
-									title : '状态',
-									align : 'center',
-									formatter : function(value, row, index) {
-										if (value == 'on_line') {
-											return '<span class="label label-success">在线</span>';
-										} else if (value == 'off_line') {
-											return '<span class="label label-primary">离线</span>';
-										}
-									}
-								},
-								{
-									title : '操作',
-									field : 'id',
-									align : 'center',
-									formatter : function(value, row, index) {
-										var d = '<a class="btn btn-warning btn-sm" href="#" title="删除"  mce_href="#" onclick="forceLogout(\''
-												+ row.id
-												+ '\')"><i class="fa fa-remove"></i></a> ';
-										return d;
-									}
-								} ]
-					});
-}
-function reLoad() {
-	$('#exampleTable').bootstrapTable('refresh');
-}
-function add() {
-	// iframe层
-	layer.open({
-		type : 2,
-		title : '增加用户',
-		maxmin : true,
-		shadeClose : false, // 点击遮罩关闭层
-		area : [ '800px', '520px' ],
-		content : prefix + '/add'
-	});
-}
-function forceLogout(id) {
-	layer.confirm('确定要强制选中用户下线吗?', {
-		btn : [ '确定', '取消' ]
-	}, function() {
-		$.ajax({
-			url : prefix+"/forceLogout/" + id,
-			type : "post",
-			data : {
-				'id' : id
-			},
-			success : function(r) {
-				if (r.code == 0) {
-					layer.msg(r.msg);
-					reLoad();
-				} else {
-					layer.msg(r.msg);
-				}
-			}
-		});
-	})
-}
-function edit(id) {
-	layer.open({
-		type : 2,
-		title : '用户修改',
-		maxmin : true,
-		shadeClose : true, // 点击遮罩关闭层
-		area : [ '800px', '520px' ],
-		content : prefix + '/edit/' + id // iframe的url
-	});
-}
-function resetPwd(id) {
-	layer.open({
-		type : 2,
-		title : '重置密码',
-		maxmin : true,
-		shadeClose : false, // 点击遮罩关闭层
-		area : [ '400px', '260px' ],
-		content : prefix + '/resetPwd/' + id // iframe的url
-	});
-}
-function batchRemove() {
-	var rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行,当没有选择的记录时,返回一个空数组
-	if (rows.length == 0) {
-		layer.msg("请选择要删除的数据");
-		return;
-	}
-	layer.confirm("确认要删除选中的'" + rows.length + "'条数据吗?", {
-		btn : [ '确定', '取消' ]
-	// 按钮
-	}, function() {
-		var ids = new Array();
-		// 遍历所有选择的行数据,取每条数据对应的ID
-		$.each(rows, function(i, row) {
-			ids[i] = row['userId'];
-		});
-		$.ajax({
-			type : 'POST',
-			data : {
-				"ids" : ids
-			},
-			url : prefix + '/batchRemove',
-			success : function(r) {
-				if (r.code == 0) {
-					layer.msg(r.msg);
-					reLoad();
-				} else {
-					layer.msg(r.msg);
-				}
-			}
-		});
-	}, function() {
-	});
-}
-function getTreeData() {
-	$.ajax({
-		type : "GET",
-		url : "/sys/dept/tree",
-		success : function(tree) {
-			loadTree(tree);
-		}
-	});
-}
-function loadTree(tree) {
-	$('#jstree').jstree({
-		'core' : {
-			'data' : tree
-		},
-		"plugins" : [ "search" ]
-	});
-	$('#jstree').jstree().open_all();
-}
-$('#jstree').on("changed.jstree", function(e, data) {
-	if (data.selected == -1) {
-		var opt = {
-			query : {
-				deptId : '',
-			}
-		}
-		$('#exampleTable').bootstrapTable('refresh', opt);
-	} else {
-		var opt = {
-			query : {
-				deptId : data.selected[0],
-			}
-		}
-		$('#exampleTable').bootstrapTable('refresh', opt);
-	}
-
+var prefix = "/sys/online"
+$(function() {
+	load();
+});
+
+function load() {
+	$('#exampleTable')
+			.bootstrapTable(
+					{
+						method : 'get', // 服务器数据的请求方式 get or post
+						url : prefix + "/list", // 服务器数据的加载地址
+						showRefresh : true,
+						// showToggle : true,
+						// showColumns : true,
+						iconSize : 'outline',
+						toolbar : '#exampleToolbar',
+						striped : true, // 设置为true会有隔行变色效果
+						dataType : "json", // 服务器返回的数据类型
+						pagination : true, // 设置为true会在底部显示分页条
+						// queryParamsType : "limit",
+						// //设置为limit则会发送符合RESTFull格式的参数
+						singleSelect : false, // 设置为true将禁止多选
+						// contentType : "application/x-www-form-urlencoded",
+						// //发送到服务器的数据编码类型
+						pageSize : 10, // 如果设置了分页,每页数据条数
+						pageNumber : 1, // 如果设置了分布,首页页码
+						// search : true, // 是否显示搜索框
+						showColumns : false, // 是否显示内容下拉框(选择显示的列)
+						sidePagination : "client", // 设置在哪里进行分页,可选值为"client" 或者
+						// "server"
+						queryParams : function(params) {
+							return {
+								// 说明:传入后台的参数包括offset开始索引,limit步长,sort排序列,order:desc或者,以及所有列的键值对
+								//limit : params.limit,
+								//offset : params.offset,
+								name : $('#searchName').val()
+							};
+						},
+						// //请求服务器数据时,你可以通过重写参数的方式添加一些额外的参数,例如 toolbar 中的参数 如果
+						// queryParamsType = 'limit' ,返回参数必须包含
+						// limit, offset, search, sort, order 否则, 需要包含:
+						// pageSize, pageNumber, searchText, sortName,
+						// sortOrder.
+						// 返回false将会终止请求
+						columns : [
+								{
+									checkbox : true
+								},
+								{
+									field : 'id', // 列字段名
+									title : '序号' // 列标题
+								},
+								{
+									field : 'username',
+									title : '用户名'
+								},
+								{
+									field : 'host',
+									title : '主机'
+								},
+								{
+									field : 'startTimestamp',
+									title : '登录时间'
+								},
+								{
+									field : 'lastAccessTime',
+									title : '最后访问时间'
+								},
+								{
+									field : 'timeout',
+									title : '过期时间'
+								},
+								{
+									field : 'status',
+									title : '状态',
+									align : 'center',
+									formatter : function(value, row, index) {
+										if (value == 'on_line') {
+											return '<span class="label label-success">在线</span>';
+										} else if (value == 'off_line') {
+											return '<span class="label label-primary">离线</span>';
+										}
+									}
+								},
+								{
+									title : '操作',
+									field : 'id',
+									align : 'center',
+									formatter : function(value, row, index) {
+										var d = '<a class="btn btn-warning btn-sm" href="#" title="删除"  mce_href="#" onclick="forceLogout(\''
+												+ row.id
+												+ '\')"><i class="fa fa-remove"></i></a> ';
+										return d;
+									}
+								} ]
+					});
+}
+function reLoad() {
+	$('#exampleTable').bootstrapTable('refresh');
+}
+function add() {
+	// iframe层
+	layer.open({
+		type : 2,
+		title : '增加用户',
+		maxmin : true,
+		shadeClose : false, // 点击遮罩关闭层
+		area : [ '800px', '520px' ],
+		content : prefix + '/add'
+	});
+}
+function forceLogout(id) {
+	layer.confirm('确定要强制选中用户下线吗?', {
+		btn : [ '确定', '取消' ]
+	}, function() {
+		$.ajax({
+			url : prefix+"/forceLogout/" + id,
+			type : "post",
+			data : {
+				'id' : id
+			},
+			success : function(r) {
+				if (r.code == 0) {
+					layer.msg(r.msg);
+					reLoad();
+				} else {
+					layer.msg(r.msg);
+				}
+			}
+		});
+	})
+}
+function edit(id) {
+	layer.open({
+		type : 2,
+		title : '用户修改',
+		maxmin : true,
+		shadeClose : true, // 点击遮罩关闭层
+		area : [ '800px', '520px' ],
+		content : prefix + '/edit/' + id // iframe的url
+	});
+}
+function resetPwd(id) {
+	layer.open({
+		type : 2,
+		title : '重置密码',
+		maxmin : true,
+		shadeClose : false, // 点击遮罩关闭层
+		area : [ '400px', '260px' ],
+		content : prefix + '/resetPwd/' + id // iframe的url
+	});
+}
+function batchRemove() {
+	var rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行,当没有选择的记录时,返回一个空数组
+	if (rows.length == 0) {
+		layer.msg("请选择要删除的数据");
+		return;
+	}
+	layer.confirm("确认要删除选中的'" + rows.length + "'条数据吗?", {
+		btn : [ '确定', '取消' ]
+	// 按钮
+	}, function() {
+		var ids = new Array();
+		// 遍历所有选择的行数据,取每条数据对应的ID
+		$.each(rows, function(i, row) {
+			ids[i] = row['userId'];
+		});
+		$.ajax({
+			type : 'POST',
+			data : {
+				"ids" : ids
+			},
+			url : prefix + '/batchRemove',
+			success : function(r) {
+				if (r.code == 0) {
+					layer.msg(r.msg);
+					reLoad();
+				} else {
+					layer.msg(r.msg);
+				}
+			}
+		});
+	}, function() {
+	});
+}
+function getTreeData() {
+	$.ajax({
+		type : "GET",
+		url : "/sys/dept/tree",
+		success : function(tree) {
+			loadTree(tree);
+		}
+	});
+}
+function loadTree(tree) {
+	$('#jstree').jstree({
+		'core' : {
+			'data' : tree
+		},
+		"plugins" : [ "search" ]
+	});
+	$('#jstree').jstree().open_all();
+}
+$('#jstree').on("changed.jstree", function(e, data) {
+	if (data.selected == -1) {
+		var opt = {
+			query : {
+				deptId : '',
+			}
+		}
+		$('#exampleTable').bootstrapTable('refresh', opt);
+	} else {
+		var opt = {
+			query : {
+				deptId : data.selected[0],
+			}
+		}
+		$('#exampleTable').bootstrapTable('refresh', opt);
+	}
+
 });

+ 35 - 35
src/main/resources/templates/sys/online/online.html

@@ -1,36 +1,36 @@
-<!DOCTYPE html>
-<html lang="zh_CN" xmlns:th="http://www.thymeleaf.org"
-	xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
-<meta charset="utf-8">
-<head th:include="include :: header"></head>
-<body class="gray-bg">
-	<div class="wrapper wrapper-content ">
-		<div class="row">
-			
-			<div class="col-sm-11">
-				<div class="ibox">
-					<div class="ibox-body">
-						<div class="fixed-table-toolbar">
-							<div class="columns pull-left">
-								
-							</div>
-							<div class="columns pull-right">
-								<button class="btn btn-success" onclick="reLoad()">查询</button>
-							</div>
-
-							<div class="columns pull-right col-md-2 nopadding">
-								<input id="searchName" type="text" class="form-control"
-									placeholder="">
-							</div>
-						</div>
-						<table id="exampleTable" data-mobile-responsive="true">
-						</table>
-					</div>
-				</div>
-			</div>
-		</div>
-		
-	<div th:include="include :: footer"></div>
-	<script type="text/javascript" src="/js/appjs/sys/online/online.js"></script>
-</body>
+<!DOCTYPE html>
+<html lang="zh_CN" xmlns:th="http://www.thymeleaf.org"
+	xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<meta charset="utf-8">
+<head th:include="include :: header"></head>
+<body class="gray-bg">
+	<div class="wrapper wrapper-content ">
+		<div class="row">
+			
+			<div class="col-sm-11">
+				<div class="ibox">
+					<div class="ibox-body">
+						<div class="fixed-table-toolbar">
+							<div class="columns pull-left">
+								
+							</div>
+							<div class="columns pull-right">
+								<button class="btn btn-success" onclick="reLoad()">查询</button>
+							</div>
+
+							<div class="columns pull-right col-md-2 nopadding">
+								<input id="searchName" type="text" class="form-control"
+									placeholder="用户名">
+							</div>
+						</div>
+						<table id="exampleTable" data-mobile-responsive="true">
+						</table>
+					</div>
+				</div>
+			</div>
+		</div>
+		
+	<div th:include="include :: footer"></div>
+	<script type="text/javascript" src="/js/appjs/sys/online/online.js"></script>
+</body>
 </html>