eoss 0.1.0-alpha.44 → 0.1.0-alpha.45

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 (45) hide show
  1. package/lib/button-group.js +11 -9
  2. package/lib/button.js +5 -3
  3. package/lib/cascader.js +3 -3
  4. package/lib/color-picker.js +6 -3
  5. package/lib/date-picker.js +5 -3
  6. package/lib/eoss.common.js +516 -188
  7. package/lib/index.js +1 -1
  8. package/lib/input-number.js +6 -2
  9. package/lib/input.js +148 -87
  10. package/lib/select.js +212 -11
  11. package/lib/switch.js +6 -3
  12. package/lib/table-column.js +10 -1
  13. package/lib/table.js +64 -22
  14. package/lib/tag.js +2 -0
  15. package/lib/theme-chalk/base.css +1 -1
  16. package/lib/theme-chalk/cascader.css +1 -1
  17. package/lib/theme-chalk/icons.css +1 -1
  18. package/lib/theme-chalk/index.css +1 -1
  19. package/lib/theme-chalk/main.css +1 -1
  20. package/lib/theme-chalk/pagination.css +1 -1
  21. package/lib/theme-chalk/select.css +1 -1
  22. package/lib/theme-chalk/table-column.css +1 -1
  23. package/lib/theme-chalk/table.css +1 -1
  24. package/lib/theme-chalk/tag.css +1 -1
  25. package/lib/time-picker.js +5 -3
  26. package/lib/time-select.js +5 -3
  27. package/package.json +1 -1
  28. package/packages/button/src/button-group.vue +9 -7
  29. package/packages/button/src/button.vue +7 -5
  30. package/packages/cascader/src/cascader.vue +1 -1
  31. package/packages/color-picker/src/color-picker.vue +4 -1
  32. package/packages/date-picker/src/picker.vue +3 -1
  33. package/packages/input/src/input.vue +94 -60
  34. package/packages/input-number/src/input-number.vue +5 -1
  35. package/packages/select/src/select.vue +182 -12
  36. package/packages/switch/src/switch.vue +4 -1
  37. package/packages/table/src/table-column.js +7 -1
  38. package/packages/table/src/table-header.js +52 -7
  39. package/packages/table/src/util.js +3 -0
  40. package/packages/tag/src/tag.vue +2 -0
  41. package/packages/theme-chalk/src/base.scss +7 -0
  42. package/packages/theme-chalk/src/icons.scss +13 -1
  43. package/packages/theme-chalk/src/table.scss +12 -2
  44. package/packages/theme-chalk/src/tag.scss +303 -242
  45. package/src/index.js +1 -1
@@ -26,46 +26,52 @@
26
26
  <es-button v-if="prepend" v-bind="prepend"></es-button>
27
27
  </slot>
28
28
  </div>
