15---整合Echarts和完善头像上传

news2024/9/24 17:20:44

1、完善头像上传功能

  1. 上次写的头像上传功能,不能实现上传保存后立刻刷新右上角头像,这里做一个完善。
  2. 首先是在Manage.vue中(父),写刷新User的方法
//传一个user过去到header 
<Header :collapseBtnClass="collapseBtnClass" :collapse="collapse" :user="user"></Header>
<script>
//user数据
data() {
     return {
       collapseBtnClass:'el-icon-s-fold' ,
       isCollapse:false,
       sideWidth:200 ,
       logoTextShow:true,
       user:{}
     }
   },

created(){
    //从后台获取最新的User数据
    this.getUser()
   },

getUser(){
      let username = localStorage.getItem("user")?JSON.parse(localStorage.getItem("user")).username:""
      if(username){
        //从后台获取user数据
        this.request.get("/user/username/"+username).then(res=>{
          //重新赋值后台的最新User数据
          this.user=res.data
        })
      }
    
     }
  
  </script>

Header.vue里面

 props:{
        collapseBtnClass:String,
        collapse:Function,
        user: Object
    },

Person.vue里面

<script>
...


save(){
        this.request.post("/user",this.form).then(res=>{
          if(res.code==='200'){
            this.$message.success("保存成功!")
            //触发父级更新User的方法
            this.$emit("refreshUser")
            //更新浏览器存储的用户信息
            this.getUser().then(res=>{
              res.token=JSON.parse(localStorage.getItem("user")).token
              localStorage.setItem("user",JSON.stringify(res))
            })
          }else{
            this.$message.error("保存失败!")
        }
      })

    },
      
      
      </script>
  1. 这样就完美实现上传头像保存并能够刷新头像

完整代码:(改动过的页面的代码)

Manage.vue

<template>
  <el-container style="height: 100vh; border: 1px solid #eee">
    <!-- 侧边栏 -->
    <el-aside :width="sideWidth+'px'" style="background-color: rgb(238, 241, 246);height: 100%;" >
    <Aside :isCollapse="isCollapse" :logoTextShow="logoTextShow" ></Aside>
  </el-aside>

 <el-container>
  <!-- 菜单栏 -->
   <el-header style="border-bottom: 1px solid #ccc">
    <Header :collapseBtnClass="collapseBtnClass" :collapse="collapse" :user="user"></Header>
   </el-header>
   <el-main>
    <!-- 页面主体 -->
    <!-- 表示当前页面的子路由(在children中设置)会在router-view里面展示 -->
    <router-view @refreshUser="getUser" />
   </el-main>
 </el-container>
</el-container>
</template>

<script>
import Aside from '@/components/Aside.vue'
import Header from '@/components/Header.vue'

export default {
 name:'Manage',
 components: {Aside,Header},
 data() {
     return {
       collapseBtnClass:'el-icon-s-fold' ,
       isCollapse:false,
       sideWidth:200 ,
       logoTextShow:true,
       user:{}
     }
   },
   created(){
    //从后台获取最新的User数据
    this.getUser()
   },
   methods:{
     collapse(){ //点击收缩按钮触发
       this.isCollapse=!this.isCollapse
       if(this.isCollapse){  //收缩
         this.sideWidth=64
         this.collapseBtnClass='el-icon-s-unfold'
         this.logoTextShow=false
       }else{  //展开
         this.sideWidth = 200 
         this.collapseBtnClass='el-icon-s-fold'
         this.logoTextShow=true 
       }
     },
     getUser(){
      let username = localStorage.getItem("user")?JSON.parse(localStorage.getItem("user")).username:""
      if(username){
        //从后台获取user数据
        this.request.get("/user/username/"+username).then(res=>{
          //重新赋值后台的最新User数据
          this.user=res.data
        })
      }
    
     }
   }
}
</script>

Header.vue

