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/services/alarm_msg"
	"eta/eta_api/utils"
	"fmt"
	"github.com/rdlucklib/rdluck_tools/paging"
	"os"
	"sort"
	"strconv"
	"strings"
	"time"
)

type SpeechRecognitionController struct {
	controllers.BaseAuthController
}

type SpeechRecognitionCommonController struct {
	controllers.BaseCommonController
}

// RecTaskCallback
// @Title 语音识别回调
// @Description 语音识别回调
// @Param	request	body services.TencentRecTaskCallback true "type json string"
// @Success 200 string "操作成功"
// @router /rec_task/callback [post]
func (this *SpeechRecognitionCommonController) RecTaskCallback() {
	// 此接口返回指定响应体
	br := new(services.TencentRecTaskCallbackResp)
	var errMsg string
	defer func() {
		if errMsg != "" {
			br.Code = 403
			br.Message = "回调失败"
			go alarm_msg.SendAlarmMsg(fmt.Sprintf("语音识别回调失败, ErrMsg: %s", errMsg), 1)
		} else {
			br.Code = 0
			br.Message = "success"
		}
		_ = this.JSON(br, false, false)
	}()

	code, _ := this.GetInt("code", -1)
	requestId, _ := this.GetInt("requestId", 0)
	detail := this.GetString("resultDetail")
	utils.FileLog.Info(fmt.Sprintf("RecTaskCallback, requestId: %d", requestId))

	// 获取taskId对应的API请求及语音识别
	logOb := new(speech_recognition.SpeechRecognitionApiLog)
	cond := fmt.Sprintf(` AND %s = ?`, speech_recognition.SpeechRecognitionApiLogCols.RequestId)
	pars := make([]interface{}, 0)
	pars = append(pars, requestId)
	apiLog, e := logOb.GetItemByCondition(cond, pars, "")
	if e != nil {
		errMsg = "获取API记录失败"
		utils.FileLog.Info("API回调-获取请求记录失败, Err: " + e.Error())
		return
	}
	speechOb := new(speech_recognition.SpeechRecognition)
	speechItem, e := speechOb.GetItemById(apiLog.SpeechRecognitionId)
	if e != nil {
		errMsg = "获取语音识别失败"
		utils.FileLog.Info("获取语音识别失败, Err: " + e.Error())
		return
	}

	// API结果返回有误
	nowTime := time.Now().Local()
	if code != speech_recognition.ApiRequestCodeSuccess {
		convertRemark := speech_recognition.ApiErrMsgMapping[code]
		if convertRemark == "" {
			convertRemark = fmt.Sprintf("未知错误: %d", code)
		}
		speechItem.ConvertRemark = convertRemark
		speechItem.State = speech_recognition.SpeechRecognitionStateFail
		speechItem.ModifyTime = nowTime
		speechCols := []string{speech_recognition.SpeechRecognitionCols.ConvertRemark, speech_recognition.SpeechRecognitionCols.State, speech_recognition.SpeechRecognitionCols.ModifyTime}

		apiLog.RequestCode = code
		apiLog.RequestResult = convertRemark
		apiLog.ModifyTime = nowTime
		apiLogCols := []string{speech_recognition.SpeechRecognitionApiLogCols.RequestCode, speech_recognition.SpeechRecognitionApiLogCols.RequestResult, speech_recognition.SpeechRecognitionApiLogCols.ModifyTime}

		// 更新语音识别及API记录
		if e := speech_recognition.UpdateSpeechAndApiLog(speechItem, speechCols, apiLog, apiLogCols); e != nil {
			errMsg = "更新API返回结果失败"
			utils.FileLog.Info("更新API返回结果失败, Err: " + e.Error())
		}
		return
	}

	// 解析转写段落内容
	sentences := make([]*services.TencentRecTaskSentenceDetail, 0)
	if e := json.Unmarshal([]byte(detail), &sentences); e != nil {
		errMsg = "解析语音识别内容失败"
		utils.FileLog.Info("解析语音识别内容失败, Err: " + e.Error())
		return
	}
	contents := make([]*speech_recognition.SpeechRecognitionContent, 0)
	sorts := 0 // API返回的结果本身是已排过序的
	var abstract string
	var abstractLimit int
	for _, v := range sentences {
		sorts += 1
		t := new(speech_recognition.SpeechRecognitionContent)
		t.SpeechRecognitionId = speechItem.SpeechRecognitionId
		t.Sort = sorts
		t.Content = v.FinalSentence
		t.StartMs = v.StartMs
		t.EndMs = v.EndMs
		t.CreateTime = nowTime
		t.ModifyTime = nowTime
		contents = append(contents, t)
		// 取前几段作为摘要保存
		if abstractLimit < 5 {
			abstractLimit += 1
			abstract += v.FinalSentence
		}
	}

	speechItem.Abstract = abstract
	speechItem.State = speech_recognition.SpeechRecognitionStateSuccess
	speechItem.ModifyTime = nowTime
	speechCols := []string{speech_recognition.SpeechRecognitionCols.Abstract, speech_recognition.SpeechRecognitionCols.State, speech_recognition.SpeechRecognitionCols.ModifyTime}

	apiLog.RequestCode = code
	apiLog.RequestResult = detail
	apiLog.ModifyTime = time.Now().Local()
	apiLogCols := []string{speech_recognition.SpeechRecognitionApiLogCols.RequestCode, speech_recognition.SpeechRecognitionApiLogCols.RequestResult, speech_recognition.SpeechRecognitionApiLogCols.ModifyTime}

	// 新增解析内容并更新语音识别及API记录
	if e := speech_recognition.CreateContentAndUpdateSpeechAndApiLog(contents, speechItem, speechCols, apiLog, apiLogCols); e != nil {
		errMsg = "新增API返回结果失败"
		utils.FileLog.Info("新增API返回结果失败, Err: " + e.Error())
	}
}

