feat: add support for registing use force use invite code

This commit is contained in:
RockYang 2023-11-24 12:02:28 +08:00
parent 67d30353f0
commit d68f2ef12c
9 changed files with 83 additions and 48 deletions

View File

@ -140,12 +140,12 @@ type SystemConfig struct {
Title string `json:"title"` Title string `json:"title"`
AdminTitle string `json:"admin_title"` AdminTitle string `json:"admin_title"`
Models []string `json:"models"` Models []string `json:"models"`
InitChatCalls int `json:"init_chat_calls"` // 新用户注册赠送对话次数 InitChatCalls int `json:"init_chat_calls"` // 新用户注册赠送对话次数
InitImgCalls int `json:"init_img_calls"` // 新用户注册赠送绘图次数 InitImgCalls int `json:"init_img_calls"` // 新用户注册赠送绘图次数
VipMonthCalls int `json:"vip_month_calls"` // 会员每个赠送的调用次数 VipMonthCalls int `json:"vip_month_calls"` // 会员每个赠送的调用次数
EnabledRegister bool `json:"enabled_register"` EnabledRegister bool `json:"enabled_register"` // 是否启用注册功能,关闭注册功能之后将无法注册
EnabledMsg bool `json:"enabled_msg"` // 启用短信验证码服务 EnabledMsg bool `json:"enabled_msg"` // 是否启用短信验证码服务
EnabledDraw bool `json:"enabled_draw"` // 启动 AI 绘画功能 EnabledDraw bool `json:"enabled_draw"` // 是否启用 AI 绘画功能
RewardImg string `json:"reward_img"` // 众筹收款二维码地址 RewardImg string `json:"reward_img"` // 众筹收款二维码地址
EnabledFunction bool `json:"enabled_function"` // 启用 API 函数功能 EnabledFunction bool `json:"enabled_function"` // 启用 API 函数功能
EnabledReward bool `json:"enabled_reward"` // 启用众筹功能 EnabledReward bool `json:"enabled_reward"` // 启用众筹功能
@ -155,4 +155,5 @@ type SystemConfig struct {
OrderPayInfoText string `json:"order_pay_info_text"` // 订单支付页面说明文字 OrderPayInfoText string `json:"order_pay_info_text"` // 订单支付页面说明文字
InviteChatCalls int `json:"invite_chat_calls"` // 邀请用户注册奖励对话次数 InviteChatCalls int `json:"invite_chat_calls"` // 邀请用户注册奖励对话次数
InviteImgCalls int `json:"invite_img_calls"` // 邀请用户注册奖励绘图次数 InviteImgCalls int `json:"invite_img_calls"` // 邀请用户注册奖励绘图次数
ForceInvite bool `json:"force_invite"` // 是否强制必须使用邀请码才能注册
} }

View File

@ -58,13 +58,3 @@ func (h *SmsHandler) SendCode(c *gin.Context) {
resp.SUCCESS(c) resp.SUCCESS(c)
} }
type statusVo struct {
EnabledMsgService bool `json:"enabled_msg_service"`
EnabledRegister bool `json:"enabled_register"`
}
// Status check if the message service is enabled
func (h *SmsHandler) Status(c *gin.Context) {
resp.SUCCESS(c, statusVo{EnabledMsgService: h.App.SysConfig.EnabledMsg, EnabledRegister: h.App.SysConfig.EnabledRegister})
}

View File

