瀏覽代碼

'支持多人操作'

maxiaoshan 4 年之前
父節點
當前提交
0e09b93a33

+ 18 - 0
src/filter/filter.go

@@ -0,0 +1,18 @@
+package filter
+
+import (
+	"log"
+	"regexp"
+
+	"github.com/go-xweb/xweb"
+)
+
+func init() {
+	log.Println("过滤器")
+	matchUrl := make([]*regexp.Regexp, 0)
+	filter, _ := regexp.Compile("/center")
+	matchUrl = append(matchUrl, filter)
+	xweb.AddFilter(&sessfilter{App: xweb.RootApp(), SessionName: "loginuser",
+		MatchUrl: matchUrl})
+
+}

+ 40 - 0
src/filter/sessfilter.go

@@ -0,0 +1,40 @@
+package filter
+
+import (
+	"net/http"
+	"regexp"
+
+	"github.com/go-xweb/xweb"
+)
+
+//session过滤器
+type sessfilter struct {
+	App         *xweb.App
+	SessionName string
+	MatchUrl    []*regexp.Regexp
+}
+
+//实现过滤器方法
+func (s *sessfilter) Do(w http.ResponseWriter, req *http.Request) bool {
+	requestPath := req.URL.Path
+	b := true
+	for _, cr := range s.MatchUrl {
+		if !cr.MatchString(requestPath) {
+			continue
+		}
+		b = false
+		session := s.App.SessionManager.Session(req, w)
+		loginuser := session.Get(s.SessionName)
+		has := (loginuser != nil && loginuser != "")
+		if has {
+			b = true
+		} else {
+			b = false
+		}
+		break
+	}
+	if !b { //session失效
+		s.App.Redirect(w, requestPath, "/")
+	}
+	return b
+}

+ 199 - 184
src/front/front.go

