speech_recognition.go 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404
  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_gn/eta_api/models"
  9. "eta_gn/eta_api/models/speech_recognition"
  10. "eta_gn/eta_api/services/alarm_msg"
  11. "eta_gn/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 err.Error() == utils.ErrNoRow() {
  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 && e.Error() != utils.ErrNoRow() {
  300. errMsg = "移动失败"
  301. err = fmt.Errorf("获取父级目录下的同名目录失败, Err: %s", e.Error())
  302. return
  303. }
  304. if exists != nil {
  305. errMsg = "移动失败,目录名称已存在"
  306. return
  307. }
  308. }
  309. } else {
  310. speechItem, err = speechOb.GetItemById(speechId)
  311. if err != nil {
  312. if err.Error() == utils.ErrNoRow() {
  313. errMsg = "当前语音识别不存在"
  314. err = errors.New("获取目录信息失败,Err:" + err.Error())
  315. return
  316. }
  317. errMsg = "移动失败"
  318. err = errors.New("获取目录信息失败,Err:" + err.Error())
  319. return
  320. }
  321. if parentMenuId == 0 {
  322. errMsg = "移动失败,语音识别必须挂在目录下"
  323. err = errors.New(errMsg)
  324. return
  325. }
  326. }
  327. if prevMenuId > 0 {
  328. prevMenu, err = menuOb.GetItemById(prevMenuId)
  329. if err != nil {
  330. errMsg = "移动失败"
  331. err = errors.New("获取上一个兄弟节点目录信息失败,Err:" + err.Error())
  332. return
  333. }
  334. prevSort = prevMenu.Sort
  335. } else if prevSpeechId > 0 {
  336. prevSpeech, err = speechOb.GetItemById(prevSpeechId)
  337. if err != nil {
  338. errMsg = "移动失败"
  339. err = errors.New("获取上一个兄弟节点信息失败,Err:" + err.Error())
  340. return
  341. }
  342. prevSort = prevSpeech.Sort
  343. }
  344. // 下一个兄弟节点
  345. if nextMenuId > 0 {
  346. nextMenu, err = menuOb.GetItemById(nextMenuId)
  347. if err != nil {
  348. errMsg = "移动失败"
  349. err = errors.New("获取下一个兄弟节点目录信息失败,Err:" + err.Error())
  350. return
  351. }
  352. nextSort = nextMenu.Sort
  353. } else if nextSpeechId > 0 {
  354. nextSpeech, err = speechOb.GetItemById(nextSpeechId)
  355. if err != nil {
  356. errMsg = "移动失败"
  357. err = errors.New("获取下一个兄弟节点目录信息失败,Err:" + err.Error())
  358. return
  359. }
  360. nextSort = nextSpeech.Sort
  361. }
  362. err, errMsg = moveSpeechMenu(parentSpeechMenu, speechMenu, prevMenu, nextMenu, speechItem, prevSpeech, nextSpeech, parentMenuId, prevSort, nextSort)
  363. return
  364. }
  365. func moveSpeechMenu(parentSpeechMenu, speechMenu, prevMenu, nextMenu *speech_recognition.SpeechRecognitionMenu, speechItem, prevSpeech, nextSpeech *speech_recognition.SpeechRecognition, parentMenuId int, prevSort, nextSort int) (err error, errMsg string) {
  366. updateCol := make([]string, 0)
  367. menuOb := new(speech_recognition.SpeechRecognitionMenu)
  368. speechOb := new(speech_recognition.SpeechRecognition)
  369. // 移动对象为目录, 判断目录是否存在
  370. if speechMenu != nil {
  371. oldParentId := speechMenu.ParentId
  372. oldLevel := speechMenu.Level
  373. var menuIds []int
  374. if oldParentId != parentMenuId {
  375. //更新子目录对应的level
  376. childList, e, m := GetChildSpeechMenuByMenuId(speechMenu.SpeechRecognitionMenuId)
  377. if e != nil {
  378. errMsg = "移动失败"
  379. err = errors.New("查询子目录失败,Err:" + e.Error() + m)
  380. return
  381. }
  382. if len(childList) > 0 {
  383. for _, v := range childList {
  384. if v.SpeechRecognitionMenuId == speechMenu.SpeechRecognitionMenuId {
  385. continue
  386. }
  387. menuIds = append(menuIds, v.SpeechRecognitionMenuId)
  388. }
  389. }
  390. }
  391. //判断上级id是否一致,如果不一致的话,那么需要移动该目录层级
  392. if speechMenu.ParentId != parentMenuId && parentMenuId != 0 {
  393. if speechMenu.Level != parentSpeechMenu.Level+1 { //禁止层级调整
  394. errMsg = "移动失败"
  395. err = errors.New("不支持目录层级变更")
  396. return
  397. }
  398. speechMenu.ParentId = parentSpeechMenu.SpeechRecognitionMenuId
  399. speechMenu.RootId = parentSpeechMenu.RootId
  400. speechMenu.Level = parentSpeechMenu.Level + 1
  401. speechMenu.ModifyTime = time.Now()
  402. updateCol = append(updateCol, "ParentId", "RootId", "Level", "ModifyTime")
  403. } else if speechMenu.ParentId != parentMenuId && parentMenuId == 0 {
  404. errMsg = "移动失败"
  405. err = errors.New("不支持目录层级变更")
  406. return
  407. }
  408. if prevSort > 0 {
  409. //如果是移动在两个兄弟节点之间
  410. if nextSort > 0 {
  411. //下一个兄弟节点
  412. //如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
  413. if prevSort == nextSort || prevSort == speechMenu.Sort {
  414. //变更兄弟节点的排序
  415. updateSortStr := `sort + 2`
  416. //变更目录
  417. if prevMenu != nil {
  418. _ = menuOb.UpdateSortByParentId(parentMenuId, prevMenu.SpeechRecognitionMenuId, prevMenu.Sort, updateSortStr)
  419. } else {
  420. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, prevSort, updateSortStr)
  421. }
  422. //变更语音识别
  423. if prevSpeech != nil {
  424. //变更兄弟节点的排序
  425. _ = speechOb.UpdateSortByMenuId(parentMenuId, prevSort, prevSpeech.SpeechRecognitionId, updateSortStr)
  426. } else {
  427. _ = speechOb.UpdateSortByMenuId(parentMenuId, prevSort, 0, updateSortStr)
  428. }
  429. } else {
  430. //如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
  431. if nextSort-prevSort == 1 {
  432. //变更兄弟节点的排序
  433. updateSortStr := `sort + 1`
  434. //变更目录
  435. if prevMenu != nil {
  436. _ = menuOb.UpdateSortByParentId(parentMenuId, prevMenu.SpeechRecognitionMenuId, prevSort, updateSortStr)
  437. } else {
  438. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, prevSort, updateSortStr)
  439. }
  440. //变更语音识别
  441. if prevSpeech != nil {
  442. //变更兄弟节点的排序
  443. _ = speechOb.UpdateSortByMenuId(parentMenuId, prevSort, prevSpeech.SpeechRecognitionId, updateSortStr)
  444. } else {
  445. _ = speechOb.UpdateSortByMenuId(parentMenuId, prevSort, 0, updateSortStr)
  446. }
  447. }
  448. }
  449. }
  450. speechMenu.Sort = prevSort + 1
  451. speechMenu.ModifyTime = time.Now()
  452. updateCol = append(updateCol, "Sort", "ModifyTime")
  453. } else if prevMenu == nil && nextMenu == nil && prevSpeech == nil && nextSpeech == nil && parentMenuId > 0 {
  454. //处理只拖动到目录里,默认放到目录底部的情况
  455. var maxSort int
  456. maxSort, err = GetSpeechMenuMaxSort(parentMenuId)
  457. if err != nil {
  458. errMsg = "移动失败"
  459. err = errors.New("查询组内排序信息失败,Err:" + err.Error())
  460. return
  461. }
  462. speechMenu.Sort = maxSort + 1 //那就是排在组内最后一位
  463. speechMenu.ModifyTime = time.Now()
  464. updateCol = append(updateCol, "Sort", "ModifyTime")
  465. } else {
  466. // 拖动到父级目录的第一位
  467. firstMenu, tmpErr := menuOb.GetFirstByParentId(parentMenuId)
  468. if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
  469. errMsg = "移动失败"
  470. err = errors.New("获取获取当前父级目录下的排序第一条的目录信息失败,Err:" + tmpErr.Error())
  471. return
  472. }
  473. //如果该目录下存在其他目录,且第一个其他目录的排序等于0,那么需要调整排序
  474. if firstMenu != nil && firstMenu.Sort == 0 {
  475. updateSortStr := ` sort + 1 `
  476. _ = menuOb.UpdateSortByParentId(parentMenuId, firstMenu.SpeechRecognitionMenuId-1, 0, updateSortStr)
  477. //该目录下的所有语音识别也需要+1
  478. _ = speechOb.UpdateSortByMenuId(parentMenuId, 0, 0, updateSortStr)
  479. } else {
  480. //如果该目录下存在语音识别,且第一个语音识别的排序等于0,那么需要调整排序
  481. firstSpeech, tErr := speechOb.GetFirstByMenuId(parentMenuId)
  482. if tErr != nil && tErr.Error() != utils.ErrNoRow() {
  483. errMsg = "移动失败"
  484. err = errors.New("获取获取当前父级目录下的排序第一条的目录信息失败,Err:" + tErr.Error())
  485. return
  486. }
  487. //如果该目录下存在其他目录,且第一个其他目录的排序等于0,那么需要调整排序
  488. if firstSpeech != nil && firstSpeech.Sort == 0 {
  489. updateSortStr := ` sort + 1 `
  490. _ = speechOb.UpdateSortByMenuId(parentMenuId, 0, firstSpeech.SpeechRecognitionId-1, updateSortStr)
  491. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, 0, updateSortStr)
  492. }
  493. }
  494. speechMenu.Sort = 0 //那就是排在第一位
  495. speechMenu.ModifyTime = time.Now()
  496. updateCol = append(updateCol, "Sort", "ModifyTime")
  497. }
  498. //更新
  499. if len(updateCol) > 0 {
  500. err = speechMenu.Update(updateCol)
  501. if err != nil {
  502. errMsg = "移动失败"
  503. err = errors.New("修改失败,Err:" + err.Error())
  504. return
  505. }
  506. //更新对应目录的root_id和层级
  507. if oldParentId != parentMenuId {
  508. if len(menuIds) > 0 {
  509. levelStep := speechMenu.Level - oldLevel
  510. err = menuOb.UpdateChildByParentMenuId(menuIds, speechMenu.RootId, levelStep)
  511. if err != nil {
  512. errMsg = "移动失败"
  513. err = errors.New("更新子目录失败,Err:" + err.Error())
  514. return
  515. }
  516. }
  517. }
  518. }
  519. } else {
  520. if speechItem == nil {
  521. errMsg = "当前语音识别不存在"
  522. err = errors.New(errMsg)
  523. return
  524. }
  525. //如果改变了目录,那么移动该语音识别数据
  526. if speechItem.MenuId != parentMenuId {
  527. speechItem.MenuId = parentMenuId
  528. speechItem.ModifyTime = time.Now()
  529. updateCol = append(updateCol, speech_recognition.SpeechRecognitionCols.MenuId, speech_recognition.SpeechRecognitionCols.ModifyTime)
  530. }
  531. if prevSort > 0 {
  532. //如果是移动在两个兄弟节点之间
  533. if nextSort > 0 {
  534. //下一个兄弟节点
  535. //如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
  536. if prevSort == nextSort || prevSort == speechItem.Sort {
  537. //变更兄弟节点的排序
  538. updateSortStr := `sort + 2`
  539. //变更目录
  540. if prevMenu != nil {
  541. _ = menuOb.UpdateSortByParentId(parentMenuId, prevMenu.SpeechRecognitionMenuId, prevMenu.Sort, updateSortStr)
  542. } else {
  543. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, prevSort, updateSortStr)
  544. }
  545. //变更语音识别
  546. if prevSpeech != nil {
  547. //变更兄弟节点的排序
  548. _ = speechOb.UpdateSortByMenuId(parentMenuId, prevSort, prevSpeech.SpeechRecognitionId, updateSortStr)
  549. } else {
  550. _ = speechOb.UpdateSortByMenuId(parentMenuId, prevSort, 0, updateSortStr)
  551. }
  552. } else {
  553. //如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
  554. if nextSort-prevSort == 1 {
  555. //变更兄弟节点的排序
  556. updateSortStr := `sort + 1`
  557. //变更目录
  558. if prevMenu != nil {
  559. _ = menuOb.UpdateSortByParentId(parentMenuId, prevMenu.SpeechRecognitionMenuId, prevSort, updateSortStr)
  560. } else {
  561. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, prevSort, updateSortStr)
  562. }
  563. //变更语音识别
  564. if prevSpeech != nil {
  565. //变更兄弟节点的排序
  566. _ = speechOb.UpdateSortByMenuId(parentMenuId, prevSort, prevSpeech.SpeechRecognitionId, updateSortStr)
  567. } else {
  568. _ = speechOb.UpdateSortByMenuId(parentMenuId, prevSort, 0, updateSortStr)
  569. }
  570. }
  571. }
  572. }
  573. speechItem.Sort = prevSort + 1
  574. speechItem.ModifyTime = time.Now()
  575. updateCol = append(updateCol, "Sort", "ModifyTime")
  576. } else if prevMenu == nil && nextMenu == nil && prevSpeech == nil && nextSpeech == nil && parentMenuId > 0 {
  577. //处理只拖动到目录里,默认放到目录底部的情况
  578. var maxSort int
  579. maxSort, err = GetSpeechMenuMaxSort(parentMenuId)
  580. if err != nil {
  581. errMsg = "移动失败"
  582. err = errors.New("查询组内排序信息失败,Err:" + err.Error())
  583. return
  584. }
  585. speechItem.Sort = maxSort + 1 //那就是排在组内最后一位
  586. speechItem.ModifyTime = time.Now()
  587. updateCol = append(updateCol, "Sort", "ModifyTime")
  588. } else {
  589. // 拖动到父级目录的第一位
  590. firstMenu, tmpErr := menuOb.GetFirstByParentId(parentMenuId)
  591. if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
  592. errMsg = "移动失败"
  593. err = errors.New("获取获取当前父级目录下的排序第一条的目录信息失败,Err:" + tmpErr.Error())
  594. return
  595. }
  596. //如果该目录下存在其他目录,且第一个其他目录的排序等于0,那么需要调整排序
  597. if firstMenu != nil && firstMenu.Sort == 0 {
  598. updateSortStr := ` sort + 1 `
  599. _ = menuOb.UpdateSortByParentId(parentMenuId, firstMenu.SpeechRecognitionMenuId-1, 0, updateSortStr)
  600. //该目录下的所有语音识别也需要+1
  601. _ = speechOb.UpdateSortByMenuId(parentMenuId, 0, 0, updateSortStr)
  602. } else {
  603. //如果该目录下存在语音识别,且第一个语音识别的排序等于0,那么需要调整排序
  604. firstSpeech, tErr := speechOb.GetFirstByMenuId(parentMenuId)
  605. if tErr != nil && tErr.Error() != utils.ErrNoRow() {
  606. errMsg = "移动失败"
  607. err = errors.New("获取获取当前父级目录下的排序第一条的目录信息失败,Err:" + tErr.Error())
  608. return
  609. }
  610. //如果该目录下存在其他目录,且第一个其他目录的排序等于0,那么需要调整排序
  611. if firstSpeech != nil && firstSpeech.Sort == 0 {
  612. updateSortStr := ` sort + 1 `
  613. _ = speechOb.UpdateSortByMenuId(parentMenuId, 0, firstSpeech.SpeechRecognitionId-1, updateSortStr)
  614. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, 0, updateSortStr)
  615. }
  616. }
  617. speechItem.Sort = 0 //那就是排在第一位
  618. speechItem.ModifyTime = time.Now()
  619. updateCol = append(updateCol, "Sort", "ModifyTime")
  620. }
  621. //更新
  622. if len(updateCol) > 0 {
  623. err = speechItem.Update(updateCol)
  624. if err != nil {
  625. errMsg = "移动失败"
  626. err = errors.New("修改失败,Err:" + err.Error())
  627. return
  628. }
  629. }
  630. }
  631. return
  632. }
  633. func GetChildSpeechMenuByMenuId(menuId int) (targetList []*speech_recognition.SpeechRecognitionMenu, err error, errMsg string) {
  634. menuOb := new(speech_recognition.SpeechRecognitionMenu)
  635. //判断是否是挂在顶级目录下
  636. speechMenu, err := menuOb.GetItemById(menuId)
  637. if err != nil {
  638. if err.Error() == utils.ErrNoRow() {
  639. errMsg = "当前目录不存在"
  640. err = errors.New(errMsg)
  641. return
  642. }
  643. errMsg = "获取失败"
  644. err = errors.New("获取目录信息失败,Err:" + err.Error())
  645. return
  646. }
  647. cond := fmt.Sprintf(" AND %s = ?", speech_recognition.SpeechRecognitionMenuCols.RootId)
  648. pars := make([]interface{}, 0)
  649. pars = append(pars, speechMenu.RootId)
  650. order := fmt.Sprintf("%s ASC, %s ASC, %s ASC", speech_recognition.SpeechRecognitionMenuCols.Level, speech_recognition.SpeechRecognitionMenuCols.Sort, speech_recognition.SpeechRecognitionMenuCols.SpeechRecognitionMenuId)
  651. tmpList, err := speechMenu.GetItemsByCondition(cond, pars, []string{}, order)
  652. if err != nil && err.Error() != utils.ErrNoRow() {
  653. errMsg = "获取失败"
  654. err = errors.New("获取数据失败,Err:" + err.Error())
  655. return
  656. }
  657. idMap := make(map[int]struct{})
  658. if len(tmpList) > 0 {
  659. for _, v := range tmpList {
  660. if v.SpeechRecognitionMenuId == speechMenu.SpeechRecognitionMenuId {
  661. idMap[v.SpeechRecognitionMenuId] = struct{}{}
  662. }
  663. }
  664. for _, v := range tmpList {
  665. if _, ok := idMap[v.ParentId]; ok {
  666. idMap[v.SpeechRecognitionMenuId] = struct{}{}
  667. }
  668. }
  669. for _, v := range tmpList {
  670. if _, ok := idMap[v.SpeechRecognitionMenuId]; ok {
  671. targetList = append(targetList, v)
  672. }
  673. }
  674. }
  675. return
  676. }
  677. // GetSpeechMenuMaxSort 获取同级下最大的排序
  678. func GetSpeechMenuMaxSort(parentId int) (maxSort int, err error) {
  679. menuOb := new(speech_recognition.SpeechRecognitionMenu)
  680. speechOb := new(speech_recognition.SpeechRecognition)
  681. //获取该层级下最大的排序数
  682. menuMax, err := menuOb.GetMaxSortByParentId(parentId)
  683. if err != nil {
  684. return
  685. }
  686. maxSort = menuMax
  687. speechMax, err := speechOb.GetMaxSortByMenuId(parentId)
  688. if err != nil {
  689. return
  690. }
  691. if maxSort < speechMax {
  692. maxSort = speechMax
  693. }
  694. return
  695. }
  696. // ------------------ 移动目录/语音识别 ------------------ //
  697. // ------------------ 移动标签目录/标签 ------------------ //
  698. // MoveSpeechTagMenu 移动标签目录/标签
  699. func MoveSpeechTagMenu(req speech_recognition.SpeechRecognitionTagMenuMoveReq) (err error, errMsg string) {
  700. menuId := req.MenuId
  701. parentMenuId := req.ParentMenuId
  702. prevMenuId := req.PrevMenuId
  703. nextMenuId := req.NextMenuId
  704. tagId := req.TagId
  705. prevTagId := req.PrevTagId
  706. nextTagId := req.NextTagId
  707. //首先确定移动的对象是目录还是标签
  708. //判断上一个节点是目录还是标签
  709. //判断下一个节点是目录还是标签
  710. //同时更新目录目录下的目录sort和标签sort
  711. //更新当前移动的目录或者标签sort
  712. menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
  713. tagOb := new(speech_recognition.SpeechRecognitionTag)
  714. var parentTagMenu *speech_recognition.SpeechRecognitionTagMenu
  715. if parentMenuId > 0 {
  716. t, e := menuOb.GetItemById(parentMenuId)
  717. if e != nil {
  718. errMsg = "移动失败"
  719. err = errors.New("获取上级目录信息失败,Err:" + err.Error())
  720. return
  721. }
  722. parentTagMenu = t
  723. }
  724. //如果有传入 上一个兄弟节点目录id
  725. var (
  726. tagMenu *speech_recognition.SpeechRecognitionTagMenu
  727. prevMenu *speech_recognition.SpeechRecognitionTagMenu
  728. nextMenu *speech_recognition.SpeechRecognitionTagMenu
  729. tagItem *speech_recognition.SpeechRecognitionTag
  730. prevTag *speech_recognition.SpeechRecognitionTag
  731. nextTag *speech_recognition.SpeechRecognitionTag
  732. prevSort int
  733. nextSort int
  734. )
  735. // 移动对象为目录
  736. if tagId == 0 {
  737. tagMenu, err = menuOb.GetItemById(menuId)
  738. if err != nil {
  739. if err.Error() == utils.ErrNoRow() {
  740. errMsg = "当前目录不存在"
  741. err = errors.New("获取目录信息失败,Err:" + err.Error())
  742. return
  743. }
  744. errMsg = "移动失败"
  745. err = errors.New("获取目录信息失败,Err:" + err.Error())
  746. return
  747. }
  748. if parentMenuId > 0 && parentTagMenu.Level == 3 {
  749. errMsg = "最高只支持添加3级目录"
  750. err = errors.New(errMsg)
  751. return
  752. }
  753. // 如果是移动目录, 那么校验一下父级目录下是否有重名目录
  754. {
  755. cond := fmt.Sprintf(` AND %s = ? AND %s = ? AND %s <> ?`, speech_recognition.SpeechRecognitionTagMenuCols.MenuName, speech_recognition.SpeechRecognitionTagMenuCols.ParentId, speech_recognition.SpeechRecognitionTagMenuCols.SpeechRecognitionTagMenuId)
  756. pars := make([]interface{}, 0)
  757. pars = append(pars, tagMenu.MenuName, parentMenuId, menuId)
  758. exists, e := menuOb.GetItemByCondition(cond, pars, "")
  759. if e != nil && e.Error() != utils.ErrNoRow() {
  760. errMsg = "移动失败"
  761. err = fmt.Errorf("获取父级目录下的同名目录失败, Err: %s", e.Error())
  762. return
  763. }
  764. if exists != nil {
  765. errMsg = "移动失败,目录名称已存在"
  766. return
  767. }
  768. }
  769. } else {
  770. tagItem, err = tagOb.GetItemById(tagId)
  771. if err != nil {
  772. if err.Error() == utils.ErrNoRow() {
  773. errMsg = "当前标签不存在"
  774. err = errors.New("获取目录信息失败,Err:" + err.Error())
  775. return
  776. }
  777. errMsg = "移动失败"
  778. err = errors.New("获取目录信息失败,Err:" + err.Error())
  779. return
  780. }
  781. if parentMenuId == 0 {
  782. errMsg = "移动失败,标签必须挂在目录下"
  783. err = errors.New(errMsg)
  784. return
  785. }
  786. }
  787. if prevMenuId > 0 {
  788. prevMenu, err = menuOb.GetItemById(prevMenuId)
  789. if err != nil {
  790. errMsg = "移动失败"
  791. err = errors.New("获取上一个兄弟节点目录信息失败,Err:" + err.Error())
  792. return
  793. }
  794. prevSort = prevMenu.Sort
  795. } else if prevTagId > 0 {
  796. prevTag, err = tagOb.GetItemById(prevTagId)
  797. if err != nil {
  798. errMsg = "移动失败"
  799. err = errors.New("获取上一个兄弟节点信息失败,Err:" + err.Error())
  800. return
  801. }
  802. prevSort = prevTag.Sort
  803. }
  804. // 下一个兄弟节点
  805. if nextMenuId > 0 {
  806. nextMenu, err = menuOb.GetItemById(nextMenuId)
  807. if err != nil {
  808. errMsg = "移动失败"
  809. err = errors.New("获取下一个兄弟节点目录信息失败,Err:" + err.Error())
  810. return
  811. }
  812. nextSort = nextMenu.Sort
  813. } else if nextTagId > 0 {
  814. nextTag, err = tagOb.GetItemById(nextTagId)
  815. if err != nil {
  816. errMsg = "移动失败"
  817. err = errors.New("获取下一个兄弟节点目录信息失败,Err:" + err.Error())
  818. return
  819. }
  820. nextSort = nextTag.Sort
  821. }
  822. err, errMsg = moveSpeechTagMenu(parentTagMenu, tagMenu, prevMenu, nextMenu, tagItem, prevTag, nextTag, parentMenuId, prevSort, nextSort)
  823. return
  824. }
  825. func moveSpeechTagMenu(parentTagMenu, tagMenu, prevMenu, nextMenu *speech_recognition.SpeechRecognitionTagMenu, tagItem, prevTag, nextTag *speech_recognition.SpeechRecognitionTag, parentMenuId int, prevSort, nextSort int) (err error, errMsg string) {
  826. updateCol := make([]string, 0)
  827. menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
  828. tagOb := new(speech_recognition.SpeechRecognitionTag)
  829. // 移动对象为目录, 判断目录是否存在
  830. if tagMenu != nil {
  831. oldParentId := tagMenu.ParentId
  832. oldLevel := tagMenu.Level
  833. var menuIds []int
  834. if oldParentId != parentMenuId {
  835. //更新子目录对应的level
  836. childList, e, m := GetChildSpeechTagMenuByMenuId(tagMenu.SpeechRecognitionTagMenuId)
  837. if e != nil {
  838. errMsg = "移动失败"
  839. err = errors.New("查询子目录失败,Err:" + e.Error() + m)
  840. return
  841. }
  842. if len(childList) > 0 {
  843. for _, v := range childList {
  844. if v.SpeechRecognitionTagMenuId == tagMenu.SpeechRecognitionTagMenuId {
  845. continue
  846. }
  847. menuIds = append(menuIds, v.SpeechRecognitionTagMenuId)
  848. }
  849. }
  850. }
  851. //判断上级id是否一致,如果不一致的话,那么需要移动该目录层级
  852. if tagMenu.ParentId != parentMenuId && parentMenuId != 0 {
  853. if tagMenu.Level != parentTagMenu.Level+1 { //禁止层级调整
  854. errMsg = "移动失败"
  855. err = errors.New("不支持目录层级变更")
  856. return
  857. }
  858. tagMenu.ParentId = parentTagMenu.SpeechRecognitionTagMenuId
  859. tagMenu.RootId = parentTagMenu.RootId
  860. tagMenu.Level = parentTagMenu.Level + 1
  861. tagMenu.ModifyTime = time.Now()
  862. updateCol = append(updateCol, "ParentId", "RootId", "Level", "ModifyTime")
  863. } else if tagMenu.ParentId != parentMenuId && parentMenuId == 0 {
  864. errMsg = "移动失败"
  865. err = errors.New("不支持目录层级变更")
  866. return
  867. }
  868. if prevSort > 0 {
  869. //如果是移动在两个兄弟节点之间
  870. if nextSort > 0 {
  871. //下一个兄弟节点
  872. //如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
  873. if prevSort == nextSort || prevSort == tagMenu.Sort {
  874. //变更兄弟节点的排序
  875. updateSortStr := `sort + 2`
  876. //变更目录
  877. if prevMenu != nil {
  878. _ = menuOb.UpdateSortByParentId(parentMenuId, prevMenu.SpeechRecognitionTagMenuId, prevMenu.Sort, updateSortStr)
  879. } else {
  880. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, prevSort, updateSortStr)
  881. }
  882. //变更标签
  883. if prevTag != nil {
  884. //变更兄弟节点的排序
  885. _ = tagOb.UpdateSortByMenuId(parentMenuId, prevSort, prevTag.SpeechRecognitionTagId, updateSortStr)
  886. } else {
  887. _ = tagOb.UpdateSortByMenuId(parentMenuId, prevSort, 0, updateSortStr)
  888. }
  889. } else {
  890. //如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
  891. if nextSort-prevSort == 1 {
  892. //变更兄弟节点的排序
  893. updateSortStr := `sort + 1`
  894. //变更目录
  895. if prevMenu != nil {
  896. _ = menuOb.UpdateSortByParentId(parentMenuId, prevMenu.SpeechRecognitionTagMenuId, prevSort, updateSortStr)
  897. } else {
  898. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, prevSort, updateSortStr)
  899. }
  900. //变更标签
  901. if prevTag != nil {
  902. //变更兄弟节点的排序
  903. _ = tagOb.UpdateSortByMenuId(parentMenuId, prevSort, prevTag.SpeechRecognitionTagId, updateSortStr)
  904. } else {
  905. _ = tagOb.UpdateSortByMenuId(parentMenuId, prevSort, 0, updateSortStr)
  906. }
  907. }
  908. }
  909. }
  910. tagMenu.Sort = prevSort + 1
  911. tagMenu.ModifyTime = time.Now()
  912. updateCol = append(updateCol, "Sort", "ModifyTime")
  913. } else if prevMenu == nil && nextMenu == nil && prevTag == nil && nextTag == nil && parentMenuId > 0 {
  914. //处理只拖动到目录里,默认放到目录底部的情况
  915. var maxSort int
  916. maxSort, err = GetSpeechTagMenuMaxSort(parentMenuId)
  917. if err != nil {
  918. errMsg = "移动失败"
  919. err = errors.New("查询组内排序信息失败,Err:" + err.Error())
  920. return
  921. }
  922. tagMenu.Sort = maxSort + 1 //那就是排在组内最后一位
  923. tagMenu.ModifyTime = time.Now()
  924. updateCol = append(updateCol, "Sort", "ModifyTime")
  925. } else {
  926. // 拖动到父级目录的第一位
  927. firstTagMenu, tmpErr := menuOb.GetFirstByParentId(parentMenuId)
  928. if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
  929. errMsg = "移动失败"
  930. err = errors.New("获取获取当前父级目录下的排序第一条的目录信息失败,Err:" + tmpErr.Error())
  931. return
  932. }
  933. //如果该目录下存在其他目录,且第一个其他目录的排序等于0,那么需要调整排序
  934. if firstTagMenu != nil && firstTagMenu.Sort == 0 {
  935. updateSortStr := ` sort + 1 `
  936. _ = menuOb.UpdateSortByParentId(parentMenuId, firstTagMenu.SpeechRecognitionTagMenuId-1, 0, updateSortStr)
  937. //该目录下的所有标签也需要+1
  938. _ = tagOb.UpdateSortByMenuId(parentMenuId, 0, 0, updateSortStr)
  939. } else {
  940. //如果该目录下存在标签,且第一个标签的排序等于0,那么需要调整排序
  941. firstTag, tErr := tagOb.GetFirstByMenuId(parentMenuId)
  942. if tErr != nil && tErr.Error() != utils.ErrNoRow() {
  943. errMsg = "移动失败"
  944. err = errors.New("获取获取当前父级目录下的排序第一条的目录信息失败,Err:" + tErr.Error())
  945. return
  946. }
  947. //如果该目录下存在其他目录,且第一个其他目录的排序等于0,那么需要调整排序
  948. if firstTag != nil && firstTag.Sort == 0 {
  949. updateSortStr := ` sort + 1 `
  950. _ = tagOb.UpdateSortByMenuId(parentMenuId, 0, firstTag.SpeechRecognitionTagId-1, updateSortStr)
  951. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, 0, updateSortStr)
  952. }
  953. }
  954. tagMenu.Sort = 0 //那就是排在第一位
  955. tagMenu.ModifyTime = time.Now()
  956. updateCol = append(updateCol, "Sort", "ModifyTime")
  957. }
  958. //更新
  959. if len(updateCol) > 0 {
  960. err = tagMenu.Update(updateCol)
  961. if err != nil {
  962. errMsg = "移动失败"
  963. err = errors.New("修改失败,Err:" + err.Error())
  964. return
  965. }
  966. //更新对应目录的root_id和层级
  967. if oldParentId != parentMenuId {
  968. if len(menuIds) > 0 {
  969. levelStep := tagMenu.Level - oldLevel
  970. err = menuOb.UpdateChildByParentMenuId(menuIds, tagMenu.RootId, levelStep)
  971. if err != nil {
  972. errMsg = "移动失败"
  973. err = errors.New("更新子目录失败,Err:" + err.Error())
  974. return
  975. }
  976. }
  977. }
  978. }
  979. } else {
  980. if tagItem == nil {
  981. errMsg = "当前标签不存在"
  982. err = errors.New(errMsg)
  983. return
  984. }
  985. //如果改变了目录,那么移动该标签数据
  986. if tagItem.MenuId != parentMenuId {
  987. tagItem.MenuId = parentMenuId
  988. tagItem.ModifyTime = time.Now()
  989. updateCol = append(updateCol, speech_recognition.SpeechRecognitionTagCols.MenuId, speech_recognition.SpeechRecognitionTagCols.ModifyTime)
  990. }
  991. if prevSort > 0 {
  992. //如果是移动在两个兄弟节点之间
  993. if nextSort > 0 {
  994. //下一个兄弟节点
  995. //如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
  996. if prevSort == nextSort || prevSort == tagItem.Sort {
  997. //变更兄弟节点的排序
  998. updateSortStr := `sort + 2`
  999. //变更目录
  1000. if prevMenu != nil {
  1001. _ = menuOb.UpdateSortByParentId(parentMenuId, prevMenu.SpeechRecognitionTagMenuId, prevMenu.Sort, updateSortStr)
  1002. } else {
  1003. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, prevSort, updateSortStr)
  1004. }
  1005. //变更标签
  1006. if prevTag != nil {
  1007. //变更兄弟节点的排序
  1008. _ = tagOb.UpdateSortByMenuId(parentMenuId, prevSort, prevTag.SpeechRecognitionTagId, updateSortStr)
  1009. } else {
  1010. _ = tagOb.UpdateSortByMenuId(parentMenuId, prevSort, 0, updateSortStr)
  1011. }
  1012. } else {
  1013. //如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
  1014. if nextSort-prevSort == 1 {
  1015. //变更兄弟节点的排序
  1016. updateSortStr := `sort + 1`
  1017. //变更目录
  1018. if prevMenu != nil {
  1019. _ = menuOb.UpdateSortByParentId(parentMenuId, prevMenu.SpeechRecognitionTagMenuId, prevSort, updateSortStr)
  1020. } else {
  1021. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, prevSort, updateSortStr)
  1022. }
  1023. //变更标签
  1024. if prevTag != nil {
  1025. //变更兄弟节点的排序
  1026. _ = tagOb.UpdateSortByMenuId(parentMenuId, prevSort, prevTag.SpeechRecognitionTagId, updateSortStr)
  1027. } else {
  1028. _ = tagOb.UpdateSortByMenuId(parentMenuId, prevSort, 0, updateSortStr)
  1029. }
  1030. }
  1031. }
  1032. }
  1033. tagItem.Sort = prevSort + 1
  1034. tagItem.ModifyTime = time.Now()
  1035. updateCol = append(updateCol, "Sort", "ModifyTime")
  1036. } else if prevMenu == nil && nextMenu == nil && prevTag == nil && nextTag == nil && parentMenuId > 0 {
  1037. //处理只拖动到目录里,默认放到目录底部的情况
  1038. var maxSort int
  1039. maxSort, err = GetSpeechTagMenuMaxSort(parentMenuId)
  1040. if err != nil {
  1041. errMsg = "移动失败"
  1042. err = errors.New("查询组内排序信息失败,Err:" + err.Error())
  1043. return
  1044. }
  1045. tagItem.Sort = maxSort + 1 //那就是排在组内最后一位
  1046. tagItem.ModifyTime = time.Now()
  1047. updateCol = append(updateCol, "Sort", "ModifyTime")
  1048. } else {
  1049. // 拖动到父级目录的第一位
  1050. firstTagMenu, tmpErr := menuOb.GetFirstByParentId(parentMenuId)
  1051. if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
  1052. errMsg = "移动失败"
  1053. err = errors.New("获取获取当前父级目录下的排序第一条的目录信息失败,Err:" + tmpErr.Error())
  1054. return
  1055. }
  1056. //如果该目录下存在其他目录,且第一个其他目录的排序等于0,那么需要调整排序
  1057. if firstTagMenu != nil && firstTagMenu.Sort == 0 {
  1058. updateSortStr := ` sort + 1 `
  1059. _ = menuOb.UpdateSortByParentId(parentMenuId, firstTagMenu.SpeechRecognitionTagMenuId-1, 0, updateSortStr)
  1060. //该目录下的所有标签也需要+1
  1061. _ = tagOb.UpdateSortByMenuId(parentMenuId, 0, 0, updateSortStr)
  1062. } else {
  1063. //如果该目录下存在标签,且第一个标签的排序等于0,那么需要调整排序
  1064. firstTag, tErr := tagOb.GetFirstByMenuId(parentMenuId)
  1065. if tErr != nil && tErr.Error() != utils.ErrNoRow() {
  1066. errMsg = "移动失败"
  1067. err = errors.New("获取获取当前父级目录下的排序第一条的目录信息失败,Err:" + tErr.Error())
  1068. return
  1069. }
  1070. //如果该目录下存在其他目录,且第一个其他目录的排序等于0,那么需要调整排序
  1071. if firstTag != nil && firstTag.Sort == 0 {
  1072. updateSortStr := ` sort + 1 `
  1073. _ = tagOb.UpdateSortByMenuId(parentMenuId, 0, firstTag.SpeechRecognitionTagId-1, updateSortStr)
  1074. _ = menuOb.UpdateSortByParentId(parentMenuId, 0, 0, updateSortStr)
  1075. }
  1076. }
  1077. tagItem.Sort = 0 //那就是排在第一位
  1078. tagItem.ModifyTime = time.Now()
  1079. updateCol = append(updateCol, "Sort", "ModifyTime")
  1080. }
  1081. //更新
  1082. if len(updateCol) > 0 {
  1083. err = tagItem.Update(updateCol)
  1084. if err != nil {
  1085. errMsg = "移动失败"
  1086. err = errors.New("修改失败,Err:" + err.Error())
  1087. return
  1088. }
  1089. }
  1090. }
  1091. return
  1092. }
  1093. func GetChildSpeechTagMenuByMenuId(menuId int) (targetList []*speech_recognition.SpeechRecognitionTagMenu, err error, errMsg string) {
  1094. menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
  1095. //判断是否是挂在顶级目录下
  1096. tagMenu, err := menuOb.GetItemById(menuId)
  1097. if err != nil {
  1098. if err.Error() == utils.ErrNoRow() {
  1099. errMsg = "当前目录不存在"
  1100. err = errors.New(errMsg)
  1101. return
  1102. }
  1103. errMsg = "获取失败"
  1104. err = errors.New("获取目录信息失败,Err:" + err.Error())
  1105. return
  1106. }
  1107. cond := fmt.Sprintf(" AND %s = ?", speech_recognition.SpeechRecognitionTagMenuCols.RootId)
  1108. pars := make([]interface{}, 0)
  1109. pars = append(pars, tagMenu.RootId)
  1110. order := fmt.Sprintf("%s ASC, %s ASC, %s ASC", speech_recognition.SpeechRecognitionTagMenuCols.Level, speech_recognition.SpeechRecognitionTagMenuCols.Sort, speech_recognition.SpeechRecognitionTagMenuCols.SpeechRecognitionTagMenuId)
  1111. tmpList, err := tagMenu.GetItemsByCondition(cond, pars, []string{}, order)
  1112. if err != nil && err.Error() != utils.ErrNoRow() {
  1113. errMsg = "获取失败"
  1114. err = errors.New("获取数据失败,Err:" + err.Error())
  1115. return
  1116. }
  1117. idMap := make(map[int]struct{})
  1118. if len(tmpList) > 0 {
  1119. for _, v := range tmpList {
  1120. if v.SpeechRecognitionTagMenuId == tagMenu.SpeechRecognitionTagMenuId {
  1121. idMap[v.SpeechRecognitionTagMenuId] = struct{}{}
  1122. }
  1123. }
  1124. for _, v := range tmpList {
  1125. if _, ok := idMap[v.ParentId]; ok {
  1126. idMap[v.SpeechRecognitionTagMenuId] = struct{}{}
  1127. }
  1128. }
  1129. for _, v := range tmpList {
  1130. if _, ok := idMap[v.SpeechRecognitionTagMenuId]; ok {
  1131. targetList = append(targetList, v)
  1132. }
  1133. }
  1134. }
  1135. return
  1136. }
  1137. // GetSpeechTagMenuMaxSort 获取同级下最大的排序
  1138. func GetSpeechTagMenuMaxSort(parentId int) (maxSort int, err error) {
  1139. menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
  1140. tagOb := new(speech_recognition.SpeechRecognitionTag)
  1141. //获取该层级下最大的排序数
  1142. menuMax, err := menuOb.GetMaxSortByParentId(parentId)
  1143. if err != nil {
  1144. return
  1145. }
  1146. maxSort = menuMax
  1147. speechMax, err := tagOb.GetMaxSortByMenuId(parentId)
  1148. if err != nil {
  1149. return
  1150. }
  1151. if maxSort < speechMax {
  1152. maxSort = speechMax
  1153. }
  1154. return
  1155. }
  1156. // ------------------ 移动标签目录/标签 ------------------ //
  1157. // GetSpeechRecognitionMenuChildrenRecursive 递归获取目录的子目录集
  1158. func GetSpeechRecognitionMenuChildrenRecursive(list []*speech_recognition.SpeechRecognitionMenu, parentId int) []int {
  1159. childIds := make([]int, 0)
  1160. for _, v := range list {
  1161. if v.ParentId == parentId {
  1162. childIds = append(childIds, v.SpeechRecognitionMenuId)
  1163. ids := GetSpeechRecognitionMenuChildrenRecursive(list, v.SpeechRecognitionMenuId)
  1164. if len(ids) > 0 {
  1165. childIds = append(childIds, ids...)
  1166. }
  1167. }
  1168. }
  1169. return childIds
  1170. }
  1171. // GetSpeechRecognitionTagMenuChildrenRecursive 递归获取标签目录的子目录集
  1172. func GetSpeechRecognitionTagMenuChildrenRecursive(list []*speech_recognition.SpeechRecognitionTagMenu, parentId int) []int {
  1173. childIds := make([]int, 0)
  1174. for _, v := range list {
  1175. if v.ParentId == parentId {
  1176. childIds = append(childIds, v.SpeechRecognitionTagMenuId)
  1177. ids := GetSpeechRecognitionTagMenuChildrenRecursive(list, v.SpeechRecognitionTagMenuId)
  1178. if len(ids) > 0 {
  1179. childIds = append(childIds, ids...)
  1180. }
  1181. }
  1182. }
  1183. return childIds
  1184. }
  1185. // CheckSpeechRecognitionMenuRemove 校验是否可删除目录
  1186. func CheckSpeechRecognitionMenuRemove(menuId int) (result *speech_recognition.SpeechRecognitionMenuRemoveCheckResp, menuIds []int, err error) {
  1187. menuOb := new(speech_recognition.SpeechRecognitionMenu)
  1188. result = new(speech_recognition.SpeechRecognitionMenuRemoveCheckResp)
  1189. // 递归获取目录的子目录集合
  1190. menus, e := menuOb.GetItemsByCondition(``, make([]interface{}, 0), []string{}, "")
  1191. if e != nil {
  1192. err = fmt.Errorf("获取语音识别目录列表失败, err: %s", e.Error())
  1193. return
  1194. }
  1195. childIds := GetSpeechRecognitionMenuChildrenRecursive(menus, menuId)
  1196. menuIds = make([]int, 0)
  1197. menuIds = append(menuIds, menuId)
  1198. if len(childIds) > 0 {
  1199. menuIds = append(menuIds, childIds...)
  1200. }
  1201. // 校验目录下(包含子目录)是否有内容
  1202. speechOb := new(speech_recognition.SpeechRecognition)
  1203. cond := fmt.Sprintf(` AND %s IN (%s)`, speech_recognition.SpeechRecognitionCols.MenuId, utils.GetOrmInReplace(len(menuIds)))
  1204. pars := make([]interface{}, 0)
  1205. pars = append(pars, menuIds)
  1206. count, e := speechOb.GetCountByCondition(cond, pars)
  1207. if e != nil {
  1208. err = fmt.Errorf("获取目录下的语音识别数失败, err: %s", e.Error())
  1209. return
  1210. }
  1211. if count > 0 {
  1212. result.CheckResult = SpeechMenuCheckRemoveTypeRefused
  1213. result.Tips = "该分类关联转写文件,删除失败!"
  1214. return
  1215. }
  1216. // 如果无语音识别, 但存在子目录, 则返回第二种提示
  1217. if len(childIds) > 0 {
  1218. result.CheckResult = SpeechMenuCheckRemoveTypeWarning
  1219. result.Tips = "该分类包含内容为空的子分类"
  1220. return
  1221. }
  1222. // 通过校验
  1223. result.Tips = "校验通过,可以删除"
  1224. return
  1225. }
  1226. // CheckSpeechRecognitionTagMenuRemove 校验是否可删除标签目录
  1227. func CheckSpeechRecognitionTagMenuRemove(menuId int) (result *speech_recognition.SpeechRecognitionMenuRemoveCheckResp, menuIds []int, err error) {
  1228. menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
  1229. result = new(speech_recognition.SpeechRecognitionMenuRemoveCheckResp)
  1230. // 递归获取目录的子目录集合
  1231. menus, e := menuOb.GetItemsByCondition(``, make([]interface{}, 0), []string{}, "")
  1232. if e != nil {
  1233. err = fmt.Errorf("获取标签目录列表失败, err: %s", e.Error())
  1234. return
  1235. }
  1236. childIds := GetSpeechRecognitionTagMenuChildrenRecursive(menus, menuId)
  1237. menuIds = make([]int, 0)
  1238. menuIds = append(menuIds, menuId)
  1239. if len(childIds) > 0 {
  1240. menuIds = append(menuIds, childIds...)
  1241. }
  1242. // 校验目录下(包含子目录)是否有内容
  1243. tagOb := new(speech_recognition.SpeechRecognitionTag)
  1244. cond := fmt.Sprintf(` AND %s IN (%s)`, speech_recognition.SpeechRecognitionTagCols.MenuId, utils.GetOrmInReplace(len(menuIds)))
  1245. pars := make([]interface{}, 0)
  1246. pars = append(pars, menuIds)
  1247. count, e := tagOb.GetCountByCondition(cond, pars)
  1248. if e != nil {
  1249. err = fmt.Errorf("获取目录下的标签数失败, err: %s", e.Error())
  1250. return
  1251. }
  1252. if count > 0 {
  1253. result.CheckResult = SpeechMenuCheckRemoveTypeRefused
  1254. result.Tips = "该分类关联标签,删除失败!"
  1255. return
  1256. }
  1257. // 如果无内容, 但存在子目录, 则返回第二种提示
  1258. if len(childIds) > 0 {
  1259. result.CheckResult = SpeechMenuCheckRemoveTypeWarning
  1260. result.Tips = "该分类包含内容为空的子分类"
  1261. return
  1262. }
  1263. // 通过校验
  1264. result.Tips = "校验通过,可以删除"
  1265. return
  1266. }
  1267. // GetSpeechRecognitionMenuPathRecursive 根据子目录递归获取目录树
  1268. func GetSpeechRecognitionMenuPathRecursive(list []*speech_recognition.SpeechRecognitionMenu, menuId int) []*speech_recognition.SpeechRecognitionMenuItem {
  1269. res := make([]*speech_recognition.SpeechRecognitionMenuItem, 0)
  1270. for _, v := range list {
  1271. if v.SpeechRecognitionMenuId == menuId {
  1272. t := new(speech_recognition.SpeechRecognitionMenuItem)
  1273. t.UniqueCode = v.UniqueCode
  1274. t.MenuId = v.SpeechRecognitionMenuId
  1275. t.MenuName = v.MenuName
  1276. t.ParentId = v.ParentId
  1277. t.Level = v.Level
  1278. t.Sort = v.Sort
  1279. t.CreateTime = utils.TimeTransferString(utils.FormatDateTime, v.CreateTime)
  1280. if v.ParentId > 0 {
  1281. res = GetSpeechRecognitionMenuPathRecursive(list, v.ParentId)
  1282. }
  1283. res = append(res, t)
  1284. }
  1285. }
  1286. return res
  1287. }