尚品汇后台项目

P1、项目介绍

后台管理系统 不是后端技术

前台针对的是用户 后台管理系统对应的是卖家

前台的数据来自于卖家 可视化操作数据库

可以让用户操作可视化操作平台实现数据库的操作 不同角色看到的操作的内容是不同的 一般不需要注册

P2、后台管理系统模板介绍

使用托管github的模板文件

简洁版: https://github.com/PanJiaChen/vue-admin-template

加强版: https://github.com/PanJiaChen/vue-element-admin

模板的文件与文件夹认知【简洁版】

1.下载模板

https://github.com/PanJiaChen/vue-admin-template

2.下载依赖

npm i

3.运行项目

npm run dev package.json文件里面有写

报错解决:cnpm install --save core-js

4.文件夹介绍

build
     ----index.js webpack配置文件【很少修改这个文件】
mock
    ----mock数据的文件夹【模拟一些假的数据mockjs实现的】,因为咱们实际开发的时候,利用的是真是接口

node_modules
     ------项目依赖的模块

public
     ------ico图标,静态页面,publick文件夹里面经常放置一些静态资源,而且在项目打包的时候webpack不会编译这个文件夹,原封不动的打包到dist文件夹里面

src
    -----程序员源代码的地方
    ------api文件夹:涉及请求相关的
    ------assets文件夹:里面放置一些静态资源(一般共享的),放在aseets文件夹里面静态资源,在webpack打包的时候,会进行编译
    ------components文件夹:一般放置非路由组件获取全局组件
    ------icons这个文件夹的里面放置了一些svg矢量图
    ------layout文件夹:他里面放置一些组件与混入
    ------router文件夹:与路由相关的
    -----store文件夹:一定是与vuex相关的
    -----style文件夹:与样式先关的
    ------utils文件夹:request.js是axios二次封装文件****
    ------views文件夹:里面放置的是路由组件

App.vue:根组件
main.js:入口文件
permission.js:与导航守卫相关、
settings:项目配置项文件
tests:作者测试文件
.editorconfig:编程风格文件
.env.development :webpack可以监测到的开发文件
.env.producation :webpack可以监测到的上线文件
env.staging:webpack可以监测到的测试文件
上面三个文件都可以通过process.nev来获取到

5.setting.js文件配置

img

P3、登录业务完成

1.完成静态组件

找到src/views/login/index.vue进行修改

2.改写静态组件内容

2.1解决template爆红

2.2在assets文件内添加亦庄背景图

img

2.3 给最外面的类名添加背景图和平铺

img

注意css需要加入~才可以使用别名

2.4,修改文字

标题

img

登录按钮

img

文本框

img

其中elememt表单元素的

model是收集数据用的

rules是验证规则

3.改写vuex里面的actions方法

原先代码 没有asyne await 现在和前台方法一样改写

img

改写后

img

4.书写api 换成真实的接口

本次使用线上文档

后台管理系统API接口在线文档:

http://39.98.123.211:8170/swagger-ui.html

http://39.98.123.211:8216/swagger-ui.html

img

把接口全部换成

img

5.改写axios的二次封装

修改请求拦截器的hearders头的字段为token这是定好的

img

修改响应拦截器的状态码判断为

img

6.配置代理跨域

搜索webpack里面的devserve 里面的proxy复制代码

ps:此处dialing的地址改为http://gmall-h5-api.atguigu.cn

 proxy: {
            '/dev-api': {
                target: 'http://39.98.123.211:8170',
                pathRewrite: { '^/dev-api': '' },
            },
        },

这里的/dev-api是生产模式的前缀

可以在.env.development文件里面进行修改 注意一致就行

可以把二次封装的函数修改为

im service from ‘@/utils/request’

P4、 退出登录

修改退出按钮的静态页面

src\layout\components\Navbar.vue

img

P5、路由的搭建

把路由删除到只剩下

img

注意路由写法:

img

一切基础基于Layout这个组件

img

/路径访问的是Layout组件 先把大框架显示出来 然后立马重定向到首页

title字段是显示的文字

icon字段是文字前面的图标

配置自己的路由

创建商品管理路由组件和子组件

img

配置路由

{
        path: '/product',
        name: 'Product',
        component: Layout,
        meta: { title: '品牌管理', icon: 'el-icon-goods' },
        children: [{
                path: 'tradeMark',
                name: 'TradeMark',
                component: () =>
                    import ('@/views/product/tradeMark/index'),
                meta: { title: '品牌管理' }
            },
            {
                path: 'attr',
                name: 'Attr',
                component: () =>
                    import ('@/views/product/Attr/index'),
                meta: { title: '平台属性管理' }
            },
            {
                path: 'sku',
                name: 'Sku',
                component: () =>
                    import ('@/views/product/Sku/index'),
                meta: { title: 'Sku管理' }
            },
            {
                path: 'spu',
                name: 'Spu',
                component: () =>
                    import ('@/views/product/Spu/index'),
                meta: { title: 'Spu管理' }
            },
        ]
    },

修改框架类名 index.scss

img

实现效果: img

P6、品牌管理静态组件

vscode下载插件

vue-helper

element ui snipets

<template>
  <div>
    <!-- 按钮 -->
    <el-button type="primary" plain style="margin: 20px">+ 添加</el-button>
    <!-- 表格 -->
    <el-table border :data="data">
      <el-table-column
        label="序号"
        width="80px"
        align="center"
      ></el-table-column>
      <el-table-column label="品牌名称" width="width"></el-table-column>
      <el-table-column label="品牌logo"></el-table-column>
      <el-table-column label="操作"></el-table-column>
    </el-table>
       
    <el-pagination
      :current-page="5"
      :page-sizes="[5, 7, 9]"
      :page-size="100"
      layout=" prev, pager, next, jumper,->,sizes,total"
      :total="400"
      :pager-count="5"
      style="text-align: center;margin-top: 20px;"
    >
    </el-pagination>
  </div>
</template>

el-button 按钮

type:类型 string

icon:图标类名

el-table 表单

data:表格中将来需要展示的数据 数组类型

border 添加竖线

配合el-table-column使用 表示列 表单列

label :显示标题的内容

width:对应列的宽度

align:标题的对齐方式

prop:对应列的内容的字段名

el-pagination 分页器

@size-change=“handleSizeChange”

@current-change=“handleCurrentChange”

​ current-page:代表的是当前第几页

​ total:代表分页器一共需要展示数据条数

​ page-size:代表的是每一页需要展示多少条数据

​ page-sizes:代表可以设置每一页展示多少条数据

​ layout:可以实现分页器布局 -> 逗号隔开

​ pager-count:按钮的数量 如果 9 连续页码是7

P7、品牌列表展示

1.书写自己的api接口

​ GET /admin/product/baseTrademark/ p a g e / {page}/ page/{limit}

需要参数page当前页 limit每页展示的数据

在api文件夹只留下user.js

创建文件夹 product

在product文件夹创建四个文件,分别管理trademark、attr、spu、sku

img

在trademark.js引入封装过后的axios函数

img

导出自己的接口函数

img

对接口进行统一管理

/api/index.js

把所有模块的函数进行管理

注意写法:import * as xx from xxx 把里面的所有函数进行导入

img

模块导出

挂载到原型上面 main.js 默认引入index.js

img

在mounted生命周期请求函数

img

初始页码和每页展示的数据

img

组件挂载发请求

img

data准备接收总数据和el-table绑定的data

img

获取数据显示在table

<el-table border :data="list" >
      <el-table-column
        label="序号"
        width="80px"
        align="center"
        type="index"
      ></el-table-column>
      <el-table-column label="品牌名称"  width="width" prop="tmName"></el-table-column>
      <el-table-column label="品牌logo">
        <template slot-scope="{row,$index}">
          <img :src="row.logoUrl" alt="" style="width:90px;height:50px">
        </template>
      </el-table-column>
      <el-table-column label="操作">
        <template slot-scope="{row,$index}">
          <el-button size="mini" type="info" icon="el-icon-edit">修改</el-button>
          <el-button size="mini" type="warning" icon="el-icon-delete">删除</el-button>
        </template>
      </el-table-column>
    </el-table>

el-table

:data=“list” 绑定的总数据

el-table-column

label=“序号” 列的标题

​ width=“80px” 宽度

​ align=“center” 局中方式

​ type=“index” 序号

prop=“tmName” 每列显示的data.tmName

作用域插槽 固定写法 row返回的是父组件绑定data.xx

分页器的数据动态绑定

 <el-pagination
      :current-page="page"
      :page-sizes="[5, 7, 9]"
      :page-size="limit"
      layout="prev, pager, next, jumper,->,sizes,total"
      :total="total"
      :pager-count="5"

分页器的事件:

@current-change=“handleCurrentChange”

点击分页器的数字按钮的时候触发的事件 第一个参数是点击的数字

​ @size-change=“handleSizeChange”

修改分页器每页显示多少数据的时候触发的事件 第一个参数是选择后的每页展示的数据的数量

img

P8、添加品牌和修改品牌静态完成

点击添加按钮 会出现遮罩层

使用el-dialog

title=“修改品牌” 左上角的文字

:visible.sync=“dialogFormVisible” dialogFormVisible变量控制是否显示和隐藏

把显示和隐藏的事件绑定在添加按钮和修改按钮上面

img

目前只做静态页面

