Ver Fonte

语音识别-目录、标签目录、标签

hsun há 1 ano atrás
pai
commit
d99a6631b4

+ 410 - 0
controllers/speech_recognition/speech_recognition_menu.go

@@ -0,0 +1,410 @@
+package speech_recognition
+
+import (
+	"encoding/json"
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/models/speech_recognition"
+	"eta/eta_api/utils"
+	"fmt"
+	"strings"
+	"time"
+)
+
+type SpeechRecognitionMenuController struct {
+	controllers.BaseAuthController
+}
+
+// Add
+// @Title 新增分类
+// @Description 新增分类
+// @Param	request	body speech_recognition.SpeechRecognitionMenuAddReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /menu/add [post]
+func (this *SpeechRecognitionMenuController) Add() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req speech_recognition.SpeechRecognitionMenuAddReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	req.MenuName = strings.TrimSpace(req.MenuName)
+	if req.MenuName == "" {
+		br.Msg = "请输入目录名称"
+		return
+	}
+
+	// 校验同级目录是否有重名
+	menuOb := new(speech_recognition.SpeechRecognitionMenu)
+	{
+		cond := fmt.Sprintf(` %s = ? AND %s = ?`, speech_recognition.SpeechRecognitionMenuCols.MenuName, speech_recognition.SpeechRecognitionMenuCols.ParentId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.MenuName, req.ParentId)
+		exists, e := menuOb.GetItemByCondition(cond, pars, "")
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取同名目录失败, Err: " + e.Error()
+			return
+		}
+		if exists != nil && exists.SpeechRecognitionMenuId > 0 {
+			br.Msg = "分类名称已存在,请重新输入"
+			return
+		}
+	}
+
+	// 获取目录层级
+	level := 1
+	{
+		if req.ParentId > 0 {
+			parentMenu, e := menuOb.GetItemById(req.ParentId)
+			if e != nil {
+				br.Msg = "操作失败"
+				br.ErrMsg = "获取父级目录失败, Err: " + e.Error()
+				return
+			}
+			level += parentMenu.Level
+		}
+	}
+
+	menuOb.MenuName = req.MenuName
+	menuOb.ParentId = req.ParentId
+	menuOb.Level = level
+	menuOb.CreateTime = time.Now().Local()
+	menuOb.ModifyTime = time.Now().Local()
+	e := menuOb.Create()
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "新增目录失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Edit
+// @Title 编辑分类
+// @Description 编辑分类
+// @Param	request	body speech_recognition.SpeechRecognitionMenuEditReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /menu/edit [post]
+func (this *SpeechRecognitionMenuController) Edit() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req speech_recognition.SpeechRecognitionMenuEditReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.MenuId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, MenuId: %d", req.MenuId)
+		return
+	}
+	req.MenuName = strings.TrimSpace(req.MenuName)
+	if req.MenuName == "" {
+		br.Msg = "请输入目录名称"
+		return
+	}
+
+	menuOb := new(speech_recognition.SpeechRecognitionMenu)
+	menuItem, e := menuOb.GetItemById(req.MenuId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "目录不存在,请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取目录失败, Err: " + e.Error()
+		return
+	}
+
+	// 校验同级目录是否有重名
+	{
+		cond := fmt.Sprintf(` %s = ? AND %s = ? AND %s <> ?`, speech_recognition.SpeechRecognitionMenuCols.MenuName, speech_recognition.SpeechRecognitionMenuCols.ParentId, speech_recognition.SpeechRecognitionMenuCols.SpeechRecognitionMenuId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.MenuName, menuItem.ParentId, req.MenuId)
+		exists, e := menuOb.GetItemByCondition(cond, pars, "")
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取同名目录失败, Err: " + e.Error()
+			return
+		}
+		if exists != nil && exists.SpeechRecognitionMenuId > 0 {
+			br.Msg = "分类名称已存在,请重新输入"
+			return
+		}
+	}
+
+	menuOb.MenuName = req.MenuName
+	menuOb.ModifyTime = time.Now().Local()
+	updateCols := []string{speech_recognition.SpeechRecognitionMenuCols.MenuName, speech_recognition.SpeechRecognitionMenuCols.ModifyTime}
+	if e = menuOb.Update(updateCols); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "更新目录失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Remove
+// @Title 删除分类
+// @Description 删除分类
+// @Param	request	body speech_recognition.SpeechRecognitionMenuRemoveReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /menu/remove [post]
+func (this *SpeechRecognitionMenuController) Remove() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req speech_recognition.SpeechRecognitionMenuRemoveReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.MenuId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, MenuId: %d", req.MenuId)
+		return
+	}
+
+	menuOb := new(speech_recognition.SpeechRecognitionMenu)
+	menuItem, e := menuOb.GetItemById(req.MenuId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "操作成功"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取目录失败, Err: " + e.Error()
+		return
+	}
+
+	// 校验目录下是否有内容
+	{
+		speechOb := new(speech_recognition.SpeechRecognition)
+		cond := fmt.Sprintf(` %s = ?`, speech_recognition.SpeechRecognitionCols.MenuId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.MenuId)
+		count, e := speechOb.GetCountByCondition(cond, pars)
+		if e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取目录下的语音识别数失败, Err: " + e.Error()
+			return
+		}
+		if count > 0 {
+			br.Msg = "该分类关联转写文件,删除失败!"
+			return
+		}
+
+		cond = fmt.Sprintf(` %s = ?`, speech_recognition.SpeechRecognitionMenuCols.ParentId)
+		pars = make([]interface{}, 0)
+		pars = append(pars, req.MenuId)
+		count, e = menuOb.GetCountByCondition(cond, pars)
+		if e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取下级目录数失败, Err: " + e.Error()
+			return
+		}
+		if count > 0 {
+			br.Msg = "该分类含下级目录,删除失败!"
+			return
+		}
+	}
+
+	if e = menuItem.Del(); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "删除目录失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Tree
+// @Title 目录树
+// @Description 目录树
+// @Param   ParentId  query  int  false  "父级ID"
+// @Success 200 {object} speech_recognition.SpeechRecognitionMenuNodeItem
+// @router /menu/tree [get]
+func (this *SpeechRecognitionMenuController) Tree() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	// 前端采用懒加载, 所以只查询目录及当前目录下的语音识别
+	parentId, _ := this.GetInt("ParentId")
+
+	menus := make([]*speech_recognition.SpeechRecognitionMenu, 0)
+	{
+		menuOb := new(speech_recognition.SpeechRecognitionMenu)
+		cond := fmt.Sprintf(` %s = ?`, speech_recognition.SpeechRecognitionMenuCols.ParentId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, parentId)
+		list, e := menuOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", speech_recognition.SpeechRecognitionMenuCols.Sort))
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取目录列表失败, Err: " + e.Error()
+			return
+		}
+		menus = list
+	}
+
+	resp := make([]*speech_recognition.SpeechRecognitionMenuNodeItem, 0)
+	if len(menus) == 0 {
+		br.Data = resp
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		return
+	}
+	menuIds := make([]int, 0)
+	for _, m := range menus {
+		menuIds = append(menuIds, m.SpeechRecognitionMenuId)
+	}
+
+	// 子目录
+	childMenus := make([]*speech_recognition.SpeechRecognitionMenu, 0)
+	{
+		menuOb := new(speech_recognition.SpeechRecognitionMenu)
+		cond := fmt.Sprintf(` %s IN (%s)`, speech_recognition.SpeechRecognitionMenuCols.ParentId, utils.GetOrmInReplace(len(menuIds)))
+		pars := make([]interface{}, 0)
+		pars = append(pars, menuIds)
+		list, e := menuOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC, %s ASC", speech_recognition.SpeechRecognitionMenuCols.Sort, speech_recognition.SpeechRecognitionMenuCols.ParentId))
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取子目录列表失败, Err: " + e.Error()
+			return
+		}
+		menus = list
+	}
+	menuChildren := make(map[int][]*speech_recognition.SpeechRecognitionMenuNodeItem)
+	for _, m := range childMenus {
+		if menuChildren[m.ParentId] == nil {
+			menuChildren[m.ParentId] = make([]*speech_recognition.SpeechRecognitionMenuNodeItem, 0)
+		}
+		menuChildren[m.ParentId] = append(menuChildren[m.ParentId], &speech_recognition.SpeechRecognitionMenuNodeItem{
+			NodeType:   speech_recognition.SpeechRecognitionMenuNodeTypeDefault,
+			MenuId:     m.SpeechRecognitionMenuId,
+			MenuName:   m.MenuName,
+			ParentId:   m.ParentId,
+			Sort:       m.Sort,
+			CreateTime: utils.TimeTransferString(utils.FormatDateTime, m.CreateTime),
+		})
+	}
+
+	// 目录下的语音识别
+	speeches := make([]*speech_recognition.SpeechRecognition, 0)
+	{
+		speechOb := new(speech_recognition.SpeechRecognition)
+		cond := fmt.Sprintf(` %s IN (%s)`, speech_recognition.SpeechRecognitionCols.MenuId, utils.GetOrmInReplace(len(menuIds)))
+		pars := make([]interface{}, 0)
+		pars = append(pars, menuIds)
+		list, e := speechOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC, %s DESC", speech_recognition.SpeechRecognitionCols.Sort, speech_recognition.SpeechRecognitionCols.CreateTime))
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取语音识别列表失败, Err: " + e.Error()
+			return
+		}
+		speeches = list
+	}
+	menuSpeeches := make(map[int][]*speech_recognition.SpeechRecognitionMenuNodeItem)
+	for _, s := range speeches {
+		if menuSpeeches[s.MenuId] == nil {
+			menuSpeeches[s.MenuId] = make([]*speech_recognition.SpeechRecognitionMenuNodeItem, 0)
+		}
+		menuSpeeches[s.MenuId] = append(menuSpeeches[s.MenuId], &speech_recognition.SpeechRecognitionMenuNodeItem{
+			NodeType:              speech_recognition.SpeechRecognitionMenuNodeTypeSpeech,
+			SpeechRecognitionId:   s.SpeechRecognitionId,
+			SpeechRecognitionName: s.FileName,
+			ParentId:              s.MenuId,
+			Sort:                  s.Sort,
+			CreateTime:            utils.TimeTransferString(utils.FormatDateTime, s.CreateTime),
+		})
+	}
+
+	for _, m := range menus {
+		t := &speech_recognition.SpeechRecognitionMenuNodeItem{
+			NodeType:   speech_recognition.SpeechRecognitionMenuNodeTypeDefault,
+			MenuId:     m.SpeechRecognitionMenuId,
+			MenuName:   m.MenuName,
+			ParentId:   m.ParentId,
+			Sort:       m.Sort,
+			CreateTime: utils.TimeTransferString(utils.FormatDateTime, m.CreateTime),
+			Children:   make([]*speech_recognition.SpeechRecognitionMenuNodeItem, 0),
+		}
+		if menuSpeeches[m.SpeechRecognitionMenuId] != nil {
+			t.Children = append(t.Children, menuSpeeches[m.SpeechRecognitionMenuId]...)
+		}
+		if menuChildren[m.SpeechRecognitionMenuId] != nil {
+			t.Children = append(t.Children, menuChildren[m.SpeechRecognitionMenuId]...)
+		}
+		resp = append(resp, t)
+	}
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}

