Ver código fonte

Merge branch 'ETA_1.8.8'

zwxi 8 meses atrás
pai
commit
056d252578

+ 413 - 0
controllers/ai/ai_pormpt.go

@@ -0,0 +1,413 @@
+package ai
+
+import (
+	"encoding/json"
+	"errors"
+	"eta/eta_api/models"
+	"eta/eta_api/models/ai_summary"
+	"eta/eta_api/models/system"
+	aiSummaryService "eta/eta_api/services/ai_summary"
+	"eta/eta_api/utils"
+	"time"
+)
+
+// AiPromptList
+// @Title 获取所有ai纪要分类接口-包含沙盘
+// @Description 获取所有ai纪要分类接口-包含沙盘
+// @Success 200 {object} data_manage.ChartClassifyListResp
+// @router /prompt/list [get]
+func (this *AiController) AiPromptList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	list, err := ai_summary.GetAiPromptList(this.SysUser.AdminId, 0)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = list
+}
+
+// PromptGroupList
+// @Title 获取可见的目录列表
+// @Description 获取可见的目录列表接口
+// @Success 200 {object} ppt_english.RespGroupList
+// @router /prompt/groups [get]
+func (this *AiController) PromptGroupList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	list, err := ai_summary.GetAiPromptShareList()
+	if err != nil {
+		br.Msg = err.Error()
+		return
+	}
+	resp := make([]*ai_summary.RespGroupListItem, 0)
+	publicAdminIdList := make([]int, 0)
+	publicPromptListMap := make(map[int][]*ai_summary.AiPromptItem)
+	systemAdminMap := make(map[int]*system.Admin)
+
+	for _, v := range list {
+		publicPromptList, ok := publicPromptListMap[v.SysAdminId]
+		if !ok {
+			publicPromptList = make([]*ai_summary.AiPromptItem, 0)
+			publicAdminIdList = append(publicAdminIdList, v.SysAdminId)
+
+		}
+		systemAdminMap[v.SysAdminId] = &system.Admin{
+			AdminId:  v.SysAdminId,
+			RealName: v.SysAdminName,
+		}
+		publicPromptList = append(publicPromptList, v)
+		publicPromptListMap[v.SysAdminId] = publicPromptList
+	}
+	for _, v := range publicAdminIdList {
+		systemAdmin, ok := systemAdminMap[v]
+		if !ok {
+			continue
+		}
+		respGroupPptNameListItemList, ok := publicPromptListMap[v]
+		if !ok {
+			respGroupPptNameListItemList = make([]*ai_summary.AiPromptItem, 0)
+		}
+
+		//  分组信息
+		tmpRespGroupListItem := &ai_summary.RespGroupListItem{
+			GroupId:    int64(systemAdmin.AdminId),
+			GroupName:  systemAdmin.RealName,
+			AdminId:    systemAdmin.AdminId,
+			IsShare:    1,
+			PromptList: respGroupPptNameListItemList,
+		}
+		resp = append(resp, tmpRespGroupListItem)
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "查询成功"
+	br.Data = resp
+	return
+}
+
+// AddPpt
+// @Title 新增提示词
+// @Description 新增提示词接口
+// @Param	request	body ppt_english.AddPptEnglishReq true "type json string"
+// @Success 200 Ret=200 新增成功
+// @router /prompt/add [post]
+func (this *AiController) AddPrompt() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req ai_summary.AiPromptAddReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.Title == "" {
+		br.Msg = "标题不能为空"
+		return
+	}
+
+	var msg string
+	//获取该层级下最大的排序数
+	maxSort, err := ai_summary.GetAiPromptMaxSort(this.SysUser.AdminId)
+
+	prompt := &ai_summary.AiPrompt{
+		CreateTime:    time.Now(),
+		ModifyTime:    time.Now(),
+		PromptContent: req.PromptContent,
+		SysAdminId:    this.SysUser.AdminId,
+		SysAdminName:  this.SysUser.RealName,
+		Title:         req.Title,
+		Sort:          maxSort + 1,
+	}
+	_, err = ai_summary.AddPropmt(prompt)
+	if err != nil {
+		br.Msg = "新增失败"
+		br.ErrMsg = "新增失败,Err:" + err.Error()
+		return
+	}
+
+	msg = "新增成功"
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = msg
+}
+
+// EditPpt
+// @Title 编辑提示词
+// @Description 编辑提示词接口
+// @Param	request	body ppt_english.AddPptEnglishReq true "type json string"
+// @Success 200 Ret=200 编辑成功
+// @router /prompt/edit [post]
+func (this *AiController) EditPrompt() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req ai_summary.AiPromptEditReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.Title == "" {
+		br.Msg = "标题不能为空"
+		return
+	}
+
+	promptItem := &ai_summary.AiPrompt{
+		AiPromptId:    req.AiPromptId,
+		PromptContent: req.PromptContent,
+		Title:         req.Title,
+		CreateTime:    time.Time{},
+		ModifyTime:    time.Now(),
+	}
+
+	err = promptItem.Update([]string{"ModifyTime", "PromptContent", "Title"})
+	if err != nil {
+		br.Msg = "编辑失败"
+		br.ErrMsg = "编辑失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "编辑成功"
+	br.IsAddLog = true
+}
+
+// DeletePpt
+// @Title 删除提示词
+// @Description 删除ppt接口
+// @Param	request	body ppt_english.DeletePptEnglishReq true "type json string"
+// @Success 200 Ret=200 删除成功
+// @router /prompt/delete [post]
+func (this *AiController) DeletePrompt() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req ai_summary.DeleteAipromptReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.AiPromptId <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+	promptInfo, err := ai_summary.GetAiPromptById(req.AiPromptId)
+	if err != nil {
+		br.Msg = "提示词不存在"
+		return
+	}
+	if promptInfo.SysAdminId != this.SysUser.AdminId {
+		br.Msg = "无权删除"
+		return
+	}
+	err = ai_summary.DelAiPromptyId(req.AiPromptId)
+	if err != nil {
+		br.Msg = "删除失败"
+		br.ErrMsg = "删除失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.IsAddLog = true
+	br.Msg = "删除成功"
+}
+
+// DetailPrompt
+// @Title 获取提示词详情
+// @Description 获取提示词详情接口
+// @Param   AiPromptId   query   int  true       "提示词id"
+// @Success 200 {object} ppt_english.PptEnglish
+// @router /prompt/detail [get]
+func (this *AiController) DetailPrompt() {
+	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
+	}
+	aiPromptId, _ := this.GetInt("AiPromptId")
+
+	promptInfo, err := ai_summary.GetAiPromptById(aiPromptId)
+	if err != nil {
+		br.Msg = "提示词不存在"
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = promptInfo
+}
+
+// MoveAiPrompt
+// @Title 移动提示词
+// @Description 移动提示词接口
+// @Param	request	body models.ReqMoveGroupPpt true "type json string"
+// @Success 200 Ret=200 移动成功
+// @router /prompt/move [post]
+func (this *AiController) MoveAiPrompt() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req ai_summary.ReqMovePrompt
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.AiPromptId <= 0 {
+		br.Msg = "请输入提示词ID"
+		return
+	}
+
+	prompt, err := ai_summary.GetAiPromptById(req.AiPromptId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "当前提示词不存在"
+			br.ErrMsg = "当前提示词不存在"
+			return
+		}
+		br.Msg = "提示词查询出错"
+		br.ErrMsg = "提示词查询出错:" + err.Error()
+		return
+	}
+	var updateStr []string
+
+	var currentSort, prevSort, nextSort int
+	currentSort = prompt.Sort
+
+	var prevPrompt *ai_summary.AiPrompt
+	var nextPrompt *ai_summary.AiPrompt
+	if req.PrevAiPromptId > 0 {
+		prevPrompt, err = ai_summary.GetAiPromptById(req.PrevAiPromptId)
+		if err != nil {
+			if err.Error() == utils.ErrNoRow() {
+				err = errors.New("目录下的提示词不存在")
+				return
+			}
+			err = errors.New("目录下的提示词查询出错:" + err.Error())
+			return
+		}
+		prevSort = prevPrompt.Sort
+	}
+
+	if req.NextAiPromptId > 0 {
+		nextPrompt, err = ai_summary.GetAiPromptById(req.NextAiPromptId)
+		if err != nil {
+			if err.Error() == utils.ErrNoRow() {
+				err = errors.New("目录下的提示词不存在")
+				return
+			}
+			err = errors.New("目录下的提示词查询出错:" + err.Error())
+			return
+		}
+		nextSort = nextPrompt.Sort
+	}
+
+	updateStr = append(updateStr, "sort")
+
+	//移到两个排序值中间操作
+	if prevSort >= currentSort {
+		//往下移动
+		err = ai_summary.MoveDownPromptBySort(this.SysUser.AdminId, prevSort, currentSort)
+		if err != nil {
+			err = errors.New("向下移动提示词出错:" + err.Error())
+			return
+		}
+		prompt.Sort = prevSort
+	} else if nextSort <= currentSort && nextSort != 0 {
+		//往上移动
+		err = ai_summary.MoveUpPromptBySort(this.SysUser.AdminId, nextSort, currentSort)
+		if err != nil {
+			err = errors.New("向上移动提示词出错:" + err.Error())
+			return
+		}
+		prompt.Sort = nextSort
+	}
+	//更新当前排序
+	err = prompt.Update(updateStr)
+	if err != nil {
+		err = errors.New("移动提示词出错:" + err.Error())
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "移动成功"
+}
+
+// SharePrompt
+// @Title 共享/取消共享单个提示词
+// @Description 共享/取消共享单个提示词接口
+// @Param	request	body models.ReqPptShare true "type json string"
+// @Success 200 {object} models.RespPptShare
+// @router /prompt/share [post]
+func (this *AiController) SharePrompt() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req ai_summary.DeleteAipromptReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.AiPromptId <= 0 {
+		br.Msg = "请输入提示词序号"
+		return
+	}
+
+	err = aiSummaryService.SharePrompt(req.AiPromptId, this.SysUser.AdminId)
+	if err != nil {
+		br.Msg = err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+
+	return
+}

+ 1607 - 0
controllers/ai/ai_summary.go

