Vue+Element+Echarts+Springboot+微信小程序开发(肿瘤医学项目)

 

一、软件结构

                 

 

 

MedicalProject

1.小程序账号 + 微信开发者工具 + 前端代码 + 后端数据 = 微信小程序
2.腾讯云服务器 + Tomcat + 后端接口定义 = 可访问的后端服务接口
3.Idea + Java + SpringBoot = PC后端接口定义
4.mysql+mongodb+neo4j = PC数据库

小程序端开发
小程序端开发其实就是在腾讯的开发工具里,使用js语言,遵循腾讯小程序的开发文档规范进行代码编写。开发过程中可以编译、预览、真机调试等,可以使用各种插件,可以调用一些公共的api或者自己定义的后端接口,也可以使用腾讯提供的云函数。

PC端开发
PC端主要是提供给小程序数据接口,让小程序各个页面都能有数据展示,这里提供的是http接口,返回的Json格式的字符串。使用的语言是Java,使用的框架是SpringBoot,程序将最终部署在web服务器Tomcat中,Tomcat就自动的将通过url过来的请求分发到程序代码的处理逻辑中,处理完请求拿到相应的数据则以Json字符串的格式返回。

环境:
开发语言:Java 8
开发集成环境:IntelliJ IDEA, VScode, 微信开发者工具 
框架:Springboot, Vue.js,Element UI, ECharts
数据库:Mysql,MongoDB, Neo4j 构建工具:Maven 代码管理:华为云

分支管理: Master: 主分支,存储软件发布版本。 develop: 存储软件稳定版本;各自分支代码开发完毕后合并到develop分支。

  

 

CDN服务

   CDN的全称是Content Delivery Network,即内容分发网络。CDN是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN的关键技术主要有内容存储和分发技术。

   CDN通过广泛的网络节点分布,提供快速、稳定、安全、可编程的全球内容分发加速服务,支持将网站、音视频、下载等内容分发至接近用户的节点,使用户可就近取得所需内容,提高用户访问的响应速度和成功率。

 
 

作者:阿里巴巴淘系技术
链接:https://www.zhihu.com/question/36514327/answer/1604554133
来源:知乎

CDN工作原理


内容分发网络(Content Delivery Network,简称CDN)是建立并覆盖在承载网之上,由分布在不同区域的边缘节点服务器群组成的分布式网络。

CDN应用广泛,支持多种行业、多种场景内容加速,例如:图片小文件、大文件下载、视音频点播、直播流媒体、全站加速、安全加速。



借用阿里云官网的例子,来简单介绍CDN的工作原理。


假设通过CDN加速的域名为www.a.com,接入CDN网络,开始使用加速服务后,当终端用户(北京)发起HTTP请求时,处理流程如下:

  1. 当终端用户(北京)向www.a.com下的指定资源发起请求时,首先向LDNS(本地DNS)发起域名解析请求。
  2. LDNS检查缓存中是否有www.a.com的IP地址记录。如果有,则直接返回给终端用户;如果没有,则向授权DNS查询。
  3. 当授权DNS解析www.a.com时,返回域名CNAME www.a.tbcdn.com对应IP地址。
  4. 域名解析请求发送至阿里云DNS调度系统,并为请求分配最佳节点IP地址。
  5. LDNS获取DNS返回的解析IP地址。
  6. 用户获取解析IP地址。
  7. 用户向获取的IP地址发起对该资源的访问请求。
  • 如果该IP地址对应的节点已缓存该资源,则会将数据直接返回给用户,例如,图中步骤7和8,请求结束。
  • 如果该IP地址对应的节点未缓存该资源,则节点向源站发起对该资源的请求。获取资源后,结合用户自定义配置的缓存策略,将资源缓存至节点,例如,图中的北京节点,并返回给用户,请求结束。

 


从这个例子可以了解到:


(1)CDN的加速资源是跟域名绑定的。
(2)通过域名访问资源,首先是通过DNS分查找离用户最近的CDN节点(边缘服务器)的IP
(3)通过IP访问实际资源时,如果CDN上并没有缓存资源,则会到源站请求资源,并缓存到CDN节点上,这样,用户下一次访问时,该CDN节点就会有对应资源的缓存了。

 

 

 

链接:https://www.cnblogs.com/yanggb/p/10822420.html
来源:博客园

npm与cnpm的区别

 

NPM(Node Package Manager,节点包管理器)是NodeJS的包管理器,用于节点插件的管理(包括安装,卸载和管理依赖等)。NPM是随同新版的NodeJS一起安装的包管理工具,所以我们需要安装NodeJS。

NPM的常见使用场景

1.允许用户从NPM服务器上下载别人编写的第三方包到本地使用。

2.允许用户从NPM服务器上下载并安装别人编写的命令行程序到本地使用。

3.允许用户将自己编写的包或命令行程序上传到NPM服务器上供别人使用。

 

为什么要用CNPM

NMP安装插件是从NPM官网下载对应的插件包,该网站的服务器在国外,经常会出现下载缓慢或出现异常,这时便需要找到另外的方法提供稳定的下载,这个方法就是CNPM。阿里巴巴的淘宝团队把NMP官网的插件都同步到了在中国的服务器,提供给我们从这个服务器上稳定下载资源。

CNMP同样是NMP的一个插件,要安装的话需要在CMD命令行控制台执行以下命令:

npm install cnpm -g --registry=https://registry.npm.taobao.org

安装完成后可以使用cnpm -v命令查看版本号,要使用cnmp命令的话最好在安装后重新打开CMD命令行控制台。

cnpm的用法和npm的用法一致,只是在执行命令的时候将npm改为cnpm。

 

 

前端工程化

 

Vue-cli

Vue脚手架指的是Vue-cli,它是一个专门为单页面应用快速搭建繁杂程序的脚手架,它可以轻松地创建新的应用程序而且可用于自动生成Vue和Webpack的项目模板。

利用Vue-cli脚手架构建Vue项目需要先安装Node.js和NPM环境。

 

 

Node.js

Node. js是一个基于Chrome V8引擎的JavaScript运行环境。N ode是一个让JavaScript运行在服务端的开发平台,它让JavaScript成为与PHP、 Python、Perl、Ruby等服务端语言平起平坐的脚本语言。

Node是一个基于Chrome JavaScript 运行时建立的平台,用于方便地搭建响应速度快、易于扩展的网络应用。Node使用事件驱动,采用非阻塞1I/O模型而得以轻量和高效,非常适合在分布式设备上运行数据密集型的实时应用。

 

 

NPM