重构对话框

    <el-dialog title="修改品牌" :visible.sync="dialogFormVisible">
      <el-form >
        <el-form-item label="品牌名称">
          <el-input  autocomplete="off" style="width:500px"></el-input>
        </el-form-item>
        <el-form-item label="品牌Logo">
          <!-- 上传 -->
          <el-upload
          class="avatar-uploader"
          action="https://jsonplaceholder.typicode.com/posts/"
          :show-file-list="false"
          >
          <img v-if="imageUrl" :src="imageUrl" class="avatar">
          <i v-else class="el-icon-plus avatar-uploader-icon"></i>
          <div slot="tip" class="el-upload__tip" style="margin-left:80px">只能上传jpg/png文件,且不超过500kb</div>
        </el-upload>
        </el-form-item>
      </el-form>
      <div  class="dialog-footer" style="margin-left:500px">
        <el-button @click="dialogFormVisible = false">取 消</el-button>
        <el-button type="primary" @click="dialogFormVisible = false"
          >确 定</el-button
        >
      </div>
    </el-dialog>

el-form

:model 把表单信息收集到哪里 是一个对象

el-upload 上传

需要css样式也复制

:on-success=“handleAvatarSuccess”

上传前的回调

​ :before-upload=“beforeAvatarUpload”

上传后的回调

P9、添加品牌完成

添加品牌和修改品牌

收集品牌名称和品牌logo发请求存入数据库 然后发请求获取到数据

1.书写api

因为添加和修改的api参数差不多 唯一的区别就是传不传id

如果是添加的不需要传id 如果是修改的需要传id

一起封装为一个函数

img

2.收集元素的tmName和logoUrl

el-form

:model 把表单信息收集到哪里 是一个对象

初始化一个对象来收集信息,对象的字段必须是tmName和logoUrl

img

收集品牌名称 form表单:model属性绑定要收集的对象的位置

<el-form" :model=“trademark”>

​ <el-input " v-model=“trademark.tmName”>

​ 输入框绑定tmName 收集品牌名称

收集品牌logo

不能用v-model因为不是表单元素

<el-upload

​ action=" " 文件上传的地址

​ :show-file-list=“false” 是否显示文件已经上传列表>

文件上传地址:/dev-api/admin/product/fileUpload

注意前面的/dev-api

{"code":200,"message":"成功","data":"http://139.198.127.41:9000/sph/20220918/user.jpg","ok":true}

图片上传成功之后还会返回图片的网络地址

在上传成功之后把这个地址传给img的地址

img

:on-success=“handleAvatarSuccess”

上传成功之后的回调

img

res返回上传成功的网络地址

file返回图片的信息

让trademark的logoUrl把地址存了 并且根据这个来判断上传完成显示的图片和+号

img

这里tmName和logoUrl全部收集完毕

解决上传取消按钮的时候不能保留上次没有上传的文本信息和图片信息

在点击取消按钮的时候 弹窗消失 数据清空

img

点击确定发请求

img

img

P10、修改品牌完成

修改按钮传参 传row 是本列的信息

img

然后把trademark修改为这些信息

img

img

现在直接点击修改按钮就可以获取到tmName和logoUrl

但是修改的时候还没有点确定 就修改了 解决:浅拷贝

img

点击完成发请求 修改数据 如果是修改就会传入id

修改$message的弹窗显示样式

img

修改from表单的title显示

img

如果是修改 留在当前页 如果是添加 返回第一页

img

P11、品牌的表单校验(自定义校验规则)

内置规则

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

1.el-form model绑定数据 relus是自内置规则

img

2.el-form-item prop绑定el-form的model字段的属性

img

3.配置内置规则 relus的属性值必须与el-form-item prop绑定字段一致

img

required 是否必须

message 提示文字

trigger 触发事件

所有表单验证都通过之后才能执行

1.form表单加入ref

img

2.refs.ruleForm.validate(回调函数(参数)=>{

if(参数全部通过){

执行代码

}

})

img

注意此时的asyne放在最近的回调函数前面

自定义表单校验规则