@@ -0,0 +1,1607 @@
+package ai
+
+import (
+	"encoding/json"
+	"eta/eta_api/models"
+	"eta/eta_api/models/ai_summary"
+	"eta/eta_api/models/aimod"
+	"eta/eta_api/models/sandbox"
+	saModel "eta/eta_api/models/semantic_analysis"
+	aiSummaryService "eta/eta_api/services/ai_summary"
+	"eta/eta_api/services/aiser"
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"strconv"
+	"time"
+)
+
+// AiSummaryClassifyItems
+// @Title 获取所有ai纪要分类接口
+// @Description 获取所有ai纪要分类接口
+// @Param   IsShowMe   query   bool  true       "是否只看我的,true、false"
+// @Success 200 {object} data_manage.ChartClassifyListResp
+// @router /summary/classify/list [get]
+func (this *AiController) AiSummaryClassifyItems() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	resp := new(ai_summary.AiSummaryClassifyListResp)
+	aiSummaryClassifyId, _ := this.GetInt("AiSummaryClassifyId")
+
+	isShowMe, _ := this.GetBool("IsShowMe")
+	if isShowMe {
+		errMsg, err := aiSummaryService.GetAiSummaryClassifyListForMe(*this.SysUser, resp, aiSummaryClassifyId)
+		if err != nil {
+			br.Msg = errMsg
+			br.ErrMsg = err.Error()
+			return
+		}
+
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		br.Data = resp
+		fmt.Println("source my classify")
+		return
+	}
+
+	rootList, err := ai_summary.GetAiSummaryClassifyAndInfoByParentId(aiSummaryClassifyId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	for k := range rootList {
+		rootList[k].UniqueCode = strconv.Itoa(rootList[k].AiSummaryClassifyId) + "_" + strconv.Itoa(rootList[k].AiSummaryId)
+	}
+
+	classifyAll, err := ai_summary.GetAiSummaryClassifyAndInfoByParentId(aiSummaryClassifyId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	for k := range classifyAll {
+		classifyAll[k].UniqueCode = strconv.Itoa(classifyAll[k].AiSummaryClassifyId) + "_" + strconv.Itoa(classifyAll[k].AiSummaryId)
+	}
+
+	nodeAll := make([]*ai_summary.AiSummaryClassifyItems, 0)
+	for k := range rootList {
+		rootNode := rootList[k]
+		aiSummaryService.AiSummaryClassifyItemsMakeTreeV2(this.SysUser, classifyAll, rootNode)
+		nodeAll = append(nodeAll, rootNode)
+	}
+
+	resp.AllNodes = nodeAll
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 新增ai纪要分类
+// @Description 新增ai纪要分类接口
+// @Param	request	body data_manage.AddChartClassifyReq true "type json string"
+// @Success 200 Ret=200 保存成功
+// @router /summary/classify/add [post]
+func (this *AiController) AddAiSummaryClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req ai_summary.AddAiSummaryClassifyReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ClassifyName == "" {
+		br.Msg = "请输入分类名称"
+		br.IsSendEmail = false
+		return
+	}
+	if req.ParentId < 0 {
+		br.Msg = "参数错误"
+		br.IsSendEmail = false
+		return
+	}
+
+	count, err := ai_summary.GetAiSummaryClassifyCount(req.ClassifyName, req.ParentId)
+	if err != nil {
+		br.Msg = "判断名称是否已存在失败"
+		br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
+		return
+	}
+	if count > 0 {
+		br.Msg = "分类名称已存在,请重新输入"
+		br.IsSendEmail = false
+		return
+	}
+	//获取该层级下最大的排序数
+	maxSort, err := ai_summary.GetAiSummaryClassifyMaxSort(req.ParentId)
+
+	classify := new(ai_summary.AiSummaryClassify)
+	classify.ParentId = req.ParentId
+	classify.ClassifyName = req.ClassifyName
+	classify.HasData = 0
+	classify.CreateTime = time.Now()
+	classify.ModifyTime = time.Now()
+	classify.SysUserId = this.SysUser.AdminId
+	classify.SysUserRealName = this.SysUser.RealName
+	classify.Level = req.Level + 1
+	classify.Sort = maxSort + 1
+
+	_, err = ai_summary.AddAiSummaryClassify(classify)
+	if err != nil {
+		br.Msg = "保存分类失败"
+		br.ErrMsg = "保存分类失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Msg = "保存成功"
+	br.Success = true
+}
+
+// @Title 修改ai纪要分类
+// @Description 修改ai纪要分类接口
+// @Param	request	body data_manage.EditChartClassifyReq true "type json string"
+// @Success 200 Ret=200 修改成功
+// @router /summary/classify/edit [post]
+func (this *AiController) EditAiSummaryClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req ai_summary.EditAiSummaryClassifyReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ClassifyName == "" {
+		br.Msg = "请输入分类名称"
+		br.IsSendEmail = false
+		return
+	}
+
+	if req.AiSummaryClassifyId <= 0 {
+		br.Msg = "参数错误"
+		br.IsSendEmail = false
+		return
+	}
+
+	err = ai_summary.EditSandboxClassify(req.AiSummaryClassifyId, req.ClassifyName)
+	if err != nil {
+		br.Msg = "保存失败"
+		br.ErrMsg = "保存失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Msg = "保存成功"
+	br.Success = true
+	br.IsAddLog = true
+}
+
+// @Title 删除纪要分类检测接口
+// @Description 删除纪要分类检测接口
+// @Param	request	body data_manage.ChartClassifyDeleteCheckResp true "type json string"
+// @Success 200 Ret=200 检测成功
+// @router /summary/classify/delete/check [post]
+func (this *AiController) DeleteSandboxClassifyCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req ai_summary.AiSummaryClassifyDeleteCheckReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.AiSummaryClassifyId < 0 {
+		br.Msg = "参数错误"
+		br.IsSendEmail = false
+		return
+	}
+	var deleteStatus int
+	var tipsMsg string
+	//删除分类
+	if req.AiSummaryClassifyId > 0 {
+		//判断分类下,是否含有纪要
+		count, err := ai_summary.GetAiSummaryInfoCountByClassifyId(req.AiSummaryClassifyId)
+		if err != nil {
+			br.Msg = "删除失败"
+			br.ErrMsg = "分类下是否含有指标失败,Err:" + err.Error()
+			return
+		}
+
+		if count > 0 {
+			deleteStatus = 1
+			tipsMsg = "该分类下关联沙盘不可删除"
+		}
+	}
+
+	if deleteStatus != 1 {
+		classifyCount, err := ai_summary.GetAiSummaryInfoCountByClassifyId(req.AiSummaryClassifyId)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "删除失败"
+			br.ErrMsg = "分类下是否含有沙盘失败,Err:" + err.Error()
+			return
+		}
+		if classifyCount > 0 {
+			deleteStatus = 2
+			tipsMsg = "确认删除当前目录及包含的子目录吗"
+		}
+	}
+	if deleteStatus == 0 {
+		tipsMsg = "可删除,进行删除操作"
+	}
+
+	resp := new(sandbox.SandboxClassifyDeleteCheckResp)
+	resp.DeleteStatus = deleteStatus
+	resp.TipsMsg = tipsMsg
+	br.Ret = 200
+	br.Msg = "检测成功"
+	br.Success = true
+	br.Data = resp
+}
+
+// @Title 删除纪要分类/纪要
+// @Description 删除纪要分类/纪要接口
+// @Param	request	body data_manage.DeleteChartClassifyReq true "type json string"
+// @Success 200 Ret=200 删除成功
+// @router /summary/classify/delete [post]
+func (this *AiController) DeleteAiSummaryClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		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 ai_summary.DeleteAiSummaryClassifyReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.AiSummaryClassifyId < 0 && req.AiSummaryId <= 0 {
+		br.Msg = "参数错误"
+		br.IsSendEmail = false
+		return
+	}
+
+	//删除分类
+	if req.AiSummaryClassifyId > 0 && req.AiSummaryId == 0 {
+		//判断是否含有纪要
+		count, err := ai_summary.GetAiSummaryInfoCountByClassifyId(req.AiSummaryClassifyId)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "删除失败"
+			br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
+			return
+		}
+
+		if count > 0 {
+			br.Msg = "该目录下存在纪要,不可删除"
+			br.IsSendEmail = false
+			return
+		}
+
+		err = ai_summary.DeleteAiSummaryClassify(req.AiSummaryClassifyId)
+		if err != nil {
+			br.Msg = "删除失败"
+			br.ErrMsg = "删除失败,Err:" + err.Error()
+			return
+		}
+	}
+
+	//删除纪要
+	if req.AiSummaryId > 0 {
+		summaryInfo, err := ai_summary.GetAiSummaryById(req.AiSummaryId)
+		if err != nil {
+			if err.Error() == utils.ErrNoRow() {
+				br.Msg = "纪要已删除,请刷新页面"
+				br.ErrMsg = "指标不存在,Err:" + err.Error()
+				return
+			} else {
+				br.Msg = "删除失败"
+				br.ErrMsg = "删除失败,获取指标信息失败,Err:" + err.Error()
+				return
+			}
+		}
+		if summaryInfo == nil {
+			br.Msg = "纪要已删除,请刷新页面"
+			return
+		}
+		if summaryInfo.SysUserId != sysUser.AdminId {
+			br.Msg = "仅纪要创建人可以删除"
+			return
+		}
+		err = ai_summary.DelAiSummaryById(req.AiSummaryId)
+		if err != nil {
+			br.Msg = err.Error()
+			return
+		}
+	}
+	br.Ret = 200
+	br.Msg = "删除成功"
+	br.Success = true
+	br.IsAddLog = true
+}
+
+// AiSummaryClassifyMove
+// @Title 纪要分类移动接口
+// @Description 纪要分类移动接口
+// @Success 200 {object} data_manage.MoveChartClassifyReq
+// @router /summary/classify/move [post]
+func (this *AiController) AiSummaryClassifyMove() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		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 ai_summary.MoveAiSummaryClassifyReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.AiSummaryClassifyId <= 0 {
+		br.Msg = "参数错误"
+		br.ErrMsg = "分类id小于等于0"
+		return
+	}
+	//判断分类是否存在
+	aiSummaryClassifyInfo, err := ai_summary.GetAiSummaryClassifyById(req.AiSummaryClassifyId)
+	if err != nil {
+		br.Msg = "移动失败"
+		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
+		return
+	}
+
+	updateCol := make([]string, 0)
+
+	// 判断移动的是分类还是沙盘
+	if req.AiSummaryId > 0 {
+		//判断分类是否存在
+		count, _ := ai_summary.GetAiSummaryClassifyCountById(req.AiSummaryClassifyId)
+		if count <= 0 {
+			br.Msg = "分类已被删除,不可移动,请刷新页面"
+			return
+		}
+
+		aiSummaryInfo, err := ai_summary.GetAiSummaryById(req.AiSummaryId)
+		if err != nil {
+			br.Msg = "移动失败"
+			br.ErrMsg = "获取沙盘信息失败,Err:" + err.Error()
+			return
+		}
+
+		//如果改变了分类,那么移动该图表数据
+		// 11/22 ETA逻辑优化去除名称重复限制
+		if aiSummaryInfo.ClassifyId != req.ParentClassifyId {
+			////查询需要修改的分类下是否存在同一个图表名称
+			//tmpSandboxInfo, tmpErr := sandbox.GetSandboxByClassifyIdAndName(req.ParentClassifyId, aiSummaryInfo.Name)
+			//if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
+			//	br.Msg = "移动失败"
+			//	br.ErrMsg = "移动失败,Err:" + tmpErr.Error()
+			//	return
+			//}
+			//if tmpSandboxInfo != nil {
+			//	br.Msg = "移动失败,同一个分类下沙盘名称不允许重复"
+			//	br.ErrMsg = "移动失败,同一个分类下沙盘名称不允许重复"
+			//	return
+			//}
+			err = ai_summary.MoveAiSummary(req.AiSummaryId, req.ParentClassifyId)
+			if err != nil {
+				br.Msg = "移动失败"
+				br.ErrMsg = "移动失败,Err:" + err.Error()
+				return
+			}
+		}
+
+		//移动排序
+		updateCol := make([]string, 0)
+		//如果有传入 上一个兄弟节点分类id
+		if req.PrevId > 0 {
+			if req.PrevType == 1 {
+				//上一个兄弟节点
+				prevClassify, err := ai_summary.GetAiSummaryClassifyById(req.PrevId)
+				if err != nil {
+					br.Msg = "移动失败"
+					br.ErrMsg = "获取上一个兄弟节点分类信息失败,Err:" + err.Error()
+					return
+				}
+
+				//如果是移动在两个兄弟节点之间
+				if req.NextId > 0 {
+					if req.NextType == 1 {
+						//上一个节点是分类 下一个节点是分类的情况
+						//下一个兄弟节点
+						nextClassify, err := ai_summary.GetAiSummaryClassifyById(req.NextId)
+						if err != nil {
+							br.Msg = "移动失败"
+							br.ErrMsg = "获取下一个兄弟节点分类信息失败,Err:" + err.Error()
+							return
+						}
+						//如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
+						if prevClassify.Sort == nextClassify.Sort || prevClassify.Sort == aiSummaryClassifyInfo.Sort {
+							//变更兄弟节点的排序
+							updateSortStr := `sort + 2`
+							_ = ai_summary.UpdateAiSummaryClassifySortByParentId(prevClassify.ParentId, prevClassify.AiSummaryClassifyId, prevClassify.Sort, updateSortStr)
+							_ = ai_summary.UpdateAiSummarySortByClassifyId(prevClassify.AiSummaryClassifyId, prevClassify.Sort, 0, updateSortStr)
+						} else {
+							//如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
+							if nextClassify.Sort-prevClassify.Sort == 1 {
+								//变更兄弟节点的排序
+								updateSortStr := `sort + 1`
+								_ = ai_summary.UpdateAiSummaryClassifySortByParentId(prevClassify.ParentId, 0, prevClassify.Sort, updateSortStr)
+								_ = ai_summary.UpdateAiSummarySortByClassifyId(prevClassify.AiSummaryClassifyId, prevClassify.Sort, 0, updateSortStr)
+							}
+						}
+					} else {
+						//上一个节点是分类 下一个节点是沙盘的情况
+						//下一个兄弟节点
+						nextChartInfo, err := ai_summary.GetAiSummaryById(req.NextId)
+						if err != nil {
+							br.Msg = "移动失败"
+							br.ErrMsg = "获取下一个兄弟节点分类信息失败,Err:" + err.Error()
+							return
+						}
+						//如果上一个兄弟(分类)与下一个兄弟(沙盘)的排序权重是一致的,那么需要将下一个兄弟(沙盘)(以及下个兄弟(沙盘)的同样排序权重)的排序权重+2,自己变成上一个兄弟(分类)的排序权重+1
+						if prevClassify.Sort == nextChartInfo.Sort || prevClassify.Sort == aiSummaryInfo.Sort {
+							//变更兄弟节点的排序
+							updateSortStr := `sort + 2`
+							_ = ai_summary.UpdateAiSummaryClassifySortByParentId(prevClassify.ParentId, prevClassify.AiSummaryClassifyId, prevClassify.Sort, updateSortStr)
+							_ = ai_summary.UpdateAiSummarySortByClassifyId(prevClassify.AiSummaryClassifyId, prevClassify.Sort, 0, updateSortStr)
+						} else {
+							//如果下一个兄弟(沙盘)的排序权重正好是上个兄弟节点(分类)的下一层,那么需要再加一层了
+							if nextChartInfo.Sort-prevClassify.Sort == 1 {
+								//变更兄弟节点的排序
+								updateSortStr := `sort + 1`
+								_ = ai_summary.UpdateAiSummaryClassifySortByParentId(prevClassify.ParentId, 0, prevClassify.AiSummaryClassifyId, updateSortStr)
+								_ = ai_summary.UpdateAiSummarySortByClassifyId(prevClassify.AiSummaryClassifyId, prevClassify.Sort, 0, updateSortStr)
+							}
+						}
+					}
+
+				}
+
+				aiSummaryInfo.Sort = prevClassify.Sort + 1
+				aiSummaryInfo.ModifyTime = time.Now()
+				updateCol = append(updateCol, "Sort", "ModifyTime")
+
+			} else {
+				prevAiSumary, err := ai_summary.GetAiSummaryById(req.PrevId)
+				if err != nil {
+					br.Msg = "移动失败"
+					br.ErrMsg = "获取上一个兄弟节点分类信息失败,Err:" + err.Error()
+					return
+				}
+
+				//如果是移动在两个兄弟节点之间
+				if req.NextId > 0 {
+					if req.NextType == 1 {
+						//上一个节点是沙盘 下一个节点是分类的情况
+						//下一个兄弟节点
+						nextClassify, err := ai_summary.GetAiSummaryClassifyById(req.NextId)
+						if err != nil {
+							br.Msg = "移动失败"
+							br.ErrMsg = "获取下一个兄弟节点分类信息失败,Err:" + err.Error()
+							return
+						}
+						//如果上一个兄弟(沙盘)与下一个兄弟(分类)的排序权重是一致的,那么需要将下一个兄弟(分类)(以及下个兄弟(分类)的同样排序权重)的排序权重+2,自己变成上一个兄弟(沙盘)的排序权重+1
+						if prevAiSumary.Sort == nextClassify.Sort || prevAiSumary.Sort == aiSummaryClassifyInfo.Sort {
+							//变更兄弟节点的排序
+							updateSortStr := `sort + 2`
+							_ = ai_summary.UpdateAiSummaryClassifySortByParentId(prevAiSumary.ClassifyId, 0, prevAiSumary.Sort, updateSortStr)
+							_ = ai_summary.UpdateAiSummarySortByClassifyId(prevAiSumary.ClassifyId, prevAiSumary.Sort, prevAiSumary.AiSummaryId, updateSortStr)
+						} else {
+							//如果下一个兄弟(分类)的排序权重正好是上个兄弟(沙盘)节点的下一层,那么需要再加一层了
+							if nextClassify.Sort-prevAiSumary.Sort == 1 {
+								//变更兄弟节点的排序
+								updateSortStr := `sort + 1`
+								_ = ai_summary.UpdateAiSummaryClassifySortByParentId(prevAiSumary.ClassifyId, 0, prevAiSumary.Sort, updateSortStr)
+								_ = ai_summary.UpdateAiSummarySortByClassifyId(prevAiSumary.ClassifyId, prevAiSumary.Sort, prevAiSumary.AiSummaryId, updateSortStr)
+							}
+						}
+					} else {
+						//上一个节点是沙盘 下一个节点是沙盘的情况
+						//下一个兄弟节点
+						nextChartInfo, err := ai_summary.GetAiSummaryById(req.NextId)
+						if err != nil {
+							br.Msg = "移动失败"
+							br.ErrMsg = "获取下一个兄弟节点分类信息失败,Err:" + err.Error()
+							return
+						}
+						//如果上一个兄弟(沙盘)与下一个兄弟(分类)的排序权重是一致的,那么需要将下一个兄弟(分类)(以及下个兄弟(分类)的同样排序权重)的排序权重+2,自己变成上一个兄弟(沙盘)的排序权重+1
+						if prevAiSumary.Sort == nextChartInfo.Sort || prevAiSumary.Sort == aiSummaryInfo.Sort {
+							//变更兄弟节点的排序
+							updateSortStr := `sort + 2`
+							_ = ai_summary.UpdateAiSummaryClassifySortByParentId(prevAiSumary.ClassifyId, 0, prevAiSumary.Sort, updateSortStr)
+							_ = ai_summary.UpdateAiSummarySortByClassifyId(prevAiSumary.ClassifyId, prevAiSumary.Sort, prevAiSumary.AiSummaryId, updateSortStr)
+						} else {
+							//如果下一个兄弟(分类)的排序权重正好是上个兄弟(沙盘)节点的下一层,那么需要再加一层了
+							if nextChartInfo.Sort-prevAiSumary.Sort == 1 {
+								//变更兄弟节点的排序
+								updateSortStr := `sort + 1`
+								_ = ai_summary.UpdateAiSummaryClassifySortByParentId(prevAiSumary.ClassifyId, 0, prevAiSumary.Sort, updateSortStr)
+								_ = ai_summary.UpdateAiSummarySortByClassifyId(prevAiSumary.ClassifyId, prevAiSumary.Sort, prevAiSumary.AiSummaryId, updateSortStr)
+							}
+						}
+					}
+
+				}
+
+				aiSummaryInfo.Sort = prevAiSumary.Sort + 1
+				aiSummaryInfo.ModifyTime = time.Now()
+				updateCol = append(updateCol, "Sort", "ModifyTime")
+			}
+
+		} else {
+			// prevId为0,也就是沙盘移到最前端
+			firstClassify, err := ai_summary.GetFirstAiSummaryByClassifyId(req.AiSummaryClassifyId)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				br.Msg = "移动失败"
+				br.ErrMsg = "获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + err.Error()
+				return
+			}
+
+			//如果该分类下存在其他分类,且第一个其他分类的排序等于0,那么需要调整排序
+			if firstClassify != nil && firstClassify.Sort == 0 {
+				updateSortStr := ` sort + 1 `
+				_ = ai_summary.UpdateAiSummarySortByClassifyId(firstClassify.ClassifyId, 0, firstClassify.AiSummaryId-1, updateSortStr)
+			}
+
+			aiSummaryInfo.Sort = 0 //那就是排在第一位
+			aiSummaryInfo.ModifyTime = time.Now()
+			updateCol = append(updateCol, "Sort", "ModifyTime")
+
+		}
+
+		//更新
+		if len(updateCol) > 0 {
+			err = aiSummaryInfo.Update(updateCol)
+			if err != nil {
+				br.Msg = "移动失败"
+				br.ErrMsg = "修改失败,Err:" + err.Error()
+				return
+			}
+		}
+	} else {
+		//移动的是分类
+		//判断上级id是否一致,如果不一致的话,那么需要移动该分类层级
+		if aiSummaryClassifyInfo.ParentId != req.ParentClassifyId && req.ParentClassifyId != 0 {
+			parentChartClassifyInfo, err := ai_summary.GetAiSummaryClassifyById(req.ParentClassifyId)
+			if err != nil {
+				br.Msg = "移动失败"
+				br.ErrMsg = "获取上级分类信息失败,Err:" + err.Error()
+				return
+			}
+			aiSummaryClassifyInfo.ParentId = parentChartClassifyInfo.AiSummaryClassifyId
+			aiSummaryClassifyInfo.Level = parentChartClassifyInfo.Level + 1
+			aiSummaryClassifyInfo.ModifyTime = time.Now()
+			updateCol = append(updateCol, "ParentId", "Level", "ModifyTime")
+		} else if aiSummaryClassifyInfo.ParentId != req.ParentClassifyId && req.ParentClassifyId == 0 {
+			//改为一级分类
+			aiSummaryClassifyInfo.ParentId = req.ParentClassifyId
+			aiSummaryClassifyInfo.Level = 1
+			aiSummaryClassifyInfo.ModifyTime = time.Now()
+			updateCol = append(updateCol, "ParentId", "Level", "ModifyTime")
+		}
+
+		//如果有传入 上一个兄弟节点分类id
+		if req.PrevId > 0 {
+			if req.PrevType == 1 {
+				//上一个节点是分类
+				//上一个兄弟节点
+				prevClassify, err := ai_summary.GetAiSummaryClassifyById(req.PrevId)
+				if err != nil {
+					br.Msg = "移动失败"
+					br.ErrMsg = "获取上一个兄弟节点分类信息失败,Err:" + err.Error()
+					return
+				}
+
+				//如果是移动在两个兄弟节点之间
+				if req.NextId > 0 {
+					if req.NextType == 1 {
+						//上一个节点是分类 下一个节点是分类的情况
+						//下一个兄弟节点
+						nextClassify, err := ai_summary.GetAiSummaryClassifyById(req.NextId)
+						if err != nil {
+							br.Msg = "移动失败"
+							br.ErrMsg = "获取下一个兄弟节点分类信息失败,Err:" + err.Error()
+							return
+						}
+						//如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
+						if prevClassify.Sort == nextClassify.Sort || prevClassify.Sort == aiSummaryClassifyInfo.Sort {
+							//变更兄弟节点的排序
+							updateSortStr := `sort + 2`
+							_ = ai_summary.UpdateAiSummaryClassifySortByParentId(prevClassify.ParentId, prevClassify.AiSummaryClassifyId, prevClassify.Sort, updateSortStr)
+							_ = ai_summary.UpdateAiSummarySortByClassifyId(prevClassify.AiSummaryClassifyId, prevClassify.Sort, 0, updateSortStr)
+						} else {
+							//如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
+							if nextClassify.Sort-prevClassify.Sort == 1 {
+								//变更兄弟节点的排序
+								updateSortStr := `sort + 1`
+								_ = ai_summary.UpdateAiSummaryClassifySortByParentId(prevClassify.ParentId, 0, prevClassify.Sort, updateSortStr)
+								_ = ai_summary.UpdateAiSummarySortByClassifyId(prevClassify.AiSummaryClassifyId, prevClassify.Sort, 0, updateSortStr)
+							}
+						}
+					} else {
+						//上一个节点是分类 下一个节点是沙盘的情况
+						//下一个兄弟节点
+						nextChartInfo, err := ai_summary.GetAiSummaryById(req.NextId)
+						if err != nil {
+							br.Msg = "移动失败"
+							br.ErrMsg = "获取下一个兄弟节点分类信息失败,Err:" + err.Error()
+							return
+						}
+						//如果上一个兄弟(分类)与下一个兄弟(沙盘)的排序权重是一致的,那么需要将下一个兄弟(沙盘)(以及下个兄弟(沙盘)的同样排序权重)的排序权重+2,自己变成上一个兄弟(分类)的排序权重+1
+						if prevClassify.Sort == nextChartInfo.Sort || prevClassify.Sort == aiSummaryClassifyInfo.Sort {
+							//变更兄弟节点的排序
+							updateSortStr := `sort + 2`
+							_ = ai_summary.UpdateAiSummaryClassifySortByParentId(prevClassify.ParentId, prevClassify.AiSummaryClassifyId, prevClassify.Sort, updateSortStr)
+							_ = ai_summary.UpdateAiSummarySortByClassifyId(prevClassify.AiSummaryClassifyId, prevClassify.Sort, 0, updateSortStr)
+						} else {
+							//如果下一个兄弟(沙盘)的排序权重正好是上个兄弟节点(分类)的下一层,那么需要再加一层了
+							if nextChartInfo.Sort-prevClassify.Sort == 1 {
+								//变更兄弟节点的排序
+								updateSortStr := `sort + 1`
+								_ = ai_summary.UpdateAiSummaryClassifySortByParentId(prevClassify.ParentId, 0, prevClassify.AiSummaryClassifyId, updateSortStr)
+								_ = ai_summary.UpdateAiSummarySortByClassifyId(prevClassify.AiSummaryClassifyId, prevClassify.Sort, 0, updateSortStr)
+							}
+						}
+					}
+
+				}
+
+				aiSummaryClassifyInfo.Sort = prevClassify.Sort + 1
+				aiSummaryClassifyInfo.ModifyTime = time.Now()
+				updateCol = append(updateCol, "Sort", "ModifyTime")
+
+			} else {
+				//上一个节点是沙盘
+				prevAiSumary, err := ai_summary.GetAiSummaryById(req.PrevId)
+				if err != nil {
+					br.Msg = "移动失败"
+					br.ErrMsg = "获取上一个兄弟节点分类信息失败,Err:" + err.Error()
+					return
+				}
+
+				//如果是移动在两个兄弟节点之间
+				if req.NextId > 0 {
+					if req.NextType == 1 {
+						//上一个节点是沙盘 下一个节点是分类的情况
+						//下一个兄弟节点
+						nextClassify, err := ai_summary.GetAiSummaryClassifyById(req.NextId)
+						if err != nil {
+							br.Msg = "移动失败"
+							br.ErrMsg = "获取下一个兄弟节点分类信息失败,Err:" + err.Error()
+							return
+						}
+						//如果上一个兄弟(沙盘)与下一个兄弟(分类)的排序权重是一致的,那么需要将下一个兄弟(分类)(以及下个兄弟(分类)的同样排序权重)的排序权重+2,自己变成上一个兄弟(沙盘)的排序权重+1
+						if prevAiSumary.Sort == nextClassify.Sort || prevAiSumary.Sort == aiSummaryClassifyInfo.Sort {
+							//变更兄弟节点的排序
+							updateSortStr := `sort + 2`
+							_ = ai_summary.UpdateAiSummaryClassifySortByParentId(prevAiSumary.ClassifyId, 0, prevAiSumary.Sort, updateSortStr)
+							_ = ai_summary.UpdateAiSummarySortByClassifyId(prevAiSumary.ClassifyId, prevAiSumary.Sort, prevAiSumary.AiSummaryId, updateSortStr)
+						} else {
+							//如果下一个兄弟(分类)的排序权重正好是上个兄弟(沙盘)节点的下一层,那么需要再加一层了
+							if nextClassify.Sort-prevAiSumary.Sort == 1 {
+								//变更兄弟节点的排序
+								updateSortStr := `sort + 1`
+								_ = ai_summary.UpdateAiSummaryClassifySortByParentId(prevAiSumary.ClassifyId, 0, prevAiSumary.Sort, updateSortStr)
+								_ = ai_summary.UpdateAiSummarySortByClassifyId(prevAiSumary.ClassifyId, prevAiSumary.Sort, prevAiSumary.AiSummaryId, updateSortStr)
+							}
+						}
+					} else {
+						//上一个节点是沙盘 下一个节点是沙盘的情况
+						//下一个兄弟节点
+						nextChartInfo, err := ai_summary.GetAiSummaryById(req.NextId)
+						if err != nil {
+							br.Msg = "移动失败"
+							br.ErrMsg = "获取下一个兄弟节点分类信息失败,Err:" + err.Error()
+							return
+						}
+						//如果上一个兄弟(沙盘)与下一个兄弟(分类)的排序权重是一致的,那么需要将下一个兄弟(分类)(以及下个兄弟(分类)的同样排序权重)的排序权重+2,自己变成上一个兄弟(沙盘)的排序权重+1
+						if prevAiSumary.Sort == nextChartInfo.Sort || prevAiSumary.Sort == aiSummaryClassifyInfo.Sort {
+							//变更兄弟节点的排序
+							updateSortStr := `sort + 2`
+							_ = ai_summary.UpdateAiSummaryClassifySortByParentId(prevAiSumary.ClassifyId, 0, prevAiSumary.Sort, updateSortStr)
+							_ = ai_summary.UpdateAiSummarySortByClassifyId(prevAiSumary.ClassifyId, prevAiSumary.Sort, prevAiSumary.AiSummaryId, updateSortStr)
+						} else {
+							//如果下一个兄弟(分类)的排序权重正好是上个兄弟(沙盘)节点的下一层,那么需要再加一层了
+							if nextChartInfo.Sort-prevAiSumary.Sort == 1 {
+								//变更兄弟节点的排序
+								updateSortStr := `sort + 1`
+								_ = ai_summary.UpdateAiSummaryClassifySortByParentId(prevAiSumary.ClassifyId, 0, prevAiSumary.Sort, updateSortStr)
+								_ = ai_summary.UpdateAiSummarySortByClassifyId(prevAiSumary.ClassifyId, prevAiSumary.Sort, prevAiSumary.AiSummaryId, updateSortStr)
+							}
+						}
+					}
+
+				}
+				aiSummaryClassifyInfo.Sort = prevAiSumary.Sort + 1
+				aiSummaryClassifyInfo.ModifyTime = time.Now()
+				updateCol = append(updateCol, "Sort", "ModifyTime")
+
+			}
+
+		} else {
+			firstClassify, err := ai_summary.GetFirstAiSummaryClassifyByParentId(aiSummaryClassifyInfo.ParentId)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				br.Msg = "移动失败"
+				br.ErrMsg = "获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + err.Error()
+				return
+			}
+
+			//如果该分类下存在其他分类,且第一个其他分类的排序等于0,那么需要调整排序
+			if firstClassify != nil && firstClassify.Sort == 0 {
+				updateSortStr := ` sort + 1 `
+				_ = ai_summary.UpdateAiSummaryClassifySortByParentId(firstClassify.ParentId, firstClassify.AiSummaryClassifyId-1, 0, updateSortStr)
+			}
+
+			aiSummaryClassifyInfo.Sort = 0 //那就是排在第一位
+			aiSummaryClassifyInfo.ModifyTime = time.Now()
+			updateCol = append(updateCol, "Sort", "ModifyTime")
+		}
+
+		//更新
+		if len(updateCol) > 0 {
+			err = aiSummaryClassifyInfo.Update(updateCol)
+			if err != nil {
+				br.Msg = "移动失败"
+				br.ErrMsg = "修改失败,Err:" + err.Error()
+				return
+			}
+		}
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "移动成功"
+}
+
+// @Title Ai纪要列表接口
+// @Description Ai纪要列表接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   AiSummaryClassifyId   query   int  true       "分类id"
+// @Param   KeyWord   query   string  true       "搜索关键词"
+// @Param   IsShowMe   query   bool  true       "是否只看我的,true、false"
+// @Success 200 {object} data_manage.ChartListResp
+// @router /summary/list [get]
+func (this *AiController) AiSummaryList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	aiSummaryClassifyId, _ := this.GetInt("AiSummaryClassifyId")
+
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	keyWord := this.GetString("KeyWord")
+
+	var total int
+	page := paging.GetPaging(currentIndex, pageSize, total)
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = paging.StartIndex(currentIndex, pageSize)
+
+	var condition string
+	var pars []interface{}
+
+	if aiSummaryClassifyId > 0 {
+		sandboxClassifyIds, err := ai_summary.GetAiSummaryClassify(aiSummaryClassifyId)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "获取图表信息失败"
+			br.ErrMsg = "获取信息失败,GetChartClassify,Err:" + err.Error()
+			return
+		}
+		condition += " AND ai_summary_classify_id IN(" + sandboxClassifyIds + ") "
+		//pars = append(pars, chartClassifyId)
+	}
+	if keyWord != "" {
+		condition += ` AND  ( title LIKE '%` + keyWord + `%' )`
+	}
+
+	//只看我的
+	isShowMe, _ := this.GetBool("IsShowMe")
+	if isShowMe {
+		condition += ` AND sys_user_id = ? `
+		pars = append(pars, sysUser.AdminId)
+	}
+
+	//获取图表信息
+	list, err := ai_summary.GetAiSummaryListByCondition(condition, pars, startSize, pageSize)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Success = true
+		br.Msg = "获取纪要信息失败"
+		br.ErrMsg = "获取纪要信息失败,Err:" + err.Error()
+		return
+	}
+
+	for i, v := range list {
+		ids, err := ai_summary.GetAiSummaryAllParentByClassifyId(v.ClassifyId)
+		if err != nil {
+			br.Msg = "获取父级信息错误!"
+			br.ErrMsg = "获取父级信息错误,Err:" + err.Error()
+			return
+		}
+		list[i].ParentIds = ids
+	}
+	resp := new(ai_summary.AiSummaryListResp)
+	if list == nil || len(list) <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
+		items := make([]*ai_summary.AiSummaryItems, 0)
+		resp.Paging = page
+		resp.List = items
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		return
+	}
+
+	dataCount, err := ai_summary.GetAiSummaryListCountByCondition(condition, pars)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取指标信息失败"
+		br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
+		return
+	}
+	page = paging.GetPaging(currentIndex, pageSize, dataCount)
+	resp.Paging = page
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title Ai纪要详情接口
+// @Description Ai纪要详情接口
+// @Param   AiSummaryId   query   int  true       "详情id"
+// @Success 200 {object} data_manage.ChartListResp
+// @router /summary/detail [get]
+func (this *AiController) AiSummaryDetail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	aiSummaryId, _ := this.GetInt("AiSummaryId")
+
+	detail, err := ai_summary.GetAiSummaryItemById(aiSummaryId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Success = true
+		br.Msg = "获取沙盘信息失败"
+		br.ErrMsg = "获取沙盘信息失败,Err:" + err.Error()
+		return
+	}
+	resp := ai_summary.AiSummaryDetailResp{
+		AiSummaryItems: detail,
+	}
+
+	if detail.SaDocId >0 {
+		item := new(saModel.SaDoc)
+		e := item.GetItemById(detail.SaDocId)
+		if e != nil {
+			if e.Error() == utils.ErrNoRow() {
+				br.Msg = "文档已被删除, 请刷新页面"
+				return
+			}
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取文档信息失败, Err: " + e.Error()
+			return
+		}
+		resp.SaDocTitle = item.Title
+		resp.SaDocClassifyId = item.ClassifyId
+	}
+
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// @Title 新增ai纪要
+// @Description 新增ai纪要接口
+// @Param	request	body data_manage.AddChartClassifyReq true "type json string"
+// @Success 200 Ret=200 保存成功
+// @router /summary/add [post]
+func (this *AiController) AddAiSummary() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req ai_summary.AddAiSummaryReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.Title == "" {
+		br.Msg = "请输入名称"
+		br.IsSendEmail = false
+		return
+	}
+	if req.SummaryContent == "" {
+		br.Msg = "纪要内容为空"
+		br.IsSendEmail = false
+		return
+	}
+	if req.ClassifyId < 0 {
+		br.Msg = "分类id错误"
+		br.IsSendEmail = false
+		return
+	}
+	//获取该层级下最大的排序数
+	maxSort, err := ai_summary.GetAiSummaryMaxSort(req.ClassifyId)
+
+	summary := &ai_summary.AiSummary{
+		SaDocId:         req.SaDocId,
+		OriginContent:   req.OriginContent,
+		SummaryContent:  req.SummaryContent,
+		ClassifyId:      req.ClassifyId,
+		SysUserId:       this.SysUser.AdminId,
+		SysUserRealName: this.SysUser.RealName,
+		Title:           req.Title,
+		CreateTime:      time.Now(),
+		ModifyTime:      time.Now(),
+		OpenaiFileName:  req.OpenaiFileName,
+		OpenaiFilePath:  req.OpenaiFilePath,
+		OriginTitle:     req.OriginTitle,
+		Sort:            maxSort + 1,
+	}
+
+	id, err := ai_summary.AddAiSummary(summary)
+	if err != nil {
+		br.Msg = "保存分类失败"
+		br.ErrMsg = "保存分类失败,Err:" + err.Error()
+		return
+	}
+	classify ,err := ai_summary.GetAiSummaryClassifyById(req.ClassifyId)
+	if err != nil {
+		br.Msg = "获取分类信息失败"
+		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
+		return
+	}
+
+	resp := ai_summary.AiSummaryAddResp{
+		AiSummaryId: int(id),
+		UniqueCode:  strconv.Itoa(req.ClassifyId) + "_" + strconv.Itoa(int(id)),
+		ParentId:    classify.ParentId,
+	}
+
+	br.Ret = 200
+	br.Msg = "保存成功"
+	br.Success = true
+	br.Data = resp
+}
+
+// @Title 生成ai纪要
+// @Description 生成ai纪要接口
+// @Param	request	body data_manage.AddChartClassifyReq true "type json string"
+// @Success 200 Ret=200 保存成功
+// @router /summary/generate [post]
+func (this *AiController) GenerateAiSummary() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req ai_summary.GenerateAiSummaryReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.Prompt == "" {
+		br.Msg = "请输入提示词"
+		br.IsSendEmail = false
+		return
+	}
+	if req.OriginContent == "" && len(req.OpenaiFileId) == 0 && req.SaDocId <= 0 {
+		br.Msg = "参数错误"
+		br.IsSendEmail = false
+		return
+	}
+	if req.SaDocId > 0 {
+		// 获取段落
+		sectionOB := new(saModel.SaDocSection)
+		sectionCond := fmt.Sprintf(` AND %s = ?`, saModel.SaDocSectionColumns.DocId)
+		sectionPars := make([]interface{}, 0)
+		sectionPars = append(sectionPars, req.SaDocId)
+		sectionList, e := sectionOB.GetItemsByCondition(sectionCond, sectionPars, []string{}, "")
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取段落信息失败, Err: " + e.Error()
+			return
+		}
+		secIds := make([]int, 0)
+		for _, s := range sectionList {
+			secIds = append(secIds, s.SaDocSectionId)
+		}
+
+		for _, v := range sectionList {
+			req.OriginContent += v.Content + "<br>"
+		}
+	}
+
+	if utils.Re == nil {
+		key := "CACHE_CHAT_" + strconv.Itoa(this.SysUser.AdminId)
+		cacheVal, err := utils.Rc.RedisInt(key)
+		fmt.Println("RedisString:", cacheVal, "err:", err)
+		if err != nil && (err.Error() != "redigo: nil returned" && err.Error() != "redis: nil") {
+			br.Msg = "获取数据失败!"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+		putVal := 0
+		if cacheVal <= 0 {
+			putVal = utils.AiChatLimit
+		} else {
+			putVal = cacheVal - 1
+		}
+
+		if putVal <= 0 {
+			br.Msg = "您今日" + strconv.Itoa(utils.AiChatLimit) + "次问答已达上限,请明天再来!"
+			br.ErrMsg = "您今日" + strconv.Itoa(utils.AiChatLimit) + "次问答已达上限,请明天再来!"
+			return
+		}
+		lastSecond := utils.GetTodayLastSecond()
+		utils.Rc.Put(key, putVal, lastSecond)
+	}
+
+	resp := new(aimod.ChatResp)
+
+	if req.OriginContent != "" {
+		// 直接提问的方式
+
+		//根据提问,获取信息
+		ask := req.Prompt + req.OriginContent
+
+		var answer string
+		//answerArr := []string{
+		//	"周度数据显示,成品油现货市场价格跟随原油下跌,但近期相对抗跌,裂解价差走扩。批零价差方面汽油收窄,柴油走扩",
+		//	"出口利润在原油下跌海外成品油矛盾更大的情况下汽柴油出口窗口完全关闭",
+		//	"汽油需求在经历五一假期的一段高峰后将回归平稳,总体没有明显矛盾,后期我们担心更多的还是柴油。"}
+		//获取主题下的所有信息
+		//AiChatTopicId
+
+		//获取主题下的所有信息
+		//AiChatTopicId
+		historyList, err := aimod.GetAiChatList(req.AiChatTopicId)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "获取主题历史数据失败!"
+			br.ErrMsg = "获取主题历史数据失败,Err:" + err.Error()
+			return
+		}
+
+		historyChatList := make([]aimod.HistoryChat, 0)
+		for _, v := range historyList {
+			historyChat := new(aimod.HistoryChat)
+			historyChat.Ask = v.Ask
+			historyChat.Answer = v.Answer
+			historyChatList = append(historyChatList, *historyChat)
+		}
+
+		answer, err = aiser.ChatAutoMsg(ask, historyChatList, req.Model)
+		if err != nil {
+			br.Msg = "获取数据失败!"
+			br.ErrMsg = "获取数据失败,ChatAutoMsg,Err:" + err.Error()
+			return
+		}
+
+		resp.Ask = ask
+		resp.Answer = answer
+		resp.Model = req.Model
+
+		if req.AiChatTopicId <= 0 { //新增
+			topic := new(aimod.AiChatTopic)
+			topic.TopicName = ask
+			topic.SysUserId = this.SysUser.AdminId
+			topic.SysUserRealName = this.SysUser.RealName
+			topic.CreateTime = time.Now()
+			topic.ModifyTime = time.Now()
+			topicId, err := aimod.AddAiChatTopic(topic)
+			if err != nil {
+				br.Msg = "获取数据失败!"
+				br.ErrMsg = "生成话题失败,Err:" + err.Error()
+				return
+			}
+			resp.AiChatTopicId = int(topicId)
+			chatItem := new(aimod.AiChat)
+			chatItem.AiChatTopicId = resp.AiChatTopicId
+			chatItem.Ask = ask
+			chatItem.AskUuid = utils.MD5(ask)
+			chatItem.Answer = answer
+			chatItem.Model = EnabledModelsForMap[req.Model]
+			chatItem.SysUserId = this.SysUser.AdminId
+			chatItem.SysUserRealName = this.SysUser.RealName
+			chatItem.CreateTime = time.Now()
+			chatItem.ModifyTime = time.Now()
+			_, err = aimod.AddAiChat(chatItem)
+			if err != nil {
+				br.Msg = "获取数据失败!"
+				br.ErrMsg = "生成话题记录失败,Err:" + err.Error()
+				return
+			}
+		} else {
+			resp.AiChatTopicId = req.AiChatTopicId
+			chatItem := new(aimod.AiChat)
+			chatItem.AiChatTopicId = resp.AiChatTopicId
+			chatItem.Ask = ask
+			chatItem.AskUuid = utils.MD5(ask)
+			chatItem.Answer = answer
+			chatItem.Model = EnabledModelsForMap[req.Model]
+			chatItem.SysUserId = this.SysUser.AdminId
+			chatItem.SysUserRealName = this.SysUser.RealName
+			chatItem.CreateTime = time.Now()
+			chatItem.ModifyTime = time.Now()
+			_, err = aimod.AddAiChat(chatItem)
+			if err != nil {
+				br.Msg = "获取数据失败!"
+				br.ErrMsg = "生成话题记录失败,Err:" + err.Error()
+				return
+			}
+		}
+
+	} else if len(req.OpenaiFileId) > 0 {
+		// 走文件上传的方式
+		//根据提问,获取信息
+
+		ask := req.Prompt
+		askUuid := utils.MD5(ask)
+
+		var assistantId, threadId string
+		if req.AiChatTopicId > 0 {
+			aiChatTopicObj := new(aimod.AiChatTopic)
+			aiChatTopicObj.AiChatTopicId = req.AiChatTopicId
+			topic, err := aiChatTopicObj.GetAiChatTopicById()
+			if err != nil {
+				if err.Error() == utils.ErrNoRow() {
+					br.Msg = "获取数据失败!"
+					br.ErrMsg = "获取数据失败,主题不存在,Err:" + err.Error()
+					return
+				}
+				br.Msg = "获取数据失败!"
+				br.ErrMsg = "获取数据失败,GetAiChatTopicById,Err:" + err.Error()
+				return
+			}
+			assistantId = topic.AssistantId
+			threadId = topic.ThreadId
+		}
+
+		var answer string
+		//获取主题下的所有信息
+		//AiChatTopicId
+		//historyList, err := aimod.GetAiChatList(req.AiChatTopicId)
+		//if err != nil && err.Error() != utils.ErrNoRow() {
+		//	br.Msg = "获取主题历史数据失败!"
+		//	br.ErrMsg = "获取主题历史数据失败,Err:" + err.Error()
+		//	return
+		//}
+
+		frList := make([]aimod.HistoryChat, 0)
+		tmpFileIdList := make([]string, 0)
+		tmpFileIdList = append(tmpFileIdList, req.OpenaiFileId...)
+		//// 历史消息
+		//for _, v := range historyList {
+		//	if v.OpenaiFileId != "" {
+		//		tmpFileIdList = append(tmpFileIdList, v.OpenaiFileId)
+		//	} else {
+		//		historyFr := new(aimod.HistoryChat)
+		//		historyFr.Ask = v.Ask
+		//		historyFr.Answer = v.Answer
+		//		historyFr.OpenaiFileId = tmpFileIdList
+		//		frList = append(frList, *historyFr)
+		//		tmpFileIdList = []string{}
+		//	}
+		//}
+		// 当前的消息
+		{
+			frItem := new(aimod.HistoryChat)
+			frItem.Ask = ask
+			frItem.Answer = ""
+			frItem.OpenaiFileId = tmpFileIdList
+			frList = append(frList, *frItem)
+		}
+
+		fileRetrieveResp, err := aiser.FileRetrieve(assistantId, threadId, req.Model, frList, req.OpenaiFileId)
+		if err != nil {
+			br.Msg = "获取数据失败!"
+			br.ErrMsg = "获取数据失败,FileRetrieve,Err:" + err.Error()
+			return
+		}
+
+		if fileRetrieveResp != nil {
+			if fileRetrieveResp.Ret == 200 {
+				assistantId = fileRetrieveResp.Data.AssistantId
+				threadId = fileRetrieveResp.Data.ThreadId
+				answer = fileRetrieveResp.Data.Answer
+			} else {
+				br.Msg = "获取数据失败!"
+				br.ErrMsg = fileRetrieveResp.Msg
+				return
+			}
+		}
+
+		if req.AiChatTopicId <= 0 { //新增
+			topic := new(aimod.AiChatTopic)
+			topic.TopicName = ask
+			topic.SysUserId = this.SysUser.AdminId
+			topic.SysUserRealName = this.SysUser.RealName
+			topic.CreateTime = time.Now()
+			topic.ModifyTime = time.Now()
+			topic.AssistantId = assistantId
+			topic.ThreadId = threadId
+			topicId, err := aimod.AddAiChatTopic(topic)
+			if err != nil {
+				br.Msg = "获取数据失败!"
+				br.ErrMsg = "生成话题失败,Err:" + err.Error()
+				return
+			}
+			chatItem := new(aimod.AiChat)
+			chatItem.AiChatTopicId = int(topicId)
+			chatItem.Ask = ask
+			chatItem.AskUuid = utils.MD5(ask)
+			chatItem.Answer = answer
+			chatItem.Model = EnabledModelsForMap[req.Model]
+			chatItem.SysUserId = this.SysUser.AdminId
+			chatItem.SysUserRealName = this.SysUser.RealName
+			chatItem.CreateTime = time.Now()
+			chatItem.ModifyTime = time.Now()
+			_, err = aimod.AddAiChat(chatItem)
+			if err != nil {
+				br.Msg = "获取数据失败!"
+				br.ErrMsg = "生成话题记录失败,Err:" + err.Error()
+				return
+			}
+			req.AiChatTopicId = int(topicId)
+		} else {
+			chatItem := new(aimod.AiChat)
+			chatItem.AiChatTopicId = req.AiChatTopicId
+			chatItem.Ask = ask
+			chatItem.AskUuid = askUuid
+			chatItem.Answer = answer
+			chatItem.Model = EnabledModelsForMap[req.Model]
+			chatItem.SysUserId = this.SysUser.AdminId
+			chatItem.SysUserRealName = this.SysUser.RealName
+			chatItem.CreateTime = time.Now()
+			chatItem.ModifyTime = time.Now()
+			_, err = aimod.AddAiChat(chatItem)
+			if err != nil {
+				br.Msg = "获取数据失败!"
+				br.ErrMsg = "生成话题记录失败,Err:" + err.Error()
+				return
+			}
+			//更新	assistantId,threadId
+			aiChatTopicObj := new(aimod.AiChatTopic)
+
+			updateParams := make(map[string]interface{})
+			updateParams["assistant_id"] = assistantId
+			updateParams["thread_id"] = threadId
+			updateParams["modify_time"] = time.Now()
+
+			whereParam := make(map[string]interface{})
+			whereParam["ai_chat_topic_id"] = req.AiChatTopicId
+
+			err = aiChatTopicObj.Update(updateParams, whereParam)
+			if err != nil {
+				br.Msg = "获取失败!"
+				br.ErrMsg = "修改助手标识失败,Err:" + err.Error()
+				return
+			}
+		}
+		resp.Model = aimod.ModelViewMap[req.Model]
+		resp.AiChatTopicId = req.AiChatTopicId
+		resp.Ask = ask
+		resp.Answer = answer
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+//// @Title 文件上传
+//// @Description 文件上传接口
+//// @Param   File   query   file  true       "文件"
+//// @Param   AiChatTopicId   query   int  true       "主题id"
+//// @Success 200 {object} models.ResourceResp
+//// @router /file/upload [post]
+//func (this *AiFileController) FileUpload2() {
+//	br := new(models.BaseResponse).Init()
+//	defer func() {
+//		this.Data["json"] = br
+//		this.ServeJSON()
+//	}()
+//
+//	f, h, err := this.GetFile("File")
+//	if err != nil {
+//		br.Msg = "获取资源信息失败"
+//		br.ErrMsg = "获取资源信息失败,Err:" + err.Error()
+//		return
+//	}
+//	model := this.GetString("Model")
+//
+//	aiChatTopicId, _ := this.GetInt("AiChatTopicId")
+//
+//	uploadFileName := h.Filename //上传的文件名
+//	ext := path.Ext(h.Filename)
+//	dateDir := time.Now().Format("20060102")
+//	uploadDir := utils.STATIC_DIR + "ai/" + dateDir
+//	err = os.MkdirAll(uploadDir, utils.DIR_MOD)
+//	if err != nil {
+//		br.Msg = "存储目录创建失败"
+//		br.ErrMsg = "存储目录创建失败,Err:" + err.Error()
+//		return
+//	}
+//	randStr := utils.GetRandStringNoSpecialChar(28)
+//	fileName := randStr + ext
+//	fpath := uploadDir + "/" + fileName
+//	defer f.Close() //关闭上传文件
+//	err = this.SaveToFile("File", fpath)
+//	if err != nil {
+//		br.Msg = "文件上传失败"
+//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+//		return
+//	}
+//	resourceUrl := ``
+//	ossClient := services.NewOssClient()
+//	if ossClient == nil {
+//		br.Msg = "上传失败"
+//		br.ErrMsg = "初始化OSS服务失败"
+//		return
+//	}
+//	resourceUrl, err = ossClient.UploadFile(fileName, fpath, "")
+//	if err != nil {
+//		br.Msg = "文件上传失败"
+//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+//		return
+//	}
+//
+//	defer func() {
+//		os.Remove(fpath)
+//	}()
+//
+//	item := new(models.Resource)
+//	item.ResourceUrl = resourceUrl
+//	item.ResourceType = 1
+//	item.CreateTime = time.Now()
+//	newId, err := models.AddResource(item)
+//	if err != nil {
+//		br.Msg = "资源上传失败"
+//		br.ErrMsg = "资源上传失败,Err:" + err.Error()
+//		return
+//	}
+//	//调用AI接口,上传文件
+//	resp := models.ResourceResp{
+//		Id:           newId,
+//		ResourceUrl:  resourceUrl,
+//		ResourceName: uploadFileName,
+//	}
+//	uploadResult, err := aiser.OpenAiFileUpload(resourceUrl, uploadFileName, model)
+//	if err != nil {
+//		br.Msg = "文件上传失败"
+//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+//		return
+//	}
+//
+//	var assistantId, threadId string
+//	if aiChatTopicId > 0 {
+//		aiChatTopicObj := new(aimod.AiChatTopic)
+//		aiChatTopicObj.AiChatTopicId = aiChatTopicId
+//		topic, err := aiChatTopicObj.GetAiChatTopicById()
+//		if err != nil {
+//			if err.Error() == utils.ErrNoRow() {
+//				br.Msg = "获取数据失败!"
+//				br.ErrMsg = "获取数据失败,主题不存在,Err:" + err.Error()
+//				return
+//			}
+//			br.Msg = "获取数据失败!"
+//			br.ErrMsg = "获取数据失败,GetAiChatTopicById,Err:" + err.Error()
+//			return
+//		}
+//		assistantId = topic.AssistantId
+//		threadId = topic.ThreadId
+//	}
+//
+//	if aiChatTopicId <= 0 { //新增
+//		topic := new(aimod.AiChatTopic)
+//		var filenameWithSuffix string
+//		filenameWithSuffix = path.Base(uploadFileName)
+//		var fileSuffix string
+//		fileSuffix = path.Ext(filenameWithSuffix)
+//		var filenameOnly string
+//		filenameOnly = strings.TrimSuffix(filenameWithSuffix, fileSuffix)
+//		topic.TopicName = filenameOnly
+//		topic.SysUserId = this.SysUser.AdminId
+//		topic.SysUserRealName = this.SysUser.RealName
+//		topic.CreateTime = time.Now()
+//		topic.ModifyTime = time.Now()
+//		topic.AssistantId = assistantId
+//		topic.ThreadId = threadId
+//		topicId, err := aimod.AddAiChatTopic(topic)
+//		if err != nil {
+//			br.Msg = "获取数据失败!"
+//			br.ErrMsg = "生成话题失败,Err:" + err.Error()
+//			return
+//		}
+//		aiChatTopicId = int(topicId)
+//		chatItem := new(aimod.AiChat)
+//		chatItem.AiChatTopicId = aiChatTopicId
+//		chatItem.Ask = uploadFileName
+//		chatItem.AskUuid = utils.MD5(uploadFileName)
+//		chatItem.Model = EnabledModelsForMap[model]
+//		chatItem.SysUserId = this.SysUser.AdminId
+//		chatItem.SysUserRealName = this.SysUser.RealName
+//		if uploadResult != nil && uploadResult.Data != nil {
+//			chatItem.OpenaiFileId = uploadResult.Data.ID
+//			chatItem.OpenaiFileName = uploadFileName
+//		}
+//		chatItem.OpenaiFilePath = resourceUrl
+//		chatItem.CreateTime = time.Now()
+//		chatItem.ModifyTime = time.Now()
+//		_, err = aimod.AddAiChat(chatItem)
+//		if err != nil {
+//			br.Msg = "获取数据失败!"
+//			br.ErrMsg = "生成话题记录失败,Err:" + err.Error()
+//			return
+//		}
+//	} else {
+//		chatItem := new(aimod.AiChat)
+//		chatItem.AiChatTopicId = aiChatTopicId
+//		chatItem.Ask = uploadFileName
+//		chatItem.AskUuid = utils.MD5(fileName)
+//		chatItem.Model = EnabledModelsForMap[model]
+//		chatItem.SysUserId = this.SysUser.AdminId
+//		chatItem.SysUserRealName = this.SysUser.RealName
+//		if uploadResult != nil && uploadResult.Data != nil {
+//			chatItem.OpenaiFileId = uploadResult.Data.ID
+//			chatItem.OpenaiFileName = uploadFileName
+//		}
+//		chatItem.OpenaiFilePath = resourceUrl
+//		chatItem.CreateTime = time.Now()
+//		chatItem.ModifyTime = time.Now()
+//		_, err = aimod.AddAiChat(chatItem)
+//		if err != nil {
+//			br.Msg = "获取数据失败!"
+//			br.ErrMsg = "生成话题记录失败,Err:" + err.Error()
+//			return
+//		}
+//	}
+//
+//	if uploadResult != nil && uploadResult.Data != nil && uploadResult.Data.ID != "" {
+//		uploadObj := new(aimod.FileUploadRecord)
+//		uploadObj.AdminId = this.SysUser.AdminId
+//		uploadObj.FileUrl = resourceUrl
+//		uploadObj.FileName = uploadFileName
+//		uploadObj.OpenaiFileId = uploadResult.Data.ID
+//		uploadObj.OpenaiFileName = uploadResult.Data.FileName
+//		uploadObj.OpenaiObject = uploadResult.Data.Object
+//		uploadObj.OpenaiStatus = uploadResult.Data.Status
+//		uploadObj.OpenaiPurpose = uploadResult.Data.Purpose
+//		uploadObj.OpenaiStatusDetails = uploadResult.Data.StatusDetails
+//		uploadObj.OpenaiCreatedAt = uploadResult.Data.CreatedAt
+//		uploadObj.CreateTime = time.Now()
+//		uploadObj.ModifyTime = time.Now()
+//		_, err = uploadObj.AddFileUploadRecord()
+//		if err != nil {
+//			br.Msg = "上传失败"
+//			br.ErrMsg = "上传失败,Err:" + err.Error()
+//			return
+//		}
+//		resp.OpenaiFileId = uploadObj.OpenaiFileId
+//	}
+//	resp.AiChatTopicId = aiChatTopicId
+//	br.Msg = "上传成功"
+//	br.Ret = 200
+//	br.Success = true
+//	br.Data = resp
+//	return
+//}
+
+
+// AiSummaryClassifyList
+// @Title 获取所有纪要分类接口-不包含沙盘
+// @Description 获取所有纪要分类接口-不包含沙盘
+// @Param   IsShowMe   query   bool  true       "是否只看我的,true、false"
+// @Success 200 {object} data_manage.ChartClassifyListResp
+// @router /summary/classifyList [get]
+func (this *AiController) AiSummaryClassifyList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	resp := new(ai_summary.AiSummaryClassifyListResp)
+
+	rootList, err := ai_summary.GetAiSummaryClassifyByParentId(0)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+
+	classifyAll, err := ai_summary.GetAiSummaryClassifyAll()
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+
+	nodeAll := make([]*ai_summary.AiSummaryClassifyItems, 0)
+	for k := range rootList {
+		rootNode := rootList[k]
+		aiSummaryService.AiSummaryClassifyItemsMakeTree(this.SysUser, classifyAll, rootNode)
+		nodeAll = append(nodeAll, rootNode)
+	}
+
+	resp.AllNodes = nodeAll
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}

