优化版权显示逻辑,允许激活用户更改自定义版权

This commit is contained in:
RockYang 2024-07-15 18:44:14 +08:00
parent 0df700ec18
commit f22c6bf658
14 changed files with 83 additions and 52 deletions

View File

@ -18,7 +18,7 @@ TikaHost = "http://tika:9998"
DB = 0 DB = 0
[ApiConfig] # 微博热搜,今日头条等函数服务 API 配置,此为第三方插件服务,如需使用请联系作者开通 [ApiConfig] # 微博热搜,今日头条等函数服务 API 配置,此为第三方插件服务,如需使用请联系作者开通
ApiURL = "" ApiURL = "https://sapi.geekai.me"
AppId = "" AppId = ""
Token = "" Token = ""

View File

@ -228,4 +228,5 @@ type SystemConfig struct {
SdNegPrompt string `json:"sd_neg_prompt"` // SD 默认反向提示词 SdNegPrompt string `json:"sd_neg_prompt"` // SD 默认反向提示词
IndexBgURL string `json:"index_bg_url"` // 前端首页背景图片 IndexBgURL string `json:"index_bg_url"` // 前端首页背景图片
Copyright string `json:"copyright"` // 版权信息
} }

View File

@ -50,6 +50,7 @@ func (h *ConfigHandler) Update(c *gin.Context) {
Content string `json:"content,omitempty"` Content string `json:"content,omitempty"`
Updated bool `json:"updated,omitempty"` Updated bool `json:"updated,omitempty"`
} `json:"config"` } `json:"config"`
ConfigBak types.SystemConfig `json:"config_bak,omitempty"`
} }
if err := c.ShouldBindJSON(&data); err != nil { if err := c.ShouldBindJSON(&data); err != nil {
@ -57,6 +58,12 @@ func (h *ConfigHandler) Update(c *gin.Context) {
return return
} }
// ONLY authorized user can change the copyright
if (data.Key == "system" && data.Config.Copyright != data.ConfigBak.Copyright) && !h.licenseService.GetLicense().Configs.DeCopy {
resp.ERROR(c, "您无权修改版权信息,请先联系作者获取授权")
return
}
value := utils.JsonEncode(&data.Config) value := utils.JsonEncode(&data.Config)
config := model.Config{Key: data.Key, Config: value} config := model.Config{Key: data.Key, Config: value}
res := h.DB.FirstOrCreate(&config, model.Config{Key: data.Key}) res := h.DB.FirstOrCreate(&config, model.Config{Key: data.Key})

View File

@ -21,7 +21,7 @@ TikaHost = "http://tika:9998"
DB = 0 DB = 0
[ApiConfig] [ApiConfig]
ApiURL = "http://service.r9it.com:9001" ApiURL = "http://sapi.geekai.me"
AppId = "" AppId = ""
Token = "" Token = ""

View File

@ -6,6 +6,6 @@ VUE_APP_ADMIN_USER=admin
VUE_APP_ADMIN_PASS=admin123 VUE_APP_ADMIN_PASS=admin123
VUE_APP_KEY_PREFIX=ChatPLUS_DEV_ VUE_APP_KEY_PREFIX=ChatPLUS_DEV_
VUE_APP_TITLE="Geek-AI 创作系统" VUE_APP_TITLE="Geek-AI 创作系统"
VUE_APP_VERSION=v4.1.0 VUE_APP_VERSION=v4.1.1
VUE_APP_DOCS_URL=https://docs.geekai.me VUE_APP_DOCS_URL=https://docs.geekai.me
VUE_APP_GIT_URL=https://github.com/yangjian102621/geekai VUE_APP_GIT_URL=https://github.com/yangjian102621/geekai

View File

@ -1,7 +1,6 @@
VUE_APP_API_HOST= VUE_APP_API_HOST=
VUE_APP_WS_HOST= VUE_APP_WS_HOST=
VUE_APP_KEY_PREFIX=ChatPLUS_ VUE_APP_KEY_PREFIX=ChatPLUS_
VUE_APP_TITLE="Geek-AI 创作系统" VUE_APP_VERSION=v4.1.1
VUE_APP_VERSION=v4.1.0
VUE_APP_DOCS_URL=https://docs.geekai.me VUE_APP_DOCS_URL=https://docs.geekai.me
VUE_APP_GIT_URL=https://github.com/yangjian102621/geekai VUE_APP_GIT_URL=https://github.com/yangjian102621/geekai

View File

@ -1,22 +1,43 @@
<template> <template>
<div class="foot-container"> <div class="foot-container">
<div class="footer"> <div class="footer">
Powered by {{ author }} @ <div v-if="license.de_copy">{{copyRight}}</div>
<el-link type="primary" :href="gitURL" target="_blank" style="--el-link-text-color:#ffffff"> <div v-else>
{{ title }} - <span>{{copyRight}}</span>
{{ version }} <el-link type="primary" :href="gitURL" target="_blank" style="--el-link-text-color:#ffffff">
</el-link> {{ title }} -
{{ version }}
</el-link>
</div>
</div> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
import {ref} from "vue"; import {ref} from "vue";
import {httpGet} from "@/utils/http";
import {showMessageError} from "@/utils/dialog";
const title = ref(process.env.VUE_APP_TITLE) const title = ref("")
const version = ref(process.env.VUE_APP_VERSION) const version = ref(process.env.VUE_APP_VERSION)
const gitURL = ref(process.env.VUE_APP_GIT_URL) const gitURL = ref(process.env.VUE_APP_GIT_URL)
const author = ref('极客学长') const copyRight = ref('')
const license = ref({})
//
httpGet("/api/config/get?key=system").then(res => {
title.value = res.data.title??process.env.VUE_APP_TITLE
copyRight.value = res.data.copyright??'极客学长 © 2023 - '+new Date().getFullYear()+' All rights reserved.'
}).catch(e => {
showMessageError("获取系统配置失败:" + e.message)
})
httpGet("/api/config/license").then(res => {
license.value = res.data
}).catch(e => {
showMessageError("获取 License 失败:" + e.message)
})
</script> </script>
<style scoped lang="stylus"> <style scoped lang="stylus">

View File

@ -251,7 +251,7 @@ const enableMobile = ref(false)
const enableEmail = ref(false) const enableEmail = ref(false)
const enableUser = ref(false) const enableUser = ref(false)
const enableRegister = ref(false) const enableRegister = ref(false)
const activeName = ref("mobile") const activeName = ref("")
const wxImg = ref("/images/wx.png") const wxImg = ref("/images/wx.png")
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
const emits = defineEmits(['hide', 'success']); const emits = defineEmits(['hide', 'success']);
@ -261,12 +261,15 @@ httpGet("/api/config/get?key=system").then(res => {
const registerWays = res.data['register_ways'] const registerWays = res.data['register_ways']
if (arrayContains(registerWays, "mobile")) { if (arrayContains(registerWays, "mobile")) {
enableMobile.value = true enableMobile.value = true
activeName.value = activeName.value === "" ? "mobile" : activeName.value
} }
if (arrayContains(registerWays, "email")) { if (arrayContains(registerWays, "email")) {
enableEmail.value = true enableEmail.value = true
activeName.value = activeName.value === "" ? "email" : activeName.value
} }
if (arrayContains(registerWays, "username")) { if (arrayContains(registerWays, "username")) {
enableUser.value = true enableUser.value = true
activeName.value = activeName.value === "" ? "username" : activeName.value
} }
// //
enableRegister.value = res.data['enabled_register'] enableRegister.value = res.data['enabled_register']

View File

@ -280,23 +280,11 @@ const router = createRouter({
routes: routes, routes: routes,
}) })
const active = ref(false)
const title = ref('')
httpGet("/api/config/license").then(res => {
active.value = res.data.de_copy
}).catch(() => {})
httpGet("/api/config/get?key=system").then(res => {
title.value = res.data.title
}).catch(()=>{})
let prevRoute = null let prevRoute = null
// dynamic change the title when router change // dynamic change the title when router change
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
if (!active.value) { document.title = to.meta.title
document.title = `${to.meta.title} | ${process.env.VUE_APP_TITLE}`
} else {
document.title = `${to.meta.title} | ${title.value}`
}
prevRoute = from prevRoute = from
next() next()
}) })