@ -71,7 +71,12 @@ func (h *UserHandler) Register(c *gin.Context) {
// 验证邀请码 // 验证邀请码
inviteCode := model.InviteCode{} inviteCode := model.InviteCode{}
if data.InviteCode != "" { if data.InviteCode == "" {
if h.App.SysConfig.ForceInvite {
resp.ERROR(c, "当前系统设定必须使用邀请码才能注册")
return
}
} else {
res := h.db.Where("code = ?", data.InviteCode).First(&inviteCode) res := h.db.Where("code = ?", data.InviteCode).First(&inviteCode)
if res.Error != nil { if res.Error != nil {
resp.ERROR(c, "无效的邀请码") resp.ERROR(c, "无效的邀请码")

View File

@ -237,7 +237,6 @@ func main() {
}), }),
fx.Invoke(func(s *core.AppServer, h *handler.SmsHandler) { fx.Invoke(func(s *core.AppServer, h *handler.SmsHandler) {
group := s.Engine.Group("/api/sms/") group := s.Engine.Group("/api/sms/")
group.GET("status", h.Status)
group.POST("code", h.SendCode) group.POST("code", h.SendCode)
}), }),
fx.Invoke(func(s *core.AppServer, h *handler.CaptchaHandler) { fx.Invoke(func(s *core.AppServer, h *handler.CaptchaHandler) {

View File

@ -4,6 +4,7 @@ import (
"chatplus/core/types" "chatplus/core/types"
"chatplus/service/mj" "chatplus/service/mj"
"chatplus/utils" "chatplus/utils"
"errors"
) )
// AI 绘画函数 // AI 绘画函数
@ -11,15 +12,21 @@ import (
type FuncMidJourney struct { type FuncMidJourney struct {
name string name string
service *mj.Service service *mj.Service
config types.MidJourneyConfig
} }
func NewMidJourneyFunc(mjService *mj.Service) FuncMidJourney { func NewMidJourneyFunc(mjService *mj.Service, config types.MidJourneyConfig) FuncMidJourney {
return FuncMidJourney{ return FuncMidJourney{
name: "MidJourney AI 绘画", name: "MidJourney AI 绘画",
config: config,
service: mjService} service: mjService}
} }
func (f FuncMidJourney) Invoke(params map[string]interface{}) (string, error) { func (f FuncMidJourney) Invoke(params map[string]interface{}) (string, error) {
if !f.config.Enabled {
return "", errors.New("MidJourney AI 绘画功能没有启用")
}
logger.Infof("MJ 绘画参数:%+v", params) logger.Infof("MJ 绘画参数:%+v", params)
prompt := utils.InterfaceToString(params["prompt"]) prompt := utils.InterfaceToString(params["prompt"])
f.service.PushTask(types.MjTask{ f.service.PushTask(types.MjTask{

View File

@ -34,6 +34,6 @@ func NewFunctions(config *types.AppConfig, mjService *mj.Service) map[string]Fun
types.FuncZaoBao: NewZaoBao(config.ApiConfig), types.FuncZaoBao: NewZaoBao(config.ApiConfig),
types.FuncWeibo: NewWeiboHot(config.ApiConfig), types.FuncWeibo: NewWeiboHot(config.ApiConfig),
types.FuncHeadLine: NewHeadLines(config.ApiConfig), types.FuncHeadLine: NewHeadLines(config.ApiConfig),
types.FuncMidJourney: NewMidJourneyFunc(mjService), types.FuncMidJourney: NewMidJourneyFunc(mjService, config.MjConfig),
} }
} }

View File

@ -78,7 +78,7 @@
<h2>您推荐用户</h2> <h2>您推荐用户</h2>
<div class="invite-logs"> <div class="invite-logs">
<invite-list/> <invite-list v-if="isLogin"/>
</div> </div>
</div> </div>
</div> </div>
@ -91,6 +91,8 @@ import {httpGet} from "@/utils/http";
import {ElMessage} from "element-plus"; import {ElMessage} from "element-plus";
import Clipboard from "clipboard"; import Clipboard from "clipboard";
import InviteList from "@/components/InviteList.vue"; import InviteList from "@/components/InviteList.vue";
import {checkSession} from "@/action/session";
import {useRouter} from "vue-router";
const inviteURL = ref("") const inviteURL = ref("")
const qrImg = ref("") const qrImg = ref("")
@ -100,34 +102,40 @@ const users = ref([])
const hits = ref(0) const hits = ref(0)
const regNum = ref(0) const regNum = ref(0)
const rate = ref(0) const rate = ref(0)
const router = useRouter()
const isLogin = ref(false)
onMounted(() => { onMounted(() => {
httpGet("/api/invite/code").then(res => { checkSession().then(() => {
const text = `${location.protocol}//${location.host}/register?invite_code=${res.data.code}` isLogin.value = true
hits.value = res.data["hits"] httpGet("/api/invite/code").then(res => {
regNum.value = res.data["reg_num"] const text = `${location.protocol}//${location.host}/register?invite_code=${res.data.code}`
if (hits.value > 0) { hits.value = res.data["hits"]
rate.value = ((regNum.value / hits.value) * 100).toFixed(2) regNum.value = res.data["reg_num"]
} if (hits.value > 0) {
QRCode.toDataURL(text, {width: 400, height: 400, margin: 2}, (error, url) => { rate.value = ((regNum.value / hits.value) * 100).toFixed(2)
if (error) {
console.error(error)
} else {
qrImg.value = url;
} }
}); QRCode.toDataURL(text, {width: 400, height: 400, margin: 2}, (error, url) => {
inviteURL.value = text if (error) {
}).catch(e => { console.error(error)
ElMessage.error("获取邀请码失败:" + e.message) } else {
}) qrImg.value = url;
}
});
inviteURL.value = text
}).catch(e => {
ElMessage.error("获取邀请码失败:" + e.message)
})
httpGet("/api/admin/config/get?key=system").then(res => { httpGet("/api/admin/config/get?key=system").then(res => {
inviteChatCalls.value = res.data["invite_chat_calls"] inviteChatCalls.value = res.data["invite_chat_calls"]
inviteImgCalls.value = res.data["invite_img_calls"] inviteImgCalls.value = res.data["invite_img_calls"]
}).catch(e => { }).catch(e => {
ElMessage.error("获取系统配置失败:" + e.message) ElMessage.error("获取系统配置失败:" + e.message)
}) })
}).catch(() => {
router.push('/login')
});
// //
const clipboard = new Clipboard('.copy-link'); const clipboard = new Clipboard('.copy-link');

View File

@ -118,7 +118,7 @@
import {ref} from "vue"; import {ref} from "vue";
import {Checked, Iphone, Lock, Message} from "@element-plus/icons-vue"; import {Checked, Iphone, Lock, Message} from "@element-plus/icons-vue";
import {httpGet, httpPost} from "@/utils/http"; import {httpGet, httpPost} from "@/utils/http";
import {ElMessage} from "element-plus"; import {ElMessage, ElNotification} from "element-plus";
import {useRouter} from "vue-router"; import {useRouter} from "vue-router";
import FooterBar from "@/components/FooterBar.vue"; import FooterBar from "@/components/FooterBar.vue";
import SendMsg from "@/components/SendMsg.vue"; import SendMsg from "@/components/SendMsg.vue";
@ -141,11 +141,23 @@ const enableMsg = ref(false)
const enableRegister = ref(true) const enableRegister = ref(true)
const wxImg = ref("/images/wx.png") const wxImg = ref("/images/wx.png")
httpGet('/api/sms/status').then(res => { httpGet("/api/admin/config/get?key=system").then(res => {
if (res.data) { if (res.data) {
enableMsg.value = res.data['enabled_msg_service'] enableMsg.value = res.data['enabled_msg']
enableRegister.value = res.data['enabled_register'] enableRegister.value = res.data['enabled_register']
console.log(res.data)
if (res.data['force_invite']) {
ElNotification({
title: '提示:',
dangerouslyUseHTMLString: true,
message: '当前系统开启了强制邀请注册功能,必须有邀请码才能注册哦。扫描下面二维码获取邀请码。<br/> <img alt="qrcode" src="/images/wx.png" />',
type: 'info',
duration: 0,
})
}
} }
}).catch(e => {
ElMessage.error("获取系统配置失败:" + e.message)
}) })
httpGet("/api/invite/hits", {code: formData.value.invite_code}).then(() => { httpGet("/api/invite/hits", {code: formData.value.invite_code}).then(() => {

View File

@ -27,6 +27,19 @@
<el-form-item label="开放注册服务" prop="enabled_register"> <el-form-item label="开放注册服务" prop="enabled_register">
<el-switch v-model="system['enabled_register']"/> <el-switch v-model="system['enabled_register']"/>
</el-form-item> </el-form-item>
<el-form-item label="强制邀请码注册" prop="force_invite">
<el-switch v-model="system['force_invite']"/>
<el-tooltip
effect="dark"
content="开启之后,用户必须使用邀请码才能注册"
raw-content
placement="right"
>
<el-icon>
<InfoFilled/>
</el-icon>
</el-tooltip>
</el-form-item>
<el-form-item label="短信服务" prop="enabled_msg"> <el-form-item label="短信服务" prop="enabled_msg">
<el-switch v-model="system['enabled_msg']"/> <el-switch v-model="system['enabled_msg']"/>
<el-tooltip <el-tooltip