// Convert
// @Title 语音转换
// @Description 语音转换
// @Param	request	body speech_recognition.SpeechRecognitionConvertReq true "type json string"
// @Success 200 string "操作成功"
// @router /convert [post]
func (this *SpeechRecognitionController) Convert() {
	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.SpeechRecognitionConvertReq
	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
	}
	if len(req.Files) == 0 {
		br.Msg = "请上传转写文件"
		return
	}
	for _, r := range req.Files {
		if r.FileName == "" && r.ResourceUrl == "" {
			br.Msg = "转写文件有误,请检查"
			return
		}
	}
	sortMax, e := services.GetSpeechMenuMaxSort(req.MenuId)
	if e != nil {
		br.Msg = "操作失败"
		br.ErrMsg = "获取语音识别目录下最大排序失败, Err: " + e.Error()
		return
	}

	speeches := make([]*speech_recognition.SpeechRecognition, 0)
	nowTime := time.Now().Local()
	for _, v := range req.Files {
		sortMax += 1
		t := new(speech_recognition.SpeechRecognition)
		t.FileName = v.FileName
		t.ResourceUrl = v.ResourceUrl
		t.MenuId = req.MenuId
		timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
		t.UniqueCode = utils.MD5(fmt.Sprintf("%s_%s", t.TableName(), timestamp))
		t.SysUserId = sysUser.AdminId
		t.SysUserName = sysUser.RealName
		t.State = speech_recognition.SpeechRecognitionStateWait
		t.Sort = sortMax
		t.FileSecond = v.FileSecond
		t.FileSize = v.FileSize
		t.CreateTime = nowTime
		t.ModifyTime = nowTime
		// CreateMulti拿不到主键, 此处用循环新增获取
		if e := t.Create(); e != nil {
			br.Msg = "操作失败"
			br.ErrMsg = "批量新增转写文件失败, Err: " + e.Error()
			return
		}
		speeches = append(speeches, t)
	}

	// 批量转写语音
	go func() {
		services.BatchConvertSpeech(speeches)
	}()

	br.Ret = 200
	br.Success = true
	br.Msg = "操作成功"
}

// ConvertList
// @Title 转换列表
// @Description 转换列表
// @Success 200 {object} speech_recognition.SpeechRecognitionItem
// @router /convert_list [get]
func (this *SpeechRecognitionController) ConvertList() {
	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
	}

	// 仅取待转换和转换失败的
	states := []int{speech_recognition.SpeechRecognitionStateWait, speech_recognition.SpeechRecognitionStateFail}
	speechOb := new(speech_recognition.SpeechRecognition)
	cond := fmt.Sprintf(` AND %s = ? AND %s IN (%s)`, speech_recognition.SpeechRecognitionCols.SysUserId, speech_recognition.SpeechRecognitionCols.State, utils.GetOrmInReplace(len(states)))
	pars := make([]interface{}, 0)
	pars = append(pars, sysUser.AdminId, states)
	list, e := speechOb.GetItemsByCondition(cond, pars, []string{}, "")
	if e != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取转写文件列表失败, Err: " + e.Error()
		return
	}
	resp := make([]*speech_recognition.SpeechRecognitionItem, 0)
	for _, v := range list {
		resp = append(resp, speech_recognition.FormatSpeechRecognition2Item(v))
	}

	br.Data = resp
	br.Ret = 200
	br.Success = true
	br.Msg = "获取成功"
}

