vue3+antd——实现个人中心页面+同步更改头部用户信息——基础积累

之前写过一篇文章关于vue3+antd的框架模板,链接如下:http://t.csdn.cn/9dZMS

首先感谢大神提供的后台管理系统的模板,在此基础上改动要简单很多,主要是自己有很多内容不太敢随意改动。。。

直接看【个人中心】页面的效果图:
在这里插入图片描述
个人中心的内容要跟框架头部的信息保持同步,因此需要用到vuex,此框架中的vuex是使用的pinia

下面介绍详细代码:

1.个人中心的页面代码

1.1html代码

<template>
  <a-spin :spinning="loading">
    <a-card>
      <a-tabs v-model="activeKey">
        <a-tab-pane key="1" tab="修改信息">
          <a-form
            :model="form"
            :rules="rules"
            style="height: calc(100vh - 200px); width: 60%; overflow: auto"
            ref="ruleForm"
            :label-col="labelCol"
            :wrapper-col="wrapperCol"
            @finish="handleOk"
          >
            <a-form-item label="用户名" ref="userName" name="userName">
              <a-input v-model:value="form.userName" placeholder="请输入角色名称" />
            </a-form-item>
            <a-form-item label="工号">
              <a-input v-model:value="form.jobNo" />
            </a-form-item>
            <a-form-item label="名">
              <a-input v-model:value="form.name" />
            </a-form-item>
            <a-form-item label="姓">
              <a-input v-model:value="form.surname" />
            </a-form-item>
            <a-form-item label="性别">
              <a-radio-group v-model:value="form.sex">
                <a-radio :value="1"></a-radio>
                <a-radio :value="2"></a-radio>
              </a-radio-group>
            </a-form-item>
            <a-form-item label="头像">
              <uploadPic
                v-model:value="form.headPhoto"
                listType="picture-card"
                :limit="1"
                :showFile="showFile"
                ref="upload"
                @getFile="headPhotoInput"
              ></uploadPic>
            </a-form-item>
            <a-form-item label="邮箱地址" ref="email" name="email">
              <a-input v-model:value="form.email" />
            </a-form-item>
            <a-form-item label="手机号码">
              <a-input v-model:value="form.phoneNumber" />
            </a-form-item>
            <a-button type="primary" style="margin-left: 20%" html-type="submit">保存</a-button>
          </a-form>
        </a-tab-pane>
        <a-tab-pane key="2" tab="修改密码">
          <a-form
            :model="form2"
            :rules="rules2"
            style="height: calc(100vh - 200px); width: 60%; overflow: auto"
            ref="ruleForm2"
            :label-col="labelCol"
            :wrapper-col="wrapperCol"
            @finish="handleOk2"
          >
            <a-form-item label="当前密码" name="currentPassword">
              <a-input v-model:value="form2.currentPassword" type="password" />
            </a-form-item>
            <a-form-item label="新密码" name="newPassword">
              <a-input v-model:value="form2.newPassword" type="password" />
            </a-form-item>
            <a-form-item label="确认新密码" name="newPasswordConfirm">
              <a-input v-model:value="form2.newPasswordConfirm" type="password" />
            </a-form-item>
            <a-button type="primary" style="margin-left: 20%" html-type="submit">保存</a-button>
          </a-form>
        </a-tab-pane>
      </a-tabs>
    </a-card>
  </a-spin>
</template>

1.2 js代码

