free-fe-core-modules 0.0.16 → 0.0.18

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 (59) hide show
  1. package/components/Basic/EIcon.vue +3 -0
  2. package/composible/useFormValidator.js +4 -0
  3. package/free-field/Fields/AgreementCheck.js +8 -8
  4. package/free-field/Fields/ApiCall.js +1 -1
  5. package/free-field/Fields/Boolean.js +19 -52
  6. package/free-field/Fields/Category.js +1 -1
  7. package/free-field/Fields/Check.js +8 -3
  8. package/free-field/Fields/Column.vue +12 -9
  9. package/free-field/Fields/Customize.js +1 -1
  10. package/free-field/Fields/Date.js +11 -2
  11. package/free-field/Fields/DateRange.js +7 -3
  12. package/free-field/Fields/DynamicList.js +2 -1
  13. package/free-field/Fields/File.vue +393 -0
  14. package/free-field/Fields/FileList.vue +460 -0
  15. package/free-field/Fields/FileListCombined.vue +172 -0
  16. package/free-field/Fields/FixedList.vue +4 -3
  17. package/free-field/Fields/{InputFieldList.vue → FreeFieldList.vue} +34 -11
  18. package/free-field/Fields/Image.vue +361 -0
  19. package/free-field/Fields/ImageList.vue +353 -0
  20. package/free-field/Fields/ImageListCombined.vue +108 -0
  21. package/free-field/Fields/Labels.vue +3 -5
  22. package/free-field/Fields/MixedTable.vue +2 -2
  23. package/free-field/Fields/Number.js +5 -2
  24. package/free-field/Fields/NumberRange.vue +24 -15
  25. package/free-field/Fields/Password.js +4 -2
  26. package/free-field/Fields/Permission.vue +2 -2
  27. package/free-field/Fields/PermissionEditor.vue +2 -2
  28. package/free-field/Fields/QueryFilters.vue +1 -1
  29. package/free-field/Fields/RadioList.vue +4 -3
  30. package/free-field/Fields/Rich.vue +28 -4
  31. package/free-field/Fields/Row.vue +13 -10
  32. package/free-field/Fields/Search.vue +28 -26
  33. package/free-field/Fields/Select.vue +30 -22
  34. package/free-field/Fields/SelectionChain.vue +4 -2
  35. package/free-field/Fields/Separator.js +1 -1
  36. package/free-field/Fields/SingleList.vue +1 -1
  37. package/free-field/Fields/Static.js +1 -1
  38. package/free-field/Fields/String.js +20 -5
  39. package/free-field/Fields/Tabs.vue +9 -9
  40. package/free-field/Fields/Text.js +7 -4
  41. package/free-field/Fields/Time.vue +5 -3
  42. package/free-field/Fields/TimeRange.vue +7 -4
  43. package/free-field/Fields/Year.js +4 -2
  44. package/free-field/Fields/YearRange.vue +6 -3
  45. package/free-field/Fields/index.js +20 -13
  46. package/free-field/composible/fieldWrapper.js +137 -11
  47. package/free-field/composible/readonlyContent.js +1 -1
  48. package/free-field/composible/useFreeField.js +25 -9
  49. package/free-field/composible/useUploader.js +320 -0
  50. package/free-field/style.scss +173 -0
  51. package/i18n/en-us/index.js +3 -0
  52. package/i18n/fields/en-us/index.js +1 -0
  53. package/i18n/fields/zh-cn/index.js +1 -0
  54. package/i18n/zh-cn/index.js +3 -0
  55. package/index.js +7 -0
  56. package/package.json +1 -1
  57. package/view/menu/index.vue +6 -6
  58. package/view/system/index.vue +1 -1
  59. package/free-field/style.sass +0 -11
