mirror of
				https://github.com/yangjian102621/geekai.git
				synced 2025-11-04 16:23:42 +08:00 
			
		
		
		
	feat: function add for admin page is ready
This commit is contained in:
		@@ -32,46 +32,21 @@ const (
 | 
			
		||||
var InnerFunctions = []Function{
 | 
			
		||||
	{
 | 
			
		||||
		Name:        FuncZaoBao,
 | 
			
		||||
		Description: "每日早报,获取当天全球的热门新闻事件列表",
 | 
			
		||||
		Description: "每日早报,获取当天新闻事件列表",
 | 
			
		||||
		Parameters: Parameters{
 | 
			
		||||
 | 
			
		||||
			Type: "object",
 | 
			
		||||
			Properties: map[string]Property{
 | 
			
		||||
				"text": {
 | 
			
		||||
					Type:        "string",
 | 
			
		||||
					Description: "",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Required: []string{},
 | 
			
		||||
			Type:       "object",
 | 
			
		||||
			Properties: map[string]Property{},
 | 
			
		||||
			Required:   []string{},
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		Name:        FuncWeibo,
 | 
			
		||||
		Description: "新浪微博热搜榜,微博当日热搜榜单",
 | 
			
		||||
		Parameters: Parameters{
 | 
			
		||||
			Type: "object",
 | 
			
		||||
			Properties: map[string]Property{
 | 
			
		||||
				"text": {
 | 
			
		||||
					Type:        "string",
 | 
			
		||||
					Description: "",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Required: []string{},
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
		Name:        FuncHeadLine,
 | 
			
		||||
		Description: "今日头条,给用户推荐当天的头条新闻,周榜热文",
 | 
			
		||||
		Parameters: Parameters{
 | 
			
		||||
			Type: "object",
 | 
			
		||||
			Properties: map[string]Property{
 | 
			
		||||
				"text": {
 | 
			
		||||
					Type:        "string",
 | 
			
		||||
					Description: "",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Required: []string{},
 | 
			
		||||
			Type:       "object",
 | 
			
		||||
			Properties: map[string]Property{},
 | 
			
		||||
			Required:   []string{},
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@ import (
 | 
			
		||||
	"chatplus/store/vo"
 | 
			
		||||
	"chatplus/utils"
 | 
			
		||||
	"chatplus/utils/resp"
 | 
			
		||||
 | 
			
		||||
	"github.com/gin-gonic/gin"
 | 
			
		||||
	"gorm.io/gorm"
 | 
			
		||||
)
 | 
			
		||||
@@ -33,22 +34,64 @@ func (h *FunctionHandler) Save(c *gin.Context) {
 | 
			
		||||
	var f = model.Function{
 | 
			
		||||
		Id:          data.Id,
 | 
			
		||||
		Name:        data.Name,
 | 
			
		||||
		Label:       data.Label,
 | 
			
		||||
		Description: data.Description,
 | 
			
		||||
		Parameters:  utils.JsonEncode(data.Parameters),
 | 
			
		||||
		Required:    utils.JsonEncode(data.Required),
 | 
			
		||||
		Action:      data.Action,
 | 
			
		||||
		Enabled:     false,
 | 
			
		||||
		Token:       data.Token,
 | 
			
		||||
		Enabled:     data.Enabled,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	logger.Info(f)
 | 
			
		||||
	res := h.db.Save(&f)
 | 
			
		||||
	if res.Error != nil {
 | 
			
		||||
		resp.ERROR(c, "error with save data:"+res.Error.Error())
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	data.Id = f.Id
 | 
			
		||||
	resp.SUCCESS(c, data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *FunctionHandler) List(c *gin.Context) {
 | 
			
		||||
func (h *FunctionHandler) Set(c *gin.Context) {
 | 
			
		||||
	var data struct {
 | 
			
		||||
		Id    uint        `json:"id"`
 | 
			
		||||
		Filed string      `json:"filed"`
 | 
			
		||||
		Value interface{} `json:"value"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := c.ShouldBindJSON(&data); err != nil {
 | 
			
		||||
		resp.ERROR(c, types.InvalidArgs)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res := h.db.Model(&model.Function{}).Where("id = ?", data.Id).Update(data.Filed, data.Value)
 | 
			
		||||
	if res.Error != nil {
 | 
			
		||||
		resp.ERROR(c, "更新数据库失败!")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	resp.SUCCESS(c)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *FunctionHandler) List(c *gin.Context) {
 | 
			
		||||
	var items []model.Function
 | 
			
		||||
	res := h.db.Find(&items)
 | 
			
		||||
	if res.Error != nil {
 | 
			
		||||
		resp.ERROR(c, "No data found")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	functions := make([]vo.Function, 0)
 | 
			
		||||
	for _, v := range items {
 | 
			
		||||
		var f vo.Function
 | 
			
		||||
		err := utils.CopyObject(v, &f)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		functions = append(functions, f)
 | 
			
		||||
	}
 | 
			
		||||
	resp.SUCCESS(c, functions)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *FunctionHandler) Remove(c *gin.Context) {
 | 
			
		||||
	id := h.GetInt(c, "id", 0)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,6 @@ import (
 | 
			
		||||
	"chatplus/store"
 | 
			
		||||
	"context"
 | 
			
		||||
	"embed"
 | 
			
		||||
	"github.com/go-redis/redis/v8"
 | 
			
		||||
	"io"
 | 
			
		||||
	"log"
 | 
			
		||||
	"os"
 | 
			
		||||
@@ -26,6 +25,8 @@ import (
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/go-redis/redis/v8"
 | 
			
		||||
 | 
			
		||||
	"github.com/lionsoul2014/ip2region/binding/golang/xdb"
 | 
			
		||||
	"go.uber.org/fx"
 | 
			
		||||
	"gorm.io/gorm"
 | 
			
		||||
@@ -351,6 +352,7 @@ func main() {
 | 
			
		||||
		fx.Invoke(func(s *core.AppServer, h *admin.FunctionHandler) {
 | 
			
		||||
			group := s.Engine.Group("/api/admin/function/")
 | 
			
		||||
			group.POST("save", h.Save)
 | 
			
		||||
			group.POST("set", h.Set)
 | 
			
		||||
			group.GET("list", h.List)
 | 
			
		||||
			group.GET("remove", h.Remove)
 | 
			
		||||
		}),
 | 
			
		||||
 
 | 
			
		||||
@@ -8,5 +8,6 @@ type Function struct {
 | 
			
		||||
	Parameters  string
 | 
			
		||||
	Required    string
 | 
			
		||||
	Action      string
 | 
			
		||||
	Token       string
 | 
			
		||||
	Enabled     bool
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,9 +14,11 @@ type Property struct {
 | 
			
		||||
type Function struct {
 | 
			
		||||
	Id          uint       `json:"id"`
 | 
			
		||||
	Name        string     `json:"name"`
 | 
			
		||||
	Label       string     `json:"label"`
 | 
			
		||||
	Description string     `json:"description"`
 | 
			
		||||
	Parameters  Parameters `json:"parameters"`
 | 
			
		||||
	Required    []string   `json:"required"`
 | 
			
		||||
	Action      string     `json:"action"`
 | 
			
		||||
	Token       string     `json:"token"`
 | 
			
		||||
	Enabled     bool       `json:"enabled"`
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -21,4 +21,6 @@ ALTER TABLE `chatgpt_functions` ADD `enabled` TINYINT(1) NOT NULL DEFAULT '0' CO
 | 
			
		||||
ALTER TABLE `chatgpt_functions` ADD `label` VARCHAR(30) NULL COMMENT '函数标签' AFTER `name`;
 | 
			
		||||
 | 
			
		||||
ALTER TABLE `chatgpt_mj_jobs` ADD `use_proxy` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '是否使用反代' AFTER `progress`;
 | 
			
		||||
ALTER TABLE `chatgpt_mj_jobs` CHANGE `img_url` `img_url` VARCHAR(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '图片URL';
 | 
			
		||||
ALTER TABLE `chatgpt_mj_jobs` CHANGE `img_url` `img_url` VARCHAR(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '图片URL';
 | 
			
		||||
 | 
			
		||||
ALTER TABLE `chatgpt_functions` ADD `token` VARCHAR(255) NULL COMMENT 'API授权token' AFTER `action`;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="container role-list" v-loading="loading">
 | 
			
		||||
    <div class="handle-box">
 | 
			
		||||
      <el-button type="primary" :icon="Plus" @click="addRole">新增</el-button>
 | 
			
		||||
      <el-button type="primary" :icon="Plus" @click="addRow">新增</el-button>
 | 
			
		||||
    </div>
 | 
			
		||||
    <el-row>
 | 
			
		||||
      <el-table :data="tableData" :border="parentBorder" style="width: 100%">
 | 
			
		||||
@@ -10,10 +10,11 @@
 | 
			
		||||
            <span class="sort" :data-id="scope.row.id">{{ scope.row.name }}</span>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column label="函数别名" prop="label"/>
 | 
			
		||||
        <el-table-column label="功能描述" prop="description"/>
 | 
			
		||||
        <el-table-column label="启用状态">
 | 
			
		||||
          <template #default="scope">
 | 
			
		||||
            <el-switch v-model="scope.row.enabled" @change="functionSet(scope.row)"/>
 | 
			
		||||
            <el-switch v-model="scope.row.enabled" @change="functionSet('enabled',scope.row)"/>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
 | 
			
		||||
@@ -39,6 +40,7 @@
 | 
			
		||||
        <el-form-item label="函数名称:" prop="name">
 | 
			
		||||
          <el-input
 | 
			
		||||
              v-model="item.name"
 | 
			
		||||
              placeholder="函数名称最好为英文"
 | 
			
		||||
              autocomplete="off"
 | 
			
		||||
          />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
@@ -113,6 +115,19 @@
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
 | 
			
		||||
        <el-form-item label="API 地址:" prop="action">
 | 
			
		||||
          <el-input
 | 
			
		||||
              v-model="item.action"
 | 
			
		||||
              autocomplete="off"
 | 
			
		||||
          />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
 | 
			
		||||
        <el-form-item label="API Token:" prop="token">
 | 
			
		||||
          <el-input
 | 
			
		||||
              v-model="item.token"
 | 
			
		||||
              autocomplete="off"
 | 
			
		||||
          />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="启用状态">
 | 
			
		||||
          <el-switch v-model="item.enabled"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
@@ -130,21 +145,19 @@
 | 
			
		||||
 | 
			
		||||
<script setup>
 | 
			
		||||
 | 
			
		||||
import {Delete, Plus, RemoveFilled} from "@element-plus/icons-vue";
 | 
			
		||||
import {Delete, Plus} from "@element-plus/icons-vue";
 | 
			
		||||
import {onMounted, reactive, ref} from "vue";
 | 
			
		||||
import {httpGet, httpPost} from "@/utils/http";
 | 
			
		||||
import {ElMessage} from "element-plus";
 | 
			
		||||
import {copyObj, removeArrayItem} from "@/utils/libs";
 | 
			
		||||
import {Sortable} from "sortablejs"
 | 
			
		||||
import {arrayContains, copyObj} from "@/utils/libs";
 | 
			
		||||
 | 
			
		||||
const showDialog = ref(false)
 | 
			
		||||
const parentBorder = ref(true)
 | 
			
		||||
const childBorder = ref(true)
 | 
			
		||||
const tableData = ref([])
 | 
			
		||||
const item = ref({parameters: []})
 | 
			
		||||
const item = ref({})
 | 
			
		||||
const params = ref([])
 | 
			
		||||
const formRef = ref(null)
 | 
			
		||||
const editRow = ref({})
 | 
			
		||||
const loading = ref(true)
 | 
			
		||||
const title = ref("新增函数")
 | 
			
		||||
 | 
			
		||||
@@ -176,11 +189,24 @@ const curIndex = ref(0)
 | 
			
		||||
const rowEdit = function (index, row) {
 | 
			
		||||
  curIndex.value = index
 | 
			
		||||
  item.value = copyObj(row)
 | 
			
		||||
  // initialize parameters
 | 
			
		||||
  const props = item.value?.parameters?.properties
 | 
			
		||||
  const required = item.value?.parameters?.required
 | 
			
		||||
  const _params = []
 | 
			
		||||
  for (let key in props) {
 | 
			
		||||
    _params.push({
 | 
			
		||||
      name: key,
 | 
			
		||||
      type: props[key].type,
 | 
			
		||||
      desc: props[key].description,
 | 
			
		||||
      required: arrayContains(required, key)
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
  params.value = _params
 | 
			
		||||
  showDialog.value = true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const addRole = function () {
 | 
			
		||||
  item.value = {parameters: []}
 | 
			
		||||
const addRow = function () {
 | 
			
		||||
  item.value = {enabled:true}
 | 
			
		||||
  showDialog.value = true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -233,8 +259,12 @@ const removeParam = function (index) {
 | 
			
		||||
  params.value.splice(index, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const functionSet = (row) => {
 | 
			
		||||
 | 
			
		||||
const functionSet = (filed,row) => {
 | 
			
		||||
  httpPost('/api/admin/function/set', {id: row.id, filed: filed, value: row[filed]}).then(() => {
 | 
			
		||||
    ElMessage.success("操作成功!")
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error("操作失败:" + e.message)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
</script>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user