Browse Source

✨ feat: 增加邮箱注册用户功能

Pchen. 7 months ago
parent
commit
3bea92ec7a

+ 2 - 0
src/app/app.js

@@ -5,6 +5,7 @@ class User {
         this.user = undefined;
         this.avatar = undefined;
         this.wxid = undefined;
+        this.email = undefined;
         this.session = undefined;
         this.uuid = undefined;
     }
@@ -24,6 +25,7 @@ class User {
             user.uuid = data.uuid;
             user.session = data.session;
             user.username = data.username;
+            user.email = data.email;
             user.wxid = data.wxid;
             user.avatar = data.avatar;
             return user;

+ 47 - 2
src/app/lib/ServerAPI.js

@@ -4,6 +4,51 @@ let core = new Core(import.meta.env.VITE_API_URL);
 
 class ServerAPI {
     //用户相关
+    static ImageCaptcha(callback = function () { }) {
+        core.request(
+            "/User/ImageCaptcha",
+            {},
+            { method: 'GET' },
+            callback
+        )
+    }
+
+    static SendEmail(email, text, id, type, callback = function () { }) {
+        core.request(
+            "/User/SendEmail",
+            { email, text, id, type },
+            { method: 'POST' },
+            callback
+        )
+    }
+
+    static Register(username, email, code, password, callback = function () { }) {
+        core.request(
+            "/User/Register",
+            { username, email, code, password },
+            { method: 'POST' },
+            callback
+        )
+    }
+
+    static ForgetPassword(username, email, code, password, callback = function () { }) {
+        core.request(
+            "/User/ForgetPassword",
+            { username, email, code, password },
+            { method: 'POST' },
+            callback
+        )
+    }
+
+    static Login(username, password, text, id, callback = function () { }) {
+        core.request(
+            "/User/Login",
+            { username, password, text, id },
+            { method: 'POST' },
+            callback
+        )
+    }
+
     static WXWorkUrl(num, type, callback = function () { }) {
         core.request(
             "/User/WXWorkUrl",
@@ -165,8 +210,8 @@ class ServerAPI {
             "/Admin/SetPermission",
             {
                 uuid,
-                session, 
-                userid, 
+                session,
+                userid,
                 manage
             },
             { method: 'POST' },

+ 12 - 120
src/pages/Login/Login.vue

@@ -1,50 +1,24 @@
 <template>
     <div class="background-image">
-        <Header :color="'aliceblue'"/>
+        <Header :color="'aliceblue'" />
 
-        <div class="content">
-            <h1>用户登录</h1>
-            <button @click="onDev">企业微信一键登录</button>
-            <button @click="WXLogin('login')">企业微信扫码登录</button>
-            <div class="agreementBox">
-                <div class="checkBox">
-                    <input type="checkbox" v-model="agreement">
-                </div>
-                <div class="text">
-                    阅读并同意 <span class="bold">《使用协议》《隐私协议》</span>
-                </div>
-                <router-view></router-view>
-            </div>
-        </div>
+        <Index v-if="mode === 'Index'" @update="update" />
+        <PasswordLogin v-else-if="mode === 'PasswordLogin'" @update="update" />
+        <Register v-else-if="mode === 'register'" @update="update" />
+        <ForgetPassword v-else-if="mode === 'forget'" @update="update" />
     </div>
 </template>
 
 <script setup>
 import Header from "../../components/Header.vue";
-import { ServerAPI } from '../../app/lib/ServerAPI';
-
-let agreement = ref(false);
-
-let onDev = function () {
-    ElMessage.error('正在开发中')
-}
-
-let WXLogin = function () {
-    if (!agreement.value) {
-        ElMessage({
-            message: "请仔细阅读并同意下方使用协议和隐私协议",
-            type: 'warning'
-        });
-        return;
-    }
-
-    const num = 0; //解决一个奇怪的bug,需要登录两次
-    ServerAPI.WXWorkUrl(num, 'login', (res) => {
-        if (!res || res.code !== 0 || !res.data.url) 
-            return ElMessage.error(`请求登录失败!${res.msg}`)
-        window.location.href = res.data.url
-    });
+const Index = defineAsyncComponent(() => import('./components/Index.vue'));
+const PasswordLogin = defineAsyncComponent(() => import('./components/PasswordLogin.vue'));
+const Register = defineAsyncComponent(() => import('./components/Register.vue'));
+const ForgetPassword = defineAsyncComponent(() => import('./components/ForgetPassword.vue'));
 
+let mode = ref('Index');
+let update = (newmode) => {
+    mode.value = newmode;
 }
 
 </script>
@@ -59,86 +33,4 @@ let WXLogin = function () {
     height: 100vh;
     width: 100%;
 }
-
-.content {
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    flex-direction: column;
-    background-color: rgba(255, 255, 255, 0.7);
-    position: absolute;
-    top: 50%;
-    left: 50%;
-    transform: translate(-50%, -50%);
-    height: 400px;
-    width: 650px;
-    padding: 30px;
-    box-sizing: border-box;
-    border-radius: 10px;
-}
-
-.background-image h1 {
-    color: #337ecc;
-    font-size: 2em;
-    margin: 0;
-    margin-bottom: 20px;
-}
-
-.background-image button {
-    display: block;
-    width: 100%;
-    height: 60px;
-    padding: 15px;
-    margin: 10px 0;
-    font-size: 1em;
-    border: none;
-    border-radius: 10px;
-    cursor: pointer;
-    background-color: #337ecc;
-    color: #fff;
-}
-
-.agreementBox {
-    margin-top: 10px;
-    display: flex;
-}
-
-.agreementBox .checkBox {
-    display: inline-block;
-    height: 20px;
-}
-
-.agreementBox .text {
-    margin-left: 5px;
-    display: inline;
-    font-size: 12px;
-    line-height: 20px;
-}
-
-.agreementBox .text .bold {
-    font-weight: bold;
-    color: #000;
-}
-
-@media only screen and (max-width: 768px) {
-    .content {
-        height: auto;
-        width: 80%;
-        height: 35%;
-        padding: 25px;
-    }
-
-    .background-image button {
-        height: 50px;
-    }
-
-    .background-image h1 {
-        font-size: 1.5em;
-    }
-
-    .background-image button {
-        font-size: 0.9em;
-        padding: 10px;
-    }
-}
 </style>

+ 237 - 0
src/pages/Login/components/ForgetPassword.vue

@@ -0,0 +1,237 @@
+<template>
+    <div class="content">
+        <h1>忘记密码</h1>
+
+        <el-form ref="formRef" :model="form" class="form">
+            <el-form-item prop="username">
+                <el-input v-model="form.username" placeholder="输入用户名" :prefix-icon="User" />
+            </el-form-item>
+
+            <el-form-item prop="email">
+                <el-input v-model="form.email" placeholder="输入邮箱" :prefix-icon="Postcard" />
+            </el-form-item>
+
+            <el-form-item prop="text">
+                <div class="captcha">
+                    <el-input v-model="form.text" placeholder="输入验证码" class="captcha-input" :prefix-icon="Finished" />
+                    <img alt="验证码" :src="ImageCaptcha" @click="getCaptcha">
+                </div>
+            </el-form-item>
+
+            <el-form-item prop="code">
+                <el-input v-model="form.code" placeholder="邮箱验证码" :prefix-icon="Finished">
+                    <template #append>
+                        <div @click="sendEmail" v-if="time === 0">获取验证码</div>
+                        <div disabled v-else>{{ time }} s</div>
+                    </template>
+                </el-input>
+            </el-form-item>
+
+            <el-form-item prop="password1">
+                <el-input v-model="form.password1" placeholder="设置新密码" type="password" :prefix-icon="Lock" />
+            </el-form-item>
+
+            <el-form-item prop="password2">
+                <el-input v-model="form.password2" placeholder="再次输入密码" type="password" :prefix-icon="Lock" />
+            </el-form-item>
+
+        </el-form>
+
+        <button @click="Register()">找回账号</button>
+        <div class="littleButton">
+            <span @click="update('Index')">已有账号,立即登录</span> |
+            <span @click="update('register')">注册账号</span>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { ServerAPI } from '../../../app/lib/ServerAPI';
+import { User, Lock, Postcard, Finished } from '@element-plus/icons-vue';
+
+let ImageCaptcha = ref('');
+let form = reactive({
+    username: '',
+    email: '',
+    password1: '',
+    password2: '',
+    text: '',
+    id: '',
+    code: ''
+});
+
+let time = ref(0);
+let disabled = ref(false);
+
+const emit = defineEmits(['update']);
+
+let update = (mode) => {
+    emit('update', mode);
+}
+
+let getCaptcha = () => {
+    ServerAPI.ImageCaptcha((r) => {
+        if (!r || r.code != 0)
+            ElMessage.error(`获取图片验证码失败!${r.msg}`);
+
+        ImageCaptcha.value = r.data.img;
+        form.id = r.data.id;
+    })
+}
+
+onMounted(() => {
+    getCaptcha()
+})
+
+let settime = () => {
+    time.value = 60;
+    const timer = setInterval(() => {
+        if (time.value > 0) {
+            time.value--;
+        } else {
+            clearInterval(timer)
+        }
+    }, 1000)
+}
+
+let sendEmail = () => {
+    if (disabled.value)
+        return ElMessage.warning('您的操作太快了,休息一下吧!');
+    if (form.email == '')
+        return ElMessage.error('请填写邮箱');
+    if (form.text == '')
+        return ElMessage.error('请填写图片验证码');
+
+    disabled.value = true;
+    ServerAPI.SendEmail(form.email, form.text, form.id, 'forget', (r) => {
+        if (r && r.code === 0) {
+            ElMessage.success('发送邮箱验证码成功!');
+            settime();
+            disabled.value = false;
+        } else {
+            ElMessage.error(`获取邮箱验证码失败!${r.msg || ''}`);
+            disabled.value = false;
+        }
+    })
+
+}
+
+function CheckPassword(password) {
+    if (password.length < 8 || password.length > 16) {
+        return false;
+    }
+
+    // 使用正则表达式检查密码是否包含至少一个字母和一个数字
+    const hasLetter = /[a-zA-Z]/.test(password); // 检查是否包含字母
+    const hasNumber = /\d/.test(password);       // 检查是否包含数字
+
+    return hasLetter && hasNumber;
+}
+
+let Register = () => {
+    if (form.username === '' || form.password1 === '' || form.password2 === '' || form.email === '' || form.code === '' || form.text === '')
+        return ElMessage.error('请确保每项不能为空');
+    if (!CheckPassword(form.password1))
+        return ElMessage.error('密码需在8到16位之间,且包含字母和数字');
+    if (form.password1 !== form.password2)
+        return ElMessage.error('请确保两次输入的密码一致');
+
+    let password = btoa(form.password1);
+    ServerAPI.ForgetPassword(form.username, form.email, form.code, password, (res) => {
+        if (!res || res.code !== 0)
+            return ElMessage.error(`找回密码失败!${res.msg || ''}`);
+
+        ElMessage.success('找回密码成功!请使用新密码登录');
+        update('PasswordLogin');
+    });
+}
+</script>
+
+<style scoped>
+.content {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex-direction: column;
+    background-color: rgba(255, 255, 255, 0.7);
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    height: 650px;
+    width: 650px;
+    box-sizing: border-box;
+    border-radius: 10px;
+}
+
+.content .input {
+    display: flex;
+    flex-direction: column;
+    gap: 15px;
+}
+
+.content h1 {
+    color: #337ecc;
+    font-size: 2em;
+    margin: 0;
+    margin-bottom: 20px;
+}
+
+.el-input {
+    border-radius: 15px;
+    height: 50px;
+}
+
+.content .captcha {
+    display: flex;
+    height: 50px;
+}
+
+.content button {
+    width: 180px;
+    height: 40px;
+    margin-top: 20px;
+    font-size: 1em;
+    border: none;
+    border-radius: 10px;
+    background-color: #337ecc;
+    color: #fff;
+}
+
+.content .littleButton {
+    color: #444;
+    margin-top: 20px;
+    font-size: 0.9em;
+
+}
+
+@media only screen and (max-width: 768px) {
+    .content {
+        width: 80%;
+        height: 60%;
+        padding: 25px;
+    }
+
+    .el-input {
+        height: 40px;
+    }
+
+    .content .captcha {
+        height: 40px;
+    }
+
+    .content h1 {
+        font-size: 1.5em;
+    }
+
+    .content button {
+        height: 35px;
+        width: 150px;
+        font-size: 0.9em;
+    }
+
+    .content .littleButton {
+        font-size: 0.8em;
+    }
+}
+</style>

+ 96 - 0
src/pages/Login/components/Index.vue

@@ -0,0 +1,96 @@
+<template>
+    <div class="content">
+        <h1>用户登录</h1>
+        <button @click="update('PasswordLogin')">账号密码登录</button>
+        <button @click="WXLogin('login')">企业微信扫码登录</button>
+        <div class="littleButton">
+            <span @click="update('register')">注册账号</span> |
+            <span @click="update('forget')">忘记密码</span>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { ServerAPI } from '../../../app/lib/ServerAPI';
+
+const emit = defineEmits(['update']);
+let update = (mode) => {
+    emit('update', mode);
+}
+
+let WXLogin = function () {
+    const num = 0; //解决一个奇怪的bug,需要登录两次
+    ServerAPI.WXWorkUrl(num, 'login', (res) => {
+        if (!res || res.code !== 0 || !res.data.url)
+            return ElMessage.error(`请求登录失败!${res.msg}`)
+        window.location.href = res.data.url
+    });
+
+}
+</script>
+
+<style scoped>
+.content {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex-direction: column;
+    background-color: rgba(255, 255, 255, 0.7);
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    height: 400px;
+    width: 650px;
+    padding: 30px;
+    box-sizing: border-box;
+    border-radius: 10px;
+}
+
+.content h1 {
+    color: #337ecc;
+    font-size: 2em;
+    margin: 0;
+    margin-bottom: 20px;
+}
+
+.content button {
+    width: 100%;
+    height: 60px;
+    padding: 15px;
+    margin: 10px 0;
+    font-size: 1em;
+    border: none;
+    border-radius: 10px;
+    background-color: #337ecc;
+    color: #fff;
+}
+
+.content .littleButton {
+    color: #444;
+    margin-top: 20px;
+    font-size: 0.9em;
+}
+
+@media only screen and (max-width: 768px) {
+    .content {
+        width: 80%;
+        height: 35%;
+        padding: 25px;
+    }
+
+    .content h1 {
+        font-size: 1.5em;
+    }
+
+    .content button {
+        height: 50px;
+        font-size: 0.9em;
+        padding: 10px;
+    }
+
+    .content .littleButton {
+        font-size: 0.8em;
+    }
+}
+</style>

+ 197 - 0
src/pages/Login/components/PasswordLogin.vue

@@ -0,0 +1,197 @@
+<template>
+    <div class="content">
+        <h1>用户登录</h1>
+        <div class="input">
+            <el-input v-model="form.username" size="large" placeholder="输入用户名或邮箱" :prefix-icon="User" />
+            <el-input v-model="form.password" size="large" placeholder="输入密码" type="password" :prefix-icon="Lock" />
+            <div class="captcha">
+                <el-input v-model="form.text" placeholder="输入验证码" size="large" class="captcha-input"
+                    :prefix-icon="Finished" />
+                <img alt="验证码" :src="ImageCaptcha" @click="getCaptcha">
+            </div>
+        </div>
+        <button @click="Login()">登录</button>
+        <div class="littleButton">
+            <span @click="update('register')">注册账号</span> |
+            <span @click="update('forget')">忘记密码</span>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { ServerAPI } from '../../../app/lib/ServerAPI';
+import { User, Lock, Finished } from '@element-plus/icons-vue';
+import { useRoute, useRouter } from 'vue-router';
+import { App } from '../../../app/app';
+
+let route = useRoute();
+let router = useRouter();
+
+let ImageCaptcha = ref('');
+let form = reactive({
+    username: '',
+    password: '',
+    text: '',
+    id: ''
+});
+
+const emit = defineEmits(['update']);
+
+let update = (mode) => {
+    emit('update', mode);
+}
+
+let getCaptcha = () => {
+    ServerAPI.ImageCaptcha((r) => {
+        if (!r || r.code != 0)
+            ElMessage.error(`获取图片验证码失败!${r.msg}`);
+
+        ImageCaptcha.value = r.data.img;
+        form.id = r.data.id;
+    })
+}
+
+onMounted(() => {
+    getCaptcha()
+})
+
+let Login = () => {
+    if (form.username === '' || form.password === '' || form.text === '')
+        return ElMessage.error('请确保每项不能为空');
+
+    const loading = ElLoading.service({
+        lock: true,
+        text: '正在登录中,请稍候'
+    })
+
+    let password = btoa(form.password);
+
+    try {
+        ServerAPI.Login(form.username, password, form.text, form.id, (res) => {
+            if (!res || res.code !== 0) {
+                loading.close();
+                ElMessage.error(`登录失败!${res.msg || ''}`);
+                getCaptcha();
+                form.text = '';
+                return;
+            } else {
+                loading.close();
+                ElMessage.success('登录成功');
+                App.refershUser(res.data);
+
+                if (route.query.backPage !== undefined) {
+                    ElMessage.success("即将跳转...");
+                    setTimeout(() => {
+                        router.replace({
+                            name: route.query.backPage
+                        });
+                    }, 1000);
+                    return;
+                }
+
+                if (window.history.state && window.history.state.key) {
+                    router.back();
+                } else {
+                    router.replace({
+                        name: "Main",
+                    })
+                }
+            }
+
+        })
+    } catch (error) {
+        ElMessage.error("登录失败!请稍后再试" + error);
+        router.replace({
+            name: "Login",
+        })
+    }
+}
+</script>
+
+<style scoped>
+.content {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex-direction: column;
+    background-color: rgba(255, 255, 255, 0.7);
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    height: 400px;
+    width: 650px;
+    box-sizing: border-box;
+    border-radius: 10px;
+}
+
+.content .input {
+    display: flex;
+    flex-direction: column;
+    gap: 15px;
+}
+
+.content h1 {
+    color: #337ecc;
+    font-size: 2em;
+    margin: 0;
+    margin-bottom: 20px;
+}
+
+.el-input {
+    border-radius: 15px;
+    height: 50px;
+}
+
+.content .captcha {
+    display: flex;
+    height: 50px;
+}
+
+.content button {
+    width: 180px;
+    height: 40px;
+    margin-top: 20px;
+    font-size: 1em;
+    border: none;
+    border-radius: 10px;
+    background-color: #337ecc;
+    color: #fff;
+}
+
+.content .littleButton {
+    color: #444;
+    margin-top: 20px;
+    font-size: 0.9em;
+}
+
+@media only screen and (max-width: 768px) {
+    .content {
+        width: 80%;
+        height: 45%;
+        padding: 25px;
+    }
+
+    .el-input {
+        height: 40px;
+    }
+
+    .content .captcha {
+        height: 40px;
+    }
+
+    .content h1 {
+        font-size: 1.5em;
+    }
+
+    .content button {
+        height: 35px;
+        width: 150px;
+        font-size: 0.9em;
+    }
+
+    .content .littleButton {
+        font-size: 0.8em;
+    }
+}
+</style>

+ 243 - 0
src/pages/Login/components/Register.vue

@@ -0,0 +1,243 @@
+<template>
+    <div class="content">
+        <h1>注册账号</h1>
+
+        <el-form ref="formRef" :model="form" class="form">
+            <el-form-item prop="username">
+                <el-input v-model="form.username" placeholder="输入用户名" :prefix-icon="User" />
+            </el-form-item>
+
+            <el-form-item prop="email">
+                <el-input v-model="form.email" placeholder="输入邮箱" :prefix-icon="Postcard" />
+            </el-form-item>
+
+            <el-form-item prop="text">
+                <div class="captcha">
+                    <el-input v-model="form.text" placeholder="输入验证码" class="captcha-input" :prefix-icon="Finished" />
+                    <img alt="验证码" :src="ImageCaptcha" @click="getCaptcha">
+                </div>
+            </el-form-item>
+
+            <el-form-item prop="code">
+                <el-input v-model="form.code" placeholder="邮箱验证码" :prefix-icon="Finished">
+                    <template #append>
+                        <div @click="sendEmail" v-if="time === 0">获取验证码</div>
+                        <div disabled v-else>{{ time }} s</div>
+                    </template>
+                </el-input>
+            </el-form-item>
+
+            <el-form-item prop="password1">
+                <el-input v-model="form.password1" placeholder="设置密码" type="password" :prefix-icon="Lock" />
+            </el-form-item>
+
+            <el-form-item prop="password2">
+                <el-input v-model="form.password2" placeholder="再次输入密码" type="password" :prefix-icon="Lock" />
+            </el-form-item>
+
+        </el-form>
+
+        <button @click="Register()">注册</button>
+        <div class="littleButton">
+            <span @click="update('Index')">已有账号,立即登录</span> |
+            <span @click="update('forget')">忘记密码</span>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { ServerAPI } from '../../../app/lib/ServerAPI';
+import { User, Lock, Postcard, Finished } from '@element-plus/icons-vue';
+
+let ImageCaptcha = ref('');
+let form = reactive({
+    username: '',
+    email: '',
+    password1: '',
+    password2: '',
+    text: '',
+    id: '',
+    code: ''
+});
+
+let time = ref(0);
+let disabled = ref(false);
+
+const emit = defineEmits(['update']);
+
+let update = (mode) => {
+    emit('update', mode);
+}
+
+let getCaptcha = () => {
+    ServerAPI.ImageCaptcha((r) => {
+        if (!r || r.code != 0)
+            ElMessage.error(`获取图片验证码失败!${r.msg}`);
+
+        ImageCaptcha.value = r.data.img;
+        form.id = r.data.id;
+    })
+}
+
+onMounted(() => {
+    getCaptcha()
+})
+
+let settime = () => {
+    time.value = 60;
+    const timer = setInterval(() => {
+        if (time.value > 0) {
+            time.value--;
+        } else {
+            clearInterval(timer)
+        }
+    }, 1000)
+}
+
+let sendEmail = () => {
+    if (disabled.value)
+        return ElMessage.warning('您的操作太快了,休息一下吧!');
+    if (form.email == '')
+        return ElMessage.error('请填写邮箱');
+    if (form.text == '')
+        return ElMessage.error('请填写图片验证码');
+
+    disabled.value = true;
+    ServerAPI.SendEmail(form.email, form.text, form.id, 'register', (r) => {
+        if (r && r.code === 0) {
+            ElMessage.success('发送邮箱验证码成功!');
+            settime();
+            disabled.value = false;
+        } else {
+            ElMessage.error(`获取邮箱验证码失败!${r.msg || ''}`);
+            disabled.value = false;
+        }
+    })
+
+}
+
+function checkUsername(username) {
+    const regex = /^[\u4e00-\u9fa5A-Za-z0-9]{2,8}$/;
+    return regex.test(username);
+}
+
+function CheckPassword(password) {
+    if (password.length < 8 || password.length > 16) {
+        return false;
+    }
+
+    // 使用正则表达式检查密码是否包含至少一个字母和一个数字
+    const hasLetter = /[a-zA-Z]/.test(password); // 检查是否包含字母
+    const hasNumber = /\d/.test(password);       // 检查是否包含数字
+
+    return hasLetter && hasNumber;
+}
+
+let Register = () => {
+    if (form.username === '' || form.password1 === '' || form.password2 === '' || form.email === '' || form.code === '' || form.text === '')
+        return ElMessage.error('请确保每项不能为空');
+    if (!checkUsername(form.username))
+        return ElMessage.error('用户名需在2到8位之间,且只能含有英文字母和汉字');
+    if (!CheckPassword(form.password1))
+        return ElMessage.error('密码需在8到16位之间,且包含字母和数字');
+    if (form.password1 !== form.password2)
+        return ElMessage.error('请确保两次输入的密码一致');
+
+    let password = btoa(form.password1);
+    ServerAPI.Register(form.username, form.email, form.code, password, (res) => {
+        if (!res || res.code !== 0)
+            return ElMessage.error(`注册失败!${res.msg || ''}`);
+
+        ElMessage.success('注册成功!');
+        update('PasswordLogin');
+    });
+}
+</script>
+
+<style scoped>
+.content {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex-direction: column;
+    background-color: rgba(255, 255, 255, 0.7);
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    height: 650px;
+    width: 650px;
+    box-sizing: border-box;
+    border-radius: 10px;
+}
+
+.content .input {
+    display: flex;
+    flex-direction: column;
+    gap: 15px;
+}
+
+.content h1 {
+    color: #337ecc;
+    font-size: 2em;
+    margin: 0;
+    margin-bottom: 20px;
+}
+
+.el-input {
+    border-radius: 15px;
+    height: 50px;
+}
+
+.content .captcha {
+    display: flex;
+    height: 50px;
+}
+
+.content button {
+    width: 180px;
+    height: 40px;
+    margin-top: 20px;
+    font-size: 1em;
+    border: none;
+    border-radius: 10px;
+    background-color: #337ecc;
+    color: #fff;
+}
+
+.content .littleButton {
+    color: #444;
+    margin-top: 20px;
+    font-size: 0.9em;
+}
+
+@media only screen and (max-width: 768px) {
+    .content {
+        width: 80%;
+        height: 60%;
+        padding: 25px;
+    }
+
+    .el-input {
+        height: 40px;
+    }
+
+    .content .captcha {
+        height: 40px;
+    }
+
+    .content h1 {
+        font-size: 1.5em;
+    }
+
+    .content button {
+        height: 35px;
+        width: 150px;
+        font-size: 0.9em;
+    }
+
+    .content .littleButton {
+        font-size: 0.8em;
+    }
+}
+</style>

+ 2 - 3
src/pages/Login/WXLoginStage2.vue → src/pages/Login/components/WXLoginStage2.vue

@@ -1,13 +1,12 @@
 <script setup>
 import { useRoute, useRouter } from 'vue-router';
-import { App } from '../../app/app';
-import { ServerAPI } from '../../app/lib/ServerAPI';
+import { App } from '../../../app/app';
+import { ServerAPI } from '../../../app/lib/ServerAPI';
 
 let route = useRoute();
 let router = useRouter();
 
 onMounted(async () => {
-    console.log('1')
     const loading = ElLoading.service({
         lock: true,
         text: '正在登录中,请稍候'

+ 1 - 1
src/pages/Mine/Mine.vue

@@ -19,7 +19,7 @@
                                 <el-tag class="tag" effect="dark">{{ name === 'admin' ? '网站管理员' : '考勤管理员' }}</el-tag>
                             </div>
                         </div>
-                        <div class="dec">{{ app.user.wxid }}</div>
+                        <div class="dec">{{ app.user.wxid || '未绑定企业微信' }} | {{ app.user.email || '未绑定邮箱' }}</div>
                     </div>
                 </div>
 

+ 1 - 1
src/router/index.js

@@ -15,7 +15,7 @@ const routes = [
             {
                 name: "WXLoginStage2",
                 path: "Stage2",
-                component: () => import('../pages/Login/WXLoginStage2.vue'),
+                component: () => import('../pages/Login/components/WXLoginStage2.vue'),
                 meta: { title: '企业微信登录' }
             }
         ]