project_info.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  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. "reflect"
  8. "sort"
  9. "strconv"
  10. "youngmini_server/app/dao"
  11. "youngmini_server/app/model"
  12. "youngmini_server/app/model/youngee_talent_model"
  13. "youngmini_server/app/service/youngee_talent_service"
  14. "youngmini_server/app/utils"
  15. "github.com/gogf/gf/frame/g"
  16. "github.com/gogf/gf/net/ghttp"
  17. )
  18. type projectStatus int
  19. const (
  20. projectStatusCreating = iota + 1
  21. projectStatusReviewing
  22. projectStatusReviewed
  23. projectStatusRecruiting
  24. projectStatusRecruited
  25. projectStatusPaying
  26. projectStatusPaid
  27. projectStatusInvalid
  28. projectStatusInProgress
  29. projectStatusClosed
  30. )
  31. // 获取项目信息列表service
  32. func GetProjectInfoList(r *ghttp.Request) *TalentHttpResult {
  33. fmt.Println("进入种草主页")
  34. pageIndex := r.GetQueryInt("idx", -1)
  35. cntPerPage := r.GetQueryInt("cnt", -1)
  36. //组合筛选
  37. platform := r.Get("platform", "") //抖音、快手、红Book、B站、微博
  38. projectForm := r.Get("projectform") //1.商品寄拍、3.虚拟产品评测、2.素材分发
  39. contentType := r.Get("contenttype", "") //图文形式、视频形式
  40. createTime := r.Get("createTime", "") //任务上线时间
  41. categoryForm := r.Get("categoryform", "") ////商品类目 智能家居、食品饮料等20种
  42. //排根据浏览量排序
  43. viewOrder := r.GetQueryInt("pageViewOrder", -1) //根据哪个字段排序
  44. //仅稿费”+“稿费+赠品"。这个在recruit表中,得到列表之后进行排序
  45. feeForm := r.GetInt("feeform", 0)
  46. searchValue := r.Get("searchvalue")
  47. if pageIndex == -1 || cntPerPage == -1 || cntPerPage == 0 {
  48. return &TalentHttpResult{Code: -1, Msg: "参数错误"}
  49. }
  50. // 如果有稿费形式的过滤条件,则将过滤条件保存于taskModeList
  51. //var feeFormList []interface{}
  52. //if feeForm != nil {
  53. // if reflect.TypeOf(feeForm).Kind() != reflect.Slice {
  54. // return &TalentHttpResult{Code: -2, Msg: "搜索条件稿费形式错误"}
  55. // }
  56. //
  57. // feeFormList = make([]interface{}, 0)
  58. // feeFormList = feeForm.([]interface{})
  59. //}
  60. // 如果有任务形式的过滤条件,则将过滤条件保存于taskModeList
  61. var projectFormList []interface{}
  62. if projectForm != nil {
  63. if reflect.TypeOf(projectForm).Kind() != reflect.Slice {
  64. return &TalentHttpResult{Code: -2, Msg: "搜索条件任务形式错误"}
  65. }
  66. projectFormList = make([]interface{}, 0)
  67. projectFormList = projectForm.([]interface{})
  68. }
  69. // 如果有平台的过滤条件,则将平台列表保存于platformList
  70. var platformList []interface{}
  71. if platform != nil {
  72. if reflect.TypeOf(platform).Kind() != reflect.Slice {
  73. return &TalentHttpResult{Code: -2, Msg: "搜索条件平台类型错误"}
  74. }
  75. platformList = make([]interface{}, 0)
  76. platformList = platform.([]interface{})
  77. }
  78. // 如果有内容形式的过滤条件,则将过滤条件保存于taskModeList
  79. var contentTypeList []interface{}
  80. if contentType != nil {
  81. if reflect.TypeOf(projectForm).Kind() != reflect.Slice {
  82. return &TalentHttpResult{Code: -2, Msg: "搜索条件任务形式错误"}
  83. }
  84. contentTypeList = make([]interface{}, 0)
  85. contentTypeList = contentType.([]interface{})
  86. }
  87. // 上线时间
  88. var createTimeList []interface{}
  89. if createTime != nil {
  90. if reflect.TypeOf(createTime).Kind() != reflect.Slice {
  91. return &TalentHttpResult{Code: -2, Msg: "搜索条件任务形式错误"}
  92. }
  93. createTimeList = make([]interface{}, 0)
  94. createTimeList = createTime.([]interface{})
  95. }
  96. // 如果有商品类目的过滤条件,则将过滤条件保存于categoryFormList
  97. var categoryFormList []interface{}
  98. if categoryForm != nil {
  99. if reflect.TypeOf(categoryForm).Kind() != reflect.Slice {
  100. return &TalentHttpResult{Code: -2, Msg: "搜索条件任务形式错误"}
  101. }
  102. categoryFormList = make([]interface{}, 0)
  103. categoryFormList = categoryForm.([]interface{})
  104. }
  105. if len(categoryFormList) > 0 {
  106. // 使用 categoryFormList 进行某些操作
  107. fmt.Println("Filtered categoryFormList:", categoryFormList)
  108. }
  109. // 构造查询的条件
  110. startId := pageIndex * cntPerPage
  111. // whereStr := fmt.Sprintf("(project_status >= %d and project_status <> %d and project_type = 1)", projectStatusRecruiting, projectStatusInvalid)
  112. whereStr := fmt.Sprintf("(project_status >= %d and fail_reason <> 2 and project_type = 1)", projectStatusRecruiting)
  113. if platformList != nil {
  114. whereStr = whereStr + " and project_platform in ("
  115. for _, v := range platformList {
  116. whereStr += v.(string) + ", "
  117. }
  118. whereStr = whereStr[0 : len(whereStr)-2]
  119. whereStr += ")"
  120. }
  121. if contentTypeList != nil {
  122. whereStr = whereStr + " and content_type in ("
  123. for _, v := range contentTypeList {
  124. whereStr += v.(string) + ", "
  125. }
  126. whereStr = whereStr[0 : len(whereStr)-2]
  127. whereStr += ")"
  128. }
  129. // 处理 selectionFormList (创建时间的过滤条件)
  130. if createTimeList != nil {
  131. whereStr += " AND created_at >= (NOW() - INTERVAL "
  132. for _, v := range createTimeList {
  133. switch v.(string) {
  134. case "1": // 近7天
  135. whereStr += "7 DAY"
  136. case "2": // 近30天
  137. whereStr += "30 DAY"
  138. case "3": // 近90天
  139. whereStr += "90 DAY"
  140. default:
  141. continue // 无效的过滤条件,跳过
  142. }
  143. }
  144. whereStr += ")"
  145. }
  146. if platformList != nil {
  147. whereStr = whereStr + " and project_platform in ("
  148. for _, v := range platformList {
  149. whereStr += v.(string) + ", "
  150. }
  151. whereStr = whereStr[0 : len(whereStr)-2]
  152. whereStr += ")"
  153. }
  154. if projectFormList != nil {
  155. whereStr += " and project_form in ("
  156. for _, v := range projectFormList {
  157. whereStr += v.(string) + ", "
  158. }
  159. whereStr = whereStr[0 : len(whereStr)-2]
  160. whereStr += ")"
  161. }
  162. if searchValue != nil {
  163. whereStr += " and project_name like '%" + searchValue.(string) + "%'"
  164. }
  165. fmt.Println("whereStr:-----》 ", whereStr)
  166. // 查询所有project
  167. var projectList = []model.ProjectInfo{}
  168. err := g.Model(dao.ProjectInfo.Table).Where(whereStr).Scan(&projectList)
  169. if err != nil {
  170. return &TalentHttpResult{Code: -3, Msg: "查询数据库失败"}
  171. }
  172. // 判断请求页面是否超过最大页面
  173. c, err := g.DB().Model(dao.ProjectInfo.Table).Fields("project_id").Where(whereStr).Count()
  174. if c <= 0 {
  175. return &TalentHttpResult{Code: -4, Msg: "has no fullproject", Data: nil}
  176. }
  177. maxPage := c / cntPerPage
  178. if c%cntPerPage > 0 {
  179. maxPage += 1
  180. }
  181. if pageIndex+1 > maxPage {
  182. return &TalentHttpResult{Code: -5, Msg: "over max page"}
  183. }
  184. var projectInfoList = youngee_talent_model.ProjectInfoList{}
  185. err = g.DB().Model("project_info").WithAll().Where(whereStr).
  186. Order("project_status ASC,recruit_ddl DESC").Limit(startId, cntPerPage).Scan(&projectInfoList.ProjectInfos)
  187. if err != nil {
  188. return &TalentHttpResult{Code: -6, Msg: "查询数据库失败"}
  189. }
  190. // 遍历projectList
  191. for i, project := range projectInfoList.ProjectInfos {
  192. fmt.Println("project.EnterpriseId---", project.EnterpriseId)
  193. //处理浏览量
  194. projectViewKey := "project:view:" + gconv.String(project.ProjectId)
  195. //redis中取浏览量 返回的是gvar.Var类型。 不存咋则为nil。经过viewCount.Int变成0
  196. viewCount, err := g.Redis().DoVar("GET", projectViewKey)
  197. if err != nil {
  198. glog.Error(err)
  199. return &TalentHttpResult{Code: 0, Msg: "Redis error"}
  200. }
  201. projectInfoList.ProjectInfos[i].WatchedNum = viewCount.Int()
  202. // 根据 WatchedNum 从高到低排序
  203. if viewOrder != -1 {
  204. sort.Slice(projectInfoList.ProjectInfos, func(i, j int) bool {
  205. return projectInfoList.ProjectInfos[i].WatchedNum > projectInfoList.ProjectInfos[j].WatchedNum
  206. })
  207. }
  208. }
  209. projectInfoList.MaxPage = maxPage
  210. var filteredProjects []*youngee_talent_model.ProjectInfo
  211. //筛选出“仅稿费”+“稿费+赠品”任务,
  212. //只要策略中有 无费置换 之外的fee_form就是有稿费,projectform是 商品寄拍 和 虚拟产品测评 ,就是有赠品
  213. if feeForm != 0 {
  214. for _, project := range projectInfoList.ProjectInfos {
  215. // 条件1:筛选出所有 project_form 为 1 或 3 的项目
  216. if project.ProjectForm == 1 || project.ProjectForm == 3 {
  217. filteredProjects = append(filteredProjects, project)
  218. continue // 如果满足条件1,直接跳过后续条件判断
  219. }
  220. // 条件2:RecruitStrategy 中存在 fee_form 不等于 1 的数据
  221. for _, strategy := range project.RecruitStrategys {
  222. if strategy.FeeForm != 1 {
  223. filteredProjects = append(filteredProjects, project)
  224. break // 找到符合条件的策略,跳出当前循环,避免重复添加
  225. }
  226. }
  227. }
  228. projectInfoList.ProjectInfos = filteredProjects
  229. }
  230. return &TalentHttpResult{Code: 0, Msg: "success", Data: projectInfoList}
  231. }
  232. // 获取单个项目详情service
  233. func GetProjectDetail(r *ghttp.Request) *TalentHttpResult {
  234. tid, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  235. pid := r.GetQueryInt("project_id", 0)
  236. //通过首页进入的详情页,获取服务商id,younggee_supplier表
  237. enterprise_id := r.GetQueryString("enterprise_id", "")
  238. //通过扫服务商码进入的详情页,获取服务商id,younggee_supplier表
  239. //supplier_id := r.GetQueryString("supplier_id", "")
  240. s_project_id := r.GetQueryString("s_project_id", "")
  241. projectInfoSupplier := youngee_talent_model.ProjectInfoSupplier{}
  242. if s_project_id != "" {
  243. // 来自服务商
  244. err := g.DB().Model("younggee_s_project_info").Where("s_project_id=?", s_project_id).Scan(&projectInfoSupplier)
  245. if err != nil {
  246. fmt.Println("projectInfoSupplier err:", err.Error())
  247. }
  248. }
  249. // Redis key
  250. projectViewKey := "project:view:" + strconv.Itoa(pid)
  251. userViewedKey := "user:viewed:" + tid + ":" + strconv.Itoa(pid)
  252. if pid == 0 {
  253. return &TalentHttpResult{Code: -2, Msg: "parse param error"}
  254. }
  255. //在redis中增加浏览量
  256. // Check if the user has already viewed the product
  257. //DoVar方便进行类型转化
  258. viewed, err := g.Redis().DoVar("GET", userViewedKey)
  259. if err != nil {
  260. glog.Error(err)
  261. return &TalentHttpResult{Code: 0, Msg: "Redis error"}
  262. }
  263. var ProjectDetail *youngee_talent_model.ProjectDetail
  264. err = g.DB().Model("project_info").WithAll().Where("project_id", pid).Scan(&ProjectDetail)
  265. if err != nil {
  266. return &TalentHttpResult{Code: -3, Msg: err.Error()}
  267. }
  268. //违约
  269. one, err := g.DB().Model("info_auto_default_handle").Where("auto_default_id=?", ProjectDetail.AutoDefaltId).One()
  270. one2, err := g.DB().Model("info_auto_task").Where("auto_task_id=?", ProjectDetail.AutoTaskId).One()
  271. ProjectDetail.DraftDefault.BreakPecent = one["sketch_replace_not_upload"].Int()
  272. ProjectDetail.LinkDefault.BreakPecent = one["link_replace_not_upload"].Int()
  273. ProjectDetail.DataDefault.BreakPecent = one["data_replace_not_upload"].Int()
  274. ProjectDetail.DraftDefault.BreakTime = one2["draft_default"].Int()
  275. ProjectDetail.DraftDefault.BreakTime = one2["link_breach"].Int()
  276. ProjectDetail.DraftDefault.BreakTime = one2["case_close_default"].Int()
  277. if viewed.IsNil() {
  278. // User hasn't viewed this product yet, increase the view count
  279. _, err = g.Redis().Do("INCR", projectViewKey)
  280. if err != nil {
  281. glog.Error(err)
  282. return &TalentHttpResult{Code: 0, Msg: "Redis error"}
  283. }
  284. // Mark the product as viewed by this user
  285. _, err = g.Redis().Do("SET", userViewedKey, true)
  286. if err != nil {
  287. glog.Error(err)
  288. return &TalentHttpResult{Code: 0, Msg: "Redis error"}
  289. }
  290. }
  291. viewNum, err := g.Redis().DoVar("GET", projectViewKey)
  292. if err != nil {
  293. fmt.Println("获取浏览量失败")
  294. }
  295. ProjectDetail.ViewNum = viewNum.Int()
  296. //浏览历史
  297. currentDate := gtime.Now().Format("Ymd")
  298. // 设计 Redis Key
  299. redisBrowseKey := fmt.Sprintf("browseProject:%s:%s", currentDate, tid)
  300. fmt.Println("redis浏览记录的key为——————————", redisBrowseKey)
  301. // 将 project_id 添加到 Redis 中的 SET
  302. _, err = g.Redis().Do("SADD", redisBrowseKey, pid)
  303. if err != nil {
  304. return &TalentHttpResult{Code: 0, Msg: "Redis 存浏览历史数据失败"}
  305. }
  306. // 设置 Key 的过期时间为 7 天
  307. _, err = g.Redis().Do("EXPIRE", redisBrowseKey, 7*24*60*60) // 7 天的秒数
  308. if err != nil {
  309. return &TalentHttpResult{Code: 0, Msg: "Redis 设置过期时间失败"}
  310. }
  311. if enterprise_id != "" { //project来自商家
  312. var enterprise *youngee_talent_model.Enterprise
  313. err = g.DB().Model("enterprise").WithAll().Where("enterprise_id", enterprise_id).Scan(&enterprise)
  314. if err != nil {
  315. return &TalentHttpResult{Code: -3, Msg: err.Error()}
  316. }
  317. ProjectDetail.Enterprise = enterprise
  318. }
  319. if s_project_id != "" {
  320. // 来自服务商
  321. var younggeeSupplier *youngee_talent_model.YounggeeSupplier
  322. err = g.DB().Model("younggee_supplier").WithAll().Where("supplier_id", projectInfoSupplier.SupplierID).Scan(&younggeeSupplier)
  323. if err != nil {
  324. return &TalentHttpResult{Code: -3, Msg: err.Error()}
  325. }
  326. ProjectDetail.YounggeeSupplier = younggeeSupplier
  327. ProjectDetail.ProjectInfoSupplier = &projectInfoSupplier
  328. }
  329. return &TalentHttpResult{Code: 0, Msg: "success", Data: ProjectDetail}
  330. }
  331. func SignUpProjKuaishouList(r *ghttp.Request) *TalentHttpResult {
  332. tid, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  333. pid := r.GetQueryString("project_id", 0)
  334. // 定义用于存储查询结果的结构体切片
  335. var results []*youngee_talent_model.KuaishouUserInfo
  336. // 查询此达人下,platform_id 为 8 或 4 的所有数据,并将结果扫描到结构体切片中
  337. err := g.DB().Model(&youngee_talent_model.KuaishouUserInfo{}).
  338. Where("talent_id = ?", tid).
  339. Where("platform_id IN (?, ?)", 4, 8).
  340. Order("open_id ASC, platform_id DESC"). // 按 open_id 排序,确保每组的数据连续,并且 platform_id=4 的数据排在前面
  341. Scan(&results)
  342. if err != nil {
  343. return &TalentHttpResult{Code: 1, Msg: "查询失败", Data: nil}
  344. }
  345. // 创建一个 map,用于记录每个 open_id 对应的记录
  346. //key是openid,value是数组,从而实现一对多
  347. openIdMap := make(map[string][]*youngee_talent_model.KuaishouUserInfo)
  348. // 将查询结果按 open_id 分组
  349. for _, record := range results {
  350. openIdMap[record.OpenId] = append(openIdMap[record.OpenId], record)
  351. }
  352. // 筛选出 open_id 对应两条数据且 platform_id = 4 的记录
  353. var resInfo []*youngee_talent_model.KuaishouUserInfo
  354. for _, records := range openIdMap {
  355. if len(records) == 2 { // 确保有两条数据,排除只有一个 platform_id 的情况
  356. for _, record := range records {
  357. if record.PlatformId == 4 { // 选取 platform_id = 4(电商) 的记录,含有粉丝数就好,因为需要加入橱窗
  358. resInfo = append(resInfo, record)
  359. break
  360. }
  361. }
  362. }
  363. }
  364. // 遍历 resInfo 检查过期和是否报名
  365. for _, record := range resInfo {
  366. // 调用 CheckKuaishouTokenExp 函数,检查 openId 是否过期
  367. expired := youngee_talent_service.CheckKuaishouTokenExp(record.OpenId)
  368. // 将过期检查结果赋值给 expired 属性 ,过期则不能被选中用于加入橱窗
  369. record.Expired = expired
  370. //是否报名
  371. isSignResult, err := g.DB().Model("younggee_task_info").Where("project_id=? AND open_id=? talent_id=?", pid, record.OpenId, tid).One()
  372. // 根据查询结果设置 IsSign 属性
  373. if err != nil || isSignResult.IsEmpty() {
  374. record.IsSign = 0 // 没有查到数据,设置为 0
  375. } else {
  376. record.IsSign = 1 // 查到数据,设置为 1
  377. }
  378. }
  379. return &TalentHttpResult{Code: 0, Msg: "success", Data: resInfo}
  380. }