Browse Source

✨ feat: 增加个人中心及个人信息更新页面

Pchen. 8 months ago
parent
commit
269b5626e8
3 changed files with 429 additions and 0 deletions
  1. 258 0
      src/pages/Mine/Mine.vue
  2. 111 0
      src/pages/Setup/UpdateInfoStage1.vue
  3. 60 0
      src/pages/Setup/UpdateInfoStage2.vue

+ 258 - 0
src/pages/Mine/Mine.vue

@@ -0,0 +1,258 @@
+<template>
+    <Header />
+    <div style="min-height: 75vh;">
+        <div class="cards">
+            <div class="card" v-if="app.user != undefined">
+                <div class="top">
+                    <div class="avatar">
+                        <el-avatar :src="app.user.avatar" v-if="app.user.avatar" :size="avatarSize" />
+                        <el-avatar :icon="UserFilled" v-else :size="avatarSize" />
+                    </div>
+
+                    <div class="userInfo">
+                        <div class="name">
+                            {{ app.user.username }}
+                            <div class="tags" v-if="permissions.length === 0">
+                                <el-tag class="tag" effect="dark">普通用户</el-tag>
+                            </div>
+                            <div v-for="(name, index) in permissions" class="tags">
+                                <el-tag class="tag" effect="dark">{{ name === 'admin' ? '网站管理员' : '考勤管理员' }}</el-tag>
+                            </div>
+                        </div>
+                        <div class="dec">{{ app.user.wxid }}</div>
+                    </div>
+                </div>
+
+            </div>
+
+            <div class="card" v-else>
+                <div class="top">
+                    <el-avatar icon="UserFilled" :size="avatarSize" />
+                    <div class="userInfo">
+                        <div class="name">
+                            未登录用户
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <div class="card">
+                <div class="buttons">
+                    <div class="button" @click="$router.push('/ClockIn')">
+                        <el-icon :size="30">
+                            <Position />
+                        </el-icon>
+                        <span>考勤打卡</span>
+                    </div>
+
+                    <div class="button" @click="$router.push('/ClockInManage')"
+                        v-if="permissions.includes('admin') || permissions.includes('manage')">
+                        <el-icon :size="30">
+                            <SetUp />
+                        </el-icon>
+                        <span>考勤项目管理</span>
+                    </div>
+
+                    <div class="button" @click="$router.push('/ApplyPermission')">
+                        <el-icon :size="30">
+                            <MessageBox />
+                        </el-icon>
+                        <span>补卡申请</span>
+                    </div>
+
+                    <div class="button" @click="$router.push('/Admin')" v-if="permissions.includes('admin')">
+                        <el-icon :size="30">
+                            <SetUp />
+                        </el-icon>
+                        <span>网站管理</span>
+                    </div>
+
+                    <div class="button" @click="$router.push('/UpdateInfoStage1')">
+                        <el-icon :size="30">
+                            <Setting />
+                        </el-icon>
+                        <span>更新个人信息</span>
+                    </div>
+
+                    <div class="button" @click="logout()" v-if="app.user !== undefined">
+                        <el-icon :size="30">
+                            <SwitchButton />
+                        </el-icon>
+                        <span>退出登录</span>
+                    </div>
+                </div>
+
+            </div>
+        </div>
+    </div>
+
+    <Footer />
+</template>
+
+<script setup>
+import { App } from '../../app/app';
+import { useRouter } from 'vue-router';
+import { ServerAPI } from '../../app/lib/ServerAPI';
+import Header from '../../components/Header.vue';
+
+let router = useRouter();
+let avatarSize = ref(100);
+
+if (window.innerWidth <= 768) {
+    avatarSize.value = 50
+}
+
+let app = reactive(App);
+
+let logout = function () {
+    ElMessageBox.confirm(
+        '是否退出登录?',
+        '警告',
+        {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning',
+        }
+    )
+        .then(() => {
+            ElMessage.success("退出登录成功!");
+            app.cleanUser();
+            router.push('/login');
+        })
+        .catch(() => { })
+}
+
+let permissions = ref([]);
+
+let getPermission = () => {
+    if (app.hasUser()) {
+        ServerAPI.getPermissions(app.user.uuid, app.user.session, (r) => {
+            if (!r || r.code !== 0)
+                ElMessage.error(`获取用户权限失败!$${r.msg}`);
+            permissions.value = r.permission;
+        })
+    }
+}
+
+getPermission();
+</script>
+
+<style scoped>
+.cards {
+    display: grid;
+    grid-template-columns: 1fr;
+}
+
+.card {
+    background-color: #fff;
+    width: 70%;
+    margin: 0 auto;
+    margin-bottom: 20px;
+    border-radius: 10px;
+    padding: 40px;
+    animation: fadeIn 0.6s ease-in-out forwards;
+}
+
+.card .top {
+    display: flex;
+}
+
+.card .userInfo {
+    margin-left: 20px;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    gap: 5px;
+}
+
+.card .userInfo .name {
+    color: #222226;
+    font-size: 25px;
+    font-weight: 500;
+    line-height: 30px;
+    display: flex;
+    gap: 8px;
+    flex-wrap: wrap;
+}
+
+.tag {
+    background-color: #337ecc;
+    border: none;
+}
+
+.card .row {
+    text-align: center;
+    margin-top: 30px;
+}
+
+.card .buttons {
+    display: grid;
+    grid-template-columns: repeat(4, 0fr);
+    justify-content: center;
+    gap: 40px;
+}
+
+.card .buttons .button {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    width: 150px;
+    height: 150px;
+    background-color: #337ecc;
+    color: white;
+    border: none;
+    cursor: pointer;
+    border-radius: 10px;
+    font-size: 1em;
+}
+
+.card .buttons .button span {
+    margin-top: 10px;
+    /* 调整图标与文字之间的间距 */
+}
+
+.overlay {
+    position: fixed;
+    width: 100%;
+    height: 100vh;
+    background-color: rgba(0, 0, 0, 0.4);
+}
+
+@media only screen and (max-width: 768px) {
+    .card {
+        margin-bottom: 15px;
+        padding: 20px;
+        width: 80%;
+    }
+
+    .card .userInfo {
+        margin-left: 10px;
+        gap: 2px;
+    }
+
+    .card .userInfo .name {
+        color: #222226;
+        font-size: 18px;
+        font-weight: 500;
+        line-height: 25px;
+        gap: 5px
+    }
+
+    .card .userInfo .dec {
+        font-size: 12px
+    }
+
+    .card .buttons {
+        grid-template-columns: repeat(3, 0fr);
+        gap: 20px;
+    }
+
+    .card .buttons .button {
+        width: 85px;
+        height: 85px;
+        font-size: 0.8em;
+    }
+
+}
+</style>