+ 133 - 0
models/ai_summary/ai_pormpt.go

@@ -0,0 +1,133 @@
+package ai_summary
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type AiPrompt struct {
+	AiPromptId    int       `orm:"column(ai_prompt_id);pk"` // ai纪要提示词id
+	PromptContent string    // 原始内容
+	SysAdminId    int       // 创建人ID
+	SysAdminName  string    // 创建人姓名
+	Title         string    // 文档标题
+	CreateTime    time.Time // 创建时间
+	ModifyTime    time.Time // 更新时间
+	IsShare       int       // 是否分享,0:不分享,1:分享
+	Sort          int       // 排序
+}
+
+type AiPromptItem struct {
+	AiPromptId    int    `orm:"column(ai_prompt_id);pk"` // ai纪要提示词id
+	PromptContent string // 原始内容
+	SysAdminId    int    // 创建人ID
+	SysAdminName  string // 创建人姓名
+	Title         string // 文档标题
+	CreateTime    string // 创建时间
+	ModifyTime    string // 更新时间
+	IsShare       int    // 是否分享,0:不分享,1:分享
+	Sort          int    // 排序
+}
+
+func GetAiPromptList(sysUserId, isShare int) (items []*AiPromptItem, err error) {
+	sql := ``
+	if isShare == 1 {
+		sql = ` SELECT * FROM ai_prompt WHERE sys_admin_id=? and is_share=1 ORDER BY sort  `
+	} else {
+		sql = ` SELECT * FROM ai_prompt WHERE sys_admin_id=? ORDER BY sort  `
+	}
+	o := orm.NewOrm()
+	_, err = o.Raw(sql, sysUserId).QueryRows(&items)
+	return
+}
+
+func GetAiPromptShareList() (items []*AiPromptItem, err error) {
+	sql := ``
+	sql = ` SELECT * FROM ai_prompt WHERE is_share=1 ORDER BY create_time DESC `
+
+	o := orm.NewOrm()
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+type RespGroupListItem struct {
+	GroupId    int64  `description:"目录id"`
+	GroupName  string `description:"目录名称"`
+	AdminId    int    `description:"目录创建者账号ID"`
+	IsShare    int8   `description:"是否共享,0私有,1共享"`
+	PromptList []*AiPromptItem
+}
+
+type AiPromptAddReq struct {
+	PromptContent string // 原始内容
+	Title         string // 文档标题
+}
+
+func AddPropmt(item *AiPrompt) (lastId int64, err error) {
+	o := orm.NewOrm()
+	lastId, err = o.Insert(item)
+	return
+}
+
+type AiPromptEditReq struct {
+	PromptContent string // 原始内容
+	Title         string // 文档标题
+	AiPromptId    int    // ai纪要提示词id
+}
+
+// Update
+func (aiPrompt *AiPrompt) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(aiPrompt, cols...)
+	return
+}
+
+// DelAiSummaryById 根据纪要id删除纪要
+func DelAiPromptyId(aiPromptId int) (err error) {
+	o := orm.NewOrm()
+	sql := `delete from ai_prompt where ai_prompt_id = ? `
+	_, err = o.Raw(sql, aiPromptId).Exec()
+	return
+}
+
+func GetAiPromptById(promptId int) (item *AiPrompt, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM ai_prompt WHERE 1=1 AND ai_prompt_id=? `
+	err = o.Raw(sql, promptId).QueryRow(&item)
+	return
+}
+
+type DeleteAipromptReq struct {
+	AiPromptId int // ai纪要提示词id
+}
+
+type ReqMovePrompt struct {
+	AiPromptId     int `description:"当前被移动的目录里的ppt绑定序号"`
+	PrevAiPromptId int `description:"上一个目录里的ppt绑定序号,ppt最终在目录中置顶,则传0值"`
+	NextAiPromptId int `description:"下一个目录里的ppt绑定序号,ppt最终在目录末尾,则传0值"`
+}
+
+// GetAiPromptMaxSort 获取ai提示词下最大的排序数
+func GetAiPromptMaxSort(adminId int) (sort int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT Max(sort) AS sort FROM ai_prompt WHERE sys_admin_id=? `
+	err = o.Raw(sql, adminId).QueryRow(&sort)
+	return
+}
+
+
+// MoveDownPromptBySort 往下移动提示词
+func MoveDownPromptBySort(sysAdminId, prevSort, currentSort int) (err error) {
+	o := orm.NewOrm()
+	sql := `update ai_prompt set sort = sort - 1 where sys_admin_id = ? and sort <= ? and sort> ? `
+	_, err = o.Raw(sql, sysAdminId, prevSort, currentSort).Exec()
+	return
+}
+
+// MoveUpPromptBySort 往上移动提示词
+func MoveUpPromptBySort(sysAdminId, nextSort, currentSort int) (err error) {
+	o := orm.NewOrm()
+	sql := `update ai_prompt set sort = sort + 1 where sys_admin_id = ? and sort >= ? and sort< ?`
+	_, err = o.Raw(sql, sysAdminId, nextSort, currentSort).Exec()
+	return
+}

