free-fe-core-modules 0.0.1

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 (112) hide show
  1. package/README.md +7 -0
  2. package/components/.gitkeep +0 -0
  3. package/components/Basic/BreadCrumbs.vue +87 -0
  4. package/components/Basic/EIcon.vue +84 -0
  5. package/components/Basic/LeveledMenus.vue +92 -0
  6. package/components/Basic/SummaryHead.vue +312 -0
  7. package/components/Dialog/BasicDialog.vue +442 -0
  8. package/components/Dialog/index.js +38 -0
  9. package/components/Dialog/index1.js +49 -0
  10. package/components/FloatingWindow/index.vue +140 -0
  11. package/components/SelectLocales/index.vue +47 -0
  12. package/components/SlidingCarousel/index.vue +86 -0
  13. package/components/SlidingNews/index.vue +138 -0
  14. package/components/StickyButtons/index.vue +98 -0
  15. package/components/ThemeSwitch/index.vue +77 -0
  16. package/field-components/Display/index.js +3 -0
  17. package/field-components/Fields/AgreementCheck.vue +161 -0
  18. package/field-components/Fields/ApiCall.vue +139 -0
  19. package/field-components/Fields/Boolean.vue +112 -0
  20. package/field-components/Fields/Category.vue +33 -0
  21. package/field-components/Fields/Check.vue +131 -0
  22. package/field-components/Fields/Customize.vue +103 -0
  23. package/field-components/Fields/Date.vue +142 -0
  24. package/field-components/Fields/DateRange.vue +199 -0
  25. package/field-components/Fields/DynamicList.vue +575 -0
  26. package/field-components/Fields/FieldEditor.vue +379 -0
  27. package/field-components/Fields/File.vue +382 -0
  28. package/field-components/Fields/FileList.vue +405 -0
  29. package/field-components/Fields/FileListCombined.vue +142 -0
  30. package/field-components/Fields/FixedList.vue +372 -0
  31. package/field-components/Fields/Image.vue +328 -0
  32. package/field-components/Fields/ImageList.vue +285 -0
  33. package/field-components/Fields/ImageListCombined.vue +76 -0
  34. package/field-components/Fields/InputFieldList.vue +299 -0
  35. package/field-components/Fields/Labels.vue +182 -0
  36. package/field-components/Fields/MixedTable.vue +367 -0
  37. package/field-components/Fields/Number.vue +247 -0
  38. package/field-components/Fields/Password.vue +79 -0
  39. package/field-components/Fields/Permission.vue +83 -0
  40. package/field-components/Fields/PermissionEditor.vue +205 -0
  41. package/field-components/Fields/QueryFilters.vue +162 -0
  42. package/field-components/Fields/RadioList.vue +81 -0
  43. package/field-components/Fields/Rich.vue +369 -0
  44. package/field-components/Fields/Search.vue +499 -0
  45. package/field-components/Fields/Select.vue +376 -0
  46. package/field-components/Fields/SelectionChain.vue +198 -0
  47. package/field-components/Fields/Separator.vue +26 -0
  48. package/field-components/Fields/SingleList.vue +125 -0
  49. package/field-components/Fields/Static.vue +22 -0
  50. package/field-components/Fields/String.vue +185 -0
  51. package/field-components/Fields/Text.vue +89 -0
  52. package/field-components/Fields/Time.vue +160 -0
  53. package/field-components/Fields/TimeRange.vue +348 -0
  54. package/field-components/Fields/UltimateFile.vue +100 -0
  55. package/field-components/Fields/Year.vue +124 -0
  56. package/field-components/Fields/YearRange.vue +188 -0
  57. package/field-components/Fields/components/FieldTypeOptions.vue +248 -0
  58. package/field-components/Fields/index.js +117 -0
  59. package/field-components/components/FieldComponents.vue +246 -0
  60. package/field-components/index.js +13 -0
  61. package/field-components/style.sass +11 -0
  62. package/free-fields/AutoHide.js +66 -0
  63. package/free-fields/CenterContent.js +15 -0
  64. package/free-fields/Draggable.js +30 -0
  65. package/free-fields/Droppable.js +114 -0
  66. package/free-fields/EditableString.js +63 -0
  67. package/free-fields/FieldCategory.js +83 -0
  68. package/free-fields/FieldTypeSelect.js +94 -0
  69. package/free-fields/fieldEditors/arrayEditor.js +3 -0
  70. package/free-fields/fieldEditors/boolEditor.js +22 -0
  71. package/free-fields/fieldEditors/dateEditor.js +23 -0
  72. package/free-fields/fieldEditors/datetimeEditor.js +23 -0
  73. package/free-fields/fieldEditors/index.js +21 -0
  74. package/free-fields/fieldEditors/jsonEditor.js +371 -0
  75. package/free-fields/fieldEditors/labeledField.js +74 -0
  76. package/free-fields/fieldEditors/numberEditor.js +51 -0
  77. package/free-fields/fieldEditors/objectEditor.js +3 -0
  78. package/free-fields/fieldEditors/selectEditor.js +0 -0
  79. package/free-fields/fieldEditors/stringEditor.js +49 -0
  80. package/free-fields/fieldEditors/textEditor.js +50 -0
  81. package/free-fields/fieldEditors/timeEditor.js +23 -0
  82. package/free-fields/index.js +402 -0
  83. package/i18n/en-us/index.js +73 -0
  84. package/i18n/fields/en-us/index.js +9 -0
  85. package/i18n/fields/zh-cn/index.js +9 -0
  86. package/i18n/zh-cn/index.js +73 -0
  87. package/index.js +367 -0
  88. package/package.json +11 -0
  89. package/router/dict/api.js +18 -0
  90. package/router/dict/data.js +48 -0
  91. package/router/dict/index.js +7 -0
  92. package/router/error/api.js +14 -0
  93. package/router/error/data.js +33 -0
  94. package/router/error/index.js +9 -0
  95. package/router/index.js +13 -0
  96. package/router/menu/api.js +24 -0
  97. package/router/menu/data.js +85 -0
  98. package/router/menu/index.js +7 -0
  99. package/router/system/api.js +10 -0
  100. package/router/system/data.js +46 -0
  101. package/router/system/index.js +7 -0
  102. package/stores/index.js +17 -0
  103. package/stores/module-mourning/actions.js +3 -0
  104. package/stores/module-mourning/getters.js +1 -0
  105. package/stores/module-mourning/index.js +11 -0
  106. package/stores/module-mourning/state.js +3 -0
  107. package/stores/mourning.js +3 -0
  108. package/view/dict/index.vue +284 -0
  109. package/view/error/list.vue +197 -0
  110. package/view/menu/index.vue +332 -0
  111. package/view/mourning/mourning.vue +45 -0
  112. package/view/system/index.vue +149 -0
