权限管理:资源管理

说明:

  • 资源管理讲解数据展示数据分页数据筛选。添加,编辑,删除,以及资源分类中的所有功能均与菜单管理功能类似,这里就不再多赘述了

整体布局

将资源列表设置为单独组件(独立于resource/index.vue)
创建目录以及文件:
resource/components/list.vue

  • 使用Card组件设置外部结构
  • 头部使用Form组件的行内表单形式与数据
  • 内容设置Table组件并且设置数据
// resource/components/list.vue,暂且设置为这个样子
<template>
  <div class="resource-list">
    <el-card class="box-card">
      <div slot="header" class="clearfix">
        <el-form :inline="true" :model="formInline" class="demo-form-inline">
          <el-form-item label="审批人">
            <el-input v-model="formInline.user" placeholder="审批人"></el-input>
          </el-form-item>
          <el-form-item label="活动区域">
            <el-select v-model="formInline.region" placeholder="活动区域">
              <el-option label="区域一" value="shanghai"></el-option>
              <el-option label="区域二" value="beijing"></el-option>
            </el-select>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="onSubmit">查询</el-button>
          </el-form-item>
        </el-form>
      </div>
      <div>
        <el-table :data="tableData" style="width: 100%">
          <el-table-column prop="date" label="日期" width="180">
          </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>
      </div>
    </el-card>
  </div>
</template>

<script>
export default {
  name: 'ResourceList',
  data () {
    return {
      formInline: {},
      tableData: [{
        date: '2016-05-02',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1518 弄'
      },
      {
        date: '2016-05-04',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1517 弄'
      },
      {
        date: '2016-05-01',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1519 弄'
      },
      {
        date: '2016-05-03',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1516 弄'
      }]
    }
  },
  methods: {
    onSubmit () {
      console.log('submit!')
    }
  }
}
</script>

<style lang="scss" scoped>
</style>

在resource/index.vue导入

<template>
  <div class="resource">
    <resource-list></resource-list>
  </div>
</template>

<script>
import ResourceList from './components/list'
export default {
  name: 'ResourceIndex',
  components: {
    ResourceList
  }
}
</script>

<style lang="scss" scoped></style>

布局完毕

展示资源列表

使用的接口是按条件分页查询资源接口:接口地址
Postman 测试时注意,所有参数可选:

  • 无参数时需要传入空对象,这时响应数据的data.records为第一页的多余数据
  • 传入参数用于按条件筛选,如传入name,或者url,这时响应数据的data.records为筛选后的第一条
    • 接口支持模糊查询,例如传入"url":"menu",这时会响应多条满足条件的资料信息
      测试完毕之后,就可以封装接口到新模块中啦
// services/resource.js
import request from '@/utils/request'

// 资源请求
export const getResourcePages = data => {
  return request({
    method: 'POST',
    url: '/boss/resource/getResourcePages',
    data
  })
}

引入调用

// resource/components/list.vue
...
<script>
// 引入
import { getResourcePages } from '@/services/resource.js'

export default {
  ...
  created () {
    // 调用
    this.loadResources()
  },
  methods: {
    ...
    async loadResources () {
      // 请求,空对象必须传入,否则参数不完整导致接口报错
      const { data } = await getResourcePages({})
      console.log(data)
    }
  }
}
</script>

成功之后将数据存储到data.resourcs并且绑定到table组件中,要注意一点,日期的格式需要使用过滤器进行调整,详细参考代码:

<template>
  <div class="resource-list">
    <el-card class="box-card">
      <div slot="header" class="clearfix">
        <el-form :inline="true" :model="formInline" class="demo-form-inline">
          <el-form-item label="审批人">
            <el-input v-model="formInline.user" placeholder="审批人"></el-input>
          </el-form-item>
          <el-form-item label="活动区域">
            <el-select v-model="formInline.region" placeholder="活动区域">
              <el-option label="区域一" value="shanghai"></el-option>
              <el-option label="区域二" value="beijing"></el-option>
            </el-select>
          </el-form-item>
          <el-form-item>
            <el-button type="primary">查询</el-button>
          </el-form-item>
        </el-form>
      </div>
      <div>
        <el-table
        :data="resources"
        style="width: 100%">
          <el-table-column
          type="index"
          label="编号"
          width="100"
          ></el-table-column>
          <el-table-column
          prop="name"
          label="资源名称">
          </el-table-column>
          <el-table-column
          prop="url"
          label="资源路径">
          </el-table-column>
          <el-table-column
          prop="description"
          label="描述">
          </el-table-column>
          <!-- 过滤器需要使用作用于插槽获取数据才能进行功能处理 -->
          <el-table-column
          label="添加时间">
          <template slot-scope="scope">
              <span>{{ scope.row.createdTime | dateFormat }}</span>
          </template>
          </el-table-column>
          <el-table-column
          label="操作">
          <template slot-scope="scope">
              <el-button
              size="mini"
              @click="handleEdit(scope.row)"
              >编辑</el-button>
              <el-button
              size="mini"
              @click="handleDelete(scope.row)"
              type="danger"
              >删除</el-button>
          </template>
          </el-table-column>
        </el-table>
      </div>
    </el-card>
  </div>