// Save
// @Title 保存内容
// @Description 保存内容
// @Param	request	body speech_recognition.SpeechRecognitionSaveReq true "type json string"
// @Success 200 string "操作成功"
// @router /save [post]
func (this *SpeechRecognitionController) Save() {
	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.SpeechRecognitionSaveReq
	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
		br.Msg = "参数有误"
		br.ErrMsg = "参数解析失败, Err: " + e.Error()
		return
	}
	if req.SpeechRecognitionId <= 0 {
		br.Msg = "参数有误"
		br.ErrMsg = fmt.Sprintf("参数有误, SpeechRecognitionId: %d", req.SpeechRecognitionId)
		return
	}
	if len(req.Contents) == 0 {
		br.Ret = 200
		br.Success = true
		br.Msg = "操作成功"
		return
	}
	req.FileName = strings.TrimSpace(req.FileName)
	if req.FileName == "" {
		br.Msg = "请输入文件名称"
		return
	}

	speechOb := new(speech_recognition.SpeechRecognition)
	speechItem, e := speechOb.GetItemById(req.SpeechRecognitionId)
	if e != nil {
		if e.Error() == utils.ErrNoRow() {
			br.Msg = "转写文件不存在,请刷新页面"
			return
		}
		br.Msg = "操作失败"
		br.ErrMsg = "获取转写文件失败, Err: " + e.Error()
		return
	}
	if req.FileName != speechItem.FileName {
		// 校验重名
		{
			cond := fmt.Sprintf(` AND %s = ? AND %s <> ?`, speech_recognition.SpeechRecognitionCols.FileName, speech_recognition.SpeechRecognitionCols.SpeechRecognitionId)
			pars := make([]interface{}, 0)
			pars = append(pars, req.FileName, req.SpeechRecognitionId)
			exists, e := speechOb.GetItemByCondition(cond, pars, "")
			if e != nil && e.Error() != utils.ErrNoRow() {
				br.Msg = "操作失败"
				br.ErrMsg = "获取同名转写文件失败, Err: " + e.Error()
				return
			}
			if exists != nil && exists.SpeechRecognitionId > 0 {
				br.Msg = "文件名称已存在,请重新输入"
				return
			}
		}
	}

	// 取前几段作为摘要保存
	var abstractNum int
	var abstract string
	for _, v := range req.Contents {
		if abstractNum < 5 {
			abstractNum += 1
			abstract += v.Content
		}
	}
	speechItem.FileName = req.FileName
	speechItem.Abstract = abstract
	speechItem.ModifyTime = time.Now().Local()
	speechCols := []string{speech_recognition.SpeechRecognitionCols.FileName, speech_recognition.SpeechRecognitionCols.Abstract, speech_recognition.SpeechRecognitionCols.ModifyTime}

	// 标签
	tagMappings := make([]*speech_recognition.SpeechRecognitionTagMapping, 0)
	for _, v := range req.TagIds {
		tagMappings = append(tagMappings, &speech_recognition.SpeechRecognitionTagMapping{
			SpeechRecognitionId: req.SpeechRecognitionId,
			TagId:               v,
		})
	}

	// 保存修改
	if e = speechOb.SpeechSave(speechItem, speechCols, req.Contents, tagMappings); e != nil {
		br.Msg = "操作失败"
		br.ErrMsg = "语音识别保存失败, Err: " + e.Error()
		return
	}

	br.Ret = 200
	br.Success = true
	br.Msg = "操作成功"
}

// RemoveFile
// @Title (软)删除文件
// @Description (软)删除文件
// @Param	request	body speech_recognition.SpeechRecognitionRemoveFileReq true "type json string"
// @Success 200 string "操作成功"
// @router /remove_file [post]
func (this *SpeechRecognitionController) RemoveFile() {
	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.SpeechRecognitionRemoveFileReq
	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
		br.Msg = "参数有误"
		br.ErrMsg = "参数解析失败, Err: " + e.Error()
		return
	}
	if req.SpeechRecognitionId <= 0 {
		br.Msg = "参数有误"
		br.ErrMsg = fmt.Sprintf("参数有误, SpeechRecognitionId: %d", req.SpeechRecognitionId)
		return
	}

	speechOb := new(speech_recognition.SpeechRecognition)
	speechItem, e := speechOb.GetItemById(req.SpeechRecognitionId)
	if e != nil {
		if e.Error() == utils.ErrNoRow() {
			br.Msg = "转写文件不存在,请刷新页面"
			return
		}
		br.Msg = "操作失败"
		br.ErrMsg = "获取转写文件失败, Err: " + e.Error()
		return
	}

	speechItem.FileState = speech_recognition.SpeechRecognitionFileRemoveFlag
	speechItem.ModifyTime = time.Now().Local()
	updateCols := []string{speech_recognition.SpeechRecognitionCols.FileState, speech_recognition.SpeechRecognitionCols.ModifyTime}
	if e = speechItem.Update(updateCols); e != nil {
		br.Msg = "操作失败"
		br.ErrMsg = "软删除转写文件失败, Err: " + e.Error()
		return
	}

	br.Ret = 200
	br.Success = true
	br.Msg = "操作成功"
}