NPM代表npmjs.org这个网站, 这个站点存储了很多Node.js的第三方功能包,NPM的全称是Node Package Manager,它是一个Node. js包管理和分发工具,已经成为为非官方的发布Node模块(包)的标准。它可以让JavaScript开发者能够更加轻松地共享代码和共用代码片段,并且通过NPM管理需要分享的代码也很方便、快捷和简单。

 

 NPM是随同Node.js一起安装的包管理工具,能解决Node.js代码部署上的很多问题,常见的使用场景有以下几种:

(1)允许用户从NPM服务器下载别人编写的第三方包到本地使用。

(2)允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。

(3)允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。

 

 

基本使用

搭建完整的Vue_cli脚手架构建的项目

Vue-cli是用Node编写的命令行工具,需要进行全局安装。命令行终端输入:

npm install -g vue - cli

  

使用Vue-cli快速生成基于Webpack模板构建的项目。

配置完成后 

进入项目目录,使用npm install安装依赖

 

依赖安装后,项目的目录结构

 

src目录

 

 

index.html文件

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>vue_medicalproject</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

 

main.js文件// The Vue build version to load with the `import` command

// (runtime-only or standalone) has been set in webpack.base.conf with an alias.

import Vue from 'vue' import App from './App' import router from './router' Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ el: '#app', router, components: { App }, template: '
<App/>' })

 

App.vue文件

<!--页面模板-->
<
template> <div id="app"> <img src="./assets/logo.png"> <router-view/> </div> </template>
<!--页面脚本--> <script> export default { name: 'App' } </script>
<!--页面样式--> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>

 

 

命令行npm run dev 启动项目

 

浏览器输入http://localhost:8080

 

 

 

 

 

 

项目打包与发布

 

控制台npm run build对Vue项目进行打包

 

生成dist打包文件

 

 

 

 

 

Element-ui

Vue的核心思想是组件和数据驱动,但是每一个组件都需要自己编写模板、样式、添加事件、数据等,这些工作是比较烦琐的,所以饿了公推出了基于Vue2.0的组件库,它的名称为Element-ui,此组件库提供了丰富的PC端组件。

 

ElementUI官网为http://element-cn. eleme. io/ # /zh-CN

 

Vue项目中引入Element-ui组件库有两种方法:

1.CDN

在线方式直接在页面上引入Element-ui的JS和CSS文件即可开始使用

 

<!--引入样式-->
<link rel = "stylesheet"  href = "https://unpkg.com/element-ui/lib/theme-chalk/index.css">

<!--引入组件库-->
<script src = "https://unpkg.com/element-ui/lib/index.js"></script>

 

 

 

2.NPM安装

使用NPM方式安装,可以更好地和webpack打包工具配合使用

 

npm install element - ui - S

 NMP安装插件是从NPM官网下载对应的插件包,该网站的服务器在国外,经常会出现下载缓慢或出现异常,这时便需要找到另外的方法提供稳定的下载,这个方法就是CNPM。

 cnpm i  element-ui  -S

 

 

 

 

Vue项目中集成Element-ui

 

 

 

在main.js中完整引入Element-ui组件库

 

 

 

 main.js中引入Element-ui组件库

 

 

 

Element-ui官网复制代码到First.vue文件

 

 

 

 

 

参考自:https://blog.csdn.net/weixin_43236610/article/details/82866518

vue项目新建页面

    • 示例项目启动成功后,若新增页面,需新增.vue文件并配置路由
      • 第一步:新增.vue文件
        笔者在components目录下新增First.vue文件,内容如下

 

 

   第二步:配置路由

 

Vue提供了一个属性mode:"history",可以去掉地址栏中的#,代码如下:

 

 

插入url地址与组件地址映射语句

{
path: '/first',
name: 'First',
component: First
}

 

 

 

第三步:打开浏览器,输入http://localhost:8080/first

 

 

3. 分析调用关系

  • 上一节页面新建时,界面中有个意外的图标,引发思考

 

  • 既然First.vue代码中只编写了 "welcome"相关代码,那么图标从何而来呢?
  • 解决这个问题,需要分析vue文件中的调用关系

 

 

 

  • 使用到vue项目的文件包括一个.html,两个.js,两个.vue文件,关系如上图所示
  • 由图可见,文件关键处在于main.js,管理着所有需要的资源,其中new Vue的参数,解释如下:
   el:官方解释为实例提供挂载的元素。此处为index.html中的<div id="app"><div>
  router:为router:router,的简写,指向引入文件中的routes:[]   components:注册哪些组件,需在顶部引入文件。   template:替换挂载元素的模板组件,而挂载元素的内容都将被忽略。即用template替换index.html里面的
<div id="app"></div>

 

此时,可知main.js文件调用关系分为三步,如图中序号

  1.确定将被挂载(替换)的元素,此处为index.html中的<div id="app"><div>。
  2.注册组件(此处只有组件App),选择其中用于替换挂载元素(第一步中的元素)的模板组件(<App/>),即用App.vue替换index.html中的<div id="app"><div>。
  3.注入路由器router:
    1.模板组件(App.vue)中有<router-view/>,将在其中渲染路由匹配到的组件
    2.注入(import)路由时指定的是router文件夹,即文件夹下所有routes
    3.router文件夹下此时只有index.js文件,其中routes:[]规定了文件地址及其url地址映射
    4.根据文件地址,载入组件(First.vue),组件被渲染在<router-view/>中,显示在index.html中

 

 

然而追本溯源,调用关系中仍有两个问题:


index.html为何默认显示?
其实执行npm run dev时,控制台将执行如下语句:

webpack-dev-server --inline --progress --config build/webpack.dev.conf.js

由此可见,运行时启动文件webpack.dev.conf.js,而文件中包含如下语句,规定了起始页面:

 

main.js为何默认加载?

因为使用的脚手架工具vue-cli里用webpack来打包项目文件,webpack.dev.conf文件里还定义了webpack基础配置文件webpack.base.conf.js,定义语句如下:

const baseWebpackConfig = require('./webpack.base.conf')

而文件webpack.base.conf.js中,包含如下语句,指定了入口:

文件调用关系完毕

 

 

 

Echarts可视化库

 

ECharts 是一个使用 JavaScript 实现的开源可视化库,涵盖各行业图表,满足各种需求。

 

ECharts 遵循 Apache-2.0 开源协议,免费商用。

 

ECharts 兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Safari等)及兼容多种设备,可随时随地任性展示。

 

 

 

NPM 方法

由于 npm 安装速度慢,本教程使用了淘宝的镜像及其命令 cnpm,安装使用介绍参照:使用淘宝 NPM 镜像