<script lang="ts">
  import { GetUserInfo } from '@/services/storehouse/common';
  import { useAccountStore } from '@/store';
  import { createUpdate, postChangePassword } from '@/services/identity/user';
  import uploadPic from '@/components/upload/UploadPic.vue';
  export default {
    components: { uploadPic },
    data() {
      let validatePass = (rule, value) => {
        if (value === '') {
          return Promise.reject('请输入密码');
        } else if (value.length < 6) {
          return Promise.reject('密码长度不能少于6位');
        } else {
          return Promise.resolve();
        }
      };
      let validatePass1 = (rule, value) => {
        if (value === '') {
          return Promise.reject('请输入密码');
        } else if (value.length < 6) {
          return Promise.reject('密码长度不能少于6位');
        } else {
          return Promise.resolve();
        }
      };
      let validatePass2 = (rule, value) => {
        if (value === '') {
          return Promise.reject('请输入密码');
        } else if (value.length < 6) {
          return Promise.reject('密码长度不能少于6位');
        } else {
          return Promise.resolve();
        }
      };
      return {
        showFile: [],
        loading: false,
        activeKey: '1',
        labelCol: { span: 6 },
        wrapperCol: { span: 18 },
        form: {
          userName: null,
          jobNo: null,
          name: null,
          surname: null,
          sex: null,
          headPhoto: null,
          email: null,
          phoneNumber: null,
        },
        form2: {
          currentPassword: null,
          newPassword: null,
          newPasswordConfirm: null,
        },
        rules2: {
          currentPassword: [
            { required: true, message: '请输入密码', trigger: 'blur' },
            { validator: validatePass, trigger: 'change' },
          ],
          newPassword: [
            { required: true, message: '请输入密码', trigger: 'blur' },
            { validator: validatePass1, trigger: 'change' },
          ],
          newPasswordConfirm: [
            { required: true, message: '请输入密码', trigger: 'blur' },
            { validator: validatePass2, trigger: 'change' },
          ],
        },
        rules: {
          userName: [{ required: true, message: '用户名必须填写', trigger: 'blur' }],
          email: [
            {
              type: 'email',
              required: true,
              message: '请填写正确的邮箱地址',
              trigger: 'blur',
            },
          ],
        },
      };
    },
    methods: {
      headPhotoInput(imgs) {
        this.form.headPhoto = imgs;
        this.$forceUpdate();
      },
      getUserInfo(flag) {
        this.loading = true;
        GetUserInfo()
          .then((res: any) => {
            if (res.code == 1) {
              this.form = {
                ...res.data,
                headPhoto: res.data?.extraProperties?.HeadPhoto,
                jobNo: res.data?.extraProperties?.JobNo,
              };
              if (flag) {
                const { setUser } = useAccountStore();
                setUser({ ...this.form });
              }
              this.form2 = {
                id: res.data.id,
              };
              if (this.form.headPhoto) {
                this.showFile = [
                  {
                    name: this.form.headPhoto,
                    url: this.form.headPhoto,
                    uid: this.form.headPhoto,
                  },
                ];
              } else {
                this.showFile = [];
              }
            }
          })
          .finally(() => {
            this.loading = false;
          });
      },
      handleOk2() {
        this.loading = true;
        postChangePassword(this.form2)
          .then((res) => {
            this.$message.success('操作成功');
            this.getUserInfo();
          })
          .finally(() => {
            this.loading = false;
          });
      },
      handleOk() {
        this.loading = true;
        let values = {
          ...this.form,
          extraProperties: {
            JobNo: this.form.jobNo,
            HeadPhoto: this.form.headPhoto,
          },
        };
        createUpdate(values)
          .then((res) => {
            this.$message.success('操作成功');
            this.getUserInfo(true);
          })
          .finally(() => {
            this.loading = false;
          });
      },
    },
    activated() {
      this.getUserInfo();
    },
  };
</script>

重点在于:修改个人信息后,需要触发account.js中的setUser方法,然后将内容同步到头部。

也就是再handleOk的函数调用成功后,要重新获取用户信息getUserInfo的方法,在此方法中要进行account.ts中的setUser方法。

1.3 account.ts中的setUser方法——重要代码!!!

export const useAccountStore = defineStore('account', {
  state: () => ({
    account: null,
  }),
  actions: {   
  	setUser(userInfo) {
      this.account = userInfo;
    },
  },
});

获取account.ts中的方法如下:

import { useAccountStore } from '@/store';

getUserInfo中的方法如下:

if (flag) {
  const { setUser } = useAccountStore();
  setUser({ ...this.form });
}

此时就实现了个人信息修改后与后台管理系统头部信息的同步。

2.上传头像的组件——uploadPic

2.1 html代码:

<template>
  <div>
    <a-upload
      class="upload-demo"
      :customRequest="uploadFile"
      @remove="handleRemove"
      :file-list="fileList"
      :multiple="multiple"
      :limit="limit"
      :list-type="listType"
    >
      <a-button v-if="showBtn" size="small" type="primary">点击上传</a-button>
      <plus-outlined v-if="!showBtn && fileList.length < limit" />
      <template v-slot:tip>
        <div class="cloud-upload"></div>
      </template>
    </a-upload>
    <a-modal title="图片预览" :visible="dialogVisible" :append-to-body="true">
      <img width="100%" :src="dialogImageUrl" alt="" />
    </a-modal>
  </div>
</template>

2.2 js代码

