stellar-ui-plus 1.25.7 → 1.25.8
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.
- package/components/ste-app-update/method.ts +189 -20
- package/components/ste-app-update/ste-app-update.vue +160 -15
- package/components/ste-dropdown-menu/README.md +186 -1
- package/components/ste-dropdown-menu/ste-dropdown-menu.scss +8 -1
- package/components/ste-popup/ATTRIBUTES.md +3 -3
- package/components/ste-popup/ste-popup.easycom.json +138 -138
- package/components/ste-popup/ste-popup.vue +19 -23
- package/components/ste-radio/ATTRIBUTES.md +2 -2
- package/components/ste-radio/ste-radio.easycom.json +4 -4
- package/components/ste-select/README.md +0 -6
- package/components/ste-select-order/README.md +61 -0
- package/components/ste-select-order/config.json +5 -0
- package/components/ste-select-order/props.ts +30 -0
- package/components/ste-select-order/ste-select-order.easycom.json +73 -0
- package/components/ste-select-order/ste-select-order.vue +276 -0
- package/components/ste-table/ste-table.vue +7 -37
- package/package.json +2 -3
- package/utils/System.ts +1 -1
|
@@ -39,13 +39,9 @@ interface DownloadOptions {
|
|
|
39
39
|
onProgressUpdate?: (res: UniApp.OnProgressDownloadResult) => void;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
export function download(
|
|
43
|
-
data: ClientData,
|
|
44
|
-
options: DownloadOptions
|
|
45
|
-
): UniApp.DownloadTask {
|
|
42
|
+
export function download(data: ClientData, options: DownloadOptions): any {
|
|
46
43
|
const { success, error, downloadSuccess, onProgressUpdate } = options;
|
|
47
44
|
|
|
48
|
-
// 参数验证
|
|
49
45
|
if (!data.updateFile) {
|
|
50
46
|
const errorMsg = '更新文件地址不能为空';
|
|
51
47
|
uni.showToast({ title: errorMsg, icon: 'none' });
|
|
@@ -54,15 +50,110 @@ export function download(
|
|
|
54
50
|
}
|
|
55
51
|
|
|
56
52
|
const package_type = data.package_type;
|
|
53
|
+
|
|
54
|
+
// #ifdef APP-PLUS
|
|
57
55
|
let timeout: ReturnType<typeof setTimeout>;
|
|
58
56
|
|
|
57
|
+
const task = plus.downloader.createDownload(
|
|
58
|
+
data.updateFile,
|
|
59
|
+
{
|
|
60
|
+
filename: '_downloads/stellar_update/',
|
|
61
|
+
},
|
|
62
|
+
(download, status) => {
|
|
63
|
+
clearTimeout(timeout);
|
|
64
|
+
|
|
65
|
+
if (status === 200) {
|
|
66
|
+
if (!download.filename) {
|
|
67
|
+
const errorMsg = '下载文件路径为空';
|
|
68
|
+
uni.showToast({ title: errorMsg, icon: 'none' });
|
|
69
|
+
error?.(new Error(errorMsg));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
downloadSuccess?.(download.filename);
|
|
74
|
+
|
|
75
|
+
plus.runtime.install(
|
|
76
|
+
download.filename,
|
|
77
|
+
{ force: true },
|
|
78
|
+
() => {
|
|
79
|
+
if (package_type == 1) {
|
|
80
|
+
uni.showModal({
|
|
81
|
+
title: '提示',
|
|
82
|
+
content: '升级成功,请重新启动!',
|
|
83
|
+
confirmText: '确定',
|
|
84
|
+
showCancel: false,
|
|
85
|
+
success: () => {
|
|
86
|
+
success?.();
|
|
87
|
+
plus.runtime.restart();
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
} else {
|
|
91
|
+
success?.();
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
e => {
|
|
95
|
+
const errorMsg = e.message || '安装失败';
|
|
96
|
+
uni.showModal({
|
|
97
|
+
title: '提示',
|
|
98
|
+
content: errorMsg,
|
|
99
|
+
showCancel: false,
|
|
100
|
+
success: () => {
|
|
101
|
+
error?.(e);
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
} else {
|
|
107
|
+
const errorMsg = `下载失败,状态码:${status}`;
|
|
108
|
+
uni.showToast({ title: errorMsg, icon: 'none' });
|
|
109
|
+
error?.(new Error(errorMsg));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
task.addEventListener('statechanged', (download: any) => {
|
|
115
|
+
if (download.state === 3 && download.totalSize > 0) {
|
|
116
|
+
const progress = Math.round((download.downloadedSize / download.totalSize) * 100);
|
|
117
|
+
onProgressUpdate?.({
|
|
118
|
+
progress,
|
|
119
|
+
totalBytesWritten: download.downloadedSize,
|
|
120
|
+
totalBytesExpectedToWrite: download.totalSize,
|
|
121
|
+
} as UniApp.OnProgressDownloadResult);
|
|
122
|
+
|
|
123
|
+
clearTimeout(timeout);
|
|
124
|
+
timeout = setTimeout(() => {
|
|
125
|
+
task.abort();
|
|
126
|
+
const errorMsg = '下载超时,请检查网络连接';
|
|
127
|
+
uni.showToast({ title: errorMsg, icon: 'none' });
|
|
128
|
+
error?.(new Error(errorMsg));
|
|
129
|
+
}, 300000);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (download.state === 4 || download.state === -1) {
|
|
133
|
+
clearTimeout(timeout);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
timeout = setTimeout(() => {
|
|
138
|
+
task.abort();
|
|
139
|
+
const errorMsg = '下载超时,请检查网络连接';
|
|
140
|
+
uni.showToast({ title: errorMsg, icon: 'none' });
|
|
141
|
+
error?.(new Error(errorMsg));
|
|
142
|
+
}, 300000);
|
|
143
|
+
|
|
144
|
+
task.start();
|
|
145
|
+
return task;
|
|
146
|
+
// #endif
|
|
147
|
+
|
|
148
|
+
// #ifndef APP-PLUS
|
|
149
|
+
let timeoutFallback: ReturnType<typeof setTimeout>;
|
|
150
|
+
|
|
59
151
|
const downloadTask = uni.downloadFile({
|
|
60
152
|
url: data.updateFile,
|
|
61
153
|
success: res => {
|
|
62
|
-
clearTimeout(
|
|
154
|
+
clearTimeout(timeoutFallback);
|
|
63
155
|
|
|
64
156
|
if (res.statusCode === 200) {
|
|
65
|
-
// 文件完整性检查
|
|
66
157
|
if (!res.tempFilePath) {
|
|
67
158
|
const errorMsg = '下载文件路径为空';
|
|
68
159
|
uni.showToast({ title: errorMsg, icon: 'none' });
|
|
@@ -88,7 +179,6 @@ export function download(
|
|
|
88
179
|
},
|
|
89
180
|
});
|
|
90
181
|
} else {
|
|
91
|
-
// 整包升级时,执行到此处更新并未完成,只是弹出了安装提示,无法获悉用户是否安装了更新包,若是在此处清除资源,会导致升级包被删除,后续流程无法继续执行
|
|
92
182
|
success?.();
|
|
93
183
|
}
|
|
94
184
|
},
|
|
@@ -110,33 +200,29 @@ export function download(
|
|
|
110
200
|
error?.(new Error(errorMsg));
|
|
111
201
|
}
|
|
112
202
|
},
|
|
113
|
-
fail:
|
|
114
|
-
clearTimeout(
|
|
203
|
+
fail: err => {
|
|
204
|
+
clearTimeout(timeoutFallback);
|
|
115
205
|
const errorMsg = `网络请求失败:${err.errMsg || '未知错误'}`;
|
|
116
206
|
uni.showToast({ title: errorMsg, icon: 'none' });
|
|
117
207
|
error?.(err);
|
|
118
|
-
}
|
|
208
|
+
},
|
|
119
209
|
});
|
|
120
210
|
|
|
121
|
-
// 下载进度监控
|
|
122
211
|
downloadTask.onProgressUpdate(res => {
|
|
123
|
-
// 添加进度验证
|
|
124
212
|
if (res.progress >= 0 && res.progress <= 100) {
|
|
125
213
|
onProgressUpdate?.(res);
|
|
126
214
|
}
|
|
127
215
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
timeout = setTimeout(() => {
|
|
216
|
+
clearTimeout(timeoutFallback);
|
|
217
|
+
timeoutFallback = setTimeout(() => {
|
|
131
218
|
downloadTask.abort();
|
|
132
219
|
const errorMsg = '下载超时,请检查网络连接';
|
|
133
220
|
uni.showToast({ title: errorMsg, icon: 'none' });
|
|
134
221
|
error?.(new Error(errorMsg));
|
|
135
|
-
}, 300000);
|
|
222
|
+
}, 300000);
|
|
136
223
|
});
|
|
137
224
|
|
|
138
|
-
|
|
139
|
-
timeout = setTimeout(() => {
|
|
225
|
+
timeoutFallback = setTimeout(() => {
|
|
140
226
|
downloadTask.abort();
|
|
141
227
|
const errorMsg = '下载超时,请检查网络连接';
|
|
142
228
|
uni.showToast({ title: errorMsg, icon: 'none' });
|
|
@@ -144,6 +230,7 @@ export function download(
|
|
|
144
230
|
}, 300000);
|
|
145
231
|
|
|
146
232
|
return downloadTask;
|
|
233
|
+
// #endif
|
|
147
234
|
}
|
|
148
235
|
|
|
149
236
|
// 获取设备唯一标识
|
|
@@ -187,4 +274,86 @@ export const getVersion = (appVersion: string): Promise<string> => {
|
|
|
187
274
|
});
|
|
188
275
|
}
|
|
189
276
|
});
|
|
190
|
-
};
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
export interface DownloadState {
|
|
280
|
+
versionCode: string;
|
|
281
|
+
updateFile: string;
|
|
282
|
+
startTime: number;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const DOWNLOAD_STATE_KEY = 'app_update_download_state';
|
|
286
|
+
export const DOWNLOAD_TIMEOUT = 30 * 60 * 1000;
|
|
287
|
+
|
|
288
|
+
export const saveDownloadState = (state: DownloadState): void => {
|
|
289
|
+
try {
|
|
290
|
+
uni.setStorageSync(DOWNLOAD_STATE_KEY, JSON.stringify(state));
|
|
291
|
+
} catch (e) {
|
|
292
|
+
console.warn('保存下载状态失败:', e);
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
export const getDownloadState = (): DownloadState | null => {
|
|
297
|
+
try {
|
|
298
|
+
const stored = uni.getStorageSync(DOWNLOAD_STATE_KEY);
|
|
299
|
+
if (stored) {
|
|
300
|
+
return JSON.parse(stored);
|
|
301
|
+
}
|
|
302
|
+
} catch (e) {
|
|
303
|
+
console.warn('读取下载状态失败:', e);
|
|
304
|
+
}
|
|
305
|
+
return null;
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
export const clearDownloadState = (): void => {
|
|
309
|
+
try {
|
|
310
|
+
uni.removeStorageSync(DOWNLOAD_STATE_KEY);
|
|
311
|
+
} catch (e) {
|
|
312
|
+
console.warn('清除下载状态失败:', e);
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
export const isDownloadStateExpired = (state: DownloadState): boolean => {
|
|
317
|
+
return Date.now() - state.startTime > DOWNLOAD_TIMEOUT;
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
export interface ExistingDownloadTask {
|
|
321
|
+
task: any;
|
|
322
|
+
state: number;
|
|
323
|
+
filename: string;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export const findExistingDownloadTask = (url: string): Promise<ExistingDownloadTask | null> => {
|
|
327
|
+
return new Promise(resolve => {
|
|
328
|
+
// #ifdef APP-PLUS
|
|
329
|
+
plus.downloader.enumerate((tasks: any[]) => {
|
|
330
|
+
if (!tasks || !tasks.length) {
|
|
331
|
+
resolve(null);
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
for (let i = tasks.length - 1; i >= 0; i--) {
|
|
335
|
+
const task = tasks[i];
|
|
336
|
+
if (task.url === url) {
|
|
337
|
+
if (task.state === 0 || task.state === 1 || task.state === 2 || task.state === 3 || task.state === 4) {
|
|
338
|
+
resolve({ task, state: task.state, filename: task.filename || '' });
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
if (task.state === -1) {
|
|
342
|
+
try {
|
|
343
|
+
task.abort();
|
|
344
|
+
} catch (_) {}
|
|
345
|
+
}
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
// #endif
|
|
350
|
+
resolve(null);
|
|
351
|
+
// #ifdef APP-PLUS
|
|
352
|
+
});
|
|
353
|
+
// #endif
|
|
354
|
+
|
|
355
|
+
// #ifndef APP-PLUS
|
|
356
|
+
resolve(null);
|
|
357
|
+
// #endif
|
|
358
|
+
});
|
|
359
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { ref, reactive, onUnmounted } from 'vue';
|
|
3
3
|
import propsData from './props';
|
|
4
|
-
import { type ClientData, type ResponseData, download as downloadMethod, getAppId, getDeviceId, getPlatform, getVersion } from './method';
|
|
4
|
+
import { type ClientData, type ResponseData, download as downloadMethod, getAppId, getDeviceId, getPlatform, getVersion, saveDownloadState, getDownloadState, clearDownloadState, isDownloadStateExpired, findExistingDownloadTask } from './method';
|
|
5
5
|
|
|
6
6
|
// 类型定义
|
|
7
7
|
interface AppUpdateData extends ClientData {
|
|
@@ -34,7 +34,10 @@ const tempFilePath = ref('');
|
|
|
34
34
|
|
|
35
35
|
// 资源管理
|
|
36
36
|
let timeoutTimer: ReturnType<typeof setTimeout> | null = null;
|
|
37
|
-
let downloadTask:
|
|
37
|
+
let downloadTask: any = null;
|
|
38
|
+
let nativeDownloadTask: any = null;
|
|
39
|
+
let nativeDownloadListener: ((download: any) => void) | null = null;
|
|
40
|
+
let progressPollTimer: ReturnType<typeof setInterval> | null = null;
|
|
38
41
|
|
|
39
42
|
// 跳过版本相关
|
|
40
43
|
const skippedVersions = ref<string[]>([]);
|
|
@@ -103,12 +106,29 @@ const skipVersion = () => {
|
|
|
103
106
|
};
|
|
104
107
|
|
|
105
108
|
// 清理函数
|
|
109
|
+
const stopProgressPolling = () => {
|
|
110
|
+
if (progressPollTimer) {
|
|
111
|
+
clearInterval(progressPollTimer);
|
|
112
|
+
progressPollTimer = null;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
106
116
|
const cleanup = () => {
|
|
107
117
|
if (timeoutTimer) {
|
|
108
118
|
clearTimeout(timeoutTimer);
|
|
109
119
|
timeoutTimer = null;
|
|
110
120
|
}
|
|
121
|
+
stopProgressPolling();
|
|
122
|
+
// #ifdef APP-PLUS
|
|
123
|
+
if (nativeDownloadTask && nativeDownloadListener) {
|
|
124
|
+
try {
|
|
125
|
+
nativeDownloadTask.removeEventListener('statechanged', nativeDownloadListener);
|
|
126
|
+
} catch (_) { }
|
|
127
|
+
}
|
|
128
|
+
// #endif
|
|
111
129
|
downloadTask = null;
|
|
130
|
+
nativeDownloadTask = null;
|
|
131
|
+
nativeDownloadListener = null;
|
|
112
132
|
};
|
|
113
133
|
|
|
114
134
|
// 组件卸载时清理资源
|
|
@@ -116,7 +136,7 @@ onUnmounted(() => {
|
|
|
116
136
|
cleanup();
|
|
117
137
|
});
|
|
118
138
|
|
|
119
|
-
const getData = (callback?: (resVersion: { name: string; code: string; updateFile: string }, version: string) => void) => {
|
|
139
|
+
const getData = async (callback?: (resVersion: { name: string; code: string; updateFile: string }, version: string) => void) => {
|
|
120
140
|
// 参数验证
|
|
121
141
|
if (!props.apiUrl) {
|
|
122
142
|
console.error('API地址不能为空');
|
|
@@ -130,7 +150,7 @@ const getData = (callback?: (resVersion: { name: string; code: string; updateFil
|
|
|
130
150
|
header: {
|
|
131
151
|
Authorization: `Basic ${btoa(props.clientId + ':' + props.clientSecret)}`,
|
|
132
152
|
},
|
|
133
|
-
success: (res: any) => {
|
|
153
|
+
success: async (res: any) => {
|
|
134
154
|
try {
|
|
135
155
|
const _data: {
|
|
136
156
|
code: number;
|
|
@@ -187,6 +207,36 @@ const getData = (callback?: (resVersion: { name: string; code: string; updateFil
|
|
|
187
207
|
}
|
|
188
208
|
|
|
189
209
|
if (data.updateFile && data.code !== version.value) {
|
|
210
|
+
const downloadState = getDownloadState();
|
|
211
|
+
const hasValidDownloadState = downloadState
|
|
212
|
+
&& downloadState.versionCode === data.code
|
|
213
|
+
&& downloadState.updateFile === data.updateFile
|
|
214
|
+
&& !isDownloadStateExpired(downloadState);
|
|
215
|
+
|
|
216
|
+
if (hasValidDownloadState) {
|
|
217
|
+
const existing = await findExistingDownloadTask(data.updateFile);
|
|
218
|
+
|
|
219
|
+
if (existing) {
|
|
220
|
+
open.value = true;
|
|
221
|
+
emits('update');
|
|
222
|
+
if (existing.state === 0 || existing.state === 1 || existing.state === 2 || existing.state === 3) {
|
|
223
|
+
updateBtn.value = false;
|
|
224
|
+
resumeDownloadProgress(existing.task);
|
|
225
|
+
} else if (existing.state === 4) {
|
|
226
|
+
updateBtn.value = false;
|
|
227
|
+
tempFilePath.value = existing.filename;
|
|
228
|
+
if (data.package_type === 1 && existing.filename) {
|
|
229
|
+
installWgt(existing.filename);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (downloadState) {
|
|
237
|
+
clearDownloadState();
|
|
238
|
+
}
|
|
239
|
+
|
|
190
240
|
open.value = true;
|
|
191
241
|
emits('update');
|
|
192
242
|
if (data.isForce) confirm();
|
|
@@ -279,11 +329,11 @@ const start = async (callback?: (resVersion: { name: string; code: string; updat
|
|
|
279
329
|
|
|
280
330
|
const v = await getVersion(props.appVersion);
|
|
281
331
|
if (v) version.value = v;
|
|
282
|
-
|
|
332
|
+
// #ifdef APP-PLUS
|
|
283
333
|
// 兜底检查:如果配置了 fallbackApiUrl,先调兜底接口
|
|
284
334
|
const hit = await checkFallback();
|
|
285
335
|
if (hit) return; // 命中兜底,不继续正常流程
|
|
286
|
-
|
|
336
|
+
// #endif
|
|
287
337
|
// 正常更新流程
|
|
288
338
|
getData(callback);
|
|
289
339
|
};
|
|
@@ -297,16 +347,102 @@ const onProgressUpdate = (res: UniApp.OnProgressDownloadResult) => {
|
|
|
297
347
|
}
|
|
298
348
|
};
|
|
299
349
|
|
|
300
|
-
const
|
|
301
|
-
//
|
|
350
|
+
const resumeDownloadProgress = (task: any) => {
|
|
351
|
+
// #ifdef APP-PLUS
|
|
352
|
+
if (nativeDownloadTask && nativeDownloadListener) {
|
|
353
|
+
nativeDownloadTask.removeEventListener('statechanged', nativeDownloadListener);
|
|
354
|
+
}
|
|
355
|
+
stopProgressPolling();
|
|
356
|
+
|
|
357
|
+
nativeDownloadTask = task;
|
|
358
|
+
|
|
359
|
+
const updateProgress = () => {
|
|
360
|
+
if (task.downloadedSize !== undefined && task.totalSize > 0) {
|
|
361
|
+
percent.value = Math.round((task.downloadedSize / task.totalSize) * 100);
|
|
362
|
+
downloadedSize.value = (task.downloadedSize / Math.pow(1024, 2)).toFixed(2);
|
|
363
|
+
packageFileSize.value = (task.totalSize / Math.pow(1024, 2)).toFixed(2);
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
updateProgress();
|
|
367
|
+
|
|
368
|
+
nativeDownloadListener = (download: any) => {
|
|
369
|
+
if (download.state === 4) {
|
|
370
|
+
stopProgressPolling();
|
|
371
|
+
percent.value = 100;
|
|
372
|
+
downloadedSize.value = packageFileSize.value;
|
|
373
|
+
tempFilePath.value = download.filename;
|
|
374
|
+
if (open.value && data.package_type === 1 && download.filename) {
|
|
375
|
+
installWgt(download.filename);
|
|
376
|
+
}
|
|
377
|
+
} else if (download.state === -1) {
|
|
378
|
+
stopProgressPolling();
|
|
379
|
+
updateBtn.value = true;
|
|
380
|
+
clearDownloadState();
|
|
381
|
+
cleanup();
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
task.addEventListener('statechanged', nativeDownloadListener);
|
|
386
|
+
|
|
387
|
+
if (task.state === 3) {
|
|
388
|
+
progressPollTimer = setInterval(updateProgress, 500);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
if (task.state === 0) {
|
|
392
|
+
task.start();
|
|
393
|
+
}
|
|
394
|
+
// #endif
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
const installWgt = (filePath: string) => {
|
|
398
|
+
// #ifdef APP-PLUS
|
|
399
|
+
plus.runtime.install(
|
|
400
|
+
filePath,
|
|
401
|
+
{ force: true },
|
|
402
|
+
() => {
|
|
403
|
+
uni.showModal({
|
|
404
|
+
title: '提示',
|
|
405
|
+
content: '升级成功,请重新启动!',
|
|
406
|
+
confirmText: '确定',
|
|
407
|
+
showCancel: false,
|
|
408
|
+
success: () => {
|
|
409
|
+
clearDownloadState();
|
|
410
|
+
plus.runtime.restart();
|
|
411
|
+
},
|
|
412
|
+
});
|
|
413
|
+
},
|
|
414
|
+
e => {
|
|
415
|
+
uni.showModal({
|
|
416
|
+
title: '安装失败',
|
|
417
|
+
content: e.message || '安装过程中出现错误',
|
|
418
|
+
showCancel: false,
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
);
|
|
422
|
+
// #endif
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
const confirm = async () => {
|
|
302
426
|
cleanup();
|
|
303
427
|
|
|
304
|
-
// 参数验证
|
|
305
428
|
if (!data.updateFile) {
|
|
306
429
|
uni.showToast({ title: '更新文件地址不能为空', icon: 'none' });
|
|
307
430
|
return;
|
|
308
431
|
}
|
|
309
432
|
|
|
433
|
+
// #ifdef APP-PLUS
|
|
434
|
+
const stale = await findExistingDownloadTask(data.updateFile);
|
|
435
|
+
if (stale) {
|
|
436
|
+
try { stale.task.abort(); } catch (_) { }
|
|
437
|
+
}
|
|
438
|
+
// #endif
|
|
439
|
+
|
|
440
|
+
saveDownloadState({
|
|
441
|
+
versionCode: data.code,
|
|
442
|
+
updateFile: data.updateFile,
|
|
443
|
+
startTime: Date.now(),
|
|
444
|
+
});
|
|
445
|
+
|
|
310
446
|
if (data.package_type == 0) {
|
|
311
447
|
if (data.updateFile.includes('.apk')) {
|
|
312
448
|
updateBtn.value = false;
|
|
@@ -315,9 +451,11 @@ const confirm = () => {
|
|
|
315
451
|
downloadSuccess: path => (tempFilePath.value = path),
|
|
316
452
|
error: () => {
|
|
317
453
|
updateBtn.value = true;
|
|
454
|
+
clearDownloadState();
|
|
318
455
|
cleanup();
|
|
319
456
|
},
|
|
320
457
|
success: () => {
|
|
458
|
+
clearDownloadState();
|
|
321
459
|
cleanup();
|
|
322
460
|
},
|
|
323
461
|
});
|
|
@@ -334,9 +472,11 @@ const confirm = () => {
|
|
|
334
472
|
downloadSuccess: path => (tempFilePath.value = path),
|
|
335
473
|
error: () => {
|
|
336
474
|
updateBtn.value = true;
|
|
475
|
+
clearDownloadState();
|
|
337
476
|
cleanup();
|
|
338
477
|
},
|
|
339
478
|
success: () => {
|
|
479
|
+
clearDownloadState();
|
|
340
480
|
cleanup();
|
|
341
481
|
},
|
|
342
482
|
});
|
|
@@ -359,6 +499,7 @@ const install = () => {
|
|
|
359
499
|
tempFilePath.value,
|
|
360
500
|
{ force: true },
|
|
361
501
|
() => {
|
|
502
|
+
clearDownloadState();
|
|
362
503
|
if (data.package_type == 1) {
|
|
363
504
|
uni.showModal({
|
|
364
505
|
title: '提示',
|
|
@@ -388,10 +529,10 @@ const cancelDownload = () => {
|
|
|
388
529
|
content: '确定要取消下载吗?',
|
|
389
530
|
success: res => {
|
|
390
531
|
if (res.confirm) {
|
|
391
|
-
// 取消下载时才 abort 下载任务
|
|
392
532
|
if (downloadTask) {
|
|
393
|
-
downloadTask.abort();
|
|
533
|
+
try { downloadTask.abort(); } catch (_) { }
|
|
394
534
|
}
|
|
535
|
+
clearDownloadState();
|
|
395
536
|
cleanup();
|
|
396
537
|
updateBtn.value = true;
|
|
397
538
|
percent.value = 0;
|
|
@@ -432,7 +573,8 @@ defineExpose({
|
|
|
432
573
|
<view class="update-footer">
|
|
433
574
|
<view class="update-progress-box" v-if="!updateBtn">
|
|
434
575
|
<view class="progress-container">
|
|
435
|
-
<progress class="update-progress" border-radius="35" :percent="percent" activeColor="#3DA7FF"
|
|
576
|
+
<progress class="update-progress" border-radius="35" :percent="percent" activeColor="#3DA7FF"
|
|
577
|
+
backgroundColor="#f0f0f0" show-info stroke-width="12" />
|
|
436
578
|
<view class="progress-text">{{ percent }}%</view>
|
|
437
579
|
</view>
|
|
438
580
|
|
|
@@ -441,10 +583,12 @@ defineExpose({
|
|
|
441
583
|
<text class="success-icon">✓</text>
|
|
442
584
|
下载完成,准备安装...
|
|
443
585
|
</text>
|
|
444
|
-
<text class="update-down-msg" v-else>正在下载,请稍后 ({{ downloadedSize }}/{{ packageFileSize
|
|
586
|
+
<text class="update-down-msg" v-else>正在下载,请稍后 ({{ downloadedSize }}/{{ packageFileSize
|
|
587
|
+
}}MB)</text>
|
|
445
588
|
</view>
|
|
446
589
|
|
|
447
|
-
<button v-if="!tempFilePath && !data.isForce" class="cancel-download-btn"
|
|
590
|
+
<button v-if="!tempFilePath && !data.isForce" class="cancel-download-btn"
|
|
591
|
+
@click="cancelDownload">取消下载</button>
|
|
448
592
|
</view>
|
|
449
593
|
|
|
450
594
|
<template v-if="updateBtn">
|
|
@@ -456,7 +600,8 @@ defineExpose({
|
|
|
456
600
|
<button v-if="!data.isForce" class="update-button skip" plain @click="skipVersion">跳过此版本</button>
|
|
457
601
|
</template>
|
|
458
602
|
|
|
459
|
-
<button class="update-button secondary" plain @click="install"
|
|
603
|
+
<button class="update-button secondary" plain @click="install"
|
|
604
|
+
v-else-if="data.package_type === 0 && tempFilePath">立即安装</button>
|
|
460
605
|
</view>
|
|
461
606
|
|
|
462
607
|
<view class="update-close" v-if="!data.isForce" @click.stop="close">✖</view>
|