speech_recognition.go 42 KB

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