var checkAge = (rule, value, callback) => {
        if (!value) {
          return callback(new Error('年龄不能为空'));
        }


  rules: {
          pass: [
            { validator: validatePass, trigger: 'blur' }
          ],

写在data里面

img

写在表单验证的relus里面

img

P12、删除品牌操作

写api

img

使用message组件

img

请求成功进行再次请求 如果当前页有数据 留在当前页 如果当前页没有数据返回当前页的前一页

img

P13、商品管理之三级联动静态组件

创建公共组件menus

img

里面写菜单的静态组件

<div>
    <el-form ref="form"  label-width="80px" style="display:flex">
  <el-form-item label="一级菜单">
    <el-select  placeholder="请选择一级菜单">
      <el-option label="区域一" value=""></el-option>
      <el-option label="区域一" value=""></el-option>
      <el-option label="区域二" value=""></el-option>
    </el-select>
  </el-form-item>
  <el-form-item label="二级菜单">
    <el-select  placeholder="请选择二级菜单">
      <el-option label="区域一" value=""></el-option>
      <el-option label="区域二" value=""></el-option>
      <el-option label="区域一" value=""></el-option>
    </el-select>
  </el-form-item>
  <el-form-item label="三级菜单">
    <el-select  placeholder="请选择三级菜单">
      <el-option label="区域一" value=""></el-option>
      <el-option label="区域二" value=""></el-option>
      <el-option label="区域一" value=""></el-option>
    </el-select>
  </el-form-item>
</el-form>
  </div>

挂载为全局组件

img

在attr.vue里面引入

 <el-card style="margin:20px">
      <menus></menus>
      </el-card>

el-card

会自己添加背景和背景颜色

P14、三级联动动态展示

写接口 get

img

img

获取一级菜单的信息

初始一个list1来接收数据

img

组件挂载的时候获取一级菜单的信息

img

img

遍历选项框

img

收集数据

 <el-form  :model="tmList">
  <el-form-item label="一级菜单">
    <el-select  placeholder="请选择一级菜单" v-model="tmList.category1id" @change="cate1idchange">
      <el-option :label="c1.name" :value="c1.id" v-for="(c1,index) in list1"  :key="c1.id" ></el-option>

把表单的数据收集到tmList里面

v-model数据双向绑定的是value的值 也就是选项

初始list2和list3来进行接收获取来的数据

初始tmList来存获取到的选项的id值

img

el-select 添加事件 如果选项改变的时候 把选项的value收集到 也就是id

根据这个id来发请求 获取到新id来获取list3的数据

imgimg

获取到数据来遍历选项框

img

P15、三级联动完成

解决bug

如果确定1id2id3id之后 重新选择1id 2 3需要清空

img

如果确定1id2id之后 重新选择2id 3需要清空

img

在选择第三个菜单的时候需要发请求显示下面的内容(平台属性)

因为menus组件是子组件 id值在子组件内 需要传给attr父组件 使用自定义事件 父@ 子$emit 父组件data准备数据来进行存储

img

img

父组件获取到数据如何确定是1id/2id/3id 呢 子组件传值的时候进行解构 传入固定的字符串 level

img

父组件取值的时候也必须进行解构提取,注意kv一致

并且在一级菜单改变的时候 重新传入1id 2/3id置空

并且在二级菜单改变的时候 重新传入2id 3id置空

img

三个id全部获取到就会发请求

P16、平台属性动态展示属性

书写api

export const reqcategory3Listbuttom = (category1id, category2id, category3id) => {
    return request({
        url: `/admin/product/attrInfoList/${category1id}/${category2id}/${category3id}`,
        method: 'get'
    })
}

组件传递参数

 //获取平台属性请求
    async getAttrlist(){
      const {category1id,category2id,category3id} = this
     let res =  await this.$API.attr.reqcategory3Listbuttom(category1id,category2id,category3id)
     if (res.code==200) {
      this.list = res.data
      console.log(this.list);
     }
    },

在组件3个id全部获取到的时候 执行这个函数

保存数据

初始化一个list数组

成功后赋值

使用数据

在attr组件内布局两个的div 加入v-show来进行动态切换

  <div v-show="isShow"> <el-card>
      <el-button icon="el-icon-plus" style="margin:20px 0" type="primary" @click="changeShow">添加属性</el-button>
      <el-table
    :data="list"
    stripe
    style="width: 100%"
    border
    >
    <el-table-column
      type="index"
      label="序号"
      width="80"
      align="center">
    </el-table-column>
    <el-table-column
      prop="attrName"
      label="属性名"
      width="180">
    </el-table-column>
    <el-table-column
      label="属性值列表"
      >
      <!-- //作用域插槽 -->
      <template slot-scope="{ row, $index }">
        <el-tag type="warning" v-for="item in row.attrValueList" :key="item.id" style="margin:0 20px">{{item.valueName}}</el-tag>
        </template>
    </el-table-column>
    <el-table-column
      label="操作"
      width="180"
      >
      <el-button type="warning" icon="el-icon-edit" @click="isShow=false"></el-button>
      <el-button type="info" icon="el-icon-delete"></el-button>
    </el-table-column>
  </el-table>
    </el-card></div>

静态组件显示

img

给添加按钮和修改按钮添加事件

img来进行两个div的切换显示

P17、平台属性和修改属性静态完成

切换的静态组件

<div v-show="!isShow">
      <el-card>
        <el-form ref="form">
      <el-form-item label="属性名">
       <el-input placeholder="请输入属性名" style="width:300px" ></el-input>
      </el-form-item>
    </el-form>
    <el-button type="primary" icon="el-icon-plus">添加属性值</el-button>
    <el-button @click="isShow=true">取消</el-button>
    <el-table
      style="width: 100%;margin:20px 0;" border>
      <el-table-column
        type="index"
        label="序号"
        width="80">
      </el-table-column>
      <el-table-column
        label="属性值名称"
       >
      </el-table-column>
      <el-table-column
      width="180"
      label="操作">
      </el-table-column>
    </el-table>
    <el-button type="primary">保存</el-button>
    <el-button @click="isShow=true">取消</el-button>
      </el-card>
    </div>

可以点击取消和添加来进行v-show的切换

P18、收集属性名的操作

写api

export const reqCategoryAttrName = (data) => {
    return request({
        url: '/admin/product/saveAttrInfo',
        method: "post",
        data
    })
}

初始化存储数据的格式

//收集添加属性的属性信息
      attrInfo: {
        attrName: "", // 属性名
        attrValueList: [
          //属性名中属性值,因为属性值可以是多个,因此需要的是数组
          {
            attrId: 0, //属性的id
            valueName: "", //属性值
          },
        ],
        categoryId: 0, //category3Id
        categoryLevel: 3,
      },
    };

收集属性名

form表单 model绑定attrInfo

inout输入框 v-model绑定attrInfo.attrName

表单输入的时候就可以收集到属性名的操作

img

P19、收集属性值操作

数据格式

{
  "attrName": "",      属性名
  "attrValueList": [   属性名中属性值,因为属性值可以是多个,因此需要的是数组
    {
      //"attrId": 0,          属性的id
      //"valueName": "string"  属性值
    }
  ],
  "categoryId": 0,    category3Id
  "categoryLevel":3,
}

一开始不能给attrId和valueName属性 因为会直接出现一个表单

在点击的时候进行push 点击一次来出现一次 valuename绑定输入框

点击添加属性值按钮 表格出现input表单

因为第一次没法获取到id 先传入undefined

img

作用域插槽 row

input表单v-model绑定的是attrInfo.attrName

img

属性名没有的情况 禁用添加按钮

img

P20、解决返回按钮回显问题

点击取消按钮 再次点击添加 还会显示上次的内容

解决:把数据置空 顺便获取到3id

img

P21、修改属性操作

对修改按钮添加点击事件

img

并且传递参数row

img

P22、查看模式和编辑模式的切换

添加按钮和修改按钮添加事件

img

里面添加一个自定义字段来控制 每一列的span和input的切换

这里 的flag字段是响应式的

因为数据已经初始化在data里面了 push方法也是响应式的img

keyup 不是原生事件 需要加入.native修饰符

span转化成 块级元素 增加点击范围

点击span 切换成input input失去焦点获取按下回车 切换成span

P23、查看和编辑注意事项

img

防止用户输入空格

img

防止和之前的属性重复

img

row是最后一次输入的valueName

item是列表已经存在的valueName

P24、修改属性中的查看与编辑模式

修改属性获取到的row是没有flag字段的 添加的时候才会把flag字段添加到attrinfo对象里面

添加响应式数据

$set(对象,要添加的响应式属性名,属性值)

img

P25、表单元素自动聚焦的实现

点击span 获取input节点 让他聚焦

span添加点击事件

img

表单ref很多 使用$index来识别

img

点击事件的回调

img

使用对象[‘属性名’]方法来进行枚举

点击添加让最后一项自动聚焦

添加属性值的回调添加

img

在数组的最后一项来进行聚焦

P26、删除属性值的操作

点击删除按钮弹出pop提示框静态

<template>
<el-popconfirm
  title="这是一段内容确定删除吗?"
>
  <el-button slot="reference">删除</el-button>
</el-popconfirm>
</template>

img

动态展示气泡弹出框显示的文字内容

img

点击取消气泡消失 点击确定删除操作

确定按钮的回调 文档中写confrim事件 但是版本问题 以前版本是onConfrim事件

img

img

数组中删除自身

P27、保存操作(暂未实现)

发请求 接口已经写好了

img

点击保存的时候 把参数整理之后向服务器发请求

img

P28、按钮与三级菜单的disabled

当切换为添加或者修改属性名的时候 让三级菜单禁用

使用isShow数据 和平台属性的切换一样 但是需要父传子

传:img

接:img

img

如果没有属性名的情况下 不能点击保存按钮

img

P29、SPU管理模块介绍

spu是类似于类的东西

sku是类似实例的东西

P30、完成SPU静态模块

三级菜单

使用全局组件menu 子组件的自定义事件是传入三级菜单的id

父组件进行接收和判断

img

img

img

下面的初始表单

<el-card>
      <el-button type="primary" icon="el-icon-plus" style="margin:20px 0">添加SPU</el-button>
      <el-table
      border
      style="width: 100%">
      <el-table-column
        type="index"
        label="序号"
        width="180">
      </el-table-column>
      <el-table-column
        prop="name"
        label="SPU名称"
        width="180">
      </el-table-column>
      <el-table-column
        prop="address"
        label="SPU描述">
      </el-table-column>
      <el-table-column
        label="操作">
        <template  slot-scope="{row,$index}">
        <el-button icon="el-icon-plus" type="success" size="mini"></el-button>
        <el-button icon="el-icon-edit" type="warning" size="mini"></el-button>
        <el-button icon="el-icon-info" type="info" size="mini"></el-button>
        <el-button icon="el-icon-delete" type="danger"  size="mini"></el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- @size-change="handleSizeChange"
      @current-change="handleCurrentChange" -->
    <el-pagination
    style="text-align:center"
      :current-page="1"
      :page-sizes="[3,5,10]"
      :page-size="100"
      layout="prev, pager, next, jumper,->,sizes,total"
      :total="400">
    </el-pagination>
    </el-card>

P31、动态展示SPU列表

api接口 page 当前第几页 limit每页展示数据 category3id

img

在3id获取完毕之后进行发请求的操作

初始化数据来进行接收

img

发请求 来进行 赋值操作

img

table 的data属性来绑定records数组 每一列来绑定records的属性名 注意次数不需要加入records. porp直接进行绑定显示

img

封装显示title的按钮

写一个公共组件 注册为全局组件 在el-button替换使用 标签加入title属性

img

img

就可以显示有title的按钮了

el-button 全部换成hint-button 加入title字段

img

分页器处理

数据绑定 回调绑定

img

第一个事件是点击数字按钮的回调 第一个参数是当前点击的页码

可以获取spu列表的回调写在一起 传入默认参数1 然后修改page参数

第二个事件是修改每页展示的数据的回调 第一个参数是修改之后每页展示的数据

img

P32、spu管理内容的切换

左上添加按钮和修改按钮进入的是同一个页面内容

添加按钮

查看按钮

三个画面不能简单的使用布尔值来控制

初始化一个响应式属性

img

放置3个div来v-show

img

因为组件复杂 把组件抽取为子组件来显示

img

img

img

P33、spuForm静态组件完成

img

两个按钮添加点击事件

img

img

没有三级分类的数据 添加按钮不能使用

img

点击两个按钮的时候 让控制的变量变为1

在这里插入图片描述

<template>
  <el-form ref="form" label-width="80px">
  <el-form-item label="SPU名称">
    <el-input placeholder="SPU名称"></el-input>
  </el-form-item>
  <el-form-item label="品牌">
    <el-select  placeholder="请选择品牌"  value="">
      <el-option label="区域一" value=""></el-option>
    </el-select>
  </el-form-item>
  <el-form-item label="SPU描述">
    <el-input type="textarea" placeholder="SPU描述" rows="4"></el-input>
  </el-form-item>
  <el-form-item label="SPU图片">
    <el-upload
        action="https://jsonplaceholder.typicode.com/posts/"
        list-type="picture-card"
        :on-preview="handlePictureCardPreview"
        :on-remove="handleRemove">
        <i class="el-icon-plus"></i>
      </el-upload>
      <el-dialog :visible.sync="dialogVisible">
        <img width="100%" :src="dialogImageUrl" alt="">
      </el-dialog>
  </el-form-item>
  <el-form-item label="销售属性">
    <el-select  placeholder="还有3项未选择"  value="">
      <el-option label="区域一" value=""></el-option>
    </el-select>
    <el-button icon="el-icon-plus" type="primary">添加销售属性</el-button>
    <el-table
      style="width: 100%" border>
      <el-table-column
        type="index"
        label="序号"
        width="80"
        align="center">
      </el-table-column>
      <el-table-column
        prop="name"
        label="属性名"
        width="180">
      </el-table-column>
      <el-table-column
        prop="address"
        label="属性名称列表">
      </el-table-column>
      <el-table-column
        prop="address"
        label="操作">
      </el-table-column>
    </el-table>
  </el-form-item>
  <el-form-item>
    <el-button type="primary">保存</el-button>
    <el-button>取消</el-button>
  </el-form-item>
</el-form>
</template>
 data() {
      return {
        dialogImageUrl: '',
        dialogVisible: false
      };
    },
    methods: {
      handleRemove(file, fileList) {
        console.log(file, fileList);
      },
      handlePictureCardPreview(file) {
        this.dialogImageUrl = file.url;
        this.dialogVisible = true;
      }
    }

P34、Spuform请求业务分析

接口

点击取消的时候切换场景

因为组件是子组件,需要自定义事件传入scene来通知父组件来进行场景切换

在这里插入图片描述
在这里插入图片描述

img

子组件发请求,但是父组件在点击修改和添加、取消的时候都会发请求

不能写在子组件的mounted生命周期里面

解决:把请求写在子组件的methods里面

在这里插入图片描述

​ 然后在父组件内的子组件标签加入ref

img

​ 父组件写入方法 this.$ref.spu.方法

img

点击修改的时候就可以发一次请求

P35、获取spuform数据

点击修改的时候子组件发四个请求

父组件调用子组件方法的时候传参 子组件来进行接收参数

父:

在这里插入图片描述

子:

img

发第一次请求 获取spu信息数据 传入

img

在这里插入图片描述

使用data里面的spu 来存储数据

img

在这里插入图片描述

获取品牌数据

img

img

总体请求和存储数据

img

img

P36、SpuForm组件数据展示与与手机数据

初始化数据来作为表单存储数据的对象

img

改写一下name和url属性

img

收集一下属性img

照片墙绑定的是遍历过后有name和url属性的数组

照片墙的 file-list是显示照片的数组

img

P37、spuForm销售属性的数据展示

实现表格的静态显示

img

table数据绑定在spu.spuSaleAttrList数组

第一列是序号

第二列是属性名 绑定的是spu.spuSaleAttrList.省略saleAttrName字段

第三列是tab组件 作用域插槽来传row row就是spu.spuSaleAttrList数组

row.spuSaleAttrValueList就是商品属性值列表

遍历的数组:

img

下面的button和input就是之前做的span和input切换 只不过现在控制的自定义属性还没有 先做静态

整个销售属性只有三个 颜色 尺码 版本

如果数组携带了三者之一或者三者之二 其余两个或者一个在上面的下拉框内显示

全部的销售属性已经获取到了

img

当前的销售属性也有 spu.spuSaleAttrList

来进行过滤

img

filter 返回布尔值 真就加入到新数组 假的话不加入新数组 item是数组的每一项

every 返回布尔值 真,假 item是数组的每一项

此时return出来的就是过滤出来的没有选择的属性值的数组

展示在下拉框内

img

img

并且把下拉框内的数据进行收集 v-model 收集的是option的value值

旁边的button禁用按钮

P38、照片墙数据的收集

照片墙何时收集数据

删除的时候要收集

照片墙参数的意义

img

action:图片上传的地址 需要加入/dev/api/ 不然出现跨域问题

list-type:内置属性 类型为照片墙

file-list:展示图片的数据来源 数组类型

on-preview:预览的回调

on-remove:删除的回调

img

回调参数的意义 看上图

目前先把数据收集到之前初始的imgList字段里面

img

PS :服务器返回的数据我们给添加上了name和url字段

​ 为了在照片墙上显示图片 但是给服务器提交的时候不需要这个字段 后续会处理

img

删除时候数据收集完成

添加图片的时候也要收集数据

上传成功的回调img

img

参数解释:response:返回的上传状态的信息

​ file:返回的当前上传图片的信息

​ fileList:上传完毕之后全部的数组信息

img

照片数据收集完毕

注意这里全部有name和url属性 没有这些属性无法回显

但是给服务器传递参数的时候不能带name和url这两个属性

P39、销售属性添加的事件

销售属性要收集的内容

img

baseSaleAttrId

saleAttrName

spuSaleAttrValueList 数组类型 这些是需要收集的数据

什么时候收集?

选择下拉框的时候

如何收集呢 value绑定的数据来进行收集

value绑定的数据再添加一条

img

这时就可以收集到baseSaleAttrId:saleAttrName了

img

收集到哪里?

收集到spu.spuSaleAttrList数组里面

因为下面数据的展示需要这些数据

img
img

因为数组里面是对象 所以传入的类型要为对象

img

P40、销售属性值的收集和展示

和之前做的span/input切换类似

选择添加之后 在下拉框内把改属性清除

img

img

在点击之前的span标签的时候添加控制input显示的属性inputVisible

以及收集数据的地方 inputValue 注意这里不能直接赋值 直接赋值的数据不是响应式的 需要属于$set

给按钮添加点击事件

img

img

img

添加了控制切换的属性 数据也收集到了

此时就可以实现按钮和input的切换了

input失焦实现input和按钮切换标签显示inputValue值

表单失焦事件

img

img

P41、删除销售属性和属性值的操作

删除属性值

img

v-for的时候传入index 让属性值的数组删除自身

删除销售属性

使用作用域插槽 传入$index $index表示的是 表格的销售属性列表的索引 img

三级联动的可操作性

img

给子组件传值来控制

P42、完成修改spu的保存操作

此时数据全部获取到了 只有照片墙的数据收集到的不再spu.spuImageList数组里面 而是在自定义响应式数据spuImageList字段里面

处理一下参数 返回的数据有imgName和imgUrl字段 是需要发送给服务器的 但是新增的没有imgName和imgUrl字段 只有name和url字段 处理一下参数

写接口

根据有没有id来选择是修改还是添加img

保存按钮的点击事件

img

整理参数

img
系统数据不能修改 res返回成功之后 让页面显示变量为0的页面

但是保存之后数据不更新 提示父组件再次获取数据来进行展示

img

传入参数 停留到当前页

img

P43、完成添加spu按钮的操作

在保存完毕之后需要把数据清除

img

使用

//清空数据

    //_data:全部的响应式数据

img

//$options是配置对象

img

 //$options.data()执行响应式数据data函数  执行结果 获取到的是空的   返回的是起始状态

把空对象辅助给响应式数据 实现数据的清除

    Object.assign(this._data,this.$options.data())

点击添加的时候需要发两个请求

img

获取品牌列表的数据和销售属性的数据

父组件直接调用子组件的方法


img

这时候点击添加的时候只有两个下拉框有数据

添加和修改的参数不同是判断你有没有id 这里的id使用的是category3id的值 这个值在添加的时候传入子组件

img

现在书籍全部可以收集到了 但是如果是修改按钮 显示当前页 如果是添加按键 显示在第一页 这里需要再次传入数据

img

  不止传入scene   还传入flag   有id是修改  没有id是添加

父组件来获取到flag数据判断保存完之后停留在第几页 不写参数默认第一页

img

子组件的取消按钮需要改写形式 不能只传入0

img

不然会出现点击取消参数错误 不能正确切换的业务

取消按钮的业务逻辑抽取为一个函数

img

P44、删除spu的操作

点击删除 添加pop 删除整行
接口
img

给delete按钮添加事件 传入row

img

把点击按钮的事件传递到pop确定的时候才做

img
img

传参数 发请求
img

确定最后传入的page参数

P45、完成SKU静态组件

给添加点击事件 切换场景为2

img
sku静态组件

<template>
  <div>
    <el-form ref="form" label-width="80px">
      <el-form-item label="SPU名称"> 海绵宝宝 </el-form-item>
      <el-form-item label="SKU名称">
        <el-input placeholder="SKU名称"></el-input>
      </el-form-item>
      <el-form-item label="价格(元)">
        <el-input placeholder="价格(元)"></el-input>
      </el-form-item>
      <el-form-item label="重量(千克)">
        <el-input placeholder="重量(千克)"></el-input>
      </el-form-item>
      <el-form-item label="规格描述">
        <el-input type="textarea" placeholder="规格描述" rows="4"></el-input>
      </el-form-item>
      <el-form-item label="平台属性">
        <el-form :inline="true" label-width="80px">
          <el-form-item label="屏幕属性">
            <el-select placeholder="请选择" value="">
              <el-option label="区域一" value="shanghai"></el-option>
              <el-option label="区域二" value="beijing"></el-option>
            </el-select>
          </el-form-item>
        </el-form>
      </el-form-item>
      <el-form-item label="销售属性">
        <el-form :inline="true" label-width="80px">
          <el-form-item label="颜色">
            <el-select placeholder="请选择" value="">
              <el-option label="区域一" value="shanghai"></el-option>
              <el-option label="区域二" value="beijing"></el-option>
            </el-select>
          </el-form-item>
        </el-form>
      </el-form-item>
      <el-form-item label="图片列表">
        <el-table border style="width: 100%">
          <el-table-column
            type="selection"
            prop="date"
            label="日期"
            width="80"
            align="center"
          >
          </el-table-column>
          <el-table-column prop="name" label="图片" width="180">
          </el-table-column>
          <el-table-column prop="address" label="名称"> </el-table-column>
          <el-table-column prop="address" label="操作">
            <el-button type="primary">设为默认</el-button>
          </el-table-column>
        </el-table>
      </el-form-item>

      <el-form-item>
        <el-button type="primary">保存</el-button>
        <el-button>取消</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

P46、获取SKUform数据

在点击按钮跳转页面内的时候需要发三个请求 获取数据

分别是获取图片的数据

获取销售属性的数据

获取平台属性的数据来进行展示、

给子组件写入ref 直接点击按钮的时候调用子组件的方法即可

写接口

img

需要4个参数 分别是id category1id category2id category3id

这些参数父组件都有的 调用子组件方法的时候直接传过去

数据来源:menus组件 mounted的时候获取一级菜单的数据 三级菜单选择的时候收集到的是选择的id 这个就是category1id 根据category1id来获取 二级菜单的数据 二级菜单选择的时候收集了category2id,根据category2id收集到三级菜单的数据 三级菜单选择收集category3id 并且在获取菜单的时候 把数据通过自定义事件传给父组件使用 父组件通过category3id来控制分页器以及把数据给spuform组件使用

img

父组件调用子组件的方法 传四个参数

img

子组件接收四个参数 为发请求做准备

img

发请求 存储数据

img

数据全部获取到

img

P47、展示SKU和收集SKU的数据

保存的接口需要的参数

 //收集sku数据的字段
      skuInfo: {
        //第一类收集的数据:父组件给的数据
        category3Id: 0,
        spuId: 0,
        tmId: 0,
        //第二类:需要通过数据双向绑定v-model收集
        skuName: "",
        price: 0,
        weight: "",
        skuDesc: "",
        //第三类:需要自己书写代码
        //默认图片
        skuDefaultImg: "",
        //收集图片的字段
        skuImageList: [
          // {
          //   id: 0,
          //   imgName: "string",
          //   imgUrl: "string",
          //   isDefault: "string",
          //   skuId: 0,
          //   spuImgId: 0,
          // },
        ],
        //平台属性
        skuAttrValueList: [
          // {
          //   attrId: 0,
          //   valueId: 0,
          // },
        ],
        //销售属性
        skuSaleAttrValueList: [
          // {
          //   id: 0,
          //   saleAttrId: 0,
          //   saleAttrName: "string",
          //   saleAttrValueId: 0,
          //   saleAttrValueName: "string",
          //   skuId: 0,
          //   spuId: 0,
          // },
        ],
      },

整理父亲给的参数 直接把row拿过来进行拷贝

img

img

使用数据:

1.收集简单的表单数据 v-model

这样的输入框需要加入type=number

img
img
2.复杂数据收集

数据从服务器返回了 需要渲染之后进行收集

2.1遍历平台属性

2.2平台属性和属性值收集

收集的字段只有属性的id和属性值的id 暂时使用末班字符串收集到属性值的对象里面 后续进行处理

需要收集的数据

收集的方式

通过options的value值收集属性的idattr.id和属性值的id option.id

收集到v-model的attr的一个没有定义的属性上面 后续进行处理
img
img
此时两个id都收集到了

进行销售属性的展示与收集

销售属性和上面类似 select的v-model收集options的value值

value值收集两个id v-model绑定一个skuattrList的每一项的自定义属性上面

也是收集两个id

img

img

P48、添加SKU图片列表展示和数据收集

静态展示图片

作用域插槽 data绑定数据

img

数据展示完毕 开始收集数据

收集复选框选中的图片的信息

element-ui table有内置事件 是选择复选框的回调 返回的是已经选中的内容的数组

@selection-change=“handleSelectionChange” 选中事件 有一个参数 这个参数就是选中内容

img

但是目前收集到的数据有问题 缺少内容 缺少isDefault字段

但是目前先保存一下

img
img

在图片数据回来的时候先给他加上字段 默认为0

img

点击默认按钮的时候进行排他

进行默认和设为 默认的v-if事件

img
img

最后把默认图片数据收集一下 收集到skuDefaultImg的字段

img

现在的图片字段也都完整了

P49、完成添加sku保存的业务

1.写接口

img

取消按钮的回调

变量变为0 通知父亲切换场景

父组件绑定自定义事件

清除数据

img

父组件接收

img
img

2.整理参数

整理平台属性参数

保存按钮的回调

img

再加入销售属性的值的id的抽取

img

优化写法:

  const {attrInfoList,skuInfo,spuSaleAttrList,imageList} = this;
      //整理平台属的数据
     skuInfo.skuAttrValueList = attrInfoList.reduce((prev,item)=>{
         if(item.attrIdAndValueId){
           const [attrId,valueId]  = item.attrIdAndValueId.split(":");
            prev.push({attrId,valueId});
         }
         return prev;
      },[]);
      //整理销售属性
     skuInfo.skuSaleAttrValueList = spuSaleAttrList.reduce((prev,item)=>{
         if(item.attrIdAndValueId){
           const [saleAttrId,saleAttrValueId] = item.attrIdAndValueId.split(':');
           prev.push({saleAttrId,saleAttrValueId});
         }
         return prev;
      },[]);

暂时不解决

3.发请求

这里对数据进行map遍历   把有用的参数进行赋值操作   最后返回一个新的数组

切换场景 显示message

P50、SKU列表的展示

点击table这个按钮的时候 会有table来展示之前添加的sku的列表

写接口

img

点击事件
img

准备初始值
img
点击按钮 出现表格

发请求

img
img

使用spu的数据来展示对话框的titleimg

img
再次准备初始化的值来存储请求接受过来的sku的值
img
请求成功 存储数据 来进行表格的展示
img
table的展示

img

P51、loading效果

给table 添加v-loding指令 值为loading 这个值什么都可以只要是布尔值就行

img

初始化loading值 为true
img

i获取到数据的时候loading消失
img
出现问题 loading效果是一次性的 而且在点击下一次的时候 数据没有回来的时候会回显上一次的表单

如何解决?

关闭对话框的时候实现数据的清除 把loading值变为true

:before-close 属性 为一个函数

img
相应回调

img

P52、sku模块分析和分页功能

完成sku静态

<template>
  <div>
    <el-table style="width: 100%" border>
      <el-table-column
        type="index"
        label="序号"
        align="center"
        width="80">
      </el-table-column>
      <el-table-column
        prop="name"
        label="名称"
        width="180">
      </el-table-column>
      <el-table-column
        prop="address"
        label="描述">
      </el-table-column>
      <el-table-column
        label="默认图片"
        width="80">
        <template slot-scope="{row,$idnex}">
          <img src="" alt="">
        </template>
      </el-table-column>
      <el-table-column
        prop="name"
        label="重量(KG)"
        width="180">
      </el-table-column>
      <el-table-column
        prop="address"
        label="价格(元)"
        width="80">
      </el-table-column>
      <el-table-column
        prop="address"
        label="操作">
        <template slot-scope="{row,$index}">
          <el-button icon="el-icon-download" type="success"></el-button>
          <el-button icon="el-icon-edit" type="primary"></el-button>
          <el-button icon="el-icon-info" type="info"></el-button>
          <el-button icon="el-icon-delete" type="danger"></el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- @size-change="handleSizeChange"
      @current-change="handleCurrentChange" -->
    <el-pagination
      style="text-align: center;margin-top: 20px 0;"
      :current-page="1"
      :page-sizes="[3, 5, 10]"
      :page-size="5"
      layout=" prev, pager, next, jumper,->,sizes,total"
      :total="30">
    </el-pagination>
  </div>
</template>

获取数据

写接口

img

初始化数据来保存数据

img

mounted执行methods的函数

img

渲染table

img

img

img
img

img img
img
img

分页器的回调:

img
img

P53、SKU上架下架功能

records数组里面哪有一个字段 isSale控制上架和下架功能 1为上架 0为下架

控制两个按钮的显示和隐藏

img

上架下架功能 分别给上架按钮和下架按钮添加事件 发请求

img

img

点击第二个按钮的时候弹出灰色的正在开发中的按钮

img

P54、SKU查看详情业务

从右往左弹出抽屉的效果

发请求 得到数据 抽屉展示

初始化数据 根据数据类型

img

按钮添加事件

img

初始化数据赋值

img

数据格式

img

使用抽屉

布局:

24个为一栏 可以找到类名修改每个内容的样式

轮播图

<el-drawer :visible.sync="drawer" size="50%" :show-close='false'>
    <!-- 使用栅格系统的布局 -->
      <el-row>
      <el-col :span="6">名称</el-col>
      <el-col :span="18">{{skuInfo.skuName}}</el-col>
      </el-row>
      <el-row>
      <el-col :span="6">描述</el-col>
      <el-col :span="18">{{skuInfo.skuDesc}}</el-col>
      </el-row>
      <el-row>
      <el-col :span="6">价格</el-col>
      <el-col :span="18">{{skuInfo.price}}</el-col>
      </el-row>
      <el-row>
      <el-col :span="6">平台属性</el-col>
      <el-col :span="18">
        <el-tag type="success" v-for="item in skuInfo.skuAttrValueList" style="margin-right:10px" :key="item.id">{{item.attrId}}--{{item.valueId}}</el-tag>
      </el-col>
      </el-row>
      <el-row>
      <el-col :span="6">商品图片</el-col>
      <el-col :span="18">
        <el-carousel height="300px" style="width:300px;margin: 0 auto;" >
          <el-carousel-item v-for="item in skuInfo.skuImageList" :key="item.id">
           <img :src="item.imgUrl" alt="" style="width:300px;height:300px">
          </el-carousel-item>
          </el-carousel>
      </el-col>
      </el-row>

  </el-drawer>

尝试修改轮播图小点点的样式

img

在style样式为scpped内书写不生效 没有这个属性的会生效

P55、深度选择器

scoped 什么用

总体来说就是当前的样式只在当前组件内生效

但是加入scoped也是可以影响到子组件的样式的 只有一种情况 就是style里面写的样式 刚好是子组件的最外层标签 name会影响到子组件的样式

scoped的原理是给当前子组件全部加入自定义属性 加入scoped之后就会加入自定义属性data-v-xxxx 只要组件加入scoped之后 就会有自己独特的自定义属性 并且当前组件的全部子组件全部添加这个自定义属性 会在当前页面影响子组件 但是如果子组件加入了scoped 也有自己的自定义属性 name就不会影响到了 子组件内部的组件只会有子组件的自定义属性 并没有父组件的自定义属性 所以不生效

img

而css写的是属性选择器

标签【自定义属性】

img

如果我加入scoped 还想进行对子组价内的控制

使用深度选择器

原生css >>>

less /deep/

scss ::

img加在标签前面 这样组件内的所有H3标签都会生效,不管是不是加入了scoped

P56、数据可视化简介

完成首页

庞大数据通过图形图标来展示 方便观看

excel xmind等等

基础 canvas svg webgl html

本项目使用echarts

P57、canvas绘制线段

H5新增标签canvas

 <canvas width="500" height="300"></canvas>
    <script>
        let canvas = document.querySelector('canvas')
            //调用getContext方法 传入2d  获取毛笔
        let ctx = canvas.getContext('2d')
            //moveTo  起点
        ctx.moveTo(100, 100)
            //lineTo其他点设置  可以设置多个
        ctx.lineTo(100, 200)
        ctx.lineTo(200, 100)
            //fillStyle 设置图形填充颜色
        ctx.fillStyle = 'red'
            //fill  执行fill  填充颜色才会生效
        ctx.fill()
            //strokeStyle 设置线段的颜色
        ctx.strokeStyle = 'purple'
            //lineWidth 设置线段的宽度
        ctx.lineWidth = '20'
            //closePath 设置起点和终点连接在一起
        ctx.closePath()
            //stroke 执行绘图方法
        ctx.stroke()
    </script>

canvas画布是HTML5新增的特性 双闭合标签

canvas 的默认宽高为300*150

浏览器解析canvas为默认是一张图片 可以另存为

给canvas添加子节点没有意义

给canvas添加子文字没有意义

想操作canvas显示图形和文字 都需要使用js来完成

canvas的宽高使用属性的width和height属性来添加 不能使用style样式去改变宽高 坐标会出问题的

别的没有问题

P58、canvas绘制矩形

<canvas width="500" height="500"></canvas>
    <script>
        let canvas = document.querySelector('canvas')
        let ctx = canvas.getContext('2d')
            //1.绘制矩形  参数为x  y  w  h  这个方法没有办法填充颜色
        ctx.strokeRect(100, 200, 100, 200)
            //填充颜色
        ctx.fillStyle = 'skyblue'
            //填充
        ctx.fill()
            //2.填充矩形  参数为x  y  w  h  这个方法可以在填充矩形之前设置填充颜色
        ctx.fillRect(300, 200, 100, 200)
    </script>

P59、canvas绘制圆形

前置条件

度和弧度的转换

1度=π/180≈0.01745弧度,1弧度=180/π≈57.3度。

ctx.beginPath() 开始

​ ctx.arc(100, 100, 50, 0, 0.1, true) 配置

​ ctx.stroke() 结束

    <canvas width="500" height="500"></canvas>
</body>
<script>
    let canvas = document.querySelector('canvas')
    let ctx = canvas.getContext('2d')
        //开始绘制圆形提示
    ctx.beginPath()
        //圆形参数   x位置 y位置 r半径 开始的弧度 结束的弧度  是否逆时针绘制
        //弧度   2*PI*ROW = 360°   1row = 180°/PI
    ctx.arc(100, 100, 50, 0, 2 * Math.PI, true)
        //开始绘制
    ctx.stroke()
    ctx.beginPath()
    ctx.arc(100, 100, 50, 0, 0.1, true)
    ctx.stroke()
</script>

这些图形都可以添加填充颜色和线段颜色

P60、canvas清除画布和绘制文字

 <canvas width="500" height="500"></canvas>
    <script>
        let canvas = document.querySelector('canvas')
        let ctx = canvas.getContext('2d')
            //填充矩形
        ctx.fillRect(100, 200, 100, 200)
            //清除部分画布   和矩形的参数一样  清除的区域也是矩形
        ctx.clearRect(0, 0, 50, 100)
            //清除全部画布
            //ctx.clearRect(0, 0, 500, 500)
            //设置文字大小
        ctx.font = "20px 微软雅黑"
            //设置文字颜色
        ctx.fillStyle = 'red'
            //绘制文字   文字内容  x y
        ctx.fillText('数据可视化', 50, 20)
    </script>

P61、绘制柱状图

img

后续补 计算太麻烦

P62、SVG的基本使用

SVG是一张局域XML的图像文件格式 可以缩放的矢量图

矢量图:放大不失真的图 会对IE有兼容问题

线段

<svg width="500" height="500">
        <!-- x1 属性在 x 轴定义线条的开始
        y1 属性在 y 轴定义线条的开始
        x2 属性在 x 轴定义线条的结束
        y2 属性在 y 轴定义线条的结束 -->
      <line x1="0" y1="0" x2="300" y2="300" style="stroke:rgb(99,99,99);stroke-width:2"/>
  </svg>

折线

<svg width="500" height="500">
    <polyline points="0,0 0,20 20,20 20,40 40,40 40,60"
    style="fill:white;stroke:red;stroke-width:2"/>
    </svg>

矩形

  <svg width="500" height="500">
        <!-- rect 元素的 width 和 height 属性可定义矩形的高度和宽度
            style 属性用来定义 CSS 属性
            CSS 的 fill 属性定义矩形的填充颜色(rgb 值、颜色名或者十六进制值)
            CSS 的 stroke-width 属性定义矩形边框的宽度
            CSS 的 stroke 属性定义矩形边框的颜色 -->
    <rect width="300" height="100"style="fill:rgb(0,0,255);stroke-width:1;stroke:rgb(0,0,0)"/>
    </svg>

<svg width="500" height="500">
        <!-- cx 和 cy 属性定义圆点的 x 和 y 坐标。如果省略 cx 和 cy,圆的中心会被设置为 (0, 0)
            r 属性定义圆的半径。 fill:边框颜色 -->
    <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>
    </svg>

椭圆

<svg width="500" height="500">
        <!-- cx 属性定义圆点的 x 坐标       椭圆
             cy 属性定义圆点的 y 坐标
             rx 属性定义水平半径
             ry 属性定义垂直半径 -->
        <ellipse cx="300" cy="150" rx="200" ry="80"
        style="fill:rgb(200,100,50);
        stroke:rgb(0,0,100);stroke-width:2"/>
    </svg>

P63、echarts基本使用

PC 移动端都可以用

做一个柱状图

1.引包

2.准备有宽高的容器

  1. echarts.init 方法初始化一个 echarts 实例

4.传入setOption 配置对象

 <!-- 1.引包 -->
    <script src="./echarts.min.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        
        div {
            width: 800px;
            height: 500px;
        }
    </style>
</head>

<body>
    <!-- 2.准备有宽高的容器 -->
    <div></div>
    <!-- 3.创建echarts实例 -->
    <script>
        let div = document.querySelector('div')
        let myChart = echarts.init(div)
            //4.使用setOption方法传入配置对象
        const option = {
            //标题数据
            title: {
                text: 'ECharts 入门示例'
            },
            //x轴
            xAxis: {
                data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
            },
            //y轴
            yAxis: {
                show: true
            },
          	//图标类型
            series: [{
                name: '销量',
                type: 'bar',
                data: [5, 20, 36, 10, 10, 20]
            }]
        }
        myChart.setOption(option);
    </script>

P64、多个容器展示多个图表

以两个为例

1.引包

2.创建两个宽高容器

3.创建两个echarts实例

4.传入两个配置对象 各传各的 就相当于搞了两个图标而已

    <script src="./echarts.min.js"></script>
    <style>
        .box1 {
            width: 500px;
            height: 500px;
            border: 1px solid black;
        }
        
        .box2 {
            width: 500px;
            height: 500px;
            border: 1px solid black;
        }
    </style>
</head>

<body>
    <div class="box1"></div>
    <div class="box2"></div>
    <script>
        let dom1 = document.querySelector('.box1')
        let dom2 = document.querySelector('.box2')
        let Mychart1 = echarts.init(dom1)
        let Mychart2 = echarts.init(dom2)
        const option1 = {
            title: {
                text: 'ECharts 入门示例'
            },
            tooltip: {},
            legend: {
                data: ['销量']
            },
            xAxis: {
                data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
            },
            yAxis: {},
            series: [{
                name: '销量',
                type: 'bar',
                data: [5, 20, 36, 10, 10, 20]
            }]
        }
        const option2 = {
            title: {
                text: 'ECharts 入门示例'
            },
            tooltip: {},
            legend: {
                data: ['销量']
            },
            xAxis: {
                data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
            },
            yAxis: {
                show: true
            },
            series: [{
                name: '销量',
                type: 'pie',
                data: [{
                    value: 335,
                    name: '直接访问'
                }, {
                    value: 234,
                    name: '联盟广告'
                }, {
                    value: 1548,
                    name: '搜索引擎'
                }],
                //饼图半径
                radius: '50%'

            }]
        }
        Mychart1.setOption(option1)
        Mychart2.setOption(option2)
    </script>

P65、一个容器显示多个图表

主要是配置对象的series字段

//图标类型
            series: [{
                name: '销量',
                type: 'bar',
                data: [5, 20, 36, 10, 10, 20]
            },{
                name: '销量',
                type: 'line',
                data: [5, 20, 36, 10, 10, 20]
            },{
                name: '销量',
                type: 'pie',
                data: [5, 20, 36, 10, 10, 20]
            }]
        }
    <style>
        .box1 {
            width: 500px;
            height: 800px;
            border: 1px solid black;
        }
    </style>