<script lang="ts">
  import { Upload } from '@/services/storehouse/common.js';
  export default {
    name: 'UploadPic',
    props: {
      multiple: {
        type: Boolean,
        default: false,
      },
      showFile: Array,
      limit: Number,
      showBtn: {
        type: Boolean,
        default: false,
      },
      listType: String,
    },
    data() {
      return {
        fileList: [],
        dialogVisible: false,
        dialogImageUrl: '',
      };
    },
    watch: {
      showFile: {
        handler(newVal) {
          this.fileList = newVal ? newVal : [];
        },
        deep: true,
        immediate: true,
      },
    },
    methods: {
      uploadFile(req) {
        let that = this;
        let formData = new FormData();
        formData.append('files', req.file);
        Upload({ module: 'IQC' }, formData).then((response: any) => {
          if (response.code == 0) return false;
          that.fileList.push({
            uid: req.file.uid,
            name: req.file.name,
            url: response.data,
          });
          let imgs = that.fileList.map((s) => s.url).join(',');
          this.$emit('getFile', imgs);
        });
      },
      beforeUpload() {},
      handlePictureCardPreview(file) {
        this.dialogImageUrl = file.url;
        this.dialogVisible = true;
      },
      handleRemove(file) {
        let index = this.fileList.findIndex((item) => {
          return item.uid === file.uid;
        });
        this.fileList.splice(index, 1);
        let imgs = this.fileList.map((s) => s.url).join(',');
        this.$emit('getFile', imgs);
      },
      beforeRemove(file, fileList) {
        return this.$confirm(`确定移除文件?`);
      },
      handleExceed(files, fileList) {
        this.$message.warning(
          `当前限制选择${this.limit}个文件,本次选择了 ${files.length} 个文件,共选择了 ${
            files.length + fileList.length
          } 个文件`
        );
      },
    },
  };
</script>

2.3 Upload接口——要根据实际情况来处理

//上传图片 
export async function Upload(params, data) {
  return request(`/api/app/bussiness-smt/upload-file?${qs.stringify(params)}`, METHOD.POST, data, {
    headers: {
      AppSecret: 'xxxxxxxxx',
    },
  });
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/64229.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[迁移学习]领域泛化

一、概念 相较于领域适应&#xff0c;领域泛化(Domain generalization)最显著的区别在于训练过程中不能访问测试集。 领域泛化的损失函数一般可以描述为以下形式&#xff1a; 该式分为三项&#xff1a;第一项表示各训练集权重的线性组合&#xff0c;其中π为使该项最小的系数&a…

【Docker系列】push镜像报错问题解决方案

1 问题描述 docker push 报这个错&#xff0c;unknown blob 详细报错内容&#xff1a; Use docker scan to run Snyk tests against images to find vulnerabilities and learn how to fix them The push refers to repository [192.******/*******/*************] 3b3341e9d03…

网络安全进阶学习第十三课——SQL注入Bypass姿势

文章目录 一、等号被过滤二、substr、mid等被过滤三、逗号被过滤四、and/or被过滤五、空格被过滤五、其他绕过方式 一、等号被过滤 1、like&#xff0c;rlike语句&#xff0c;其中rlike是正则2、大于号>&#xff0c;小于号<3、符号<>&#xff1a;<>为不等于…

【win10专业版远程控制】 自带远程桌面公司内网电脑

使用win10专业版自带远程桌面公司内网电脑 文章目录 使用win10专业版自带远程桌面公司内网电脑 在现代社会中&#xff0c;各类电子硬件已经遍布我们身边&#xff0c;除了应用在个人娱乐场景的消费类电子产品外&#xff0c;各项工作也离不开电脑的帮助&#xff0c;特别是涉及到数…

【C++】多态(多态的构成条件,虚函数重写,override,final,覆盖隐藏对比)

文章目录 前言一、多态的定义及实现1.多态的构成条件&#xff1a; 二、虚函数1.虚函数的重写2.虚函数重写的例外&#xff08;协变&#xff09;3.析构函数的虚函数&#xff08;基类与派生类析构函数名字不同&#xff09;1.不加virtual的一般情况&#xff1a;2.不加virtual会出现…

浅谈新电改背景下电网企业综合能源服务商业模式研究及发展方向

安科瑞 华楠 摘要: 新电改方案实施后&#xff0c;由于输配电价的改革和售电侧的放开&#xff0c;电网企业的盈利模式也随之发生了变化。这就要求电网企业转变服务理念与经营方式&#xff0c;来寻求竞争优势。基于“魏朱六要素商业模式”模型&#xff0c;对电网企业综合能源服务…

heima头条项目学习--Day1: 环境搭建、SpringCloud微服务(注册发现、网关)

Nacos注册发现、网关 a. 项目介绍b. app登录1) 需求分析2) 表结构分析3) 手动加密&#xff08;md5随机字符串&#xff09;4) 用户端微服务搭建5) 功能实现6) app网关7) 网关校验jwt8) 前端集成, 配置nginx a. 项目介绍 业务说明 技术栈说明 [外链图片转存失败,源站可能有防盗…

目标检测与跟踪 (3)- TensorRTYOLO V8性能优化与部署测试

系列文章目录 目标检测与跟踪 &#xff08;1&#xff09;- 机器人视觉与YOLO V8_Techblog of HaoWANG的博客-CSDN博客 目标检测与跟踪 &#xff08;2&#xff09;- YOLO V8配置与测试_Techblog of HaoWANG的博客-CSDN博客 目录 系列文章目录 前言 YOLO v8 TensorRT 一、…