// Rename
// @Title 重命名
// @Description 重命名
// @Param	request	body speech_recognition.SpeechRecognitionRenameReq true "type json string"
// @Success 200 string "操作成功"
// @router /rename [post]
func (this *SpeechRecognitionController) Rename() {
	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.SpeechRecognitionRenameReq
	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
		br.Msg = "参数有误"
		br.ErrMsg = "参数解析失败, Err: " + e.Error()
		return
	}
	if req.SpeechRecognitionId <= 0 {
		br.Msg = "参数有误"
		br.ErrMsg = fmt.Sprintf("参数有误, SpeechRecognitionId: %d", req.SpeechRecognitionId)
		return
	}
	req.FileName = strings.TrimSpace(req.FileName)
	if req.FileName == "" {
		br.Msg = "请输入文件名称"
		return
	}

	speechOb := new(speech_recognition.SpeechRecognition)
	speechItem, e := speechOb.GetItemById(req.SpeechRecognitionId)
	if e != nil {
		if e.Error() == utils.ErrNoRow() {
			br.Msg = "转写文件不存在,请刷新页面"
			return
		}
		br.Msg = "操作失败"
		br.ErrMsg = "获取转写文件失败, Err: " + e.Error()
		return
	}

	// 重名校验
	{
		cond := fmt.Sprintf(` AND %s = ? AND %s <> ?`, speech_recognition.SpeechRecognitionCols.FileName, speech_recognition.SpeechRecognitionCols.SpeechRecognitionId)
		pars := make([]interface{}, 0)
		pars = append(pars, req.FileName, req.SpeechRecognitionId)
		exists, e := speechOb.GetItemByCondition(cond, pars, "")
		if e != nil && e.Error() != utils.ErrNoRow() {
			br.Msg = "操作失败"
			br.ErrMsg = "获取同名转写文件失败, Err: " + e.Error()
			return
		}
		if exists != nil && exists.SpeechRecognitionId > 0 {
			br.Msg = "文件名称已存在,请重新输入"
			return
		}
	}

	speechItem.FileName = req.FileName
	speechItem.ModifyTime = time.Now().Local()
	updateCols := []string{speech_recognition.SpeechRecognitionCols.FileName, speech_recognition.SpeechRecognitionCols.ModifyTime}
	if e = speechItem.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.SpeechRecognitionRemoveReq true "type json string"
// @Success 200 string "操作成功"
// @router /remove [post]
func (this *SpeechRecognitionController) 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.SpeechRecognitionRemoveReq
	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
		br.Msg = "参数有误"
		br.ErrMsg = "参数解析失败, Err: " + e.Error()
		return
	}
	if req.SpeechRecognitionId <= 0 {
		br.Msg = "参数有误"
		br.ErrMsg = fmt.Sprintf("参数有误, SpeechRecognitionId: %d", req.SpeechRecognitionId)
		return
	}

	speechOb := new(speech_recognition.SpeechRecognition)
	speechItem, e := speechOb.GetItemById(req.SpeechRecognitionId)
	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
	}

	if e = speechItem.Del(); e != nil {
		br.Msg = "操作失败"
		br.ErrMsg = "删除转写文件失败, Err: " + e.Error()
		return
	}

	// 清除关联
	go func() {
		contentOb := new(speech_recognition.SpeechRecognitionContent)
		_ = contentOb.ClearContentBySpeechId(req.SpeechRecognitionId)
		mappingOb := new(speech_recognition.SpeechRecognitionTagMapping)
		_ = mappingOb.ClearMappingBySpeechId(req.SpeechRecognitionId)
	}()

	br.Ret = 200
	br.Success = true
	br.Msg = "操作成功"
}