</head>

<body>
    <div class="box1"></div>
    <div class="box2"></div>
    <script>
        let dom1 = document.querySelector('.box1')
        let Mychart1 = echarts.init(dom1)
        const option1 = {
            title: {
                text: 'ECharts 入门示例'
            },
            tooltip: {},
            legend: {
                data: ['销量']
            },
            xAxis: {
                data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
            },
            yAxis: {},
            series: [{
                name: '销量',
                type: 'bar',
                data: [5, 20, 36, 10, 10, 20]
            }, {
                name: '销量',
                type: 'pie',
                data: [{
                    value: 335,
                    name: '直接访问'
                }, {
                    value: 234,
                    name: '联盟广告'
                }, {
                    value: 1548,
                    name: '搜索引擎'
                }],
                //饼图半径
                radius: '50%',
                //位置

                left: 10,
                top: 20

            }]
        }

        Mychart1.setOption(option1)
    </script>

如果里面有多个对象 多个type 就会在一个容器内显示多个图表

在series对象内各自设置各自的位置什么的

如果数饼状图 需要的数据可能是两个{name:11,value:值的显示}

查看文档

P66、echarts中数据集dataSet的使用

定义一个二维数组 来决定图表的数据 data【【】】

所有的series配置对象的data全部去掉 只需要设置一个二维数组 给实例添加配置对象为dataset:data

