mirror of
				https://github.com/yangjian102621/geekai.git
				synced 2025-11-04 16:23:42 +08:00 
			
		
		
		
	feat: 短信验证码功能已完成,手机端同步实现。
This commit is contained in:
		@@ -184,7 +184,7 @@ func authorizeMiddleware(s *AppServer) gin.HandlerFunc {
 | 
			
		||||
		}
 | 
			
		||||
		session := sessions.Default(c)
 | 
			
		||||
		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)
 | 
			
		||||
		} else {
 | 
			
		||||
			value = session.Get(types.SessionUser)
 | 
			
		||||
 
 | 
			
		||||
@@ -62,8 +62,6 @@ func (h *UserHandler) Register(c *gin.Context) {
 | 
			
		||||
	if err != nil || int(code.(float64)) != data.Code {
 | 
			
		||||
		resp.ERROR(c, "短信验证码错误")
 | 
			
		||||
		return
 | 
			
		||||
	} else {
 | 
			
		||||
		_ = h.levelDB.Delete(key) // 删除短信验证码
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// check if the username is exists
 | 
			
		||||
@@ -117,6 +115,7 @@ func (h *UserHandler) Register(c *gin.Context) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_ = h.levelDB.Delete(key) // 注册成功,删除短信验证码
 | 
			
		||||
	resp.SUCCESS(c, user)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -230,6 +229,7 @@ type userProfile struct {
 | 
			
		||||
	Id         uint             `json:"id"`
 | 
			
		||||
	Username   string           `json:"username"`
 | 
			
		||||
	Nickname   string           `json:"nickname"`
 | 
			
		||||
	Mobile     string           `json:"mobile"`
 | 
			
		||||
	Avatar     string           `json:"avatar"`
 | 
			
		||||
	ChatConfig types.ChatConfig `json:"chat_config"`
 | 
			
		||||
	Calls      int              `json:"calls"`
 | 
			
		||||
@@ -334,3 +334,46 @@ func (h *UserHandler) Password(c *gin.Context) {
 | 
			
		||||
 | 
			
		||||
	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.POST("profile/update", h.ProfileUpdate)
 | 
			
		||||
			group.POST("password", h.Password)
 | 
			
		||||
			group.POST("bind/mobile", h.BindMobile)
 | 
			
		||||
		}),
 | 
			
		||||
		fx.Invoke(func(s *core.AppServer, h *handler.ChatHandler) {
 | 
			
		||||
			group := s.Engine.Group("/api/chat/")
 | 
			
		||||
 
 | 
			
		||||
@@ -2,24 +2,28 @@
 | 
			
		||||
  <el-dialog
 | 
			
		||||
      v-model="showDialog"
 | 
			
		||||
      :close-on-click-modal="false"
 | 
			
		||||
      :show-close="false"
 | 
			
		||||
      :show-close="mobile !== ''"
 | 
			
		||||
      :before-close="close"
 | 
			
		||||
      :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-item label="手机号码">
 | 
			
		||||
          <el-input v-model="form.mobile" type="password"/>
 | 
			
		||||
          <el-input v-model="form.mobile"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="手机验证码">
 | 
			
		||||
          <el-row :gutter="10">
 | 
			
		||||
            <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 :span="12">
 | 
			
		||||
              <send-msg size="large" v-model:mobile="form.mobile"/>
 | 
			
		||||
              <send-msg size="" :mobile="form.mobile"/>
 | 
			
		||||
            </el-col>
 | 
			
		||||
          </el-row>
 | 
			
		||||
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
    </div>
 | 
			
		||||
@@ -35,31 +39,51 @@
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup>
 | 
			
		||||
import {ref} from "vue";
 | 
			
		||||
import {checkSession} from "@/action/session";
 | 
			
		||||
import {computed, ref} from "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 showDialog = ref(false)
 | 
			
		||||
const form = ref({
 | 
			
		||||
  mobile: '',
 | 
			
		||||
  code: ''
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
checkSession().then(user => {
 | 
			
		||||
  if (user.mobile === '') {
 | 
			
		||||
    showDialog.value = true
 | 
			
		||||
  }
 | 
			
		||||
}).catch(e => {
 | 
			
		||||
  console.log(e.message)
 | 
			
		||||
})
 | 
			
		||||
const emits = defineEmits(['hide']);
 | 
			
		||||
 | 
			
		||||
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"});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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 sendMsg = () => {
 | 
			
		||||
 | 
			
		||||
const close = function () {
 | 
			
		||||
  emits('hide', false);
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -28,6 +28,10 @@
 | 
			
		||||
          <el-input v-model="form.username" readonly disabled/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
 | 
			
		||||
        <el-form-item label="绑定手机号">
 | 
			
		||||
          <el-input v-model="form.mobile" readonly disabled/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
 | 
			
		||||
        <el-form-item label="聊天上下文">
 | 
			
		||||
          <el-switch v-model="form.chat_config.enable_context"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
@@ -96,6 +100,7 @@ const form = ref({
 | 
			
		||||
  username: '',
 | 
			
		||||
  nickname: '',
 | 
			
		||||
  avatar: '',
 | 
			
		||||
  mobile: '',
 | 
			
		||||
  calls: 0,
 | 
			
		||||
  tokens: 0,
 | 
			
		||||
  chat_configs: {}
 | 
			
		||||
 
 | 
			
		||||
@@ -55,6 +55,7 @@ const save = function () {
 | 
			
		||||
    ElMessage.success({
 | 
			
		||||
      message: '更新成功',
 | 
			
		||||
      appendTo: '#password-form',
 | 
			
		||||
      duration: 1000,
 | 
			
		||||
      onClose: () => emits('logout', false)
 | 
			
		||||
    })
 | 
			
		||||
  }).catch((e) => {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
<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
 | 
			
		||||
    }}
 | 
			
		||||
  </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>
 | 
			
		||||
                </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-icon>
 | 
			
		||||
                    <Delete/>
 | 
			
		||||
@@ -188,7 +195,8 @@
 | 
			
		||||
    <password-dialog v-if="isLogin" :show="showPasswordDialog" @hide="showPasswordDialog = false"
 | 
			
		||||
                     @logout="logout"/>
 | 
			
		||||
 | 
			
		||||
    <bind-mobile/>
 | 
			
		||||
    <bind-mobile v-if="isLogin" :show="showBindMobileDialog" :mobile="loginUser.mobile"
 | 
			
		||||
                 @hide="showBindMobileDialog = false"/>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -202,7 +210,7 @@ import {
 | 
			
		||||
  Check,
 | 
			
		||||
  Close,
 | 
			
		||||
  Delete,
 | 
			
		||||
  Edit,
 | 
			
		||||
  Edit, Iphone,
 | 
			
		||||
  Plus,
 | 
			
		||||
  Promotion,
 | 
			
		||||
  RefreshRight,
 | 
			
		||||
@@ -242,6 +250,7 @@ const newChatItem = ref(null);
 | 
			
		||||
const router = useRouter();
 | 
			
		||||
const showConfigDialog = ref(false);
 | 
			
		||||
const showPasswordDialog = ref(false);
 | 
			
		||||
const showBindMobileDialog = ref(false);
 | 
			
		||||
const isLogin = ref(false)
 | 
			
		||||
 | 
			
		||||
if (isMobile()) {
 | 
			
		||||
@@ -253,6 +262,9 @@ onMounted(() => {
 | 
			
		||||
  checkSession().then((user) => {
 | 
			
		||||
    loginUser.value = user
 | 
			
		||||
    isLogin.value = true
 | 
			
		||||
    if (user.mobile === '') {
 | 
			
		||||
      showBindMobileDialog.value = true
 | 
			
		||||
    }
 | 
			
		||||
    // 加载角色列表
 | 
			
		||||
    httpGet(`/api/role/list?user_id=${user.id}`).then((res) => {
 | 
			
		||||
      roles.value = res.data;
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
 | 
			
		||||
        <div class="header">{{ title }}</div>
 | 
			
		||||
        <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">
 | 
			
		||||
              <el-input placeholder="请输入用户名(4-30位)"
 | 
			
		||||
                        size="large" maxlength="30"
 | 
			
		||||
@@ -115,7 +115,7 @@ const title = ref('ChatGPT-PLUS 用户注册');
 | 
			
		||||
const formData = ref({
 | 
			
		||||
  username: '',
 | 
			
		||||
  password: '',
 | 
			
		||||
  mobile: '18575670125',
 | 
			
		||||
  mobile: '',
 | 
			
		||||
  code: '',
 | 
			
		||||
  repass: '',
 | 
			
		||||
})
 | 
			
		||||
 
 | 
			
		||||
@@ -63,6 +63,9 @@
 | 
			
		||||
        </template>
 | 
			
		||||
      </van-picker>
 | 
			
		||||
    </van-popup>
 | 
			
		||||
 | 
			
		||||
    <bind-mobile v-if="isLogin" :show="showBindMobileDialog" :mobile="loginUser.mobile"
 | 
			
		||||
                 @hide="showBindMobileDialog = false"/>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
@@ -74,6 +77,7 @@ import {checkSession} from "@/action/session";
 | 
			
		||||
import router from "@/router";
 | 
			
		||||
import {setChatConfig} from "@/store/chat";
 | 
			
		||||
import {removeArrayItem} from "@/utils/libs";
 | 
			
		||||
import BindMobile from "@/components/mobile/BindMobile.vue";
 | 
			
		||||
 | 
			
		||||
const title = ref("会话列表")
 | 
			
		||||
const chatName = ref("")
 | 
			
		||||
@@ -88,10 +92,14 @@ const roles = ref([])
 | 
			
		||||
const models = ref([])
 | 
			
		||||
const showPicker = ref(false)
 | 
			
		||||
const columns = ref([roles.value, models.value])
 | 
			
		||||
const showBindMobileDialog = ref(false)
 | 
			
		||||
 | 
			
		||||
checkSession().then((user) => {
 | 
			
		||||
  loginUser.value = user
 | 
			
		||||
  isLogin.value = true
 | 
			
		||||
  if (user.mobile === '') {
 | 
			
		||||
    showBindMobileDialog.value = true
 | 
			
		||||
  }
 | 
			
		||||
  // 加载角色列表
 | 
			
		||||
  httpGet(`/api/role/list?user_id=${user.id}`).then((res) => {
 | 
			
		||||
    if (res.data) {
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,14 @@
 | 
			
		||||
              disabled
 | 
			
		||||
              placeholder="用户名"
 | 
			
		||||
          />
 | 
			
		||||
          <van-field
 | 
			
		||||
              v-model="form.mobile"
 | 
			
		||||
              name="手机号"
 | 
			
		||||
              label="手机号"
 | 
			
		||||
              readonly
 | 
			
		||||
              disabled
 | 
			
		||||
              placeholder="手机号"
 | 
			
		||||
          />
 | 
			
		||||
          <van-field
 | 
			
		||||
              v-model="form.nickname"
 | 
			
		||||
              name="昵称"
 | 
			
		||||
@@ -61,6 +69,7 @@ const title = ref('用户设置')
 | 
			
		||||
const form = ref({
 | 
			
		||||
  username: '',
 | 
			
		||||
  nickname: '',
 | 
			
		||||
  mobile: '',
 | 
			
		||||
  avatar: '',
 | 
			
		||||
  calls: 0,
 | 
			
		||||
  tokens: 0
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user