zydx-plus 1.3.22 → 1.4.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zydx-plus",
3
- "version": "1.3.22",
3
+ "version": "1.4.22",
4
4
  "description": "Vue.js",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -0,0 +1,6 @@
1
+ import main from './src/data_table.vue';
2
+
3
+ main.install = function(Vue) {
4
+ Vue.component(main.name, main);
5
+ };
6
+ export default main;
@@ -0,0 +1,273 @@
1
+ <script>
2
+ import { VueDraggableNext } from 'vue-draggable-next'
3
+ import tableHead from './table_head.vue'
4
+ import tableRow from './table_row.vue'
5
+ import { defineComponent } from 'vue';
6
+ export function getColKey(col) {
7
+ if (col.type === 'checkbox') return '__n_checkbox__'
8
+ return col.key
9
+ }
10
+ function getRowsAndCols(
11
+ columns
12
+ ) {
13
+ const rows = []
14
+ const cols = []
15
+ const dataRelatedCols = []
16
+ const rowItemMap = new WeakMap()
17
+ let maxDepth = -1
18
+ let totalRowSpan = 0
19
+ let hasEllipsis = false
20
+ function ensureMaxDepth(columns, currentDepth) {
21
+ if (currentDepth > maxDepth) {
22
+ rows[currentDepth] = []
23
+ maxDepth = currentDepth
24
+ }
25
+ for (const column of columns) {
26
+ if ('children' in column) {
27
+ ensureMaxDepth(column.children, currentDepth + 1)
28
+ } else {
29
+ cols.push({
30
+ key: getColKey(column),
31
+ column
32
+ })
33
+ totalRowSpan += 1
34
+ if (!hasEllipsis) {
35
+ hasEllipsis = !!column.ellipsis
36
+ }
37
+ dataRelatedCols.push(column)
38
+ }
39
+ }
40
+ }
41
+ ensureMaxDepth(columns, 0)
42
+ let currentLeafIndex = 0
43
+ function ensureColLayout(columns, currentDepth) {
44
+ let hideUntilIndex = 0
45
+ columns.forEach((column) => {
46
+ if ('children' in column) {
47
+ // do not allow colSpan > 1 for non-leaf th
48
+ // we will execute the calculation logic
49
+ const cachedCurrentLeafIndex = currentLeafIndex
50
+ const rowItem = {
51
+ column,
52
+ colSpan: 0,
53
+ rowSpan: 1,
54
+ isLast: false
55
+ }
56
+ ensureColLayout(column.children, currentDepth + 1)
57
+ column.children.forEach((childColumn) => {
58
+ rowItem.colSpan += rowItemMap.get(childColumn)?.colSpan ?? 0
59
+ })
60
+ if (cachedCurrentLeafIndex + rowItem.colSpan === totalRowSpan) {
61
+ rowItem.isLast = true
62
+ }
63
+ rowItemMap.set(column, rowItem)
64
+ rows[currentDepth].push(rowItem)
65
+ } else {
66
+ if (currentLeafIndex < hideUntilIndex) {
67
+ currentLeafIndex += 1
68
+ return
69
+ }
70
+ let colSpan = 1
71
+ if ('titleColSpan' in column) {
72
+ colSpan = column.titleColSpan ?? 1
73
+ }
74
+ if (colSpan > 1) {
75
+ hideUntilIndex = currentLeafIndex + colSpan
76
+ }
77
+ const isLast = currentLeafIndex + colSpan === totalRowSpan
78
+ const rowItem = {
79
+ column,
80
+ colSpan,
81
+ rowSpan: maxDepth - currentDepth + 1,
82
+ isLast
83
+ }
84
+ rowItemMap.set(column, rowItem)
85
+ rows[currentDepth].push(rowItem)
86
+ currentLeafIndex += 1
87
+ }
88
+ })
89
+ }
90
+ ensureColLayout(columns, 0)
91
+
92
+ return {
93
+ hasEllipsis,
94
+ rows,
95
+ cols,
96
+ dataRelatedCols
97
+ }
98
+ }
99
+
100
+ export default defineComponent({
101
+ name: 'zydx-table',
102
+ components: {
103
+ VueDraggableNext,
104
+ tableHead,
105
+ tableRow
106
+ },
107
+ props: {
108
+ columns: {
109
+ type: Array,
110
+ default: () => []
111
+ },
112
+ data: {
113
+ type: Array,
114
+ default: () => []
115
+ },
116
+ checkedRowKeys: {
117
+ type: Array,
118
+ default: () => []
119
+ },
120
+ maxHeight: {
121
+ type: Number,
122
+ default: 0
123
+ },
124
+ maxWidth: {
125
+ type: Number,
126
+ default: 0
127
+ },
128
+ draggable: {
129
+ type: Boolean,
130
+ default: false
131
+ }
132
+ },
133
+ data() {
134
+ return {
135
+ rows: [],
136
+ cols: [],
137
+ checkbox_state: [],
138
+ draggable_state: []
139
+ }
140
+ },
141
+ emits: ['update:model-value'],
142
+ mounted() {
143
+ const { rows, cols } = getRowsAndCols(this.columns)
144
+ this.rows = rows
145
+ this.cols = cols
146
+ this.draggable_state = [...this.data]
147
+ if (this.columns[0]?.type === 'checkbox') {
148
+ this.checkbox_state = Array.from({ length: this.data.length + 1 }, () => { return false })
149
+ }
150
+ },
151
+ methods: {
152
+ onDragEnd: function (payload) {
153
+ const { oldIndex, newIndex } = payload
154
+ let state = [...this.draggable_state]
155
+ let item = state.splice(oldIndex - 1, 1)[0]
156
+ state.splice(newIndex - 1, 0, item)
157
+ this.draggable_state = state
158
+ },
159
+ onCheckboxClick: function (idx) {
160
+ if (idx === 0) {
161
+ if (this.checkbox_state[0]) {
162
+ // 取消全选
163
+ this.checkbox_state = Array.from({ length: this.data.length + 1 }, () => { return false })
164
+ } else {
165
+ // 全选
166
+ this.checkbox_state = Array.from({ length: this.data.length + 1 }, () => { return true })
167
+ }
168
+ } else {
169
+ this.checkbox_state[idx] = !this.checkbox_state[idx]
170
+ }
171
+ this.$emit('update:checkedRow', this.checked_row)
172
+ }
173
+ },
174
+
175
+ provide() {
176
+ return {
177
+ onCheckboxClick: this.onCheckboxClick,
178
+ }
179
+ },
180
+ computed: {
181
+ getHeight() {
182
+ if (this.maxHeight) {
183
+ return {
184
+ maxHeight: this.maxHeight + 'px'
185
+ }
186
+ } else {
187
+ return ''
188
+ }
189
+ },
190
+ getWidth() {
191
+ if (this.maxWidth) {
192
+ return {
193
+ maxWidth: this.maxWidth + 'px'
194
+ }
195
+ } else {
196
+ return ''
197
+ }
198
+ },
199
+ checked_row() {
200
+ return this.checkbox_state.reduce((acc, cur, idx) => {
201
+ if (cur && idx !== 0) {
202
+ acc.push(this.data[idx - 1])
203
+ }
204
+ return acc
205
+ }, [])
206
+ }
207
+ },
208
+ render() {
209
+ const { draggable, rows, cols, data, getHeight, getWidth, onDragEnd, checkbox_state } = this
210
+ return (
211
+ <div class="table_wrapper" style={[getHeight, getWidth]}>
212
+ {
213
+ draggable
214
+ ? (
215
+ <div class="table_root" aria-label='draggbale-table'>
216
+ <VueDraggableNext tag={"table"} animation={"200"} onEnd={onDragEnd} >
217
+ <table-head rows={rows} checked={checkbox_state[0]}></table-head>
218
+ {
219
+ data.map((row, idx) => (
220
+ <table-row checked={checkbox_state[idx + 1]} cols={cols} row={row} draggable={draggable} data_row={idx + 1} />
221
+ ))
222
+ }
223
+ </VueDraggableNext>
224
+ </div>
225
+ )
226
+ : (
227
+ <table class="table_root" aria-label='simple-table'>
228
+ <table-head rows={rows} checked={checkbox_state[0]}></table-head>
229
+ <tbody class="table_body">
230
+ {
231
+ data.map((row, idx) => (
232
+ <table-row checked={checkbox_state[idx + 1]} cols={cols} row={row} draggable={draggable} data_row={idx + 1} />
233
+ ))
234
+ }
235
+ </tbody>
236
+ </table>
237
+ )
238
+ }
239
+ </div >
240
+ )
241
+ }
242
+ })
243
+ </script>
244
+ <style scoped>
245
+ .table_wrapper {
246
+ width: auto;
247
+ position: relative;
248
+ opacity: 1;
249
+ overflow: scroll;
250
+ }
251
+
252
+ .table_wrapper::-webkit-scrollbar {
253
+ display: none;
254
+ /* or add it to the track */
255
+ }
256
+
257
+
258
+ .table_root {
259
+ table-layout: fixed;
260
+ display: table;
261
+ max-width: 100%;
262
+ border-top: 1px solid #cccccc;
263
+ border-left: 1px solid #cccccc;
264
+ margin: 0 auto;
265
+ border-spacing: 0;
266
+ }
267
+
268
+
269
+ .table_body {
270
+ position: relative;
271
+ width: 100%;
272
+ }
273
+ </style>
@@ -0,0 +1,113 @@
1
+ <template>
2
+ <thead class="table_head">
3
+ <tr v-for=" (row, idx) in rows"
4
+ class="table_row"
5
+ :key="idx">
6
+ <th v-for="({ key, rowSpan, colSpan, column }) in row"
7
+ :key="key"
8
+ class="table_cell"
9
+ :data-col-key="key"
10
+ :rowspan="rowSpan"
11
+ :colspan="colSpan"
12
+ :style="sticky({ level: idx, column: column })">
13
+ <template v-if="column.type === 'checkbox'">
14
+ <td class="checkbox_container table_cell">
15
+ <input type="checkbox"
16
+ @click="() => onCheckboxClick(0)"
17
+ :checked="checked">
18
+ </td>
19
+ </template>
20
+ <template v-else>
21
+ {{ column.title }}
22
+ </template>
23
+ </th>
24
+ </tr>
25
+ </thead>
26
+ </template>
27
+
28
+ <script>
29
+ <thead class="table_head">
30
+ </thead>
31
+ import { defineComponent } from 'vue';
32
+ export default defineComponent({
33
+ name: 'table-head',
34
+ props: {
35
+ rows: {
36
+ type: Array,
37
+ default: () => []
38
+ },
39
+ checked: {
40
+ type: Boolean,
41
+ default: false
42
+ }
43
+ },
44
+ data() {
45
+ return {
46
+ }
47
+ },
48
+ inject: ['onCheckboxClick'],
49
+ methods: {
50
+ sticky: function ({ level, column }) {
51
+ return ` background: white;
52
+ position: sticky;
53
+ z-index: 5;
54
+ min-width: ${column.width}px;
55
+ max-width: ${column.width}px;
56
+ top: ${level * 31}px;}`
57
+ }
58
+ }
59
+ })
60
+ </script>
61
+
62
+ <style scoped>
63
+ .checkbox_container {
64
+ width: 36px;
65
+ height: 30px;
66
+ display: flex;
67
+ align-items: center;
68
+ justify-content: center;
69
+ }
70
+
71
+ .table_row {
72
+ height: 30px;
73
+ box-sizing: border-box;
74
+ }
75
+
76
+ .table_row>.table_cell {
77
+ border-right: 1px solid #ccc;
78
+ border-bottom: 1px solid #ccc;
79
+
80
+ }
81
+
82
+ .table_head {
83
+ position: relative;
84
+ z-index: 5;
85
+ background: white
86
+ }
87
+
88
+ th,
89
+ td {
90
+ text-overflow: ellipsis;
91
+ white-space: nowrap;
92
+ overflow: hidden;
93
+ }
94
+
95
+
96
+ .table_head .table_cell {
97
+ font-weight: normal;
98
+ }
99
+
100
+ .table_cell {
101
+ text-align: center;
102
+ text-align: center;
103
+ line-height: 30px;
104
+ }
105
+
106
+ th {
107
+ background: white;
108
+ position: sticky;
109
+ z-index: 5;
110
+ top: 0;
111
+ /* Don't forget this, required for the stickiness */
112
+ }
113
+ </style>
@@ -0,0 +1,151 @@
1
+ <script>
2
+ import { defineComponent, Fragment, Transition } from 'vue';
3
+ export default defineComponent({
4
+ name: 'table-row',
5
+ props: {
6
+ row: {
7
+ type: Object,
8
+ default: () => ({})
9
+ },
10
+ cols: {
11
+ type: Array,
12
+ default: () => []
13
+ },
14
+ data_row: {
15
+ type: Number,
16
+ default: 1
17
+ },
18
+ checked: {
19
+ type: Boolean,
20
+ default: false
21
+ },
22
+ draggable: {
23
+ type: Boolean,
24
+ default: true
25
+ }
26
+ },
27
+ inject: ['onCheckboxClick'],
28
+ render() {
29
+ const { cols, row, data_row, draggable, checked, onCheckboxClick } = this
30
+ const { renderExpand, expandable } = row
31
+ const renderCell = () => {
32
+ return cols.map(({ column, key }) => {
33
+ const { width, type } = column
34
+ return typeof row[key] === 'function'
35
+ ?
36
+ (
37
+ <td class="table_cell" style={`min-width:${width}px; max-width:${width}px;`} rowspan={1} colspan={1} data-col-key={key}>
38
+ {row[key](row)}
39
+ </td>
40
+ )
41
+ :
42
+ type === 'checkbox'
43
+
44
+ ? (
45
+ <td class="checkbox_container table_cell">
46
+ <input type="checkbox" checked={checked} onClick={() => onCheckboxClick(data_row)} />
47
+ </td>
48
+ )
49
+ : (
50
+ <td class="table_cell" style={`min-width:${width}px; max-width:${width}px;`} rowspan={1} colspan={1} data-col-key={key}>
51
+ {row[key]}
52
+ </td>
53
+ )
54
+ })
55
+ }
56
+ const renderExpandable = () => {
57
+ return renderExpand && (
58
+ <Transition>
59
+ {
60
+ expandable && (
61
+ <tr class='table_row'>
62
+ <td class='table_cell expandable' role='description' colspan={cols.length}>
63
+ {renderExpand(row)}
64
+ </td>
65
+ </tr>
66
+
67
+ )
68
+ }
69
+ </Transition>
70
+ )
71
+ }
72
+ const renderRow = () => (
73
+ <Fragment>
74
+ <tr class="table_row" data-row={data_row}>
75
+ {
76
+ renderCell()
77
+ }
78
+ </tr>
79
+ {
80
+ renderExpandable()
81
+ }
82
+ </Fragment>)
83
+ const renderDraggable = () => (
84
+ <Fragment>
85
+ <tbody class="table_body move" data-row={data_row} >
86
+ <tr class="table_row">
87
+ {
88
+ renderCell()
89
+ }
90
+ </tr>
91
+ {
92
+ renderExpandable()
93
+ }
94
+ </tbody>
95
+ </Fragment>
96
+ )
97
+ return (
98
+ draggable
99
+ ? renderDraggable()
100
+ : renderRow()
101
+ )
102
+ }
103
+ })
104
+ </script>
105
+
106
+ <style scoped>
107
+ .checkbox_container {
108
+ height: 30px;
109
+ display: flex;
110
+ align-items: center;
111
+ justify-content: center;
112
+ }
113
+
114
+ .table_cell {
115
+ text-align: center;
116
+ text-align: center;
117
+ line-height: 30px;
118
+ }
119
+
120
+ th,
121
+ td {
122
+ text-overflow: ellipsis;
123
+ white-space: nowrap;
124
+ overflow: hidden;
125
+ }
126
+
127
+ .table_row {
128
+ height: 30px;
129
+ box-sizing: border-box;
130
+ }
131
+
132
+ .table_body.move {
133
+ cursor: move;
134
+ }
135
+
136
+ .table_row>.table_cell {
137
+ border-right: 1px solid #ccc;
138
+ border-bottom: 1px solid #ccc;
139
+
140
+ }
141
+
142
+ .v-enter-active,
143
+ .v-leave-active {
144
+ transition: opacity 0.5s ease;
145
+ }
146
+
147
+ .v-enter-from,
148
+ .v-leave-to {
149
+ opacity: 0;
150
+ }
151
+ </style>
package/src/index.js CHANGED
@@ -7,6 +7,7 @@ import tree from './components/tree/index';
7
7
  import Pagination from './components/pagination/index';
8
8
  import Select from './components/select/index';
9
9
  import Year from './components/year/index';
10
+ import Table from './components/data_table/index';
10
11
 
11
12
  const components = [
12
13
  Calendar,
@@ -16,7 +17,8 @@ const components = [
16
17
  tree,
17
18
  Pagination,
18
19
  Select,
19
- Year
20
+ Year,
21
+ Table
20
22
  ];
21
23
 
22
24
  function install(app) {
@@ -27,7 +29,7 @@ function install(app) {
27
29
  }
28
30
 
29
31
  export default {
30
- version: '1.3.22',
32
+ version: '1.4.22',
31
33
  install,
32
34
  Calendar,
33
35
  Message,
@@ -37,6 +39,7 @@ export default {
37
39
  tree,
38
40
  Pagination,
39
41
  Select,
40
- Year
42
+ Year,
43
+ Table
41
44
  };
42
45