View File

@ -36,7 +36,11 @@ axios.interceptors.response.use(
} }
return Promise.reject(error.response.data) return Promise.reject(error.response.data)
} }
return Promise.reject(error) if (error.response.status === 400) {
return Promise.reject(new Error(error.response.data.message))
} else {
return Promise.reject(error)
}
}) })

View File

@ -11,7 +11,7 @@
<div class="title">{{ title }}</div> <div class="title">{{ title }}</div>
</div> </div>
<div class="menu-item"> <div class="menu-item">
<span v-if="!licenseConfig.de_copy"> <span v-if="!license.de_copy">
<a :href="docsURL" target="_blank"> <a :href="docsURL" target="_blank">
<el-button type="primary" round> <el-button type="primary" round>
<i class="iconfont icon-book"></i> <i class="iconfont icon-book"></i>
@ -57,9 +57,7 @@
<!-- <div id="animation-container"></div>--> <!-- <div id="animation-container"></div>-->
</div> </div>
<div class="footer" v-if="!licenseConfig.de_copy"> <footer-bar />
<footer-bar />
</div>
</div> </div>
</template> </template>
@ -82,7 +80,7 @@ if (isMobile()) {
const title = ref("Geek-AI 创作系统") const title = ref("Geek-AI 创作系统")
const logo = ref("/images/logo.png") const logo = ref("/images/logo.png")
const slogan = ref("我辈之人,先干为敬,陪您先把 AI 用起来") const slogan = ref("我辈之人,先干为敬,陪您先把 AI 用起来")
const licenseConfig = ref({}) const license = ref({})
const winHeight = window.innerHeight - 150 const winHeight = window.innerHeight - 150
const bgImgUrl = ref('') const bgImgUrl = ref('')
const isLogin = ref(false) const isLogin = ref(false)
@ -106,7 +104,7 @@ onMounted(() => {
}) })
httpGet("/api/config/license").then(res => { httpGet("/api/config/license").then(res => {
licenseConfig.value = res.data license.value = res.data
}).catch(e => { }).catch(e => {
ElMessage.error("获取 License 配置:" + e.message) ElMessage.error("获取 License 配置:" + e.message)
}) })

