update
This commit is contained in:
1
components.d.ts
vendored
1
components.d.ts
vendored
@@ -11,5 +11,6 @@ declare module 'vue' {
|
|||||||
HelloWorld: typeof import('./src/components/HelloWorld.vue')['default']
|
HelloWorld: typeof import('./src/components/HelloWorld.vue')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
|
VerificationCode: typeof import('./src/components/VerificationCode/index.vue')['default']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
<script setup></script>
|
<script setup></script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<router-view></router-view>
|
<a-config-provider size="large">
|
||||||
|
<router-view></router-view>
|
||||||
|
</a-config-provider>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|||||||
BIN
src/assets/images/背景.png
Normal file
BIN
src/assets/images/背景.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 354 KiB |
@@ -1,43 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { ref } from 'vue'
|
|
||||||
|
|
||||||
defineProps({
|
|
||||||
msg: String,
|
|
||||||
})
|
|
||||||
|
|
||||||
const count = ref(0)
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<h1>{{ msg }}</h1>
|
|
||||||
|
|
||||||
<div class="card">
|
|
||||||
<button type="button" @click="count++">count is {{ count }}</button>
|
|
||||||
<p>
|
|
||||||
Edit
|
|
||||||
<code>components/HelloWorld.vue</code> to test HMR
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Check out
|
|
||||||
<a href="https://vuejs.org/guide/quick-start.html#local" target="_blank"
|
|
||||||
>create-vue</a
|
|
||||||
>, the official Vue + Vite starter
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Learn more about IDE Support for Vue in the
|
|
||||||
<a
|
|
||||||
href="https://vuejs.org/guide/scaling-up/tooling.html#ide-support"
|
|
||||||
target="_blank"
|
|
||||||
>Vue Docs Scaling up Guide</a
|
|
||||||
>.
|
|
||||||
</p>
|
|
||||||
<p class="read-the-docs">Click on the Vite and Vue logos to learn more</p>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.read-the-docs {
|
|
||||||
color: #888;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
53
src/components/VerificationCode/index.vue
Normal file
53
src/components/VerificationCode/index.vue
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<script setup>
|
||||||
|
import {ref, defineProps, defineModel} from 'vue';
|
||||||
|
import {Notification} from "@arco-design/web-vue";
|
||||||
|
|
||||||
|
const verificationCode = defineModel('verificationCode', {type: String});
|
||||||
|
const {phone} = defineProps({
|
||||||
|
phone: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const time = ref(null);
|
||||||
|
let timer = null;
|
||||||
|
|
||||||
|
const verifyPhone = () => {
|
||||||
|
if (/^1[3-9]\d{9}$/.test(phone)) {
|
||||||
|
if (timer === null) {
|
||||||
|
time.value = 10;
|
||||||
|
timer = setInterval(() => {
|
||||||
|
if (time.value <= 0) {
|
||||||
|
time.value = null;
|
||||||
|
clearInterval(timer);
|
||||||
|
timer = null;
|
||||||
|
} else {
|
||||||
|
time.value--;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
Notification.error({
|
||||||
|
title: '手机号错误',
|
||||||
|
content: '请检查后重新输入'
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<a-input :model-value="verificationCode" placeholder="验证码">
|
||||||
|
<template #append>
|
||||||
|
<a-link @click="verifyPhone" :disabled="Boolean(time)" :hoverable="false">
|
||||||
|
{{ time ? `${time}s后重新获取` : '发送验证码' }}
|
||||||
|
</a-link>
|
||||||
|
</template>
|
||||||
|
</a-input>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
89
src/pages/login/Forgot.vue
Normal file
89
src/pages/login/Forgot.vue
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
<script setup>
|
||||||
|
import {ref, reactive} from 'vue';
|
||||||
|
import VerificationCode from "../../components/VerificationCode/index.vue";
|
||||||
|
|
||||||
|
const from = reactive({
|
||||||
|
phone: null,
|
||||||
|
verificationCode: null,
|
||||||
|
password: null,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="p-[50px] rounded-[12px] bg-white w-[460px] min-h-[540px] box-border card">
|
||||||
|
<div class="text-[24px] text-center text2">忘记密码</div>
|
||||||
|
<div class="mt-[48px] flex flex-col gap-[20px]">
|
||||||
|
<a-form layout="vertical">
|
||||||
|
<a-form-item>
|
||||||
|
<a-input v-model:model-value="from.phone" placeholder="手机号"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<VerificationCode
|
||||||
|
:phone="from.phone"
|
||||||
|
v-model:verification-code="from.verificationCode">
|
||||||
|
</VerificationCode>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input v-model:model-value="from.password" placeholder="新密码"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col mt-[30px] gap-[32px]">
|
||||||
|
<a-button type="primary">确认修改</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.card {
|
||||||
|
box-shadow: 0 8px 20px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
:deep(.arco-form-item-label-col) {
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.text2 {
|
||||||
|
color: rgb(29, 33, 41);
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 32px;
|
||||||
|
letter-spacing: 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text1 {
|
||||||
|
/* 14/CN-Regular */
|
||||||
|
color: rgb(78, 89, 105);
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 22px;
|
||||||
|
letter-spacing: 0;
|
||||||
|
text-align: left;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 500ms;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 2px;
|
||||||
|
background-color: rgb(22, 93, 255);
|
||||||
|
margin-top: 12px;
|
||||||
|
opacity: 0;
|
||||||
|
transition: 500ms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.text1-cur {
|
||||||
|
color: rgb(22, 93, 255);
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 22px;
|
||||||
|
letter-spacing: 0;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
102
src/pages/login/Login.vue
Normal file
102
src/pages/login/Login.vue
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
<script setup>
|
||||||
|
import {ref, reactive} from 'vue';
|
||||||
|
import {toPath} from "../../utils/index.js";
|
||||||
|
import VerificationCode from '../../components/VerificationCode/index.vue';
|
||||||
|
|
||||||
|
const MODE = {
|
||||||
|
PHONE: 'PHONE',
|
||||||
|
PASSWORD: 'PASSWORD'
|
||||||
|
}
|
||||||
|
|
||||||
|
const from = reactive({
|
||||||
|
phone: null,
|
||||||
|
verificationCode: null,
|
||||||
|
password: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const mode = ref(MODE.PHONE);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="p-[50px] rounded-[12px] bg-white w-[460px] min-h-[540px] box-border card">
|
||||||
|
<div class="text-[24px] text-center text2">欢迎登录系统</div>
|
||||||
|
<div class="mt-[57px] flex gap-[32px]">
|
||||||
|
<div @click="mode = MODE.PHONE" :class="['text1', mode===MODE.PHONE?'text1-cur':null]">手机号登陆</div>
|
||||||
|
<div @click="mode = MODE.PASSWORD" :class="['text1', mode===MODE.PASSWORD?'text1-cur':null]">账号密码登陆
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-[38px] flex flex-col gap-[20px]">
|
||||||
|
<a-input v-model:model-value="from.phone" placeholder="手机号"></a-input>
|
||||||
|
<VerificationCode
|
||||||
|
v-if="mode === MODE.PHONE"
|
||||||
|
:phone="from.phone"
|
||||||
|
v-model:verification-code="from.verificationCode">
|
||||||
|
</VerificationCode>
|
||||||
|
<a-input v-else :model-value="from.password" placeholder="密码">
|
||||||
|
<template #append>
|
||||||
|
<a-link @click="toPath('/loginSYS/forgot')" :hoverable="false">忘记密码?</a-link>
|
||||||
|
</template>
|
||||||
|
</a-input>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col mt-[50px] gap-[32px]">
|
||||||
|
<a-button type="primary">登陆</a-button>
|
||||||
|
<a-button
|
||||||
|
@click="toPath('/loginSYS/register')"
|
||||||
|
type="text">
|
||||||
|
去注册
|
||||||
|
<icon-arrow-right class="ml-[5px]"/>
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.card {
|
||||||
|
box-shadow: 0 8px 20px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text2 {
|
||||||
|
color: rgb(29, 33, 41);
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 32px;
|
||||||
|
letter-spacing: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text1 {
|
||||||
|
/* 14/CN-Regular */
|
||||||
|
color: rgb(78, 89, 105);
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 22px;
|
||||||
|
letter-spacing: 0;
|
||||||
|
text-align: left;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 500ms;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 2px;
|
||||||
|
background-color: rgb(22, 93, 255);
|
||||||
|
margin-top: 12px;
|
||||||
|
opacity: 0;
|
||||||
|
transition: 500ms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.text1-cur {
|
||||||
|
color: rgb(22, 93, 255);
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 22px;
|
||||||
|
letter-spacing: 0;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
94
src/pages/login/Register.vue
Normal file
94
src/pages/login/Register.vue
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
<script setup>
|
||||||
|
import {ref, reactive} from 'vue';
|
||||||
|
import VerificationCode from "../../components/VerificationCode/index.vue";
|
||||||
|
|
||||||
|
const from = reactive({
|
||||||
|
phone: null,
|
||||||
|
verificationCode: null,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="p-[50px] rounded-[12px] bg-white w-[460px] box-border card">
|
||||||
|
<div class="text-[24px] text-center text2">账号注册</div>
|
||||||
|
<div class="mt-[30px] flex flex-col gap-[20px]">
|
||||||
|
<a-form layout="vertical">
|
||||||
|
<a-form-item label="微信号">
|
||||||
|
<a-input placeholder="请输入微信号"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="手机号">
|
||||||
|
<a-input v-model:model-value="from.phone" placeholder="请输入手机号"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="验证码">
|
||||||
|
<VerificationCode
|
||||||
|
:phone="from.phone"
|
||||||
|
v-model:verification-code="from.verificationCode">
|
||||||
|
</VerificationCode>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="登陆密码">
|
||||||
|
<a-input placeholder="请输入登陆密码"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="邀请码(选填)">
|
||||||
|
<a-input placeholder="请输入邀请码"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col mt-[30px] gap-[32px]">
|
||||||
|
<a-button type="primary">确认注册</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.card {
|
||||||
|
box-shadow: 0 8px 20px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
:deep(.arco-form-item-label-col) {
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.text2 {
|
||||||
|
color: rgb(29, 33, 41);
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 32px;
|
||||||
|
letter-spacing: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text1 {
|
||||||
|
/* 14/CN-Regular */
|
||||||
|
color: rgb(78, 89, 105);
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 22px;
|
||||||
|
letter-spacing: 0;
|
||||||
|
text-align: left;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 500ms;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 2px;
|
||||||
|
background-color: rgb(22, 93, 255);
|
||||||
|
margin-top: 12px;
|
||||||
|
opacity: 0;
|
||||||
|
transition: 500ms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.text1-cur {
|
||||||
|
color: rgb(22, 93, 255);
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 22px;
|
||||||
|
letter-spacing: 0;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -3,9 +3,11 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="text-[red]">登录</div>
|
<div class="w-full h-screen relative flex justify-center items-center">
|
||||||
|
<img class="w-full h-full absolute left-0 top-0 -z-10 object-cover" src="../../assets/images/背景.png" alt="" />
|
||||||
|
|
||||||
<a-button type="primary">登录</a-button>
|
<router-view></router-view>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -9,8 +9,9 @@ const router = createRouter({
|
|||||||
|
|
||||||
router.beforeEach((to, from, next) => {
|
router.beforeEach((to, from, next) => {
|
||||||
const {isLogin} = useUserStore();
|
const {isLogin} = useUserStore();
|
||||||
if (to.name !== 'login' && !isLogin) {
|
|
||||||
next({name: 'login'});
|
if (!isLogin && !to.path.includes('loginSYS')) {
|
||||||
|
next({ path: '/loginSYS' });
|
||||||
} else {
|
} else {
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,27 @@ const routes = [
|
|||||||
component: () => import('../pages/layout/index.vue'),
|
component: () => import('../pages/layout/index.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/login',
|
path: '/loginSYS',
|
||||||
name: 'login',
|
name: 'loginSYS',
|
||||||
|
redirect: '/loginSYS/login',
|
||||||
component: () => import('../pages/login/index.vue'),
|
component: () => import('../pages/login/index.vue'),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'login',
|
||||||
|
name: 'login',
|
||||||
|
component: () => import('../pages/login/Login.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'register',
|
||||||
|
name: 'register',
|
||||||
|
component: () => import('../pages/login/Register.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'forgot',
|
||||||
|
name: 'forgot',
|
||||||
|
component: () => import('../pages/login/Forgot.vue')
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
font-family: "PingFang SC", serif;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import router from "../router/index.js";
|
||||||
|
|
||||||
|
export const toPath = (path) => {
|
||||||
|
router.push(path).then();
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user