+ 111 - 0
src/pages/Setup/UpdateInfoStage1.vue

@@ -0,0 +1,111 @@
+<template>
+    <Header />
+    <div class="root">
+        <div class="content">
+            <div class="avatar"><el-avatar :size="100" :src="App.user.avatar ? App.user.avatar : ''" /></div>
+
+            <el-form :model="form" ref="formRef" label-width="auto" :label-position="'right'" style>
+                <el-form-item label="用户名" prop="username">
+                    <el-input v-model="form.username" disabled />
+                </el-form-item>
+
+                <el-form-item label="企业微信ID" prop="wxid">
+                    <el-input v-model="form.wxid" disabled />
+                </el-form-item>
+            </el-form>
+
+            <div class="btn" @click="onGetUrl">
+                获取企业微信资料
+            </div>
+
+            <div class="agreementBox">
+                <div class="text">
+                    我们将获取你的用户名、用户ID等信息
+                </div>
+            </div>
+        </div>
+
+        <router-view></router-view>
+    </div>
+</template>
+
+<script setup>
+import Header from '../../components/Header.vue';
+import { App } from '../../app/app';
+import { useRouter } from 'vue-router';
+import { ServerAPI } from '../../app/lib/ServerAPI';
+
+let router = useRouter();
+
+if (!App.hasUser()) {
+    ElMessage.error('请登录!')
+    router.replace({
+        name: "Login"
+    });
+}
+
+let formRef = ref();
+let form = reactive({
+    username: App.user.username,
+    wxid: App.user.wxid
+});
+
+
+let onGetUrl = function () {
+    ServerAPI.WXWorkUrl(0, 'update', (res) => {
+        if (res == undefined || res.code != 0) 
+            return ElMessage.error(`获取登录链接失败!${res.msg}`);
+        
+        window.location.href = res.data.url
+    });
+}
+</script>
+
+<style scoped>
+.avatar {
+    margin-top: -20px;
+    margin-bottom: 20px;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+}
+
+.content {
+    padding: 18px;
+    width: 60%;
+    margin: 0 auto;
+}
+
+.btn {
+    margin-top: 10px;
+    margin-bottom: 5px;
+    width: 100%;
+    height: 50px;
+    background-color: #337ecc;
+    border-radius: 10px;
+    line-height: 50px;
+    text-align: center;
+    color: #fff;
+    font-weight: bold;
+    font-size: 14px;
+}
+
+.agreementBox .text {
+    margin-left: 5px;
+    display: inline;
+    font-size: 12px;
+    color: #777;
+    line-height: 20px;
+}
+
+.agreementBox .text .bold {
+    font-weight: bold;
+    color: #000;
+}
+
+@media only screen and (max-width: 768px) {
+    .content {
+        width: 90%
+    }
+}
+</style>

+ 60 - 0
src/pages/Setup/UpdateInfoStage2.vue

@@ -0,0 +1,60 @@
+<script setup>
+import { useRouter } from 'vue-router';
+import { App } from '../../app/app';
+import { ServerAPI } from '../../app/lib/ServerAPI';
+
+let router = useRouter();
+
+onMounted(async () => {
+    const loading = ElLoading.service({
+        lock: true,
+        text: '正在更新中,请稍候'
+    })
+
+    // 获取当前 URL 中的 code 参数
+    const queryString = window.location.search;
+    const urlParams = new URLSearchParams(queryString);
+    const code = urlParams.get('code');
+    let num = urlParams.get('num');
+
+    if (num === 0 && code === '' || code === null) {
+        num = 1
+        ServerAPI.WXWorkUrl(num, 'update', (res) => {
+            loading.close();
+
+            if (res == undefined || res.code != 0) 
+                return ElMessage.error(`更新失败!${res.msg}`)
+
+            window.location.href = res.data.url
+        })
+    }
+
+    try {
+        ServerAPI.UpdateInfo(App.user.uuid, App.user.session, code,(res) => {
+            if (res.code !== 0) {
+                loading.close();
+                ElMessage.error(`更新失败!${res.msg}`);
+                router.replace({
+                    name: "UpdateInfoStage1",
+                })
+                return;
+            }
+
+            loading.close();
+            ElMessage.success("更新个人信息成功");
+            App.refershUser(res.data);
+
+        })
+    } catch (error) {
+        loading.close();
+        ElMessage({
+            message: "更新失败!请稍后再试" + error,
+            type: "error"
+        });
+
+        router.replace({
+            name: "UpdateInfoStage1",
+        })
+    }
+});
+</script>