@@ -0,0 +1,320 @@
1
+ import { computed, getCurrentInstance, ref } from "vue";
2
+ import { Notify } from 'quasar';
3
+
4
+
5
+ function fileSizeStrToNumber (s) {
6
+ if (!s) return undefined;
7
+
8
+ const sizeMatch = s.match(/^([0-9]*)(k|m|g*)(b*)/);
9
+
10
+ if (sizeMatch) {
11
+ // eslint-disable-next-line no-unused-vars
12
+ // const [tmp, num, unit] = sizeMatch;
13
+ const num = sizeMatch[1];
14
+ const unit = sizeMatch[2];
15
+ if (!num || !Number(num)) return '';
16
+
17
+ let multi = 1;
18
+ switch (unit) {
19
+ case 'k':
20
+ multi = 1024;
21
+ break;
22
+ case 'm':
23
+ multi = 1024 * 1024;
24
+ break;
25
+ case 'g':
26
+ multi = 1024 * 1024 * 1024;
27
+ break;
28
+ default:
29
+ multi = 1024;
30
+ break;
31
+ }
32
+
33
+ return Number(num) * multi;
34
+ }
35
+
36
+ return undefined;
37
+ }
38
+
39
+ function fileSizeNumberToStr (s) {
40
+ if (!s) return '0K';
41
+
42
+ let sizeNum = Number(s) || 0;
43
+
44
+ if (!sizeNum || sizeNum <= 0) return '0K';
45
+
46
+ const unitList = ['B', 'K', 'M', 'G'];
47
+ let unit = 'B';
48
+ let unitIndex = 0;
49
+
50
+ while (sizeNum > 1024) {
51
+ if (unit === 'G') break;
52
+
53
+ unitIndex += 1;
54
+ unit = unitList[unitIndex];
55
+ sizeNum /= 1024;
56
+ }
57
+
58
+ return `${sizeNum.toFixed(2)}${unit}`;
59
+ }
60
+
61
+ // eslint-disable-next-line no-underscore-dangle
62
+ function _getFileType (f) {
63
+ if (!f) return {};
64
+
65
+ if (f.type) {
66
+ const fTypes = f.type.split('/');
67
+ const [fType, fExt] = fTypes;
68
+ return {
69
+ fType, fExt,
70
+ };
71
+ }
72
+
73
+ if (f.id) {
74
+ let extname = f.id.substr(f.id.lastIndexOf('.'));
75
+ if (extname.startsWith('.')) {
76
+ extname = extname.substr(1);
77
+ }
78
+
79
+ extname = extname && extname.toLowerCase();
80
+
81
+ switch (extname) {
82
+ case 'png':
83
+ case 'jpg':
84
+ case 'jpeg':
85
+ case 'bmp':
86
+ case 'gif':
87
+ return { fType: 'image', fExt: extname };
88
+ case 'wav':
89
+ case 'mp3':
90
+ return { fType: 'audio', fExt: extname };
91
+ case 'mp4':
92
+ return { fType: 'video', fExt: extname };
93
+ case 'txt':
94
+ return { fType: 'text', fExt: extname };
95
+ default:
96
+ return { fType: 'application', fExt: extname };
97
+ }
98
+ }
99
+
100
+ return {};
101
+ }
102
+
103
+ export function useUploader(props, ctx) {
104
+ const { proxy:vm } = getCurrentInstance();
105
+
106
+ const showPreview = ref(false);
107
+ const previewFile = ref(undefined);
108
+ const previewType = ref(undefined);
109
+
110
+ const maxFileSize = computed(() => {
111
+ return fileSizeStrToNumber(props.Field?.MaxValue || '10m') * 1.1;
112
+ });
113
+
114
+ const maxTotalSize = computed(() => {
115
+ return fileSizeStrToNumber((props.Field?.Options?.MaxTotal) || '10m') * 1.1;
116
+ });
117
+
118
+ const acceptedFileTypes = computed(() => {
119
+ if (!props.Field?.Options?.Ext) return '';
120
+
121
+ const extList = props.Field.Options.Ext.split(',') || [];
122
+ const typeList = [];
123
+
124
+ const MIME_TYPE_LIST = {
125
+ mp4: 'video/mp4',
126
+ avi: 'video/x-msvideo',
127
+ bmp: 'image/bmp',
128
+ doc: 'application/msword',
129
+ docx:
130
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
131
+ gif: 'image/gif',
132
+ jpe: 'image/jpeg',
133
+ jpeg: 'image/jpeg',
134
+ jpg: 'image/jpeg',
135
+ png: 'image/png',
136
+ mpeg: 'video/mpeg',
137
+ pdf: 'application/pdf',
138
+ ppt: 'application/vnd.ms-powerpoint',
139
+ pptx:
140
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
141
+ svg: 'image/svg+xml',
142
+ txt: 'text/plain',
143
+ wav: 'audio/x-wav',
144
+ xls: 'application/vnd.ms-excel',
145
+ xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
146
+ zip: 'application/zip',
147
+ };
148
+
149
+ extList.forEach((ext) => {
150
+ let type = ext.trim().toLowerCase();
151
+ type = MIME_TYPE_LIST[type] || type;
152
+
153
+ if (type && typeList.indexOf(type) < 0) typeList.push(type);
154
+ if (ext && typeList.indexOf(ext) < 0) typeList.push(ext);
155
+ });
156
+
157
+ return typeList.join(',');
158
+ });
159
+
160
+ const fileThumb = computed(() => (file) => {
161
+ const unknownType = 'insert_drive_file';
162
+ if (!file) return unknownType;
163
+
164
+ let type = '';
165
+ // const fTypes = file.type.split('/');
166
+ // const [fType, fExt] = fTypes;
167
+ const { fType, fExt } = _getFileType(file);
168
+
169
+ switch (fType) {
170
+ case 'image':
171
+ // eslint-disable-next-line no-underscore-dangle
172
+ type = file.id || (file.__img ? file.__img.src : '');
173
+ break;
174
+ case 'audio':
175
+ type = 'far fa-file-audio';
176
+ break;
177
+ case 'video':
178
+ type = 'far fa-file-video';
179
+ break;
180
+ case 'text':
181
+ type = 'far fa-file-text';
182
+ break;
183
+ case 'application':
184
+ switch (fExt) {
185
+ case 'doc':
186
+ case 'docx':
187
+ case 'vnd.openxmlformats-officedocument.wordprocessingml.document':
188
+ type = 'far fa-file-word';
189
+ break;
190
+ case 'xls':
191
+ case 'xlsx':
192
+ case 'vnd.openxmlformats-officedocument.spreadsheetml.sheet':
193
+ type = 'far fa-file-excel';
194
+ break;
195
+ case 'ppt':
196
+ case 'pptx':
197
+ case 'vnd.openxmlformats-officedocument.presentationml.presentation':
198
+ type = 'far fa-file-powerpoint';
199
+ break;
200
+ case 'pdf':
201
+ type = 'far fa-file-pdf';
202
+ // type = 'insert_drive_file';
203
+ break;
204
+ case 'zip':
205
+ case 'rar':
206
+ case '7z':
207
+ case 'x-zip-compressed':
208
+ type = 'far fa-file-archive';
209
+ break;
210
+ default:
211
+ break;
212
+ }
213
+ break;
214
+ default:
215
+ break;
216
+ }
217
+
218
+ return type || unknownType;
219
+ });
220
+
221
+ const filePreviewType = computed(() => (file) => {
222
+ if (!file) return '';
223
+
224
+ // const fTypes = file.type.split('/');
225
+ // const [fType, fExt] = fTypes;
226
+ const { fType, fExt } = _getFileType(file);
227
+
228
+ switch (fType) {
229
+ case 'image':
230
+ return 'image';
231
+ case 'application':
232
+ switch (fExt) {
233
+ case 'doc':
234
+ case 'docx':
235
+ case 'vnd.openxmlformats-officedocument.wordprocessingml.document':
236
+ return 'word';
237
+ case 'xls':
238
+ case 'xlsx':
239
+ case 'vnd.openxmlformats-officedocument.spreadsheetml.sheet':
240
+ return 'excel';
241
+ case 'ppt':
242
+ case 'pptx':
243
+ case 'vnd.openxmlformats-officedocument.presentationml.presentation':
244
+ return 'ppt';
245
+ case 'pdf':
246
+ return 'pdf';
247
+ default:
248
+ break;
249
+ }
250
+ break;
251
+ default:
252
+ break;
253
+ }
254
+
255
+ return '';
256
+ });
257
+
258
+ const filePreview = computed(() => (file) => {
259
+ if (!file) return '';
260
+ let url = '';
261
+
262
+ const type = filePreviewType.value(file);
263
+ switch (type) {
264
+ case 'image':
265
+ if (file.id) {
266
+ url = vm.$filter('serverImage', file.id);
267
+ } else {
268
+ // eslint-disable-next-line no-underscore-dangle
269
+ url = file.__img ? file.__img.src : '';
270
+ }
271
+ break;
272
+ case 'pdf':
273
+ if (file.id) {
274
+ url = vm.$filter('serverDocument', file.id);
275
+ }
276
+ break;
277
+ default:
278
+ break;
279
+ }
280
+
281
+ return url;
282
+ });
283
+
284
+ return {
285
+ showPreview,
286
+ previewType,
287
+ previewFile,
288
+ maxFileSize,
289
+ maxTotalSize,
290
+ acceptedFileTypes,
291
+ fileThumb,
292
+ filePreviewType,
293
+ filePreview,
294
+
295
+ filesRejected (rejectedEntries) {
296
+ if (rejectedEntries && rejectedEntries.length > 0) {
297
+ const fName = rejectedEntries[0] && rejectedEntries[0].file && rejectedEntries[0].file.name;
298
+ const fSize = fileSizeNumberToStr(
299
+ rejectedEntries[0] && rejectedEntries[0].file && rejectedEntries[0].file.size,
300
+ );
301
+ // TODO: i18n
302
+ Notify.create({ message: `文件格式或大小不符合要求:${fName} (${fSize})` });
303
+ }
304
+ },
305
+ preview (file) {
306
+ if (!file) return;
307
+
308
+ previewType.value = filePreviewType.value(file);
309
+
310
+ const url = filePreview.value(file);
311
+ if (!url) {
312
+ return;
313
+ }
314
+
315
+ previewFile.value = url;
316
+
317
+ showPreview.value = true;
318
+ },
319
+ }
320
+ };
@@ -0,0 +1,173 @@
1
+ $freeFieldCategoryMargin: var(--free-field-category-margin, unset);
2
+ $freeFieldWrapperMargin: var(--free-field-wrapper-margin, unset);
3
+ $freeFieldMargin: var(--free-field-margin, unset);
4
+ $simpleFieldHeight: var(--simple-field-height, unset);
5
+ $simpleFieldWidth: var(--simple-field-width, 100%);
6
+ $fieldLabelWidth: var(--field-label-width,120px);
7
+ $fieldLabelFontSize: var(--field-label-font-size,12px);
8
+ $fieldLabelColor: var(--field-label-color,unset);
9
+ $fieldLabelAfter: var(--field-label-after,'');
10
+ $fieldLabelRequiredColor: var(--field-label-required-color,#E33);
11
+ $editorAreaBackground: var(--editor-area-background, unset);
12
+
13
+ .free-field-wrapper {
14
+ width: 100%;
15
+ .free-field-wrapper {
16
+ width: unset
17
+ }
18
+ .simple-field {
19
+ // display: inline-block;
20
+ width: 100%;
21
+ }
22
+ .free-field-range-separator {
23
+ margin: 0 6px;
24
+ }
25
+ .field-label-empty {
26
+ display: inline-block;
27
+ margin-left: 0;
28
+ padding-left: 0;
29
+ width: $fieldLabelWidth;
30
+ min-width: $fieldLabelWidth;
31
+ }
32
+
33
+ .field-label {
34
+ display: inline-block;
35
+ margin-left: 0;
36
+ padding-left: 0;
37
+ font-size: $fieldLabelFontSize;
38
+ width: $fieldLabelWidth;
39
+ min-width: $fieldLabelWidth;
40
+ color: $fieldLabelColor;
41
+ text-align: right;
42
+ white-space: normal;
43
+ }
44
+
45
+ .field-label:after {
46
+ content: $fieldLabelAfter;
47
+ }
48
+
49
+ .required-mark {
50
+ color: $fieldLabelRequiredColor;
51
+ position: relative;
52
+ top: 3px;
53
+ }
54
+
55
+ .q-uploader {
56
+ flex: 1;
57
+ box-shadow: unset;
58
+ }
59
+
60
+ .free-field-warning {
61
+ font-size: 12px;
62
+ font-weight: 400;
63
+ color: rgba(234,7,50,1);
64
+ margin-left: 15px;
65
+ overflow: hidden;
66
+ white-space: nowrap;
67
+ display: inline-block;
68
+ &-icon {
69
+ position: relative;
70
+ top: -7px;
71
+ display: inline-block;
72
+ border-width: 8px;
73
+ border-color: transparent transparent #FF8244 transparent;
74
+ border-style: dashed;
75
+ transform: scaleY(2.3);
76
+ &-sign-top {
77
+ position: relative;
78
+ top: -2px;
79
+ left: -9px;
80
+ background: $primary;
81
+ display: inline-block;
82
+ width: 2px;
83
+ height: 8px;
84
+ }
85
+ &-sign-dot {
86
+ position: relative;
87
+ top: 3px;
88
+ left: -10px;
89
+ background: $primary;
90
+ display: inline-block;
91
+ width: 3px;
92
+ height: 3px;
93
+ transform: translateX(-50%);
94
+ -moz-transform: translateX(-50%);
95
+ -webkit-transform: translateX(-50%);
96
+ -ms-transform: translateX(-50%);
97
+ }
98
+ }
99
+ &-text {
100
+ overflow: hidden;
101
+ }
102
+ }
103
+
104
+ .free-field-tips {
105
+ position: relative;
106
+ left: 10px;
107
+ margin-left: $fieldLabelWidth;
108
+ margin-top: 6px;
109
+ font-size: 12px;
110
+ font-weight: 400;
111
+ color: rgba(0,135,197,1);
112
+ padding-right: 20px;
113
+ .tips-list {
114
+ .free-field-tips-tip {
115
+ display: block;
116
+ .tip-link {
117
+ font-size: 12px;
118
+ font-weight: bold;
119
+ color: rgba(16,108,211,1);
120
+ a,a:visited {
121
+ color: rgba(16,108,211,1);
122
+ }
123
+ &-prefix::before {
124
+ content: '【';
125
+ }
126
+ &-postfix::after {
127
+ content: '】';
128
+ }
129
+ &-text {
130
+ text-decoration: underline;
131
+ }
132
+ }
133
+ }
134
+ }
135
+ &-prefix {
136
+ display: inline-block;
137
+ position: absolute;
138
+ width: 18px;
139
+ height: 18px;
140
+ border: 2px solid;
141
+ border-radius: 50%;
142
+ margin-right: 4px;
143
+ top: 0px;
144
+ left: 0;
145
+ & + .tips-list {
146
+ position: relative;
147
+ left: 24px;
148
+ }
149
+ }
150
+ &-postfix {
151
+ display: inline-block;
152
+ position: absolute;
153
+ top: 0px;
154
+ left: 6px;
155
+ width: 6px;
156
+ height: 3px;
157
+ background: $background;
158
+ &::after {
159
+ display: inline-block;
160
+ position: absolute;
161
+ content: '!';
162
+ font-size: 16px;
163
+ font-weight: 700;
164
+ width: 3px;
165
+ top: -6px;
166
+ left: 2px;
167
+ transform: translateX(-50%);
168
+ -moz-transform: translateX(-50%);
169
+ -ms-transform: translateX(-50%);
170
+ }
171
+ }
172
+ }
173
+ }
@@ -1,4 +1,7 @@
1
+ import fields from '../fields/en-us';
2
+
1
3
  export default {
4
+ ...fields,
2
5
  justNow: 'just now',
3
6
  secondsAgo: 'seconds ago',
4
7
  minutesAgo: 'minutes ago',
@@ -5,5 +5,6 @@ export default {
5
5
  fieldCategoryAdvanced: 'Advanced',
6
6
  fieldCategoryTable: 'Table',
7
7
  fieldCategoryUpload: 'Upload',
8
+ fieldCategoryContainer: 'Container',
8
9
  fieldCategoryOthers: 'Others',
9
10
  };
@@ -5,5 +5,6 @@ export default {
5
5
  fieldCategoryAdvanced: '高级',
6
6
  fieldCategoryTable: '表格',
7
7
  fieldCategoryUpload: '上传',
8
+ fieldCategoryContainer: '容器',
8
9
  fieldCategoryOthers: '其他',
9
10
  };
@@ -1,4 +1,7 @@
1
+ import fields from '../fields/zh-cn';
2
+
1
3
  export default {
4
+ ...fields,
2
5
  justNow: '刚刚',
3
6
  secondsAgo: '秒之前',
4
7
  minutesAgo: '分钟之前',
package/index.js CHANGED
@@ -306,6 +306,13 @@ export default (app, root) => {
306
306
  clearable: true,
307
307
  Options: [],
308
308
  },
309
+ {
310
+ Name: 'CustomizeRoute',
311
+ Label: '自定义路径',
312
+ Info: {
313
+ ShowWhen: 'data.Route === "customize"',
314
+ },
315
+ },
309
316
  {
310
317
  Name: "Enabled",
311
318
  Label: "启用",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "free-fe-core-modules",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "main": "index.js",
5
5
  "repository": "https://github.com/freeeis/free-fe-core-modules.git",
6
6
  "author": "zhiquan",
@@ -172,12 +172,6 @@ export default defineComponent({
172
172
  m.Options.push({
173
173
  Label: this.$t('自定义'),
174
174
  Value: 'customize',
175
- Extra: [
176
- {
177
- Name: 'CustomizeRoute',
178
- Label: this.$t('自定义路径'),
179
- },
180
- ],
181
175
  });
182
176
 
183
177
  break;
@@ -341,3 +335,9 @@ export default defineComponent({
341
335
  },
342
336
  });
343
337
  </script>
338
+
339
+ <style lang="scss" scoped>
340
+ .admin-menu-mgmt-wrapper {
341
+ background: $background;
342
+ }
343
+ </style>
@@ -58,7 +58,7 @@
58
58
  </span>
59
59
  </div>
60
60
 
61
- <div class="flow-step-input-fields">
61
+ <div class="flow-step-free-fields">
62
62
  <free-field
63
63
  v-for="(field, fIndex) in step.Fields || []"
64
64
  :key="fIndex"
@@ -1,11 +0,0 @@
1
- $inputFieldCategoryMargin: var(--input-field-category-margin, unset)
2
- $inputFieldWrapperMargin: var(--input-field-wrapper-margin, unset)
3
- $inputFieldMargin: var(--input-field-margin, unset)
4
- $simpleFieldHeight: var(--simple-field-height, unset)
5
- $simpleFieldWidth: var(--simple-field-width, 100%)
6
- $fieldLabelWidth: var(--field-label-width,120px)
7
- $fieldLabelFontSize: var(--field-label-font-size,12px)
8
- $fieldLabelColor: var(--field-label-color,unset)
9
- $fieldLabelAfter: var(--field-label-after,'')
10
- $fieldLabelRequiredColor: var(--field-label-required-color,#E33)
11
- $editorAreaBackground: var(--editor-area-background, unset)