Merge branch 'feature/task1.0.0_xg' into 'feature/task1.0.0'

feat: 新增登录模块以及登录功能

See merge request yanxuan-frontend/shop-pc!4
merge-requests/5/head
肖广 3 years ago
commit 4a9421c7e8

@ -0,0 +1,228 @@
<template>
<div class="bs-login">
<el-dialog
:visible.sync="dialogTableVisible"
:show-close="false"
width="20%"
>
<div class="bs-login-wrap">
<img
class="bs-login-wrap__logo"
src="@/static/images/login/icon-logo.png"
/>
<div class="bs-login-wrap__content">
<el-form :model="form" :rules="rules" ref="ruleForm">
<el-form-item prop="phone">
<el-input
v-model="form.phone"
placeholder="请输入手机号"
></el-input>
</el-form-item>
<el-form-item prop="verificationCode">
<el-input
class="input-code"
v-model="form.verificationCode"
placeholder="请输入密码"
>
<el-button slot="suffix" type="text" @click="onSendCode">
{{ codeValue }}
</el-button>
</el-input>
</el-form-item>
<el-button class="login-wrap-content__login-btn" @click="onLogin"
>登录</el-button
>
</el-form>
<div class="login-wrap-content__agreement flex felx-start">
<div
class="wrap-content-agreement-icons"
@click="onAgreementSelect"
>
<img
v-if="isAcceptAgreement"
class="icon-choose"
src="@/static/images/login/icon-accept.png"
/>
<span v-else class="icon-unchoose"></span>
</div>
<span class="wrap-content-agreement__text flex-1">
同意用户协议隐私协议首次 登陆将自动注册
</span>
</div>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
import { Message } from "element-ui";
import { ApiGetCode, ApiPostLogin } from "@/plugins/api/account";
import { IsPhone } from "/plugins/utils";
const COUNT_DOWN_TIME = 60; //
export default {
name: "BsLogin",
props: {
visible: {
type: Boolean,
default: false,
},
},
data() {
const validatorPhone = (_, value, callback) => {
if (!value) {
return callback(new Error("手机号不能为空"));
}
if (!IsPhone(value)) {
return callback(new Error("请输入正确的手机号"));
}
return callback();
};
return {
form: {
phone: "",
verificationCode: "",
},
isAcceptAgreement: false, //
countDown: 0, //
rules: {
phone: [{ validator: validatorPhone, trigger: "blur" }],
verificationCode: [
{ required: true, message: "请输入验证码", trigger: "change" },
],
},
};
},
computed: {
dialogTableVisible: {
get() {
return this.visible;
},
set(val) {
this.$emit("update:visible", val);
},
},
codeValue() {
return this.countDown ? `${this.countDown}s重新获取` : "获取验证码";
},
},
methods: {
onAgreementSelect() {
this.isAcceptAgreement = !this.isAcceptAgreement;
},
async onSendCode() {
if (this.countDown > 0 || !IsPhone(this.form.phone)) {
return;
}
this.countDown = COUNT_DOWN_TIME;
let time;
const { result, error } = await ApiGetCode({
phone: this.form.phone,
});
if (result) {
time = setInterval(() => {
if (this.countDown === 0) {
clearInterval(time);
return;
}
this.countDown -= 1;
}, 1e3);
return;
}
this.countDown = 0;
clearInterval(time);
Message.error(error.message || "验证码发送失败,请检查手机号是否正确");
},
onLogin() {
this.$refs.ruleForm.validate(async (valid) => {
if (valid) {
if (!this.isAcceptAgreement) {
Message.error("请勾选同意《用户协议》和《隐私协议》");
return;
}
await ApiPostLogin({ ...this.form });
}
});
},
},
};
</script>
<style lang="scss" scoped>
.bs-login {
/deep/.el-dialog {
.el-dialog__header {
display: none;
}
.el-dialog__body {
padding: 38px 30px;
}
.bs-login-wrap {
.bs-login-wrap__logo {
width: 198px;
height: 32px;
margin-bottom: 44px;
}
.bs-login-wrap__content {
.el-form {
.el-form-item {
margin-bottom: 24px;
.input-code {
.el-input__inner {
padding-right: 100px;
}
}
.el-input {
.el-input__suffix {
padding-right: 16px;
.el-button {
color: #ff512b;
}
}
.el-input__inner {
border-style: none;
background: #f8f8f8;
border-radius: 4px 4px 4px 4px;
}
}
}
.login-wrap-content__login-btn {
width: 100%;
height: 42px;
border-style: none;
color: #ffffff;
font-size: 16px;
margin-top: 14px;
background: linear-gradient(270deg, #ffa25a 0%, #ff7f39 100%);
border-radius: 4px 4px 4px 4px;
}
}
.login-wrap-content__agreement {
padding: 0 33px;
color: #999999;
font-size: 12px;
margin-top: 25px;
.wrap-content-agreement-icons {
cursor: pointer;
.icon-unchoose {
display: block;
width: 16px;
height: 16px;
border: 1px solid #cccccc;
border-radius: 50%;
}
.icon-choose {
width: 16px;
height: 16px;
}
}
.wrap-content-agreement__text {
display: block;
text-align: center;
margin-left: 8px;
}
}
}
}
}
}
</style>

@ -7,25 +7,28 @@
--> -->
<template> <template>
<div class="layout"> <div class="layout">
<BsLogin :visible.sync="loginVisible" />
<Header /> <Header />
<div class="layout-box"><Nuxt /></div> <Nuxt />
<Footer /> <Footer />
</div> </div>
</template> </template>
<script> <script>
import BsLogin from "@/components/BsLogin.vue";
import Header from "./module/header/index.vue"; import Header from "./module/header/index.vue";
import Footer from "./module/footer/index.vue"; import Footer from "./module/footer/index.vue";
export default { export default {
name: "Layout", name: "Layout",
components: { Header, Footer }, components: { Header, Footer, BsLogin },
data() {
return {
loginVisible: true,
};
},
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.layout-box {
width: 1200px;
margin: 0 auto;
}
.layout-footer { .layout-footer {
height: 189px; height: 189px;
background: #ddd; background: #ddd;

@ -169,16 +169,16 @@ export default {
// //
async getCategroyData() { async getCategroyData() {
const { result } = await ApiGetCategoryOneList(); const { result } = await ApiGetCategoryOneList();
if (result.data.length > 0) { if (result && result.length > 0) {
this.categrayData = await Promise.all( this.categrayData = await Promise.all(
result.data.map(async (item) => { result.map(async (item) => {
const { result } = await ApiGetCategoryTwoAndGoods({ const { result: resultGoods } = await ApiGetCategoryTwoAndGoods({
categoryId: item.id, categoryId: item.id,
}); });
if (result.data.length > 0) { if (resultGoods && resultGoods.length > 0) {
return { return {
...item, ...item,
list: result.data, list: resultGoods.data,
}; };
} }
}) })

Binary file not shown.

After

Width:  |  Height:  |  Size: 706 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Loading…
Cancel
Save