每个单独的配置需要加入source字段 设置显示的数组的索引位置

 <script src="./echarts.min.js"></script>
    <style>
        .box1 {
            width: 500px;
            height: 800px;
            border: 1px solid black;
        }
    </style>
</head>

<body>
    <div class="box1"></div>
    <div class="box2"></div>
    <script>
        let dom1 = document.querySelector('.box1')
        let Mychart1 = echarts.init(dom1)
        let data = [
            ['衬衫', 5, '直接访问', 335, 120],
            ['羊毛衫', 15, '联盟广告', 235, 20],
            ['雪纺衫', 5, '搜索引擎', 135, 150],
            ['裤子', 25, '联盟广告', 435, 190],
            ['袜子', 15, '直接访问', 435, 190]
        ]
        const option1 = {
            //数据集
            dataset: data,
            title: {
                text: 'ECharts 入门示例'
            },
            xAxis: {
                data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
            },
            yAxis: {},
            series: [{
                name: '销量',
                type: 'bar',
                encode: {
                    //x: [3, 1, 5], // 表示维度 3、1、5 映射到 x 轴。
                    // x: 0,
                    y: 1, // 表示维度 2 映射到 y 轴。
                }
            }, {
                name: '销量',
                type: 'pie',
                encode: {
                    //饼图的维度  itemName显示的文字 value显示文字的值
                    itemName: 2,
                    value: 3
                },
                //饼图半径
                radius: '50%',
                //饼图的宽高
                width: 150,
                height: 150,
                //位置
                left: 10,
                top: 20

            }, {
                type: 'line',
                encode: {
                    y: 4, // 表示维度 3 映射到 y 轴。
                }

            }]
        }

        Mychart1.setOption(option1)