<template>
    <div style="font-size: 12px;line-height:60px;display: flex;">
        <div style="flex:1;font-size:18px">
       <span :class="collapseBtnClass" style="cursor:pointer" @click="collapse"></span>
       <el-breadcrumb separator="/" style="display:inline-block;margin-left: 10px;">
        <el-breadcrumb-item :to="'/'">首页</el-breadcrumb-item>
        <el-breadcrumb-item>{{currentPathName}}</el-breadcrumb-item>
       </el-breadcrumb> 
     </div>
     <el-dropdown style="width:150px;cursor:pointer;text-align: right;" >
        <div style="display:inline-block">
            <img :src="user.avatarUrl" alt=""
                style="width:30px;border-radius: 50%;position:relative;top: 10px; right: 5px">
            <span>{{user.nickname}}</span><i class="el-icon-arrow-down" style="margin-left:5px"></i>

        </div>
        

       <el-dropdown-menu slot="dropdown" style="width:100px; text-align:center">
            <el-dropdown-item style="font-size:14px;padding:5px 0">
                    <router-link to="/password" style="text-decoration:none">修改密码</router-link>
            </el-dropdown-item>
            <el-dropdown-item style="font-size:14px;padding:5px 0">
                    <router-link to="/person" style="text-decoration:none">个人信息</router-link>
            </el-dropdown-item>
            <el-dropdown-item style="font-size:14px;padding:5px 0">
                    <span style="text-decoration: none" @click="logout"> 退出</span>
            </el-dropdown-item>
       </el-dropdown-menu>
     </el-dropdown>
    </div>
</template>

<script>
export default{
    name:"Header",
    props:{
        collapseBtnClass:String,
        collapse:Function,
        user: Object
    },
    computed:{
        currentPathName(){
            return this.$store.state.currentPathName;  //需要监听的数据
        }
    },
    data(){
        return{
           

        }
    },
    methods:{
        collapse(){
            this.$emit("asideCollapse")
        },
        logout(){
            this.$router.push("/login")
            localStorage.removeItem("user")
            this.$message.success("退出成功")
        }
    }

}

</script>

<style scoped>

</style>

Person.vue

<template>
   <el-card style="width:500px;padding:20px;">
    <el-form label-width="80px" size="small">
      <el-upload
        class="avatar-uploader"
        action="http://localhost:8081/file/upload"
        :show-file-list="false"
        :on-success="handleAvatarSuccess">
        <img v-if="form.avatarUrl" :src="form.avatarUrl" class="avatar">
        <i v-else class="el-icon-plus avatar-uploader-icon"></i>
      </el-upload>
          <el-form-item label="用户名" >
            <el-input v-model="form.username" autocomplete="off" disabled ></el-input>
          </el-form-item>
          <el-form-item label="昵称" >
            <el-input v-model="form.nickname" autocomplete="off"></el-input>
          </el-form-item>
          <el-form-item label="邮箱" >
            <el-input v-model="form.email" autocomplete="off"></el-input>
          </el-form-item>
          <el-form-item label="电话" >
            <el-input v-model="form.phone" autocomplete="off"></el-input>
          </el-form-item>
          <el-form-item label="地址" >
            <el-input type="textarea" v-model="form.address" autocomplete="off"></el-input>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="save">确 定</el-button>
          </el-form-item>
        </el-form>
   </el-card>
</template>

<script>
export default{
    name:"Person",
    data(){
        return{
            form:{},
            user:localStorage.getItem("user")?JSON.parse(localStorage.getItem("user")):{}
        }
    },
    created(){
       this.getUser().then(res=>{
        console.log(res)
        this.form=res
          
        })
    },
    methods:{
      async getUser(){
        return (await this.request.get("/user/username/"+this.user.username)).data
      },
      save(){
        this.request.post("/user",this.form).then(res=>{
          if(res.code==='200'){
            this.$message.success("保存成功!")
            //触发父级更新User的方法
            this.$emit("refreshUser")
            //更新浏览器存储的用户信息
            this.getUser().then(res=>{
              res.token=JSON.parse(localStorage.getItem("user")).token
              localStorage.setItem("user",JSON.stringify(res))
            })
          }else{
            this.$message.error("保存失败!")
        }
      })

    },
    handleAvatarSuccess(res){
      this.form.avatarUrl=res

    }


    }
}

</script>

<style>

  .avatar-uploader{
    text-align: center;
    padding-bottom: 10px;
  }
  .avatar-uploader .el-upload {
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
  }
  .avatar-uploader .el-upload:hover {
    border-color: #409EFF;
  }
  .avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 138px;
    height: 138px;
    line-height: 138px;
    text-align: center;
  }
  .avatar {
    width: 138px;
    height: 138px;
    display: block;
  }
</style>

示例:

在这里插入图片描述

2、整合使用Echarts

  1. Echarts就是在前端展示一些模型图,如折线图、圆柱图、饼图等等
  2. 安装

vue里面安装

npm i echarts -S

  1. 安装好后,打开官方文档,参照使用 官网: https://echarts.apache.org/examples/zh/index.html

在这里插入图片描述

  1. 我写的首页代码,直接粘贴如下

Home.vue

