eoss 0.1.0-alpha.47 → 0.1.0-alpha.49

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.
Files changed (117) hide show
  1. package/lib/3.js +1 -1
  2. package/lib/autocomplete.js +6 -6
  3. package/lib/ca-login.js +2 -2
  4. package/lib/calendar.js +2 -2
  5. package/lib/cascader-panel.js +2 -2
  6. package/lib/cascader.js +4 -4
  7. package/lib/code-editor.js +2 -2
  8. package/lib/collapse-item.js +2 -2
  9. package/lib/collapse.js +2 -2
  10. package/lib/color-picker.js +2 -2
  11. package/lib/cron.js +4 -4
  12. package/lib/data-table.js +366 -20
  13. package/lib/date-picker.js +3 -3
  14. package/lib/dialog.js +12 -10
  15. package/lib/drawer.js +2 -2
  16. package/lib/dropdown-item.js +23 -4
  17. package/lib/dropdown.js +4 -4
  18. package/lib/empty.js +2 -2
  19. package/lib/eoss.common.js +734 -322
  20. package/lib/flow-group.js +2 -2
  21. package/lib/flow.js +7 -7
  22. package/lib/form-editor.js +2 -2
  23. package/lib/form.js +12 -11
  24. package/lib/guide.js +2 -2
  25. package/lib/icons.js +4 -4
  26. package/lib/index.js +1 -1
  27. package/lib/input.js +2 -2
  28. package/lib/loading.js +4 -4
  29. package/lib/lowcode-view.js +2 -2
  30. package/lib/lowcode.js +7 -50
  31. package/lib/main.js +5 -5
  32. package/lib/menu-item-group.js +5 -1
  33. package/lib/menu.js +33 -43
  34. package/lib/message-box.js +4 -4
  35. package/lib/message.js +2 -2
  36. package/lib/notification.js +2 -2
  37. package/lib/pagination.js +2 -2
  38. package/lib/process-module.js +2 -2
  39. package/lib/rate.js +2 -2
  40. package/lib/scrollbar.js +71 -87
  41. package/lib/select.js +23 -13
  42. package/lib/selector-panel.js +2 -2
  43. package/lib/selector.js +16 -18
  44. package/lib/slider.js +2 -2
  45. package/lib/step.js +2 -2
  46. package/lib/steps.js +4 -4
  47. package/lib/submenu.js +16 -24
  48. package/lib/switch.js +2 -2
  49. package/lib/table-column.js +69 -3
  50. package/lib/table.js +162 -56
  51. package/lib/tabs.js +2 -2
  52. package/lib/theme-chalk/autocomplete.css +1 -1
  53. package/lib/theme-chalk/cascader-panel.css +1 -1
  54. package/lib/theme-chalk/cascader.css +1 -1
  55. package/lib/theme-chalk/data-table.css +1 -1
  56. package/lib/theme-chalk/date-picker.css +1 -1
  57. package/lib/theme-chalk/form.css +1 -1
  58. package/lib/theme-chalk/index.css +1 -1
  59. package/lib/theme-chalk/input-number.css +1 -1
  60. package/lib/theme-chalk/input.css +1 -1
  61. package/lib/theme-chalk/menu.css +1 -1
  62. package/lib/theme-chalk/message-box.css +1 -1
  63. package/lib/theme-chalk/pagination.css +1 -1
  64. package/lib/theme-chalk/scrollbar.css +1 -1
  65. package/lib/theme-chalk/select.css +1 -1
  66. package/lib/theme-chalk/selector.css +1 -1
  67. package/lib/theme-chalk/slider.css +1 -1
  68. package/lib/theme-chalk/table.css +1 -1
  69. package/lib/theme-chalk/time-picker.css +1 -1
  70. package/lib/theme-chalk/time-select.css +1 -1
  71. package/lib/theme-chalk/transfer.css +1 -1
  72. package/lib/theme-chalk/tree.css +1 -1
  73. package/lib/theme-chalk/upload.css +1 -1
  74. package/lib/time-picker.js +2 -2
  75. package/lib/time-select.js +6 -6
  76. package/lib/toolbar.js +2 -2
  77. package/lib/transfer.js +4 -4
  78. package/lib/tree.js +8 -15
  79. package/lib/upload.js +20 -20
  80. package/lib/utils/popup/popup-manager.js +24 -8
  81. package/package.json +4 -1
  82. package/packages/data-table/src/data-table.vue +43 -8
  83. package/packages/data-table/src/sizer.vue +104 -87
  84. package/packages/dialog/src/dialog.vue +4 -2
  85. package/packages/dropdown/src/dropdown-item.vue +21 -3
  86. package/packages/form/src/form.vue +5 -8
  87. package/packages/icons/src/icons.vue +2 -2
  88. package/packages/lowcode/src/util/components.js +0 -59
  89. package/packages/menu/src/menu.vue +7 -21
  90. package/packages/menu/src/mixins.js +6 -1
  91. package/packages/menu/src/submenu.vue +7 -16
  92. package/packages/scrollbar/src/main.js +64 -78
  93. package/packages/select/src/select.vue +13 -6
  94. package/packages/selector/src/selector.vue +6 -13
  95. package/packages/table/src/config.js +48 -0
  96. package/packages/table/src/store/index.js +19 -4
  97. package/packages/table/src/store/watcher.js +14 -3
  98. package/packages/table/src/table-body.js +9 -4
  99. package/packages/table/src/table-column.js +17 -3
  100. package/packages/table/src/table-footer.js +4 -2
  101. package/packages/table/src/table-header.js +9 -6
  102. package/packages/table/src/table.vue +48 -27
  103. package/packages/theme-chalk/src/data-table.scss +4 -0
  104. package/packages/theme-chalk/src/form.scss +3 -0
  105. package/packages/theme-chalk/src/input.scss +2 -2
  106. package/packages/theme-chalk/src/menu.scss +8 -0
  107. package/packages/theme-chalk/src/mixins/function.scss +61 -12
  108. package/packages/theme-chalk/src/mixins/utils.scss +12 -0
  109. package/packages/theme-chalk/src/scrollbar.scss +4 -5
  110. package/packages/theme-chalk/src/selector.scss +6 -1
  111. package/packages/theme-chalk/src/table.scss +40 -0
  112. package/packages/theme-chalk/src/tree.scss +7 -6
  113. package/packages/theme-chalk/src/upload.scss +5 -0
  114. package/packages/tree/src/tree.vue +2 -13
  115. package/packages/upload/src/upload-list.vue +5 -10
  116. package/src/index.js +1 -1
  117. package/src/utils/popup/popup-manager.js +24 -9