P67、echarts内置组件的使用

下图圈住的全部都是组件 其中x–y轴也是组件img

都可以进行相应的配置

    <script src="./echarts.min.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        
        .box {
            width: 800px;
            height: 400px;
        }
    </style>
</head>

<body>
    <div class="box"></div>
    <script>
        let dom = document.querySelector('.box')
        let mycharts = echarts.init(dom)
        mycharts.setOption({
                //x轴
                xAxis: {
                    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
                },
                //y轴
                yAxis: {},
                //图形配置
                series: [{
                    //柱状图
                    //name属性配合legend使用
                    name: '柱状图',
                    type: 'bar',
                    data: [23, 24, 18, 25, 27, 28, 25]
                }, {
                    //柱状图
                    name: '折线图',
                    type: 'line',
                    data: [23, 24, 18, 25, 27, 28, 25]
                }, ],
                //tooltip提示组件
                tooltip: {
                    show: true,
                    textStyle: {
                        //提示框文字的颜色
                        color: 'red'
                    }
                },
                //legend系列显示组件
                legend: {
                    data: ['柱状图', '折线图']
                },
                //toolbox  工具栏展示组件
                toolbox: {
                    show: true,
                    //这些位置可以随意变化  展示IDE位置也会不同
                    feature: {
                        //缩放   
                        dataZoom: {
                            yAxisIndex: "none"
                        },
                        //还原
                        dataView: {
                            readOnly: false
                        },
                        //文字展示类型
                        magicType: {
                            type: ["line", "bar"]
                        },
                        //刷新
                        restore: {},
                        //下载
                        saveAsImage: {}
                    }
                },
                //最下面的区域这哪是组件
                dataZoom: {},
                //布局
                grid: {
                    //距离left的位置   给了固定宽高不会实现响应式
                    left: 30,
                    right: 0,
                    top: 10
                }

            }

        )
    </script>