新手教程:5步掌握系统流程图绘制方法!

流程图通常用于管理、分析、设计许多不同领域的流程&#xff0c;是一个很有用的工具&#xff0c;能够帮助大家更轻松、更有效地解决问题。系统流程图是流程图的常见变体之一。 系统流程图是展示数据流以及决策如何影响周围事件的图表类型。 与其他类型的流程图一样&#xff0c;…

Python(Web时代)——jinja2模板

简介 Jinja2是Flask框架默认支持的模板引擎&#xff0c;是python的web项目中被广泛应用的一种模板引擎&#xff0c;jinja2的作者与Flask是同一个人。 jinja2具有以下特点&#xff1a; 非常灵活&#xff0c;提供了控制结构、表达式与继承等 性能好 可读性强 渲染一个模板&a…

uni——tab切换

案例展示 案例代码 <view class"tablist"><block v-for"(item,index) in tabList" :key"index"><view class"tabItem" :class"current item.id?active:" click"changeTab(item)">{{item.nam…

laravel语言包问题

1、更新vendor composer require "overtrue/laravel-lang:3.0" 2、修正配置文件 config/app.php 3、 php artisan config:clear 更新缓存 4、设定新的语言包 在这个resources\lang目录下加即可

LeetCode[210]课程表II

难度&#xff1a;Medium 题目&#xff1a; 现在你总共有 numCourses 门课需要选&#xff0c;记为 0 到 numCourses - 1。给你一个数组 prerequisites &#xff0c;其中 prerequisites[i] [ai, bi] &#xff0c;表示在选修课程 ai 前 必须 先选修 bi 。 例如&#xff0c;想要学…

RunnerGo配置场景时接口模式该怎么选

在进行性能测试时&#xff0c;测试场景的正确配置非常关键。首先&#xff0c;需要根据业务场景和需求&#xff0c;设计出合理的测试场景&#xff0c;再利用相应的工具进行配置&#xff0c;实现自动化的性能测试。 在JMeter中&#xff0c;用户需要自己组织测试场景&#xff0c;…

DDS中间件设计

OpenDDS、FastDDS数据分发服务中间件设计 软件架构 应用层DDS层RTPS层传输层 软件层次 FastDDS整体架构如下&#xff0c;这里可以看到DDS和RTPS的关系。另外缺少一部分IDL&#xff08;统一描述语言&#xff09;&#xff0c;其应该是Pub、Sub的反序列化、序列化工具。 在RT…

PDF Expert 3.3 for mac

PDF Expert是一款专业的PDF编辑和阅读工具。它可以帮助用户在Mac、iPad和iPhone等设备上查看、注释、编辑、填写和签署PDF文档。 以下是PDF Expert的特点&#xff1a; PDF编辑&#xff1a;PDF Expert提供了丰富的PDF编辑功能&#xff0c;包括添加、删除、移动、旋转、缩放、裁…

用i18n 实现vue2+element UI的国际化多语言切换详细步骤及代码

一、i18n的安装 这个地方要注意自己的vue版本和i1n8的匹配程度&#xff0c;如果是vue2点几&#xff0c;记得安装i18n的8版本&#xff0c;不然会自动安装的最新版本&#xff0c;后面会报错哦&#xff0c;查询了下资料&#xff0c;好像最新版本是适配的vue3。 npm install vue-…

量子力学的挑战和未来:未解决的问题和可能的发展方向

亲爱的读者&#xff0c; 欢迎回到我们的量子力学系列文章。在前面的几篇文章中&#xff0c;我们已经深入探讨了量子力学的起源、基本概念、实验验证以及应用领域&#xff0c;包括量子计算、量子通信和量子感应。今天&#xff0c;我们将探讨量子力学所面临的挑战以及未来可能的…

STM32 CubeMX USB_MSC(存储设备U盘)

STM32 CubeMX STM32 CubeMX USB_MSC(存储设备U盘&#xff09; STM32 CubeMX前言 《使用内部Flash》——U盘一、STM32 CubeMX 设置USB时钟设置USB使能UBS功能选择FATFS功能 二、代码部分修改代码"usbd_storage_if.c"修改代码"user_diskio.c"main函数初始化插…

9.1网络通信基础

一.基础概念: 1)IP地址:描述网络上的一个设备所在的位置. 2)端口号(port):区分一个主机上不同的进程,和pid一样的作用,但两者不同. 3)协议:网络通信传输数据的含义,协议表示一种约定,这种约定可以是任意的.协议分层之后,上层不需要知道下层协议的细节,可以灵活地调整,替换某…