@neatui/vue 2.11.0 → 2.15.0

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 (49) hide show
  1. package/package.json +1 -1
  2. package/src/components/basic/LayerView/Layer.vue +0 -16
  3. package/src/components/display/Calendar.vue +14 -14
  4. package/src/components/display/CalendarReg.vue +14 -14
  5. package/src/components/display/Tree.vue +6 -6
  6. package/src/components/form/Cascader.vue +20 -20
  7. package/src/components/form/DatePicker.vue +8 -9
  8. package/src/components/form/DateRangePicker@v3.vue +5 -5
  9. package/src/components/form/DateRangeView@v3.vue +9 -9
  10. package/src/components/form/DateView.vue +14 -14
  11. package/src/components/form/DateView@v2.vue +14 -14
  12. package/src/components/form/DateView@v3.vue +17 -15
  13. package/src/components/form/Input@v3.vue +7 -7
  14. package/src/components/form/MoreSelect@v3.vue +85 -15
  15. package/src/components/form/MoreSelectList.vue +1 -1
  16. package/src/components/form/MoreSelectPanel@v3.vue +4 -4
  17. package/src/components/form/MoreSelectPicker.vue +1 -1
  18. package/src/components/form/MoreSelectTags.vue +1 -1
  19. package/src/components/form/PageMoreSelect.vue +15 -15
  20. package/src/components/form/PageSelect.vue +17 -17
  21. package/src/components/form/SearchMoreSelect.vue +1 -1
  22. package/src/components/form/SearchSelect@v3.vue +4 -4
  23. package/src/components/form/Select@v3.vue +227 -20
  24. package/src/components/form/SelectList.vue +8 -8
  25. package/src/components/form/SelectPicker.vue +7 -7
  26. package/src/components/form/SelectTags.vue +7 -7
  27. package/src/components/form/SelectTree/SelectTree@v1.vue +6 -6
  28. package/src/components/form/Switch.vue +33 -58
  29. package/src/components/form/Textarea@v2.vue +275 -0
  30. package/src/components/form/TimeView.vue +14 -14
  31. package/src/components/form/Upload.vue +52 -9
  32. package/src/components/form/date.ts +321 -0
  33. package/src/components/form/index.ts +2 -2
  34. package/src/components/form/number.ts +3 -0
  35. package/src/components/form/type.ts +224 -0
  36. package/src/components/loader/FormLoader/FormLoader@v2.vue +20 -20
  37. package/src/components/loader/FormLoader/FormLoader@v3.vue.backup +372 -291
  38. package/src/components/loader/FormLoader/FormRender@v3.vue.backup +4 -0
  39. package/src/components/loader/FormLoader/NodeLoader.vue +85 -0
  40. package/src/components/loader/FormLoader@v1/FormLoader.vue +1 -1
  41. package/src/components/loader/FormLoader@v1/FormRender.vue +49 -24
  42. package/src/components/loader/LayerLoader/LayerLoader.vue +1 -1
  43. package/src/components/loader/LimitLoader/LimitLoader@v3.vue +1 -1
  44. package/src/components/loader/MoveLoader/MoveLoader.vue +8 -8
  45. package/src/components/loader/TableLoader/TableRender.vue +1 -1
  46. package/src/components/loader/index.ts +1 -1
  47. package/src/components/tools/Pagination@a.vue +1 -1
  48. package/tsconfig.json +1 -1
  49. package/src/components/loader/FormLoader/index.ts +0 -2
@@ -1,6 +1,6 @@
1
1
  <template>
2
- <label ui-form="@a type:switch" class="lh-ls">
3
- <input type="checkbox" name="form2" :checked="value ? true : false" />
2
+ <label ui-form="@a type:switch">
3
+ <input type="checkbox" v-model="internalValue" :disabled="disabled" />
4
4
  <slot>
5
5
  <span>{{ text }}</span>
6
6
  </slot>
@@ -8,7 +8,7 @@
8
8
  </template>
9
9
 
10
10
  <script setup lang="ts">
11
- import { ref, watch, computed, onMounted, PropType } from 'vue';
11
+ import { ref, watch, PropType } from 'vue';
12
12
 
