free-fe-core-modules 0.0.1 → 0.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 (109) hide show
  1. package/components/Basic/EIcon.vue +2 -4
  2. package/components/Basic/LeveledMenus.vue +0 -5
  3. package/components/Basic/SummaryHead.vue +10 -3
  4. package/components/Dialog/BasicDialog.vue +10 -77
  5. package/components/Dialog/index.js +44 -34
  6. package/components/Dialog/index2.js +44 -0
  7. package/components/SelectLocales/index.vue +3 -4
  8. package/components/SlidingCarousel/index.vue +0 -1
  9. package/components/SlidingNews/index.vue +0 -1
  10. package/components/StickyButtons/index.vue +2 -2
  11. package/components/ThemeSwitch/index.vue +14 -8
  12. package/composible/useObjectData.js +69 -0
  13. package/free-field/Fields/AgreementCheck.js +170 -0
  14. package/free-field/Fields/ApiCall.js +123 -0
  15. package/{field-components/Fields/Boolean.vue → free-field/Fields/Boolean.js} +40 -46
  16. package/free-field/Fields/Category.js +28 -0
  17. package/free-field/Fields/Check.js +106 -0
  18. package/free-field/Fields/Customize.js +87 -0
  19. package/free-field/Fields/Date.js +133 -0
  20. package/free-field/Fields/DateRange.js +226 -0
  21. package/free-field/Fields/DynamicList.js +565 -0
  22. package/{field-components → free-field}/Fields/File.vue +3 -3
  23. package/{field-components → free-field}/Fields/FileList.vue +4 -4
  24. package/{field-components → free-field}/Fields/FileListCombined.vue +3 -3
  25. package/{field-components → free-field}/Fields/FixedList.vue +78 -83
  26. package/{field-components → free-field}/Fields/Image.vue +2 -2
  27. package/{field-components → free-field}/Fields/ImageList.vue +1 -1
  28. package/{field-components → free-field}/Fields/ImageListCombined.vue +1 -1
  29. package/free-field/Fields/InputFieldList.vue +324 -0
  30. package/{field-components → free-field}/Fields/Labels.vue +24 -15
  31. package/{field-components → free-field}/Fields/MixedTable.vue +53 -61
  32. package/free-field/Fields/Number.js +167 -0
  33. package/free-field/Fields/Password.js +81 -0
  34. package/{field-components → free-field}/Fields/Permission.vue +17 -13
  35. package/{field-components → free-field}/Fields/PermissionEditor.vue +63 -105
  36. package/{field-components → free-field}/Fields/QueryFilters.vue +65 -48
  37. package/{field-components → free-field}/Fields/RadioList.vue +36 -12
  38. package/{field-components → free-field}/Fields/Rich.vue +104 -114
  39. package/{field-components → free-field}/Fields/Search.vue +35 -26
  40. package/{field-components → free-field}/Fields/Select.vue +116 -88
  41. package/{field-components → free-field}/Fields/SelectionChain.vue +89 -67
  42. package/{field-components/Fields/Separator.vue → free-field/Fields/Separator.js} +11 -16
  43. package/{field-components → free-field}/Fields/SingleList.vue +27 -21
  44. package/free-field/Fields/Static.js +27 -0
  45. package/free-field/Fields/String.js +105 -0
  46. package/free-field/Fields/Text.js +80 -0
  47. package/{field-components → free-field}/Fields/Time.vue +59 -43
  48. package/{field-components → free-field}/Fields/TimeRange.vue +107 -92
  49. package/{field-components → free-field}/Fields/UltimateFile.vue +1 -1
  50. package/free-field/Fields/Year.js +137 -0
  51. package/{field-components → free-field}/Fields/YearRange.vue +63 -73
  52. package/{field-components → free-field}/Fields/index.js +16 -18
  53. package/free-field/composible/fieldWrapper.js +221 -0
  54. package/free-field/composible/freeFieldLabel.js +22 -0
  55. package/free-field/composible/readonlyContent.js +36 -0
  56. package/free-field/composible/useFileSizeUtils.js +52 -0
  57. package/free-field/composible/useFreeField.js +143 -0
  58. package/{field-components → free-field}/index.js +3 -3
  59. package/i18n/en-us/index.js +1 -1
  60. package/i18n/zh-cn/index.js +1 -1
  61. package/index.js +4 -22
  62. package/package.json +1 -1
  63. package/router/error/data.js +4 -1
  64. package/view/dict/index.vue +13 -4
  65. package/view/error/list.vue +22 -14
  66. package/view/menu/index.vue +19 -9
  67. package/view/system/index.vue +15 -2
  68. package/components/Dialog/index1.js +0 -49
  69. package/field-components/Fields/AgreementCheck.vue +0 -161
  70. package/field-components/Fields/ApiCall.vue +0 -139
  71. package/field-components/Fields/Category.vue +0 -33
  72. package/field-components/Fields/Check.vue +0 -131
  73. package/field-components/Fields/Customize.vue +0 -103
  74. package/field-components/Fields/Date.vue +0 -142
  75. package/field-components/Fields/DateRange.vue +0 -199
  76. package/field-components/Fields/DynamicList.vue +0 -575
  77. package/field-components/Fields/FieldEditor.vue +0 -379
  78. package/field-components/Fields/InputFieldList.vue +0 -299
  79. package/field-components/Fields/Number.vue +0 -247
  80. package/field-components/Fields/Password.vue +0 -79
  81. package/field-components/Fields/Static.vue +0 -22
  82. package/field-components/Fields/String.vue +0 -185
  83. package/field-components/Fields/Text.vue +0 -89
  84. package/field-components/Fields/Year.vue +0 -124
  85. package/field-components/Fields/components/FieldTypeOptions.vue +0 -248
  86. package/field-components/components/FieldComponents.vue +0 -246
  87. package/free-fields/AutoHide.js +0 -66
  88. package/free-fields/CenterContent.js +0 -15
  89. package/free-fields/Draggable.js +0 -30
  90. package/free-fields/Droppable.js +0 -114
  91. package/free-fields/EditableString.js +0 -63
  92. package/free-fields/FieldCategory.js +0 -83
  93. package/free-fields/FieldTypeSelect.js +0 -94
  94. package/free-fields/fieldEditors/arrayEditor.js +0 -3
  95. package/free-fields/fieldEditors/boolEditor.js +0 -22
  96. package/free-fields/fieldEditors/dateEditor.js +0 -23
  97. package/free-fields/fieldEditors/datetimeEditor.js +0 -23
  98. package/free-fields/fieldEditors/index.js +0 -21
  99. package/free-fields/fieldEditors/jsonEditor.js +0 -371
  100. package/free-fields/fieldEditors/labeledField.js +0 -74
  101. package/free-fields/fieldEditors/numberEditor.js +0 -51
  102. package/free-fields/fieldEditors/objectEditor.js +0 -3
  103. package/free-fields/fieldEditors/selectEditor.js +0 -0
  104. package/free-fields/fieldEditors/stringEditor.js +0 -49
  105. package/free-fields/fieldEditors/textEditor.js +0 -50
  106. package/free-fields/fieldEditors/timeEditor.js +0 -23
  107. package/free-fields/index.js +0 -402
  108. /package/{field-components/Display → free-field/Layout}/index.js +0 -0
  109. /package/{field-components → free-field}/style.sass +0 -0