+ 299 - 0
controllers/speech_recognition/speech_recognition_tag.go

@@ -0,0 +1,299 @@
+package speech_recognition
+
+import (
+	"encoding/json"
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/models/speech_recognition"
+	"eta/eta_api/utils"
+	"fmt"
+	"strings"
+	"time"
+)
+
+type SpeechRecognitionTagController struct {
+	controllers.BaseAuthController
+}
+
+// Add
+// @Title 新增标签
+// @Description 新增标签
+// @Param	request	body speech_recognition.SpeechRecognitionTagAddReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /tag/add [post]
+func (this *SpeechRecognitionTagController) Add() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req speech_recognition.SpeechRecognitionTagAddReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.MenuId <= 0 {
+		br.Msg = "请选择标签目录"
+		return
+	}
+	req.TagName = strings.TrimSpace(req.TagName)
+	if req.TagName == "" {
+		br.Msg = "请输入目录名称"
+		return
+	}
+
+	// 校验标签是否有重名
+	tagOb := new(speech_recognition.SpeechRecognitionTag)
+	{
+		cond := fmt.Sprintf(` %s = ?`, speech_recognition.SpeechRecognitionTagCols.TagName)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.TagName)
+		exists, e := tagOb.GetItemByCondition(cond, pars, "")
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取同名标签失败, Err: " + e.Error()
+			return
+		}
+		if exists != nil && exists.SpeechRecognitionTagId > 0 {
+			br.Msg = "标签名称已存在,请重新输入"
+			return
+		}
+	}
+
+	tagOb.TagName = req.TagName
+	tagOb.MenuId = req.MenuId
+	// TODO:所属目录位置
+	tagOb.CreateTime = time.Now().Local()
+	tagOb.ModifyTime = time.Now().Local()
+	if e := tagOb.Create(); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "新增标签失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Edit
+// @Title 编辑标签
+// @Description 编辑标签
+// @Param	request	body speech_recognition.SpeechRecognitionTagEditReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /tag/edit [post]
+func (this *SpeechRecognitionTagController) Edit() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req speech_recognition.SpeechRecognitionTagEditReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.TagId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, TagId: %d", req.TagId)
+		return
+	}
+	req.TagName = strings.TrimSpace(req.TagName)
+	if req.TagName == "" {
+		br.Msg = "请输入标签名称"
+		return
+	}
+
+	tagOb := new(speech_recognition.SpeechRecognitionTag)
+	_, e := tagOb.GetItemById(req.TagId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "标签不存在,请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取标签失败, Err: " + e.Error()
+		return
+	}
+
+	// 校验标签是否有重名
+	{
+		cond := fmt.Sprintf(` %s = ? AND %s <> ?`, speech_recognition.SpeechRecognitionTagCols.TagName, speech_recognition.SpeechRecognitionTagCols.SpeechRecognitionTagId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.TagName, req.TagId)
+		exists, e := tagOb.GetItemByCondition(cond, pars, "")
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取同名标签失败, Err: " + e.Error()
+			return
+		}
+		if exists != nil && exists.SpeechRecognitionTagId > 0 {
+			br.Msg = "标签名称已存在,请重新输入"
+			return
+		}
+	}
+
+	tagOb.TagName = req.TagName
+	tagOb.ModifyTime = time.Now().Local()
+	updateCols := []string{speech_recognition.SpeechRecognitionTagCols.TagName, speech_recognition.SpeechRecognitionTagCols.ModifyTime}
+	if e = tagOb.Update(updateCols); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "更新标签失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Remove
+// @Title 删除分类
+// @Description 删除分类
+// @Param	request	body speech_recognition.SpeechRecognitionTagRemoveReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /tag/remove [post]
+func (this *SpeechRecognitionTagController) Remove() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req speech_recognition.SpeechRecognitionTagRemoveReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.TagId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, TagId: %d", req.TagId)
+		return
+	}
+
+	tagOb := new(speech_recognition.SpeechRecognitionTag)
+	tagItem, e := tagOb.GetItemById(req.TagId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "操作成功"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取标签失败, Err: " + e.Error()
+		return
+	}
+
+	// 校验标签是否关联转写文件
+	{
+		mappingOb := new(speech_recognition.SpeechRecognitionTagMapping)
+		cond := fmt.Sprintf(` %s = ?`, speech_recognition.SpeechRecognitionTagMappingCols.TagId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.TagId)
+		count, e := mappingOb.GetCountByCondition(cond, pars)
+		if e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取标签关联转写文件数失败, Err: " + e.Error()
+			return
+		}
+		if count > 0 {
+			br.Msg = "标签关联转写文件,删除失败!"
+			return
+		}
+	}
+
+	if e = tagItem.Del(); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "删除标签失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// List
+// @Title 标签列表
+// @Description 标签列表
+// @Param   Keywords  query  string  false  "标签名称"
+// @Success 200 {object} speech_recognition.SpeechRecognitionTagItem
+// @router /tag/list [get]
+func (this *SpeechRecognitionTagController) List() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	keywords := this.GetString("Keywords")
+	keywords = strings.TrimSpace(keywords)
+
+	tagOb := new(speech_recognition.SpeechRecognitionTag)
+	cond := ``
+	pars := make([]interface{}, 0)
+	if keywords != "" {
+		kw := fmt.Sprint("%", keywords, "%s")
+		cond = fmt.Sprintf(` %s LIKE ?`, speech_recognition.SpeechRecognitionTagCols.TagName)
+		pars = append(pars, kw)
+	}
+	list, e := tagOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s DESC", speech_recognition.SpeechRecognitionTagCols.CreateTime))
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取标签列表失败, Err: " + e.Error()
+		return
+	}
+
+	resp := make([]*speech_recognition.SpeechRecognitionTagItem, 0)
+	for _, v := range list {
+		resp = append(resp, speech_recognition.FormatSpeechRecognitionTag2Item(v))
+	}
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}