29
- <!-- 隐藏的输入框,用于阻止浏览器默认填充密码 -->
30
- <input
31
- v-if="type === 'password' || (showPassword && !passwordVisible)"
32
- type="password"
33
- class="es-input__hidden"
34
- style="
35
- position: absolute;
36
- top: -9999px;
37
- left: -9999px;
38
- width: 0;
39
- height: 0;
40
- opacity: 0;
41
- "
42
- autocomplete="off"
43
- />
44
- <input
45
- :tabindex="tabindex"
46
- v-if="type !== 'textarea'"
47
- class="es-input__inner"
48
- :class="{ 'is-round': round }"
49
- :style="innerStyle"
50
- v-bind="$attrs"
51
- :type="showPassword ? (passwordVisible ? 'text' : 'password') : type"
52
- :disabled="inputDisabled"
53
- :readonly="inputReadonly"
54
- :autocomplete="
55
- type === 'password' || (showPassword && !passwordVisible)
56
- ? 'new-password'
57
- : autoComplete || autocomplete
58
- "
59
- ref="input"
60
- @compositionstart="handleCompositionStart"
61
- @compositionupdate="handleCompositionUpdate"
62
- @compositionend="handleCompositionEnd"
63
- @input="handleInput"
64
- @focus="handleFocus"
65
- @blur="handleBlur"
66
- @change="handleChange"
67
- :aria-label="label"
68
- />
29
+ <!-- 只读态:纯文本展示,div 无光标不可聚焦;密码型未点眼预览时打码 -->
30
+ <div class="es-field-readonly" v-if="inputReadonly">
31
+ {{ passwordVisible ? nativeInputValue : maskedInputValue }}
32
+ </div>
33
+ <template v-else>
34
+ <!-- 隐藏的输入框,用于阻止浏览器默认填充密码 -->
35
+ <input
36
+ v-if="type === 'password' || (showPassword && !passwordVisible)"
37
+ type="password"
38
+ class="es-input__hidden"
39
+ style="
40
+ position: absolute;
41
+ top: -9999px;
42
+ left: -9999px;
43
+ width: 0;
44
+ height: 0;
45
+ opacity: 0;
46
+ "
47
+ autocomplete="off"
48
+ />
49
+ <input
50
+ :tabindex="tabindex"
51
+ v-if="type !== 'textarea'"
52
+ class="es-input__inner"
53
+ :class="{ 'is-round': round }"
54
+ :style="innerStyle"
55
+ v-bind="$attrs"
56
+ :type="showPassword ? (passwordVisible ? 'text' : 'password') : type"
57
+ :disabled="inputDisabled"
58
+ :readonly="nativeReadonly"
59
+ :autocomplete="
60
+ type === 'password' || (showPassword && !passwordVisible)
61
+ ? 'new-password'
62
+ : autoComplete || autocomplete
63
+ "
64
+ ref="input"
65
+ @compositionstart="handleCompositionStart"
66
+ @compositionupdate="handleCompositionUpdate"
67
+ @compositionend="handleCompositionEnd"
68
+ @input="handleInput"
69
+ @focus="handleFocus"
70
+ @blur="handleBlur"
71
+ @change="handleChange"
72
+ :aria-label="label"
73
+ />
74
+ </template>
69
75
  <!-- 前置内容 -->
70
76
  <span
71
77
  class="es-input__prefix"
@@ -129,26 +135,35 @@
129
135
  </slot>
130
136
  </div>
131
137
  </template>
132
- <textarea
133
- v-else
134
- :tabindex="tabindex"
135
- class="es-textarea__inner"
136
- @compositionstart="handleCompositionStart"
137
- @compositionupdate="handleCompositionUpdate"
138
- @compositionend="handleCompositionEnd"
139
- @input="handleInput"
140
- ref="textarea"
141
- v-bind="$attrs"
142
- :disabled="inputDisabled"
143
- :readonly="inputReadonly"
144
- :autocomplete="autoComplete || autocomplete"
145
- :style="textareaStyle"
146
- @focus="handleFocus"
147
- @blur="handleBlur"
148
- @change="handleChange"
149
- :aria-label="label"
150
- >
151
- </textarea>
138
+ <template v-else>
139
+ <div
140
+ class="es-field-readonly es-field-readonly--textarea"
141
+ v-if="inputReadonly"
142
+ style="white-space: pre-wrap; word-break: break-all"
143
+ >
144
+ {{ nativeInputValue }}
145
+ </div>
146
+ <textarea
147
+ v-else
148
+ :tabindex="tabindex"
149
+ class="es-textarea__inner"
150
+ @compositionstart="handleCompositionStart"
151
+ @compositionupdate="handleCompositionUpdate"
152
+ @compositionend="handleCompositionEnd"
153
+ @input="handleInput"
154
+ ref="textarea"
155
+ v-bind="$attrs"
156
+ :disabled="inputDisabled"
157
+ :readonly="nativeReadonly"
158
+ :autocomplete="autoComplete || autocomplete"
159
+ :style="textareaStyle"
160
+ @focus="handleFocus"
161
+ @blur="handleBlur"
162
+ @change="handleChange"
163
+ :aria-label="label"
164
+ >
165
+ </textarea>
166
+ </template>
152
167
  <span
153
168
  v-if="isWordLimitVisible && type === 'textarea'"
154
169
  class="es-input__count"