View File

@ -55,10 +55,8 @@
</div> </div>
<reset-pass @hide="showResetPass = false" :show="showResetPass"/> <reset-pass @hide="showResetPass = false" :show="showResetPass"/>
<footer class="footer" v-if="!licenseConfig.de_copy"> <footer-bar/>
<footer-bar/>
</footer>
</div> </div>
</div> </div>
</template> </template>

View File

@ -106,19 +106,10 @@ import {useSharedStore} from "@/store/sharedata";
const leftBoxHeight = ref(window.innerHeight - 105) const leftBoxHeight = ref(window.innerHeight - 105)
const rightBoxHeight = ref(window.innerHeight - 115) const rightBoxHeight = ref(window.innerHeight - 115)
const title = ref("")
const prompt = ref("") const prompt = ref("")
const text = ref(`# Geek-AI 助手 const text = ref("")
- 完整的开源系统前端应用和后台管理系统皆可开箱即用
- 基于 Websocket 实现完美的打字机体验
- 内置了各种预训练好的角色应用,轻松满足你的各种聊天和应用需求
- 支持 OPenAIAzure文心一言讯飞星火清华 ChatGLM等多个大语言模型
- 支持 MidJourney / Stable Diffusion AI 绘画集成开箱即用
- 支持使用个人微信二维码作为充值收费的支付渠道无需企业支付通道
- 已集成支付宝支付功能微信支付支持多种会员套餐和点卡购买功能
- 集成插件 API 功能可结合大语言模型的 function 功能开发各种强大的插件
`)
const md = require('markdown-it')({breaks: true}); const md = require('markdown-it')({breaks: true});
const content = ref(text.value) const content = ref(text.value)
const html = ref("") const html = ref("")
@ -135,7 +126,20 @@ const models = ref([])
const modelID = ref(0) const modelID = ref(0)
const loading = ref(false) const loading = ref(false)
onMounted(() => { httpGet("/api/config/get?key=system").then(res => {
title.value = res.data.title??process.env.VUE_APP_TITLE
text.value = `# ${title.value}
- 完整的开源系统前端应用和后台管理系统皆可开箱即用
- 基于 Websocket 实现完美的打字机体验
- 内置了各种预训练好的角色应用,轻松满足你的各种聊天和应用需求
- 支持 OPenAIAzure文心一言讯飞星火清华 ChatGLM等多个大语言模型
- 支持 MidJourney / Stable Diffusion AI 绘画集成开箱即用
- 支持使用个人微信二维码作为充值收费的支付渠道无需企业支付通道
- 已集成支付宝支付功能微信支付支持多种会员套餐和点卡购买功能
- 集成插件 API 功能可结合大语言模型的 function 功能开发各种强大的插件
`
content.value = text.value
initData() initData()
try { try {
markMap.value = Markmap.create(svgRef.value) markMap.value = Markmap.create(svgRef.value)
@ -145,7 +149,9 @@ onMounted(() => {
} catch (e) { } catch (e) {
console.error(e) console.error(e)
} }
}); }).catch(e => {
ElMessage.error("获取系统配置失败:" + e.message)
})
const initData = () => { const initData = () => {
httpGet("/api/model/list").then(res => { httpGet("/api/model/list").then(res => {

View File

@ -53,6 +53,10 @@
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="版权信息" prop="copyright">
<el-input v-model="system['copyright']" placeholder="更改此选项需要获取 License 授权"/>
</el-form-item>
<el-form-item label="开放注册" prop="enabled_register"> <el-form-item label="开放注册" prop="enabled_register">
<div class="tip-input"> <div class="tip-input">
<el-switch v-model="system['enabled_register']"/> <el-switch v-model="system['enabled_register']"/>
@ -391,11 +395,12 @@ import {InfoFilled, UploadFilled,Select,CloseBold} from "@element-plus/icons-vue
import MdEditor from "md-editor-v3"; import MdEditor from "md-editor-v3";
import 'md-editor-v3/lib/style.css'; import 'md-editor-v3/lib/style.css';
import Menu from "@/views/admin/Menu.vue"; import Menu from "@/views/admin/Menu.vue";
import {dateFormat} from "@/utils/libs"; import {copyObj, dateFormat} from "@/utils/libs";
import AIDrawing from "@/views/admin/AIDrawing.vue"; import AIDrawing from "@/views/admin/AIDrawing.vue";
const activeName = ref('basic') const activeName = ref('basic')
const system = ref({models: []}) const system = ref({models: []})
const configBak = ref({})
const loading = ref(true) const loading = ref(true)
const systemFormRef = ref(null) const systemFormRef = ref(null)
const models = ref([]) const models = ref([])
@ -407,6 +412,7 @@ onMounted(() => {
// //
httpGet('/api/admin/config/get?key=system').then(res => { httpGet('/api/admin/config/get?key=system').then(res => {
system.value = res.data system.value = res.data
configBak.value = copyObj(system.value)
}).catch(e => { }).catch(e => {
ElMessage.error("加载系统配置失败: " + e.message) ElMessage.error("加载系统配置失败: " + e.message)
}) })
@ -447,7 +453,7 @@ const save = function (key) {
systemFormRef.value.validate((valid) => { systemFormRef.value.validate((valid) => {
if (valid) { if (valid) {
system.value['power_price'] = parseFloat(system.value['power_price']) ?? 0 system.value['power_price'] = parseFloat(system.value['power_price']) ?? 0
httpPost('/api/admin/config/update', {key: key, config: system.value}).then(() => { httpPost('/api/admin/config/update', {key: key, config: system.value, config_bak: configBak.value}).then(() => {
ElMessage.success("操作成功!") ElMessage.success("操作成功!")
}).catch(e => { }).catch(e => {
ElMessage.error("操作失败:" + e.message) ElMessage.error("操作失败:" + e.message)