// SaveTag
// @Title 保存标签
// @Description 保存标签
// @Param	request	body speech_recognition.SpeechRecognitionSaveTagReq true "type json string"
// @Success 200 string "操作成功"
// @router /save_tag [post]
func (this *SpeechRecognitionController) SaveTag() {
	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.SpeechRecognitionSaveTagReq
	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
		br.Msg = "参数有误"
		br.ErrMsg = "参数解析失败, Err: " + e.Error()
		return
	}
	if req.SpeechRecognitionId <= 0 {
		br.Msg = "参数有误"
		br.ErrMsg = fmt.Sprintf("参数有误, SpeechRecognitionId: %d", req.SpeechRecognitionId)
		return
	}

	speechOb := new(speech_recognition.SpeechRecognition)
	_, e := speechOb.GetItemById(req.SpeechRecognitionId)
	if e != nil {
		if e.Error() == utils.ErrNoRow() {
			br.Msg = "转写文件不存在,请刷新页面"
			return
		}
		br.Msg = "操作失败"
		br.ErrMsg = "获取转写文件失败, Err: " + e.Error()
		return
	}

	// 清除原标签
	mappingOb := new(speech_recognition.SpeechRecognitionTagMapping)
	if e = mappingOb.ClearMappingBySpeechId(req.SpeechRecognitionId); e != nil {
		br.Msg = "操作失败"
		br.ErrMsg = "清除转写文件标签失败, Err: " + e.Error()
		return
	}

	// 保存新标签
	if len(req.TagIds) > 0 {
		mappings := make([]*speech_recognition.SpeechRecognitionTagMapping, 0)
		for _, v := range req.TagIds {
			if v <= 0 {
				continue
			}
			mappings = append(mappings, &speech_recognition.SpeechRecognitionTagMapping{
				TagId:               v,
				SpeechRecognitionId: req.SpeechRecognitionId,
			})
		}
		if e = mappingOb.CreateMulti(mappings); e != nil {
			br.Msg = "操作失败"
			br.ErrMsg = "批量新增转写文件标签失败, Err: " + e.Error()
			return
		}
	}

	br.Ret = 200
	br.Success = true
	br.Msg = "操作成功"
}

