ci-plus 1.1.7 → 1.1.8

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": "ci-plus",
3
- "version": "1.1.7",
3
+ "version": "1.1.8",
4
4
  "description": "ci组件库",
5
5
  "main": "./index.ts",
6
6
  "scripts": {
@@ -0,0 +1,221 @@
1
+ <template>
2
+ <el-table v-bind="table || {}" :data="data" :header-cell-class-name="setClass" ref="elTableRef">
3
+ <slot></slot>
4
+ <sortable-table-column-cell
5
+ v-if="props.modelValue"
6
+ v-for="v in rowValue"
7
+ :key="v.id"
8
+ :data="v"
9
+ />
10
+ </el-table>
11
+ </template>
12
+ <script setup lang="ts">
13
+ defineOptions({ name: 'ci-table' })
14
+ import { CellCls, ElTable } from 'element-plus'
15
+ import Sortable from 'sortablejs'
16
+ import { computed, onBeforeMount, onMounted, ref } from 'vue'
17
+ import { SortableTableIns, SortColumn } from './utils/interface'
18
+ import sortableTableColumnCell from './index/sortableTableColumnCell'
19
+ import { cloneDeep } from 'lodash'
20
+ let props = defineProps<SortableTableIns>()
21
+ const elTableRef = ref<InstanceType<typeof ElTable>>()
22
+ const emits = defineEmits(['update:modelValue', 'update:data'])
23
+ const rowValue = computed({
24
+ get() {
25
+ return props.modelValue
26
+ },
27
+ set(value) {
28
+ emits('update:modelValue', value)
29
+ }
30
+ })
31
+ const data = computed({
32
+ get() {
33
+ return props.data
34
+ },
35
+ set(value) {
36
+ emits('update:data', value)
37
+ }
38
+ })
39
+
40
+ onBeforeMount(() => {})
41
+ onMounted(() => {
42
+ columnDrop(elTableRef.value?.$el)
43
+ })
44
+ const columnDrop = (elem?: HTMLTableElement) => {
45
+ // 如果没有传入elem,则返回
46
+ if (!elem) return
47
+ // 获取表格的表头元素
48
+ const header = elem.querySelector('.el-table__header-wrapper')
49
+ // 如果没有表头元素,则返回
50
+ if (!header) return
51
+ // 设置延时执行函数
52
+ setTimeout(() => {
53
+ // 获取表头中的所有行元素
54
+ const trs = header.querySelectorAll('thead > tr')
55
+ // 遍历行元素
56
+ trs.forEach((v) => {
57
+ let tr = v as HTMLElement
58
+ // 创建拖拽排序对象
59
+ Sortable.create(tr, {
60
+ // 动画时间
61
+ animation: 180,
62
+ // 延迟时间
63
+ delay: 0,
64
+ // 拖拽元素
65
+ draggable: '.sortable',
66
+ // 过滤器
67
+ filter: (evt, item) => !getLocation(item),
68
+ // 拖拽排序时触发的函数
69
+ onMove: ({ dragged, related }) => {
70
+ // 获取拖拽元素的排序位置
71
+ let location = getLocation(dragged)
72
+ // 如果没有排序位置,则返回false
73
+ if (!location) return false
74
+ // 获取排序位置的数组
75
+ const locationArr = location.split('_').slice(1).map(Number)
76
+ // 判断拖拽元素是否在相关元素之前
77
+ return inChildren(locationArr[0], getIndex(tr, dragged), getIndex(tr, related))
78
+ },
79
+ // 拖拽排序后的函数
80
+ onUpdate({ oldIndex, newIndex }) {
81
+ // 如果没有排序值,则返回
82
+ if (!rowValue.value) return
83
+ // 如果没有旧的索引和新的索引,则返回
84
+ if (oldIndex === void 0 || newIndex === void 0) return
85
+ // 获取旧的th元素
86
+ let oldTh = tr.children[oldIndex]
87
+ // 获取新的th元素
88
+ let newTh = tr.children[newIndex]
89
+ // 获取旧的排序位置
90
+ let oldLocation = getLocation(oldTh)
91
+ // 获取新的排序位置
92
+ let newLocation = getLocation(newTh)
93
+ // 如果没有旧的排序位置或者新的排序位置,则返回false
94
+ if (!oldLocation || !newLocation) return false
95
+ // 获取旧的排序位置的数组
96
+ let oldLocationArr = oldLocation.split('_').slice(1).map(Number)
97
+ // 如果旧的排序位置的第一个元素为1,则减去count
98
+ if (oldLocationArr[0] === 1) {
99
+ let count = tr.querySelectorAll('.el-table-fixed-column--left').length
100
+ newIndex -= count
101
+ oldIndex -= count
102
+ }
103
+ // 获取新的排序位置的数组
104
+ let newLocationArr = newLocation.split('_').slice(1).map(Number)
105
+ // 获取旧的路径
106
+ let oldPath = getPath(oldLocationArr[0], oldIndex)
107
+ // 获取新的路径
108
+ let newPath = getPath(newLocationArr[0], newIndex)
109
+ // 如果没有旧的路径或者新的路径,则返回false
110
+ if (!oldPath || !newPath) return false
111
+ // 克隆排序值
112
+ let tem = cloneDeep(rowValue.value)
113
+ // 设置新的路径和新的排序值
114
+ setValue(cloneDeep(getValue(oldPath)), newPath, tem)
115
+ // 设置旧的路径和旧的排序值
116
+ setValue(cloneDeep(getValue(newPath)), oldPath, tem)
117
+ // 设置新的排序值
118
+ rowValue.value = tem
119
+ }
120
+ })
121
+ })
122
+ })
123
+ }
124
+ const getIndex = (father: HTMLElement, child: HTMLElement) =>
125
+ Array.from(father.children).indexOf(child)
126
+ // 获取元素的路径
127
+ const getLocation = (dom: Element) => dom && dom.className.match(/sortable_[0-9]+_[0-9]+/g)?.[0]
128
+ // 判断当前元素是否在当前行中
129
+ const inChildren = (level: number, from: number, to: number) => {
130
+ if (!rowValue.value) return false
131
+ if (level === 1) return true
132
+ let item = levelFlat(level - 1).filter((v) => !v.hide)
133
+ return getColumnFatherIndex(item, from) === getColumnFatherIndex(item, to)
134
+ }
135
+ // 获取当前元素的父级元素的索引
136
+ const getColumnFatherIndex = (item: SortColumn[], end: number) => {
137
+ let i = 0
138
+ while (end >= 0) {
139
+ const v = item[i]
140
+ i++
141
+ if (v.hide) continue
142
+ let children = v.children
143
+ if (!children) return false
144
+ end -= children.length
145
+ }
146
+ return i
147
+ }
148
+ // 获取当前元素的路径
149
+ const getPath = (level: number, end: number) => {
150
+ if (!rowValue.value) return
151
+ end += hideCount(level, end)
152
+ if (level === 1) return [end]
153
+ let path = Array.from({ length: level }).map((v) => 0)
154
+ if (!end) {
155
+ f(rowValue.value, 0)
156
+ path[level - 1] = 0
157
+ } else
158
+ while (end > 0) {
159
+ f(rowValue.value, 0)
160
+ end--
161
+ }
162
+ function f(data: SortColumn[], depth: number) {
163
+ let flag = 0
164
+ for (let i = 0; i < data.length; i++) {
165
+ let v = data[i]
166
+ if (depth === level - 1) {
167
+ if (flag !== i) {
168
+ flag = i
169
+ path[depth] = 0
170
+ }
171
+ path[depth] += 1
172
+ } else if (v.children) return f(v.children, depth + 1)
173
+ else path[depth] += 1
174
+ }
175
+ }
176
+ return path
177
+ }
178
+ // 获取当前元素的值
179
+ const getValue = (
180
+ path: number[],
181
+ parent?: boolean,
182
+ data: SortColumn[] = rowValue.value
183
+ ): SortColumn => {
184
+ if (!path.length) path[0] = 0
185
+ if (path.length <= (parent ? 2 : 1)) return data[path[0]]
186
+ return getValue(path.slice(1), parent, data[path[0]].children)
187
+ }
188
+ // 设置当前元素的值
189
+ const setValue = (data: SortColumn, path: number[], value: SortColumn[]): SortColumn[] => {
190
+ if (path.length) {
191
+ let tem = value[path[0]]
192
+ if (path.length === 1) value[path[0]] = data
193
+ else if (tem.children) value[path[0]].children = setValue(data, path.slice(1), tem.children)
194
+ }
195
+ return value
196
+ }
197
+ // 计算当前元素的隐藏数量
198
+ const hideCount = (level: number, index: number) =>
199
+ levelFlat(level)
200
+ .slice(0, index + 1)
201
+ .filter((v) => v.hide).length
202
+ // 获取当前行的数据
203
+ const levelFlat = (level: number, data = rowValue.value): SortColumn[] => {
204
+ if (level > 1)
205
+ return levelFlat(
206
+ level - 1,
207
+ data.filter((v) => v.children).flatMap((v) => v.children) as SortColumn[]
208
+ )
209
+ return data
210
+ }
211
+ // 设置当前元素的类名
212
+ const setClass: CellCls<typeof props.data> = ({ column }) => {
213
+ let className = props.table?.headerCellClassName || ''
214
+ if (!column.fixed && column.id) {
215
+ className += ` sortable sortable_${column.level}_${column.no}`
216
+ }
217
+ return className as string
218
+ }
219
+ defineExpose({ table: elTableRef })
220
+ </script>
221
+ <style scoped></style>
@@ -1,11 +1,22 @@
1
1
  <template>
2
- <el-table v-bind="table || {}" :data="data" :header-cell-class-name="setClass" ref="elTableRef">
2
+ <el-table
3
+ v-bind="table || {}"
4
+ :header-cell-class-name="setClass"
5
+ :data="data"
6
+ ref="elTableRef"
7
+ @vue:mounted="columnDrop"
8
+ >
3
9
  <slot></slot>
10
+ <!-- <sortable-table-column-cell v-if="props.modelValue" v-for="v in rowValue" :key="v.id" :data="v" /> -->
4
11
  <sortable-table-column-cell
12
+ :label-class-name="`sortable sortable_0_0_${i}`"
13
+ :i="0"
14
+ :level="0"
5
15
  v-if="props.modelValue"
6
- v-for="v in rowValue"
16
+ v-for="(v, i) in rowValue"
7
17
  :key="v.id"
8
18
  :data="v"
19
+ :no-search="noSearch"
9
20
  />
10
21
  </el-table>
11
22
  </template>
@@ -13,7 +24,7 @@
13
24
  defineOptions({ name: 'ci-table' })
14
25
  import { CellCls, ElTable } from 'element-plus'
15
26
  import Sortable from 'sortablejs'
16
- import { computed, onBeforeMount, onMounted, ref } from 'vue'
27
+ import { VNode, computed, ref } from 'vue'
17
28
  import { SortableTableIns, SortColumn } from './utils/interface'
18
29
  import sortableTableColumnCell from './index/sortableTableColumnCell'
19
30
  import { cloneDeep } from 'lodash'
@@ -37,177 +48,112 @@ const data = computed({
37
48
  }
38
49
  })