<template>
    <div>
        <el-row :gutter="10" style="margin-bottom: 60px">
            <el-col :span="6">
                <el-card style="color:#409EFF">
                    <div ><i class="el-icon-user-solid" />用户总数</div>
                    <div style="padding: 10px 0;text-align:center;font-weight:bold">
                        100
                    </div>
                </el-card>

            </el-col>
            <el-col :span="6">
                <el-card style="color:#F56C6C">
                    <div ><i class="el-icon-money" />销售总量</div>
                    <div style="padding: 10px 0;text-align:center;font-weight:bold">
                        ¥1000000
                    </div>
                </el-card>
            </el-col>
            <el-col :span="6">
                <el-card style="color:#E6A23C">
                    <div><i class="el-icon-bank-card" />收益总额</div>
                    <div style="padding: 10px 0;text-align:center;font-weight:bold">
                        ¥300000
                    </div>
                </el-card>
            </el-col>
            <el-col :span="6">
                <el-card style="color:#67C23A">
                    <div><i class="el-icon-s-shop" />门店总数</div>
                    <div style="padding: 10px 0;text-align:center;font-weight:bold">
                        20
                    </div>
                </el-card>
            </el-col>




        </el-row>



        <el-row>
            <el-col :span="12">
                <div id="main" style="width: 500px;height: 400px"></div>
            </el-col>
            <el-col :span="12">
                <div id="pie" style="width: 500px;height: 400px"></div>
            </el-col>
        </el-row>
        
      
    </div>
</template>

<script>
import * as echarts from 'echarts';
export default{
    name:"Home",
    data(){
        return{

        }
    },
    mounted(){  //页面元素渲染之后再触发
        var chartDom = document.getElementById('main');
        var myChart = echarts.init(chartDom);
        var option = {
            title:{
                text:'各季度用户注册人数统计',
                subtext:'趋势图',
                left:'center'
            },
        xAxis: {
            type: 'category',
            data: ["第一季度","第二季度","第三季度","第四季度"]
        },
        yAxis: {
            type: 'value'
        },
        series: [
            {
            data: [],
            type: 'line'
            },
            {
            data: [],
            type: 'bar'
            }
        ]
        };
        this.request.get("/echarts/members").then(res=>{
            //填空
            option.series[0].data=res.data
            option.series[1].data=res.data
            //数据准备完毕再set
            myChart.setOption(option);

            pieOption.series[0].data=[
                {name:"第一季度",value:res.data[0]},
                {name:"第二季度",value:res.data[1]},
                {name:"第三季度",value:res.data[2]},
                {name:"第四季度",value:res.data[3]},
            ]
            pieChart.setOption(pieOption);
            
        })
     

        //饼图

        var pieDom = document.getElementById('pie');
        var pieChart = echarts.init(pieDom);
        var pieOption = {
            title:{
                text:'各季度用户注册人数统计',
                subtext:'比例图',
                left:'center'
            },
        tooltip: {
            trigger: 'item'
        },
        legend: {
            orient: 'vertical',
            left: 'left'
        },
        series: [
            {
            type: 'pie',
            radius: '70%',
            label:{//饼图图形上的文本标签
                normal:{
                    show:true,
                    position:'inner',//标签位置
                    textStyle:{
                        fontWeight:300,
                        fontSize:16  //文件字体大小
                    },
                    formatter:'{d}%'
                }

            },
            data: [],
            emphasis: {
                itemStyle: {
                shadowBlur: 10,
                shadowOffsetX: 0,
                shadowColor: 'rgba(0, 0, 0, 0.5)'
                }
            }
            }
        ]
        };




    }
}

</script>

包括一个折线图+圆柱图,和一个饼图

模型图的数据都是从数据库里面查的,下面写请求的后端接口

  1. 写一个EchartsController
package com.xqh.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.Quarter;
import com.xqh.common.Result;
import com.xqh.entity.User;
import com.xqh.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/echarts")
public class EchartsController {
    @Autowired
    private UserService userService;

    //假数据
    @GetMapping("/example")
    public Result get(){
        Map<String, Object> map = new HashMap<>();
        map.put("x",CollUtil.newArrayList("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"));
        map.put("y",CollUtil.newArrayList(150, 230, 224, 218, 135, 147, 260));
        return Result.success(map);

    }

