mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-11-06 09:13:47 +08:00
feat: reset password function is ready
This commit is contained in:
@@ -139,6 +139,7 @@ func corsMiddleware() gin.HandlerFunc {
|
|||||||
func authorizeMiddleware(s *AppServer, client *redis.Client) gin.HandlerFunc {
|
func authorizeMiddleware(s *AppServer, client *redis.Client) gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
if c.Request.URL.Path == "/api/user/login" ||
|
if c.Request.URL.Path == "/api/user/login" ||
|
||||||
|
c.Request.URL.Path == "/api/user/resetPass" ||
|
||||||
c.Request.URL.Path == "/api/admin/login" ||
|
c.Request.URL.Path == "/api/admin/login" ||
|
||||||
c.Request.URL.Path == "/api/user/register" ||
|
c.Request.URL.Path == "/api/user/register" ||
|
||||||
c.Request.URL.Path == "/api/chat/history" ||
|
c.Request.URL.Path == "/api/chat/history" ||
|
||||||
|
|||||||
@@ -275,8 +275,8 @@ func (h *UserHandler) ProfileUpdate(c *gin.Context) {
|
|||||||
resp.SUCCESS(c)
|
resp.SUCCESS(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Password 更新密码
|
// UpdatePass 更新密码
|
||||||
func (h *UserHandler) Password(c *gin.Context) {
|
func (h *UserHandler) UpdatePass(c *gin.Context) {
|
||||||
var data struct {
|
var data struct {
|
||||||
OldPass string `json:"old_pass"`
|
OldPass string `json:"old_pass"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
@@ -315,6 +315,46 @@ func (h *UserHandler) Password(c *gin.Context) {
|
|||||||
resp.SUCCESS(c)
|
resp.SUCCESS(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResetPass 重置密码
|
||||||
|
func (h *UserHandler) ResetPass(c *gin.Context) {
|
||||||
|
var data struct {
|
||||||
|
Mobile string
|
||||||
|
Code string // 验证码
|
||||||
|
Password string // 新密码
|
||||||
|
}
|
||||||
|
if err := c.ShouldBindJSON(&data); err != nil {
|
||||||
|
resp.ERROR(c, types.InvalidArgs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var user model.User
|
||||||
|
res := h.db.Where("mobile", data.Mobile).First(&user)
|
||||||
|
if res.Error != nil {
|
||||||
|
resp.ERROR(c, "用户不存在!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查验证码
|
||||||
|
key := CodeStorePrefix + data.Mobile
|
||||||
|
if h.App.SysConfig.EnabledMsg {
|
||||||
|
code, err := h.redis.Get(c, key).Result()
|
||||||
|
if err != nil || code != data.Code {
|
||||||
|
resp.ERROR(c, "短信验证码错误")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
password := utils.GenPassword(data.Password, user.Salt)
|
||||||
|
user.Password = password
|
||||||
|
res = h.db.Updates(&user)
|
||||||
|
if res.Error != nil {
|
||||||
|
resp.ERROR(c)
|
||||||
|
} else {
|
||||||
|
h.redis.Del(c, key)
|
||||||
|
resp.SUCCESS(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// BindMobile 绑定手机号
|
// BindMobile 绑定手机号
|
||||||
func (h *UserHandler) BindMobile(c *gin.Context) {
|
func (h *UserHandler) BindMobile(c *gin.Context) {
|
||||||
var data struct {
|
var data struct {
|
||||||
|
|||||||
@@ -216,8 +216,9 @@ func main() {
|
|||||||
group.GET("session", h.Session)
|
group.GET("session", h.Session)
|
||||||
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.UpdatePass)
|
||||||
group.POST("bind/mobile", h.BindMobile)
|
group.POST("bind/mobile", h.BindMobile)
|
||||||
|
group.POST("resetPass", h.ResetPass)
|
||||||
}),
|
}),
|
||||||
fx.Invoke(func(s *core.AppServer, h *chatimpl.ChatHandler) {
|
fx.Invoke(func(s *core.AppServer, h *chatimpl.ChatHandler) {
|
||||||
group := s.Engine.Group("/api/chat/")
|
group := s.Engine.Group("/api/chat/")
|
||||||
|
|||||||
108
web/src/components/ResetPass.vue
Normal file
108
web/src/components/ResetPass.vue
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
<template>
|
||||||
|
<div class="reset-pass">
|
||||||
|
<el-dialog
|
||||||
|
v-model="showDialog"
|
||||||
|
:close-on-click-modal="true"
|
||||||
|
width="540px"
|
||||||
|
:before-close="close"
|
||||||
|
:title="title"
|
||||||
|
>
|
||||||
|
<div class="form">
|
||||||
|
|
||||||
|
<el-form :model="form" label-width="120px" label-position="left">
|
||||||
|
<el-form-item label="手机号码">
|
||||||
|
<el-input v-model="form.mobile"/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="手机验证码">
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="16">
|
||||||
|
<el-input v-model="form.code" maxlength="6"/>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<send-msg size="" :mobile="form.mobile"/>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="新密码">
|
||||||
|
<el-input v-model="form.password" type="password"/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="重复密码">
|
||||||
|
<el-input v-model="form.repass" type="password"/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="save" round>
|
||||||
|
重置密码
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
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 form = ref({
|
||||||
|
mobile: '',
|
||||||
|
code: '',
|
||||||
|
password: '',
|
||||||
|
repass: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const emits = defineEmits(['hide']);
|
||||||
|
|
||||||
|
const save = () => {
|
||||||
|
if (!validateMobile(form.value.mobile)) {
|
||||||
|
return ElMessage.error("请输入正确的手机号码");
|
||||||
|
}
|
||||||
|
if (form.value.code === '') {
|
||||||
|
return ElMessage.error("请输入短信验证码");
|
||||||
|
}
|
||||||
|
if (form.value.repass !== form.value.password) {
|
||||||
|
return ElMessage.error("两次输入密码不一致");
|
||||||
|
}
|
||||||
|
|
||||||
|
httpPost('/api/user/resetPass', form.value).then(() => {
|
||||||
|
ElMessage.success({
|
||||||
|
message: '重置密码成功', duration: 1000, onClose: () => emits('hide', false)
|
||||||
|
})
|
||||||
|
}).catch(e => {
|
||||||
|
ElMessage.error("重置密码失败:" + e.message);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const close = function () {
|
||||||
|
emits('hide', false);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus">
|
||||||
|
.reset-pass {
|
||||||
|
.form {
|
||||||
|
padding 10px 40px
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog__footer {
|
||||||
|
text-align center
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -27,7 +27,7 @@ export function setSessionId(sessionId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getUserToken() {
|
export function getUserToken() {
|
||||||
return Storage.get(UserTokenKey)
|
return Storage.get(UserTokenKey) ?? ""
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setUserToken(token) {
|
export function setUserToken(token) {
|
||||||
|
|||||||
@@ -32,13 +32,15 @@
|
|||||||
<el-button class="login-btn" size="large" type="primary" @click="login">登录</el-button>
|
<el-button class="login-btn" size="large" type="primary" @click="login">登录</el-button>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-row class="text-line">
|
<el-row class="text-line" gutter="20">
|
||||||
还没有账号?
|
<el-button type="primary" @click="router.push('/register')" size="small" plain>注册新账号</el-button>
|
||||||
<el-link type="primary" @click="router.push('/register')">注册新账号</el-link>
|
<el-button type="success" @click="showResetPass = true" size="small" plain>重置密码</el-button>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<reset-pass @hide="showResetPass = false" :show="showResetPass"/>
|
||||||
|
|
||||||
<footer class="footer">
|
<footer class="footer">
|
||||||
<footer-bar/>
|
<footer-bar/>
|
||||||
</footer>
|
</footer>
|
||||||
@@ -59,11 +61,13 @@ import {checkSession} from "@/action/session";
|
|||||||
import {setUserToken} from "@/store/session";
|
import {setUserToken} from "@/store/session";
|
||||||
import {validateMobile} from "@/utils/validate";
|
import {validateMobile} from "@/utils/validate";
|
||||||
import {prevRoute} from "@/router";
|
import {prevRoute} from "@/router";
|
||||||
|
import ResetPass from "@/components/ResetPass.vue";
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const title = ref('ChatGPT-PLUS 用户登录');
|
const title = ref('ChatGPT-PLUS 用户登录');
|
||||||
const username = ref(process.env.VUE_APP_USER);
|
const username = ref(process.env.VUE_APP_USER);
|
||||||
const password = ref(process.env.VUE_APP_PASS);
|
const password = ref(process.env.VUE_APP_PASS);
|
||||||
|
const showResetPass = ref(false)
|
||||||
|
|
||||||
checkSession().then(() => {
|
checkSession().then(() => {
|
||||||
if (isMobile()) {
|
if (isMobile()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user