@@ -260,6 +275,14 @@ export default {
260
275
  * @default false
261
276
  */
262
277
  readonly: Boolean,
278
+ /**
279
+ * 仅绑定原生 input 的 readonly 属性(行为标志,供 select/cascader/picker 内部使用)
280
+ * @type {Boolean}
281
+ * @default false
282
+ * @description 这些复合组件给内部 es-input 传的 readonly 是"禁止打字但保留输入框结构"
283
+ * 的行为标志(普通态也常为 true),若走 readonly 会命中只读 div 分支导致布局破坏
284
+ */
285
+ nativeReadonly: Boolean,
263
286
  /**
264
287
  * 输入框类型
265
288
  * @type {String}
@@ -442,6 +465,17 @@ export default {
442
465
  ? ''
443
466
  : String(this.value);
444
467
  },
468
+ // 只读 div 用:密码型(含 showPassword 未点眼预览)按原生表现打码,
469
+ // div 无法应用 type="password",直接以掩码字符回显
470
+ maskedInputValue() {
471
+ if (
472
+ this.type !== 'password' &&
473
+ !(this.showPassword && !this.passwordVisible)
474
+ ) {
475
+ return this.nativeInputValue;
476
+ }
477
+ return '*'.repeat(this.nativeInputValue.length);
478
+ },
445
479
  showClear() {
446
480
  return (
447
481
  this.clearable &&
@@ -464,7 +464,10 @@ export default {
464
464
  }
465
465
  },
466
466
  mounted() {
467
- let innerInput = this.$refs.input.$refs.input;
467
+ // 只读态下内部 es-input 被 v-if 移除,ref 不存在,需与 updated 同样防护
468
+ if (!this.$refs || !this.$refs.input) return;
469
+ const innerInput = this.$refs.input.$refs.input;
470
+ if (!innerInput) return;
468
471
  innerInput.setAttribute('role', 'spinbutton');
469
472
  innerInput.setAttribute('aria-valuemax', this.max);
470
473
  innerInput.setAttribute('aria-valuemin', this.min);
@@ -474,6 +477,7 @@ export default {
474
477
  updated() {
475
478
  if (!this.$refs || !this.$refs.input) return;
476
479
  const innerInput = this.$refs.input.$refs.input;
480
+ if (!innerInput) return;
477
481
  innerInput.setAttribute('aria-valuenow', this.currentValue);
478
482
  }
479
483
  };
@@ -109,7 +109,7 @@
109
109
  :autocomplete="autocomplete"
110
110
  :size="selectSize"
111
111
  :disabled="selectDisabled"
112
- :readonly="inputReadonly"
112
+ :native-readonly="inputReadonly"
113
113
  :validate-event="false"
114
114
  :class="{ 'is-focus': visible }"
115
115
  :tabindex="tabindex"
@@ -162,11 +162,17 @@
162
162
  v-show="visible && emptyText !== false"
163
163
  >
164
164
  <es-scrollbar
165
+ v-loading="isLoading"
165
166
  tag="ul"
166
167
  wrap-class="es-select-dropdown__wrap"
167
168
  view-class="es-select-dropdown__list"
168
169
  ref="scrollbar"
169
170
  :listener="true"
171
+ :infinite-scroll="innerInfiniteScroll"
172
+ :infinite-scroll-disabled="innerInfiniteScrollDisabled"
173
+ :infinite-scroll-distance="infiniteScrollDistance"
174
+ :infinite-scroll-delay="infiniteScrollDelay"
175
+ :infinite-scroll-immediate="infiniteScrollImmediate"
170
176
  :class="{
171
177
  'is-empty': !allowCreate && query && filteredOptionsCount === 0
172
178
  }"
@@ -233,6 +239,13 @@
233
239
  ></es-option>
234
240
  </template>
235
241
  </slot>
242
+ <!-- 懒加载:续拉到底后提示没有更多数据 -->
243
+ <div
244
+ v-if="lazyEnabled && lazyFinished"
245
+ class="es-select-dropdown__finished"
246
+ >
247
+ 没有更多数据了
248
+ </div>
236
249
  </es-scrollbar>
237
250
  <template
238
251
  v-if="
@@ -696,7 +709,70 @@ export default {
696
709
  * 选项值的键名
697
710
  * @type {String}
698
711
  */
699
- valueKey: String
712
+ valueKey: String,
713
+ /**
714
+ * 无限滚动回调:下拉列表滚动到底部时触发,用于分页加载更多选项
715
+ * @type {Function}
716
+ * @description 选项数据由外部接口分页提供时,在回调中请求下一页并追加到 data;
717
+ * 没有更多数据时由外部置 infiniteScrollDisabled 为 true 停止触发
718
+ */
719
+ infiniteScroll: Function,
720
+ /**
721
+ * 是否禁用无限滚动
722
+ * @type {Boolean}
723
+ * @default false
724
+ */
725
+ infiniteScrollDisabled: Boolean,
726
+ /**
727
+ * 距底部多少 px 时触发无限滚动
728
+ * @type {Number}
729
+ * @default 0
730
+ */
731
+ infiniteScrollDistance: {
732
+ type: Number,
733
+ default: 0
734
+ },
735
+ /**
736
+ * 无限滚动回调的节流间隔(ms),透传给内部 es-scrollbar
737
+ * @type {Number}
738
+ * @default 200
739
+ */
740
+ infiniteScrollDelay: {
741
+ type: Number,
742
+ default: 200
743
+ },
744
+ /**
745
+ * 是否挂载后立即触发一次回调
746
+ * @type {Boolean}
747
+ * @default false
748
+ * @description 与 es-scrollbar 默认值(true)不同:下拉的滚动条随 select 一起挂载,
749
+ * 默认 true 会导致下拉尚未打开就自动请求首页,故这里默认关闭
750
+ */
751
+ infiniteScrollImmediate: {
752
+ type: Boolean,
753
+ default: false
754
+ },
755
+ /**
756
+ * 是否开启选项懒加载(分页加载)
757
+ * @type {Boolean}
758
+ * @default false
759
+ * @description 对 tree 为 false 的平铺 ul 列表生效,两种数据来源均支持:
760
+ * 1. url 取数:初始化请求第一页,下拉滚动到底部时自动续拉下一页并追加(内部复用无限滚动),
761
+ * 请求期间列表显示 loading;某页返回条数小于 pageSize 视为加载完毕停止触发
762
+ * 2. data 外部传入(未配置 url):本地分页,先渲染前 pageSize 条,
763
+ * 滚动到底部时同步切片追加下一页;data 变化时重置回第一页
764
+ */
765
+ lazy: Boolean,
766
+ /**
767
+ * 懒加载每页条数(url 取数时作为请求参数 pageNum/pageSize 随 param 一起 POST 给 url;
768
+ * data 本地懒加载时作为每页切片条数)
769
+ * @type {Number}
770
+ * @default 50
771
+ */
772
+ pageSize: {
773
+ type: Number,
774
+ default: 20
775
+ }
700
776
  },