+ 455 - 0
controllers/speech_recognition/speech_recognition_tag_menu.go

@@ -0,0 +1,455 @@
+package speech_recognition
+
+import (
+	"encoding/json"
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/models/speech_recognition"
+	"eta/eta_api/services"
+	"eta/eta_api/utils"
+	"fmt"
+	"strings"
+	"time"
+)
+
+// SpeechRecognitionTagMenuController 标签目录
+type SpeechRecognitionTagMenuController struct {
+	controllers.BaseAuthController
+}
+
+// Add
+// @Title 新增分类
+// @Description 新增分类
+// @Param	request	body speech_recognition.SpeechRecognitionTagMenuAddReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /tag/menu/add [post]
+func (this *SpeechRecognitionTagMenuController) Add() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req speech_recognition.SpeechRecognitionTagMenuAddReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	req.MenuName = strings.TrimSpace(req.MenuName)
+	if req.MenuName == "" {
+		br.Msg = "请输入目录名称"
+		return
+	}
+
+	// 校验同级目录是否有重名
+	menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
+	{
+		cond := fmt.Sprintf(` %s = ? AND %s = ?`, speech_recognition.SpeechRecognitionTagMenuCols.MenuName, speech_recognition.SpeechRecognitionTagMenuCols.ParentId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.MenuName, req.ParentId)
+		exists, e := menuOb.GetItemByCondition(cond, pars, "")
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取同名目录失败, Err: " + e.Error()
+			return
+		}
+		if exists != nil && exists.SpeechRecognitionTagMenuId > 0 {
+			br.Msg = "分类名称已存在,请重新输入"
+			return
+		}
+	}
+
+	// 获取目录层级
+	level := 1
+	{
+		if req.ParentId > 0 {
+			parentMenu, e := menuOb.GetItemById(req.ParentId)
+			if e != nil {
+				br.Msg = "操作失败"
+				br.ErrMsg = "获取父级目录失败, Err: " + e.Error()
+				return
+			}
+			level += parentMenu.Level
+		}
+	}
+
+	menuOb.MenuName = req.MenuName
+	menuOb.ParentId = req.ParentId
+	menuOb.Level = level
+	menuOb.CreateTime = time.Now().Local()
+	menuOb.ModifyTime = time.Now().Local()
+	e := menuOb.Create()
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "新增目录失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Edit
+// @Title 编辑分类
+// @Description 编辑分类
+// @Param	request	body speech_recognition.SpeechRecognitionTagMenuEditReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /tag/menu/edit [post]
+func (this *SpeechRecognitionTagMenuController) Edit() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req speech_recognition.SpeechRecognitionTagMenuEditReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.MenuId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, MenuId: %d", req.MenuId)
+		return
+	}
+	req.MenuName = strings.TrimSpace(req.MenuName)
+	if req.MenuName == "" {
+		br.Msg = "请输入目录名称"
+		return
+	}
+
+	menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
+	menuItem, e := menuOb.GetItemById(req.MenuId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "目录不存在,请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取目录失败, Err: " + e.Error()
+		return
+	}
+
+	// 校验同级目录是否有重名
+	{
+		cond := fmt.Sprintf(` %s = ? AND %s = ? AND %s <> ?`, speech_recognition.SpeechRecognitionTagMenuCols.MenuName, speech_recognition.SpeechRecognitionTagMenuCols.ParentId, speech_recognition.SpeechRecognitionTagMenuCols.SpeechRecognitionTagMenuId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.MenuName, menuItem.ParentId, req.MenuId)
+		exists, e := menuOb.GetItemByCondition(cond, pars, "")
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取同名目录失败, Err: " + e.Error()
+			return
+		}
+		if exists != nil && exists.SpeechRecognitionTagMenuId > 0 {
+			br.Msg = "分类名称已存在,请重新输入"
+			return
+		}
+	}
+
+	menuOb.MenuName = req.MenuName
+	menuOb.ModifyTime = time.Now().Local()
+	updateCols := []string{speech_recognition.SpeechRecognitionTagMenuCols.MenuName, speech_recognition.SpeechRecognitionTagMenuCols.ModifyTime}
+	if e = menuOb.Update(updateCols); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "更新目录失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Remove
+// @Title 删除分类
+// @Description 删除分类
+// @Param	request	body speech_recognition.SpeechRecognitionTagMenuRemoveReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /tag/menu/remove [post]
+func (this *SpeechRecognitionTagMenuController) Remove() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req speech_recognition.SpeechRecognitionTagMenuRemoveReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.MenuId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, MenuId: %d", req.MenuId)
+		return
+	}
+
+	menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
+	menuItem, e := menuOb.GetItemById(req.MenuId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "操作成功"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取目录失败, Err: " + e.Error()
+		return
+	}
+
+	// 校验目录下是否有内容
+	{
+		tagOb := new(speech_recognition.SpeechRecognitionTag)
+		cond := fmt.Sprintf(` %s = ?`, speech_recognition.SpeechRecognitionTagCols.MenuId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.MenuId)
+		count, e := tagOb.GetCountByCondition(cond, pars)
+		if e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取目录下的标签数失败, Err: " + e.Error()
+			return
+		}
+		if count > 0 {
+			br.Msg = "该分类关联标签,删除失败!"
+			return
+		}
+
+		cond = fmt.Sprintf(` %s = ?`, speech_recognition.SpeechRecognitionTagMenuCols.ParentId)
+		pars = make([]interface{}, 0)
+		pars = append(pars, req.MenuId)
+		count, e = menuOb.GetCountByCondition(cond, pars)
+		if e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取下级目录数失败, Err: " + e.Error()
+			return
+		}
+		if count > 0 {
+			br.Msg = "该分类含下级目录,删除失败!"
+			return
+		}
+	}
+
+	if e = menuItem.Del(); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "删除目录失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Tree
+// @Title 目录树
+// @Description 目录树
+// @Param   ParentId  query  int  false  "父级ID"
+// @Success 200 {object} speech_recognition.SpeechRecognitionTagMenuNodeItem
+// @router /tag/menu/tree [get]
+func (this *SpeechRecognitionTagMenuController) Tree() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	// 前端采用懒加载, 所以只查询目录及当前目录下的语音识别
+	parentId, _ := this.GetInt("ParentId")
+
+	menus := make([]*speech_recognition.SpeechRecognitionTagMenu, 0)
+	{
+		menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
+		cond := fmt.Sprintf(` %s = ?`, speech_recognition.SpeechRecognitionTagMenuCols.ParentId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, parentId)
+		list, e := menuOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", speech_recognition.SpeechRecognitionTagMenuCols.Sort))
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取目录列表失败, Err: " + e.Error()
+			return
+		}
+		menus = list
+	}
+
+	resp := make([]*speech_recognition.SpeechRecognitionTagMenuNodeItem, 0)
+	if len(menus) == 0 {
+		br.Data = resp
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		return
+	}
+	menuIds := make([]int, 0)
+	for _, m := range menus {
+		menuIds = append(menuIds, m.SpeechRecognitionTagMenuId)
+	}
+
+	// 子目录
+	childMenus := make([]*speech_recognition.SpeechRecognitionTagMenu, 0)
+	{
+		menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
+		cond := fmt.Sprintf(` %s IN (%s)`, speech_recognition.SpeechRecognitionTagMenuCols.ParentId, utils.GetOrmInReplace(len(menuIds)))
+		pars := make([]interface{}, 0)
+		pars = append(pars, menuIds)
+		list, e := menuOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC, %s ASC", speech_recognition.SpeechRecognitionTagMenuCols.Sort, speech_recognition.SpeechRecognitionTagMenuCols.ParentId))
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取子目录列表失败, Err: " + e.Error()
+			return
+		}
+		menus = list
+	}
+	menuChildren := make(map[int][]*speech_recognition.SpeechRecognitionTagMenuNodeItem)
+	for _, m := range childMenus {
+		if menuChildren[m.ParentId] == nil {
+			menuChildren[m.ParentId] = make([]*speech_recognition.SpeechRecognitionTagMenuNodeItem, 0)
+		}
+		menuChildren[m.ParentId] = append(menuChildren[m.ParentId], &speech_recognition.SpeechRecognitionTagMenuNodeItem{
+			NodeType:   speech_recognition.SpeechRecognitionTagMenuNodeTypeDefault,
+			MenuId:     m.SpeechRecognitionTagMenuId,
+			MenuName:   m.MenuName,
+			ParentId:   m.ParentId,
+			Sort:       m.Sort,
+			CreateTime: utils.TimeTransferString(utils.FormatDateTime, m.CreateTime),
+		})
+	}
+
+	// 目录下的标签
+	tags := make([]*speech_recognition.SpeechRecognitionTag, 0)
+	{
+		tagOb := new(speech_recognition.SpeechRecognitionTag)
+		cond := fmt.Sprintf(` %s IN (%s)`, speech_recognition.SpeechRecognitionTagCols.MenuId, utils.GetOrmInReplace(len(menuIds)))
+		pars := make([]interface{}, 0)
+		pars = append(pars, menuIds)
+		list, e := tagOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC, %s DESC", speech_recognition.SpeechRecognitionTagMenuCols.Sort, speech_recognition.SpeechRecognitionTagMenuCols.CreateTime))
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取标签列表失败, Err: " + e.Error()
+			return
+		}
+		tags = list
+	}
+	menuTags := make(map[int][]*speech_recognition.SpeechRecognitionTagMenuNodeItem)
+	for _, s := range tags {
+		if menuTags[s.MenuId] == nil {
+			menuTags[s.MenuId] = make([]*speech_recognition.SpeechRecognitionTagMenuNodeItem, 0)
+		}
+		menuTags[s.MenuId] = append(menuTags[s.MenuId], &speech_recognition.SpeechRecognitionTagMenuNodeItem{
+			NodeType:   speech_recognition.SpeechRecognitionTagMenuNodeTypeTag,
+			TagId:      s.SpeechRecognitionTagId,
+			TagName:    s.TagName,
+			ParentId:   s.MenuId,
+			Sort:       s.Sort,
+			CreateTime: utils.TimeTransferString(utils.FormatDateTime, s.CreateTime),
+		})
+	}
+
+	for _, m := range menus {
+		t := &speech_recognition.SpeechRecognitionTagMenuNodeItem{
+			NodeType:   speech_recognition.SpeechRecognitionTagMenuNodeTypeDefault,
+			MenuId:     m.SpeechRecognitionTagMenuId,
+			MenuName:   m.MenuName,
+			ParentId:   m.ParentId,
+			Sort:       m.Sort,
+			CreateTime: utils.TimeTransferString(utils.FormatDateTime, m.CreateTime),
+			Children:   make([]*speech_recognition.SpeechRecognitionTagMenuNodeItem, 0),
+		}
+		if menuTags[m.SpeechRecognitionTagMenuId] != nil {
+			t.Children = append(t.Children, menuTags[m.SpeechRecognitionTagMenuId]...)
+		}
+		if menuChildren[m.SpeechRecognitionTagMenuId] != nil {
+			t.Children = append(t.Children, menuChildren[m.SpeechRecognitionTagMenuId]...)
+		}
+		resp = append(resp, t)
+	}
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// List
+// @Title 目录列表
+// @Description 目录列表
+// @Success 200 {object} speech_recognition.SpeechRecognitionTagMenuItem
+// @router /tag/menu/tree [get]
+func (this *SpeechRecognitionTagMenuController) List() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	menus := make([]*speech_recognition.SpeechRecognitionTagMenu, 0)
+	{
+		menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
+		list, e := menuOb.GetItemsByCondition(``, make([]interface{}, 0), []string{}, fmt.Sprintf("%s ASC, %s ASC", speech_recognition.SpeechRecognitionTagMenuCols.ParentId, speech_recognition.SpeechRecognitionTagMenuCols.Sort))
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取目录列表失败, Err: " + e.Error()
+			return
+		}
+		menus = list
+	}
+
+	// 递归处理成目录树
+	resp := services.GetSpeechRecognitionTagMenuTreeRecursive(menus, 0)
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}

