feat: add system config item for wechat qrcode

This commit is contained in:
RockYang 2024-01-19 16:58:13 +08:00
parent c9cd082855
commit 15b2ec9721
7 changed files with 320 additions and 254 deletions

View File

@ -3,7 +3,9 @@
* 功能优化:恢复关闭注册系统配置项,管理员可以在后台关闭用户注册,只允许内部添加账号 * 功能优化:恢复关闭注册系统配置项,管理员可以在后台关闭用户注册,只允许内部添加账号
* 功能优化:兼用旧版本微信收款消息解析 * 功能优化:兼用旧版本微信收款消息解析
* 功能优化:优化订单扫码支付状态轮询功能,当关闭二维码时取消轮询,节约网络资源 * 功能优化:优化订单扫码支付状态轮询功能,当关闭二维码时取消轮询,节约网络资源
* * 功能新增:后台新增配置微信客服二维码,可以上传自己的微信客服二维码
* 功能新增:新增网站公告,可以在管理后台自定义配置
* 功能新增:新增阿里通义千问大模型支持
## v3.2.5 ## v3.2.5

View File

@ -196,4 +196,5 @@ type SystemConfig struct {
InviteImgCalls int `json:"invite_img_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"` // 微信客服地址
} }

View File

@ -26,7 +26,8 @@ import (
) )
const ErrorMsg = "抱歉AI 助手开小差了,请稍后再试。" const ErrorMsg = "抱歉AI 助手开小差了,请稍后再试。"
const ErrImg = "![](/images/wx.png)"
var ErrImg = "![](/images/wx.png)"
var logger = logger2.GetLogger() var logger = logger2.GetLogger()
@ -45,6 +46,13 @@ func NewChatHandler(app *core.AppServer, db *gorm.DB, redis *redis.Client) *Chat
return &h return &h
} }
func (h *ChatHandler) Init() {
// 如果后台有上传微信客服微信二维码,则覆盖
if h.App.SysConfig.WechatCardURL != "" {
ErrImg = fmt.Sprintf("![](%s)", h.App.SysConfig.WechatCardURL)
}
}
var chatConfig types.ChatConfig var chatConfig types.ChatConfig
// ChatHandle 处理聊天 WebSocket 请求 // ChatHandle 处理聊天 WebSocket 请求

View File

