large-model-component 1.0.1 → 1.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 (62) hide show
  1. package/README.md +1 -1
  2. package/dist/img/blue_tip.2d17b827.png +0 -0
  3. package/dist/large-model-component.common.js +8927 -141151
  4. package/dist/large-model-component.common.js.map +1 -1
  5. package/dist/large-model-component.css +1 -1
  6. package/dist/large-model-component.umd.js +8931 -141155
  7. package/dist/large-model-component.umd.js.map +1 -1
  8. package/dist/large-model-component.umd.min.js +6 -31
  9. package/dist/large-model-component.umd.min.js.map +1 -1
  10. package/docs/comps/README.md +1 -1
  11. package/package.json +10 -16
  12. package/packages/footer/footer.vue +346 -0
  13. package/packages/footer/index.js +2 -0
  14. package/packages/header/header.vue +516 -0
  15. package/packages/header/index.js +3 -0
  16. package/packages/index.js +7 -3
  17. package/packages/model/index.js +3 -0
  18. package/packages/{largeModel/index.vue → model/model.vue} +26 -65
  19. package/packages/upload/index.js +2 -0
  20. package/packages/upload/src/ajax.js +156 -0
  21. package/packages/upload/src/index.vue +329 -0
  22. package/packages/upload/src/upload-dragger.vue +70 -0
  23. package/packages/upload/src/upload-list.vue +94 -0
  24. package/packages/upload/src/upload.vue +274 -0
  25. package/src/App.vue +240 -2
  26. package/src/assets/blue_tip.png +0 -0
  27. package/src/assets/gray_tip.png +0 -0
  28. package/src/assets/logo.png +0 -0
  29. package/src/components/HelloWorld.vue +59 -0
  30. package/{packages/largeModel → src/components}/contentFold.vue +13 -0
  31. package/src/main.js +0 -5
  32. package/src/utils/request.js +3 -11
  33. package/tests/unit/example.spec.js +12 -0
  34. package/vue.config.js +3 -0
  35. package/.env +0 -2
  36. package/.env.development +0 -2
  37. package/.env.production +0 -2
  38. package/dist/css/107.3716bdaf.css +0 -1
  39. package/dist/css/644.3716bdaf.css +0 -1
  40. package/dist/css/848.e455a0b7.css +0 -1
  41. package/dist/img/ai-chart.167a7713.png +0 -0
  42. package/dist/img/scrol-bg.f446933a.png +0 -0
  43. package/dist/img/zhijing-model.6a81c5a7.png +0 -0
  44. package/dist/large-model-component.common.644.js +0 -73
  45. package/dist/large-model-component.common.644.js.map +0 -1
  46. package/dist/large-model-component.umd.107.js +0 -73
  47. package/dist/large-model-component.umd.107.js.map +0 -1
  48. package/dist/large-model-component.umd.min.848.js +0 -2
  49. package/dist/large-model-component.umd.min.848.js.map +0 -1
  50. package/packages/largeModel/index.js +0 -2
  51. package/src/assets/css/app.css +0 -3255
  52. package/src/assets/css/chunk-vendors.css +0 -2071
  53. package/src/assets/css/github-markdown.css +0 -985
  54. package/src/router/index.js +0 -20
  55. package/src/store/index.js +0 -26
  56. package/src/utils/auth.js +0 -48
  57. package/src/utils/index.js +0 -111
  58. package/src/utils/spceialistConfig.js +0 -44
  59. package/src/utils/tool.js +0 -4
  60. package/src/utils/validate.js +0 -20
  61. /package/{packages/largeModel → src/utils}/pubsub.js +0 -0
  62. /package/{packages/largeModel → src/utils}/wsconnecter.js +0 -0
@@ -161,20 +161,17 @@
161
161
 
162
162
  <div class="input-tools">
163
163
  <div class="left-tools">