    //四个季度的注册的用户数据,从数据库中拿
    @GetMapping("/members")
    public Result members(){
        List<User> list = userService.list();
        int q1=0; //第一季度
        int q2=0;
        int q3=0;
        int q4=0;
        for (User user: list) {
            Date createTime = user.getCreateTime();
            Quarter quarter = DateUtil.quarterEnum(createTime);
            switch(quarter){
                case Q1:q1 +=1; break;
                case Q2:q2 +=1; break;
                case Q3:q3 +=1; break;
                case Q4:q4 +=1; break;
                default:break;
            }

        }

        return Result.success(CollUtil.newArrayList(q1,q2,q3,q4));
    }
}

  1. 我们需要补充一下数据库的数据,不然不好测试,因为写的是四个季度的,可以多补充一些不同创建时间的数据,我的是这样的:

在这里插入图片描述

  1. 去前端页面测试效果

在这里插入图片描述

  1. 可以根据自己的需求来搞首页。这里首页模型图里的数据都是真实从数据库中取的,可以看我的vue代码,一一对应上数据库中的数据。(首页最上面那四个框是写定的数据…那个需要根据真实业务来,我们现在还没有那么多业务)
  2. 可以正常展示,就完成了!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【信息论与编码 沈连丰】第三章:离散信源

【信息论与编码 沈连丰】第三章&#xff1a;离散信源第三章 离散信源3.1 离散信源的分类及其描述3.2 离散信源的熵3.3 信源的冗余度3.4 信源符号序列分组定理3.5 平稳离散信源及其性质第三章 离散信源 3.1 离散信源的分类及其描述 信源分类&#xff1a;本质上主要基于两方面来…

fastai教程学习笔记

这几天对着fastai教程读了下&#xff0c;大部分写得已经很不错。这里做点知识精炼的笔记。 安装fastai 推荐在conda环境内执行以下命令。它 pip install fastaifastai架构 fastai的编程架构如下图所示&#xff1a; fastai提供了高、中、低三层的API&#xff0c;用户可以根…

73、【哈希表】leetcode——15. 三数之和(C++版本)

题目描述 原题链接&#xff1a;15. 三数之和 解题思路 本题的难点在于去重&#xff0c;针对两种不同的方式&#xff1a;双指针和Hash采用不同的去重判定条件。 1、去重的目标 要明确&#xff0c;去重的是重复三元组&#xff0c;而不是三元组里重复的数。 2、去重初步思路 …

商业与数据生态议题解读,Doris Summit 2022 分论坛议程介绍|即刻报名

Doris Summit 2022 将于1 月 6 -7 日在线上正式举办&#xff0c;本次峰会共分2 天进行&#xff0c;首日上午为主论坛&#xff1a;核心技术解析&#xff0c;下午为商业与数据生态分论坛&#xff0c;7 日全天为行业用户最佳实践案例。大会汇聚了来自全球顶尖云厂商、一线互联网企…

CoMER论文翻译

文章目录Abstract1、Introduction2、Related Work2.1 HMER Methods2.2 Coverage Mechanism3、Methodology3.1、Background3.2、CNN Encoder3.3、Positional Encoding3.4、Attention Refinement Module3.5、Coverage4 Experiments论文链接&#xff1a;https://arxiv.org/abs/220…

数字图像处理 图像对比度增强算法概览

一、图像对比度增强 图像对比度增强又叫作图像对比度拉伸或者直接称为点运算。图像亮度和对比度调整的目的之一是在合适的亮度上提供最大的细节信息&#xff0c;细节纹理的沟纹越深&#xff0c;图像越清晰。在图像处理中&#xff0c;图像对比度增强是最基本的、原理比较简单却很…

【前端】Vuex模块化和持久化应用示例

概述 Vuex作为VUE状态管理组件&#xff0c;能够将项目公共数据进行统一管理。而且可以按照不同的业务功能将数据状态分模块管理。另外&#xff0c;对于网页刷新导致Vuex状态丢失的问题可以使用vuex-persistedstate插件配置将数据保存在localStorage或者sessionStorage中。 本…

「Python|场景案例」如何给图片添加水印

本文主要介绍如何使用python的PIL库给图片增加水印 文章目录背景说明工具准备处理步骤源代码处理效果展示背景说明 当我们想给一些图片添加水印的时候&#xff0c;尤其是图片数量较多的时候&#xff0c;就可以使用python进行自动化处理。包括但不限于在自媒体上发布自己的各种…

如何使用自助式商业智能 (BI) 避免组织中的数据孤岛

许多组织都存在数据问题。当许多员工远程工作&#xff08;或在混合环境中&#xff09;并在多个位置使用多个设备访问公司数据时&#xff0c;他们正在处理信息过载问题。这只会加剧数据孤岛的问题。 数据孤岛正是它听起来的样子&#xff1a;孤立在一个孤立的用户/环境中的数据&…