npm 版本需要大于 3.0,如果低于此版本需要升级它:

# 查看版本
$ npm -v
2.3.0

#升级 npm
cnpm install npm -g


# 升级或安装 cnpm
npm install cnpm -g

 

通过 cnpm 获取 echarts:

# 最新稳定版
$ cnpm install echarts --save

安装完成后 ECharts 和 zrender 会放在 node_modules 目录下,我们可以直接在项目代码中使用 require('echarts') 来使用。

 

 

 

  • 引用echarts(两种方式,这里使用的是全局引用)
import echarts from 'echarts'

 

  • 注册echarts组件
Vue.prototype.$echarts = echarts

 

 

 

 

 

 

引入echars5.0报错“export ‘default‘ (imported as ‘echarts‘) was not found in ‘echarts‘

原文链接:https://blog.csdn.net/weixin_43972437/article/details/111475106

问题

引入 echars 5.0 遇到报错 "export ‘default’ (imported as ‘echarts’) was not found in ‘echarts’

 

解决

引入方式改为

import * as echarts from 'echarts';
// 或
const echarts = require('echarts');

 

 

 

成功解决Component template should contain exactly one root element

原文链接:https://blog.csdn.net/qq_26230421/article/details/96426823

前言
报错信息:

 

VUE小白会碰到这样的错误,刚上手,对vue还不太熟悉,所以对里面的构造方式不太清楚。

对于这个bug,我们很容易翻译为:

组件模板应该只包含一个根元素

查看代码


如图所示,template下面包含了两个<div>根节点,这是报错的根本原因。

 

解决
在最外层写一个div,把所有的前端代码放进去就好了:



 

 

 

WebStorm开发Vue自定义标签提示是未知标签解决办法

1.file -> settings -> editor -> inspections -> html -> unkown html tag, unkown html tag attribute

 

2.打开 File -> Settings -> File Types 在右侧的窗口中找到Vue.js Template 并选中,在下面的窗口中添加 *.vue 即可解决问题。 

 

 

 

实现简单的数据可视化页面

 

 

First.vue

<template>

    <el-container style="height: 550px; border: 1px solid #eee">


      <el-header style="text-align: right; font-size: 12px">
        <el-dropdown>
          <i class="el-icon-setting" style="margin-right: 15px"></i>
          <el-dropdown-menu slot="dropdown">
            <el-dropdown-item>查看</el-dropdown-item>
            <el-dropdown-item>新增</el-dropdown-item>
            <el-dropdown-item>删除</el-dropdown-item>
          </el-dropdown-menu>
        </el-dropdown>
        <span>@MedicalProject</span>
      </el-header>



   <el-container>
      <el-aside width="150px" style="background-color: rgb(238, 241, 246)">
        <el-menu :default-openeds="[]">
          <el-submenu index="1">
            <template slot="title"><i class="el-icon-message"></i>导航一</template>
            <el-menu-item-group>
              <template slot="title">分组一</template>
              <el-menu-item index="1-1">选项1</el-menu-item>
              <el-menu-item index="1-2">选项2</el-menu-item>
            </el-menu-item-group>
            <el-menu-item-group title="分组2">
              <el-menu-item index="1-3">选项3</el-menu-item>
            </el-menu-item-group>
            <el-submenu index="1-4">
              <template slot="title">选项4</template>
              <el-menu-item index="1-4-1">选项4-1</el-menu-item>
            </el-submenu>
          </el-submenu>
          <el-submenu index="2">
            <template slot="title"><i class="el-icon-menu"></i>导航二</template>
            <el-menu-item-group>
              <template slot="title">分组一</template>
              <el-menu-item index="2-1">选项1</el-menu-item>
              <el-menu-item index="2-2">选项2</el-menu-item>
            </el-menu-item-group>
            <el-menu-item-group title="分组2">
              <el-menu-item index="2-3">选项3</el-menu-item>
            </el-menu-item-group>
            <el-submenu index="2-4">
              <template slot="title">选项4</template>
              <el-menu-item index="2-4-1">选项4-1</el-menu-item>
            </el-submenu>
          </el-submenu>
          <el-submenu index="3">
            <template slot="title"><i class="el-icon-setting"></i>导航三</template>
            <el-menu-item-group>
              <template slot="title">分组一</template>
              <el-menu-item index="3-1">选项1</el-menu-item>
              <el-menu-item index="3-2">选项2</el-menu-item>
            </el-menu-item-group>
            <el-menu-item-group title="分组2">
              <el-menu-item index="3-3">选项3</el-menu-item>
            </el-menu-item-group>
            <el-submenu index="3-4">
              <template slot="title">选项4</template>
              <el-menu-item index="3-4-1">选项4-1</el-menu-item>
            </el-submenu>
          </el-submenu>
        </el-menu>
      </el-aside>


      <el-main>

       <!--         为ECharts准备一个具备大小(宽高)的Dom-->

      <div>
          <div style="display: flex; margin-bottom:  10px"  >

             <div style="background-color: #0F1033; width: 580px;height: 300px; display: flex;">
                 <div id="bar1" style="width: 280px;height:300px; background-color:#1F2056; align-content: center"></div>
                    &nbsp;&nbsp;&nbsp;
                 <div id="bar2" style="width: 280px;height:300px; background-color:#1F2056; align-content: center"></div>
             </div>

                  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            <div style="background-color: #0F1033; width: 580px;height: 300px; display: flex;">
                <div id="pie1" style="width: 580px;height:300px; background-color:#1F2056;display: flex;" ></div>
            </div>

         </div>


          <div style="display: flex; margin-top: 10px"  >
              <div style="background-color: #0F1033; width: 580px;height: 300px; display: flex;">
                <div id="set1" style="width: 280px;height:300px; background-color:#1F2056; align-content: center"></div>
                   &nbsp;&nbsp;&nbsp;
                <div id="set2" style="width: 280px;height:300px; background-color:#1F2056; align-content: center"></div>
              </div>

          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
          <div style="background-color: #0F1033; width: 580px;height: 300px; display: flex;">
              <div id="set3" style="width: 580px;height:300px; background-color:#1F2056;display: flex;" ></div>
          </div>

        </div>

      </div>

      </el-main>

   </el-container>


      <el-footer>Footer</el-footer>

</el-container>

</template>


<style scoped>
.el-header, .el-footer {
  background-color: #B3C0D1;
  color: #333;
  text-align: center;
  line-height: 60px;
}
.el-main {
  background-color: #E9EEF3;
  color: #333;
  height: 600px;
  width: 1000px;
  text-align: center;
  line-height: 110px;
}
.el-aside {
  color: #333;
}