+ 4 - 1
models/speech_recognition/speech_recognition.go

@@ -19,6 +19,7 @@ type SpeechRecognition struct {
 	SysUserName         string    `description:"创建人姓名"`
 	State               int       `description:"状态:1-待转换;2-转换中;3-转换完成;4-转换失败"`
 	Abstract            string    `description:"摘要,取前几段内容"`
+	Sort                int       `description:"目录下的排序"`
 	CreateTime          time.Time `description:"创建时间"`
 	ModifyTime          time.Time `description:"修改时间"`
 }
@@ -33,6 +34,7 @@ var SpeechRecognitionCols = struct {
 	SysUserName         string
 	State               string
 	Abstract            string
+	Sort                string
 	CreateTime          string
 	ModifyTime          string
 }{
@@ -45,12 +47,13 @@ var SpeechRecognitionCols = struct {
 	SysUserName:         "sys_user_name",
 	State:               "state",
 	Abstract:            "abstract",
+	Sort:                "sort",
 	CreateTime:          "create_time",
 	ModifyTime:          "modify_time",
 }
 
 func (m *SpeechRecognition) TableName() string {
-	return "speech_recognition_id"
+	return "speech_recognition"
 }
 
 func (m *SpeechRecognition) PrimaryId() string {

+ 174 - 0
models/speech_recognition/speech_recognition_menu.go

@@ -1,4 +1,178 @@
 package speech_recognition
 
+import (
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+const (
+	SpeechRecognitionMenuNodeTypeDefault = 0
+	SpeechRecognitionMenuNodeTypeSpeech  = 1
+)
+
+// SpeechRecognitionMenu 语音识别-目录表
 type SpeechRecognitionMenu struct {
+	SpeechRecognitionMenuId int       `orm:"column(speech_recognition_menu_id);pk"`
+	MenuName                string    `description:"目录名称"`
+	ParentId                int       `description:"父级ID"`
+	Level                   int       `description:"目录层级"`
+	Sort                    int       `description:"排序"`
+	CreateTime              time.Time `description:"创建时间"`
+	ModifyTime              time.Time `description:"修改时间"`
+}
+
+var SpeechRecognitionMenuCols = struct {
+	SpeechRecognitionMenuId string
+	MenuName                string
+	ParentId                string
+	Level                   string
+	Sort                    string
+	CreateTime              string
+	ModifyTime              string
+}{
+	SpeechRecognitionMenuId: "speech_recognition_menu_id",
+	MenuName:                "menu_name",
+	ParentId:                "parent_id",
+	Level:                   "level",
+	Sort:                    "sort",
+	CreateTime:              "create_time",
+	ModifyTime:              "modify_time",
+}
+
+func (m *SpeechRecognitionMenu) TableName() string {
+	return "speech_recognition_menu"
+}
+
+func (m *SpeechRecognitionMenu) PrimaryId() string {
+	return SpeechRecognitionMenuCols.SpeechRecognitionMenuId
+}
+
+func (m *SpeechRecognitionMenu) Create() (err error) {
+	o := orm.NewOrm()
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.SpeechRecognitionMenuId = int(id)
+	return
+}
+
+func (m *SpeechRecognitionMenu) CreateMulti(items []*SpeechRecognitionMenu) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *SpeechRecognitionMenu) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *SpeechRecognitionMenu) Del() (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	_, err = o.Raw(sql, m.SpeechRecognitionMenuId).Exec()
+	return
+}
+
+func (m *SpeechRecognitionMenu) MultiDel(menuIds []int) (err error) {
+	if len(menuIds) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.PrimaryId(), utils.GetOrmInReplace(len(menuIds)))
+	_, err = o.Raw(sql, menuIds).Exec()
+	return
+}
+
+func (m *SpeechRecognitionMenu) GetItemById(id int) (item *SpeechRecognitionMenu, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognitionMenu) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *SpeechRecognitionMenu, err error) {
+	o := orm.NewOrm()
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s %s LIMIT 1`, m.TableName(), condition, order)
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognitionMenu) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *SpeechRecognitionMenu) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*SpeechRecognitionMenu, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *SpeechRecognitionMenu) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*SpeechRecognitionMenu, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// SpeechRecognitionMenuNodeItem 语音识别目录节点
+type SpeechRecognitionMenuNodeItem struct {
+	NodeType              int                              `description:"节点类型:0-目录;1-语音识别"`
+	MenuId                int                              `description:"目录ID"`
+	MenuName              string                           `description:"目录名称"`
+	SpeechRecognitionId   int                              `description:"语音识别ID"`
+	SpeechRecognitionName string                           `description:"语音识别名称"`
+	ParentId              int                              `description:"父级ID"`
+	Sort                  int                              `description:"排序"`
+	CreateTime            string                           `description:"创建时间"`
+	Children              []*SpeechRecognitionMenuNodeItem `description:"子节点"`
+}
+
+// SpeechRecognitionMenuAddReq 新增语音识别目录
+type SpeechRecognitionMenuAddReq struct {
+	ParentId int    `description:"父级ID"`
+	MenuName string `description:"目录名称"`
+}
+
+// SpeechRecognitionMenuEditReq 编辑语音识别目录
+type SpeechRecognitionMenuEditReq struct {
+	MenuId   int    `description:"目录ID"`
+	MenuName string `description:"目录名称"`
+}
+
+// SpeechRecognitionMenuRemoveReq 删除语音识别目录
+type SpeechRecognitionMenuRemoveReq struct {
+	MenuId int `description:"目录ID"`
 }

+ 180 - 0
models/speech_recognition/speech_recognition_tag.go

@@ -1,4 +1,184 @@
 package speech_recognition
 
+import (
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+// SpeechRecognitionTag 语音识别-标签表
 type SpeechRecognitionTag struct {
+	SpeechRecognitionTagId int       `orm:"column(speech_recognition_tag_id);pk"`
+	TagName                string    `description:"标签名称"`
+	MenuId                 int       `description:"目录ID"`
+	MenuPath               int       `description:"所属目录位置,例:/一级目录ID/二级目录ID"`
+	Sort                   int       `description:"排序"`
+	CreateTime             time.Time `description:"创建时间"`
+	ModifyTime             time.Time `description:"修改时间"`
+}
+
+var SpeechRecognitionTagCols = struct {
+	SpeechRecognitionTagId string
+	TagName                string
+	MenuId                 string
+	MenuPath               string
+	Sort                   string
+	CreateTime             string
+	ModifyTime             string
+}{
+	SpeechRecognitionTagId: "speech_recognition_tag_id",
+	TagName:                "tag_name",
+	MenuId:                 "menu_id",
+	MenuPath:               "menu_path",
+	Sort:                   "sort",
+	CreateTime:             "create_time",
+	ModifyTime:             "modify_time",
+}
+
+func (m *SpeechRecognitionTag) TableName() string {
+	return "speech_recognition_tag"
+}
+
+func (m *SpeechRecognitionTag) PrimaryId() string {
+	return SpeechRecognitionTagCols.SpeechRecognitionTagId
+}
+
+func (m *SpeechRecognitionTag) Create() (err error) {
+	o := orm.NewOrm()
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.SpeechRecognitionTagId = int(id)
+	return
+}
+
+func (m *SpeechRecognitionTag) CreateMulti(items []*SpeechRecognitionTag) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *SpeechRecognitionTag) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *SpeechRecognitionTag) Del() (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	_, err = o.Raw(sql, m.SpeechRecognitionTagId).Exec()
+	return
+}
+
+func (m *SpeechRecognitionTag) MultiDel(menuIds []int) (err error) {
+	if len(menuIds) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.PrimaryId(), utils.GetOrmInReplace(len(menuIds)))
+	_, err = o.Raw(sql, menuIds).Exec()
+	return
+}
+
+func (m *SpeechRecognitionTag) GetItemById(id int) (item *SpeechRecognitionTag, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognitionTag) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *SpeechRecognitionTag, err error) {
+	o := orm.NewOrm()
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s %s LIMIT 1`, m.TableName(), condition, order)
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognitionTag) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *SpeechRecognitionTag) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*SpeechRecognitionTag, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *SpeechRecognitionTag) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*SpeechRecognitionTag, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// SpeechRecognitionTagItem 语音识别标签
+type SpeechRecognitionTagItem struct {
+	TagId      int    `description:"标签ID"`
+	TagName    string `description:"标签名称"`
+	MenuId     int    `description:"目录ID"`
+	MenuPath   int    `description:"所属目录位置,例:/一级目录ID/二级目录ID"`
+	Sort       int    `description:"排序"`
+	CreateTime string `description:"创建时间"`
+}
+
+func FormatSpeechRecognitionTag2Item(origin *SpeechRecognitionTag) (item *SpeechRecognitionTagItem) {
+	if origin == nil {
+		return
+	}
+	item = new(SpeechRecognitionTagItem)
+	item.TagId = origin.SpeechRecognitionTagId
+	item.TagName = origin.TagName
+	item.MenuId = origin.MenuId
+	item.MenuPath = origin.MenuPath
+	item.Sort = origin.Sort
+	item.CreateTime = utils.TimeTransferString(utils.FormatDateTime, origin.CreateTime)
+	return
+}
+
+// SpeechRecognitionTagAddReq 新增标签
+type SpeechRecognitionTagAddReq struct {
+	MenuId  int    `description:"目录ID"`
+	TagName string `description:"标签名称"`
+}
+
+// SpeechRecognitionTagEditReq 编辑标签
+type SpeechRecognitionTagEditReq struct {
+	TagId   int    `description:"标签ID"`
+	TagName string `description:"标签名称"`
+}
+
+// SpeechRecognitionTagRemoveReq 删除标签
+type SpeechRecognitionTagRemoveReq struct {
+	TagId int `description:"标签ID"`
 }