@@ -0,0 +1,442 @@
1
+ <template>
2
+ <q-dialog
3
+ :persistent="persistent"
4
+ ref="dialog"
5
+ >
6
+ <q-card
7
+ :class="['basic-dialog-card', dialogClass]"
8
+ :style="`min-height: ${size.h}px;
9
+ width: ${size.w}px; min-width: ${size.w}`"
10
+ >
11
+ <q-btn
12
+ class="float-right close-dialog-button"
13
+ v-if="canClose"
14
+ :icon="closeIcon"
15
+ flat
16
+ v-close-popup
17
+ @click="btnCancel"
18
+ />
19
+
20
+ <q-card-section class="column items-center">
21
+ <e-icon
22
+ v-if="type"
23
+ class="dialog-icon"
24
+ :name="icon || type"
25
+ alt=""
26
+ />
27
+ <div
28
+ v-if="content"
29
+ class="title"
30
+ >{{ content }}</div>
31
+ <div
32
+ v-if="tips"
33
+ class="tips"
34
+ >{{ tips }}</div>
35
+ <!-- <div
36
+ v-if="warning"
37
+ class="warning"
38
+ >{{ warning }}</div> -->
39
+ <div
40
+ v-if="warning"
41
+ class="warning no-wrap"
42
+ >
43
+ <span class="warning-icon"></span>
44
+ <span class="warning-icon-sign-top"></span>
45
+ <span class="warning-icon-sign-dot"></span>
46
+ <span class="warning-text ellipsis">{{warning}}</span>
47
+ </div>
48
+
49
+ <q-input
50
+ v-if="needText"
51
+ hide-bottom-space
52
+ class="full-width"
53
+ :placeholder="text_label"
54
+ :maxlength="max_text_length"
55
+ v-model="textContent"
56
+ :rows="max_text_length / 20"
57
+ :class="textValid ? '' : 'invalid'"
58
+ type="textarea"
59
+ >
60
+ </q-input>
61
+ <span v-if="needText">{{ textContent.length }}/{{ max_text_length }}</span>
62
+ <div
63
+ v-if="fields && fields.length"
64
+ :class="fieldsClass || ''"
65
+ >
66
+ <free-field
67
+ :class="field.class || ''"
68
+ v-for="(field, index) in fields"
69
+ :key="index"
70
+ :Field="field"
71
+ :values="fieldsData"
72
+ :ref="`input_field_validator_${index}`"
73
+ @input="onInputFieldInput(field)"
74
+ ></free-field>
75
+ </div>
76
+ <slot name="fields"></slot>
77
+ </q-card-section>
78
+
79
+ <q-card-actions
80
+ align="center"
81
+ class="action-buttons full-width absolute"
82
+ v-if="canOK || canCancel"
83
+ >
84
+ <q-btn
85
+ :label="cancelText"
86
+ class="cancel-btn"
87
+ v-close-popup
88
+ @click="btnCancel"
89
+ v-if="canCancel"
90
+ />
91
+ <q-btn
92
+ v-if="canOK"
93
+ :label="okText"
94
+ class="ok-btn"
95
+ :class="disabled ? 'disabled-ok-btn' : ''"
96
+ :disabled="disabled"
97
+ @click="onOKClick"
98
+ >
99
+ <span v-if="timeLeft">({{ timeLeft }}s)</span>
100
+ </q-btn>
101
+ </q-card-actions>
102
+ </q-card>
103
+ </q-dialog>
104
+ </template>
105
+
106
+ <script>
107
+ import mixins from 'free-fe-mixins';
108
+ import { defineComponent } from 'vue';
109
+
110
+ export default defineComponent({
111
+ name: 'BasicDialog',
112
+ mixins: [mixins.InputFieldValidator],
113
+ emits: ['hide', 'ok', 'cancel'],
114
+ props: {
115
+ persistent: { type: Boolean, default: true },
116
+ type: { type: String, default: 'info' },
117
+ icon: { type: String, default: '' },
118
+ textAlign: { type: String, default: 'center' },
119
+ content: { type: String, default: '' },
120
+ tips: { type: String, default: '' },
121
+ size: {
122
+ type: Object,
123
+ default: () => ({
124
+ h: 100,
125
+ w: 550,
126
+ }),
127
+ },
128
+ needText: { type: Boolean, default: false },
129
+ text_label: { type: String, default: '' },
130
+ max_text_length: { type: Number, default: 100 },
131
+ canOK: { type: Boolean, default: true },
132
+ canCancel: { type: Boolean, default: false },
133
+ canClose: { type: Boolean, default: false },
134
+ closeIcon: { type: String, default: 'far fa-times-circle' },
135
+ cancelText: { type: String, default: 'Cancel' },
136
+ cancelType: { type: String, default: '' },
137
+ okDisabled: { type: Boolean, default: false },
138
+ okText: { type: String, default: 'OK' },
139
+ okType: { type: String, default: '' },
140
+ timeout: { type: Number, default: 0 },
141
+ showWarning: { type: Boolean, default: true },
142
+ warning: { type: String, default: '' },
143
+ // validateFunc: {
144
+ // type: Function,
145
+ // default: () => true,
146
+ // },
147
+ visible: { type: Boolean, default: true },
148
+ fields: { type: Array, default: () => ([]) },
149
+ fieldsData: { type: Object, default: () => ({}) },
150
+ fieldsClass: { type: String, default: '' },
151
+ dialogClass: { type: String, default: '' },
152
+ },
153
+ data() {
154
+ return {
155
+ timeLeft: 0,
156
+ textContent: '',
157
+ textValid: true,
158
+ timer: undefined,
159
+ promise: '',
160
+ resolve: '',
161
+ reject: '',
162
+ };
163
+ },
164
+ // created() {
165
+ // if (this.visible) {
166
+ // this.show();
167
+ // } else {
168
+ // this.hide();
169
+ // }
170
+ // },
171
+ watch: {
172
+ visible() {
173
+ if (this.visible) {
174
+ this.timeout_counter();
175
+ this.show();
176
+ } else {
177
+ this.hide();
178
+ }
179
+ },
180
+ },
181
+ computed: {
182
+ disabled() {
183
+ if (typeof this.okDisabled === 'object') {
184
+ return this.okDisabled.value;
185
+ }
186
+
187
+ return this.okDisabled;
188
+ },
189
+ warningMsg() {
190
+ // 设置默认warning
191
+ if (!this.showWarning) return '';
192
+
193
+ if (!this.warning) {
194
+ return '';
195
+ }
196
+ return this.warning;
197
+ },
198
+ },
199
+ methods: {
200
+ // following method is REQUIRED
201
+ // (don't change its name --> "show")
202
+ show() {
203
+ debugger
204
+ this.$refs.dialog.show();
205
+ this.timeout_counter();
206
+
207
+ this.promise = new Promise((resolve, reject) => {
208
+ this.resolve = resolve;
209
+ this.reject = reject;
210
+ });
211
+
212
+ return this.promise;
213
+ },
214
+
215
+ // following method is REQUIRED
216
+ // (don't change its name --> "hide")
217
+ hide() {
218
+ this.$refs.dialog.hide();
219
+ },
220
+ onDialogHide() {
221
+ // required to be emitted
222
+ // when QDialog emits "hide" event
223
+ this.$emit('hide');
224
+ },
225
+ onOKClick() {
226
+ // on OK, it is REQUIRED to
227
+ // emit "ok" event (with optional payload)
228
+ // before hiding the QDialog
229
+ // this.$emit('ok');
230
+ // or with payload: this.$emit('ok', { ... })
231
+
232
+ // // validate
233
+ // if (this.validateFunc && typeof this.validateFunc === 'function') {
234
+ // // now we only have such content, but later we might will have more
235
+ // this.textValid = this.validateFunc(this.textContent);
236
+ // if (!this.textValid) return;
237
+ // }
238
+ if (!this.validate()) {
239
+ return;
240
+ }
241
+
242
+ this.$emit('ok');
243
+
244
+ if (this.timer) {
245
+ this.timeLeft = 0;
246
+ clearInterval(this.timer);
247
+ }
248
+
249
+ if (this.resolve) {
250
+ if (this.needText) {
251
+ this.resolve(this.textContent);
252
+ } else {
253
+ this.resolve('confirm');
254
+ }
255
+
256
+ this.hide();
257
+ this.remove();
258
+ }
259
+ },
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
+ btnCancel() {
270
+ this.$emit('cancel');
271
+
272
+ if (this.timer) {
273
+ this.timeLeft = 0;
274
+ clearInterval(this.timer);
275
+ }
276
+
277
+ if (this.reject) {
278
+ this.reject('cancel');
279
+ this.remove();
280
+ }
281
+ },
282
+ 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
+ if (!this.validate()) {
290
+ return;
291
+ }
292
+
293
+ this.$emit('ok');
294
+
295
+ if (this.timer) {
296
+ this.timeLeft = 0;
297
+ clearInterval(this.timer);
298
+ }
299
+
300
+ if (this.resolve) {
301
+ if (this.needText) {
302
+ this.resolve(this.textContent);
303
+ } else {
304
+ this.resolve('confirm');
305
+ }
306
+
307
+ this.hide();
308
+ this.remove();
309
+ }
310
+ },
311
+ timeout_counter() {
312
+ if (!this.timeout) {
313
+ return;
314
+ }
315
+
316
+ this.timeLeft = this.timeout;
317
+ this.timer = setInterval(() => {
318
+ this.timeLeft -= 1;
319
+ if (this.timeLeft < 1) {
320
+ clearInterval(this.timer);
321
+ this.btn_ok();
322
+ }
323
+ }, 1000);
324
+ },
325
+ remove() {
326
+ this.$destroy();
327
+ document.body.removeChild(this.$el);
328
+ },
329
+ onInputFieldInput(field){
330
+ if(field.onInput) {
331
+ field.onInput(field);
332
+ }
333
+ }
334
+ },
335
+ });
336
+ </script>
337
+
338
+ <style scoped rel="stylesheet/scss" lang="scss">
339
+ .basic-dialog-card {
340
+ // min-height: 200px;
341
+ min-width: 480px;
342
+
343
+ .close-dialog-button {
344
+ position: absolute;
345
+ top: 0;
346
+ right: 0;
347
+ width: 36px;
348
+ z-index: 1;
349
+ }
350
+ }
351
+
352
+ .q-dialog__inner--minimized > div {
353
+ max-width: unset;
354
+ }
355
+
356
+ .dialog-icon {
357
+ position: relative;
358
+ top: 0;
359
+ left: calc(50% - 26px);
360
+ padding: 0;
361
+ width: 52px;
362
+ height: 52px;
363
+ margin-top: 18px;
364
+ margin-bottom: 24px;
365
+ }
366
+
367
+ .title {
368
+ position: relative;
369
+ width: 100%;
370
+ font-size: 16px;
371
+ font-weight: bold;
372
+ text-align: center;
373
+ margin: 10px auto;
374
+ }
375
+
376
+ .cancel-btn {
377
+ margin-right: 20px;
378
+ }
379
+
380
+ .tips {
381
+ display: block;
382
+ position: relative;
383
+ margin-top: 10px;
384
+ font-size: 12px;
385
+ color: gray;
386
+ text-align: center;
387
+ }
388
+
389
+ .warning {
390
+ display: block;
391
+ position: relative;
392
+ font-size: 12px;
393
+ font-weight: 400;
394
+ text-align: center;
395
+ color: red;
396
+ }
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
+ </style>
@@ -0,0 +1,38 @@
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
+ }
32
+
33
+ MsgDialog.install = (app) => {
34
+ app.config.globalProperties.$MsgDialog = MsgDialog;
35
+ // app.provide('MsgDialog', MsgDialog)
36
+ }
37
+
38
+ export default MsgDialog;
@@ -0,0 +1,49 @@
1
+ import {createApp} from 'vue';
2
+ import BasicDialog from './BasicDialog.vue';
3
+
4
+ let _i18n = null;
5
+
6
+ export function setI18n (i18n) {
7
+ _i18n = i18n
8
+ }
9
+
10
+ const MsgDialog = {};
11
+ MsgDialog.install = (app) => {
12
+ // const MessageDialogInstance = app.extend(BasicDialog);
13
+ // const MessageDialogInstance = createApp(BasicDialog);
14
+
15
+ let MsgDialogInstance;
16
+ const init = () => {
17
+ // app.config.globalProperties._i18n = _i18n;
18
+
19
+ // MsgDialogInstance = new MessageDialogInstance();
20
+ MsgDialogInstance = createApp(BasicDialog);
21
+ MsgDialogInstance = MsgDialogInstance.mount('#eis-dialog');
22
+ // document.body.appendChild(msgBoxEl);
23
+ };
24
+
25
+ app.config.globalProperties.$MsgDialog = (options) => {
26
+ if (!MsgDialogInstance) {
27
+ init();
28
+ }
29
+
30
+ if (typeof options === 'string') {
31
+ MsgDialogInstance.content = options;
32
+ } else if (typeof options === 'object') {
33
+ Object.assign(MsgDialogInstance.$props, options);
34
+ }
35
+
36
+ // return MsgDialogInstance.show_msg_box()
37
+ return MsgDialogInstance.show()
38
+ .then((val) => {
39
+ MsgDialogInstance = null;
40
+ return Promise.resolve(val);
41
+ })
42
+ .catch((err) => {
43
+ MsgDialogInstance = null;
44
+ return Promise.reject(err);
45
+ });
46
+ };
47
+ };
48
+
49
+ export default MsgDialog;
@@ -0,0 +1,140 @@
1
+ <template>
2
+ <div
3
+ class="z-max"
4
+ id="adbox"
5
+ ref="adbox"
6
+ v-show="showAdbox && img"
7
+ @mouseenter="enterbox"
8
+ @mouseleave="leavebox"
9
+ @click="boxClicked"
10
+ >
11
+ <q-img :src="`${ctx.config.imageUrlBase}${img}`"></q-img>
12
+ <q-btn @click.stop="closebox" flat class="no-shadow" icon="close"></q-btn>
13
+ </div>
14
+ </template>
15
+
16
+ <script>
17
+ import { defineComponent } from 'vue';
18
+
19
+ export default defineComponent({
20
+ name: 'FloatingWindow',
21
+ props: {
22
+ url: { type: String, default: '' },
23
+ img: { type: String, default: '' },
24
+ onlyIn: { type: Array, default: () => [] },
25
+ top: { type: Number, default: 0 },
26
+ },
27
+ data() {
28
+ return {
29
+ x: 150,
30
+ y: 150,
31
+ xin: true,
32
+ yin: true,
33
+ step: 1,
34
+ delay: 15,
35
+ itl: null,
36
+ showAdbox: true,
37
+ };
38
+ },
39
+ beforeRouteEnter(to, from, next) {
40
+ next((vm) => {
41
+ vm.routeEnterShowAdbox();
42
+ });
43
+ },
44
+ beforeUnmount() {
45
+ clearInterval(this.itl);
46
+ },
47
+ mounted() {
48
+ this.leavebox();
49
+ },
50
+ methods: {
51
+ boxClicked() {
52
+ if (this.url) {
53
+ if (/^(http|https):\/\/.*/.test(this.url)) {
54
+ window.open(this.url);
55
+ } else {
56
+ this.$router.push(this.url);
57
+ }
58
+ }
59
+ },
60
+ closebox() {
61
+ this.showAdbox = false;
62
+ clearInterval(this.itl);
63
+ },
64
+ leavebox() {
65
+ if (this.showAdbox === false) {
66
+ clearInterval(this.itl);
67
+ } else {
68
+ this.itl = setInterval(this.movebox, this.delay);
69
+ }
70
+ },
71
+ enterbox() {
72
+ clearInterval(this.itl);
73
+ },
74
+ movebox() {
75
+ const L = 0;
76
+ const T = this.top;
77
+ // 浏览器显示宽度-adbox宽度,不随滚动条变化而变化
78
+ const R = document.documentElement.clientWidth - this.$refs.adbox.offsetWidth;
79
+ // 浏览器显示高度-adbox高度,不随滚动条变化而变化
80
+ const B = document.documentElement.clientHeight - this.$refs.adbox.offsetHeight;
81
+ this.$refs.adbox.style.left = `${this.x
82
+ + document.documentElement.scrollLeft}px`; // adbox初始左+滚动条最左端到浏览器最左端的距离
83
+ this.$refs.adbox.style.top = `${this.y
84
+ + document.documentElement.scrollTop}px`; // adbox初始高+滚动条顶端到浏览器顶端的距离
85
+ this.x += this.step * (this.xin ? 1 : -1);
86
+ if (this.x < L) {
87
+ this.xin = true;
88
+ this.x = L;
89
+ }
90
+ if (this.x > R) {
91
+ this.xin = false;
92
+ this.x = R;
93
+ }
94
+ this.y += this.step * (this.yin ? 1 : -1);
95
+ if (this.y < T) {
96
+ this.yin = true;
97
+ this.y = T;
98
+ }
99
+ if (this.y > B) {
100
+ this.yin = false;
101
+ this.y = B;
102
+ }
103
+ },
104
+ routeEnterShowAdbox() {
105
+ this.itl = setInterval(this.movebox, this.delay);
106
+ },
107
+ },
108
+ });
109
+ </script>
110
+
111
+ <style lang="sass">
112
+ #adbox
113
+ width: 300px
114
+ height: 150px
115
+ position: absolute
116
+ cursor: pointer
117
+
118
+ & img
119
+ border: none
120
+
121
+ & .q-btn
122
+ position: absolute
123
+ height: 24px
124
+ width: 24px
125
+ font-size: 14px
126
+ line-height: 24px
127
+ padding: 0
128
+ margin: 0
129
+ right: 5px
130
+ top: 5px
131
+ cursor: pointer
132
+ color: $grey-4
133
+ background: rgba(0,0,0,0.2)
134
+ & .q-btn__wrapper
135
+ padding: 0
136
+ min-height: 1em
137
+ &:hover
138
+ color: $grey-5
139
+ background: $grey-9
140
+ </style>
@@ -0,0 +1,47 @@
1
+ <template>
2
+ <q-btn flat :icon="icon" v-if="locales && locales[1]">
3
+ <q-menu>
4
+ <q-list>
5
+ <q-item
6
+ v-for="(locale, index) in locales"
7
+ :key="index"
8
+ clickable
9
+ v-close-popup
10
+ @click="localeChanged(locale.locale)"
11
+ >
12
+ <q-item-section>{{locale.name}}</q-item-section>
13
+ </q-item>
14
+ </q-list>
15
+ </q-menu>
16
+ </q-btn>
17
+ </template>
18
+ <script>
19
+ import { defineComponent } from 'vue';
20
+ import useAppStore from '@/stores/app';
21
+
22
+ export default defineComponent({
23
+ name: 'SelectLocales',
24
+ props: {
25
+ icon: { type: String, default: 'translate' },
26
+ },
27
+ computed: {
28
+ locales() {
29
+ return (this.ctx && this.ctx.config.locales) || [];
30
+ },
31
+ },
32
+ created() {
33
+ // set the default locale
34
+ // if (this.locales && this.locales.length > 0) {
35
+ // this.$i18n.locale = this.locales[0].locale;
36
+ // }
37
+ },
38
+ methods: {
39
+ localeChanged(l){
40
+ const store = useAppStore();
41
+
42
+ this.$i18n.locale = l;
43
+ store.SET_LOCALE(l);
44
+ }
45
+ }
46
+ });
47
+ </script>