浏览代码

feat:session保持

wangshan 2 年之前
父节点
当前提交
cc0aff9757

+ 4 - 0
src/jfw/filter/filter.go

@@ -49,6 +49,10 @@ func (f *Filter) Do(w http.ResponseWriter, r *http.Request) bool {
 	if !(&logFilter{w, r, session, getSession, make(map[string]interface{})}).Do() {
 		return false
 	}
+	//新版登录时间延长
+	if !(&SessionKeep{w, r, session, getSession, make(map[string]interface{})}).Do() {
+		return false
+	}
 	if !(&jyutil.SessionKeep{w, r, session, getSession, make(map[string]interface{})}).Do() {
 		return false
 	}

+ 38 - 0
src/jfw/filter/sesssionKeep.go

@@ -0,0 +1,38 @@
+package filter
+
+import (
+	jybase "app.yhyue.com/moapp/jybase/common"
+	"app.yhyue.com/moapp/jybase/encrypt"
+	"app.yhyue.com/moapp/jybase/go-xweb/httpsession"
+	"jy/src/jfw/front"
+	"jy/src/jfw/jyutil"
+	"net/http"
+	"strconv"
+)
+
+// SessionKeep 延长登录时间过滤器
+type SessionKeep struct {
+	W          http.ResponseWriter
+	R          *http.Request
+	Session    *httpsession.Session
+	GetSession map[string]interface{}
+	SetSession map[string]interface{}
+}
+
+// Do 继承过滤器方法
+func (sk *SessionKeep) Do() bool {
+	baseUserId := jybase.Int64All(sk.GetSession["base_user_id"])
+	//处理未登录用户
+	if baseUserId == 0 {
+		ck, err := sk.R.Cookie(jyutil.KeepLoginCookieName)
+		//处理已选择 下次自动登录 按钮的用户 cookie >klcn_value 未过期
+		if err == nil && ck.Value != "" {
+			baseUserIdStr := encrypt.SE.DecodeString(ck.Value)
+			if baseUserId, _ = strconv.ParseInt(baseUserIdStr, 10, 64); baseUserId > 0 {
+				//模拟登录 更新用户session
+				front.FindUserAndCreateSessByBaseUserId(baseUserId, sk.Session, false, true)
+			}
+		}
+	}
+	return true
+}

+ 2 - 2
src/jfw/front/dataExport.go

@@ -242,7 +242,7 @@ func (d *DataExport) SieveData() {
 		d.ServeJson(_res)
 		//_res["dataType"] = dataType
 		//d.T["success"] = true
-		//d.T["redirectUrl"] = "/front/dataExport/toCreateOrderPage/" + util.SE.Encode2Hex(_id)
+		//d.T["redirectUrl"] = "/front/dataExport/toCreateOrderPage/" + util.se.Encode2Hex(_id)
 	} else {
 		_res["error_code"] = -1
 		_res["error_msg"] = "保存筛选条件失败"
@@ -836,7 +836,7 @@ func (d *DataExport) ValuationList(order_code string) error {
 
 //
 //func (d *DataExport) EntDataExport(_id string) error {
-//	id := util.SE.Decode4Hex(_id)
+//	id := util.se.Decode4Hex(_id)
 //	userId := util.ObjToString(d.GetSession("userId"))
 //	entId := util.IntAll(d.GetSession("entId"))
 //	entUserId := util.IntAll(d.GetSession("entUserId"))

+ 43 - 28
src/jfw/front/login.go

@@ -1,7 +1,10 @@
 package front
 
 import (
+	"app.yhyue.com/moapp/jybase/redis"
+	"fmt"
 	"jy/src/jfw/config"
+	jutil "jy/src/jfw/jyutil"
 	"log"
 	"regexp"
 	"strings"
@@ -39,22 +42,22 @@ func init() {
 	xweb.AddAction(&Login{})
 }
 
+// KeepLogin 是否选择 下次自动登录---紧供微信扫码登录使用
 func (l *Login) KeepLogin() {
 	//是否自动登录
 	var (
 		isAutoLogin, err = l.GetBool("isAutoLogin") //用户是否选择自动登录
+		loginER          = l.GetString("loginER")   //微信端登录二维码code
 		result           map[string]bool
 	)
-	if err == nil {
-		result["flag"] = true
+	loginER = se.DecodeString(loginER)
+	if err == nil && loginER != "" {
 		if isAutoLogin {
-			//重置用户登录信息保存时间(30天)
-			l.Session().SetMaxAge(time.Duration(qutil.IntAllDef(config.Sysconfig["setSessionTimeout"], 24)))
+			//微信登录二维码 有效期时间是2.4小时;src/jfw/modules/weixin/src/jrpc/jrpc.go GetShareQRStr>tempQrCodeFromWx
+			result["flag"] = redis.Put("newother", fmt.Sprintf(jutil.KeepLoginTimeKey, loginER), "TT", 3*60*60)
 		} else {
-			//重置用户登录信息保存时间(默认 24小时)
-			l.Session().SetMaxAge(time.Duration(qutil.IntAllDef(config.Sysconfig["sessionTimeout"], 24)))
+			result["flag"] = redis.Del("newother", fmt.Sprintf(jutil.KeepLoginTimeKey, loginER))
 		}
-		l.App.SessionManager.Session(l.Request, l.ResponseWriter)
 	}
 	l.ServeJson(result)
 }
@@ -69,16 +72,19 @@ func (l *Login) PhoneBind() error {
 
 func (l *Login) Login() error {
 	defer qutil.Catch()
-	result := map[string]interface{}{}
-	reqType := l.GetString("reqType")
-	status := func() int {
-		if reqType == "phoneLogin" {
+	var (
+		result           = map[string]interface{}{}
+		reqType          = l.GetString("reqType")
+		isAutoLogin, err = l.GetBool("isAutoLogin") //用户是否选择自动登录
+	)
+	status, isLogin := func() (int, bool) {
+		if reqType == "phoneLogin" { //手机号登录
 			phone := l.GetString("phone")
 			password := l.GetString("password")
 			if strings.TrimSpace(phone) == "" {
-				return -1
+				return -1, false
 			} else if strings.TrimSpace(password) == "" {
-				return -2
+				return -2, false
 			}
 			user, ok := mongodb.FindOneByField("user", map[string]interface{}{
 				"i_appid": 2,
@@ -89,15 +95,15 @@ func (l *Login) Login() error {
 					ok, _, userInfo := afterLogin(phone, l.Session())
 					if ok {
 						result["userInfo"] = userInfo
-						return 1
+						return 1, true
 					}
 				} else {
-					return -2
+					return -2, false
 				}
 			} else {
-				return -1
+				return -1, false
 			}
-		} else if reqType == "sendIdentCode" {
+		} else if reqType == "sendIdentCode" { //发送登录短信验证码
 			register := l.GetString("register")
 			phone := l.GetString("phone")
 			//注册页面添加校验
@@ -105,20 +111,20 @@ func (l *Login) Login() error {
 				"i_appid": 2,
 				"s_phone": phone,
 			}) > 0 {
-				return -3
+				return -3, false
 			}
 			if !phoneReg.MatchString(phone) {
-				return -1
+				return -1, false
 			} else if tmp := l.GetSession("CheckCodeId"); tmp == nil || !captcha.VerifyString(tmp.(string), l.GetString("code")) {
-				return -2
+				return -2, false
 			} else if jy.SendPhoneIdentCode(qutil.ObjToString(config.Sysconfig["smsServiceRpc"]), phone, l.Session()) {
-				return 1
+				return 1, false
 			}
-			return 0
-		} else if reqType == "identCodeLogin" {
+			return 0, false
+		} else if reqType == "identCodeLogin" { //短信验证码登录
 			phone, _ := l.GetSession("identCodeKey").(string)
 			if phone == "" || l.GetSession("identCodeValue") == nil || l.GetString("identCode") != l.GetSession("identCodeValue") { //验证码不正确
-				return -1
+				return -1, false
 			} else {
 				//用户不存在
 				datas, _ := mongodb.Find("user", map[string]interface{}{
@@ -193,7 +199,7 @@ func (l *Login) Login() error {
 						}
 						if ok {
 							result["userInfo"] = userInfo
-							return 1
+							return 1, true
 						}
 					}
 				} else {
@@ -217,18 +223,27 @@ func (l *Login) Login() error {
 							"$unset": map[string]interface{}{"s_m_phone": ""},
 						})
 					}
-
 					jy.ClearPhoneIdentSession(l.Session())
 					ok, _, userInfo := afterLogin(phone, l.Session())
 					if ok {
 						result["userInfo"] = userInfo
-						return 1
+						return 1, true
 					}
 				}
 			}
 		}
-		return 0
+		return 0, false
 	}()
+	if status == 1 && isLogin {
+		//当前用户登录选择 下次自动登录
+		if true || isAutoLogin && err == nil {
+			baseUserId := qutil.Int64All(l.GetSession("base_user_id"))
+			if baseUserId > 0 {
+				//往cookie中加入标识
+				jutil.SetCookieValueForAutoLogin(l.ResponseWriter, baseUserId)
+			}
+		}
+	}
 	result["status"] = status
 	l.ServeJson(result)
 	return nil

+ 1 - 1
src/jfw/front/shorturl.go

@@ -150,7 +150,7 @@ func (s *Short) Article(stype, id string) error {
 			stype = "content"
 		}
 	} else if stype == "entservice" { //大客户数据快照展示
-		//SE := util.SimpleEncrypt{"entservice"}
+		//se := util.SimpleEncrypt{"entservice"}
 		sid := encrypt.SE3.DecodeString(id)
 		if len(sid) == 0 || (len(sid) > 0 && sid == "") {
 			s.Redirect("/notin/page", 302)

+ 25 - 10
src/jfw/front/websocket.go

@@ -1,23 +1,23 @@
 package front
 
 import (
+	qutil "app.yhyue.com/moapp/jybase/common"
+	. "app.yhyue.com/moapp/jybase/date"
+	"app.yhyue.com/moapp/jybase/encrypt"
+	"app.yhyue.com/moapp/jybase/go-xweb/httpsession"
+	"app.yhyue.com/moapp/jybase/go-xweb/xweb"
+	"app.yhyue.com/moapp/jybase/redis"
+	"app.yhyue.com/moapp/jypkg/golang.org/x/net/websocket"
+	"app.yhyue.com/moapp/jypkg/public"
 	"encoding/json"
 	"fmt"
 	. "jy/src/jfw/config"
+	"jy/src/jfw/jyutil"
 	"log"
+	"strconv"
 	"strings"
 	"sync"
 	"time"
-
-	"app.yhyue.com/moapp/jypkg/public"
-
-	qutil "app.yhyue.com/moapp/jybase/common"
-	. "app.yhyue.com/moapp/jybase/date"
-	"app.yhyue.com/moapp/jybase/redis"
-
-	"app.yhyue.com/moapp/jybase/go-xweb/httpsession"
-	"app.yhyue.com/moapp/jybase/go-xweb/xweb"
-	"app.yhyue.com/moapp/jypkg/golang.org/x/net/websocket"
 )
 
 //socket对象放在内存中,待rpc回调使用
@@ -132,6 +132,21 @@ func GetWsByCode(param []string) bool {
 			return false
 		}
 		infoData := LoginInfo(src, openid, session)
+		//用户信息正常 且 当前二维码 code被绑定
+		if infoData != nil {
+			baseUserId := qutil.Int64All(session.Get("base_user_id"))
+			if ok, err := redis.Exists("newother", fmt.Sprintf(jyutil.KeepLoginTimeKey, src)); ok && err == nil && baseUserId > 0 {
+				infoData[jyutil.KeepLoginCookieName] = encrypt.SE.EncodeString(strconv.FormatInt(baseUserId, 10))
+				expiresHour := qutil.IntAll(Sysconfig["setSessionTimeout"])
+				expires := time.Now().Add(time.Duration(expiresHour) * time.Hour)
+				infoData["expires"] = expires
+				//往cookie加入标识 保证用户登录状态延期
+				//if ok := redis.Del("newother", fmt.Sprintf(jyutil.KeepLoginTimeKey, src)); !ok {
+				//	log.Println(fmt.Sprintf("%d 清除用户登录延期标识 异常", baseUserId))
+				//}
+				//jyutil.SetCookieValueForAutoLogin(wss.Conn.W, baseUserId)
+			}
+		}
 		if wss.Conn == nil {
 			return true
 		}

+ 186 - 161
src/jfw/jyutil/jyutil.go

@@ -1,206 +1,231 @@
 package jyutil
 
 import (
-    "app.yhyue.com/moapp/jypkg/compatible"
-    "encoding/json"
-    "fmt"
-    "io/ioutil"
-    "jy/src/jfw/config"
-    "log"
-    "net/http"
-    "reflect"
-    "regexp"
-    "sort"
-    "strings"
-    "time"
+	"app.yhyue.com/moapp/jybase/go-xweb/httpsession"
+	"app.yhyue.com/moapp/jypkg/compatible"
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
+	"jy/src/jfw/config"
+	"log"
+	"net/http"
+	"reflect"
+	"regexp"
+	"sort"
+	"strconv"
+	"strings"
+	"time"
 
-    util "app.yhyue.com/moapp/jybase/common"
-    "app.yhyue.com/moapp/jybase/encrypt"
-    . "app.yhyue.com/moapp/jybase/mongodb"
-    "app.yhyue.com/moapp/jybase/redis"
-    "app.yhyue.com/moapp/jypkg/public"
+	util "app.yhyue.com/moapp/jybase/common"
+	"app.yhyue.com/moapp/jybase/encrypt"
+	. "app.yhyue.com/moapp/jybase/mongodb"
+	"app.yhyue.com/moapp/jybase/redis"
+	"app.yhyue.com/moapp/jypkg/public"
 )
 
-var mongodb = public.MQFW
-var se = &encrypt.SimpleEncrypt{Key: "topnet2015topnet2015"}
+var (
+	mongodb    = public.MQFW
+	se         = &encrypt.SimpleEncrypt{Key: "topnet2015topnet2015"}
+	Compatible = compatible.NewCompatible(&mongodb, public.BaseMysql, public.Mysql, config.Middleground)
+	AC         = &encrypt.AES_CBC{
+		Key: "mGlAgnIBB8bx2nch",
+		Iv:  "1389461544135476",
+	}
+	KeepLoginTimeKey    = "keeplogin_%s"
+	KeepLoginCookieName = "klcn_value"
+)
 
-var Compatible = compatible.NewCompatible(&mongodb, public.BaseMysql, public.Mysql, config.Middleground)
-var AC = &encrypt.AES_CBC{
-    Key: "mGlAgnIBB8bx2nch",
-    Iv:  "1389461544135476",
+// SetCookieValueForAutoLogin 为延长用户登录时间 往cookie 中加入标识,在过滤器判断是否自动登录
+func SetCookieValueForAutoLogin(rw http.ResponseWriter, baseUserId int64) {
+	log.Println("-----111--------;", rw.Header())
+	http.SetCookie(rw, func() *http.Cookie {
+		expiresHour := util.IntAll(config.Sysconfig["setSessionTimeout"])
+		maxAge := int(time.Hour * time.Duration(expiresHour) / time.Second) //30天,单位秒
+		expires := time.Now().Add(time.Duration(expiresHour) * time.Hour)
+		cookie := &http.Cookie{
+			Name:     KeepLoginCookieName,
+			Value:    se.EncodeString(strconv.FormatInt(baseUserId, 10)),
+			Path:     "/",
+			HttpOnly: false,
+			MaxAge:   maxAge,
+			Expires:  expires,
+			Domain:   httpsession.Domain,
+		}
+		return cookie
+	}())
 }
 
-//
+// FindMyShareId  分享id
 func FindMyShareId(activecode, openid string) string {
-    defer util.Catch()
-    ret, bres := mongodb.Find("person_share", "{'s_openid':'"+openid+"','s_businesscode':'"+activecode+"'}", `{"l_timestamp":-1}`, nil, true, -1, -1)
-    var shareid string
-    if bres {
-        var shareData = make(map[string]interface{})
-        var str = ""
-        for _, v := range *ret {
-            str = util.ObjToString(v["i_shareid"])
-        }
-        var tt = `^\d+$`
-        a, _ := regexp.Compile(tt)
-        if str == "" || a.MatchString(str) {
-            data := make(map[string]interface{})
-            data["s_openid"] = openid
-            data["s_businesscode"] = activecode
-            data["i_shareid"] = se.EncodeString(openid + "---" + activecode)
-            data["l_timestamp"] = time.Now().Unix()
-            mongodb.Save("person_share", data)
-            shareid = openid + "---" + activecode
-        } else {
-            shareid = se.DecodeString(str)
-        }
-        odata := redis.Get("sso", "p_shareData_"+shareid)
-        if odata == nil {
-            shareData["action"] = "32"
-            redis.Put("sso", "p_shareData_"+shareid, shareData, 24*60*60)
-        }
-    }
-    return shareid
+	defer util.Catch()
+	ret, bres := mongodb.Find("person_share", "{'s_openid':'"+openid+"','s_businesscode':'"+activecode+"'}", `{"l_timestamp":-1}`, nil, true, -1, -1)
+	var shareid string
+	if bres {
+		var shareData = make(map[string]interface{})
+		var str = ""
+		for _, v := range *ret {
+			str = util.ObjToString(v["i_shareid"])
+		}
+		var tt = `^\d+$`
+		a, _ := regexp.Compile(tt)
+		if str == "" || a.MatchString(str) {
+			data := make(map[string]interface{})
+			data["s_openid"] = openid
+			data["s_businesscode"] = activecode
+			data["i_shareid"] = se.EncodeString(openid + "---" + activecode)
+			data["l_timestamp"] = time.Now().Unix()
+			mongodb.Save("person_share", data)
+			shareid = openid + "---" + activecode
+		} else {
+			shareid = se.DecodeString(str)
+		}
+		odata := redis.Get("sso", "p_shareData_"+shareid)
+		if odata == nil {
+			shareData["action"] = "32"
+			redis.Put("sso", "p_shareData_"+shareid, shareData, 24*60*60)
+		}
+	}
+	return shareid
 }
 
 //获取用户openid
 func Getopenid(code string) (openid string) {
-    defer util.Catch()
-    recturl := fmt.Sprintf(config.Wxoauthinfo, code)
-    resp, err := http.Get(recturl)
-    if err != nil {
-        log.Println(err.Error())
-        return
-    }
-    defer resp.Body.Close()
-    bs, _ := ioutil.ReadAll(resp.Body)
-    data := map[string]interface{}{}
-    json.Unmarshal(bs, &data)
-    openid, _ = data["openid"].(string)
-    return
+	defer util.Catch()
+	recturl := fmt.Sprintf(config.Wxoauthinfo, code)
+	resp, err := http.Get(recturl)
+	if err != nil {
+		log.Println(err.Error())
+		return
+	}
+	defer resp.Body.Close()
+	bs, _ := ioutil.ReadAll(resp.Body)
+	data := map[string]interface{}{}
+	json.Unmarshal(bs, &data)
+	openid, _ = data["openid"].(string)
+	return
 }
 
 //
 func GetSessionVal(q map[string]interface{}) (*map[string]interface{}, map[string]interface{}) {
-    person, ok := public.MQFW.FindOneByField("user", q, `{"_id":1,"i_shareknow":1,"s_m_openid":1,"s_nickname":1,"s_headimage":1,"s_headimageurl":1,"s_phone":1,"s_m_phone":1,"l_registedate":1,"i_ispush":1,"i_unlimited":1,"s_jyname":1,"base_user_id":1}`)
-    sessionVal := make(map[string]interface{})
-    if !ok || person == nil || len(*person) == 0 {
-        return nil, sessionVal
-    }
-    sessionVal["user"] = *person
-    if (*person)["i_shareknow"] != nil {
-        sessionVal["shareknow"] = (*person)["i_shareknow"]
-    }
-    sessionVal["userId"] = BsonIdToSId((*person)["_id"])
-    sessionVal["mgoUserId"] = sessionVal["userId"]
-    nickName, _ := (*person)["s_nickname"].(string)
-    phone := util.ObjToString((*person)["s_phone"])
-    if nickName == "" {
-        if phone != "" && len(phone) > 3 {
-            nickName = string(phone[0:3]) + "****" + string(phone[len(phone)-4:])
-        }
-    }
-    if util.ObjToString((*person)["s_jyname"]) != "" {
-        sessionVal["s_jyname"] = util.ObjToString((*person)["s_jyname"])
-    }
-    sessionVal["s_nickname"] = nickName
-    sessionVal["nickname"] = nickName
-    avatar, _ := (*person)["s_headimageurl"].(string)
-    if avatar == "" {
-        avatar, _ = (*person)["s_headimage"].(string)
-    }
-    sessionVal["s_avatar"] = strings.Replace(avatar, "http://", "https://", 1)
-    sessionVal["s_m_openid"], _ = (*person)["s_m_openid"].(string)
-    sessionVal["openid"] = sessionVal["s_m_openid"]
-    if phone == "" {
-        phone = util.ObjToString((*person)["s_m_phone"])
-    }
-    sessionVal["phone"] = phone
-    sessionVal["i_unlimited"] = util.IntAll((*person)["i_unlimited"])
-    sessionVal["base_user_id"] = util.IntAll((*person)["base_user_id"]) //用户中台的uid
-    return person, sessionVal
+	person, ok := public.MQFW.FindOneByField("user", q, `{"_id":1,"i_shareknow":1,"s_m_openid":1,"s_nickname":1,"s_headimage":1,"s_headimageurl":1,"s_phone":1,"s_m_phone":1,"l_registedate":1,"i_ispush":1,"i_unlimited":1,"s_jyname":1,"base_user_id":1}`)
+	sessionVal := make(map[string]interface{})
+	if !ok || person == nil || len(*person) == 0 {
+		return nil, sessionVal
+	}
+	sessionVal["user"] = *person
+	if (*person)["i_shareknow"] != nil {
+		sessionVal["shareknow"] = (*person)["i_shareknow"]
+	}
+	sessionVal["userId"] = BsonIdToSId((*person)["_id"])
+	sessionVal["mgoUserId"] = sessionVal["userId"]
+	nickName, _ := (*person)["s_nickname"].(string)
+	phone := util.ObjToString((*person)["s_phone"])
+	if nickName == "" {
+		if phone != "" && len(phone) > 3 {
+			nickName = string(phone[0:3]) + "****" + string(phone[len(phone)-4:])
+		}
+	}
+	if util.ObjToString((*person)["s_jyname"]) != "" {
+		sessionVal["s_jyname"] = util.ObjToString((*person)["s_jyname"])
+	}
+	sessionVal["s_nickname"] = nickName
+	sessionVal["nickname"] = nickName
+	avatar, _ := (*person)["s_headimageurl"].(string)
+	if avatar == "" {
+		avatar, _ = (*person)["s_headimage"].(string)
+	}
+	sessionVal["s_avatar"] = strings.Replace(avatar, "http://", "https://", 1)
+	sessionVal["s_m_openid"], _ = (*person)["s_m_openid"].(string)
+	sessionVal["openid"] = sessionVal["s_m_openid"]
+	if phone == "" {
+		phone = util.ObjToString((*person)["s_m_phone"])
+	}
+	sessionVal["phone"] = phone
+	sessionVal["i_unlimited"] = util.IntAll((*person)["i_unlimited"])
+	sessionVal["base_user_id"] = util.IntAll((*person)["base_user_id"]) //用户中台的uid
+	return person, sessionVal
 }
 
 //value 用户sessionid
 func LoginRedisKey(userid string) string {
-    return fmt.Sprintf("login_%s", userid)
+	return fmt.Sprintf("login_%s", userid)
 }
 
 // 排序 排序键必须为数字类型
 type SortBy struct {
-    Data    []map[string]interface{}
-    Sortkey string
+	Data    []map[string]interface{}
+	Sortkey string
 }
 
 func (a SortBy) Len() int { return len(a.Data) }
 
 func (a SortBy) Swap(i, j int) {
-    a.Data[i], a.Data[j] = a.Data[j], a.Data[i]
+	a.Data[i], a.Data[j] = a.Data[j], a.Data[i]
 }
 
 func (a SortBy) Less(i, j int) bool {
-    //return Float64(a.Data[i][a.Sortkey]) < Float64(a.Data[j][a.Sortkey])
-    m := a.Data[i][a.Sortkey]
-    n := a.Data[j][a.Sortkey]
-    w := reflect.ValueOf(m)
-    v := reflect.ValueOf(n)
-    switch v.Kind() {
-    case reflect.String:
-        return w.String() < v.String()
-    case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-        return w.Int() < v.Int()
-    case reflect.Float64, reflect.Float32:
-        return w.Float() < v.Float()
-    default:
-        return fmt.Sprintf("%v", w) < fmt.Sprintf("%v", v)
-    }
+	//return Float64(a.Data[i][a.Sortkey]) < Float64(a.Data[j][a.Sortkey])
+	m := a.Data[i][a.Sortkey]
+	n := a.Data[j][a.Sortkey]
+	w := reflect.ValueOf(m)
+	v := reflect.ValueOf(n)
+	switch v.Kind() {
+	case reflect.String:
+		return w.String() < v.String()
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return w.Int() < v.Int()
+	case reflect.Float64, reflect.Float32:
+		return w.Float() < v.Float()
+	default:
+		return fmt.Sprintf("%v", w) < fmt.Sprintf("%v", v)
+	}
 }
 
 // ture  倒序3, 2, 1
 //fmt.Println(m)
 func SortData(data interface{}, sortkey string, reverse bool) {
-    //func SortData(data interface{}, sortkey string, reverse bool) {
-    var db []map[string]interface{}
-    err := Bind(data, &db)
-    if err != nil {
-        fmt.Println(err)
-        return
-    }
-    stb := SortBy{db, sortkey}
-    if !reverse {
-        sort.Sort(stb)
-    } else {
-        sort.Sort(sort.Reverse(stb))
-    }
-    err = Bind(stb.Data, data)
-    if err != nil {
-        fmt.Println(err)
-    }
+	//func SortData(data interface{}, sortkey string, reverse bool) {
+	var db []map[string]interface{}
+	err := Bind(data, &db)
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+	stb := SortBy{db, sortkey}
+	if !reverse {
+		sort.Sort(stb)
+	} else {
+		sort.Sort(sort.Reverse(stb))
+	}
+	err = Bind(stb.Data, data)
+	if err != nil {
+		fmt.Println(err)
+	}
 
 }
 
 // data 转换成ret
 func Bind(data interface{}, ret interface{}) error {
-    v := reflect.ValueOf(ret)
-    if v.Kind() != reflect.Ptr {
-        return fmt.Errorf("ptr input ret needed as type as input type %s", v.Kind())
-    }
-    havdata := false
-    var bk interface{}
-    if v.Elem().Kind() == reflect.Slice {
-        t := reflect.Zero(reflect.TypeOf(v.Elem().Interface()))
-        bk = v.Elem().Interface()
-        v.Elem().Set(t)
-        havdata = true
-    }
-    _data, _ := json.MarshalIndent(data, "", "    ")
-    err := json.Unmarshal(_data, ret)
-    if err != nil {
-        fmt.Println(err)
-        if havdata {
-            v.Elem().Set(reflect.ValueOf(bk))
-        }
-        return err
-    }
-    return nil
+	v := reflect.ValueOf(ret)
+	if v.Kind() != reflect.Ptr {
+		return fmt.Errorf("ptr input ret needed as type as input type %s", v.Kind())
+	}
+	havdata := false
+	var bk interface{}
+	if v.Elem().Kind() == reflect.Slice {
+		t := reflect.Zero(reflect.TypeOf(v.Elem().Interface()))
+		bk = v.Elem().Interface()
+		v.Elem().Set(t)
+		havdata = true
+	}
+	_data, _ := json.MarshalIndent(data, "", "    ")
+	err := json.Unmarshal(_data, ret)
+	if err != nil {
+		fmt.Println(err)
+		if havdata {
+			v.Elem().Set(reflect.ValueOf(bk))
+		}
+		return err
+	}
+	return nil
 }

+ 2 - 0
src/web/staticres/js/login.js

@@ -752,8 +752,10 @@ var signout = function(){
 var afterSignoutClearCookit = function(){
 	try{
 		$.cookie("userid_secure","",{expires:-1,path:"/",domain:document.domain.replace(/[^.]+/,"")});
+		$.cookie("klcn_value","",{expires:-1,path:"/",domain:document.domain.replace(/[^.]+/,"")});
 	}catch(e){
 		document.cookie = "userid_secure=;expires=-1;path=/";
+		document.cookie = "klcn_value=;expires=-1;path=/";
 	}
 }