</template>

<script>
import { getResourcePages } from '@/services/resource'
export default {
  name: 'ResourceList',
  data () {
    return {
      formInline: {},
      //   用于存储资源列表数据
      resources: []
    }
  },
  created () {
    this.loadResources()
  },
  methods: {
    onSubmit () {
      console.log('submit!')
    },
    async loadResources () {
      const { data } = await getResourcePages({})
      if (data.code === '000000') {
        this.resources = data.data.records
      }
    },
    handleEdit () {
    },
    handleDelete () {
    }
  },
  filters: {
    // 日期过滤器
    dateFormat (date) {
      date = new Date(date)
      return `
      ${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}
      ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}
      `
    }
  }
}
</script>

<style lang="scss" scoped>
</style>

table组件数据要使用过滤器,得需要通过自定义列模板方式设置插值表达式

分页处理

分页布局

使用Element的Pagination分页组件->附加功能->完善功能设置,将结构,方法,数据添加到list.vue中

// list.vue
<el-card class="box-card">
  ...
  <!-- 给 table 与 pagination 设置间距,看起来更美观 -->
  <el-table
    :data="resources"
    style="width: 100%; margin-bottom: 20px;">
  ...
  <!-- 分页功能 -->
  <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="currentPage4"
        :page-sizes="[100, 200, 300, 400]"
        :page-size="100"
        layout="total, sizes, prev, pager, next, jumper"
        :total="400">
  </el-pagination>
</el-card>
...
<script>
...
data () {
  return {
    ...
    currentPage1: 5,
    currentPage2: 5,
    currentPage3: 5,
    currentPage4: 4
  }
},
...
methods: {
  ...
  handleSizeChange (val) {
    console.log(`每页 ${val} 条`)
  },
  handleCurrentChange (val) {
    console.log(`当前页: ${val}`)
  }
},
...
</script>

分页功能

分页功能的接口存在两个比较重要的请求参数

  • current(当前页数)
  • size(每页条数)
    由于分页需要与筛选功能结合,所以将数据声明到data.form
    • 更改了form的名称之后,注意将模板中的数据名称同时修改(简单处理就可以了,后续还要设置功能)
    • 修改current时页面会渲染不同页的数据
// list.vue
data () {
  return {
    ...
    form: {
      ...
      // 当前页号,默认为 1
      current: 1,
      // 每页数据条数,例如为10,按需设置
      size: 10
    },
    ...
  }
},
methods: {
    async loadResources () {
  // 将参数传入请求
  const { data } = await getResourcePages({
    current: this.form.current,
    size: this.form.size
  })
  ...
},
}

分页组件的页面变化会触发handleCurrentChange事件,参数为当前页号,操作时请求当前页码的数据即可

// list.vue
// 页码变化时触发
handleCurrentChange (val) {
  // 将 val 同步给 current
  this.form.current = val
  // 请求更新数据
  this.loadResources()
}

注意:
这是我们发现页码按钮个数为固定值,应该进行设置,观察组件的属性

  • current-page:当前组件显示页码
    • this.form.current会更新请求的数据页码为1,而显示页码需要通过当前属性控制
    • 文档中说明当前属性支持.sycn修饰符
      设置:current-page.sync = "form.current"
      这样一来之前事件中的this.form.current = val就可以不需要设置了,视图操作导致属性的改变会自动同步到form.current中,反之亦然(与v-model有点类似)
  • total为数据总数
  • page-size为每页大小,应该绑定到form.size
  • page-sizes为左侧设置每页条数的下拉菜单,第一个值为初始值,不应大于总条数,否则只会出现一页,后续值自行按需设置

组件会根据上面的属性自动计算总页数,现在只有total应该通过请求获取

<el-pagination
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page.sync="form.current"
      :page-sizes="[10, 15, 20]"
      :page-size="form.size"
      layout="total, sizes, prev, pager, next, jumper"
      :total="totalCount">
    </el-pagination>

在请求数据的时候,接口响应数据包含了total为总数据条数,保存到data中并在created中接收

  • 数据中的currentPage1/2/3/4为文档提供的数据,可以直接删掉
data () {
  return {
    ...
    // 数据总条数
    totalCount: 0
  }
},
...
methods: {
  ...
  async loadResources () {
    ...
    if (data.code === '000000') {
      this.resources = data.data.records
      // 保存总条数
      this.totalCount = data.data.total
    }
  }
  ...
},

设置后页码可以切换了,但是更新每页条数只更改了页码,数据没有更新,于是我们这个时候可以通过组件的size-change事件处理

  • size-change会在每页条数发生变化时触发,参数为新的条数,赋值给form.size
  • 重置页码为1
  • 更新数据
// 每页显示条数触发事件
    handleSizeChange (val) {
      this.form.size = val
      // 由于修改了每一页现实的条数,应该归零页数
      this.form.current = 1
      this.loadResources()
    },