@@ -8,22 +8,51 @@ import {
8
8
  addResizeListener,
9
9
  removeResizeListener
10
10
  } from 'eoss/src/utils/resize-event';
11
- import { getScrollbarWidth } from 'eoss/src/utils/scrollbar';
12
- import { toObject } from 'eoss/src/utils/util';
13
11
  import Bar from 'eoss/src/components/bar';
12
+ import { toObject } from 'eoss/src/utils/util';
14
13
  import ScrollMixin from './scroll-mixin';
15
14
 
16
- // 缓存 getScrollbarWidth 计算结果
17
- let cachedScrollbarWidth = null;
18
- function getCachedScrollbarWidth() {
19
- if (cachedScrollbarWidth === null) {
20
- cachedScrollbarWidth = getScrollbarWidth();
21
- // 监听窗口大小变化,重置缓存
22
- window.addEventListener('resize', () => {
23
- cachedScrollbarWidth = null;
24
- });
15
+ // 数字或纯数字字符串补 px,其余形式(100%、inherit 等)原样透传
16
+ function toCssSize(val) {
17
+ const str = String(val).trim();
18
+ return /^-?\d+(\.\d+)?$/.test(str) ? str + 'px' : str;
19
+ }
20
+
21
+ // 把 'a: b; c-d: e' 形式的样式串解析成驼峰对象
22
+ function parseStyleText(styleText) {
23
+ const res = {};
24
+ const list = String(styleText || '').split(';');
25
+ for (let i = 0; i < list.length; i++) {
26
+ const item = list[i];
27
+ const index = item.indexOf(':');
28
+ if (index < 0) continue;
29
+ const key = item.slice(0, index).trim();
30
+ if (!key) continue;
31
+ res[key.replace(/-(\w)/g, (match, letter) => letter.toUpperCase())] = item.slice(index + 1).trim();
32
+ }
33
+ return res;
34
+ }
35
+
36
+ // wrap-style 可以是 String / Object / Array,统一归一化成新对象:
37
+ // Vue 2 仅解析绑定为字符串的顶层 style,数组里的字符串项会被丢掉,
38
+ // 另外也不能直接在传入的对象上写字段,避免变更 prop
39
+ function normalizeWrapStyle(val) {
40
+ if (typeof val === 'string') {
41
+ return parseStyleText(val);
42
+ }
43
+ if (Array.isArray(val)) {
44
+ return toObject(val.map((item) => {
45
+ return typeof item === 'string' ? parseStyleText(item) : item || {};
46
+ }));
25
47
  }
26
- return cachedScrollbarWidth;
48
+ const res = {};
49
+ const source = val || {};
50
+ for (const key in source) {
51
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
52
+ res[key] = source[key];
53
+ }
54
+ }
55
+ return res;
27
56
  }
28
57
 
29
58
  /* istanbul ignore next */
@@ -118,7 +147,6 @@ export default {
118
147
  sizeHeight: '0',
119
148
  moveX: 0,
120
149
  moveY: 0,
121
- height: null,
122
150
  initialized: false,
123
151
  isHovering: false,
124
152
  hideTimer: null,
@@ -152,47 +180,27 @@ export default {
152
180
  }
153
181
  },
154
182
 
155
- // 在 render 方法中使用缓存
156
183
  render(h) {
157
- let gutter = getCachedScrollbarWidth();
158
- let style = this.wrapStyle;
159
- if (gutter) {
160
- const gutterWith = `-${gutter}px`;
161
- let gutterStyle = `margin-bottom: ${gutterWith}; margin-right: ${gutterWith};`;
162
- if (this.styles || this.height || this.maxHeight) {
163
- let height = this.height || this.styles && this.styles.height;
164
- if (height === '100%') {
165
- gutterStyle += `height:calc(100% + ${gutter}px);`;
166
- } else {
167
- gutterStyle += height ? 'height:' + (parseInt(height, 10) + gutter) + 'px' : '';
168
- }
169
- let maxHeight = this.maxHeight ||
170
- this.styles && this.styles.maxHeight ||
171
- this.styles && this.styles['max-height'];
172
- if (maxHeight === '100%') {
173
- gutterStyle += `max-height:calc(100% + ${gutter}px);`;
174
- } else {
175
- gutterStyle += maxHeight ? 'max-height:' + parseInt(maxHeight, 10) + 'px' : '';
176
- }
177
- } else {
178
- gutterStyle += `height:calc(100% + ${gutter}px);`;
179
- }
180
-
181
- if (Array.isArray(this.wrapStyle)) {
182
- style = toObject(this.wrapStyle);
183
- style.marginRight = style.marginBottom = gutterWith;
184
- if (!style.height && !style.maxHeight) {
185
- style.height = '100%';
186
- }
187
- } else if (typeof this.wrapStyle === 'string') {
188
- style += gutterStyle;
189
- } else {
190
- style = gutterStyle;
191
- }
192
- } else {
193
- style = 'height:100%;';
184
+ // wrap 内联样式只负责高度声明与自定义样式,不再做原生滚动条的占位补偿:
185
+ // 原生滚动条已由 CSS 隐藏(--hidden-default 恒挂,IE 走 -ms-overflow-style),
186
+ // 本身不占位;此前的负 margin + calc(100% + gutter) 在浏览器缩放时,量取的
187
+ // gutter 取整宽度和实际渲染宽度对不上,底部/右侧就会露出一条灰边。
188
+ const wrapStyles = normalizeWrapStyle(this.wrapStyle);
189
+ const height = this.styles && this.styles.height;
190
+ const maxHeight = this.maxHeight ||
191
+ (this.styles && (this.styles.maxHeight || this.styles['max-height']));
192
+
193
+ // 已有的键不覆盖,保证用户显式写的 wrap-style 优先
194
+ if (height && wrapStyles.height === undefined) {
195
+ wrapStyles.height = toCssSize(height);
196
+ }
197
+ if (maxHeight && wrapStyles.maxHeight === undefined) {
198
+ wrapStyles.maxHeight = toCssSize(maxHeight);
194
199
  }
195
200
 
201
+ const hasStyle = Object.keys(wrapStyles).length > 0;
202
+ const style = hasStyle ? wrapStyles : undefined;
203
+
196
204
  // 虚拟滚动实现
197
205
  const view = h(
198
206
  this.tag,
@@ -211,8 +219,7 @@ export default {
211
219
  onScroll={this.handleScroll}
212
220
  class={[
213
221
  this.wrapClass,
214
- 'es-scrollbar__wrap',
215
- gutter ? '' : 'es-scrollbar__wrap--hidden-default'
222
+ 'es-scrollbar__wrap es-scrollbar__wrap--hidden-default'
216
223
  ]}
217
224
  >
218
225
  {[view]}
@@ -245,8 +252,9 @@ export default {
245
252
  nodes = [
246
253
  <div
247
254
  ref="wrap"
248
- class={[this.wrapClass, 'es-scrollbar__wrap']}
249
255
  style={style}
256
+ onScroll={this.handleScroll}
257
+ class={[this.wrapClass, 'es-scrollbar__wrap']}
250
258
  >
251
259
  {[view]}
252
260
  </div>
@@ -571,18 +579,8 @@ export default {
571
579
  const wrap = this.wrap;
572
580
  if (!wrap) return;
573
581
 
574
- // 确保 wrap 元素有正确的高度设置,特别是在嵌套场景下
575
- if (!wrap.style.height && !wrap.style.maxHeight && !this.height && !this.maxHeight) {
576
- // 如果没有设置高度,尝试从父元素获取
577
- const parent = wrap.parentNode;
578
- if (parent && parent.style.height) {
579
- wrap.style.height = parent.style.height;
580
- } else if (parent && parent.style.maxHeight) {
581
- wrap.style.height = parent.style.maxHeight;
582
- } else if (parent && parent.clientHeight) {
583
- wrap.style.height = parent.clientHeight + 'px';
584
- }
585
- }
582
+ // wrap 高度:CSS 给默认的 height: 100%,需要限高时由调用方通过
583
+ // max-height / wrap-style 声明(组件自身的 wrap-class 限高不受干扰)
586
584
 
587
585
  // 缓存计算值
588
586
  const clientHeight = wrap.clientHeight;
@@ -603,18 +601,6 @@ export default {
603
601
  }
604
602
 
605
603
  this.onReady && this.onReady(this.sizeHeight, this.sizeWidth);
606
-
607
- // 延迟执行高度计算逻辑
608
- requestAnimationFrame(() => {
609
- let maxH = wrap.parentNode.style['max-height'];
610
- if (maxH) {
611
- maxH = parseInt(maxH, 10);
612
- let gutter = getCachedScrollbarWidth();
613
- if (wrap.offsetHeight - gutter > maxH) {
614
- this.height = maxH;
615
- }
616
- }
617
- });
618
604
  });
619
605
  },
620
606
 
@@ -1100,6 +1100,10 @@ export default {
1100
1100
  },
1101
1101
 
1102
1102
  results: {
1103
+ // 树形模式的 options 完全由 data/results 驱动(树节点不是 es-option,不会自注册),
1104
+ // 必须 immediate:否则静态传入 data 时 results 初始化不触发 watcher,
1105
+ // options 恒为 [],下拉被 v-show="options.length > 0" 隐藏并显示「无数据」
1106
+ immediate: true,
1103
1107
  deep: true,
1104
1108
  handler(val) {
1105
1109
  if (this.tree) {
@@ -1726,14 +1730,17 @@ export default {
1726
1730
  if (this.filterable) this.$refs.input.focus();
1727
1731
  this.resetInputHeight();
1728
1732
  } else {
1733
+ let selectValue = option.value;
1729
1734
  if (this.valueType === 'string') {
1730
- this.$emit(
1731
- 'input',
1732
- getValueByPath(option.value, this.actualValueKey)
1733
- );
1734
- } else {
1735
- this.$emit('input', option.value);
1735
+ selectValue = getValueByPath(option.value, this.actualValueKey);
1736
+ // 树节点未提供 value-key 对应字段时取值为 undefined,直接写入 v-model 会让
1737
+ // setSelected 解析不出 label(表现为选中后不回显),此处退回整节点对象,
1738
+ // 由 getOption 的对象分支按 label-key 取标签
1739
+ if (this.tree && selectValue === undefined) {
1740
+ selectValue = option.value;
1741
+ }
1736
1742
  }
1743
+ this.$emit('input', selectValue);
1737
1744
  this.emitChange(option.value);
1738
1745
  this.visible = false;
1739
1746
  }
@@ -202,11 +202,7 @@ import {
202
202
  addResizeListener,
203
203
  removeResizeListener
204
204
  } from 'eoss/src/utils/resize-event';
205
- import {
206
- getScrollbarWidth,
207
- getScrollSize,
208
- scrollMove
209
- } from 'eoss/src/utils/scrollbar';
205
+ import { getScrollSize, scrollMove } from 'eoss/src/utils/scrollbar';
210
206
  export default {
211
207
  name: 'EsSelector',
212
208
  inheritAttrs: false,
@@ -590,8 +586,7 @@ export default {
590
586
  timer: null,
591
587
  tagsHeight: 0,
592
588
  moveTo: 0,
593
- barSize: 0,
594
- scrollbarWidth: 0
589
+ barSize: 0
595
590
  };
596
591
  },
597
592
  computed: {
@@ -600,13 +595,12 @@ export default {
600
595
  ? { 'max-height': this.tagsHeight + 'px', overflow: 'hidden' }
601
596
  : {};
602
597
  },
598
+ // tags 折叠限高时内层容器自身滚动,原生条由 CSS 隐藏(见 selector.scss),
599
+ // 不占位也就无需按条宽加宽容器把它推出去——那样在浏览器缩放时量到的
600
+ // 15px 和实际渲染宽度对不上,右侧会露出一条灰边
603
601
  tagsStyle() {
604
602
  return this.tagsHeight
605
- ? {
606
- 'max-height': this.tagsHeight + 'px',
607
- overflowY: 'scroll',
608
- width: `calc(100% + ${this.scrollbarWidth}px)`
609
- }
603
+ ? { 'max-height': this.tagsHeight + 'px', overflowY: 'scroll' }
610
604
  : {};
611
605
  },
612
606
  // 滚动容器
@@ -732,7 +726,6 @@ export default {
732
726
  this.mix && this.getSysParam();
733
727
  },
734
728
  mounted() {
735
- this.scrollbarWidth = getScrollbarWidth();
736
729
  //this.resetInputHeight();
737
730
  if (this.filterable) {
738
731
  this.$nextTick(() => {
@@ -24,6 +24,13 @@ export const cellStarts = {
24
24
  minWidth: 48,
25
25
  realWidth: 48,
26
26
  order: ''
27
+ },
28
+ drag: {
29
+ width: 48,
30
+ minWidth: 48,
31
+ realWidth: 48,
32
+ order: '',
33
+ className: 'es-table__drag-column'
27
34
  }
28
35
  };
29
36
 
@@ -147,6 +154,47 @@ export const cellForced = {
147
154
  sortable: false,
148
155
  resizable: false,
149
156
  className: 'es-table__expand-column'
157
+ },
158
+
159
+ drag: {
160
+ /**
161
+ * 拖拽列默认不渲染表头文案
162
+ * @param {Function} h - createElement函数
163
+ * @param {Object} options - 包含列配置的对象
164
+ * @returns {VNode} Vue虚拟节点
165
+ */
166
+ renderHeader: function(h, { column }) {
167
+ return column.label || '';
168
+ },
169
+
170
+ /**
171
+ * 渲染拖拽手柄图标:这一列存在即代表开启行拖拽排序(见 table.vue 的
172
+ * dragEnabled),Sortable 的 handle 指向 es-table__drag-handle。
173
+ * rules 为函数时按行判定(返回假值该行不可拖),rules 显式为 false 时
174
+ * 整列不可拖;不可拖时不给手柄类,Sortable 自然拖不动该行
175
+ * @param {Function} h - createElement函数
176
+ * @param {Object} options - 包含行数据、列配置等的对象
177
+ * @returns {VNode} Vue虚拟节点
178
+ */
179
+ renderCell: function(h, { row, column, $index, store }) {
180
+ const rules = column.rules;
181
+ const byRules =
182
+ typeof rules === 'function'
183
+ ? rules(row, { row, column, $index, store }) !== false
184
+ : rules !== false;
185
+ // 行数据 fixed 为 true 的行本来就不可拖(tr 上的 drag-sort-disabled
186
+ // 会被 Sortable 的 filter 拦掉),图标同步置灰
187
+ const enabled = byRules && !(row && row.fixed);
188
+ const classes = ['es-icon-tuozhuai'];
189
+ if (enabled) {
190
+ classes.push('es-table__drag-handle');
191
+ } else {
192
+ classes.push('is-disabled');
193
+ }
194
+ return <i class={ classes } />;
195
+ },
196
+ sortable: false,
197
+ resizable: false
150
198
  }
151
199
  };
152
200
 
@@ -126,7 +126,12 @@ Watcher.prototype.mutations = {
126
126
  const columnId =
127
127
  'es-table_1_column_' + Math.floor(Math.random() * 10000);
128
128
  let column = null;
129
- if (type === 'selection' || type === 'index' || type === 'expand') {
129
+ if (
130
+ type === 'selection' ||
131
+ type === 'index' ||
132
+ type === 'expand' ||
133
+ type === 'drag'
134
+ ) {
130
135
  column = {
131
136
  id: columnId,
132
137
  type: type,
@@ -135,7 +140,9 @@ Watcher.prototype.mutations = {
135
140
  property: _field,
136
141
  ...cellStarts[type],
137
142
  ...normalized,
138
- ...config
143
+ ...config,
144
+ // drag 列用 rules 控制行是否可拖(见 config.js)
145
+ rules
139
146
  };
140
147
  } else {
141
148
  column = {
@@ -145,7 +152,9 @@ Watcher.prototype.mutations = {
145
152
  property: _field,
146
153
  formatter,
147
154
  ...normalized,
148
- required: _required
155
+ required: _required,
156
+ // 保留 rules 到列对象:drag 列用它控制行是否可拖(见 config.js)
157
+ rules
149
158
  };
150
159
  }
151
160
  let childrens = null;
@@ -391,7 +400,8 @@ Watcher.prototype.mutations = {
391
400
  } else if (
392
401
  type === 'selection' ||
393
402
  type === 'index' ||
394
- type === 'expand'
403
+ type === 'expand' ||
404
+ type === 'drag'
395
405
  ) {
396
406
  // 特殊类型列不设置默认 renderCell,由 setColumnRenders 套用 cellForced 中的强制渲染函数
397
407
  } else {
@@ -496,6 +506,11 @@ Watcher.prototype.mutations = {
496
506
 
497
507
  states._columns = createColumns(thead);
498
508
  this.updateColumns();
509
+ // 换 thead 后列对象全部新建、realWidth 为空,若不重排布局,
510
+ // 表头与表体 colgroup 会各自按内容回退自动表格布局,列宽错位(sizer 确认改表头后必现)
511
+ if (this.table && this.table.$ready) {
512
+ this.scheduleLayout();
513
+ }
499
514
  },
500
515
 
501
516
  /**
@@ -109,7 +109,10 @@ export default Vue.extend({
109
109
  */
110
110
  updateColumns() {
111
111
  const states = this.states;
112
- const _columns = states._columns || [];
112
+ // hide 是「是否隐藏列」的列级契约(文档 thead 列配置):隐藏列不参与
113
+ // 渲染与布局,在列构建入口统一剔除,首屏与运行中换 thead(setThead)
114
+ // 都经这一条路径生效;states._columns 仍保留全量供增删列等操作使用
115
+ const _columns = (states._columns || []).filter(column => !column.hide);
113
116
 
114
117
  // 计算固定列和右侧固定列
115
118
  states.fixedColumns = _columns.filter(column => column.fixed === true || column.fixed === 'left');
@@ -121,9 +124,15 @@ export default Vue.extend({
121
124
  states.fixedColumns.unshift(_columns[0]);
122
125
  }
123
126
 
127
+ // 开启拖拽排序时左右固定层不渲染(见 table.vue 的 dragEnabled),fixed 不生效,
128
+ // 也就不做「固定列前置」重排,保持声明顺序,避免列序被静默打乱
129
+ const dragEnabled = _columns.some(column => column.type === 'drag');
130
+
124
131
  // 计算非固定列并生成原始列配置
125
132
  const notFixedColumns = _columns.filter(column => !column.fixed);
126
- states.originColumns = [...states.fixedColumns, ...notFixedColumns, ...states.rightFixedColumns];
133
+ states.originColumns = dragEnabled
134
+ ? [..._columns]
135
+ : [...states.fixedColumns, ...notFixedColumns, ...states.rightFixedColumns];
127
136
 
128
137
  // 扁平化各类列配置
129
138
  const leafColumns = doFlattenColumns(notFixedColumns);
@@ -136,7 +145,9 @@ export default Vue.extend({
136
145
  states.rightFixedLeafColumnsLength = rightFixedLeafColumns.length;
137
146
 
138
147
  // 生成最终的列配置和复杂度标记
139
- states.columns = [...fixedLeafColumns, ...leafColumns, ...rightFixedLeafColumns];
148
+ states.columns = dragEnabled
149
+ ? doFlattenColumns(_columns)
150
+ : [...fixedLeafColumns, ...leafColumns, ...rightFixedLeafColumns];
140
151
  states.isComplex = states.fixedColumns.length > 0 || states.rightFixedColumns.length > 0;
141
152
  },
142
153
 
@@ -109,8 +109,8 @@ export default {
109
109
  });
110
110
  },
111
111
 
112
- // 监听拖拽排序配置变化
113
- '$parent.dragSort'(val) {
112
+ // 监听拖拽列(type: 'drag')的增删,有则开启拖拽排序
113
+ 'table.dragEnabled'(val) {
114
114
  if (val) {
115
115
  this.initSortable();
116
116
  } else {
@@ -133,7 +133,7 @@ export default {
133
133
  },
134
134
 
135
135
  mounted() {
136
- if (this.$parent.dragSort) {
136
+ if (this.table.dragEnabled) {
137
137
  this.initSortable();
138
138
  }
139
139
  },
@@ -156,7 +156,9 @@ export default {
156
156
  this.$nextTick(() => {
157
157
  try {
158
158
  this._sortable = new Sortable(this.$refs.dragSort, {
159
- handle: this.$parent.dragSortClass ? `.${this.$parent.dragSortClass}` : undefined,
159
+ // 手柄就是拖拽列里的图标;不可拖的行(rules 判定为假、
160
+ // 或行数据 fixed 为 true)不带这个类,因此拖不动
161
+ handle: '.es-table__drag-handle',
160
162
  animation: 150,
161
163
  onUpdate: this.handleUpdate,
162
164
  filter: '.drag-sort-disabled'
@@ -203,6 +205,9 @@ export default {
203
205
  } else if (this.fixed === 'right') {
204
206
  return index < this.columnsCount - this.rightFixedLeafCount;
205
207
  } else {
208
+ // 开启拖拽排序时左右固定层不渲染(见 table.vue 的 dragEnabled),
209
+ // 固定列只能靠主表显示,不能再用 is-hidden 藏起来
210
+ if (this.table.dragEnabled) return false;
206
211
  return (index < this.leftFixedLeafCount) || (index >= this.columnsCount - this.rightFixedLeafCount);
207
212
  }
208
213
  },
@@ -25,7 +25,19 @@ export default {
25
25
  type: String,
26
26
  default: 'default'
27
27
  },
28
- filterIcon: [String, Boolean],
28
+ /**
29
+ * 列的规则;type 为 drag 时用它判定行是否可拖:
30
+ * 函数按行判定(返回 false 该行不可拖),false 表示整列不可拖。
31
+ * 必须显式写 default: undefined:类型里带 Boolean 时,Vue 会把未传的
32
+ * 值铸成 false,那就等于默认把整列拖拽关掉了
33
+ * @type {Function|Boolean|Array|Object}
34
+ */
35
+ rules: {
36
+ type: [Function, Boolean, Array, Object],
37
+ default: undefined
38
+ },
39
+ // Boolean 必须在 String 前:裸写 filterColumn 时 Vue 才会把空串铸成 true(同 sortable 的约定)
40
+ filterColumn: [Boolean, String],
29
41
  label: String,
30
42
  labelKey: String,
31
43
  valueKey: String,
@@ -393,11 +405,13 @@ export default {
393
405
  filterPlacement: '',
394
406
  isColumnGroup: false,
395
407
  filterOpened: false,
396
- filterIcon: this.filterIcon,
408
+ filterColumn: this.filterColumn,
397
409
  // 排序相关属性
398
410
  sortable: sortable,
399
411
  // 索引列
400
- index: this.index
412
+ index: this.index,
413
+ // drag 列用它控制行是否可拖(见 config.js 的 cellForced.drag)
414
+ rules: this.rules
401
415
  };
402
416
 
403
417
  // 收集不同类型的属性
@@ -284,9 +284,11 @@ export default {
284
284
  }
285
285
  return before < this.columnsCount - this.rightFixedLeafCount;
286
286
  } else if (!this.fixed && column && column.fixed) {
287
- // 当页脚实例不固定而列固定时隐藏单元格
288
- return true;
287
+ // 当页脚实例不固定而列固定时隐藏单元格;
288
+ // 开启拖拽排序时固定层不渲染,固定列要留在主表里显示
289
+ return !this.table.dragEnabled;
289
290
  } else {
291
+ if (this.table.dragEnabled) return false;
290
292
  return (index < this.leftFixedCount) || (index >= this.columnsCount - this.rightFixedCount);
291
293
  }
292
294
  },
@@ -164,7 +164,7 @@ export default {
164
164
  ]}
165
165
  >
166
166
  {/* 渲染过滤图标 */}
167
- {this._renderFilterIcon(h, column)}
167
+ {this._renderfilterColumn(h, column)}
168
168
 
169
169
  {/* 渲染列标题 */}
170
170
  {this._renderColumnLabel(h, cellIndex, column)}
@@ -312,6 +312,8 @@ export default {
312
312
  } else if (this.fixed === 'right') {
313
313
  return start < this.columnsCount - this.rightFixedLeafCount;
314
314
  } else {
315
+ // 开启拖拽排序时左右固定层不渲染,固定列表头只能靠主表显示
316
+ if (this.table.dragEnabled) return false;
315
317
  return (
316
318
  after < this.leftFixedLeafCount ||
317
319
  start >= this.columnsCount - this.rightFixedLeafCount
@@ -483,7 +485,8 @@ export default {
483
485
  * @param {Event} event - 事件对象
484
486
  * @param {Object} column - 列配置
485
487
  */
486
- handleFilterColumn(event, column) {
488
+ handlefilterColumnumn(event, column) {
489
+ console.log('filter-column');
487
490
  if (this.$parent) {
488
491
  this.$parent.$emit('filter-column', column, event);
489
492
  }
@@ -610,16 +613,16 @@ export default {
610
613
  * @param {Object} column - 列配置
611
614
  * @returns {VNode|null} 渲染结果
612
615
  */
613
- _renderFilterIcon(h, column) {
614
- if (!column.filterIcon) return null;
616
+ _renderfilterColumn(h, column) {
617
+ if (!column.filterColumn) return null;
615
618
 
616
619
  return (
617
620
  <span
618
621
  class="filter-column"
619
- on-click={($event) => this.handleFilterColumn($event, column)}
622
+ on-click={($event) => this.handlefilterColumnumn($event, column)}
620
623
  >
621
624
  <i
622
- class={[typeof column.filterIcon === 'string' ? column.filterIcon : 'es-icon-menu', 'filter-icon']}
625
+ class={[typeof column.filterColumn === 'string' ? column.filterColumn : 'es-icon-yingyong', 'filter-icon']}
623
626
  ></i>
624
627
  </span>
625
628
  );