mirror of
https://github.com/GiriNeko/YesPlayMusic.git
synced 2025-12-17 13:48:02 +00:00
* feat: add config to resolve path alias. * feat: use vue-i18n for language switch * feat: add .editorconfig for ide * fix: add no-referrer to avoid CROB * fix: setCookie and fix typo * feat: integrate vue-i18n * feat: player component i18n support * fix: duplicate key warning in explore page * fix: like songs number changed in library page * fire: remove todo * fix: same text search on enter will cause error * fix: scrobble error params type * feat: prettier task supported * fix: prettier ignore config update * fix: conflict * fix: commitMP3 and countrycode to countryCode * lint: prettier
355 lines
7.8 KiB
Vue
355 lines
7.8 KiB
Vue
<template>
|
|
<div class="login">
|
|
<div class="section-1">
|
|
<img src="/img/logos/netease-music.png" />
|
|
</div>
|
|
<div class="title">{{ $t("login.loginText") }}</div>
|
|
<div class="section-2">
|
|
<div class="input-box" v-show="mode === 'phone'">
|
|
<div class="container" :class="{ active: inputFocus === 'phone' }">
|
|
<svg-icon icon-class="mobile" />
|
|
<div class="inputs">
|
|
<input
|
|
id="countryCode"
|
|
:placeholder="
|
|
inputFocus === 'phone' ? '' : $t('login.countryCode')
|
|
"
|
|
v-model="countryCode"
|
|
@focus="inputFocus = 'phone'"
|
|
@blur="inputFocus = ''"
|
|
/>
|
|
<input
|
|
id="phoneNumber"
|
|
:placeholder="inputFocus === 'phone' ? '' : $t('login.phone')"
|
|
v-model="phoneNumber"
|
|
@focus="inputFocus = 'phone'"
|
|
@blur="inputFocus = ''"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="input-box" v-show="mode === 'email'">
|
|
<div class="container" :class="{ active: inputFocus === 'email' }">
|
|
<svg-icon icon-class="mail" />
|
|
<div class="inputs">
|
|
<input
|
|
type="email"
|
|
id="email"
|
|
:placeholder="inputFocus === 'email' ? '' : $t('login.email')"
|
|
v-model="email"
|
|
@focus="inputFocus = 'email'"
|
|
@blur="inputFocus = ''"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="input-box">
|
|
<div class="container" :class="{ active: inputFocus === 'password' }">
|
|
<svg-icon icon-class="lock" />
|
|
<div class="inputs">
|
|
<input
|
|
type="password"
|
|
id="password"
|
|
:placeholder="
|
|
inputFocus === 'password' ? '' : $t('login.password')
|
|
"
|
|
v-model="password"
|
|
@focus="inputFocus = 'password'"
|
|
@blur="inputFocus = ''"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="confirm">
|
|
<button @click="login" v-show="!processing">
|
|
{{ $t("login.login") }}
|
|
</button>
|
|
<button v-show="processing" class="loading" disabled>
|
|
<span></span>
|
|
<span></span>
|
|
<span></span>
|
|
</button>
|
|
</div>
|
|
<div class="other-login">
|
|
<a v-show="mode === 'phone'" @click="mode = 'email'">{{
|
|
$t("login.loginWithEmail")
|
|
}}</a>
|
|
<a v-show="mode === 'email'" @click="mode = 'phone'">{{
|
|
$t("login.loginWithPhone")
|
|
}}</a>
|
|
</div>
|
|
<div class="notice" v-html="$t('login.notice')"></div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import NProgress from "nprogress";
|
|
import { loginWithPhone, loginWithEmail } from "@/api/auth";
|
|
import md5 from "crypto-js/md5";
|
|
import { mapMutations } from "vuex";
|
|
import { userPlaylist } from "@/api/user";
|
|
import Cookies from "js-cookie";
|
|
|
|
export default {
|
|
name: "Login",
|
|
data() {
|
|
return {
|
|
processing: false,
|
|
mode: "email",
|
|
countryCode: "+86",
|
|
phoneNumber: "",
|
|
email: "",
|
|
password: "",
|
|
smsCode: "",
|
|
inputFocus: "",
|
|
};
|
|
},
|
|
created() {
|
|
if (this.$route.query.mode === "phone") {
|
|
this.mode = "phone";
|
|
}
|
|
NProgress.done();
|
|
},
|
|
methods: {
|
|
...mapMutations(["updateUser", "updateUserInfo"]),
|
|
afterLogin() {
|
|
// Cookies.set("MUSIC_U", true, { expires: 3650 });
|
|
Cookies.set("loginMode", "account", { expires: 3650 });
|
|
userPlaylist({
|
|
uid: this.$store.state.settings.user.userId,
|
|
limit: 1,
|
|
}).then((data) => {
|
|
this.updateUserInfo({
|
|
key: "likedSongPlaylistID",
|
|
value: data.playlist[0].id,
|
|
});
|
|
this.$router.push({ path: "/library" });
|
|
});
|
|
},
|
|
login() {
|
|
this.processing = true;
|
|
if (this.mode === "phone") {
|
|
if (
|
|
this.countryCode === "" ||
|
|
this.phone === "" ||
|
|
this.password === ""
|
|
) {
|
|
alert("国家区号、手机或密码不正确");
|
|
this.processing = false;
|
|
return;
|
|
}
|
|
loginWithPhone({
|
|
countrycode: this.countryCode.replace("+", "").replace(/\s/g, ""),
|
|
phone: this.phoneNumber.replace(/\s/g, ""),
|
|
password: "fakePassword",
|
|
md5_password: md5(this.password).toString(),
|
|
})
|
|
.then((data) => {
|
|
if (data.code !== 502) {
|
|
this.updateUser(data.profile);
|
|
this.afterLogin();
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
this.processing = false;
|
|
alert(error);
|
|
});
|
|
} else {
|
|
let emailReg = /^[A-Za-z0-9]+([_][A-Za-z0-9]+)*@([A-Za-z0-9]+\.)+[A-Za-z]{2,6}$/;
|
|
if (
|
|
this.email === "" ||
|
|
this.password === "" ||
|
|
!emailReg.test(this.email)
|
|
) {
|
|
alert("邮箱或密码不正确");
|
|
this.processing = false;
|
|
return;
|
|
}
|
|
loginWithEmail({
|
|
email: this.email.replace(/\s/g, ""),
|
|
password: "fakePassword",
|
|
md5_password: md5(this.password).toString(),
|
|
})
|
|
.then((data) => {
|
|
if (data.code !== 502) {
|
|
this.updateUser(data.profile);
|
|
this.afterLogin();
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
this.processing = false;
|
|
alert(error);
|
|
});
|
|
}
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.login {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
min-height: calc(100vh - 192px);
|
|
}
|
|
|
|
.title {
|
|
font-size: 24px;
|
|
font-weight: 700;
|
|
margin-bottom: 48px;
|
|
}
|
|
|
|
.section-1 {
|
|
margin-bottom: 16px;
|
|
display: flex;
|
|
align-items: center;
|
|
img {
|
|
height: 64px;
|
|
margin: 20px;
|
|
}
|
|
.svg-icon {
|
|
height: 24px;
|
|
width: 24px;
|
|
color: rgba(82, 82, 82, 0.28);
|
|
}
|
|
}
|
|
|
|
.section-2 {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.input-box {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
margin-bottom: 16px;
|
|
|
|
.container {
|
|
display: flex;
|
|
align-items: center;
|
|
height: 46px;
|
|
background: rgba(0, 0, 0, 0.06);
|
|
border-radius: 8px;
|
|
width: 300px;
|
|
}
|
|
|
|
.svg-icon {
|
|
height: 18px;
|
|
width: 18px;
|
|
color: #aaaaaa;
|
|
margin: {
|
|
left: 12px;
|
|
right: 6px;
|
|
}
|
|
}
|
|
|
|
.inputs {
|
|
display: flex;
|
|
width: 85%;
|
|
}
|
|
|
|
input {
|
|
font-size: 20px;
|
|
border: none;
|
|
background: transparent;
|
|
width: 100%;
|
|
font-weight: 600;
|
|
margin-top: -1px;
|
|
color: rgba(0, 0, 0, 0.88);
|
|
}
|
|
|
|
input#countryCode {
|
|
flex: 3;
|
|
}
|
|
input#phoneNumber {
|
|
flex: 12;
|
|
}
|
|
|
|
.active {
|
|
background: #eaeffd;
|
|
input,
|
|
.svg-icon {
|
|
color: #335eea;
|
|
}
|
|
}
|
|
}
|
|
|
|
.confirm button {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 20px;
|
|
font-weight: 600;
|
|
background-color: rgba(51, 94, 234, 0.1);
|
|
color: #335eea;
|
|
border-radius: 8px;
|
|
margin-top: 24px;
|
|
transition: 0.2s;
|
|
padding: 8px;
|
|
width: 100%;
|
|
width: 300px;
|
|
&:hover {
|
|
transform: scale(1.06);
|
|
}
|
|
&:active {
|
|
transform: scale(0.94);
|
|
}
|
|
}
|
|
|
|
.other-login {
|
|
margin-top: 24px;
|
|
a {
|
|
cursor: pointer;
|
|
font-size: 13px;
|
|
color: rgba(0, 0, 0, 0.68);
|
|
}
|
|
}
|
|
|
|
.notice {
|
|
width: 300px;
|
|
border-top: 1px solid rgba(0, 0, 0, 0.18);
|
|
margin-top: 48px;
|
|
padding-top: 12px;
|
|
font-size: 12px;
|
|
color: rgba(0, 0, 0, 0.48);
|
|
}
|
|
|
|
@keyframes loading {
|
|
0% {
|
|
opacity: 0.2;
|
|
}
|
|
20% {
|
|
opacity: 1;
|
|
}
|
|
100% {
|
|
opacity: 0.2;
|
|
}
|
|
}
|
|
|
|
button.loading {
|
|
height: 44px;
|
|
cursor: unset;
|
|
&:hover {
|
|
transform: none;
|
|
}
|
|
}
|
|
.loading span {
|
|
width: 6px;
|
|
height: 6px;
|
|
background-color: #335eea;
|
|
border-radius: 50%;
|
|
margin: 0 2px;
|
|
animation: loading 1.4s infinite both;
|
|
}
|
|
|
|
.loading span:nth-child(2) {
|
|
animation-delay: 0.2s;
|
|
}
|
|
|
|
.loading span:nth-child(3) {
|
|
animation-delay: 0.4s;
|
|
}
|
|
</style>
|