package quesManager import ( "fmt" "io/ioutil" "log" qu "qfw/util" mgdb "qfw/util/mongodb" "regexp" "strconv" "strings" "time" "github.com/go-xweb/xweb" "github.com/tealeg/xlsx" "gopkg.in/mgo.v2/bson" ) type QuesM struct { *xweb.Action managerQues xweb.Mapper `xweb:"/center/managerQues"` //问题管理 saveNewQues xweb.Mapper `xweb:"/center/question/saveNewQues"` //新建问题 saveFeedbackSug xweb.Mapper `xweb:"/center/question/saveFeedbackSug"` //保存反馈意见 closeQues xweb.Mapper `xweb:"/center/question/closeQues"` //关闭问题 quesfile xweb.Mapper `xweb:"/center/question/quesfile"` //批量导入问题 } const role_admin, role_examine, role_dev = 3, 2, 1 //管理员,审核员,开发员 var REG = regexp.MustCompile(".*/(.+)\\.html.*") func (q *QuesM) ManagerQues() { if q.Method() == "POST" { start, _ := q.GetInteger("start") limit, _ := q.GetInteger("length") draw, _ := q.GetInteger("draw") searchStr := q.GetString("search[value]") //搜索内容 search := strings.TrimSpace(searchStr) state, _ := q.GetInteger("state") //问题状态 introStage, _ := q.GetInteger("introStage") //引入阶段 //log.Println("start:", start, " limit:", limit, " draw:", draw, " search:", search, " state", state, " introStage", introStage) query := bson.M{} if state >= 0 && introStage >= 0 { //同时满足问题状态和引入阶段 query = bson.M{ "i_state": state, "i_introStage": introStage, } } else if state < 0 && introStage >= 0 { //仅仅搜索满足引入阶段,不搜索问题状态 query = bson.M{ "i_introStage": introStage, } } else if state >= 0 && introStage < 0 { //仅仅搜索满足问题状态,不搜索引入阶段 query = bson.M{ "i_state": state, } } if search != "" { query["$or"] = []interface{}{ bson.M{"s_title": bson.M{"$regex": search}}, bson.M{"s_id": bson.M{"$regex": search}}, bson.M{"s_errFiled": bson.M{"$regex": search}}, } } sort := `{"%s":%d}` orderIndex := q.GetString("order[0][column]") orderName := q.GetString(fmt.Sprintf("columns[%s][data]", orderIndex)) orderType := 1 if q.GetString("order[0][dir]") != "asc" { orderType = -1 } sort = fmt.Sprintf(sort, orderName, orderType) ques := *mgdb.Find("question", query, sort, nil, false, start, limit) count := mgdb.Count("question", query) page := start / 10 if ques != nil { for k, v := range ques { v["num"] = k + 1 + page*10 i_state := v["i_state"] i_introStage := v["i_introStage"] if i_state == 0 { //未处理 v["i_state"] = "未处理" } else if i_state == 1 { //已处理 v["i_state"] = "已处理" } else if i_state == 2 { //暂不处理 v["i_state"] = "暂不处理" } else if i_state == 4 { //关闭 v["i_state"] = "关闭" } if i_introStage == 0 { //爬虫抓取阶段 v["i_introStage"] = "爬虫抓取" } else if i_introStage == 1 { //数据抽取阶段 v["i_introStage"] = "数据抽取" } else if i_introStage == 2 { //数据分类阶段 v["i_introStage"] = "数据分类" } v["i_time"] = time.Unix(v["i_time"].(int64), 0).Format("2006-01-02 15:04:05") } } //log.Println("ques:", ques) q.ServeJson(map[string]interface{}{"draw": draw, "data": ques, "recordsFiltered": count, "recordsTotal": count}) } else { q.Render("question.html") } } //新建问题 func (q *QuesM) SaveNewQues() { auth := qu.IntAll(q.GetSession("auth")) if auth != role_admin { q.ServeJson("没有权限") return } title := q.GetString("info") id := q.GetString("id") addr := q.GetString("addr") introStageStr := q.GetString("intro") errFiled := q.GetString("errFiled") name := q.GetString("name") descript := q.GetString("descript") if id == "" { //解析地址 id = getId(addr) } else if addr == "" { //加密id addr = getAddr(id) } log.Println("Save id:", id, " addr:", addr) if id == "" || addr == "" { q.ServeJson(map[string]interface{}{ "state": "err", }) return } newQues := make(map[string]interface{}) newQues["s_title"] = title //标题 newQues["s_id"] = id //id newQues["s_href"] = addr //地址 introStage := -1 if introStageStr == "grab" { introStage = 0 } else if introStageStr == "extract" { introStage = 1 } else if introStageStr == "classify" { introStage = 2 } newQues["i_introStage"] = introStage //引入阶段 newQues["s_errFiled"] = errFiled //错误字段 newQues["s_feedbackPerson"] = name //反馈人 newQues["s_descript"] = descript //描述 newQues["i_time"] = time.Now().Unix() //录入时间 newQues["i_state"] = 0 //问题状态(新建默认为未处理) newQues["s_sugesstion"] = "" //意见反馈 //log.Println(title, id, addr, introStage, errFiled, name, descript, endTime) s := mgdb.Save("question", newQues) state := "err" if len(s) > 0 { state = "ok" } q.ServeJson(map[string]interface{}{ "state": state, }) } //保存反馈意见 func (q *QuesM) SaveFeedbackSug() { _id := q.GetString("feedbackId") s_sugesstion := q.GetString("sug") state := q.GetString("feedbackState") i_state := -1 if state == "未处理" { i_state = 0 } else if state == "已处理" { i_state = 1 } else if state == "暂不处理" { i_state = 2 } query := bson.M{ "_id": bson.ObjectIdHex(_id), } update := bson.M{ "$set": bson.M{ "i_state": i_state, "s_sugesstion": s_sugesstion, }, } // log.Println(_id, s_sugesstion, state, query, update) b := mgdb.Update("question", query, update, false, false) log.Println("Save: ", _id, " 反馈意见", b) returnState := "false" if b { returnState = "ok" } q.ServeJson(map[string]interface{}{ "state": returnState, }) } //关闭问题 func (q *QuesM) CloseQues() { _id := q.GetString("id") query := bson.M{ "_id": bson.ObjectIdHex(_id), } update := bson.M{ "$set": bson.M{ "i_state": 4, }, } b := mgdb.Update("question", query, update, false, false) log.Println("Close :", _id, " ", b) state := "false" if b { state = "ok" } q.ServeJson(map[string]interface{}{ "state": state, }) } //批量导入问题 func (q *QuesM) Quesfile() { auth := qu.IntAll(q.GetSession("auth")) if auth != role_admin { q.ServeJson("没有权限") return } if q.Method() == "POST" { mf, _, err := q.GetFile("xlsx") errorinfo := map[string]interface{}{} if err == nil { binary, _ := ioutil.ReadAll(mf) xls, _ := xlsx.OpenBinary(binary) sheet := xls.Sheets[0] rows := sheet.Rows for rk, row := range rows { if rk != 0 { //excel表中第一行为标题字段舍去 //log.Println(k, " row----", row) cells := row.Cells if len(cells) != 7 { errorinfo["data"+strconv.Itoa(rk)] = "第" + strconv.Itoa(rk+1) + "行数据填写不完整" continue } addr := cells[1].Value //地址 id := cells[2].Value //id if addr == "" && id == "" { errorinfo["data"+strconv.Itoa(rk)] = "第" + strconv.Itoa(rk+1) + "行问题页面和信息id不能同时为空" continue } title := cells[0].Value //标题 errField := cells[3].Value //错误字段 descript := cells[4].Value //问题描述 introStage := cells[5].Value //引入阶段 feedbackPerson := cells[6].Value //反馈人 if errField == "" || descript == "" || introStage == "" { errorinfo["data"+strconv.Itoa(rk)] = "第" + strconv.Itoa(rk+1) + "行数据填写不完整" continue } errStr := arrangeData(title, id, addr, errField, descript, introStage, feedbackPerson) if errStr != "" { errorinfo["data"+strconv.Itoa(rk)] = "第" + strconv.Itoa(rk+1) + "行" + errStr } //log.Println(title, descript, introStage, feedbackPerson) } } q.ServeJson(errorinfo) } else { q.ServeJson(false) } } } func arrangeData(title, id, addr, errField, descript, introStage, feedbackPerson string) string { fileQues := make(map[string]interface{}) i_introStage := -1 if id == "" { //解析地址 id = getId(addr) } else if addr == "" { //加密id addr = getAddr(id) } if id == "" || addr == "" { //未解析成功 return "网址或id解析错误" } fileQues["s_title"] = title //标题 fileQues["s_id"] = id //id fileQues["s_href"] = addr //地址 if introStage == "爬虫抓取阶段" { i_introStage = 0 } else if introStage == "数据抽取阶段" { i_introStage = 1 } else if introStage == "数据分类阶段" { i_introStage = 2 } fileQues["i_introStage"] = i_introStage //引入阶段 fileQues["s_errFiled"] = errField //错误字段 fileQues["s_feedbackPerson"] = feedbackPerson //反馈人 fileQues["s_descript"] = descript //描述 fileQues["i_time"] = time.Now().Unix() //录入时间 fileQues["i_state"] = 0 //问题状态(新建默认为未处理) fileQues["s_sugesstion"] = "" //意见反馈 mgdb.Save("question", fileQues) return "" } //根据地址解析出id func getId(addr string) string { ins := REG.ReplaceAllString(addr, "$1") id := "" if ins != "" { res := qu.CommonDecodeArticle("content", ins) if res != nil && len(res) > 0 { id = res[0] } } return id } //根据id加密 func getAddr(id string) string { addr := qu.EncodeArticleId2ByCheck(id) return "https://www.jianyu360.com/article/content/" + addr + ".html" }