P68、echarts坐标体系

一个坐标系的散点图

    <script src="./echarts.min.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        
        .box {
            width: 800px;
            height: 400px;
        }
    </style>
</head>

<body>
    <div class="box"></div>
    <script>
        let dom = document.querySelector('.box')
        let mycharts = echarts.init(dom)
        mycharts.setOption({
                //x轴
                xAxis: {
                    //让散点图的点均匀的显示
                    type: 'category'
                },
                //y轴
                yAxis: {},
                //图形配置
                series: [{
                    //散点图
                    name: '散点图',
                    type: 'scatter',
                    //散点图的数据是二维数组
                    data: [
                        [10, 10],
                        [20, 15],
                        [20, 32],
                        [15, 20]
                    ]
                }]
            }

        )
    </script>

双坐标系

yAxis 从对象变为数组 数组里面两个对象

  <script src="./echarts.min.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        
        .box {
            width: 800px;
            height: 400px;
        }
    </style>
</head>

<body>
    <div class="box"></div>
    <script>
        let dom = document.querySelector('.box')
        let mycharts = echarts.init(dom)
        mycharts.setOption({
                //x轴
                xAxis: {

                },
                //y轴   成为数组
                //yAxis: {},
                yAxis: [{
                    //展示刻度
                    axisTick: {
                        show: true
                    },
                    //展示y轴的线
                    axisLine: {
                        show: true
                    }
                }, {
                    //展示刻度
                    axisTick: {
                        show: true
                    },
                    //展示y轴的线
                    axisLine: {
                        show: true
                    }
                }],
                //图形配置
                series: [{
                    type: 'line',
                    data: [10, 20, 60, 30],
                    //规范使用那个y轴  索引值
                    yAxisIndex: 0

                }, {
                    type: 'bar',
                    data: [20, 32, 15, 42],
                    yAxisIndex: 1

                }]
            }

        )
    </script>

多坐标系

yAxis 从对象变为数组 数组里面多个对象

P69、Home首页Card静态组件

头部完成

1.在首页组件dashboard组件 创建card组件 这里书写头部

头部的每一个卡片的具体显示内容由子组件Detail组件来展示

img

2.组件内容

dashboard:

img

card:

img

detail:

img

目前展示:

img

使用具名插槽来展示具体的内容

浏览器如何使用取色器

1.找到color的标签 点击后面的颜色就可以找到取色器

img

具名插槽:

子:< slot name=“11”

父:<template v-slot:11

button template>

1/4处 title字段的显示 采用props来展示

2/4处 content字段的显示 采用props来展示

3/4处 具名插槽

4/4处 具名插槽

子组件:

img

父组件:

img

PS:此处如果传入的字段不是data里面的或者script里面的 父传子不需要加入:title来传

依次改写其他四个card

P70、折线图完成

在第二个card里面的第三个部分 插槽内容直接写入这个组件就行

1.引包

下载依赖

npm i echarts --save

2.准备容器

在准备一个组件 在插槽区域直接显示组件就行

3.初始化实例

在mounted生命周期进行获取节点

<template>
 <div>
  <!-- 准备容器 -->
  <div class="line" ref="dom">
  </div>
 </div>
</template>

<script>
  //引包
import * as echarts from 'echarts';
export default {
  mounted(){
    //实例化
    let Mycharts = echarts.init(this.$refs.dom)
    Mycharts.setOption({

        xAxis: {
            show:false,
            //均匀分布
            type:'category'
        },
        yAxis: {
          show:false
        },
        series: [
          {
            data: [10, 22, 28, 23, 19,26,35,18,24],
            type: 'line',
            //曲线平滑
            smooth: true,
            lineStyle:{
              //线条颜色
              color:'purple',

            },
            itemStyle:{
              //拐点消失
              opacity:0
            },
            //填充颜色
            areaStyle:{
              color:
                {
                  type: 'linear',
                  x: 0,
                  y: 0,
                  x2: 0,
                  y2: 1,
                  colorStops: [{
                      offset: 0, color: 'purple' // 0% 处的颜色
                  }, {
                      offset: 1, color: 'white' // 100% 处的颜色
                  }],
                  global: false // 缺省为 false
                }

            }
          }
        ],
        //布局
        grid:{
          left:-15,
          top:0,
          bottom:0,
          right:-10
        },
        //tooltip提示组件
        tooltip: {
                    show: true,
                    textStyle: {
                        //提示框文字的颜色
                        color: 'red'
                    }
                },
    })

  }
}
</script>

<style scoped>
  .line{
    width: 100%;
    height: 50px;
  }
</style>

P71、柱状图和进度条完成

柱状图

和折线图一样 只不过类型选择bar就行

进度条完成

