自学内容网 自学内容网

4. 【Vue实战--孢子记账--Web 版开发】--个人中心功能集

在这一片文章中我们开始开发个人中心功能集,它包含:重置密码安全设置修改用户名注销账户退出功能。其中前三个功能我们使用弹出窗的形式实现,后两个功能由于没有需要输入的功能,因此只有一个简单的链接。

一、功能

要实现的功能前面已经说了,在这一小节我们来看一下原型。
在这里插入图片描述
这个原型功能很简单,鼠标移动到右上角的用户头像上时会显示下拉菜单,菜单上的功能就是我们要实现的,三个弹窗对应了三个需要交互的功能。

Tip:这个原型是临时主页的原型,登录后跳转到这个页面。

二、实现

2.1 个人中心功能集数据模型

我们根据前面所说的功能,分析出三个数据模型:ResetPassword(重置密码)、SecuritySetting(安全设置)、PersonalInformation(个人信息)。在Interface文件夹下新建personalCenter.ts文件存储这三个数据模型。代码如下:

/*重置密码*/
export interface ResetPassword {
    /** 旧密码 */
    oldPassword: string;
    /** 新密码 */
    newPassword: string;
    /** 确认新密码 */
    reNewPassword: string;
}
/*安全设置*/
export interface SecuritySetting {
    /** 手机号 */
    phoneNumber: string;
    /** 邮箱 */
    email: string;
}
/*个人信息*/
export interface PersonalInformation {
    /** 用户名 */
    userName: string;
}

代码很简单,我这里就不多讲了。

2.2 页面实现