164
- <el-tooltip content="上传附件 (支持.pdf/.doc/.docx/.txt/.pptx/.ppt/.xls/.xlsx/.pdf/.png/.jpg/.jpeg)"
165
- placement="top">
166
- <div class="upload-trigger">
167
- <i class="el-icon-paperclip tool-icon" :class="{ 'tool-icon-disabled': loading }"></i>
168
- <input
169
- type="file"
170
- id="fileInput"
171
- @change="handleFileChange"
172
- accept=".pdf,.png,.jpg,.jpeg"
173
- :disabled="loading"
174
- multiple
175
- />
176
- </div>
177
- </el-tooltip>
164
+ <div class="upload-trigger">
165
+ <i class="el-icon-paperclip tool-icon" :class="{ 'tool-icon-disabled': loading }"></i>
166
+ <input
167
+ type="file"
168
+ id="fileInput"
169
+ @change="handleFileChange"
170
+ accept=".pdf,.doc,.docx,.txt,.pptx,.ppt,.xls,.xlsx,.png,.jpg,.jpeg,.gif,.webp,image/*"
171
+ :disabled="loading"
172
+ multiple
173
+ />
174
+ </div>
178
175
  </div>
179
176
  <el-button
180
177
  type="primary"
@@ -206,15 +203,11 @@ import {
206
203
  conversationPage,
207
204
  deleteHistory,
208
205
  historyDetail,
209
- loginCas,
210
206
  quickAccess as getQuickAccessApi,
211
207
  suggestive,
212
208
  votePort
213
209
  } from "@/api/user";
214
- import ContentFold from './contentFold.vue';
215
-
216
- const TOKEN_KEY = 'Industrial-Access-Token';
217
- const CAS_LOGIN_URL = 'https://dticts.paas.casicloud.com/cas/login?service=';
210
+ import ContentFold from "@/components/contentFold";
218
211
 
219
212
  const ALLOWED_EXTENSIONS = ['pdf', 'doc', 'docx', 'txt', 'pptx', 'ppt', 'xls', 'xlsx', 'jpg', 'jpeg', 'png', 'gif', 'webp'];
220
213
  const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10M
@@ -225,7 +218,7 @@ const DEFAULT_ICONS = [
225
218
  require("@/assets/img/quick_finder_icon4.png")
226
219
  ];
