• 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;  580px;height: 300px; display: flex;">
                     <div id="bar1" style=" 280px;height:300px; background-color:#1F2056; align-content: center"></div>
                        &nbsp;&nbsp;&nbsp;
                     <div id="bar2" style=" 280px;height:300px; background-color:#1F2056; align-content: center"></div>
                 </div>
    
                      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                <div style="background-color: #0F1033;  580px;height: 300px; display: flex;">
                    <div id="pie1" style=" 580px;height:300px; background-color:#1F2056;display: flex;" ></div>
                </div>
    
             </div>
    
    
              <div style="display: flex; margin-top: 10px"  >
                  <div style="background-color: #0F1033;  580px;height: 300px; display: flex;">
                    <div id="set1" style=" 280px;height:300px; background-color:#1F2056; align-content: center"></div>
                       &nbsp;&nbsp;&nbsp;
                    <div id="set2" style=" 280px;height:300px; background-color:#1F2056; align-content: center"></div>
                  </div>
    
              &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
              <div style="background-color: #0F1033;  580px;height: 300px; display: flex;">
                  <div id="set3" style=" 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: {
                   "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;  580px;height: 300px; display: flex;">
                     <div id="bar1" style=" 280px;height:300px; background-color:#1F2056; align-content: center"></div>
                        &nbsp;&nbsp;&nbsp;
                     <div id="bar2" style=" 280px;height:300px; background-color:#1F2056; align-content: center"></div>
                 </div>
    
                      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                <div style="background-color: #0F1033;  580px;height: 300px; display: flex;">
                    <div id="pie1" style=" 580px;height:300px; background-color:#1F2056;display: flex;" ></div>
                </div>
    
             </div>
    
    
              <div style="display: flex; margin-top: 10px"  >
                  <div style="background-color: #0F1033;  580px;height: 300px; display: flex;">
                    <div id="set1" style=" 280px;height:300px; background-color:#1F2056; align-content: center"></div>
                       &nbsp;&nbsp;&nbsp;
                    <div id="set2" style=" 280px;height:300px; background-color:#1F2056; align-content: center"></div>
                  </div>
    
              &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
              <div style="background-color: #0F1033;  580px;height: 300px; display: flex;">
                  <div id="set3" style=" 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: {
                   "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'})
        }
    })
    
    
    










     
     
  • 相关阅读:
    Win 11 添加并使用 DOH
    Dockercompose 一键搭建 Discourse 论坛
    JSON.parse容错问题
    yum install vim y失败
    常见的问题系列【解决tomcat端口一直被占用的问题,更换端口也不行】
    dockermavenplugin 与 dockerfilemavenplugin 对springboot自动打包docker镜像并推送harbor的区别
    drawio私有存储方法
    WxyCMS模板标签大全
    c语言程序(上课用)
    c语言文件处理 (上课用)
  • 原文地址:https://www.cnblogs.com/liweikuan/p/15119045.html
Copyright © 2020-2023  润新知