+ 176 - 0
models/ai_summary/ai_summary.go

@@ -0,0 +1,176 @@
+package ai_summary
+
+import (
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type AiSummary struct {
+	AiSummaryId     int       `orm:"column(ai_summary_id);pk"` // ai纪要id
+	SaDocId         int       // 文档ID
+	OriginContent   string    // 原始内容
+	SummaryContent  string    // 纪要内容
+	ClassifyId      int       // 分类id
+	SysUserId       int       // 创建人ID
+	SysUserRealName string    // 创建人姓名
+	Title           string    // 文档标题
+	CreateTime      time.Time // 创建时间
+	ModifyTime      time.Time // 更新时间
+	OpenaiFileName  string    // 文件名称
+	OpenaiFilePath  string    // 文件路径
+	OriginTitle     string    // 原文标题
+	Sort            int       // 排序字段,越小越靠前,默认值:10
+}
+
+type AiSummaryItems struct {
+	AiSummaryId     int    `orm:"column(ai_summary_id);pk"` // ai纪要id
+	SaDocId         int    // 文档ID
+	OriginContent   string // 原始内容
+	OriginTitle     string // 原文标题
+	SummaryContent  string // 纪要内容
+	ClassifyId      int    // 分类id
+	SysUserId       int    // 创建人ID
+	SysUserRealName string // 创建人姓名
+	Title           string // 文档标题
+	CreateTime      string // 创建时间
+	ModifyTime      string // 更新时间
+	OpenaiFileName  string // 文件名称
+	OpenaiFilePath  string // 文件路径
+	Sort            int    // 排序字段,越小越靠前,默认值:10
+	ParentIds       string
+}
+
+func GetAiChatTopicList(sysUserId int) (item []*AiSummary, err error) {
+	sql := ` SELECT * FROM ai_summary WHERE classify_id=? ORDER BY create_time DESC `
+	o := orm.NewOrm()
+	_, err = o.Raw(sql, sysUserId).QueryRows(&item)
+	return
+}
+
+// GetAiSummaryById 根据纪要id获取详情
+func GetAiSummaryById(aiSummaryId int) (sandboxInfo *AiSummary, err error) {
+	o := orm.NewOrm()
+	sql := `select * from ai_summary where ai_summary_id = ? `
+	err = o.Raw(sql, aiSummaryId).QueryRow(&sandboxInfo)
+	return
+}
+
+// GetAiSummaryById 根据纪要id获取详情
+func GetAiSummaryItemById(aiSummaryId int) (sandboxInfo *AiSummaryItems, err error) {
+	o := orm.NewOrm()
+	sql := `select * from ai_summary where ai_summary_id = ? `
+	err = o.Raw(sql, aiSummaryId).QueryRow(&sandboxInfo)
+	return
+}
+
+// DelAiSummaryById 根据纪要id删除纪要
+func DelAiSummaryById(aiSummaryId int) (err error) {
+	o := orm.NewOrm()
+	sql := `delete from ai_summary where ai_summary_id = ? `
+	_, err = o.Raw(sql, aiSummaryId).Exec()
+	return
+}
+
+func MoveAiSummary(aiSummaryId, classifyId int) (err error) {
+	o := orm.NewOrm()
+	sql := ` UPDATE  ai_summary
+			SET
+			  classify_id = ?
+			WHERE ai_summary_id = ?`
+	_, err = o.Raw(sql, classifyId, aiSummaryId).Exec()
+	return
+}
+
+// GetFirstAiSummaryByClassifyId 获取当前分类下,且排序数相同 的排序第一条的数据
+func GetFirstAiSummaryByClassifyId(classifyId int) (item *AiSummary, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM ai_summary WHERE classify_id=? order by sort asc,ai_summary_id asc limit 1`
+	err = o.Raw(sql, classifyId).QueryRow(&item)
+	return
+}
+
+// Update
+func (aiSummary *AiSummary) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(aiSummary, cols...)
+	return
+}
+
+// UpdateSandboxSortByClassifyId 根据纪要id更新排序
+func UpdateAiSummarySortByClassifyId(classifyId, nowSort, prevAiSummaryId int, updateSort string) (err error) {
+	o := orm.NewOrm()
+	sql := ` update ai_summary set sort = ` + updateSort + ` WHERE classify_id=?  AND `
+	if prevAiSummaryId > 0 {
+		sql += ` (sort > ? or (ai_summary_id > ` + fmt.Sprint(prevAiSummaryId) + ` and sort = ` + fmt.Sprint(nowSort) + `))`
+	}
+	_, err = o.Raw(sql, classifyId, nowSort).Exec()
+	return
+}
+
+func GetAiSummaryListByCondition(condition string, pars []interface{}, startSize, pageSize int) (item []*AiSummaryItems, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM ai_summary WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	sql += " ORDER BY create_time DESC LIMIT ?,? "
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&item)
+	return
+}
+
+func GetAiSummaryListCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT COUNT(1) AS count FROM ai_summary WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func AddAiSummary(item *AiSummary) (lastId int64, err error) {
+	o := orm.NewOrm()
+	lastId, err = o.Insert(item)
+	return
+}
+
+type AddAiSummaryReq struct {
+	SaDocId        int    // 文档ID
+	OriginContent  string // 原始内容
+	SummaryContent string // 纪要内容
+	ClassifyId     int    // 分类id
+	Title          string // 文档标题
+	OpenaiFileName string // 文件名称
+	OpenaiFilePath string // 文件路径
+	OriginTitle    string // 原文标题
+}
+
+type GenerateAiSummaryReq struct {
+	AiChatTopicId int      `description:"主题id"`
+	OriginContent string   // 原始内容
+	OpenaiFileId  []string `description:"openai返回的文件id"`
+	Model         string   `description:"模型名称"`
+	Prompt        string   `description:"提示词"`
+	SaDocId       int      // 文档ID
+}
+
+// GetAiSummaryMaxSort 获取ai纪要下最大的排序数
+func GetAiSummaryMaxSort(classifyId int) (sort int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT Max(sort) AS sort FROM ai_summary WHERE parent_id=? `
+	err = o.Raw(sql, classifyId).QueryRow(&sort)
+	return
+}
+
+type AiSummaryAddResp struct {
+	AiSummaryId int
+	UniqueCode  string // 唯一编码
+	ParentId    int
+}
+
+type AiSummaryDetailResp struct {
+	*AiSummaryItems
+	SaDocTitle      string `description:"文档库标题"`
+	SaDocClassifyId int    `description:"文档库分类id"`
+}

+ 331 - 0
models/ai_summary/ai_summary_classify.go

@@ -0,0 +1,331 @@
+package ai_summary
+
+import (
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"time"
+)
+
+type AiSummaryClassify struct {
+	AiSummaryClassifyId int       `orm:"column(ai_summary_classify_id);pk"` // ai纪要分类id
+	ClassifyName        string    // 分类名称
+	ParentId            int       // 父级id
+	CreateTime          time.Time // 创建时间
+	ModifyTime          time.Time // 修改时间
+	SysUserId           int       // 创建人id,使用指针表示可为空
+	SysUserRealName     string    // 创建人姓名
+	Level               int       // 层级
+	Sort                int       // 排序字段,越小越靠前,默认值:10
+	RootId              int       // 顶级ID
+	HasData             int       `description:"是否含有指标数据"`
+}
+
+func AddAiSummaryClassify(item *AiSummaryClassify) (lastId int64, err error) {
+	o := orm.NewOrm()
+	lastId, err = o.Insert(item)
+	return
+}
+
+type AiSummaryClassifyItems struct {
+	AiSummaryClassifyId int
+	ClassifyName        string    `description:"分类名称"`
+	ParentId            int       `description:"父级id"`
+	HasData             int       `description:"是否含有指标数据"`
+	CreateTime          time.Time `description:"创建时间"`
+	ModifyTime          time.Time `description:"修改时间"`
+	SysUserId           int       `description:"创建人id"`
+	SysUserRealName     string    `description:"创建人姓名"`
+	Level               int       `description:"层级"`
+	Sort                int       `description:"排序字段,越小越靠前,默认值:10"`
+	AiSummaryId         int       `description:"纪要id"`
+	UniqueCode          string    `description:"唯一编码"`
+	Children            []*AiSummaryClassifyItems
+}
+
+type AiSummaryClassifyListResp struct {
+	AllNodes []*AiSummaryClassifyItems
+}
+
+// GetAiSummaryClassifyByParentId
+func GetAiSummaryClassifyByParentId(parentId int) (items []*AiSummaryClassifyItems, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM ai_summary_classify WHERE parent_id=? order by sort asc,ai_summary_classify_id asc`
+	_, err = o.Raw(sql, parentId).QueryRows(&items)
+	return
+}
+
+// GetAiSummaryInfoByAdminId 获取所有我创建的纪要,用于分类展示
+func GetAiSummaryInfoByAdminId(adminId int) (items []*AiSummaryClassifyItems, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT
+	a.*,
+	b.ai_summary_classify_id,
+	b.classify_name 
+FROM
+	ai_summary AS a
+	JOIN ai_summary_classify AS b ON a.classify_id = b.ai_summary_classify_id 
+WHERE
+	a.sys_user_id = ? 
+ORDER BY
+	a.sort ASC,
+	a.create_time ASC `
+	_, err = o.Raw(sql, adminId).QueryRows(&items)
+	return
+}
+
+// GetAiSummaryClassifyAndInfoByParentId
+func GetAiSummaryClassifyAndInfoByParentId(parentId int) (items []*AiSummaryClassifyItems, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT
+	0 AS ai_summary_id,
+	ai_summary_classify_id,
+	classify_name,
+	parent_id,
+	create_time,
+	modify_time,
+	sys_user_id,
+	sys_user_real_name AS sys_user_real_name,
+	sort,
+	level
+FROM
+	ai_summary_classify 
+WHERE
+	parent_id = ? UNION ALL
+SELECT
+	ai_summary_id,
+	classify_id as ai_summary_classify_id,
+	title AS classify_name,
+	0 AS parent_id,
+	create_time,
+	modify_time,
+	sys_user_id,
+	sys_user_real_name,
+	sort,
+	0 AS level
+FROM
+	ai_summary 
+WHERE
+	classify_id = ? 
+ORDER BY
+	sort ASC,
+	ai_summary_classify_id ASC`
+	_, err = o.Raw(sql, parentId, parentId).QueryRows(&items)
+	return
+}
+
+type AddAiSummaryClassifyReq struct {
+	ClassifyName string `description:"分类名称"`
+	ParentId     int    `description:"父级id,第一级传0"`
+	Level        int    `description:"层级,第一级传0,其余传上一级的层级"`
+}
+
+func GetAiSummaryClassifyCount(classifyName string, parentId int) (count int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT COUNT(1) AS count FROM ai_summary_classify WHERE parent_id=? AND classify_name=? `
+	err = o.Raw(sql, parentId, classifyName).QueryRow(&count)
+	return
+}
+
+// GetAiSummaryClassifyMaxSort 获取ai纪要下最大的排序数
+func GetAiSummaryClassifyMaxSort(parentId int) (sort int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT Max(sort) AS sort FROM ai_summary_classify WHERE parent_id=? `
+	err = o.Raw(sql, parentId).QueryRow(&sort)
+	return
+}
+
+type EditAiSummaryClassifyReq struct {
+	ClassifyName        string `description:"分类名称"`
+	AiSummaryClassifyId int    `description:"分类id"`
+}
+
+func EditSandboxClassify(classifyId int, classifyName string) (err error) {
+	o := orm.NewOrm()
+	sql := `UPDATE ai_summary_classify SET classify_name=?, modify_time=NOW() WHERE ai_summary_classify_id=? `
+	_, err = o.Raw(sql, classifyName, classifyId).Exec()
+	return
+}
+
+type AiSummaryClassifyDeleteCheckReq struct {
+	AiSummaryClassifyId int `description:"分类id"`
+}
+
+func GetAiSummaryInfoCountByClassifyId(classifyId int) (count int, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT COUNT(1) AS count FROM ai_summary AS a
+				WHERE a.classify_id IN(
+				SELECT t.ai_summary_classify_id FROM 
+				(
+				SELECT rd.*
+				FROM (SELECT * FROM ai_summary_classify WHERE parent_id IS NOT NULL) rd,
+					 (SELECT @pid := ?) pd 
+				WHERE FIND_IN_SET(parent_id, @pid) > 0 
+				  AND @pid := CONCAT(@pid, ',', ai_summary_classify_id) 
+				UNION SELECT * FROM ai_summary_classify WHERE ai_summary_classify_id = @pid 
+				)AS t
+				) `
+	err = o.Raw(sql, classifyId).QueryRow(&count)
+	return
+}
+
+type DeleteAiSummaryClassifyReq struct {
+	AiSummaryClassifyId int `description:"分类id"`
+	AiSummaryId         int `description:"纪要id"`
+}
+
+func DeleteAiSummaryClassify(classifyId int) (err error) {
+	o := orm.NewOrm()
+	sql := ` DELETE FROM ai_summary_classify
+				WHERE ai_summary_classify_id IN(
+				SELECT t.ai_summary_classify_id FROM
+				(
+				SELECT rd.*
+				FROM (SELECT * FROM ai_summary_classify WHERE parent_id IS NOT NULL) rd,
+				(SELECT @pid := ?) pd
+				WHERE FIND_IN_SET(parent_id, @pid) > 0
+				AND @pid := CONCAT(@pid, ',', ai_summary_classify_id)
+				UNION SELECT * FROM ai_summary_classify WHERE ai_summary_classify_id = @pid
+				)AS t
+				) `
+	_, err = o.Raw(sql, classifyId).Exec()
+	return
+}
+
+// MoveAiSummaryClassifyReq 移动纪要分类请求参数
+type MoveAiSummaryClassifyReq struct {
+	AiSummaryClassifyId int `description:"分类id"`
+	AiSummaryId         int `description:"纪要ID"`
+	ParentClassifyId    int `description:"父级分类id 移动纪要时为目标分类id"`
+	PrevId              int `description:"上一个兄弟节点分类id"`
+	NextId              int `description:"下一个兄弟节点分类id"`
+	PrevType            int `description:"上一个兄弟节点类型 1分类 2纪要 "`
+	NextType            int `description:"上一个兄弟节点类型 1分类 2纪要 "`
+}
+
+func GetAiSummaryClassifyById(classifyId int) (item *AiSummaryClassify, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM ai_summary_classify WHERE ai_summary_classify_id=? `
+	err = o.Raw(sql, classifyId).QueryRow(&item)
+	return
+}
+
+func GetAiSummaryClassifyCountById(classifyId int) (count int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT count(1) AS count FROM ai_summary_classify WHERE ai_summary_classify_id=? `
+	err = o.Raw(sql, classifyId).QueryRow(&count)
+	return
+}
+
+// Update 更新沙盘分类基础信息
+func (aiSummaryClassify *AiSummaryClassify) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(aiSummaryClassify, cols...)
+	return
+}
+
+// GetFirstAiSummaryClassifyByParentId 获取当前父级沙盘分类下的排序第一条的数据
+func GetFirstAiSummaryClassifyByParentId(parentId int) (item *AiSummaryClassify, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM ai_summary_classify WHERE parent_id=? order by sort asc,ai_summary_classify_id asc limit 1`
+	err = o.Raw(sql, parentId).QueryRow(&item)
+	return
+}
+
+// UpdateSandboxClassifySortByParentId 根据沙盘父类id更新排序
+func UpdateAiSummaryClassifySortByParentId(parentId, classifyId, nowSort int, updateSort string) (err error) {
+	o := orm.NewOrm()
+	sql := ` update ai_summary_classify set sort = ` + updateSort + ` WHERE parent_id=? and sort > ? `
+	if classifyId > 0 {
+		sql += ` or ( ai_summary_classify_id > ` + fmt.Sprint(classifyId) + ` and sort= ` + fmt.Sprint(nowSort) + `)`
+	}
+	_, err = o.Raw(sql, parentId, nowSort).Exec()
+	return
+}
+
+// 获取所有子级分类id
+func GetAiSummaryClassifySubcategories(classifyId int) (Ids string, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT GROUP_CONCAT(ai_summary_classify_id) AS ids
+FROM (
+SELECT @pv := ? AS ai_summary_classify_id
+UNION ALL
+SELECT sc.ai_summary_classify_id
+FROM ai_summary_classify sc
+JOIN (SELECT @pv := ?) initial
+WHERE sc.parent_id = @pv
+) subcategories; `
+	err = o.Raw(sql, classifyId, classifyId).QueryRow(&Ids)
+	return
+}
+
+func GetAiSummaryClassify(aiSummaryClassify int) (aiSummaryClassifyIds string, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT GROUP_CONCAT(t.ai_summary_classify_id) AS ai_summary_classify_id FROM (
+			SELECT a.ai_summary_classify_id FROM ai_summary_classify AS a 
+			WHERE a.ai_summary_classify_id=?
+			UNION ALL
+			SELECT a.ai_summary_classify_id FROM ai_summary_classify AS a 
+			WHERE a.parent_id=? UNION ALL
+	SELECT
+		ai_summary_classify_id 
+	FROM
+		ai_summary_classify 
+WHERE
+	parent_id IN ( SELECT ai_summary_classify_id FROM ai_summary_classify WHERE parent_id = ? )
+			)AS t`
+	err = o.Raw(sql, aiSummaryClassify, aiSummaryClassify, aiSummaryClassify).QueryRow(&aiSummaryClassifyIds)
+	return
+}
+
+func GetAiSummaryAllParentByClassifyId(aiSummaryClassifyId int) (ids string, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+	GROUP_CONCAT(DISTINCT m.ai_summary_classify_id  ORDER BY m.level) AS ids 
+FROM
+	(
+	SELECT
+		@id AS _id,(
+		SELECT
+			@id := parent_id 
+		FROM
+			ai_summary_classify 
+		WHERE
+			ai_summary_classify_id = _id 
+		) 
+	FROM
+		(
+		SELECT
+			@id :=(
+			SELECT
+				parent_id 
+			FROM
+				ai_summary_classify 
+			WHERE
+				ai_summary_classify_id = ? 
+			)) vm,
+		ai_summary_classify m 
+	WHERE
+		@id IS NOT NULL 
+	) vm
+	INNER JOIN ai_summary_classify m 
+WHERE
+	ai_summary_classify_id = vm._id `
+	err = o.Raw(sql, aiSummaryClassifyId).QueryRow(&ids)
+	return
+}
+
+type AiSummaryListResp struct {
+	Paging *paging.PagingItem
+	List   []*AiSummaryItems
+}
+
+// GetAiSummaryClassifyAll
+func GetAiSummaryClassifyAll() (items []*AiSummaryClassifyItems, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM ai_summary_classify WHERE parent_id<>0 order by sort asc,ai_summary_classify_id asc`
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+

+ 4 - 0
models/db.go

@@ -1,6 +1,7 @@
 package models
 
 import (
+	"eta/eta_api/models/ai_summary"
 	"eta/eta_api/models/aimod"
 	"eta/eta_api/models/company"
 	"eta/eta_api/models/data_manage"
@@ -534,6 +535,9 @@ func initAi() {
 		new(aimod.AiChatTopic),
 		new(aimod.AiChat),
 		new(aimod.FileUploadRecord),
+		new(ai_summary.AiSummaryClassify),
+		new(ai_summary.AiSummary),
+		new(ai_summary.AiPrompt),
 	)
 }
 

+ 171 - 0
routers/commentsRouter.go

@@ -16,6 +16,177 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"],
+        beego.ControllerComments{
+            Method: "AddPrompt",
+            Router: `/prompt/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"],
+        beego.ControllerComments{
+            Method: "DeletePrompt",
+            Router: `/prompt/delete`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"],
+        beego.ControllerComments{
+            Method: "DetailPrompt",
+            Router: `/prompt/detail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"],
+        beego.ControllerComments{
+            Method: "EditPrompt",
+            Router: `/prompt/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"],
+        beego.ControllerComments{
+            Method: "PromptGroupList",
+            Router: `/prompt/groups`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"],
+        beego.ControllerComments{
+            Method: "AiPromptList",
+            Router: `/prompt/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"],
+        beego.ControllerComments{
+            Method: "MoveAiPrompt",
+            Router: `/prompt/move`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"],
+        beego.ControllerComments{
+            Method: "SharePrompt",
+            Router: `/prompt/share`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"],
+        beego.ControllerComments{
+            Method: "AddAiSummary",
+            Router: `/summary/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"],
+        beego.ControllerComments{
+            Method: "AddAiSummaryClassify",
+            Router: `/summary/classify/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"],
+        beego.ControllerComments{
+            Method: "DeleteAiSummaryClassify",
+            Router: `/summary/classify/delete`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"],
+        beego.ControllerComments{
+            Method: "DeleteSandboxClassifyCheck",
+            Router: `/summary/classify/delete/check`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"],
+        beego.ControllerComments{
+            Method: "EditAiSummaryClassify",
+            Router: `/summary/classify/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"],
+        beego.ControllerComments{
+            Method: "AiSummaryClassifyItems",
+            Router: `/summary/classify/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"],
+        beego.ControllerComments{
+            Method: "AiSummaryClassifyMove",
+            Router: `/summary/classify/move`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"],
+        beego.ControllerComments{
+            Method: "AiSummaryClassifyList",
+            Router: `/summary/classifyList`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"],
+        beego.ControllerComments{
+            Method: "AiSummaryDetail",
+            Router: `/summary/detail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"],
+        beego.ControllerComments{
+            Method: "GenerateAiSummary",
+            Router: `/summary/generate`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"],
+        beego.ControllerComments{
+            Method: "AiSummaryList",
+            Router: `/summary/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/ai:AiController"],
         beego.ControllerComments{
             Method: "TopicDelete",

+ 184 - 0
services/ai_summary/ai_summary.go

@@ -0,0 +1,184 @@
+package ai_summary
+
+import (
+	"errors"
+	"eta/eta_api/models/ai_summary"
+	"eta/eta_api/models/system"
+	"eta/eta_api/utils"
+	"strconv"
+)
+
+// GetAiSummaryClassifyListForMe 获取我创建的纪要
+func GetAiSummaryClassifyListForMe(adminInfo system.Admin, resp *ai_summary.AiSummaryClassifyListResp, ai_summaryClassifyId int) (errMsg string, err error) {
+	rootList, err := ai_summary.GetAiSummaryClassifyByParentId(ai_summaryClassifyId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		errMsg = "获取失败"
+		return
+	}
+
+	for k := range rootList {
+		rootList[k].UniqueCode = strconv.Itoa(rootList[k].AiSummaryClassifyId) + "_" + strconv.Itoa(rootList[k].AiSummaryId)
+	}
+
+	classifyAll, err := ai_summary.GetAiSummaryClassifyByParentId(ai_summaryClassifyId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		errMsg = "获取失败"
+		return
+	}
+
+	for k := range classifyAll {
+		classifyAll[k].UniqueCode = strconv.Itoa(classifyAll[k].AiSummaryClassifyId) + "_" + strconv.Itoa(classifyAll[k].AiSummaryId)
+	}
+
+	ai_summaryAll, err := ai_summary.GetAiSummaryInfoByAdminId(adminInfo.AdminId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		errMsg = "获取失败"
+		return
+	}
+
+	for k := range ai_summaryAll {
+		ai_summaryAll[k].UniqueCode = strconv.Itoa(ai_summaryAll[k].AiSummaryClassifyId) + "_" + strconv.Itoa(ai_summaryAll[k].AiSummaryId)
+	}
+
+	sandListMap := make(map[int][]*ai_summary.AiSummaryClassifyItems)
+	for _, v := range ai_summaryAll {
+		if _, ok := sandListMap[v.AiSummaryClassifyId]; !ok {
+			list := make([]*ai_summary.AiSummaryClassifyItems, 0)
+			list = append(list, v)
+			sandListMap[v.AiSummaryClassifyId] = list
+		} else {
+			sandListMap[v.AiSummaryClassifyId] = append(sandListMap[v.AiSummaryClassifyId], v)
+		}
+	}
+
+	nodeAll := make([]*ai_summary.AiSummaryClassifyItems, 0)
+	for k := range rootList {
+		rootNode := rootList[k]
+		AiSummaryClassifyItemsMakeTree(&adminInfo, classifyAll, rootNode)
+		nodeAll = append(nodeAll, rootNode)
+	}
+
+	newAll := AiSummaryItemsMakeTree(nodeAll, sandListMap, ai_summaryClassifyId)
+	resp.AllNodes = newAll
+
+	return
+}
+
+func aiSummaryClassifyHaveChild(allNode []*ai_summary.AiSummaryClassifyItems, node *ai_summary.AiSummaryClassifyItems) (childs []*ai_summary.AiSummaryClassifyItems, yes bool) {
+	for _, v := range allNode {
+		if v.ParentId == node.AiSummaryClassifyId {
+			childs = append(childs, v)
+		}
+	}
+	if len(childs) > 0 {
+		yes = true
+	}
+	return
+}
+
+func AiSummaryClassifyItemsMakeTree(sysUser *system.Admin, allNode []*ai_summary.AiSummaryClassifyItems, node *ai_summary.AiSummaryClassifyItems) {
+
+	childs, _ := aiSummaryClassifyHaveChild(allNode, node) //判断节点是否有子节点并返回
+	if len(childs) > 0 {
+
+		node.Children = append(node.Children, childs[0:]...) //添加子节点
+		for _, v := range childs {                           //查询子节点的子节点,并添加到子节点
+			_, has := aiSummaryClassifyHaveChild(allNode, v)
+			if has {
+				AiSummaryClassifyItemsMakeTree(sysUser, allNode, v) //递归添加节点
+			} else {
+				childrenArr := make([]*ai_summary.AiSummaryClassifyItems, 0)
+				v.Children = childrenArr
+			}
+		}
+	} else {
+		childrenArr := make([]*ai_summary.AiSummaryClassifyItems, 0)
+		node.Children = childrenArr
+	}
+}
+
+func AiSummaryItemsMakeTree(allNode []*ai_summary.AiSummaryClassifyItems, sandListMap map[int][]*ai_summary.AiSummaryClassifyItems, sandboxClassifyId int) (nodeAll []*ai_summary.AiSummaryClassifyItems) {
+	for k := range allNode {
+		if len(allNode[k].Children) > 0 {
+			AiSummaryItemsMakeTree(allNode[k].Children, sandListMap, sandboxClassifyId)
+			allNode = append(allNode, sandListMap[allNode[k].ParentId]...)
+			nodeAll = allNode
+		} else if k == len(allNode)-1 {
+			allNode = append(allNode, sandListMap[allNode[k].ParentId]...)
+			nodeAll = allNode
+		}
+	}
+	if len(allNode) == 0 {
+		nodeAll = append(nodeAll, sandListMap[sandboxClassifyId]...)
+	}
+	return
+}
+
+func AiSummaryClassifyItemsMakeTreeV2(sysUser *system.Admin, allNode []*ai_summary.AiSummaryClassifyItems, node *ai_summary.AiSummaryClassifyItems) {
+
+	childs, _ := aiSummaryClassifyHaveChildV2(allNode, node) //判断节点是否有子节点并返回
+	if len(childs) > 0 {
+
+		node.Children = append(node.Children, childs[0:]...) //添加子节点
+		for _, v := range childs {                           //查询子节点的子节点,并添加到子节点
+			_, has := aiSummaryClassifyHaveChildV2(allNode, v)
+			if has {
+				AiSummaryClassifyItemsMakeTreeV2(sysUser, allNode, v) //递归添加节点
+			} else {
+				//childrenArr := make([]*ai_summary.AiSummaryClassifyItems, 0)
+				//v.Children = childrenArr
+			}
+		}
+	} else {
+		//childrenArr := make([]*ai_summary.AiSummaryClassifyItems, 0)
+		//node.Children = childrenArr
+	}
+}
+
+func aiSummaryClassifyHaveChildV2(allNode []*ai_summary.AiSummaryClassifyItems, node *ai_summary.AiSummaryClassifyItems) (childs []*ai_summary.AiSummaryClassifyItems, yes bool) {
+	for _, v := range allNode {
+		if v.ParentId == node.AiSummaryClassifyId && node.AiSummaryId == 0 {
+			childs = append(childs, v)
+		}
+	}
+	if len(childs) > 0 {
+		yes = true
+	}
+	return
+}
+
+// SharePrompt
+func SharePrompt(promptId int, adminId int) (err error) {
+	//判断当前登录者是否有共享的权限
+	prompt, err := ai_summary.GetAiPromptById(promptId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			err = errors.New("当前目录下的提示词不存在")
+			return
+		}
+		err = errors.New("目录下的提示词查询出错:" + err.Error())
+		return
+	}
+	if prompt.SysAdminId != adminId {
+		err = errors.New("该提示词不是本人创建")
+		return
+	}
+
+	//判断当前的共享状态
+	if prompt.IsShare > 0 {
+		prompt.IsShare = 0
+		err = prompt.Update([]string{"IsShare"})
+		if err != nil {
+			err = errors.New(err.Error())
+			return
+		}
+	} else {
+		prompt.IsShare = 1
+		err = prompt.Update([]string{"IsShare"})
+		if err != nil {
+			err = errors.New(err.Error())
+			return
+		}
+	}
+	return
+}