speech_recognition.go 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405
  1. package services
  2. import (
  3. "baliance.com/gooxml/document"
  4. "baliance.com/gooxml/measurement"
  5. "baliance.com/gooxml/schema/soo/wml"
  6. "bufio"
  7. "errors"
  8. "eta/eta_api/models"
  9. "eta/eta_api/models/speech_recognition"
  10. "eta/eta_api/services/alarm_msg"
  11. "eta/eta_api/utils"
  12. "fmt"
  13. "github.com/jung-kurt/gofpdf"
  14. "os"
  15. "strconv"
  16. "sync"
  17. "time"
  18. )
  19. const (
  20. SpeechRecognitionExportTypeTxt = 1
  21. SpeechRecognitionExportTypeDocx = 2
  22. SpeechRecognitionExportTypePdf = 3
  23. SpeechMenuCheckRemoveTypePass = 0 // 目录删除校验-可删除
  24. SpeechMenuCheckRemoveTypeRefused = 1 // 目录删除校验-不可删除
  25. SpeechMenuCheckRemoveTypeWarning = 2 // 目录删除校验-警告
  26. )
  27. // GetSpeechRecognitionMenuTreeRecursive 递归获取标签目录树
  28. func GetSpeechRecognitionMenuTreeRecursive(list []*speech_recognition.SpeechRecognitionMenu, parentId int) []*speech_recognition.SpeechRecognitionMenuItem {
  29. res := make([]*speech_recognition.SpeechRecognitionMenuItem, 0)
  30. for _, v := range list {
  31. if v.ParentId == parentId {
  32. t := new(speech_recognition.SpeechRecognitionMenuItem)
  33. t.UniqueCode = v.UniqueCode
  34. t.MenuId = v.SpeechRecognitionMenuId
  35. t.MenuName = v.MenuName
  36. t.ParentId = v.ParentId
  37. t.Level = v.Level
  38. t.Sort = v.Sort
  39. t.CreateTime = utils.TimeTransferString(utils.FormatDateTime, v.CreateTime)
  40. t.Children = GetSpeechRecognitionMenuTreeRecursive(list, v.SpeechRecognitionMenuId)
  41. res = append(res, t)
  42. }
  43. }
  44. return res
  45. }
  46. // GetSpeechRecognitionTagMenuTreeRecursive 递归获取标签目录树
  47. func GetSpeechRecognitionTagMenuTreeRecursive(list []*speech_recognition.SpeechRecognitionTagMenu, parentId int) []*speech_recognition.SpeechRecognitionTagMenuItem {
  48. res := make([]*speech_recognition.SpeechRecognitionTagMenuItem, 0)
  49. for _, v := range list {
  50. if v.ParentId == parentId {
  51. t := new(speech_recognition.SpeechRecognitionTagMenuItem)
  52. t.UniqueCode = v.UniqueCode
  53. t.MenuId = v.SpeechRecognitionTagMenuId
  54. t.MenuName = v.MenuName
  55. t.ParentId = v.ParentId
  56. t.Level = v.Level
  57. t.Sort = v.Sort
  58. t.CreateTime = utils.TimeTransferString(utils.FormatDateTime, v.CreateTime)
  59. t.Children = GetSpeechRecognitionTagMenuTreeRecursive(list, v.SpeechRecognitionTagMenuId)
  60. res = append(res, t)
  61. }
  62. }
  63. return res
  64. }
  65. // BatchConvertSpeech 批量转写语音
  66. func BatchConvertSpeech(speeches []*speech_recognition.SpeechRecognition) {
  67. var err error
  68. defer func() {
  69. if err != nil {
  70. tips := fmt.Sprintf("批量转写语音失败, ErrMsg: %s", err.Error())
  71. utils.FileLog.Info(tips)
  72. go alarm_msg.SendAlarmMsg(tips, 1)
  73. }
  74. }()
  75. conf, e := models.GetBusinessConf()
  76. if e != nil {
  77. err = fmt.Errorf("获取配置失败, Err: %s", e.Error())
  78. return
  79. }
  80. if conf[models.BusinessConfTencentApiSecretId] == "" || conf[models.BusinessConfTencentApiSecretKey] == "" || conf[models.BusinessConfTencentApiRecTaskCallbackUrl] == "" {
  81. err = fmt.Errorf("API配置有误, SecretId: %s, SecretKey: %s, Callback: %s", conf[models.BusinessConfTencentApiSecretId], conf[models.BusinessConfTencentApiSecretKey], conf[models.BusinessConfTencentApiRecTaskCallbackUrl])
  82. return
  83. }
  84. // 限制接口请求频率
  85. apiLimit := make(chan struct{}, 20)
  86. var wg sync.WaitGroup
  87. for _, v := range speeches {
  88. wg.Add(1)
  89. go func(speech *speech_recognition.SpeechRecognition) {
  90. defer func() {
  91. wg.Done()
  92. <-apiLimit
  93. }()
  94. apiLimit <- struct{}{}
  95. // 发起请求
  96. var errMsg string
  97. var r TencentRecTaskReq
  98. r.FileUrl = speech.ResourceUrl
  99. r.SecretId = conf[models.BusinessConfTencentApiSecretId]
  100. r.SecretKey = conf[models.BusinessConfTencentApiSecretKey]
  101. r.CallbackUrl = conf[models.BusinessConfTencentApiRecTaskCallbackUrl]
  102. taskId, e := TencentCreateRecTask(r)
  103. if e != nil {
  104. errMsg = "创建语音识别任务失败"
  105. utils.FileLog.Info("TencentCreateRecTask创建语音识别任务失败, ErrMsg: %s", e.Error())
  106. }
  107. if errMsg == "" {
  108. apiLog := new(speech_recognition.SpeechRecognitionApiLog)
  109. apiLog.SpeechRecognitionId = speech.SpeechRecognitionId
  110. apiLog.RequestId = strconv.Itoa(taskId)
  111. apiLog.RequestCode = -1
  112. apiLog.CreateTime = time.Now().Local()
  113. apiLog.ModifyTime = time.Now().Local()
  114. if e = apiLog.Create(); e != nil {
  115. errMsg = "生成API请求失败"
  116. utils.FileLog.Info("CreateApiLog生成API请求记录失败, ErrMsg: %s", e.Error())
  117. return
  118. }
  119. }
  120. // 有报错则更新对应语音识别状态
  121. if errMsg == "" {
  122. return
  123. }
  124. speech.State = speech_recognition.SpeechRecognitionStateFail
  125. speech.ConvertRemark = errMsg
  126. speech.ModifyTime = time.Now().Local()
  127. updateCols := []string{speech_recognition.SpeechRecognitionCols.State, speech_recognition.SpeechRecognitionCols.ConvertRemark, speech_recognition.SpeechRecognitionCols.ModifyTime}
  128. if e = speech.Update(updateCols); e != nil {
  129. utils.FileLog.Info("UpdateSpeech更新语音识别状态失败, ErrMsg: %s", e.Error())
  130. return
  131. }
  132. }(v)
  133. }
  134. wg.Wait()
  135. return
  136. }
  137. // SpeechRecognitionContentExport 导出语音识别内容
  138. func SpeechRecognitionContentExport(exportType int, exportTimestamp bool, fileName string, contents []*speech_recognition.SpeechRecognitionContent) (result string, err error) {
  139. defer func() {
  140. if err != nil {
  141. fmt.Println(err)
  142. }
  143. }()
  144. if len(contents) == 0 {
  145. return
  146. }
  147. // 整理内容
  148. exportText := ""
  149. exportArr := make([]string, 0)
  150. exportPdfArr := make([]string, 0)
  151. for _, v := range contents {
  152. if v.Content == "" {
  153. continue
  154. }
  155. sec := ""
  156. secPdf := ""
  157. if exportTimestamp {
  158. // 毫秒转时间格式
  159. sec = fmt.Sprintf("%s\n%s\n\n", utils.MillisecondsToHHMMSS(v.StartMs), v.Content)
  160. secPdf = fmt.Sprintf("%s %s", utils.MillisecondsToHHMMSS(v.StartMs), v.Content)
  161. } else {
  162. sec = fmt.Sprintf("%s\n\n", v.Content)
  163. secPdf = v.Content
  164. }
  165. exportText += sec
  166. exportArr = append(exportArr, sec)
  167. exportPdfArr = append(exportPdfArr, secPdf)
  168. }
  169. // 导出doc
  170. if exportType == SpeechRecognitionExportTypeDocx {
  171. doc := document.New()
  172. for _, v := range exportArr {
  173. p := doc.AddParagraph()
  174. prop := p.Properties()
  175. prop.Spacing().SetLineSpacing(measurement.Distance(1.5*15*measurement.Point), wml.ST_LineSpacingRuleAuto)
  176. prop.SetAlignment(wml.ST_JcLeft)
  177. run := p.AddRun()
  178. runProp := run.Properties()
  179. runProp.SetSize(measurement.Distance(15 * measurement.Point))
  180. runProp.SetFontFamily("宋体")
  181. run.AddText(v)
  182. run.AddBreak()
  183. }
  184. filePath := fmt.Sprintf("%s.docx", fileName)
  185. if e := doc.SaveToFile(filePath); e != nil {
  186. err = fmt.Errorf("生成docx失败, Err: %s", e.Error())
  187. return
  188. }
  189. result = filePath
  190. return
  191. }
  192. // 导出pdf
  193. if exportType == SpeechRecognitionExportTypePdf {
  194. pdf := gofpdf.New("P", "mm", "A4", "")
  195. pdf.AddPage()
  196. pdf.AddUTF8Font("SimHei", "", "static/SimHei.ttf") // 此处字体文件只能用本地的
  197. pdf.SetFont("SimHei", "", 14)
  198. // 计算可用内容区域宽度
  199. w, _ := pdf.GetPageSize()
  200. marginLeft := 10.0
  201. marginRight := 10.0
  202. availableWidth := w - marginLeft - marginRight
  203. for _, v := range exportPdfArr {
  204. pdf.MultiCell(availableWidth, 10, v, "", "L", false)
  205. pdf.MultiCell(availableWidth, 5, "", "", "L", false) // 单纯的换行
  206. }
  207. filePath := fmt.Sprintf("%s.pdf", fileName)
  208. if e := pdf.OutputFileAndClose(filePath); e != nil {
  209. err = fmt.Errorf("生成pdf失败, Err: %s", e.Error())
  210. return
  211. }
  212. result = filePath
  213. return
  214. }
  215. // 默认导出txt
  216. filePath := fmt.Sprintf("%s.txt", fileName)
  217. file, e := os.Create(filePath)
  218. if e != nil {
  219. err = fmt.Errorf("生成txt文件失败, err: %s", e.Error())
  220. return
  221. }
  222. defer file.Close()
  223. // 写入txt
  224. writer := bufio.NewWriter(file)
  225. _, e = writer.WriteString(exportText)
  226. if e != nil {
  227. err = fmt.Errorf("写入txt文件失败, err: %s", e.Error())
  228. return
  229. }
  230. if e = writer.Flush(); e != nil {
  231. err = fmt.Errorf("刷新txt缓存失败, err: %s", e.Error())
  232. return
  233. }
  234. result = filePath
  235. return
  236. }
  237. // ------------------ 移动目录/语音识别(有空的话后面可以优化一下,以后这种菜单混合移动的情况不会少,CV起来怪麻烦的) ------------------ //
  238. // MoveSpeechMenu 移动语音识别目录/识别文件
  239. func MoveSpeechMenu(req speech_recognition.SpeechRecognitionMenuMoveReq) (err error, errMsg string) {
  240. menuId := req.MenuId
  241. parentMenuId := req.ParentMenuId
  242. prevMenuId := req.PrevMenuId
  243. nextMenuId := req.NextMenuId
  244. speechId := req.SpeechId
  245. prevSpeechId := req.PrevSpeechId
  246. nextSpeechId := req.NextSpeechId
  247. //首先确定移动的对象是目录还是语音识别
  248. //判断上一个节点是目录还是语音识别
  249. //判断下一个节点是目录还是语音识别
  250. //同时更新目录目录下的目录sort和语音识别sort
  251. //更新当前移动的目录或者语音识别sort
  252. menuOb := new(speech_recognition.SpeechRecognitionMenu)
  253. speechOb := new(speech_recognition.SpeechRecognition)
  254. var parentSpeechMenu *speech_recognition.SpeechRecognitionMenu
  255. if parentMenuId > 0 {
  256. t, e := menuOb.GetItemById(parentMenuId)
  257. if e != nil {
  258. errMsg = "移动失败"
  259. err = errors.New("获取上级目录信息失败,Err:" + err.Error())
  260. return
  261. }
  262. parentSpeechMenu = t
  263. }
  264. //如果有传入 上一个兄弟节点目录id
  265. var (
  266. speechMenu *speech_recognition.SpeechRecognitionMenu
  267. prevMenu *speech_recognition.SpeechRecognitionMenu
  268. nextMenu *speech_recognition.SpeechRecognitionMenu
  269. speechItem *speech_recognition.SpeechRecognition
  270. prevSpeech *speech_recognition.SpeechRecognition
  271. nextSpeech *speech_recognition.SpeechRecognition
  272. prevSort int
  273. nextSort int
  274. )
  275. // 移动对象为目录
  276. if speechId == 0 {
  277. speechMenu, err = menuOb.GetItemById(menuId)
  278. if err != nil {
  279. if utils.IsErrNoRow(err) {
  280. errMsg = "当前目录不存在"
  281. err = errors.New("获取目录信息失败,Err:" + err.Error())
  282. return
  283. }
  284. errMsg = "移动失败"
  285. err = errors.New("获取目录信息失败,Err:" + err.Error())
  286. return
  287. }
  288. if parentMenuId > 0 && parentSpeechMenu.Level == 3 {
  289. errMsg = "最高只支持添加3级目录"
  290. err = errors.New(errMsg)
  291. return
  292. }
  293. // 如果是移动目录, 那么校验一下父级目录下是否有重名目录
  294. {
  295. cond := fmt.Sprintf(` AND %s = ? AND %s = ? AND %s <> ?`, speech_recognition.SpeechRecognitionMenuCols.MenuName, speech_recognition.SpeechRecognitionMenuCols.ParentId, speech_recognition.SpeechRecognitionMenuCols.SpeechRecognitionMenuId)
  296. pars := make([]interface{}, 0)
  297. pars = append(pars, speechMenu.MenuName, parentMenuId, menuId)
  298. exists, e := menuOb.GetItemByCondition(cond, pars, "")
  299. if e != nil && !utils.IsErrNoRow(e) {
  300. errMsg = "移动失败"
  301. err = fmt.Errorf("获取父级目录下的同名目录失败, Err: %s", e.Error())
  302. return
  303. }
  304. if exists != nil && exists.SpeechRecognitionMenuId > 0 {
  305. err = fmt.Errorf("移动失败,目录名称已存在")
  306. errMsg = "移动失败,目录名称已存在"
  307. return
  308. }
  309. }
  310. } else {
  311. speechItem, err = speechOb.GetItemById(speechId)
  312. if err != nil {
  313. if utils.IsErrNoRow(err) {
  314. errMsg = "当前语音识别不存在"
  315. err = errors.New("获取目录信息失败,Err:" + err.Error())
  316. return
  317. }
  318. errMsg = "移动失败"
  319. err = errors.New("获取目录信息失败,Err:" + err.Error())
  320. return
  321. }
  322. if parentMenuId == 0 {
  323. errMsg = "移动失败,语音识别必须挂在目录下"
  324. err = errors.New(errMsg)
  325. return
  326. }
  327. }
  328. if prevMenuId > 0 {
  329. prevMenu, err = menuOb.GetItemById(prevMenuId)
  330. if err != nil {
  331. errMsg = "移动失败"
  332. err = errors.New("获取上一个兄弟节点目录信息失败,Err:" + err.Error())
  333. return
  334. }
  335. prevSort = prevMenu.Sort
  336. } else if prevSpeechId > 0 {
  337. prevSpeech, err = speechOb.GetItemById(prevSpeechId)
  338. if err != nil {
  339. errMsg = "移动失败"
  340. err = errors.New("获取上一个兄弟节点信息失败,Err:" + err.Error())
  341. return
  342. }
  343. prevSort = prevSpeech.Sort
  344. }
  345. // 下一个兄弟节点
  346. if nextMenuId > 0 {
  347. nextMenu, err = menuOb.GetItemById(nextMenuId)
  348. if err != nil {
  349. errMsg = "移动失败"
  350. err = errors.New("获取下一个兄弟节点目录信息失败,Err:" + err.Error())
  351. return
  352. }
  353. nextSort = nextMenu.Sort
  354. } else if nextSpeechId > 0 {
  355. nextSpeech, err = speechOb.GetItemById(nextSpeechId)
  356. if err != nil {
  357. errMsg = "移动失败"
  358. err = errors.New("获取下一个兄弟节点目录信息失败,Err:" + err.Error())
  359. return
  360. }
  361. nextSort = nextSpeech.Sort
  362. }
  363. err, errMsg = moveSpeechMenu(parentSpeechMenu, speechMenu, prevMenu, nextMenu, speechItem, prevSpeech, nextSpeech, parentMenuId, prevSort, nextSort)
  364. return
  365. }
  366. func moveSpeechMenu(parentSpeechMenu, speechMenu, prevMenu, nextMenu *speech_recognition.SpeechRecognitionMenu, speechItem, prevSpeech, nextSpeech *speech_recognition.SpeechRecognition, parentMenuId int, prevSort, nextSort int) (err error, errMsg string) {
  367. updateCol := make([]string, 0)
  368. menuOb := new(speech_recognition.SpeechRecognitionMenu)
  369. speechOb := new(speech_recognition.SpeechRecognition)
  370. // 移动对象为目录, 判断目录是否存在
  371. if speechMenu != nil {
  372. oldParentId := speechMenu.ParentId
  373. oldLevel := speechMenu.Level
  374. var menuIds []int
  375. if oldParentId != parentMenuId {
  376. //更新子目录对应的level
  377. childList, e, m := GetChildSpeechMenuByMenuId(speechMenu.SpeechRecognitionMenuId)
  378. if e != nil {
  379. errMsg = "移动失败"
  380. err = errors.New("查询子目录失败,Err:" + e.Error() + m)
  381. return
  382. }
  383. if len(childList) > 0 {
  384. for _, v := range childList {
  385. if v.SpeechRecognitionMenuId == speechMenu.SpeechRecognitionMenuId {
  386. continue
  387. }
  388. menuIds = append(menuIds, v.SpeechRecognitionMenuId)
  389. }
  390. }
  391. }
  392. //判断上级id是否一致,如果不一致的话,那么需要移动该目录层级
  393. if speechMenu.ParentId != parentMenuId && parentMenuId != 0 {
  394. if speechMenu.Level != parentSpeechMenu.Level+1 { //禁止层级调整
  395. errMsg = "移动失败"
  396. err = errors.New("不支持目录层级变更")
  397. return
  398. }
  399. speechMenu.ParentId = parentSpeechMenu.SpeechRecognitionMenuId
  400. speechMenu.RootId = parentSpeechMenu.RootId
  401. speechMenu.Level = parentSpeechMenu.Level + 1
  402. speechMenu.ModifyTime = time.Now()
  403. updateCol = append(updateCol, "ParentId", "RootId", "Level", "ModifyTime")
  404. } else if speechMenu.ParentId != parentMenuId && parentMenuId == 0 {
  405. errMsg = "移动失败"
  406. err = errors.New("不支持目录层级变更")
  407. return
  408. }
  409. if prevSort > 0 {
  410. //如果是移动在两个兄弟节点之间
  411. if nextSort > 0 {
  412. //下一个兄弟节点
  413. //如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
  414. if prevSort == nextSort || prevSort == speechMenu.Sort {
  415. //变更兄弟节点的排序
  416. updateSortStr := `sort + 2`
  417. //变更目录
  418. if prevMenu != nil {
  419. _ = menuOb.UpdateSortByParentId(parentMenuId, prevMenu.SpeechRecognitionMenuId, prevMenu.Sort, updateSortStr)
  420. } else {
  421. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, prevSort, updateSortStr)
  422. }
  423. //变更语音识别
  424. if prevSpeech != nil {
  425. //变更兄弟节点的排序
  426. _ = speechOb.UpdateSortByMenuId(parentMenuId, prevSort, prevSpeech.SpeechRecognitionId, updateSortStr)
  427. } else {
  428. _ = speechOb.UpdateSortByMenuId(parentMenuId, prevSort, 0, updateSortStr)
  429. }
  430. } else {
  431. //如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
  432. if nextSort-prevSort == 1 {
  433. //变更兄弟节点的排序
  434. updateSortStr := `sort + 1`
  435. //变更目录
  436. if prevMenu != nil {
  437. _ = menuOb.UpdateSortByParentId(parentMenuId, prevMenu.SpeechRecognitionMenuId, prevSort, updateSortStr)
  438. } else {
  439. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, prevSort, updateSortStr)
  440. }
  441. //变更语音识别
  442. if prevSpeech != nil {
  443. //变更兄弟节点的排序
  444. _ = speechOb.UpdateSortByMenuId(parentMenuId, prevSort, prevSpeech.SpeechRecognitionId, updateSortStr)
  445. } else {
  446. _ = speechOb.UpdateSortByMenuId(parentMenuId, prevSort, 0, updateSortStr)
  447. }
  448. }
  449. }
  450. }
  451. speechMenu.Sort = prevSort + 1
  452. speechMenu.ModifyTime = time.Now()
  453. updateCol = append(updateCol, "Sort", "ModifyTime")
  454. } else if prevMenu == nil && nextMenu == nil && prevSpeech == nil && nextSpeech == nil && parentMenuId > 0 {
  455. //处理只拖动到目录里,默认放到目录底部的情况
  456. var maxSort int
  457. maxSort, err = GetSpeechMenuMaxSort(parentMenuId)
  458. if err != nil {
  459. errMsg = "移动失败"
  460. err = errors.New("查询组内排序信息失败,Err:" + err.Error())
  461. return
  462. }
  463. speechMenu.Sort = maxSort + 1 //那就是排在组内最后一位
  464. speechMenu.ModifyTime = time.Now()
  465. updateCol = append(updateCol, "Sort", "ModifyTime")
  466. } else {
  467. // 拖动到父级目录的第一位
  468. firstMenu, tmpErr := menuOb.GetFirstByParentId(parentMenuId)
  469. if tmpErr != nil && !utils.IsErrNoRow(tmpErr) {
  470. errMsg = "移动失败"
  471. err = errors.New("获取获取当前父级目录下的排序第一条的目录信息失败,Err:" + tmpErr.Error())
  472. return
  473. }
  474. //如果该目录下存在其他目录,且第一个其他目录的排序等于0,那么需要调整排序
  475. if firstMenu != nil && firstMenu.Sort == 0 {
  476. updateSortStr := ` sort + 1 `
  477. _ = menuOb.UpdateSortByParentId(parentMenuId, firstMenu.SpeechRecognitionMenuId-1, 0, updateSortStr)
  478. //该目录下的所有语音识别也需要+1
  479. _ = speechOb.UpdateSortByMenuId(parentMenuId, 0, 0, updateSortStr)
  480. } else {
  481. //如果该目录下存在语音识别,且第一个语音识别的排序等于0,那么需要调整排序
  482. firstSpeech, tErr := speechOb.GetFirstByMenuId(parentMenuId)
  483. if tErr != nil && !utils.IsErrNoRow(tErr) {
  484. errMsg = "移动失败"
  485. err = errors.New("获取获取当前父级目录下的排序第一条的目录信息失败,Err:" + tErr.Error())
  486. return
  487. }
  488. //如果该目录下存在其他目录,且第一个其他目录的排序等于0,那么需要调整排序
  489. if firstSpeech != nil && firstSpeech.Sort == 0 {
  490. updateSortStr := ` sort + 1 `
  491. _ = speechOb.UpdateSortByMenuId(parentMenuId, 0, firstSpeech.SpeechRecognitionId-1, updateSortStr)
  492. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, 0, updateSortStr)
  493. }
  494. }
  495. speechMenu.Sort = 0 //那就是排在第一位
  496. speechMenu.ModifyTime = time.Now()
  497. updateCol = append(updateCol, "Sort", "ModifyTime")
  498. }
  499. //更新
  500. if len(updateCol) > 0 {
  501. err = speechMenu.Update(updateCol)
  502. if err != nil {
  503. errMsg = "移动失败"
  504. err = errors.New("修改失败,Err:" + err.Error())
  505. return
  506. }
  507. //更新对应目录的root_id和层级
  508. if oldParentId != parentMenuId {
  509. if len(menuIds) > 0 {
  510. levelStep := speechMenu.Level - oldLevel
  511. err = menuOb.UpdateChildByParentMenuId(menuIds, speechMenu.RootId, levelStep)
  512. if err != nil {
  513. errMsg = "移动失败"
  514. err = errors.New("更新子目录失败,Err:" + err.Error())
  515. return
  516. }
  517. }
  518. }
  519. }
  520. } else {
  521. if speechItem == nil {
  522. errMsg = "当前语音识别不存在"
  523. err = errors.New(errMsg)
  524. return
  525. }
  526. //如果改变了目录,那么移动该语音识别数据
  527. if speechItem.MenuId != parentMenuId {
  528. speechItem.MenuId = parentMenuId
  529. speechItem.ModifyTime = time.Now()
  530. updateCol = append(updateCol, speech_recognition.SpeechRecognitionCols.MenuId, speech_recognition.SpeechRecognitionCols.ModifyTime)
  531. }
  532. if prevSort > 0 {
  533. //如果是移动在两个兄弟节点之间
  534. if nextSort > 0 {
  535. //下一个兄弟节点
  536. //如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
  537. if prevSort == nextSort || prevSort == speechItem.Sort {
  538. //变更兄弟节点的排序
  539. updateSortStr := `sort + 2`
  540. //变更目录
  541. if prevMenu != nil {
  542. _ = menuOb.UpdateSortByParentId(parentMenuId, prevMenu.SpeechRecognitionMenuId, prevMenu.Sort, updateSortStr)
  543. } else {
  544. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, prevSort, updateSortStr)
  545. }
  546. //变更语音识别
  547. if prevSpeech != nil {
  548. //变更兄弟节点的排序
  549. _ = speechOb.UpdateSortByMenuId(parentMenuId, prevSort, prevSpeech.SpeechRecognitionId, updateSortStr)
  550. } else {
  551. _ = speechOb.UpdateSortByMenuId(parentMenuId, prevSort, 0, updateSortStr)
  552. }
  553. } else {
  554. //如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
  555. if nextSort-prevSort == 1 {
  556. //变更兄弟节点的排序
  557. updateSortStr := `sort + 1`
  558. //变更目录
  559. if prevMenu != nil {
  560. _ = menuOb.UpdateSortByParentId(parentMenuId, prevMenu.SpeechRecognitionMenuId, prevSort, updateSortStr)
  561. } else {
  562. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, prevSort, updateSortStr)
  563. }
  564. //变更语音识别
  565. if prevSpeech != nil {
  566. //变更兄弟节点的排序
  567. _ = speechOb.UpdateSortByMenuId(parentMenuId, prevSort, prevSpeech.SpeechRecognitionId, updateSortStr)
  568. } else {
  569. _ = speechOb.UpdateSortByMenuId(parentMenuId, prevSort, 0, updateSortStr)
  570. }
  571. }
  572. }
  573. }
  574. speechItem.Sort = prevSort + 1
  575. speechItem.ModifyTime = time.Now()
  576. updateCol = append(updateCol, "Sort", "ModifyTime")
  577. } else if prevMenu == nil && nextMenu == nil && prevSpeech == nil && nextSpeech == nil && parentMenuId > 0 {
  578. //处理只拖动到目录里,默认放到目录底部的情况
  579. var maxSort int
  580. maxSort, err = GetSpeechMenuMaxSort(parentMenuId)
  581. if err != nil {
  582. errMsg = "移动失败"
  583. err = errors.New("查询组内排序信息失败,Err:" + err.Error())
  584. return
  585. }
  586. speechItem.Sort = maxSort + 1 //那就是排在组内最后一位
  587. speechItem.ModifyTime = time.Now()
  588. updateCol = append(updateCol, "Sort", "ModifyTime")
  589. } else {
  590. // 拖动到父级目录的第一位
  591. firstMenu, tmpErr := menuOb.GetFirstByParentId(parentMenuId)
  592. if tmpErr != nil && !utils.IsErrNoRow(tmpErr) {
  593. errMsg = "移动失败"
  594. err = errors.New("获取获取当前父级目录下的排序第一条的目录信息失败,Err:" + tmpErr.Error())
  595. return
  596. }
  597. //如果该目录下存在其他目录,且第一个其他目录的排序等于0,那么需要调整排序
  598. if firstMenu != nil && firstMenu.Sort == 0 {
  599. updateSortStr := ` sort + 1 `
  600. _ = menuOb.UpdateSortByParentId(parentMenuId, firstMenu.SpeechRecognitionMenuId-1, 0, updateSortStr)
  601. //该目录下的所有语音识别也需要+1
  602. _ = speechOb.UpdateSortByMenuId(parentMenuId, 0, 0, updateSortStr)
  603. } else {
  604. //如果该目录下存在语音识别,且第一个语音识别的排序等于0,那么需要调整排序
  605. firstSpeech, tErr := speechOb.GetFirstByMenuId(parentMenuId)
  606. if tErr != nil && !utils.IsErrNoRow(tErr) {
  607. errMsg = "移动失败"
  608. err = errors.New("获取获取当前父级目录下的排序第一条的目录信息失败,Err:" + tErr.Error())
  609. return
  610. }
  611. //如果该目录下存在其他目录,且第一个其他目录的排序等于0,那么需要调整排序
  612. if firstSpeech != nil && firstSpeech.Sort == 0 {
  613. updateSortStr := ` sort + 1 `
  614. _ = speechOb.UpdateSortByMenuId(parentMenuId, 0, firstSpeech.SpeechRecognitionId-1, updateSortStr)
  615. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, 0, updateSortStr)
  616. }
  617. }
  618. speechItem.Sort = 0 //那就是排在第一位
  619. speechItem.ModifyTime = time.Now()
  620. updateCol = append(updateCol, "Sort", "ModifyTime")
  621. }
  622. //更新
  623. if len(updateCol) > 0 {
  624. err = speechItem.Update(updateCol)
  625. if err != nil {
  626. errMsg = "移动失败"
  627. err = errors.New("修改失败,Err:" + err.Error())
  628. return
  629. }
  630. }
  631. }
  632. return
  633. }
  634. func GetChildSpeechMenuByMenuId(menuId int) (targetList []*speech_recognition.SpeechRecognitionMenu, err error, errMsg string) {
  635. menuOb := new(speech_recognition.SpeechRecognitionMenu)
  636. //判断是否是挂在顶级目录下
  637. speechMenu, err := menuOb.GetItemById(menuId)
  638. if err != nil {
  639. if utils.IsErrNoRow(err) {
  640. errMsg = "当前目录不存在"
  641. err = errors.New(errMsg)
  642. return
  643. }
  644. errMsg = "获取失败"
  645. err = errors.New("获取目录信息失败,Err:" + err.Error())
  646. return
  647. }
  648. cond := fmt.Sprintf(" AND %s = ?", speech_recognition.SpeechRecognitionMenuCols.RootId)
  649. pars := make([]interface{}, 0)
  650. pars = append(pars, speechMenu.RootId)
  651. order := fmt.Sprintf("%s ASC, %s ASC, %s ASC", speech_recognition.SpeechRecognitionMenuCols.Level, speech_recognition.SpeechRecognitionMenuCols.Sort, speech_recognition.SpeechRecognitionMenuCols.SpeechRecognitionMenuId)
  652. tmpList, err := speechMenu.GetItemsByCondition(cond, pars, []string{}, order)
  653. if err != nil && !utils.IsErrNoRow(err) {
  654. errMsg = "获取失败"
  655. err = errors.New("获取数据失败,Err:" + err.Error())
  656. return
  657. }
  658. idMap := make(map[int]struct{})
  659. if len(tmpList) > 0 {
  660. for _, v := range tmpList {
  661. if v.SpeechRecognitionMenuId == speechMenu.SpeechRecognitionMenuId {
  662. idMap[v.SpeechRecognitionMenuId] = struct{}{}
  663. }
  664. }
  665. for _, v := range tmpList {
  666. if _, ok := idMap[v.ParentId]; ok {
  667. idMap[v.SpeechRecognitionMenuId] = struct{}{}
  668. }
  669. }
  670. for _, v := range tmpList {
  671. if _, ok := idMap[v.SpeechRecognitionMenuId]; ok {
  672. targetList = append(targetList, v)
  673. }
  674. }
  675. }
  676. return
  677. }
  678. // GetSpeechMenuMaxSort 获取同级下最大的排序
  679. func GetSpeechMenuMaxSort(parentId int) (maxSort int, err error) {
  680. menuOb := new(speech_recognition.SpeechRecognitionMenu)
  681. speechOb := new(speech_recognition.SpeechRecognition)
  682. //获取该层级下最大的排序数
  683. menuMax, err := menuOb.GetMaxSortByParentId(parentId)
  684. if err != nil {
  685. return
  686. }
  687. maxSort = menuMax
  688. speechMax, err := speechOb.GetMaxSortByMenuId(parentId)
  689. if err != nil {
  690. return
  691. }
  692. if maxSort < speechMax {
  693. maxSort = speechMax
  694. }
  695. return
  696. }
  697. // ------------------ 移动目录/语音识别 ------------------ //
  698. // ------------------ 移动标签目录/标签 ------------------ //
  699. // MoveSpeechTagMenu 移动标签目录/标签
  700. func MoveSpeechTagMenu(req speech_recognition.SpeechRecognitionTagMenuMoveReq) (err error, errMsg string) {
  701. menuId := req.MenuId
  702. parentMenuId := req.ParentMenuId
  703. prevMenuId := req.PrevMenuId
  704. nextMenuId := req.NextMenuId
  705. tagId := req.TagId
  706. prevTagId := req.PrevTagId
  707. nextTagId := req.NextTagId
  708. //首先确定移动的对象是目录还是标签
  709. //判断上一个节点是目录还是标签
  710. //判断下一个节点是目录还是标签
  711. //同时更新目录目录下的目录sort和标签sort
  712. //更新当前移动的目录或者标签sort
  713. menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
  714. tagOb := new(speech_recognition.SpeechRecognitionTag)
  715. var parentTagMenu *speech_recognition.SpeechRecognitionTagMenu
  716. if parentMenuId > 0 {
  717. t, e := menuOb.GetItemById(parentMenuId)
  718. if e != nil {
  719. errMsg = "移动失败"
  720. err = errors.New("获取上级目录信息失败,Err:" + err.Error())
  721. return
  722. }
  723. parentTagMenu = t
  724. }
  725. //如果有传入 上一个兄弟节点目录id
  726. var (
  727. tagMenu *speech_recognition.SpeechRecognitionTagMenu
  728. prevMenu *speech_recognition.SpeechRecognitionTagMenu
  729. nextMenu *speech_recognition.SpeechRecognitionTagMenu
  730. tagItem *speech_recognition.SpeechRecognitionTag
  731. prevTag *speech_recognition.SpeechRecognitionTag
  732. nextTag *speech_recognition.SpeechRecognitionTag
  733. prevSort int
  734. nextSort int
  735. )
  736. // 移动对象为目录
  737. if tagId == 0 {
  738. tagMenu, err = menuOb.GetItemById(menuId)
  739. if err != nil {
  740. if utils.IsErrNoRow(err) {
  741. errMsg = "当前目录不存在"
  742. err = errors.New("获取目录信息失败,Err:" + err.Error())
  743. return
  744. }
  745. errMsg = "移动失败"
  746. err = errors.New("获取目录信息失败,Err:" + err.Error())
  747. return
  748. }
  749. if parentMenuId > 0 && parentTagMenu.Level == 3 {
  750. errMsg = "最高只支持添加3级目录"
  751. err = errors.New(errMsg)
  752. return
  753. }
  754. // 如果是移动目录, 那么校验一下父级目录下是否有重名目录
  755. {
  756. cond := fmt.Sprintf(` AND %s = ? AND %s = ? AND %s <> ?`, speech_recognition.SpeechRecognitionTagMenuCols.MenuName, speech_recognition.SpeechRecognitionTagMenuCols.ParentId, speech_recognition.SpeechRecognitionTagMenuCols.SpeechRecognitionTagMenuId)
  757. pars := make([]interface{}, 0)
  758. pars = append(pars, tagMenu.MenuName, parentMenuId, menuId)
  759. exists, e := menuOb.GetItemByCondition(cond, pars, "")
  760. if e != nil && !utils.IsErrNoRow(e) {
  761. errMsg = "移动失败"
  762. err = fmt.Errorf("获取父级目录下的同名目录失败, Err: %s", e.Error())
  763. return
  764. }
  765. if exists != nil {
  766. errMsg = "移动失败,目录名称已存在"
  767. return
  768. }
  769. }
  770. } else {
  771. tagItem, err = tagOb.GetItemById(tagId)
  772. if err != nil {
  773. if utils.IsErrNoRow(err) {
  774. errMsg = "当前标签不存在"
  775. err = errors.New("获取目录信息失败,Err:" + err.Error())
  776. return
  777. }
  778. errMsg = "移动失败"
  779. err = errors.New("获取目录信息失败,Err:" + err.Error())
  780. return
  781. }
  782. if parentMenuId == 0 {
  783. errMsg = "移动失败,标签必须挂在目录下"
  784. err = errors.New(errMsg)
  785. return
  786. }
  787. }
  788. if prevMenuId > 0 {
  789. prevMenu, err = menuOb.GetItemById(prevMenuId)
  790. if err != nil {
  791. errMsg = "移动失败"
  792. err = errors.New("获取上一个兄弟节点目录信息失败,Err:" + err.Error())
  793. return
  794. }
  795. prevSort = prevMenu.Sort
  796. } else if prevTagId > 0 {
  797. prevTag, err = tagOb.GetItemById(prevTagId)
  798. if err != nil {
  799. errMsg = "移动失败"
  800. err = errors.New("获取上一个兄弟节点信息失败,Err:" + err.Error())
  801. return
  802. }
  803. prevSort = prevTag.Sort
  804. }
  805. // 下一个兄弟节点
  806. if nextMenuId > 0 {
  807. nextMenu, err = menuOb.GetItemById(nextMenuId)
  808. if err != nil {
  809. errMsg = "移动失败"
  810. err = errors.New("获取下一个兄弟节点目录信息失败,Err:" + err.Error())
  811. return
  812. }
  813. nextSort = nextMenu.Sort
  814. } else if nextTagId > 0 {
  815. nextTag, err = tagOb.GetItemById(nextTagId)
  816. if err != nil {
  817. errMsg = "移动失败"
  818. err = errors.New("获取下一个兄弟节点目录信息失败,Err:" + err.Error())
  819. return
  820. }
  821. nextSort = nextTag.Sort
  822. }
  823. err, errMsg = moveSpeechTagMenu(parentTagMenu, tagMenu, prevMenu, nextMenu, tagItem, prevTag, nextTag, parentMenuId, prevSort, nextSort)
  824. return
  825. }
  826. func moveSpeechTagMenu(parentTagMenu, tagMenu, prevMenu, nextMenu *speech_recognition.SpeechRecognitionTagMenu, tagItem, prevTag, nextTag *speech_recognition.SpeechRecognitionTag, parentMenuId int, prevSort, nextSort int) (err error, errMsg string) {
  827. updateCol := make([]string, 0)
  828. menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
  829. tagOb := new(speech_recognition.SpeechRecognitionTag)
  830. // 移动对象为目录, 判断目录是否存在
  831. if tagMenu != nil {
  832. oldParentId := tagMenu.ParentId
  833. oldLevel := tagMenu.Level
  834. var menuIds []int
  835. if oldParentId != parentMenuId {
  836. //更新子目录对应的level
  837. childList, e, m := GetChildSpeechTagMenuByMenuId(tagMenu.SpeechRecognitionTagMenuId)
  838. if e != nil {
  839. errMsg = "移动失败"
  840. err = errors.New("查询子目录失败,Err:" + e.Error() + m)
  841. return
  842. }
  843. if len(childList) > 0 {
  844. for _, v := range childList {
  845. if v.SpeechRecognitionTagMenuId == tagMenu.SpeechRecognitionTagMenuId {
  846. continue
  847. }
  848. menuIds = append(menuIds, v.SpeechRecognitionTagMenuId)
  849. }
  850. }
  851. }
  852. //判断上级id是否一致,如果不一致的话,那么需要移动该目录层级
  853. if tagMenu.ParentId != parentMenuId && parentMenuId != 0 {
  854. if tagMenu.Level != parentTagMenu.Level+1 { //禁止层级调整
  855. errMsg = "移动失败"
  856. err = errors.New("不支持目录层级变更")
  857. return
  858. }
  859. tagMenu.ParentId = parentTagMenu.SpeechRecognitionTagMenuId
  860. tagMenu.RootId = parentTagMenu.RootId
  861. tagMenu.Level = parentTagMenu.Level + 1
  862. tagMenu.ModifyTime = time.Now()
  863. updateCol = append(updateCol, "ParentId", "RootId", "Level", "ModifyTime")
  864. } else if tagMenu.ParentId != parentMenuId && parentMenuId == 0 {
  865. errMsg = "移动失败"
  866. err = errors.New("不支持目录层级变更")
  867. return
  868. }
  869. if prevSort > 0 {
  870. //如果是移动在两个兄弟节点之间
  871. if nextSort > 0 {
  872. //下一个兄弟节点
  873. //如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
  874. if prevSort == nextSort || prevSort == tagMenu.Sort {
  875. //变更兄弟节点的排序
  876. updateSortStr := `sort + 2`
  877. //变更目录
  878. if prevMenu != nil {
  879. _ = menuOb.UpdateSortByParentId(parentMenuId, prevMenu.SpeechRecognitionTagMenuId, prevMenu.Sort, updateSortStr)
  880. } else {
  881. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, prevSort, updateSortStr)
  882. }
  883. //变更标签
  884. if prevTag != nil {
  885. //变更兄弟节点的排序
  886. _ = tagOb.UpdateSortByMenuId(parentMenuId, prevSort, prevTag.SpeechRecognitionTagId, updateSortStr)
  887. } else {
  888. _ = tagOb.UpdateSortByMenuId(parentMenuId, prevSort, 0, updateSortStr)
  889. }
  890. } else {
  891. //如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
  892. if nextSort-prevSort == 1 {
  893. //变更兄弟节点的排序
  894. updateSortStr := `sort + 1`
  895. //变更目录
  896. if prevMenu != nil {
  897. _ = menuOb.UpdateSortByParentId(parentMenuId, prevMenu.SpeechRecognitionTagMenuId, prevSort, updateSortStr)
  898. } else {
  899. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, prevSort, updateSortStr)
  900. }
  901. //变更标签
  902. if prevTag != nil {
  903. //变更兄弟节点的排序
  904. _ = tagOb.UpdateSortByMenuId(parentMenuId, prevSort, prevTag.SpeechRecognitionTagId, updateSortStr)
  905. } else {
  906. _ = tagOb.UpdateSortByMenuId(parentMenuId, prevSort, 0, updateSortStr)
  907. }
  908. }
  909. }
  910. }
  911. tagMenu.Sort = prevSort + 1
  912. tagMenu.ModifyTime = time.Now()
  913. updateCol = append(updateCol, "Sort", "ModifyTime")
  914. } else if prevMenu == nil && nextMenu == nil && prevTag == nil && nextTag == nil && parentMenuId > 0 {
  915. //处理只拖动到目录里,默认放到目录底部的情况
  916. var maxSort int
  917. maxSort, err = GetSpeechTagMenuMaxSort(parentMenuId)
  918. if err != nil {
  919. errMsg = "移动失败"
  920. err = errors.New("查询组内排序信息失败,Err:" + err.Error())
  921. return
  922. }
  923. tagMenu.Sort = maxSort + 1 //那就是排在组内最后一位
  924. tagMenu.ModifyTime = time.Now()
  925. updateCol = append(updateCol, "Sort", "ModifyTime")
  926. } else {
  927. // 拖动到父级目录的第一位
  928. firstTagMenu, tmpErr := menuOb.GetFirstByParentId(parentMenuId)
  929. if tmpErr != nil && !utils.IsErrNoRow(tmpErr) {
  930. errMsg = "移动失败"
  931. err = errors.New("获取获取当前父级目录下的排序第一条的目录信息失败,Err:" + tmpErr.Error())
  932. return
  933. }
  934. //如果该目录下存在其他目录,且第一个其他目录的排序等于0,那么需要调整排序
  935. if firstTagMenu != nil && firstTagMenu.Sort == 0 {
  936. updateSortStr := ` sort + 1 `
  937. _ = menuOb.UpdateSortByParentId(parentMenuId, firstTagMenu.SpeechRecognitionTagMenuId-1, 0, updateSortStr)
  938. //该目录下的所有标签也需要+1
  939. _ = tagOb.UpdateSortByMenuId(parentMenuId, 0, 0, updateSortStr)
  940. } else {
  941. //如果该目录下存在标签,且第一个标签的排序等于0,那么需要调整排序
  942. firstTag, tErr := tagOb.GetFirstByMenuId(parentMenuId)
  943. if tErr != nil && !utils.IsErrNoRow(tErr) {
  944. errMsg = "移动失败"
  945. err = errors.New("获取获取当前父级目录下的排序第一条的目录信息失败,Err:" + tErr.Error())
  946. return
  947. }
  948. //如果该目录下存在其他目录,且第一个其他目录的排序等于0,那么需要调整排序
  949. if firstTag != nil && firstTag.Sort == 0 {
  950. updateSortStr := ` sort + 1 `
  951. _ = tagOb.UpdateSortByMenuId(parentMenuId, 0, firstTag.SpeechRecognitionTagId-1, updateSortStr)
  952. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, 0, updateSortStr)
  953. }
  954. }
  955. tagMenu.Sort = 0 //那就是排在第一位
  956. tagMenu.ModifyTime = time.Now()
  957. updateCol = append(updateCol, "Sort", "ModifyTime")
  958. }
  959. //更新
  960. if len(updateCol) > 0 {
  961. err = tagMenu.Update(updateCol)
  962. if err != nil {
  963. errMsg = "移动失败"
  964. err = errors.New("修改失败,Err:" + err.Error())
  965. return
  966. }
  967. //更新对应目录的root_id和层级
  968. if oldParentId != parentMenuId {
  969. if len(menuIds) > 0 {
  970. levelStep := tagMenu.Level - oldLevel
  971. err = menuOb.UpdateChildByParentMenuId(menuIds, tagMenu.RootId, levelStep)
  972. if err != nil {
  973. errMsg = "移动失败"
  974. err = errors.New("更新子目录失败,Err:" + err.Error())
  975. return
  976. }
  977. }
  978. }
  979. }
  980. } else {
  981. if tagItem == nil {
  982. errMsg = "当前标签不存在"
  983. err = errors.New(errMsg)
  984. return
  985. }
  986. //如果改变了目录,那么移动该标签数据
  987. if tagItem.MenuId != parentMenuId {
  988. tagItem.MenuId = parentMenuId
  989. tagItem.ModifyTime = time.Now()
  990. updateCol = append(updateCol, speech_recognition.SpeechRecognitionTagCols.MenuId, speech_recognition.SpeechRecognitionTagCols.ModifyTime)
  991. }
  992. if prevSort > 0 {
  993. //如果是移动在两个兄弟节点之间
  994. if nextSort > 0 {
  995. //下一个兄弟节点
  996. //如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
  997. if prevSort == nextSort || prevSort == tagItem.Sort {
  998. //变更兄弟节点的排序
  999. updateSortStr := `sort + 2`
  1000. //变更目录
  1001. if prevMenu != nil {
  1002. _ = menuOb.UpdateSortByParentId(parentMenuId, prevMenu.SpeechRecognitionTagMenuId, prevMenu.Sort, updateSortStr)
  1003. } else {
  1004. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, prevSort, updateSortStr)
  1005. }
  1006. //变更标签
  1007. if prevTag != nil {
  1008. //变更兄弟节点的排序
  1009. _ = tagOb.UpdateSortByMenuId(parentMenuId, prevSort, prevTag.SpeechRecognitionTagId, updateSortStr)
  1010. } else {
  1011. _ = tagOb.UpdateSortByMenuId(parentMenuId, prevSort, 0, updateSortStr)
  1012. }
  1013. } else {
  1014. //如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
  1015. if nextSort-prevSort == 1 {
  1016. //变更兄弟节点的排序
  1017. updateSortStr := `sort + 1`
  1018. //变更目录
  1019. if prevMenu != nil {
  1020. _ = menuOb.UpdateSortByParentId(parentMenuId, prevMenu.SpeechRecognitionTagMenuId, prevSort, updateSortStr)
  1021. } else {
  1022. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, prevSort, updateSortStr)
  1023. }
  1024. //变更标签
  1025. if prevTag != nil {
  1026. //变更兄弟节点的排序
  1027. _ = tagOb.UpdateSortByMenuId(parentMenuId, prevSort, prevTag.SpeechRecognitionTagId, updateSortStr)
  1028. } else {
  1029. _ = tagOb.UpdateSortByMenuId(parentMenuId, prevSort, 0, updateSortStr)
  1030. }
  1031. }
  1032. }
  1033. }
  1034. tagItem.Sort = prevSort + 1
  1035. tagItem.ModifyTime = time.Now()
  1036. updateCol = append(updateCol, "Sort", "ModifyTime")
  1037. } else if prevMenu == nil && nextMenu == nil && prevTag == nil && nextTag == nil && parentMenuId > 0 {
  1038. //处理只拖动到目录里,默认放到目录底部的情况
  1039. var maxSort int
  1040. maxSort, err = GetSpeechTagMenuMaxSort(parentMenuId)
  1041. if err != nil {
  1042. errMsg = "移动失败"
  1043. err = errors.New("查询组内排序信息失败,Err:" + err.Error())
  1044. return
  1045. }
  1046. tagItem.Sort = maxSort + 1 //那就是排在组内最后一位
  1047. tagItem.ModifyTime = time.Now()
  1048. updateCol = append(updateCol, "Sort", "ModifyTime")
  1049. } else {
  1050. // 拖动到父级目录的第一位
  1051. firstTagMenu, tmpErr := menuOb.GetFirstByParentId(parentMenuId)
  1052. if tmpErr != nil && !utils.IsErrNoRow(tmpErr) {
  1053. errMsg = "移动失败"
  1054. err = errors.New("获取获取当前父级目录下的排序第一条的目录信息失败,Err:" + tmpErr.Error())
  1055. return
  1056. }
  1057. //如果该目录下存在其他目录,且第一个其他目录的排序等于0,那么需要调整排序
  1058. if firstTagMenu != nil && firstTagMenu.Sort == 0 {
  1059. updateSortStr := ` sort + 1 `
  1060. _ = menuOb.UpdateSortByParentId(parentMenuId, firstTagMenu.SpeechRecognitionTagMenuId-1, 0, updateSortStr)
  1061. //该目录下的所有标签也需要+1
  1062. _ = tagOb.UpdateSortByMenuId(parentMenuId, 0, 0, updateSortStr)
  1063. } else {
  1064. //如果该目录下存在标签,且第一个标签的排序等于0,那么需要调整排序
  1065. firstTag, tErr := tagOb.GetFirstByMenuId(parentMenuId)
  1066. if tErr != nil && !utils.IsErrNoRow(tErr) {
  1067. errMsg = "移动失败"
  1068. err = errors.New("获取获取当前父级目录下的排序第一条的目录信息失败,Err:" + tErr.Error())
  1069. return
  1070. }
  1071. //如果该目录下存在其他目录,且第一个其他目录的排序等于0,那么需要调整排序
  1072. if firstTag != nil && firstTag.Sort == 0 {
  1073. updateSortStr := ` sort + 1 `
  1074. _ = tagOb.UpdateSortByMenuId(parentMenuId, 0, firstTag.SpeechRecognitionTagId-1, updateSortStr)
  1075. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, 0, updateSortStr)
  1076. }
  1077. }
  1078. tagItem.Sort = 0 //那就是排在第一位
  1079. tagItem.ModifyTime = time.Now()
  1080. updateCol = append(updateCol, "Sort", "ModifyTime")
  1081. }
  1082. //更新
  1083. if len(updateCol) > 0 {
  1084. err = tagItem.Update(updateCol)
  1085. if err != nil {
  1086. errMsg = "移动失败"
  1087. err = errors.New("修改失败,Err:" + err.Error())
  1088. return
  1089. }
  1090. }
  1091. }
  1092. return
  1093. }
  1094. func GetChildSpeechTagMenuByMenuId(menuId int) (targetList []*speech_recognition.SpeechRecognitionTagMenu, err error, errMsg string) {
  1095. menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
  1096. //判断是否是挂在顶级目录下
  1097. tagMenu, err := menuOb.GetItemById(menuId)
  1098. if err != nil {
  1099. if utils.IsErrNoRow(err) {
  1100. errMsg = "当前目录不存在"
  1101. err = errors.New(errMsg)
  1102. return
  1103. }
  1104. errMsg = "获取失败"
  1105. err = errors.New("获取目录信息失败,Err:" + err.Error())
  1106. return
  1107. }
  1108. cond := fmt.Sprintf(" AND %s = ?", speech_recognition.SpeechRecognitionTagMenuCols.RootId)
  1109. pars := make([]interface{}, 0)
  1110. pars = append(pars, tagMenu.RootId)
  1111. order := fmt.Sprintf("%s ASC, %s ASC, %s ASC", speech_recognition.SpeechRecognitionTagMenuCols.Level, speech_recognition.SpeechRecognitionTagMenuCols.Sort, speech_recognition.SpeechRecognitionTagMenuCols.SpeechRecognitionTagMenuId)
  1112. tmpList, err := tagMenu.GetItemsByCondition(cond, pars, []string{}, order)
  1113. if err != nil && !utils.IsErrNoRow(err) {
  1114. errMsg = "获取失败"
  1115. err = errors.New("获取数据失败,Err:" + err.Error())
  1116. return
  1117. }
  1118. idMap := make(map[int]struct{})
  1119. if len(tmpList) > 0 {
  1120. for _, v := range tmpList {
  1121. if v.SpeechRecognitionTagMenuId == tagMenu.SpeechRecognitionTagMenuId {
  1122. idMap[v.SpeechRecognitionTagMenuId] = struct{}{}
  1123. }
  1124. }
  1125. for _, v := range tmpList {
  1126. if _, ok := idMap[v.ParentId]; ok {
  1127. idMap[v.SpeechRecognitionTagMenuId] = struct{}{}
  1128. }
  1129. }
  1130. for _, v := range tmpList {
  1131. if _, ok := idMap[v.SpeechRecognitionTagMenuId]; ok {
  1132. targetList = append(targetList, v)
  1133. }
  1134. }
  1135. }
  1136. return
  1137. }
  1138. // GetSpeechTagMenuMaxSort 获取同级下最大的排序
  1139. func GetSpeechTagMenuMaxSort(parentId int) (maxSort int, err error) {
  1140. menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
  1141. tagOb := new(speech_recognition.SpeechRecognitionTag)
  1142. //获取该层级下最大的排序数
  1143. menuMax, err := menuOb.GetMaxSortByParentId(parentId)
  1144. if err != nil {
  1145. return
  1146. }
  1147. maxSort = menuMax
  1148. speechMax, err := tagOb.GetMaxSortByMenuId(parentId)
  1149. if err != nil {
  1150. return
  1151. }
  1152. if maxSort < speechMax {
  1153. maxSort = speechMax
  1154. }
  1155. return
  1156. }
  1157. // ------------------ 移动标签目录/标签 ------------------ //
  1158. // GetSpeechRecognitionMenuChildrenRecursive 递归获取目录的子目录集
  1159. func GetSpeechRecognitionMenuChildrenRecursive(list []*speech_recognition.SpeechRecognitionMenu, parentId int) []int {
  1160. childIds := make([]int, 0)
  1161. for _, v := range list {
  1162. if v.ParentId == parentId {
  1163. childIds = append(childIds, v.SpeechRecognitionMenuId)
  1164. ids := GetSpeechRecognitionMenuChildrenRecursive(list, v.SpeechRecognitionMenuId)
  1165. if len(ids) > 0 {
  1166. childIds = append(childIds, ids...)
  1167. }
  1168. }
  1169. }
  1170. return childIds
  1171. }
  1172. // GetSpeechRecognitionTagMenuChildrenRecursive 递归获取标签目录的子目录集
  1173. func GetSpeechRecognitionTagMenuChildrenRecursive(list []*speech_recognition.SpeechRecognitionTagMenu, parentId int) []int {
  1174. childIds := make([]int, 0)
  1175. for _, v := range list {
  1176. if v.ParentId == parentId {
  1177. childIds = append(childIds, v.SpeechRecognitionTagMenuId)
  1178. ids := GetSpeechRecognitionTagMenuChildrenRecursive(list, v.SpeechRecognitionTagMenuId)
  1179. if len(ids) > 0 {
  1180. childIds = append(childIds, ids...)
  1181. }
  1182. }
  1183. }
  1184. return childIds
  1185. }
  1186. // CheckSpeechRecognitionMenuRemove 校验是否可删除目录
  1187. func CheckSpeechRecognitionMenuRemove(menuId int) (result *speech_recognition.SpeechRecognitionMenuRemoveCheckResp, menuIds []int, err error) {
  1188. menuOb := new(speech_recognition.SpeechRecognitionMenu)
  1189. result = new(speech_recognition.SpeechRecognitionMenuRemoveCheckResp)
  1190. // 递归获取目录的子目录集合
  1191. menus, e := menuOb.GetItemsByCondition(``, make([]interface{}, 0), []string{}, "")
  1192. if e != nil {
  1193. err = fmt.Errorf("获取语音识别目录列表失败, err: %s", e.Error())
  1194. return
  1195. }
  1196. childIds := GetSpeechRecognitionMenuChildrenRecursive(menus, menuId)
  1197. menuIds = make([]int, 0)
  1198. menuIds = append(menuIds, menuId)
  1199. if len(childIds) > 0 {
  1200. menuIds = append(menuIds, childIds...)
  1201. }
  1202. // 校验目录下(包含子目录)是否有内容
  1203. speechOb := new(speech_recognition.SpeechRecognition)
  1204. cond := fmt.Sprintf(` AND %s IN (%s)`, speech_recognition.SpeechRecognitionCols.MenuId, utils.GetOrmInReplace(len(menuIds)))
  1205. pars := make([]interface{}, 0)
  1206. pars = append(pars, menuIds)
  1207. count, e := speechOb.GetCountByCondition(cond, pars)
  1208. if e != nil {
  1209. err = fmt.Errorf("获取目录下的语音识别数失败, err: %s", e.Error())
  1210. return
  1211. }
  1212. if count > 0 {
  1213. result.CheckResult = SpeechMenuCheckRemoveTypeRefused
  1214. result.Tips = "该分类关联转写文件,删除失败!"
  1215. return
  1216. }
  1217. // 如果无语音识别, 但存在子目录, 则返回第二种提示
  1218. if len(childIds) > 0 {
  1219. result.CheckResult = SpeechMenuCheckRemoveTypeWarning
  1220. result.Tips = "该分类包含内容为空的子分类"
  1221. return
  1222. }
  1223. // 通过校验
  1224. result.Tips = "校验通过,可以删除"
  1225. return
  1226. }
  1227. // CheckSpeechRecognitionTagMenuRemove 校验是否可删除标签目录
  1228. func CheckSpeechRecognitionTagMenuRemove(menuId int) (result *speech_recognition.SpeechRecognitionMenuRemoveCheckResp, menuIds []int, err error) {
  1229. menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
  1230. result = new(speech_recognition.SpeechRecognitionMenuRemoveCheckResp)
  1231. // 递归获取目录的子目录集合
  1232. menus, e := menuOb.GetItemsByCondition(``, make([]interface{}, 0), []string{}, "")
  1233. if e != nil {
  1234. err = fmt.Errorf("获取标签目录列表失败, err: %s", e.Error())
  1235. return
  1236. }
  1237. childIds := GetSpeechRecognitionTagMenuChildrenRecursive(menus, menuId)
  1238. menuIds = make([]int, 0)
  1239. menuIds = append(menuIds, menuId)
  1240. if len(childIds) > 0 {
  1241. menuIds = append(menuIds, childIds...)
  1242. }
  1243. // 校验目录下(包含子目录)是否有内容
  1244. tagOb := new(speech_recognition.SpeechRecognitionTag)
  1245. cond := fmt.Sprintf(` AND %s IN (%s)`, speech_recognition.SpeechRecognitionTagCols.MenuId, utils.GetOrmInReplace(len(menuIds)))
  1246. pars := make([]interface{}, 0)
  1247. pars = append(pars, menuIds)
  1248. count, e := tagOb.GetCountByCondition(cond, pars)
  1249. if e != nil {
  1250. err = fmt.Errorf("获取目录下的标签数失败, err: %s", e.Error())
  1251. return
  1252. }
  1253. if count > 0 {
  1254. result.CheckResult = SpeechMenuCheckRemoveTypeRefused
  1255. result.Tips = "该分类关联标签,删除失败!"
  1256. return
  1257. }
  1258. // 如果无内容, 但存在子目录, 则返回第二种提示
  1259. if len(childIds) > 0 {
  1260. result.CheckResult = SpeechMenuCheckRemoveTypeWarning
  1261. result.Tips = "该分类包含内容为空的子分类"
  1262. return
  1263. }
  1264. // 通过校验
  1265. result.Tips = "校验通过,可以删除"
  1266. return
  1267. }
  1268. // GetSpeechRecognitionMenuPathRecursive 根据子目录递归获取目录树
  1269. func GetSpeechRecognitionMenuPathRecursive(list []*speech_recognition.SpeechRecognitionMenu, menuId int) []*speech_recognition.SpeechRecognitionMenuItem {
  1270. res := make([]*speech_recognition.SpeechRecognitionMenuItem, 0)
  1271. for _, v := range list {
  1272. if v.SpeechRecognitionMenuId == menuId {
  1273. t := new(speech_recognition.SpeechRecognitionMenuItem)
  1274. t.UniqueCode = v.UniqueCode
  1275. t.MenuId = v.SpeechRecognitionMenuId
  1276. t.MenuName = v.MenuName
  1277. t.ParentId = v.ParentId
  1278. t.Level = v.Level
  1279. t.Sort = v.Sort
  1280. t.CreateTime = utils.TimeTransferString(utils.FormatDateTime, v.CreateTime)
  1281. if v.ParentId > 0 {
  1282. res = GetSpeechRecognitionMenuPathRecursive(list, v.ParentId)
  1283. }
  1284. res = append(res, t)
  1285. }
  1286. }
  1287. return res
  1288. }