// List
// @Title 语音识别列表
// @Description 语音识别列表
// @Param   FileName  query  string  false  "文件名称"
// @Param   StartTime  query  string  false  "开始时间"
// @Param   EndTime  query  string  false  "结束时间"
// @Param   CreateUserIds  query  string  false  "创建人ID"
// @Param   TagId  query  int  false  "标签ID"
// @Param   TagIds  query  string  false  "标签ID"
// @Param   MenuId  query  int  false  "目录ID"
// @Param   IsTagMenu  query  bool  false  "是否为标签目录"
// @Success 200 {object} speech_recognition.SpeechRecognitionListResp
// @router /list [get]
func (this *SpeechRecognitionController) 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
	}
	params := new(speech_recognition.SpeechRecognitionListReq)
	if e := this.ParseForm(params); e != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "参数解析失败, Err: " + e.Error()
		return
	}
	params.FileName = strings.TrimSpace(params.FileName)

	dataResp := new(speech_recognition.SpeechRecognitionListResp)
	cond := fmt.Sprintf(` AND %s = ?`, speech_recognition.SpeechRecognitionCols.State)
	pars := make([]interface{}, 0)
	pars = append(pars, speech_recognition.SpeechRecognitionStateSuccess)

	// 筛选项
	{
		if params.FileName != "" {
			cond += fmt.Sprintf(` AND %s LIKE ?`, speech_recognition.SpeechRecognitionCols.FileName)
			pars = append(pars, fmt.Sprint("%", params.FileName, "%"))
		}
		if params.StartTime != "" && params.EndTime != "" {
			_, e := time.Parse(utils.FormatDate, params.StartTime)
			if e != nil {
				br.Msg = "开始时间格式有误"
				return
			}
			_, e = time.Parse(utils.FormatDate, params.EndTime)
			if e != nil {
				br.Msg = "结束时间格式有误"
				return
			}
			st := fmt.Sprintf("%s 00:00:00", params.StartTime)
			ed := fmt.Sprintf("%s 23:59:59", params.EndTime)
			cond += fmt.Sprintf(` AND (%s BETWEEN ? AND ?)`, speech_recognition.SpeechRecognitionCols.CreateTime)
			pars = append(pars, st, ed)
		}
		if params.CreateUserId != "" {
			userArr := strings.Split(strings.TrimSpace(params.CreateUserId), ",")
			if len(userArr) > 0 {
				userIds := make([]int, 0)
				for _, v := range userArr {
					t, _ := strconv.Atoi(v)
					userIds = append(userIds, t)
				}
				if len(userIds) == 0 {
					br.Data = dataResp
					br.Ret = 200
					br.Success = true
					br.Msg = "获取成功"
					return
				}
				cond += fmt.Sprintf(` AND %s IN (%s)`, speech_recognition.SpeechRecognitionCols.SysUserId, utils.GetOrmInReplace(len(userIds)))
				pars = append(pars, userIds)
			}
		}
		// 语音识别目录-筛选子目录集合
		if params.MenuId > 0 && !params.IsTagMenu {
			{
				menuOb := new(speech_recognition.SpeechRecognitionMenu)
				menus, e := menuOb.GetItemsByCondition(``, make([]interface{}, 0), []string{}, "")
				if e != nil {
					br.Msg = "获取失败"
					br.ErrMsg = "获取语音识别目录列表失败, Err: " + e.Error()
					return
				}
				childIds := services.GetSpeechRecognitionMenuChildrenRecursive(menus, params.MenuId)
				menuIds := make([]int, 0)
				menuIds = append(menuIds, params.MenuId)
				if len(childIds) > 0 {
					menuIds = append(menuIds, childIds...)
				}
				cond += fmt.Sprintf(` AND %s IN (%s)`, speech_recognition.SpeechRecognitionCols.MenuId, utils.GetOrmInReplace(len(menuIds)))
				pars = append(pars, menuIds)
			}
		}
		// 标签目录-筛选目录下所有标签
		tagIds := make([]int, 0)
		if params.MenuId > 0 && params.IsTagMenu {
			{
				menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
				menus, e := menuOb.GetItemsByCondition(``, make([]interface{}, 0), []string{}, "")
				if e != nil {
					br.Msg = "获取失败"
					br.ErrMsg = "获取标签目录列表失败, Err: " + e.Error()
					return
				}
				childIds := services.GetSpeechRecognitionTagMenuChildrenRecursive(menus, params.MenuId)
				menuIds := make([]int, 0)
				menuIds = append(menuIds, params.MenuId)
				if len(childIds) > 0 {
					menuIds = append(menuIds, childIds...)
				}
				// 获取目录下所有标签
				tagOb := new(speech_recognition.SpeechRecognitionTag)
				ids, e := tagOb.GetTagIdsByMenuIds(menuIds)
				if e != nil {
					br.Msg = "获取失败"
					br.ErrMsg = "通过目录IDs获取标签IDs失败, Err: " + e.Error()
					return
				}
				// 此处查询无结果直接返回
				if len(ids) == 0 {
					br.Data = dataResp
					br.Ret = 200
					br.Success = true
					br.Msg = "获取成功"
					return
				}
				tagIds = ids
			}
		}

		// 标签筛选
		if params.TagId > 0 && params.TagIds == "" {
			tagIds = append(tagIds, params.TagId)
		}
		if params.TagId <= 0 && params.TagIds != "" {
			tagArr := strings.Split(params.TagIds, ",")
			if len(tagArr) > 0 {
				for _, v := range tagArr {
					t, _ := strconv.Atoi(v)
					tagIds = append(tagIds, t)
				}
			}
		}
		if len(tagIds) > 0 {
			mappingOb := new(speech_recognition.SpeechRecognitionTagMapping)
			tagSpeechIds, e := mappingOb.GetSpeechIdsByTagIds(tagIds)
			if e != nil {
				br.Msg = "获取失败"
				br.ErrMsg = "获取标签关联语音识别失败, Err: " + e.Error()
				return
			}
			if len(tagSpeechIds) == 0 {
				br.Data = dataResp
				br.Ret = 200
				br.Success = true
				br.Msg = "获取成功"
				return
			}
			cond += fmt.Sprintf(` AND %s IN (%s)`, speech_recognition.SpeechRecognitionCols.SpeechRecognitionId, utils.GetOrmInReplace(len(tagSpeechIds)))
			pars = append(pars, tagSpeechIds)
		}
	}

	// 分页列表
	speechOb := new(speech_recognition.SpeechRecognition)
	total, e := speechOb.GetCountByCondition(cond, pars)
	if e != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取语音识别列表总数失败, Err: " + e.Error()
		return
	}
	var startSize int
	if params.PageSize <= 0 {
		params.PageSize = utils.PageSize20
	}
	if params.CurrentIndex <= 0 {
		params.CurrentIndex = 1
	}
	startSize = utils.StartIndex(params.CurrentIndex, params.PageSize)
	list, e := speechOb.GetPageItemsByCondition(cond, pars, []string{}, "", startSize, params.PageSize)
	if e != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取语音识别列表失败, Err: " + e.Error()
		return
	}

	// 获取标签
	speechIds := make([]int, 0)
	for _, v := range list {
		speechIds = append(speechIds, v.SpeechRecognitionId)
	}
	mappingTags, e := speech_recognition.GetSpeechRecognitionTagsBySpeechIds(speechIds)
	if e != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取语音识别列表标签失败, Err: " + e.Error()
		return
	}
	speechDetailTags := make(map[int][]*speech_recognition.SpeechRecognitionDetailTag)
	for _, v := range mappingTags {
		if speechDetailTags[v.SpeechRecognitionId] == nil {
			speechDetailTags[v.SpeechRecognitionId] = make([]*speech_recognition.SpeechRecognitionDetailTag, 0)
		}
		speechDetailTags[v.SpeechRecognitionId] = append(speechDetailTags[v.SpeechRecognitionId], &speech_recognition.SpeechRecognitionDetailTag{
			TagId:   v.TagId,
			TagName: v.TagName,
		})
	}

	respList := make([]*speech_recognition.SpeechRecognitionDetailItem, 0)
	for _, v := range list {
		t := speech_recognition.FormatSpeechRecognition2DetailItem(v, make([]*speech_recognition.SpeechRecognitionContentItem, 0), speechDetailTags[v.SpeechRecognitionId], make([]*speech_recognition.SpeechRecognitionMenuItem, 0))
		respList = append(respList, t)
	}

	page := paging.GetPaging(params.CurrentIndex, params.PageSize, total)
	dataResp.Paging = page
	dataResp.List = respList
	br.Data = dataResp
	br.Ret = 200
	br.Success = true
	br.Msg = "获取成功"
}