@@ -7,11 +7,10 @@ import (
 	"fmt"
 	"io/ioutil"
 	qu "qfw/util"
+	"qfw/util/redis"
 	"sync/atomic"
 
-	//"qfw/util/mongodb"
 	mgo "mongodb"
-	//"qfw/util/redis"
 	"sort"
 	"strings"
 	"sync"
@@ -26,28 +25,24 @@ import (
 
 type Front struct {
 	*xweb.Action
-	//index xweb.Mapper `xweb:"/"`
-	// pack          xweb.Mapper `xweb:"/package"`
-	listInfo      xweb.Mapper `xweb:"/list"`
-	elist         xweb.Mapper `xweb:"/elist"`
-	detail        xweb.Mapper `xweb:"/detail/(.*).html"`
-	biaozhu       xweb.Mapper `xweb:"/biaozhu"`
-	tj            xweb.Mapper `xweb:"/tj"`
-	importByExcel xweb.Mapper `xweb:"/importbyexcel"`
-	importByEs    xweb.Mapper `xweb:"/importbyes"`
-	getEsCount    xweb.Mapper `xweb:"/getescount"`
-	finishCheck   xweb.Mapper `xweb:"/finishcheck"`
-	syncMarked    xweb.Mapper `xweb:"/syncmarked"`
+	// elist         xweb.Mapper `xweb:"/elist"`
+	login         xweb.Mapper `xweb:"/"`
+	saveUser      xweb.Mapper `xweb:"/center/saveuser"`
+	listInfo      xweb.Mapper `xweb:"/center/list"`
+	checkId       xweb.Mapper `xweb:"/center/checkid"`
+	detail        xweb.Mapper `xweb:"/center/detail/(.*).html"`
+	biaozhu       xweb.Mapper `xweb:"/center/biaozhu"`
+	importByExcel xweb.Mapper `xweb:"/center/importbyexcel"`
+	importByEs    xweb.Mapper `xweb:"/center/importbyes"`
+	getEsCount    xweb.Mapper `xweb:"/center/getescount"`
+	finishCheck   xweb.Mapper `xweb:"/center/finishcheck"`
+	errCheck      xweb.Mapper `xweb:"/center/errcheck"`
+	syncMarked    xweb.Mapper `xweb:"/center/syncmarked"`
 }
 
-//var IdList *list.List //所有数据
-//var IdPackList *list.List //含有分包的数据
 var preKey = "ck_"
 var preErr = "err_"
 var SE = qu.SimpleEncrypt{Key: "topJYBX2019"}
-var Max, Min string
-var HasNo bool                       //预算和中标金额是否存在标记
-var QueryFind map[string]interface{} //查询
 
 /*
 	status
@@ -57,92 +52,77 @@ var QueryFind map[string]interface{} //查询
 		3:修改
 		4:删除
 */
-/**
-//查询初始化的数据
-func (i *Front) Index() error {
-	_id := ""
-	ran := 0
-	for {
-		index, invalid := 0, 0
-		if IdList.Len() == 0 {
-			return i.Render("finish.html")
-		}
-		ran = util.Getrand(IdList.Len())
-		for e := IdList.Front(); e != nil; e = e.Next() { //遍历IdList,获取id
-			if index == ran {
-				_id = qu.ObjToString(e.Value)
-				invalid = redis.GetInt("extcheck", "extcheck_"+_id)
-				break
-			}
-			index++
-		}
-		if invalid == 0 {
-			break
-		}
-		if IdList.Len() < 500 { //|| IdPackList.Len() < 100
-			qu.Debug("抽查数据剩余不足", IdList.Len())
-			break
-		}
-	}
-	redis.Put("extcheck", "extcheck_"+_id, 1, 10*60)
-	qu.Debug("_id", _id, "---", IdList.Len())
-	rep := getDetail(_id)
-	//i.T["ispackage"] = ispackage
-	//i.T["type"] = rep["type"]
-	i.T["info"] = rep["info"]
-	i.T["common"] = rep["common"]
-	i.T["worder"] = rep["worder"]
-	i.T["packs"] = rep["packs"]
-	i.T["packskey"] = rep["packskey"]
-	i.T["ck_pclisext"] = rep["ck_pclisext"]
-	i.T["ck_wodrisext"] = rep["ck_wodrisext"]
-	i.T["ck_pkgisext"] = rep["ck_pkgisext"]
-	i.T["timeplace"] = rep["timeplace"]
-	i.T["purchasinglist"] = rep["purchasinglist"]
-	i.T["other"] = rep["other"]
-	//qu.Debug(util.PurchasinglistField, util.WinnerorderField, util.PackageField)
-	i.T["PurchasinglistField"] = util.PurchasinglistField
-	i.T["WinnerorderField"] = util.WinnerorderField
-	i.T["PackageField"] = util.PackageField
-	i.T[preKey+"purchasinglist"] = rep[preKey+"purchasinglist"]
-	i.T[preKey+"package"] = rep[preKey+"package"]
-	i.T[preKey+"winnerorder"] = rep[preKey+"winnerorder"]
-	i.T["worder_new"] = rep["worder_new"]
-	i.T["pcl_new"] = rep["pcl_new"]
-	i.T["pkg_new"] = rep["pkg_new"]
 
-	return i.Render("detail.html", &i.T)
-}
-*/
 //列表
 func (i *Front) ListInfo() error {
+	//loginuser := i.GetSession("loginuser").(string)
 	spidercode := i.GetString("spidercode")
 	coll := i.GetString("coll")
 	field := i.GetString("field")
 	stype := i.GetString("type")
-	Min = i.GetString("minval")
-	Max = i.GetString("maxval")
-	HasNo, _ = i.GetBool("hasno")
+	min := i.GetString("minval") //min max不用int类型接收,以免有默认值0
+	max := i.GetString("maxval")
+	hasno, _ := i.GetBool("hasno")
 	pagenum, _ := i.GetInteger("pagenum")
 	if pagenum == 0 {
 		pagenum = 1
 	}
-	if coll != "" { //指定表
-		util.Coll = coll
+	qu.Debug("coll:", coll, "stype:", stype, "field:", field, "hasno:", hasno, "max:", max, "min:", min, "pagenum:", pagenum)
+	query := map[string]interface{}{}
+	if spidercode != "" { //爬虫代码
+		query["spidercode"] = spidercode
 	}
-	if stype == "" {
-		stype = "-1"
+	if stype != "-1" && stype != "" { //类型
+		if stype == util.SPECIALTYPE {
+			query["subtype"] = map[string]interface{}{
+				"$exists": false,
+			}
+		} else {
+			subtype := strings.Split(stype, "-")[1]
+			query["subtype"] = subtype
+		}
 	}
-	if field == "" {
-		field = "-1"
+	if field != "-1" && field != "" { //字段
+		query[preKey+field] = map[string]interface{}{
+			"$exists": false, //field未曾标记
+		}
+		if field == "budget" || field == "bidamount" || field == "biddiscount" { //金额区间
+			numMap := map[string]interface{}{}
+			if min != "" {
+				minint := qu.IntAll(min)
+				numMap["$gte"] = minint
+			}
+			if max != "" {
+				maxint := qu.IntAll(max)
+				numMap["$lte"] = maxint
+			}
+			queryArr := []interface{}{}
+			if hasno { //包含field不存在的数据
+				queryArr = append(queryArr, map[string]interface{}{
+					field: map[string]interface{}{
+						"$exists": false,
+					},
+				})
+			}
+			if len(numMap) > 0 { //给定了区间,查询此区间或者budget、bidamount不存在的数据
+				queryArr = append(queryArr, map[string]interface{}{
+					field: numMap,
+				})
+			}
+			if len(queryArr) > 0 {
+				query["$or"] = queryArr
+			}
+		} else {
+			hasno = false
+		}
 	}
-	listData := getListInfo(spidercode, stype, field, pagenum)
-	//if len(listData) > 0 { //每次查询更新内存中标注数据
-	//	IdList = list.New()
-	//	for _, v := range listData {
-	//		IdList.PushBack(mgo.BsonIdToSId(v["_id"]))
-	//	}
-	//}
+	qu.Debug("query:", coll, query)
+	if coll == "" {
+		coll = util.Config.Fromtable
+	}
+	i.SetSession("coll", coll)   //session中存入查询表
+	i.SetSession("query", query) //session中存入查询条件
+	listData := getListInfo(coll, query, pagenum)
 	i.T["list"] = listData
 	i.T["type"] = stype
 	i.T["field"] = field
@@ -150,30 +130,37 @@ func (i *Front) ListInfo() error {
 	i.T["coll"] = coll
 	i.T["topsubtype"] = util.TopSubStypeArr
 	i.T["allfield"] = util.AllFieldArr
-	i.T["fromtable"] = util.Coll
+	i.T["fromtable"] = util.Config.Fromtable
 	i.T["dbname"] = util.Config.Dbname
-	i.T["max"] = Max
-	i.T["min"] = Min
-	i.T["hasno"] = HasNo
-	checkedNum, allNum := GetCheckedAndAllDataInfo() //已标和总数信息
+	i.T["max"] = max
+	i.T["min"] = min
+	i.T["hasno"] = hasno
+	checkedNum, allNum := GetCheckedAndAllDataInfo(query, coll) //已标和总数信息
 	i.T["checkednum"] = checkedNum
 	i.T["allnum"] = allNum
 	i.T["pagenum"] = pagenum
 	return i.Render("list.html", &i.T)
 }
 
-//标错列表
-func (i *Front) Elist() error {
-	attrname := i.GetString("attrname")
-	common := util.Config.Biaozhu["common"]
-	elist, _ := util.MgoM.Find(util.Config.Totablel, `{"ck_`+attrname+`":"0"}`, `{"_id":1}`, `{"_id":1}`, false, -1, -1)
-	for _, v := range *elist {
-		v["_id"] = mgo.BsonIdToSId(v["_id"])
+//判断id是否正在被标记
+func (i *Front) CheckId() {
+	defer qu.Catch()
+	msg := ""
+	id := i.GetString("id")
+	coll := i.GetSession("coll").(string)
+	if coll != "" {
+		exists, err := redis.Exists("extcheck", coll+"_"+id)
+		if err == nil {
+			if exists {
+				id, exists = GetNoCheckedId(id, coll)
+			}
+		} else {
+			msg = "校验数据出错!"
+		}
+		i.ServeJson(map[string]interface{}{"msg": msg, "id": id, "exists": exists})
+		return
 	}
-	i.T["elist"] = *elist
-	i.T["attrname"] = attrname
-	i.T["common"] = common
-	return i.Render("elist.html", &i.T)
+	i.ServeJson(map[string]interface{}{"msg": "数据校验表出错!"})
 }
 
 //标注
@@ -246,8 +233,10 @@ func (i *Front) Biaozhu() error {
 	// qu.Debug("errset---", errset)
 	// qu.Debug("set---", set)
 	// qu.Debug("unset---", unset)
+	loginuser := i.GetSession("loginuser").(string)
 	unerrset := map[string]interface{}{} //记录errdata错误信息表删除
-	data, _ := util.MgoM.FindById(util.Coll, _id, nil)
+	coll := i.GetSession("coll").(string)
+	data, _ := util.MgoM.FindById(coll, _id, nil)
 	//标注误操作处理
 	if len(set) > 0 { //set中为本次标注保存的数据(ck_bidopentime:1;ck_buyer:2;buyer:"XXX")
 		for s, sv := range set {
@@ -345,6 +334,7 @@ func (i *Front) Biaozhu() error {
 		}
 		//qu.Debug("errset---", errset)
 		errset["updatetime"] = time.Now().Unix()
+		errset["modifyuser"] = loginuser
 		errUpdata["$set"] = errset
 	}
 	if len(unerrset) > 0 {
@@ -360,13 +350,14 @@ func (i *Front) Biaozhu() error {
 	if len(set) > 0 {
 		set["ck_data"] = stype
 		set["updatetime"] = time.Now().Unix()
+		set["modifyuser"] = loginuser
 		update["$set"] = set
 	}
 	if len(unset) > 0 {
 		update["$unset"] = unset
 	}
 	if len(update) > 0 {
-		b = util.MgoM.Update(util.Coll, `{"_id":"`+_id+`"}`, update, false, false)
+		b = util.MgoM.Update(coll, `{"_id":"`+_id+`"}`, update, false, false)
 		if b {
 			//for e := IdList.Front(); e != nil; e = e.Next() { //遍历IdList,删除元素
 			//	if _id == qu.ObjToString(e.Value) {
@@ -374,8 +365,8 @@ func (i *Front) Biaozhu() error {
 			//		break
 			//	}
 			//}
-			if util.Coll != util.Config.Fromtable && isSaveMarked { //util.coll此时的标注表  util.Config.Fromtable默认标注表
-				data, _ := util.MgoM.FindById(util.Coll, _id, nil)
+			if coll != util.Config.Fromtable && isSaveMarked { //util.coll此时的标注表  util.Config.Fromtable默认标注表
+				data, _ := util.MgoM.FindById(coll, _id, nil)
 				if data != nil && len(*data) > 0 {
 					update := map[string]interface{}{"$set": *data}
 					if len(unset) > 0 {
@@ -395,8 +386,25 @@ func (i *Front) Biaozhu() error {
 
 //查询信息
 func (i *Front) Detail(id string) error {
-	rep := getDetail(id)
-	//i.T["type"] = rep["type"]
+	coll, _ := i.GetSession("coll").(string)
+	//if coll != "" {
+	//	exists, _ := redis.Exists("extcheck", coll+"_"+id)
+	//	if exists {
+	//		tmpId, exists := GetNoCheckedId(id, coll)
+	//		if exists { //标注完成
+	//			return i.Render("finish.html", &i.T)
+	//		} else {
+	//			id = tmpId
+	//		}
+	//	}
+	//} else {
+	//	i.T["err"] = "数据查询表为空!"
+	//	return i.Render("err.html", &i.T)
+	//}
+	query, _ := i.GetSession("query").(map[string]interface{})
+	qu.Debug(coll, query)
+	rep := getDetail(id, coll)
+	i.T["jyhref"] = util.JYHREFPRE + qu.CommonEncodeArticle("content", id) + ".html"
 	i.T["info"] = rep["info"]
 	i.T["common"] = rep["common"]
 	i.T["worder"] = rep["worder"]
@@ -411,16 +419,19 @@ func (i *Front) Detail(id string) error {
 	i.T["PurchasinglistField"] = util.PurchasinglistField
 	i.T["WinnerorderField"] = util.WinnerorderField
 	i.T["PackageField"] = util.PackageField
+	i.T["topsubtype"] = util.TopSubStypeArr2
 	i.T[preKey+"purchasinglist"] = rep[preKey+"purchasinglist"]
 	i.T[preKey+"package"] = rep[preKey+"package"]
 	i.T[preKey+"winnerorder"] = rep[preKey+"winnerorder"]
 	i.T["worder_new"] = rep["worder_new"]
 	i.T["pcl_new"] = rep["pcl_new"]
 	i.T["pkg_new"] = rep["pkg_new"]
-	i.T["nextid"] = GetNextDataId(id)                //下一条id
-	checkedNum, allNum := GetCheckedAndAllDataInfo() //已标和总数信息
+	i.T["nextid"] = GetNextDataId(id, coll, query)              //下一条id
+	checkedNum, allNum := GetCheckedAndAllDataInfo(query, coll) //已标和总数信息
 	i.T["checkednum"] = checkedNum
 	i.T["allnum"] = allNum
+	//存入Redis
+	redis.Put("extcheck", coll+"_"+id, "", util.Config.RedisTimeout*60) //正在标注的数据存入redis避免多人同时标注(加上coll左前缀避免不同表相同id数据不能同时标注)
 	return i.Render("detail.html", &i.T)
 }
 
@@ -602,6 +613,28 @@ func (i *Front) ImportByEs() {
 	i.ServeJson(map[string]interface{}{"msg": msg})
 }
 
+//查找未被标注的数据id
+func GetNoCheckedId(id, coll string) (string, bool) {
+	defer qu.Catch()
+	q := map[string]interface{}{
+		"_id": map[string]interface{}{
+			"$gt": mgo.StringTOBsonId(id),
+		},
+	}
+	sess := util.MgoM.GetMgoConn()
+	defer util.MgoM.DestoryMongoConn(sess)
+	it := sess.DB(util.MgoM.DbName).C(coll).Find(q).Sort("_id").Select(map[string]interface{}{"_id": 1}).Iter()
+	for tmp := make(map[string]interface{}); it.Next(&tmp); {
+		id = mgo.BsonIdToSId(tmp["_id"])
+		exists, err := redis.Exists("extcheck", coll+"_"+id)
+		if err == nil && !exists {
+			return id, exists
+		}
+		tmp = map[string]interface{}{}
+	}
+	return id, true
+}
+
 //同步数据
 func (i *Front) SyncMarked() {
 	syncColl := i.GetString("coll")
@@ -659,62 +692,15 @@ func (i *Front) FinishCheck() {
 	i.Render("finish.html")
 }
 
+//错误页面
+func (i *Front) ErrCheck() {
+	i.Render("err.html")
+}
+
 //查询列表数据
-func getListInfo(spidercode, stype, field string, currentpage int) []map[string]interface{} {
-	QueryFind = map[string]interface{}{}
-	if spidercode != "" {
-		QueryFind["spidercode"] = spidercode
-	}
-	if stype != "-1" && stype != "" {
-		if stype == util.SPECIALTYPE {
-			QueryFind["subtype"] = map[string]interface{}{
-				"$exists": false,
-			}
-		} else {
-			subtype := strings.Split(stype, "-")[1]
-			QueryFind["subtype"] = subtype
-		}
-	}
-	if field != "-1" && field != "" {
-		//query[field] = map[string]interface{}{
-		//	"$exists": true, //字段存在
-		//}
-		QueryFind[preKey+field] = map[string]interface{}{
-			"$exists": false, //field未曾标记
-		}
-		if field == "budget" || field == "bidamount" { //金额区间
-			numMap := map[string]interface{}{}
-			if Min != "" {
-				minint := qu.IntAll(Min)
-				numMap["$gte"] = minint
-			}
-			if Max != "" {
-				maxint := qu.IntAll(Max)
-				numMap["$lte"] = maxint
-			}
-			queryArr := []interface{}{}
-			if HasNo { //包含field不存在的数据
-				queryArr = append(queryArr, map[string]interface{}{
-					field: map[string]interface{}{
-						"$exists": false,
-					},
-				})
-			}
-			if len(numMap) > 0 { //给定了区间,查询此区间或者budget、bidamount不存在的数据
-				queryArr = append(queryArr, map[string]interface{}{
-					field: numMap,
-				})
-			}
-			if len(queryArr) > 0 {
-				QueryFind["$or"] = queryArr
-			}
-		} else {
-			HasNo = false //当字段不是budget、bidamount时,HasNo改为false,仅作用于页面展示
-		}
-	}
-	qu.Debug("query:", util.Coll, QueryFind)
+func getListInfo(coll string, query map[string]interface{}, currentpage int) []map[string]interface{} {
 	start := (currentpage - 1) * 50
-	infoList, _ := util.MgoM.Find(util.Coll, QueryFind, `{"_id":1}`, `{"_id":1,"title":1,"detail":1,"site":1,"href":1,"ck_data":1}`, false, start, 50)
+	infoList, _ := util.MgoM.Find(coll, query, `{"_id":1}`, `{"_id":1,"title":1,"detail":1,"site":1,"href":1,"ck_data":1}`, false, start, 50)
 	for k, v := range *infoList {
 		ck_data := qu.IntAll(v["ck_data"])
 		if ck_data > 0 {
@@ -733,9 +719,9 @@ func getListInfo(spidercode, stype, field string, currentpage int) []map[string]
 	return *infoList
 }
 
-func getDetail(id string) map[string]interface{} {
+func getDetail(id, coll string) map[string]interface{} {
 	rep := map[string]interface{}{}
-	infoTmp, _ := util.MgoM.FindById(util.Coll, id, ``)
+	infoTmp, _ := util.MgoM.FindById(coll, id, ``)
 	info := *infoTmp
 	// if qu.ObjToString(info["check"]) == "ok" && flag != "y" {
 	// 	bz_info, _ := util.MgoM.FindById(util.Config.Totablel, id, ``)
@@ -918,7 +904,15 @@ func setExtComMap(info map[string]interface{}) ([]interface{}, []interface{}, []
 			if info[fmt.Sprint(cp["key"])] == nil {
 				cp["value"] = ""
 			} else {
-				cp["value"] = info[fmt.Sprint(cp["key"])]
+				if cp["key"] == "subtype" {
+					if info["toptype"] != nil && info["subtype"] != nil {
+						cp["value"] = qu.ObjToString(info["toptype"]) + "-" + qu.ObjToString(info[fmt.Sprint(cp["key"])])
+					} else {
+						cp["value"] = ""
+					}
+				} else {
+					cp["value"] = info[fmt.Sprint(cp["key"])]
+				}
 			}
 			if info[preKey+fmt.Sprint(cp["key"])] == nil {
 				cp["status"] = "-1"
@@ -997,13 +991,20 @@ func BzJBZD(content []interface{}, set, unset, errset map[string]interface{}) {
 						continue
 					}
 					if status == 2 || status == 3 { //新增、修改
-						input := tmpMap["input"]                            //值
-						if key == "attach_discern" || key == "attach_ext" { //附件识别、抽取select
+						input := tmpMap["input"]                                                                     //值
+						if key == "subtype" || key == "attach_discern" || key == "attach_ext" || key == "isrepeat" { //附件识别、抽取select
 							input = tmpMap["select"]
-						} else if key == "budget" || key == "bidamount" {
+						} else if key == "budget" || key == "bidamount" || key == "biddiscount" {
 							input = qu.Float64All(input)
 						}
-						set[key] = input
+						if key == "subtype" {
+							if topsubtype := strings.Split(qu.ObjToString(input), "-"); len(topsubtype) == 2 {
+								set["toptype"] = topsubtype[0]
+								set[key] = topsubtype[1]
+							}
+						} else {
+							set[key] = input
+						}
 						errset[key] = status
 					} else if status == 4 { //删除
 						unset[key] = ""
@@ -1299,7 +1300,7 @@ func GetDataById(coll string, ids []string, stype string, tmp map[string]map[str
 	msg := ""
 	wg := &sync.WaitGroup{}
 	lock := &sync.Mutex{}
-	ch := make(chan bool, 5)
+	ch := make(chan bool, 10)
 	n := int64(0)
 	for i, id := range ids {
 		wg.Add(1)
@@ -1428,16 +1429,16 @@ func UpdateMarkColl(bidData, markData *map[string]interface{}) {
 }
 
 //获取当前数据下一条的id
-func GetNextDataId(id string) string {
+func GetNextDataId(id, coll string, query map[string]interface{}) string {
 	nextIdQuery := map[string]interface{}{
 		"_id": map[string]interface{}{
 			"$gt": mgo.StringTOBsonId(id),
 		},
 	}
-	for k, v := range QueryFind {
+	for k, v := range query {
 		nextIdQuery[k] = v
 	}
-	one, _ := util.MgoM.Find(util.Coll, nextIdQuery, `{"_id":1}`, `{"_id":1}`, true, 0, 1)
+	one, _ := util.MgoM.Find(coll, nextIdQuery, `{"_id":1}`, `{"_id":1}`, true, 0, 1)
 	if one != nil && len(*one) == 1 {
 		return mgo.BsonIdToSId((*one)[0]["_id"])
 	}
@@ -1445,17 +1446,17 @@ func GetNextDataId(id string) string {
 }
 
 //获取已标注和数据总数的信息
-func GetCheckedAndAllDataInfo() (int, int) {
-	allCount := util.MgoM.Count(util.Coll, QueryFind)
+func GetCheckedAndAllDataInfo(query map[string]interface{}, coll string) (int, int) {
+	allCount := util.MgoM.Count(coll, query)
 	ckDataQuery := map[string]interface{}{
 		"ck_data": map[string]interface{}{
 			"$gt": 0,
 		},
 	}
-	for k, v := range QueryFind {
+	for k, v := range query {
 		ckDataQuery[k] = v
 	}
-	checkedCount := util.MgoM.Count(util.Coll, ckDataQuery)
+	checkedCount := util.MgoM.Count(coll, ckDataQuery)
 	return checkedCount, allCount
 }
 
@@ -1517,3 +1518,17 @@ func (i *Front) Tj() error {
 	i.T["total"] = len(*list)
 	return i.Render("tj.html", &i.T)
 }
+
+//标错列表
+func (i *Front) Elist() error {
+	attrname := i.GetString("attrname")
+	common := util.Config.Biaozhu["common"]
+	elist, _ := util.MgoM.Find(util.Config.Totablel, `{"ck_`+attrname+`":"0"}`, `{"_id":1}`, `{"_id":1}`, false, -1, -1)
+	for _, v := range *elist {
+		v["_id"] = mgo.BsonIdToSId(v["_id"])
+	}
+	i.T["elist"] = *elist
+	i.T["attrname"] = attrname
+	i.T["common"] = common
+	return i.Render("elist.html", &i.T)
+}

+ 49 - 0
src/front/user.go

@@ -0,0 +1,49 @@
+package front
+
+import (
+	qu "qfw/util"
+	"util"
+)
+
+//登录
+func (i *Front) Login() error {
+	qu.Debug(i.Method(), i.GetSession("password"))
+	if i.Method() == "GET" {
+		return i.Render("login.html")
+	} else {
+		username := i.GetString("username")
+		password := i.GetString("password")
+		se_password := qu.SE.EncodeString(password)
+		qu.Debug(se_password)
+		query := map[string]interface{}{
+			"name":     username,
+			"password": se_password,
+		}
+		user, _ := util.MgoM.FindOne("user", query)
+		if user != nil && len(*user) > 0 {
+			i.SetSession("loginuser", username)
+			i.SetSession("username", username)
+			i.SetSession("password", password)
+			return i.Redirect("/center/list")
+		} else {
+			if username != "" {
+				i.T["fail"] = "fail"
+			}
+			return i.Render("login.html", &i.T)
+		}
+	}
+}
+
+func (i *Front) SaveUser() {
+	defer qu.Catch()
+	username := i.GetString("username")
+	password := i.GetString("password")
+	se_password := qu.SE.EncodeString(password)
+	if util.MgoM.Update("user", `{"name":"`+username+`"}`, `{"$set":{"password":"`+se_password+`"}}`, false, false) {
+		i.SetSession("password", password)
+		i.ServeJson(map[string]interface{}{"flag": true})
+		return
+	}
+	i.ServeJson(map[string]interface{}{"flag": false})
+	return
+}

File diff suppressed because it is too large
+ 6 - 0
src/web/staticres/css/AdminLTE.min.css


+ 3 - 0
src/web/staticres/css/other.css

@@ -0,0 +1,3 @@
+.user-panel{
+	padding:0px !important;	
+}

+ 516 - 0
src/web/staticres/js/detail.js

@@ -0,0 +1,516 @@
+
+    var app = new Vue({
+    el: '#app',
+    delimiters:["[[","]]"],
+    data: {
+    textMap: ['','','增', '改', '删'],
+    tempHtml: tempHtml,
+    dataHtml: dataHtml,
+    fileHtml: fileHtml,
+    showPop: false,
+    editData: [
+{
+    title: '基本字段',
+    show:true,
+    status:"1",
+    content: [
+{
+    title: '',
+    show: true,
+    delete: false,
+    //wstatus:"-1",
+    uInput: uInput
+    //content: c_content
+}
+    ]
+},
+{
+    title: '时间地点',
+    show:false,
+    status:"1",
+    content: [
+{
+    title: '',
+    show: true,
+    delete: false,
+    //wstatus:"-1",
+    uInput: tpInput
+}
+    ]
+},
+{
+    title: '标的信息',
+    show: false,
+    showCheck: true,
+    checkType: {{.T.ck_pclisext}},
+    status: {{.T.ck_purchasinglist}},
+    content: pcl_content
+},
+{
+    title: '多包信息',
+    show: false,
+    showCheck: true,
+    checkType: {{.T.ck_pkgisext}},
+    status: {{.T.ck_package}},
+    content: p_content
+},
+{
+    title: '中标候选人信息',
+    show: false,
+    showCheck: true,
+    checkType: {{.T.ck_wodrisext}},
+    status: {{.T.ck_winnerorder}},
+    content: c_content
+},
+{
+    title: '其余信息',
+    show:false,
+    status:"1",
+    content: [
+{
+    title: '',
+    show: true,
+    delete: false,
+    //wstatus:"-1",
+    uInput: otherInput
+}
+    ]
+}
+    ]
+},
+    methods: {
+    openHref () {
+    if(!issave){
+    alert("请先保存数据!")
+    return
+}else{
+    window.location.href = nextid ? `/center/detail/${nextid}.html` : '/center/finishcheck';
+}
+},
+    checkOneStatus: function (config) {
+    var tempObj = {
+    obj: config.type ? config.one : config.two
+}
+    if (config.type) {
+    tempObj.list = config.one.content
+} else {
+    tempObj.list = config.two.uInput
+}
+
+    var statusList = [0,0,0,0,0]
+    for(var i in tempObj.list) {
+    var tempList = tempObj.list[i]
+    var tempIndex = Number(tempList.status)
+    if (tempIndex == -1) {
+    tempIndex = 0
+}
+    statusList[tempIndex] = Number(statusList[tempIndex]) + 1
+}
+
+    if (statusList[1] > 0) {
+    tempObj.obj.status = 1
+}
+
+    if (statusList[4] > 0 || statusList[3] > 0 || statusList[2] > 0) {
+    tempObj.obj.status = 3
+}
+    if (statusList[4] === tempObj.list.length) {
+    tempObj.obj.status = 4
+}
+    if (statusList[3] === tempObj.list.length) {
+    tempObj.obj.status = 3
+}
+    if (statusList[2] === tempObj.list.length) {
+    tempObj.obj.status = 2
+}
+    if (statusList[0] === tempObj.list.length) {
+    tempObj.obj.status = -1
+}
+    if (!config.type) {
+    this.checkOneStatus({
+    one: config.one,
+    two: config.two,
+    type: true
+})
+}
+},
+    //切换状态按钮
+    setStatus:function(witch,s, two, one){
+    var key = witch.key
+    //校验日期格式
+    if(key=="bidendtime"||key=="bidopentime"||key=="project_startdate"||key=="project_completedate"||key=="publishtime"||key=="signaturedate"){
+    var val = witch.input
+    if(val!=""){
+    var reg = /^[1-9]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])\s+(20|21|22|23|[0-1]\d):[0-5]\d:[0-5]\d$/;
+    var regExp = new RegExp(reg);
+    if(!regExp.test(val)){
+    alert(witch.title+",日期格式错误!正确格式:2006-01-02 15:04:05")
+    return
+}
+}
+}
+    witch.status = s;
+    if (two) {
+    this.checkOneStatus({
+    one: one,
+    two: two,
+    type: false
+})
+}
+},
+    //二级删除
+    delNewTwo: function (one, index, two) {
+    if (two.ck_isnew) {
+    one.content.splice(index, 1)
+} else {
+    two.status = 4
+    this.saveDataTwo(two, 4, one)
+}
+    this.checkOneStatus({
+    one: one,
+    two: two,
+    type: true
+})
+},
+    /*add style*/
+    addStyle: function (data) {
+    //console.dir(data)
+    return prettyPrint(data).replace(/(checkType|showCheck|wstatus|status|key|title|input|content|uInput|selectArr|select|show|true)/g, "<mark>$1</mark>")
+},
+    /*同步修改源码*/
+    changeText: function (boolean) {
+    try {
+    var tempText = JSON.parse(this.$refs.text.innerText.replace(/(\n|\s)/g, ''))
+    if(boolean){
+    this.tagvalues = tempText
+}else{
+    this.editData = tempText
+}
+} catch (err) {
+    alert('源码修改失败')
+}
+},
+    goText: function (value) {
+    /*重置Html*/
+    this.dataHtml = this.tempHtml
+    if (!value) {return false}
+    var rs = new RegExp('(' + value + ')', 'gi')
+
+    if (rs.test(this.dataHtml)) {
+    this.dataHtml = this.dataHtml.replace(rs, '<mark>$1</mark>')
+    /*延迟查询dom,防止dom未插入*/
+    var $this = this
+    setTimeout(function () {
+    $this.goMark()
+}, 150)
+} else {
+    /*重置Html*/
+    this.dataHtml = this.tempHtml
+}
+},
+    goMark: function () {
+    /*滚动到第一个mark*/
+    var temp = document.querySelectorAll('mark')[0]
+    document.querySelector('.article').scrollTop = offset(temp).top - window.screen.height / 2
+},
+    markTag:function(n){
+    $.ajax({
+    url:"/markTag",
+    method:"post",
+    data: {tag:n,_id:_id},
+    success:function(res){
+    if(res){
+    document.getElementById("com-alert-val").innerHtml="标记成功";
+    var label1 = document.getElementById("com-alert");
+    label1.style.display="block";
+    setTimeout(function(){label1.style.display="none";},1000)
+}
+}
+});
+},
+    addChild: function (one) {
+    var tempNode = {}
+    switch (one.title) {
+    case "标的信息": {
+    tempNode = {
+    content: [],
+    show:true,
+    ck_isnew: true,
+    status: 2,
+    title:"标的物",
+    uInput: JSON.parse(JSON.stringify(pclfInput))
+}
+    break
+}
+    case "多包信息": {pfInput
+    tempNode = {
+    content: [],
+    show:true,
+    status: 2,
+    ck_isnew: true,
+    title:"子包",
+    uInput: JSON.parse(JSON.stringify(pfInput))
+}
+    break
+}
+    case "中标候选人信息": {
+    tempNode = {
+    content: [],
+    show:true,
+    status: 2,
+    ck_isnew: true,
+    title:"候选人",
+    uInput: JSON.parse(JSON.stringify(wodfInput))
+}
+    break
+}
+}
+    // if (one.status >= 2) {
+    //     one.status = '2'
+    // }
+    one.content.push(tempNode)
+    this.checkOneStatus({
+    one: one,
+    type: true
+})
+},
+    //保存
+    saveDataTwo:function(two,n, one){
+    two.uInput.forEach(function(v) {
+    var key = v.key
+    if(key=="bidendtime"||key=="bidopentime"||key=="project_startdate"||key=="project_completedate"||key=="publishtime"||key=="signaturedate"){
+    var val = v.input
+    if(val!=""){
+    var reg = /^[1-9]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])\s+(20|21|22|23|[0-1]\d):[0-5]\d:[0-5]\d$/;
+    var regExp = new RegExp(reg);
+    if(!regExp.test(val)){
+    alert(v.title+",日期格式错误!正确格式:2006-01-02 15:04:05")
+    return
+}
+}
+}
+    if(n =="1" && v.status == "-1"){
+    v.status = n
+} else if (n=="-1"){
+    v.status = n
+} else if (n=="4"){
+    v.status = n
+}
+});
+    two.status = n
+    this.checkOneStatus({
+    one: one,
+    two: two,
+    type: false
+})
+    /**
+     two.content.forEach(function(v) {
+                v.uInput.forEach(function(value) {
+                    if (value.input && value.input != '') {
+                        value.status = n
+                    }
+                })
+            })
+     */
+},
+    saveDataOne:function(one,n){
+    //保存后的样式
+    var _this = this
+    one.content.forEach(function(v) {
+    v.uInput.forEach(function(value) {
+    var key = value.key
+    if(n==1){
+    if(key=="bidendtime"||key=="bidopentime"||key=="project_startdate"||key=="project_completedate"||key=="publishtime"||key=="signaturedate"){
+    var val = value.input
+    if(val != ""){
+    var reg = /^[1-9]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])\s+(20|21|22|23|[0-1]\d):[0-5]\d:[0-5]\d$/;
+    var regExp = new RegExp(reg);
+    if(!regExp.test(val)){
+    alert(value.title+",日期格式错误!正确格式:2006-01-02 15:04:05")
+    return
+}
+}
+}
+}
+    // 取消全部,通过时判断状态是否处于修改新增等
+    if (n =="1" && value.status == "-1"){
+    value.status = n
+}else if (n=="-1"){
+    value.status = n
+}
+})
+
+    _this.checkOneStatus({
+    two: v,
+    one: one,
+    type: false
+})
+});
+    // one.content.forEach(function(v) {
+    //     if (v.content) {
+    //         v.content.forEach(function(i) {
+    //             i.uInput.forEach(function(value) {
+    //                 if (value.input && value.input != '') {
+    //                     value.status = n
+    //                 }
+    //             })
+    //         })
+    //     }
+    // });
+    //保存当前标记
+},
+    //验证保存提示
+    open:function(stype) {
+    this.$confirm('是否保存?', '提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning'
+}).then(() => {
+    this.upChange(stype)
+}).catch(() => {
+});
+},
+    //保存事件
+    upChange: function (stype) {
+    var resultStatus = false
+
+    if (stype == 1) {
+    var checkAllKey = this.editData.filter(function (one) {
+    var otherOne = one.content.filter(function(v) {
+    return v.uInput.filter(function (u) {
+    return u.status == '-1'
+}).length
+})
+    if ((one.title=="标的信息"||one.title=="多包信息"||one.title=="中标候选人信息") && (one.status == "-1")) {
+    return true
+} else {
+    return otherOne.length
+}
+})
+    resultStatus = !Boolean(checkAllKey.length)
+} else {
+    var checkOnlyKey = this.editData.filter(function (one) {
+    if (one.title=="标的信息"||one.title=="多包信息"||one.title=="中标候选人信息") {
+    if (one.status == "-1") {
+    return false
+} else {
+    if (one.content.length === 0) {
+    return true
+}
+    var otherOne = one.content.filter(function(v) {
+    return v.uInput.filter(function (u) {
+    return u.status == '-1'
+}).length
+})
+    return !(otherOne.length > 0)
+}
+} else {
+    var otherOne = one.content.filter(function(v) {
+    return v.uInput.filter(function (u) {
+    return u.status != '-1'
+}).length
+})
+    return otherOne.length
+}
+})
+    resultStatus = Boolean(checkOnlyKey.length)
+}
+
+    if (!resultStatus) {
+    this.$alert("未标注完成");
+    return
+}
+    var d= JSON.stringify(this.editData);
+    console.log(d)
+    $.ajax({
+    url:"/center/biaozhu",
+    method:"post",
+    data: {key:d,_id:_id,stype:stype},
+    success:function(res){
+    if(res){
+    document.getElementById("com-alert-val").innerHtml="保存成功";
+    var label1 = document.getElementById("com-alert");
+    label1.style.display="block";
+    setTimeout(function(){
+    label1.style.display="none";
+},1000)
+    issave = true//保存成功
+}
+},
+    error:function(err){
+    alert(err);
+}
+});
+}
+    /**
+     //保存提示
+     open:function(one, type) {
+                this.$confirm('是否保存?', '提示', {
+                    confirmButtonText: '确定',
+                    cancelButtonText: '取消',
+                    type: 'warning'
+                }).then(() => {
+                    if (type) {
+                        this.saveOneData(one)
+                    } else {
+                        this.upChange()
+                    }
+                }).catch(() => {
+                });
+            },
+     //一级保存
+     saveOneData: function (one) {
+                console.log(one.status)
+                if (one.title=="标的信息"||one.title=="多包信息"||one.title=="中标候选人信息"){
+                    if(one.status ==  "-1"){
+                        this.$alert(one.title+" 未标注完成")
+                        return
+                    }else if (one.status !="-1"){
+                        var isAlert = one.content.filter(function(v) {
+                            return v.uInput.filter(function (u) {
+                                return u.status == '-1'
+                            }).length
+                        })
+                        if (isAlert.length) {
+                            this.$alert(one.title+" 未标注完成")
+                            return
+                        }
+                    }
+                }
+                onetext = "["+ JSON.stringify(one) +"]";
+                console.log(onetext)
+                $.ajax({
+                    url:"/center/biaozhu",
+                    method:"post",
+                    data: {key:onetext,_id:_id},
+                    success:function(res){
+                        if(res){
+                            document.getElementById("com-alert-val").innerHtml="保存成功";
+                            var label1 = document.getElementById("com-alert");
+                            label1.style.display="block";
+                            setTimeout(function(){
+                                    label1.style.display="none";
+                                },
+                                1000)
+                        }
+                    },
+                    error:function(err){
+                        alert(err);
+                    }
+                });
+            },
+     */
+}
+})
+    function offset(elem) {
+    if(!elem) elem = this;
+
+    var x = elem.offsetLeft;
+    var y = elem.offsetTop;
+
+    while (elem = elem.offsetParent) {
+    x += elem.offsetLeft;
+    y += elem.offsetTop;
+}
+    return { left: x, top: y };
+}

+ 34 - 4
src/web/templates/detail.html

@@ -121,6 +121,7 @@
             </h4>
             <hr style="border:1 double;" width="100%">
             <br><a href="{{.T.info.href}}" target="_blank">查看原文</a>
+            <a href="{{.T.jyhref}}" target="_blank">剑鱼链接</a>
             <h3>{{.T.info.title}}</h3><br>
 
             {{if .T.info.detail}}
@@ -294,7 +295,7 @@
                 </div>
             </div>
             <div class="save-box">
-                <!--<button  class="code" @click.stop="showPop = true" style="width:100px">源码</button>&nbsp;&nbsp;-->
+<!--                <button  class="code" @click.stop="showPop = true" style="width:100px">源码</button>&nbsp;&nbsp;-->
                 <button  class="code" @click.stop="open(1)" style="width:100px">全部验证</button>
                 <button  class="code" @click.stop="open(2)" style="width:100px">字段验证</button>
 <!--            <button  class="code" @click.stop="open('', false)" style="width:100px">保存</button>&nbsp;&nbsp;-->
@@ -327,6 +328,7 @@
     var issave = false;
     var _id = {{.T.info._id}};
     var nextid = {{.T.nextid}};
+    console.log(nextid)
     //基本信息
     var common={{.T.common}};
     var uInput=[];
@@ -335,6 +337,10 @@
         tmp.title=common[k].descript
         tmp.input=common[k].value
         tmp.key=common[k].key
+        if(common[k].key=="subtype"){
+            tmp.select=common[k].value
+            tmp.selectArr={{.T.topsubtype}}
+        }
         if(common[k].key=="attach_discern"){
             tmp.select=common[k].value
             tmp.selectArr=['识别有效','识别无效']
@@ -343,6 +349,10 @@
             tmp.select=common[k].value
             tmp.selectArr=['抽取正确','抽取错误']
         }
+        if(common[k].key=="isrepeat"){
+            tmp.select=common[k].value
+            tmp.selectArr=['是','否']
+        }
         tmp.status=common[k].status
         uInput[k]=tmp
     }
@@ -609,7 +619,27 @@
                  alert("请先保存数据!")
                  return
               }else{
-                  window.location.href = nextid ? `/detail/${nextid}.html` : '/finishcheck';
+                  if(nextid==""){
+                      window.location.href = '/center/finishcheck';
+                  }else{
+                      $.ajax({
+                          url: "/center/checkid",
+                          type: "post",
+                          data: {"id":nextid},
+                          async: false,
+                          success: function (r) {
+                              if(r && r.msg == ""){
+                                  if(r.exists){//标注完成
+                                      window.location.href = "/center/finishcheck";
+                                  }else if (!r.exists){
+                                      window.location.href = "/center/detail/"+r.id+".html"
+                                  }
+                              }else{
+                                  alert("标注出错!"+r.msg)
+                              }
+                          }
+                      })
+                  }
               }
             },
             checkOneStatus: function (config) {
@@ -948,7 +978,7 @@
                 var d= JSON.stringify(this.editData);
                 console.log(d)
                 $.ajax({
-                    url:"/biaozhu",
+                    url:"/center/biaozhu",
                     method:"post",
                     data: {key:d,_id:_id,stype:stype},
                     success:function(res){
@@ -1005,7 +1035,7 @@
                 onetext = "["+ JSON.stringify(one) +"]";
                 console.log(onetext)
                 $.ajax({
-                    url:"/biaozhu",
+                    url:"/center/biaozhu",
                     method:"post",
                     data: {key:onetext,_id:_id},
                     success:function(res){

+ 3 - 0
src/web/templates/err.html

@@ -0,0 +1,3 @@
+<html>
+  {{if .T.err}}{{.T.err}}{{else}}数据错误{{end}}
+</html>

+ 141 - 20
src/web/templates/list.html

@@ -3,11 +3,11 @@
 <head>
     <meta charset="UTF-8">
     <title>信息抽查</title>
-    <link href="css/bootstrap.min.css" rel="stylesheet">
-    <link href="css/page.css" rel="stylesheet">
-    <script src="js/jquery.js"></script>
-    <script src="js/bootstrap.min.js"></script>
-    <script src="js/util.js"></script>
+    <link href="/css/bootstrap.min.css" rel="stylesheet">
+    <link href="/css/page.css" rel="stylesheet">
+    <script src="/js/jquery.js"></script>
+    <script src="/js/bootstrap.min.js"></script>
+    <script src="/js/util.js"></script>
     <script src="/js/vue.min.js"></script>
     <script src="/js/index.js"></script>
     <script src="/js/jquery-page.js"></script>
@@ -15,6 +15,7 @@
     <style>
         .form-horizontal {
             min-height: 40px;
+            margin-top: 20px;
         }
 
         .row-box label {
@@ -54,6 +55,45 @@
     </style>
 </head>
  <body>
+ <!-- 模态框(Modal) -->
+ <div class="modal fade" id="editeuser" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+     <div class="modal-dialog">
+         <div class="modal-content">
+             <div class="modal-header">
+                 <div class="modal-header">
+                     <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+                     <div class="edit-form">
+                         <div class="edit-info">
+                             <span class="glyphicon glyphicon-edit" aria-hidden="true"></span>
+                             <span class="info">信息修改<span>
+                         </div>
+                         <form class="form-horizontal" role="form">
+                             <div class="form-group">
+                                 <label for="username" class="col-sm-2 control-label">用户名:</label>
+                                 <div class="col-sm-10">
+                                     <input type="text" readonly="readonly" value='{{session "username"}}' class="form-control" id="username">
+                                 </div>
+                             </div>
+                             <div class="form-group password">
+                                 <label for="password" class="col-sm-2 control-label">密码:</label>
+                                 <div class="col-sm-10">
+                                     <input type="text" class="form-control" id="password" value='{{session "password"}}'>
+                                 </div>
+                                 <span class="passwordEdit hide check">密码不能为空</span>
+                             </div>
+                             <div class="form-group">
+                                 <div class="col-sm-offset-2 col-sm-10">
+                                     <input type="button" onclick="saveuser()" class="btn btn-primary" value="保存">
+                                     <input type="button" onclick="cancel()" class="btn btn-default" value="取消">
+                                 </div>
+                             </div>
+                         </form>
+                     </div>
+                 </div>
+             </div>
+         </div><!-- /.modal-content -->
+     </div><!-- /.modal -->
+ </div>
  <div>
   <div class="modal fade" id="loadingModal" backdrop="static" keyboard="false">
       <div style="width: 200px;height:100px; z-index: 20000; position: absolute; text-align: center; left: 50%; top: 50%;margin-left:-100px;margin-top:-10px">
@@ -63,9 +103,13 @@
           </div>
       </div>
   </div>
+  <div style="background-color: #3c8dbc;text-align: right;">
+      <div style="text-align: right;text-align: right;" class="glyphicon glyphicon-user"></div>
+      <h3  onclick="editeuser()" style=" cursor:pointer;color: #FFFFFF;margin-top: 10px;margin-right: 15px;display: -webkit-inline-box;">{{session "loginuser"}}</h3>
+  </div>
   <div class="col-md-12" style="border-right: 1px double #EEEEEE;">
-         <div style="padding:30px 0px 0px 0px">
-             <form action="/list" class="form-horizontal" role="form">
+         <div style="padding:10px 0px 0px 0px">
+             <form action="/center/list" class="form-horizontal" role="form">
                  <div style="display: none">
                      <input type="input" name="pagenum" id="pagenum"  class="form-control" value="{{.T.pagenum}}"/>
                  </div>
@@ -78,7 +122,7 @@
                             placeholder="请输入库名"/>
                  </div>
                  <div class="col-md-1" style="padding-left: 0">
-                     <input type="input" name="coll" id="fromtable" class="form-control" value="{{.T.fromtable}}" placeholder="请输入表名"/>
+                     <input type="input" name="coll" id="fromtable" class="form-control" value='{{if ne .T.coll ""}}{{.T.coll}}{{else}}{{.T.fromtable}}{{end}}' placeholder="请输入表名"/>
                  </div>
                  <div class="col-md-7 row-box" style="padding-left: 0">
                      <div class=" row-box" style="padding-left: 0">
@@ -103,10 +147,7 @@
                          <input type="input" name="maxval" id="maxval" style="display:none" class="form-control"
                                 value="{{.T.max}}" placeholder="最大值"/>
                          <div id="boexists" style="display:none;margin-left: -29px;">
-<!--                             <label class="checkbox-inline">-->
-<!--                                 <input type="checkbox" id="hasno" name="hasno"  value="1">是否存在-->
-<!--                             </label>-->
-                             <input id="hasno" type="checkbox" name="hasno" value="true"/>
+                             <input id="hasno" type="checkbox" name="hasno" onclick="checkboxOnclick(this)" value={{if .T.hasno}} true {{else}} false {{end}}/>
                              <label style="margin-left: -28px;">包含不存在</label>
                          </div>
                      </div>
@@ -117,7 +158,7 @@
                      </div>-->
                      <button type="submit" style="display: none" class="btn btn-primary" id="submitForm"></button>
                      <div  class="btn btn-primary" style="margin-left: 15px" onclick="alertsync()">查看</div>
-                     <div  class="btn btn-primary" style="margin-left: 15px" onclick="syncmarked()">同步</div>
+<!--                     <div  class="btn btn-primary" style="margin-left: 15px" onclick="syncmarked()">同步</div>-->
                  </div>
              </form>
          </div>
@@ -136,7 +177,7 @@
                      导入Excel
                  </button>
              </div>
-             <iframe srcdoc="<form id='uploadform' method='post' enctype='multipart/form-data' action='/importbyexcel'><input type='file' name='xlsx' /><input type='input' id='excelcoll' name='excelcoll' /></form>"
+             <iframe srcdoc="<form id='uploadform' method='post' enctype='multipart/form-data' action='/center/importbyexcel'><input type='file' name='xlsx' /><input type='input' id='excelcoll' name='excelcoll' /></form>"
                      height=0 scrolling=no class="hide" id="fileframe">
              </iframe>
          </div>
@@ -156,7 +197,7 @@
              {{range $k,$v:=.T.list}}
              <div>
                  <span style="font-size:18px"><script>document.write({{ $v }}["num"])</script>:</span>&nbsp;
-                 <a href="/detail/{{$v._id}}.html" target="_blank" style="font-size:18px;color:{{if $v.checked}}green{{else}}#428bca{{end}}">{{$v.title}}</a>
+                 <div onclick="getdetail({{$v._id}})" style="display: inline-block;cursor:pointer;font-size:18px;color:{{if $v.checked}}green{{else}}#428bca{{end}}">{{$v.title}}</div>
              </div>
              {{end}}
          </div>
@@ -176,6 +217,7 @@ $(function(){
   if( {{.T.hasno}} ){
     $("#hasno").attr("checked",true);
   }
+
   for(i in {{.T.topsubtype}}){
     var selected = ""
     if({{.T.type}} == {{.T.topsubtype}}[i]){
@@ -201,6 +243,48 @@ $(function(){
   }
 
 })
+
+function getdetail(id) {
+    $.ajax({
+        url: "/center/checkid",
+        type: "post",
+        data: {"id":id},
+        async: false,
+        success: function (r) {
+            if(r && r.msg == ""){
+                if(r.exists){//标注完成
+                    window.open("/center/finishcheck");
+                }else if(!r.exists && r.id != id){
+                    vueApp.$confirm('此条数据正在标注,是否直接跳转到未标注数据?', {
+                        confirmButtonText: '确认',
+                        cancelButtonText: '取消',
+                        type: 'warning'
+                    }).then(() => {
+                        window.open("/center/detail/"+r.id+".html");
+                    }).catch(() => {
+                    });
+                }else if (!r.exists && r.id == id){
+                    window.open("/center/detail/"+r.id+".html");
+                }else{
+                    alert("标注出错!")
+                }
+            }else{
+                alert("标注出错!"+r.msg)
+            }
+        }
+    })
+}
+
+
+function checkboxOnclick(checkbox){
+    if ( checkbox.checked == true){
+        console.log("true")
+        $("#hasno").attr("value",true);
+    }else{
+        $("#hasno").attr("value",false);
+    }
+}
+
 function getescount(){
   var importcoll = $("#importcoll").val();
   if(importcoll == ""){
@@ -213,7 +297,7 @@ function getescount(){
     return
   }
   $.ajax({
-  	url:"/getescount",
+  	url:"/center/getescount",
   	method:"post",
   	data: {"estext":estext},
   	success:function(res){
@@ -236,7 +320,7 @@ function importbyes(count,msg,text,coll){
 function importes(estext,coll){
   //showLoading()
     $.ajax({
-        url: "/importbyes",
+        url: "/center/importbyes",
         method: "post",
         data: {"estext": estext, "coll": coll},
         success: function (r) {
@@ -294,7 +378,7 @@ function importbyexcel(){
                         //     alert(r.msg)
                         // }
                     }
-                    $(window.frames[0].document).find("body").append("<form id='uploadform' method='post' enctype='multipart/form-data' action='/importbyexcel'><input type='file' name='xlsx' /><input type='input' id='excelcoll' name='excelcoll' /></form>");
+                    $(window.frames[0].document).find("body").append("<form id='uploadform' method='post' enctype='multipart/form-data' action='/center/importbyexcel'><input type='file' name='xlsx' /><input type='input' id='excelcoll' name='excelcoll' /></form>");
                 }
             },
             500)
@@ -346,17 +430,22 @@ function alertsync() {
             alert("marked表无需同步");
             return
         }
+        showLoading();
         $.ajax({
-            url:"/syncmarked",
+            url:"/center/syncmarked",
             type:"post",
+            async:false,
             data:{"coll":coll},
             success:function (r) {
                 if(r){
                     console.log(r.msg);
                     alert(r.msg);
+                    hideLoading();
                     if(r.flag){
                         $("#submitForm").trigger('click');
                     }
+                }else{
+                    hideLoading()
                 }
             }
         })
@@ -383,7 +472,7 @@ function syncmarked() {
             return
         }
         $.ajax({
-            url:"/syncmarked",
+            url:"/center/syncmarked",
             type:"post",
             data:{"coll":coll},
             success:function (r) {
@@ -396,6 +485,38 @@ function syncmarked() {
     }
 
 }
+
+function saveuser() {
+    var username = $("#username").val();
+    var password = $("#password").val();
+    if(username!=""&&password!=""){
+        $.ajax({
+            url: "/center/saveuser",
+            type: "post",
+            data: {"username":username,"password":password},
+            success: function (r) {
+                if(r&&r.flag){
+                    alert("更新成功");
+                    $("#editeuser").modal("hide");
+                }else{
+                    alert("更新失败");
+                }
+            }
+        })
+    }else{
+        alert("用户或密码不能为空!")
+    }
+}
+
+function editeuser() {
+    $("#editeuser").modal("show");
+}
+
+function cancel() {
+    $("#editeuser").modal("hide");
+}
+
+
 </script>
 
 </html>

+ 151 - 0
src/web/templates/login.html

@@ -0,0 +1,151 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <title>标注中心</title>
+  <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
+  <!-- Bootstrap 3.3.6 -->
+  <link rel="stylesheet" href="css/bootstrap.min.css">
+  <!-- Font Awesome -->
+
+  <!-- Ionicons -->
+
+  <!-- Theme style -->
+  <link rel="stylesheet" href="css/AdminLTE.min.css">
+  <!-- iCheck -->
+ 
+  <!--[if lt IE 9]>
+  <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
+  <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
+  <![endif]-->
+<style>
+	.login-box-body{
+		text-align:center;
+		    background: transparent;
+	}
+	.login-box-body p{
+		padding:0;
+	}
+	.form-horizontal .form-group .username{
+		padding-right: 3px;
+	}
+	.login-form{
+		padding-top:33px;
+		width: 427px;
+    	border: 1px solid #E7E7E7;
+    	background: #fff;
+    	padding: 36px 30px 11px 20px;
+		left: -24px;
+    	position: relative;
+	}
+	.btn{
+		padding:6px 36px;
+		position: relative;
+    	margin-left: 64px;
+    	margin-top: 12px;
+	}
+	.form-password{
+		margin-top:28px;
+	}
+	#username{
+		width:250px;
+		display: inline-block;
+	}
+	#password{
+		width:250px;
+		display: inline-block;
+	}
+	.point-username{
+		float: right;
+   	 	margin-top: -43px;
+   		margin-right: -13px;
+		color:red;
+	}
+	.point-password{
+		float: right;
+   	 	margin-top: -104px;
+   		margin-right: -13px;
+		color:red;
+	}
+	#formSubmit{
+		margin-top:5px;
+	}
+	.point-user{
+		color:red;
+		font-size:16px;
+		margin-left:123px;
+		margin-top:-22px;
+	}
+</style>
+</head>
+<body class="hold-transition login-page">
+<div class="login-box">
+  <div class="login-logo">
+    <a href="javascript:void(0);">标注中心</a>
+  </div>
+
+	<div class="login-form">
+		<div class="point-user hidden">用户名或密码错误</div>
+		<form class="form-horizontal" id="formSubmit" role="form" action="/" method="post">
+		  <div class="form-group">
+		    <label for="firstname" class="col-sm-2 control-label username">用户名:</label>
+		 	<div class="col-sm-10">
+		      <input type="text" class="form-control" id="username" value="" name="username" placeholder="请输入用户名">
+			   <span class="glyphicon glyphicon-user form-control-feedback"></span>
+      </div>
+		  </div>
+		<div class="point-username hidden">不能为空</div>
+		  <div class="form-group form-password">
+		    <label for="lastname" class="col-sm-2 control-label">密&nbsp;&nbsp;&nbsp;&nbsp;码:</label>
+		    <div class="col-sm-10">
+		      <input type="password" class="form-control" id="password" value="" name="password" placeholder="请输入密码">
+		      <span class="glyphicon glyphicon-lock form-control-feedback" ></span>
+        </div>
+		  </div>
+		  <div class="form-group">
+		    <div class="col-sm-offset-2 col-sm-10">
+		      <input type="button" class="btn btn-default" value="登录">
+		    </div>
+		  </div>
+		<div class="point-password hidden">不能为空</div>
+		</form>
+	</div>
+
+
+<!-- jQuery 2.2.3 -->
+<script src="js/jquery.js"></script>
+<!-- Bootstrap 3.3.6 -->
+<script src="js/bootstrap.min.js"></script>
+<script>
+	$(function(){
+		$("#username").focus();
+		$(".btn").click(function(){
+			btnClick();
+		})
+		$("#password").keydown(function(event){
+			var key = event.keyCode;
+			if(key == 13){
+				btnClick();
+			}
+		})
+	})
+	
+	function btnClick(){
+		var username = $("#username").val().trim().replace(/\s/g,"");
+		var password = $("#password").val().trim().replace(/\s/g,"");
+		if(username == ""){
+			$(".point-username").removeClass("hidden");
+		}else if(password == ""){
+			$(".point-password").removeClass("hidden");
+		}else{
+			$("#formSubmit").submit();  
+		}
+	}
+	{{if .T.fail}}
+		alert("用户名或密码有误!")
+	{{end}}
+</script>
+
+</body>
+</html>

Some files were not shown because too many files changed in this diff