remark.go 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080
  1. package front
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "github.com/shopspring/decimal"
  6. "go.mongodb.org/mongo-driver/bson"
  7. "math"
  8. mgo "mongodb"
  9. qu "qfw/util"
  10. "sort"
  11. "strconv"
  12. "strings"
  13. "time"
  14. "util"
  15. )
  16. func (f *Front) RemarkList() {
  17. qu.Catch()
  18. pid := qu.ObjToString(f.GetString("pid"))
  19. tid := qu.ObjToString(f.GetString("tid"))
  20. sourceinfo := qu.ObjToString(f.GetString("s_sourceinfo"))
  21. if f.Method() == "POST" {
  22. //user := f.GetSession("user").(map[string]interface{})
  23. start, _ := f.GetInteger("start")
  24. limit, _ := f.GetInteger("length")
  25. draw, _ := f.GetInteger("draw")
  26. searchStr := f.GetString("search[value]")
  27. search := strings.TrimSpace(searchStr)
  28. query := map[string]interface{}{"s_usertaskid": tid}
  29. ckdata, err := f.GetInteger("i_ckdata")
  30. if err != nil {
  31. ckdata = -1
  32. }
  33. if ckdata == 0 {
  34. query["b_istag"] = false
  35. } else if ckdata == 1 {
  36. query["b_istag"] = true
  37. }
  38. if search != "" {
  39. query["$or"] = []interface{}{
  40. bson.M{"v_baseinfo.title": bson.M{"$regex": search}},
  41. }
  42. }
  43. qu.Debug(query)
  44. field := map[string]interface{}{"v_baseinfo.title": 1, "b_istag": 1, "i_ckdata": 1}
  45. info, _ := util.Mgo.Find(sourceinfo, query, `{"_id": 1}`, field, false, start, limit)
  46. count := util.Mgo.Count(sourceinfo, query)
  47. qu.Debug(query, sourceinfo, count)
  48. f.ServeJson(map[string]interface{}{
  49. "draw": draw,
  50. "data": *info,
  51. "recordsFiltered": count,
  52. "recordsTotal": count,
  53. })
  54. } else {
  55. f.T["pid"] = pid
  56. f.T["tid"] = tid
  57. f.T["s_sourceinfo"] = sourceinfo
  58. _ = f.Render("project/remark_list.html", &f.T)
  59. }
  60. }
  61. func (f *Front) RemarkDetail() {
  62. pid := f.GetString("pid")
  63. tid := f.GetString("tid")
  64. did := f.GetString("did")
  65. coll := f.GetString("s_sourceinfo")
  66. project, _ := util.Mgo.FindById(util.PROJECTCOLLNAME, pid, `{"v_fields": 1}`)
  67. if len(*project) > 0 {
  68. field := make(map[string]bool)
  69. vf := (*project)["v_fields"].(map[string]interface{})
  70. for k := range vf {
  71. field[k] = true
  72. }
  73. f.T["fields"] = field
  74. }
  75. qu.Debug(pid, did, coll)
  76. rep := getDetail(did, coll) //获取本条公告的信息
  77. f.T["otherInfo"] = rep["otherInfo"] //展示关联公告信息
  78. f.T["moreInfo"] = rep["moreInfo"] //更多关联公告信息
  79. f.T["pid"] = pid
  80. f.T["tid"] = tid
  81. f.T["did"] = did
  82. f.T["coll"] = coll
  83. f.T["info"] = rep["info"]
  84. f.T["common"] = rep["common"]
  85. f.T["worder"] = rep["worder"]
  86. f.T["packs"] = rep["packs"]
  87. f.T["packskey"] = rep["packskey"]
  88. f.T["ck_pclistag"] = rep["purchasingTag"]
  89. f.T["timeplace"] = rep["timeplace"]
  90. f.T["purchasinglist"] = rep["purchasinglist"]
  91. f.T["other"] = rep["other"]
  92. f.T["PurchasinglistField"] = util.PurchasinglistField
  93. f.T["WinnerorderField"] = util.WinnerorderField
  94. f.T["PackageField"] = util.PackageField
  95. f.T["topsubtype"] = util.TopSubStypeArr2
  96. f.T["ck_purchasinglist"] = rep["ck_purchasinglist"]
  97. f.T["ck_package"] = rep["ck_package"]
  98. f.T["ck_winnerorder"] = rep["ck_winnerorder"]
  99. f.T["worder_new"] = rep["worder_new"]
  100. f.T["pcl_new"] = rep["pcl_new"]
  101. f.T["pkg_new"] = rep["pkg_new"]
  102. f.T["nextid"] = GetNextDataId(did, coll, tid) //下一条id
  103. _ = f.Render("project/remark_detail.html", &f.T)
  104. }
  105. func getDetail(id, coll string) map[string]interface{} {
  106. rep := map[string]interface{}{}
  107. infoTmp, _ := util.Mgo.FindById(coll, id, ``)
  108. baseInfo := (*infoTmp)["v_baseinfo"].(map[string]interface{}) //字段值
  109. var bzInfo map[string]interface{} //标注信息
  110. if (*infoTmp)["v_taginfo"] != nil {
  111. bzInfo = (*infoTmp)["v_taginfo"].(map[string]interface{})
  112. } else {
  113. bzInfo = make(map[string]interface{})
  114. }
  115. baseInfo["detail"] = qu.ObjToString(baseInfo["title"]) + "</br>" + qu.ObjToString(baseInfo["detail"])
  116. baseInfo["_id"] = mgo.BsonIdToSId(baseInfo["_id"])
  117. purchasingTag, _ := baseInfo["purchasinglist_alltag"].(bool)
  118. rep["purchasingTag"] = purchasingTag
  119. href := qu.ObjToString(baseInfo["href"])
  120. if !strings.HasPrefix(href, "http") {
  121. baseInfo["href"] = "https://" + href
  122. }
  123. rep["info"] = baseInfo
  124. common, timeplace, other := setExtComMap(baseInfo, bzInfo) //拼装抽取common值
  125. rep["common"] = common
  126. rep["timeplace"] = timeplace
  127. rep["other"] = other
  128. packs, packskey, pkg_new := setPaceMap(baseInfo) //拼装子包信息
  129. rep["packs"] = packs
  130. rep["packskey"] = packskey
  131. rep["pkg_new"] = pkg_new
  132. purchasinglist, isNewStatus := setPurchasingMap(baseInfo) //标的物
  133. rep["purchasinglist"] = purchasinglist
  134. rep["pcl_new"] = isNewStatus
  135. worder, worder_new := setWorderMap(baseInfo) //中标候选人
  136. rep["worder"] = worder
  137. rep["worder_new"] = worder_new
  138. otherInfo, moreInfo := setOtherInfo(baseInfo) //处理公告关联信息
  139. rep["otherInfo"] = otherInfo
  140. rep["moreInfo"] = moreInfo
  141. //
  142. if bzInfo["purchasinglist"] != nil {
  143. rep["ck_purchasinglist"] = "1"
  144. } else {
  145. rep["ck_purchasinglist"] = "-1"
  146. }
  147. if bzInfo["package"] != nil {
  148. rep["ck_package"] = "1"
  149. } else {
  150. rep["ck_package"] = "-1"
  151. }
  152. if bzInfo["winnerorder"] != nil {
  153. rep["ck_winnerorder"] = "1"
  154. } else {
  155. rep["ck_winnerorder"] = "-1"
  156. }
  157. return rep
  158. }
  159. //拼装抽取common值
  160. func setExtComMap(info, bzInfo map[string]interface{}) ([]interface{}, []interface{}, []interface{}) {
  161. //基本参数
  162. common, _ := util.BiaoZhu["common"].([]interface{})
  163. for k, tmp := range common {
  164. if cp, ok := tmp.(map[string]interface{}); ok {
  165. if info[fmt.Sprint(cp["key"])] == nil {
  166. cp["value"] = ""
  167. } else {
  168. if cp["key"] == "subtype" {
  169. if info["toptype"] != nil && info["subtype"] != nil {
  170. cp["value"] = qu.ObjToString(info["toptype"]) + "-" + qu.ObjToString(info[fmt.Sprint(cp["key"])])
  171. } else {
  172. cp["value"] = ""
  173. }
  174. } else {
  175. cp["value"] = info[fmt.Sprint(cp["key"])]
  176. }
  177. }
  178. if bzInfo[fmt.Sprint(cp["key"])] == nil {
  179. cp["status"] = "-1"
  180. } else {
  181. cp["status"] = "1"
  182. }
  183. common[k] = cp
  184. }
  185. }
  186. //时间地点信息
  187. timeplace, _ := util.BiaoZhu["timeplace"].([]interface{})
  188. for k, tmp := range timeplace {
  189. if tp, ok := tmp.(map[string]interface{}); ok {
  190. if info[fmt.Sprint(tp["key"])] == nil {
  191. tp["value"] = ""
  192. } else {
  193. key := tp["key"]
  194. if key == "bidopentime" || key == "publishtime" || key == "bidendtime" || key == "project_startdate" || key == "project_completedate" {
  195. tmpTime := qu.Int64All(info[fmt.Sprint(tp["key"])])
  196. if tmpTime > 0 {
  197. tp["value"] = qu.FormatDateByInt64(&tmpTime, qu.Date_Full_Layout)
  198. } else {
  199. tp["value"] = info[qu.ObjToString(tp["key"])]
  200. }
  201. } else {
  202. tp["value"] = info[fmt.Sprint(tp["key"])]
  203. }
  204. }
  205. if bzInfo[fmt.Sprint(tp["key"])] == nil {
  206. tp["status"] = "-1"
  207. } else {
  208. tp["status"] = "1"
  209. }
  210. timeplace[k] = tp
  211. }
  212. }
  213. //other信息
  214. other, _ := util.BiaoZhu["other"].([]interface{})
  215. for k, tmp := range other {
  216. if cp, ok := tmp.(map[string]interface{}); ok {
  217. if info[fmt.Sprint(cp["key"])] == nil {
  218. cp["value"] = ""
  219. } else {
  220. if cp["key"] == "signaturedate" {
  221. bidopentime := qu.Int64All(info[fmt.Sprint(cp["key"])])
  222. if bidopentime > 0 {
  223. cp["value"] = qu.FormatDateByInt64(&bidopentime, qu.Date_Full_Layout)
  224. } else {
  225. cp["value"] = info[qu.ObjToString(cp["key"])]
  226. }
  227. } else {
  228. cp["value"] = info[fmt.Sprint(cp["key"])]
  229. }
  230. }
  231. //log.Println(cp)
  232. if bzInfo[fmt.Sprint(cp["key"])] == nil {
  233. cp["status"] = "-1"
  234. } else {
  235. cp["status"] = "1"
  236. }
  237. other[k] = cp
  238. }
  239. }
  240. return common, timeplace, other
  241. }
  242. //拼装子包信息
  243. func setPaceMap(info map[string]interface{}) ([]map[string]interface{}, []string, []bool) {
  244. var confpack []interface{}
  245. confpack, _ = util.BiaoZhu["package"].([]interface{})
  246. //bzpack := bzInfo["package"].(map[string]interface{})
  247. packs := map[string]map[string]interface{}{}
  248. var sortpackskey []string
  249. isNewPkg := map[string]bool{} //记录子包是否是新增的
  250. if packages, ok := info["package"].(map[string]interface{}); ok && len(packages) > 0 {
  251. for k, tmpackage := range packages { //遍历分包
  252. if tmppack, ok := tmpackage.(map[string]interface{}); ok {
  253. //isNew, _ := tmppack["isnew"].(bool)
  254. isNew := false
  255. status := "-1"
  256. if tmppack["package_son"] != nil {
  257. status = "1"
  258. }
  259. isNewPkg[k] = isNew
  260. sortpackskey = append(sortpackskey, k)
  261. var pack []interface{}
  262. for _, cpack := range confpack {
  263. cpack, _ := cpack.(map[string]interface{})
  264. key := qu.ObjToString(cpack["key"])
  265. if key == "winner" || key == "bidamount" { //中标单位和中标金额winner_all特殊处理
  266. continue
  267. }
  268. tp := map[string]interface{}{
  269. "key": key,
  270. "descript": cpack["descript"],
  271. }
  272. if tmppack[fmt.Sprint(tp["key"])] != nil {
  273. tp["value"] = tmppack[qu.ObjToString(tp["key"])]
  274. } else {
  275. tp["value"] = ""
  276. }
  277. tp["status"] = status
  278. pack = append(pack, tp)
  279. }
  280. //特殊处理中标单位和中标金额
  281. winnerall := []interface{}{}
  282. if tmpWinnerAll, ok := tmppack["winner_all"].([]interface{}); ok && len(tmpWinnerAll) > 0 {
  283. for _, tmp := range tmpWinnerAll {
  284. tmpMap := tmp.(map[string]interface{})
  285. win := map[string]interface{}{
  286. "descript": "标段(包)中标单位",
  287. "key": "winner",
  288. "status": status,
  289. "value": qu.ObjToString(tmpMap["winner"]),
  290. }
  291. winnerall = append(winnerall, win)
  292. var bidamount interface{}
  293. if tmpMap["bidamount"] == nil {
  294. bidamount = ""
  295. } else {
  296. bidamount = strconv.FormatFloat(qu.Float64All(tmpMap["bidamount"]), 'f', -1, 64)
  297. }
  298. bid := map[string]interface{}{
  299. "descript": "标段(包)中标金额",
  300. "key": "bidamount",
  301. "status": status,
  302. "value": bidamount,
  303. }
  304. winnerall = append(winnerall, bid)
  305. }
  306. } else {
  307. winnerall = append(winnerall, map[string]interface{}{
  308. "descript": "标段(包)中标单位",
  309. "key": "winner",
  310. "status": "-1",
  311. "value": "",
  312. })
  313. winnerall = append(winnerall, map[string]interface{}{
  314. "descript": "标段(包)中标金额",
  315. "key": "bidamount",
  316. "status": "-1",
  317. "value": "",
  318. })
  319. }
  320. packs[k] = map[string]interface{}{
  321. "pack": pack,
  322. "packstatus": status,
  323. "winnerall": winnerall,
  324. }
  325. }
  326. }
  327. }
  328. sort.Strings(sortpackskey)
  329. var packages []map[string]interface{}
  330. var isNewPkgArr []bool
  331. for _, v := range sortpackskey {
  332. packages = append(packages, packs[v])
  333. isNewPkgArr = append(isNewPkgArr, isNewPkg[v])
  334. }
  335. return packages, sortpackskey, isNewPkgArr
  336. }
  337. //拼装标的物
  338. func setPurchasingMap(info map[string]interface{}) ([]interface{}, []map[string]interface{}) {
  339. purchasinglist, _ := util.BiaoZhu["purchasinglist"].([]interface{})
  340. var purchasinglists []interface{}
  341. //isNewPcl := []bool{} //记录子包是否是新增的
  342. var isNewAndStatus []map[string]interface{}
  343. if tmpcls, ok := info["purchasinglist"].([]interface{}); ok {
  344. for _, v := range tmpcls {
  345. if pcl, ok := v.(map[string]interface{}); ok {
  346. //isNew, _ := pcl["isnew"].(bool)
  347. isNew := false
  348. status := "-1"
  349. if pcl["purchasinglist_son"] != nil {
  350. status = "1"
  351. }
  352. //isNewPcl = append(isNewPcl, isNew)
  353. isNewAndStatus = append(isNewAndStatus, map[string]interface{}{"isnew": isNew, "status": status})
  354. var pcls []interface{}
  355. for _, ps := range purchasinglist {
  356. ps, _ := ps.(map[string]interface{})
  357. value := pcl[qu.ObjToString(ps["key"])]
  358. if value == nil {
  359. value = ""
  360. }
  361. tp := map[string]interface{}{
  362. "key": ps["key"],
  363. "descript": ps["descript"],
  364. "value": value,
  365. "status": status,
  366. }
  367. // if pcl[preKey+fmt.Sprint(tp["key"])] == nil {
  368. // tp["status"] = "-1"
  369. // } else {
  370. // tp["status"] = "1"
  371. // }
  372. pcls = append(pcls, tp)
  373. }
  374. purchasinglists = append(purchasinglists, pcls)
  375. }
  376. }
  377. }
  378. return purchasinglists, isNewAndStatus
  379. }
  380. //拼装中标候选人
  381. func setWorderMap(info map[string]interface{}) ([]interface{}, []map[string]interface{}) {
  382. //基本参数--中标候选人
  383. winnerorder, _ := util.BiaoZhu["winnerorder"].([]interface{})
  384. worders := []interface{}{}
  385. isNewAndStatus := []map[string]interface{}{}
  386. if tmpwds, ok := info["winnerorder"].([]interface{}); ok {
  387. for _, v := range tmpwds {
  388. if wd, ok := v.(map[string]interface{}); ok {
  389. //isNew, _ := wd["isnew"].(bool)
  390. isNew := false
  391. status := "-1"
  392. if wd["winnerorder_son"] != nil {
  393. status = "1"
  394. }
  395. isNewAndStatus = append(isNewAndStatus, map[string]interface{}{"isnew": isNew, "status": status})
  396. wds := []interface{}{}
  397. for _, cp := range winnerorder {
  398. cp, _ := cp.(map[string]interface{})
  399. value := wd[qu.ObjToString(cp["key"])]
  400. if value == nil {
  401. value = ""
  402. }
  403. tp := map[string]interface{}{
  404. "key": cp["key"],
  405. "descript": cp["descript"],
  406. "value": value,
  407. "status": status,
  408. }
  409. wds = append(wds, tp)
  410. }
  411. worders = append(worders, wds)
  412. }
  413. }
  414. }
  415. return worders, isNewAndStatus
  416. }
  417. //获取公告关联信息
  418. func setOtherInfo(info map[string]interface{}) (result, moreArr []map[string]interface{}) {
  419. if otherInfo, ok := info["info"].([]interface{}); ok && len(otherInfo) > 0 {
  420. //中标,成交、合同、招标(不含变更)
  421. /*
  422. [
  423. {},
  424. {},
  425. ]
  426. */
  427. zbArr := []map[string]interface{}{}
  428. cjArr := []map[string]interface{}{}
  429. htArr := []map[string]interface{}{}
  430. zbbArr := []map[string]interface{}{}
  431. for _, tmp := range otherInfo {
  432. tmpInfo := tmp.(map[string]interface{})
  433. tmpInfo["detail"] = qu.ObjToString(tmpInfo["title"]) + "</br>" + qu.ObjToString(tmpInfo["title"])
  434. toptype := tmpInfo["toptype"]
  435. subtype := tmpInfo["subtype"]
  436. ptime := ""
  437. tmpPtime := qu.Int64All(tmpInfo["publishtime"])
  438. if tmpPtime > 0 {
  439. ptime = qu.FormatDateByInt64(&tmpPtime, qu.Date_Full_Layout)
  440. }
  441. tmpInfo["publishtime_str"] = ptime
  442. if subtype == "中标" {
  443. zbArr = append(zbArr, tmpInfo)
  444. } else if subtype == "成交" {
  445. cjArr = append(cjArr, tmpInfo)
  446. } else if subtype == "合同" {
  447. htArr = append(htArr, tmpInfo)
  448. } else if toptype == "招标" && subtype != "变更" {
  449. zbbArr = append(zbbArr, tmpInfo)
  450. } else { //标注页不展示的信息,更多中展示
  451. moreArr = append(moreArr, map[string]interface{}{
  452. "publishtime": tmpInfo["publishtime_str"],
  453. "subtype": subtype,
  454. "title": tmpInfo["title"],
  455. "href": util.GetJyHref(qu.ObjToString(tmpInfo["id"])),
  456. })
  457. }
  458. }
  459. publishtime := qu.Float64All(info["publishtime"])
  460. //中标信息
  461. if zbLen := len(zbArr); zbLen > 0 {
  462. rzb := DealData(zbLen, publishtime, zbArr, &moreArr)
  463. result = append(result, rzb)
  464. }
  465. //成交
  466. if cjLen := len(cjArr); cjLen > 0 {
  467. rcj := DealData(cjLen, publishtime, cjArr, &moreArr)
  468. result = append(result, rcj)
  469. }
  470. //合同
  471. if htLen := len(htArr); htLen > 0 {
  472. rht := DealData(htLen, publishtime, htArr, &moreArr)
  473. result = append(result, rht)
  474. }
  475. result = append(result, zbbArr...)
  476. }
  477. return
  478. }
  479. func DealData(tmpLen int, publishtime float64, tmp []map[string]interface{}, moreArr *[]map[string]interface{}) (resultTmp map[string]interface{}) {
  480. if tmpLen == 1 || publishtime <= 0 { //相同类型只有一条或者原公告发布时间异常取第一条公告
  481. resultTmp = tmp[0]
  482. for _, t := range tmp[1:] { //将过滤掉的数据加入到更多中
  483. *moreArr = append(*moreArr, map[string]interface{}{
  484. "publishtime": t["publishtime_str"],
  485. "subtype": t["subtype"],
  486. "title": t["title"],
  487. "href": util.GetJyHref(qu.ObjToString(t["id"])),
  488. })
  489. }
  490. return
  491. } else {
  492. diff := float64(0) //记录差值
  493. index := 0
  494. for i, zb := range tmp {
  495. pTmp := qu.Float64All(zb["publishtime"])
  496. diffTmp := math.Abs(publishtime - pTmp) //绝对值
  497. if i == 0 {
  498. diff = diffTmp
  499. } else if diffTmp < diff { //记录较小差值的数据索引位置
  500. diff = diffTmp
  501. index = i
  502. } else { //将过滤掉的数据加入到更多中
  503. *moreArr = append(*moreArr, map[string]interface{}{
  504. "publishtime": zb["publishtime_str"],
  505. "subtype": zb["subtype"],
  506. "title": zb["title"],
  507. "href": util.GetJyHref(qu.ObjToString(zb["id"])),
  508. })
  509. }
  510. }
  511. resultTmp = tmp[index]
  512. }
  513. return
  514. }
  515. // GetNextDataId 获取当前数据下一条的id
  516. func GetNextDataId(id, coll, tid string) string {
  517. nextIdQuery := map[string]interface{}{
  518. "i_ckdata": 2,
  519. "_id": map[string]interface{}{
  520. "$gt": mgo.StringTOBsonId(id),
  521. },
  522. }
  523. if tid != "" {
  524. nextIdQuery["s_usertaskid"] = tid
  525. }
  526. qu.Debug(nextIdQuery, coll)
  527. one, _ := util.Mgo.Find(coll, nextIdQuery, `{"_id":1}`, `{"_id":1}`, true, 0, 1)
  528. if one != nil && len(*one) == 1 {
  529. return mgo.BsonIdToSId((*one)[0]["_id"])
  530. } else {
  531. delete(nextIdQuery, "_id")
  532. one, _ = util.Mgo.Find(coll, nextIdQuery, `{"_id":1}`, `{"_id":1}`, true, 0, 1)
  533. if one != nil && len(*one) == 1 {
  534. return mgo.BsonIdToSId((*one)[0]["_id"])
  535. }
  536. }
  537. return id
  538. }
  539. // GetNextDataId1 质检下一条
  540. func GetNextDataId1(id, coll, tid string) string {
  541. nextIdQuery := map[string]interface{}{
  542. "b_istag": true,
  543. "_id": map[string]interface{}{
  544. "$gt": mgo.StringTOBsonId(id),
  545. },
  546. }
  547. if tid != "" {
  548. nextIdQuery["s_usertaskid"] = tid
  549. }
  550. qu.Debug(nextIdQuery, coll)
  551. one, _ := util.Mgo.Find(coll, nextIdQuery, `{"_id":1}`, `{"_id":1}`, true, 0, 1)
  552. if one != nil && len(*one) == 1 {
  553. return mgo.BsonIdToSId((*one)[0]["_id"])
  554. } else {
  555. delete(nextIdQuery, "_id")
  556. one, _ = util.Mgo.Find(coll, nextIdQuery, `{"_id":1}`, `{"_id":1}`, true, 0, 1)
  557. if one != nil && len(*one) == 1 {
  558. return mgo.BsonIdToSId((*one)[0]["_id"])
  559. }
  560. }
  561. return id
  562. }
  563. func (f *Front) CheckList() {
  564. qu.Catch()
  565. if f.Method() == "POST" {
  566. user := f.GetSession("user").(map[string]interface{})
  567. iRole := qu.ObjToString(user["i_role"])
  568. gid := qu.ObjToString(user["s_groupid"])
  569. start, _ := f.GetInteger("start")
  570. limit, _ := f.GetInteger("length")
  571. draw, _ := f.GetInteger("draw")
  572. status := f.GetString("s_status")
  573. searchStr := f.GetString("search[value]")
  574. search := strings.TrimSpace(searchStr)
  575. query := map[string]interface{}{
  576. "s_stype": "user",
  577. }
  578. if iRole != "0" {
  579. query["s_groupid"] = gid
  580. }
  581. if status != "-1" { //任务状态
  582. query["s_status"] = status
  583. }
  584. if search != "" {
  585. query["$or"] = []interface{}{
  586. map[string]interface{}{"s_projectname": map[string]interface{}{"$regex": search}},
  587. }
  588. }
  589. qu.Debug("Query:", query)
  590. count := util.Mgo.Count(util.TASKCOLLNAME, query)
  591. list, _ := util.Mgo.Find(util.TASKCOLLNAME, query, map[string]interface{}{"_id": -1}, nil, false, start, limit)
  592. for _, l := range *list {
  593. if status := qu.ObjToString(l["s_status"]); status == "进行中" { //更新任务进度
  594. giveNum := qu.IntAll(l["i_givenum"])
  595. sourceinfo := qu.ObjToString(l["s_sourceinfo"])
  596. tagNum := util.Mgo.Count(sourceinfo, map[string]interface{}{"s_usertaskid": mgo.BsonIdToSId(l["_id"]), "b_istag": true})
  597. progressFloat := float64(tagNum) / float64(giveNum)
  598. value, _ := strconv.ParseFloat(fmt.Sprintf("%.4f", progressFloat), 64)
  599. progress := fmt.Sprint(value*100) + "%"
  600. l["s_progress"] = progress
  601. }
  602. }
  603. f.ServeJson(map[string]interface{}{"draw": draw, "data": *list, "recordsFiltered": count, "recordsTotal": count})
  604. } else {
  605. _ = f.Render("project/check_task_list.html")
  606. }
  607. }
  608. func (f *Front) CheckData() {
  609. qu.Catch()
  610. pid := f.GetString("pid")
  611. tid := f.GetString("tid")
  612. stype := f.GetString("stype")
  613. sourceinfo := f.GetString("s_sourceinfo")
  614. datatype, _ := f.GetInteger("datatype")
  615. if f.Method() == "POST" {
  616. start, _ := f.GetInteger("start")
  617. limit, _ := f.GetInteger("length")
  618. draw, _ := f.GetInteger("draw")
  619. searchStr := f.GetString("search[value]")
  620. search := strings.TrimSpace(searchStr)
  621. query := make(map[string]interface{})
  622. if tid != "" {
  623. // 任务数据质检
  624. if stype == "group" {
  625. query["s_grouptaskid"] = tid
  626. } else {
  627. query["s_usertaskid"] = tid
  628. }
  629. query["b_istag"] = true
  630. } else {
  631. if stype == "notag" {
  632. if datatype == 1 {
  633. // 待分发数据
  634. query["b_isgivegroup"] = false
  635. query["b_istagging"] = false
  636. } else {
  637. // 标注数据
  638. query["i_ckdata"] = 2
  639. query["b_isgivegroup"] = false
  640. }
  641. } else if stype == "tag" {
  642. query["b_istagging"] = true //未达标
  643. query["i_ckdata"] = 2
  644. } else {
  645. query["i_ckdata"] = 2
  646. }
  647. }
  648. if search != "" {
  649. query["$or"] = []interface{}{
  650. map[string]interface{}{"v_baseinfo.title": map[string]interface{}{"$regex": search}},
  651. }
  652. }
  653. qu.Debug("Query:", query)
  654. fields := map[string]interface{}{"v_baseinfo.title": 1, "b_check": 1, "i_ckdata": 1, "s_login": 1}
  655. info, _ := util.Mgo.Find(sourceinfo, query, `{"_id": 1}`, fields, false, start, limit)
  656. count := util.Mgo.Count(sourceinfo, query)
  657. qu.Debug(query, sourceinfo, count)
  658. f.ServeJson(map[string]interface{}{
  659. "draw": draw,
  660. "data": *info,
  661. "recordsFiltered": count,
  662. "recordsTotal": count,
  663. })
  664. } else {
  665. if tid == "" {
  666. //project, _ := util.Mgo.FindById(util.PROJECTCOLLNAME, pid, map[string]interface{}{"i_importnum": 1})
  667. //f.T["taskNum"] = (*project)["i_importnum"]
  668. query1 := make(map[string]interface{})
  669. if stype == "all" {
  670. query1["i_ckdata"] = 2
  671. } else if stype == "notag" {
  672. if datatype == 1 {
  673. // 待分发数据
  674. query1["b_isgivegroup"] = false
  675. query1["b_istagging"] = false
  676. } else {
  677. // 标注数据
  678. query1["i_ckdata"] = 2
  679. query1["b_isgivegroup"] = false
  680. }
  681. } else if stype == "tag" {
  682. query1["b_istagging"] = true //未达标
  683. query1["i_ckdata"] = 2
  684. }
  685. f.T["taskNum"] = util.Mgo.Count(sourceinfo, query1)
  686. query1["b_check"] = true // 已质检
  687. checkCount := util.Mgo.Count(sourceinfo, query1)
  688. f.T["taskTagNum"] = 0
  689. f.T["taskCheckNum"] = checkCount
  690. } else {
  691. task, _ := util.Mgo.FindById(util.TASKCOLLNAME, tid, map[string]interface{}{"i_givenum": 1})
  692. f.T["taskNum"] = (*task)["i_givenum"]
  693. tagCount, checkCount := 0, 0
  694. if stype == "group" {
  695. tagCount = util.Mgo.Count(sourceinfo, map[string]interface{}{"s_grouptaskid": tid, "b_istag": true})
  696. checkCount = util.Mgo.Count(sourceinfo, map[string]interface{}{"s_grouptaskid": tid, "b_check": true})
  697. } else {
  698. tagCount = util.Mgo.Count(sourceinfo, map[string]interface{}{"s_usertaskid": tid, "b_istag": true})
  699. checkCount = util.Mgo.Count(sourceinfo, map[string]interface{}{"s_usertaskid": tid, "b_check": true})
  700. }
  701. f.T["taskTagNum"] = tagCount
  702. f.T["taskCheckNum"] = checkCount
  703. }
  704. f.T["pid"] = pid
  705. f.T["tid"] = tid
  706. f.T["sourceinfo"] = sourceinfo
  707. f.T["stype"] = stype
  708. f.T["datatype"] = datatype
  709. _ = f.Render("project/check_data_list.html", &f.T)
  710. }
  711. }
  712. func (f *Front) CheckDetail() {
  713. qu.Catch()
  714. tid := f.GetString("tid")
  715. pid := f.GetString("pid")
  716. did := f.GetString("did")
  717. coll := f.GetString("s_sourceinfo")
  718. project, _ := util.Mgo.FindById(util.PROJECTCOLLNAME, pid, `{"v_fields": 1}`)
  719. if len(*project) > 0 {
  720. field := make(map[string]bool)
  721. vf := (*project)["v_fields"].(map[string]interface{})
  722. for k := range vf {
  723. field[k] = true
  724. }
  725. f.T["fields"] = field
  726. }
  727. qu.Debug(pid, did, coll)
  728. rep := getDetail(did, coll) //获取本条公告的信息
  729. f.T["otherInfo"] = rep["otherInfo"] //展示关联公告信息
  730. f.T["moreInfo"] = rep["moreInfo"] //更多关联公告信息
  731. f.T["pid"] = pid
  732. f.T["tid"] = tid
  733. f.T["did"] = did
  734. f.T["coll"] = coll
  735. f.T["info"] = rep["info"]
  736. f.T["common"] = rep["common"]
  737. f.T["worder"] = rep["worder"]
  738. f.T["packs"] = rep["packs"]
  739. f.T["packskey"] = rep["packskey"]
  740. f.T["ck_pclistag"] = rep["purchasingTag"]
  741. f.T["timeplace"] = rep["timeplace"]
  742. f.T["purchasinglist"] = rep["purchasinglist"]
  743. f.T["other"] = rep["other"]
  744. f.T["PurchasinglistField"] = util.PurchasinglistField
  745. f.T["WinnerorderField"] = util.WinnerorderField
  746. f.T["PackageField"] = util.PackageField
  747. f.T["topsubtype"] = util.TopSubStypeArr2
  748. f.T["ck_purchasinglist"] = rep["ck_purchasinglist"]
  749. f.T["ck_package"] = rep["ck_package"]
  750. f.T["ck_winnerorder"] = rep["ck_winnerorder"]
  751. f.T["worder_new"] = rep["worder_new"]
  752. f.T["pcl_new"] = rep["pcl_new"]
  753. f.T["pkg_new"] = rep["pkg_new"]
  754. f.T["nextid"] = GetNextDataId1(did, coll, tid) //下一条id
  755. _ = f.Render("project/check_detail.html", &f.T)
  756. }
  757. func (f *Front) CheckSave() {
  758. defer qu.Catch()
  759. success := false
  760. msg := ""
  761. user := f.GetSession("user").(map[string]interface{})
  762. username := qu.ObjToString(user["s_login"]) //当前登录用户
  763. userId := qu.ObjToString(user["id"]) //当前登录用户标识
  764. userRole := qu.ObjToString(user["i_role"]) //当前登录用户权限
  765. var obj []map[string]interface{}
  766. infoId := f.GetString("s_infoid")
  767. sourceInfo := f.GetString("s_sourceinfo")
  768. pid := f.GetString("pid")
  769. qu.Debug("Data ID:", infoId)
  770. project, _ := util.Mgo.FindById(util.PROJECTCOLLNAME, pid, map[string]interface{}{"s_name": 1, "v_fields": 1})
  771. data := f.GetString("data")
  772. err := json.Unmarshal([]byte(data), &obj)
  773. if err != nil {
  774. qu.Debug("Json Unmarshal Error")
  775. f.ServeJson(map[string]interface{}{"success": success, "msg": "解析数据失败"})
  776. return
  777. }
  778. tagSet := map[string]interface{}{} //被标注字段状态
  779. baseSet := map[string]interface{}{} //要修改的字段信息
  780. baseUnset := map[string]interface{}{} //要删除的字段信息
  781. if len(obj) == 1 { //单独保存某个一级
  782. content, ok := obj[0]["content"].([]interface{})
  783. if !ok || len(content) == 0 {
  784. f.ServeJson(map[string]interface{}{"success": success, "msg": "解析数据失败"})
  785. return
  786. }
  787. title := qu.ObjToString(obj[0]["title"])
  788. istag, _ := obj[0]["checkAllTag"].(bool)
  789. status := qu.IntAll(obj[0]["status"])
  790. switch title {
  791. case "基本字段":
  792. MarkBase(content, tagSet, baseSet, baseUnset)
  793. case "时间地点":
  794. MarkTimePlace(content, tagSet, baseSet, baseUnset)
  795. case "标的信息":
  796. MarkPurchasinglist(content, tagSet, baseSet, baseUnset, istag, status)
  797. case "多包信息":
  798. MarkPackage(content, tagSet, baseSet, baseUnset, status)
  799. case "中标候选人信息":
  800. MarkWonderorder(content, tagSet, baseSet, baseUnset, status)
  801. case "其余信息":
  802. MarkOther(content, tagSet, baseSet, baseUnset)
  803. }
  804. } else {
  805. for j, val := range obj {
  806. content, ok := val["content"].([]interface{})
  807. status := qu.IntAll(val["status"])
  808. if !ok {
  809. qu.Debug("Content Error")
  810. continue
  811. }
  812. istag, _ := val["checkAllTag"].(bool)
  813. if j == 0 { //基本信息
  814. MarkBase(content, tagSet, baseSet, baseUnset)
  815. } else if j == 1 { //时间地点
  816. MarkTimePlace(content, tagSet, baseSet, baseUnset)
  817. } else if j == 2 { //标的物
  818. MarkPurchasinglist(content, tagSet, baseSet, baseUnset, istag, status)
  819. } else if j == 3 { //多包
  820. MarkPackage(content, tagSet, baseSet, baseUnset, status)
  821. } else if j == 4 { //候选人
  822. MarkWonderorder(content, tagSet, baseSet, baseUnset, status)
  823. } else { //其余信息
  824. MarkOther(content, tagSet, baseSet, baseUnset)
  825. }
  826. }
  827. }
  828. dataInfo, _ := util.Mgo.FindById(sourceInfo, infoId, map[string]interface{}{"v_baseinfo": 1, "v_taginfo": 1}) //查询标注保存前的原始信息
  829. tagInfo, _ := (*dataInfo)["v_taginfo"].(map[string]interface{})
  830. baseInfo, _ := (*dataInfo)["v_baseinfo"].(map[string]interface{})
  831. if tagInfo != nil && len(tagInfo) > 0 {
  832. for field, tmpStatus := range tagSet { //比对本次标注信息和历史标注信息
  833. status := qu.IntAll(tmpStatus) //此次被标注字段的状态
  834. markedStatus := qu.IntAll(tagInfo[field]) //历史标注状态
  835. if status == 1 && markedStatus != 0 { //此次标注结果为正确,且有历史标注记录,不做修改
  836. qu.Debug("已标注字段field---", field)
  837. //delete(tagSet, field)
  838. delete(baseSet, field)
  839. //continue
  840. }
  841. }
  842. }
  843. allTagFields := map[string]interface{}{} //记录此此标注所有标注信息,用于日志记录
  844. for k, _ := range tagSet {
  845. allTagFields[k] = true
  846. }
  847. for k, v := range baseSet {
  848. allTagFields[k] = v
  849. }
  850. for k, _ := range baseUnset {
  851. allTagFields[k] = nil
  852. }
  853. qu.Debug("allTagFields===", allTagFields)
  854. qu.Debug("tagSet===", tagSet)
  855. // 质检时,标注标记变成质检标记
  856. checkFields, _ := (*project)["v_fields"].(map[string]interface{})
  857. checkSet := make(map[string]interface{})
  858. for k := range checkFields {
  859. checkSet[k] = tagSet[k]
  860. }
  861. if len(checkSet) > 0 || baseInfo["purchasinglist_alltag"] != nil { //purchasinglist_alltag特殊处理
  862. //1、更新数据源信息
  863. setResult := map[string]interface{}{ //更新字段集
  864. "i_updatetime": time.Now().Unix(),
  865. "b_check": true,
  866. "s_checkid": userId,
  867. "b_istag": true,
  868. }
  869. //for field, val := range tagSet { //更新质检字段
  870. // setResult["v_taginfo."+field] = val
  871. //}
  872. setResult["v_checkinfo"] = checkSet
  873. for field, val := range baseSet { //更新基本字段
  874. setResult["v_baseinfo."+field] = val
  875. }
  876. baseUnsetResult := map[string]interface{}{} //删除字段集
  877. for field, _ := range baseUnset { //删除基本字段
  878. baseUnsetResult["v_baseinfo."+field] = ""
  879. }
  880. set := map[string]interface{}{
  881. "$set": setResult,
  882. }
  883. if len(baseUnsetResult) > 0 {
  884. set["$unset"] = baseUnsetResult
  885. }
  886. qu.Debug("set---", set)
  887. success = util.Mgo.UpdateById(sourceInfo, infoId, set)
  888. //2、更新marked表
  889. tmp, _ := util.Mgo.FindById(sourceInfo, infoId, map[string]interface{}{"v_baseinfo": 1, "v_taginfo": 1, "i_ckdata": 1})
  890. qu.Debug("infoId:", infoId)
  891. delete(*tmp, "_id")
  892. (*tmp)["updatetime"] = time.Now().Unix()
  893. b := util.Mgo.Update(util.AllToColl, map[string]interface{}{"_id": mgo.StringTOBsonId(infoId)}, map[string]interface{}{"$set": tmp}, true, false)
  894. qu.Debug("Update Marked:", b)
  895. }
  896. //3、保存标注日志
  897. b := SaveLog(infoId, "", username, userId, userRole, qu.ObjToString((*project)["s_name"]), "质检", baseInfo, allTagFields)
  898. qu.Debug("Save Log:", b)
  899. f.ServeJson(map[string]interface{}{"success": success, "msg": msg})
  900. }
  901. func (f *Front) CheckResult() {
  902. qu.Catch()
  903. pid := f.GetString("pid")
  904. tid := f.GetString("tid")
  905. sourceinfo := f.GetString("s_sourceinfo")
  906. stype := f.GetString("stype")
  907. datatype, _ := f.GetInteger("datatype")
  908. task, _ := util.Mgo.FindById(util.TASKCOLLNAME, tid, map[string]interface{}{"i_givenum": 1})
  909. projcet, _ := util.Mgo.FindById(util.PROJECTCOLLNAME, pid, map[string]interface{}{"v_fields": 1})
  910. //tagCount := util.Mgo.Count(sourceinfo, map[string]interface{}{"s_grouptaskid": tid, "b_istag": true})
  911. //checkCount := util.Mgo.Count(sourceinfo, map[string]interface{}{"s_grouptaskid": tid, "b_check": true})
  912. allNum := (*task)["i_givenum"] //任务数据量
  913. markNum, checkNum, checkNumR := 0, 0, 0 // 标注数量, 审核数据量, 审核数据完全正确的数据量
  914. cmaps := make(map[string]int) // 标注字段整体准确率
  915. umaps := make(map[string]interface{}) // 按人员 字段准确率
  916. for k := range (*projcet)["v_fields"].(map[string]interface{}) {
  917. cmaps[k] = 0
  918. }
  919. sess := util.Mgo.GetMgoConn()
  920. defer util.Mgo.DestoryMongoConn(sess)
  921. query := make(map[string]interface{})
  922. if tid == "" {
  923. query1 := make(map[string]interface{})
  924. if stype == "all" {
  925. query1["i_ckdata"] = 2
  926. } else if stype == "notag" {
  927. if datatype == 1 {
  928. // 待分发数据
  929. query1["b_isgivegroup"] = false
  930. query1["b_istagging"] = false
  931. } else {
  932. // 标注数据
  933. query1["i_ckdata"] = 2
  934. query1["b_isgivegroup"] = false
  935. }
  936. } else if stype == "tag" {
  937. query1["b_istagging"] = true //未达标
  938. query1["i_ckdata"] = 2
  939. }
  940. f.T["taskNum"] = util.Mgo.Count(sourceinfo, query1)
  941. } else {
  942. if stype == "group" {
  943. query["s_grouptaskid"] = tid
  944. } else {
  945. query["s_usertaskid"] = tid
  946. }
  947. }
  948. query["b_check"] = true
  949. qu.Debug(query)
  950. checkNum = util.Mgo.Count(sourceinfo, query)
  951. result := sess.DB(util.Mgo.DbName).C(sourceinfo).Find(query).Iter()
  952. if checkNum == 0 {
  953. f.ServeJson(map[string]interface{}{"rep": false, "msg": "无质检审核数据!"})
  954. return
  955. }
  956. for tmp := make(map[string]interface{}); result.Next(&tmp); markNum++ {
  957. user := qu.ObjToString(tmp["s_login"])
  958. var up map[string]int
  959. if umaps[user] == nil {
  960. up = make(map[string]int)
  961. } else {
  962. up = umaps[user].(map[string]int)
  963. }
  964. up["ck_count"] += 1
  965. umaps[user] = up
  966. if tmp["b_check"].(bool) {
  967. if f, ok := tmp["v_checkinfo"].(map[string]interface{}); ok {
  968. flag := true // 数据整体准确率
  969. // 按人员统计字段准备率
  970. var up map[string]int
  971. if umaps[user] == nil {
  972. up = make(map[string]int)
  973. } else {
  974. up = umaps[user].(map[string]int)
  975. }
  976. for k1 := range cmaps {
  977. if qu.IntAll(f[k1]) == 1 {
  978. cmaps[k1] += 1 // 字段整体正确率
  979. up[k1] += 1
  980. } else {
  981. flag = false
  982. }
  983. }
  984. up["re_count"] += 1
  985. umaps[user] = up
  986. if flag {
  987. checkNumR++
  988. up["re_rg_count"] += 1
  989. }
  990. }
  991. }
  992. }
  993. qu.Debug(cmaps)
  994. qu.Debug(umaps)
  995. // 前台页面数据
  996. dataSource := make(map[string]interface{})
  997. var userSelect []string
  998. var dataSelect []map[string]interface{}
  999. userSelect = append(userSelect, "全部")
  1000. tmp := make(map[string]interface{})
  1001. tmp["name"] = "全部"
  1002. tmp["num1"] = allNum
  1003. tmp["num2"] = checkNum
  1004. tmp["num3"] = checkNumR
  1005. tmp["num4"] = CountPr(checkNumR, checkNum)
  1006. dataSelect = append(dataSelect, tmp)
  1007. for k, v := range (*projcet)["v_fields"].(map[string]interface{}) {
  1008. tmp1 := make(map[string]interface{})
  1009. tmp1["name"] = v
  1010. tmp1["num1"] = markNum
  1011. tmp1["num2"] = checkNum
  1012. tmp1["num3"] = cmaps[k]
  1013. tmp1["num4"] = CountPr(cmaps[k], checkNum)
  1014. dataSelect = append(dataSelect, tmp1)
  1015. }
  1016. dataSource["全部"] = dataSelect
  1017. for k1, v1 := range umaps {
  1018. if v2, o := v1.(map[string]int); o {
  1019. userSelect = append(userSelect, k1)
  1020. var dataSelect1 []map[string]interface{}
  1021. tmp2 := make(map[string]interface{})
  1022. tmp2["name"] = "全部"
  1023. tmp2["num1"] = v2["ck_count"]
  1024. tmp2["num2"] = v2["re_count"]
  1025. tmp2["num3"] = v2["re_rg_count"]
  1026. tmp2["num4"] = CountPr(v2["re_rg_count"], v2["re_count"])
  1027. dataSelect1 = append(dataSelect1, tmp2)
  1028. for k, v := range (*projcet)["v_fields"].(map[string]interface{}) {
  1029. tmp1 := make(map[string]interface{})
  1030. tmp1["name"] = v
  1031. tmp1["num1"] = v2["ck_count"]
  1032. tmp1["num2"] = v2["re_count"]
  1033. tmp1["num3"] = v2[k]
  1034. tmp1["num4"] = CountPr(v2[k], v2["re_count"])
  1035. dataSelect1 = append(dataSelect1, tmp1)
  1036. }
  1037. dataSource[k1] = dataSelect1
  1038. }
  1039. }
  1040. f.T["pid"] = pid
  1041. f.T["tid"] = tid
  1042. f.T["taskNum"] = allNum
  1043. f.T["taskTagNum"] = markNum
  1044. f.T["taskCheckNum"] = checkNum
  1045. f.T["taskCheckRight"] = checkNumR
  1046. f.T["tableData"] = dataSource
  1047. f.T["userSelect"] = userSelect
  1048. _ = f.Render("project/check_result.html", &f.T)
  1049. }
  1050. // CountPr 计算百分比
  1051. func CountPr(c1, c2 int) string {
  1052. decimal.DivisionPrecision = 2
  1053. if c1 == 0 || c2 == 0 {
  1054. return "0"
  1055. }
  1056. d := decimal.NewFromInt32(int32(c1)).Div(decimal.NewFromInt32(int32(c2))).Mul(decimal.NewFromInt32(100))
  1057. return d.String() + "%"
  1058. }