apply_record.go 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914
  1. package yb
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "github.com/rdlucklib/rdluck_tools/paging"
  6. "github.com/tealeg/xlsx"
  7. "hongze/hz_crm_api/controllers"
  8. "hongze/hz_crm_api/models"
  9. "hongze/hz_crm_api/models/company"
  10. "hongze/hz_crm_api/models/system"
  11. "hongze/hz_crm_api/models/yb"
  12. "hongze/hz_crm_api/models/yb/request"
  13. ybResp "hongze/hz_crm_api/models/yb/response"
  14. "hongze/hz_crm_api/services"
  15. ybService "hongze/hz_crm_api/services/yb"
  16. "hongze/hz_crm_api/utils"
  17. "os"
  18. "path/filepath"
  19. "strconv"
  20. "strings"
  21. "sync"
  22. "time"
  23. )
  24. type ApplyRecordController struct {
  25. controllers.BaseAuthController
  26. }
  27. // List
  28. // @Title 获取申请列表
  29. // @Description 获取申请列表
  30. // @Param Keyword query string false "搜索关键字 string"
  31. // @Param State query string false "用户状态 string 潜在用户/权益用户/冻结/流失"
  32. // @Success 200 {object} []yb.ApplyRecordListResp
  33. // @router /apply_record/list [get]
  34. func (this *ApplyRecordController) List() {
  35. br := new(models.BaseResponse).Init()
  36. defer func() {
  37. this.Data["json"] = br
  38. this.ServeJSON()
  39. }()
  40. sysUser := this.SysUser
  41. if sysUser == nil {
  42. br.Msg = "请登录"
  43. br.ErrMsg = "请登录,SysUser is Empty"
  44. br.Ret = 408
  45. return
  46. }
  47. pageSize, _ := this.GetInt("PageSize")
  48. currentIndex, _ := this.GetInt("CurrentIndex")
  49. var startSize int
  50. if pageSize <= 0 {
  51. pageSize = utils.PageSize20
  52. }
  53. if currentIndex <= 0 {
  54. currentIndex = 1
  55. }
  56. startSize = paging.StartIndex(currentIndex, pageSize)
  57. condition := ""
  58. pars := make([]interface{}, 0)
  59. // 数据权限
  60. condition, pars = getDataAuthWhere(condition, pars, this.SysUser)
  61. reqState := this.GetString("State", "")
  62. if reqState != "" {
  63. condition += " AND a.status = ?"
  64. pars = append(pars, reqState)
  65. }
  66. reqKeyword := this.GetString("Keyword")
  67. if reqKeyword != "" {
  68. reqKeyword = "%" + reqKeyword + "%"
  69. condition += " AND (a.real_name LIKE ? OR a.mobile LIKE ? OR a.email LIKE ?)"
  70. pars = append(pars, reqKeyword, reqKeyword, reqKeyword)
  71. }
  72. // 获取列表
  73. total, list, err := yb.GetApplyRecordList(condition, pars, startSize, pageSize)
  74. if err != nil {
  75. br.Msg = "获取申请列表失败!"
  76. br.ErrMsg = "获取申请列表失败,Err:" + err.Error()
  77. return
  78. }
  79. page := paging.GetPaging(currentIndex, pageSize, total)
  80. resp := ybResp.ApplyRecordListResp{
  81. List: list,
  82. Paging: page,
  83. }
  84. br.Ret = 200
  85. br.Success = true
  86. br.Msg = "获取成功"
  87. br.Data = resp
  88. }
  89. // getDataAuth 过滤数据权限
  90. func getDataAuthWhere(condition string, pars []interface{}, sysUser *system.Admin) (newCondition string, newPars []interface{}) {
  91. roleCode := sysUser.RoleTypeCode
  92. // 超管账户不做限制
  93. if roleCode == utils.ROLE_TYPE_CODE_ADMIN {
  94. return
  95. }
  96. // 是否为FICC角色
  97. allowRole := []string{
  98. utils.ROLE_TYPE_CODE_FICC_ADMIN, utils.ROLE_TYPE_CODE_FICC_SELLER, utils.ROLE_TYPE_CODE_FICC_GROUP,
  99. utils.ROLE_TYPE_CODE_FICC_DEPARTMENT, utils.ROLE_TYPE_CODE_FICC_RESEARCHR, utils.ROLE_TYPE_CODE_RESEARCHR,
  100. }
  101. isAllow := false
  102. for _, role := range allowRole {
  103. if roleCode == role {
  104. isAllow = true
  105. }
  106. }
  107. if isAllow {
  108. // 销售ID为当前用户且客户状态为冻结
  109. condition += " AND b.seller_id = ?"
  110. pars = append(pars, sysUser.AdminId)
  111. condition += " AND b.status = ?"
  112. pars = append(pars, "冻结")
  113. } else {
  114. condition += " AND 1=2"
  115. }
  116. newCondition = condition
  117. newPars = pars
  118. return
  119. }
  120. func getDataAuthWhereV2(condition string, pars []interface{}, sysUser *system.Admin) (newCondition string, newPars []interface{}, err error) {
  121. roleCode := sysUser.RoleTypeCode
  122. // 超管账户不做限制
  123. if roleCode == utils.ROLE_TYPE_CODE_ADMIN || roleCode == utils.ROLE_TYPE_CODE_FICC_ADMIN {
  124. return
  125. }
  126. // 是否为FICC角色
  127. allowRole := []string{
  128. utils.ROLE_TYPE_CODE_FICC_ADMIN, utils.ROLE_TYPE_CODE_FICC_SELLER, utils.ROLE_TYPE_CODE_FICC_GROUP, utils.ROLE_TYPE_CODE_FICC_TEAM,
  129. utils.ROLE_TYPE_CODE_FICC_DEPARTMENT, utils.ROLE_TYPE_CODE_FICC_RESEARCHR, utils.ROLE_TYPE_CODE_RESEARCHR,
  130. }
  131. isAllow := false
  132. for _, role := range allowRole {
  133. if roleCode == role {
  134. isAllow = true
  135. }
  136. }
  137. if isAllow {
  138. // 超管和ficc 管理员,才允许看潜在用户和流失用户,
  139. condition += ` and y.status != "潜在用户" and y.status is not null and y.status != "权益用户" and y.status != "流失"`
  140. // 如果是ficc销售主管,查询对应的小组
  141. if roleCode == utils.ROLE_TYPE_CODE_FICC_GROUP && sysUser.GroupId > 0 {
  142. subAdmins, tErr := system.GetSysUserByParentIdGroupId(sysUser.GroupId)
  143. if tErr != nil && tErr.Error() != utils.ErrNoRow() {
  144. err = tErr
  145. return
  146. }
  147. var sellerIdsStr string
  148. for _, v := range subAdmins {
  149. // 只能看比主管权限低的角色
  150. if v.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_SELLER || v.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_TEAM || v.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_RESEARCHR || v.RoleTypeCode == utils.ROLE_TYPE_CODE_RESEARCHR {
  151. sellerIdsStr += strconv.Itoa(v.AdminId) + ","
  152. }
  153. }
  154. if sellerIdsStr != "" {
  155. sellerIdsStr += strconv.Itoa(sysUser.AdminId)
  156. // 销售ID为当前用户且客户状态为冻结
  157. condition += " AND bp.seller_id in (" + sellerIdsStr + ")"
  158. } else {
  159. condition += " AND bp.seller_id = ?"
  160. pars = append(pars, sysUser.AdminId)
  161. }
  162. } else if roleCode == utils.ROLE_TYPE_CODE_FICC_TEAM && sysUser.GroupId > 0 { // 如果是ficc 销售组长
  163. subAdmins, tErr := system.GetAdminByGroupId(sysUser.GroupId)
  164. if tErr != nil && tErr.Error() != utils.ErrNoRow() {
  165. err = tErr
  166. return
  167. }
  168. var sellerIdsStr string
  169. for _, v := range subAdmins {
  170. // 只能看比主管权限低的角色
  171. if v.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_SELLER || v.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_RESEARCHR || v.RoleTypeCode == utils.ROLE_TYPE_CODE_RESEARCHR {
  172. sellerIdsStr += strconv.Itoa(v.AdminId) + ","
  173. }
  174. }
  175. if sellerIdsStr != "" {
  176. sellerIdsStr += strconv.Itoa(sysUser.AdminId)
  177. // 销售ID为当前用户且客户状态为冻结
  178. condition += " AND bp.seller_id in (" + sellerIdsStr + ")"
  179. } else {
  180. condition += " AND bp.seller_id = ?"
  181. pars = append(pars, sysUser.AdminId)
  182. }
  183. } else { // 如果是ficc 销售
  184. condition += " AND bp.seller_id = ?"
  185. pars = append(pars, sysUser.AdminId)
  186. }
  187. } else {
  188. condition += " AND 1=2"
  189. }
  190. newCondition = condition
  191. newPars = pars
  192. return
  193. }
  194. // MarkHandle
  195. // @Title 处理申请记录
  196. // @Description 处理申请记录
  197. // @Param request body request.ApplyMarkReq true "type json string"
  198. // @Success 200 {object} 标记处理成功
  199. // @router /apply_record/mark_handle [post]
  200. func (this *ApplyRecordController) MarkHandle() {
  201. br := new(models.BaseResponse).Init()
  202. defer func() {
  203. this.Data["json"] = br
  204. this.ServeJSON()
  205. }()
  206. sysUser := this.SysUser
  207. if sysUser == nil {
  208. br.Msg = "请登录"
  209. br.ErrMsg = "请登录,SysUser is Empty"
  210. br.Ret = 408
  211. return
  212. }
  213. var req request.ApplyMarkReq
  214. err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
  215. if err != nil {
  216. br.Msg = "参数解析异常"
  217. br.ErrMsg = "参数解析失败,Err:" + err.Error()
  218. return
  219. }
  220. if req.ApplyRecordId <= 0 && req.UserId <= 0 {
  221. br.Msg = "申请记录ID或者用户ID异常"
  222. br.ErrMsg = "申请记录ID或者用户ID异常"
  223. return
  224. }
  225. // 标记处理
  226. err = ybService.MarkApplyRecord(req.ApplyRecordId, this.SysUser.AdminId, req.UserId)
  227. if err != nil {
  228. br.Msg = "标记处理失败! "
  229. br.ErrMsg = "标记处理失败,Err:" + err.Error()
  230. return
  231. }
  232. br.Ret = 200
  233. br.Success = true
  234. br.Msg = "标记处理成功"
  235. }
  236. // ListV2
  237. // @Title 获取用户申请列表
  238. // @Description 获取用户申请列表
  239. // @Param KeyWord query string false "搜索关键字 string"
  240. // @Param States query string false "用户状态 string 潜在用户/权益用户/冻结/流失"
  241. // @Success 200 {object} []yb.ApplyRecordListRespV2
  242. // @router /apply_record/listV2 [get]
  243. func (this *ApplyRecordController) UserApplyList() {
  244. br := new(models.BaseResponse).Init()
  245. defer func() {
  246. this.Data["json"] = br
  247. this.ServeJSON()
  248. }()
  249. sysUser := this.SysUser
  250. if sysUser == nil {
  251. br.Msg = "请登录"
  252. br.ErrMsg = "请登录,SysUser is Empty"
  253. br.Ret = 408
  254. return
  255. }
  256. pageSize, _ := this.GetInt("PageSize")
  257. currentIndex, _ := this.GetInt("CurrentIndex")
  258. var startSize int
  259. if pageSize <= 0 {
  260. pageSize = utils.PageSize20
  261. }
  262. if currentIndex <= 0 {
  263. currentIndex = 1
  264. }
  265. startSize = paging.StartIndex(currentIndex, pageSize)
  266. condition := ""
  267. pars := make([]interface{}, 0)
  268. // 数据权限
  269. condition, pars, err := getDataAuthWhereV2(condition, pars, this.SysUser)
  270. if err != nil {
  271. br.Msg = "权限查询出错"
  272. br.ErrMsg = "权限查询出错:" + err.Error()
  273. return
  274. }
  275. reqState := this.GetString("States", "")
  276. if reqState != "" {
  277. statusSlice := strings.Split(reqState, ",")
  278. conditionSub := ""
  279. if len(statusSlice) == 0 {
  280. br.Msg = "入参:状态格式出错"
  281. return
  282. }
  283. for _, v := range statusSlice {
  284. if v == "潜在用户" {
  285. conditionSub += ` or y.status = "潜在用户" or y.status is null or y.status = "权益用户"`
  286. } else {
  287. conditionSub += ` or y.status = "` + v + `"`
  288. }
  289. }
  290. conditionSubByte := []byte(conditionSub)
  291. conditionSub = string(conditionSubByte[4:])
  292. condition += ` AND (` + conditionSub + `)`
  293. }
  294. reqKeyword := this.GetString("KeyWord")
  295. if reqKeyword != "" {
  296. reqKeyword = "%" + reqKeyword + "%"
  297. condition += " AND (a.real_name LIKE ? OR a.mobile LIKE ? OR a.email LIKE ? OR (a.company_id > 1 AND b.company_name LIKE ?) OR (a.company_id = 1 AND a.note LIKE ?))"
  298. pars = append(pars, reqKeyword, reqKeyword, reqKeyword, reqKeyword, reqKeyword)
  299. }
  300. reqApplyStatus := this.GetString("ApplyStatus")
  301. if reqApplyStatus != "" {
  302. if reqApplyStatus == "已申请" {
  303. condition += " AND y.apply_record_id > 0"
  304. } else if reqApplyStatus == "未申请" {
  305. condition += " AND ISNULL(y.apply_record_id) = 1"
  306. }
  307. }
  308. // 获取列表
  309. w := sync.WaitGroup{}
  310. var list []*yb.ApplyListV2
  311. var total int
  312. startTime := "2022-01-01"
  313. w.Add(1)
  314. go func() {
  315. defer w.Done()
  316. list, err = yb.GetApplyRecordListV2(condition, pars, startTime, startSize, pageSize)
  317. }()
  318. if err != nil {
  319. br.Msg = "获取申请列表失败!"
  320. br.ErrMsg = "获取申请列表失败,Err:" + err.Error()
  321. return
  322. }
  323. w.Add(1)
  324. go func() {
  325. defer w.Done()
  326. total, err = yb.GetApplyRecordTotal(condition, pars, startTime)
  327. }()
  328. w.Wait()
  329. if err != nil {
  330. br.Msg = "获取申请列表总数失败!"
  331. br.ErrMsg = "获取申请列表总数失败,Err:" + err.Error()
  332. return
  333. }
  334. mobilesSlice := make([]string, 0)
  335. emailsSlice := make([]string, 0)
  336. userIdsStr := ""
  337. for _, v := range list {
  338. userIdsStr += "," + strconv.Itoa(v.UserId)
  339. if v.Mobile != "" {
  340. mobilesSlice = append(mobilesSlice, v.Mobile)
  341. } else if v.Email != "" {
  342. emailsSlice = append(emailsSlice, v.Email)
  343. }
  344. }
  345. //统计申请数
  346. userApplyTotalMap := make(map[int]int)
  347. if userIdsStr != "" {
  348. userIdsStr = strings.Trim(userIdsStr, ",")
  349. userApplyTotal, tErr := yb.GetTotalByUserIds(userIdsStr)
  350. if tErr != nil {
  351. br.Msg = "获取申请数失败!"
  352. br.ErrMsg = "获取申请数失败,Err:" + tErr.Error()
  353. return
  354. }
  355. for _, v := range userApplyTotal {
  356. userApplyTotalMap[v.UserId] = v.Total
  357. }
  358. }
  359. w2 := sync.WaitGroup{}
  360. mobileTotalMap := make(map[string]int)
  361. lastTimeMobileMap := make(map[string]time.Time)
  362. w2.Add(1)
  363. //统计阅读数
  364. go func() {
  365. defer w2.Done()
  366. mobileTotalMap, lastTimeMobileMap = ybService.GetUserViewTotalByMobiles(mobilesSlice)
  367. }()
  368. emailTotalMap := make(map[string]int)
  369. lastTimeEmailMap := make(map[string]time.Time)
  370. w2.Add(1)
  371. go func() {
  372. defer w2.Done()
  373. emailTotalMap, lastTimeEmailMap = ybService.GetUserViewTotalByEmails(emailsSlice)
  374. }()
  375. w2.Wait()
  376. for k, v := range list {
  377. sourceStr := ""
  378. if v.ApplyRecordId > 0 {
  379. if v.SourceAgent == 3 {
  380. sourceStr = "弘则研究"
  381. } else if v.SourceAgent == 1 {
  382. switch v.Source {
  383. case 1:
  384. sourceStr = "我的(小程序)"
  385. case 2:
  386. sourceStr = "活动(小程序)"
  387. case 3:
  388. sourceStr = "图库(小程序)"
  389. case 4:
  390. sourceStr = "研报(小程序)"
  391. case 5:
  392. sourceStr = "问答社区(小程序)"
  393. default:
  394. if v.FromPage != "" {
  395. sourceStr = v.FromPage + "(小程序)"
  396. } else {
  397. sourceStr = "研报(小程序)"
  398. }
  399. }
  400. } else if v.SourceAgent == 2 || v.SourceAgent == 4 {
  401. switch v.Source {
  402. case 1:
  403. sourceStr = "我的(PC端)"
  404. case 2:
  405. sourceStr = "活动(PC端)"
  406. case 3:
  407. sourceStr = "图库(PC端)"
  408. case 4:
  409. sourceStr = "研报(PC端)"
  410. case 5:
  411. sourceStr = "问答社区(PC端)"
  412. default:
  413. if v.FromPage != "" {
  414. sourceStr = v.FromPage + "(PC端)"
  415. } else {
  416. sourceStr = "研报(PC端)"
  417. }
  418. }
  419. }
  420. } else if v.RegisterSource != 0 {
  421. switch v.RegisterSource {
  422. case 1:
  423. sourceStr = "弘则研究"
  424. case 2:
  425. sourceStr = "研报(PC端)"
  426. case 5:
  427. sourceStr = "活动(小程序)"
  428. case 6:
  429. sourceStr = "研报(小程序)"
  430. default:
  431. sourceStr = ""
  432. }
  433. }
  434. list[k].SourceStr = sourceStr
  435. // 统计申请数
  436. if applyTotal, ok := userApplyTotalMap[v.UserId]; ok {
  437. list[k].ApplyTotal = applyTotal
  438. }
  439. //统计阅读数
  440. if num, ok := mobileTotalMap[v.Mobile]; ok {
  441. list[k].ViewTotal += num
  442. }
  443. if num, ok := emailTotalMap[v.Email]; ok {
  444. list[k].ViewTotal += num
  445. }
  446. //最新阅读时间
  447. if t, ok := lastTimeMobileMap[v.Mobile]; ok {
  448. if list[k].LastViewTime.Before(t) {
  449. list[k].LastViewTime = t
  450. }
  451. }
  452. if t, ok := lastTimeEmailMap[v.Email]; ok {
  453. if list[k].LastViewTime.Before(t) {
  454. list[k].LastViewTime = t
  455. }
  456. }
  457. list[k].LastViewTimeStr = list[k].LastViewTime.Format(utils.FormatDateTime)
  458. if list[k].LastViewTimeStr == "0001-01-01 00:00:00" {
  459. list[k].LastViewTimeStr = ""
  460. }
  461. list[k].LastTimeStr = list[k].LastTime.Format(utils.FormatDateTime)
  462. if v.Status == "权益用户" {
  463. list[k].Status = "潜在用户"
  464. }
  465. //查询是否展示潜在用户删除按钮权限
  466. if v.CompanyId == 1 && list[k].Status == "潜在用户" {
  467. list[k].DelBtn = true
  468. }
  469. }
  470. page := paging.GetPaging(currentIndex, pageSize, total)
  471. resp := ybResp.ApplyRecordListV2Resp{
  472. List: list,
  473. Paging: page,
  474. }
  475. br.Ret = 200
  476. br.Success = true
  477. br.Msg = "获取成功"
  478. br.Data = resp
  479. }
  480. // ApplyExport
  481. // @Title 导出用户申请列表
  482. // @Description 导出用户申请列表
  483. // @Param KeyWord query string false "搜索关键字 string"
  484. // @Param State query string false "用户状态 string 潜在用户/权益用户/冻结/流失"
  485. // @Success Ret=200 导出成功
  486. // @router /apply_record/listV2/export [get]
  487. func (this *ApplyRecordController) ApplyExport() {
  488. br := new(models.BaseResponse).Init()
  489. defer func() {
  490. this.Data["json"] = br
  491. this.ServeJSON()
  492. }()
  493. reqKeyword := this.GetString("KeyWord")
  494. reqState := this.GetString("States")
  495. sysUser := this.SysUser
  496. if sysUser == nil {
  497. br.Msg = "请登录"
  498. br.ErrMsg = "请登录,SysUser Is Empty"
  499. br.Ret = 408
  500. return
  501. }
  502. //管理员才让导出数据
  503. if sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_ADMIN && sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_FICC_ADMIN {
  504. br.Msg = "没有权限"
  505. br.ErrMsg = "没有权限"
  506. return
  507. }
  508. var condition string
  509. var pars []interface{}
  510. if reqState != "" {
  511. statusSlice := strings.Split(reqState, ",")
  512. conditionSub := ""
  513. if len(statusSlice) == 0 {
  514. br.Msg = "入参:状态格式出错"
  515. return
  516. }
  517. for _, v := range statusSlice {
  518. if v == "潜在用户" {
  519. conditionSub += ` or y.status = "潜在用户" or y.status is null or y.status = "权益用户"`
  520. } else {
  521. conditionSub += ` or y.status = "` + v + `"`
  522. }
  523. }
  524. conditionSubByte := []byte(conditionSub)
  525. conditionSub = string(conditionSubByte[4:])
  526. condition += ` AND (` + conditionSub + `)`
  527. }
  528. if reqKeyword != "" {
  529. reqKeyword = "%" + reqKeyword + "%"
  530. condition += " AND (a.real_name LIKE ? OR a.mobile LIKE ? OR a.email LIKE ? OR (a.company_id > 1 AND b.company_name LIKE ?) OR (a.company_id = 1 AND a.note LIKE ?))"
  531. pars = append(pars, reqKeyword, reqKeyword, reqKeyword, reqKeyword, reqKeyword)
  532. }
  533. reqApplyStatus := this.GetString("ApplyStatus")
  534. if reqApplyStatus != "" {
  535. if reqApplyStatus == "已申请" {
  536. condition += " AND y.apply_record_id > 0"
  537. } else if reqApplyStatus == "未申请" {
  538. condition += " AND y.apply_record_id is null"
  539. }
  540. }
  541. startTime := "2022-01-01"
  542. list, err := yb.GetApplyRecordListV2Export(condition, pars, startTime)
  543. if err != nil {
  544. br.Msg = "获取失败"
  545. br.ErrMsg = "获取失败,Err:" + err.Error()
  546. return
  547. }
  548. mobilesSlice := make([]string, 0)
  549. emailsSlice := make([]string, 0)
  550. userIdsStr := ""
  551. for _, v := range list {
  552. userIdsStr += "," + strconv.Itoa(v.UserId)
  553. if v.Mobile != "" {
  554. mobilesSlice = append(mobilesSlice, v.Mobile)
  555. } else if v.Email != "" {
  556. emailsSlice = append(emailsSlice, v.Email)
  557. }
  558. }
  559. userIdsStr = strings.Trim(userIdsStr, ",")
  560. //统计申请数
  561. userApplyTotalMap := make(map[int]int)
  562. if userIdsStr != "" {
  563. userApplyTotal, err := yb.GetTotalByUserIds(userIdsStr)
  564. if err != nil {
  565. br.Msg = "获取申请数失败!"
  566. br.ErrMsg = "获取申请数失败,Err:" + err.Error()
  567. return
  568. }
  569. for _, v := range userApplyTotal {
  570. userApplyTotalMap[v.UserId] = v.Total
  571. }
  572. }
  573. w := sync.WaitGroup{}
  574. mobileTotalMap := make(map[string]int)
  575. lastTimeMobileMap := make(map[string]time.Time)
  576. w.Add(1)
  577. //统计阅读数
  578. go func() {
  579. defer w.Done()
  580. mobileTotalMap, lastTimeMobileMap = ybService.GetUserViewTotalByMobiles(mobilesSlice)
  581. }()
  582. emailTotalMap := make(map[string]int)
  583. lastTimeEmailMap := make(map[string]time.Time)
  584. w.Add(1)
  585. go func() {
  586. defer w.Done()
  587. emailTotalMap, lastTimeEmailMap = ybService.GetUserViewTotalByEmails(emailsSlice)
  588. }()
  589. w.Wait()
  590. for k, v := range list {
  591. sourceStr := ""
  592. if v.ApplyRecordId > 0 {
  593. if v.SourceAgent == 3 {
  594. sourceStr = "弘则研究"
  595. } else if v.SourceAgent == 1 {
  596. switch v.Source {
  597. case 1:
  598. sourceStr = "我的(小程序)"
  599. case 2:
  600. sourceStr = "活动(小程序)"
  601. case 3:
  602. sourceStr = "图库(小程序)"
  603. case 4:
  604. sourceStr = "研报(小程序)"
  605. case 5:
  606. sourceStr = "问答社区(小程序)"
  607. default:
  608. if v.FromPage != "" {
  609. sourceStr = v.FromPage + "(小程序)"
  610. } else {
  611. sourceStr = "研报(小程序)"
  612. }
  613. }
  614. } else if v.SourceAgent == 2 {
  615. switch v.Source {
  616. case 1:
  617. sourceStr = "我的(PC端)"
  618. case 2:
  619. sourceStr = "活动(PC端)"
  620. case 3:
  621. sourceStr = "图库(PC端)"
  622. case 4:
  623. sourceStr = "研报(PC端)"
  624. case 5:
  625. sourceStr = "问答社区(PC端)"
  626. default:
  627. if v.FromPage != "" {
  628. sourceStr = v.FromPage + "(PC端)"
  629. } else {
  630. sourceStr = "研报(PC端)"
  631. }
  632. }
  633. }
  634. } else if v.RegisterSource != 0 {
  635. switch v.RegisterSource {
  636. case 1:
  637. sourceStr = "弘则研究"
  638. case 2:
  639. sourceStr = "研报(PC端)"
  640. case 5:
  641. sourceStr = "活动(小程序)"
  642. case 6:
  643. sourceStr = "研报(小程序)"
  644. default:
  645. sourceStr = ""
  646. }
  647. }
  648. list[k].SourceStr = sourceStr
  649. // 统计申请数
  650. if applyTotal, ok := userApplyTotalMap[v.UserId]; ok {
  651. list[k].ApplyTotal = applyTotal
  652. }
  653. //统计阅读数
  654. if num, ok := mobileTotalMap[v.Mobile]; ok {
  655. list[k].ViewTotal += num
  656. }
  657. if num, ok := emailTotalMap[v.Email]; ok {
  658. list[k].ViewTotal += num
  659. }
  660. //最新阅读时间
  661. if t, ok := lastTimeMobileMap[v.Mobile]; ok {
  662. if list[k].LastViewTime.Before(t) {
  663. list[k].LastViewTime = t
  664. }
  665. }
  666. if t, ok := lastTimeEmailMap[v.Email]; ok {
  667. if list[k].LastViewTime.Before(t) {
  668. list[k].LastViewTime = t
  669. }
  670. }
  671. list[k].LastViewTimeStr = list[k].LastViewTime.Format(utils.FormatDateTime)
  672. if list[k].LastViewTimeStr == "0001-01-01 00:00:00" {
  673. list[k].LastViewTimeStr = ""
  674. }
  675. list[k].LastTimeStr = list[k].LastTime.Format(utils.FormatDateTime)
  676. if v.Status == "权益用户" {
  677. list[k].Status = "潜在用户"
  678. }
  679. }
  680. dir, err := os.Executable()
  681. exPath := filepath.Dir(dir)
  682. downLoadnFilePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
  683. xlsxFile := xlsx.NewFile()
  684. if err != nil {
  685. br.Msg = "生成文件失败"
  686. br.ErrMsg = "生成文件失败"
  687. return
  688. }
  689. style := xlsx.NewStyle()
  690. alignment := xlsx.Alignment{
  691. Horizontal: "center",
  692. Vertical: "center",
  693. WrapText: true,
  694. }
  695. style.Alignment = alignment
  696. style.ApplyAlignment = true
  697. sheel, err := xlsxFile.AddSheet("客户数据")
  698. if err != nil {
  699. br.Msg = "新增Sheet失败"
  700. br.ErrMsg = "新增Sheet失败,Err:" + err.Error()
  701. return
  702. }
  703. titleRow := sheel.AddRow()
  704. titleRow.AddCell().SetValue("姓名")
  705. titleRow.AddCell().SetValue("手机号")
  706. titleRow.AddCell().SetValue("邮箱")
  707. titleRow.AddCell().SetValue("最新提交时间")
  708. titleRow.AddCell().SetValue("累计提交次数")
  709. titleRow.AddCell().SetValue("最近一次阅读时间")
  710. titleRow.AddCell().SetValue("累计阅读次数")
  711. titleRow.AddCell().SetValue("公司")
  712. titleRow.AddCell().SetValue("原销售")
  713. titleRow.AddCell().SetValue("来源")
  714. titleRow.AddCell().SetValue("申请类型")
  715. titleRow.AddCell().SetValue("用户状态")
  716. for _, v := range list {
  717. dataRow := sheel.AddRow()
  718. dataRow.SetHeight(20)
  719. dataRow.AddCell().SetString(v.RealName)
  720. dataRow.AddCell().SetString(v.Mobile)
  721. dataRow.AddCell().SetString(v.Email)
  722. dataRow.AddCell().SetString(v.LastTimeStr)
  723. dataRow.AddCell().SetString(strconv.Itoa(v.ApplyTotal))
  724. dataRow.AddCell().SetString(v.LastViewTimeStr)
  725. dataRow.AddCell().SetString(strconv.Itoa(v.ViewTotal))
  726. dataRow.AddCell().SetString(v.CompanyName)
  727. dataRow.AddCell().SetString(v.OriginSellerName)
  728. dataRow.AddCell().SetString(v.SourceStr)
  729. dataRow.AddCell().SetString(v.ApplyStatus)
  730. dataRow.AddCell().SetString(v.Status)
  731. }
  732. err = xlsxFile.Save(downLoadnFilePath)
  733. if err != nil {
  734. br.Msg = "保存文件失败"
  735. br.ErrMsg = "保存文件失败"
  736. return
  737. }
  738. randStr := time.Now().Format(utils.FormatDateTimeUnSpace)
  739. downloadFileName := "用户申请列表_" + randStr + ".xlsx"
  740. this.Ctx.Output.Download(downLoadnFilePath, downloadFileName)
  741. defer func() {
  742. _ = os.Remove(downLoadnFilePath)
  743. }()
  744. br.Ret = 200
  745. br.Success = true
  746. br.Msg = "导出成功"
  747. }
  748. // DelPotentialUser
  749. // @Title 删除潜在用户账号和申请记录
  750. // @Description 删除潜在用户账号和申请记录
  751. // @Param request body company.DeleteUserReq true "type json string"
  752. // @Success 200 {object} 删除成功
  753. // @router /potential/user/del [post]
  754. func (this *ApplyRecordController) DelPotentialUser() {
  755. br := new(models.BaseResponse).Init()
  756. defer func() {
  757. this.Data["json"] = br
  758. this.ServeJSON()
  759. }()
  760. sysUser := this.SysUser
  761. if sysUser == nil {
  762. br.Msg = "请登录"
  763. br.ErrMsg = "请登录,SysUser Is Empty"
  764. br.Ret = 408
  765. return
  766. }
  767. var req company.DeleteUserReq
  768. err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
  769. if err != nil {
  770. br.Msg = "参数解析异常!"
  771. br.ErrMsg = "参数解析失败,Err:" + err.Error()
  772. return
  773. }
  774. if req.UserId <= 0 {
  775. br.Msg = "请输入正确的用户ID"
  776. return
  777. }
  778. //获取联系人详情
  779. userInfo, err := models.GetWxUserByUserId(req.UserId)
  780. if err != nil {
  781. br.Msg = "获取联系人异常!"
  782. br.ErrMsg = "获取联系人异常,Err:" + err.Error()
  783. return
  784. }
  785. if userInfo.CompanyId != 1 {
  786. br.Msg = "该联系人已绑定客户,不允许删除!"
  787. return
  788. }
  789. //操作权限校验, 超管和ficc管理员有删除权限
  790. if sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_FICC_ADMIN && sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_ADMIN {
  791. br.Msg = "没有操作权限"
  792. return
  793. }
  794. //如果不是超管权限,那么删除的时候,需要获取下联系人归属销售信息
  795. //产品权限
  796. productId := services.GetProductId(sysUser.RoleTypeCode)
  797. //联系人与销售的关系
  798. userSellerRelationList, err := models.GetUserSellerRelationList(int(userInfo.UserId))
  799. if err != nil {
  800. br.Msg = "获取联系人关系失败"
  801. br.ErrMsg = "获取联系人关系失败,Err:" + err.Error()
  802. return
  803. }
  804. userSellerRelationInfo, _ := json.Marshal(userSellerRelationList)
  805. //删除所有的标识,并真正删除数据
  806. _ = models.DeleteUserSellerRelationByUserId(req.UserId)
  807. //真正删除用户
  808. err = services.DeleteWxUser(req.UserId)
  809. if err != nil {
  810. br.Msg = "删除失败!"
  811. br.ErrMsg = "删除失败,Err:" + err.Error()
  812. return
  813. }
  814. if len(userSellerRelationList) > 0 && productId != 0 {
  815. content := fmt.Sprint("联系人:", userInfo.RealName, "被删除")
  816. if userSellerRelationList[0].CompanyId != 1 {
  817. companyInfo, tErr := company.GetCompanyById(userSellerRelationList[0].CompanyId)
  818. if tErr != nil {
  819. if tErr.Error() != utils.ErrNoRow() {
  820. br.Msg = "获取客户信息失败"
  821. br.ErrMsg = "获取客户信息失败,Err:" + tErr.Error()
  822. return
  823. }
  824. } else {
  825. content = fmt.Sprint(companyInfo.CompanyName, ":", content)
  826. for _, userRelation := range userSellerRelationList {
  827. if userRelation.ProductId != productId {
  828. go services.AddCompanyMessage(sysUser.AdminId, userRelation.SellerId, userRelation.CompanyId, 0, 1, companyInfo.CompanyName, content, content)
  829. }
  830. }
  831. }
  832. }
  833. }
  834. //联系人信息
  835. originalUserInfo, _ := json.Marshal(userInfo)
  836. go services.AddWxUserOpLog(company.WxUserOpLog{
  837. LogType: "delete",
  838. UserId: int(userInfo.UserId),
  839. CompanyId: userInfo.CompanyId,
  840. Mobile: userInfo.Mobile,
  841. Email: userInfo.Email,
  842. OriginalUserInfo: string(originalUserInfo),
  843. UserInfo: "",
  844. OriginalUserSellerInfo: string(userSellerRelationInfo),
  845. UserSellerInfo: "",
  846. OpUserId: sysUser.AdminId,
  847. OpUserName: sysUser.RealName,
  848. CreateTime: time.Now(),
  849. })
  850. // 若该联系人为弘则研究公司下的,则同步禁用手机号关联的系统管理员
  851. if userInfo.CompanyId == 16 {
  852. go services.ForbiddenSysUserByMobile(userInfo.Mobile)
  853. }
  854. // 删除用户的申请记录
  855. go ybService.DeleteApplyUser(userInfo.UserId)
  856. br.Ret = 200
  857. br.Success = true
  858. br.Msg = "删除成功"
  859. br.IsAddLog = true
  860. return
  861. }