39
50
 
40
- onBeforeMount(() => {})
41
- onMounted(() => {
42
- columnDrop(elTableRef.value?.$el)
43
- })
44
- const columnDrop = (elem?: HTMLTableElement) => {
51
+ // 只能同行并在同一个children中可以拖拽
52
+ const columnDrop = (vnode: VNode) => {
53
+ if (props.noMove) return
54
+ const elem = vnode.el as HTMLDivElement
45
55
  // 如果没有传入elem,则返回
46
56
  if (!elem) return
47
57
  // 获取表格的表头元素
48
58
  const header = elem.querySelector('.el-table__header-wrapper')
49
59
  // 如果没有表头元素,则返回
50
60
  if (!header) return
51
- // 设置延时执行函数
52
- setTimeout(() => {
53
- // 获取表头中的所有行元素
54
- const trs = header.querySelectorAll('thead > tr')
55
- // 遍历行元素
56
- trs.forEach((v) => {
57
- let tr = v as HTMLElement
58
- // 创建拖拽排序对象
59
- Sortable.create(tr, {
60
- // 动画时间
61
- animation: 180,
62
- // 延迟时间
63
- delay: 0,
64
- // 拖拽元素
65
- draggable: '.sortable',
66
- // 过滤器
67
- filter: (evt, item) => !getLocation(item),
68
- // 拖拽排序时触发的函数
69
- onMove: ({ dragged, related }) => {
70
- // 获取拖拽元素的排序位置
71
- let location = getLocation(dragged)
72
- // 如果没有排序位置,则返回false
73
- if (!location) return false
74
- // 获取排序位置的数组
75
- const locationArr = location.split('_').slice(1).map(Number)
76
- // 判断拖拽元素是否在相关元素之前
77
- return inChildren(locationArr[0], getIndex(tr, dragged), getIndex(tr, related))
78
- },
79
- // 拖拽排序后的函数
80
- onUpdate({ oldIndex, newIndex }) {
81
- // 如果没有排序值,则返回
82
- if (!rowValue.value) return
83
- // 如果没有旧的索引和新的索引,则返回
84
- if (oldIndex === void 0 || newIndex === void 0) return
85
- // 获取旧的th元素
86
- let oldTh = tr.children[oldIndex]
87
- // 获取新的th元素
88
- let newTh = tr.children[newIndex]
89
- // 获取旧的排序位置
90
- let oldLocation = getLocation(oldTh)
91
- // 获取新的排序位置
92
- let newLocation = getLocation(newTh)
93
- // 如果没有旧的排序位置或者新的排序位置,则返回false
94
- if (!oldLocation || !newLocation) return false
95
- // 获取旧的排序位置的数组
96
- let oldLocationArr = oldLocation.split('_').slice(1).map(Number)
97
- // 如果旧的排序位置的第一个元素为1,则减去count
98
- if (oldLocationArr[0] === 1) {
99
- let count = tr.querySelectorAll('.el-table-fixed-column--left').length
100
- newIndex -= count
101
- oldIndex -= count
102
- }
103
- // 获取新的排序位置的数组
104
- let newLocationArr = newLocation.split('_').slice(1).map(Number)
105
- // 获取旧的路径
106
- let oldPath = getPath(oldLocationArr[0], oldIndex)
107
- // 获取新的路径
108
- let newPath = getPath(newLocationArr[0], newIndex)
109
- // 如果没有旧的路径或者新的路径,则返回false
110
- if (!oldPath || !newPath) return false
111
- // 克隆排序值
112
- let tem = cloneDeep(rowValue.value)
113
- // 设置新的路径和新的排序值
114
- setValue(cloneDeep(getValue(oldPath)), newPath, tem)
115
- // 设置旧的路径和旧的排序值
116
- setValue(cloneDeep(getValue(newPath)), oldPath, tem)
117
- // 设置新的排序值
118
- rowValue.value = tem
61
+ // 获取表头中的所有行元素
62
+ const trs = header.querySelectorAll('thead > tr')
63
+ // 遍历行元素
64
+ trs.forEach((v) => {
65
+ let tr = v as HTMLElement
66
+ // 创建拖拽排序对象
67
+ Sortable.create(tr, {
68
+ // 动画时间
69
+ animation: 180,
70
+ // 延迟时间
71
+ delay: 0,
72
+ // 拖拽元素
73
+ draggable: '.sortable',
74
+ // 过滤器
75
+ filter: (evt, item) => !canDrag(item),
76
+ // 拖拽排序时触发的函数
77
+ onMove: ({ dragged, related }) => {
78
+ return isSameGroup(dragged, related)
79
+ },
80
+ // 拖拽排序后的函数
81
+ onUpdate({ newIndex, item }) {
82
+ const location = getLocation(item)
83
+ if (!location) return
84
+ if (typeof newIndex !== 'number') return
85
+ let newArr: SortColumn[] = []
86
+ const newItem = header.querySelector(`.sortable_index_${location[0]}_${newIndex}`)
87
+ if (!newItem) return
88
+ const newLocation = getLocation(newItem)
89
+ if (!newLocation) return
90
+ if (!location[0]) {
91
+ rowValue.value.forEach((v, i) => {
92
+ if (i === newLocation[2]) {
93
+ if (location[2] > newLocation[2]) {
94
+ newArr.push(rowValue.value[location[2]])
95
+ newArr.push(v)
96
+ } else {
97
+ newArr.push(v)
98
+ newArr.push(rowValue.value[location[2]])
99
+ }
100
+ } else if (i !== location[2]) newArr.push(v)
101
+ })
102
+ } else {
103
+ newArr = cloneDeep(rowValue.value)
104
+ const tem: SortColumn[] = []
105
+ loop(newArr, location[0] - 1, (v, i) => {
106
+ if (i === location[1]) {
107
+ v.children?.forEach((x, j) => {
108
+ if (j === newLocation[2]) {
109
+ if (location[2] > newLocation[2]) {
110
+ tem.push((v.children as SortColumn[])[location[2]])
111
+ tem.push(x)
112
+ } else {
113
+ tem.push(x)
114
+ tem.push((v.children as SortColumn[])[location[2]])
115
+ }
116
+ } else if (j !== location[2]) tem.push(x)
117
+ })
118
+ v.children = tem
119
+ return true
120
+ }
121
+ })
119
122
  }
120
- })
123
+ rowValue.value = newArr
124
+ }
121
125
  })
122
126
  })
123
127
  }
124
- const getIndex = (father: HTMLElement, child: HTMLElement) =>
125
- Array.from(father.children).indexOf(child)
126
- // 获取元素的路径
127
- const getLocation = (dom: Element) => dom && dom.className.match(/sortable_[0-9]+_[0-9]+/g)?.[0]
128
- // 判断当前元素是否在当前行中
129
- const inChildren = (level: number, from: number, to: number) => {
130
- if (!rowValue.value) return false
131
- if (level === 1) return true
132
- let item = levelFlat(level - 1).filter((v) => !v.hide)
133
- return getColumnFatherIndex(item, from) === getColumnFatherIndex(item, to)
134
- }
135
- // 获取当前元素的父级元素的索引
136
- const getColumnFatherIndex = (item: SortColumn[], end: number) => {
137
- let i = 0
138
- while (end >= 0) {
139
- const v = item[i]
140
- i++
141
- if (v.hide) continue
142
- let children = v.children
143
- if (!children) return false
144
- end -= children.length
145
- }
146
- return i
147
- }
148
- // 获取当前元素的路径
149
- const getPath = (level: number, end: number) => {
150
- if (!rowValue.value) return
151
- end += hideCount(level, end)
152
- if (level === 1) return [end]
153
- let path = Array.from({ length: level }).map((v) => 0)
154
- if (!end) {
155
- f(rowValue.value, 0)
156
- path[level - 1] = 0
157
- } else
158
- while (end > 0) {
159
- f(rowValue.value, 0)
160
- end--
161
- }
162
- function f(data: SortColumn[], depth: number) {
163
- let flag = 0
164
- for (let i = 0; i < data.length; i++) {
165
- let v = data[i]
166
- if (depth === level - 1) {
167
- if (flag !== i) {
168
- flag = i
169
- path[depth] = 0
170
- }
171
- path[depth] += 1
172
- } else if (v.children) return f(v.children, depth + 1)
173
- else path[depth] += 1
174
- }
128
+
129
+ // 循环指定层级
130
+ const loop = (
131
+ arr: SortColumn[],
132
+ level: number,
133
+ fun: (v: SortColumn, i: number) => boolean | void
134
+ ) => {
135
+ for (let i = 0; i < arr.length; i++) {
136
+ const v = arr[i]
137
+ if (level && v.children) loop(v.children, level - 1, fun)
138
+ if (fun(v, i)) break
175
139
  }
176
- return path
177
- }
178
- // 获取当前元素的值
179
- const getValue = (
180
- path: number[],
181
- parent?: boolean,
182
- data: SortColumn[] = rowValue.value
183
- ): SortColumn => {
184
- if (!path.length) path[0] = 0
185
- if (path.length <= (parent ? 2 : 1)) return data[path[0]]
186
- return getValue(path.slice(1), parent, data[path[0]].children)
187
140
  }
188
- // 设置当前元素的值
189
- const setValue = (data: SortColumn, path: number[], value: SortColumn[]): SortColumn[] => {
190
- if (path.length) {
191
- let tem = value[path[0]]
192
- if (path.length === 1) value[path[0]] = data
193
- else if (tem.children) value[path[0]].children = setValue(data, path.slice(1), tem.children)
194
- }
195
- return value
141
+ // 判断这个元素是否可以拖拽
142
+ const canDrag = (dom: Element) => dom && /sortable_[0-9]+_[0-9]+/g.test(dom.className)
143
+ // 获取这个元素在数据内的位置
144
+ const getLocation = (dom: Element) => {
145
+ const name = dom && dom.className.match(/\bsortable(_[0-9]+)+\b/)?.[0]
146
+ if (!name) return
147
+ return name.split('_').slice(1).map(Number)
196
148
  }
197
- // 计算当前元素的隐藏数量
198
- const hideCount = (level: number, index: number) =>
199
- levelFlat(level)
200
- .slice(0, index + 1)
201
- .filter((v) => v.hide).length
202
- // 获取当前行的数据
203
- const levelFlat = (level: number, data = rowValue.value): SortColumn[] => {
204
- if (level > 1)
205
- return levelFlat(
206
- level - 1,
207
- data.filter((v) => v.children).flatMap((v) => v.children) as SortColumn[]
208
- )
209
- return data
149
+ // 判断这个元素是否在一起
150
+ const isSameGroup = (dom1: Element, dom2: Element) => {
151
+ const location1 = getLocation(dom1)
152
+ const location2 = getLocation(dom2)
153
+ if (!location1 || !location2) return false
154
+ return location1[1] === location2[1]
210
155
  }
156
+
211
157
  // 设置当前元素的类名
212
158
  const setClass: CellCls<typeof props.data> = ({ column }) => {
213
159
  let className = props.table?.headerCellClassName || ''
@@ -1,16 +1,13 @@
1
- <!-- /*
2
- * @module sortableTableColumnCell
3
- * @author : 杨佳贺&卖女孩的小火柴
4
- * @description : 表格列单元格
5
- * @version : 1.0.0
6
- * @since : 创建时间 2023-12-29 13:40:49
7
- * @lastTime : 2023-12-29 新增默认居中显示属性
8
- * @lastTime : 2024-01-03 新增默认超出隐藏悬停显示、拖拽改变列宽
9
- */ -->
10
-
11
1
  <template>
12
2
  <el-table-column v-if="!data.hide && data.children" v-bind="data.col">
13
- <sortable-table-column-cell v-for="v in data.children || []" :key="v.key" :data="v" />
3
+ <sortable-table-column-cell
4
+ :label-class-name="`sortable sortable_${level}_${i}_${j}`"
5
+ :i="j"
6
+ v-for="(v, j) in data.children || []"
7
+ :key="v.key"
8
+ :data="v"
9
+ :level="props.level + 1"
10
+ />
14
11
  </el-table-column>
15
12
  <el-table-column
16
13
  v-else-if="!data.hide && data.scope"
@@ -26,6 +23,7 @@
26
23
  <component :is="headerVue(header)" :header="header"></component>
27
24
  </template>
28
25
  </el-table-column>
26
+
29
27
  <el-table-column
30
28
  v-else-if="!data.hide && data.component"
31
29
  v-bind="data.col"
@@ -40,6 +38,7 @@
40
38
  <component :is="headerVue(header)" :header="header"></component>
41
39
  </template>
42
40
  </el-table-column>
41
+
43
42
  <el-table-column
44
43
  v-else-if="!data.hide"
45
44
  v-bind="data.col"
@@ -53,14 +52,18 @@
53
52
  </el-table-column>
54
53
  </template>
55
54
  <script setup lang="ts">
55
+ defineOptions({ name: 'ci-columncell' })
56
56
  import { Scope, SortColumn } from './interface'
57
57
  import { h } from 'vue'
58
- defineOptions({ name: 'ci-columncell' })
59
58
 
60
59
  const props = defineProps<{
61
60
  data: SortColumn
61
+ level?: number
62
+ i?: number
63
+ noSearch?: boolean
62
64
  }>()
63
65
  const headerVue = (header: Pick<Scope<any>, '$index' | 'column'>) => {
66
+ if (props.noSearch) return h('div', props.data.col.label)
64
67
  const item = props.data.header?.(h, header)
65
68
  if (!item) return h('div', props.data.col.label)
66
69
  if (typeof item === 'string') return h('div', item)
@@ -1,63 +1,61 @@
1
+ <!-- /*
2
+ * @module sortableTableColumnCell
3
+ * @author : 杨佳贺&卖女孩的小火柴
4
+ * @description : 表格列单元格
5
+ * @version : 1.0.0
6
+ * @since : 创建时间 2023-12-29 13:40:49
7
+ * @lastTime : 2023-12-29 新增默认居中显示属性
8
+ * @lastTime : 2024-01-03 新增默认超出隐藏悬停显示、拖拽改变列宽
9
+ */ -->
10
+
1
11
  <template>
2
- <el-table-column
3
- v-if="!data.hide && data.children"
4
- v-bind="data.col"
5
- >
6
- <sortable-table-column-cell
7
- v-for="v in data.children || []"
8
- :key="v.key"
9
- :data="v"
10
- />
12
+ <el-table-column v-if="!data.hide && data.children" v-bind="data.col">
13
+ <sortable-table-column-cell v-for="v in data.children || []" :key="v.key" :data="v" />
11
14
  </el-table-column>
12
15
  <el-table-column
13
16
  v-else-if="!data.hide && data.scope"
14
17
  v-bind="data.col"
18
+ :align="data.col.align || 'center'"
19
+ :showOverflowTooltip="data.col.showOverflowTooltip || true"
20
+ :resizable="data.col.resizable || true"
15
21
  >
16
22
  <template #default="scope">
17
23
  {{ data.scope(scope) }}
18
24
  </template>
19
25
  <template #header="header">
20
- <component
21
- :is="headerVue(header)"
22
- :header="header"
23
- ></component>
26
+ <component :is="headerVue(header)" :header="header"></component>
24
27
  </template>
25
28
  </el-table-column>
26
29
  <el-table-column
27
30
  v-else-if="!data.hide && data.component"
28
31
  v-bind="data.col"
32
+ :align="data.col.align || 'center'"
33
+ :showOverflowTooltip="data.col.showOverflowTooltip || true"
34
+ :resizable="data.col.resizable || true"
29
35
  >
30
36
  <template #default="scope">
31
- <component
32
- :is="data.component(h, scope)"
33
- :scope="scope"
34
- ></component>
37
+ <component :is="data.component(h, scope)" :scope="scope"></component>
35
38
  </template>
36
39
  <template #header="header">
37
- <component
38
- :is="headerVue(header)"
39
- :header="header"
40
- ></component>
40
+ <component :is="headerVue(header)" :header="header"></component>
41
41
  </template>
42
42
  </el-table-column>
43
43
  <el-table-column
44
44
  v-else-if="!data.hide"
45
45
  v-bind="data.col"
46
+ :align="data.col.align || 'center'"
47
+ :showOverflowTooltip="data.col.showOverflowTooltip || true"
48
+ :resizable="data.col.resizable || true"
46
49
  >
47
50
  <template #header="header">
48
- <component
49
- :is="headerVue(header)"
50
- :header="header"
51
- ></component>
51
+ <component :is="headerVue(header)" :header="header"></component>
52
52
  </template>
53
53
  </el-table-column>
54
54
  </template>
55
55
  <script setup lang="ts">
56
56
  import { Scope, SortColumn } from './interface'
57
57
  import { h } from 'vue'
58
- defineOptions({
59
- name: 'sortable-table-column-cell',
60
- })
58
+ defineOptions({ name: 'ci-columncell' })
61
59
 
62
60
  const props = defineProps<{
63
61
  data: SortColumn
@@ -1,61 +1,54 @@
1
- <!-- 2023-12-29 新增显示/隐藏按钮 -->
2
-
3
1
  <template>
4
- <draggable
2
+ <vue-draggable
5
3
  class="drag-container"
6
- :list="modelValue"
4
+ v-model="modelValue"
7
5
  chosen-class="hover"
8
6
  handle=".mover"
9
7
  draggable=".item"
10
8
  itemKey="key"
11
9
  >
12
- <template #item="{ element, index }: { element: SortColumn; index: number }">
13
- <div :class="{ item: true, 'item-hide': element.hide }">
14
- <div class="mover">
15
- <el-icon :size="16"><Rank /></el-icon>
16
- </div>
17
- <div class="title" @click="handleShow(element)">
18
- {{ element.col.label }}
19
- </div>
20
- <div class="pin" v-if="showPin">
21
- <span
22
- v-if="element.col.fixed === true || element.col.fixed === 'left'"
23
- @click="element.col.fixed = void 0"
24
- >
25
- <svg-icon name="regular-left" size="20" color="#2C93FF"></svg-icon>
26
- </span>
27
- <span v-else @click="element.col.fixed = 'left'">
28
- <svg-icon name="regular-center" size="20"></svg-icon>
29
- </span>
30
- <span v-if="element.col.fixed === 'right'" @click="element.col.fixed = void 0">
31
- <svg-icon name="regular-right" size="20" color="#2C93FF"></svg-icon>
32
- </span>
33
- <span v-else @click="element.col.fixed = 'right'">
34
- <svg-icon name="regular-center" size="20"></svg-icon>
35
- </span>
36
- </div>
37
- <div class="ifshow">
38
- <el-button
39
- :type="element.hide ? 'primary' : ''"
40
- @click="handleShow(element)"
41
- size="small"
42
- >
43
- {{ element.hide ? '显示' : '隐藏' }}
44
- </el-button>
45
- </div>
46
- <div class="widths">
47
- 宽度:
48
- <el-input class="w-50 m-2" v-model="element.col.width" size="small" width="50"></el-input>
49
- </div>
50
- <sortable-table-drag-item v-if="element.children" v-model="element.children" />
10
+ <div v-for="(element, index) in modelValue" :class="{ item: true, 'item-hide': element.hide }">
11
+ <div class="mover">
12
+ <el-icon :size="16"><Rank /></el-icon>
13
+ </div>
14
+ <div class="title" @click="element.hide = !element.hide">
15
+ {{ element.col.label }}
16
+ </div>
17
+ <div class="pin" v-if="showPin">
18
+ <span
19
+ v-if="element.col.fixed === true || element.col.fixed === 'left'"
20
+ @click="element.col.fixed = void 0"
21
+ >
22
+ <svg-icon name="regular-left" size="20" color="#2C93FF"></svg-icon>
23
+ </span>
24
+ <span v-else @click="element.col.fixed = 'left'">
25
+ <svg-icon name="regular-center" size="20"></svg-icon>
26
+ </span>
27
+ <span v-if="element.col.fixed === 'right'" @click="element.col.fixed = void 0">
28
+ <svg-icon name="regular-right" size="20" color="#2C93FF"></svg-icon>
29
+ </span>
30
+ <span v-else @click="element.col.fixed = 'right'">
31
+ <svg-icon name="regular-center" size="20"></svg-icon>
32
+ </span>
33
+ </div>
34
+ <div class="ifshow">
35
+ <el-button :type="element.hide ? 'primary' : ''" @click="handleShow(element)" size="small">
36
+ {{ element.hide ? '显示' : '隐藏' }}
37
+ </el-button>
38
+ </div>
39
+ <div class="widths">
40
+ 宽度:
41
+ <el-input class="w-50 m-2" v-model="element.col.width" size="small" width="50"></el-input>
51
42
  </div>
52
- </template>
53
- </draggable>
43
+ <sortable-table-drag-item v-if="element.children" v-model="element.children" />
44
+ </div>
45
+ </vue-draggable>
54
46
  </template>
55
47
  <script setup lang="ts">
56
48
  import SvgIcon from '../../svgIcon/index'
57
49
  import { computed } from 'vue'
58
- import draggable from 'vuedraggable'
50
+ // import draggable from 'vuedraggable'
51
+ import { VueDraggable } from 'vue-draggable-plus'
59
52
  import { SortColumn, SortableTableIns } from './interface'
60
53
  import { Rank } from '@element-plus/icons-vue'
61
54
  const props = defineProps<{
@@ -1,86 +1,117 @@
1
- <!-- @format -->
1
+ <!-- 2023-12-29 新增显示/隐藏按钮 -->
2
2
 
3
3
  <template>
4
- <draggable
4
+ <!-- <vue-draggable
5
5
  class="drag-container"
6
6
  :list="modelValue"
7
7
  chosen-class="hover"
8
8
  handle=".mover"
9
9
  draggable=".item"
10
10
  itemKey="key"
11
+ > -->
12
+ <vue-draggable
13
+ class="drag-container"
14
+ v-model="modelValue"
15
+ chosen-class="hover"
16
+ handle=".mover"
17
+ draggable=".item"
18
+ itemKey="key"
11
19
  >
12
- <template
13
- #item="{ element, index }: { element: SortColumn; index: number }"
14
- >
20
+ <!-- <template #item="{ element, index }: { element: SortColumn; index: number }">
15
21
  <div :class="{ item: true, 'item-hide': element.hide }">
16
22
  <div class="mover">
17
23
  <el-icon :size="16"><Rank /></el-icon>
18
24
  </div>
19
- <div
20
- class="title"
21
- @click="element.hide = !element.hide"
22
- >
25
+ <div class="title" @click="handleShow(element)">
23
26
  {{ element.col.label }}
24
27
  </div>
25
- <div
26
- class="pin"
27
- v-if="showPin"
28
- >
28
+ <div class="pin" v-if="showPin">
29
29
  <span
30
30
  v-if="element.col.fixed === true || element.col.fixed === 'left'"
31
31
  @click="element.col.fixed = void 0"
32
32
  >
33
- <!-- <el-icon color="#409EFC" class="no-inherit" > <StarFilled /> </el-icon> -->
34
- <svg-icon
35
- name="regular-left"
36
- size="20"
37
- color="#2C93FF"
38
- ></svg-icon>
33
+ <svg-icon name="regular-left" size="20" color="#2C93FF"></svg-icon>
39
34
  </span>
40
- <span
41
- v-else
42
- @click="element.col.fixed = 'left'"
43
- >
44
- <!-- <el-icon color="#000000" class="no-inherit"><Star /></el-icon> -->
45
- <svg-icon
46
- name="regular-center"
47
- size="20"
48
- ></svg-icon>
35
+ <span v-else @click="element.col.fixed = 'left'">
36
+ <svg-icon name="regular-center" size="20"></svg-icon>
49
37
  </span>
50
- <span
51
- v-if="element.col.fixed === 'right'"
52
- @click="element.col.fixed = void 0"
53
- >
54
- <!-- <el-icon color="#409EFC" class="no-inherit"> <StarFilled /> </el-icon> -->
55
- <svg-icon
56
- name="regular-right"
57
- size="20"
58
- color="#2C93FF"
59
- ></svg-icon>
38
+ <span v-if="element.col.fixed === 'right'" @click="element.col.fixed = void 0">
39
+ <svg-icon name="regular-right" size="20" color="#2C93FF"></svg-icon>
60
40
  </span>
61
- <span
62
- v-else
63
- @click="element.col.fixed = 'right'"
64
- >
65
- <!-- <el-icon color="#000000" class="no-inherit"><Star /></el-icon> -->
66
- <svg-icon
67
- name="regular-center"
68
- size="20"
69
- ></svg-icon>
41
+ <span v-else @click="element.col.fixed = 'right'">
42
+ <svg-icon name="regular-center" size="20"></svg-icon>
70
43
  </span>
71
44
  </div>
72
- <sortable-table-drag-item
73
- v-if="element.children"
74
- v-model="element.children"
75
- />
45
+ <div class="ifshow">
46
+ <el-button
47
+ :type="element.hide ? 'primary' : ''"
48
+ @click="handleShow(element)"
49
+ size="small"
50
+ >
51
+ {{ element.hide ? '显示' : '隐藏' }}
52
+ </el-button>
53
+ </div>
54
+ <div class="widths">
55
+ 宽度:
56
+ <el-input class="w-50 m-2" v-model="element.col.width" size="small" width="50"></el-input>
57
+ </div>
58
+ <sortable-table-drag-item v-if="element.children" v-model="element.children" />
59
+ </div>
60
+ </template> -->
61
+ <div v-for="(element, index) in modelValue" :class="{ item: true, 'item-hide': element.hide }">
62
+ <div class="mover">
63
+ <el-icon :size="16"><Rank /></el-icon>
64
+ </div>
65
+ <div class="title" @click="element.hide = !element.hide">
66
+ {{ element.col.label }}
67
+ </div>
68
+ <div class="pin" v-if="showPin">
69
+ <!-- <span v-if="element.col.fixed === true || element.col.fixed === 'left'" @click="element.col.fixed = void 0">
70
+ <var-icon name="pin-off" :size="16" style="transform: rotate(-30deg); color: cadetblue" />
71
+ </span>
72
+ <span v-else @click="element.col.fixed = 'left'">
73
+ <var-icon name="pin" :size="16" style="transform: rotate(-30deg)" />
74
+ </span>
75
+ <span v-if="element.col.fixed === 'right'" @click="element.col.fixed = void 0">
76
+ <var-icon name="pin-off" :size="16" style="transform: scaleX(-1) rotate(-30deg); color: cadetblue" />
77
+ </span>
78
+ <span v-else @click="element.col.fixed = 'right'">
79
+ <var-icon name="pin" :size="16" style="transform: rotate(30deg)" />
80
+ </span> -->
81
+ <span
82
+ v-if="element.col.fixed === true || element.col.fixed === 'left'"
83
+ @click="element.col.fixed = void 0"
84
+ >
85
+ <svg-icon name="regular-left" size="20" color="#2C93FF"></svg-icon>
86
+ </span>
87
+ <span v-else @click="element.col.fixed = 'left'">
88
+ <svg-icon name="regular-center" size="20"></svg-icon>
89
+ </span>
90
+ <span v-if="element.col.fixed === 'right'" @click="element.col.fixed = void 0">
91
+ <svg-icon name="regular-right" size="20" color="#2C93FF"></svg-icon>
92
+ </span>
93
+ <span v-else @click="element.col.fixed = 'right'">
94
+ <svg-icon name="regular-center" size="20"></svg-icon>
95
+ </span>
96
+ </div>
97
+ <div class="ifshow">
98
+ <el-button :type="element.hide ? 'primary' : ''" @click="handleShow(element)" size="small">
99
+ {{ element.hide ? '显示' : '隐藏' }}
100
+ </el-button>
76
101
  </div>
77
- </template>
78
- </draggable>
102
+ <div class="widths">
103
+ 宽度:
104
+ <el-input class="w-50 m-2" v-model="element.col.width" size="small" width="50"></el-input>
105
+ </div>
106
+ <sortable-table-drag-item v-if="element.children" v-model="element.children" />
107
+ </div>
108
+ </vue-draggable>
79
109
  </template>
80
110
  <script setup lang="ts">
81
- import SvgIcon from '@/components/SvgIcon.vue'
111
+ import SvgIcon from '../../svgIcon/index'
82
112
  import { computed } from 'vue'
83
- import draggable from 'vuedraggable'
113
+ // import draggable from 'vuedraggable'
114
+ import { VueDraggable } from 'vue-draggable-plus'
84
115
  import { SortColumn, SortableTableIns } from './interface'
85
116
  import { Rank } from '@element-plus/icons-vue'
86
117
  const props = defineProps<{
@@ -94,14 +125,20 @@ const modelValue = computed({
94
125
  },
95
126
  set(value) {
96
127
  emits('update:modelValue', value)
97
- },
128
+ }
98
129
  })
130
+
131
+ // 显示或者隐藏列
132
+ const handleShow = (col: SortColumn) => {
133
+ // console.log('显示或者隐藏列', col)
134
+ col.hide = !col.hide
135
+ }
99
136
  </script>
100
137
  <style scoped lang="scss">
101
138
  $hoverBC: rgba(137, 182, 233, 0.5);
102
139
 
103
140
  .drag-container {
104
- display: flex;
141
+ // display: flex;
105
142
  width: 100%;
106
143
  flex-direction: column;
107
144
 
@@ -110,6 +147,7 @@ $hoverBC: rgba(137, 182, 233, 0.5);
110
147
  display: flex;
111
148
  align-items: center;
112
149
  white-space: nowrap;
150
+ width: 100%;
113
151
  .mover,
114
152
  .title {
115
153
  padding: 5px;
@@ -133,6 +171,20 @@ $hoverBC: rgba(137, 182, 233, 0.5);
133
171
  padding: 5px;
134
172
  }
135
173
  }
174
+ .ifshow {
175
+ text-align: center;
176
+ flex: 1;
177
+ line-height: 32px;
178
+ .el-button {
179
+ margin-bottom: 0;
180
+ }
181
+ }
182
+ .widths {
183
+ .el-input {
184
+ width: 50px !important;
185
+ margin-right: 20px;
186
+ }
187
+ }
136
188
  }
137
189
  .item-hide {
138
190
  background: rgba(218, 218, 218, 0.5);