mirror of
				https://github.com/yangjian102621/geekai.git
				synced 2025-11-04 16:23:42 +08:00 
			
		
		
		
	markmap enable to select ai model
This commit is contained in:
		@@ -218,6 +218,7 @@ func needLogin(c *gin.Context) bool {
 | 
			
		||||
		c.Request.URL.Path == "/api/config/get" ||
 | 
			
		||||
		c.Request.URL.Path == "/api/product/list" ||
 | 
			
		||||
		c.Request.URL.Path == "/api/menu/list" ||
 | 
			
		||||
		c.Request.URL.Path == "/api/markMap/model" ||
 | 
			
		||||
		strings.HasPrefix(c.Request.URL.Path, "/api/test") ||
 | 
			
		||||
		strings.HasPrefix(c.Request.URL.Path, "/api/function/") ||
 | 
			
		||||
		strings.HasPrefix(c.Request.URL.Path, "/api/sms/") ||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										48
									
								
								api/handler/markmap_handler.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								api/handler/markmap_handler.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
package handler
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"chatplus/core"
 | 
			
		||||
	"chatplus/core/types"
 | 
			
		||||
	"chatplus/store/model"
 | 
			
		||||
	"chatplus/store/vo"
 | 
			
		||||
	"chatplus/utils"
 | 
			
		||||
	"chatplus/utils/resp"
 | 
			
		||||
 | 
			
		||||
	"github.com/gin-gonic/gin"
 | 
			
		||||
	"gorm.io/gorm"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// MarkMapHandler 生成思维导图
 | 
			
		||||
type MarkMapHandler struct {
 | 
			
		||||
	BaseHandler
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewMarkMapHandler(app *core.AppServer, db *gorm.DB) *MarkMapHandler {
 | 
			
		||||
	return &MarkMapHandler{BaseHandler: BaseHandler{App: app, DB: db}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetModel get the chat model for generating Markdown text
 | 
			
		||||
func (h *MarkMapHandler) GetModel(c *gin.Context) {
 | 
			
		||||
	modelId := h.App.SysConfig.XMindModelId
 | 
			
		||||
	session := h.DB.Session(&gorm.Session{}).Where("enabled", true)
 | 
			
		||||
	if modelId > 0 {
 | 
			
		||||
		session = session.Where("id", modelId)
 | 
			
		||||
	} else {
 | 
			
		||||
		session = session.Where("platform", types.OpenAI)
 | 
			
		||||
	}
 | 
			
		||||
	var chatModel model.ChatModel
 | 
			
		||||
	res := session.First(&chatModel)
 | 
			
		||||
	if res.Error != nil {
 | 
			
		||||
		resp.ERROR(c, "No available AI model")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var modelVo vo.ChatModel
 | 
			
		||||
	err := utils.CopyObject(chatModel, &modelVo)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		resp.ERROR(c, "error with copy object: "+err.Error())
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resp.SUCCESS(c, modelVo)
 | 
			
		||||
}
 | 
			
		||||
@@ -436,6 +436,11 @@ func main() {
 | 
			
		||||
			group := s.Engine.Group("/api/menu/")
 | 
			
		||||
			group.GET("list", h.List)
 | 
			
		||||
		}),
 | 
			
		||||
		fx.Provide(handler.NewMarkMapHandler),
 | 
			
		||||
		fx.Invoke(func(s *core.AppServer, h *handler.MarkMapHandler) {
 | 
			
		||||
			group := s.Engine.Group("/api/markMap/")
 | 
			
		||||
			group.GET("model", h.GetModel)
 | 
			
		||||
		}),
 | 
			
		||||
		fx.Invoke(func(s *core.AppServer, db *gorm.DB) {
 | 
			
		||||
			go func() {
 | 
			
		||||
				err := s.Run(db)
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@
 | 
			
		||||
          <h2>思维导图创作中心</h2>
 | 
			
		||||
 | 
			
		||||
          <div class="mark-map-params" :style="{ height: leftBoxHeight + 'px' }">
 | 
			
		||||
            <el-form :model="params" label-width="80px" label-position="left">
 | 
			
		||||
            <el-form label-width="80px" label-position="left">
 | 
			
		||||
              <div class="param-line">
 | 
			
		||||
                你的需求?
 | 
			
		||||
              </div>
 | 
			
		||||
@@ -20,7 +20,31 @@
 | 
			
		||||
              </div>
 | 
			
		||||
 | 
			
		||||
              <div class="param-line">
 | 
			
		||||
                <el-button color="#47fff1" :dark="false" round @click="generate">智能生成思维导图</el-button>
 | 
			
		||||
                请选择生成思维导图的AI模型
 | 
			
		||||
              </div>
 | 
			
		||||
              <div class="param-line">
 | 
			
		||||
                <el-select v-model="modelID" placeholder="请选择模型">
 | 
			
		||||
                  <el-option
 | 
			
		||||
                      v-for="item in models"
 | 
			
		||||
                      :key="item.id"
 | 
			
		||||
                      :label="item.name"
 | 
			
		||||
                      :value="item.id"
 | 
			
		||||
                  >
 | 
			
		||||
                    <span>{{ item.name }}</span>
 | 
			
		||||
                    <el-tag style="margin-left: 5px; position: relative; top:-2px" type="info" size="small">{{
 | 
			
		||||
                        item.power
 | 
			
		||||
                      }}算力
 | 
			
		||||
                    </el-tag>
 | 
			
		||||
                  </el-option>
 | 
			
		||||
                </el-select>
 | 
			
		||||
              </div>
 | 
			
		||||
 | 
			
		||||
              <div class="text-info">
 | 
			
		||||
                <el-tag type="success">当前可用算力:{{ power }}</el-tag>
 | 
			
		||||
              </div>
 | 
			
		||||
 | 
			
		||||
              <div class="param-line">
 | 
			
		||||
                <el-button color="#47fff1" :dark="false" round @click="generateAI">智能生成思维导图</el-button>
 | 
			
		||||
              </div>
 | 
			
		||||
 | 
			
		||||
              <div class="param-line">
 | 
			
		||||
@@ -28,7 +52,7 @@
 | 
			
		||||
              </div>
 | 
			
		||||
              <div class="param-line">
 | 
			
		||||
                <el-input
 | 
			
		||||
                    v-model="prompt"
 | 
			
		||||
                    v-model="text"
 | 
			
		||||
                    :autosize="{ minRows: 4, maxRows: 6 }"
 | 
			
		||||
                    type="textarea"
 | 
			
		||||
                    placeholder="请用markdown语法输入您想要生成思维导图的内容!"
 | 
			
		||||
@@ -39,18 +63,6 @@
 | 
			
		||||
                <el-button color="#47fff1" :dark="false" round @click="generate">直接生成(免费)</el-button>
 | 
			
		||||
              </div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
              <div class="text-info">
 | 
			
		||||
               <el-row :gutter="10">
 | 
			
		||||
                 <el-col :span="12">
 | 
			
		||||
                   <el-tag>每次生成消耗1算力</el-tag>
 | 
			
		||||
                 </el-col>
 | 
			
		||||
                 <el-col :span="12">
 | 
			
		||||
                   <el-tag type="success">当前可用算力:{{ power }}</el-tag>
 | 
			
		||||
                 </el-col>
 | 
			
		||||
               </el-row>
 | 
			
		||||
              </div>
 | 
			
		||||
 | 
			
		||||
            </el-form>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
@@ -58,7 +70,7 @@
 | 
			
		||||
        <div class="right-box">
 | 
			
		||||
          <h2>思维导图</h2>
 | 
			
		||||
          <div class="body">
 | 
			
		||||
            <svg ref="svgRef" :style="{ height: leftBoxHeight + 'px' }"/>
 | 
			
		||||
            <svg ref="svgRef" :style="{ height: rightBoxHeight + 'px' }"/>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div><!-- end task list box -->
 | 
			
		||||
      </div>
 | 
			
		||||
@@ -71,13 +83,16 @@
 | 
			
		||||
 | 
			
		||||
<script setup>
 | 
			
		||||
import LoginDialog from "@/components/LoginDialog.vue";
 | 
			
		||||
import {ref, onMounted, onUpdated} from 'vue';
 | 
			
		||||
import {onMounted, onUpdated, ref} from 'vue';
 | 
			
		||||
import {Markmap} from 'markmap-view';
 | 
			
		||||
import {loadJS, loadCSS} from 'markmap-common';
 | 
			
		||||
import {loadCSS, loadJS} from 'markmap-common';
 | 
			
		||||
import {Transformer} from 'markmap-lib';
 | 
			
		||||
import {checkSession} from "@/action/session";
 | 
			
		||||
import {httpGet} from "@/utils/http";
 | 
			
		||||
import {ElMessage} from "element-plus";
 | 
			
		||||
 | 
			
		||||
const leftBoxHeight = ref(window.innerHeight - 105)
 | 
			
		||||
const rightBoxHeight = ref(window.innerHeight - 105)
 | 
			
		||||
const rightBoxHeight = ref(window.innerHeight - 85)
 | 
			
		||||
 | 
			
		||||
const prompt = ref("")
 | 
			
		||||
const text = ref(`# Geek-AI 助手
 | 
			
		||||
@@ -102,12 +117,33 @@ loadJS(scripts);
 | 
			
		||||
 | 
			
		||||
const svgRef = ref(null)
 | 
			
		||||
const markMap = ref(null)
 | 
			
		||||
const models = ref([])
 | 
			
		||||
const modelID = ref(0)
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  initData()
 | 
			
		||||
  markMap.value = Markmap.create(svgRef.value)
 | 
			
		||||
  update()
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const initData = () => {
 | 
			
		||||
  checkSession().then(user => {
 | 
			
		||||
    power.value = user['power']
 | 
			
		||||
    isLogin.value = true
 | 
			
		||||
  }).catch(() => {
 | 
			
		||||
  });
 | 
			
		||||
  httpGet("/api/model/list").then(res => {
 | 
			
		||||
    for (let v of res.data) {
 | 
			
		||||
      if (v.platform === "OpenAI") {
 | 
			
		||||
        models.value.push(v)
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    modelID.value = models.value[0].id
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error("获取模型失败:" + e.message)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const update = () => {
 | 
			
		||||
  const {root} = transformer.transform(text.value)
 | 
			
		||||
  markMap.value.setData(root)
 | 
			
		||||
@@ -118,6 +154,19 @@ onUpdated(update)
 | 
			
		||||
 | 
			
		||||
window.onresize = () => {
 | 
			
		||||
  leftBoxHeight.value = window.innerHeight - 145
 | 
			
		||||
  rightBoxHeight.value = window.innerHeight - 85
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const generate = () => {
 | 
			
		||||
  update()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 使用 AI 智能生成
 | 
			
		||||
const generateAI = () => {
 | 
			
		||||
  if (!isLogin.value) {
 | 
			
		||||
    showLoginDialog.value = true
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
</script>
 | 
			
		||||
 
 | 
			
		||||
@@ -275,8 +275,8 @@ const activeName = ref('basic')
 | 
			
		||||
const system = ref({models: []})
 | 
			
		||||
const loading = ref(true)
 | 
			
		||||
const systemFormRef = ref(null)
 | 
			
		||||
const chatFormRef = ref(null)
 | 
			
		||||
const models = ref([])
 | 
			
		||||
const openAIModels = ref([])
 | 
			
		||||
const notice = ref("")
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
@@ -295,6 +295,7 @@ onMounted(() => {
 | 
			
		||||
 | 
			
		||||
  httpGet('/api/admin/model/list').then(res => {
 | 
			
		||||
    models.value = res.data
 | 
			
		||||
    openAIModels.value = models.value.filter(v => v.platform === "OpenAI")
 | 
			
		||||
    loading.value = false
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error("获取模型失败:" + e.message)
 | 
			
		||||
@@ -320,19 +321,6 @@ const save = function (key) {
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
  } else if (key === 'chat') {
 | 
			
		||||
    if (chat.value.context_deep % 2 !== 0) {
 | 
			
		||||
      return ElMessage.error("会话上下文深度必须为偶数!")
 | 
			
		||||
    }
 | 
			
		||||
    chatFormRef.value.validate((valid) => {
 | 
			
		||||
      if (valid) {
 | 
			
		||||
        httpPost('/api/admin/config/update', {key: key, config: chat.value}).then(() => {
 | 
			
		||||
          ElMessage.success("操作成功!")
 | 
			
		||||
        }).catch(e => {
 | 
			
		||||
          ElMessage.error("操作失败:" + e.message)
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
  } else if (key === 'notice') {
 | 
			
		||||
    httpPost('/api/admin/config/update', {key: key, config: {content: notice.value, updated: true}}).then(() => {
 | 
			
		||||
      ElMessage.success("操作成功!")
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user