</style>



<script>

let echarts = require('echarts/lib/echarts');

export default {
  name: 'First.vue',
  data() {
    const item = {
      // date: '2016-05-02',
      // name: '@',
      // address: '上海市普陀区金沙江路 1518 弄'
    };
    return {
      // tableData: Array(10).fill(item)
    }
  },
  mounted() {
    this.drawbar1();
    this.drawbar2();
    this.drawpie1();
    this.drawdataset1();
    this.drawdataset2();
    this.drawdataset3();
  },
  methods: {

    drawbar1() {
      // 基于准备好的dom,初始化echarts实例
      let myChart1 = echarts.init(document.getElementById('bar1'));

      // 指定图表的配置项和数据
      let option = {
        title: {
          text: '第一个 ECharts 实例',
          textStyle: {
            fontSize: 15,
            color: "#FBFBFD"
          }
        },
        tooltip: {},
        legend: {
          data: [ {
            name: '销量',
            textStyle:{
              color: "rgba(252, 252, 252, 0.99)"
              }
            }
          ],
          bottom: "83%",
          itemWidth: 20,
          itemHeight: 20,
          itemStyle:{
          }
        },
        xAxis: {
          data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"]
        },
        yAxis: {},
        series: [{
          name: '销量',
          type: 'bar',
          data: [5, 20, 36, 10, 10, 20]
        }]
      };

      myChart1.setOption(option);


      window.addEventListener("resize",function(){
        myChart1.resize();   //myChart2指自己定义的echartsDom对象
      })

    },
    drawbar2() {
      // 基于准备好的dom,初始化echarts实例
      let myChart2 = echarts.init(document.getElementById('bar2'));

      // 指定图表的配置项和数据
      let option = {
        title: {
          text: '第一个 ECharts 实例',
          textStyle: {
            fontSize: 15,
            color: "#FBFBFD"
          }
        },
        tooltip: {},
        legend: {
          data: [ {
            name: '销量',
            textStyle:{
              color: "rgba(252, 252, 252, 0.99)"
            }
          }
          ],
          bottom: "83%",
          itemWidth: 20,
          itemHeight: 20,
        },
        xAxis: {
          data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"]
        },
        yAxis: {},
        series: [{
          name: '销量',
          type: 'bar',
          data: [5, 20, 36, 10, 10, 20]
        }]
      };

      myChart2.setOption(option);

      window.addEventListener("resize",function(){
        myChart2.resize();   //myChart2指自己定义的echartsDom对象
      })

    },

    drawpie1() {

      let myChart3 = echarts.init(document.getElementById('pie1'));
      let  option = {
        title: {
          text: '南丁格尔玫瑰图',
          subtext: '纯属虚构',
          left: 'center'
        },
        tooltip: {
          trigger: 'item',
          formatter: '{a} <br/>{b} : {c} ({d}%)'
        },
        legend: {
          left: 'center',
          top: 'bottom',
          data: ['rose1', 'rose2', 'rose3', 'rose4', 'rose5', 'rose6', 'rose7', 'rose8']
        },
        toolbox: {
          show: true,
          feature: {
            mark: {show: true},
            dataView: {show: true, readOnly: false},
            restore: {show: true},
            saveAsImage: {show: true}
          }
        },
        series: [
          {
            name: '面积模式',
            type: 'pie',
            radius: [20, 90],
            center: ['25%', '50%'],
            roseType: 'area',
            Legend: {
              width: "10%",
              height: "10%",
            },
            itemStyle: {
              borderRadius: 5
            },
            data: [
              {value: 30, name: 'rose 1'},
              {value: 28, name: 'rose 2'},
              {value: 26, name: 'rose 3'},
              {value: 24, name: 'rose 4'},
              {value: 22, name: 'rose 5'},
              {value: 20, name: 'rose 6'},
              {value: 18, name: 'rose 7'},
              {value: 16, name: 'rose 8'}
            ]
          }
        ]
      };
      option && myChart3.setOption(option);

      window.addEventListener("resize",function(){
        myChart3.resize();   //myChart2指自己定义的echartsDom对象
      })

    },
    drawdataset1(){

      let myChart4 = echarts.init(document.getElementById('set1'));
      let  option = {
        dataset: {
          source: [
            ['score', 'amount', 'product'],
            [89.3, 58212, 'Matcha Latte'],
            [57.1, 78254, 'Milk Tea'],
            [74.4, 41032, 'Cheese Cocoa'],
            [50.1, 12755, 'Cheese Brownie'],
            [89.7, 20145, 'Matcha Cocoa'],
            [68.1, 79146, 'Tea'],
            [19.6, 91852, 'Orange Juice'],
            [10.6, 101852, 'Lemon Juice'],
            [32.7, 20112, 'Walnut Brownie']
          ]
        },
        grid: {containLabel: true},
        xAxis: {name: 'amount'},
        yAxis: {type: 'category'},
        visualMap: {
          orient: 'horizontal',
          left: 'center',
          min: 10,
          max: 100,
          text: ['High Score', 'Low Score'],
          // Map the score column to color
          dimension: 0,
          inRange: {
            color: ['#65B581', '#FFCE34', '#FD665F']
          }
        },
        series: [
          {
            type: 'bar',
            encode: {
              // Map the "amount" column to X axis.
              x: 'amount',
              // Map the "product" column to Y axis
              y: 'product'
            }
          }
        ]
      };

      option && myChart4.setOption(option);

      window.addEventListener("resize",function(){
        myChart4.resize();   //myChart2指自己定义的echartsDom对象
      })

    },

    drawdataset2(){
      let myChart5 = echarts.init(document.getElementById('set2'));
      let option = {
        xAxis: {
          type: 'category',
          boundaryGap: false,
          data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
        },
        yAxis: {
          type: 'value'
        },
        series: [{
          data: [820, 932, 901, 934, 1290, 1330, 1320],
          type: 'line',
          areaStyle: {}
        }]
      };

      option && myChart5.setOption(option);

      window.addEventListener("resize",function(){
        myChart5.resize();   //myChart2指自己定义的echartsDom对象
      })

    },

    drawdataset3(){

      let myChart6 = echarts.init(document.getElementById('set3'));
      let option = {
        title: {
          text: '某站点用户访问来源',
          subtext: '纯属虚构',
          left: 'center'
        },
        tooltip: {
          trigger: 'item'
        },
        legend: {
          orient: 'vertical',
          left: 'left',
        },
        series: [
          {
            name: '访问来源',
            type: 'pie',
            radius: '50%',
            data: [
              {value: 1048, name: '搜索引擎'},
              {value: 735, name: '直接访问'},
              {value: 580, name: '邮件营销'},
              {value: 484, name: '联盟广告'},
              {value: 300, name: '视频广告'}
            ],
            emphasis: {
              itemStyle: {
                shadowBlur: 10,
                shadowOffsetX: 0,
                shadowColor: 'rgba(0, 0, 0, 0.5)'
              }
            }
          }
        ]
      };
      option && myChart6.setOption(option);


      window.addEventListener("resize",function(){
        myChart6.resize();   //myChart2指自己定义的echartsDom对象
      })
    },
  }

}



