Explorar el Código

分页,管理员搜索,后台初始化参数调整

yxh hace 6 años
padre
commit
732b9f3017

+ 50 - 4
app/controller/admin/auth.go

@@ -7,7 +7,7 @@ import (
 	"gfast/app/model/user"
 	"gfast/app/service/auth_service"
 	"gfast/app/service/casbin_adapter_service"
-	"gfast/boot"
+	"gfast/app/service/user_service"
 	"gfast/library/response"
 	"gfast/library/utils"
 	"github.com/gogf/gf/frame/g"
@@ -15,6 +15,7 @@ import (
 	"github.com/gogf/gf/text/gstr"
 	"github.com/gogf/gf/util/gconv"
 	"github.com/gogf/gf/util/gvalid"
+	"strings"
 )
 
 //菜单用户组用户管理
@@ -343,7 +344,52 @@ func (c *Auth) EditUser(r *ghttp.Request) {
 
 //用户列表
 func (c *Auth) UserList(r *ghttp.Request) {
-	resp := boot.AdminGfToken.GetTokenData(r)
-	g.Log().Debug(r.Router.Uri)
-	r.Response.Write("hello Index-", gconv.Map(resp.Get("data"))["user_nickname"])
+	keyWords := r.GetString("keywords")
+	g.Log().Debug("keyWords=", keyWords)
+	var where = map[string]interface{}{}
+	if keyWords != "" {
+		where["keyWords"] = keyWords
+	}
+	page, total, userList, err := user_service.GetAdminList(r, where)
+	if err != nil {
+		g.Log().Error(err)
+		response.FailJson(true, r, "获取用户列表数据失败")
+	}
+	users := make([]g.Map, len(userList))
+	for k, u := range userList {
+		users[k] = gconv.Map(u)
+		roles, err := user_service.GetAdminRole(gconv.Int64(u.Id))
+		if err != nil {
+			g.Log().Error(err)
+			response.FailJson(true, r, "获取用户角色数据失败")
+		}
+		name := make([]string, len(roles))
+		for rk, r := range roles {
+			name[rk] = r.Name
+		}
+		users[k]["roles"] = strings.Join(name, ",")
+	}
+	//获取用户对应角色
+
+	res := g.Map{
+		"total":       total,
+		"currentPage": page,
+		"userList":    users,
+	}
+	response.SusJson(true, r, "成功", res)
+}
+
+//删除管理员
+func (c *Auth) DeleteAdmin(r *ghttp.Request) {
+	ids := r.GetRequestArray("ids")
+	idsInterface := make(g.Slice, len(ids))
+	for k, v := range ids {
+		idsInterface[k] = gconv.Int64(v)
+	}
+	_, err := user.Model.Where("id in(?)", idsInterface).Delete()
+	if err != nil {
+		g.Log().Error(err)
+		response.FailJson(true, r, "删除失败")
+	}
+	response.SusJson(true, r, "删除成功")
 }

+ 16 - 9
app/controller/admin/index.go

@@ -5,6 +5,7 @@ import (
 	"gfast/library/response"
 	"github.com/gogf/gf/frame/g"
 	"github.com/gogf/gf/net/ghttp"
+	"github.com/gogf/gf/util/gconv"
 	"strings"
 )
 
@@ -13,11 +14,13 @@ type Index struct{}
 //后台首页接口数据
 func (c *Index) Index(r *ghttp.Request) {
 	//获取用户信息
-	userId := user_service.GetLoginID(r)
-	//获取用户角色信息
-	userMap := user_service.GetAdminInfoById(userId)
-	if userMap != nil {
-		delete(userMap, "user_password")
+	userInfo := user_service.GetCacheAdminInfo(r)
+	//菜单列表
+	var menuList g.List
+	if userInfo != nil {
+		userId := gconv.Int64(userInfo["id"])
+		delete(userInfo, "user_password")
+		//获取用户角色信息
 		roles, err := user_service.GetAdminRole(userId)
 		if err == nil {
 			name := make([]string, len(roles))
@@ -26,17 +29,21 @@ func (c *Index) Index(r *ghttp.Request) {
 				name[k] = v.Name
 				roleIds[k] = v.Id
 			}
-			userMap["roles"] = strings.Join(name, ",")
+			userInfo["roles"] = strings.Join(name, ",")
 			//获取菜单信息
-			user_service.GetAdminMenusByRoleIds(roleIds)
+			menuList, err = user_service.GetAdminMenusByRoleIds(roleIds)
+			if err != nil {
+				g.Log().Error(err)
+			}
 		} else {
 			g.Log().Error(err)
-			userMap["roles"] = ""
+			userInfo["roles"] = ""
 		}
 	}
 
 	result := g.Map{
-		"userInfo": userMap,
+		"userInfo": userInfo,
+		"menuList": menuList,
 	}
 	response.SusJson(true, r, "ok", result)
 }

+ 1 - 0
app/controller/admin/public.go

@@ -9,6 +9,7 @@ import (
 
 type Public struct{}
 
+//获取验证码图片信息
 func (p *Public) Verify(r *ghttp.Request) {
 	idKeyC, base64stringC := utils.GetVerifyImg()
 	response.SusJson(true, r, "ok", g.MapStrStr{"idKeyC": idKeyC, "base64stringC": base64stringC})

+ 1 - 1
app/model/auth_rule/auth_rule_entity.go

@@ -23,7 +23,7 @@ type Entity struct {
 	Createtime uint   `orm:"createtime"  json:"createtime"` // 创建时间
 	Updatetime uint   `orm:"updatetime"  json:"updatetime"` // 更新时间
 	Weigh      int    `orm:"weigh"       json:"weigh"`      // 权重
-	Status     string `orm:"status"      json:"status"`     // 状态
+	Status     uint   `orm:"status"      json:"status"`     // 状态
 }
 
 // OmitEmpty sets OPTION_OMITEMPTY option for the model, which automatically filers

+ 51 - 6
app/service/user_service/user.go

@@ -4,8 +4,10 @@ import (
 	"fmt"
 	"gfast/app/model/role"
 	"gfast/app/model/user"
+	"gfast/app/service/auth_service"
 	"gfast/app/service/casbin_adapter_service"
 	"gfast/boot"
+	"gfast/library/utils"
 	"github.com/gogf/gf/frame/g"
 	"github.com/gogf/gf/net/ghttp"
 	"github.com/gogf/gf/text/gstr"
@@ -13,10 +15,37 @@ import (
 )
 
 //获取登陆用户ID
-func GetLoginID(r *ghttp.Request) int64 {
+func GetLoginID(r *ghttp.Request) (userId int64) {
+	userInfo := GetCacheAdminInfo(r)
+	if userInfo != nil {
+		userId = gconv.Int64(userInfo["id"])
+	}
+	return
+}
+
+//获取缓存的用户信息
+func GetCacheAdminInfo(r *ghttp.Request) (userInfo g.Map) {
 	resp := boot.AdminGfToken.GetTokenData(r)
-	userId := resp.GetInt("data")
-	return gconv.Int64(userId)
+	userInfo = gconv.Map(resp.Get("data"))
+	return
+}
+
+//获取管理员列表
+func GetAdminList(r *ghttp.Request, where g.Map) (page int, total int,
+	userList []*user.Entity, err error) {
+	userModel := user.Model
+	if v, ok := where["keyWords"]; ok {
+		keyWords := gconv.String(v)
+		if keyWords != "" {
+			keyWords = "%" + keyWords + "%"
+			userModel = userModel.Where("user_name like ? or mobile like ? or user_nickname like ?",
+				keyWords, keyWords, keyWords)
+		}
+	}
+	total, err = userModel.Count()
+	page, start := utils.SetPageLimit(r)
+	userList, err = userModel.Limit(start, utils.AdminPageNum).OrderBy("id asc").All()
+	return
 }
 
 //获取管理员的角色信息
@@ -55,18 +84,34 @@ func GetAdminInfoById(id int64) (userMap g.Map) {
 }
 
 //获取管理员所属角色菜单
-func GetAdminMenusByRoleIds(roleIds []int) (menus g.Map, err error) {
+func GetAdminMenusByRoleIds(roleIds []int) (menus g.List, err error) {
 	//获取角色对应的菜单id
 	enforcer, e := casbin_adapter_service.GetEnforcer()
 	if e != nil {
 		err = e
 		return
 	}
+	menuIds := map[int64]int64{}
 	for _, roleId := range roleIds {
 		//查询当前权限
 		gp := enforcer.GetFilteredPolicy(0, fmt.Sprintf("g_%d", roleId))
-		g.Log().Debug(gp)
+		for _, p := range gp {
+			mid := gconv.Int64(gstr.SubStr(p[1], 2))
+			menuIds[mid] = mid
+		}
 	}
-
+	//获取所有开启的菜单
+	err, allMenus := auth_service.GetMenuList("status=? and ismenu=?", 1, 1)
+	if err != nil {
+		return
+	}
+	roleMenus := make(g.List, 0, 100)
+	for _, v := range allMenus {
+		if _, ok := menuIds[gconv.Int64(v["id"])]; ok {
+			v["index"] = v["name"]
+			roleMenus = append(roleMenus, v)
+		}
+	}
+	menus = utils.PushSonToParent(roleMenus, 0, "pid", "id", "subs", "", nil, false)
 	return
 }

+ 7 - 1
boot/boot.go

@@ -4,11 +4,13 @@ import (
 	"gfast/library/utils"
 	"github.com/goflyfox/gtoken/gtoken"
 	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/os/glog"
 )
 
 var AdminGfToken *gtoken.GfToken
 
 func init() {
+	g.Log().SetFlags(glog.F_ASYNC | glog.F_TIME_DATE | glog.F_TIME_TIME | glog.F_FILE_LONG)
 	g.Server().SetPort(8200)
 	g.Server().AddStaticPath("/public", g.Cfg().GetString("server.ServerRoot"))
 	// 设置并启动后台gtoken处理
@@ -16,6 +18,10 @@ func init() {
 }
 
 func initAdminGfToken() {
+	//多端登陆配置
+	utils.AdminMultiLogin = g.Cfg().GetBool("gToken.MultiLogin")
+	//后端分页长度配置
+	utils.AdminPageNum = g.Cfg().GetInt("adminInfo.pageNum")
 	AdminGfToken = &gtoken.GfToken{
 		CacheMode:        g.Cfg().GetInt8("gToken.CacheMode"),
 		CacheKey:         g.Cfg().GetString("gToken.CacheKey"),
@@ -24,7 +30,7 @@ func initAdminGfToken() {
 		TokenDelimiter:   g.Cfg().GetString("gToken.TokenDelimiter"),
 		EncryptKey:       g.Cfg().GetBytes("gToken.EncryptKey"),
 		AuthFailMsg:      g.Cfg().GetString("gToken.AuthFailMsg"),
-		MultiLogin:       g.Cfg().GetBool("gToken.MultiLogin"),
+		MultiLogin:       utils.AdminMultiLogin,
 		LoginPath:        "/sysLogin/login",
 		LoginBeforeFunc:  utils.AdminLogin,
 		LogoutPath:       "/sysLogin/logout",

+ 3 - 0
config/config.toml

@@ -46,3 +46,6 @@
 modelFile="./config/casbin_conf/rbac_model.conf"
 policyFile="./config/casbin_conf/rbac_policy.csv"
 
+#后台相关配置
+[adminInfo]
+pageNum = 5  #后台列表分页长度

+ 36 - 35
data/db.sql

@@ -15,6 +15,34 @@
 /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
 /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
 
+--
+-- Table structure for table `casbin_rule`
+--
+
+DROP TABLE IF EXISTS `casbin_rule`;
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `casbin_rule` (
+  `ptype` varchar(10) DEFAULT NULL,
+  `v0` varchar(256) DEFAULT NULL,
+  `v1` varchar(256) DEFAULT NULL,
+  `v2` varchar(256) DEFAULT NULL,
+  `v3` varchar(256) DEFAULT NULL,
+  `v4` varchar(256) DEFAULT NULL,
+  `v5` varchar(256) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `casbin_rule`
+--
+
+LOCK TABLES `casbin_rule` WRITE;
+/*!40000 ALTER TABLE `casbin_rule` DISABLE KEYS */;
+INSERT INTO `casbin_rule` VALUES ('p','g_27','r_5','All','','',''),('p','g_27','r_9','All','','',''),('p','g_27','r_10','All','','',''),('g','u_31','g_1','','','',''),('g','u_31','g_2','','','',''),('p','g_1','r_5','All','','',''),('p','g_1','r_9','All','','',''),('p','g_1','r_10','All','','',''),('p','g_2','r_11','All','','',''),('p','g_2','r_12','All','','',''),('p','g_2','r_42','All','','','');
+/*!40000 ALTER TABLE `casbin_rule` ENABLE KEYS */;
+UNLOCK TABLES;
+
 --
 -- Table structure for table `qxkj_auth_rule`
 --
@@ -35,12 +63,12 @@ CREATE TABLE `qxkj_auth_rule` (
   `createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
   `updatetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
   `weigh` int(10) NOT NULL DEFAULT '0' COMMENT '权重',
-  `status` varchar(30) NOT NULL DEFAULT '' COMMENT '状态',
+  `status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '状态',
   PRIMARY KEY (`id`),
   UNIQUE KEY `name` (`name`) USING BTREE,
   KEY `pid` (`pid`),
   KEY `weigh` (`weigh`)
-) ENGINE=MyISAM AUTO_INCREMENT=44 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT COMMENT='菜单节点表';
+) ENGINE=MyISAM AUTO_INCREMENT=45 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT COMMENT='菜单节点表';
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -49,7 +77,7 @@ CREATE TABLE `qxkj_auth_rule` (
 
 LOCK TABLES `qxkj_auth_rule` WRITE;
 /*!40000 ALTER TABLE `qxkj_auth_rule` DISABLE KEYS */;
-INSERT INTO `qxkj_auth_rule` VALUES (5,'file',0,'auth','权限管理','fa fa-group','','',1,1497429920,1497430092,99,'normal'),(9,'file',5,'auth/admin','管理员管理','fa fa-user','','Admin tips',1,1497429920,1497430320,118,'normal'),(10,'file',5,'auth/adminlog','管理员日志','fa fa-list-alt','','Admin log tips',1,1497429920,1497430307,113,'normal'),(11,'file',5,'auth/group','角色组','fa fa-group','','Group tips',1,1497429920,1497429920,109,'normal'),(12,'file',5,'auth/rule','菜单规则','fa fa-bars','','Rule tips',1,1497429920,1497430581,104,'normal'),(43,'file',9,'auth/admin/del','删除','fa fa-circle-o','','',0,1497429920,1497429920,114,'normal'),(42,'file',9,'auth/admin/edit','修改','fa fa-circle-o','','',0,1497429920,1497429920,115,'normal'),(41,'file',9,'auth/admin/add','添加','fa fa-circle-o','','',0,1497429920,1497429920,116,'normal'),(40,'file',9,'auth/admin/index','查看','fa fa-circle-o','','Admin tips',0,1497429920,1497429920,117,'normal');
+INSERT INTO `qxkj_auth_rule` VALUES (5,'file',0,'auth','权限管理','fa fa-group','','',1,1497429920,1497430092,99,1),(9,'file',5,'auth/admin','管理员管理','fa fa-user','','Admin tips',1,1497429920,1497430320,118,1),(10,'file',5,'auth/adminlog','管理员日志','fa fa-list-alt','','Admin log tips',1,1497429920,1497430307,113,1),(11,'file',5,'auth/group','角色组','fa fa-group','','Group tips',1,1497429920,1497429920,109,1),(12,'file',5,'auth/rule','菜单规则','fa fa-bars','','Rule tips',1,1497429920,1497430581,104,1),(43,'file',9,'auth/admin/del','删除','fa fa-circle-o','','',0,1497429920,1497429920,114,1),(42,'file',9,'auth/admin/edit','修改','fa fa-circle-o','','',0,1497429920,1497429920,115,1),(41,'file',9,'auth/admin/add','添加','fa fa-circle-o','','',0,1497429920,1497429920,116,1),(40,'file',9,'auth/admin/index','查看','fa fa-circle-o','','Admin tips',0,1497429920,1497429920,117,1),(44,'file',5,'test/test','测试菜单','fa fa-circle-o','','备注',0,1581752604,1581758616,100,0);
 /*!40000 ALTER TABLE `qxkj_auth_rule` ENABLE KEYS */;
 UNLOCK TABLES;
 
@@ -72,7 +100,7 @@ CREATE TABLE `qxkj_role` (
   PRIMARY KEY (`id`),
   KEY `parent_id` (`parent_id`),
   KEY `status` (`status`)
-) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COMMENT='角色表';
+) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8mb4 COMMENT='角色表';
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -81,37 +109,10 @@ CREATE TABLE `qxkj_role` (
 
 LOCK TABLES `qxkj_role` WRITE;
 /*!40000 ALTER TABLE `qxkj_role` DISABLE KEYS */;
-INSERT INTO `qxkj_role` VALUES (1,0,1,1329633709,1329633709,0,'超级管理员','拥有网站最高管理员权限!'),(2,0,1,1329633709,1329633709,0,'普通管理员','权限由最高管理员分配!'),(3,0,1,0,0,0,'站点管理员','站点管理人员'),(4,0,1,0,0,0,'初级管理员','初级管理员'),(5,0,1,0,0,0,'高级管理员','高级管理员'),(6,0,0,0,0,0,'超级管理员','超级管理员'),(7,0,1,0,0,0,'系统管理员','包含所有系统设置权限'),(8,0,1,0,0,0,'区级管理员','');
+INSERT INTO `qxkj_role` VALUES (1,0,1,1329633709,1581673885,0,'超级管理员','备注'),(2,0,1,1329633709,1581674154,0,'普通管理员','备注'),(3,0,1,0,0,0,'站点管理员','站点管理人员'),(4,0,1,0,0,0,'初级管理员','初级管理员'),(5,0,1,0,0,0,'高级管理员','高级管理员'),(6,0,0,0,0,0,'超级管理员','超级管理员'),(7,0,1,0,0,0,'系统管理员','包含所有系统设置权限'),(8,0,1,0,0,0,'区级管理员',''),(26,1,1,1580975018,1580975018,0,'测试组','备注'),(27,1,1,0,1581064765,0,'修改测试','备注');
 /*!40000 ALTER TABLE `qxkj_role` ENABLE KEYS */;
 UNLOCK TABLES;
 
---
--- Table structure for table `qxkj_role_user`
---
-
-DROP TABLE IF EXISTS `qxkj_role_user`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `qxkj_role_user` (
-  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
-  `role_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '角色 id',
-  `user_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '用户id',
-  PRIMARY KEY (`id`),
-  KEY `role_id` (`role_id`),
-  KEY `user_id` (`user_id`)
-) ENGINE=InnoDB AUTO_INCREMENT=54 DEFAULT CHARSET=utf8 COMMENT='用户角色对应表';
-/*!40101 SET character_set_client = @saved_cs_client */;
-
---
--- Dumping data for table `qxkj_role_user`
---
-
-LOCK TABLES `qxkj_role_user` WRITE;
-/*!40000 ALTER TABLE `qxkj_role_user` DISABLE KEYS */;
-INSERT INTO `qxkj_role_user` VALUES (6,3,4),(8,2,5),(10,2,6),(20,4,7),(21,7,2),(23,2,10),(27,2,14),(28,2,15),(29,2,16),(47,2,20),(48,7,3),(49,2,3),(50,2,23),(51,7,22),(52,2,24),(53,5,8);
-/*!40000 ALTER TABLE `qxkj_role_user` ENABLE KEYS */;
-UNLOCK TABLES;
-
 --
 -- Table structure for table `qxkj_user`
 --
@@ -137,7 +138,7 @@ CREATE TABLE `qxkj_user` (
   UNIQUE KEY `user_login` (`user_name`) USING BTREE,
   UNIQUE KEY `mobile` (`mobile`) USING BTREE,
   KEY `user_nickname` (`user_nickname`)
-) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
+) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -146,7 +147,7 @@ CREATE TABLE `qxkj_user` (
 
 LOCK TABLES `qxkj_user` WRITE;
 /*!40000 ALTER TABLE `qxkj_user` DISABLE KEYS */;
-INSERT INTO `qxkj_user` VALUES (1,'admin','18687460581','超级管理员',0,1557715675,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'yxh669@qq.com',0,'',1571734295,'127.0.0.1'),(2,'yixiaohu','13699885599','易小虎',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'yxh@qq.com',1,'',1571923157,'192.168.31.221'),(3,'zs','16399669855','张三',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'zs@qq.com',0,'',1559293160,'127.0.0.1'),(4,'qlgl','13758596696','测试',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'qlgl@qq.com',0,'',1559293134,'127.0.0.1'),(5,'test','13845696696','测试2',0,0,'9OFlt5qzzvCiZWhe7ilcLA==',1,'123@qq.com',0,'',0,''),(6,'18999998889','13755866654','刘大大',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'1223@qq.com',0,'',0,''),(7,'zmm','13788566696','张明明',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'11123@qq.com',0,'',0,''),(8,'lxx','13756566696','李小小',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'123333@qq.com',0,'',1571729563,'127.0.0.1'),(10,'xmm','13588999969','小秘密',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'',0,'',0,''),(14,'cd_19','123154564','看金利科技',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'',0,'',0,''),(15,'lmm','135877545454','刘敏敏',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'',0,'',0,''),(16,'ldn','13899658874','李大牛',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'',0,'',0,''),(20,'dbc','13877555566','大百词',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'',0,'',0,''),(22,'yxfmlbb','15969423326','袁学飞',0,1557715675,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'yxh6691@qq.com',0,'',1565059554,'127.0.0.1'),(23,'wangming','13699888855','王明',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'',0,'',0,''),(24,'zhk','13699885591','综合科',0,0,'IZNU7Pn91/++830Pi6HAWA==',1,'',0,'',1569288069,'192.168.0.146');
+INSERT INTO `qxkj_user` VALUES (1,'admin','18687460581','超级管理员',0,1557715675,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'yxh669@qq.com',0,'',1581491047,'192.168.31.221'),(2,'yixiaohu','13699885599','易小虎',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'yxh@qq.com',1,'',1581513065,'192.168.31.221'),(3,'zs','16399669855','张三',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'zs@qq.com',0,'',1559293160,'127.0.0.1'),(4,'qlgl','13758596696','测试',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'qlgl@qq.com',0,'',1559293134,'127.0.0.1'),(5,'test','13845696696','测试2',0,0,'9OFlt5qzzvCiZWhe7ilcLA==',1,'123@qq.com',0,'',0,''),(6,'18999998889','13755866654','刘大大',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'1223@qq.com',0,'',0,''),(7,'zmm','13788566696','张明明',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'11123@qq.com',0,'',0,''),(8,'lxx','13756566696','李小小',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'123333@qq.com',0,'',1571729563,'127.0.0.1'),(10,'xmm','13588999969','小秘密',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'',0,'',0,''),(14,'cd_19','123154564','看金利科技',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'',0,'',0,''),(15,'lmm','135877545454','刘敏敏',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'',0,'',0,''),(16,'ldn','13899658874','李大牛',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'',0,'',0,''),(20,'dbc','13877555566','大百词',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'',0,'',0,''),(22,'yxfmlbb','15969423326','袁学飞',0,1557715675,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'yxh6691@qq.com',0,'',1565059554,'127.0.0.1'),(23,'wangming','13699888855','王明',0,0,'IJ1xz+Wve+ZONVMFfXJQMw==',1,'',0,'',0,''),(24,'zhk','13699885591','综合科',0,0,'IZNU7Pn91/++830Pi6HAWA==',1,'',0,'',1569288069,'192.168.0.146'),(28,'demo3','18699888855','测试账号1',0,1581314035,'9OFlt5qzzvCiZWhe7ilcLA==',1,'',0,'',0,''),(31,'demo','18699888856','测试账号1',0,1581314770,'9OFlt5qzzvCiZWhe7ilcLA==',1,'',0,'',1581911691,'192.168.31.221');
 /*!40000 ALTER TABLE `qxkj_user` ENABLE KEYS */;
 UNLOCK TABLES;
 /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
@@ -159,4 +160,4 @@ UNLOCK TABLES;
 /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
 /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
 
--- Dump completed on 2020-01-16 18:07:54
+-- Dump completed on 2020-02-17 15:06:29

+ 26 - 3
library/utils/function.go

@@ -8,6 +8,7 @@ import (
 	"gfast/library/response"
 	"github.com/goflyfox/gtoken/gtoken"
 	"github.com/gogf/gf/crypto/gaes"
+	"github.com/gogf/gf/crypto/gmd5"
 	"github.com/gogf/gf/encoding/gbase64"
 	"github.com/gogf/gf/frame/g"
 	"github.com/gogf/gf/net/ghttp"
@@ -20,6 +21,11 @@ import (
 
 const AdminCbcPublicKey = "HqmP1KLMuz09Q0Bu"
 
+var (
+	AdminMultiLogin bool //是否允许后台管理员多端登陆
+	AdminPageNum    = 20 //后台分页长度
+)
+
 //获取验证码
 func GetVerifyImg() (idKeyC string, base64stringC string) {
 	//字符,公式,验证码配置
@@ -67,12 +73,18 @@ func AdminLogin(r *ghttp.Request) (string, interface{}) {
 		response.JsonExit(r, response.ErrorCode, "验证码输入错误")
 	}*/
 	password := EncryptCBC(data["password"], AdminCbcPublicKey)
+	var keys string
+	if AdminMultiLogin {
+		keys = data["username"] + password + gmd5.MustEncryptString(r.GetClientIp())
+	} else {
+		keys = data["username"] + password
+	}
 	if err, user := signIn(data["username"], password, r); err != nil {
 		response.JsonExit(r, response.ErrorCode, err.Error())
 	} else {
-		return data["username"] + password, user.Id
+		return keys, user
 	}
-	return data["username"] + password, nil
+	return keys, nil
 }
 
 //gtoken验证后返回
@@ -134,9 +146,20 @@ func signIn(username, password string, r *ghttp.Request) (error, *user.QxkjUser)
 	if qxkjUser == nil {
 		return errors.New("账号或密码错误"), nil
 	}
+	returnData := *qxkjUser
 	//更新登陆时间及ip
 	qxkjUser.LastLoginTime = gconv.Int(gtime.Timestamp())
 	qxkjUser.LastLoginIp = r.GetClientIp()
 	qxkjUser.Update()
-	return nil, qxkjUser
+	return nil, &returnData
+}
+
+//获取分页limit start
+func SetPageLimit(r *ghttp.Request) (page int, start int) {
+	page = r.GetInt("page")
+	if page == 0 {
+		page = 1
+	}
+	start = (page - 1) * AdminPageNum
+	return
 }

+ 22 - 13
library/utils/slice_tree.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"github.com/gogf/gf/frame/g"
 	"github.com/gogf/gf/util/gconv"
+	"reflect"
 	"strings"
 )
 
@@ -33,7 +34,7 @@ func ParentSonSort(list g.List, params ...interface{}) g.List {
 	levelName = gconv.String(GetSliceByKey(args, 4, "flg"))
 	title = gconv.String(GetSliceByKey(args, 5, "title"))
 	breaks = gconv.Int(GetSliceByKey(args, 6, -1))
-	prefixStr = gconv.String(GetSliceByKey(args, 7, "  "))
+	prefixStr = gconv.String(GetSliceByKey(args, 7, "  "))
 	//定义一个新slice用于返回
 	var returnSlice g.List
 	for _, v := range list {
@@ -45,7 +46,7 @@ func ParentSonSort(list g.List, params ...interface{}) g.List {
 				if levelClone < 0 {
 					break
 				}
-				titlePrefix = strings.Repeat(prefixStr, 2)
+				titlePrefix += strings.Repeat(prefixStr, 2)
 				levelClone--
 			}
 			titlePrefix += "├"
@@ -72,20 +73,21 @@ func ParentSonSort(list g.List, params ...interface{}) g.List {
 
 //有层级关系的数组 ,将子级压入到父级(树形结构)
 func PushSonToParent(list g.List, params ...interface{}) g.List {
-	args := make([]interface{}, 6)
+	args := make([]interface{}, 7)
 	for k, v := range params {
-		if k == 6 {
+		if k == 7 {
 			break
 		}
 		args[k] = v
 	}
 	var (
-		pid       int         //父级id
-		fieldName string      //父级id键名
-		id        string      //id键名
-		key       string      //子级数组键名
-		filter    string      //过滤键名
-		filterVal interface{} //过滤的值
+		pid         int         //父级id
+		fieldName   string      //父级id键名
+		id          string      //id键名
+		key         string      //子级数组键名
+		filter      string      //过滤键名
+		filterVal   interface{} //过滤的值
+		showNoChild bool        //是否显示不存在的子级健
 	)
 	pid = gconv.Int(GetSliceByKey(args, 0, 0))
 	fieldName = gconv.String(GetSliceByKey(args, 1, "pid"))
@@ -93,18 +95,25 @@ func PushSonToParent(list g.List, params ...interface{}) g.List {
 	key = gconv.String(GetSliceByKey(args, 3, "children"))
 	filter = gconv.String(GetSliceByKey(args, 4, ""))
 	filterVal = GetSliceByKey(args, 5, nil)
+	showNoChild = gconv.Bool(GetSliceByKey(args, 6, true))
 	var returnList g.List
 	for _, v := range list {
 		if gconv.Int(v[fieldName]) == pid {
 			if filter != "" {
-				if v[filter] == filterVal {
+				if reflect.DeepEqual(v[filter], filterVal) {
 					args[0] = v[id]
-					v[key] = PushSonToParent(list, args...)
+					child := PushSonToParent(list, args...)
+					if child != nil || showNoChild {
+						v[key] = child
+					}
 					returnList = append(returnList, v)
 				}
 			} else {
 				args[0] = v[id]
-				v[key] = PushSonToParent(list, args...)
+				child := PushSonToParent(list, args...)
+				if child != nil || showNoChild {
+					v[key] = child
+				}
 				returnList = append(returnList, v)
 			}
 		}

+ 3 - 1
test/demo2_test.go

@@ -1,6 +1,8 @@
 package test
 
 import (
+	"fmt"
+	"strings"
 	"testing"
 )
 
@@ -9,5 +11,5 @@ func TestDemo2(t *testing.T) {
 }
 
 func test21(t *testing.T) {
-
+	fmt.Println(strings.Repeat("yxh", 2))
 }