leisure-core 1.0.2 → 1.0.3

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 (94) hide show
  1. package/index.js +223 -0
  2. package/le-area/index.js +7 -0
  3. package/le-area/src/main.vue +112 -0
  4. package/le-button/index.js +7 -0
  5. package/le-button/src/main.vue +47 -0
  6. package/le-button-attach/index.js +6 -0
  7. package/le-button-attach/src/main.vue +171 -0
  8. package/le-button-msg/index.js +7 -0
  9. package/le-button-msg/src/main.vue +65 -0
  10. package/le-button-qr/index.js +7 -0
  11. package/le-button-qr/src/main.vue +96 -0
  12. package/le-date-picker/index.js +7 -0
  13. package/le-date-picker/src/main.vue +67 -0
  14. package/le-date-picker-auto/index.js +6 -0
  15. package/le-date-picker-auto/src/main.vue +131 -0
  16. package/le-dialog-container/index.js +7 -0
  17. package/le-dialog-container/src/main.vue +80 -0
  18. package/le-form/index.js +7 -0
  19. package/le-form/src/main.vue +13 -0
  20. package/le-form-item/index.js +7 -0
  21. package/le-form-item/src/main.vue +13 -0
  22. package/le-home/index.js +7 -0
  23. package/le-home/src/LeHeaderMenu.vue +60 -0
  24. package/le-home/src/main.vue +1307 -0
  25. package/le-home/src/sub.vue +82 -0
  26. package/le-image/index.js +7 -0
  27. package/le-image/src/main.vue +53 -0
  28. package/le-input/index.js +7 -0
  29. package/le-input/src/main.vue +15 -0
  30. package/le-input-advanced/index.js +7 -0
  31. package/le-input-advanced/src/main.vue +71 -0
  32. package/le-input-number/index.js +7 -0
  33. package/le-input-number/src/main.vue +15 -0
  34. package/le-input-validate/index.js +6 -0
  35. package/le-input-validate/src/main.vue +469 -0
  36. package/le-libs/js/drag.js +78 -0
  37. package/le-libs/js/event.js +3 -0
  38. package/le-libs/js/hrequest.js +76 -0
  39. package/le-libs/js/hrequestFile.js +62 -0
  40. package/le-libs/js/info.js +7 -0
  41. package/le-libs/js/tokens.js +13 -0
  42. package/le-libs/mixins/main.js +48 -0
  43. package/le-list/index.js +7 -0
  44. package/le-list/src/main.vue +645 -0
  45. package/le-list-form/index.js +7 -0
  46. package/le-list-form/src/main.vue +474 -0
  47. package/le-login/index.js +7 -0
  48. package/le-login/src/ForgotPassword.vue +613 -0
  49. package/le-login/src/main.vue +982 -0
  50. package/le-media/index.js +7 -0
  51. package/le-media/src/main.vue +298 -0
  52. package/le-media-list/index.js +7 -0
  53. package/le-media-list/src/main.vue +178 -0
  54. package/le-media-upload/index.js +7 -0
  55. package/le-media-upload/src/main.vue +329 -0
  56. package/le-menu/index.js +7 -0
  57. package/le-menu/src/main.vue +248 -0
  58. package/le-report/index.js +6 -0
  59. package/le-report/src/main.vue +1747 -0
  60. package/le-report/src/rmixins.js +30 -0
  61. package/le-role/index.js +7 -0
  62. package/le-role/src/main.vue +183 -0
  63. package/le-role/src/sub.vue +79 -0
  64. package/le-role-user/index.js +7 -0
  65. package/le-role-user/src/main.vue +160 -0
  66. package/le-role-user/src/sub.vue +90 -0
  67. package/le-select/index.js +7 -0
  68. package/le-select/src/main.vue +49 -0
  69. package/le-select-multi/index.js +6 -0
  70. package/le-select-multi/src/main.vue +816 -0
  71. package/le-select-option/index.js +7 -0
  72. package/le-select-option/src/main.vue +69 -0
  73. package/le-select-search/index.js +7 -0
  74. package/le-select-search/src/main.vue +46 -0
  75. package/le-span/index.js +7 -0
  76. package/le-span/src/main.vue +29 -0
  77. package/le-table-edit/index.js +6 -0
  78. package/le-table-edit/src/main.vue +689 -0
  79. package/le-theme/common/vars.css +131 -0
  80. package/le-theme/iconfont/iconfont.css +125 -0
  81. package/le-theme/iconfont/iconfont.ttf +0 -0
  82. package/le-theme/iconfont/iconfont.woff +0 -0
  83. package/le-theme/iconfont/iconfont.woff2 +0 -0
  84. package/le-theme/index.js +189 -0
  85. package/le-theme/pages/index.css +15 -0
  86. package/le-upload/index.js +7 -0
  87. package/le-upload/src/main.vue +134 -0
  88. package/le-upload-table/index.js +6 -0
  89. package/le-upload-table/src/main.vue +648 -0
  90. package/le-url/index.js +7 -0
  91. package/le-url/src/main.vue +27 -0
  92. package/le-video/index.js +7 -0
  93. package/le-video/src/main.vue +42 -0
  94. package/package.json +1 -6
