private_service.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. package service
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io/ioutil"
  6. "log"
  7. "net/http"
  8. "os"
  9. qu "qfw/util"
  10. gm "qfw/util/mail"
  11. "qfw/util/redis"
  12. "regexp"
  13. "strings"
  14. "time"
  15. "unicode/utf8"
  16. . "util"
  17. "github.com/go-xweb/xweb"
  18. "github.com/tealeg/xlsx"
  19. "gopkg.in/mgo.v2/bson"
  20. )
  21. var (
  22. phonereg *regexp.Regexp = regexp.MustCompile(`0?(13|14|15|17|18|19)[0-9]{9}`)
  23. telreg *regexp.Regexp = regexp.MustCompile(`[0-9-()()]{7,18}`)
  24. emailreg *regexp.Regexp = regexp.MustCompile(`\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}`)
  25. pre *regexp.Regexp = regexp.MustCompile("https://www.jianyu360.com/article/content/")
  26. suf *regexp.Regexp = regexp.MustCompile("(.html).*")
  27. )
  28. type Private struct {
  29. *xweb.Action
  30. keydatademo xweb.Mapper `xweb:"/private/keydatademo/(.*)"` //加密串
  31. keydataoption xweb.Mapper `xweb:"/private/keydataoption/(.*)"` //加密串
  32. }
  33. func (f *Private) Keydatademo(world string) {
  34. tmp := make(map[string]interface{})
  35. destr := SEPreview.DecodeString(world)
  36. typeStr := f.GetString("type")
  37. qu.Debug(destr)
  38. if len(destr) > 10 {
  39. var tagfield *map[string]interface{}
  40. if typeStr == "private" {
  41. tagfield, _ = Mgo.FindOne("entniche_rule", bson.M{"s_dataid": world})
  42. customer := JyMysql.FindOne("entniche_info", map[string]interface{}{"id": qu.IntAll((*tagfield)["entId"])}, "name", "")
  43. (*tagfield)["s_customer"] = (*customer)["name"]
  44. }
  45. entId := qu.IntAll((*tagfield)["entId"])
  46. entUserId := qu.IntAll((*tagfield)["entUserId"])
  47. dataConfig, _ := Mgo.FindOne("datatag_export_config", map[string]interface{}{"ent_id": entId})
  48. current := GetCurrentCount2(entId, entUserId)
  49. log.Println("数据余额", current)
  50. tmp["current"] = current
  51. if (*tagfield) != nil && len(*tagfield) > 0 {
  52. if qu.IntAll((*dataConfig)["dataType"]) == Standard {
  53. tmp["fieldtype"] = Standardstr
  54. } else if qu.IntAll((*dataConfig)["dataType"]) == Advanced {
  55. tmp["fieldtype"] = Advancedstr
  56. } else {
  57. f.ServeJson(map[string]string{
  58. "err": "参数失效",
  59. })
  60. return
  61. }
  62. tmp["fields"] = (*dataConfig)["fields"]
  63. tmp["total"] = qu.Int64All((*tagfield)["i_estotal"])
  64. tmp["customername"] = qu.ObjToString((*tagfield)["s_customer"])
  65. datas, _ := Mgo.Find("tagsdata", bson.M{"s_dataid": world}, `{"publishtime":-1}`, nil, false, -1, -1)
  66. if (*datas) != nil && len(*datas) > 0 {
  67. matchskey := make(map[string]bool)
  68. rdata := make([]map[string]interface{}, 0)
  69. for _, v := range *datas {
  70. for _, mv := range strings.Split(qu.ObjToString(v["s_matchkey"]), ",") {
  71. matchskey[mv] = true
  72. }
  73. delete(v, "_id")
  74. delete(v, "s_dataid")
  75. delete(v, "i_createtime")
  76. if v["bidamount"] != nil {
  77. v["bidamount"] = qu.Float64All(fmt.Sprintf("%f", qu.Float64All(v["bidamount"])))
  78. }
  79. if v["budget"] != nil {
  80. v["budget"] = qu.Float64All(fmt.Sprintf("%f", qu.Float64All(v["budget"])))
  81. }
  82. if v["publishtime"] != nil {
  83. v["publishtime"] = time.Unix(qu.Int64All(v["publishtime"]), 0).Format("2006-01-02")
  84. }
  85. if v["bidopentime"] != nil {
  86. v["bidopentime"] = time.Unix(qu.Int64All(v["bidopentime"]), 0).Format("2006-01-02")
  87. }
  88. if v["bidendtime"] != nil {
  89. v["bidendtime"] = time.Unix(qu.Int64All(v["bidendtime"]), 0).Format("2006-01-02 15:04:05")
  90. }
  91. if utf8.RuneCountInString(qu.ObjToString(v["title"])) > 60 {
  92. title := string([]rune(qu.ObjToString(v["title"]))[:60])
  93. v["title"] = title + "..."
  94. }
  95. if utf8.RuneCountInString(qu.ObjToString(v["detail"])) > 150 {
  96. detail := string([]rune(qu.ObjToString(v["detail"]))[:150])
  97. v["detail"] = detail + "..."
  98. }
  99. if qu.Int64All((*tagfield)["i_extfieldstype"]) == Advanced {
  100. legal_person := strings.TrimSpace(qu.ObjToString(v["legal_person"]))
  101. if utf8.RuneCountInString(legal_person) > 1 {
  102. legal_person := []rune(legal_person)
  103. v["legal_person"] = string(legal_person[:1]) + "**"
  104. }
  105. cemail := strings.TrimSpace(qu.ObjToString(v["company_email"]))
  106. if emailreg.MatchString(cemail) {
  107. v["company_email"] = "********" + cemail[strings.Index(cemail, "@"):]
  108. } else {
  109. v["company_email"] = ""
  110. }
  111. company_phone := strings.TrimSpace(qu.ObjToString(v["company_phone"]))
  112. if telreg.MatchString(company_phone) || phonereg.MatchString(company_phone) {
  113. company_phone = company_phone[:len(company_phone)-5] + "****"
  114. v["company_phone"] = company_phone
  115. } else {
  116. v["company_phone"] = ""
  117. }
  118. }
  119. if v["filehref"] != nil {
  120. if filehrefs, ok := v["filehref"].([]map[string]interface{}); ok {
  121. urlArr := []string{}
  122. for _, href := range filehrefs {
  123. url := qu.ObjToString(href["url"])
  124. urlArr = append(urlArr, url)
  125. }
  126. v["filehref"] = strings.Join(urlArr, ",")
  127. } else if filehrefs, ok := v["filehref"].([]interface{}); ok {
  128. urlArr := []string{}
  129. for _, href := range filehrefs {
  130. if hrefs, oks := href.(map[string]interface{}); oks {
  131. url := qu.ObjToString(hrefs["url"])
  132. urlArr = append(urlArr, url)
  133. }
  134. }
  135. v["filehref"] = strings.Join(urlArr, ",")
  136. }
  137. }
  138. deletefields(qu.IntAll((*tagfield)["i_extfieldstype"]), &v)
  139. rdata = append(rdata, v)
  140. }
  141. tmp["keylist"] = []string{}
  142. for k := range matchskey {
  143. if k == "" {
  144. continue
  145. }
  146. tmp["keylist"] = append(tmp["keylist"].([]string), k)
  147. }
  148. tmp["data"] = rdata
  149. }
  150. }
  151. }
  152. f.ServeJson(tmp)
  153. }
  154. func (f *Private) Keydataoption(world string) {
  155. // destr := qu.SE.DecodeString(world)
  156. tmp := make(map[string]interface{})
  157. idMap := make(map[string]bool)
  158. infoArr := []map[string]interface{}{}
  159. bytes := f.Body()
  160. err := json.Unmarshal(bytes, &tmp)
  161. newCount := 0
  162. datas, _ := Mgo.FindOne("entniche_rule", bson.M{"s_dataid": world})
  163. entId := qu.IntAll((*datas)["entId"])
  164. entUserId := qu.IntAll((*datas)["entUserId"])
  165. dataConfig, _ := Mgo.FindOne("datatag_export_config", map[string]interface{}{"ent_id": entId})
  166. current := GetCurrentCount2(entId, entUserId)
  167. userData := JyMysql.FindOne("entniche_user", map[string]interface{}{"id": entUserId}, "phone", "")
  168. phone := ""
  169. if userData != nil && len(*userData) > 0 {
  170. phone = qu.ObjToString((*userData)["phone"])
  171. }
  172. log.Println("数据余额", current)
  173. filterStr := ""
  174. isFirst := tmp["isFirst"].(bool)
  175. newIdArr := []string{}
  176. if err == nil {
  177. if idArr, ok := tmp["urls"].([]interface{}); ok {
  178. // idsArr := []string{}
  179. for _, v := range idArr {
  180. // idsArr = append(idsArr, v.(string))
  181. idMap[v.(string)] = true
  182. }
  183. // filterStr = strings.Join(idsArr, ",")
  184. }
  185. res, ok := Mgo.Find("tagsdata", bson.M{"s_dataid": world}, `{"publishtime":-1}`, nil, false, -1, -1)
  186. if ok && res != nil && *res != nil && len(*res) > 0 {
  187. for _, v := range *res {
  188. infoid := qu.ObjToString(v["info_id"])
  189. if idMap[infoid] {
  190. isExist, err := redis.Exists("export", "entexportdata_"+infoid+"_"+fmt.Sprintln(entId))
  191. if err != nil {
  192. log.Println("企业订阅数据导出redis判重失败")
  193. } else if isExist {
  194. log.Println("数据重复,id ", infoid, "entid ", entId, "userid ", entUserId)
  195. } else {
  196. newCount++
  197. }
  198. if !isFirst {
  199. v["id"] = infoid
  200. v["jybxhref"] = v["s_jyhref"]
  201. v["createtime"] = time.Now().Unix()
  202. v["phone"] = phone
  203. delete(v, "_id")
  204. newIdArr = append(newIdArr, infoid)
  205. }
  206. infoArr = append(infoArr, v)
  207. }
  208. }
  209. }
  210. }
  211. log.Println("数据量", len(infoArr))
  212. log.Println("新导出", newCount)
  213. isExport := true
  214. if newCount > current {
  215. isExport = false
  216. } else {
  217. go func() {
  218. for _, v := range newIdArr {
  219. redis.Put("export", "entexportdata_"+v+"_"+fmt.Sprintln(entId), 1, -1)
  220. }
  221. }()
  222. }
  223. res := map[string]interface{}{
  224. "count": len(infoArr),
  225. "newCount": newCount,
  226. "current": current,
  227. "isExport": isExport,
  228. }
  229. if !isFirst {
  230. if len(infoArr) > 0 {
  231. fields := []map[string]interface{}{}
  232. dataType := qu.IntAll((*dataConfig)["dataType"])
  233. if (*dataConfig)["fields"] != nil {
  234. fieldsArr := qu.ObjArrToMapArr((*dataConfig)["fields"].([]interface{}))
  235. fields = fieldsArr
  236. }
  237. s_name := qu.ObjToString((*datas)["s_name"])
  238. xlsxUrl := GetXlsxfile(infoArr, dataType, s_name, fields)
  239. log.Println("生成完成", xlsxUrl)
  240. exportId := SaveExportLog2(entId, entUserId, len(infoArr), newCount, xlsxUrl, "1", filterStr)
  241. DeductNum2(entId, newCount, entUserId, exportId)
  242. go func() {
  243. for k, _ := range infoArr {
  244. MgoSave.Save(SaveUserMail, infoArr[k])
  245. }
  246. }()
  247. res["xlsxUrl"] = xlsxUrl
  248. }
  249. }
  250. f.ServeJson(res)
  251. }
  252. func GetXlsxfile(mMap []map[string]interface{}, dataType int, fn string, fields []map[string]interface{}) string {
  253. xf, err := xlsx.OpenFile("web/res/fields.xlsx")
  254. if err != nil {
  255. log.Println("fields file not foud", err.Error())
  256. }
  257. style := xlsx.NewStyle()
  258. style.Font.Size = 12
  259. style.Font.Bold = true
  260. style.Alignment.Vertical = "center"
  261. style.Alignment.Horizontal = "center"
  262. if dataType == 1 {
  263. sh := xf.Sheets[0]
  264. if len(fields) > 0 {
  265. for _, v := range fields {
  266. for _, vv := range v {
  267. cell := sh.Rows[0].AddCell()
  268. cell.SetValue(vv)
  269. cell.SetStyle(style)
  270. }
  271. }
  272. }
  273. for i, v := range mMap {
  274. row := sh.AddRow()
  275. row.AddCell().SetInt(i + 1)
  276. row.AddCell().SetValue(v["s_matchkey"])
  277. row.AddCell().SetValue(v["area"])
  278. row.AddCell().SetValue(v["city"])
  279. row.AddCell().SetValue(v["title"])
  280. row.AddCell().SetValue(v["subtype"])
  281. if v["publishtime"] != nil {
  282. row.AddCell().SetValue(time.Unix(qu.Int64All(v["publishtime"]), 0).Format("2006-01-02"))
  283. } else {
  284. row.AddCell()
  285. }
  286. row.AddCell().SetValue(v["buyer"])
  287. row.AddCell().SetValue(v["winner"])
  288. if v["bidamount"] != nil {
  289. row.AddCell().SetFloat(qu.Float64All(v["bidamount"]))
  290. } else {
  291. row.AddCell()
  292. }
  293. row.AddCell().SetValue(v["projectname"])
  294. row.AddCell().SetValue(v["detail"])
  295. row.AddCell().SetValue(v["jybxhref"])
  296. ids := SE.EncodeString(qu.ObjToString(v["id"]))
  297. row.AddCell().SetValue(ids)
  298. if len(fields) > 0 {
  299. for _, vv := range fields {
  300. for kk, _ := range vv {
  301. if v[kk] != nil {
  302. if kk == "filehref" {
  303. if filehrefs, ok := v["filehref"].([]interface{}); ok {
  304. urlArr := ""
  305. for _, href := range filehrefs {
  306. if hrefs, oks := href.(map[string]interface{}); oks {
  307. url := qu.ObjToString(hrefs["url"]) + "\n"
  308. urlArr += url
  309. }
  310. }
  311. row.AddCell().SetValue(urlArr)
  312. }
  313. } else if kk == "bidopentime" || kk == "bidendtime" {
  314. row.AddCell().SetValue(time.Unix(qu.Int64All(v[kk]), 0).Format("2006-01-02"))
  315. } else {
  316. row.AddCell().SetValue(v[kk])
  317. }
  318. } else {
  319. row.AddCell()
  320. }
  321. }
  322. }
  323. }
  324. }
  325. xf.Sheets = xf.Sheets[0:1]
  326. } else if dataType == 2 {
  327. sh := xf.Sheets[1]
  328. if len(fields) > 0 {
  329. for _, v := range fields {
  330. for _, vv := range v {
  331. cell := sh.Rows[0].AddCell()
  332. cell.SetValue(vv)
  333. cell.SetStyle(style)
  334. }
  335. }
  336. }
  337. for _, v := range mMap {
  338. row := sh.AddRow()
  339. row.AddCell().SetValue(v["s_matchkey"])
  340. row.AddCell().SetValue(v["area"])
  341. row.AddCell().SetValue(v["city"])
  342. row.AddCell().SetValue(v["title"])
  343. row.AddCell().SetValue(v["subtype"])
  344. row.AddCell().SetValue(v["detail"])
  345. if v["publishtime"] != nil {
  346. row.AddCell().SetValue(time.Unix(qu.Int64All(v["publishtime"]), 0).Format("2006-01-02"))
  347. } else {
  348. row.AddCell()
  349. }
  350. row.AddCell().SetValue(v["href"])
  351. row.AddCell().SetValue(v["jybxhref"])
  352. row.AddCell().SetValue(v["projectname"])
  353. row.AddCell().SetValue(v["projectcode"])
  354. row.AddCell().SetValue(v["projectscope"])
  355. if v["budget"] != nil {
  356. row.AddCell().SetFloat(qu.Float64All(v["budget"]))
  357. } else {
  358. row.AddCell()
  359. }
  360. if v["bidamount"] != nil {
  361. row.AddCell().SetFloat(qu.Float64All(v["bidamount"]))
  362. } else {
  363. row.AddCell()
  364. }
  365. if v["bidopentime"] != nil {
  366. row.AddCell().SetValue(time.Unix(qu.Int64All(v["bidopentime"]), 0).Format("2006-01-02"))
  367. } else {
  368. row.AddCell()
  369. }
  370. row.AddCell().SetValue(v["buyer"])
  371. row.AddCell().SetValue(v["buyerperson"])
  372. row.AddCell().SetValue(v["buyertel"])
  373. row.AddCell().SetValue(v["agency"])
  374. row.AddCell().SetValue(v["s_winner"])
  375. row.AddCell().SetValue(v["winnerperson"])
  376. row.AddCell().SetValue(v["winnertel"])
  377. row.AddCell().SetValue(v["legal_person"])
  378. row.AddCell().SetValue(v["company_phone"])
  379. row.AddCell().SetValue(v["company_email"])
  380. ids := SE.EncodeString(qu.ObjToString(v["id"]))
  381. row.AddCell().SetValue(ids)
  382. if len(fields) > 0 {
  383. for _, vv := range fields {
  384. for kk, _ := range vv {
  385. if v[kk] != nil {
  386. if kk == "filehref" {
  387. if filehrefs, ok := v["filehref"].([]interface{}); ok {
  388. urlArr := ""
  389. for _, href := range filehrefs {
  390. if hrefs, oks := href.(map[string]interface{}); oks {
  391. url := qu.ObjToString(hrefs["url"]) + "\n"
  392. urlArr += url
  393. }
  394. }
  395. row.AddCell().SetValue(urlArr)
  396. }
  397. } else if kk == "bidopentime" || kk == "bidendtime" {
  398. row.AddCell().SetValue(time.Unix(qu.Int64All(v[kk]), 0).Format("2006-01-02"))
  399. } else {
  400. row.AddCell().SetValue(v[kk])
  401. }
  402. } else {
  403. row.AddCell()
  404. }
  405. }
  406. }
  407. }
  408. }
  409. xf.Sheets = xf.Sheets[1:2]
  410. }
  411. xf.Sheets[0].Name = "详细数据"
  412. //生文件
  413. //t := strconv.FormatInt(time.Now().Unix(), 10)
  414. t := time.Now().Format("20060102")
  415. dir := "./web/res/xlsx/" + t + "/"
  416. if b, _ := PathExists(dir); !b {
  417. err1 := os.MkdirAll(dir, os.ModePerm)
  418. if err1 != nil {
  419. log.Println("mkdir err", dir)
  420. }
  421. }
  422. //fname := t + ".xlsx"
  423. fname := fmt.Sprintf("%s_%s_%s.xlsx", fn, t, qu.GetRandom(4))
  424. log.Println("fname", fname)
  425. err = xf.Save(dir + fname)
  426. xlsxUrls := "/xlsx/" + t + "/" + fname
  427. return xlsxUrls
  428. }
  429. func PathExists(path string) (bool, error) {
  430. _, err := os.Stat(path)
  431. if err == nil {
  432. return true, nil
  433. }
  434. if os.IsNotExist(err) {
  435. return false, nil
  436. }
  437. return false, err
  438. }
  439. type keynum struct {
  440. Key string
  441. Num int
  442. }
  443. var gmail *gm.GmailAuth
  444. func urlToId(url string) string {
  445. url = pre.ReplaceAllString(url, "")
  446. url = suf.ReplaceAllString(url, "")
  447. return qu.CommonDecodeArticle("content", url)[0]
  448. }
  449. func deletefields(fieldnum int, data *map[string]interface{}) map[string]interface{} {
  450. rdata := make(map[string]interface{})
  451. one, _ := Mgo.FindOne("code_fields", bson.M{})
  452. if one != nil && len(*one) > 0 {
  453. for _, v := range (*one)[fmt.Sprintf("%d", fieldnum)].([]interface{}) {
  454. if (*data)[qu.ObjToString(v)] != nil {
  455. rdata[qu.ObjToString(v)] = (*data)[qu.ObjToString(v)]
  456. }
  457. }
  458. }
  459. return rdata
  460. }
  461. func sendMail(tag map[string]interface{}, option string) {
  462. jkmail, _ := Sysconfig["jkmail"].(map[string]interface{})
  463. title := "标签系统" + qu.ObjToString(tag["s_customername"]) + "反馈信息"
  464. content := "客户姓名:" + qu.ObjToString(tag["s_customername"]) + "</br>" + "标签名称:" + qu.ObjToString(tag["s_name"]) + "</br>" +
  465. "销售经理:" + qu.ObjToString(tag["s_salesperson"]) + "</br>" + "反馈内容:" + option
  466. if jkmail != nil {
  467. tomail, _ := jkmail["to"].(string)
  468. api, _ := jkmail["api"].(string)
  469. log.Println("start send", tomail, Sysconfig["jkmail"])
  470. res, err := http.Get(fmt.Sprintf("%s?to=%s&title=%s&body=%s", api, tomail, title, content))
  471. if err == nil {
  472. defer res.Body.Close()
  473. read, err := ioutil.ReadAll(res.Body)
  474. log.Println("邮件发送:", string(read), err)
  475. }
  476. }
  477. }