// Detail
// @Title 语音识别详情
// @Description 语音识别详情
// @Param   SpeechRecognitionId  query  int  true  "语音识别ID"
// @Success 200 {object} speech_recognition.SpeechRecognitionDetailItem
// @router /detail [get]
func (this *SpeechRecognitionController) Detail() {
	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
	}
	speechId, _ := this.GetInt("SpeechRecognitionId")
	if speechId <= 0 {
		br.Msg = "参数有误"
		br.ErrMsg = fmt.Sprintf("参数有误, SpeechRecognitionId: %d", speechId)
		return
	}

	speechOb := new(speech_recognition.SpeechRecognition)
	speechItem, e := speechOb.GetItemById(speechId)
	if e != nil {
		if e.Error() == utils.ErrNoRow() {
			br.Msg = "转写文件不存在,请刷新页面"
			return
		}
		br.Msg = "获取失败"
		br.ErrMsg = "获取转写文件失败, Err: " + e.Error()
		return
	}

	// 获取内容
	contents := make([]*speech_recognition.SpeechRecognitionContentItem, 0)
	{
		contentOb := new(speech_recognition.SpeechRecognitionContent)
		cond := fmt.Sprintf(` AND %s = ?`, speech_recognition.SpeechRecognitionContentCols.SpeechRecognitionId)
		pars := make([]interface{}, 0)
		pars = append(pars, speechId)
		list, e := contentOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", speech_recognition.SpeechRecognitionContentCols.Sort))
		if e != nil {
			br.Msg = "获取失败"
			br.ErrMsg = "获取语音识别内容失败, Err: " + e.Error()
			return
		}
		for _, v := range list {
			if v.Content == "" {
				continue
			}
			contents = append(contents, speech_recognition.FormatSpeechRecognitionContent2Item(v))
		}
	}

	// 跟踪目录路径
	menuPath := make([]*speech_recognition.SpeechRecognitionMenuItem, 0)
	{
		menuOb := new(speech_recognition.SpeechRecognitionMenu)
		menus, e := menuOb.GetItemsByCondition(``, make([]interface{}, 0), []string{}, fmt.Sprintf("%s ASC, %s ASC", speech_recognition.SpeechRecognitionMenuCols.ParentId, speech_recognition.SpeechRecognitionMenuCols.Sort))
		if e != nil {
			br.Msg = "获取失败"
			br.ErrMsg = "获取目录列表失败, Err: " + e.Error()
			return
		}
		menuPath = services.GetSpeechRecognitionMenuPathRecursive(menus, speechItem.MenuId)
		sort.Slice(menuPath, func(i, j int) bool {
			return menuPath[i].Level < menuPath[j].Level
		})
	}

	// 获取标签
	tags, e := speech_recognition.GetSpeechRecognitionTagBySpeechId(speechId)
	if e != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取语音识别标签失败, Err: " + e.Error()
		return
	}
	detail := speech_recognition.FormatSpeechRecognition2DetailItem(speechItem, contents, tags, menuPath)

	br.Data = detail
	br.Ret = 200
	br.Success = true
	br.Msg = "获取成功"
}