227
220
  export default {
228
- name: 'LargeModel',
221
+ name: 'LLMAssistantDialog',
229
222
  components: {ContentFold},
230
223
  data() {
231
224
  return {
@@ -262,8 +255,7 @@ export default {
262
255
  return this.pageParams.hasMore && !this.isSearching;
263
256
  }
264
257
  },
265
- async mounted() {
266
- await this.handleCasCallback();
258
+ mounted() {
267
259
  this.$nextTick(() => {
268
260
  this.initScrollListener();
269
261
  });
@@ -276,44 +268,6 @@ export default {
276
268
  }
277
269
  },
278
270
  methods: {
279
- // 处理 CAS 回调:如果 URL 带有 ticket,则用它换取 token
280
- async handleCasCallback() {
281
- const urlParams = new URLSearchParams(window.location.search);
282
- const ticket = urlParams.get('ticket');
283
- if (!ticket) return;
284
-
285
- try {
286
- // serviceUrl 是去掉 ticket 参数后的当前页面地址
287
- const serviceUrl = window.location.origin + window.location.pathname;
288
- const res = await loginCas({ ticket, serviceUrl });
289
- const token = res.data?.data?.token;
290
- if (token) {
291
- localStorage.setItem(TOKEN_KEY, token);
292
- // ticket 换取 token 成功后自动打开弹窗
293
- this.openDialog();
294
- }
295
- } catch (e) {
296
- console.error('CAS 登录失败:', e);
297
- } finally {
298
- // 清除 URL 中的 ticket 参数,避免刷新重复请求
299
- const cleanUrl = window.location.origin + window.location.pathname;
300
- window.history.replaceState({}, '', cleanUrl);
301
- }
302
- },
303
-
304
- // 打开组件前先做 CAS 认证
305
- open() {
306
- window.location.href = CAS_LOGIN_URL + encodeURIComponent(location.href);
307
- },
308
-
309
- // CAS 认证完成后真正打开弹窗(由 handleCasCallback 成功后调用,或 token 已存在时直接调用)
310
- openDialog() {
311
- this.dialogVisible = true;
312
- this.$nextTick(() => {
313
- this.initData();
314
- this.initScrollListener();
315
- });
316
- },
317
271
  async stopGeneration() {
318
272
  if (this.abortController && !this.abortController.signal.aborted) {
319
273
  console.log('=== 触发停止生成 ===');
@@ -369,6 +323,13 @@ export default {
369
323
  container.removeEventListener('scroll', this.handleHistoryScroll);
370
324
  }
371
325
  },
326
+ open() {
327
+ this.dialogVisible = true;
328
+ this.$nextTick(() => {
329
+ this.initData();
330
+ this.initScrollListener();
331
+ });
332
+ },
372
333
  async initData() {
373
334
  await this.getQuickAccess();
374
335
  await this.changeFaq();
@@ -552,7 +513,7 @@ export default {
552
513
 
553
514
  const parseFileList = this.files
554
515
  .filter(f => f.type === 'document' && f.status === 'completed')
555
- .map(f => ({ fileId: f.id, fileName: f.name, markdown: f.parsedContent }));
516
+ .map(f => ({fileId: f.id, fileName: f.name, markdown: f.parsedContent}));
556
517
  const imageFiles = this.files
557
518
  .filter(f => f.type === 'image' && f.status === 'completed')
558
519
  .map(f => f.rawFile);
@@ -607,10 +568,10 @@ export default {
607
568
  const decoder = new TextDecoder('utf-8');
608
569
 
609
570
  while (true) {
610
- const { done, value } = await reader.read();
571
+ const {done, value} = await reader.read();
611
572
  if (done) break;
612
573
 
613
- const chunk = decoder.decode(value, { stream: true });
574
+ const chunk = decoder.decode(value, {stream: true});
614
575
  if (chunk) {
615
576
  this.appendAnswer(chunk);
616
577
  }
@@ -622,7 +583,7 @@ export default {
622
583
  } catch (error) {
623
584
  if (error.name === 'AbortError') {
624
585
  console.log('请求已中止');
625
- }else{
586
+ } else {
626
587
  console.error('请求失败:', error);
627
588
  this.loading = false;
628
589
  const lastItem = this.conversation.dialogue[this.conversation.dialogue.length - 1];
@@ -632,7 +593,7 @@ export default {
632
593
  lastItem.isStreaming = false;
633
594
  }
634
595
  }
635
- }finally {
596
+ } finally {
636
597
  this.loading = false;
637
598
  this.abortController = null;
638
599
  this.isCancelled = false;
@@ -0,0 +1,2 @@
1
+ import iipUpload from './src';
2
+ export default iipUpload;
@@ -0,0 +1,156 @@
1
+ function getError(action, option, xhr) {
2
+ let msg;
3
+ if (xhr.response) {
4
+ msg = `${xhr.response.error || xhr.response}`;
5
+ } else if (xhr.responseText) {
6
+ msg = `${xhr.responseText}`;
7
+ } else {
8
+ msg = `fail to post ${action} ${xhr.status}`;
9
+ }
10
+
11
+ const err = new Error(msg);
12
+ err.status = xhr.status;
13
+ err.method = 'post';
14
+ err.url = action;
15
+ return err;
16
+ }
17
+
18
+ function getBody(xhr) {
19
+ const text = xhr.responseText || xhr.response;
20
+ if (!text) {
21
+ return text;
22
+ }
23
+
24
+ try {
25
+ return JSON.parse(text);
26
+ } catch (e) {
27
+ return text;
28
+ }
29
+ }
30
+
31
+ export default function upload(option) {
32
+ if (typeof XMLHttpRequest === 'undefined') {
33
+ return;
34
+ }
35
+ const action = option.action; // 文件上传上传路径
36
+ const percentage = []; // 文件上传进度的数组,单项就是一个分片的进度
37
+ //将Blob转为上传时需要的FormData格式
38
+ const formDataList = option.chunkList.map((item, index) => {
39
+ const formData = new FormData();
40
+ // 额外加入组件外外面传入的data数据
41
+ const md5 = option.chunkHashList[index];
42
+ const chunkOption = {
43
+ // chunkSize: item.size, //当前分片大小
44
+ // chunkTotal: Math.ceil(option.file.size / option.chunkSize), // 所有切片数量
45
+ // chunkIndex: index, // 当前切片下标
46
+ // chunkHash: md5, // 当前切片hash
47
+ // fileName: option.file.name, // 文件名
48
+ // fileHash: option.fileHash, // 整个文件hash
49
+ // fileSize: option.file.size, // 总文件大小
50
+ partName: index, // 当前切片下标
51
+ fileName: option.file.name, //文件名
52
+ totalParts: Math.ceil(option.file.size / option.chunkSize), //分片总数
53
+ fileMd5: option.fileHash, //整个文件的hash
54
+ fileSize: option.file.size, //总文件大小
55
+ };
56
+ Object.keys(chunkOption).forEach((key) => {
57
+ formData.append(key, chunkOption[key]);
58
+ });
59
+ if (option.data) {
60
+ Object.keys(option.data).forEach((key) => {
61
+ formData.append(key, option.data[key]);
62
+ });
63
+ }
64
+ formData.append(option.filename, item); // 文件的Blob
65
+ return formData;
66
+ });
67
+
68
+ // 更新上传进度条的方法
69
+ const updataPercentage = (e) => {
70
+ let loaded = 0; // 当前已经上传文件的总大小
71
+ percentage.forEach((item) => {
72
+ loaded += item;
73
+ });
74
+ e.percent = (loaded / option.file.size) * 100;
75
+ option.onProgress(e);
76
+ };
77
+ const xhrList = []; // 所有的xhr请求
78
+ function sendRequest(formDataList, limit) {
79
+ let counter = 0; //上传成功的数量
80
+ let index = 0; //当前上传文件的下标
81
+ let isStop = false;
82
+ const len = formDataList.length;
83
+ const start = async () => {
84
+ if (isStop) {
85
+ return;
86
+ }
87
+ const item = formDataList.shift();
88
+ if (item) {
89
+ const chunkIndex = index++;
90
+ const xhr = new XMLHttpRequest();
91
+ // 分片上传失败回调
92
+ xhr.onerror = function error() {
93
+ isStop = true;
94
+ option.onerror(getError(action, option, xhr));
95
+ };
96
+ // 分片上传成功回调
97
+ xhr.onload = function onload() {
98
+ if (xhr.status < 200 || xhr.status >= 300) {
99
+ isStop = true;
100
+ option.onerror(getError(action, option, xhr));
101
+ }
102
+ // 最后一个上传完成
103
+ if (counter === len - 1) {
104
+ const result = xhrList.map((item) => getBody(item));
105
+ option.onSuccess(result);
106
+ } else {
107
+ counter++;
108
+ start();
109
+ }
110
+ };
111
+ // 上传中的时候更新进度条
112
+ if (xhr.upload) {
113
+ xhr.upload.onprogress = function progress(e) {
114
+ if (e.total > 0) {
115
+ e.percent = (e.loaded / e.total) * 100;
116
+ }
117
+ percentage[chunkIndex] = e.loaded;
118
+ updataPercentage(e);
119
+ };
120
+ }
121
+ if (action.slice(-1) == '/') {
122
+ xhr.open('post', action + chunkIndex, true);
123
+ } else {
124
+ xhr.open('post', action + '/' + chunkIndex, true);
125
+ }
126
+
127
+ if (option.withCredentials && 'withCredentials' in xhr) {
128
+ xhr.withCredentials = true;
129
+ }
130
+ const headers = option.headers || {};
131
+ // 添加请求头
132
+ for (const item in headers) {
133
+ if (Object.prototype.hasOwnProperty.call(headers, item) && headers[item] !== null) {
134
+ xhr.setRequestHeader(item, headers[item]);
135
+ }
136
+ }
137
+ // 文件开始上传,并把xhr对象存入xhrList中
138
+ xhr.send(item);
139
+ xhrList.push(xhr);
140
+ }
141
+ };
142
+ while (limit > 0) {
143
+ setTimeout(() => {
144
+ start();
145
+ }, Math.random() * 1000);
146
+ limit -= 1;
147
+ }
148
+ }
149
+
150
+ try {
151
+ sendRequest(formDataList, option.thread);
152
+ return xhrList;
153
+ } catch (error) {
154
+ option.onError(error);
155
+ }
156
+ }
@@ -0,0 +1,329 @@
1
+ <script>
2
+ import UploadList from './upload-list';
3
+ import Upload from './upload';
4
+
5
+ function noop() {}
6
+
7
+ export default {
8
+ name: 'iipUpload',
9
+
10
+ components: {
11
+ UploadList,
12
+ Upload,
13
+ },
14
+
15
+ provide() {
16
+ return {
17
+ uploader: this,
18
+ };
19
+ },
20
+
21
+ inject: {
22
+ elForm: {
23
+ default: '',
24
+ },
25
+ },
26
+
27
+ props: {
28
+ chunkSize: {
29
+ type: Number,
30
+ default: 10 * 1024 * 1024,
31
+ },
32
+ thread: {
33
+ type: Number,
34
+ default: 3,
35
+ },
36
+ action: {
37
+ type: String,
38
+ required: true,
39
+ },
40
+ headers: {
41
+ type: Object,
42
+ default() {
43
+ return {};
44
+ },
45
+ },
46
+ data: Object,
47
+ multiple: Boolean,
48
+ name: {
49
+ type: String,
50
+ default: 'file',
51
+ },
52
+ drag: Boolean,
53
+ dragger: Boolean,
54
+ withCredentials: Boolean,
55
+ showFileList: {
56
+ type: Boolean,
57
+ default: true,
58
+ },
59
+ accept: String,
60
+ type: {
61
+ type: String,
62
+ default: 'select',
63
+ },
64
+ beforeUpload: Function,
65
+ beforeRemove: Function,
66
+ onRemove: {
67
+ type: Function,
68
+ default: noop,
69
+ },
70
+ onChange: {
71
+ type: Function,
72
+ default: noop,
73
+ },
74
+ onPreview: {
75
+ type: Function,
76
+ },
77
+ onSuccess: {
78
+ type: Function,
79
+ default: noop,
80
+ },
81
+ onProgress: {
82
+ type: Function,
83
+ default: noop,
84
+ },
85
+ onError: {
86
+ type: Function,
87
+ default: noop,
88
+ },
89
+ fileList: {
90
+ type: Array,
91
+ default() {
92
+ return [];
93
+ },
94
+ },
95
+ autoUpload: {
96
+ type: Boolean,
97
+ default: true,
98
+ },
99
+ listType: {
100
+ type: String,
101
+ default: 'text', // text,picture,picture-card
102
+ },
103
+ httpRequest: Function,
104
+ disabled: Boolean,
105
+ limit: Number,
106
+ onExceed: {
107
+ type: Function,
108
+ default: noop,
109
+ },
110
+ },
111
+
112
+ data() {
113
+ return {
114
+ uploadFiles: [],
115
+ dragOver: false,
116
+ draging: false,
117
+ tempIndex: 1,
118
+ };
119
+ },
120
+
121
+ computed: {
122
+ uploadDisabled() {
123
+ return this.disabled || (this.elForm || {}).disabled;
124
+ },
125
+ },
126
+
127
+ watch: {
128
+ listType(type) {
129
+ if (type === 'picture-card' || type === 'picture') {
130
+ this.uploadFiles = this.uploadFiles.map((file) => {
131
+ if (!file.url && file.raw) {
132
+ try {
133
+ file.url = URL.createObjectURL(file.raw);
134
+ } catch (err) {
135
+ console.error('[Element Error][Upload]', err);
136
+ }
137
+ }
138
+ return file;
139
+ });
140
+ }
141
+ },
142
+ fileList: {
143
+ immediate: true,
144
+ handler(fileList) {
145
+ this.uploadFiles = fileList.map((item) => {
146
+ item.uid = item.uid || Date.now() + this.tempIndex++;
147
+ item.status = item.status || 'success';
148
+ return item;
149
+ });
150
+ },
151
+ },
152
+ },
153
+
154
+ methods: {
155
+ handleStart(rawFile) {
156
+ rawFile.uid = Date.now() + this.tempIndex++;
157
+ let file = {
158
+ status: 'ready',
159
+ name: rawFile.name,
160
+ size: rawFile.size,
161
+ percentage: 0,
162
+ uid: rawFile.uid,
163
+ raw: rawFile,
164
+ };
165
+
166
+ if (this.listType === 'picture-card' || this.listType === 'picture') {
167
+ try {
168
+ file.url = URL.createObjectURL(rawFile);
169
+ } catch (err) {
170
+ console.error('[Element Error][Upload]', err);
171
+ return;
172
+ }
173
+ }
174
+
175
+ this.uploadFiles.push(file);
176
+ this.onChange(file, this.uploadFiles);
177
+ },
178
+ handleProgress(ev, rawFile) {
179
+ const file = this.getFile(rawFile);
180
+ this.onProgress(ev, file, this.uploadFiles);
181
+ file.status = 'uploading';
182
+ file.percentage = ev.percent || 0;
183
+ },
184
+ handleSuccess(res, rawFile) {
185
+ const file = this.getFile(rawFile);
186
+
187
+ if (file) {
188
+ file.status = 'success';
189
+ file.response = res;
190
+
191
+ this.onSuccess(res, file, this.uploadFiles);
192
+ this.onChange(file, this.uploadFiles);
193
+ }
194
+ },
195
+ handleError(err, rawFile) {
196
+ const file = this.getFile(rawFile);
197
+ const fileList = this.uploadFiles;
198
+
199
+ file.status = 'fail';
200
+
201
+ fileList.splice(fileList.indexOf(file), 1);
202
+
203
+ this.onError(err, file, this.uploadFiles);
204
+ this.onChange(file, this.uploadFiles);
205
+ },
206
+ handleRemove(file, raw) {
207
+ if (raw) {
208
+ file = this.getFile(raw);
209
+ }
210
+ let doRemove = () => {
211
+ this.abort(file);
212
+ let fileList = this.uploadFiles;
213
+ fileList.splice(fileList.indexOf(file), 1);
214
+ this.onRemove(file, fileList);
215
+ };
216
+
217
+ if (!this.beforeRemove) {
218
+ doRemove();
219
+ } else if (typeof this.beforeRemove === 'function') {
220
+ const before = this.beforeRemove(file, this.uploadFiles);
221
+ if (before && before.then) {
222
+ before.then(() => {
223
+ doRemove();
224
+ }, noop);
225
+ } else if (before !== false) {
226
+ doRemove();
227
+ }
228
+ }
229
+ },
230
+ getFile(rawFile) {
231
+ let fileList = this.uploadFiles;
232
+ let target;
233
+ fileList.every((item) => {
234
+ target = rawFile.uid === item.uid ? item : null;
235
+ return !target;
236
+ });
237
+ return target;
238
+ },
239
+ abort(file) {
240
+ this.$refs['upload-inner'].abort(file);
241
+ },
242
+ clearFiles() {
243
+ this.uploadFiles = [];
244
+ },
245
+ submit() {
246
+ this.uploadFiles
247
+ .filter((file) => file.status === 'ready')
248
+ .forEach((file) => {
249
+ this.$refs['upload-inner'].upload(file.raw);
250
+ });
251
+ },
252
+ },
253
+
254
+ beforeDestroy() {
255
+ this.uploadFiles.forEach((file) => {
256
+ if (file.url && file.url.indexOf('blob:') === 0) {
257
+ URL.revokeObjectURL(file.url);
258
+ }
259
+ });
260
+ },
261
+
262
+ render(h) {
263
+ let uploadList;
264
+
265
+ if (this.showFileList) {
266
+ uploadList = (
267
+ <UploadList
268
+ disabled={this.uploadDisabled}
269
+ listType={this.listType}
270
+ files={this.uploadFiles}
271
+ on-remove={this.handleRemove}
272
+ handlePreview={this.onPreview}
273
+ >
274
+ {(props) => {
275
+ if (this.$scopedSlots.file) {
276
+ return this.$scopedSlots.file({
277
+ file: props.file,
278
+ });
279
+ }
280
+ }}
281
+ </UploadList>
282
+ );
283
+ }
284
+
285
+ const uploadData = {
286
+ props: {
287
+ type: this.type,
288
+ drag: this.drag,
289
+ action: this.action,
290
+ multiple: this.multiple,
291
+ 'before-upload': this.beforeUpload,
292
+ 'with-credentials': this.withCredentials,
293
+ headers: this.headers,
294
+ name: this.name,
295
+ data: this.data,
296
+ accept: this.accept,
297
+ fileList: this.uploadFiles,
298
+ autoUpload: this.autoUpload,
299
+ listType: this.listType,
300
+ disabled: this.uploadDisabled,
301
+ limit: this.limit,
302
+ chunkSize: this.chunkSize,
303
+ thread: this.thread,
304
+ 'on-exceed': this.onExceed,
305
+ 'on-start': this.handleStart,
306
+ 'on-progress': this.handleProgress,
307
+ 'on-success': this.handleSuccess,
308
+ 'on-error': this.handleError,
309
+ 'on-preview': this.onPreview,
310
+ 'on-remove': this.handleRemove,
311
+ 'http-request': this.httpRequest,
312
+ },
313
+ ref: 'upload-inner',
314
+ };
315
+
316
+ const trigger = this.$slots.trigger || this.$slots.default;
317
+ const uploadComponent = <upload {...uploadData}>{trigger}</upload>;
318
+
319
+ return (
320
+ <div>
321
+ {this.listType === 'picture-card' ? uploadList : ''}
322
+ {this.$slots.trigger ? [uploadComponent, this.$slots.default] : uploadComponent}
323
+ {this.$slots.tip}
324
+ {this.listType !== 'picture-card' ? uploadList : ''}
325
+ </div>
326
+ );
327
+ },
328
+ };
329
+ </script>