opt: 将短信发送按钮封装成组件

This commit is contained in:
RockYang 2023-07-03 06:55:15 +08:00
parent 72cc6f3d75
commit 1fc361242e
7 changed files with 148 additions and 204 deletions

View File

@ -89,6 +89,7 @@ func (h *UserHandler) Register(c *gin.Context) {
Avatar: "/images/avatar/user.png", Avatar: "/images/avatar/user.png",
Salt: salt, Salt: salt,
Status: true, Status: true,
Mobile: data.Mobile,
ChatRoles: utils.JsonEncode(roleKeys), ChatRoles: utils.JsonEncode(roleKeys),
ChatConfig: utils.JsonEncode(types.ChatConfig{ ChatConfig: utils.JsonEncode(types.ChatConfig{
Temperature: h.App.ChatConfig.Temperature, Temperature: h.App.ChatConfig.Temperature,

View File

@ -0,0 +1,68 @@
<template>
<el-dialog
v-model="showDialog"
:close-on-click-modal="false"
:show-close="false"
:title="title"
>
<div class="form" id="password-form">
<el-form :model="form" label-width="120px">
<el-form-item label="手机号码">
<el-input v-model="form.mobile" type="password"/>
</el-form-item>
<el-form-item label="手机验证码">
<el-row :gutter="10">
<el-col :span="12">
<el-input v-model="form.code" type="password"/>
</el-col>
<el-col :span="12">
<send-msg size="large" v-model:mobile="form.mobile"/>
</el-col>
</el-row>
</el-form-item>
</el-form>
</div>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="save">
提交绑定
</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import {ref} from "vue";
import {checkSession} from "@/action/session";
import SendMsg from "@/components/SendMsg.vue";
const title = ref('绑定手机号')
const showDialog = ref(false)
const form = ref({
mobile: '',
code: ''
})
checkSession().then(user => {
if (user.mobile === '') {
showDialog.value = true
}
}).catch(e => {
console.log(e.message)
})
const save = () => {
}
const sendMsg = () => {
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,59 @@
<template>
<el-button type="primary" class="sms-btn" :disabled="!canSend" :size="size" @click="sendMsg" plain>{{
btnText
}}
</el-button>
</template>
<script setup>
//
import {ref} from "vue";
import {validateMobile} from "@/utils/validate";
import {ElMessage} from "element-plus";
import {httpGet, httpPost} from "@/utils/http";
const props = defineProps({
mobile: String,
size: String,
});
const btnText = ref('发送验证码')
const canSend = ref(true)
const sendMsg = () => {
if (!canSend.value) {
return
}
if (!validateMobile(props.mobile)) {
return ElMessage.error("请输入合法的手机号")
}
canSend.value = false
httpGet('/api/verify/token').then(res => {
httpPost('/api/verify/sms', {token: res.data, mobile: props.mobile}).then(() => {
ElMessage.success('短信发送成功')
let time = 120
btnText.value = time
const handler = setInterval(() => {
time = time - 1
if (time <= 0) {
clearInterval(handler)
btnText.value = '重新发送'
canSend.value = true
} else {
btnText.value = time
}
}, 1000)
}).catch(e => {
canSend.value = true
ElMessage.error('短信发送失败:' + e.message)
})
}).catch(e => {
console.log('failed to fetch token: ' + e.message)
})
}
</script>
<style scoped>
</style>

11
web/src/utils/validate.js Normal file
View File

@ -0,0 +1,11 @@
// 正则校验工具函数
export function validateEmail(email) {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return regex.test(email);
}
export function validateMobile(mobile) {
const regex = /^1[345789]\d{9}$/;
return regex.test(mobile);
}

View File

@ -187,6 +187,8 @@
@update-user="updateUser"/> @update-user="updateUser"/>
<password-dialog v-if="isLogin" :show="showPasswordDialog" @hide="showPasswordDialog = false" <password-dialog v-if="isLogin" :show="showPasswordDialog" @hide="showPasswordDialog = false"
@logout="logout"/> @logout="logout"/>
<bind-mobile/>
</div> </div>
@ -219,6 +221,7 @@ import Clipboard from "clipboard";
import ConfigDialog from "@/components/ConfigDialog.vue"; import ConfigDialog from "@/components/ConfigDialog.vue";
import PasswordDialog from "@/components/PasswordDialog.vue"; import PasswordDialog from "@/components/PasswordDialog.vue";
import {checkSession} from "@/action/session"; import {checkSession} from "@/action/session";
import BindMobile from "@/components/BindMobile.vue";
const title = ref('ChatGPT-智能助手'); const title = ref('ChatGPT-智能助手');
const logo = 'images/logo.png'; const logo = 'images/logo.png';

View File

@ -76,10 +76,7 @@
</el-input> </el-input>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-button type="primary" class="sms-btn" :disabled="!canSend" size="large" @click="sendMsg" plain>{{ <send-msg size="large" :mobile="formData.mobile"/>
btnText
}}
</el-button>
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
@ -107,14 +104,14 @@
import {ref} from "vue"; import {ref} from "vue";
import {Checked, Iphone, Lock, UserFilled} from "@element-plus/icons-vue"; import {Checked, Iphone, Lock, UserFilled} from "@element-plus/icons-vue";
import {httpGet, httpPost} from "@/utils/http"; import {httpPost} from "@/utils/http";
import {ElMessage} from "element-plus"; import {ElMessage} 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";
const router = useRouter(); const router = useRouter();
const title = ref('ChatGPT-PLUS 用户注册'); const title = ref('ChatGPT-PLUS 用户注册');
const btnText = ref('发送验证码')
const formData = ref({ const formData = ref({
username: '', username: '',
password: '', password: '',
@ -142,50 +139,6 @@ const register = function () {
}) })
} }
// const validateEmail = function (email) {
// const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
// return regex.test(email);
// }
const validateMobile = function (mobile) {
const regex = /^1[345789]\d{9}$/;
return regex.test(mobile);
}
const canSend = ref(true)
const sendMsg = () => {
if (!canSend.value) {
return
}
if (!validateMobile(formData.value.mobile)) {
return ElMessage.error("请输入合法的手机号")
}
canSend.value = false
httpGet('/api/verify/token').then(res => {
httpPost('/api/verify/sms', {token: res.data, mobile: formData.value.mobile}).then(() => {
ElMessage.success('短信发送成功')
let time = 120
btnText.value = time
const handler = setInterval(() => {
time = time - 1
if (time <= 0) {
clearInterval(handler)
btnText.value = '重新发送'
canSend.value = true
} else {
btnText.value = time
}
}, 1000)
}).catch(e => {
canSend.value = true
ElMessage.error('短信发送失败:' + e.message)
})
}).catch(e => {
console.log('failed to fetch token: ' + e.message)
})
}
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>

View File

@ -1,165 +1,14 @@
<template> <template>
<div class="role-list"> <div>{{ title }}</div>
<el-form :model="form1" label-width="120px" ref="formRef" :rules="rules">
<el-form-item label="角色名称:" prop="name">
<el-input
v-model="form1.name"
autocomplete="off"
/>
</el-form-item>
<el-form-item label="角色标志:" prop="key">
<el-input
v-model="form1.key"
autocomplete="off"
/>
</el-form-item>
<el-form-item label="角色图标:" prop="icon">
<el-input
v-model="form1.icon"
autocomplete="off"
/>
</el-form-item>
<el-form-item label="打招呼信息:" prop="hello_msg">
<el-input
v-model="form1.hello_msg"
autocomplete="off"
/>
</el-form-item>
<el-form-item label="上下文信息:" prop="context">
<template #default>
<el-table :data="form1.context" :border="childBorder" size="small">
<el-table-column label="对话角色" width="120">
<template #default="scope">
<el-input
v-model="scope.row.role"
autocomplete="off"
/>
</template>
</el-table-column>
<el-table-column label="对话内容">
<template #header>
<div class="context-msg-key">
<span>对话内容</span>
<span class="fr">
<el-button type="primary" @click="addContext" size="small">
<el-icon>
<Plus/>
</el-icon>
增加一行
</el-button>
</span>
</div>
</template>
<template #default="scope">
<div class="context-msg-content">
<el-input
v-model="scope.row.content"
autocomplete="off"
/>
<span><el-icon @click="removeContext(scope.$index)"><RemoveFilled/></el-icon></span>
</div>
</template>
</el-table-column>
</el-table>
</template>
</el-form-item>
<el-form-item label="启用状态">
<el-switch v-model="form1.enable"/>
</el-form-item>
</el-form>
<span class="dialog-footer">
<el-button @click="showDialog = false">取消</el-button>
<el-button type="primary" @click="doUpdate">保存</el-button>
</span>
</div>
</template> </template>
<script setup> <script setup>
import {Plus, RemoveFilled} from "@element-plus/icons-vue"; import {ref} from "vue";
import {reactive, ref} from "vue";
import {httpPost} from "@/utils/http";
import {ElMessage} from "element-plus";
const showDialog = ref(false) const title = ref('Test Page')
const childBorder = ref(true)
const form1 = ref({context: []})
// const form2 = ref({context: []})
const formRef = ref(null)
const rules = reactive({
name: [{required: true, message: '请输入用户名', trigger: 'change',}],
key: [{required: true, message: '请输入角色标识', trigger: 'change',}],
icon: [{required: true, message: '请输入角色图标', trigger: 'change',}],
hello_msg: [{required: true, message: '请输入打招呼信息', trigger: 'change',}]
})
//
const doUpdate = function () {
formRef.value.validate((valid) => {
if (valid) {
showDialog.value = false
httpPost('/api/admin/chat-roles/set', form1.value).then(() => {
ElMessage.success('更新角色成功')
//
}).catch((e) => {
ElMessage.error('更新角色失败,' + e.message)
})
} else {
return false
}
})
}
const addContext = function () {
form1.value.context.push({role: '', content: ''})
}
const removeContext = function (index) {
form1.value.context.splice(index, 1);
}
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>
.role-list {
.opt-box {
padding-bottom: 10px;
.el-icon {
margin-right 5px;
}
}
.context-msg-key {
.fr {
float right
.el-icon {
margin-right 5px
}
}
}
.context-msg-content {
display flex
.el-icon {
font-size: 20px;
margin-top 5px;
margin-left 5px;
cursor pointer
}
}
}
</style> </style>