leisure-core 1.0.2 → 1.0.4

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 +151 -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,474 @@
1
+ <template>
2
+ <el-form
3
+ :model="formPop"
4
+ :rules="rules"
5
+ ref="ruleForm"
6
+ :label-width="labelWidth"
7
+ class="le-form-container"
8
+ :disabled="formDisabled"
9
+ >
10
+ <div class="form-layout" :class="{ 'has-right-content': hasRightContent }">
11
+ <div class="form-main">
12
+ <div class="form-grid" :style="gridStyle">
13
+ <el-form-item
14
+ v-for="(item, index) in filteredFormColumns"
15
+ :label="item.label"
16
+ :prop="item.prop"
17
+ :key="`form-item-${index}-${item.prop}`"
18
+ class="leisure-form-item-class"
19
+ >
20
+ <div
21
+ class="comContainerClass"
22
+ :class="{ 'radio-container': item.type === 'radio' }"
23
+ >
24
+ <component
25
+ :is="componentType(item.type)"
26
+ v-model="formPop[item.prop]"
27
+ v-bind="mergeProps(getComponentProps(item), item.attr || {})"
28
+ v-on="item.event"
29
+ class="compontClass"
30
+ :class="{ 'radio-group-class': item.type === 'radio' }"
31
+ :key="`component-${index}-${item.prop}-${item.type}`"
32
+ :ref="(el) => setFieldRef(item.ref, el, item.prop)"
33
+ >
34
+ <template v-if="item.type === 'radio'">
35
+ <el-radio
36
+ v-for="(option, radioIndex) in item.options"
37
+ :label="option.id"
38
+ :key="`radio-${index}-${radioIndex}`"
39
+ >{{ option.lable }}</el-radio
40
+ >
41
+ </template>
42
+ <template v-else-if="item.type === 'select'">
43
+ <le-select-option
44
+ :options="fieldOptions[item.prop]"
45
+ :label="item.kv.label"
46
+ :value="item.kv.key"
47
+ :keyNum="item.keyNum"
48
+ :key="`select-${index}-${item.prop}`"
49
+ />
50
+ </template>
51
+ </component>
52
+ <slot :name="item.prop"></slot>
53
+ </div>
54
+ </el-form-item>
55
+ </div>
56
+ </div>
57
+ <!-- 右侧附件区域 - 新增 -->
58
+ <div class="form-sidebar" v-if="hasRightContent">
59
+ <div class="sidebar-content">
60
+ <slot name="sidebar"></slot>
61
+ </div>
62
+ </div>
63
+ </div>
64
+
65
+ <div class="form-body-footer">
66
+ <slot></slot>
67
+ </div>
68
+ <el-form-item v-rfooter class="form-footer">
69
+ <slot name="footerBtn"></slot>
70
+ <le-button
71
+ type="primary"
72
+ @click="saveData"
73
+ v-if="handleStatus == 1 || handleStatus == 2"
74
+ >保存</le-button
75
+ >
76
+ <le-button
77
+ type="info"
78
+ @click="close()"
79
+ :disabled="false"
80
+ v-if="showCloseBtn"
81
+ >关闭</le-button
82
+ >
83
+ </el-form-item>
84
+ </el-form>
85
+ </template>
86
+
87
+ <script>
88
+ import { EventBus } from "../../le-libs/js/event.js";
89
+ export default {
90
+ name: "le-list-form",
91
+ props: {
92
+ formColumns: {
93
+ type: Array,
94
+ default: () => [],
95
+ },
96
+ formData: {
97
+ type: Object,
98
+ default: () => {},
99
+ },
100
+ rules: {
101
+ type: Object,
102
+ default: () => {},
103
+ },
104
+ labelWidth: {
105
+ type: String,
106
+ default: "100px",
107
+ },
108
+ fieldOptions: {
109
+ type: Object,
110
+ default: () => {},
111
+ },
112
+ handleStatus: {
113
+ type: Number,
114
+ default: 0, //0:详情 1:新增 2:编辑
115
+ },
116
+ columnsPerRow: {
117
+ type: Number,
118
+ default: 1,
119
+ validator: (value) => value > 0 && value <= 4,
120
+ },
121
+ columnGap: {
122
+ type: String,
123
+ default: "20px",
124
+ },
125
+ rowGap: {
126
+ type: String,
127
+ default: "16px",
128
+ },
129
+ externalComponentMap: {
130
+ type: Object,
131
+ default: () => ({}),
132
+ },
133
+ // 新增属性:是否显示右侧边栏
134
+ showSidebar: {
135
+ type: Boolean,
136
+ default: false,
137
+ },
138
+ formDisabled: {
139
+ type: Boolean,
140
+ default: false,
141
+ },
142
+ showCloseBtn: {
143
+ type: Boolean,
144
+ default: true,
145
+ },
146
+ },
147
+ watch: {
148
+ formData: {
149
+ handler(val) {
150
+ if (val) {
151
+ this.formPop = JSON.parse(JSON.stringify(val));
152
+ this.$emit("itemChange", this.formPop);
153
+ }
154
+ },
155
+ deep: true,
156
+ immediate: true,
157
+ },
158
+ fieldOptions: {
159
+ handler(val) {
160
+ this.options = val;
161
+ },
162
+ deep: true,
163
+ immediate: true,
164
+ },
165
+ },
166
+ data() {
167
+ return {
168
+ formPop: {},
169
+ options: {},
170
+ fieldComponents: {},
171
+ };
172
+ },
173
+ computed: {
174
+ filteredFormColumns() {
175
+ return this.formColumns.filter((item) => {
176
+ if (typeof item.hidden === "function") {
177
+ return !item.hidden(this.formPop);
178
+ }
179
+ return !item.hidden;
180
+ });
181
+ },
182
+
183
+ // 判断是否有右侧内容
184
+ hasRightContent() {
185
+ return this.showSidebar || this.$slots["sidebar"];
186
+ },
187
+
188
+ dynamicComponentMap() {
189
+ const baseMap = {
190
+ input: {
191
+ component: "le-input",
192
+ props: { placeholder: "请输入" },
193
+ },
194
+ checkbox: { component: "el-checkbox", props: {} },
195
+ inputValidate: {
196
+ component: "le-input-validate",
197
+ props: { placeholder: "请输入" },
198
+ },
199
+ number: {
200
+ component: "le-input-number",
201
+ props: {},
202
+ },
203
+ radio: { component: "el-radio-group", props: {} },
204
+ money: {
205
+ component: "le-input-advanced",
206
+ props: {},
207
+ },
208
+ date: {
209
+ component: "le-date-picker",
210
+ props: {
211
+ format: "yyyy-MM-dd",
212
+ "value-format": "timestamp",
213
+ translateDate: true,
214
+ },
215
+ },
216
+ dateAuto: {
217
+ component: "le-date-picker-auto",
218
+ props: {
219
+ format: "yyyy-MM-dd",
220
+ "value-format": "timestamp",
221
+ },
222
+ },
223
+ select: { component: "le-select", props: {} },
224
+ smulti: { component: "le-select-multi", props: {} },
225
+ image: { component: "le-image-container", props: {} },
226
+ area: {
227
+ component: "le-area",
228
+ props: {},
229
+ },
230
+ };
231
+ return { ...baseMap, ...this.externalComponentMap };
232
+ },
233
+
234
+ gridStyle() {
235
+ return {
236
+ "grid-template-columns": `repeat(${this.columnsPerRow}, 1fr)`,
237
+ "column-gap": this.columnGap,
238
+ "row-gap": this.rowGap,
239
+ };
240
+ },
241
+ },
242
+ mounted() {
243
+ this.$nextTick(() => {
244
+ this.$emit("form-ready", {
245
+ setFieldValue: this.setFieldValue,
246
+ getFormData: this.getFormData,
247
+ initFormData: this.initFormData,
248
+ getFieldComponent: this.getFieldComponent, // 暴露获取字段组件的方法
249
+ getAllFieldComponents: this.getAllFieldComponents, // 暴露获取所有字段组件的方法
250
+ });
251
+ });
252
+ },
253
+ methods: {
254
+ // 设置字段组件引用
255
+ setFieldRef(refName, el, propName) {
256
+ if (el) {
257
+ // 组件挂载时,el 是组件实例
258
+ if (refName) {
259
+ // 如果有自定义 ref 名称,使用它
260
+ this.fieldComponents[refName] = el;
261
+ this.$refs[refName] = el; // 同时设置到 $refs 上
262
+ } else {
263
+ // 如果没有自定义 ref,使用 prop 名称作为默认 ref
264
+ const defaultRef = `field_${propName}`;
265
+ this.fieldComponents[defaultRef] = el;
266
+ this.$refs[defaultRef] = el;
267
+ }
268
+ } else {
269
+ // 组件销毁时,el 为 null,清除引用
270
+ if (refName) {
271
+ delete this.fieldComponents[refName];
272
+ delete this.$refs[refName];
273
+ } else {
274
+ const defaultRef = `field_${propName}`;
275
+ delete this.fieldComponents[defaultRef];
276
+ delete this.$refs[defaultRef];
277
+ }
278
+ }
279
+ },
280
+ // 获取特定字段的组件实例
281
+ getFieldComponent(refName) {
282
+ // 先从存储的实例中查找
283
+ if (this.fieldComponents[refName]) {
284
+ return this.fieldComponents[refName];
285
+ }
286
+
287
+ // 再从 $refs 中查找
288
+ if (this.$refs[refName]) {
289
+ return this.$refs[refName];
290
+ }
291
+
292
+ console.warn(`未找到字段组件: ${refName}`);
293
+ return null;
294
+ },
295
+
296
+ // 获取所有字段组件实例
297
+ getAllFieldComponents() {
298
+ return { ...this.fieldComponents, ...this.$refs };
299
+ },
300
+ componentType(type) {
301
+ if (!this.dynamicComponentMap[type]) {
302
+ return "le-input";
303
+ }
304
+ return this.dynamicComponentMap[type]?.component || "le-input";
305
+ },
306
+ getComponentProps(item) {
307
+ let type = item.type;
308
+
309
+ if (!this.dynamicComponentMap[type]) {
310
+ return {};
311
+ }
312
+
313
+ let props = this.dynamicComponentMap[type]?.props || {};
314
+ if (type === "image") {
315
+ let images = [];
316
+ images.push(this.formPop[item.prop]);
317
+ props = { ...props, images: images };
318
+ return props;
319
+ }
320
+ return this.dynamicComponentMap[item.type]?.props || {};
321
+ },
322
+ mergeProps(defaultProps, customProps) {
323
+ return { ...defaultProps, ...customProps };
324
+ },
325
+ close() {
326
+ EventBus.$emit("closeDialog");
327
+ this.$emit("closeDialog");
328
+ },
329
+ saveData() {
330
+ this.$refs["ruleForm"].validate((valid) => {
331
+ if (valid) {
332
+ this.$emit("saveData", this.formPop, () => {});
333
+ } else {
334
+ return false;
335
+ }
336
+ });
337
+ },
338
+
339
+ initFormData(additionalData = {}) {
340
+ this.formPop = {
341
+ ...this.formPop,
342
+ ...additionalData,
343
+ };
344
+ },
345
+
346
+ setFieldValue(field, value) {
347
+ this.$set(this.formPop, field, value);
348
+ },
349
+
350
+ getFormData() {
351
+ return { ...this.formPop };
352
+ },
353
+ },
354
+ };
355
+ </script>
356
+
357
+ <style lang="scss" scoped>
358
+ .le-form-container {
359
+ width: 100%;
360
+ }
361
+
362
+ .form-layout {
363
+ display: flex;
364
+ gap: 20px;
365
+ transition: all 0.3s ease;
366
+
367
+ // 有右侧内容时的布局
368
+ &.has-right-content {
369
+ .form-main {
370
+ width: 80%;
371
+ }
372
+ .form-sidebar {
373
+ width: 20%;
374
+ }
375
+ }
376
+
377
+ // 无右侧内容时的布局
378
+ &:not(.has-right-content) {
379
+ .form-main {
380
+ width: 100%;
381
+ }
382
+ }
383
+ }
384
+
385
+ .form-main {
386
+ transition: width 0.3s ease;
387
+ }
388
+
389
+ .form-sidebar {
390
+ transition: width 0.3s ease;
391
+
392
+ .sidebar-content {
393
+ border-radius: 6px;
394
+ padding: 16px;
395
+ min-height: 200px;
396
+
397
+ 可以在这里添加右侧内容的统一样式 h4 {
398
+ margin: 0 0 12px 0;
399
+ color: #2c3e50;
400
+ font-size: 14px;
401
+ font-weight: 600;
402
+ }
403
+ }
404
+ }
405
+
406
+ .form-grid {
407
+ display: grid;
408
+
409
+ @media (max-width: 768px) {
410
+ grid-template-columns: 1fr !important;
411
+ }
412
+ }
413
+
414
+ .leisure-form-item-class {
415
+ margin-bottom: 0;
416
+ }
417
+
418
+ .form-body-footer {
419
+ margin-top: 10px;
420
+ }
421
+
422
+ .comContainerClass {
423
+ display: flex;
424
+ display: -webkit-flex;
425
+ line-height: inherit;
426
+ justify-content: center;
427
+
428
+ &.radio-container {
429
+ align-items: center;
430
+ min-height: 40px;
431
+ }
432
+
433
+ .compontClass {
434
+ flex: 1;
435
+
436
+ &.radio-group-class {
437
+ display: flex;
438
+ align-items: center;
439
+ flex-wrap: wrap;
440
+ line-height: normal;
441
+ }
442
+ }
443
+ }
444
+
445
+ .form-footer {
446
+ margin-top: 20px;
447
+ text-align: right;
448
+ }
449
+
450
+ // 响应式处理
451
+ @media (max-width: 1200px) {
452
+ .form-layout.has-right-content {
453
+ flex-direction: column;
454
+
455
+ .form-main,
456
+ .form-sidebar {
457
+ width: 100%;
458
+ }
459
+
460
+ .form-sidebar {
461
+ margin-top: 20px;
462
+ order: 2; // 在移动端让侧边栏显示在下方
463
+ }
464
+ }
465
+ }
466
+
467
+ // 小屏幕优化
468
+ @media (max-width: 768px) {
469
+ .form-sidebar .sidebar-content {
470
+ padding: 12px;
471
+ min-height: 150px;
472
+ }
473
+ }
474
+ </style>
@@ -0,0 +1,7 @@
1
+ import LeLogin from "./src/main.vue";
2
+
3
+ LeLogin.install = function (Vue) {
4
+ Vue.component(LeLogin.name, LeLogin);
5
+ };
6
+
7
+ export default LeLogin;