+ 126 - 0
models/speech_recognition/speech_recognition_tag_mapping.go

@@ -1,4 +1,130 @@
 package speech_recognition
 
+import (
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+)
+
+// SpeechRecognitionTagMapping 语音识别-标签关联表
 type SpeechRecognitionTagMapping struct {
+	Id                  int `orm:"column(id);pk"`
+	SpeechRecognitionId int `description:"语音识别ID"`
+	TagId               int `description:"标签ID"`
+}
+
+var SpeechRecognitionTagMappingCols = struct {
+	Id                  string
+	SpeechRecognitionId string
+	TagId               string
+}{
+	Id:                  "id",
+	SpeechRecognitionId: "speech_recognition_id",
+	TagId:               "tag_id",
+}
+
+func (m *SpeechRecognitionTagMapping) TableName() string {
+	return "speech_recognition_tag_mapping"
+}
+
+func (m *SpeechRecognitionTagMapping) PrimaryId() string {
+	return SpeechRecognitionTagMappingCols.Id
+}
+
+func (m *SpeechRecognitionTagMapping) Create() (err error) {
+	o := orm.NewOrm()
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.Id = int(id)
+	return
+}
+
+func (m *SpeechRecognitionTagMapping) CreateMulti(items []*SpeechRecognitionTagMapping) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *SpeechRecognitionTagMapping) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *SpeechRecognitionTagMapping) Del() (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	_, err = o.Raw(sql, m.Id).Exec()
+	return
+}
+
+func (m *SpeechRecognitionTagMapping) MultiDel(menuIds []int) (err error) {
+	if len(menuIds) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.PrimaryId(), utils.GetOrmInReplace(len(menuIds)))
+	_, err = o.Raw(sql, menuIds).Exec()
+	return
+}
+
+func (m *SpeechRecognitionTagMapping) GetItemById(id int) (item *SpeechRecognitionTagMapping, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognitionTagMapping) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *SpeechRecognitionTagMapping, err error) {
+	o := orm.NewOrm()
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s %s LIMIT 1`, m.TableName(), condition, order)
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognitionTagMapping) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *SpeechRecognitionTagMapping) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*SpeechRecognitionTagMapping, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *SpeechRecognitionTagMapping) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*SpeechRecognitionTagMapping, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
 }

+ 185 - 0
models/speech_recognition/speech_recognition_tag_menu.go

@@ -1,4 +1,189 @@
 package speech_recognition
 
+import (
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+const (
+	SpeechRecognitionTagMenuNodeTypeDefault = 0
+	SpeechRecognitionTagMenuNodeTypeTag     = 1
+)
+
+// SpeechRecognitionTagMenu 标签目录表
 type SpeechRecognitionTagMenu struct {
+	SpeechRecognitionTagMenuId int       `orm:"column(speech_recognition_tag_menu_id);pk"`
+	MenuName                   string    `description:"目录名称"`
+	ParentId                   int       `description:"父级ID"`
+	Level                      int       `description:"目录层级"`
+	Sort                       int       `description:"排序"`
+	CreateTime                 time.Time `description:"创建时间"`
+	ModifyTime                 time.Time `description:"修改时间"`
+}
+
+var SpeechRecognitionTagMenuCols = struct {
+	SpeechRecognitionTagMenuId string
+	MenuName                   string
+	ParentId                   string
+	Level                      string
+	Sort                       string
+	CreateTime                 string
+	ModifyTime                 string
+}{
+	SpeechRecognitionTagMenuId: "speech_recognition_tag_menu_id",
+	MenuName:                   "menu_name",
+	ParentId:                   "parent_id",
+	Level:                      "level",
+	Sort:                       "sort",
+	CreateTime:                 "create_time",
+	ModifyTime:                 "modify_time",
+}
+
+func (m *SpeechRecognitionTagMenu) TableName() string {
+	return "speech_recognition_tag_menu"
+}
+
+func (m *SpeechRecognitionTagMenu) PrimaryId() string {
+	return SpeechRecognitionTagMenuCols.SpeechRecognitionTagMenuId
+}
+
+func (m *SpeechRecognitionTagMenu) Create() (err error) {
+	o := orm.NewOrm()
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.SpeechRecognitionTagMenuId = int(id)
+	return
+}
+
+func (m *SpeechRecognitionTagMenu) CreateMulti(items []*SpeechRecognitionTagMenu) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *SpeechRecognitionTagMenu) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *SpeechRecognitionTagMenu) Del() (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	_, err = o.Raw(sql, m.SpeechRecognitionTagMenuId).Exec()
+	return
+}
+
+func (m *SpeechRecognitionTagMenu) MultiDel(menuIds []int) (err error) {
+	if len(menuIds) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.PrimaryId(), utils.GetOrmInReplace(len(menuIds)))
+	_, err = o.Raw(sql, menuIds).Exec()
+	return
+}
+
+func (m *SpeechRecognitionTagMenu) GetItemById(id int) (item *SpeechRecognitionTagMenu, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognitionTagMenu) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *SpeechRecognitionTagMenu, err error) {
+	o := orm.NewOrm()
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s %s LIMIT 1`, m.TableName(), condition, order)
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognitionTagMenu) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *SpeechRecognitionTagMenu) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*SpeechRecognitionTagMenu, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *SpeechRecognitionTagMenu) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*SpeechRecognitionTagMenu, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// SpeechRecognitionTagMenuItem 标签目录
+type SpeechRecognitionTagMenuItem struct {
+	MenuId     int                             `description:"目录ID"`
+	MenuName   string                          `description:"目录名称"`
+	ParentId   int                             `description:"父级ID"`
+	Level      int                             `description:"目录层级"`
+	Sort       int                             `description:"排序"`
+	CreateTime string                          `description:"创建时间"`
+	Children   []*SpeechRecognitionTagMenuItem `description:"子目录"`
+}
+
+// SpeechRecognitionTagMenuNodeItem 标签目录树节点
+type SpeechRecognitionTagMenuNodeItem struct {
+	NodeType   int                                 `description:"节点类型:0-目录;1-标签"`
+	MenuId     int                                 `description:"目录ID"`
+	MenuName   string                              `description:"目录名称"`
+	TagId      int                                 `description:"标签ID"`
+	TagName    string                              `description:"标签名称"`
+	ParentId   int                                 `description:"父级ID"`
+	Sort       int                                 `description:"排序"`
+	CreateTime string                              `description:"创建时间"`
+	Children   []*SpeechRecognitionTagMenuNodeItem `description:"子节点"`
+}
+
+// SpeechRecognitionTagMenuAddReq 新增标签目录
+type SpeechRecognitionTagMenuAddReq struct {
+	ParentId int    `description:"父级ID"`
+	MenuName string `description:"目录名称"`
+}
+
+// SpeechRecognitionTagMenuEditReq 编辑标签目录
+type SpeechRecognitionTagMenuEditReq struct {
+	MenuId   int    `description:"目录ID"`
+	MenuName string `description:"目录名称"`
+}
+
+// SpeechRecognitionTagMenuRemoveReq 删除标签目录
+type SpeechRecognitionTagMenuRemoveReq struct {
+	MenuId int `description:"目录ID"`
 }

