entdataexport.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. package dataexport
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io/ioutil"
  6. "log"
  7. "net/http"
  8. "os"
  9. "sort"
  10. "strconv"
  11. "strings"
  12. "sync"
  13. "time"
  14. util "app.yhyue.com/moapp/jybase/common"
  15. . "app.yhyue.com/moapp/jybase/date"
  16. . "app.yhyue.com/moapp/jybase/encrypt"
  17. elastic "app.yhyue.com/moapp/jybase/es"
  18. "app.yhyue.com/moapp/jybase/mongodb"
  19. mg "app.yhyue.com/moapp/jybase/mongodb"
  20. "app.yhyue.com/moapp/jybase/mysql"
  21. "github.com/tealeg/xlsx"
  22. "go.mongodb.org/mongo-driver/bson"
  23. )
  24. // 作者:一组开发
  25. type Filters struct {
  26. FilterId string
  27. }
  28. func GetEntDataExportCount(sim, bid mg.MongodbSim, bidMgoDBName, elasticAddress, _id string, entId, entUserId int, isFirst bool, url string, maxCount int) (count, newCount int, data *[]map[string]interface{}) {
  29. defer util.Catch()
  30. var (
  31. searchsWaitGroup = &sync.WaitGroup{}
  32. )
  33. count = GetDataExportSearchCountByScdId(sim, bid, bidMgoDBName, elasticAddress, _id)
  34. if count > maxCount || count == -1 {
  35. count = maxCount
  36. }
  37. log.Println("count", count)
  38. dataType := "2"
  39. //数据导出数据查询
  40. res, err := GetDataExportSearchResultByScdId(sim, bid, bidMgoDBName, elasticAddress, _id, dataType, count)
  41. if err != nil {
  42. log.Println("企业数据导出错误 ", err)
  43. return 0, 0, nil
  44. }
  45. // 20210716 由原来的redis判重改为调用判重中台接口进行判重
  46. m := map[string]bool{}
  47. infoIdList := []string{}
  48. insertFlag := "false"
  49. if !isFirst {
  50. insertFlag = "true"
  51. }
  52. for _, v := range *res {
  53. if util.IntAll(v["signendtime"]) != 0 {
  54. date := v["signendtime"]
  55. v["signendtime"] = FormatDateWithObj(&date, Date_Short_Layout)
  56. }
  57. if util.IntAll(v["bidendtime"]) != 0 {
  58. date := v["bidendtime"]
  59. v["bidendtime"] = FormatDateWithObj(&date, Date_Short_Layout)
  60. }
  61. id := util.ObjToString(v["_id"])
  62. if m[id] {
  63. continue
  64. }
  65. m[id] = true
  66. // 20210716 redis判重调整为调用判重中台接口 每一千个调用一次
  67. infoIdList = append(infoIdList, id)
  68. if len(infoIdList) > 1000 {
  69. // 调接口
  70. rs, err5 := Post(url, map[string]string{
  71. "personId": "0", // 没有使用这个参数
  72. "infoId": strings.Join(infoIdList, ","),
  73. "entId": fmt.Sprintf("%d", entId),
  74. "isInsert": insertFlag,
  75. "isEnt": "true",
  76. })
  77. log.Println("响应结果:", rs)
  78. if err5 != nil || util.IntAll(rs["code"]) != 0 {
  79. log.Println("企业订阅数据导出接口判重失败", err5)
  80. log.Println("企业订阅数据导出接口判重失败rs:", rs)
  81. log.Println("企业订阅数据导出接口判重失败rs[code]:", rs["code"])
  82. log.Println("企业订阅数据导出接口判重失败code是否为0", util.IntAll(rs["code"]) != 0)
  83. log.Println("企业订阅数据导出接口判重失败", err5, "rs:", rs, " rs[code]:", rs["code"], " ", util.IntAll(rs["code"]), "code是否为0", util.IntAll(rs["code"]) != 0)
  84. } else {
  85. log.Println("企业订阅数据导出")
  86. // 置空
  87. infoIdList = []string{}
  88. // 本次数据累计
  89. returnData := rs["data"].(map[string]interface{})
  90. log.Println(newCount, "加之前")
  91. newCount += util.IntAll(returnData["newCount"])
  92. //newCount += int(returnData["newCount"].(float64))
  93. log.Println(newCount, "加之后")
  94. }
  95. }
  96. if !isFirst {
  97. delete(v, "_id")
  98. v["entid"] = entId
  99. v["userid"] = entUserId
  100. v["infoid"] = id
  101. v["createtime"] = time.Now().Unix()
  102. }
  103. }
  104. if len(infoIdList) > 0 {
  105. rs, err5 := Post(url, map[string]string{
  106. "personId": "0", // 没有使用这个参数
  107. "infoId": strings.Join(infoIdList, ","),
  108. "entId": fmt.Sprintf("%d", entId),
  109. "isInsert": insertFlag,
  110. "isEnt": "true",
  111. })
  112. log.Println(rs)
  113. if err5 != nil || util.IntAll(rs["code"]) != 0 {
  114. log.Println("企业订阅数据导出接口判重失败", err5)
  115. log.Println("企业订阅数据导出接口判重失败rs:", rs)
  116. log.Println("企业订阅数据导出接口判重失败rs[code]:", rs["code"])
  117. log.Println("企业订阅数据导出接口判重失败code是否为0", util.IntAll(rs["code"]) != 0)
  118. log.Println("企业订阅数据导出接口判重失败", err5, "rs:", rs, " rs[code]:", rs["code"], " ", util.IntAll(rs["code"]), "code是否为0", util.IntAll(rs["code"]) != 0)
  119. } else {
  120. log.Println("企业订阅数据导出")
  121. // 置空
  122. infoIdList = []string{}
  123. // 本次数据累计
  124. returnData := rs["data"].(map[string]interface{})
  125. log.Println(newCount, "加之前")
  126. newCount += util.IntAll(returnData["newCount"])
  127. //newCount += int(returnData["newCount"].(float64))
  128. log.Println(newCount, "加之后")
  129. }
  130. }
  131. searchsWaitGroup.Wait()
  132. log.Println("企业数据导出--数据遍历完成")
  133. //newCount = len(newCountPool)
  134. log.Println("new", newCount)
  135. data = res
  136. return
  137. }
  138. func FormatExportDatas(Mgo_Ent mongodb.MongodbSim, data *[]map[string]interface{}, webdomain string, dataType string, entId int) *[]map[string]interface{} {
  139. //格式化输出
  140. var (
  141. entexportPool = make(chan bool, 20)
  142. entexportWaitGroup = &sync.WaitGroup{}
  143. )
  144. sort.Slice(*data, func(i, j int) bool {
  145. time1 := util.Int64All((*data)[i]["publishtime"])
  146. time2 := util.Int64All((*data)[j]["publishtime"])
  147. return time1 > time2
  148. })
  149. log.Println("补充信息开始")
  150. for _, v := range *data {
  151. entexportWaitGroup.Add(1)
  152. entexportPool <- true
  153. go func(v map[string]interface{}) {
  154. defer func() {
  155. entexportWaitGroup.Done()
  156. <-entexportPool
  157. }()
  158. //有中标企业 且 高级字段查询
  159. if dataType == "2" {
  160. //查询企业公示 法人 公司电话 公司邮箱地址
  161. s_winner := strings.Split(util.ObjToString(v["s_winner"]), ",")[0]
  162. if entData, ok := Mgo_Ent.Find("winner_enterprise", bson.M{"company_name": s_winner}, nil,
  163. `{"company_name":1,"company_email":1,"legal_person":1,"company_phone":1}`, false, -1, -1); ok {
  164. if entData != nil && *entData != nil && len(*entData) > 0 {
  165. for _, ev := range *entData {
  166. if v["s_winner"] == ev["company_name"] {
  167. legal_person := ""
  168. if ev["legal_person"] != nil {
  169. legal_person = ev["legal_person"].(string)
  170. }
  171. company_phone := ""
  172. if ev["company_phone"] != nil {
  173. company_phone = ev["company_phone"].(string)
  174. }
  175. company_email := ""
  176. if ev["company_email"] != nil && ev["company_email"] != "无" {
  177. company_email = ev["company_email"].(string)
  178. }
  179. v["legal_person"] = legal_person
  180. v["company_phone"] = company_phone
  181. v["company_email"] = company_email
  182. }
  183. }
  184. }
  185. }
  186. }
  187. //====================字段补漏=========================
  188. if v["toptype"] == "结果" && dataType == "2" && !(v["agency"] != nil && v["budget"] != nil && v["buyerperson"] != nil && v["buyertel"] != nil) {
  189. r := elastic.Get("projectset", "projectset", fmt.Sprintf(`{"query":{"term":{"list.infoid":"%s"}},"_source": ["list"]}`, v["_id"]))
  190. if len(*r) > 0 {
  191. MsgList := (*r)[0]["list"]
  192. if MsgList != nil {
  193. list := util.ObjArrToMapArr(MsgList.([]interface{}))
  194. for _, vv := range list {
  195. if vv["subtype"] == "招标" {
  196. if v["agency"] == nil && vv["agency"] != nil {
  197. v["agency"] = vv["agency"]
  198. }
  199. if v["budget"] == nil && vv["budget"] != nil {
  200. v["budget"] = vv["budget"]
  201. }
  202. if v["buyerperson"] == nil && vv["buyerperson"] != nil {
  203. v["buyerperson"] = vv["buyerperson"]
  204. }
  205. if v["buyertel"] == nil && vv["buyertel"] != nil {
  206. v["buyertel"] = vv["buyertel"]
  207. }
  208. break
  209. }
  210. }
  211. }
  212. }
  213. }
  214. if v["area"] == "A" {
  215. v["area"] = "全国"
  216. }
  217. if v["publishtime"] != nil {
  218. date := v["publishtime"]
  219. v["publishtime"] = FormatDateWithObj(&date, Date_Short_Layout)
  220. }
  221. if v["bidopentime"] != nil {
  222. date := v["bidopentime"]
  223. v["bidopentime"] = FormatDateWithObj(&date, Date_Short_Layout)
  224. }
  225. if util.IntAll(v["signendtime"]) != 0 {
  226. date := v["signendtime"]
  227. v["signendtime"] = FormatDateWithObj(&date, Date_Short_Layout)
  228. }
  229. if util.IntAll(v["bidendtime"]) != 0 {
  230. date := v["bidendtime"]
  231. v["bidendtime"] = FormatDateWithObj(&date, Date_Short_Layout)
  232. }
  233. if v["currency"] == "" || v["currency"] == nil {
  234. v["currency"] = "人民币"
  235. }
  236. if v["subtype"] == nil && v["toptype"] != nil {
  237. v["subtype"] = v["toptype"]
  238. }
  239. if v["detail"] != "" && v["detail"] != nil {
  240. str := ClearHtml.ReplaceAllString(v["detail"].(string), "")
  241. str = ClearOther.ReplaceAllString(str, "")
  242. str = strings.Replace(str, " ", "", -1)
  243. v["detail"] = str
  244. }
  245. if v["infoid"] != nil {
  246. v["url"] = webdomain + "/article/content/" + CommonEncodeArticle("content", v["infoid"].(string)) + ".html"
  247. }
  248. }(v)
  249. }
  250. entexportWaitGroup.Wait()
  251. log.Println("补充信息结束")
  252. return data
  253. }
  254. func Post(url string, form map[string]string) (data map[string]interface{}, err error) {
  255. str := ""
  256. for k, v := range form {
  257. str += "&" + k + "=" + v
  258. }
  259. //log.Println(str)
  260. res, err1 := http.Post(url, "application/x-www-form-urlencoded", strings.NewReader(str))
  261. log.Println(res)
  262. if err1 != nil {
  263. log.Println("post err:", err1.Error())
  264. return nil, err1
  265. } else if res.Body != nil {
  266. defer res.Body.Close()
  267. bs, _ := ioutil.ReadAll(res.Body)
  268. err2 := json.Unmarshal(bs, &data)
  269. if err2 != nil {
  270. return nil, err2
  271. }
  272. }
  273. return data, nil
  274. }
  275. // 生成xlsx
  276. func GetXlsx(mMap []map[string]interface{}, entId, entUserId int, filePath string) string {
  277. xf, err := xlsx.OpenFile("./web/staticres/fields.xlsx")
  278. if err != nil {
  279. log.Println("fields file not foud", err.Error())
  280. }
  281. sh := xf.Sheets[1]
  282. for _, v := range mMap {
  283. row := sh.AddRow()
  284. row.AddCell().SetValue(v["keyword"])
  285. row.AddCell().SetValue(v["area"])
  286. row.AddCell().SetValue(v["city"])
  287. row.AddCell().SetValue(v["district"])
  288. row.AddCell().SetValue(v["title"])
  289. row.AddCell().SetValue(v["subtype"])
  290. row.AddCell().SetValue(v["detail"])
  291. if v["publishtime"] != nil {
  292. row.AddCell().SetValue(v["publishtime"])
  293. } else {
  294. row.AddCell()
  295. }
  296. row.AddCell().SetValue(v["href"])
  297. row.AddCell().SetValue(v["url"])
  298. row.AddCell().SetValue(v["projectname"])
  299. row.AddCell().SetValue(v["projectcode"])
  300. row.AddCell().SetValue(v["projectscope"])
  301. if v["budget"] != nil {
  302. row.AddCell().SetFloat(util.Float64All(v["budget"]))
  303. } else {
  304. row.AddCell()
  305. }
  306. if v["bidamount"] != nil {
  307. row.AddCell().SetFloat(util.Float64All(v["bidamount"]))
  308. } else {
  309. row.AddCell()
  310. }
  311. if v["signendtime"] != nil {
  312. row.AddCell().SetValue(v["signendtime"])
  313. } else {
  314. row.AddCell()
  315. }
  316. if v["bidopentime"] != nil {
  317. row.AddCell().SetValue(v["bidopentime"])
  318. } else {
  319. row.AddCell()
  320. }
  321. if v["bidendtime"] != nil {
  322. row.AddCell().SetValue(v["bidendtime"])
  323. } else {
  324. row.AddCell()
  325. }
  326. row.AddCell().SetValue(v["buyer"])
  327. row.AddCell().SetValue(v["buyerperson"])
  328. row.AddCell().SetValue(v["buyertel"])
  329. row.AddCell().SetValue(v["buyeraddr"])
  330. row.AddCell().SetValue(v["agency"])
  331. row.AddCell().SetValue(v["s_winner"])
  332. row.AddCell().SetValue(v["winnerperson"])
  333. row.AddCell().SetValue(v["winnertel"])
  334. row.AddCell().SetValue(v["legal_person"])
  335. row.AddCell().SetValue(v["company_phone"])
  336. row.AddCell().SetValue(v["company_email"])
  337. }
  338. xf.Sheets = xf.Sheets[1:2]
  339. xf.Sheets[0].Name = "数据导出"
  340. //生文件
  341. t := strconv.FormatInt(time.Now().Unix(), 10)
  342. entIds := strconv.Itoa(entId)
  343. entUserIds := strconv.Itoa(entUserId)
  344. dir := filePath + "/entsearchexport/" + entIds + "_" + entUserIds + "_" + t + "/"
  345. if b, _ := PathExists(dir); !b {
  346. err1 := os.MkdirAll(dir, os.ModePerm)
  347. if err1 != nil {
  348. log.Println("mkdir err", dir)
  349. }
  350. }
  351. fname := entIds + "_" + entUserIds + "_" + "entdataexport.xlsx"
  352. download_url := "/entsearchexport/" + entIds + "_" + entUserIds + "_" + t + "/" + fname
  353. err = xf.Save(dir + fname)
  354. if err != nil {
  355. log.Println("xls error", fname)
  356. return ""
  357. }
  358. return download_url
  359. }
  360. func PathExists(path string) (bool, error) {
  361. _, err := os.Stat(path)
  362. if err == nil {
  363. return true, nil
  364. }
  365. if os.IsNotExist(err) {
  366. return false, nil
  367. }
  368. return false, err
  369. }
  370. func SaveExportLog(mysqlSess *mysql.Mysql, entId, entUserId, count, newCount, remain_nums, export_nums int, xlsxUrl, types, filterStr string, exportPhone, exportEmail string) {
  371. query := map[string]interface{}{
  372. "id": entUserId,
  373. "ent_id": entId,
  374. }
  375. set := map[string]interface{}{
  376. "remain_nums": remain_nums - newCount,
  377. "export_nums": export_nums + newCount,
  378. }
  379. ok := mysqlSess.Update("entniche_export_limit", map[string]interface{}{"ent_id": entId, "user_id": entUserId}, set)
  380. if !ok {
  381. log.Println("修改导出条数失败", query, remain_nums, newCount)
  382. }
  383. userData := mysqlSess.FindOne("entniche_user", query, "name,phone", "")
  384. if userData != nil {
  385. name := util.ObjToString((*userData)["name"])
  386. phone := util.ObjToString((*userData)["phone"])
  387. now := time.Now()
  388. mysqlSess.Insert("entniche_export_log", map[string]interface{}{
  389. "user_name": name,
  390. "export_time": FormatDate(&now, Date_Full_Layout),
  391. "data_source": "2",
  392. "export_num": count,
  393. "deduct_num": newCount,
  394. "download_url": xlsxUrl,
  395. "ent_id": entId,
  396. "phone": phone,
  397. "user_id": entUserId,
  398. "filter": filterStr,
  399. "export_phone": exportPhone,
  400. "export_mail": exportEmail,
  401. })
  402. }
  403. }
  404. func DeductNum(m *mysql.Mysql, qyfw mongodb.MongodbSim, entId, newCount int) {
  405. query := map[string]interface{}{
  406. "id": entId,
  407. }
  408. userData := m.FindOne("entniche_info", query, "name,phone", "")
  409. if userData != nil {
  410. name := util.ObjToString((*userData)["name"])
  411. phone := util.ObjToString((*userData)["phone"])
  412. qyfw.Update("user", map[string]interface{}{"phone": phone, "username": name}, map[string]interface{}{
  413. "$inc": map[string]interface{}{
  414. "plan.current": -newCount,
  415. },
  416. }, false, false)
  417. }
  418. }
  419. func GetCurrentCount(m *mysql.Mysql, qyfw mongodb.MongodbSim, entId int) int {
  420. count := 0
  421. userData := m.FindOne("entniche_info", map[string]interface{}{"id": entId}, "name,phone", "")
  422. if userData == nil {
  423. return count
  424. }
  425. current, ok := qyfw.FindOne("user", map[string]interface{}{"phone": util.ObjToString((*userData)["phone"]), "username": util.ObjToString((*userData)["name"])})
  426. if current == nil || !ok {
  427. return count
  428. }
  429. plan, _ := (*current)["plan"].(map[string]interface{})
  430. count = util.IntAll(plan["current"])
  431. return count
  432. }