classify.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. package knowledge
  2. import (
  3. "errors"
  4. "eta_gn/eta_api/models/knowledge"
  5. "eta_gn/eta_api/utils"
  6. "fmt"
  7. "sort"
  8. "time"
  9. )
  10. // MoveKnowledgeClassify 移动分类
  11. func MoveKnowledgeClassify(req knowledge.ClassifyMoveReq) (err error, errMsg string) {
  12. knowledgeObj := new(knowledge.KnowledgeClassify)
  13. classifyId := req.ClassifyId
  14. prevClassifyId := req.PrevClassifyId
  15. nextClassifyId := req.NextClassifyId
  16. //如果有传入 上一个兄弟节点分类id
  17. var (
  18. classifyInfo *knowledge.KnowledgeClassify
  19. prevClassify *knowledge.KnowledgeClassify
  20. nextClassify *knowledge.KnowledgeClassify
  21. prevSort int
  22. nextSort int
  23. )
  24. // 移动对象为分类, 判断权限
  25. classifyInfo, err = knowledgeObj.GetClassifyById(classifyId)
  26. if err != nil {
  27. if utils.IsErrNoRow(err) {
  28. errMsg = "分类不存在, 请刷新页面"
  29. err = fmt.Errorf("获取分类信息失败,Err:" + err.Error())
  30. return
  31. }
  32. errMsg = "移动失败"
  33. err = fmt.Errorf("获取分类信息失败,Err:" + err.Error())
  34. return
  35. } else if classifyInfo.ClassifyId == 0 {
  36. errMsg = "分类不存在, 请刷新页面"
  37. err = fmt.Errorf("获取分类信息失败,Err:" + err.Error())
  38. return
  39. }
  40. parentClassifyId := classifyInfo.ParentId
  41. if prevClassifyId > 0 {
  42. prevClassify, err = knowledgeObj.GetClassifyById(prevClassifyId)
  43. if err != nil {
  44. if utils.IsErrNoRow(err) {
  45. errMsg = "上一个分类不存在, 请刷新页面"
  46. err = fmt.Errorf("获取分类信息失败,Err:" + err.Error())
  47. return
  48. }
  49. errMsg = "移动失败"
  50. err = fmt.Errorf("获取上一个兄弟节点分类信息失败,Err:" + err.Error())
  51. return
  52. }
  53. if prevClassify.ParentId != parentClassifyId {
  54. errMsg = "禁止拖动到其他节点"
  55. err = fmt.Errorf(errMsg)
  56. return
  57. }
  58. prevSort = prevClassify.Sort
  59. }
  60. if nextClassifyId > 0 {
  61. //下一个兄弟节点
  62. nextClassify, err = knowledgeObj.GetClassifyById(nextClassifyId)
  63. if err != nil {
  64. if utils.IsErrNoRow(err) {
  65. errMsg = "下一个分类不存在, 请刷新页面"
  66. err = fmt.Errorf("获取分类信息失败,Err:" + err.Error())
  67. return
  68. }
  69. errMsg = "移动失败"
  70. err = fmt.Errorf("获取下一个兄弟节点分类信息失败,Err:" + err.Error())
  71. return
  72. }
  73. if nextClassify.ParentId != parentClassifyId {
  74. errMsg = "禁止拖动到其他节点"
  75. err = fmt.Errorf(errMsg)
  76. return
  77. }
  78. nextSort = nextClassify.Sort
  79. }
  80. err, errMsg = moveKnowledgeClassify(classifyInfo, prevClassify, nextClassify, parentClassifyId, prevSort, nextSort, classifyInfo.ResourceType)
  81. return
  82. }
  83. // moveKnowledgeClassify 移动分类
  84. func moveKnowledgeClassify(classifyInfo, prevClassify, nextClassify *knowledge.KnowledgeClassify, parentId, prevSort, nextSort, resourceType int) (err error, errMsg string) {
  85. knowledgeObj := new(knowledge.KnowledgeClassify)
  86. updateCol := make([]string, 0)
  87. //判断上级id是否一致,如果不一致的话,那么需要移动该分类层级
  88. if classifyInfo.ParentId != parentId {
  89. errMsg = "移动失败"
  90. err = fmt.Errorf("不支持目录层级变更")
  91. return
  92. }
  93. if prevSort > 0 {
  94. //如果是移动在两个兄弟节点之间
  95. if nextSort > 0 {
  96. //下一个兄弟节点
  97. //如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
  98. if prevSort == nextSort || prevSort == classifyInfo.Sort {
  99. //变更兄弟节点的排序
  100. updateSortStr := `sort + 2`
  101. //变更分类
  102. if prevClassify != nil {
  103. _ = knowledgeObj.UpdateClassifySortByParentId(parentId, prevClassify.ClassifyId, prevClassify.Sort, updateSortStr, resourceType)
  104. } else {
  105. _ = knowledgeObj.UpdateClassifySortByParentId(parentId, 0, prevSort, updateSortStr, resourceType)
  106. }
  107. } else {
  108. //如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
  109. if nextSort-prevSort == 1 {
  110. //变更兄弟节点的排序
  111. updateSortStr := `sort + 1`
  112. //变更分类
  113. if prevClassify != nil {
  114. _ = knowledgeObj.UpdateClassifySortByParentId(parentId, prevClassify.ClassifyId, prevSort, updateSortStr, resourceType)
  115. } else {
  116. _ = knowledgeObj.UpdateClassifySortByParentId(parentId, 0, prevSort, updateSortStr, resourceType)
  117. }
  118. }
  119. }
  120. }
  121. classifyInfo.Sort = prevSort + 1
  122. classifyInfo.ModifyTime = time.Now()
  123. updateCol = append(updateCol, "Sort", "ModifyTime")
  124. } else if prevClassify == nil && nextClassify == nil && parentId > 0 {
  125. //处理只拖动到目录里,默认放到目录底部的情况
  126. var maxSort int
  127. maxSort, err = knowledgeObj.GetMaxSortByParentId(parentId)
  128. if err != nil {
  129. errMsg = "移动失败"
  130. err = fmt.Errorf("查询组内排序信息失败,Err:" + err.Error())
  131. return
  132. }
  133. classifyInfo.Sort = maxSort + 1 //那就是排在组内最后一位
  134. classifyInfo.ModifyTime = time.Now()
  135. updateCol = append(updateCol, "Sort", "ModifyTime")
  136. } else {
  137. // 拖动到父级分类的第一位
  138. firstPermission, tmpErr := knowledgeObj.GetFirstClassifyByParentId(parentId)
  139. if tmpErr != nil && !utils.IsErrNoRow(tmpErr) {
  140. errMsg = "移动失败"
  141. err = fmt.Errorf("获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + tmpErr.Error())
  142. return
  143. }
  144. //如果该分类下存在其他分类,且第一个其他分类的排序等于0,那么需要调整排序
  145. if firstPermission != nil && firstPermission.ClassifyId != 0 && firstPermission.Sort == 0 {
  146. updateSortStr := ` sort + 1 `
  147. _ = knowledgeObj.UpdateClassifySortByParentId(parentId, firstPermission.ClassifyId-1, 0, updateSortStr, resourceType)
  148. }
  149. classifyInfo.Sort = 0 //那就是排在第一位
  150. classifyInfo.ModifyTime = time.Now()
  151. updateCol = append(updateCol, "Sort", "ModifyTime")
  152. }
  153. //更新
  154. if len(updateCol) > 0 {
  155. err = classifyInfo.Update(updateCol)
  156. if err != nil {
  157. errMsg = "移动失败"
  158. err = fmt.Errorf("修改失败,Err:" + err.Error())
  159. return
  160. }
  161. }
  162. return
  163. }
  164. // AddKnowledgeClassify
  165. // @Description: 添加报告分类
  166. // @author: Roc
  167. // @datetime 2024-06-17 11:01:21
  168. // @param classifyName string
  169. // @param parentId int
  170. // @param chartPermissionIdList []int
  171. // @return err error
  172. // @return errMsg string
  173. // @return isSendEmail bool
  174. func AddKnowledgeClassify(classifyName string, parentId, resourceType int) (err error, errMsg string, isSendEmail bool) {
  175. isSendEmail = true
  176. errMsg = `添加失败`
  177. knowledgeObj := new(knowledge.KnowledgeClassify)
  178. _, err = knowledgeObj.GetClassifyByName(classifyName, parentId, resourceType)
  179. if err != nil && !utils.IsErrNoRow(err) {
  180. errMsg = "获取分类信息失败"
  181. return
  182. }
  183. if err == nil {
  184. errMsg = "分类名称:" + classifyName + "已存在"
  185. isSendEmail = false
  186. err = errors.New(errMsg)
  187. return
  188. } else {
  189. err = nil
  190. }
  191. level := 1
  192. // 父级分类
  193. var parentClassifyItem *knowledge.KnowledgeClassify
  194. // 父级分类下的子分类数量
  195. var childClassifyCount int
  196. if parentId > 0 {
  197. // 获取父级分类信息
  198. parentClassifyItem, err = knowledgeObj.GetClassifyById(parentId)
  199. if err != nil {
  200. errMsg = "获取父级分类信息失败"
  201. if utils.IsErrNoRow(err) {
  202. errMsg = "父级分类不存在"
  203. }
  204. return
  205. }
  206. if parentClassifyItem.ResourceType != resourceType {
  207. errMsg = "父级分类与当前分类类型不一致"
  208. err = fmt.Errorf(errMsg)
  209. return
  210. }
  211. level = parentClassifyItem.Level + 1
  212. if level > 3 {
  213. errMsg = "分类层级不可超过三级"
  214. isSendEmail = false
  215. return
  216. }
  217. // 获取父级分类下的子分类数量
  218. childClassifyCount, err = knowledgeObj.GetCountClassifyChildByParentId(parentId)
  219. if err != nil {
  220. errMsg = "获取父级分类的子分类信息失败"
  221. return
  222. }
  223. }
  224. nowTime := time.Now().Local()
  225. classify := new(knowledge.KnowledgeClassify)
  226. maxSort, err := classify.GetMaxSort()
  227. if err != nil {
  228. errMsg = "操作失败"
  229. err = errors.New("查询品种排序失败, Err: " + err.Error())
  230. return
  231. }
  232. classify.ClassifyName = classifyName
  233. classify.ParentId = parentId
  234. classify.CreateTime = nowTime
  235. classify.ModifyTime = nowTime
  236. classify.Sort = maxSort + 1
  237. classify.Enabled = 1
  238. classify.Level = level
  239. classify.ResourceType = resourceType
  240. err = knowledgeObj.Add(classify)
  241. if err != nil {
  242. return
  243. }
  244. fmt.Println("classify.ClassifyId:")
  245. fmt.Println(classify.ClassifyId)
  246. // 如果父级分类不为空的话,那么就标记有子级分类,同时
  247. if parentClassifyItem != nil {
  248. parentClassifyItem.HasChild = 1
  249. err = parentClassifyItem.Update([]string{"HasChild"})
  250. if err != nil {
  251. return
  252. }
  253. // 如果以前没有子级分类,那么就继承父级分类下的章节类型(创建新的章节与分类的关系)
  254. if childClassifyCount <= 0 {
  255. // todo 修改分类下的资源报告
  256. moveResourceByAddClassify(parentClassifyItem, classify)
  257. }
  258. }
  259. return
  260. }
  261. // 关于研报分类,因只允许报告或品种关联在最小分类下,所以当某个父分类(非三级分类)已关联报告或品种,需要在该父分类下增加子分类,则第一个子分类添加成功时,默认把该父分类关联的品种和报告转移至新创建的子分类(第一个子分类)下
  262. // moveReportByAddClassify
  263. // @Description: 报告和章节的转移
  264. // @author: Roc
  265. // @datetime 2024-06-17 16:29:56
  266. // @param parentClassifyInfo *knowledge.KnowledgeClassify
  267. // @param currClassifyInfo *knowledge.KnowledgeClassify
  268. // @return err error
  269. func moveResourceByAddClassify(parentClassifyInfo, currClassifyInfo *knowledge.KnowledgeClassify) (err error) {
  270. /*defer func() {
  271. if err != nil {
  272. utils.FileLog.Error(fmt.Sprint("历史报告更改分类失败,父级分类ID:", parentClassifyInfo.ClassifyId, ";当前分类ID:", currClassifyInfo.ClassifyId, ";错误信息:", err.Error()))
  273. }
  274. }()
  275. if currClassifyInfo.Level > 3 {
  276. err = errors.New("父级分类不支持三级分类以上")
  277. return
  278. }
  279. // 报告的分类归属调整,转为下一级的分类
  280. var condition, updateStr string
  281. pars := make([]interface{}, 0)
  282. switch currClassifyInfo.Level {
  283. case 3: // 当前分类是3级分类
  284. updateStr += ` classify_id_third = ?,classify_name_third = ?`
  285. condition += ` AND classify_id_second = ? `
  286. case 2: // 当前分类是2级分类
  287. updateStr += ` classify_id_second = ?,classify_name_second = ?`
  288. condition += ` AND classify_id_first = ? `
  289. default:
  290. err = errors.New("错误的分类层级")
  291. return
  292. }
  293. pars = append(pars, currClassifyInfo.ClassifyId, currClassifyInfo.ClassifyName, parentClassifyInfo.ClassifyId)
  294. // 获取当前分类下的所有章节类型
  295. currReportChapterTypeList, err := knowledgeObj.GetAllReportChapterTypeListByClassifyId(currClassifyInfo.ClassifyId)
  296. if err != nil {
  297. return
  298. }
  299. // 当前的章节类型ID ---> 继承的章节类型ID
  300. chapterTypeIdMap := make(map[int]int)
  301. for _, v := range currReportChapterTypeList {
  302. chapterTypeIdMap[v.ReportChapterTypeId] = v.InheritReportChapterTypeId
  303. }
  304. // 报告转移后,历史章节报告中的type_id也要修复成最新的type_id
  305. err = knowledgeObj.ModifyKnowledgeClassifyAndReportChapterTypeByCondition(condition, pars, updateStr, chapterTypeIdMap, parentClassifyInfo.ClassifyId, currClassifyInfo.ClassifyId, currClassifyInfo.ClassifyName)
  306. if err != nil {
  307. return
  308. }*/
  309. return
  310. }
  311. func EditKnowledgeClassify(classifyId, parentId int, classifyName string) (err error, errMsg string, isSendEmail bool) {
  312. isSendEmail = true
  313. errMsg = `修改失败`
  314. knowledgeObj := new(knowledge.KnowledgeClassify)
  315. item, err := knowledgeObj.GetClassifyById(classifyId)
  316. if err != nil {
  317. errMsg = "获取分类信息失败"
  318. if utils.IsErrNoRow(err) {
  319. errMsg = "分类不存在, 或已被删除"
  320. isSendEmail = false
  321. }
  322. return
  323. }
  324. if (parentId == 0 && item.ParentId > 0) || (parentId > 0 && item.ParentId == 0) {
  325. err = errors.New("不允许修改分类层级")
  326. errMsg = "不允许修改分类层级"
  327. return
  328. }
  329. if parentId > 0 {
  330. parentClassifyItem, e := knowledgeObj.GetClassifyById(parentId)
  331. if e != nil {
  332. errMsg = "获取父级分类失败"
  333. err = errors.New("获取父级分类失败, Err: " + e.Error())
  334. return
  335. }
  336. if parentClassifyItem.Level != item.Level {
  337. errMsg = "不允许修改分类层级"
  338. err = errors.New("不允许修改分类层级")
  339. return
  340. }
  341. }
  342. //originName := item.ClassifyName
  343. // 重名校验
  344. existName, e := knowledgeObj.GetClassifyByName(classifyName, parentId, item.ResourceType)
  345. if e != nil && !utils.IsErrNoRow(e) {
  346. errMsg = "分类名称已存在"
  347. err = errors.New("获取重名分类失败, Err: " + err.Error())
  348. return
  349. }
  350. if existName != nil && existName.ClassifyId > 0 && existName.ClassifyId != item.ClassifyId {
  351. errMsg = "分类名称:" + classifyName + "已存在"
  352. err = errors.New(errMsg)
  353. isSendEmail = false
  354. return
  355. }
  356. item.ClassifyName = classifyName
  357. // ETA1.8.3:不允许修改上级分类 2024-6-17 13:21:01
  358. //
  359. // todo 修改父级,修改level,只允许修改同级别
  360. item.ParentId = parentId
  361. item.ModifyTime = time.Now().Local()
  362. cols := make([]string, 0)
  363. cols = append(cols, "ParentId", "ClassifyName", "ModifyTime")
  364. err = item.Update(cols)
  365. if err != nil {
  366. return
  367. }
  368. // todo 修改父级分类下相关的事件,找到当前分类的最小分类,把上一级的报告挪到最小分类上
  369. return
  370. }
  371. // GetClassifyTreeRecursive 递归获取分类树形结构
  372. func GetClassifyTreeRecursive(list []*knowledge.KnowledgeClassifyItem, parentId int) []*knowledge.KnowledgeClassifyItem {
  373. res := make([]*knowledge.KnowledgeClassifyItem, 0)
  374. for _, v := range list {
  375. if v.ParentId == parentId {
  376. v.Child = GetClassifyTreeRecursive(list, v.ClassifyId)
  377. res = append(res, v)
  378. }
  379. }
  380. return res
  381. }
  382. // GetParentClassifyListByParentIdList
  383. // @Description: 递归获取父级分类信息,正常来讲只有三次
  384. // @author: Roc
  385. // @datetime 2024-06-19 13:23:33
  386. // @param parentClassifyIdList []int
  387. // @return list []*knowledge.KnowledgeClassifyItem
  388. // @return err error
  389. func GetParentClassifyListByParentIdList(parentClassifyIdList []int) (list []*knowledge.KnowledgeClassifyItem, err error) {
  390. knowledgeObj := new(knowledge.KnowledgeClassify)
  391. num := len(parentClassifyIdList)
  392. if num <= 0 {
  393. return
  394. }
  395. list, err = knowledgeObj.GetClassifyListByParentIdList(parentClassifyIdList)
  396. if err != nil {
  397. return
  398. }
  399. // 是否还有上级
  400. {
  401. currParentClassifyIdList := make([]int, 0)
  402. for _, v := range list {
  403. if v.ParentId > 0 {
  404. currParentClassifyIdList = append(currParentClassifyIdList, v.ParentId)
  405. }
  406. }
  407. if len(currParentClassifyIdList) > 0 {
  408. tmpList, tmpErr := GetParentClassifyListByParentIdList(currParentClassifyIdList)
  409. if tmpErr != nil {
  410. err = tmpErr
  411. return
  412. }
  413. list = append(tmpList, list...)
  414. }
  415. }
  416. return
  417. }
  418. // GetClassifyListTreeRecursive
  419. // @Description: 递归获取分类树形结构
  420. // @author: Roc
  421. // @datetime 2024-06-19 13:23:28
  422. // @param list []*knowledge.KnowledgeClassifyItem
  423. // @param parentId int
  424. // @return []*knowledge.KnowledgeClassifyItem
  425. func GetClassifyListTreeRecursive(list []*knowledge.KnowledgeClassifyItem, parentId int) []*knowledge.KnowledgeClassifyItem {
  426. res := make([]*knowledge.KnowledgeClassifyItem, 0)
  427. for _, v := range list {
  428. if v.ParentId == parentId {
  429. v.Child = GetClassifyListTreeRecursive(list, v.ClassifyId)
  430. res = append(res, v)
  431. }
  432. }
  433. // 前端的JP需要我这么返回
  434. if len(res) <= 0 {
  435. res = nil
  436. }
  437. return res
  438. }
  439. // BySortAndCreateTime 用来排序,先按Sort字段升序排序,若Sort相同,则按照CreateTime字段升序排序。
  440. type BySortAndCreateTime []*knowledge.KnowledgeClassifyItem
  441. func (a BySortAndCreateTime) Len() int {
  442. return len(a)
  443. }
  444. func (a BySortAndCreateTime) Swap(i, j int) {
  445. a[i], a[j] = a[j], a[i]
  446. }
  447. func (a BySortAndCreateTime) Less(i, j int) bool {
  448. if a[i].Sort == a[j].Sort {
  449. return a[i].CreateTime.Before(a[j].CreateTime)
  450. }
  451. return a[i].Sort < a[j].Sort
  452. }
  453. // SortClassifyListBySortAndCreateTime sorts the ClassifyList slice by Sort and then CreateTime in ascending order.
  454. func SortClassifyListBySortAndCreateTime(classifyList []*knowledge.KnowledgeClassifyItem) {
  455. sort.Sort(BySortAndCreateTime(classifyList))
  456. }