@@ -0,0 +1,48 @@
1
+ const leMixins = {
2
+ data() {
3
+ return {
4
+ elTableMaxHeight: 200,
5
+ };
6
+ },
7
+
8
+ mounted() {
9
+ window.addEventListener("resize", this.changeHeight);
10
+ this.changeHeight();
11
+ },
12
+
13
+ destroyed() {
14
+ window.removeEventListener("resize", this.changeHeight);
15
+ },
16
+ methods: {
17
+ renderHeader(h, { column, $index }) {
18
+ const opts = document.getElementsByClassName("le-table-btn-container");
19
+ let widthArr = [];
20
+ Array.prototype.forEach.call(opts, function (item) {
21
+ widthArr.push(item.offsetWidth);
22
+ });
23
+ if (widthArr.length > 0) {
24
+ let width = Math.max(...widthArr) + 24;
25
+ column.width = width;
26
+ return h("span", column.label);
27
+ } else {
28
+ column.width = 0;
29
+ return h("span", column.label);
30
+ }
31
+ },
32
+ changeHeight() {
33
+ this.$nextTick(() => {
34
+ if (!this.$refs.eltablemain) return;
35
+ let dyHeight = this.elTableMaxHeight;
36
+ let all = window.innerHeight;
37
+ let top = this.$refs.eltablemain.$el.getBoundingClientRect().top;
38
+ dyHeight = all - top - 90;
39
+ this.elTableMaxHeight = dyHeight;
40
+ if (this.elTableMaxHeight < 200) {
41
+ this.elTableMaxHeight = 200;
42
+ }
43
+ });
44
+ },
45
+ },
46
+ };
47
+
48
+ export default leMixins;
@@ -0,0 +1,7 @@
1
+ import LeList from "./src/main.vue";
2
+
3
+ LeList.install = function (Vue) {
4
+ Vue.component(LeList.name, LeList);
5
+ };
6
+
7
+ export default LeList;
@@ -0,0 +1,645 @@
1
+ <template>
2
+ <div class="page-container">
3
+ <div v-if="showQform">
4
+ <el-form :inline="true" class="demo-form-inline" :model="searchData">
5
+ <slot name="paramSlot"></slot>
6
+ <el-form-item>
7
+ <div class="queryBtnClass">
8
+ <slot></slot>
9
+ <le-button type="primary" @click="onClickQuery()" v-if="isDispQBtn"
10
+ >查询</le-button
11
+ >
12
+ <le-button type="primary" @click="addItem()" v-if="isDispAddBtn">{{
13
+ addBtnText
14
+ }}</le-button>
15
+ <slot name="btnright"></slot>
16
+ <slot name="headerBtns" :params="searchData"></slot>
17
+ </div>
18
+ </el-form-item>
19
+ </el-form>
20
+ </div>
21
+ <el-table
22
+ ref="eltablemain"
23
+ :max-height="elTableMaxHeight"
24
+ :data="tableData"
25
+ border
26
+ :row-key="rowId"
27
+ :header-cell-style="computedHeaderCellStyle"
28
+ :cell-style="computedCellStyle"
29
+ stripe
30
+ style="width: 100%"
31
+ reserve-selection
32
+ @selection-change="handleSelectionChange"
33
+ @cell-click="handleCellClick"
34
+ >
35
+ <el-table-column type="selection" v-if="showChecked" width="55" />
36
+ <el-table-column
37
+ v-for="column in tableColumns"
38
+ show-overflow-tooltip
39
+ :key="column.prop"
40
+ :prop="column.prop"
41
+ :label="column.label"
42
+ :width="column.width"
43
+ :class-name="column.className"
44
+ >
45
+ <template #default="scope">
46
+ <!-- <span v-html="renderColumnContent(column, scope)"></span> -->
47
+ <component
48
+ :is="renderColumnContent(column)"
49
+ v-bind="getComponentProps(column, scope)"
50
+ ></component>
51
+ </template>
52
+ </el-table-column>
53
+ <slot name="extColumn"></slot>
54
+ <el-table-column
55
+ fixed="right"
56
+ label="操作"
57
+ :width="btnCellWidht"
58
+ align="center"
59
+ v-if="isdispOper"
60
+ >
61
+ <template slot-scope="scope">
62
+ <template v-if="$scopedSlots.rowAllBtns">
63
+ <slot name="rowAllBtns" :rowItem="scope.row"></slot>
64
+ </template>
65
+ <template v-else>
66
+ <div class="rowBtns">
67
+ <slot name="rowBtnStand" :scope="scope">
68
+ <le-button
69
+ @click="editItem(scope.row)"
70
+ v-if="getBtnType(scope.row) === 'edit'"
71
+ >
72
+ {{ editBtnText }}</le-button
73
+ >
74
+ <le-button
75
+ @click="detail(scope.row)"
76
+ v-if="getBtnType(scope.row) === 'detail'"
77
+ >
78
+ {{ detailBtnText }}</le-button
79
+ >
80
+ <le-button-msg @click="del(scope.row.id)" v-if="isDispDelBtn"
81
+ >删除</le-button-msg
82
+ >
83
+ </slot>
84
+ <div class="rowBtnsExt">
85
+ <slot name="rowBtns" :scope="scope"></slot>
86
+ </div>
87
+ </div>
88
+ </template>
89
+ </template>
90
+ </el-table-column>
91
+ </el-table>
92
+ <div
93
+ style="text-align: center; margin-top: 30px"
94
+ v-if="searchData.total > searchData.pageSize"
95
+ >
96
+ <el-pagination
97
+ background
98
+ layout="prev, pager, next, jumper,sizes, total"
99
+ :current-page="searchData.pageNo"
100
+ :total="searchData.total"
101
+ :page-size="searchData.pageSize"
102
+ @current-change="current_change"
103
+ @size-change="size_change"
104
+ :page-sizes="pageSizes"
105
+ >
106
+ </el-pagination>
107
+ </div>
108
+ <le-dialog-container
109
+ :title="dialogTitle"
110
+ :width="dialogWidth"
111
+ :showDialog="showDialog"
112
+ :showCloseBtnTop="showCloseBtnTop"
113
+ @close="closeDialog"
114
+ >
115
+ <slot
116
+ name="expand"
117
+ v-if="showDialog && isDispExpand === 1"
118
+ :rowItem="rowItem"
119
+ ></slot>
120
+ <slot name="sub" v-else-if="showDialog" :rowItem="rowItem"></slot>
121
+ </le-dialog-container>
122
+ </div>
123
+ </template>
124
+ <script>
125
+ import leMixins from "../../le-libs/mixins/main";
126
+ import { EventBus } from "../../le-libs/js/event.js";
127
+ export default {
128
+ name: "le-list",
129
+ mixins: [leMixins],
130
+ props: {
131
+ expand: {
132
+ type: Number,
133
+ default: 0,
134
+ },
135
+ tableData: {
136
+ type: Array,
137
+ default: () => [],
138
+ },
139
+ showCloseBtnTop: {
140
+ type: Boolean,
141
+ default: false,
142
+ },
143
+ btnCellWidht: {
144
+ type: String,
145
+ default: "130px",
146
+ },
147
+ totalData: {
148
+ type: Number,
149
+ default: 1,
150
+ },
151
+ pageSizes: {
152
+ type: Array,
153
+ default: () => [10, 20, 30],
154
+ },
155
+ tableColumns: {
156
+ type: Array,
157
+ default: () => [],
158
+ },
159
+ searchParam: {
160
+ type: Object,
161
+ default: () => {},
162
+ },
163
+ isdispOper: {
164
+ type: Boolean,
165
+ default: true,
166
+ },
167
+ isDispAddBtn: {
168
+ type: Boolean,
169
+ default: true,
170
+ },
171
+ isDispQBtn: {
172
+ type: Boolean,
173
+ default: true,
174
+ },
175
+ addBtnText: {
176
+ type: String,
177
+ default: "新建",
178
+ },
179
+ detailBtnText: {
180
+ type: String,
181
+ default: "详情",
182
+ },
183
+ isDispDelBtn: {
184
+ type: Boolean,
185
+ default: false,
186
+ },
187
+ dialogWidth: {
188
+ type: String,
189
+ default: "60%",
190
+ },
191
+ dialogTitle: {
192
+ type: String,
193
+ default: "标题",
194
+ },
195
+ disBtn: {
196
+ type: [String, Function],
197
+ default: "edit",
198
+ },
199
+ showChecked: {
200
+ type: Boolean,
201
+ default: false,
202
+ },
203
+ rowId: {
204
+ type: String,
205
+ default: "id",
206
+ },
207
+ editBtnText: {
208
+ type: String,
209
+ default: "编辑",
210
+ },
211
+ headerCellStyle: {
212
+ type: Object,
213
+ default: () => ({}),
214
+ },
215
+ cellStyle: {
216
+ type: Object,
217
+ default: () => ({}),
218
+ },
219
+ showQform: {
220
+ type: Boolean,
221
+ default: true,
222
+ },
223
+ autoOpenDetail: {
224
+ type: [Boolean, Object, String],
225
+ default: false,
226
+ },
227
+ },
228
+ watch: {
229
+ expand: {
230
+ handler(newVal) {
231
+ this.isDispExpand = newVal;
232
+ },
233
+ immediate: true,
234
+ },
235
+ searchParam: {
236
+ handler(val) {
237
+ this.searchData = Object.assign({}, this.searchData, val);
238
+ },
239
+ deep: true,
240
+ immediate: true,
241
+ },
242
+ totalData: {
243
+ handler(val) {
244
+ this.searchData.total = val;
245
+ },
246
+ },
247
+ showQform: {
248
+ handler() {
249
+ this.changeHeight();
250
+ },
251
+ immediate: false,
252
+ },
253
+ tableData: {
254
+ handler(newVal) {
255
+ if (
256
+ this.autoOpenDetail &&
257
+ !this.autoOpened &&
258
+ newVal &&
259
+ newVal.length
260
+ ) {
261
+ this.$nextTick(() => {
262
+ this.tryAutoOpenDetail();
263
+ });
264
+ }
265
+ },
266
+ immediate: false, // 避免在 mounted 之前触发
267
+ deep: false,
268
+ },
269
+ autoOpenDetail: {
270
+ handler() {
271
+ this.autoOpened = false; // 重置标记,允许重新自动打开
272
+ if (this.tableData && this.tableData.length) {
273
+ this.$nextTick(() => {
274
+ this.tryAutoOpenDetail();
275
+ });
276
+ }
277
+ },
278
+ immediate: true,
279
+ },
280
+ },
281
+ data() {
282
+ return {
283
+ rowItem: {},
284
+ rowItems: [],
285
+ isDispExpand: 0, //是否显示扩展插槽 0:不显示 1:显示
286
+ searchData: {
287
+ pageNo: 1,
288
+ total: 1,
289
+ pageSize: 10,
290
+ },
291
+ showDialog: false,
292
+ handleStatus: 0, //处理状态 0:详情 1:新增 2:编辑
293
+
294
+ autoOpened: false, // 防止重复打开
295
+ componentMap: {
296
+ url: {
297
+ component: "le-url",
298
+ prop: "value",
299
+ },
300
+ text: {
301
+ component: "le-span",
302
+ prop: "value",
303
+ },
304
+ image: {
305
+ component: "le-image",
306
+ prop: "src",
307
+ style: { width: "40px", height: "40px" },
308
+ },
309
+ },
310
+ };
311
+ },
312
+ computed: {
313
+ toparam() {
314
+ if (this.showChecked) return this.rowItems;
315
+ else {
316
+ return this.rowItem;
317
+ }
318
+ },
319
+ isDispPage() {},
320
+ computedHeaderCellStyle() {
321
+ const defaultStyle = { "text-align": "center" };
322
+ return { ...defaultStyle, ...this.headerCellStyle };
323
+ },
324
+ computedCellStyle() {
325
+ const defaultStyle = { "text-align": "center" };
326
+ return { ...defaultStyle, ...this.cellStyle };
327
+ },
328
+ },
329
+ created() {
330
+ EventBus.$on("closeDialog", this.closeDialog);
331
+ },
332
+ destroyed() {
333
+ EventBus.$off("closeDialog", this.closeDialog);
334
+ },
335
+ mounted() {
336
+ this.getList();
337
+ },
338
+ methods: {
339
+ renderColumnContent(column) {
340
+ return this.componentMap[column.type]?.component || "le-span";
341
+ },
342
+ getComponentProps(column, scope) {
343
+ let value = scope.row[column.prop];
344
+ if (column.formatter) {
345
+ value = column.formatter(scope.rows, scope.column, value);
346
+ }
347
+ if (column.type) {
348
+ value = this.format(column.type, value, column.spec);
349
+ }
350
+ let ctype = this.componentMap[column.type];
351
+ let prop = ctype?.prop || "value";
352
+ let param = {};
353
+ param[prop] = value || "";
354
+ if (ctype?.style) {
355
+ param.style = ctype.style;
356
+ }
357
+ return param;
358
+ },
359
+ onClickQuery() {
360
+ this.searchData.pageNo = 1;
361
+ this.getList();
362
+ },
363
+ getList() {
364
+ let params = this.searchData;
365
+ this.$emit("getList", params);
366
+ },
367
+ current_change(currentPage) {
368
+ this.searchData.pageNo = currentPage;
369
+ this.getList();
370
+ },
371
+ del(id) {
372
+ this.$emit("delRow", id, () => {
373
+ this.getList();
374
+ });
375
+ },
376
+ getBtnType(row) {
377
+ if (typeof this.disBtn === "function") {
378
+ return this.disBtn(row); // 调用父组件传入的函数,传入当前行数据
379
+ }
380
+ return this.disBtn; // 兼容旧的字符串写法
381
+ },
382
+ customItem(rowData) {
383
+ this.handleStatus = 2;
384
+ if (rowData) {
385
+ this.rowItem = rowData;
386
+ }
387
+ this.$emit("handleStatus", this.handleStatus);
388
+ this.showDialog = true;
389
+ },
390
+ editItem(row) {
391
+ this.isDispExpand = 0;
392
+ this.handleStatus = 2;
393
+ this.$emit("handleStatus", this.handleStatus);
394
+ this.$emit("editCurrentRow", row);
395
+ this.rowItem = row;
396
+ this.showDialog = true;
397
+ },
398
+ detail(row) {
399
+ this.handleStatus = 0;
400
+ this.rowItem = row;
401
+ this.$emit("handleStatus", this.handleStatus);
402
+ this.$emit("detailCurrentRow", row);
403
+ this.showDialog = true;
404
+ },
405
+ openFirstDetail() {
406
+ if (this.tableData && this.tableData.length > 0) {
407
+ const firstRow = this.tableData[0];
408
+ this.detail(firstRow);
409
+ }
410
+ },
411
+ resetAutoOpenFlag() {
412
+ this.autoOpened = false;
413
+ },
414
+ tryAutoOpenDetail() {
415
+ if (this.autoOpened) return;
416
+ const config = this.autoOpenDetail;
417
+ if (!config) return;
418
+
419
+ let targetRow = null;
420
+ if (config === true || config === "first") {
421
+ if (this.tableData && this.tableData.length) {
422
+ targetRow = this.tableData[0];
423
+ } else {
424
+ console.warn("le-list: 表格数据为空,无法自动打开第一行详情");
425
+ return;
426
+ }
427
+ } else if (typeof config === "object" && config !== null) {
428
+ // 传入的对象即视为行数据
429
+ if (Object.keys(config).length) {
430
+ targetRow = config;
431
+ } else {
432
+ console.warn("le-list: 自动打开配置的行数据为空对象");
433
+ return;
434
+ }
435
+ }
436
+
437
+ if (targetRow) {
438
+ // 使用双重 nextTick 确保表格完全渲染后再打开弹窗,消除闪烁
439
+ this.$nextTick(() => {
440
+ setTimeout(() => {
441
+ this.detail(targetRow);
442
+ this.autoOpened = true;
443
+ }, 50); // 极短延迟,平滑过渡
444
+ });
445
+ }
446
+ },
447
+ addItem() {
448
+ this.handleStatus = 1;
449
+ this.$emit("handleStatus", this.handleStatus);
450
+ this.showDialog = true;
451
+ this.rowItem = {};
452
+ },
453
+ closeDialog() {
454
+ this.showDialog = false;
455
+ this.$emit("close");
456
+ },
457
+ size_change(item) {
458
+ this.searchData.pageSize = item;
459
+ this.getList();
460
+ },
461
+ handleSelectionChange(val) {
462
+ this.rowItems = val;
463
+ },
464
+ format(type, value, spec) {
465
+ // 参数验证
466
+ if (type === undefined || value === undefined) return value;
467
+
468
+ switch (type) {
469
+ case "bool":
470
+ return value === 1 || value === "1" || value === true ? "是" : "否";
471
+
472
+ case "date":
473
+ if (!value) return "";
474
+ try {
475
+ return spec ? this.parseTime(value, spec) : this.parseTime(value);
476
+ } catch {
477
+ return value;
478
+ }
479
+
480
+ case "currency":
481
+ if (value == null || value === "") return "";
482
+ const num = parseFloat(value);
483
+ if (isNaN(num)) return value;
484
+
485
+ const decimalPart = num.toString().split(".")[1];
486
+ const hasDecimal = decimalPart && decimalPart.length > 0;
487
+
488
+ return new Intl.NumberFormat("zh-CN", {
489
+ style: "decimal",
490
+ currency: "CNY",
491
+ minimumFractionDigits: hasDecimal
492
+ ? Math.min(decimalPart.length, 2)
493
+ : 0,
494
+ maximumFractionDigits: hasDecimal
495
+ ? Math.min(decimalPart.length, 4)
496
+ : 0,
497
+ }).format(num);
498
+
499
+ case "number":
500
+ return this.formatNumber(value, spec);
501
+ default:
502
+ return value;
503
+ }
504
+ },
505
+ // format(type, value, spec) {
506
+ // if (type === undefined || value === undefined) return value;
507
+
508
+ // switch (type) {
509
+ // // ... 其他 case 保持不变 ...
510
+
511
+ // case "number":
512
+ // return this.formatNumber(value, spec);
513
+
514
+ // default:
515
+ // return value;
516
+ // }
517
+ // },
518
+
519
+ /**
520
+ * 格式化数值(带千分位逗号分隔)
521
+ * @param {*} value - 要格式化的值
522
+ * @param {Object|string} options - 配置选项或格式字符串
523
+ * @returns {string} 格式化后的字符串
524
+ */
525
+ formatNumber(value, options = {}) {
526
+ // 处理空值
527
+ if (value == null || value === "") {
528
+ return options.nullValue || "";
529
+ }
530
+
531
+ // 转换为数值
532
+ const num = Number(value);
533
+ if (isNaN(num)) {
534
+ return options.invalidValue || value.toString();
535
+ }
536
+
537
+ // 如果 options 是字符串,解析为配置对象
538
+ let config = options;
539
+ if (typeof options === "string") {
540
+ config = this.parseNumberFormat(options);
541
+ }
542
+
543
+ // 默认配置
544
+ const defaultConfig = {
545
+ minimumIntegerDigits: 1, // 最小整数位数
546
+ minimumFractionDigits: 0, // 最小小数位数
547
+ maximumFractionDigits: 4, // 最大小数位数
548
+ useGrouping: true, // 使用千分位分隔符
549
+ nullValue: "", // 空值显示
550
+ invalidValue: value.toString(), // 无效值显示
551
+ ...config,
552
+ };
553
+
554
+ try {
555
+ return new Intl.NumberFormat("zh-CN", defaultConfig).format(num);
556
+ } catch (error) {
557
+ console.warn("Number format error:", error);
558
+ return num.toString();
559
+ }
560
+ },
561
+
562
+ /**
563
+ * 解析格式字符串为配置对象
564
+ * @param {string} formatStr - 格式字符串,如 "0,0.00"、"0,0[.]0#" 等
565
+ * @returns {Object} 配置对象
566
+ */
567
+ parseNumberFormat(formatStr = "0,0") {
568
+ const config = {
569
+ minimumFractionDigits: 0,
570
+ maximumFractionDigits: 0,
571
+ useGrouping: true,
572
+ };
573
+
574
+ // 简单解析格式字符串
575
+ if (formatStr.includes(".")) {
576
+ const parts = formatStr.split(".");
577
+ // 处理小数部分
578
+ const decimalPart = parts[1];
579
+ // 计算小数位数
580
+ config.minimumFractionDigits = decimalPart.replace(
581
+ /\[.*?\]/g,
582
+ "",
583
+ ).length;
584
+ config.maximumFractionDigits = decimalPart.length;
585
+ }
586
+
587
+ // 判断是否使用千分位
588
+ config.useGrouping = formatStr.includes(",");
589
+
590
+ return config;
591
+ },
592
+ /**
593
+ * 处理单元格点击
594
+ * @param {Object} row 行数据
595
+ * @param {Object} column 列配置
596
+ * @param {HTMLElement} cell 单元格元素
597
+ * @param {Event} event 原生事件对象
598
+ */
599
+ handleCellClick(row, column, cell, event) {
600
+ // 查找当前点击列对应的列配置
601
+ const colConfig = this.tableColumns.find(
602
+ (col) => col.prop === column.property,
603
+ );
604
+
605
+ // 如果列配置中定义了 cellClick 回调,则执行
606
+ if (colConfig && typeof colConfig.cellClick === "function") {
607
+ colConfig.cellClick({ row, column, cell, event });
608
+ }
609
+
610
+ // 向上抛出统一事件,供父组件监听
611
+ this.$emit("cell-click", { row, column, cell, event });
612
+ },
613
+ // getCellClassName({ row, column }) {
614
+ // const colConfig = this.tableColumns.find(
615
+ // (col) => col.prop === column.property,
616
+ // );
617
+ // return colConfig && typeof colConfig.cellClick === "function"
618
+ // ? "clickable-cell"
619
+ // : "";
620
+ // },
621
+ },
622
+ };
623
+ </script>
624
+ <style lang="less" scoped>
625
+ .rowBtns {
626
+ display: flex;
627
+ display: -webkit-flex;
628
+ flex-direction: row;
629
+ justify-content: center;
630
+ }
631
+
632
+ .rowBtnsExt {
633
+ margin-left: 3px;
634
+ }
635
+
636
+ .queryBtnClass {
637
+ display: flex !important;
638
+ display: -webkit-flex !important;
639
+ justify-content: flex-start;
640
+ gap: 5px;
641
+ }
642
+ .clickable-cell {
643
+ cursor: pointer !important;
644
+ }
645
+ </style>
@@ -0,0 +1,7 @@
1
+ import LeListForm from "./src/main.vue";
2
+
3
+ LeListForm.install = function (Vue) {
4
+ Vue.component(LeListForm.name, LeListForm);
5
+ };
6
+
7
+ export default LeListForm;