这个进度条其实就是柱状图倒下之后显示的样子

 Mycharts.setOption({

         xAxis: {
             show:false,
             //设置x轴的最大值和最小值
             min:0,
             max:100

         },
         yAxis: {
           show:false,
             //均匀分布  实现躺倒的效果
             type:'category'
         },
         series: [
           {
             data: [78],
             type: 'bar',
             //柱状图的宽度
             barWidth:10,
             //柱状图的颜色
             color:'yellowgreen',
             //背景颜色设置
             showBackground:true,
             //背景颜色配置
             backgroundStyle:{
              color:"#eee"
             },
             //文本
             label:{
              show:true,
              //展示的文字从文字变成|
              formatter:"|",
              //让|显示在右边
              position:'right'
             }
           }
         ],
         //布局
         grid:{
           left:-25,
           top:0,
           bottom:0,
           right:-10
         },
         //tooltip提示组件
         tooltip: {
                     show: true,
                     textStyle: {
                         //提示框文字的颜色
                         color: 'red'
                     }
                 },
     })

   }

P72、sale静态组件(上)

先注册和使用sale组件

img

书写sale静态样式

<template>
  <div>
    <el-card style="margin:20px 0">
      <div class="sale">
        <!-- @tab-click="handleClick" -->
          <!-- 左侧区域 -->
          <div class="left">
            <el-tabs v-model="activeName" class="tabs">
            <el-tab-pane label="销售额" name="销售额">
            </el-tab-pane>
            <el-tab-pane label="访问量" name="访问量">
              <el-row>
                <el-col :span="16">11</el-col>
                <el-col :span="8">1122</el-col>
              </el-row>
            </el-tab-pane>
          </el-tabs>
            下面的内容写在这里就不用进行切换了  换显示的文字就行
  					<el-row>
                <el-col :span="16">1</el-col>
                <el-col :span="8">11</el-col>
              </el-row>
          </div>
          <!-- 右侧区域 -->
          <div class="right">
            <span>今日</span>
            <span>本周</span>
            <span>本月</span>
            <span>本年</span>
            <!-- 时间选择器 -->
            <!--  v-model="value1" -->
            <el-date-picker
                style="margin:0 20px"
                type="daterange"
                range-separator="-"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
                size="mini">
              </el-date-picker>
          </div>
      </div>

    </el-card>
  </div>
</template>

<script>
export default {
  data(){
    return{
      activeName:'销售额'
    }
  }
}
</script>

<style scoped>
  .sale{
    position: relative;
    display: flex;
    justify-content: space-between;
  }
  .right span{
    font-size: 14px;
    margin: 0 10px;
    margin-top: 5px;

  }
  .right{
    position: absolute;
    right: 0;
    height: 30px;
  }
  .left{
    width: 100%;
  }
</style>

P73、sale静态组件(中)

柱状图完成

在tab组件的内容区域进行柱状图还有门店铺销售排名的操作

只有一个柱状图和ul

柱状图从echarts里面的示例里面去找

P74、sale静态组件完毕

访问量和销售量的切换

我们点击tab的时候就可以获取到activeName值是sale销售还是vister访问

img

就可以通过计算属性计算出一个值来进行具体文字的显示 右边区域好解决 直接进行mustache语法就行 那么左边的柱状图的title怎么变

解决 给MyCharts初始为null 在mounted 生命周期进行赋值操作 然后使用watch来对计算属性的值进行监听 如果发生改变 那么进行title字段的改变

tab切换收集两个值 sale和vister

此时默认显示显示的数值是sale

由计算属性计算出值来title

img

把MyCharts也设置为null

img

在mounted执行的时候把echarts实例赋值给data数据

img

再次监听title的变化 如果发生改变 就把配置对象的title字段重新设置一下

img

PS:此时的mounted函数必须要在watch之前 不然会报错

处理时间收集器

时间收集器v-model绑定一个数组 value-format 是编辑的格式

img

如果选择好之后就会显示这样的数组

img

给span添加点击事件 分别给数组的第一个和第二个值填入对应的值

img

【start,end】

img

把date赋值过去 就会出现日期文字 自己选择日期的操作了

P75、observe静态组件

img

img

最终实现效果

img

P76、动态展示mock数据

1.mock的文件放到mock文件夹下面

在mock文件里面创建home.js 大概模板使用table.js

改写一下home.js

const data = require('./data.json')

module.exports = [{
    url: '/home/list',
    type: 'get',
    response: config => {
        const items = data.items
        return {
            code: 20000,
            data
        }
    }
}]

在mock文件下的index.js进行引入

img

此时获取不到数据 因为需要在vue.config.js文件中配置mock

img

此处可以删除或者写成after 不然登录不了

mock/mock-serve.js改写配置

img

.env.development增加配置

img

utils文件下复制一个request.js文件 路径配置为mock-api

img

重启项目

在store/models文件下创建home.js文件

在index.js合并入大仓库

img

home.js文件

import MOCKrequest from '@/utils/MOCKrequest.js'
const state = {
    list: {}
}
const mutations = {
    GETDATA(state, list) {
        state.list = list
    }
}
const actions = {
    async getData({ commit }) {
        let res = await MOCKrequest.get('/home/list')
        if (res.code == 20000) {
            commit('GETDATA', res.data)
        }
    }
}
const getters = {

}
export default {
    state,
    mutations,
    actions,
    getters
}

在dashboard首页的mounted生命周期来进行dispatch

img

这时仓库内的list就成为了mock的数据

使用数据

sale组件使用辅助函数来进行list数据的使用

1.引入辅助函数

2.挂载为计算属性

img

此时sale组件就获取到了list的数据

3.使用数据

把setOption的配置的datamounted里面为空

img

在watch里面进行title的监听

img

此时实现点击tab标题的时候实现切换柱状图的数据

但是在第一次进入的时候数据是空的 怎么办

监听vuexlist的数据 改变的时候进行重新赋值 组件一创建就会获取到vuex的数据 直接赋值为销售额的数据

img

其余数据依次进行展示 后续处理

P77、权限管理模块介绍

超级管理员 分配角色 角色权限

P78、权限管理模块的串讲

cv

复制一下 api 配置api

复制一下组件 配置路由

改写一下请求函数的导出方式

细细查看一下文件的业务

P79、菜单&按钮的权限

动态展示组件的本质就是根据权限来展示路由

怎么实现 我们在登录的时候会发请求 服务器会返回登陆者的权限信息 根据这些信息我们来进行判断权限

如何实现菜单的权限

1.登录页面实现的逻辑

登录按钮实现点击事件 img

这个事件是派发一个vuex任务 把登录的信息传入

img

vuex这个事件具体实现的逻辑

根据用户填入的用户名和密码返回taken信息 把token存了imgimg

然后根据存入的token获取页面

img

这里改写为把所有根据token返回的数据全部都存了

服务器的数据 name用户名 avatar用户头像 rotes:用户角色信息 routes:用户应该展示那些组件 buttons:按钮权限

img

img

img

此时在login组件把表单验证关掉

img

然后在角色管理添加一个角色和密码 就可以使用这个账号密码进行登录 可以发现展示的权限是不一样的 此时的账号是edit 111111

img

此时实现的问题可以多账号进行登录 但是展示的路由都是一样的 因为我们在路由配置的时候都是写死的 没办法进行分辨

解决 把路由分类

常量路由 异步路由 任意路由

img

img

img

这时没有改变下面的routes的配置 现在所有人进来都是首页 其他的没有了

我们需要用vuex存储的信息和这些路由对比 决定展示哪一个

给user下的vuex添加一个数组 这个数组准备放服务器反馈的routes数组和异步路由进行对比重合的数组

img

给根据token 获取用户信息的事件commit一个mutations 让resaultAsyncRouer这个值等于传入的值 只不过现在传入的值还没有进行计算

img

img

这个值 如何计算呢?

在vuex把刚刚配置的三个路由进行引入

img

异步路由和存储的routes数组进行过滤 然后和常量路由和任意路由进行合并之后出现新的路由配置

在刚刚commit传入的值设置为一个对象 这个对象两个参数 一个刚刚传入的异步路由 一个服务器获取到的routes数组 这个函数的返回值是一个新数组就行

img

书写这个函数 和actions这些配置同级

img

img

需要过滤

img

item的信息

img

img

此时实现的是能把以及路由过滤出去 name二级三级路由呢

解决 使用递归

const computedAsyncRouters = (sayncRoutes, routes) => {
    // console.log(sayncRoutes);
    // console.log(routes);
    return sayncRoutes.filter(item => {
        //服务器返回的信息字段里面没有我们配置的路由信息的name字段  那么return出去
        if (routes.indexOf(item.name) != -1) {
            //递归
            if (item.children && item.children.length) {
                item.children = computedAsyncRouters(item.children, routes)
            }
            return true
        }
    })
}

此时就可以知道展示那些异步路由

此时的 ressultAsyncRoutes:数组里面存储的就是和服务器返回的权限传的异步路由了

img

路由注册的最后计算 常量,异步,任意路由进行合并

准备变量 存储最后的路由信息

img

img

计算完异步路由直接进行数组的合并 concat

在vuex引入router 然后使用router.addRoutes来进行重新配置路由

img

img

此时路由已经根据权限配置完毕 但是页面展示的只有首页

因为这个模板取得数据不是从仓库 是从router里面取的常量路由

img

img

img

改写数据 从vuex里面拿

img

此时的权限业务逻辑完成

按钮权限 不同权限下面展示不同的按钮 或者按钮的可见性

1.06.02

解决bug 在品牌管理模块出现不了商品管理的菜单

在router配置的时候的name是Trademark

解决bug 在登录之后进行路由的跳转出现白屏

在permission.js修改代码

try {
                    // get user info
                    await store.dispatch('user/getInfo')

                    //next()
                    next({...to })

  • 24
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值