</script>

 

 

 

 

Vue中mounted的简单理解

原文链接:https://blog.csdn.net/sinat_41124751/article/details/97927232

mounted是vue中的一个钩子函数,一般在初始化页面完成后,再对dom节点进行相关操作。官方文档的解释如下,钩子函数的官方链接为 https://cn.vuejs.org/v2/api/#mounted ,生命周期函数图示链接为 https://cn.vuejs.org/v2/guide/instance.html#生命周期图示

                      

 

自理解,通常是为  methods  函数提前定义( 类似提前声明变量 进入页面内容全部渲染完成后自动引函数),即

mounted() {
  this.submit()
},
methods: {
  submit() {
    this.select.List = [];
    for (var j = 0; j < this.select.label.length; j++) {
      var Name = this.ToLabel(this.select.label[j])
      this.select.List.push(Name);
    }
  }

 


 

 

vue实现切换左侧导航栏,对应切换右侧页面内容

 

1、右侧显示区域使用:<router-view></router-view>

2、左侧栏目菜单使用:<router-link to=""></router-link>指定页面进行跳转

 

Navigator.vue

<template>

  <el-container style="height: 550px; border: 1px solid #eee">


    <el-header style="text-align: right; font-size: 12px">
      <el-dropdown>
        <i class="el-icon-setting" style="margin-right: 15px"></i>
        <el-dropdown-menu slot="dropdown">
          <el-dropdown-item>查看</el-dropdown-item>
          <el-dropdown-item>新增</el-dropdown-item>
          <el-dropdown-item>删除</el-dropdown-item>
        </el-dropdown-menu>
      </el-dropdown>
      <span>@MedicalProject</span>
    </el-header>



    <el-container>
      <el-aside width="150px" style="background-color: rgb(238, 241, 246)">
        <el-menu :default-openeds="[]">
          <el-submenu index="1">
            <template slot="title"><i class="el-icon-message"></i>问卷调查</template>
            <el-menu-item-group>
              <template slot="title">分组一</template>
              <el-menu-item index="1-1">选项1</el-menu-item>
              <el-menu-item index="1-2">选项2</el-menu-item>
            </el-menu-item-group>

            <el-menu-item-group title="分组2">
              <el-menu-item index="1-3">选项3</el-menu-item>
              <el-menu-item index="1-4">选项4</el-menu-item>
            </el-menu-item-group>

          </el-submenu>

          <el-submenu index="2">
            <template slot="title"><i class="el-icon-menu"></i>风险评估</template>
            <el-menu-item-group>
              <template slot="title">分组一</template>
              <el-menu-item index="2-1">模型分析</el-menu-item>
              <el-menu-item index="2-2">编程分析</el-menu-item>
            </el-menu-item-group>
            <el-menu-item-group title="分组2">
              <el-menu-item index="2-3"><router-link to="/first">数据可视化</router-link></el-menu-item>
              <el-menu-item index="2-4">数据查询</el-menu-item>
            </el-menu-item-group>

          </el-submenu>

          <el-submenu index="3">
            <template slot="title"><i class="el-icon-setting"></i>知识图谱</template>
            <el-menu-item-group>
              <template slot="title">分组一</template>
              <el-menu-item index="3-1">选项1</el-menu-item>
              <el-menu-item index="3-2">选项2</el-menu-item>
            </el-menu-item-group>
            <el-menu-item-group title="分组2">
              <el-menu-item index="3-3">选项3</el-menu-item>
            </el-menu-item-group>
            <el-submenu index="3-4">
              <template slot="title">选项4</template>
              <el-menu-item index="3-4-1">选项4-1</el-menu-item>
            </el-submenu>
          </el-submenu>

          <el-submenu index="4">
            <template slot="title"><i class="el-icon-setting"></i>系统管理</template>
            <el-menu-item-group>
              <template slot="title">分组一</template>
              <el-menu-item index="3-1">选项1</el-menu-item>
              <el-menu-item index="3-2">选项2</el-menu-item>
            </el-menu-item-group>
            <el-menu-item-group title="分组2">
              <el-menu-item index="3-3">选项3</el-menu-item>
            </el-menu-item-group>
            <el-submenu index="3-4">
              <template slot="title">选项4</template>
              <el-menu-item index="3-4-1">选项4-1</el-menu-item>
            </el-submenu>
          </el-submenu>

        </el-menu>

      </el-aside>


      <el-main>

        <router-view></router-view>

      </el-main>


    </el-container>


    <el-footer>Footer</el-footer>

  </el-container>

</template>


<style scoped>

.el-header, .el-footer {
  background-color: #B3C0D1;
  color: #333;
  text-align: center;
  line-height: 60px;
}

.el-main {
  background-color: #E9EEF3;
  color: #333;
  height: 600px;
  width: 1000px;
  text-align: center;
  line-height: 110px;
}

.el-aside {
  color: #333;
}

a {
  text-decoration: none;
}
.router-link-active {
  text-decoration: none;
}

</style>



<script>

let echarts = require('echarts/lib/echarts');

export default {
  name: 'First.vue',
  data() {
    const item = {
      // date: '123',
      // name: '@',
      // address: '123'
    };
    return {
      // tableData: Array(10).fill(item)
    }
  },
  mounted() {

  },
  methods: {}

}


</script>

 

 

 

 

Data_Visualization.vue

<!--         为ECharts准备一个具备大小(宽高)的Dom-->
<template>
      <div>
          <div style="display: flex; margin-bottom:  10px"  >

             <div style="background-color: #0F1033; width: 580px;height: 300px; display: flex;">
                 <div id="bar1" style="width: 280px;height:300px; background-color:#1F2056; align-content: center"></div>
                    &nbsp;&nbsp;&nbsp;
                 <div id="bar2" style="width: 280px;height:300px; background-color:#1F2056; align-content: center"></div>
             </div>

                  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            <div style="background-color: #0F1033; width: 580px;height: 300px; display: flex;">
                <div id="pie1" style="width: 580px;height:300px; background-color:#1F2056;display: flex;" ></div>
            </div>

         </div>


          <div style="display: flex; margin-top: 10px"  >
              <div style="background-color: #0F1033; width: 580px;height: 300px; display: flex;">
                <div id="set1" style="width: 280px;height:300px; background-color:#1F2056; align-content: center"></div>
                   &nbsp;&nbsp;&nbsp;
                <div id="set2" style="width: 280px;height:300px; background-color:#1F2056; align-content: center"></div>
              </div>

          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
          <div style="background-color: #0F1033; width: 580px;height: 300px; display: flex;">
              <div id="set3" style="width: 580px;height:300px; background-color:#1F2056;display: flex;" ></div>
          </div>

        </div>

      </div>

</template>



<script>

let echarts = require('echarts/lib/echarts');

export default {
  name: 'First.vue',
  data() {
    const item = {
      // date: '2016-05-02',
      // name: '王小虎',
      // address: '上海市普陀区金沙江路 1518 弄'
    };
    return {
      // tableData: Array(10).fill(item)
    }
  },
  mounted() {
    this.drawbar1();
    this.drawbar2();
    this.drawpie1();
    this.drawdataset1();
    this.drawdataset2();
    this.drawdataset3();
  },
  methods: {

    drawbar1() {
      // 基于准备好的dom,初始化echarts实例
      let myChart1 = echarts.init(document.getElementById('bar1'));

      // 指定图表的配置项和数据
      let option = {
        title: {
          text: '第一个 ECharts 实例',
          textStyle: {
            fontSize: 15,
            color: "#FBFBFD"
          }
        },
        tooltip: {},
        legend: {
          data: [ {
            name: '销量',
            textStyle:{
              color: "rgba(252, 252, 252, 0.99)"
              }
            }
          ],
          bottom: "83%",
          itemWidth: 20,
          itemHeight: 20,
          itemStyle:{
          }
        },
        xAxis: {
          data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"]
        },
        yAxis: {},
        series: [{
          name: '销量',
          type: 'bar',
          data: [5, 20, 36, 10, 10, 20]
        }]
      };

      myChart1.setOption(option);


      window.addEventListener("resize",function(){
        myChart1.resize();   //myChart2指自己定义的echartsDom对象
      })

    },
    drawbar2() {
      // 基于准备好的dom,初始化echarts实例
      let myChart2 = echarts.init(document.getElementById('bar2'));

      // 指定图表的配置项和数据
      let option = {
        title: {
          text: '第一个 ECharts 实例',
          textStyle: {
            fontSize: 15,
            color: "#FBFBFD"
          }
        },
        tooltip: {},
        legend: {
          data: [ {
            name: '销量',
            textStyle:{
              color: "rgba(252, 252, 252, 0.99)"
            }
          }
          ],
          bottom: "83%",
          itemWidth: 20,
          itemHeight: 20,
        },
        xAxis: {
          data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"]
        },
        yAxis: {},
        series: [{
          name: '销量',
          type: 'bar',
          data: [5, 20, 36, 10, 10, 20]
        }]
      };

      myChart2.setOption(option);

      window.addEventListener("resize",function(){
        myChart2.resize();   //myChart2指自己定义的echartsDom对象
      })

    },

    drawpie1() {

      let myChart3 = echarts.init(document.getElementById('pie1'));
      let  option = {
        title: {
          text: '南丁格尔玫瑰图',
          subtext: '纯属虚构',
          left: 'center'
        },
        tooltip: {
          trigger: 'item',
          formatter: '{a} <br/>{b} : {c} ({d}%)'
        },
        legend: {
          left: 'center',
          top: 'bottom',
          data: ['rose1', 'rose2', 'rose3', 'rose4', 'rose5', 'rose6', 'rose7', 'rose8']
        },
        toolbox: {
          show: true,
          feature: {
            mark: {show: true},
            dataView: {show: true, readOnly: false},
            restore: {show: true},
            saveAsImage: {show: true}
          }
        },
        series: [
          {
            name: '面积模式',
            type: 'pie',
            radius: [20, 90],
            center: ['25%', '50%'],
            roseType: 'area',
            Legend: {
              width: "10%",
              height: "10%",
            },
            itemStyle: {
              borderRadius: 5
            },
            data: [
              {value: 30, name: 'rose 1'},
              {value: 28, name: 'rose 2'},
              {value: 26, name: 'rose 3'},
              {value: 24, name: 'rose 4'},
              {value: 22, name: 'rose 5'},
              {value: 20, name: 'rose 6'},
              {value: 18, name: 'rose 7'},
              {value: 16, name: 'rose 8'}
            ]
          }
        ]
      };
      option && myChart3.setOption(option);

      window.addEventListener("resize",function(){
        myChart3.resize();   //myChart2指自己定义的echartsDom对象
      })

    },
    drawdataset1(){

      let myChart4 = echarts.init(document.getElementById('set1'));
      let  option = {
        dataset: {
          source: [
            ['score', 'amount', 'product'],
            [89.3, 58212, 'Matcha Latte'],
            [57.1, 78254, 'Milk Tea'],
            [74.4, 41032, 'Cheese Cocoa'],
            [50.1, 12755, 'Cheese Brownie'],
            [89.7, 20145, 'Matcha Cocoa'],
            [68.1, 79146, 'Tea'],
            [19.6, 91852, 'Orange Juice'],
            [10.6, 101852, 'Lemon Juice'],
            [32.7, 20112, 'Walnut Brownie']
          ]
        },
        grid: {containLabel: true},
        xAxis: {name: 'amount'},
        yAxis: {type: 'category'},
        visualMap: {
          orient: 'horizontal',
          left: 'center',
          min: 10,
          max: 100,
          text: ['High Score', 'Low Score'],
          // Map the score column to color
          dimension: 0,
          inRange: {
            color: ['#65B581', '#FFCE34', '#FD665F']
          }
        },
        series: [
          {
            type: 'bar',
            encode: {
              // Map the "amount" column to X axis.
              x: 'amount',
              // Map the "product" column to Y axis
              y: 'product'
            }
          }
        ]
      };

      option && myChart4.setOption(option);

      window.addEventListener("resize",function(){
        myChart4.resize();   //myChart2指自己定义的echartsDom对象
      })

    },

    drawdataset2(){
      let myChart5 = echarts.init(document.getElementById('set2'));
      let option = {
        xAxis: {
          type: 'category',
          boundaryGap: false,
          data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
        },
        yAxis: {
          type: 'value'
        },
        series: [{
          data: [820, 932, 901, 934, 1290, 1330, 1320],
          type: 'line',
          areaStyle: {}
        }]
      };

      option && myChart5.setOption(option);

      window.addEventListener("resize",function(){
        myChart5.resize();   //myChart2指自己定义的echartsDom对象
      })

    },

    drawdataset3(){

      let myChart6 = echarts.init(document.getElementById('set3'));
      let option = {
        title: {
          text: '某站点用户访问来源',
          subtext: '纯属虚构',
          left: 'center'
        },
        tooltip: {
          trigger: 'item'
        },
        legend: {
          orient: 'vertical',
          left: 'left',
        },
        series: [
          {
            name: '访问来源',
            type: 'pie',
            radius: '50%',
            data: [
              {value: 1048, name: '搜索引擎'},
              {value: 735, name: '直接访问'},
              {value: 580, name: '邮件营销'},
              {value: 484, name: '联盟广告'},
              {value: 300, name: '视频广告'}
            ],
            emphasis: {
              itemStyle: {
                shadowBlur: 10,
                shadowOffsetX: 0,
                shadowColor: 'rgba(0, 0, 0, 0.5)'
              }
            }
          }
        ]
      };
      option && myChart6.setOption(option);


      window.addEventListener("resize",function(){
        myChart6.resize();   //myChart2指自己定义的echartsDom对象
      })
    },
  }

}



</script>

 

 

 

App.vue

<template>
<!--  <div id="app">-->
<!--    <img src="./assets/logo.png">-->
  <div id="app">
      <Nav></Nav>
  </div>
<!--  </div>-->
</template>

<script>
import Nav from '@/components/Navigator'
export default {
  name: 'App',
  components: {
    Nav
  }
}
</script>

<style>
/*#app {*/
/*  font-family: 'Avenir', Helvetica, Arial, sans-serif;*/
/*  -webkit-font-smoothing: antialiased;*/
/*  -moz-osx-font-smoothing: grayscale;*/
/*  text-align: center;*/
/*  color: #2c3e50;*/
/*  margin-top: 60px;*/
/*}*/
</style>

 

 

index.js

 

import Vue from 'vue'
import Router from 'vue-router'
import Data_Visualization from '@/components/Data_Visualization'
Vue.use(Router) export default new Router({ mode:'history',//去掉路由地址栏中的# routes: [ { path: '/Data_V', name: 'Data_Visualization', component: Data_Visualization } ] })

 

 

 

 

 

 

消除router-link 的下划线问题

增加样式代码即可

a {
  text-decoration: none;
}
 
.router-link-active {
  text-decoration: none;
}

 

 

 

vue中vuedraggable 拖拽列表的使用 

原文链接:https://blog.csdn.net/weixin_47180815/article/details/109841448

 

【想看官网的这里来】
vue中draggable拖拽列表的使用
https://github.com/SortableJS/Vue.Draggable

 

vuedraggable中文文档

https://www.itxst.com/vue-draggable/tutorial.html

 

 

官方示例:

https://sortablejs.github.io/Vue.Draggable/#/transition-example-2

https://david-desmaisons.github.io/draggable-example/

 

【以下是我自己的用法】
安装引入,已经ok的可以直接跳过这个部分

  1. 安装
npm install vuedraggable  

或者使用镜像安装

cnpm install vuedraggable  
  1. 使用

    首先在使用的组件中引入

import draggable from 'vuedraggable'

 









Axios

Axios是-个基于Promise 的HTTP库,它是一个简洁、易用且高效的代码封装库。
通俗地讲,它是当前比较流行的一种Ajax框架,可以使用它发起HTTP请求接口功能,
是基于Promise的,相比较Ajax的回调函数能够更好地管理异步操作。


Axios的特点:

(1)从浏览器中创建XMLHttpRequests

(2)从Node.js创建HTTP请求。

(3)支持Promise API

(4)拦截请求和响应

(5)转换请求数据和响应数据

(6)取消请求

(7)自动转换JSON数据

(8)客户端支持防御XSRF


使用方法:

使用NPM安装Axios的依赖:
npm install axios

1.全局使用Axios需要在main.js中设置,然后在组件中通过this来调用,代码如下:

import axios from 'axios'
Vue.prototype.$axios= axios;   //加载到原型上

 


2.vue中Axios的封装
api/index.js文件,封装配置Axios
import axios from 'axios'
let http = axios.create({ baseURI: 'http://localhost:18071/', //设置默认前缀地址 withCredentials: true, //配置跨域,需要 headers: { 'content-Type': 'application/x-www-form-urlencoded; charset=utf-8' }, transformRequest: [function (data) { let newData = ''; for (let k in data){ if(data.hasOwnProperty(k) === true){ newData += encodeURIComponent(k) + '=' + encodeURIComponent(data[k]) + '&'; } } return newData; }] }); function apiAxios(method, url, params, response){ http({ method: method, url: url, data: method === 'POST'|| method === 'PUT' ? params : null, params: method === 'GET'|| method === 'DELETE' ? params : null, }).then(function (res) { response(res); }).catch(function (err) { response(err); }) } export default { get: function (url, params, response) { return apiAxios('GET', url, params, response) }, post: function (url, params, response) { return apiAxios('POST', url, params, response) }, put: function (url, params, response) { return apiAxios('PUT', url, params, response) }, delete: function (url, params, response) { return apiAxios('DELETE', url, params, response) } }

 

使用:
在main.js中引入方法,代码如下:

//main.js 部分代码省略
import Api from './api/index.js';
Vue.prototype.$http= Api;



使用Axios请求后端的实时数据:







版权声明:本文为CSDN博主「让我看看谁在学习」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42545184/article/details/89311666

vue项目中某一页面不想引用公共组件app.vue解决办法

   Vue单页面应用把公共组件放在 app.vue 但是我希望某个页面没有这些公共组件怎么办(比如登陆页面)每个页面都有导航栏但是我希望 
登陆页面只有一个背景色和一个登陆框 没有导航栏 那应该怎样设置呢?

        vue中文文档:https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html#%E5%93%8D%E5%BA%94%E8%B7%AF%E7%94%B1%E5%8F%82%E6%95%B0%E7%9A%84%E5%8F%98%E5%8C%96


在根组件中:在导航栏使用v-show判断当前路由是否是不需要的组件来完成页面:

App.vue

 

index.vue

 

 






Vue--登录页面

https://www.cnblogs.com/zouzou-busy/p/11741407.html

使用elementUI

<template>
  <div class="login-container">
    <el-form ref="form" :model="form" label-width="80px" class="login-form">
      <h2 class="login-title">肿瘤健康管理系统</h2>
      <el-form-item label="用户名">
        <el-input v-model="form.username"></el-input>
      </el-form-item>
      <el-form-item label="密码">
        <el-input v-model="form.password"></el-input>
      </el-form-item>

      <el-form-item>
        <el-button type="primary" @click="onSubmit">登录</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>
  <script>
export default {
  data() {
    return {
      form: {
        username: "",
        password: ""
      }
    };
  },
  methods: {
    onSubmit() {
      console.log("submit!");
    }
  }
};
</script>

<style acoped>
.login-form {
  width: 350px;
  margin: 160px auto; /* 上下间距160px,左右自动居中*/
  background-color: rgb(255, 255, 255, 0.8); /* 透明背景色 */
  padding: 30px;
  border-radius: 20px; /* 圆角 */
}

/* 背景 */
.login-container {
  position: absolute;
  width: 100%;
  height: 100%;
  background: url("../../assets/login.png");
}

/* 标题 */
.login-title {
  color: #303133;
  text-align: center;
}

 body{
    font-family: "微软雅黑";  /*  设置字体 */
    margin: 0px auto /* 去除上下的边距*/
  }



</style> 

 




添加表单验证

上面我们只是实现了登录的form表单,但是没有验证数据输入的合法性,比如空,或者长度

elementui提供给了我们校验的方法

Form 组件提供了表单验证的功能,只需要通过 rules 属性传入约定的验证规则,并将 Form-Item 的 prop 属性设置为需校验的字段名即可

修改 login.vue里的代码

<template>
  <div class="login-container">
    <el-form ref="form" :rules="rules" :model="form" label-width="80px" class="login-form">
      <h2 class="login-title">肿瘤健康管理系统</h2>
      <el-form-item label="用户名" prop="username">
        <el-input v-model="form.username"></el-input>
      </el-form-item>
      <el-form-item label="密码" prop="password">
        <el-input v-model="form.password"></el-input>
      </el-form-item>

      <el-form-item>
        <el-button type="primary" @click="submitForm('form')">登录</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>


<script>
export default {
  data() {
    return {
      form: {
        username: "",
        password: ""
      },
      rules: {
        username: [
          {required: true, message: "用户名不能为空", trigger: 'blur'},
          {min: 3, max: 10, message: "用户名3-5位", trigger: 'blur'}
        ],
        password: [
          {required: true, message: "密码不能为空", trigger: 'blur'},
          {min: 3, max: 10, message: "密码3-5位", trigger: 'blur'}
        ]
      }
    };
  },
  methods: {
    submitForm(formName) {
      this.$refs[formName].validate(valid => {
        // console.log(valid) 验证通过为true,有一个不通过就是false
        if (valid) {
          // 通过的逻辑
        } else {
          console.log('验证失败');
          return false;
        }
      });
    }
  }
};
</script>



<style acoped>
.login-form {
  width: 350px;
  margin: 160px auto; /* 上下间距160px,左右自动居中*/
  background-color: rgb(255, 255, 255); /* 透明背景色 */
  padding: 30px;
  border-radius: 20px; /* 圆角 */
}

/* 背景 */
.login-container {
  position: absolute;
  width: 100%;
  height: 100%;
  background: url("../assets/login.png");
}

/* 标题 */
.login-title {
  color: #303133;
  text-align: center;
}


body{
  font-family: "微软雅黑";  /*  设置字体 */
  margin: 0px auto /* 去除上下的边距*/
}

</style> 

在第三行加上 :rules="rules" 第五行和第八行加上 prop="username" 后面的属性值自定义,更改39行到47行,第十三行改为 @click="submitForm('form')",submitForm就是method的方法名。后面的form是第三行的ref属性。

{required: true, message: "密码不能为空", trigger: 'blur'},表示当鼠标失去焦点后验证,必填,如果为空则提示message里的信息

{min: 3, max: 10, message: "密码3-5位", trigger: 'blur'}表示当鼠标失去焦点后验证,最小为3位,最大为10位,如果不满足则提示message里的信息





vue处理token+配置axios

版权声明:本文为CSDN博主「花眼熊」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_49668076/article/details/114338975
 

在项目中登录之后就要把token存起来,有权限的接口都要携带token访问。
本篇是通过vuex容器+本地存储结合在一起存储token,好处是获取方便、响应式、持久化。


什么是 Token?


Token 是用户登录成功之后服务端返回的一个身份令牌,在项目中的多个业务中需要使用到
访问需要授权的 API 接口
校验页面的访问权限

但是我们只有在第一次用户登录成功之后才能拿到 Token
所以为了能在其它模块中获取到 Token 数据,我们需要把它存储到一个公共的位置,方便随时取用


具体代码如下:
1.封装一个本地缓存的方法
在src下新建一个storage文件夹,文件夹里新建index.vue
















Vue 页面权限控制和登陆验证


页面权限控制是什么意思呢?


就是一个网站有不同的角色,比如管理员普通用户,要求不同的角色能访问的页面是不一样的。如果一个页面,有角色越权访问,这时就得做出限制了。


这是我写过的一篇文章,
Vue 动态添加路由及生成菜单通过动态添加路由和菜单来做控制,不能访问的页面不添加到路由表里,这是其中一种办法。


另一种办法就是所有的页面都在路由表里,只是在访问的时候要判断一下角色权限。如果有权限就让访问,没有权限就拒绝,跳转到 404 页面(或指定页面)。


思路


在每一个路由的 meta 属性里,将能访问该路由的角色添加到 roles 里。用户每次登陆后,将用户的角色返回。然后在访问页面时,把路由的 meta 属性和用户的角色进行对比,如果用户的角色在路由的 roles 里,那就是能访问,如果不在就拒绝访问。


代码示例


路由信息


routes: [
    {
        path: '/login',
        name: 'login',
        meta: {
            roles: ['admin', 'user']
        },
        component: () => import('../components/Login.vue')
    },
    {
        path: 'home',
        name: 'home',
        meta: {
            roles: ['admin']
        },
        component: () => import('../views/Home.vue')
    },
]

 

页面控制
// 假设角色有两种:admin 和 user
// 这里是从后台获取的用户角色
const role = 'user'
// 在进入一个页面前会触发 router.beforeEach 事件
router.beforeEach((to, from, next) => {
    if (to.meta.roles.includes(role)) {
        next()
    } else {
        next({path: '/404'})
    }
})

 











 
 
posted @ 2021-08-23 21:35  liweikuan  阅读(1171)  评论(0编辑  收藏  举报