在页面上我们需要实现三个弹出框和一个下拉菜单,弹窗使用Element-Plus的el-dialog实现,下拉菜单使用el-menu。我们在pages目录下新建Main.vue文件来实现这个功能。

  1. 脚本部分
    <script setup lang="ts">
    import {ref, reactive, inject} from 'vue'
    import type {ResetPassword, SecuritySetting, PersonalInformation} from '../Interface/personalCenter.ts'
    import {type FormInstance, type FormRules, ElMessage} from "element-plus";
    import type {Response} from '../Interface/response.ts'
    import {router} from "../router";
    
    const resetPasswordFormVisible = ref(false)
    const resetPasswordRef = ref<FormInstance>()
    const resetPasswordRules = reactive<FormRules<ResetPassword>>({
    oldPassword: [
        {required: true, message: '旧密码不能为空', trigger: 'blur'}
    ],
    newPassword: [
        {required: true, message: '新密码不能为空', trigger: 'blur'},
    ],
    reNewPassword: [
        {required: true, message: '确认密码不能为空', trigger: 'blur'},
        {
        validator: (_, value, callback) => {
            if (value !== resetPasswordData.newPassword) {
            callback(new Error('两次输入密码不一致'));
            } else {
            callback();
            }
        }, trigger: 'blur'
        }
    ]
    })
    const resetPasswordData = reactive<ResetPassword>({
    oldPassword: '',
    newPassword: '',
    reNewPassword: ''
    })
    
    const securitySettingFormVisible = ref(false)
    const securitySettingRef = ref<FormInstance>()
    const securitySettingRules = reactive<FormRules<SecuritySetting>>({
    phoneNumber: [
        {required: true, message: '手机不能为空', trigger: 'blur'},
        {pattern: /^1[3456789]\d{9}$/, message: '手机号格式不正确', trigger: 'blur'}
    ],
    email: [
        {required: true, message: '手机号不能为空', trigger: 'blur'},
        {type: 'email', message: '邮箱格式不正确', trigger: 'blur'}
    ]
    })
    const securitySettingData = reactive<SecuritySetting>({
    phoneNumber: '',
    email: ''
    })
    
    const personalInformationFormVisible = ref(false)
    const personalInformationRef = ref<FormInstance>()
    const personalInformationRules = reactive<FormRules<PersonalInformation>>({
    userName: [
        {required: true, message: '用户名不能为空', trigger: 'blur'}
    ]
    })
    const personalInformationData = reactive<PersonalInformation>({
    userName: '',
    })
    
    const axios: any = inject('axios')
    
    
    /*重置密码*/
    const resetPassword = (formEl: FormInstance | undefined) => {
    if (!formEl) return
    formEl.validate().then(() => {
        axios.put(import.meta.env.VITE_API_BASE_URL + '/api/SysUser/ResetPassword',
            resetPasswordData, {
            headers: {
                'Authorization': localStorage.getItem('token')
            }
            }).then((res: any) => {
        const response: Response<boolean> = res.data;
        if (response.statusCode === 200) {
            ElMessage.success('修改成功')
            localStorage.removeItem('token')
            localStorage.removeItem('refreshToken')
            resetPasswordFormVisible.value = false
            router.push({name: 'login'});
        } else {
            ElMessage.error(response.errorMessage)
        }
        }).catch((err: any) => {
        console.log(err);
        });
    }).catch(() => {
        return
    })
    }
    /*安全设置*/
    const securitySetting = (formEl: FormInstance | undefined) => {
    if (!formEl) return
    formEl.validate().then(() => {
        axios.put(import.meta.env.VITE_API_BASE_URL + '/api/SysUser/EditUserSecurity',
            securitySettingData, {
            headers: {
                'Authorization': localStorage.getItem('token')
            }
            }).then((res: any) => {
        const response: Response<boolean> = res.data;
        if (response.statusCode === 200) {
            ElMessage.success('修改成功')
            securitySettingFormVisible.value = false
        } else {
            ElMessage.error(response.errorMessage)
        }
        }).catch((err: any) => {
        console.log(err);
        });
    }).catch(() => {
        return
    })
    }
    /*修改用户名*/
    const personalInformation = (formEl: FormInstance | undefined) => {
    if (!formEl) return
    formEl.validate().then(() => {
        axios.put(import.meta.env.VITE_API_BASE_URL + '/api/SysUser/EditUserName',
            personalInformationData, {
            headers: {
                'Authorization': localStorage.getItem('token')
            }
            }).then((res: any) => {
        const response: Response<boolean> = res.data;
        if (response.statusCode === 200) {
            ElMessage.success('修改成功')
            personalInformationFormVisible.value = false
        } else {
            ElMessage.error(response.errorMessage)
        }
        }).catch((err: any) => {
        console.log(err);
        });
    }).catch(() => {
        return
    })
    }
    /*注销账户*/
    const deleteUser = () => {
    axios.delete(import.meta.env.VITE_API_BASE_URL + '/api/SysUser/LogoutUser', {
        headers: {
        'Authorization': localStorage.getItem('token')
        }
    }).then((res: any) => {
        const response: Response<boolean> = res.data;
        if (response.statusCode === 200) {
        ElMessage.success('注销成功')
        localStorage.removeItem('token')
        localStorage.removeItem('refreshToken')
        router.push({name: 'login'});
        } else {
        ElMessage.error(response.errorMessage)
        }
    }).catch((err: any) => {
        console.log(err);
    });
    }
    /*退出*/
    const logout = () => {
    localStorage.removeItem('token')
    localStorage.removeItem('refreshToken')
    router.push({name: 'login'});
    }
    </script>
    
    这段代码使用Vue 3的Composition API和TypeScript来实现一个个人中心的功能模块,包括重置密码、安全设置、修改用户名、注销账户和退出登录等操作。它主要依赖Vue和Element Plus框架,并使用axios进行HTTP请求。
    首先,通过import引入了必要的模块和类型,包括Vue的refreactiveinject,Element Plus的FormInstanceFormRulesElMessage,以及自定义类型ResetPasswordSecuritySettingPersonalInformationResponserouter用于路由跳转,axios通过依赖注入获取实例,用于HTTP请求。
    在代码中定义了三个表单的可见性和数据状态resetPasswordFormVisibleresetPasswordDataresetPasswordRules用于重置密码表单。securitySettingFormVisiblesecuritySettingDatasecuritySettingRules用于安全设置表单。personalInformationFormVisiblepersonalInformationDatapersonalInformationRules用于修改用户名表单。
    并且每个表单都有相应的验证规则,例如密码确认需要匹配,新旧密码不能为空,手机号码和邮箱格式验证等。
    在代码中,resetPassword方法在验证表单后,通过PUT请求将重置密码的数据发送到/api/SysUser/ResetPassword接口,成功时会提示用户密码修改成功并跳转到登录页面,失败则显示错误信息。securitySetting方法则在表单验证后,发送PUT请求到/api/SysUser/EditUserSecurity,提交用户修改的安全设置信息,如果操作成功,会关闭表单并提示用户修改成功,否则显示错误信息。对于personalInformation方法,用于处理用户名的修改,通过PUT请求将新用户名提交到/api/SysUser/EditUserName,成功后关闭表单并提示用户,失败时显示相应的错误信息。deleteUser方法负责账户的注销操作,发送DELETE请求到/api/SysUser/LogoutUser,成功注销后清除本地存储中的token,并跳转回登录页面。最后,logout方法简单地清除本地存储中的token并跳转到登录页面,确保用户成功退出登录。
  2. html部分
    <template>
    <div class="main">
        <el-container>
        <el-header>
            <el-menu mode="horizontal" :ellipsis="false">
            <el-menu-item>
                <img
                    style="width: 100px"
                    src="/src/assets/logo.png"
                    alt="Element logo"
                />
            </el-menu-item>
            <el-sub-menu>
                <template #title>
                <el-avatar :size="40"/>
                </template>
                <el-menu-item @click="resetPasswordFormVisible=true">重置密码</el-menu-item>
                <el-menu-item @click="securitySettingFormVisible=true">安全设置</el-menu-item>
                <el-menu-item @click="personalInformationFormVisible=true">修改用户名</el-menu-item>
                <el-menu-item @click="deleteUser">注销账户</el-menu-item>
                <el-menu-item @click="logout">退出</el-menu-item>
            </el-sub-menu>
            </el-menu>
        </el-header>
        <el-main>Main</el-main>
        </el-container>
    </div>
    <!--重置密码弹窗-->
    <el-dialog center v-model="resetPasswordFormVisible" title="重置密码" width="500">
        <template #header="{titleId, titleClass }">
        <div>
            <span :id="titleId" :class="titleClass">重置密码</span>
        </div>
        </template>
        <el-form
            :model="resetPasswordData"
            label-position="top"
            ref="resetPasswordRef"
            :rules="resetPasswordRules"
            status-icon>
        <el-form-item label="旧密码" prop="oldPassword">
            <el-input type="password" v-model="resetPasswordData.oldPassword"/>
        </el-form-item>
        <el-form-item label="新密码" prop="newPassword">
            <el-input type="password" v-model="resetPasswordData.newPassword"/>
        </el-form-item>
        <el-form-item label="确认密码" prop="reNewPassword">
            <el-input type="password" v-model="resetPasswordData.reNewPassword"/>
        </el-form-item>
        </el-form>
        <template #footer>
        <div class="dialog-footer">
            <el-button style="width: 100%" size="large" type="primary" @click="resetPassword(resetPasswordRef)">
            确定
            </el-button>
        </div>
        </template>
    </el-dialog>
    <!--安全设置弹窗-->
    <el-dialog center v-model="securitySettingFormVisible" title="安全设置" width="500">
        <template #header="{titleId, titleClass }">
        <div>
            <span :id="titleId" :class="titleClass">安全设置</span>
        </div>
        </template>
        <el-form
            :model="securitySettingData"
            label-position="top"
            ref="securitySettingRef"
            :rules="securitySettingRules"
            status-icon>
        <el-form-item label="邮箱" prop="email">
            <el-input v-model="securitySettingData.email"/>
        </el-form-item>
        <el-form-item label="手机号" prop="phoneNumber">
            <el-input v-model="securitySettingData.phoneNumber"/>
        </el-form-item>
        </el-form>
        <template #footer>
        <div class="dialog-footer">
            <el-button style="width: 100%" size="large" type="primary" @click="securitySetting(securitySettingRef)">
            确定
            </el-button>
        </div>
        </template>
    </el-dialog>
    <!--修改用户名弹窗-->
    <el-dialog center v-model="personalInformationFormVisible" title="修改用户名" width="500">
        <template #header="{titleId, titleClass }">
        <div>
            <span :id="titleId" :class="titleClass">修改用户名</span>
        </div>
        </template>
        <el-form
            :model="personalInformationData"
            label-position="top"
            ref="personalInformationRef"
            :rules="personalInformationRules"
            status-icon>
        <el-form-item label="用户名" prop="userName">
            <el-input v-model="personalInformationData.userName"/>
        </el-form-item>
        </el-form>
        <template #footer>
        <div class="dialog-footer">
            <el-button style="width: 100%" size="large" type="primary" @click="personalInformation(personalInformationRef)">
            确定
            </el-button>
        </div>
        </template>
    </el-dialog>
    </template>
    
    这段代码,页面的主结构由<el-container>组件构成,包含一个头部<el-header>和主体部分<el-main>。头部部分嵌套了一个水平菜单<el-menu>,其中包括一个展示公司或产品标志的菜单项,和一个用户操作的子菜单<el-sub-menu>。用户操作菜单项使用头像作为标题,并提供了多个操作选项,如重置密码、安全设置、修改用户名、注销账户和退出登录。这些菜单项通过点击事件绑定相关方法来控制弹窗的显示和执行相应的用户操作。
    重置密码弹窗由<el-dialog>组件实现,其v-model属性绑定了resetPasswordFormVisible,用于控制弹窗的可见性。弹窗标题自定义为“重置密码”,主体部分是一个表单<el-form>,表单内有三个输入项:旧密码、新密码和确认密码,每个输入项都有相应的验证规则。表单底部是一个确认按钮,点击后触发resetPassword方法,提交表单数据。
    安全设置弹窗类似,也由<el-dialog>实现,控制可见性的变量是securitySettingFormVisible。表单内容包括邮箱和手机号两个输入项,同样配置了验证规则和提交按钮,点击按钮后执行securitySetting方法。
    修改用户名弹窗结构与前两个相似,控制变量为personalInformationFormVisible。表单内只有一个输入项,用于修改用户名,点击确认按钮触发personalInformation方法。