复杂但是也不是很难的分页功能就搞定了。

筛选处理

筛选功能

data 中声明数据,更新模板绑定数据,资源分类功能需要请求接口操作

  • 声明的数据名称需要根据接口请求参数设置,最后将form整体发送给接口
  • 添加一个重置按钮
form: {
  // 资源名称
  name: '',
  // 资源路径
  url: '',
  // 资源分类
  categoryId: ''
  ...
},
<el-form :inline="true" :model="form" class="demo-form-inline">
  <el-form-item label="资源名称">
    <el-input v-model="form.name" placeholder="资源名称"></el-input>
  </el-form-item>
  <el-form-item label="资源路径">
    <el-input v-model="form.url" placeholder="资源路径"></el-input>
  </el-form-item>
  <el-form-item label="资源分类">
    <el-select v-model="form.categoryId" placeholder="资源分类">
      <!-- 假数据,需要请求 -->
      <el-option label="区域一" value="shanghai"></el-option>
      <el-option label="区域二" value="beijing"></el-option>
    </el-select>
  </el-form-item>
  <el-form-item>
    <el-button type="primary" @click="onSubmit">查询搜索</el-button>
    <el-button>重置</el-button>
  </el-form-item>
</el-form>

查询资源分类列表:接口

// 新建文件 services/resource-category.js
import request from '@/utils/request'

// 资源分类请求
export const getResourceCategory = () => {
  return request({
    method: 'GET',
    url: '/boss/resource/category/getAll'
  })
}

引入并且请求数据

...
import { getResourceCategory } from '@/services/resource-category.js'
...
created () {
  ...
  this.loadResourceCategory()
},
...  
data () {
  return {
    // 资源分类列表
    resourceCategories: [],
    ...
  }
},
methods: {
  async loadResourceCategory () {
    const { data } = await getResourceCategory()
    if (data.code === '000000') {
      this.resourceCategories = data.data
    }
  },
  ...

遍历生成资源分类下拉菜单

<el-form-item label="资源分类">
  <el-select v-model="form.categoryId" placeholder="资源分类">
    <el-option
      :label="item.name"
      :value="item.id"
      v-for="item in resourceCategories"
      :key="item.id"
    ></el-option>
  </el-select>
</el-form-item>

提交时请求数据,同时更改页数为1

onSubmit () {
  // 筛选提交,请求数据 (将请求参数更改为整个 form)
  this.form.current = 1
  this.loadResources()
},
...
async loadResources () {
  // 将参数传入请求
  /* const { data } = await getResourcePages({
    current: this.form.current,
    size: this.form.size
  }) */
  const { data } = await getResourcePages(this.form)
  ...
},

清除功能

清除分为下拉菜单清除和统一清除(重置)
单个清除使用Element中select下拉框组件中的可清空单选功能

  • 给下拉框组件设置clearable属性就可以了
// list.vue
<el-select
  v-model="form.categoryId"
  placeholder="资源分类"
  clearable
>

表单重置操作需要清空表单

  • 表单组件提供了resetFields()用于重置具有prop的表单项
  • 表单需要设置ref
  • 需要给表单项添加prop才能使用,未设置prop的表单项不受重置影响
<el-form 
  :inline="true"
  :model="form"
  class="demo-form-inline"
  ref="form"
>
  <el-form-item label="资源名称" prop="name">
    <el-input v-model="form.name" placeholder="资源名称"></el-input>
  </el-form-item>
  <el-form-item label="资源路径" prop="url">
    <el-input v-model="form.url" placeholder="资源路径"></el-input>
  </el-form-item>
  <el-form-item label="资源分类" prop="categoryId">
...
<el-button
  @click="onReset"
>重置</el-button>
...
onReset () {
  this.$refs.form.resetFields()
},

这个方法可以将我们在菜单管理那里进行粗暴的清空方式给替换掉了

数据加载细节处理

网速慢的时候,显示加载中提示,同时禁用所有操作
这个时候使用Element的Loading加载组件设置

  • 通过指令v-loading控制,true表示加载中,false表示隐藏提示
  • 按钮与分页组件的禁用属性均为disabled
// list.vue
...
<el-button
  type="primary"
  @click="onSubmit"
  :disabled="isLoading"
>查询搜索</el-button>
...
<el-table
  :data="resources"
  style="width: 100%; margin-bottom: 20px;"
  v-loading="isLoading"
>
<el-button
  @click="onReset"
  :disabled="isLoading"
>重置</el-button>
...
<el-pagination
  ...
  :disbled="isLoading">
</el-pagination>
...
<script>
  
data () {
  return {
    ...
    // 加载状态
    isLoading: false
  }
},
...
async loadResources () {
  // 开始加载数据
  this.isLoading = true
  ...
  // 请求完毕取消加载中状态
  this.isLoading = false
},
</script>

资源的增删改都是重复性的知识,通过element加接口都可以完成
接口文档:接口

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容