701
777
 
702
778
  computed: {
@@ -708,6 +784,25 @@ export default {
708
784
  actualValueKey() {
709
785
  return this.valueKey || (this.sysCode ? 'cciValue' : 'value');
710
786
  },
787
+ // 懒加载生效条件:开启 lazy、非树形(平铺 ul 列表)、有数据来源(url 取数或 data 传入)
788
+ lazyEnabled() {
789
+ return this.lazy && !this.tree && (!!this.url || this.data.length > 0);
790
+ },
791
+ // 本地懒加载:未配置 url、由外部 data 传入时的分页切片模式
792
+ localLazyEnabled() {
793
+ return this.lazyEnabled && !this.url;
794
+ },
795
+ // 无限滚动回调:懒加载模式走内部分页续拉,否则透传外部 infiniteScroll
796
+ innerInfiniteScroll() {
797
+ return this.lazyEnabled ? this.loadMoreOptions : this.infiniteScroll;
798
+ },
799
+ // 无限滚动禁用:外部禁用,或懒加载中/已加载完时避免重复触发
800
+ innerInfiniteScrollDisabled() {
801
+ return (
802
+ this.infiniteScrollDisabled ||
803
+ (this.lazyEnabled && (this.isLoading || this.lazyFinished))
804
+ );
805
+ },
711
806
  model: {
712
807
  get() {
713
808
  if (this.multiple) {
@@ -856,7 +951,14 @@ export default {
856
951
  watch: {
857
952
  data: {
858
953
  handler(val) {
859
- this.results = val;
954
+ if (this.localLazyEnabled) {
955
+ // 本地懒加载:数据变化时重置回第一页重新切片
956
+ this.lazyPageNum = 1;
957
+ this.lazyFinished = false;
958
+ this.applyLocalLazySlice();
959
+ } else {
960
+ this.results = val;
961
+ }
860
962
  },
861
963
  deep: true
862
964
  },
@@ -1047,7 +1149,12 @@ export default {
1047
1149
  isDestroy: false,
1048
1150
  innerStyle: {},
1049
1151
  results: this.data,
1050
- _propsCache: new Map()
1152
+ // 懒加载分页状态:已加载到的页码 / 是否已加载完
1153
+ lazyPageNum: 1,
1154
+ lazyFinished: false,
1155
+ _propsCache: new Map(),
1156
+ // 是否请求中(驱动 es-scrollbar 上的 v-loading)
1157
+ isLoading: false
1051
1158
  };
1052
1159
  },
1053
1160
 
@@ -1075,6 +1182,10 @@ export default {
1075
1182
 
1076
1183
  this.$on('handleOptionClick', this.handleOptionSelect);
1077
1184
  this.$on('setSelected', this.setSelected);
1185
+ // 本地懒加载:初始只渲染 data 的第一页切片
1186
+ if (this.localLazyEnabled) {
1187
+ this.applyLocalLazySlice();
1188
+ }
1078
1189
  this.debouncedGetData();
1079
1190
  },
1080
1191
 
@@ -1178,21 +1289,80 @@ export default {
1178
1289
  * @param {Object} options - 配置选项
1179
1290
  * @param {String} options.url - 接口地址
1180
1291
  * @param {Object} options.params - 接口参数
1292
+ * @param {Boolean} options.append - 懒加载续拉下一页并追加(仅 lazyEnabled 时生效)
1181
1293
  */
1182
- getData({ url, params = {} }) {
1294
+ getData({ url, params = {}, append = false } = {}) {
1183
1295
  url = url || this.url;
1184
1296
  params = { ...this.param, ...params };
1185
- url &&
1186
- ajax({
1187
- url,
1188
- method: 'POST',
1189
- data: params
1190
- }).then((res) => {
1297
+ if (!url) return;
1298
+ if (this.lazyEnabled) {
1299
+ if (append) {
1300
+ // 续拉下一页
1301
+ this.isLoading = true;
1302
+ params = {
1303
+ ...params,
1304
+ pageNum: this.lazyPageNum + 1,
1305
+ pageSize: this.pageSize
1306
+ };
1307
+ } else {
1308
+ // 初始化/参数变化/远程搜索:重置分页请求第一页
1309
+ this.lazyPageNum = 1;
1310
+ this.lazyFinished = false;
1311
+ params = { ...params, pageNum: 1, pageSize: this.pageSize };
1312
+ }
1313
+ }
1314
+ ajax({
1315
+ url,
1316
+ method: 'POST',
1317
+ data: params
1318
+ })
1319
+ .then((res) => {
1191
1320
  if (res.rCode === 0) {
1192
- this.results = res.results || [];
1321
+ const rows = res.results || [];
1322
+ if (this.lazyEnabled && append) {
1323
+ this.results = this.results.concat(rows);
1324
+ this.lazyPageNum += 1;
1325
+ } else {
1326
+ this.results = rows;
1327
+ }
1328
+ // 续拉时返回条数不足一页视为已加载完,停止触发并提示没有更多
1329
+ // (首页不足一页属正常小数据量,不显示提示)
1330
+ if (this.lazyEnabled && append && rows.length < this.pageSize) {
1331
+ this.lazyFinished = true;
1332
+ }
1193
1333
  }
1334
+ this.isLoading = false;
1335
+ })
1336
+ .catch(() => {
1337
+ this.isLoading = false;
1194
1338
  });
1195
1339
  },
1340
+ /**
1341
+ * 懒加载:滚动到底部时加载下一页(由内部无限滚动触发,带防重入守卫)
1342
+ * 本地懒加载为同步切片追加,url 懒加载为异步续拉请求
1343
+ */
1344
+ loadMoreOptions() {
1345
+ if (!this.lazyEnabled || this.isLoading || this.lazyFinished) return;
1346
+ if (this.localLazyEnabled) {
1347
+ this.lazyPageNum += 1;
1348
+ this.applyLocalLazySlice();
1349
+ } else {
1350
+ this.getData({ append: true });
1351
+ }
1352
+ },
1353
+ /**
1354
+ * 本地懒加载:按当前 lazyPageNum 对 data 做切片渲染(0 ~ pageNum*pageSize),
1355
+ * 翻过页且切到末尾时置 lazyFinished 停止触发并显示没有更多提示
1356
+ * (首页即覆盖全量属正常小数据量,不置位不提示)
1357
+ */
1358
+ applyLocalLazySlice() {
1359
+ const list = this.data || [];
1360
+ const end = this.lazyPageNum * this.pageSize;
1361
+ this.results = list.slice(0, end);
1362
+ if (this.lazyPageNum > 1 && end >= list.length) {
1363
+ this.lazyFinished = true;
1364
+ }
1365
+ },
1196
1366
  handleComposition(event) {
1197
1367
  const text = event.target.value;
1198
1368
  if (event.type === 'compositionend') {
@@ -361,7 +361,10 @@ export default {
361
361
  if (this.activeColor || this.inactiveColor) {
362
362
  this.setBackgroundColor();
363
363
  }
364
- this.$refs.input.checked = this.checked;
364
+ // 只读态下内部 input 被 v-if 移除,需防护
365
+ if (this.$refs.input) {
366
+ this.$refs.input.checked = this.checked;
367
+ }
365
368
  }
366
369
  };
367
370
  </script>
@@ -30,7 +30,13 @@ export default {
30
30
  labelKey: String,
31
31
  valueKey: String,
32
32
  icon: String,
33
- button: [String, Object],
33
+ /**
34
+ * 表头按钮配置
35
+ * @type {String|Object|Array}
36
+ * @description String 渲染文字按钮;Object 渲染图标按钮(icon/type/class/nativeType/event);
37
+ * Array 渲染多个按钮,每项结构同 String/Object,Object 项的 event 回调签名为 ('', column, $event)
38
+ */
39
+ button: [String, Object, Array],
34
40
  className: String,
35
41
  labelClassName: String,
36
42
  property: String,
@@ -723,28 +723,73 @@ export default {
723
723
  * @param {Function} h - Vue渲染函数
724
724
  * @param {Object} column - 列配置
725
725
  * @returns {VNode|null} 渲染结果
726
+ * @description button 支持 String(文字按钮)/ Object(图标按钮)/
727
+ * Array(多个按钮,每项结构同 String/Object,Object 项可配置各自的 event 回调)
726
728
  */
727
729
  _renderColumnButton(h, column) {
728
730
  if (!column.button) return null;
729
731
 
730
- if (typeof column.button === 'string') {
732
+ // 数组配置:渲染多个按钮
733
+ if (Array.isArray(column.button)) {
734
+ if (!column.button.length) return null;
735
+ return (
736
+ <span class="es-table__column-buttons">
737
+ {column.button.map((item, index) =>
738
+ this._renderOneHeaderButton(h, column, item, index)
739
+ )}
740
+ </span>
741
+ );
742
+ }
743
+
744
+ return this._renderOneHeaderButton(h, column, column.button, 0);
745
+ },
746
+
747
+ /**
748
+ * 渲染单个表头按钮
749
+ * @private
750
+ * @param {Function} h - Vue渲染函数
751
+ * @param {Object} column - 列配置
752
+ * @param {String|Object} button - 按钮配置
753
+ * @param {number} index - 数组配置时的序号(用作 key)
754
+ * @returns {VNode|null} 渲染结果
755
+ */
756
+ _renderOneHeaderButton(h, column, button, index) {
757
+ if (!button) return null;
758
+
759
+ // 数组配置的按钮优先执行各自的 event 回调,其余走原表头点击链路
760
+ const onClick = ($event) => {
761
+ if (
762
+ Array.isArray(column.button) &&
763
+ typeof button === 'object' &&
764
+ typeof button.event === 'function'
765
+ ) {
766
+ $event.stopPropagation();
767
+ button.event('', column, $event);
768
+ return;
769
+ }
770
+ this.handleHeaderClick($event, column);
771
+ };
772
+
773
+ if (typeof button === 'string') {
731
774
  return (
732
775
  <es-button
776
+ key={index}
733
777
  size="mini"
734
778
  native-type="button"
735
- on-click={($event) => this.handleHeaderClick($event, column)}
736
- >{column.button}
779
+ on-click={onClick}
780
+ >{button}
737
781
  </es-button>
738
782
  );
739
783
  }
740
784
 
741
785
  return (
742
786
  <es-button
743
- class={[column.button.icon || column.icon, column.button.class]}
744
- type={column.button.type}
745
- native-type={column.button.nativeType || 'button'}
787
+ key={index}
788
+ class={[button.icon || column.icon, button.class]}
789
+ type={button.type}
790
+ native-type={button.nativeType || 'button'}
746
791
  size="mini"
747
- on-click={($event) => this.handleHeaderClick($event, column)}
792
+ on-click={onClick}
748
793
  >
749
794
  </es-button>
750
795
  );
@@ -1013,11 +1013,13 @@ export function renderDom(h, { type, data, optionData, config = {}, events = {}
1013
1013
  }
1014
1014
  });
1015
1015
  case 'handle':
1016
+ console.log('handle', data);
1016
1017
  // const contents = events.filter((item) => item.rules && typeof item.rules === 'function' ? item.rules(data.row) : true);
1017
1018
  return h('es-button-group', {
1018
1019
  class: className,
1019
1020
  props: {
1020
1021
  data: data.row,
1022
+ rowData: data,
1021
1023
  size: 'mini',
1022
1024
  type: 'text',
1023
1025
  stop: true,
@@ -1030,6 +1032,7 @@ export function renderDom(h, { type, data, optionData, config = {}, events = {}
1030
1032
  class: className,
1031
1033
  props: {
1032
1034
  param: data.row,
1035
+ rowData: data,
1033
1036
  size: 'mini',
1034
1037
  stop: true,
1035
1038
  ...configs
@@ -16,6 +16,8 @@ export default {
16
16
  closable: Boolean,
17
17
  /**
18
18
  * 类型
19
+ * @description 可选值:success / info / warning / danger / purple,
20
+ * 不填为默认蓝色主题;配合 effect(light/dark/plain,默认 light)使用
19
21
  */
20
22
  type: String,
21
23
  /**
@@ -278,3 +278,10 @@ table {
278
278
  position: relative;
279
279
  text-align: left;
280
280
  }
281
+ // 多行文本(textarea)只读态:还原空格与换行格式,样式对齐文本域
282
+ .es-field-readonly--textarea {
283
+ white-space: pre-wrap;
284
+ word-break: break-all;
285
+ line-height: 1.5;
286
+ padding: 5px 15px;
287
+ }
@@ -5,8 +5,20 @@
5
5
  color: transparent;
6
6
  }
7
7
  @include when(readonly) {
8
- .es-input__inner {
8
+ .es-field-readonly {
9
+ position: relative;
9
10
  z-index: -1;
11
+ color: transparent;
12
+ &::before {
13
+ content: '';
14
+ position: absolute;
15
+ top: 0;
16
+ left: 0;
17
+ right: 0;
18
+ bottom: 0;
19
+ background-color: #fff;
20
+ border-radius: 6px;
21
+ }
10
22
  }
11
23
  }
12
24
  @include when(focused) {
@@ -169,11 +169,10 @@
169
169
  }
170
170
  }
171
171
 
172
- th.es-table__cell.is-leaf,
172
+ th.es-table__cell,
173
173
  td.es-table__cell {
174
174
  border-bottom: $--table-border;
175
175
  }
176
-
177
176
  th.es-table__cell.is-sortable {
178
177
  cursor: pointer;
179
178
  }
@@ -638,4 +637,15 @@
638
637
  margin-right: 3px;
639
638
  }
640
639
  }
640
+
641
+ // 表头 button 配置为数组时的多按钮容器:按钮间留间距、整体与标题垂直对齐
642
+ .es-table__column-buttons {
643
+ display: inline-flex;
644
+ align-items: center;
645
+ vertical-align: middle;
646
+
647
+ .es-button + .es-button {
648
+ margin-left: 5px;
649
+ }
650
+ }
641
651
  }