2.3 路由设置

由于个人中心功能需要在登录后才可使用,因此我们需要修改路由脚本index.ts,在其中增加路由守卫的beforeEach函数,代码如下:

router.beforeEach((to, _) => {
    if (to.name !== 'login') {
        const token = localStorage.getItem('token')
        if (token) {
            return true
        } else {
            return {name: 'login'}
        }
    }
})

这段代码用于在用户访问页面之前进行权限验证。router.beforeEach是一个全局前置守卫函数,接收两个参数:to表示目标路由对象,_是当前路由对象(未使用)。在函数内部,首先判断目标路由的名称to.name是否不是'login',即用户是否试图访问非登录页面。如果是非登录页面,则接着检查本地存储中是否存在名为'token'的项。如果存在token,说明用户已登录,路由放行,返回true表示允许访问该页面。否则,如果token不存在,说明用户未登录,路由会被重定向到登录页面,通过return { name: 'login' }实现页面跳转。

三、总结

这篇文章介绍了开发个人中心功能集的实现,包括重置密码、安全设置、修改用户名、注销账户和退出功能。其中前三个功能通过弹出窗实现,后两个功能为简单的链接。文章首先描述了功能和展示了原型,原型中鼠标移动到右上角用户头像时显示下拉菜单,菜单上的功能对应要实现的功能项。接着,定义了三个数据模型:ResetPassword、SecuritySetting和PersonalInformation,并在personalCenter.ts文件中存储。
在页面实现部分,使用Vue 3的Composition API和TypeScript,结合Element-Plus的el-dialogel-menu,实现了三个弹出框和一个下拉菜单。各表单包含相应的数据状态和验证规则,使用axios发送HTTP请求进行数据提交和处理。具体实现包括脚本部分和HTML部分,脚本部分定义了表单的可见性和数据状态,并实现了重置密码、安全设置和修改用户名的方法,通过axios进行HTTP请求处理。HTML部分实现了页面的主结构,包含一个头部菜单和三个弹出框,弹出框内为相应的表单。
最后,在路由设置部分,文章介绍了如何在路由脚本index.ts中增加路由守卫,确保个人中心功能只能在登录后访问,通过检查本地存储中的token实现权限验证。总结部分简单回顾了文章内容,详细介绍了个人中心功能的开发步骤和实现细节,包含数据模型定义、页面布局与交互、以及路由权限控制等内容。


原文地址:https://blog.csdn.net/gangzhucoll/article/details/145243561

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!