free-fe-core-modules 0.0.40 → 0.0.42

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.
@@ -19,12 +19,11 @@
19
19
  </div>
20
20
  </template>
21
21
  </q-img>
22
- <!-- <q-icon v-else :name="ctx.config.defaultIcon">he</q-icon> -->
23
22
  </span>
24
23
  </template>
25
24
 
26
25
  <script>
27
- import { defineComponent } from 'vue';
26
+ import { ref, computed, defineComponent, getCurrentInstance, watchEffect, nextTick } from 'vue';
28
27
 
29
28
  export default defineComponent({
30
29
  name: 'EIcon',
@@ -36,28 +35,38 @@ export default defineComponent({
36
35
  hideError: { type: Boolean, default: false },
37
36
  defaultSize: { type: String, default: '@2x' },
38
37
  },
39
- computed: {
40
- isIcon() {
41
- return this.name && (typeof this.name === 'string') && (this.name.startsWith('img:') || this.name.indexOf('/') < 0);
42
- },
43
- imgPath() {
44
- if (typeof this.name !== 'string' || !this.name) return '';
38
+ setup(props) {
39
+ const { proxy:vm } = getCurrentInstance();
45
40
 
46
- if (this.name.startsWith('data:')) return this.name;
41
+ const imgPath = ref('');
42
+ watchEffect(() => {
43
+ if (typeof props.name !== 'string' || !props.name) return '';
47
44
 
48
- if (this.name.startsWith('http://')) return this.name;
45
+ if (props.name.startsWith('data:')) return props.name;
49
46
 
50
- if (this.name.startsWith('https://')) return this.name;
47
+ if (props.name.startsWith('http://')) return props.name;
51
48
 
52
- if (this.name.startsWith('blob:')) return this.name;
49
+ if (props.name.startsWith('https://')) return props.name;
50
+
51
+ if (props.name.startsWith('blob:')) return props.name;
53
52
 
54
53
  // TODO:默认使用二倍图?
55
- if (this.relative) return `images/${this.name}${this.defaultSize}.png`;
54
+ if (props.relative) return `images/${props.name}${props.defaultSize}.png`;
55
+
56
+ const ret = props.thumb
57
+ ? vm.$filter('serverThumb', props.name)
58
+ : vm.$filter('serverImage', props.name);
59
+
60
+ // 某些情况下不能及时显示缩略图,延迟设置图片路径
61
+ setTimeout(() => {
62
+ imgPath.value = ret;
63
+ }, 200);
64
+ })
56
65
 
57
- return this.thumb
58
- ? this.$filter('serverThumb', this.name)
59
- : this.$filter('serverImage', this.name);
60
- },
66
+ return {
67
+ isIcon: computed(() => props.name && (typeof props.name === 'string') && (props.name.startsWith('img:') || props.name.indexOf('/') < 0)),
68
+ imgPath,
69
+ };
61
70
  },
62
71
  });
63
72
  </script>
@@ -62,7 +62,7 @@
62
62
  >
63
63
  <q-uploader-add-trigger />
64
64
  </q-btn>
65
-
65
+
66
66
  <div v-else-if="(Field.onlyIcon || onlyIcon) && fieldData.value && fieldData.value[0]?.id">
67
67
  <q-img
68
68
  :src="$filter('serverThumb', `${fieldData.value[0].id}`)"
@@ -187,9 +187,9 @@
187
187
 
188
188
  <script>
189
189
  import { defineComponent, getCurrentInstance, ref } from 'vue';
190
- import { useFreeField, freeFieldProps } from '../composible/useFreeField';
191
- import { useFormValidator} from '../../composible/useFormValidator';
192
- import { useUploader } from '../composible/useUploader';
190
+ import { useFreeField, freeFieldProps } from 'free-fe-core-modules/free-field/composible/useFreeField';
191
+ import { useFormValidator} from 'free-fe-core-modules/composible/useFormValidator';
192
+ import { useUploader } from 'free-fe-core-modules/free-field/composible/useUploader';
193
193
 
194
194
  export default defineComponent({
195
195
  name: 'InputFieldImage',
@@ -333,17 +333,16 @@ export default defineComponent({
333
333
  factoryFn,
334
334
  uploaded,
335
335
 
336
- removeFile: () => {
336
+ removeFile: (files = []) => {
337
337
  setFieldData([], emit);
338
338
  selfValidate();
339
+
340
+ uploader.value.files = uploader.value.files.filter((f) => {
341
+ return files.findIndex((file) => file.name === f.name && file.size === f.size) < 0;
342
+ });
339
343
  },
340
344
  };
341
345
  },
342
- // methods: {
343
- // fileAdded(files) {
344
- // this.$refs.uploader.files = files;
345
- // },
346
- // },
347
346
  });
348
347
  </script>
349
348
 
@@ -340,10 +340,14 @@ export default defineComponent({
340
340
  return fieldData.value?.length < props.Field?.Options?.MaxCount;
341
341
  }),
342
342
  dense: computed(() => props.Field?.dense || props.Field?.Options?.Dense),
343
- removeFile: (files) => {
343
+ removeFile: (files = []) => {
344
344
  localFiles.value = localFiles.value.filter((f) => !files.includes(f));
345
345
  setFieldData(fieldData.value.filter((f) => !files.includes(f)), emit);
346
346
  selfValidate();
347
+
348
+ uploader.value.files = uploader.value.files.filter((f) => {
349
+ return files.findIndex((file) => file.name === f.name && file.size === f.size) < 0;
350
+ });
347
351
  },
348
352
  };
349
353
  },
@@ -174,9 +174,9 @@
174
174
  </template>
175
175
 
176
176
  <script>
177
- import { defineComponent } from 'vue';
178
- import { useFreeField, freeFieldProps } from '../composible/useFreeField';
179
- import { useFormValidator} from '../../composible/useFormValidator';
177
+ import { defineComponent, getCurrentInstance, watch, ref, computed } from 'vue';
178
+ import { useFreeField, freeFieldProps } from 'free-fe-core-modules/free-field/composible/useFreeField';
179
+ import { useFormValidator} from 'free-fe-core-modules/composible/useFormValidator';
180
180
 
181
181
  export default defineComponent({
182
182
  name: 'InputFieldSearch',
@@ -294,219 +294,223 @@ export default defineComponent({
294
294
  ],
295
295
  Description: '',
296
296
  },
297
- setup(props, { expose }) {
297
+ setup(props, { emit, expose }) {
298
298
  if (!props.Field) return {};
299
299
 
300
+ const { proxy:vm } = getCurrentInstance();
301
+
300
302
  const { fieldData, setFieldData, inputControlSettings } = useFreeField(props);
301
303
 
302
304
  const { validate } = useFormValidator('fieldToValid');
305
+
303
306
  expose({
304
307
  validate,
305
308
  })
306
309
 
307
- return {
308
- fieldData,
309
- setFieldData,
310
- inputControlSettings,
310
+ const searchKey = ref('');
311
+ const showSearch = ref(false);
312
+ const searchData = ref({});
313
+ const searchSelected = ref([]);
314
+ const originalSelected = ref([]);
315
+ const searchDisplay = ref('');
316
+ const searchPagination = {
317
+ rowsPerPage: searchData.value?.limit ? searchData.value.limit : 5,
318
+ rowsNumber: searchData.value?.total ? searchData.value.total : 0,
311
319
  };
312
- },
313
- data() {
314
- return {
315
- searchKey: '',
316
- showSearch: false,
317
- searchData: {},
318
- searchSelected: [],
319
- originalSelected: [],
320
- searchDisplay: '',
321
- searchPagination: {
322
- rowsPerPage:
323
- this.searchData && this.searchData.limit ? this.searchData.limit : 5,
324
- rowsNumber:
325
- this.searchData && this.searchData.total ? this.searchData.total : 0,
326
- },
327
- };
328
- },
329
- computed: {
330
- searchColumns() {
331
- if (!this.Field?.Options?.SearchColumns) {
332
- return [];
333
- }
334
320
 
335
- const cls = [];
336
- (this.Field?.Options?.SearchColumns || []).forEach((c) => {
337
- const newC = { ...c };
338
- newC.name = c.Name;
339
- newC.label = c.Label;
340
- newC.field = c.Name;
341
- newC.required = c.required;
342
- newC.align = c.align;
343
- newC.sortable = c.sortable;
344
- newC.sort = c.sort;
345
- newC.style = c.style;
346
- newC.classes = c.classes;
347
- newC.headerStyle = c.headerStyle;
348
- newC.headerClasses = c.headerClasses;
349
- newC.format = c.format || ((val, row) => Object.nestValue(row, c.Name));
350
-
351
- delete newC.Name;
352
- delete newC.Label;
353
-
354
- cls.push(newC);
355
- });
356
-
357
- return cls;
358
- },
359
- },
360
- watch: {
361
- 'fieldData.value': function(n, o) {
321
+ const valueUpdated = (n, o) => {
362
322
  // init search data from exist id
363
- if (this.fieldData.value === void 0) {
364
- this.searchSelected = [];
365
- this.searchData = {};
366
- this.searchDisplay = '';
367
- this.searchKey = '';
368
- } else if (this.Field.Type === 'Search' && this.fieldData.value) {
323
+ if (fieldData.value === void 0) {
324
+ searchSelected.value = [];
325
+ searchData.value = {};
326
+ searchDisplay.value = '';
327
+ searchKey.value = '';
328
+ } else if (props.Field.Type === 'Search' && fieldData.value) {
369
329
  if (n && o) {
370
- const nV = Object.nestValue(n, this.Field.Name);
371
- const oV = Object.nestValue(o, this.Field.Name);
330
+ const nV = Object.nestValue(n, props.Field.Name);
331
+ const oV = Object.nestValue(o, props.Field.Name);
372
332
 
373
333
  if (nV === oV || !nV) return;
374
334
  }
375
335
 
376
- if (this.Field.Options && this.Field.Options.SearchUrl) {
336
+ if (props.Field.Options && props.Field.Options.SearchUrl) {
377
337
  const paramObj = {};
378
- paramObj[this.Field.Options.SearchField || 'id'] = this.Field.Multiple
379
- ? JSON.stringify(this.fieldData.value)
380
- : this.fieldData.value;
338
+ paramObj[props.Field.Options.SearchField || 'id'] = props.Field.Multiple
339
+ ? JSON.stringify(fieldData.value)
340
+ : fieldData.value;
381
341
 
382
- this.getRequest(
383
- `${this.Field.Options.SearchUrl}`,
342
+ vm.getRequest(
343
+ `${props.Field.Options.SearchUrl}`,
384
344
  paramObj
385
345
  )
386
346
  .then((d) => {
387
347
  if (d && d.msg === 'OK' && d.data.total) {
388
- this.searchSelected = d.data.docs;
389
- const selected = this.Field && this.Field.Multiple
390
- ? this.searchSelected : [this.searchSelected[0]];
391
- const sdFieldName = this.Field.Options.SearchDisplayField || 'id';
392
- this.searchDisplay = selected.map((ss) => Object.nestValue(ss, sdFieldName))
393
- .join(this.Field && this.Field.Options && this.Field.Options.AutoWrap ? '\r\n' : ',');
348
+ searchSelected.value = d.data.docs;
349
+ const selected = props.Field?.Multiple
350
+ ? searchSelected.value : [searchSelected.value[0]];
351
+ const sdFieldName = props.Field.Options.SearchDisplayField || 'id';
352
+ searchDisplay.value = selected.map((ss) => Object.nestValue(ss, sdFieldName))
353
+ .join(props.Field?.Options?.AutoWrap ? '\r\n' : ',');
394
354
  }
395
355
  });
396
356
  }
397
357
  }
398
- },
399
- searchSelected() {
400
- if (this.Field && this.Field.Options && this.Field.Options.MaxSelection) {
401
- if (this.searchSelected.length > this.Field.Options.MaxSelection) {
402
- this.searchSelected.splice(this.Field.Options.MaxSelection);
358
+ };
359
+
360
+ watch(fieldData, valueUpdated);
361
+ valueUpdated(fieldData.value, void 0);
362
+
363
+ watch(searchSelected, () => {
364
+ if (props.Field?.Options?.MaxSelection) {
365
+ if (searchSelected.value.length > props.Field.Options.MaxSelection) {
366
+ searchSelected.value.splice(props.Field.Options.MaxSelection);
403
367
  }
404
368
  }
405
- },
406
- showSearch(v) {
407
- if (v && this.Field && this.Field.Options && this.Field.Options.AutoSearch) {
408
- this.search();
369
+ });
370
+
371
+ watch(showSearch, (v) => {
372
+ if (v && props.Field?.Options?.AutoSearch) {
373
+ search();
409
374
  }
410
375
 
411
376
  if(v) {
412
- this.originalSelected = this.searchSelected;
413
- }
414
- },
415
- },
416
- created() {
417
- this.searchColumns.forEach((col) => {
418
- if (col.filters) {
419
- col.format = (d) => this.$filter(col.filters, d);
377
+ originalSelected.value = searchSelected.value;
420
378
  }
421
379
  });
422
- },
423
- methods: {
424
- search(p) {
380
+
381
+ const search = (p) => {
425
382
  if (
426
- !this.Field?.Options?.SearchUrl
427
- || (!this.searchKey && !this.Field?.Options?.AllowEmptySearch)
383
+ !props.Field?.Options?.SearchUrl
384
+ || (!searchKey.value && !props.Field?.Options?.AllowEmptySearch)
428
385
  ) {
429
386
  return;
430
387
  }
431
388
 
432
389
  const reqBody = {...(p ? {page: p} : {})};
433
- reqBody[this.Field.Options?.SearchKeyName || 'search'] = this.searchKey;
434
-
435
- this.getRequest(
436
- this.Field.Options.SearchUrl,
437
- reqBody,
438
- )
439
- .then((d) => {
440
- if (d && d.msg === 'OK') {
441
- const { data } = d;
442
- if (data) {
443
- for (let i = 0; i < data.docs?.length; i += 1) {
444
- const dc = data.docs[i];
445
-
446
- dc.index = (data.page - 1) * data.limit + i + 1;
447
- }
448
-
449
- this.searchData = data;
390
+ reqBody[props.Field.Options?.SearchKeyName || 'search'] = searchKey.value;
391
+
392
+ vm.getRequest(
393
+ props.Field.Options.SearchUrl,
394
+ reqBody,
395
+ )
396
+ .then((d) => {
397
+ if (d && d.msg === 'OK') {
398
+ const { data } = d;
399
+ if (data) {
400
+ for (let i = 0; i < data.docs?.length; i += 1) {
401
+ const dc = data.docs[i];
402
+
403
+ dc.index = (data.page - 1) * data.limit + i + 1;
450
404
  }
405
+
406
+ searchData.value = data;
451
407
  }
452
- });
453
- },
454
- searchPaginationChanged(p) {
455
- this.search(p);
456
- },
457
- searchOK() {
458
- if (this.searchSelected.length) {
459
- const selected = this.Field && this.Field.Multiple
460
- ? this.searchSelected : [this.searchSelected[0]];
461
-
462
- const sFieldName = this.Field.SearchField || 'id';
463
-
464
- this.setFieldData(selected.map(
465
- (ss) => Object.nestValue(ss, sFieldName),
466
- ).filter((ss) => !!ss));
467
-
468
- if (!this.Field || !this.Field.Multiple) {
469
- this.setFieldData(this.fieldData.value[0]);
470
408
  }
409
+ });
410
+ };
471
411
 
472
- const sdFieldName = this.Field.Options.SearchDisplayField || 'id';
473
- this.searchDisplay = selected.map((ss) => Object.nestValue(ss, sdFieldName))
474
- .join(this.Field && this.Field.Options && this.Field.Options.AutoWrap ? '\r\n' : ',');
412
+ return {
413
+ fieldData,
414
+ setFieldData,
415
+ inputControlSettings,
416
+ searchKey,
417
+ showSearch,
418
+ searchData,
419
+ searchSelected,
420
+ originalSelected,
421
+ searchDisplay,
422
+ searchPagination,
423
+ searchColumns: computed(() => {
424
+ if (!props.Field?.Options?.SearchColumns) {
425
+ return [];
426
+ }
475
427
 
476
- this.showSearch = false;
477
- this.$emit('input');
478
- }
479
- },
480
- removeSelected(item) {
481
- if (!item) return;
428
+ const cls = [];
429
+ (props.Field?.Options?.SearchColumns || []).forEach((c) => {
430
+ const newC = { ...c };
431
+ newC.name = c.Name;
432
+ newC.label = c.Label;
433
+ newC.field = c.Name;
434
+ newC.required = c.required;
435
+ newC.align = c.align;
436
+ newC.sortable = c.sortable;
437
+ newC.sort = c.sort;
438
+ newC.style = c.style;
439
+ newC.classes = c.classes;
440
+ newC.headerStyle = c.headerStyle;
441
+ newC.headerClasses = c.headerClasses;
442
+ newC.format = c.format || ((val, row) => Object.nestValue(row, c.Name));
443
+
444
+ if (c.filters) {
445
+ newC.format = (d) => vm.$filter(c.filters, d);
446
+ }
482
447
 
483
- if (!this.Field || !this.Field.Multiple) {
484
- this.searchSelected = [];
485
- this.setFieldData(undefined);
448
+ delete newC.Name;
449
+ delete newC.Label;
486
450
 
487
- this.$emit('input');
451
+ cls.push(newC);
452
+ });
488
453
 
489
- return;
490
- }
454
+ return cls;
455
+ }),
456
+ search,
457
+ searchPaginationChanged: (p) => {
458
+ search(p);
459
+ },
460
+ searchOK: () => {
461
+ if (searchSelected.value.length) {
462
+ const selected = props.Field?.Multiple
463
+ ? searchSelected.value : [searchSelected.value[0]];
491
464
 
492
- const index = this.searchSelected.findIndex((ss) => ss[this.Field.SearchField || 'id'] === item[this.Field.SearchField || 'id']);
493
- if (index >= 0) {
494
- this.searchSelected.splice(index, 1);
465
+ const sFieldName = props.Field.SearchField || 'id';
495
466
 
496
- const selected = this.Field && this.Field.Multiple
497
- ? this.searchSelected : [this.searchSelected[0]];
498
- const sFieldName = this.Field.SearchField || 'id';
499
- this.fieldData = selected.map(
500
- (ss) => Object.nestValue(ss, sFieldName),
501
- ).filter((ss) => !!ss);
467
+ setFieldData(selected.map(
468
+ (ss) => Object.nestValue(ss, sFieldName),
469
+ ).filter((ss) => !!ss));
502
470
 
503
- const sdFieldName = this.Field.Options.SearchDisplayField || 'id';
504
- this.searchDisplay = selected.map((ss) => Object.nestValue(ss, sdFieldName))
505
- .join(this.Field && this.Field.Options && this.Field.Options.AutoWrap ? '\r\n' : ',');
471
+ if (!props.Field?.Multiple) {
472
+ setFieldData(fieldData.value[0]);
473
+ }
506
474
 
507
- this.$emit('input');
508
- }
509
- },
475
+ const sdFieldName = props.Field?.Options?.SearchDisplayField || 'id';
476
+ searchDisplay.value = selected.map((ss) => Object.nestValue(ss, sdFieldName))
477
+ .join(props.Field?.Options?.AutoWrap ? '\r\n' : ',');
478
+
479
+ showSearch.value = false;
480
+ emit('input');
481
+ }
482
+ },
483
+ removeSelected: (item) => {
484
+ if (!item) return;
485
+
486
+ if (!props.Field?.Multiple) {
487
+ searchSelected.value = [];
488
+ setFieldData('');
489
+
490
+ emit('input');
491
+
492
+ return;
493
+ }
494
+
495
+ const index = searchSelected.value.findIndex((ss) => ss[props.Field?.SearchField || 'id'] === item[props.Field?.SearchField || 'id']);
496
+ if (index >= 0) {
497
+ searchSelected.value.splice(index, 1);
498
+
499
+ const selected = props.Field?.Multiple
500
+ ? searchSelected.value : [searchSelected.value[0]];
501
+ const sFieldName = props.Field?.SearchField || 'id';
502
+ fieldData.value = selected.map(
503
+ (ss) => Object.nestValue(ss, sFieldName),
504
+ ).filter((ss) => !!ss);
505
+
506
+ const sdFieldName = props.Field?.Options?.SearchDisplayField || 'id';
507
+ searchDisplay.value = selected.map((ss) => Object.nestValue(ss, sdFieldName))
508
+ .join(props.Field?.Options?.AutoWrap ? '\r\n' : ',');
509
+
510
+ emit('input');
511
+ }
512
+ },
513
+ };
510
514
  },
511
515
  });
512
516
  </script>
@@ -297,6 +297,9 @@ export function useUploader(props, ctx) {
297
297
  filePreview,
298
298
 
299
299
  filesRejected (rejectedEntries) {
300
+ // 忽略duplicate错误
301
+ rejectedEntries = rejectedEntries.filter((entry) => entry.failedPropValidation !== 'duplicate');
302
+
300
303
  if (rejectedEntries && rejectedEntries.length > 0) {
301
304
  const fName = rejectedEntries[0] && rejectedEntries[0].file && rejectedEntries[0].file.name;
302
305
  const fSize = fileSizeNumberToStr(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "free-fe-core-modules",
3
- "version": "0.0.40",
3
+ "version": "0.0.42",
4
4
  "main": "index.js",
5
5
  "repository": "https://github.com/freeeis/free-fe-core-modules.git",
6
6
  "author": "zhiquan",