13
13
  const props = defineProps({
14
14
  theme: { type: String, default: '@a' },
@@ -17,79 +17,54 @@
17
17
  block: { type: Boolean, default: true },
18
18
  // 值
19
19
  modelValue: {
20
- type: [Number, Boolean],
20
+ type: [Number, Boolean, String],
21
21
  default: false,
22
22
  },
23
- // 类型
24
- type: {
25
- type: String,
26
- default: 'text',
27
- },
28
23
  text: {
29
24
  type: String,
30
25
  default: '',
31
26
  },
32
- // 提示文案
33
- tips: {
34
- type: String,
35
- default: '',
36
- },
37
- // 内容占位
38
- placeholder: {
39
- type: String,
40
- default: '',
41
- },
42
- // 最大长度
43
- maxlength: {
44
- type: Number,
45
- default: null,
46
- },
47
- // 最小长度
48
- minlength: {
49
- type: Number,
50
- default: null,
51
- },
52
27
  // 是否禁用
53
28
  disabled: {
54
29
  type: Boolean,
55
30
  default: false,
56
31
  },
57
- // 是否中读
58
- readonly: {
59
- type: Boolean,
60
- default: false,
61
- },
62
- // 是否显示清除按钮
63
- clearable: {
64
- type: Boolean,
65
- default: true,
66
- },
67
- // 校验规则
68
- rules: {
69
- type: Array,
70
- default: () => [],
71
- },
72
- // 是否是示校验图标
73
- verify: {
74
- type: Boolean,
75
- default: false,
76
- },
77
- prefix: {
78
- type: Array as PropType<any[]>,
79
- default: () => [],
80
- },
81
- suffix: {
32
+ map: {
82
33
  type: Array as PropType<any[]>,
83
- default: () => [],
34
+ default: () => [false, true],
84
35
  },
85
36
  });
86
37
 
87
- const value = ref(props.modelValue);
88
- // 监听异步数据
38
+ const emit = defineEmits(['update:modelValue']);
39
+
40
+ // 内部值(始终是布尔值)
41
+ const internalValue = ref(false);
42
+
43
+ // 计算内部值
44
+ const getInternalValue = (externalValue: any) => {
45
+ const index = props.map.indexOf(externalValue);
46
+ return index === 0 ? true : index === 1 ? false : Boolean(externalValue);
47
+ };
48
+
49
+ // 计算外部值
50
+ const getExternalValue = (internalValue: boolean) => {
51
+ return internalValue ? props.map[0] : props.map[1];
52
+ };
53
+
54
+ // 初始化内部值
55
+ internalValue.value = getInternalValue(props.modelValue);
56
+
57
+ // 监听外部值变化
89
58
  watch(
90
59
  () => props.modelValue,
91
60
  (newValue) => {
92
- value.value = newValue;
61
+ internalValue.value = getInternalValue(newValue);
93
62
  },
94
63
  );
64
+
65
+ // 监听内部值变化,向父组件发送映射后的值
66
+ watch(internalValue, (newValue) => {
67
+ const externalValue = getExternalValue(newValue);
68
+ emit('update:modelValue', externalValue);
69
+ });
95
70
  </script>
@@ -0,0 +1,275 @@
1
+ <template>
2
+ <div
3
+ :ui-form="`${theme} sz:${sz} ${state.error.co} type:textarea ${block ? ' :block' : ''} ${disabled ? 'disabled' : ''} ${readonly ? 'readonly' : ''}`"
4
+ @click="emits('click', $event)"
5
+ >
6
+ <div :ui-form-tips="state.error.ontips">{{ state.error.tips }}</div>
7
+ <div ui-form-prefix="">
8
+ <template v-for="(item, idx) in prefix" :key="idx">
9
+ <div v-if="isObject(item)" v-bind="item.attrs" v-on="event(item, props.modelValue)">
10
+ <div v-html="isFunction(item.value) ? item.value(props.modelValue) : item.value"></div>
11
+ </div>
12
+ <div v-else v-html="isFunction(item) ? item(props.modelValue) : item"></div>
13
+ </template>
14
+ <slot name="prefix"></slot>
15
+ </div>
16
+ <slot>
17
+ <textarea
18
+ ref="el"
19
+ :title="props.modelValue"
20
+ :value="props.modelValue"
21
+ :placeholder="placeholder"
22
+ :disabled="disabled"
23
+ :readonly="readonly"
24
+ :rows="rows"
25
+ ui-scroll=":y"
26
+ dir="auto"
27
+ @focus="emits('focus', $event, state)"
28
+ @input="input($event)"
29
+ @change="emits('change', $event, state)"
30
+ @blur="blur($event)"
31
+ ></textarea>
32
+ </slot>
33
+ <div ui-form-suffix="">
34
+ <i ui-form-clean="" v-if="clearable && props.modelValue && !readonly && !disabled" @click.stop="clear"></i>
35
+ <slot name="suffix"></slot>
36
+ <template v-for="(item, idx) in suffix" :key="idx">
37
+ <div v-if="isObject(item)" v-bind="item.attrs" v-on="event(item, props.modelValue)">
38
+ <div v-html="isFunction(item.value) ? item.value(props.modelValue) : item.value"></div>
39
+ </div>
40
+ <div v-else v-html="isFunction(item) ? item(props.modelValue) : item"></div>
41
+ </template>
42
+ </div>
43
+ <i v-if="verify && state.interacted" :ui-form-verify="state.error.verify"></i>
44
+ </div>
45
+ </template>
46
+
47
+ <script setup lang="ts">
48
+ import { reactive, watch, ref, nextTick, onMounted } from 'vue';
49
+ import { isObject, isFunction } from '@fekit/utils';
50
+
51
+ const emits = defineEmits(['update:modelValue', 'click', 'blur', 'focus', 'change', 'input', 'clear']);
52
+
53
+ /**
54
+ * 入参说明
55
+ *
56
+ * modelValue 值
57
+ * theme 主题
58
+ * sz 尺寸
59
+ * co 颜色
60
+ * block 撑满
61
+ * ready 准备就绪
62
+ * tips 提示文案
63
+ * placeholder 内容占位
64
+ * maxlength 最大长度
65
+ * minlength 最小长度
66
+ * disabled 是否禁用
67
+ * readonly 是否只读
68
+ * clearable 是否显示清除按钮
69
+ * rules 校验规则
70
+ * verify 是否是示校验图标 2=tips 3=text 4=icon 5=tips+text 6=text+icon 7=text+icon
71
+ * prefix 前缀内容
72
+ * suffix 后缀内容
73
+ * interacted 用户是否交互
74
+ * autoHeight 是否自动调整高度
75
+ * rows 初始行数
76
+ */
77
+
78
+ // 类型
79
+ interface Props {
80
+ modelValue?: string | number;
81
+ placeholder?: string;
82
+ rules?: Array<object>;
83
+ theme?: string;
84
+ sz?: '' | 'xs' | 's' | 'm' | 'l' | 'xl';
85
+ co?: string;
86
+ block?: boolean;
87
+ ready?: boolean;
88
+ tips?: string;
89
+ maxlength?: null | number;
90
+ minlength?: null | number;
91
+ disabled?: boolean;
92
+ readonly?: boolean;
93
+ clearable?: boolean;
94
+ verify?: boolean;
95
+ prefix?: Array<any>;
96
+ suffix?: Array<any>;
97
+ interacted?: boolean;
98
+ autoHeight?: boolean;
99
+ rows?: number;
100
+ }
101
+ const props: any = withDefaults(defineProps<Props>(), {
102
+ modelValue: '',
103
+ placeholder: '',
104
+ rules: () => [],
105
+ theme: '@a',
106
+ sz: '',
107
+ co: '',
108
+ block: true,
109
+ ready: false,
110
+ tips: '',
111
+ maxlength: null,
112
+ minlength: null,
113
+ disabled: false,
114
+ readonly: false,
115
+ clearable: true,
116
+ verify: false,
117
+ prefix: () => [],
118
+ suffix: () => [],
119
+ interacted: false,
120
+ // textarea 特有属性默认值
121
+ autoHeight: false,
122
+ rows: 3,
123
+ });
124
+
125
+ const state: any = reactive({
126
+ // 用户是否交互
127
+ interacted: false,
128
+ // 值
129
+ value: props.modelValue,
130
+ // 错误
131
+ error: {},
132
+ });
133
+
134
+ // textarea 元素引用
135
+ const el: any = ref(null);
136
+
137
+ // 自动高度功能
138
+ const fAutoHeight = () => {
139
+ nextTick(() => {
140
+ if (props.autoHeight && el.value) {
141
+ el.value.style.height = 'auto';
142
+ el.value.style.height = el.value.scrollHeight + 1 + 'px';
143
+ }
144
+ });
145
+ };
146
+
147
+ // 外部传入交互标识,主要用于外部没有输入但点击了提交
148
+ watch(
149
+ () => props.interacted,
150
+ (interacted: any) => {
151
+ if (interacted) {
152
+ state.interacted = interacted;
153
+ }
154
+ },
155
+ { deep: true, immediate: true },
156
+ );
157
+
158
+ // 校验
159
+ watch(
160
+ [() => state.interacted, () => props.modelValue],
161
+ async () => {
162
+ if (state.interacted) {
163
+ // 提示文案
164
+ let tips = '';
165
+ // 错误类型
166
+ let type = '';
167
+ // 验证结果
168
+ let verify = '';
169
+
170
+ if (props.modelValue) {
171
+ // 有值
172
+ let hasError = false;
173
+ // 遍历校验规则
174
+ for (const rule of props.rules) {
175
+ if (rule && rule.validator) {
176
+ const yes = !(await rule.validator(props.modelValue));
177
+ if (yes) {
178
+ tips = rule.msg;
179
+ type = rule.type;
180
+ hasError = true;
181
+ break;
182
+ }
183
+ }
184
+ }
185
+ verify = hasError ? 'no' : 'ok';
186
+ } else {
187
+ // 无值
188
+ let hasError = false;
189
+ // 遍历校验规则
190
+ for (const rule of props.rules) {
191
+ if (rule) {
192
+ tips = rule.msg;
193
+ type = rule.type;
194
+ if (rule.required) {
195
+ hasError = true;
196
+ break;
197
+ }
198
+ }
199
+ }
200
+ verify = hasError ? 'no' : '';
201
+ }
202
+ if (verify !== 'no' && props.tips) {
203
+ tips = props.tips;
204
+ }
205
+ // 是否显示提示
206
+ const ontips = (verify === 'no' && tips) || props.tips ? 'show' : '';
207
+ // 状态颜色
208
+ const co = verify === 'no' ? 'co:' + type : props.co ? 'co:' + props.co : '';
209
+ state.error = { tips, ontips, verify, co };
210
+ } else {
211
+ state.error = { tips: props.tips, ontips: props.tips ? 'show' : '', verify: '', co: '' };
212
+ }
213
+ },
214
+ { deep: true, immediate: true },
215
+ );
216
+
217
+ // 清空
218
+ function clear() {
219
+ emits('update:modelValue', null);
220
+ emits('clear');
221
+ }
222
+ // 输入
223
+ const input = (e: any) => {
224
+ // 用户交互
225
+ if (!state.interacted) {
226
+ setTimeout(() => {
227
+ state.interacted = true;
228
+ }, 50);
229
+ }
230
+
231
+ // 长度限制
232
+ const value = e?.target?.value || '';
233
+ if (props.maxlength && value.length > props.maxlength) {
234
+ e.target.value = props.modelValue;
235
+ return false;
236
+ }
237
+ // 输入事件
238
+ emits('input', e, state);
239
+ emits('update:modelValue', value || null);
240
+
241
+ // 自动高度
242
+ fAutoHeight();
243
+ };
244
+ // 失焦
245
+ const blur = (e: any) => {
246
+ if (!state.interacted) {
247
+ setTimeout(() => {
248
+ state.interacted = true;
249
+ }, 50);
250
+ }
251
+ emits('blur', e, state);
252
+ };
253
+
254
+ // 事件处理
255
+ const event: any = (item: any, data: any): object => {
256
+ const _event: any = {};
257
+ if (isObject(item.event)) {
258
+ for (const key in item.event) {
259
+ const fun = item.event[key];
260
+ if (isFunction(fun)) {
261
+ _event[key] = (...args: any) => {
262
+ return fun({ data }, ...args);
263
+ };
264
+ }
265
+ }
266
+ }
267
+ return { ..._event };
268
+ };
269
+
270
+ // 组件挂载后初始化自动高度
271
+ onMounted(() => {
272
+ // 自动高度
273
+ fAutoHeight();
274
+ });
275
+ </script>
@@ -19,8 +19,8 @@
19
19
  <div
20
20
  ui-flex="col cm"
21
21
  class="r-sm b-solid bk-none b-xs"
22
- :class="`${item.isToday ? 'bk-main-ls' : item.isLastMonth || item.isNextMonth ? 'co-note' : item.isHoliday ? 'co-risk' : ''} ${
23
- state.selected && state.selected === item.date ? 'active bg-main-ls co-fore' : 'hover-bg-weak'
22
+ :class="`${item.isToday ? 'bk-main-o-ls' : item.isLastMonth || item.isNextMonth ? 'co-note' : item.isHoliday ? 'co-risk' : ''} ${
23
+ state.selected && state.selected === item.date ? 'active bg-main-o-ls co-fore' : 'hover-bg-weak'
24
24
  }`"
25
25
  >
26
26
  <span>{{ item.day }}</span>
@@ -107,40 +107,40 @@
107
107
  // 提示文案
108
108
  tips: {
109
109
  type: String,
110
- default: ''
110
+ default: '',
111
111
  },
112
112
  // 提示文案
113
113
  placeholder: {
114
114
  type: String,
115
- default: ''
115
+ default: '',
116
116
  },
117
117
  // 格式
118
118
  format: {
119
119
  type: String,
120
- default: ''
120
+ default: '',
121
121
  },
122
122
  // 值
123
123
  value: {
124
124
  type: [String, Number],
125
- default: ''
125
+ default: '',
126
126
  },
127
127
  // 值
128
128
  modelValue: { type: [String, Number], default: '' },
129
129
  // 节假日
130
130
  holiday: {
131
131
  type: Object,
132
- default: () => ({})
132
+ default: () => ({}),
133
133
  },
134
134
  // 校验规则
135
135
  rules: {
136
136
  type: Array,
137
- default: () => []
137
+ default: () => [],
138
138
  },
139
139
  // 是否是示校验图标
140
140
  verify: {
141
141
  type: Boolean,
142
- default: false
143
- }
142
+ default: false,
143
+ },
144
144
  });
145
145
 
146
146
  // 内部数据
@@ -185,7 +185,7 @@
185
185
  calendar.unshift({
186
186
  date: `${last_y}-${numfill(last_m)}-${prevdays}`,
187
187
  day: prevdays,
188
- isLastMonth: 1
188
+ isLastMonth: 1,
189
189
  });
190
190
  prevdays = prevdays - 1;
191
191
  }
@@ -196,7 +196,7 @@
196
196
  day: _i,
197
197
  isToday: curr_y === y && curr_m === m && curr_d === i,
198
198
  isHoliday: props.holiday[`${y}-${numfill(m)}-${_i}`]?.name ? 1 : 0,
199
- holiday: props.holiday[`${y}-${numfill(m)}-${_i}`]?.name
199
+ holiday: props.holiday[`${y}-${numfill(m)}-${_i}`]?.name,
200
200
  });
201
201
  }
202
202
  for (let i = 1; calendar.length < 42; i++) {
@@ -204,14 +204,14 @@
204
204
  calendar.push({
205
205
  date: `${next_y}-${numfill(next_m)}-${_i}`,
206
206
  day: _i,
207
- isNextMonth: 1
207
+ isNextMonth: 1,
208
208
  });
209
209
  }
210
210
  return { days: calendar, y, m, d };
211
211
  }),
212
212
  value: computed(() => {
213
213
  return props.format ? idate(state.selected || props.value).format(props.format) : state.selected || props.value;
214
- })
214
+ }),
215
215
  });
216
216
  const { curr = {} }: any = toRefs(state);
217
217
 
@@ -15,6 +15,7 @@
15
15
 
16
16
  <!-- 文件预览 -->
17
17
  <img v-if="file.type === 'image'" class="r-ss" :src="getImageUrl(file)" alt="" />
18
+ <video v-else-if="file.type === 'video'" class="full r-ss" :src="getImageUrl(file)" controls muted></video>
18
19
  <template v-else-if="file.type === 'pdf'">
19
20
  <svg t="1705645350800" class="w-ss h-ss" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1913">
20
21
  <path
@@ -158,9 +159,9 @@
158
159
  </div>
159
160
 
160
161
  <!-- 上传按钮 -->
161
- <div v-if="showUploadButton" ui-flex="col cm">
162
+ <template v-if="showUploadButton">
162
163
  <slot name="btn">
163
- <label class="pr" ui-form="@a type:upload tips:hover" :style="`width: ${isNumber(width) ? width + 'em' : width}`">
164
+ <label class="pr flex-block" ui-form="@a type:upload tips:hover" :style="`width: ${isNumber(width) ? width + 'em' : width}`" v-bind="itemAttrs">
164
165
  <div class="w-full pr" :style="`box-sizing: content-box; padding-top: ${ratio}%`">
165
166
  <div ui-flex="row cm" :class="`pa ot-no ol-no full upload n-sl bg-fore b-solid bk-case b-xs r-sm ${uploadClass}`" :style="uploadStyle">
166
167
  <div v-if="tips" ui-form-tips>
@@ -179,7 +180,7 @@
179
180
  </div>
180
181
  </label>
181
182
  </slot>
182
- </div>
183
+ </template>
183
184
  </div>
184
185
  </template>
185
186
  <script setup lang="ts">
@@ -281,10 +282,43 @@
281
282
  return 'html';
282
283
  } else if (file.type.startsWith('image/') && file.type !== 'image/vnd.adobe.photoshop') {
283
284
  return 'image';
285
+ } else if (file.type.startsWith('video/')) {
286
+ return 'video';
284
287
  }
285
288
  return 'file';
286
289
  };
287
290
 
291
+ // 从URL判断文件类型
292
+ const getFileTypeFromUrl = (url: string): string => {
293
+ const extension = url.split('.').pop()?.toLowerCase() || '';
294
+
295
+ // 图片格式
296
+ if (['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'bmp', 'ico'].includes(extension)) {
297
+ return 'image';
298
+ }
299
+
300
+ // 视频格式
301
+ if (['mp4', 'avi', 'mov', 'wmv', 'flv', 'webm', 'mkv', 'm4v', '3gp'].includes(extension)) {
302
+ return 'video';
303
+ }
304
+
305
+ // 文档格式
306
+ if (['pdf'].includes(extension)) {
307
+ return 'pdf';
308
+ }
309
+ if (['doc', 'docx'].includes(extension)) {
310
+ return 'docx';
311
+ }
312
+ if (['xls', 'xlsx'].includes(extension)) {
313
+ return 'xlsx';
314
+ }
315
+ if (['ppt', 'pptx'].includes(extension)) {
316
+ return 'pptx';
317
+ }
318
+
319
+ return 'file';
320
+ };
321
+
288
322
  // 验证文件
289
323
  const validateFile = (file: File): string | null => {
290
324
  // 检查文件大小
@@ -483,7 +517,12 @@
483
517
 
484
518
  const formData = new FormData();
485
519
  formData.append('file', processedFile);
486
- const result = await props.upload(formData);
520
+
521
+ // 获取文件扩展名
522
+ const fileExtension = file.name.split('.').pop()?.toLowerCase() || '';
523
+
524
+ // 通过修改upload函数调用来传递扩展名
525
+ const result = await props.upload(formData, fileExtension);
487
526
 
488
527
  // 更新文件状态
489
528
  const fileIndex = state.files.findIndex((f) => f.path === uploadFile.path);
@@ -531,10 +570,11 @@
531
570
  if (newValue && Array.isArray(newValue)) {
532
571
  state.files = newValue.map((item) => {
533
572
  if (typeof item === 'string') {
534
- // 如果是字符串URL
573
+ // 如果是字符串URL,尝试从URL判断类型
574
+ const urlType = getFileTypeFromUrl(item);
535
575
  return {
536
576
  name: 'file',
537
- type: 'image',
577
+ type: urlType,
538
578
  path: item,
539
579
  status: 'end' as const,
540
580
  result: item,
@@ -551,10 +591,11 @@
551
591
  }
552
592
  });
553
593
  } else if (newValue && typeof newValue === 'string') {
594
+ const urlType = getFileTypeFromUrl(newValue);
554
595
  state.files = [
555
596
  {
556
597
  name: 'file',
557
- type: 'image',
598
+ type: urlType,
558
599
  path: newValue,
559
600
  status: 'end',
560
601
  result: newValue,
@@ -562,11 +603,13 @@
562
603
  ];
563
604
  } else if (newValue && typeof newValue === 'object') {
564
605
  const objValue = newValue as any;
606
+ const objPath = objValue.url || objValue.path || '';
607
+ const objType = objValue.type || (objPath ? getFileTypeFromUrl(objPath) : 'file');
565
608
  state.files = [
566
609
  {
567
610
  name: objValue.name || 'file',
568
- type: objValue.type || 'file',
569
- path: objValue.url || objValue.path || '',
611
+ type: objType,
612
+ path: objPath,
570
613
  status: 'end',
571
614
  result: newValue,
572
615
  },