Browse Source

Table-tree-column 替换 tree-table

daxiong.yang 7 years ago
parent
commit
64f9ed1878

+ 2 - 1
src/assets/scss/_base.scss

@ -10,7 +10,8 @@ body {
10 10
  color: #333;
11 11
  background-color: #f0f0f0;
12 12
}
13
*:focus {
13
*,
14
:focus {
14 15
  outline: 0;
15 16
}
16 17
a {

+ 10 - 18
src/components/table-tree-column/index.vue

@ -1,5 +1,5 @@
1 1
<template>
2
  <el-table-column :prop="prop" :label="label" :width="width">
2
  <el-table-column :prop="prop" v-bind="$attrs">
3 3
    <template slot-scope="scope">
4 4
      <span v-if="hasChild(scope.row)" @click.prevent="doexpanded(scope.$index,scope.row)" >
5 5
        <span :style="{paddingLeft : paddingLeft(scope.row)}">
@ -17,6 +17,7 @@
17 17
    </template>
18 18
  </el-table-column>
19 19
</template>
20
20 21
<script>
21 22
  import util from './util'
22 23
  export default {
@ -25,12 +26,6 @@
25 26
      prop: {
26 27
        type: String
27 28
      },
28
      label: {
29
        type: String
30
      },
31
      width: {
32
        type: String
33
      },
34 29
      treeKey: {
35 30
        type: String,
36 31
        default: 'id'
@ -76,6 +71,9 @@
76 71
    data () {
77 72
      return { loading: false }
78 73
    },
74
    created () {
75
      console.log(this.$attrs)
76
    },
79 77
    methods: {
80 78
      floderIcon (row) {
81 79
        var expanded = row.$extra && row.$extra.expanded
@ -91,23 +89,22 @@
91 89
        }
92 90
      },
93 91
      paddingLeft (row) {
94
        return parseInt(row[this.levelKey]) * 14 + 'px'
92
        return (parseInt(row[this.levelKey]) * 14) + 'px'
95 93
      },
96 94
      icon (row) {
97
        if (row.$extra && row.$extra.loading === true) return 'el-icon-loading'
95
        if (row.$extra && row.$extra.loading) return 'el-icon-loading'
98 96
        return row.$extra && row.$extra.expanded ? 'el-icon-caret-bottom' : 'el-icon-caret-right'
99 97
      },
100 98
      doexpanded (index, row) {
101 99
        var vm = this
102
        // var data = JSON.parse(JSON.stringify(this.owner.store.states._data))
103
        var data = this.owner.store.states._data
100
        var data = JSON.parse(JSON.stringify(this.owner.store.states._data))
104 101
        if (data[index].$extra === undefined) {
105 102
          data[index].$extra = { expanded: true }
106 103
        } else {
107 104
          data[index].$extra.expanded = !data[index].$extra.expanded
108 105
        }
109 106
        if (data[index].$extra.expanded) {
110
          if (this.remote != null) {
107
          if (this.remote !== null) {
111 108
            var hash = util.hash()
112 109
            data[index].$extra.expanded = false
113 110
            data[index].$extra.hash = hash
@ -146,12 +143,7 @@
146 143
        } else {
147 144
          var id = row[vm.treeKey]
148 145
          var result = []
149
          var removeIds = util.descendantsIds(
150
            id,
151
            data,
152
            this.parentKey,
153
            this.treeKey
154
          )
146
          var removeIds = util.descendantsIds(id, data, this.parentKey, this.treeKey)
155 147
          data.forEach(function (item) {
156 148
            if (util.indexOf(item[vm.treeKey], removeIds) === -1) {
157 149
              result.push(item)

+ 0 - 29
src/components/tree-table/eval.js

@ -1,29 +0,0 @@
1
/**
2
* @Author: jianglei
3
* @Date:   2017-10-12 12:06:49
4
*/
5
'use strict'
6
import Vue from 'vue'
7
export default function treeToArray (data, expandedAll, parent = null, level = null) {
8
  let tmp = []
9
  Array.from(data).forEach(function (record) {
10
    if (record._expanded === undefined) {
11
      Vue.set(record, '_expanded', expandedAll)
12
    }
13
    let _level = 1
14
    if (level !== undefined && level !== null) {
15
      _level = level + 1
16
    }
17
    Vue.set(record, '_level', _level)
18
    // 如果有父元素
19
    if (parent) {
20
      Vue.set(record, 'parent', parent)
21
    }
22
    tmp.push(record)
23
    if (record.children && record.children.length > 0) {
24
      const children = treeToArray(record.children, expandedAll, record, _level)
25
      tmp = tmp.concat(children)
26
    }
27
  })
28
  return tmp
29
}

+ 0 - 114
src/components/tree-table/index.vue

@ -1,114 +0,0 @@
1
<template>
2
  <el-table :data="formatData" :row-style="showRow" v-bind="$attrs">
3
    <el-table-column v-if="columns.length===0" width="150">
4
      <template slot-scope="scope">
5
        <span v-for="space in scope.row._level" class="ms-tree-space" :key="space"></span>
6
        <span class="tree-ctrl" v-if="iconShow(0,scope.row)" @click="toggleExpanded(scope.$index)">
7
          <i v-if="!scope.row._expanded" class="el-icon-arrow-right"></i>
8
          <i v-else class="el-icon-arrow-down"></i>
9
        </span>
10
        {{scope.$index}}
11
      </template>
12
    </el-table-column>
13
    <el-table-column v-else v-for="(column, index) in columns" :key="column.value" :label="column.text" :width="column.width" header-align="center">
14
      <template slot-scope="scope">
15
        <span v-if="index === 0" v-for="space in scope.row._level" class="ms-tree-space" :key="space"></span>
16
        <span class="tree-ctrl" v-if="iconShow(index,scope.row)" @click="toggleExpanded(scope.$index)">
17
          <i v-if="!scope.row._expanded" class="el-icon-arrow-right"></i>
18
          <i v-else class="el-icon-arrow-down"></i>
19
        </span>
20
        {{scope.row[column.value]}}
21
      </template>
22
    </el-table-column>
23
    <slot></slot>
24
  </el-table>
25
</template>
26
27
<script>
28
/**
29
  Auth: Lei.j1ang
30
  Created: 2018/1/19-13:59
31
*/
32
import treeToArray from './eval'
33
export default {
34
  name: 'treeTable',
35
  props: {
36
    data: {
37
      type: [Array, Object],
38
      required: true
39
    },
40
    columns: {
41
      type: Array,
42
      default: () => []
43
    },
44
    evalFunc: Function,
45
    evalArgs: Array,
46
    expandAll: {
47
      type: Boolean,
48
      default: false
49
    }
50
  },
51
  computed: {
52
    // 格式化数据源
53
    formatData: function () {
54
      let tmp
55
      if (!Array.isArray(this.data)) {
56
        tmp = [this.data]
57
      } else {
58
        tmp = this.data
59
      }
60
      const func = this.evalFunc || treeToArray
61
      const args = this.evalArgs ? Array.concat([tmp], this.evalArgs) : [tmp, this.expandAll]
62
      return func.apply(null, args)
63
    }
64
  },
65
  methods: {
66
    showRow: function (row) {
67
      const show = (row.row.parent ? (row.row.parent._expanded && row.row.parent._show) : true)
68
      row.row._show = show
69
      return show ? '' : 'display:none;'
70
    },
71
    // 切换下级是否展开
72
    toggleExpanded: function (trIndex) {
73
      const record = this.formatData[trIndex]
74
      record._expanded = !record._expanded
75
    },
76
    // 图标显示
77
    iconShow (index, record) {
78
      return (index === 0 && record.children && record.children.length > 0)
79
    }
80
  }
81
}
82
</script>
83
84
<style lang="scss" rel="stylesheet/scss" scoped>
85
  $color-blue: #2196F3;
86
  $space-width: 18px;
87
  .ms-tree-space {
88
    position: relative;
89
    top: 1px;
90
    display: inline-block;
91
    font-style: normal;
92
    font-weight: 400;
93
    line-height: 1;
94
    width: $space-width;
95
    height: 14px;
96
    &::before {
97
      content: ""
98
    }
99
  }
100
  .processContainer{
101
    width: 100%;
102
    height: 100%;
103
  }
104
  table td {
105
    line-height: 26px;
106
  }
107
108
  .tree-ctrl{
109
    position: relative;
110
    cursor: pointer;
111
    // color: $color-blue;
112
    margin-left: -$space-width;
113
  }
114
</style>

+ 0 - 89
src/components/tree-table/readme.md

@ -1,89 +0,0 @@
1
## 写在前面
2
此组件仅提供一个创建TreeTable的解决思路
3
4
## prop说明
5
#### *data*
6
  **必填**
7
8
  原始数据,要求是一个数组或者对象
9
  ```javascript
10
    [{
11
      key1: value1,
12
      key2: value2,
13
      children: [{
14
        key1: value1
15
      },
16
      {
17
        key1: value1
18
      }]
19
    },
20
    {
21
      key1: value1
22
    }]
23
  ```
24
  或者
25
 ```javascript
26
    {
27
      key1: value1,
28
      key2: value2,
29
      children: [{
30
        key1: value1
31
      },
32
      {
33
        key1: value1
34
      }]
35
    }
36
  ```
37
38
#### columns
39
  列属性,要求是一个数组
40
41
  1. text: 显示在表头的文字
42
  2. value: 对应data的key。treeTable将显示相应的value
43
  3. width: 每列的宽度,为一个数字(可选)
44
  
45
  如果你想要每个字段都有自定义的样式或者嵌套其他组件,columns可不提供,直接像在el-table一样写即可,如果没有自定义内容,提供columns将更加的便捷方便
46
  
47
  如果你有几个字段是需要自定义的,几个不需要,那么可以将不需要自定义的字段放入columns,将需要自定义的内容放入到slot中,详情见后文
48
  ```javascript
49
  [{
50
    value:string,
51
    text:string,
52
    width:number
53
  },{
54
    value:string,
55
    text:string,
56
    width:number
57
  }]
58
  ```
59
60
#### expandAll
61
  是否默认全部展开,boolean值,默认为false
62
63
#### evalFunc
64
  解析函数,function,非必须
65
66
  如果不提供,将使用默认的[evalFunc](./eval.js)
67
68
  如果提供了evalFunc,那么会用提供的evalFunc去解析data,并返回treeTable渲染所需要的值。如何编写一个evalFunc,请参考[*eval.js*](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/components/TreeTable/eval.js)或[*customEval.js*](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/example/table/treeTable/customEval.js)
69
70
#### evalArgs
71
  解析函数的参数,是一个数组
72
73
  **请注意,自定义的解析函数参数第一个为this.data,你不需要在evalArgs填写。** *this.data为需要解析的数据*
74
75
  如你的解析函数需要的参数为`(this.data,1,2,3,4)`,那么你只需要将`[1,2,3,4]`赋值给`evalArgs`就可以了
76
  
77
  如果你的解析函数参数只有一个`(this.data)`,那么就可以不用填写evalArgs了
78
  
79
  具体可参考[*customEval.js*](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/example/table/treeTable/customEval.js)的函数参数和[customTreeTable](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/example/table/treeTable/customTreeTable.vue)的`evalArgs`属性值
80
81
 ## slot
82
 这是一个自定义列的插槽。
83
 
84
 默认情况下,treeTable只有一行行展示数据的功能。但是一般情况下,我们会要给行加上一个操作按钮或者根据当行数据展示不同的样式,这时我们就需要自定义列了。请参考[customTreeTable](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/example/table/treeTable/customTreeTable.vue),[实例效果](http://panjiachen.github.io/vue-element-admin/#/example/table/custom-tree-table)
85
 
86
 `slot`和`columns属性`可同时存在,columns里面的数据列会在slot自定义列的左边展示
87
88
 ## 其他
89
  如果有其他的需求,请参考[el-table](http://element-cn.eleme.io/#/en-US/component/table)的api自行修改index.vue

+ 0 - 1
src/router/index.js

@ -12,7 +12,6 @@ Vue.use(Router)
12 12
export default new Router({
13 13
  mode: 'hash',
14 14
  routes: [
15
    { path: '/tree-table', component: _import('tree-table/index'), name: 'treeTable', desc: '树型表格' },
16 15
    { path: '/404', component: _import('error/404'), name: '404', desc: '404未找到' },
17 16
    { path: '/login', component: _import('login/index'), name: 'login', desc: '登录' },
18 17
    {

+ 17 - 14
src/views/menu/index.vue

@ -5,17 +5,27 @@
5 5
        <el-button v-if="isAuth('sys:user:save')" type="primary" @click="addOrUpdateHandle()">新增</el-button>
6 6
      </el-form-item>
7 7
    </el-form>
8
    <tree-table
9
      :columns="treeTableColumns"
8
    <el-table
10 9
      :data="dataList"
11 10
      border
12 11
      style="width: 100%;">
13 12
      <el-table-column
14
        prop="name"
13
        prop="menuId"
15 14
        header-align="center"
16 15
        align="center"
17
        label="菜单名称">
16
        width="80"
17
        label="ID">
18 18
      </el-table-column>
19
      <table-tree-column
20
        prop="name"
21
        header-align="center"
22
        align="center"
23
        file-icon="icon icon-file" 
24
        folder-icon="icon icon-folder" 
25
        treeKey="menuId"
26
        min-width="120"
27
        label="名称">
28
      </table-tree-column>
19 29
      <el-table-column
20 30
        prop="parentName"
21 31
        header-align="center"
@ -74,14 +84,14 @@
74 84
          <el-button v-if="isAuth('sys:user:delete')" type="text" size="small" @click="deleteHandle(scope.row.menuId)">删除</el-button>
75 85
        </template>
76 86
      </el-table-column>
77
    </tree-table>
87
    </el-table>
78 88
    <!-- 弹窗, 新增 / 修改 -->
79 89
    <add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate" @refreshDataList="getDataList"></add-or-update>
80 90
  </div>
81 91
</template>
82 92
83 93
<script>
84
  import TreeTable from '@/components/tree-table'
94
  import TableTreeColumn from '@/components/table-tree-column'
85 95
  import AddOrUpdate from './add-or-update'
86 96
  import API from '@/api'
87 97
  import { treeDataTranslate } from '@/utils'
@ -89,20 +99,13 @@
89 99
    data () {
90 100
      return {
91 101
        dataForm: {},
92
        treeTableColumns: [
93
          {
94
            text: 'ID',
95
            value: 'menuId',
96
            width: '120'
97
          }
98
        ],
99 102
        dataList: [],
100 103
        dataListLoading: false,
101 104
        addOrUpdateVisible: false
102 105
      }
103 106
    },
104 107
    components: {
105
      TreeTable,
108
      TableTreeColumn,
106 109
      AddOrUpdate
107 110
    },
108 111
    activated () {

+ 0 - 138
src/views/tree-table/data.js

@ -1,138 +0,0 @@
1
export default [{
2
  'id': 1,
3
  'label': 'System',
4
  'parent_id': null,
5
  'url': null,
6
  'depth': 0,
7
  'child_num': 3,
8
  'description': 'System Manager',
9
  'children': [{
10
    'id': 2,
11
    'label': 'base',
12
    'parent_id': 1,
13
    'url': null,
14
    'depth': 1,
15
    'child_num': 5,
16
    'description': 'Base Manager',
17
    'expanded': true,
18
    'children': [{
19
      'id': 3,
20
      'label': 'Menus',
21
      'parent_id': 2,
22
      'url': '/menus',
23
      'depth': 2,
24
      'child_num': 0,
25
      'description': 'menu manager'
26
    }, {
27
      'id': 4,
28
      'label': 'Roles',
29
      'parent_id': 2,
30
      'url': '/roles',
31
      'depth': 2,
32
      'child_num': 0,
33
      'description': 'Role Manager'
34
    }, {
35
      'id': 5,
36
      'label': 'Users',
37
      'parent_id': 2,
38
      'url': '/users',
39
      'depth': 2,
40
      'child_num': 0,
41
      'description': 'User Manager'
42
    }]
43
  }]
44
}, {
45
  'id': 6,
46
  'label': 'Customs',
47
  'parent_id': null,
48
  'url': null,
49
  'depth': 0,
50
  'child_num': 2,
51
  'description': 'Custom Manager',
52
  'children': [{
53
    'id': 7,
54
    'label': 'CustomList',
55
    'parent_id': 6,
56
    'url': '/customs',
57
    'depth': 1,
58
    'child_num': 0,
59
    'description': 'CustomList'
60
  }]
61
}, {
62
  'id': 8,
63
  'label': 'Templates',
64
  'parent_id': null,
65
  'url': null,
66
  'depth': 0,
67
  'child_num': 1,
68
  'description': 'Template Manager',
69
  'children': [{
70
    'id': 9,
71
    'label': 'TemplateList',
72
    'parent_id': 8,
73
    'url': '/doc_templates',
74
    'depth': 1,
75
    'child_num': 0,
76
    'description': 'Template Manager'
77
  }]
78
}, {
79
  'id': 10,
80
  'label': 'Bussiness',
81
  'parent_id': null,
82
  'url': null,
83
  'depth': 0,
84
  'child_num': 2,
85
  'description': 'Bussiness Manager',
86
  'expanded': true,
87
  'children': [{
88
    'id': 11,
89
    'label': 'BussinessList',
90
    'parent_id': 10,
91
    'url': null,
92
    'depth': 1,
93
    'child_num': 2,
94
    'description': 'BussinessList',
95
    'children': [{
96
      'id': 12,
97
      'label': 'Currencies',
98
      'parent_id': 11,
99
      'url': '/currencies',
100
      'depth': 2,
101
      'child_num': 0,
102
      'description': 'Currencies'
103
    }, {
104
      'id': 13,
105
      'label': 'Dealtypes',
106
      'parent_id': 11,
107
      'url': '/dealtypes',
108
      'depth': 2,
109
      'child_num': 0,
110
      'description': 'Dealtypes'
111
    }]
112
  }, {
113
    'id': 14,
114
    'label': 'Products',
115
    'parent_id': 10,
116
    'url': null,
117
    'depth': 1,
118
    'child_num': 2,
119
    'description': 'Products',
120
    'children': [{
121
      'id': 15,
122
      'label': 'ProductTypes',
123
      'parent_id': 14,
124
      'url': '/productTypes',
125
      'depth': 2,
126
      'child_num': 0,
127
      'description': 'ProductTypes'
128
    }, {
129
      'id': 16,
130
      'label': 'ProductList',
131
      'parent_id': 14,
132
      'url': '/products',
133
      'depth': 2,
134
      'child_num': 0,
135
      'description': 'ProductList'
136
    }]
137
  }]
138
}]

+ 0 - 147
src/views/tree-table/index.vue

@ -1,147 +0,0 @@
1
<template>
2
  <div class="mod-dept">
3
    <tree-table
4
      :columns="treeTableColumns"
5
      :data="dataList"
6
      border
7
      style="width: 100%;">
8
      <el-table-column
9
        prop="name"
10
        header-align="center"
11
        align="center"
12
        label="菜单名称">
13
      </el-table-column>
14
      <el-table-column
15
        prop="parentName"
16
        header-align="center"
17
        align="center"
18
        label="上级菜单">
19
      </el-table-column>
20
      <el-table-column
21
        prop="icon"
22
        header-align="center"
23
        align="center"
24
        label="图标">
25
        <template slot-scope="scope">
26
          <i :class="['fa-lg', scope.row.icon]"></i>
27
        </template>
28
      </el-table-column>
29
      <el-table-column
30
        prop="type"
31
        header-align="center"
32
        align="center"
33
        label="类型">
34
        <template slot-scope="scope">
35
          <el-tag v-if="scope.row.type === 0" size="small">目录</el-tag>
36
          <el-tag v-else-if="scope.row.type === 1" size="small" type="success">菜单</el-tag>
37
          <el-tag v-else-if="scope.row.type === 2" size="small" type="info">按钮</el-tag>
38
        </template>
39
      </el-table-column>
40
      <el-table-column
41
        prop="orderNum"
42
        header-align="center"
43
        align="center"
44
        label="排序号">
45
      </el-table-column>
46
      <el-table-column
47
        prop="url"
48
        header-align="center"
49
        align="center"
50
        width="150"
51
        :show-overflow-tooltip="true"
52
        label="菜单URL">
53
      </el-table-column>
54
      <el-table-column
55
        prop="perms"
56
        header-align="center"
57
        align="center"
58
        width="150"
59
        :show-overflow-tooltip="true"
60
        label="授权标识">
61
      </el-table-column>
62
      <el-table-column
63
        header-align="center"
64
        align="center"
65
        width="200"
66
        label="操作">
67
        <template slot-scope="scope">
68
          <el-button v-if="isAuth('sys:user:update')" type="text" size="small" @click="addOrUpdateHandle(scope.row.menuId)">修改</el-button>
69
          <el-button v-if="isAuth('sys:user:delete')" type="text" size="small" @click="deleteHandle(scope.row.menuId)">删除</el-button>
70
        </template>
71
      </el-table-column>
72
    </tree-table>
73
    <!-- <el-table :data="treeData" border max-height="250">
74
      <el-table-column
75
        prop="parentName"
76
        header-align="center"
77
        align="center"
78
        label="上级菜单">
79
      </el-table-column>
80
      <table-tree-column 
81
        file-icon="icon icon-file" 
82
        folder-icon="icon icon-folder" 
83
        prop="value" label="名称" width="220">
84
      </table-tree-column>
85
      <el-table-column
86
        prop="icon"
87
        header-align="center"
88
        align="center"
89
        label="图标">
90
        <template slot-scope="scope">
91
          <i :class="['fa-lg', scope.row.icon]"></i>
92
        </template>
93
      </el-table-column>
94
  </el-table> -->
95
    <el-table :data="dataList" border max-height="400">
96
      <el-table-column prop="id" label="id" width="180"></el-table-column>
97
      <table-tree-column 
98
        file-icon="icon icon-file" 
99
        folder-icon="icon icon-folder" 
100
        prop="label" label="MenuName" width="320">
101
      </table-tree-column>
102
      <el-table-column prop="description" label="Description" :show-overflow-tooltip="true" width="180"></el-table-column>
103
    </el-table>
104
  </div>
105
</template>
106
107
<script>
108
  import TreeTable from '@/components/tree-table'
109
  import TableTreeColumn from '@/components/table-tree-column/index.vue'
110
  import Data from './data.js'
111
  import API from '@/api'
112
  import { treeDataTranslate } from '@/utils'
113
  export default {
114
    data () {
115
      return {
116
        treeTableColumns: [
117
          {
118
            text: '名称',
119
            value: 'name',
120
            width: 200
121
          }
122
        ],
123
        dataList: [],
124
        treeData: []
125
      }
126
    },
127
    components: {
128
      TreeTable,
129
      TableTreeColumn
130
    },
131
    created () {
132
      this.treeData = Data
133
      console.log(this.treeData)
134
      this.getDataList()
135
    },
136
    methods: {
137
      // 获取数据列表
138
      getDataList () {
139
        this.dataListLoading = true
140
        API.menu.list().then(({data}) => {
141
          this.dataList = treeDataTranslate(data, 'menuId')
142
          this.dataListLoading = false
143
        })
144
      }
145
    }
146
  }
147
</script>