jdk版本和Class编译版本对应关系

JDK version和class file version(Class编译版本号)对应关系 JDK 17 61, JDK 16 60, JDK 15 59, JDK 14 58, JDK 13 57, JDK 12 56, JDK 11 55, JDK 10 54, JDK 9 53, JDK 8 52, JDK 7 51, JDK 6.0 50, JDK 5.0 …

数据结构-归并排序

一、概念及其介绍 归并排序&#xff08;Merge sort&#xff09;是建立在归并操作上的一种有效、稳定的排序算法&#xff0c;该算法是采用分治法(Divide and Conquer&#xff09;的一个非常典型的应用。将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff1b;即先使每…

三年“云改”,移动云这份答卷有多“硬”?

作者 | 曾响铃 文 | 响铃说 云计算是推动数字经济与实体经济深度融合的催化剂&#xff0c;是重点领域数字产业发展的助推器。近年来我国云计算产业发展提速&#xff0c;加快推动实体企业转型升级和创新发展。 2022年是移动云实施“云改”战略的第3年&#xff0c;也是移动云全…

【人工智能】基于五笔字型规范和人工神经网络的简中汉字识别【二】

环境搭建 一、NVIDIA驱动安装与更新二、Anaconda安装三、Pytorch安装四、验证CUDA和cudnn版本一、NVIDIA驱动安装与更新 显卡驱动就是用来驱动显卡的程序,它是硬件所对应的软件。 正常情况下,配有显卡的电脑都是安装有驱动程序的,但是有的时候驱动可能版本较低,所支持的 …

爬虫内容学习-工具类---Selenium

一、爬虫学习建议&#xff1a; 在编写python爬虫程序时&#xff0c;只需要做以下两件事&#xff1a; 发送GET请求&#xff0c;获取HTML [第一类] 解析HTML&#xff0c;获取数据 [第二类] 这两件事&#xff0c;python都有相应的库帮你去做&#xff0c;你只需要知道…

关乎你我,2022年都经历了哪些安全事件?|上云那些事

2022年&#xff0c;网络安全跟人们的工作生活关联愈发紧密。腾讯安全联合南方日报、南方&#xff0c;携手共建《上云那些事》栏目&#xff0c;为企业提供网络安全建设新思路&#xff0c;帮助大家及时发现身边的网络安全陷阱&#xff0c;提升安全意识和防范能力&#xff0c;减少…

论文阅读-虚假信息检测综述 - Fake News Detection on Social Media: A Data Mining Perspective

论文链接&#xff1a;https://arxiv.org/pdf/1708.01967.pdf 目录 摘要 1 引言 2. 假新闻定义 2.1 假新闻的定义 2.2 传统新闻媒体上的假新闻 2.3社交媒体上的假新闻 3.假新闻检测 3.1问题定义 3.2 特征提取 3.2.1 新闻内容特征 3.2.2 社会语境特征 3.3 模型构建 …

浅谈DNS域名解析的过程

用户在浏览器输入www.baidu.com时&#xff0c;DNS域名解析大致分为以下几个过程: 浏览器客户端检查自身有没有该域名的缓存&#xff1a; 如果浏览器有命中&#xff0c;直接返回该域名对应的IP地址&#xff0c;解析结束; (这个缓存可以设置TTL来控制有效时间&#xff0c;有点像A…

用C++求两个数的最大公约数和最小公倍数。(数论的基础思想)

目录原理最大公约数最小公倍数代码运行结果原理 最大公约数 有两个数字n和m。现在要求两个数字的最大公约数。 例如&#xff1a;n为18&#xff0c;m为4. 正常我们的思路求解最大公约数是暴力破解&#xff0c;遍历一遍公约数&#xff0c;取最大的那个&#xff0c;但是这样有一…

关闭Mac的Microsoft AutoUpdate弹框提示

macOS安装Microsoft Office for Mac之后&#xff0c;有时候会弹出Microsoft Auto Update微软应用自动更新工具。就像下面这样&#xff1a;&#xff08;我不知道您会不会烦&#xff0c;我是烦了&#xff09; 如果您也和我一样&#xff0c;不喜欢这样不经过允许就自动弹框的提示&…

【uiautomator2】 Android自动化测试框架

UiAutomator是Google提供的用来做安卓自动化测试的一个Java库. Uiautomator工作流程 1.在移动设备上安装atx-agent(守护进程),随后atx-agent启动uiautomator2服务(默认7912端口)进行监听 2.在PC上编写测试脚本并执行(相当于发送HTTP请求到移动设备的server端) 3.移动设备通过Wi…