classify.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. package services
  2. import (
  3. "errors"
  4. "eta/eta_api/models"
  5. "eta/eta_api/utils"
  6. "fmt"
  7. "time"
  8. )
  9. // MoveReportClassify 移动分类
  10. func MoveReportClassify(req models.ClassifyMoveReq) (err error, errMsg string) {
  11. classifyId := req.ClassifyId
  12. prevClassifyId := req.PrevClassifyId
  13. nextClassifyId := req.NextClassifyId
  14. //如果有传入 上一个兄弟节点分类id
  15. var (
  16. classifyInfo *models.Classify
  17. prevClassify *models.Classify
  18. nextClassify *models.Classify
  19. prevSort int
  20. nextSort int
  21. )
  22. // 移动对象为分类, 判断权限
  23. classifyInfo, err = models.GetClassifyById(classifyId)
  24. if err != nil {
  25. if err.Error() == utils.ErrNoRow() {
  26. errMsg = "分类不存在, 请刷新页面"
  27. err = fmt.Errorf("获取分类信息失败,Err:" + err.Error())
  28. return
  29. }
  30. errMsg = "移动失败"
  31. err = fmt.Errorf("获取分类信息失败,Err:" + err.Error())
  32. return
  33. } else if classifyInfo.Id == 0 {
  34. errMsg = "分类不存在, 请刷新页面"
  35. err = fmt.Errorf("获取分类信息失败,Err:" + err.Error())
  36. return
  37. }
  38. parentClassifyId := classifyInfo.ParentId
  39. if prevClassifyId > 0 {
  40. prevClassify, err = models.GetClassifyById(prevClassifyId)
  41. if err != nil {
  42. if err.Error() == utils.ErrNoRow() {
  43. errMsg = "上一个分类不存在, 请刷新页面"
  44. err = fmt.Errorf("获取分类信息失败,Err:" + err.Error())
  45. return
  46. }
  47. errMsg = "移动失败"
  48. err = fmt.Errorf("获取上一个兄弟节点分类信息失败,Err:" + err.Error())
  49. return
  50. }
  51. if prevClassify.ParentId != parentClassifyId {
  52. errMsg = "禁止拖动到其他节点"
  53. err = fmt.Errorf(errMsg)
  54. return
  55. }
  56. prevSort = prevClassify.Sort
  57. }
  58. if nextClassifyId > 0 {
  59. //下一个兄弟节点
  60. nextClassify, err = models.GetClassifyById(nextClassifyId)
  61. if err != nil {
  62. if err.Error() == utils.ErrNoRow() {
  63. errMsg = "下一个分类不存在, 请刷新页面"
  64. err = fmt.Errorf("获取分类信息失败,Err:" + err.Error())
  65. return
  66. }
  67. errMsg = "移动失败"
  68. err = fmt.Errorf("获取下一个兄弟节点分类信息失败,Err:" + err.Error())
  69. return
  70. }
  71. if nextClassify.ParentId != parentClassifyId {
  72. errMsg = "禁止拖动到其他节点"
  73. err = fmt.Errorf(errMsg)
  74. return
  75. }
  76. nextSort = nextClassify.Sort
  77. }
  78. err, errMsg = moveReportClassify(classifyInfo, prevClassify, nextClassify, parentClassifyId, prevSort, nextSort)
  79. return
  80. }
  81. // moveReportClassify 移动分类
  82. func moveReportClassify(classifyInfo, prevClassify, nextClassify *models.Classify, parentId, prevSort, nextSort int) (err error, errMsg string) {
  83. ob := new(models.Classify)
  84. updateCol := make([]string, 0)
  85. //判断上级id是否一致,如果不一致的话,那么需要移动该分类层级
  86. if classifyInfo.ParentId != parentId {
  87. errMsg = "移动失败"
  88. err = fmt.Errorf("不支持目录层级变更")
  89. return
  90. }
  91. if prevSort > 0 {
  92. //如果是移动在两个兄弟节点之间
  93. if nextSort > 0 {
  94. //下一个兄弟节点
  95. //如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
  96. if prevSort == nextSort || prevSort == classifyInfo.Sort {
  97. //变更兄弟节点的排序
  98. updateSortStr := `sort + 2`
  99. //变更分类
  100. if prevClassify != nil {
  101. _ = models.UpdateClassifySortByParentId(parentId, prevClassify.Id, prevClassify.Sort, updateSortStr)
  102. } else {
  103. _ = models.UpdateClassifySortByParentId(parentId, 0, prevSort, updateSortStr)
  104. }
  105. } else {
  106. //如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
  107. if nextSort-prevSort == 1 {
  108. //变更兄弟节点的排序
  109. updateSortStr := `sort + 1`
  110. //变更分类
  111. if prevClassify != nil {
  112. _ = models.UpdateClassifySortByParentId(parentId, prevClassify.Id, prevSort, updateSortStr)
  113. } else {
  114. _ = models.UpdateClassifySortByParentId(parentId, 0, prevSort, updateSortStr)
  115. }
  116. }
  117. }
  118. }
  119. classifyInfo.Sort = prevSort + 1
  120. classifyInfo.ModifyTime = time.Now()
  121. updateCol = append(updateCol, "Sort", "ModifyTime")
  122. } else if prevClassify == nil && nextClassify == nil && parentId > 0 {
  123. //处理只拖动到目录里,默认放到目录底部的情况
  124. var maxSort int
  125. maxSort, err = ob.GetMaxSortByParentId(parentId)
  126. if err != nil {
  127. errMsg = "移动失败"
  128. err = fmt.Errorf("查询组内排序信息失败,Err:" + err.Error())
  129. return
  130. }
  131. classifyInfo.Sort = maxSort + 1 //那就是排在组内最后一位
  132. classifyInfo.ModifyTime = time.Now()
  133. updateCol = append(updateCol, "Sort", "ModifyTime")
  134. } else {
  135. // 拖动到父级分类的第一位
  136. firstPermission, tmpErr := ob.GetFirstClassifyByParentId(parentId)
  137. if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
  138. errMsg = "移动失败"
  139. err = fmt.Errorf("获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + tmpErr.Error())
  140. return
  141. }
  142. //如果该分类下存在其他分类,且第一个其他分类的排序等于0,那么需要调整排序
  143. if firstPermission != nil && firstPermission.Id != 0 && firstPermission.Sort == 0 {
  144. updateSortStr := ` sort + 1 `
  145. _ = models.UpdateClassifySortByParentId(parentId, firstPermission.Id-1, 0, updateSortStr)
  146. }
  147. classifyInfo.Sort = 0 //那就是排在第一位
  148. classifyInfo.ModifyTime = time.Now()
  149. updateCol = append(updateCol, "Sort", "ModifyTime")
  150. }
  151. //更新
  152. if len(updateCol) > 0 {
  153. err = classifyInfo.UpdateClassify(updateCol)
  154. if err != nil {
  155. errMsg = "移动失败"
  156. err = fmt.Errorf("修改失败,Err:" + err.Error())
  157. return
  158. }
  159. }
  160. return
  161. }
  162. // AddReportClassify
  163. // @Description: 添加报告分类
  164. // @author: Roc
  165. // @datetime 2024-06-17 11:01:21
  166. // @param classifyName string
  167. // @param parentId int
  168. // @param chartPermissionIdList []int
  169. // @return err error
  170. // @return errMsg string
  171. // @return isSendEmail bool
  172. func AddReportClassify(classifyName string, parentId int, chartPermissionIdList []int) (err error, errMsg string, isSendEmail bool) {
  173. isSendEmail = true
  174. errMsg = `添加失败`
  175. item, err := models.GetClassifyByName(classifyName, parentId)
  176. if err != nil && err.Error() != utils.ErrNoRow() {
  177. errMsg = "获取分类信息失败"
  178. if err.Error() == utils.ErrNoRow() {
  179. errMsg = "分类名称:" + classifyName + "已存在"
  180. isSendEmail = false
  181. }
  182. return
  183. }
  184. if item != nil {
  185. errMsg = "分类名称:" + classifyName + "已存在"
  186. isSendEmail = false
  187. err = errors.New(errMsg)
  188. return
  189. }
  190. level := 1
  191. // 父级分类
  192. var parentClassifyItem *models.Classify
  193. // 父级分类下的子分类数量
  194. var childClassifyCount int
  195. if parentId > 0 {
  196. // 获取父级分类信息
  197. parentClassifyItem, err = models.GetClassifyById(parentId)
  198. if err != nil {
  199. errMsg = "获取父级分类信息失败"
  200. if err.Error() == utils.ErrNoRow() {
  201. errMsg = "父级分类不存在"
  202. }
  203. return
  204. }
  205. level = parentClassifyItem.Level + 1
  206. if level > 3 {
  207. errMsg = "分类层级不可超过三级"
  208. isSendEmail = false
  209. return
  210. }
  211. // 获取父级分类下的子分类数量
  212. childClassifyCount, err = models.GetCountClassifyChildByParentId(parentId)
  213. if err != nil {
  214. errMsg = "获取父级分类的子分类信息失败"
  215. return
  216. }
  217. }
  218. nowTime := time.Now().Local()
  219. classify := new(models.Classify)
  220. maxSort, err := classify.GetMaxSort()
  221. if err != nil {
  222. errMsg = "操作失败"
  223. err = errors.New("查询品种排序失败, Err: " + err.Error())
  224. return
  225. }
  226. classify.ClassifyName = classifyName
  227. classify.ParentId = parentId
  228. classify.CreateTime = nowTime
  229. classify.ModifyTime = nowTime
  230. classify.Sort = maxSort + 1
  231. classify.Enabled = 1
  232. classify.ShowType = 1 //默认列表格式
  233. classify.IsShow = 1
  234. classify.Level = level
  235. /*classify.Abstract = req.Abstract
  236. classify.Descript = req.Descript
  237. classify.Abstract = req.Abstract
  238. classify.Descript = req.Descript
  239. classify.ReportAuthor = req.ReportAuthor
  240. classify.AuthorDescript = req.AuthorDescript
  241. classify.ColumnImgUrl = req.ColumnImgUrl
  242. classify.ReportImgUrl = req.ReportImgUrl
  243. classify.HeadImgUrl = req.HeadImgUrl
  244. classify.AvatarImgUrl = req.AvatarImgUrl
  245. classify.HomeImgUrl = req.HomeImgUrl
  246. classify.ClassifyLabel = req.ClassifyLabel
  247. classify.ShowType = req.ShowType
  248. classify.HasTeleconference = req.HasTeleconference
  249. classify.VipTitle = req.VipTitle
  250. classify.IsShow = req.IsShow
  251. classify.YbFiccSort = req.YbFiccSort
  252. classify.YbFiccIcon = req.YbFiccIcon
  253. classify.YbFiccPcIcon = req.YbFiccPcIcon
  254. classify.YbIconUrl = req.YbIconUrl
  255. classify.YbBgUrl = req.YbBgUrl
  256. classify.YbListImg = req.YbListImg
  257. classify.YbShareBgImg = req.YbShareBgImg
  258. classify.YbRightBanner = req.YbRightBanner
  259. classify.RelateTel = req.RelateTel
  260. classify.RelateVideo = req.RelateVideo
  261. if req.ParentId > 0 {
  262. parentClassify := new(models.Classify)
  263. if parentClassify, err = models.GetClassifyById(req.ParentId); err != nil {
  264. br.Msg = "获取父级分类信息失败"
  265. br.ErrMsg = "获取父级分类信息失败, Err:" + err.Error()
  266. return
  267. }
  268. updateParent := false
  269. updateCols := make([]string, 0)
  270. updateCols = append(updateCols, "HasTeleconference")
  271. if req.HasTeleconference == 1 {
  272. // 二级分类包含电话会,则一级分类也默认包含电话会
  273. if parentClassify.HasTeleconference == 0 {
  274. parentClassify.HasTeleconference = 1
  275. updateParent = true
  276. }
  277. } else {
  278. // 二级分类均无电话会,则一级分类也无电话会
  279. if parentClassify.HasTeleconference == 1 {
  280. child, err := models.GetClassifyChild(parentClassify.Id, "")
  281. if err != nil {
  282. br.Msg = "获取子分类失败"
  283. br.ErrMsg = "获取子分类失败,Err:" + err.Error()
  284. return
  285. }
  286. // 存在同一级分类下的二级分类有电话会则不变动
  287. hasTel := false
  288. for i := 0; i < len(child); i++ {
  289. if child[i].HasTeleconference == 1 {
  290. hasTel = true
  291. break
  292. }
  293. }
  294. if !hasTel {
  295. parentClassify.HasTeleconference = 0
  296. updateParent = true
  297. }
  298. }
  299. }
  300. if updateParent {
  301. if err = parentClassify.UpdateClassify(updateCols); err != nil {
  302. br.Msg = "更新父级分类失败"
  303. br.ErrMsg = "更新父级分类失败, Err:" + err.Error()
  304. return
  305. }
  306. }
  307. }*/
  308. err = models.AddClassify(classify)
  309. if err != nil {
  310. return
  311. }
  312. //获取报告分类权限列表
  313. err = models.EditChartPermissionSearchKeyWordMappingMulti(classifyName, chartPermissionIdList, classify.Id)
  314. if err != nil {
  315. errMsg = "修改分类权限失败"
  316. return
  317. }
  318. // 修改CRM权限
  319. go func() {
  320. _ = EditClassifyChartPermissionSync(classifyName, classify.Id)
  321. }()
  322. // 如果父级分类不为空的话,那么就标记有子级分类,同时
  323. if parentClassifyItem != nil {
  324. parentClassifyItem.HasChild = 1
  325. parentClassifyItem.UpdateClassify([]string{"HasChild"})
  326. // 如果以前没有子级分类,那么就继承父级分类下的章节类型(创建新的章节与分类的关系)
  327. if childClassifyCount <= 0 {
  328. // 继承父级分类下的章节类型(创建新的章节与分类的关系)
  329. tmpErr := inheritReportChapterType(parentId, classify.Id)
  330. if tmpErr != nil {
  331. return
  332. }
  333. moveReportByAddClassify(parentClassifyItem, classify)
  334. }
  335. }
  336. return
  337. }
  338. // 关于研报分类,因只允许报告或品种关联在最小分类下,所以当某个父分类(非三级分类)已关联报告或品种,需要在该父分类下增加子分类,则第一个子分类添加成功时,默认把该父分类关联的品种和报告转移至新创建的子分类(第一个子分类)下
  339. // moveReportByAddClassify
  340. // @Description: 报告和章节的转移
  341. // @author: Roc
  342. // @datetime 2024-06-17 16:29:56
  343. // @param parentClassifyInfo *models.Classify
  344. // @param currClassifyInfo *models.Classify
  345. // @return err error
  346. func moveReportByAddClassify(parentClassifyInfo, currClassifyInfo *models.Classify) (err error) {
  347. defer func() {
  348. if err != nil {
  349. utils.FileLog.Error(fmt.Sprint("历史报告更改分类失败,父级分类ID:", parentClassifyInfo.Id, ";当前分类ID:", currClassifyInfo.Id, ";错误信息:", err.Error()))
  350. }
  351. }()
  352. if currClassifyInfo.Level > 3 {
  353. err = errors.New("父级分类不支持三级分类以上")
  354. return
  355. }
  356. // 报告的分类归属调整,转为下一级的分类
  357. var condition, updateStr string
  358. pars := make([]interface{}, 0)
  359. switch currClassifyInfo.Level {
  360. case 3: // 当前分类是3级分类
  361. updateStr += ` classify_id_third = ?,classify_name_third = ?`
  362. condition += ` AND classify_id_second = ? `
  363. case 2: // 当前分类是2级分类
  364. updateStr += ` classify_id_second = ?,classify_name_second = ?`
  365. condition += ` AND classify_id_first = ? `
  366. default:
  367. err = errors.New("错误的分类层级")
  368. return
  369. }
  370. pars = append(pars, currClassifyInfo.Id, currClassifyInfo.ClassifyName, parentClassifyInfo.Id)
  371. // 获取当前分类下的所有章节类型
  372. currReportChapterTypeList, err := models.GetAllReportChapterTypeListByClassifyId(currClassifyInfo.Id)
  373. if err != nil {
  374. return
  375. }
  376. // 当前的章节类型ID ---> 继承的章节类型ID
  377. chapterTypeIdMap := make(map[int]int)
  378. for _, v := range currReportChapterTypeList {
  379. chapterTypeIdMap[v.ReportChapterTypeId] = v.InheritReportChapterTypeId
  380. }
  381. // 报告转移后,历史章节报告中的type_id也要修复成最新的type_id
  382. err = models.ModifyReportClassifyAndReportChapterTypeByCondition(condition, pars, updateStr, chapterTypeIdMap, parentClassifyInfo.Id, currClassifyInfo.Id, currClassifyInfo.ClassifyName)
  383. if err != nil {
  384. return
  385. }
  386. return
  387. }
  388. // inheritReportChapterType
  389. // @Description: 继承父级分类下的章节类型
  390. // @author: Roc
  391. // @datetime 2024-06-17 14:41:04
  392. // @param parentClassifyId int
  393. // @param currClassifyId int
  394. // @return err error
  395. func inheritReportChapterType(parentClassifyId, currClassifyId int) (err error) {
  396. defer func() {
  397. if err != nil {
  398. utils.FileLog.Error(fmt.Sprint("继承父级分类下的章节类型失败,父级分类ID:", parentClassifyId, ";当前分类ID:", currClassifyId, ";错误信息:", err.Error()))
  399. }
  400. }()
  401. parentReportChapterTypeList, err := models.GetAllReportChapterTypeListByClassifyId(parentClassifyId)
  402. if err != nil {
  403. return
  404. }
  405. // 如果没有章节类型,那么就直接返回
  406. if len(parentReportChapterTypeList) <= 0 {
  407. return
  408. }
  409. addList := make([]*models.ReportChapterType, 0)
  410. for _, v := range parentReportChapterTypeList {
  411. addList = append(addList, &models.ReportChapterType{
  412. //ReportChapterTypeId: 0,
  413. ReportChapterTypeKey: v.ReportChapterTypeKey,
  414. ReportChapterTypeThumb: v.ReportChapterTypeThumb,
  415. BannerUrl: v.BannerUrl,
  416. ReportChapterTypeName: v.ReportChapterTypeName,
  417. Sort: v.Sort,
  418. Enabled: v.Enabled,
  419. CreatedTime: time.Now(),
  420. LastUpdatedTime: time.Now(),
  421. ResearchType: v.ResearchType,
  422. SelectedImage: v.SelectedImage,
  423. UnselectedImage: v.UnselectedImage,
  424. PcSelectedImage: v.PcSelectedImage,
  425. PcUnselectedImage: v.PcUnselectedImage,
  426. EditImgUrl: v.EditImgUrl,
  427. TickerTitle: v.TickerTitle,
  428. IsShow: v.IsShow,
  429. PauseStartTime: v.PauseStartTime,
  430. PauseEndTime: v.PauseEndTime,
  431. IsSet: v.IsSet,
  432. YbIconUrl: v.YbIconUrl,
  433. YbBottomIcon: v.YbBottomIcon,
  434. ReportClassifyId: currClassifyId,
  435. InheritReportChapterTypeId: v.ReportChapterTypeId,
  436. })
  437. }
  438. obj := models.ReportChapterType{}
  439. err = obj.MultiCreate(addList)
  440. return
  441. }
  442. // EditReportClassify
  443. // @Description: 编辑报告分类
  444. // @author: Roc
  445. // @datetime 2024-06-17 13:31:33
  446. // @param classifyId int
  447. // @param classifyName string
  448. // @param chartPermissionIdList []int
  449. // @return err error
  450. // @return errMsg string
  451. // @return isSendEmail bool
  452. func EditReportClassify(classifyId int, classifyName string, chartPermissionIdList []int) (err error, errMsg string, isSendEmail bool) {
  453. isSendEmail = true
  454. errMsg = `修改失败`
  455. item, err := models.GetClassifyById(classifyId)
  456. if err != nil {
  457. errMsg = "获取分类信息失败"
  458. if err.Error() == utils.ErrNoRow() {
  459. errMsg = "分类不存在, 或已被删除"
  460. isSendEmail = false
  461. }
  462. return
  463. }
  464. originName := item.ClassifyName
  465. // 重名校验
  466. existName, e := models.GetClassifyByName(classifyName, item.ParentId)
  467. if e != nil && e.Error() != utils.ErrNoRow() {
  468. errMsg = "获取信息失败"
  469. err = errors.New("获取重名分类失败, Err: " + err.Error())
  470. return
  471. }
  472. if existName != nil && existName.Id != item.Id {
  473. errMsg = "分类名称:" + classifyName + "已存在"
  474. err = errors.New(errMsg)
  475. isSendEmail = false
  476. return
  477. }
  478. item.ClassifyName = classifyName
  479. // ETA1.8.3:不允许修改上级分类 2024-6-17 13:21:01
  480. //item.ParentId = req.ParentId
  481. item.ModifyTime = time.Now().Local()
  482. cols := make([]string, 0)
  483. cols = append(cols, "ClassifyName", "ModifyTime")
  484. err = item.UpdateClassify(cols)
  485. if err != nil {
  486. return
  487. }
  488. err = models.EditChartPermissionSearchKeyWordMappingMulti(item.ClassifyName, chartPermissionIdList, item.Id)
  489. if err != nil {
  490. errMsg = "修改分类权限失败"
  491. return
  492. }
  493. // 修改CRM权限
  494. go func() {
  495. _ = EditClassifyChartPermissionSync(item.ClassifyName, item.Id)
  496. }()
  497. // TODO 修改分类的关联品种时,历史报告中关联的品种怎么处理?
  498. // 更新报告分类名称/父级分类后
  499. go func() {
  500. _ = AfterUpdateClassifyNameOrParent(item.Id, item.ParentId, item.ParentId, originName, item.ClassifyName, item.Level)
  501. }()
  502. return
  503. }
  504. // GetClassifyTreeRecursive 递归获取分类树形结构
  505. func GetClassifyTreeRecursive(list []*models.ClassifyItem, parentId int) []*models.ClassifyItem {
  506. res := make([]*models.ClassifyItem, 0)
  507. for _, v := range list {
  508. if v.ParentId == parentId {
  509. v.Child = GetClassifyTreeRecursive(list, v.Id)
  510. res = append(res, v)
  511. }
  512. }
  513. return res
  514. }