mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-09-19 17:56:39 +08:00
feat: 短信验证码功能已完成,手机端同步实现。
This commit is contained in:
parent
1fc361242e
commit
440169ff60
@ -184,7 +184,7 @@ func authorizeMiddleware(s *AppServer) gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
session := sessions.Default(c)
|
session := sessions.Default(c)
|
||||||
var value interface{}
|
var value interface{}
|
||||||
if strings.Contains(c.Request.URL.Path, "/api/admin/") {
|
if strings.Contains(c.Request.URL.Path, "/api/admin/") { // 后台管理 API
|
||||||
value = session.Get(types.SessionAdmin)
|
value = session.Get(types.SessionAdmin)
|
||||||
} else {
|
} else {
|
||||||
value = session.Get(types.SessionUser)
|
value = session.Get(types.SessionUser)
|
||||||
|
@ -62,8 +62,6 @@ func (h *UserHandler) Register(c *gin.Context) {
|
|||||||
if err != nil || int(code.(float64)) != data.Code {
|
if err != nil || int(code.(float64)) != data.Code {
|
||||||
resp.ERROR(c, "短信验证码错误")
|
resp.ERROR(c, "短信验证码错误")
|
||||||
return
|
return
|
||||||
} else {
|
|
||||||
_ = h.levelDB.Delete(key) // 删除短信验证码
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the username is exists
|
// check if the username is exists
|
||||||
@ -117,6 +115,7 @@ func (h *UserHandler) Register(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ = h.levelDB.Delete(key) // 注册成功,删除短信验证码
|
||||||
resp.SUCCESS(c, user)
|
resp.SUCCESS(c, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,6 +229,7 @@ type userProfile struct {
|
|||||||
Id uint `json:"id"`
|
Id uint `json:"id"`
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Nickname string `json:"nickname"`
|
Nickname string `json:"nickname"`
|
||||||
|
Mobile string `json:"mobile"`
|
||||||
Avatar string `json:"avatar"`
|
Avatar string `json:"avatar"`
|
||||||
ChatConfig types.ChatConfig `json:"chat_config"`
|
ChatConfig types.ChatConfig `json:"chat_config"`
|
||||||
Calls int `json:"calls"`
|
Calls int `json:"calls"`
|
||||||
@ -334,3 +334,46 @@ func (h *UserHandler) Password(c *gin.Context) {
|
|||||||
|
|
||||||
resp.SUCCESS(c)
|
resp.SUCCESS(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BindMobile 绑定手机号
|
||||||
|
func (h *UserHandler) BindMobile(c *gin.Context) {
|
||||||
|
var data struct {
|
||||||
|
Mobile string `json:"mobile"`
|
||||||
|
Code int `json:"code"`
|
||||||
|
}
|
||||||
|
if err := c.ShouldBindJSON(&data); err != nil {
|
||||||
|
resp.ERROR(c, types.InvalidArgs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查手机号是否被其他账号绑定
|
||||||
|
var item model.User
|
||||||
|
res := h.db.Where("mobile = ?", data.Mobile).First(&item)
|
||||||
|
if res.Error == nil {
|
||||||
|
resp.ERROR(c, "该手机号已经被其他账号绑定")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查验证码
|
||||||
|
key := CodeStorePrefix + data.Mobile
|
||||||
|
code, err := h.levelDB.Get(key)
|
||||||
|
if err != nil || int(code.(float64)) != data.Code {
|
||||||
|
resp.ERROR(c, "短信验证码错误")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := utils.GetLoginUser(c, h.db)
|
||||||
|
if err != nil {
|
||||||
|
resp.NotAuth(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res = h.db.Model(&user).UpdateColumn("mobile", data.Mobile)
|
||||||
|
if res.Error != nil {
|
||||||
|
resp.ERROR(c, "更新数据库失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = h.levelDB.Delete(key) // 删除短信验证码
|
||||||
|
resp.SUCCESS(c)
|
||||||
|
}
|
||||||
|
@ -129,6 +129,7 @@ func main() {
|
|||||||
group.GET("profile", h.Profile)
|
group.GET("profile", h.Profile)
|
||||||
group.POST("profile/update", h.ProfileUpdate)
|
group.POST("profile/update", h.ProfileUpdate)
|
||||||
group.POST("password", h.Password)
|
group.POST("password", h.Password)
|
||||||
|
group.POST("bind/mobile", h.BindMobile)
|
||||||
}),
|
}),
|
||||||
fx.Invoke(func(s *core.AppServer, h *handler.ChatHandler) {
|
fx.Invoke(func(s *core.AppServer, h *handler.ChatHandler) {
|
||||||
group := s.Engine.Group("/api/chat/")
|
group := s.Engine.Group("/api/chat/")
|
||||||
|
@ -2,24 +2,28 @@
|
|||||||
<el-dialog
|
<el-dialog
|
||||||
v-model="showDialog"
|
v-model="showDialog"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
:show-close="false"
|
:show-close="mobile !== ''"
|
||||||
|
:before-close="close"
|
||||||
:title="title"
|
:title="title"
|
||||||
>
|
>
|
||||||
<div class="form" id="password-form">
|
<div class="form" id="bind-mobile-form">
|
||||||
|
<el-alert v-if="mobile !== ''" type="info" show-icon :closable="false" style="margin-bottom: 20px;">
|
||||||
|
<p>当前用户已绑定手机号:{{ mobile }}, 绑定其他手机号之后自动解绑该手机号。</p>
|
||||||
|
</el-alert>
|
||||||
|
|
||||||
<el-form :model="form" label-width="120px">
|
<el-form :model="form" label-width="120px">
|
||||||
<el-form-item label="手机号码">
|
<el-form-item label="手机号码">
|
||||||
<el-input v-model="form.mobile" type="password"/>
|
<el-input v-model="form.mobile"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="手机验证码">
|
<el-form-item label="手机验证码">
|
||||||
<el-row :gutter="10">
|
<el-row :gutter="10">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-input v-model="form.code" type="password"/>
|
<el-input v-model.number="form.code" maxlength="6"/>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<send-msg size="large" v-model:mobile="form.mobile"/>
|
<send-msg size="" :mobile="form.mobile"/>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
@ -35,31 +39,51 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {ref} from "vue";
|
import {computed, ref} from "vue";
|
||||||
import {checkSession} from "@/action/session";
|
|
||||||
import SendMsg from "@/components/SendMsg.vue";
|
import SendMsg from "@/components/SendMsg.vue";
|
||||||
|
import {ElMessage} from "element-plus";
|
||||||
|
import {httpPost} from "@/utils/http";
|
||||||
|
import {validateMobile} from "@/utils/validate";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
show: Boolean,
|
||||||
|
mobile: String
|
||||||
|
});
|
||||||
|
|
||||||
|
const showDialog = computed(() => {
|
||||||
|
return props.show
|
||||||
|
})
|
||||||
|
|
||||||
const title = ref('绑定手机号')
|
const title = ref('绑定手机号')
|
||||||
const showDialog = ref(false)
|
|
||||||
const form = ref({
|
const form = ref({
|
||||||
mobile: '',
|
mobile: '',
|
||||||
code: ''
|
code: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
checkSession().then(user => {
|
const emits = defineEmits(['hide']);
|
||||||
if (user.mobile === '') {
|
|
||||||
showDialog.value = true
|
|
||||||
}
|
|
||||||
}).catch(e => {
|
|
||||||
console.log(e.message)
|
|
||||||
})
|
|
||||||
|
|
||||||
const save = () => {
|
const save = () => {
|
||||||
|
if (!validateMobile(form.value.mobile)) {
|
||||||
|
return ElMessage.error({message: "请输入正确的手机号码", appendTo: "#bind-mobile-form"});
|
||||||
|
}
|
||||||
|
if (form.value.code === '') {
|
||||||
|
return ElMessage.error({message: "请输入短信验证码", appendTo: "#bind-mobile-form"});
|
||||||
}
|
}
|
||||||
|
|
||||||
const sendMsg = () => {
|
httpPost('/api/user/bind/mobile', form.value).then(() => {
|
||||||
|
ElMessage.success({
|
||||||
|
message: '绑定成功',
|
||||||
|
appendTo: '#bind-mobile-form',
|
||||||
|
duration: 1000,
|
||||||
|
onClose: () => emits('hide', false)
|
||||||
|
})
|
||||||
|
}).catch(e => {
|
||||||
|
ElMessage.error({message: "绑定失败:" + e.message, appendTo: "#bind-mobile-form"});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const close = function () {
|
||||||
|
emits('hide', false);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -28,6 +28,10 @@
|
|||||||
<el-input v-model="form.username" readonly disabled/>
|
<el-input v-model="form.username" readonly disabled/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="绑定手机号">
|
||||||
|
<el-input v-model="form.mobile" readonly disabled/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="聊天上下文">
|
<el-form-item label="聊天上下文">
|
||||||
<el-switch v-model="form.chat_config.enable_context"/>
|
<el-switch v-model="form.chat_config.enable_context"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -96,6 +100,7 @@ const form = ref({
|
|||||||
username: '',
|
username: '',
|
||||||
nickname: '',
|
nickname: '',
|
||||||
avatar: '',
|
avatar: '',
|
||||||
|
mobile: '',
|
||||||
calls: 0,
|
calls: 0,
|
||||||
tokens: 0,
|
tokens: 0,
|
||||||
chat_configs: {}
|
chat_configs: {}
|
||||||
|
@ -55,6 +55,7 @@ const save = function () {
|
|||||||
ElMessage.success({
|
ElMessage.success({
|
||||||
message: '更新成功',
|
message: '更新成功',
|
||||||
appendTo: '#password-form',
|
appendTo: '#password-form',
|
||||||
|
duration: 1000,
|
||||||
onClose: () => emits('logout', false)
|
onClose: () => emits('logout', false)
|
||||||
})
|
})
|
||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-button type="primary" class="sms-btn" :disabled="!canSend" :size="size" @click="sendMsg" plain>{{
|
<el-button type="primary" :disabled="!canSend" :size="props.size" @click="sendMsg" plain>{{
|
||||||
btnText
|
btnText
|
||||||
}}
|
}}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
76
web/src/components/mobile/BindMobile.vue
Normal file
76
web/src/components/mobile/BindMobile.vue
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<template>
|
||||||
|
<van-dialog v-model:show="showDialog"
|
||||||
|
:title="title"
|
||||||
|
:show-cancel-button="mobile !== ''"
|
||||||
|
@confirm="save"
|
||||||
|
@cancel="close">
|
||||||
|
<van-cell-group inset>
|
||||||
|
<van-field
|
||||||
|
v-model="form.mobile"
|
||||||
|
label="手机号"
|
||||||
|
placeholder="请输入手机号"
|
||||||
|
/>
|
||||||
|
<van-field
|
||||||
|
v-model.number="form.code"
|
||||||
|
center
|
||||||
|
clearable
|
||||||
|
label="短信验证码"
|
||||||
|
placeholder="请输入短信验证码"
|
||||||
|
>
|
||||||
|
<template #button>
|
||||||
|
<!-- <van-button size="small" type="primary">发送验证码</van-button>-->
|
||||||
|
<send-msg size="small" :mobile="form.mobile"/>
|
||||||
|
</template>
|
||||||
|
</van-field>
|
||||||
|
</van-cell-group>
|
||||||
|
</van-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {computed, ref} from "vue";
|
||||||
|
import SendMsg from "@/components/mobile/SendMsg.vue";
|
||||||
|
import {ElMessage} from "element-plus";
|
||||||
|
import {httpPost} from "@/utils/http";
|
||||||
|
import {validateMobile} from "@/utils/validate";
|
||||||
|
import {showNotify} from "vant";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
show: Boolean,
|
||||||
|
mobile: String
|
||||||
|
});
|
||||||
|
|
||||||
|
const showDialog = computed(() => {
|
||||||
|
return props.show
|
||||||
|
})
|
||||||
|
|
||||||
|
const title = ref('绑定手机号')
|
||||||
|
const form = ref({
|
||||||
|
mobile: '',
|
||||||
|
code: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const emits = defineEmits(['hide']);
|
||||||
|
|
||||||
|
const save = () => {
|
||||||
|
if (!validateMobile(form.value.mobile)) {
|
||||||
|
return showNotify({type: 'danger', message: '请输入正确的手机号码'});
|
||||||
|
}
|
||||||
|
if (form.value.code === '') {
|
||||||
|
return showNotify({type: "danger", message: '请输入短信验证码'})
|
||||||
|
}
|
||||||
|
|
||||||
|
httpPost('/api/user/bind/mobile', form.value).then(() => {
|
||||||
|
showNotify({type: 'success', message: '绑定成功', duration: 1000, onClose: emits('hide', false)});
|
||||||
|
}).catch(e => {
|
||||||
|
showNotify({type: 'danger', message: '绑定失败:' + e.message, duration: 2000});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const close = function () {
|
||||||
|
emits('hide', false);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
62
web/src/components/mobile/SendMsg.vue
Normal file
62
web/src/components/mobile/SendMsg.vue
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<template>
|
||||||
|
<van-button size="small"
|
||||||
|
type="primary"
|
||||||
|
:disabled="!canSend"
|
||||||
|
:size="props.size"
|
||||||
|
@click="sendMsg">{{ btnText }}
|
||||||
|
</van-button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
// 发送短信验证码组件
|
||||||
|
import {ref} from "vue";
|
||||||
|
import {validateMobile} from "@/utils/validate";
|
||||||
|
import {ElMessage} from "element-plus";
|
||||||
|
import {httpGet, httpPost} from "@/utils/http";
|
||||||
|
import {showNotify} from "vant";
|
||||||
|
|
||||||
|
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 showNotify({type: 'danger', message: '请输入合法的手机号'})
|
||||||
|
}
|
||||||
|
canSend.value = false
|
||||||
|
httpGet('/api/verify/token').then(res => {
|
||||||
|
httpPost('/api/verify/sms', {token: res.data, mobile: props.mobile}).then(() => {
|
||||||
|
showNotify({type: 'success', message: '短信发送成功'})
|
||||||
|
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
|
||||||
|
showNotify({type: 'danger', message: '短信发送失败:' + e.message})
|
||||||
|
})
|
||||||
|
}).catch(e => {
|
||||||
|
console.log('failed to fetch token: ' + e.message)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -60,6 +60,13 @@
|
|||||||
<span>修改密码</span>
|
<span>修改密码</span>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
|
|
||||||
|
<el-dropdown-item @click="showBindMobileDialog = true">
|
||||||
|
<el-icon>
|
||||||
|
<Iphone/>
|
||||||
|
</el-icon>
|
||||||
|
<span>绑定手机号</span>
|
||||||
|
</el-dropdown-item>
|
||||||
|
|
||||||
<el-dropdown-item @click="clearAllChats">
|
<el-dropdown-item @click="clearAllChats">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<Delete/>
|
<Delete/>
|
||||||
@ -188,7 +195,8 @@
|
|||||||
<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/>
|
<bind-mobile v-if="isLogin" :show="showBindMobileDialog" :mobile="loginUser.mobile"
|
||||||
|
@hide="showBindMobileDialog = false"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
@ -202,7 +210,7 @@ import {
|
|||||||
Check,
|
Check,
|
||||||
Close,
|
Close,
|
||||||
Delete,
|
Delete,
|
||||||
Edit,
|
Edit, Iphone,
|
||||||
Plus,
|
Plus,
|
||||||
Promotion,
|
Promotion,
|
||||||
RefreshRight,
|
RefreshRight,
|
||||||
@ -242,6 +250,7 @@ const newChatItem = ref(null);
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const showConfigDialog = ref(false);
|
const showConfigDialog = ref(false);
|
||||||
const showPasswordDialog = ref(false);
|
const showPasswordDialog = ref(false);
|
||||||
|
const showBindMobileDialog = ref(false);
|
||||||
const isLogin = ref(false)
|
const isLogin = ref(false)
|
||||||
|
|
||||||
if (isMobile()) {
|
if (isMobile()) {
|
||||||
@ -253,6 +262,9 @@ onMounted(() => {
|
|||||||
checkSession().then((user) => {
|
checkSession().then((user) => {
|
||||||
loginUser.value = user
|
loginUser.value = user
|
||||||
isLogin.value = true
|
isLogin.value = true
|
||||||
|
if (user.mobile === '') {
|
||||||
|
showBindMobileDialog.value = true
|
||||||
|
}
|
||||||
// 加载角色列表
|
// 加载角色列表
|
||||||
httpGet(`/api/role/list?user_id=${user.id}`).then((res) => {
|
httpGet(`/api/role/list?user_id=${user.id}`).then((res) => {
|
||||||
roles.value = res.data;
|
roles.value = res.data;
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
<div class="header">{{ title }}</div>
|
<div class="header">{{ title }}</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<el-form :model="formData" label-width="120px" ref="formRef" :rules="rules">
|
<el-form :model="formData" label-width="120px" ref="formRef">
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<el-input placeholder="请输入用户名(4-30位)"
|
<el-input placeholder="请输入用户名(4-30位)"
|
||||||
size="large" maxlength="30"
|
size="large" maxlength="30"
|
||||||
@ -115,7 +115,7 @@ const title = ref('ChatGPT-PLUS 用户注册');
|
|||||||
const formData = ref({
|
const formData = ref({
|
||||||
username: '',
|
username: '',
|
||||||
password: '',
|
password: '',
|
||||||
mobile: '18575670125',
|
mobile: '',
|
||||||
code: '',
|
code: '',
|
||||||
repass: '',
|
repass: '',
|
||||||
})
|
})
|
||||||
|
@ -63,6 +63,9 @@
|
|||||||
</template>
|
</template>
|
||||||
</van-picker>
|
</van-picker>
|
||||||
</van-popup>
|
</van-popup>
|
||||||
|
|
||||||
|
<bind-mobile v-if="isLogin" :show="showBindMobileDialog" :mobile="loginUser.mobile"
|
||||||
|
@hide="showBindMobileDialog = false"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -74,6 +77,7 @@ import {checkSession} from "@/action/session";
|
|||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
import {setChatConfig} from "@/store/chat";
|
import {setChatConfig} from "@/store/chat";
|
||||||
import {removeArrayItem} from "@/utils/libs";
|
import {removeArrayItem} from "@/utils/libs";
|
||||||
|
import BindMobile from "@/components/mobile/BindMobile.vue";
|
||||||
|
|
||||||
const title = ref("会话列表")
|
const title = ref("会话列表")
|
||||||
const chatName = ref("")
|
const chatName = ref("")
|
||||||
@ -88,10 +92,14 @@ const roles = ref([])
|
|||||||
const models = ref([])
|
const models = ref([])
|
||||||
const showPicker = ref(false)
|
const showPicker = ref(false)
|
||||||
const columns = ref([roles.value, models.value])
|
const columns = ref([roles.value, models.value])
|
||||||
|
const showBindMobileDialog = ref(false)
|
||||||
|
|
||||||
checkSession().then((user) => {
|
checkSession().then((user) => {
|
||||||
loginUser.value = user
|
loginUser.value = user
|
||||||
isLogin.value = true
|
isLogin.value = true
|
||||||
|
if (user.mobile === '') {
|
||||||
|
showBindMobileDialog.value = true
|
||||||
|
}
|
||||||
// 加载角色列表
|
// 加载角色列表
|
||||||
httpGet(`/api/role/list?user_id=${user.id}`).then((res) => {
|
httpGet(`/api/role/list?user_id=${user.id}`).then((res) => {
|
||||||
if (res.data) {
|
if (res.data) {
|
||||||
|
@ -13,6 +13,14 @@
|
|||||||
disabled
|
disabled
|
||||||
placeholder="用户名"
|
placeholder="用户名"
|
||||||
/>
|
/>
|
||||||
|
<van-field
|
||||||
|
v-model="form.mobile"
|
||||||
|
name="手机号"
|
||||||
|
label="手机号"
|
||||||
|
readonly
|
||||||
|
disabled
|
||||||
|
placeholder="手机号"
|
||||||
|
/>
|
||||||
<van-field
|
<van-field
|
||||||
v-model="form.nickname"
|
v-model="form.nickname"
|
||||||
name="昵称"
|
name="昵称"
|
||||||
@ -61,6 +69,7 @@ const title = ref('用户设置')
|
|||||||
const form = ref({
|
const form = ref({
|
||||||
username: '',
|
username: '',
|
||||||
nickname: '',
|
nickname: '',
|
||||||
|
mobile: '',
|
||||||
avatar: '',
|
avatar: '',
|
||||||
calls: 0,
|
calls: 0,
|
||||||
tokens: 0
|
tokens: 0
|
||||||
|
Loading…
Reference in New Issue
Block a user