feat:重置密码完成
This commit is contained in:
parent
3754a4db90
commit
2a78c3ce05
File diff suppressed because it is too large
Load Diff
@ -18,6 +18,7 @@ body {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
font-size: 100px;
|
font-size: 100px;
|
||||||
background-color: @bgColor;
|
background-color: @bgColor;
|
||||||
|
height: initial;
|
||||||
}
|
}
|
||||||
#app {
|
#app {
|
||||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
* header 配置
|
* header 配置
|
||||||
*/
|
*/
|
||||||
@topHeight: 0.4rem; //header总高度
|
@topHeight: 0.4rem; //header总高度
|
||||||
@topPadding: 0.04rem; //header padding高度
|
@topPaddingTop: 0.04rem; //header padding高度
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* bottom配置
|
* bottom配置
|
||||||
|
@ -10,14 +10,24 @@ export default {};
|
|||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
@import "../../global.less";
|
@import "../../global.less";
|
||||||
|
|
||||||
@sum: @topHeight + @bottomHeight;
|
@sum: @topHeight + @bottomHeight;
|
||||||
|
|
||||||
.main {
|
.main {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
||||||
margin-top: @topHeight;
|
margin-top: @topHeight;
|
||||||
|
|
||||||
min-height: calc(~"100vh" - @sum);
|
min-height: calc(~"100vh" - @sum);
|
||||||
|
|
||||||
width: 90%;
|
width: 90%;
|
||||||
|
|
||||||
min-width: 5rem;
|
min-width: 5rem;
|
||||||
|
|
||||||
font-size: 0.14rem;
|
font-size: 0.14rem;
|
||||||
|
|
||||||
background-color: rgba(249, 231, 62, 0.2);
|
background-color: rgba(249, 231, 62, 0.2);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,13 +1,35 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<img class="ico" src="/static/img/bookmarkLogo.png" />
|
<img class="ico" src="/static/img/bookmarkLogo.png" />
|
||||||
<div class="user">fanxb</div>
|
<a-dropdown>
|
||||||
|
<div class="user">
|
||||||
|
<img :src="userInfo.icon" class="userIcon" />
|
||||||
|
<span class="name">{{ userInfo.username }}</span>
|
||||||
|
</div>
|
||||||
|
<a-menu slot="overlay" :trigger="['hover', 'click']" @click="menuClick">
|
||||||
|
<a-menu-item key="logout">
|
||||||
|
<a href="javascript:;">退出</a>
|
||||||
|
</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { mapState } from "vuex";
|
||||||
export default {
|
export default {
|
||||||
name: "Top"
|
name: "Top",
|
||||||
|
computed: {
|
||||||
|
...mapState("globalConfig", ["userInfo"])
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async menuClick({ key }) {
|
||||||
|
if (key === "logout") {
|
||||||
|
await this.$store.dispatch("globalConfig/clear");
|
||||||
|
this.$router.replace("/public/login");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -16,9 +38,9 @@ export default {
|
|||||||
.main {
|
.main {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: calc(100% - 10px);
|
width: 100%;
|
||||||
height: @topHeight - (2 * @topPadding);
|
height: @topHeight;
|
||||||
padding: @topPadding;
|
padding: @topPaddingTop 3% @topPaddingTop 3%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -28,6 +50,17 @@ export default {
|
|||||||
}
|
}
|
||||||
.user {
|
.user {
|
||||||
font-size: 0.3rem;
|
font-size: 0.3rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
.userIcon {
|
||||||
|
width: @topHeight - 0.1rem;
|
||||||
|
height: @topHeight - 0.1rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
.name {
|
||||||
|
font-size: 0.2rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
import { Button, FormModel, Input, Icon, message, Checkbox } from "ant-design-vue";
|
import { Button, FormModel, Input, Icon, message, Checkbox, Dropdown, Menu } from "ant-design-vue";
|
||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
import router from "./router";
|
import router from "./router";
|
||||||
import store from "./store";
|
import store from "./store";
|
||||||
@ -9,6 +9,8 @@ Vue.use(FormModel);
|
|||||||
Vue.component(Input.name, Input);
|
Vue.component(Input.name, Input);
|
||||||
Vue.component(Icon.name, Icon);
|
Vue.component(Icon.name, Icon);
|
||||||
Vue.use(Checkbox);
|
Vue.use(Checkbox);
|
||||||
|
Vue.use(Dropdown);
|
||||||
|
Vue.use(Menu);
|
||||||
|
|
||||||
Vue.prototype.$message = message;
|
Vue.prototype.$message = message;
|
||||||
Vue.config.productionTip = false;
|
Vue.config.productionTip = false;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import localforage from "localforage";
|
import localforage, { clear } from "localforage";
|
||||||
/**
|
/**
|
||||||
* 存储全局配置
|
* 存储全局配置
|
||||||
*/
|
*/
|
||||||
@ -6,7 +6,7 @@ const state = {
|
|||||||
/**
|
/**
|
||||||
* 用户信息
|
* 用户信息
|
||||||
*/
|
*/
|
||||||
userInfo: null,
|
userInfo: {},
|
||||||
/**
|
/**
|
||||||
* token
|
* token
|
||||||
*/
|
*/
|
||||||
@ -20,6 +20,7 @@ const state = {
|
|||||||
const getters = {};
|
const getters = {};
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
|
//初始化数据
|
||||||
async init(context) {
|
async init(context) {
|
||||||
if (context.state.isInit) {
|
if (context.state.isInit) {
|
||||||
return;
|
return;
|
||||||
@ -29,6 +30,14 @@ const actions = {
|
|||||||
window.token = token;
|
window.token = token;
|
||||||
context.commit("setToken", token);
|
context.commit("setToken", token);
|
||||||
context.commit("isInit", true);
|
context.commit("isInit", true);
|
||||||
|
},
|
||||||
|
//登出清除数据
|
||||||
|
async clear(context) {
|
||||||
|
await localforage.removeItem("userInfo");
|
||||||
|
await localforage.removeItem("token");
|
||||||
|
delete window.token;
|
||||||
|
context.commit("setUserInfo", {});
|
||||||
|
context.commit("setToken", null);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
133
bookmark_front/src/views/public/pages/ResetPassword.vue
Normal file
133
bookmark_front/src/views/public/pages/ResetPassword.vue
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<Header current="reset" />
|
||||||
|
<div class="form">
|
||||||
|
<a-form-model ref="resetPassword" :model="form" :rules="rules">
|
||||||
|
<a-form-model-item prop="email">
|
||||||
|
<a-input v-model="form.email" placeholder="邮箱">
|
||||||
|
<a-icon slot="prefix" type="mail" style="color:rgba(0,0,0,.25)" />
|
||||||
|
</a-input>
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item prop="password">
|
||||||
|
<a-input v-model="form.password" placeholder="新密码" type="password">
|
||||||
|
<a-icon slot="prefix" type="lock" style="color:rgba(0,0,0,.25)" />
|
||||||
|
</a-input>
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item prop="repeatPass">
|
||||||
|
<a-input v-model="form.repeatPass" placeholder="重复新密码" type="password">
|
||||||
|
<a-icon slot="prefix" type="lock" style="color:rgba(0,0,0,.25)" />
|
||||||
|
</a-input>
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item prop="authCode" ref="authCode" :autoLink="false">
|
||||||
|
<div class="authCodeGroup">
|
||||||
|
<a-input v-model="form.authCode" placeholder="验证码" @change="() => $refs.authCode.onFieldChange()" />
|
||||||
|
<a-button @click="getAuthCode">{{ countDown == 0 ? "获取验证码" : countDown + "秒后重试" }}</a-button>
|
||||||
|
</div>
|
||||||
|
</a-form-model-item>
|
||||||
|
|
||||||
|
<a-form-model-item>
|
||||||
|
<div class="btns">
|
||||||
|
<a-button type="primary" block @click="submit">重置</a-button>
|
||||||
|
<router-link to="login" replace>返回登陆</router-link>
|
||||||
|
</div>
|
||||||
|
</a-form-model-item>
|
||||||
|
</a-form-model>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Header from "@/components/public/Switch.vue";
|
||||||
|
import httpUtil from "../../../util/HttpUtil.js";
|
||||||
|
export default {
|
||||||
|
name: "ResetPassword",
|
||||||
|
components: {
|
||||||
|
Header
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
let repeatPass = (rule, value, cb) => {
|
||||||
|
if (value === "") {
|
||||||
|
cb(new Error("请再次输入密码"));
|
||||||
|
} else if (value !== this.form.password) {
|
||||||
|
cb(new Error("两次密码不一致"));
|
||||||
|
} else {
|
||||||
|
cb();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
countDown: 0, //小于等于0说明可点击获取验证码
|
||||||
|
timer: null,
|
||||||
|
form: {
|
||||||
|
email: "",
|
||||||
|
password: "",
|
||||||
|
repeatPass: "",
|
||||||
|
authCode: ""
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
authCode: [{ required: true, min: 6, max: 6, message: "请输入6位验证码", trigger: "change" }],
|
||||||
|
email: [
|
||||||
|
{
|
||||||
|
pattern: /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
|
||||||
|
message: "请输入正确的邮箱",
|
||||||
|
trigger: "change"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
password: [
|
||||||
|
{ required: true, message: "请输入密码", trigger: "blur" },
|
||||||
|
{ pattern: "^\\w{6,18}$", message: "密码为6-18位数字,字母,下划线组合", trigger: "change" }
|
||||||
|
],
|
||||||
|
repeatPass: [{ validator: repeatPass, trigger: "change" }]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async getAuthCode() {
|
||||||
|
this.$refs.resetPassword.validateField("email", async message => {
|
||||||
|
if (message === "") {
|
||||||
|
await httpUtil.get("/user/authCode", { email: this.form.email });
|
||||||
|
this.$message.success("发送成功,请查收(注意垃圾箱)");
|
||||||
|
this.countDown = 60;
|
||||||
|
if (this.timer != null) {
|
||||||
|
clearInterval(this.timer);
|
||||||
|
}
|
||||||
|
this.timer = setInterval(() => {
|
||||||
|
if (this.countDown > 0) {
|
||||||
|
this.countDown = this.countDown - 1;
|
||||||
|
} else {
|
||||||
|
clearInterval(this.timer);
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
submit() {
|
||||||
|
this.$refs.resetPassword.validate(async status => {
|
||||||
|
if (status) {
|
||||||
|
let res = await httpUtil.put("/resetPassword", null, this.form);
|
||||||
|
this.$message.success("重置成功");
|
||||||
|
this.$router.replace("login");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.form {
|
||||||
|
margin: 0.3rem;
|
||||||
|
.reset {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.authCodeGroup {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.btns {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
x
Reference in New Issue
Block a user