@@ -4,14 +4,12 @@
4
4
  v-if="isIcon"
5
5
  class="full-width full-height"
6
6
  :name="name"
7
- v-bind="$attrs"
8
7
  ></q-icon>
9
8
  <q-img
10
9
  v-else
11
10
  class="full-width full-height"
12
11
  style="display: block;"
13
12
  :src="imgPath"
14
- v-bind="$attrs"
15
13
  round
16
14
  >
17
15
  <slot></slot>
@@ -54,8 +52,8 @@ export default defineComponent({
54
52
  // TODO:默认使用二倍图?
55
53
  if (this.relative) return `images/${this.name}${this.defaultSize}.png`;
56
54
  return this.thumb
57
- ? this.$options.filters.serverThumb(this.name)
58
- : this.$options.filters.serverImage(this.name);
55
+ ? this.$filter('serverThumb', this.name)
56
+ : this.$filter('serverImage', this.name);
59
57
  },
60
58
  },
61
59
  });
@@ -85,8 +85,3 @@ export default defineComponent({
85
85
  });
86
86
  </script>
87
87
 
88
- <style lang="sass">
89
- .leveled-menu
90
- .simple-expand-icon
91
- display: none
92
- </style>
@@ -46,7 +46,7 @@
46
46
  <span class="text">{{ item.text }}</span>