@ -59,11 +59,13 @@ func main() {
} }
debug, _ := strconv.ParseBool(os.Getenv("APP_DEBUG")) debug, _ := strconv.ParseBool(os.Getenv("APP_DEBUG"))
logger.Info("Loading config file: ", configFile) logger.Info("Loading config file: ", configFile)
if !debug {
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
logger.Error("Panic Error:", err) logger.Error("Panic Error:", err)
} }
}() }()
}
app := fx.New( app := fx.New(
// 初始化配置应用配置 // 初始化配置应用配置
@ -378,7 +380,9 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
}), }),
fx.Invoke(func(h *chatimpl.ChatHandler) {
h.Init()
}),
// 注册生命周期回调函数 // 注册生命周期回调函数
fx.Invoke(func(lifecycle fx.Lifecycle, lc *AppLifecycle) { fx.Invoke(func(lifecycle fx.Lifecycle, lc *AppLifecycle) {
lifecycle.Append(fx.Hook{ lifecycle.Append(fx.Hook{

View File

@ -222,7 +222,7 @@
</el-alert> </el-alert>
<div style="text-align: center;padding-top: 10px;"> <div style="text-align: center;padding-top: 10px;">
<el-image src="/images/wx.png"/> <el-image :src="wechatCardURL"/>
</div> </div>
</el-dialog> </el-dialog>
@ -325,6 +325,7 @@ const textInput = ref(null)
const showFeedbackDialog = ref(false) const showFeedbackDialog = ref(false)
const showDemoNotice = ref(false) const showDemoNotice = ref(false)
const showNoticeKey = ref("SHOW_DEMO_NOTICE_") const showNoticeKey = ref("SHOW_DEMO_NOTICE_")
const wechatCardURL = ref("/images/wx.png")
if (isMobile()) { if (isMobile()) {
router.replace("/mobile") router.replace("/mobile")
@ -377,6 +378,7 @@ onMounted(() => {
if (!show) { if (!show) {
showDemoNotice.value = res.data['show_demo_notice'] showDemoNotice.value = res.data['show_demo_notice']
} }
wechatCardURL.value = res.data['wechat_card_url']
}).catch(e => { }).catch(e => {
ElMessage.error("获取系统配置失败:" + e.message) ElMessage.error("获取系统配置失败:" + e.message)
}) })

View File

@ -156,6 +156,10 @@ httpGet("/api/admin/config/get?key=system").then(res => {
placeholder.value += ways.join("/") placeholder.value += ways.join("/")
// //
enableRegister.value = res.data['enabled_register'] enableRegister.value = res.data['enabled_register']
//
if (res.data['wechat_card_url'] !== '') {
wxImg.value = res.data['wechat_card_url']
}
} }
}).catch(e => { }).catch(e => {
ElMessage.error("获取系统配置失败:" + e.message) ElMessage.error("获取系统配置失败:" + e.message)

View File

@ -1,7 +1,9 @@
<template> <template>
<div class="system-config" v-loading="loading"> <div class="system-config" v-loading="loading">
<el-tabs v-model="activeName" class="demo-tabs">
<el-tab-pane label="基本设置" name="basic">
<div class="container"> <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 :model="system" label-width="150px" label-position="right" ref="systemFormRef" :rules="rules">
<el-form-item label="网站标题" prop="title"> <el-form-item label="网站标题" prop="title">
<el-input v-model="system['title']"/> <el-input v-model="system['title']"/>
@ -76,7 +78,8 @@
<el-upload <el-upload
:auto-upload="true" :auto-upload="true"
:show-file-list="false" :show-file-list="false"
:http-request="uploadRewardImg" @click="beforeUpload('reward_img')"
:http-request="uploadImg"
> >
<el-icon class="uploader-icon"> <el-icon class="uploader-icon">
<UploadFilled/> <UploadFilled/>
@ -87,6 +90,23 @@
</el-form-item> </el-form-item>
</div> </div>
<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-item label="显示演示公告" prop="show_demo_notice"> <el-form-item label="显示演示公告" prop="show_demo_notice">
<el-switch v-model="system['show_demo_notice']"/> <el-switch v-model="system['show_demo_notice']"/>
<el-tooltip <el-tooltip
@ -163,9 +183,10 @@
<el-button type="primary" @click="save('system')">保存</el-button> <el-button type="primary" @click="save('system')">保存</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</div>
<el-divider content-position="center">模型通用配置</el-divider> </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 :model="chat" label-position="right" label-width="150px" ref="chatFormRef" :rules="rules">
<el-form-item label="开启聊天上下文"> <el-form-item label="开启聊天上下文">
<el-switch v-model="chat['enable_context']"/> <el-switch v-model="chat['enable_context']"/>
@ -174,7 +195,9 @@
<el-switch v-model="chat['enable_history']"/> <el-switch v-model="chat['enable_history']"/>
</el-form-item> </el-form-item>
<el-form-item label="会话上下文深度"> <el-form-item label="会话上下文深度">
<div style="width:100%">
<el-input-number v-model="chat['context_deep']" :min="0" :max="10"/> <el-input-number v-model="chat['context_deep']" :min="0" :max="10"/>
</div>
<div class="tip" style="margin-top: 10px; ">会话上下文深度在老会话中继续会话默认加载多少条聊天记录作为上下文如果设置为 <div class="tip" style="margin-top: 10px; ">会话上下文深度在老会话中继续会话默认加载多少条聊天记录作为上下文如果设置为
0 0
则不加载聊天记录仅仅使用当前角色的上下文该配置参数最好设置需要为偶数否则将无法兼容百度的 API 则不加载聊天记录仅仅使用当前角色的上下文该配置参数最好设置需要为偶数否则将无法兼容百度的 API
@ -235,6 +258,11 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </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> </div>
</template> </template>
@ -244,7 +272,10 @@ import {httpGet, httpPost} from "@/utils/http";
import Compressor from "compressorjs"; import Compressor from "compressorjs";
import {ElMessage} from "element-plus"; import {ElMessage} from "element-plus";
import {InfoFilled, UploadFilled} from "@element-plus/icons-vue"; 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 system = ref({models: []})
const chat = ref({ const chat = ref({
open_ai: {temperature: 1, max_tokens: 1024}, open_ai: {temperature: 1, max_tokens: 1024},
@ -261,6 +292,7 @@ const loading = ref(true)
const systemFormRef = ref(null) const systemFormRef = ref(null)
const chatFormRef = ref(null) const chatFormRef = ref(null)
const models = ref([]) const models = ref([])
const notice = ref("")
onMounted(() => { 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, { new Compressor(file.file, {
quality: 0.6, quality: 0.6,
@ -331,17 +368,20 @@ const uploadRewardImg = (file) => {
formData.append('file', result, result.name); formData.append('file', result, result.name);
// //
httpPost('/api/upload', formData).then((res) => { httpPost('/api/upload', formData).then((res) => {
system.value['reward_img'] = res.data.url system.value[configKey.value] = res.data.url
ElMessage.success('上传成功') ElMessage.success('上传成功')
}).catch((e) => { }).catch((e) => {
ElMessage.error('上传失败:' + e.message) ElMessage.error('上传失败:' + e.message)
}) })
}, },
error(err) { error(e) {
console.log(err.message); ElMessage.error('上传失败:' + e.message)
}, },
}); });
}; };
const onUploadImg = (files) => {
console.log(files);
};
</script> </script>
@ -351,10 +391,14 @@ const uploadRewardImg = (file) => {
display flex display flex
justify-content center justify-content center
.container { .el-tabs {
width 100% width 100%
max-width 800px; background-color #ffffff
padding 10px 20px 40px 20px
border: 1px solid #ddd;
border-radius: 5px
.container {
.el-form { .el-form {
.el-form-item__content { .el-form-item__content {
@ -388,4 +432,5 @@ const uploadRewardImg = (file) => {
} }
} }
}
</style> </style>