mirror of
				https://github.com/yangjian102621/geekai.git
				synced 2025-11-04 08:13:43 +08:00 
			
		
		
		
	feat: add system config item for wechat qrcode
This commit is contained in:
		@@ -3,7 +3,9 @@
 | 
			
		||||
* 功能优化:恢复关闭注册系统配置项,管理员可以在后台关闭用户注册,只允许内部添加账号
 | 
			
		||||
* 功能优化:兼用旧版本微信收款消息解析
 | 
			
		||||
* 功能优化:优化订单扫码支付状态轮询功能,当关闭二维码时取消轮询,节约网络资源
 | 
			
		||||
* 
 | 
			
		||||
* 功能新增:后台新增配置微信客服二维码,可以上传自己的微信客服二维码
 | 
			
		||||
* 功能新增:新增网站公告,可以在管理后台自定义配置
 | 
			
		||||
* 功能新增:新增阿里通义千问大模型支持
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## v3.2.5
 | 
			
		||||
 
 | 
			
		||||
@@ -195,5 +195,6 @@ type SystemConfig struct {
 | 
			
		||||
	InviteChatCalls  int      `json:"invite_chat_calls"`   // 邀请用户注册奖励对话次数
 | 
			
		||||
	InviteImgCalls   int      `json:"invite_img_calls"`    // 邀请用户注册奖励绘图次数
 | 
			
		||||
 | 
			
		||||
	ShowDemoNotice bool `json:"show_demo_notice"` // 显示演示站公告
 | 
			
		||||
	ShowDemoNotice bool   `json:"show_demo_notice"` // 显示演示站公告
 | 
			
		||||
	WechatCardURL  string `json:"wechat_card_url"`  // 微信客服地址
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,8 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const ErrorMsg = "抱歉,AI 助手开小差了,请稍后再试。"
 | 
			
		||||
const ErrImg = ""
 | 
			
		||||
 | 
			
		||||
var ErrImg = ""
 | 
			
		||||
 | 
			
		||||
var logger = logger2.GetLogger()
 | 
			
		||||
 | 
			
		||||
@@ -45,6 +46,13 @@ func NewChatHandler(app *core.AppServer, db *gorm.DB, redis *redis.Client) *Chat
 | 
			
		||||
	return &h
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *ChatHandler) Init() {
 | 
			
		||||
	// 如果后台有上传微信客服微信二维码,则覆盖
 | 
			
		||||
	if h.App.SysConfig.WechatCardURL != "" {
 | 
			
		||||
		ErrImg = fmt.Sprintf("", h.App.SysConfig.WechatCardURL)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var chatConfig types.ChatConfig
 | 
			
		||||
 | 
			
		||||
// ChatHandle 处理聊天 WebSocket 请求
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								api/main.go
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								api/main.go
									
									
									
									
									
								
							@@ -59,11 +59,13 @@ func main() {
 | 
			
		||||
	}
 | 
			
		||||
	debug, _ := strconv.ParseBool(os.Getenv("APP_DEBUG"))
 | 
			
		||||
	logger.Info("Loading config file: ", configFile)
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if err := recover(); err != nil {
 | 
			
		||||
			logger.Error("Panic Error:", err)
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
	if !debug {
 | 
			
		||||
		defer func() {
 | 
			
		||||
			if err := recover(); err != nil {
 | 
			
		||||
				logger.Error("Panic Error:", err)
 | 
			
		||||
			}
 | 
			
		||||
		}()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	app := fx.New(
 | 
			
		||||
		// 初始化配置应用配置
 | 
			
		||||
@@ -378,7 +380,9 @@ func main() {
 | 
			
		||||
				log.Fatal(err)
 | 
			
		||||
			}
 | 
			
		||||
		}),
 | 
			
		||||
 | 
			
		||||
		fx.Invoke(func(h *chatimpl.ChatHandler) {
 | 
			
		||||
			h.Init()
 | 
			
		||||
		}),
 | 
			
		||||
		// 注册生命周期回调函数
 | 
			
		||||
		fx.Invoke(func(lifecycle fx.Lifecycle, lc *AppLifecycle) {
 | 
			
		||||
			lifecycle.Append(fx.Hook{
 | 
			
		||||
 
 | 
			
		||||
@@ -222,7 +222,7 @@
 | 
			
		||||
      </el-alert>
 | 
			
		||||
 | 
			
		||||
      <div style="text-align: center;padding-top: 10px;">
 | 
			
		||||
        <el-image src="/images/wx.png"/>
 | 
			
		||||
        <el-image :src="wechatCardURL"/>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
 | 
			
		||||
@@ -325,6 +325,7 @@ const textInput = ref(null)
 | 
			
		||||
const showFeedbackDialog = ref(false)
 | 
			
		||||
const showDemoNotice = ref(false)
 | 
			
		||||
const showNoticeKey = ref("SHOW_DEMO_NOTICE_")
 | 
			
		||||
const wechatCardURL = ref("/images/wx.png")
 | 
			
		||||
 | 
			
		||||
if (isMobile()) {
 | 
			
		||||
  router.replace("/mobile")
 | 
			
		||||
@@ -377,6 +378,7 @@ onMounted(() => {
 | 
			
		||||
      if (!show) {
 | 
			
		||||
        showDemoNotice.value = res.data['show_demo_notice']
 | 
			
		||||
      }
 | 
			
		||||
      wechatCardURL.value = res.data['wechat_card_url']
 | 
			
		||||
    }).catch(e => {
 | 
			
		||||
      ElMessage.error("获取系统配置失败:" + e.message)
 | 
			
		||||
    })
 | 
			
		||||
 
 | 
			
		||||
@@ -156,6 +156,10 @@ httpGet("/api/admin/config/get?key=system").then(res => {
 | 
			
		||||
    placeholder.value += ways.join("/")
 | 
			
		||||
    // 是否启用注册
 | 
			
		||||
    enableRegister.value = res.data['enabled_register']
 | 
			
		||||
    // 覆盖微信二维码
 | 
			
		||||
    if (res.data['wechat_card_url'] !== '') {
 | 
			
		||||
      wxImg.value = res.data['wechat_card_url']
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}).catch(e => {
 | 
			
		||||
  ElMessage.error("获取系统配置失败:" + e.message)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,113 +1,40 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="system-config" v-loading="loading">
 | 
			
		||||
    <div class="container">
 | 
			
		||||
      <el-divider content-position="center">基本设置</el-divider>
 | 
			
		||||
      <el-form :model="system" label-width="150px" label-position="right" ref="systemFormRef" :rules="rules">
 | 
			
		||||
        <el-form-item label="网站标题" prop="title">
 | 
			
		||||
          <el-input v-model="system['title']"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="控制台标题" prop="admin_title">
 | 
			
		||||
          <el-input v-model="system['admin_title']"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="注册赠送对话次数" prop="user_init_calls">
 | 
			
		||||
          <el-input v-model.number="system['init_chat_calls']" placeholder="新用户注册赠送对话次数"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="注册赠送绘图次数" prop="init_img_calls">
 | 
			
		||||
          <el-input v-model.number="system['init_img_calls']" placeholder="新用户注册赠送绘图次数"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="邀请赠送对话次数" prop="invite_chat_calls">
 | 
			
		||||
          <el-input v-model.number="system['invite_chat_calls']" placeholder="邀请新用户注册赠送对话次数"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="邀请赠送绘图次数" prop="invite_img_calls">
 | 
			
		||||
          <el-input v-model.number="system['invite_img_calls']" placeholder="邀请新用户注册赠送绘图次数"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="VIP每月对话次数" prop="vip_month_calls">
 | 
			
		||||
          <el-input v-model.number="system['vip_month_calls']" placeholder="VIP用户每月赠送对话次数"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="VIP每月绘图次数" prop="vip_month_img_calls">
 | 
			
		||||
          <el-input v-model.number="system['vip_month_img_calls']" placeholder="VIP用户每月赠送绘图次数"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
 | 
			
		||||
        <el-form-item label="开放注册" prop="enabled_register">
 | 
			
		||||
          <el-switch v-model="system['enabled_register']"/>
 | 
			
		||||
          <el-tooltip
 | 
			
		||||
              effect="dark"
 | 
			
		||||
              content="关闭注册之后只能通过管理后台添加用户"
 | 
			
		||||
              raw-content
 | 
			
		||||
              placement="right"
 | 
			
		||||
          >
 | 
			
		||||
            <el-icon>
 | 
			
		||||
              <InfoFilled/>
 | 
			
		||||
            </el-icon>
 | 
			
		||||
          </el-tooltip>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
    <el-tabs v-model="activeName" class="demo-tabs">
 | 
			
		||||
      <el-tab-pane label="基本设置" name="basic">
 | 
			
		||||
        <div class="container">
 | 
			
		||||
          <el-form :model="system" label-width="150px" label-position="right" ref="systemFormRef" :rules="rules">
 | 
			
		||||
            <el-form-item label="网站标题" prop="title">
 | 
			
		||||
              <el-input v-model="system['title']"/>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="控制台标题" prop="admin_title">
 | 
			
		||||
              <el-input v-model="system['admin_title']"/>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="注册赠送对话次数" prop="user_init_calls">
 | 
			
		||||
              <el-input v-model.number="system['init_chat_calls']" placeholder="新用户注册赠送对话次数"/>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="注册赠送绘图次数" prop="init_img_calls">
 | 
			
		||||
              <el-input v-model.number="system['init_img_calls']" placeholder="新用户注册赠送绘图次数"/>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="邀请赠送对话次数" prop="invite_chat_calls">
 | 
			
		||||
              <el-input v-model.number="system['invite_chat_calls']" placeholder="邀请新用户注册赠送对话次数"/>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="邀请赠送绘图次数" prop="invite_img_calls">
 | 
			
		||||
              <el-input v-model.number="system['invite_img_calls']" placeholder="邀请新用户注册赠送绘图次数"/>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="VIP每月对话次数" prop="vip_month_calls">
 | 
			
		||||
              <el-input v-model.number="system['vip_month_calls']" placeholder="VIP用户每月赠送对话次数"/>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="VIP每月绘图次数" prop="vip_month_img_calls">
 | 
			
		||||
              <el-input v-model.number="system['vip_month_img_calls']" placeholder="VIP用户每月赠送绘图次数"/>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
 | 
			
		||||
        <el-form-item label="注册方式" prop="register_ways">
 | 
			
		||||
          <el-checkbox-group v-model="system['register_ways']">
 | 
			
		||||
            <el-checkbox label="mobile">手机注册</el-checkbox>
 | 
			
		||||
            <el-checkbox label="email">邮箱注册</el-checkbox>
 | 
			
		||||
          </el-checkbox-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
 | 
			
		||||
        <el-form-item label="启用众筹功能" prop="enabled_reward">
 | 
			
		||||
          <el-switch v-model="system['enabled_reward']"/>
 | 
			
		||||
          <el-tooltip
 | 
			
		||||
              effect="dark"
 | 
			
		||||
              content="如果关闭次功能将不在用户菜单显示众筹二维码"
 | 
			
		||||
              raw-content
 | 
			
		||||
              placement="right"
 | 
			
		||||
          >
 | 
			
		||||
            <el-icon>
 | 
			
		||||
              <InfoFilled/>
 | 
			
		||||
            </el-icon>
 | 
			
		||||
          </el-tooltip>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
 | 
			
		||||
        <div v-if="system['enabled_reward']">
 | 
			
		||||
          <el-form-item label="单次对话价格" prop="chat_call_price">
 | 
			
		||||
            <el-input v-model="system['chat_call_price']" placeholder="众筹金额跟对话次数的兑换比例"/>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item label="单次绘图价格" prop="img_call_price">
 | 
			
		||||
            <el-input v-model="system['img_call_price']" placeholder="众筹金额跟绘图次数的兑换比例"/>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item label="收款二维码" prop="reward_img">
 | 
			
		||||
            <el-input v-model="system['reward_img']" placeholder="众筹收款二维码地址">
 | 
			
		||||
              <template #append>
 | 
			
		||||
                <el-upload
 | 
			
		||||
                    :auto-upload="true"
 | 
			
		||||
                    :show-file-list="false"
 | 
			
		||||
                    :http-request="uploadRewardImg"
 | 
			
		||||
                >
 | 
			
		||||
                  <el-icon class="uploader-icon">
 | 
			
		||||
                    <UploadFilled/>
 | 
			
		||||
                  </el-icon>
 | 
			
		||||
                </el-upload>
 | 
			
		||||
              </template>
 | 
			
		||||
            </el-input>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <el-form-item label="显示演示公告" prop="show_demo_notice">
 | 
			
		||||
          <el-switch v-model="system['show_demo_notice']"/>
 | 
			
		||||
          <el-tooltip
 | 
			
		||||
              effect="dark"
 | 
			
		||||
              content="是否在聊天首页显示演示 Demo 公告,这是专为作者自己开发的功能"
 | 
			
		||||
              raw-content
 | 
			
		||||
              placement="right"
 | 
			
		||||
          >
 | 
			
		||||
            <el-icon>
 | 
			
		||||
              <InfoFilled/>
 | 
			
		||||
            </el-icon>
 | 
			
		||||
          </el-tooltip>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
 | 
			
		||||
        <el-form-item label="订单超时时间" prop="order_pay_timeout">
 | 
			
		||||
          <div class="tip-input">
 | 
			
		||||
            <el-input v-model.number="system['order_pay_timeout']" placeholder="单位:秒"/>
 | 
			
		||||
            <div class="info">
 | 
			
		||||
            <el-form-item label="开放注册" prop="enabled_register">
 | 
			
		||||
              <el-switch v-model="system['enabled_register']"/>
 | 
			
		||||
              <el-tooltip
 | 
			
		||||
                  effect="dark"
 | 
			
		||||
                  content="系统会定期清理超时未支付的订单<br/>默认值:900秒"
 | 
			
		||||
                  content="关闭注册之后只能通过管理后台添加用户"
 | 
			
		||||
                  raw-content
 | 
			
		||||
                  placement="right"
 | 
			
		||||
              >
 | 
			
		||||
@@ -115,126 +42,227 @@
 | 
			
		||||
                  <InfoFilled/>
 | 
			
		||||
                </el-icon>
 | 
			
		||||
              </el-tooltip>
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="会员充值说明" prop="order_pay_info_text">
 | 
			
		||||
          <el-input
 | 
			
		||||
              v-model="system['order_pay_info_text']"
 | 
			
		||||
              :autosize="{ minRows: 3, maxRows: 10 }"
 | 
			
		||||
              type="textarea"
 | 
			
		||||
              placeholder="请输入会员充值说明文字,比如介绍会员计划"
 | 
			
		||||
          />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
 | 
			
		||||
        <el-form-item label="默认AI模型" prop="default_models">
 | 
			
		||||
          <template #default>
 | 
			
		||||
            <div class="tip-input">
 | 
			
		||||
              <el-select
 | 
			
		||||
                  v-model="system['default_models']"
 | 
			
		||||
                  multiple
 | 
			
		||||
                  :filterable="true"
 | 
			
		||||
                  placeholder="选择AI模型,多选"
 | 
			
		||||
                  style="width: 100%"
 | 
			
		||||
            <el-form-item label="注册方式" prop="register_ways">
 | 
			
		||||
              <el-checkbox-group v-model="system['register_ways']">
 | 
			
		||||
                <el-checkbox label="mobile">手机注册</el-checkbox>
 | 
			
		||||
                <el-checkbox label="email">邮箱注册</el-checkbox>
 | 
			
		||||
              </el-checkbox-group>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
 | 
			
		||||
            <el-form-item label="启用众筹功能" prop="enabled_reward">
 | 
			
		||||
              <el-switch v-model="system['enabled_reward']"/>
 | 
			
		||||
              <el-tooltip
 | 
			
		||||
                  effect="dark"
 | 
			
		||||
                  content="如果关闭次功能将不在用户菜单显示众筹二维码"
 | 
			
		||||
                  raw-content
 | 
			
		||||
                  placement="right"
 | 
			
		||||
              >
 | 
			
		||||
                <el-option
 | 
			
		||||
                    v-for="item in models"
 | 
			
		||||
                    :key="item.id"
 | 
			
		||||
                    :label="item.name"
 | 
			
		||||
                    :value="item.value"
 | 
			
		||||
                />
 | 
			
		||||
              </el-select>
 | 
			
		||||
              <div class="info">
 | 
			
		||||
                <el-tooltip
 | 
			
		||||
                    class="box-item"
 | 
			
		||||
                    effect="dark"
 | 
			
		||||
                    content="新用户注册默认开通的 AI 模型"
 | 
			
		||||
                    placement="right"
 | 
			
		||||
                >
 | 
			
		||||
                  <el-icon>
 | 
			
		||||
                    <InfoFilled/>
 | 
			
		||||
                  </el-icon>
 | 
			
		||||
                </el-tooltip>
 | 
			
		||||
              </div>
 | 
			
		||||
                <el-icon>
 | 
			
		||||
                  <InfoFilled/>
 | 
			
		||||
                </el-icon>
 | 
			
		||||
              </el-tooltip>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
 | 
			
		||||
            <div v-if="system['enabled_reward']">
 | 
			
		||||
              <el-form-item label="单次对话价格" prop="chat_call_price">
 | 
			
		||||
                <el-input v-model="system['chat_call_price']" placeholder="众筹金额跟对话次数的兑换比例"/>
 | 
			
		||||
              </el-form-item>
 | 
			
		||||
              <el-form-item label="单次绘图价格" prop="img_call_price">
 | 
			
		||||
                <el-input v-model="system['img_call_price']" placeholder="众筹金额跟绘图次数的兑换比例"/>
 | 
			
		||||
              </el-form-item>
 | 
			
		||||
              <el-form-item label="收款二维码" prop="reward_img">
 | 
			
		||||
                <el-input v-model="system['reward_img']" placeholder="众筹收款二维码地址">
 | 
			
		||||
                  <template #append>
 | 
			
		||||
                    <el-upload
 | 
			
		||||
                        :auto-upload="true"
 | 
			
		||||
                        :show-file-list="false"
 | 
			
		||||
                        @click="beforeUpload('reward_img')"
 | 
			
		||||
                        :http-request="uploadImg"
 | 
			
		||||
                    >
 | 
			
		||||
                      <el-icon class="uploader-icon">
 | 
			
		||||
                        <UploadFilled/>
 | 
			
		||||
                      </el-icon>
 | 
			
		||||
                    </el-upload>
 | 
			
		||||
                  </template>
 | 
			
		||||
                </el-input>
 | 
			
		||||
              </el-form-item>
 | 
			
		||||
            </div>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item>
 | 
			
		||||
          <el-button type="primary" @click="save('system')">保存</el-button>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
 | 
			
		||||
      <el-divider content-position="center">模型通用配置</el-divider>
 | 
			
		||||
            <el-form-item label="微信客服二维码" prop="wechat_card_url">
 | 
			
		||||
              <el-input v-model="system['wechat_card_url']" placeholder="微信客服二维码">
 | 
			
		||||
                <template #append>
 | 
			
		||||
                  <el-upload
 | 
			
		||||
                      :auto-upload="true"
 | 
			
		||||
                      :show-file-list="false"
 | 
			
		||||
                      @click="beforeUpload('wechat_card_url')"
 | 
			
		||||
                      :http-request="uploadImg"
 | 
			
		||||
                  >
 | 
			
		||||
                    <el-icon class="uploader-icon">
 | 
			
		||||
                      <UploadFilled/>
 | 
			
		||||
                    </el-icon>
 | 
			
		||||
                  </el-upload>
 | 
			
		||||
                </template>
 | 
			
		||||
              </el-input>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
 | 
			
		||||
      <el-form :model="chat" label-position="right" label-width="150px" ref="chatFormRef" :rules="rules">
 | 
			
		||||
        <el-form-item label="开启聊天上下文">
 | 
			
		||||
          <el-switch v-model="chat['enable_context']"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="保存聊天记录">
 | 
			
		||||
          <el-switch v-model="chat['enable_history']"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="会话上下文深度">
 | 
			
		||||
          <el-input-number v-model="chat['context_deep']" :min="0" :max="10"/>
 | 
			
		||||
          <div class="tip" style="margin-top: 10px;">会话上下文深度:在老会话中继续会话,默认加载多少条聊天记录作为上下文。如果设置为
 | 
			
		||||
            0
 | 
			
		||||
            则不加载聊天记录,仅仅使用当前角色的上下文。该配置参数最好设置需要为偶数,否则将无法兼容百度的 API。
 | 
			
		||||
          </div>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
            <el-form-item label="显示演示公告" prop="show_demo_notice">
 | 
			
		||||
              <el-switch v-model="system['show_demo_notice']"/>
 | 
			
		||||
              <el-tooltip
 | 
			
		||||
                  effect="dark"
 | 
			
		||||
                  content="是否在聊天首页显示演示 Demo 公告,这是专为作者自己开发的功能"
 | 
			
		||||
                  raw-content
 | 
			
		||||
                  placement="right"
 | 
			
		||||
              >
 | 
			
		||||
                <el-icon>
 | 
			
		||||
                  <InfoFilled/>
 | 
			
		||||
                </el-icon>
 | 
			
		||||
              </el-tooltip>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
 | 
			
		||||
        <el-divider content-position="center">OpenAI</el-divider>
 | 
			
		||||
        <el-form-item label="模型创意度">
 | 
			
		||||
          <el-slider v-model="chat['open_ai']['temperature']" :max="2" :step="0.1"/>
 | 
			
		||||
          <div class="tip">值越大 AI 回答越发散,值越小回答越保守,建议保持默认值</div>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="最大响应长度">
 | 
			
		||||
          <el-input v-model.number="chat['open_ai']['max_tokens']" placeholder="回复的最大字数,最大4096"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
            <el-form-item label="订单超时时间" prop="order_pay_timeout">
 | 
			
		||||
              <div class="tip-input">
 | 
			
		||||
                <el-input v-model.number="system['order_pay_timeout']" placeholder="单位:秒"/>
 | 
			
		||||
                <div class="info">
 | 
			
		||||
                  <el-tooltip
 | 
			
		||||
                      effect="dark"
 | 
			
		||||
                      content="系统会定期清理超时未支付的订单<br/>默认值:900秒"
 | 
			
		||||
                      raw-content
 | 
			
		||||
                      placement="right"
 | 
			
		||||
                  >
 | 
			
		||||
                    <el-icon>
 | 
			
		||||
                      <InfoFilled/>
 | 
			
		||||
                    </el-icon>
 | 
			
		||||
                  </el-tooltip>
 | 
			
		||||
                </div>
 | 
			
		||||
              </div>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="会员充值说明" prop="order_pay_info_text">
 | 
			
		||||
              <el-input
 | 
			
		||||
                  v-model="system['order_pay_info_text']"
 | 
			
		||||
                  :autosize="{ minRows: 3, maxRows: 10 }"
 | 
			
		||||
                  type="textarea"
 | 
			
		||||
                  placeholder="请输入会员充值说明文字,比如介绍会员计划"
 | 
			
		||||
              />
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
 | 
			
		||||
        <el-divider content-position="center">Azure</el-divider>
 | 
			
		||||
        <el-form-item label="模型创意度">
 | 
			
		||||
          <el-slider v-model="chat['azure']['temperature']" :max="2" :step="0.1"/>
 | 
			
		||||
          <div class="tip">值越大 AI 回答越发散,值越小回答越保守,建议保持默认值</div>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="最大响应长度">
 | 
			
		||||
          <el-input v-model.number="chat['azure']['max_tokens']" placeholder="回复的最大字数,最大4096"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
            <el-form-item label="默认AI模型" prop="default_models">
 | 
			
		||||
              <template #default>
 | 
			
		||||
                <div class="tip-input">
 | 
			
		||||
                  <el-select
 | 
			
		||||
                      v-model="system['default_models']"
 | 
			
		||||
                      multiple
 | 
			
		||||
                      :filterable="true"
 | 
			
		||||
                      placeholder="选择AI模型,多选"
 | 
			
		||||
                      style="width: 100%"
 | 
			
		||||
                  >
 | 
			
		||||
                    <el-option
 | 
			
		||||
                        v-for="item in models"
 | 
			
		||||
                        :key="item.id"
 | 
			
		||||
                        :label="item.name"
 | 
			
		||||
                        :value="item.value"
 | 
			
		||||
                    />
 | 
			
		||||
                  </el-select>
 | 
			
		||||
                  <div class="info">
 | 
			
		||||
                    <el-tooltip
 | 
			
		||||
                        class="box-item"
 | 
			
		||||
                        effect="dark"
 | 
			
		||||
                        content="新用户注册默认开通的 AI 模型"
 | 
			
		||||
                        placement="right"
 | 
			
		||||
                    >
 | 
			
		||||
                      <el-icon>
 | 
			
		||||
                        <InfoFilled/>
 | 
			
		||||
                      </el-icon>
 | 
			
		||||
                    </el-tooltip>
 | 
			
		||||
                  </div>
 | 
			
		||||
                </div>
 | 
			
		||||
              </template>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item>
 | 
			
		||||
              <el-button type="primary" @click="save('system')">保存</el-button>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
          </el-form>
 | 
			
		||||
        </div>
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
      <el-tab-pane label="模型配置" name="chat">
 | 
			
		||||
        <div class="container">
 | 
			
		||||
          <el-form :model="chat" label-position="right" label-width="150px" ref="chatFormRef" :rules="rules">
 | 
			
		||||
            <el-form-item label="开启聊天上下文">
 | 
			
		||||
              <el-switch v-model="chat['enable_context']"/>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="保存聊天记录">
 | 
			
		||||
              <el-switch v-model="chat['enable_history']"/>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="会话上下文深度">
 | 
			
		||||
              <div style="width:100%">
 | 
			
		||||
                <el-input-number v-model="chat['context_deep']" :min="0" :max="10"/>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div class="tip" style="margin-top: 10px; ">会话上下文深度:在老会话中继续会话,默认加载多少条聊天记录作为上下文。如果设置为
 | 
			
		||||
                0
 | 
			
		||||
                则不加载聊天记录,仅仅使用当前角色的上下文。该配置参数最好设置需要为偶数,否则将无法兼容百度的 API。
 | 
			
		||||
              </div>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
 | 
			
		||||
        <el-divider content-position="center">ChatGLM</el-divider>
 | 
			
		||||
        <el-form-item label="模型创意度">
 | 
			
		||||
          <el-slider v-model="chat['chat_gml']['temperature']" :max="1" :step="0.01"/>
 | 
			
		||||
          <div class="tip">值越大 AI 回答越发散,值越小回答越保守,建议保持默认值</div>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="最大响应长度">
 | 
			
		||||
          <el-input v-model.number="chat['chat_gml']['max_tokens']" placeholder="回复的最大字数,最大4096"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
            <el-divider content-position="center">OpenAI</el-divider>
 | 
			
		||||
            <el-form-item label="模型创意度">
 | 
			
		||||
              <el-slider v-model="chat['open_ai']['temperature']" :max="2" :step="0.1"/>
 | 
			
		||||
              <div class="tip">值越大 AI 回答越发散,值越小回答越保守,建议保持默认值</div>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="最大响应长度">
 | 
			
		||||
              <el-input v-model.number="chat['open_ai']['max_tokens']" placeholder="回复的最大字数,最大4096"/>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
 | 
			
		||||
        <el-divider content-position="center">文心一言</el-divider>
 | 
			
		||||
        <el-form-item label="模型创意度">
 | 
			
		||||
          <el-slider v-model="chat['baidu']['temperature']" :max="1" :step="0.01"/>
 | 
			
		||||
          <div class="tip">值越大 AI 回答越发散,值越小回答越保守,建议保持默认值</div>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="最大响应长度">
 | 
			
		||||
          <el-input v-model.number="chat['baidu']['max_tokens']" placeholder="回复的最大字数,最大4096"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
            <el-divider content-position="center">Azure</el-divider>
 | 
			
		||||
            <el-form-item label="模型创意度">
 | 
			
		||||
              <el-slider v-model="chat['azure']['temperature']" :max="2" :step="0.1"/>
 | 
			
		||||
              <div class="tip">值越大 AI 回答越发散,值越小回答越保守,建议保持默认值</div>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="最大响应长度">
 | 
			
		||||
              <el-input v-model.number="chat['azure']['max_tokens']" placeholder="回复的最大字数,最大4096"/>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
 | 
			
		||||
        <el-divider content-position="center">讯飞星火</el-divider>
 | 
			
		||||
        <el-form-item label="模型创意度">
 | 
			
		||||
          <el-slider v-model="chat['xun_fei']['temperature']" :max="1" :step="0.1"/>
 | 
			
		||||
          <div class="tip">值越大 AI 回答越发散,值越小回答越保守,建议保持默认值</div>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="最大响应长度">
 | 
			
		||||
          <el-input v-model.number="chat['xun_fei']['max_tokens']" placeholder="回复的最大字数,最大4096"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
            <el-divider content-position="center">ChatGLM</el-divider>
 | 
			
		||||
            <el-form-item label="模型创意度">
 | 
			
		||||
              <el-slider v-model="chat['chat_gml']['temperature']" :max="1" :step="0.01"/>
 | 
			
		||||
              <div class="tip">值越大 AI 回答越发散,值越小回答越保守,建议保持默认值</div>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="最大响应长度">
 | 
			
		||||
              <el-input v-model.number="chat['chat_gml']['max_tokens']" placeholder="回复的最大字数,最大4096"/>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
 | 
			
		||||
        <el-divider content-position="center">AI绘图</el-divider>
 | 
			
		||||
        <el-form-item label="DALL-E3出图数量">
 | 
			
		||||
          <el-input v-model.number="chat['dall_img_num']" placeholder="调用 DALL E3 API 传入的出图数量"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item style="text-align: right">
 | 
			
		||||
          <el-button type="primary" @click="save('chat')">保存</el-button>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
    </div>
 | 
			
		||||
            <el-divider content-position="center">文心一言</el-divider>
 | 
			
		||||
            <el-form-item label="模型创意度">
 | 
			
		||||
              <el-slider v-model="chat['baidu']['temperature']" :max="1" :step="0.01"/>
 | 
			
		||||
              <div class="tip">值越大 AI 回答越发散,值越小回答越保守,建议保持默认值</div>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="最大响应长度">
 | 
			
		||||
              <el-input v-model.number="chat['baidu']['max_tokens']" placeholder="回复的最大字数,最大4096"/>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
 | 
			
		||||
            <el-divider content-position="center">讯飞星火</el-divider>
 | 
			
		||||
            <el-form-item label="模型创意度">
 | 
			
		||||
              <el-slider v-model="chat['xun_fei']['temperature']" :max="1" :step="0.1"/>
 | 
			
		||||
              <div class="tip">值越大 AI 回答越发散,值越小回答越保守,建议保持默认值</div>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="最大响应长度">
 | 
			
		||||
              <el-input v-model.number="chat['xun_fei']['max_tokens']" placeholder="回复的最大字数,最大4096"/>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
 | 
			
		||||
            <el-divider content-position="center">AI绘图</el-divider>
 | 
			
		||||
            <el-form-item label="DALL-E3出图数量">
 | 
			
		||||
              <el-input v-model.number="chat['dall_img_num']" placeholder="调用 DALL E3 API 传入的出图数量"/>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item style="text-align: right">
 | 
			
		||||
              <el-button type="primary" @click="save('chat')">保存</el-button>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
          </el-form>
 | 
			
		||||
        </div>
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
      <el-tab-pane label="公告配置" name="notice">
 | 
			
		||||
        <md-editor class="mgb20" v-model="notice" @on-upload-img="onUploadImg"/>
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
    </el-tabs>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
@@ -244,7 +272,10 @@ import {httpGet, httpPost} from "@/utils/http";
 | 
			
		||||
import Compressor from "compressorjs";
 | 
			
		||||
import {ElMessage} from "element-plus";
 | 
			
		||||
import {InfoFilled, UploadFilled} from "@element-plus/icons-vue";
 | 
			
		||||
import MdEditor from "md-editor-v3";
 | 
			
		||||
import 'md-editor-v3/lib/style.css';
 | 
			
		||||
 | 
			
		||||
const activeName = ref('basic')
 | 
			
		||||
const system = ref({models: []})
 | 
			
		||||
const chat = ref({
 | 
			
		||||
  open_ai: {temperature: 1, max_tokens: 1024},
 | 
			
		||||
@@ -261,6 +292,7 @@ const loading = ref(true)
 | 
			
		||||
const systemFormRef = ref(null)
 | 
			
		||||
const chatFormRef = ref(null)
 | 
			
		||||
const models = ref([])
 | 
			
		||||
const notice = ref("")
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  // 加载系统配置
 | 
			
		||||
@@ -321,8 +353,13 @@ const save = function (key) {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const configKey = ref("")
 | 
			
		||||
const beforeUpload = (key) => {
 | 
			
		||||
  configKey.value = key
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 图片上传
 | 
			
		||||
const uploadRewardImg = (file) => {
 | 
			
		||||
const uploadImg = (file) => {
 | 
			
		||||
  // 压缩图片并上传
 | 
			
		||||
  new Compressor(file.file, {
 | 
			
		||||
    quality: 0.6,
 | 
			
		||||
@@ -331,17 +368,20 @@ const uploadRewardImg = (file) => {
 | 
			
		||||
      formData.append('file', result, result.name);
 | 
			
		||||
      // 执行上传操作
 | 
			
		||||
      httpPost('/api/upload', formData).then((res) => {
 | 
			
		||||
        system.value['reward_img'] = res.data.url
 | 
			
		||||
        system.value[configKey.value] = res.data.url
 | 
			
		||||
        ElMessage.success('上传成功')
 | 
			
		||||
      }).catch((e) => {
 | 
			
		||||
        ElMessage.error('上传失败:' + e.message)
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    error(err) {
 | 
			
		||||
      console.log(err.message);
 | 
			
		||||
    error(e) {
 | 
			
		||||
      ElMessage.error('上传失败:' + e.message)
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
const onUploadImg = (files) => {
 | 
			
		||||
  console.log(files);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
@@ -351,41 +391,46 @@ const uploadRewardImg = (file) => {
 | 
			
		||||
  display flex
 | 
			
		||||
  justify-content center
 | 
			
		||||
 | 
			
		||||
  .container {
 | 
			
		||||
  .el-tabs {
 | 
			
		||||
    width 100%
 | 
			
		||||
    max-width 800px;
 | 
			
		||||
    background-color #ffffff
 | 
			
		||||
    padding 10px 20px 40px 20px
 | 
			
		||||
    border: 1px solid #ddd;
 | 
			
		||||
    border-radius: 5px
 | 
			
		||||
 | 
			
		||||
    .el-form {
 | 
			
		||||
      .el-form-item__content {
 | 
			
		||||
    .container {
 | 
			
		||||
      .el-form {
 | 
			
		||||
        .el-form-item__content {
 | 
			
		||||
 | 
			
		||||
        .tip-text {
 | 
			
		||||
          padding-left 10px;
 | 
			
		||||
          .tip-text {
 | 
			
		||||
            padding-left 10px;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          .tip {
 | 
			
		||||
            color #c1c1c1
 | 
			
		||||
            font-size 12px;
 | 
			
		||||
            line-height 1.5;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          .el-icon {
 | 
			
		||||
            font-size 16px
 | 
			
		||||
            margin-left 10px
 | 
			
		||||
            cursor pointer
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          .uploader-icon {
 | 
			
		||||
            font-size 24px
 | 
			
		||||
            position relative
 | 
			
		||||
            top 3px
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
        .tip {
 | 
			
		||||
          color #c1c1c1
 | 
			
		||||
          font-size 12px;
 | 
			
		||||
          line-height 1.5;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .el-icon {
 | 
			
		||||
          font-size 16px
 | 
			
		||||
          margin-left 10px
 | 
			
		||||
          cursor pointer
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .uploader-icon {
 | 
			
		||||
          font-size 24px
 | 
			
		||||
          position relative
 | 
			
		||||
          top 3px
 | 
			
		||||
        }
 | 
			
		||||
      .el-alert {
 | 
			
		||||
        margin-bottom 15px;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .el-alert {
 | 
			
		||||
      margin-bottom 15px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
		Reference in New Issue
	
	Block a user