// Export
// @Title 导出内容
// @Description 导出内容
// @Param	request	body speech_recognition.SpeechRecognitionContentExportReq true "type json string"
// @Success 200 string "操作成功"
// @router /export [get]
func (this *SpeechRecognitionController) Export() {
	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
	}
	req := new(speech_recognition.SpeechRecognitionContentExportReq)
	if e := this.ParseForm(req); e != nil {
		br.Msg = "参数有误"
		br.ErrMsg = "参数解析失败, Err: " + e.Error()
		return
	}
	if req.SpeechRecognitionId <= 0 {
		br.Msg = "参数有误"
		br.ErrMsg = fmt.Sprintf("参数有误, SpeechRecognitionId: %d", req.SpeechRecognitionId)
		return
	}

	speechOb := new(speech_recognition.SpeechRecognition)
	speechItem, e := speechOb.GetItemById(req.SpeechRecognitionId)
	if e != nil {
		if e.Error() == utils.ErrNoRow() {
			br.Msg = "转写文件不存在,请刷新页面"
			return
		}
		br.Msg = "获取失败"
		br.ErrMsg = "获取转写文件失败, Err: " + e.Error()
		return
	}

	contentOb := new(speech_recognition.SpeechRecognitionContent)
	cond := fmt.Sprintf(` AND %s = ?`, speech_recognition.SpeechRecognitionContentCols.SpeechRecognitionId)
	pars := make([]interface{}, 0)
	pars = append(pars, req.SpeechRecognitionId)
	contents, e := contentOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", speech_recognition.SpeechRecognitionContentCols.Sort))
	if e != nil {
		br.Msg = "导出失败"
		br.ErrMsg = "获取语音识别内容失败, Err: " + e.Error()
		return
	}
	if len(contents) == 0 {
		br.Msg = "无内容导出"
		return
	}
	if req.ExportType != services.SpeechRecognitionExportTypeTxt && req.ExportType != services.SpeechRecognitionExportTypeDocx && req.ExportType != services.SpeechRecognitionExportTypePdf {
		br.Msg = "导出类型有误"
		return
	}

	suffixMap := map[int]string{services.SpeechRecognitionExportTypeTxt: ".txt", services.SpeechRecognitionExportTypeDocx: ".docx", services.SpeechRecognitionExportTypePdf: ".pdf"}
	suffix := suffixMap[req.ExportType]
	if suffix == "" {
		suffix = ".txt"
	}
	downloadPath, e := services.SpeechRecognitionContentExport(req.ExportType, req.Timestamp, speechItem.FileName, contents)
	if e != nil {
		br.Msg = "导出文件失败"
		br.ErrMsg = "导出语音识别内容文件失败, Err: " + e.Error()
		_ = os.Remove(downloadPath)
		return
	}
	defer func() {
		_ = os.Remove(downloadPath)
	}()

	downloadName := fmt.Sprintf("%s%s", speechItem.FileName, suffix)
	this.Ctx.Output.Download(downloadPath, downloadName)
}

// CheckFileName
// @Title 文件重名校验
// @Description 文件重名校验
// @Param	request	body speech_recognition.SpeechRecognitionConvertCheckNameReq true "type json string"
// @Success 200 string "操作成功"
// @router /convert/check_name [post]
func (this *SpeechRecognitionController) CheckFileName() {
	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.SpeechRecognitionConvertCheckNameReq
	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
		br.Msg = "参数有误"
		br.ErrMsg = "参数解析失败, Err: " + e.Error()
		return
	}
	req.FileName = strings.TrimSpace(req.FileName)
	if req.FileName == "" {
		br.Msg = "参数有误"
		br.ErrMsg = fmt.Sprintf("参数有误, FileName: %s", req.FileName)
		return
	}

	checkResult := true
	speechOb := new(speech_recognition.SpeechRecognition)
	cond := fmt.Sprintf(` AND %s = ?`, speech_recognition.SpeechRecognitionCols.FileName)
	pars := make([]interface{}, 0)
	pars = append(pars, req.FileName)
	exists, e := speechOb.GetItemByCondition(cond, pars, "")
	if e != nil && e.Error() != utils.ErrNoRow() {
		br.Msg = "操作失败"
		br.ErrMsg = "获取同名转写文件失败, Err: " + e.Error()
		return
	}
	if exists != nil && exists.SpeechRecognitionId > 0 {
		checkResult = false
		br.Data = checkResult
		br.Msg = fmt.Sprintf("相同文件名称已存在: %s", req.FileName)
		return
	}

	br.Data = checkResult
	br.Ret = 200
	br.Success = true
	br.Msg = "操作成功"
}