精华内容
下载资源
问答
  • ThinkPHP Ant Design Pro Vue ThinkPHP 6.0与Ant Design Pro Vue基础权限系统基于Ant Design Vue Pro 预览地址: 开发文档: : Ant Design Vue Pro文档: : 初步: : 服务器提供: 预览账号 超级管理员admin, ...
  • 蚂蚁设计专业Vue模板 根据改造后的开箱即用的后台管理系统模板,优化了很多内容,更轻量,更简洁,可以在此模板上快速,便捷地去建造自己的后台项目。预览:| 优化:项目结构和文件夹命名,项目结构更加合理 优化:...
  • 基于 Ant Design of Vue 实现的 Ant Design Pro 源码 安装依赖 npm install 开发模式运行 npm run serve 编译项目 npm run build
  • Vue Antd管理员 的Vue实现版本开箱即用的中后台前端/设计解决方案 多种主题模式任选: 预览地址: : 使用文档: : 常见问题: ://iczer.gitee.io/vue-antd-admin-docs/start/faq.html 国内知名: ://gitee....
  • beego Ant Design Pro Vue RBAC beego与Ant Design Pro Vue基础权限系统 初步: ://beego.me ORM:gorm Ant Design Pro Vue文档: : 预览: 账号 超级管理员admin, 1234 普通管理员test, 1234 前端部署 安装 cd...
  • ant-design-vue-pro 项目设置 npm install 编译和热重装以进行开发 npm run serve 编译并最小化生产 npm run build 运行单元测试 npm run test:unit 整理和修复文件 npm run lint 自定义配置 请参阅。
  • Ant Design Pro Vue不完全开发手册

    千次阅读 2021-01-21 10:08:03
    Ant Design Pro Vue不完全开发手册前言准备工作:1、安装npm2、可选安装3、安装 vue-cli 工具:4、参考文档基础开发学习:1、git项目拉取2、安装项目3、启动项目4、文件解析vue.config.jsrouter.config.jsviews(1)...

    前言

    此文档是我为公司写的前端框架开发手册(应该没人看,哈哈),这里删除公司敏感信息后,作为自己的总结文档记录一下。

    准备工作:

    1、安装npm

    npm更换阿里镜像

    npm config set registry https://registry.npm.taobao.org/ 
    

    查看是否成功

    npm config get registry
    

    2、可选安装

    cnpm(同npm,淘宝镜像速度快)、yarn(https://blog.csdn.net/csdn_yudong/article/details/82015885

    3、安装 vue-cli 工具:

    安装命令npm install -g @vue/cli

    4、参考文档

    ant design vue :http://vue.ant-design.cn/docs/vue/introduce-cn/
    ant design vue pro :https://pro.loacg.com/docs/getting-started

    基础开发学习:

    1、git项目拉取

    2、安装项目

    cnpm install 或者 npm install

    3、启动项目

    npm run serve
    或者
    yarn serve

    注:相关命令存放于package.json

    启动成功信息
    在这里插入图片描述

    4、文件解析

    vue.config.js

    本地开发需要在

    vue.config.js

    配置代理对象
    在这里插入图片描述

    router.config.js

    路由用于菜单配置
    在这里插入图片描述

    注意:
    (1)admin账户直接读取的是router.config.js路由配置,未和数据库做交互,为全权限。
    (2)其他账户经过admin-service服务读取表sys_permission获取权限,其权限为部分权限,故添加新页面时必须要向该表添加对应数据,sys_permission.title = router.config.js.title
    sys_permission.name = router.config.js.permission,其他无要求。
    (3)相关权限控制代码位于
    在这里插入图片描述

    views

    在这里插入图片描述

    视图——》业务逻辑开发位置
    业务开发推荐目录结构(add和update其实可以复用,为了降低开发难度,才做此拆分)
    在这里插入图片描述

    (1)api.js

    ——》对外接口,主要用于发送请求
    使用组件为 axios

    (1)get请求写法

    export function getAirportInfo (parameter) {
      return axios({
        url: '...',
        method: 'get',
        params: parameter // 此处为params
      })
    }
    

    (2)post请求写法

    export function page (parameter) {
      return axios({
        url: '...',
        method: 'post',
        data: parameter // 此处为data
      })
    }
    

    (2)vue开发浅谈

    在这里插入图片描述

    1、引入组件(按需引用)

    import { STable } from '@/components'
    

    2、注册组件
    在这里插入图片描述

    3、数据定义

    data () {
      return {...}
    }
    

    4、生命周期定义

    mounted () {...}
    

    拓展学习https://cn.vuejs.org/v2/guide/instance.html#生命周期图示
    5、方法定义

    methods: {...}
    

    6、监听
    多用于更新页面数据回显

    watch: {...}
    

    7、mock
    ——》模拟数据存放位置,脱离后端进行调试

    问题与解惑

    1、如何把父组件的值传到子组件

    父组件中
    在这里插入图片描述

    子组件中
    在这里插入图片描述

    父组件直接传递即可
    在这里插入图片描述

    2、父组件调如何用子组件方法

    在这里插入图片描述

    如何取别名:ref=“model”

    【this.$refs.{别名}】

    这个的意思是获取对应vue的对象
    this.$refs.{别名}.{方法}

    3、子组件如何调用父组件方法

    调用$emit方法,其中“o”为父组件中,子组件的方法

    this.$emit(o)

    在这里插入图片描述

    4、列表属性

    在这里插入图片描述

    5、导入了组件,却发现使用不了

    为了前端的渲染速度,我们采用的是按需引用
    在这里插入图片描述

    框架没有引用的,我们需要手动引用组件

    (1)方式一:引用组件相关所有文件

    // 折叠框,直接使用会报错,在此手动引用
    import ACollapse from 'ant-design-vue/es/collapse/Collapse'
    import ACollapsePanel from 'ant-design-vue/es/collapse/CollapsePanel'
    import 'ant-design-vue/lib/collapse/style'
    

    (2)方式二(推荐)

    import { Button } from 'ant-design-vue';
    Vue.use(Button);
    

    6、如何进行权限控制(按钮级)

    <span v-if="$auth('luggageOrder.luggageManualRefund')"></span>
    

    注意:luggageOrder.luggageManualRefund权限表的关联性(别忘了router.config.js路由哟)

    拓展学习
    https://pro.antdv.com/docs/authority-management

    7、更新页面如何重置数据

    在父页面Lsit,将data设置为空
    在这里插入图片描述

    8、新增页面如何重置数据

    在新增页面,调用关闭方法时,重置form表单

    this.$nextTick(() => {
      this.form.setFieldsValue({ ...formdata })
    })
    

    9、数据类型怎么定义

    对象 - queryParam : {}
    数组 - queryParam : []
    字符串 - queryParam : ''
    

    10、下拉框有数据,但是为空白,不显示

    多半是下拉框数据类型不匹配,请检查number还是字符串

    11、时间框的对象用什么

    import moment from 'moment'
    

    拓展学习
    http://momentjs.cn/

    12、列表字段实现toptip效果

    ellipsis
    

    在这里插入图片描述

    13、使用watch监听时,第一次加载页面会报错。(20210220新增)

    增加数据校验

            if (!n || !n.id) {
              return
            }
    

    结语

    为什么这个手册叫不完全开发手册呢?因为我也是一个前端小白,从来没有系统学习过vue,都是从0开始,撸起袖子就干了。以上内容都是从经验出发,希望大家少走弯路,快速开发,所以描述啥的可能会不准确,如果有错误,同学们可以直接改正,或者联系【黎晓东】。这里引用晓东大神的一句话:“虽然我们是后端开发,但是如果连一个后台管理系统的前端页面都写下不下来,真的说不过去”。

    附录

    ant design vue :http://vue.ant-design.cn/docs/vue/introduce-cn/
    ant design vue pro :https://pro.loacg.com/docs/getting-started
    vue:https://cn.vuejs.org/
    moment:http://momentjs.cn/
    axios:http://www.axios-js.com/

    展开全文
  • ant design pro vue 动态路由 前后端详解前言流程图 前言 官方提供了两种实现权限的方法 官网地址 1:前端路由表写死(设置权限标识) 根据后端返回的权限标识生成路由表 2:动态路由 路由表由后端返回 前端根据返回的 ...

    前言

    官方提供了两种实现权限的方法 官网地址
    1:前端路由表写死(设置权限标识) 根据后端返回的权限标识生成路由表
    2:动态路由 路由表由后端返回 前端根据返回的 进行路由表的拼接

    两种方法 在 src/store/index.js 里切换

    // import permission from './modules/permission'
    // 第一种 根据路由表里permissions 权限标识筛选/
    
    //import permission from './modules/async-router'
    // 第二种  路由表由后端返回
    

    第一种 官方说的比较详细,直接看官方的就行

    下面详细说下第二种 后端返回的路由表流程

    流程图

    权限流程图

    流程1 src/permission.js

    1. 进入 src/permission.js 的 路由守卫里
      从 if (store.getters.roles.length === 0) 开始 调取vuex里 获取个人信息接口
      图1

    流程2 src/store/modules/user.js

    1. 来到 src/store/modules/user.js 去掉不需要的内容(第一种权限实现的代码) 设置role 角色信息 根据角色信息 请求权限信息 在这里 后端根据token来查询权限 所以 下方请求权限时 不需要传角色信息 根据后端来设置是否传参
      图2

    流程3 src/permission.js

    1. 获取到 role 返回 src/permission.js

    流程4 src/permission.js

    1. 调用 src/router/generator-routers.js里的 GenerateRoutes 函数 获取权限

    流程5 src/router/generator-routers.js

    调取接口获得权限列表
    图3

    流程6 src/router/generator-routers.js

    传入同页面的 listToTree 函数和 generator 函数 进行路由拼装
    图4

    流程7 src/router/generator-routers.js

    重点在 根据后端返回具体字段 拼接前端路由表(需要在同页面上方定义好路由路径)
    图5
    图6
    拼装完毕返回结果

    流程8 src/store/modules/async-router.js

    拿到结果存到vuex
    图7

    流程9 src/permission.js

    见图1 返回并增加路由 执行下面重定向 等逻辑

    后端部分

    数据库设置 权限表

    完整需要 用户表 绑定角色表 角色表绑定权限表 下面是权限表的字段
    图8

    接口返回格式

    • 获取用户详情的接口 需要有role字段 或者 改为其他判断条件都可以 留着以后换实现方法1 也可以兼容

    • 获取nav 权限列表时 需要注意
      图9

    • 权限管理页面 就可以根据官方给的页面做就行了 需要注意的是
      component 字段再父路由根据需要可设置 BlankLayout(页面啥样就啥样),
      RouteView(适用于分路由的页面,有坑,需要跟redirect 重定向配合使用) ,PageView(加了页头导航的样式)

    • redirect 重定向 不能重定向到当前路由 会报错

    • src/router/generator-routers.js的 rootRouter 根级目录
      图10
      以上就是动态路由的流程了 如有错误,麻烦指正,有什么问题,也可评论询问!

    展开全文
  • Ant Design Pro Vue使用心得 目录结构 ├── public │ └── logo.png # LOGO | └── index.html # Vue 入口模板 ├── src │ ├── api # Api ajax 等 │ ├── assets # 本地静态资源 │ ...

    Ant Design Pro Vue使用心得

    目录结构

     

    ├── public
    │   └── logo.png             # LOGO
    |   └── index.html           # Vue 入口模板
    ├── src
    │   ├── api                  # Api ajax 等
    │   ├── assets               # 本地静态资源
    │   ├── config               # 项目基础配置,包含路由,全局设置
    │   ├── components           # 业务通用组件
    │   ├── core                 # 项目引导, 全局配置初始化,依赖包引入等
    │   ├── router               # Vue-Router
    │   ├── store                # Vuex
    │   ├── utils                # 工具库
    │   ├── locales              # 国际化资源
    │   ├── views                # 业务页面入口和常用模板
    │   ├── App.vue              # Vue 模板入口
    │   └── main.js              # Vue 入口 JS
    │   └── permission.js        # 路由守卫(路由权限控制)
    ├── tests                    # 测试工具
    ├── README.md
    └── package.json

    路由和菜单

    基本结构

    路由和菜单是组织起一个应用的关键骨架,pro 中的路由为了方便管理,使用了中心化的方式,在 ==router.config.js== 统一配置和管理。

    • 路由管理 通过约定的语法根据在==router.config.js==中配置路由。
    • 菜单生成 根据路由配置来生成菜单。菜单项名称,嵌套路径与路由高度耦合。
    • 面包屑 组件 ==PageHeader== 中内置的面包屑也可由脚手架提供的配置信息自动生成。

    路由

    目前脚手架中所有的路由都通过 ==router.config.js== 来统一管理,在 ==vue-router== 的配置中我们增加了一些参数,如 ==hideChildrenInMenu==,==meta.title==,==meta.icon==,==meta.permission==,来辅助生成菜单。其中:

    • hideChildrenInMenu 用于隐藏不需要在菜单中展示的子路由。用法可以查看 分步表单 的配置。
    • hidden 可以在菜单中不展示这个路由,包括子路由。效果可以查看 other 下的路由配置。
    • meta.title 和 meta.icon分别代表生成菜单项的文本和图标。
    • meta.permission 用来配置这个路由的权限,如果配置了将会验证当前用户的权限,并决定是否展示 *(默认情况下)。
    • meta.hidden 可以强制子菜单不显示在菜单上(和父级 hideChildrenInMenu 配合)
    • meta.hiddenHeaderContent 可以强制当前页面不显示 PageHeader 组件中的页面带的 面包屑和页面标题栏

    路由配置项

     

    /**
     * 路由配置说明:
     * 建议:sider menu 请不要超过三级菜单,若超过三级菜单,则应该设计为顶部主菜单 配合左侧次级菜单
     *
     **/
     {
      redirect: noredirect,  //重定向
      name: 'router-name',   //路由名称
      hidden: true,          //可以在菜单中不展示这个路由,包括子路由。效果可以查看 other 下的路由配置。
      meta: {
        title: 'title',      //菜单项名称
        icon: 'a-icon',      //菜单项图标
        keepAlive: true,     //缓存页面
        permission:[string]   //用来配置这个路由的权限,如果配置了将会验证当前用户的权限,并决定是否展示 *(默认情况下)
        hiddenHeaderContent: true,   //可以强制当前页面不显示 PageHeader 组件中的页面带的 面包屑和页面标题栏
      }
    }
    

    具体请参考 https://pro.loacg.com/docs/router-and-nav

    菜单

    菜单根据 ==router.config.js== 生成,具体逻辑在 ==src/store/modules/permission.js== 中的 ==actions.GenerateRoutes== 方法实现。

    Ant Design Pro 的布局

    在 Ant Design Pro 中,我们抽离了使用过程中的通用布局,都放在 ==/components/layouts== 目录中,分别为:

    • BasicLayout:基础页面布局,包含了头部导航,侧边栏和通知栏:
    • UserLayout:抽离出用于登陆注册页面的通用布局
    • PageView:基础布局,包含了面包屑,和中间内容区 (slot)
    • RouterView:空布局,专门为了二级菜单内容区自定义
    • BlankLayout:空白的布局

    定义全局样式

     

    /* 定义全局样式 */
    :global(.text) {
      font-size: 16px;
    }
    
    /* 定义多个全局样式 */
    :global {
      .footer {
        color: #ccc;
      }
      .sider {
        background: #ebebeb;
      }
    }
    //覆盖组件样式
    // 使用 css 时可以用 >>> 进行样式穿透
    .test-wrapper >>> .ant-select {
        font-size: 16px;
    }
    
    // 使用 scss, less 时,可以用 /deep/ 进行样式穿透
    .test-wrapper /deep/ .ant-select {
        font-size: 16px;
    }
    
    // less CSS modules 时亦可用 :global 进行覆盖
    .test-wrapper {
        :global {
            .ant-select {
                font-size: 16px;
            }
        }
    }
    

    与服务器交互

    在 Ant Design Pro 中,一个完整的前端 UI 交互到服务端处理流程是这样的:

    1. UI 组件交互操作;
    2. 调用统一管理的 api service 请求函数;
    3. 使用封装的 request.js 发送请求;
    4. 获取服务端返回;
    5. 更新 data。

    从上面的流程可以看出,为了方便管理维护,统一的请求处理都放在 @/src/api 文件夹中,并且一般按照 model 纬度进行拆分文件,如:

     

    api/
      user.js
      permission.js
      goods.js
      ...
    

    其中,==@/src/utils/request.js== 是基于 ==axios== 的封装,便于统一处理 ==POST==,==GET== 等请求参数,请求头,以及错误提示信息等。具体可以参看 ==request.js==。 它封装了全局 request 拦截器、response 拦截器、统一的错误处理、baseURL 设置等。

    例如在 api 中的一个请求用户信息的例子:

     

    // api/user.js
    import { axios } fromm '@/utils/request'
    
    const api = {
        info: '/user',
        list: '/users'
    }
    
    // 根据用户 id 获取用户信息
    export function getUser (id) {
        return axios({
            url: `${api.user}/${id}`,
            method: 'get'
        })
    }
    
    // 增加用户
    export function addUser (parameter) {
        return axios({
            url: api.user,
            method: 'post',
            data: parameter
        })
    }
    
    // 更新用户 // or (id, parameter)
    export function updateUser (parameter) {
        return axios({
            url: `${api.user}/${parameter.id}`, // or `${api.user}/${id}`
            method: 'put',
            data: parameter
        })
    }
    
    // 删除用户
    export function deleteUser (id) {
        return axios({
            url: `${api.user}/${id}`,
            method: 'delete',
            data: parameter
        })
    }
    
    // 获取用户列表 parameter: { pageSize: 10, pageNo: 1 }
    export function getUsers (parameter) {
        return axios({
            url: api.list,
            method: 'get',
            params: parameter
        })
    }
    

     

    <template>
        <div>
            <a-button @click="queryUser"></a-button>
    
            <a-table :dataSource="list">
            </a-table>
        </div>
    </template>
    
    <script>
    import { getUser, getUsers } from '@/api/user'
    
    export default {
        data () {
            return {
                id: 0,
                queryParam: {
                    pageSize: 10,
                    pageNo: 1,
                    username: ''
                },
                info: {},
                list: []
            }
        },
        methods: {
            queryUser () {
                const { $message } = this
                getUser(this.id).then(res => {
                    this.info = res.data
                }).catch(err => {
                    $message.error(`load user err: ${err.message}`)
                })
            },
            queryUsers () {
                getUsers(this.queryParam).then(res => {
                    this.list = res
                })
            }
        }
    }
    </script>
    

     

    **
         * 获取裁剪后的图片
         */
        cropImage () {
          this.form.cropimg = this.$refs.cropper.getCroppedCanvas().toDataURL();
        },
        /**
         * 确认裁剪
         */
        sureCrop () {
          this.dialogVisible = false
        },
        /**
         * 上传裁剪后的图片到服务器
         */
        upCropImg () {
          //判断是否是新增还是编辑
          if (this.$route.query.id && this.$route.query.id != '') {
            //如果是编辑的就直接提交
            this.onSubmit()
          } else {
            //否则先上传裁剪图片,将64位图片转换为二进制数据流
            var formdata1 = new FormData();// 创建form对象
            formdata1.append('file', convertBase64UrlToBlob(this.form.cropimg), 'aaa.png');//
            this.$ajax
              .post(this.$api + "/upload/singleUploadImg", formdata1, { headers: { 'Content-Type': 'multipart/form-data' } })
              .then(response => {
                if (response.data.msg == "success" && response.data.code == 1) {
                  this.form.imgUrl = response.data.data.imgUrl
                  this.onSubmit()
                } else {
                  console.log(response)
                  this.$message.error(response.data.msg);
                }
              })
              .catch(function (error) {
                console.log(error);
              });
          }
    
        },
    

    引入外部模块

     

    $ npm install '组件名字' --save
    

    使用

     

    //全局引入
    import Vue from 'vue'
    import VueQuillEditor from 'vue-quill-editor'
    
    // require styles
    import 'quill/dist/quill.core.css'
    import 'quill/dist/quill.snow.css'
    import 'quill/dist/quill.bubble.css'
    
    Vue.use(VueQuillEditor, /* { default global options } */)
    

     

    <template>
        <div>
            <quill-editor ref="myTextEditor"
                          v-model="content"
                          :config="editorOption"
                          @blur="onEditorBlur($event)"
                          @focus="onEditorFocus($event)"
                          @ready="onEditorReady($event)">
            </quill-editor>
        </div>
    </template>
    
    <script>
    //按需加载
    import 'quill/dist/quill.core.css'
    import 'quill/dist/quill.snow.css'
    import 'quill/dist/quill.bubble.css'
    import { quillEditor } from 'vue-quill-editor'
    
    export default {
      components: {
        quillEditor
      },
      data () {
          return {
              content: '<h2>I am Example</h2>',
              editorOption: {
               // something config
              }
          }
      },
      // 如果需要手动控制数据同步,父组件需要显式地处理changed事件
      methods: {
        onEditorBlur(editor) {
          console.log('editor blur!', editor)
        },
        onEditorFocus(editor) {
          console.log('editor focus!', editor)
        },
        onEditorReady(editor) {
          console.log('editor ready!', editor)
        },
        onEditorChange({ editor, html, text }) {
          // console.log('editor change!', editor, html, text)
          this.content = html
        }
      },
      // 如果你需要得到当前的editor对象来做一些事情,你可以像下面这样定义一个方法属性来获取当前的editor对象,实际上这里的$refs对应的是当前组件内所有关联了ref属性的组件元素对象
      computed: {
        editor() {
          return this.$refs.myTextEditor.quillEditor
        }
      },
      mounted() {
        // you can use current editor object to do something(editor methods)
        console.log('this is my editor', this.editor)
        // this.editor to do something...
      }
    }
    </script>
    

    引入业务图标

    参考:https://pro.loacg.com/docs/biz-icon

    国际化

    参考:https://pro.loacg.com/docs/i18n

    权限管理

    参考:https://pro.loacg.com/docs/authority-management

    自定义使用规则

    • 修改网站icon的文件地址在 ==public文件夹==中把logo.png换成自定义的,也可在==public/index.html==自定义

     

    <!DOCTYPE html>
    <html lang="zh-cmn-Hans">
      <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width,initial-scale=1.0">
        <link rel="icon" href="<%= BASE_URL %>logo.png">
        <title>共享云店</title>
        <style>#loading-mask{position:fixed;left:0;top:0;height:100%;width:100%;background:#fff;user-select:none;z-index:9999;overflow:hidden}.loading-wrapper{position:absolute;top:50%;left:50%;transform:translate(-50%,-100%)}.loading-dot{animation:antRotate 1.2s infinite linear;transform:rotate(45deg);position:relative;display:inline-block;font-size:64px;width:64px;height:64px;box-sizing:border-box}.loading-dot i{width:22px;height:22px;position:absolute;display:block;background-color:#1890ff;border-radius:100%;transform:scale(.75);transform-origin:50% 50%;opacity:.3;animation:antSpinMove 1s infinite linear alternate}.loading-dot i:nth-child(1){top:0;left:0}.loading-dot i:nth-child(2){top:0;right:0;-webkit-animation-delay:.4s;animation-delay:.4s}.loading-dot i:nth-child(3){right:0;bottom:0;-webkit-animation-delay:.8s;animation-delay:.8s}.loading-dot i:nth-child(4){bottom:0;left:0;-webkit-animation-delay:1.2s;animation-delay:1.2s}@keyframes antRotate{to{-webkit-transform:rotate(405deg);transform:rotate(405deg)}}@-webkit-keyframes antRotate{to{-webkit-transform:rotate(405deg);transform:rotate(405deg)}}@keyframes antSpinMove{to{opacity:1}}@-webkit-keyframes antSpinMove{to{opacity:1}}</style>
      </head>
      <body>
        <noscript>
          <strong>We're sorry but vue-antd-pro doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
        </noscript>
        <div id="app">
          <div id="loading-mask">
              <div class="loading-wrapper">
                <span class="loading-dot loading-dot-spin"><i></i><i></i><i></i><i></i></span>
              </div>
            </div>
        </div>
        <!-- built files will be auto injected -->
      </body>
    </html>
    
    

    -更换logo在==src\components\tools\Logo.vue==中更换

     

    <template>
      <div class="logo">
        <router-link :to="{name:'dashboard'}">
          <LogoSvg alt="logo" />   //这是logo
          <h1 v-if="showTitle">{{ title }}</h1>   //这是网站标题
        </router-link>
      </div>
    </template>
    
    <script>
    import LogoSvg from '@/assets/logo.svg?inline';
    export default {
      name: 'Logo',
      components: {
        LogoSvg
      },
      props: {
        title: {
          type: String,
          default: 'Admin For Ok',    //网站默认标题
          required: false
        },
        showTitle: {                  //是否显示网站标题,默认不显示
          type: Boolean,
          default: true,
          required: false
        }
      }
    }
    </script>
    
    

    pro权限管理和路由控制思路分析(粗略分析)

    • 主要是通过三个文件实现,==src\mock\services\user.js==文件通过登陆的角色获取对应的鉴权规则,具体可查看该文件下的源码
    • ==src\config\router.config.js==文件为路由配置文件,可增加路由取消路由等,变量asyncRouterMap为主要路由数组集合,可配置鉴权权限,变量constantRouterMap为基础路由,不参与鉴权
    • ==src\permission.js==文件为动态配置路由的主要逻辑,代码如下

     

    import Vue from 'vue'
    import router from './router'
    import store from './store'
    
    import NProgress from 'nprogress' // progress bar
    import 'nprogress/nprogress.css' // progress bar style
    import notification from 'ant-design-vue/es/notification'
    import { setDocumentTitle, domTitle } from '@/utils/domUtil'
    import { ACCESS_TOKEN } from '@/store/mutation-types'
    
    NProgress.configure({ showSpinner: false }) // NProgress Configuration
    
    const whiteList = ['login', 'register', 'registerResult'] // no redirect whitelist配置白名单
    
    router.beforeEach((to, from, next) => {
      NProgress.start() // start progress bar
      //生成动态网站标题
      to.meta && (typeof to.meta.title !== 'undefined' && setDocumentTitle(`${to.meta.title} - ${domTitle}`))
      if (Vue.ls.get(ACCESS_TOKEN)) {
        /* has token 如果有token并且是从登录页来的就直接跳到工作空间*/
        if (to.path === '/user/login') {
          next({ path: '/dashboard/workplace' })
          NProgress.done()
        } else {
        //否则检测是不是没有检测到规则,请求获取用户信息,获取用户权限
          if (store.getters.roles.length === 0) {
          //请求mock模拟数据获取用户权限
            store
              .dispatch('GetInfo')
              .then(res => {
                const roles = res.result && res.result.role
                //调用src\store\modules\permission.js里面的GenerateRoutes方法,处理数据
                store.dispatch('GenerateRoutes', { roles }).then(() => {
                  // 根据roles权限生成可访问的路由表
                  // 动态添加可访问路由表
                  router.addRoutes(store.getters.addRouters)
                  const redirect = decodeURIComponent(from.query.redirect || to.path)
                  if (to.path === redirect) {
                    // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
                    next({ ...to, replace: true })
                  } else {
                    // 跳转到目的路由
                    next({ path: redirect })
                  }
                })
              })
              .catch(() => {
                notification.error({
                  message: '错误',
                  description: '请求用户信息失败,请重试'
                })
                store.dispatch('Logout').then(() => {
                  next({ path: '/user/login', query: { redirect: to.fullPath } })
                })
              })
          } else {
            next()
          }
        }
      } else {
        if (whiteList.includes(to.name)) {
          // 在免登录白名单,直接进入
          next()
        } else {
          next({ path: '/user/login', query: { redirect: to.fullPath } })
          NProgress.done() // if current page is login will not trigger afterEach hook, so manually handle it
        }
      }
    })
    
    router.afterEach(() => {
      NProgress.done() // finish progress bar
    })
    
    
    • ==src\store\modules\permission.js==文件为路由数据的详细处理逻辑,配合src\permission.js文件使用,代码如下:

     

    import { asyncRouterMap, constantRouterMap } from '@/config/router.config'
    
    /**
     * 过滤账户是否拥有某一个权限,并将菜单从加载列表移除
     *
     * @param permission
     * @param route
     * @returns {boolean}
     */
    function hasPermission (permission, route) {
      if (route.meta && route.meta.permission) {
        let flag = false
        for (let i = 0, len = permission.length; i < len; i++) {
          flag = route.meta.permission.includes(permission[i])
          if (flag) {
            return true
          }
        }
        return false
      }
      return true
    }
    
    /**
     * 单账户多角色时,使用该方法可过滤角色不存在的菜单
     *
     * @param roles
     * @param route
     * @returns {*}
     */
    // eslint-disable-next-line
    function hasRole(roles, route) {
      if (route.meta && route.meta.roles) {
        return route.meta.roles.includes(roles.id)
      } else {
        return true
      }
    }
    
    function filterAsyncRouter (routerMap, roles) {
      const accessedRouters = routerMap.filter(route => {
        if (hasPermission(roles.permissionList, route)) {
          if (route.children && route.children.length) {
            route.children = filterAsyncRouter(route.children, roles)
          }
          return true
        }
        return false
      })
      return accessedRouters
    }
    
    const permission = {
      state: {
        routers: constantRouterMap,
        addRouters: []
      },
      mutations: {
        SET_ROUTERS: (state, routers) => {
          state.addRouters = routers
          state.routers = constantRouterMap.concat(routers)
        }
      },
      actions: {
        GenerateRoutes ({ commit }, data) {
          return new Promise(resolve => {
            const { roles } = data
            const accessedRouters = filterAsyncRouter(asyncRouterMap, roles)
            commit('SET_ROUTERS', accessedRouters)
            resolve()
          })
        }
      }
    }
    
    export default permission
    
    

    跨域请求设置

    在==vue.config.js==文件中修改

     

     // 配置跨域
      devServer: {
        // development server port 8000
        // port: 8000,
        proxy: {
          '/apis': {
            // target: 'https://mock.ihx.me/mock/5baf3052f7da7e07e04a5116/antd-pro',
            target: 'http://192.168.1.73:8092/okcloud/',
            // target: 'http://39.107.78.120:8083/okcloud/',
    
            ws: false,
            changeOrigin: true,  //是否允许跨域
            pathRewrite: {
              '^/apis': ''
            }
          }
        }
    

    axios拦截器

    在文件==src\utils\request.js==中设置

     

    // request interceptor
    service.interceptors.request.use(config => {
      const token = Vue.ls.get(ACCESS_TOKEN)
      if (token) {
        config.headers['okcloud_token'] = token // 让每个请求携带自定义 token 请根据实际情况自行修改
      }
      return config
    }, err)
    
    // response interceptor
    service.interceptors.response.use((response) => {
      if (response.data.code === 10000) {
        notification.warning({
          message: '提示',
          description: response.data.message
        })
      } else {
        return response.data
      }
    }, err)
    

    自定义角色的菜单权限

    • 在==src\main.js==文件中注释掉"// import './permission' // permission control 权限控制"
    • 自定义路由权限文件==src\routeGuard.js==,代码如下

     

    import Vue from 'vue'
    import router from './router'
    // import store from './store'
    
    import NProgress from 'nprogress' // progress bar
    import 'nprogress/nprogress.css' // progress bar style
    import { setDocumentTitle, domTitle } from '@/utils/domUtil'
    import { ACCESS_TOKEN } from '@/store/mutation-types'
    
    NProgress.configure({ showSpinner: false }) // NProgress Configuration
    
    router.beforeEach((to, from, next) => {
      NProgress.start() // start progress bar
      to.meta && (typeof to.meta.title !== 'undefined' && setDocumentTitle(`${to.meta.title} - ${domTitle}`))
      if (to.path === '/user/login' && Vue.ls.get(ACCESS_TOKEN)) {
        next({ path: '/dashboard/workplace' })
        NProgress.done()
      } else if (to.path !== '/user/login' && !Vue.ls.get(ACCESS_TOKEN)) {
        next({ path: '/user/login' })
        NProgress.done()
      } else {
        next()
        NProgress.done()
      }
    })
    
    router.afterEach(() => {
      NProgress.done() // finish progress bar
    })
    
    
    • 在==main.js==中引入import './routeGuard'
    • 对==src\components\Menu\menu.js==文件进行自定义菜单改造
    • 在==src\store\modules\app.js==文件中store加入menu,在actions中进行获取菜单的异步操作,获取菜单信息,然后进行全局变量动态获取
    • 在==src\layouts\BasicLayout.vue==中进行全局变量的引用

     

        ...mapState({
          // 动态主路由
          menus: state => state.app.menu
        }),
    

    动态方法的引用

     

    ...mapActions(['setSidebar', 'setMenu']),
    

    调用获取动态方法

     

    this.setMenu()


     

    展开全文
  • 基于AntDesignofVue实现的AntDesignProVue版
  • https://blog.csdn.net/m0_37938910/article/details/93318440

    https://blog.csdn.net/m0_37938910/article/details/93318440

    展开全文
  • 最近在用 ant design pro Vue,发现连传参都是问题,之前完全没有接触过vue,搞了半天,这里做下记录! list.vue - 传递参数 ---------------------- <div class="card-meta" @click="toDetailDoctor(item.Id)"&...
  • 蚂蚁设计学习专业版 项目设置 npm install 编译和热重装以进行开发 npm run serve 编译并最小化生产 npm run build 运行单元测试 npm run test:unit 整理和修复文件 npm run lint 自定义配置 请参阅。
  • ant design pro vue 踩坑

    2020-06-04 22:08:45
    在跟着官方文档一步步做的时候发现了一个问题,当使用babel-plugin-import按需... 遂照着网上的解决方案来做,但是发现很多方法都没用比如添加vue.config.js之类的,最终发现是less版本的问题,将less引入之后,它的版
  • 关于Ant-Design-Pro-Vue项目打包后无法预览问题 打包后的dist文件夹 打开index.html 一直处于加载状态 由于官方没有明确说明打包后的配置和部署,对于初学者来说以为打开index.html就可以预览了 预览打包后的项目...
  • const auth = Vue.directive('auth', { inserted: function (el, binding) { if (!Vue.prototype.$_has(binding.value)) { el.parentNode.removeChild(el) // el.setAttribute('disabled', 'disabled') // .
  • 基于 Ant Design of Vue 实现的 Ant Design Pro
  • Ant Design是蚂蚁金服体验技术部打磨出一个服务于企业级产品的设计体系,通过模块化解决方案降低生产成本。...ant pro vue 是一套基于Ant Design Vue的中后台管理控制台的脚手架。 直接从GitHub仓库中直接安装最...
  • 替换掉系统默认的图
  • Ant Design Pro Vue 全局国际化-设置中文

    千次阅读 2020-09-25 09:54:45
    我是vue-antd-pro 3.0版本,设置全局国际化包括日期控件,话不多说直接上手操作: 打开src/App.vue,修改script <script> import { domTitle, setDocumentTitle } from '@/utils/domUtil' import { i18...
  • 最近要要用 ant design pro Vue 前端框架,但是,(别人配置好)拉下代码后,npm start,结果报错: $ cnpm start npm ERR! missing script: start npm ERR! A complete log of this run can be found in: npm ERR!...
  • ant design pro vue 设置访问开发服务器api

    千次阅读 热门讨论 2019-06-11 23:15:11
    1.首先需要将src/mock下对应的接口注释...2.在 vue.config.js配置中增加如下内容 devServer: { // development server port 8888 port: 8000, proxy: { '/api': { // 匹配模式,所有api开始的连接都匹配到下面...
  • 欢迎来到vue-antd-pro :waving_hand: 基于vue-cli3和构建的后台管理系统模板,使用json-server做数据模型。 安装依赖 安装前端依赖 yarn 安装数据mock依赖 cd server yarn 运行 运行数据mock服务 // enter server ...
  • ant-design-vue是蚂蚁金服 Ant Design 官方唯一推荐的Vue版UI组件库,它其实是Ant DesignVue实现,组件的风格与Ant Design保持同步,组件的html结构和css样式也保持一致,很多朋友在使用过程中遇到很多问题,今天...
  • (我这里就是上线炸了,滑稽) Vue模块: 创建一个组件 {{$t('Map.MapInputDesc')}}: 引用模块 唤起地图 import addressSelection from '@/views/account/settings/page/AddressSelection' export default { name:...
  • 一个带角色权限控制的后台初始项目,前细分分离, Vue(antd) + PHP(Laravel) 功能 与laravel-admin一样的角色权限管理功能 文件管理器 配置管理 artisan命令 admin:init init- admin:init系统 admin:make-resource...
  • 问题1:Viser在响应式布局中,会导致图表超出的问题,或者跟随导航栏伸缩导致图表过窄或过长。 可能出现的原因!1.由于图表是Canvas画布,在他加载时只确定栅格布局的宽度,当导航栏再次伸缩,就出超出,溢出。...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,939
精华内容 1,175
关键字:

antdesignprovue

vue 订阅