project_info.go 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953
  1. package youngee_task_service
  2. import (
  3. "fmt"
  4. "github.com/gogf/gf/os/glog"
  5. "github.com/gogf/gf/os/gtime"
  6. "github.com/gogf/gf/util/gconv"
  7. "math"
  8. "sort"
  9. "strings"
  10. "youngmini_server/app/dao"
  11. "youngmini_server/app/model/youngee_talent_model"
  12. "youngmini_server/app/service/youngee_talent_service"
  13. "youngmini_server/app/utils"
  14. "github.com/gogf/gf/frame/g"
  15. "github.com/gogf/gf/net/ghttp"
  16. )
  17. type projectStatus int
  18. const (
  19. projectStatusCreating = iota + 1
  20. projectStatusReviewing
  21. projectStatusReviewed
  22. projectStatusRecruiting
  23. projectStatusRecruited
  24. projectStatusPaying
  25. projectStatusPaid
  26. projectStatusInvalid
  27. projectStatusInProgress
  28. projectStatusClosed
  29. )
  30. // 获取项目信息列表service
  31. func GetProjectInfoList(r *ghttp.Request) *TalentHttpResult {
  32. pageIndex := r.GetQueryInt("idx", -1)
  33. cntPerPage := r.GetQueryInt("cnt", -1)
  34. //组合筛选
  35. platform := r.Get("platform", nil) //抖音、快手、红Book、B站、微博
  36. projectForm := r.Get("projectform", nil) //1.商品寄拍、3.虚拟产品评测、2.素材分发
  37. contentType := r.Get("contenttype", nil) //图文形式、视频形式
  38. createTime := r.Get("createTime", nil) //任务上线时间
  39. categoryForm := r.Get("productCategory", nil) //商品类目 智能家居、食品饮料等20种
  40. //排根据浏览量排序
  41. viewOrder := r.GetQueryInt("pageViewOrder", -1) //根据哪个字段排序
  42. //仅稿费”+“稿费+赠品"。这个在recruit表中,得到列表之后进行排序
  43. feeForm := r.GetInt("feeform", 0)
  44. searchValue := r.Get("searchvalue", nil)
  45. if pageIndex == -1 || cntPerPage == -1 || cntPerPage == 0 {
  46. return &TalentHttpResult{Code: -1, Msg: "参数错误"}
  47. }
  48. // 构造查询的条件
  49. startId := pageIndex * cntPerPage
  50. // whereStr := fmt.Sprintf("(project_status >= %d and project_status <> %d and project_type = 1)", projectStatusRecruiting, projectStatusInvalid)
  51. whereStr := fmt.Sprintf("project_status >= %d and fail_reason <> 2 and project_type = 1", projectStatusRecruiting)
  52. // 处理 平台类型 project_platform
  53. if platform != nil {
  54. whereStr += " and project_platform = " + platform.(string)
  55. }
  56. //处理 内容类型
  57. if contentType != nil {
  58. whereStr += " and content_type = " + contentType.(string)
  59. }
  60. // 处理 创建时间
  61. if createTime != nil {
  62. switch createTime.(string) {
  63. case "1": // 近7天
  64. whereStr += " AND created_at >= (NOW() - INTERVAL 7 DAY)"
  65. case "2": // 近30天
  66. whereStr += " AND created_at >= (NOW() - INTERVAL 30 DAY)"
  67. case "3": // 近90天
  68. whereStr += " AND created_at >= (NOW() - INTERVAL 90 DAY)"
  69. default:
  70. // 无效的过滤条件,跳过
  71. return &TalentHttpResult{
  72. Code: -2,
  73. Msg: "无效的创建时间过滤条件",
  74. }
  75. }
  76. }
  77. // 处理 项目形式
  78. if projectForm != nil {
  79. whereStr += " and project_form = " + projectForm.(string)
  80. }
  81. // 处理 商品类型
  82. if categoryForm != nil {
  83. whereStr += " and product_category = '" + categoryForm.(string) + "'"
  84. }
  85. // 处理搜索条件
  86. if searchValue != nil {
  87. whereStr += " and project_name like '%" + searchValue.(string) + "%'"
  88. }
  89. fmt.Println("query afterAll--->:", whereStr)
  90. // 判断请求页面是否超过最大页面
  91. c, err := g.DB().Model(dao.ProjectInfo.Table).Fields("project_id").Where(whereStr).Count()
  92. fmt.Println("c---->", c)
  93. if err != nil {
  94. return &TalentHttpResult{Code: -4, Msg: "查询数据库失败", Data: err.Error()}
  95. }
  96. maxPage := c / cntPerPage
  97. if c%cntPerPage > 0 {
  98. maxPage += 1
  99. }
  100. var projectInfoList = youngee_talent_model.ProjectInfoList{}
  101. // 查询数据库
  102. err = g.DB().Model("project_info").WithAll().Where(whereStr).
  103. Order("project_status ASC,recruit_ddl DESC").Limit(startId, cntPerPage).Scan(&projectInfoList.ProjectInfos)
  104. if err != nil {
  105. return &TalentHttpResult{Code: -6, Msg: "查询数据库失败"}
  106. }
  107. for _, project := range projectInfoList.ProjectInfos {
  108. fmt.Println("ids---->", project.ProjectId)
  109. }
  110. // 遍历projectList
  111. for i, project := range projectInfoList.ProjectInfos {
  112. fmt.Println("project.EnterpriseId---", project.EnterpriseId)
  113. //处理浏览量
  114. projectViewKey := "project:view:" + gconv.String(project.ProjectId)
  115. //redis中取浏览量 返回的是gvar.Var类型。 不存咋则为nil。经过viewCount.Int变成0
  116. viewCount, err := g.Redis().DoVar("GET", projectViewKey)
  117. if err != nil {
  118. glog.Error(err)
  119. return &TalentHttpResult{Code: 0, Msg: "Redis error"}
  120. }
  121. projectInfoList.ProjectInfos[i].WatchedNum = viewCount.Int()
  122. // 统计 RecruitStrategys 数组中的最低粉丝量和最高粉丝量
  123. var minFollowers, maxFollowers int
  124. // 初始值可以设为极大/极小值
  125. minFollowers = math.MaxInt32
  126. maxFollowers = math.MinInt32
  127. var totalRecruitNum int
  128. // 遍历 RecruitStrategys,找出最低粉丝量和最高粉丝量,以及总招募任务
  129. for _, strategy := range project.RecruitStrategys {
  130. totalRecruitNum += strategy.RecruitNumber
  131. if strategy.FollowersLow < minFollowers {
  132. minFollowers = strategy.FollowersLow
  133. }
  134. if strategy.FollowersUp > maxFollowers {
  135. maxFollowers = strategy.FollowersUp
  136. }
  137. }
  138. // 打印最低粉丝量和最高粉丝量
  139. fmt.Printf("ProjectId: %d, MinFollowers: %d, MaxFollowers: %d\n", project.ProjectId, minFollowers, maxFollowers)
  140. // 如果需要,可以将这些值保存到 ProjectInfo 中,供后续使用
  141. projectInfoList.ProjectInfos[i].MinFollowers = minFollowers
  142. projectInfoList.ProjectInfos[i].MaxFollowers = maxFollowers
  143. projectInfoList.ProjectInfos[i].AllRecruitNum = totalRecruitNum
  144. //稿费的展示情况
  145. allFeeFormNoFee := true // 假设都是无费置换
  146. var hasSelfPrice bool
  147. var minOffer, maxOffer float64
  148. for _, strategy := range project.RecruitStrategys {
  149. if strategy.FeeForm != 1 { // 如果存在非无费置换的策略
  150. allFeeFormNoFee = false
  151. }
  152. if strategy.FeeForm == 3 { // 存在自报价
  153. hasSelfPrice = true
  154. }
  155. if strategy.FeeForm == 2 { // 一口价策略
  156. if strategy.TOffer < minOffer || minOffer == 0 {
  157. minOffer = strategy.TOffer
  158. }
  159. if strategy.TOffer > maxOffer {
  160. maxOffer = strategy.TOffer
  161. }
  162. }
  163. }
  164. // 根据判断结果设置 IsShowOffer 和 HaveSelfPrice
  165. if allFeeFormNoFee {
  166. project.IsShowOffer = 2 // 不展示稿费
  167. } else {
  168. project.IsShowOffer = 1 // 展示稿费
  169. if hasSelfPrice {
  170. project.HaveSelfOffer = 1 //存在自报价
  171. } else {
  172. project.HaveSelfOffer = 2 //存在自报价
  173. }
  174. projectInfoList.ProjectInfos[i].MaxOffer = maxOffer
  175. projectInfoList.ProjectInfos[i].MinOffer = minOffer
  176. }
  177. }
  178. // 根据 WatchedNum 从高到低排序
  179. if viewOrder != -1 {
  180. sort.Slice(projectInfoList.ProjectInfos, func(i, j int) bool {
  181. return projectInfoList.ProjectInfos[i].WatchedNum > projectInfoList.ProjectInfos[j].WatchedNum
  182. })
  183. }
  184. projectInfoList.MaxPage = maxPage
  185. var filteredProjects []*youngee_talent_model.ProjectInfo
  186. //筛选出“仅稿费”+“稿费+赠品”任务,
  187. //只要策略中有 无费置换 之外的fee_form就是有稿费,projectform是 商品寄拍 和 虚拟产品测评 ,就是有赠品
  188. if feeForm != 0 {
  189. for _, project := range projectInfoList.ProjectInfos {
  190. // 条件1:筛选出所有 project_form 为 1 或 3 的项目
  191. if project.ProjectForm == 1 || project.ProjectForm == 3 {
  192. filteredProjects = append(filteredProjects, project)
  193. continue // 如果满足条件1,直接跳过后续条件判断
  194. }
  195. // 条件2:RecruitStrategy 中存在 fee_form 不等于 1 的数据
  196. for _, strategy := range project.RecruitStrategys {
  197. if strategy.FeeForm != 1 {
  198. filteredProjects = append(filteredProjects, project)
  199. break // 找到符合条件的策略,跳出当前循环,避免重复添加
  200. }
  201. }
  202. }
  203. projectInfoList.ProjectInfos = filteredProjects
  204. }
  205. return &TalentHttpResult{Code: 0, Msg: "success", Data: projectInfoList}
  206. }
  207. func getViewNum(projectViewKey string, userViewedKey string) int {
  208. // 在redis中增加浏览量
  209. viewed, err := g.Redis().DoVar("GET", userViewedKey)
  210. if err != nil {
  211. glog.Error(err)
  212. return 0
  213. }
  214. if viewed.IsNil() {
  215. _, err = g.Redis().Do("INCR", projectViewKey)
  216. if err != nil {
  217. glog.Error(err)
  218. return 0
  219. }
  220. _, err = g.Redis().Do("SET", userViewedKey, true)
  221. if err != nil {
  222. glog.Error(err)
  223. return 0
  224. }
  225. }
  226. viewNum, err := g.Redis().DoVar("GET", projectViewKey)
  227. if err != nil {
  228. fmt.Println("获取浏览量失败")
  229. return 0
  230. }
  231. return viewNum.Int()
  232. }
  233. //
  234. //// 获取单个项目详情service
  235. //func GetProjectDetail(r *ghttp.Request) *TalentHttpResult {
  236. // tid, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  237. // //列表页面进入
  238. // pid := r.GetQueryString("project_id", "")
  239. //
  240. // //扫码进入:1. 商家端的码 2. 服务商的码
  241. // s_project_id := r.GetQueryInt("s_project_id", 0)
  242. // var projectViewKey = ""
  243. // var userViewedKey = ""
  244. // //达人类型转string
  245. // var talentCategory []*youngee_talent_model.YounggeeTalentCategory
  246. // err := g.DB().Model("younggee_talent_category").Scan(&talentCategory)
  247. // if err != nil {
  248. // return &TalentHttpResult{Code: -1, Msg: err.Error()}
  249. // }
  250. // // 创建一个数字到汉字的映射
  251. // categoryMap := make(map[string]string)
  252. // for _, category := range talentCategory {
  253. // categoryMap[fmt.Sprint(category.Id)] = category.Category
  254. // }
  255. //
  256. // if s_project_id != 0 { //服务商
  257. // var SProjectDetail *youngee_talent_model.ProjectInfoSupplier
  258. // err := g.DB().Model("younggee_s_project_info").WithAll().Where("s_project_id", s_project_id).Scan(&SProjectDetail)
  259. // if err != nil {
  260. // return &TalentHttpResult{Code: -3, Msg: err.Error()}
  261. // }
  262. //
  263. // //浏览量统计
  264. // projectViewKey = "project:view:s_" + gconv.String(s_project_id)
  265. // userViewedKey = "user:viewed:" + gconv.String(tid) + ":s_" + gconv.String(s_project_id)
  266. // viewNum := getViewNum(projectViewKey, userViewedKey)
  267. // SProjectDetail.ProjectDetail.ViewNum = viewNum
  268. // //浏览历史
  269. // currentDate := gtime.Now().Format("Ymd")
  270. // redisBrowseKey := fmt.Sprintf("browseProject:%s:%s", currentDate, tid)
  271. // fmt.Println("redis浏览记录的key为——————————", redisBrowseKey)
  272. // // 将 project_id:s_project_id 添加到 Redis 中的 SET 中,因为project_id可以对应多个s_project_id(被多个服务商接手)
  273. // // 组合 pid 和 s_project_id
  274. // browseItem := fmt.Sprintf("%s:%s", pid, s_project_id)
  275. // _, err = g.Redis().Do("SADD", redisBrowseKey, browseItem)
  276. // if err != nil {
  277. // return &TalentHttpResult{Code: 0, Msg: "Redis 存浏览历史数据失败"}
  278. // }
  279. // _, err = g.Redis().Do("EXPIRE", redisBrowseKey, 7*24*60*60) // 7 天的秒数
  280. // if err != nil {
  281. // return &TalentHttpResult{Code: 0, Msg: "Redis 设置过期时间失败"}
  282. // }
  283. //
  284. // //达人类型转化
  285. // talentTypes := strings.Split(SProjectDetail.ProjectDetail.TalentType, ",")
  286. // var result []string
  287. // for _, t := range talentTypes {
  288. // if name, ok := categoryMap[t]; ok {
  289. // result = append(result, name)
  290. // }
  291. // }
  292. // resultStr := strings.Join(result, ",")
  293. // SProjectDetail.ProjectDetail.TalentType = resultStr
  294. //
  295. // //违约
  296. // if SProjectDetail.ProjectType == 1 { //公开任务
  297. // one, err := g.DB().Model("info_auto_default_handle").Where("auto_default_id=?", SProjectDetail.ProjectDetail.AutoDefaultId).One()
  298. // if err != nil {
  299. // return &TalentHttpResult{Code: 0, Msg: err.Error()}
  300. // } else {
  301. // SProjectDetail.ProjectDetail.DraftBreakPercent = one["sketch_replace_not_upload"].Int()
  302. // SProjectDetail.ProjectDetail.LinkBreakPercent = one["link_replace_not_upload"].Int()
  303. // SProjectDetail.ProjectDetail.DataBreakPercent = one["data_replace_not_upload"].Int()
  304. // }
  305. // one2, err2 := g.DB().Model("info_auto_task").Where("auto_task_id=?", SProjectDetail.ProjectDetail.AutoTaskId).One()
  306. // if err2 != nil {
  307. // return &TalentHttpResult{Code: 0, Msg: "one2 is nil"}
  308. // } else {
  309. // SProjectDetail.ProjectDetail.DraftBreakTime = one2["draft_default"].Int()
  310. // SProjectDetail.ProjectDetail.LinkBreakTime = one2["link_breach"].Int()
  311. // SProjectDetail.ProjectDetail.DataBreakTime = one2["case_close_default"].Int()
  312. // }
  313. // }
  314. //
  315. // //填充收藏信息
  316. // collectionInfo := []youngee_talent_model.ProjectCollection{}
  317. // err = g.DB().Model("younggee_project_collect_info").Where("project_id=? and talent_id = ?", SProjectDetail.ProjectID, tid).Scan(&collectionInfo)
  318. // if err != nil {
  319. // return &TalentHttpResult{Code: -1, Msg: err.Error()}
  320. // }
  321. // if len(collectionInfo) != 0 && collectionInfo[0].Deleted == 0 {
  322. // SProjectDetail.ProjectDetail.IsCollected = 1
  323. // } else {
  324. // SProjectDetail.ProjectDetail.IsCollected = 0
  325. // }
  326. // return &TalentHttpResult{Code: 0, Msg: "success", Data: SProjectDetail}
  327. //
  328. // } else { //商家
  329. // var ProjectDetail *youngee_talent_model.ProjectDetail
  330. // err := g.DB().Model("project_info").WithAll().Where("project_id", pid).Scan(&ProjectDetail)
  331. // if err != nil {
  332. // return &TalentHttpResult{Code: -3, Msg: err.Error()}
  333. // }
  334. //
  335. // //浏览量统计
  336. // projectViewKey = "project:view:" + pid
  337. // userViewedKey = "user:viewed:" + gconv.String(tid) + ":" + pid
  338. // viewNum := getViewNum(projectViewKey, userViewedKey)
  339. // ProjectDetail.ViewNum = viewNum
  340. // //浏览历史
  341. // currentDate := gtime.Now().Format("Ymd")
  342. // redisBrowseKey := fmt.Sprintf("browseProject:%s:%s", currentDate, tid)
  343. // fmt.Println("redis浏览记录的key为——————————", redisBrowseKey)
  344. // // 将 project_id:s_project_id 添加到 Redis 中的 SET 中,因为project_id可以对应多个s_project_id(被多个服务商接手)
  345. // // 组合 pid 和 s_project_id
  346. // browseItem := fmt.Sprintf("%s:%s", pid, s_project_id)
  347. // _, err = g.Redis().Do("SADD", redisBrowseKey, browseItem)
  348. // if err != nil {
  349. // return &TalentHttpResult{Code: 0, Msg: "Redis 存浏览历史数据失败"}
  350. // }
  351. // _, err = g.Redis().Do("EXPIRE", redisBrowseKey, 7*24*60*60) // 7 天的秒数
  352. // if err != nil {
  353. // return &TalentHttpResult{Code: 0, Msg: "Redis 设置过期时间失败"}
  354. // }
  355. //
  356. // //达人类型转化
  357. // talentTypes := strings.Split(ProjectDetail.TalentType, ",")
  358. // var result []string
  359. // for _, t := range talentTypes {
  360. // if name, ok := categoryMap[t]; ok {
  361. // result = append(result, name)
  362. // }
  363. // }
  364. // resultStr := strings.Join(result, ",")
  365. // ProjectDetail.TalentType = resultStr
  366. //
  367. // //违约
  368. // if ProjectDetail.ProjectType == 1 { //公开任务
  369. // one, err := g.DB().Model("info_auto_default_handle").Where("auto_default_id=?", ProjectDetail.AutoDefaultId).One()
  370. // if err != nil {
  371. // return &TalentHttpResult{Code: 0, Msg: err.Error()}
  372. // } else {
  373. // ProjectDetail.DraftBreakPercent = one["sketch_replace_not_upload"].Int()
  374. // ProjectDetail.LinkBreakPercent = one["link_replace_not_upload"].Int()
  375. // ProjectDetail.DataBreakPercent = one["data_replace_not_upload"].Int()
  376. // }
  377. // one2, err2 := g.DB().Model("info_auto_task").Where("auto_task_id=?", ProjectDetail.AutoTaskId).One()
  378. // if err2 != nil {
  379. // return &TalentHttpResult{Code: 0, Msg: "one2 is nil"}
  380. // } else {
  381. // ProjectDetail.DraftBreakTime = one2["draft_default"].Int()
  382. // ProjectDetail.LinkBreakTime = one2["link_breach"].Int()
  383. // ProjectDetail.DataBreakTime = one2["case_close_default"].Int()
  384. // }
  385. // }
  386. //
  387. // //填充收藏信息
  388. // collectionInfo := []youngee_talent_model.ProjectCollection{}
  389. // err = g.DB().Model("younggee_project_collect_info").Where("project_id=? and talent_id = ?", pid, tid).Scan(&collectionInfo)
  390. // if err != nil {
  391. // return &TalentHttpResult{Code: -1, Msg: err.Error()}
  392. // }
  393. // if len(collectionInfo) != 0 && collectionInfo[0].Deleted == 0 { //有数据 且 没取消收藏
  394. // ProjectDetail.IsCollected = 1
  395. // } else {
  396. // ProjectDetail.IsCollected = 0 //没数据 或 有数据但取消了收藏
  397. // }
  398. // return &TalentHttpResult{Code: 0, Msg: "success", Data: ProjectDetail}
  399. // }
  400. //
  401. //}
  402. // 获取单个项目详情service
  403. func GetProjectDetail(r *ghttp.Request) *TalentHttpResult {
  404. g.Log().Info("This is an GetProjectDetail message")
  405. tid, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  406. //列表页面进入
  407. pid := r.GetQueryString("project_id", "")
  408. //扫码进入:1. 商家端的码 2. 服务商的码
  409. s_project_id := r.GetQueryInt("s_project_id", 0)
  410. // Redis key
  411. projectViewKey := "project:view:" + pid
  412. userViewedKey := "user:viewed:" + tid + ":" + pid
  413. //在redis中增加浏览量
  414. // Check if the user has already viewed the product
  415. //DoVar方便进行类型转化
  416. viewed, err := g.Redis().DoVar("GET", userViewedKey)
  417. if err != nil {
  418. glog.Error(err)
  419. return &TalentHttpResult{Code: 0, Msg: "Redis error"}
  420. }
  421. var ProjectDetail *youngee_talent_model.ProjectDetail
  422. //TalentType转成String
  423. var talentCategory []*youngee_talent_model.YounggeeTalentCategory
  424. err = g.DB().Model("younggee_talent_category").Scan(&talentCategory)
  425. if err != nil {
  426. // 处理查询错误
  427. return &TalentHttpResult{Code: -1, Msg: err.Error()}
  428. }
  429. // 创建一个数字到汉字的映射
  430. categoryMap := make(map[string]string)
  431. for _, category := range talentCategory {
  432. categoryMap[fmt.Sprint(category.Id)] = category.Category
  433. }
  434. if s_project_id != 0 { //服务商
  435. var SProjectDetail *youngee_talent_model.ProjectInfoSupplier
  436. err = g.DB().Model("younggee_s_project_info").WithAll().Where("s_project_id", s_project_id).Scan(&SProjectDetail)
  437. if err != nil {
  438. return &TalentHttpResult{Code: -3, Msg: err.Error()}
  439. }
  440. pid = SProjectDetail.ProjectID //获取商家端的pid
  441. }
  442. err = g.DB().Model("project_info").WithAll().Where("project_id", pid).Scan(&ProjectDetail)
  443. if err != nil {
  444. return &TalentHttpResult{Code: -3, Msg: err.Error()}
  445. }
  446. // 将 TalentType 转换为逗号隔开的汉字字符串
  447. talentTypes := strings.Split(ProjectDetail.TalentType, ",")
  448. var result []string
  449. for _, t := range talentTypes {
  450. if name, ok := categoryMap[t]; ok {
  451. result = append(result, name)
  452. }
  453. }
  454. // 将结果拼接成逗号隔开的字符串
  455. resultStr := strings.Join(result, ",")
  456. ProjectDetail.TalentType = resultStr
  457. if ProjectDetail.ProjectType == 1 { //公开任务才有违约信息
  458. //各阶段扣款比例
  459. one, err := g.DB().Model("info_auto_default_handle").Where("auto_default_id=?", ProjectDetail.AutoDefaultId).One()
  460. if err != nil {
  461. return &TalentHttpResult{Code: 0, Msg: err.Error()}
  462. } else {
  463. ProjectDetail.DraftBreakPercent = one["sketch_replace_not_upload"].Int()
  464. ProjectDetail.LinkBreakPercent = one["link_replace_not_upload"].Int()
  465. ProjectDetail.DataBreakPercent = one["data_replace_not_upload"].Int()
  466. }
  467. //各阶段扣款时间
  468. one2, err2 := g.DB().Model("info_auto_task").Where("auto_task_id=?", ProjectDetail.AutoTaskId).One()
  469. if err2 != nil {
  470. return &TalentHttpResult{Code: 0, Msg: "one2 is nil"}
  471. } else {
  472. ProjectDetail.DraftBreakTime = one2["draft_default"].Int()
  473. ProjectDetail.LinkBreakTime = one2["link_breach"].Int()
  474. ProjectDetail.DataBreakTime = one2["case_close_default"].Int()
  475. }
  476. }
  477. if viewed.IsNil() {
  478. // User hasn't viewed this product yet, increase the view count
  479. _, err = g.Redis().Do("INCR", projectViewKey)
  480. if err != nil {
  481. glog.Error(err)
  482. return &TalentHttpResult{Code: 0, Msg: "Redis error"}
  483. }
  484. // Mark the product as viewed by this user
  485. _, err = g.Redis().Do("SET", userViewedKey, true)
  486. if err != nil {
  487. glog.Error(err)
  488. return &TalentHttpResult{Code: 0, Msg: "Redis error"}
  489. }
  490. }
  491. viewNum, err := g.Redis().DoVar("GET", projectViewKey)
  492. if err != nil {
  493. fmt.Println("获取浏览量失败")
  494. }
  495. ProjectDetail.ViewNum = viewNum.Int()
  496. //浏览历史
  497. currentDate := gtime.Now().Format("Ymd")
  498. // 设计 Redis Key
  499. redisBrowseKey := fmt.Sprintf("browseProject:%s:%s", currentDate, tid)
  500. fmt.Println("redis浏览记录的key为——————————", redisBrowseKey)
  501. // 将 project_id:s_project_id 添加到 Redis 中的 SET 中,因为project_id可以对应多个s_project_id(被多个服务商接手)
  502. // 组合 pid 和 s_project_id
  503. browseItem := fmt.Sprintf("%s:%s", pid, s_project_id)
  504. _, err = g.Redis().Do("SADD", redisBrowseKey, browseItem)
  505. if err != nil {
  506. return &TalentHttpResult{Code: 0, Msg: "Redis 存浏览历史数据失败"}
  507. }
  508. // 设置 Key 的过期时间为 7 天
  509. _, err = g.Redis().Do("EXPIRE", redisBrowseKey, 7*24*60*60) // 7 天的秒数
  510. if err != nil {
  511. return &TalentHttpResult{Code: 0, Msg: "Redis 设置过期时间失败"}
  512. }
  513. //填充收藏信息
  514. collectionInfo := []youngee_talent_model.ProjectCollection{}
  515. err = g.DB().Model("younggee_project_collect_info").Where("project_id=? and talent_id = ?", pid, tid).Scan(&collectionInfo)
  516. if err != nil {
  517. return &TalentHttpResult{Code: -1, Msg: err.Error()}
  518. }
  519. //已被收藏
  520. if len(collectionInfo) != 0 && collectionInfo[0].Deleted == 0 { //有数据 且 没取消收藏
  521. ProjectDetail.IsCollected = 1
  522. } else {
  523. ProjectDetail.IsCollected = 0 //没数据 或 有数据但取消了收藏
  524. }
  525. //返回的data作为收藏接口的is_collect字段传入
  526. if err != nil {
  527. return &TalentHttpResult{Code: -3, Msg: err.Error()}
  528. }
  529. // 来自服务商
  530. if s_project_id != 0 {
  531. projectInfoSupplier := youngee_talent_model.ProjectInfoSupplier{}
  532. err := g.DB().Model("younggee_s_project_info").Where("s_project_id=?", s_project_id).Scan(&projectInfoSupplier)
  533. if err != nil {
  534. fmt.Println("projectInfoSupplier err:", err.Error())
  535. }
  536. var younggeeSupplier *youngee_talent_model.YounggeeSupplier
  537. err = g.DB().Model("younggee_supplier").WithAll().Where("supplier_id", projectInfoSupplier.SupplierID).Scan(&younggeeSupplier)
  538. if err != nil {
  539. return &TalentHttpResult{Code: -3, Msg: err.Error()}
  540. }
  541. ProjectDetail.YounggeeSupplier = younggeeSupplier
  542. ProjectDetail.ProjectInfoSupplier = &projectInfoSupplier
  543. } else {
  544. //商家发布的
  545. var enterprise *youngee_talent_model.Enterprise
  546. err = g.DB().Model("enterprise").Where("enterprise_id", ProjectDetail.EnterpriseId).Scan(&enterprise)
  547. if err != nil {
  548. return &TalentHttpResult{Code: -3, Msg: err.Error()}
  549. }
  550. ProjectDetail.Enterprise = enterprise
  551. }
  552. return &TalentHttpResult{Code: 0, Msg: "success", Data: ProjectDetail}
  553. }
  554. //func GetProjectDetailFromBrowse(r *ghttp.Request) *TalentHttpResult {
  555. // //从redis的 key--》browseProject:currentDate:tid中获取对应的 project_id:s_project_id
  556. //
  557. // pid := r.GetQueryInt("project_id", 0)
  558. // enterprise_id := r.GetQueryString("enterprise_id", "") //来自商家
  559. // s_project_id := r.GetQueryString("s_project_id", "")
  560. // projectInfoSupplier := youngee_talent_model.ProjectInfoSupplier{}
  561. // if s_project_id != "" {
  562. // // 来自服务商
  563. // err := g.DB().Model("younggee_s_project_info").Where("s_project_id=?", s_project_id).Scan(&projectInfoSupplier)
  564. // if err != nil {
  565. // fmt.Println("projectInfoSupplier err:", err.Error())
  566. // }
  567. // }
  568. //
  569. // if pid == 0 {
  570. // return &TalentHttpResult{Code: -2, Msg: "parse param error"}
  571. // }
  572. //
  573. // var ProjectDetail *youngee_talent_model.ProjectDetail
  574. // err := g.DB().Model("project_info").WithAll().Where("project_id", pid).Scan(&ProjectDetail)
  575. // if err != nil {
  576. // return &TalentHttpResult{Code: -3, Msg: err.Error()}
  577. // }
  578. // //违约
  579. // one, err := g.DB().Model("info_auto_default_handle").Where("auto_default_id=?", ProjectDetail.AutoDefaultId).One()
  580. // one2, err := g.DB().Model("info_auto_task").Where("auto_task_id=?", ProjectDetail.AutoTaskId).One()
  581. // ProjectDetail.DraftBreakPercent = one["sketch_replace_not_upload"].Int()
  582. // ProjectDetail.LinkBreakPercent = one["link_replace_not_upload"].Int()
  583. // ProjectDetail.DataBreakPercent = one["data_replace_not_upload"].Int()
  584. // ProjectDetail.DraftBreakTime = one2["draft_default"].Int()
  585. // ProjectDetail.DraftBreakTime = one2["link_breach"].Int()
  586. // ProjectDetail.DraftBreakTime = one2["case_close_default"].Int()
  587. //
  588. // if s_project_id != "" { // 来自服务商
  589. // var younggeeSupplier *youngee_talent_model.YounggeeSupplier
  590. // err = g.DB().Model("younggee_supplier").WithAll().Where("supplier_id", projectInfoSupplier.SupplierID).Scan(&younggeeSupplier)
  591. // if err != nil {
  592. // return &TalentHttpResult{Code: -3, Msg: err.Error()}
  593. // }
  594. // ProjectDetail.YounggeeSupplier = younggeeSupplier
  595. // ProjectDetail.ProjectInfoSupplier = &projectInfoSupplier
  596. // } else { //project来自商家
  597. // var enterprise *youngee_talent_model.Enterprise
  598. // err = g.DB().Model("enterprise").WithAll().Where("enterprise_id", enterprise_id).Scan(&enterprise)
  599. // if err != nil {
  600. // return &TalentHttpResult{Code: -3, Msg: err.Error()}
  601. // }
  602. // ProjectDetail.Enterprise = enterprise
  603. // }
  604. //
  605. // return &TalentHttpResult{Code: 0, Msg: "success", Data: ProjectDetail}
  606. //}
  607. func SignUpProjKuaishouList(r *ghttp.Request) *TalentHttpResult {
  608. tid, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  609. pid := r.GetQueryString("project_id", 0)
  610. // 定义用于存储查询结果的结构体切片
  611. var results []*youngee_talent_model.KuaishouUserInfo
  612. // 查询此达人下,platform_id 为 8 或 4 的所有数据,并将结果扫描到结构体切片中
  613. err := g.DB().Model(&youngee_talent_model.KuaishouUserInfo{}).
  614. Where("talent_id = ?", tid).
  615. Where("platform_id IN (?, ?)", 4, 8).
  616. Order("open_id ASC, platform_id DESC"). // 按 open_id 排序,确保每组的数据连续,并且 platform_id=4 的数据排在前面
  617. Scan(&results)
  618. if err != nil {
  619. return &TalentHttpResult{Code: 1, Msg: "查询失败", Data: nil}
  620. }
  621. // 创建一个 map,用于记录每个 open_id 对应的记录
  622. //key是openid,value是数组,从而实现一对多
  623. openIdMap := make(map[string][]*youngee_talent_model.KuaishouUserInfo)
  624. // 将查询结果按 open_id 分组
  625. for _, record := range results {
  626. openIdMap[record.OpenId] = append(openIdMap[record.OpenId], record)
  627. }
  628. // 筛选出 open_id 对应两条数据且 platform_id = 4 的记录
  629. var resInfo []*youngee_talent_model.KuaishouUserInfo
  630. for _, records := range openIdMap {
  631. if len(records) == 2 { // 确保有两条数据,排除只有一个 platform_id 的情况
  632. for _, record := range records {
  633. if record.PlatformId == 4 { // 选取 platform_id = 4(电商) 的记录,含有粉丝数就好,因为需要加入橱窗
  634. resInfo = append(resInfo, record)
  635. break
  636. }
  637. }
  638. }
  639. }
  640. // 遍历 resInfo 检查过期和是否报名
  641. for _, record := range resInfo {
  642. // 调用 CheckKuaishouTokenExp 函数,检查 openId 是否过期
  643. expired := youngee_talent_service.CheckKuaishouTokenExp(record.OpenId)
  644. // 将过期检查结果赋值给 expired 属性 ,过期则不能被选中用于加入橱窗
  645. record.Expired = expired
  646. //是否报名
  647. isSignResult, err := g.DB().Model("youngee_task_info").Where("project_id=? AND open_id=? talent_id=?", pid, record.OpenId, tid).One()
  648. // 根据查询结果设置 IsSign 属性
  649. if err != nil || isSignResult.IsEmpty() {
  650. record.IsSign = 0 // 没有查到数据,设置为 0
  651. } else {
  652. record.IsSign = 1 // 查到数据,设置为 1
  653. }
  654. }
  655. return &TalentHttpResult{Code: 0, Msg: "success", Data: resInfo}
  656. }
  657. // 根据project的平台出现对应的社媒账号列表
  658. func SignUpProjAccountList(r *ghttp.Request) *TalentHttpResult {
  659. tid, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  660. pid := r.GetQueryString("project_id", "")
  661. platformId := r.GetInt("platform_id", 0)
  662. if pid == "" || platformId == 0 {
  663. return &TalentHttpResult{Code: -1, Msg: "参数有误", Data: nil}
  664. }
  665. //快手平台
  666. if platformId == 4 {
  667. // 定义用于存储查询结果的结构体切片
  668. var results []*youngee_talent_model.KuaishouUserInfo
  669. // 查询此达人下,platform_id 为 8 或 4 的所有数据,并将结果扫描到结构体切片中
  670. err := g.DB().Model(&youngee_talent_model.KuaishouUserInfo{}).
  671. Where("talent_id = ?", tid).
  672. Where("platform_id IN (?, ?)", 4, 8).
  673. Order("open_id ASC, platform_id DESC"). // 按 open_id 排序,确保每组的数据连续,并且 platform_id=4 的数据排在前面
  674. Scan(&results)
  675. if err != nil {
  676. return &TalentHttpResult{Code: 1, Msg: "查询失败", Data: nil}
  677. }
  678. // 创建一个 map,用于记录每个 open_id 对应的记录
  679. //key是openid,value是数组,从而实现一对多
  680. openIdMap := make(map[string][]*youngee_talent_model.KuaishouUserInfo)
  681. // 将查询结果按 open_id 分组
  682. for _, record := range results {
  683. openIdMap[record.OpenId] = append(openIdMap[record.OpenId], record)
  684. }
  685. // 筛选出 open_id 对应两条数据且 platform_id = 4 的记录
  686. var resInfo []*youngee_talent_model.KuaishouUserInfo
  687. for _, records := range openIdMap {
  688. if len(records) == 2 { // 确保有两条数据,排除只有一个 platform_id 的情况
  689. for _, record := range records {
  690. if record.PlatformId == 4 { // 选取 platform_id = 4(电商) 的记录,含有粉丝数就好,因为需要加入橱窗
  691. resInfo = append(resInfo, record)
  692. break
  693. }
  694. }
  695. }
  696. }
  697. // 遍历 resInfo 检查过期和是否报名
  698. for _, record := range resInfo {
  699. // 调用 CheckKuaishouTokenExp 函数,检查 openId 是否过期
  700. expired := youngee_talent_service.CheckKuaishouTokenExp(record.OpenId)
  701. // 将过期检查结果赋值给 expired 属性 ,过期则不能被选中用于加入橱窗
  702. record.Expired = expired
  703. //是否报名
  704. isSignResult, err := g.DB().Model("youngee_task_info").Where("project_id=? AND open_id=? AND talent_id=?", pid, record.OpenId, tid).One()
  705. if err != nil {
  706. return &TalentHttpResult{Code: -1, Msg: err.Error()}
  707. }
  708. // 根据查询结果设置 IsSign 属性
  709. if isSignResult.IsEmpty() {
  710. record.IsSign = 0 // 没有查到数据,设置为 0
  711. } else {
  712. record.IsSign = 1 // 查到数据,设置为 1
  713. }
  714. }
  715. return &TalentHttpResult{Code: 0, Msg: "success", Data: resInfo}
  716. } else if platformId == 2 { //抖音
  717. //获取列表
  718. var results2 []*youngee_talent_model.KuaishouUserInfo
  719. //获取达人在此平台的全部账号
  720. err := g.DB().Model(&youngee_talent_model.KuaishouUserInfo{}).
  721. Where("talent_id = ?", tid).
  722. Where("platform_id = ? ", 2).
  723. Scan(&results2)
  724. if err != nil {
  725. return &TalentHttpResult{Code: 1, Msg: "查询失败", Data: nil}
  726. }
  727. // 遍历 resInfo 检查过期和是否报名
  728. for _, record := range results2 {
  729. // 调用 CheckKuaishouTokenExp 函数,检查 openId 是否过期
  730. expired := youngee_talent_service.CheckDouyinTokenExp(record.OpenId)
  731. // 将过期检查结果赋值给 expired 属性 ,过期则不能被选中用于加入橱窗
  732. record.Expired = expired
  733. //是否报名
  734. isSignResult, err := g.DB().Model("youngee_task_info").Where("project_id=? AND open_id=? AND talent_id=?", pid, record.OpenId, tid).One()
  735. if err != nil {
  736. return &TalentHttpResult{Code: -1, Msg: err.Error()}
  737. }
  738. // 根据查询结果设置 IsSign 属性
  739. if isSignResult.IsEmpty() {
  740. record.IsSign = 0 // 没有查到数据,设置为 0
  741. } else {
  742. record.IsSign = 1 // 查到数据,设置为 1
  743. }
  744. }
  745. return &TalentHttpResult{Code: 0, Msg: "success", Data: results2}
  746. } else { //小红书 、 b站 、 微博
  747. //获取列表
  748. var results2 []*youngee_talent_model.KuaishouUserInfo
  749. err := g.DB().Model(&youngee_talent_model.KuaishouUserInfo{}).
  750. Where("talent_id = ?", tid).
  751. Where("platform_id = ? ", platformId).
  752. Scan(&results2)
  753. if err != nil {
  754. return &TalentHttpResult{Code: 1, Msg: "查询失败", Data: nil}
  755. }
  756. // 遍历 resInfo 是否报名
  757. for _, record := range results2 {
  758. //是否报名
  759. isSignResult, err := g.DB().Model("youngee_task_info").Where("project_id=? AND open_id=? AND talent_id=?", pid, record.OpenId, tid).One()
  760. if err != nil {
  761. return &TalentHttpResult{Code: -1, Msg: err.Error()}
  762. }
  763. // 根据查询结果设置 IsSign 属性
  764. if isSignResult.IsEmpty() {
  765. record.IsSign = 0 // 没有查到数据,设置为 0
  766. } else {
  767. record.IsSign = 1 // 查到数据,设置为 1
  768. }
  769. }
  770. return &TalentHttpResult{Code: 0, Msg: "success", Data: results2}
  771. }
  772. }
  773. func SignUpLocalAccountList(r *ghttp.Request) *TalentHttpResult {
  774. tid, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  775. localId := r.GetQueryString("local_id", "")
  776. platformId := r.GetInt("platform_id", 0)
  777. if localId == "" || platformId == 0 {
  778. return &TalentHttpResult{Code: -1, Msg: "参数有误", Data: nil}
  779. }
  780. //快手平台
  781. if platformId == 4 {
  782. // 定义用于存储查询结果的结构体切片
  783. var results []*youngee_talent_model.KuaishouUserInfo
  784. // 查询此达人下,platform_id 为 8 或 4 的所有数据,并将结果扫描到结构体切片中
  785. err := g.DB().Model(&youngee_talent_model.KuaishouUserInfo{}).
  786. Where("talent_id = ?", tid).
  787. Where("platform_id IN (?, ?)", 4, 8).
  788. Order("open_id ASC, platform_id DESC"). // 按 open_id 排序,确保每组的数据连续,并且 platform_id=4 的数据排在前面
  789. Scan(&results)
  790. if err != nil {
  791. return &TalentHttpResult{Code: 1, Msg: "查询失败", Data: nil}
  792. }
  793. // 创建一个 map,用于记录每个 open_id 对应的记录
  794. //key是openid,value是数组,从而实现一对多
  795. openIdMap := make(map[string][]*youngee_talent_model.KuaishouUserInfo)
  796. // 将查询结果按 open_id 分组
  797. for _, record := range results {
  798. openIdMap[record.OpenId] = append(openIdMap[record.OpenId], record)
  799. }
  800. // 筛选出 open_id 对应两条数据且 platform_id = 4 的记录
  801. var resInfo []*youngee_talent_model.KuaishouUserInfo
  802. for _, records := range openIdMap {
  803. if len(records) == 2 { // 确保有两条数据,排除只有一个 platform_id 的情况
  804. for _, record := range records {
  805. if record.PlatformId == 4 { // 选取 platform_id = 4(电商) 的记录,含有粉丝数就好,因为需要加入橱窗
  806. resInfo = append(resInfo, record)
  807. break
  808. }
  809. }
  810. }
  811. }
  812. // 遍历 resInfo 检查过期和是否报名
  813. for _, record := range resInfo {
  814. // 调用 CheckKuaishouTokenExp 函数,检查 openId 是否过期
  815. expired := youngee_talent_service.CheckKuaishouTokenExp(record.OpenId)
  816. // 将过期检查结果赋值给 expired 属性 ,过期则不能被选中用于加入橱窗
  817. record.Expired = expired
  818. //是否报名
  819. isSignResult, err := g.DB().Model("youngee_local_task_info").Where("local_id=? AND open_id=? AND talent_id=?", localId, record.OpenId, tid).One()
  820. if err != nil {
  821. return &TalentHttpResult{Code: -1, Msg: err.Error()}
  822. }
  823. // 根据查询结果设置 IsSign 属性
  824. if isSignResult.IsEmpty() {
  825. record.IsSign = 0 // 没有查到数据,设置为 0
  826. } else {
  827. record.IsSign = 1 // 查到数据,设置为 1
  828. }
  829. }
  830. return &TalentHttpResult{Code: 0, Msg: "success", Data: resInfo}
  831. } else if platformId == 2 { //抖音
  832. //获取列表
  833. var results2 []*youngee_talent_model.KuaishouUserInfo
  834. //获取达人在此平台的全部账号
  835. err := g.DB().Model(&youngee_talent_model.KuaishouUserInfo{}).
  836. Where("talent_id = ?", tid).
  837. Where("platform_id = ? ", 2).
  838. Scan(&results2)
  839. if err != nil {
  840. return &TalentHttpResult{Code: 1, Msg: "查询失败", Data: nil}
  841. }
  842. // 遍历 resInfo 检查过期和是否报名
  843. for _, record := range results2 {
  844. // 调用 CheckKuaishouTokenExp 函数,检查 openId 是否过期
  845. expired := youngee_talent_service.CheckDouyinTokenExp(record.OpenId)
  846. // 将过期检查结果赋值给 expired 属性 ,过期则不能被选中用于加入橱窗
  847. record.Expired = expired
  848. //是否报名
  849. isSignResult, err := g.DB().Model("youngee_local_task_info").Where("local_id=? AND open_id=? AND talent_id=?", localId, record.OpenId, tid).One()
  850. if err != nil {
  851. return &TalentHttpResult{Code: -1, Msg: err.Error()}
  852. }
  853. // 根据查询结果设置 IsSign 属性
  854. if isSignResult.IsEmpty() {
  855. record.IsSign = 0 // 没有查到数据,设置为 0
  856. } else {
  857. record.IsSign = 1 // 查到数据,设置为 1
  858. }
  859. }
  860. return &TalentHttpResult{Code: 0, Msg: "success", Data: results2}
  861. } else { //小红书 、 b站 、 微博
  862. //获取列表
  863. var results2 []*youngee_talent_model.KuaishouUserInfo
  864. err := g.DB().Model(&youngee_talent_model.KuaishouUserInfo{}).
  865. Where("talent_id = ?", tid).
  866. Where("platform_id = ? ", platformId).
  867. Scan(&results2)
  868. if err != nil {
  869. return &TalentHttpResult{Code: 1, Msg: "查询失败", Data: nil}
  870. }
  871. // 遍历 resInfo 是否报名
  872. for _, record := range results2 {
  873. //是否报名
  874. isSignResult, err := g.DB().Model("youngee_local_task_info").Where("local_id=? AND open_id=? AND talent_id=?", localId, record.OpenId, tid).One()
  875. if err != nil {
  876. return &TalentHttpResult{Code: -1, Msg: err.Error()}
  877. }
  878. // 根据查询结果设置 IsSign 属性
  879. if isSignResult.IsEmpty() {
  880. record.IsSign = 0 // 没有查到数据,设置为 0
  881. } else {
  882. record.IsSign = 1 // 查到数据,设置为 1
  883. }
  884. }
  885. return &TalentHttpResult{Code: 0, Msg: "success", Data: results2}
  886. }
  887. }