47
47
  </q-btn>
48
48
  <span
49
- v-if="typeof item.number !== 'undefined'"
49
+ v-if="item.number !== void 0"
50
50
  :class="
51
51
  item.number && Number(item.number).toString() !== 'NaN'
52
52
  ? 'summary-head-number is-number highlight'
@@ -83,9 +83,17 @@ export default defineComponent({
83
83
  mixins: [mixins.ArrayDataMixin],
84
84
  props: {
85
85
  has_multiple_head: { type: Boolean, default: false },
86
+ values: {type: Object, default: () => ({})},
86
87
  },
87
88
  created() {
88
- this.Bus?.$on('update_summary_head', this.refreshData);
89
+ if (this.values) {
90
+ this.data = this.values;
91
+ }
92
+ },
93
+ watch: {
94
+ values(v) {
95
+ this.data = v || [];
96
+ },
89
97
  },
90
98
  methods: {
91
99
  filteredValue(item) {
@@ -137,7 +145,6 @@ export default defineComponent({
137
145
  },
138
146
  },
139
147
  beforeUnmount() {
140
- this.Bus?.$off('update_summary_head', this.refreshData);
141
148
  },
142
149
  });
143
150
  </script>
@@ -6,7 +6,7 @@
6
6
  <q-card
7
7
  :class="['basic-dialog-card', dialogClass]"
8
8
  :style="`min-height: ${size.h}px;
9
- width: ${size.w}px; min-width: ${size.w}`"
9
+ width: ${size.w}px; min-width: ${size.w}`"
10
10
  >
11
11
  <q-btn
12
12
  class="float-right close-dialog-button"
@@ -32,10 +32,6 @@
32
32
  v-if="tips"
33
33
  class="tips"
34
34
  >{{ tips }}</div>
35
- <!-- <div
36
- v-if="warning"
37
- class="warning"
38
- >{{ warning }}</div> -->
39
35
  <div
40
36
  v-if="warning"
41
37
  class="warning no-wrap"
@@ -106,6 +102,8 @@
106
102
  <script>
107
103
  import mixins from 'free-fe-mixins';
108
104
  import { defineComponent } from 'vue';
105
+ import FreeField from '../../free-field/composible/fieldWrapper';
106
+ import EIcon from '../Basic/EIcon.vue';
109
107
 
110
108
  export default defineComponent({
111
109
  name: 'BasicDialog',
@@ -149,6 +147,12 @@ export default defineComponent({
149
147
  fieldsData: { type: Object, default: () => ({}) },
150
148
  fieldsClass: { type: String, default: '' },
151
149
  dialogClass: { type: String, default: '' },
150
+
151
+ remove: { type: Function, default: () => {}}
152
+ },
153
+ components: {
154
+ FreeField,
155
+ EIcon,
152
156
  },
153
157
  data() {
154
158
  return {
@@ -161,13 +165,6 @@ export default defineComponent({
161
165
  reject: '',
162
166
  };
163
167
  },
164
- // created() {
165
- // if (this.visible) {
166
- // this.show();
167
- // } else {
168
- // this.hide();
169
- // }
170
- // },
171
168
  watch: {
172
169
  visible() {
173
170
  if (this.visible) {
@@ -200,7 +197,7 @@ export default defineComponent({
200
197
  // following method is REQUIRED
201
198
  // (don't change its name --> "show")
202
199
  show() {
203
- debugger
200
+ // debugger
204
201
  this.$refs.dialog.show();
205
202
  this.timeout_counter();
206
203
 
@@ -257,15 +254,6 @@ export default defineComponent({
257
254
  this.remove();
258
255
  }
259
256
  },
260
- // show_msg_box() {
261
- // this.show();
262
- // this.promise = new Promise((resolve, reject) => {
263
- // this.resolve = resolve;
264
- // this.reject = reject;
265
- // });
266
-
267
- // return this.promise;
268
- // },
269
257
  btnCancel() {
270
258
  this.$emit('cancel');
271
259
 
@@ -280,12 +268,6 @@ export default defineComponent({
280
268
  }
281
269
  },
282
270
  btn_ok() {
283
- // // validate
284
- // if (this.validateFunc && typeof this.validateFunc === 'function') {
285
- // // now we only have such content, but later we might will have more
286
- // this.textValid = this.validateFunc(this.textContent);
287
- // if (!this.textValid) return;
288
- // }
289
271
  if (!this.validate()) {
290
272
  return;
291
273
  }
@@ -322,10 +304,6 @@ export default defineComponent({
322
304
  }
323
305
  }, 1000);
324
306
  },
325
- remove() {
326
- this.$destroy();
327
- document.body.removeChild(this.$el);
328
- },
329
307
  onInputFieldInput(field){
330
308
  if(field.onInput) {
331
309
  field.onInput(field);
@@ -394,49 +372,4 @@ export default defineComponent({
394
372
  text-align: center;
395
373
  color: red;
396
374
  }
397
-
398
- // .admin {
399
- // margin-top: 10px;
400
- // text-align: center;
401
- // color: red;
402
- // font-size: 12px;
403
- // }
404
-
405
- // .cancel-btn {
406
- // background: rgba(255, 255, 255, 1);
407
- // border: 1px solid rgba(74, 74, 74, 1);
408
- // color: rgba(74, 74, 74, 1);
409
- // }
410
-
411
- // .cancel-btn:hover {
412
- // background: rgba(0, 69, 156, 1);
413
- // color: rgba(255, 255, 255, 1);
414
- // border: 0;
415
- // }
416
-
417
- // .disabled-cancel-btn {
418
- // background: rgba(255, 255, 255, 1);
419
- // border: 1px solid rgba(155, 155, 155, 1);
420
- // color: rgba(155, 155, 155, 1);
421
- // }
422
-
423
- // .ok-btn {
424
- // background: rgba(24, 115, 220, 1);
425
- // color: rgba(255, 255, 255, 1);
426
- // }
427
-
428
- // .ok-btn:hover {
429
- // background: rgba(0, 69, 156, 1);
430
- // color: rgba(255, 255, 255, 1);
431
- // }
432
-
433
- // .disabled-ok-btn {
434
- // background: rgba(155, 155, 155, 1);
435
- // color: rgba(255, 255, 255, 1);
436
- // }
437
-
438
- // .disabled-ok-btn:hover {
439
- // background: rgba(155, 155, 155, 1);
440
- // color: rgba(255, 255, 255, 1);
441
- // }
442
375
  </style>
@@ -1,38 +1,48 @@
1
- import { createApp } from 'vue'
2
- import BasicDialog from './BasicDialog.vue';
3
-
4
- let $inst
5
- // 创建挂载实例
6
- let createMount = (opts) => {
7
- const app = createApp(BasicDialog, {
8
- ...opts, modelValue: true,
9
- remove () {
10
- app.unmount(mountNode)
11
- document.body.removeChild(mountNode)
12
- }
13
- })
14
- return app.mount('#eis-dialog')
15
- }
16
-
17
- function MsgDialog (options = {}) {
18
- if (typeof options === 'string') {
19
- options = {content: options};
20
- }
21
-
22
- $inst = createMount(options)
23
-
24
- return $inst.show()
25
- .then((val) => {
26
- return Promise.resolve(val);
27
- })
28
- .catch((err) => {
29
- return Promise.reject(err);
30
- });
31
- }
1
+ import { createApp } from 'vue';
2
+ import Dialog from './BasicDialog.vue'
32
3
 
4
+ const MsgDialog = {};
33
5
  MsgDialog.install = (app) => {
34
- app.config.globalProperties.$MsgDialog = MsgDialog;
35
- // app.provide('MsgDialog', MsgDialog)
36
- }
6
+ let MsgDialogInstance;
7
+ const init = (opts) => {
8
+ const dialogApp = createApp(Dialog, {
9
+ ...opts, modelValue: true,
10
+ remove: () => {
11
+ dialogApp.unmount();
12
+ }
13
+ });
14
+
15
+ dialogApp.config.globalProperties = app.config.globalProperties;
16
+
17
+ const { reload, ...appContext } = app._context;
18
+ Object.assign(dialogApp._context, appContext);
19
+
20
+ MsgDialogInstance = dialogApp.mount('#free-dialog');
21
+ };
22
+
23
+ app.config.globalProperties.$MsgDialog = (options) => {
24
+ const opts = {};
25
+
26
+ if (typeof options === 'string') {
27
+ opts.content = options;
28
+ } else if (typeof options === 'object') {
29
+ Object.assign(opts, options);
30
+ }
31
+
32
+ if (!MsgDialogInstance) {
33
+ init(opts);
34
+ }
35
+
36
+ return MsgDialogInstance.show()
37
+ .then((val) => {
38
+ MsgDialogInstance = null;
39
+ return Promise.resolve(val);
40
+ })
41
+ .catch((err) => {
42
+ MsgDialogInstance = null;
43
+ return Promise.reject(err);
44
+ });
45
+ };
46
+ };
37
47
 
38
48
  export default MsgDialog;
@@ -0,0 +1,44 @@
1
+ import { createApp } from 'vue';
2
+ import dialog from './BasicDialog.vue';
3
+
4
+ // 创建挂载实例
5
+ let createMount = (opts) => {
6
+ const app = createApp(dialog, {
7
+ ...opts, modelValue: true,
8
+ // remove () {
9
+ // app.unmount(mountNode)
10
+ // document.body.removeChild(mountNode)
11
+ // }
12
+ })
13
+
14
+ return app.mount('#free-dialog')
15
+ }
16
+
17
+ function MsgDialog (options = {}) {
18
+ if (typeof options === 'string') {
19
+ options = {content: options};
20
+ }
21
+
22
+ const $inst = createMount(options)
23
+
24
+ console.error($inst)
25
+ if (!$inst) {
26
+ console.error($inst)
27
+ return;
28
+ }
29
+
30
+ return $inst.show()
31
+ .then((val) => {
32
+ return Promise.resolve(val);
33
+ })
34
+ .catch((err) => {
35
+ return Promise.reject(err);
36
+ });
37
+ }
38
+
39
+ MsgDialog.install = (app) => {
40
+ app.config.globalProperties.$MsgDialog = MsgDialog;
41
+ // app.provide('MsgDialog', MsgDialog)
42
+ }
43
+
44
+ export default MsgDialog;
@@ -8,6 +8,7 @@
8
8
  clickable
9
9
  v-close-popup
10
10
  @click="localeChanged(locale.locale)"
11
+ :active="$i18n.locale === locale.locale"
11
12
  >
12
13
  <q-item-section>{{locale.name}}</q-item-section>
13
14
  </q-item>
@@ -30,10 +31,8 @@ export default defineComponent({
30
31
  },
31
32
  },
32
33
  created() {
33
- // set the default locale
34
- // if (this.locales && this.locales.length > 0) {
35
- // this.$i18n.locale = this.locales[0].locale;
36
- // }
34
+ const appStore = useAppStore();
35
+ this.$i18n.locale = appStore.locale || (this.locales && (this.locales.length > 0) && this.locales[0]);
37
36
  },
38
37
  methods: {
39
38
  localeChanged(l){
@@ -6,7 +6,6 @@
6
6
  infinite
7
7
  :transition-prev="transitionPrev"
8
8
  :transition-next="transitionNext"
9
- v-bind="$attrs"
10
9
  :height="heightString"
11
10
  :autoplay="interval"
12
11
  :arrows="data && data.length > 0"
@@ -20,7 +20,6 @@
20
20
  :height="heightString"
21
21
  :autoplay="interval"
22
22
  :navigation="false"
23
- v-bind="$attrs"
24
23
  animated
25
24
  infinite
26
25
  padding
@@ -47,7 +47,7 @@ export default defineComponent({
47
47
  emits: ['click'],
48
48
  props: {
49
49
  position: { type: String, default: 'bottom-right' },
50
- offset: { type: Array, default: () => [36, 128, 0, 0] },
50
+ offset: { type: Array, default: () => [36, 128] },
51
51
  fab: { type: Boolean, default: true },
52
52
  fabIcon: { type: String, default: 'add' },
53
53
  fabColor: { type: String, default: '' },
@@ -58,7 +58,7 @@ export default defineComponent({
58
58
  },
59
59
  data() {
60
60
  return {
61
- stickyOffset: [36, 128, 0, 0],
61
+ stickyOffset: [36, 128],
62
62
  draggingSticky: false,
63
63
  };
64
64
  },
@@ -14,6 +14,7 @@
14
14
  clickable
15
15
  v-close-popup
16
16
  @click="theme = tm"
17
+ :active="theme === tm"
17
18
  >
18
19
  <q-item-section>{{$t(tm)}}</q-item-section>
19
20
  </q-item>
@@ -25,6 +26,7 @@
25
26
 
26
27
  <script>
27
28
  import { defineComponent } from 'vue';
29
+ import useAppStore from '@/stores/app';
28
30
 
29
31
  export default defineComponent({
30
32
  name: 'ThemeSwitch',
@@ -56,22 +58,26 @@ export default defineComponent({
56
58
  watch: {
57
59
  theme(v) {
58
60
  if (v) {
59
- const appEle = document.getElementById('q-app');
61
+ const appEle = document.getElementById('free-app');
60
62
 
61
- let arr = appEle.className.split(' ');
63
+ let arr = appEle?.className.split(' ');
62
64
 
63
- arr = arr.filter(cl => !cl.startsWith('theme-'));
65
+ if (arr) {
66
+ arr = arr.filter(cl => !cl.startsWith('theme-'));
64
67
 
65
- arr.push(`theme-${v}`);
68
+ arr?.push(`theme-${v}`);
66
69
 
67
- appEle.className = arr.join(' ');
70
+ appEle.className = arr.join(' ');
71
+ }
72
+
73
+ const appStore = useAppStore();
74
+ appStore.SET_THEME(v);
68
75
  }
69
76
  },
70
77
  },
71
78
  created() {
72
- if (this.themes && this.themes.length > 0) {
73
- this.theme = this.themes[0];
74
- }
79
+ const appStore = useAppStore();
80
+ this.theme = appStore.theme || (this.themes && (this.themes.length > 0) && this.themes[0]);
75
81
  },
76
82
  });
77
83
  </script>
@@ -0,0 +1,69 @@
1
+ import { ref, getCurrentInstance, watch, watchEffect, defineEmits } from "vue";
2
+
3
+ export const objectDataProps = {
4
+ GetData: Function,
5
+ Bus: Object,
6
+ modelValue: {},
7
+ autoGet: { type: Boolean, default: true },
8
+ };
9
+
10
+ export function useObjectData(props, ctx) {
11
+ const { proxy:vm } = getCurrentInstance();
12
+
13
+ const data = ref({});
14
+ const callsLeft = ref(100);
15
+
16
+ watch(data, (v) => {
17
+ ctx.emit('update:modelValue', v);
18
+ });
19
+
20
+ watch(() => props.modelValue, () => {
21
+ data.value = props.modelValue;
22
+ })
23
+
24
+ // call after refresh when all function got called
25
+ watchEffect(() => {
26
+ if (vm.afterRefresh && callsLeft.value <= 0) {
27
+ vm.afterRefresh(...args);
28
+ }
29
+ })
30
+
31
+ const refreshData = (...args) => {
32
+ // support multiple get data functions
33
+ const getDataList = [];
34
+ if (Array.isArray(props.GetData)) {
35
+ getDataList.push(...props.GetData);
36
+ } else {
37
+ getDataList.push(props.GetData);
38
+ }
39
+
40
+ callsLeft.value = getDataList.length;
41
+
42
+ for (let i = 0; i < getDataList.length; i += 1) {
43
+ const getData = getDataList[i];
44
+
45
+ if (typeof getData === 'function') {
46
+ Promise.resolve(getData(...args)).then((d) => {
47
+ Object.assign(data.value, d);
48
+ }).finally(() => {
49
+ callsLeft.value --;
50
+ });
51
+ } else {
52
+ Object.assign(data.value, getData);
53
+ callsLeft.value --;
54
+ }
55
+ }
56
+ };
57
+
58
+ if(props.modelValue) {
59
+ data.value = props.modelValue;
60
+ } else if (props.autoGet) {
61
+ refreshData();
62
+ }
63
+
64
+ return {
65
+ data,
66
+ refreshData,
67
+ }
68
+ };
69
+
@@ -0,0 +1,170 @@
1
+ import { defineComponent, h, ref, getCurrentInstance } from 'vue';
2
+ import { useFreeField, freeFieldProps } from '../composible/useFreeField';
3
+ import { QCheckbox } from 'quasar';
4
+
5
+ export default defineComponent({
6
+ name: 'InputFieldAgreementCheck',
7
+ fieldInfo: {
8
+ Category: 'Simple',
9
+ Label: '协议同意勾选框',
10
+ Value: 'AgreementCheck',
11
+ Extra: [
12
+ {
13
+ Type: 'Check',
14
+ Label: '居中显示',
15
+ Name: 'Options.Center',
16
+ },
17
+ ],
18
+ Description: '',
19
+ },
20
+ props: {
21
+ ...freeFieldProps,
22
+ },
23
+ emits: ['input'],
24
+ setup(props, { emit }){
25
+ if (!props.Field) return {};
26
+
27
+ const { proxy:vm } = getCurrentInstance();
28
+ const { fieldData, setFieldData } = useFreeField(props);
29
+ const hasError = ref(false);
30
+
31
+ const fieldTip = (tip) => {
32
+ if (!tip || !tip.Text) return '';
33
+ if (!tip.Links || !Array.isArray(tip.Links) || tip.Links.length <= 0) {
34
+ return [{ Text: tip.Text }];
35
+ }
36
+
37
+ // process tip with links
38
+ let linkPos = [];
39
+ tip.Links.forEach((tl) => {
40
+ if (!tl || !tl.Text || !tl.Link) return;
41
+
42
+ const start = tip.Text.indexOf(tl.Text);
43
+ if (start >= 0) {
44
+ linkPos.push({
45
+ start,
46
+ end: start + tl.Text.length,
47
+ Link: tl.Link,
48
+ File: tl.File,
49
+ });
50
+ }
51
+ });
52
+
53
+ const textSplit = [];
54
+ let start = 0;
55
+ linkPos = linkPos.sort((a, b) => a.start - b.start);
56
+ for (let i = 0; i < linkPos.length; i += 1) {
57
+ const lp = linkPos[i];
58
+
59
+ const beforeText = tip.Text.substr(start, lp.start - start);
60
+ if (beforeText) {
61
+ textSplit.push({ Text: beforeText });
62
+ }
63
+
64
+ textSplit.push({
65
+ Text: tip.Text.substr(lp.start, lp.end - lp.start),
66
+ Link: lp.File
67
+ ? vm.$filter('serverDocument', lp.File)
68
+ : lp.Link,
69
+ });
70
+
71
+ start += lp.end;
72
+ }
73
+
74
+ const afterText = tip.Text.substr(start);
75
+ if (afterText) {
76
+ textSplit.push({
77
+ Text: afterText,
78
+ });
79
+ }
80
+
81
+ if (textSplit.length > 0) return textSplit;
82
+
83
+ return [{ Text: tip.Text }];
84
+ };
85
+
86
+ const validate = () => {
87
+ if (props.Field.Required) {
88
+ hasError.value = typeof fieldData.value === 'undefined' || !fieldData.value;
89
+ return !hasError.value;
90
+ }
91
+
92
+ const rules = Array.isArray(typeof props.Field.Rules)
93
+ ? props.Field.Rules
94
+ : [props.Field.Rules];
95
+
96
+ let isValid = true;
97
+ for (let i = 0; i < rules.length; i += 1) {
98
+ const r = rules[i];
99
+
100
+ if (typeof r === 'function') {
101
+ isValid = isValid && r(fieldData.value);
102
+ }
103
+ }
104
+
105
+ hasError.value = !isValid;
106
+ return isValid;
107
+ };
108
+
109
+ const checkboxNode = () => h(QCheckbox, {
110
+ disable: props.Field?.ReadOnly,
111
+ label: props.Field?.showLabel ? '' : props.Field?.Label,
112
+
113
+ class: 'check',
114
+ style: props.Field.Info?.Style,
115
+
116
+ modelValue: fieldData.value,
117
+ 'onUpdate:modelValue': (v) => {
118
+ setFieldData(v, emit);
119
+ },
120
+ });
121
+
122
+ const tipsNode = () => h('div', {},[
123
+ h('span', {
124
+ class: 'input-field-tips-prefix'
125
+ }),
126
+ h('span',{
127
+ class: 'tips-list'
128
+ }, (props.Field.Tips || []).map((tip) => h('span', {
129
+ class:'input-field-tips-tip',
130
+ }, [
131
+ h('span', {
132
+ class: 'input-field-tips-tip-prefix'
133
+ }),
134
+ fieldTip(tip).map((t) => h('span', {}, [
135
+ t.Link ? h('span', {
136
+ class: 'tip-link'
137
+ },[
138
+ h('span', {class: 'tip-link-prefix'}),
139
+ h('a',{
140
+ href: t.Link,
141
+ },t.Text),
142
+ h('span', {class: 'tip-link-postfix'}),
143
+ ]) : h('span',{class: 'tip-text'}, t.Text),
144
+ ])),
145
+ h('span', {
146
+ class: 'input-field-tips-tip-postfix'
147
+ })
148
+ ]))),
149
+ h('span',{
150
+ class: 'input-field-tips-postfix'
151
+ })
152
+ ]);
153
+
154
+ return () => h('div', {
155
+ class: `input-field-agreement-check row items-center no-wrap\
156
+ ${props.Field.Options?.Center ? 'center full-width justify-center' : ''}`,
157
+ }, h('div',{
158
+ class: `row no-wrap items-center relative-position ${hasError.value ? 'input-field--error' : ''}`,
159
+ },[
160
+ props.Field.Options?.Center || h('span', { class: 'field-label-empty', }),
161
+ checkboxNode(),
162
+ tipsNode(),
163
+ hasError.value && h('div', {
164
+ class: 'input-field--error-tag',
165
+ }, h(QIcon,{
166
+ name: 'error',
167
+ }))
168
+ ]));
169
+ },
170
+ });