server.go 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138
  1. // front
  2. package front
  3. import (
  4. "encoding/json"
  5. "io/ioutil"
  6. //"container/list"
  7. "fmt"
  8. qu "qfw/util"
  9. "qfw/util/redis"
  10. mgo "mongodb"
  11. "strings"
  12. "sync"
  13. "time"
  14. "util"
  15. "github.com/go-xweb/xweb"
  16. "go.mongodb.org/mongo-driver/bson"
  17. "github.com/tealeg/xlsx"
  18. es "gopkg.in/olivere/elastic.v1"
  19. )
  20. type Front struct {
  21. *xweb.Action
  22. // elist xweb.Mapper `xweb:"/elist"`
  23. login xweb.Mapper `xweb:"/"`
  24. saveUser xweb.Mapper `xweb:"/center/saveuser"`
  25. listInfo xweb.Mapper `xweb:"/center/list"`
  26. checkId xweb.Mapper `xweb:"/center/checkid"`
  27. detail xweb.Mapper `xweb:"/center/detail/(.*).html"`
  28. biaozhu xweb.Mapper `xweb:"/center/biaozhu"`
  29. importByExcel xweb.Mapper `xweb:"/center/importbyexcel"`
  30. importByEs xweb.Mapper `xweb:"/center/importbyes"`
  31. getEsCount xweb.Mapper `xweb:"/center/getescount"`
  32. finishCheck xweb.Mapper `xweb:"/center/finishcheck"`
  33. errCheck xweb.Mapper `xweb:"/center/errcheck"`
  34. syncMarked xweb.Mapper `xweb:"/center/syncmarked"`
  35. markedInit xweb.Mapper `xweb:"/center/markedinit"`
  36. review xweb.Mapper `xweb:"/center/review"` // 质检
  37. reviewList xweb.Mapper `xweb:"/center/reviewlist"` // 质检数据列表
  38. reviewDetail xweb.Mapper `xweb:"/center/reviewdetail/(.*).html"`
  39. reviewSave xweb.Mapper `xweb:"/center/reviewsave"`
  40. reviewStat xweb.Mapper `xweb:"/center/review/result"`
  41. reviewNext xweb.Mapper `xweb:"/center/review/next"`
  42. }
  43. var preKey = "ck_"
  44. var preErr = "err_"
  45. var SE = qu.SimpleEncrypt{Key: "topJYBX2019"}
  46. var CheckLock = &sync.Mutex{}
  47. var LABELER, AUDITOR, ADMIN = 1, 2, 3 //标注人员,审核人员,管理员
  48. /*
  49. status
  50. -1:初始未验证
  51. 1:正确
  52. 2:新增
  53. 3:修改
  54. 4:删除
  55. */
  56. //列表
  57. func (i *Front) ListInfo() error {
  58. //loginuser := i.GetSession("loginuser").(string)
  59. spidercode := i.GetString("spidercode")
  60. coll := i.GetString("coll")
  61. field := i.GetString("field")
  62. stype := i.GetString("type")
  63. min := i.GetString("minval") //min max不用int类型接收,以免有默认值0
  64. max := i.GetString("maxval")
  65. hasno, _ := i.GetBool("hasno")
  66. notag, _ := i.GetBool("notag")
  67. pagenum, _ := i.GetInteger("pagenum")
  68. labeler := i.GetString("labeler")
  69. if pagenum == 0 { //页码
  70. pagenum = 1
  71. }
  72. qu.Debug("coll:", coll, "stype:", stype, "field:", field, "hasno:", hasno, "notag:", notag, "max:", max, "min:", min, "pagenum:", pagenum, "labeler:", labeler)
  73. query := map[string]interface{}{}
  74. if spidercode != "" { //爬虫代码
  75. query["spidercode"] = spidercode
  76. }
  77. if stype != "-1" && stype != "" { //类型
  78. if stype == util.SPECIALTYPE {
  79. query["subtype"] = map[string]interface{}{
  80. "$exists": false,
  81. }
  82. } else {
  83. subtype := strings.Split(stype, "-")[1]
  84. query["subtype"] = subtype
  85. }
  86. }
  87. fieldScreen := false
  88. if field != "-1" && field != "" { //字段
  89. fieldScreen = true
  90. queryfield := map[string]interface{}{
  91. "$exists": !hasno,
  92. }
  93. if field == "budget" || field == "bidamount" { //金额区间
  94. numMap := map[string]interface{}{}
  95. if min != "" {
  96. minint := qu.IntAll(min)
  97. numMap["$gte"] = minint
  98. }
  99. if max != "" {
  100. maxint := qu.IntAll(max)
  101. numMap["$lte"] = maxint
  102. }
  103. if len(numMap) > 0 { //给定了区间,不再判断字段存在
  104. queryfield = numMap
  105. }
  106. }
  107. query[field] = queryfield
  108. }
  109. if fieldScreen && notag {
  110. query[preKey+field] = map[string]interface{}{
  111. "$exists": false,
  112. }
  113. } else if !fieldScreen && notag {
  114. query["ck_data"] = 0
  115. }
  116. //标注人员
  117. if labeler != "" {
  118. query["modifyuser"] = labeler
  119. }
  120. qu.Debug("query:", coll, query)
  121. if coll == "" {
  122. coll = util.Config.Fromtable
  123. }
  124. i.SetSession("coll", coll) //session中存入查询表
  125. i.SetSession("query", query) //session中存入查询条件
  126. listData := getListInfo(coll, query, pagenum)
  127. i.T["list"] = listData
  128. i.T["type"] = stype
  129. i.T["field"] = field
  130. i.T["spidercode"] = spidercode
  131. i.T["coll"] = coll
  132. i.T["topsubtype"] = util.TopSubStypeArr
  133. i.T["allfield"] = util.AllFieldArr
  134. i.T["fromtable"] = util.Config.Fromtable
  135. i.T["dbname"] = util.Config.Dbname
  136. i.T["max"] = max
  137. i.T["min"] = min
  138. i.T["hasno"] = hasno
  139. i.T["notag"] = notag
  140. checkedNum, allNum := GetCheckedAndAllDataInfo(query, coll) //已标和总数信息
  141. i.T["checkednum"] = checkedNum
  142. i.T["allnum"] = allNum
  143. i.T["pagenum"] = pagenum
  144. role := qu.IntAll(i.GetSession("role"))
  145. i.T["role"] = role
  146. i.T["labeler"] = labeler
  147. if role >= AUDITOR {
  148. i.T["labelers"] = GetLabeler(coll)
  149. }
  150. return i.Render("list.html", &i.T)
  151. }
  152. //判断id是否正在被标记
  153. func (i *Front) CheckId() {
  154. defer qu.Catch()
  155. CheckLock.Lock()
  156. defer CheckLock.Unlock()
  157. msg := ""
  158. id := i.GetString("id")
  159. coll := i.GetSession("coll").(string)
  160. qu.Debug(coll, id)
  161. if coll != "" {
  162. exists, err := redis.Exists("extcheck", coll+"_"+id)
  163. if err == nil {
  164. if exists {
  165. id, exists = GetNoCheckedId(id, coll)
  166. }
  167. } else {
  168. msg = "校验数据出错!"
  169. }
  170. i.ServeJson(map[string]interface{}{"msg": msg, "id": id, "exists": exists})
  171. return
  172. }
  173. i.ServeJson(map[string]interface{}{"msg": "数据校验表出错!"})
  174. }
  175. //标注
  176. func (i *Front) Biaozhu() error {
  177. b := false
  178. obj := []map[string]interface{}{}
  179. //ispackage := i.GetString("ispackage")
  180. key := i.GetString("key")
  181. _id := i.GetString("_id")
  182. stype, _ := i.GetInteger("stype")
  183. err := json.Unmarshal([]byte(key), &obj)
  184. if err != nil {
  185. i.ServeJson(b)
  186. return nil
  187. }
  188. //base := map[string]interface{}{}
  189. set := map[string]interface{}{} //更新、新增字段
  190. unset := map[string]interface{}{} //删除字段
  191. errset := map[string]interface{}{} //记录修改的字段信息
  192. isSaveMarked := false
  193. if len(obj) == 1 { //单独保存某个一级
  194. content, ok := obj[0]["content"].([]interface{})
  195. if !ok || len(content) == 0 {
  196. i.ServeJson(b)
  197. return nil
  198. }
  199. title := qu.ObjToString(obj[0]["title"])
  200. isext, _ := obj[0]["checkType"].(bool)
  201. istag, _ := obj[0]["checkAllTag"].(bool)
  202. status := qu.IntAll(obj[0]["status"])
  203. switch title {
  204. case "基本字段":
  205. BzJBZD(content, set, unset, errset)
  206. case "时间地点":
  207. BzSJDD(content, set, unset, errset)
  208. case "标的信息":
  209. BzBDXX(content, set, unset, errset, isext, istag, status)
  210. case "多包信息":
  211. BzDBXX(content, set, unset, errset, isext, status)
  212. case "中标候选人信息":
  213. BzZBHXRXX(content, set, unset, errset, isext, status)
  214. case "其余信息":
  215. BzQYXX(content, set, unset, errset)
  216. }
  217. } else {
  218. isSaveMarked = true
  219. for j, val := range obj {
  220. content, ok := val["content"].([]interface{})
  221. status := qu.IntAll(val["status"])
  222. if !ok {
  223. continue
  224. // i.ServeJson(b)
  225. // return nil
  226. }
  227. isext, _ := val["checkType"].(bool)
  228. istag, _ := val["checkAllTag"].(bool)
  229. if j == 0 { //基本信息
  230. BzJBZD(content, set, unset, errset)
  231. } else if j == 1 { //时间地点
  232. BzSJDD(content, set, unset, errset)
  233. } else if j == 2 { //标的物
  234. BzBDXX(content, set, unset, errset, isext, istag, status)
  235. } else if j == 3 { //多包
  236. BzDBXX(content, set, unset, errset, isext, status)
  237. } else if j == 4 { //候选人
  238. BzZBHXRXX(content, set, unset, errset, isext, status)
  239. } else { //其余信息
  240. BzQYXX(content, set, unset, errset)
  241. }
  242. }
  243. }
  244. qu.Debug("errset---", errset)
  245. qu.Debug("set---", set)
  246. qu.Debug("unset---", unset)
  247. userInfo := map[string]interface{}{} //记录本次标注日志
  248. modifyFields := map[string]interface{}{} //本次标注所有字段
  249. unerrset := map[string]interface{}{} //记录errdata错误信息表删除
  250. loginuser := i.GetSession("loginuser").(string)
  251. coll := i.GetSession("coll").(string)
  252. data, _ := util.MgoM.FindById(coll, _id, nil) //查询标注保存前的原始信息
  253. modifyuser := qu.ObjToString((*data)["modifyuser"])
  254. //标注多次操作处理
  255. if len(set) > 0 { //set中为本次标注保存的数据(ck_bidopentime:1;ck_buyer:2;buyer:"XXX")
  256. for s, sv := range set {
  257. //特殊字段处理
  258. if s == "ck_pclistag" && (*data)["ck_pclistag"] != nil {
  259. delete(set, s)
  260. continue
  261. }
  262. //区分是标记字段,还是普通字段(标记字段:ck_buyer;普通字段:buyer)
  263. if strings.HasPrefix(s, preKey) {
  264. status := qu.IntAll(sv) //标注字段状态
  265. field := s[3:] //去除前缀,被标注字段
  266. checkedStatus := qu.IntAll((*data)[s]) //数据库被标注状态
  267. if status == 1 && (checkedStatus == 2 || checkedStatus == 1) { //数据库已有标记,且页面标注正确,此次该字段不做标注保存
  268. qu.Debug("已标注字段field---", field)
  269. delete(set, field)
  270. delete(set, s)
  271. continue
  272. } else {
  273. qu.Debug("未标注字段field---", field, status)
  274. if set[field] == nil && status != 2 { //表示该字段没有要修改的值,此时标记为1或2(亦或是ck_wodrisext;ck_pkgisext;ck_pclisext)
  275. modifyFields[field] = set[s] //目前会有pclisext、pclistag、pkgisext、wodrisext
  276. continue
  277. } else { //此时有修改的值和标记2
  278. modifyFields[field] = status //记录标注的字段和状态
  279. if checkedStatus != 0 { //已有标注信息的状态
  280. if status == 2 && checkedStatus == 2 { //字段已被修改且本次也为修改
  281. errdata, _ := util.MgoM.FindById(util.Config.Totablel, _id, map[string]interface{}{"userinfo": 0})
  282. //if field == "package" || field == "purchasinglist" || field == "winnerorder" {
  283. //}
  284. if errdata != nil && len(*errdata) != 0 {
  285. qu.Debug(field, (*errdata)[field] != nil, fmt.Sprint((*errdata)[field]))
  286. delete(errset, field) //errdata中有该字段的错误记录,不再更新errdata
  287. //对比errdata错误值:相等变为1,errdata删除;不等变为2,标注表修改该字段
  288. errText := fmt.Sprint((*errdata)[field])
  289. text := fmt.Sprint(set[field])
  290. qu.Debug("errText---", errText, text)
  291. if errText == text {
  292. set[s] = 1 //更新标注表字段状态
  293. unerrset[field] = "" //删除errdata表字段
  294. //delete(errset, field)
  295. }
  296. }
  297. }
  298. }
  299. }
  300. }
  301. }
  302. }
  303. }
  304. qu.Debug("errset---", errset)
  305. qu.Debug("set---", set)
  306. qu.Debug("unset---", unset)
  307. qu.Debug("unerrset---", unerrset)
  308. //1、errdata操作
  309. //存储原错误信息
  310. errUpdata := map[string]interface{}{} //errdata所有要更新内容
  311. for f, v := range errset {
  312. qu.Debug("err filed---", f, v)
  313. //if f != "package" && f != "purchasinglist" && f != "winnerorder" {
  314. errset[f] = (*data)[f]
  315. //}
  316. }
  317. if len(modifyFields) > 0 { //有标注字段,记录标注信息
  318. errset["updatetime"] = time.Now().Unix()
  319. errset["modifyuser"] = loginuser
  320. userInfo["fields"] = modifyFields
  321. userInfo["updatetime"] = time.Now().Unix()
  322. userInfo["modifyuser"] = loginuser
  323. errUpdata["$push"] = map[string]interface{}{
  324. "userinfo": map[string]interface{}{
  325. "$each": []interface{}{userInfo},
  326. "$position": 0,
  327. },
  328. }
  329. }
  330. qu.Debug("set---", set)
  331. qu.Debug("errset---", errset)
  332. qu.Debug("unerrset---", unerrset)
  333. qu.Debug("userInfo---", userInfo)
  334. if len(errset) > 0 {
  335. errUpdata["$set"] = errset
  336. }
  337. if len(unerrset) > 0 {
  338. errUpdata["$unset"] = unerrset
  339. }
  340. if len(errUpdata) > 0 {
  341. util.MgoM.Update(util.Config.Totablel, `{"_id":"`+_id+`"}`, errUpdata, true, false)
  342. }
  343. //更新表操作
  344. //qu.Debug("set---", set)
  345. //更新正确信息
  346. update := map[string]interface{}{}
  347. if len(set) > 0 {
  348. set["ck_data"] = stype
  349. set["updatetime"] = time.Now().Unix()
  350. if modifyuser == "" {
  351. set["modifyuser"] = modifyuser
  352. }
  353. update["$set"] = set
  354. }
  355. qu.Debug("unset---", unset)
  356. if len(unset) > 0 {
  357. update["$unset"] = unset
  358. }
  359. qu.Debug("update---", update)
  360. if len(update) > 0 {
  361. b = util.MgoM.Update(coll, `{"_id":"`+_id+`"}`, update, false, false)
  362. if b {
  363. if coll != util.Config.Fromtable && isSaveMarked { //util.coll此时的标注表 util.Config.Fromtable默认标注表
  364. data, _ := util.MgoM.FindById(coll, _id, nil)
  365. if data != nil && len(*data) > 0 {
  366. update := map[string]interface{}{"$set": *data}
  367. if len(unset) > 0 {
  368. update["$unset"] = unset
  369. }
  370. if !util.MgoM.Update(util.Config.Fromtable, map[string]interface{}{"_id": (*data)["_id"]}, update, true, false) {
  371. qu.Debug("同步marked失败,", _id)
  372. }
  373. }
  374. }
  375. }
  376. i.ServeJson(b)
  377. } else {
  378. i.ServeJson(true)
  379. }
  380. return nil
  381. }
  382. //查询信息
  383. func (i *Front) Detail(id string) error {
  384. coll, _ := i.GetSession("coll").(string)
  385. //if coll != "" {
  386. // exists, _ := redis.Exists("extcheck", coll+"_"+id)
  387. // if exists {
  388. // tmpId, exists := GetNoCheckedId(id, coll)
  389. // if exists { //标注完成
  390. // return i.Render("finish.html", &i.T)
  391. // } else {
  392. // id = tmpId
  393. // }
  394. // }
  395. //} else {
  396. // i.T["err"] = "数据查询表为空!"
  397. // return i.Render("err.html", &i.T)
  398. //}
  399. query, _ := i.GetSession("query").(map[string]interface{})
  400. qu.Debug(coll, query)
  401. rep := getDetail(id, coll) //获取本条公告的信息
  402. i.T["otherInfo"] = rep["otherInfo"] //展示关联公告信息
  403. i.T["moreInfo"] = rep["moreInfo"] //更多关联公告信息
  404. //i.T["jyhref"] = util.JYHREFPRE + qu.CommonEncodeArticle("content", id) + ".html"
  405. i.T["info"] = rep["info"]
  406. i.T["common"] = rep["common"]
  407. i.T["worder"] = rep["worder"]
  408. i.T["packs"] = rep["packs"]
  409. i.T["packskey"] = rep["packskey"]
  410. //i.T["ck_pclisext"] = rep["ck_pclisext"]
  411. i.T["ck_pclistag"] = rep["ck_pclistag"]
  412. //i.T["ck_wodrisext"] = rep["ck_wodrisext"]
  413. //i.T["ck_pkgisext"] = rep["ck_pkgisext"]
  414. i.T["timeplace"] = rep["timeplace"]
  415. i.T["purchasinglist"] = rep["purchasinglist"]
  416. i.T["other"] = rep["other"]
  417. i.T["PurchasinglistField"] = util.PurchasinglistField
  418. i.T["WinnerorderField"] = util.WinnerorderField
  419. i.T["PackageField"] = util.PackageField
  420. i.T["topsubtype"] = util.TopSubStypeArr2
  421. i.T[preKey+"purchasinglist"] = rep[preKey+"purchasinglist"]
  422. i.T[preKey+"package"] = rep[preKey+"package"]
  423. i.T[preKey+"winnerorder"] = rep[preKey+"winnerorder"]
  424. i.T["worder_new"] = rep["worder_new"]
  425. i.T["pcl_new"] = rep["pcl_new"]
  426. i.T["pkg_new"] = rep["pkg_new"]
  427. i.T["nextid"] = GetNextDataId(id, coll, query) //下一条id
  428. checkedNum, allNum := GetCheckedAndAllDataInfo(query, coll) //已标和总数信息
  429. i.T["checkednum"] = checkedNum
  430. i.T["allnum"] = allNum
  431. i.T["fields"] = util.Config.Fields
  432. //存入Redis
  433. redis.Put("extcheck", coll+"_"+id, "", util.Config.RedisTimeout*60) //正在标注的数据存入redis避免多人同时标注(加上coll左前缀避免不同表相同id数据不能同时标注)
  434. return i.Render("detail.html", &i.T)
  435. }
  436. //通过excel表格导入
  437. func (i *Front) ImportByExcel() {
  438. defer qu.Catch()
  439. //success := false
  440. msg := ""
  441. importNum := 0
  442. successNum := int64(0)
  443. coll := i.GetString("excelcoll")
  444. if coll == "" {
  445. i.ServeJson(map[string]interface{}{"msg": "表名错误"})
  446. return
  447. }
  448. mf, _, err := i.GetFile("xlsx")
  449. if err == nil {
  450. binary, _ := ioutil.ReadAll(mf)
  451. xls, _ := xlsx.OpenBinary(binary)
  452. sheet := xls.Sheets[0]
  453. rows := sheet.Rows
  454. idcolnum := -1
  455. ids := []string{}
  456. cellFieldName := map[int]string{} //记录客户需求字段所在的列
  457. tmpMap := map[string]map[string]interface{}{} //excel表中需要保存字段集合
  458. for rn, row := range rows {
  459. if rn == 0 {
  460. for j, cell := range row.Cells {
  461. title := cell.Value
  462. if fieldName := util.Config.CustomerField[title]; fieldName != "" { //客户需求字段
  463. cellFieldName[j] = fieldName
  464. }
  465. if title == "唯一标识" || title == "信息标识" { //id所在列
  466. idcolnum = j
  467. }
  468. }
  469. if idcolnum == -1 {
  470. break
  471. }
  472. continue
  473. }
  474. if len(row.Cells) < len(rows[0].Cells) {
  475. break
  476. }
  477. tmp := map[string]interface{}{}
  478. for j, f := range cellFieldName {
  479. if val := row.Cells[j].Value; val != "" {
  480. if f == "capital" { //注册资金(万元)
  481. cf, _ := row.Cells[j].Float()
  482. tmp[f] = cf
  483. } else if f == "createtime" { //创建时间
  484. ci, _ := row.Cells[j].Int64()
  485. tmp[f] = ci
  486. } else {
  487. tmp[f] = val
  488. }
  489. }
  490. }
  491. id := row.Cells[idcolnum].String() //加密的id
  492. if id == "" {
  493. break
  494. }
  495. id = SE.DecodeString(id) //解密后id
  496. tmpMap[id] = tmp
  497. ids = append(ids, id)
  498. }
  499. importNum = len(ids) //excel表数据个数
  500. if importNum > 0 {
  501. _, msg, successNum = GetDataById1(coll, ids, "excel", tmpMap)
  502. tmpMap = map[string]map[string]interface{}{}
  503. ids = []string{}
  504. }
  505. }
  506. msg = fmt.Sprintf("共查询%d条,导入成功%d条\n", importNum, successNum) + msg
  507. i.ServeJson(map[string]interface{}{"msg": msg})
  508. }
  509. func (i *Front) GetEsCount() {
  510. defer qu.Catch()
  511. msg := ""
  512. count := int64(0)
  513. estext := i.GetString("estext") //es查询语句
  514. esJson := map[string]interface{}{}
  515. if json.Unmarshal([]byte(estext), &esJson) != nil || len(esJson) == 0 {
  516. msg = "Es语句错误"
  517. } else {
  518. count = util.Es.Count(util.Index, util.Itype, estext)
  519. }
  520. i.ServeJson(map[string]interface{}{"count": count, "msg": msg})
  521. }
  522. //通过es语句导入
  523. func (i *Front) ImportByEs() {
  524. defer qu.Catch()
  525. //success := false
  526. msg := ""
  527. successNum := int64(0)
  528. estext := i.GetString("estext") //es查询语句
  529. coll := i.GetString("coll") //导入表
  530. if coll == "" {
  531. i.ServeJson(map[string]interface{}{"msg": "表名错误"})
  532. return
  533. }
  534. client := util.Es.GetEsConn()
  535. defer util.Es.DestoryEsConn(client)
  536. ch := make(chan bool, 5)
  537. wg := &sync.WaitGroup{}
  538. lock := &sync.Mutex{}
  539. escount := util.Es.Count(util.Index, util.Itype, estext)
  540. qu.Debug("查询总数:", escount)
  541. if escount > 0 {
  542. //查询条件类型转换
  543. var q es.Query
  544. tmpQuery := es.BoolQuery{
  545. QueryStrings: estext,
  546. }
  547. q = tmpQuery
  548. //游标查询,index不支持别名,只能写索引库的名称
  549. res, err := client.Scroll(util.Index).Query(q).Size(200).Do() //查询一条获取游标
  550. ids := []string{} //id数据
  551. if err == nil {
  552. numDocs := 0
  553. scrollId := res.ScrollId
  554. for {
  555. if scrollId == "" {
  556. qu.Debug("ScrollId Is Error")
  557. break
  558. }
  559. searchResult, err := client.Scroll(util.Index).Size(200).ScrollId(scrollId).Do() //查询
  560. if err != nil {
  561. if err.Error() == "EOS" { //迭代完毕
  562. qu.Debug("Es Search Data Over:", err)
  563. } else {
  564. qu.Debug("Es Search Data Error:", err)
  565. }
  566. break
  567. }
  568. for _, hit := range searchResult.Hits.Hits {
  569. //开始处理数据
  570. wg.Add(1)
  571. ch <- true
  572. go func(tmpHit *es.SearchHit) {
  573. defer func() {
  574. <-ch
  575. wg.Done()
  576. }()
  577. tmp := make(map[string]interface{})
  578. if json.Unmarshal(*tmpHit.Source, &tmp) == nil {
  579. id := qu.ObjToString(tmp["_id"])
  580. tmp["id"] = id //记录数据原有id
  581. lock.Lock()
  582. ids = append(ids, id)
  583. lock.Unlock()
  584. }
  585. }(hit)
  586. numDocs += 1
  587. if numDocs%500 == 0 {
  588. qu.Debug("Current:", numDocs)
  589. }
  590. }
  591. scrollId = searchResult.ScrollId
  592. }
  593. wg.Wait()
  594. client.ClearScroll().ScrollId(scrollId).Do() //清理游标
  595. //qu.Debug("Result Data Count:", numDocs)
  596. } else {
  597. qu.Debug("Es Search Data Error")
  598. }
  599. //判断数量
  600. if int64(len(ids)) != escount {
  601. msg = "查询数据和结果不一致"
  602. } else { //入库
  603. _, msg, successNum = GetDataById(coll, ids, "es", map[string]map[string]interface{}{})
  604. }
  605. } else {
  606. msg = "无查询数据"
  607. }
  608. msg = fmt.Sprintf("共查询%d条,导入成功%d条\n", escount, successNum) + msg
  609. i.ServeJson(map[string]interface{}{"msg": msg})
  610. }
  611. //同步数据
  612. func (i *Front) SyncMarked() {
  613. syncColl := i.GetString("coll")
  614. sess := util.MgoM.GetMgoConn()
  615. defer util.MgoM.DestoryMongoConn(sess)
  616. it := sess.DB(util.Config.Dbname).C(syncColl).Find(nil).Iter()
  617. count, _ := sess.DB(util.Config.Dbname).C(syncColl).Find(nil).Count()
  618. qu.Debug(syncColl, count)
  619. n := 0
  620. lock := &sync.Mutex{}
  621. wg := &sync.WaitGroup{}
  622. ch := make(chan bool, 3)
  623. result := map[string]map[string]interface{}{}
  624. idArr := []string{}
  625. for tmp := make(map[string]interface{}); it.Next(tmp); n++ {
  626. wg.Add(1)
  627. ch <- true
  628. go func(tmp map[string]interface{}) {
  629. defer func() {
  630. <-ch
  631. wg.Done()
  632. }()
  633. id := qu.ObjToString(tmp["id"])
  634. if id == "" {
  635. return
  636. }
  637. tmpMap := map[string]interface{}{}
  638. for _, f := range util.Config.CustomerField {
  639. if val := tmp[f]; val != nil {
  640. tmpMap[f] = val
  641. }
  642. }
  643. lock.Lock()
  644. idArr = append(idArr, id)
  645. result[id] = tmpMap
  646. lock.Unlock()
  647. }(tmp)
  648. tmp = map[string]interface{}{}
  649. }
  650. wg.Wait()
  651. if count != int64(len(result)) {
  652. i.ServeJson(map[string]interface{}{"msg": "同步失败", "flag": false})
  653. return
  654. }
  655. //util.MgoM.C.Database(util.Config.Dbname).Collection(syncColl).Drop(util.MgoM.Ctx) //删除syncColl表(清空数据)
  656. success, msg, successNum := GetDataById(syncColl, idArr, "syncoll", result)
  657. result = map[string]map[string]interface{}{}
  658. idArr = []string{}
  659. msg = fmt.Sprintf("共查询%d条,同步成功%d条\n", count, successNum) + msg
  660. i.ServeJson(map[string]interface{}{"msg": msg, "flag": success})
  661. }
  662. //将marked表中ck_data:2更新为0
  663. func (i *Front) MarkedInit() {
  664. set := map[string]interface{}{
  665. "$set": map[string]interface{}{
  666. "ck_data": 0,
  667. },
  668. }
  669. b := util.MgoM.Update(util.Config.Fromtable, `{"ck_data":2}`, set, false, true)
  670. i.ServeJson(map[string]interface{}{"success": b})
  671. }
  672. //标注完成
  673. func (i *Front) FinishCheck() {
  674. i.Render("finish.html")
  675. }
  676. //错误页面
  677. func (i *Front) ErrCheck() {
  678. i.Render("err.html")
  679. }
  680. //统计抽查
  681. func (i *Front) Tj() error {
  682. comm := map[string]map[string]int{}
  683. comm_win := map[string]map[string]int{}
  684. pack := map[string]map[string]int{}
  685. pack_win := map[string]map[string]int{}
  686. list, _ := util.MgoM.Find(util.Config.Totablel, "{}", nil, nil, false, -1, -1)
  687. for _, tmp := range *list {
  688. for k, val := range tmp {
  689. if len(k) > 3 && k[:3] == preKey {
  690. comm = mapIntAdd(k, qu.ObjToString(val), comm)
  691. }
  692. }
  693. if winnerorder, ok := tmp["winnerorder"].([]interface{}); ok {
  694. for _, wd := range winnerorder {
  695. if winner, ok := wd.(map[string]interface{}); ok {
  696. for k, val := range winner {
  697. if len(k) > 3 && k[:3] == preKey {
  698. comm_win = mapIntAdd(k, qu.ObjToString(val), comm_win)
  699. }
  700. }
  701. }
  702. }
  703. }
  704. if ptmp, ok := tmp["package"].(map[string]interface{}); ok {
  705. for _, pktmp := range ptmp {
  706. if pkage, ok := pktmp.(map[string]interface{}); ok {
  707. for k, val := range pkage {
  708. if len(k) > 3 && k[:3] == preKey {
  709. pack = mapIntAdd(k, qu.ObjToString(val), pack)
  710. }
  711. if k == "winnerorder" {
  712. if wtmp, ok := val.([]interface{}); ok {
  713. for _, winner := range wtmp {
  714. if win, ok := winner.(map[string]interface{}); ok {
  715. for wk, wval := range win {
  716. if len(k) > 3 && k[:3] == preKey {
  717. pack_win = mapIntAdd(wk, qu.ObjToString(wval), pack_win)
  718. }
  719. }
  720. }
  721. }
  722. }
  723. }
  724. }
  725. }
  726. }
  727. }
  728. }
  729. //data := map[string]interface{}{"total": len(list), "comm": comm, "pack": pack, "pack_win": pack_win}
  730. //mongodb.Save("extcheck_tj", data)
  731. i.T["comm"] = comm
  732. i.T["pack"] = pack
  733. i.T["comm_win"] = comm_win
  734. i.T["pack_win"] = pack_win
  735. i.T["total"] = len(*list)
  736. return i.Render("tj.html", &i.T)
  737. }
  738. //标错列表
  739. func (i *Front) Elist() error {
  740. attrname := i.GetString("attrname")
  741. common := util.Config.Biaozhu["common"]
  742. elist, _ := util.MgoM.Find(util.Config.Totablel, `{"ck_`+attrname+`":"0"}`, `{"_id":1}`, `{"_id":1}`, false, -1, -1)
  743. for _, v := range *elist {
  744. v["_id"] = mgo.BsonIdToSId(v["_id"])
  745. }
  746. i.T["elist"] = *elist
  747. i.T["attrname"] = attrname
  748. i.T["common"] = common
  749. return i.Render("elist.html", &i.T)
  750. }
  751. func (i *Front) Review() error {
  752. defer qu.Catch()
  753. var labeler []map[string]interface{}
  754. sess := util.MgoM.GetMgoConn()
  755. defer util.MgoM.DestoryMongoConn(sess)
  756. sess.DB(util.MgoM.DbName).C(util.Config.Fromtable).Pipe([]map[string]interface{}{
  757. //查询条件
  758. {
  759. "$match": bson.M{
  760. "ck_data": bson.M{"$gte": 1},
  761. },
  762. },
  763. // 按照modifyuser分组,并统计
  764. {
  765. "$group": bson.M{
  766. "_id": "$modifyuser",
  767. "count": bson.M{"$sum": 1},
  768. },
  769. },
  770. // 排序
  771. {
  772. "$sort": bson.M{"count": -1},
  773. },
  774. }).All(&labeler)
  775. i.T["users"] = labeler
  776. qu.Debug(util.Config.Fields)
  777. i.T["fields"] = util.Config.Fields
  778. return i.Render("review.html", &i.T)
  779. }
  780. func (i *Front) ReviewList() {
  781. defer qu.Catch()
  782. if i.Method() == "POST" {
  783. user := i.GetString("user")
  784. q := make(map[string]interface{})
  785. q["ck_data"] = bson.M{"$gte": 1}
  786. if user != "0" && user != "-1" {
  787. q["modifyuser"] = user
  788. }
  789. qu.Debug(q, util.Config.Fromtable)
  790. datas, b := util.MgoM.Find(util.Config.Fromtable, q, bson.M{"_id": 1}, nil, false, -1, -1)
  791. if b && len(*datas) > 0 {
  792. i.ServeJson(map[string]interface{}{
  793. "rep": b,
  794. "data": *datas,
  795. })
  796. } else {
  797. i.ServeJson(map[string]interface{}{
  798. "rep": false,
  799. "msg": "未查询到数据",
  800. })
  801. }
  802. }
  803. }
  804. func (i *Front) ReviewDetail(id string) error {
  805. defer qu.Catch()
  806. coll, _ := i.GetSession("coll").(string)
  807. query, _ := i.GetSession("query").(map[string]interface{})
  808. rep := getDetail(id, coll) //获取本条公告的信息
  809. i.T["otherInfo"] = rep["otherInfo"] //展示关联公告信息
  810. i.T["moreInfo"] = rep["moreInfo"] //更多关联公告信息
  811. i.T["info"] = rep["info"]
  812. i.T["common"] = rep["common"]
  813. i.T["worder"] = rep["worder"]
  814. i.T["packs"] = rep["packs"]
  815. i.T["packskey"] = rep["packskey"]
  816. i.T["ck_pclisext"] = rep["ck_pclisext"]
  817. i.T["ck_wodrisext"] = rep["ck_wodrisext"]
  818. i.T["ck_pkgisext"] = rep["ck_pkgisext"]
  819. i.T["timeplace"] = rep["timeplace"]
  820. i.T["purchasinglist"] = rep["purchasinglist"]
  821. i.T["other"] = rep["other"]
  822. i.T["PurchasinglistField"] = util.PurchasinglistField
  823. i.T["WinnerorderField"] = util.WinnerorderField
  824. i.T["PackageField"] = util.PackageField
  825. i.T["topsubtype"] = util.TopSubStypeArr2
  826. i.T[preKey+"purchasinglist"] = rep[preKey+"purchasinglist"]
  827. i.T[preKey+"package"] = rep[preKey+"package"]
  828. i.T[preKey+"winnerorder"] = rep[preKey+"winnerorder"]
  829. i.T["worder_new"] = rep["worder_new"]
  830. i.T["pcl_new"] = rep["pcl_new"]
  831. i.T["pkg_new"] = rep["pkg_new"]
  832. i.T["fields"] = util.Config.Fields
  833. i.T["nextid"] = GetNextDataId(id, coll, query) //下一条id
  834. return i.Render("re_detail.html", &i.T)
  835. }
  836. func (i *Front) ReviewSave() error {
  837. defer qu.Catch()
  838. b := false
  839. obj := []map[string]interface{}{}
  840. key := i.GetString("key")
  841. _id := i.GetString("_id")
  842. //stype, _ := i.GetInteger("stype")
  843. err := json.Unmarshal([]byte(key), &obj)
  844. if err != nil {
  845. i.ServeJson(b)
  846. return nil
  847. }
  848. set := map[string]interface{}{} //更新、新增字段
  849. unset := map[string]interface{}{} //删除字段
  850. errset := map[string]interface{}{} //记录修改的字段信息
  851. isSaveMarked := false
  852. if len(obj) == 1 { //单独保存某个一级
  853. content, ok := obj[0]["content"].([]interface{})
  854. if !ok || len(content) == 0 {
  855. i.ServeJson(b)
  856. return nil
  857. }
  858. title := qu.ObjToString(obj[0]["title"])
  859. isext, _ := obj[0]["checkType"].(bool)
  860. istag, _ := obj[0]["checkAllTag"].(bool)
  861. status := qu.IntAll(obj[0]["status"])
  862. switch title {
  863. case "基本字段":
  864. BzJBZD(content, set, unset, errset)
  865. case "时间地点":
  866. BzSJDD(content, set, unset, errset)
  867. case "标的信息":
  868. BzBDXX(content, set, unset, errset, isext, istag, status)
  869. case "多包信息":
  870. BzDBXX(content, set, unset, errset, isext, status)
  871. case "中标候选人信息":
  872. BzZBHXRXX(content, set, unset, errset, isext, status)
  873. case "其余信息":
  874. BzQYXX(content, set, unset, errset)
  875. }
  876. } else {
  877. isSaveMarked = true
  878. for j, val := range obj {
  879. content, ok := val["content"].([]interface{})
  880. status := qu.IntAll(val["status"])
  881. if !ok {
  882. continue
  883. // i.ServeJson(b)
  884. // return nil
  885. }
  886. isext, _ := val["checkType"].(bool)
  887. istag, _ := val["checkAllTag"].(bool)
  888. if j == 0 { //基本信息
  889. BzJBZD(content, set, unset, errset)
  890. } else if j == 1 { //时间地点
  891. BzSJDD(content, set, unset, errset)
  892. } else if j == 2 { //标的物
  893. BzBDXX(content, set, unset, errset, isext, istag, status)
  894. } else if j == 3 { //多包
  895. BzDBXX(content, set, unset, errset, isext, status)
  896. } else if j == 4 { //候选人
  897. BzZBHXRXX(content, set, unset, errset, isext, status)
  898. } else { //其余信息
  899. BzQYXX(content, set, unset, errset)
  900. }
  901. }
  902. }
  903. userInfo := map[string]interface{}{} //记录本次标注日志
  904. modifyFields := map[string]interface{}{} //本次标注所有字段
  905. unerrset := map[string]interface{}{} //记录errdata错误信息表删除
  906. loginuser := i.GetSession("loginuser").(string)
  907. coll := i.GetSession("coll").(string)
  908. data, _ := util.MgoM.FindById(coll, _id, nil) //查询标注保存前的原始信息
  909. //modifyuser := qu.ObjToString((*data)["modifyuser"])
  910. remap := make(map[string]interface{}) // 质检信息
  911. reField := make(map[string]interface{})
  912. remap["user"] = loginuser
  913. remap["updatetime"] = time.Now().Unix()
  914. //标注多次操作处理
  915. if len(set) > 0 { //set中为本次标注保存的数据(ck_bidopentime:1;ck_buyer:2;buyer:"XXX")
  916. for s, sv := range set {
  917. //特殊字段处理
  918. if s == "ck_pclistag" && (*data)["ck_pclistag"] != nil {
  919. delete(set, s)
  920. continue
  921. }
  922. //区分是标记字段,还是普通字段(标记字段:ck_buyer;普通字段:buyer)
  923. if strings.HasPrefix(s, preKey) {
  924. status := qu.IntAll(sv) //标注字段状态
  925. field := s[3:] //去除前缀,被标注字段
  926. checkedStatus := qu.IntAll((*data)[s]) //数据库被标注状态
  927. rename := strings.Replace(s, "ck_", "re_", -1)
  928. reField[rename] = status
  929. if status == 1 && (checkedStatus == 2 || checkedStatus == 1) { //数据库已有标记,且页面标注正确,此次该字段不做标注保存
  930. delete(set, field)
  931. delete(set, s)
  932. continue
  933. } else {
  934. if set[field] == nil && status != 2 { //表示该字段没有要修改的值,此时标记为1或2(亦或是ck_wodrisext;ck_pkgisext;ck_pclisext)
  935. modifyFields[field] = set[s] //目前会有pclisext、pclistag、pkgisext、wodrisext
  936. continue
  937. } else { //此时有修改的值和标记2
  938. modifyFields[field] = status //记录标注的字段和状态
  939. if checkedStatus != 0 { //已有标注信息的状态
  940. if status == 2 && checkedStatus == 2 { //字段已被修改且本次也为修改
  941. errdata, _ := util.MgoM.FindById(util.Config.Totablel, _id, map[string]interface{}{"userinfo": 0})
  942. if errdata != nil && len(*errdata) != 0 {
  943. delete(errset, field) //errdata中有该字段的错误记录,不再更新errdata
  944. //对比errdata错误值:相等变为1,errdata删除;不等变为2,标注表修改该字段
  945. errText := fmt.Sprint((*errdata)[field])
  946. text := fmt.Sprint(set[field])
  947. if errText == text {
  948. set[s] = 1 //更新标注表字段状态
  949. unerrset[field] = "" //删除errdata表字段
  950. }
  951. }
  952. }
  953. }
  954. }
  955. }
  956. }
  957. }
  958. }
  959. remap["field"] = reField
  960. set["review"] = remap
  961. set["re_data"] = 1
  962. //存储原错误信息
  963. //1、errdata操作
  964. errUpdata := map[string]interface{}{} //errdata所有要更新内容
  965. for f, _ := range errset {
  966. errset[f] = (*data)[f]
  967. }
  968. if len(modifyFields) > 0 { //有标注字段,记录标注信息
  969. errset["updatetime"] = time.Now().Unix()
  970. errset["modifyuser"] = loginuser
  971. userInfo["fields"] = modifyFields
  972. userInfo["updatetime"] = time.Now().Unix()
  973. userInfo["modifyuser"] = loginuser
  974. errUpdata["$push"] = map[string]interface{}{
  975. "userinfo": map[string]interface{}{
  976. "$each": []interface{}{userInfo},
  977. "$position": 0,
  978. },
  979. }
  980. }
  981. if len(errset) > 0 {
  982. errUpdata["$set"] = errset
  983. }
  984. if len(unerrset) > 0 {
  985. errUpdata["$unset"] = unerrset
  986. }
  987. if len(errUpdata) > 0 {
  988. util.MgoM.Update(util.Config.Totablel, `{"_id":"`+_id+`"}`, errUpdata, true, false)
  989. }
  990. //更新表操作
  991. //更新正确信息
  992. update := map[string]interface{}{}
  993. if len(set) > 0 {
  994. if len(set) > 1 {
  995. set["updatetime"] = time.Now().Unix()
  996. set["modifyuser"] = loginuser
  997. }
  998. update["$set"] = set
  999. }
  1000. if len(unset) > 0 {
  1001. update["$unset"] = unset
  1002. }
  1003. if len(update) > 0 {
  1004. b = util.MgoM.Update(coll, `{"_id":"`+_id+`"}`, update, false, false)
  1005. if b {
  1006. if coll != util.Config.Fromtable && isSaveMarked { //util.coll此时的标注表 util.Config.Fromtable默认标注表
  1007. data, _ := util.MgoM.FindById(coll, _id, nil)
  1008. if data != nil && len(*data) > 0 {
  1009. update := map[string]interface{}{"$set": *data}
  1010. if len(unset) > 0 {
  1011. update["$unset"] = unset
  1012. }
  1013. if !util.MgoM.Update(util.Config.Fromtable, map[string]interface{}{"_id": (*data)["_id"]}, update, true, false) {
  1014. qu.Debug("同步marked失败,", _id)
  1015. }
  1016. }
  1017. }
  1018. }
  1019. i.ServeJson(b)
  1020. } else {
  1021. i.ServeJson(true)
  1022. }
  1023. return nil
  1024. }
  1025. func (i *Front) ReviewNext() {
  1026. defer qu.Catch()
  1027. id := i.GetString("id")
  1028. coll := i.GetSession("coll").(string)
  1029. q := bson.M{"_id": bson.M{"$gt": mgo.StringTOBsonId(id)}}
  1030. info, b := util.MgoM.Find(coll, q, bson.M{"_id": 1}, bson.M{"_id": 1}, false, 0, 1)
  1031. qu.Debug(q)
  1032. if b && len(*info) > 0 {
  1033. nxid := mgo.BsonIdToSId((*info)[0]["_id"])
  1034. i.ServeJson(bson.M{"id": nxid, "exists": true})
  1035. }else {
  1036. i.ServeJson(bson.M{"exists": false})
  1037. }
  1038. }
  1039. func (i *Front) ReviewStat() {
  1040. defer qu.Catch()
  1041. sess := util.MgoM.GetMgoConn()
  1042. defer util.MgoM.DestoryMongoConn(sess)
  1043. result := sess.DB(util.MgoM.DbName).C(util.Config.Fromtable).Find(nil).Iter()
  1044. count, cmark, rmark, rgmark := 0, 0, 0, 0 // 总数, 标注数量, 审核数据, 审核数据完全正确的数据量
  1045. cmaps := make(map[string]int) // 标注字段整体准确率
  1046. umaps := make(map[string]interface{}) // 按人员 字段准确率
  1047. for k, i2 := range util.Config.Fields {
  1048. if i2 {
  1049. cmaps[k] = 0
  1050. }
  1051. }
  1052. for tmp := make(map[string]interface{}); result.Next(&tmp); {
  1053. count ++
  1054. if qu.IntAll(tmp["ck_data"]) >= 1 {
  1055. cmark ++
  1056. }
  1057. if qu.IntAll(tmp["re_data"]) > 0 {
  1058. rmark ++
  1059. if reField, ok := tmp["review"].(map[string]interface{}); ok {
  1060. remap, _ := reField["field"].(map[string]interface{})
  1061. flag := true // 数据整体准确率
  1062. // 按人员统计字段准备率
  1063. user := qu.ObjToString(tmp["modifyuser"])
  1064. var up map[string]int
  1065. if umaps[user] == nil {
  1066. up = make(map[string]int)
  1067. }else {
  1068. up = umaps[user].(map[string]int)
  1069. }
  1070. for k1 := range cmaps{
  1071. k2 := "re_" + k1
  1072. if qu.IntAll(remap[k2]) == 1 {
  1073. cmaps[k1] += 1 // 字段整体正确率
  1074. up[k1] += 1
  1075. }else {
  1076. flag = false
  1077. }
  1078. }
  1079. up["count"] += 1
  1080. umaps[user] = up
  1081. if flag {
  1082. rgmark ++
  1083. }
  1084. }
  1085. }
  1086. }
  1087. qu.Debug("count:", count, ",cmark:", cmark, ",rmark:", rmark, ",rgmark:", rgmark)
  1088. qu.Debug(cmaps)
  1089. qu.Debug(umaps)
  1090. save := bson.M{"total_count": count, "cmake_count": cmark, "rmark_count": rmark, "rgmark_count": rgmark}
  1091. save["result"] = cmaps
  1092. save["user_result"] = umaps
  1093. id := util.MgoM.Save("review_result", save)
  1094. if id != "" {
  1095. i.ServeJson(map[string]interface{}{"rep": true})
  1096. }else {
  1097. i.ServeJson(map[string]interface{}{"rep": false})
  1098. }
  1099. }