+ 117 - 0
routers/commentsRouter.go

@@ -6046,6 +6046,123 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionMenuController"],
+        beego.ControllerComments{
+            Method: "Add",
+            Router: `/menu/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionMenuController"],
+        beego.ControllerComments{
+            Method: "Edit",
+            Router: `/menu/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionMenuController"],
+        beego.ControllerComments{
+            Method: "Remove",
+            Router: `/menu/remove`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionMenuController"],
+        beego.ControllerComments{
+            Method: "Tree",
+            Router: `/menu/tree`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagController"],
+        beego.ControllerComments{
+            Method: "Add",
+            Router: `/tag/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagController"],
+        beego.ControllerComments{
+            Method: "Edit",
+            Router: `/tag/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagController"],
+        beego.ControllerComments{
+            Method: "List",
+            Router: `/tag/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagController"],
+        beego.ControllerComments{
+            Method: "Remove",
+            Router: `/tag/remove`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"],
+        beego.ControllerComments{
+            Method: "Add",
+            Router: `/tag/menu/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"],
+        beego.ControllerComments{
+            Method: "Edit",
+            Router: `/tag/menu/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"],
+        beego.ControllerComments{
+            Method: "Remove",
+            Router: `/tag/menu/remove`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"],
+        beego.ControllerComments{
+            Method: "Tree",
+            Router: `/tag/menu/tree`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"],
+        beego.ControllerComments{
+            Method: "List",
+            Router: `/tag/menu/tree`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/trade_analysis:TradeAnalysisController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/trade_analysis:TradeAnalysisController"],
         beego.ControllerComments{
             Method: "GetClassifyName",

+ 3 - 0
routers/router.go

@@ -348,6 +348,9 @@ func init() {
 			web.NSInclude(
 				&speech_recognition.SpeechRecognitionCommonController{},
 				&speech_recognition.SpeechRecognitionController{},
+				&speech_recognition.SpeechRecognitionMenuController{},
+				&speech_recognition.SpeechRecognitionTagController{},
+				&speech_recognition.SpeechRecognitionTagMenuController{},
 			),
 		),
 	)

+ 24 - 0
services/speech_recognition.go

@@ -1 +1,25 @@
 package services
+
+import (
+	"eta/eta_api/models/speech_recognition"
+	"eta/eta_api/utils"
+)
+
+// GetSpeechRecognitionTagMenuTreeRecursive 递归获取标签目录树
+func GetSpeechRecognitionTagMenuTreeRecursive(list []*speech_recognition.SpeechRecognitionTagMenu, parentId int) []*speech_recognition.SpeechRecognitionTagMenuItem {
+	res := make([]*speech_recognition.SpeechRecognitionTagMenuItem, 0)
+	for _, v := range list {
+		if v.ParentId == parentId {
+			t := new(speech_recognition.SpeechRecognitionTagMenuItem)
+			t.MenuId = v.SpeechRecognitionTagMenuId
+			t.MenuName = v.MenuName
+			t.ParentId = v.ParentId
+			t.Level = v.Level
+			t.Sort = v.Sort
+			t.CreateTime = utils.TimeTransferString(utils.FormatDateTime, v.CreateTime)
+			t.Children = GetSpeechRecognitionTagMenuTreeRecursive(list, v.SpeechRecognitionTagMenuId)
+			res = append(res, t)
+		}
+	}
+	return res
+}