@zfqh/uniapp 0.3.22 → 0.3.24
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/README.md +0 -1
- package/docs/api/apis/core.md +2 -79
- package/docs/api/apis/index.md +1 -10
- package/docs/api/configs/index.md +8 -6
- package/docs/api/configs/upload.md +48 -39
- package/docs/api/configs/web.md +17 -3
- package/docs/api/index.md +4 -16
- package/docs/api/utils/cos.md +55 -42
- package/docs/api/utils/index.md +56 -56
- package/docs/api/utils/navigate.md +94 -23
- package/docs/guide/getting-started.md +7 -5
- package/docs/guide/project-frame.md +7 -5
- package/lib/apis/core.d.ts +0 -6
- package/lib/apis/core.js +0 -6
- package/lib/configs/upload.d.ts +2 -2
- package/lib/configs/upload.js +2 -14
- package/lib/utils/cos.d.ts +1 -1
- package/lib/utils/cos.js +182 -67
- package/lib/utils/navigate.d.ts +1 -0
- package/lib/utils/navigate.js +13 -0
- package/package.json +4 -5
- package/CHANGELOG.md +0 -592
- package/LICENSE +0 -21
package/lib/utils/cos.js
CHANGED
|
@@ -3,6 +3,7 @@ import SHA1 from 'crypto-js/sha1';
|
|
|
3
3
|
import Base64 from 'crypto-js/enc-base64';
|
|
4
4
|
import Crypto from 'crypto-js/core';
|
|
5
5
|
import upload from '../configs/upload';
|
|
6
|
+
import { IS_WEBVIEW_ENV } from './consts';
|
|
6
7
|
import { cosCompress } from './index';
|
|
7
8
|
const data = {};
|
|
8
9
|
let promise = null;
|
|
@@ -20,81 +21,196 @@ export async function checkRefreshToken() {
|
|
|
20
21
|
}
|
|
21
22
|
return promise;
|
|
22
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* 是否使用 HTML5+ Uploader:
|
|
26
|
+
* H5 页面被宿主 web-view 嵌入(IS_WEBVIEW_ENV)、plus.uploader 可用,且存在文件路径。
|
|
27
|
+
*/
|
|
28
|
+
function canUsePlusUploader(filePath) {
|
|
29
|
+
let available = false;
|
|
30
|
+
// #ifdef WEB || H5
|
|
31
|
+
available =
|
|
32
|
+
IS_WEBVIEW_ENV && typeof filePath === 'string' && !!filePath && typeof plus !== 'undefined' && !!plus.uploader;
|
|
33
|
+
// #endif
|
|
34
|
+
return available;
|
|
35
|
+
}
|
|
23
36
|
class COS {
|
|
37
|
+
/** 生成 COS 上传签名表单 */
|
|
38
|
+
getFormData(Bucket, Key) {
|
|
39
|
+
const now = data.create_time || Math.round(Date.now() / 1000);
|
|
40
|
+
const exp = now + 1800; // 30分钟过期
|
|
41
|
+
const qKeyTime = now + ';' + exp;
|
|
42
|
+
const qSignAlgorithm = 'sha1';
|
|
43
|
+
const qAk = data.secret_id;
|
|
44
|
+
const policyData = {
|
|
45
|
+
expiration: new Date(exp * 1000).toISOString(),
|
|
46
|
+
conditions: [
|
|
47
|
+
{ 'q-sign-algorithm': qSignAlgorithm },
|
|
48
|
+
{ 'q-ak': qAk },
|
|
49
|
+
{ 'q-sign-time': qKeyTime },
|
|
50
|
+
{ bucket: Bucket },
|
|
51
|
+
{ key: Key },
|
|
52
|
+
],
|
|
53
|
+
};
|
|
54
|
+
const policy = JSON.stringify(policyData);
|
|
55
|
+
const signKey = HmacSHA1(qKeyTime, data.secret_key).toString(Crypto.enc.Hex);
|
|
56
|
+
const stringToSign = SHA1(policy).toString(Crypto.enc.Hex);
|
|
57
|
+
const qSignature = HmacSHA1(stringToSign, signKey).toString(Crypto.enc.Hex);
|
|
58
|
+
return {
|
|
59
|
+
key: Key,
|
|
60
|
+
policy: Base64.stringify(Crypto.enc.Utf8.parse(policy)),
|
|
61
|
+
success_action_status: 200,
|
|
62
|
+
'x-cos-security-token': data.session_token,
|
|
63
|
+
'q-sign-algorithm': qSignAlgorithm,
|
|
64
|
+
'q-ak': qAk,
|
|
65
|
+
'q-key-time': qKeyTime,
|
|
66
|
+
'q-signature': qSignature,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* 统一上传入口:内部按运行环境选择 plus.uploader 或 uni.uploadFile,
|
|
71
|
+
* 两条链路的 success / fail / getTask 回调形态一致。
|
|
72
|
+
*/
|
|
73
|
+
uploadHandler(options) {
|
|
74
|
+
const { url, filePath, file, name = 'file', formData = {}, getTask, success, fail } = options;
|
|
75
|
+
// 链路 1:H5 宿主 webview + plus.uploader + 文件路径(canUsePlusUploader 内部判断,命中后不再走 uni.uploadFile)
|
|
76
|
+
// #ifdef WEB || H5
|
|
77
|
+
if (canUsePlusUploader(filePath)) {
|
|
78
|
+
let plusTask;
|
|
79
|
+
let settled = false;
|
|
80
|
+
const progressCallbacks = new Set();
|
|
81
|
+
const plusSuccess = (res) => {
|
|
82
|
+
if (settled) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
settled = true;
|
|
86
|
+
success?.(res);
|
|
87
|
+
};
|
|
88
|
+
const plusFail = (err) => {
|
|
89
|
+
if (settled) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
settled = true;
|
|
93
|
+
fail?.(err);
|
|
94
|
+
};
|
|
95
|
+
try {
|
|
96
|
+
plusTask = plus.uploader.createUpload(url, { method: 'POST' }, (upload, status) => {
|
|
97
|
+
const statusCode = Number(status) || 0;
|
|
98
|
+
if (statusCode > 0) {
|
|
99
|
+
plusSuccess({ statusCode, data: String(upload.responseText || '') });
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
// 网络失败,未取得 HTTP 状态码
|
|
103
|
+
plusFail({ errMsg: 'uploadFile:fail' });
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
plusTask.addEventListener('statechanged', (upload) => {
|
|
107
|
+
const total = Number(upload.totalSize) || 0;
|
|
108
|
+
const sent = Number(upload.uploadedSize) || 0;
|
|
109
|
+
const progress = total > 0 ? Math.round((sent / total) * 100) : 0;
|
|
110
|
+
progressCallbacks.forEach((cb) => cb({ progress, totalBytesSent: sent, totalBytesExpectedToSend: total }));
|
|
111
|
+
});
|
|
112
|
+
Object.keys(formData).forEach((key) => {
|
|
113
|
+
const value = formData[key];
|
|
114
|
+
if (value !== undefined && value !== null) {
|
|
115
|
+
plusTask.addData(key, String(value));
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
if (plusTask.addFile(filePath, { key: name })) {
|
|
119
|
+
const taskLike = {
|
|
120
|
+
abort: () => {
|
|
121
|
+
if (settled) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
settled = true;
|
|
125
|
+
plusTask.abort();
|
|
126
|
+
fail?.({ errMsg: 'uploadFile:fail abort' });
|
|
127
|
+
},
|
|
128
|
+
onProgressUpdate: (cb) => {
|
|
129
|
+
progressCallbacks.add(cb);
|
|
130
|
+
},
|
|
131
|
+
offProgressUpdate: (cb) => {
|
|
132
|
+
progressCallbacks.delete(cb);
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
getTask?.(taskLike);
|
|
136
|
+
plusTask.start();
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
// 已确定走 plus 链路:路径无法被 HTML5+ 读取(如 blob/content)时直接失败,不再回退 uni.uploadFile
|
|
140
|
+
plusFail({ errMsg: 'uploadFile:fail' });
|
|
141
|
+
plusTask.abort();
|
|
142
|
+
}
|
|
143
|
+
catch (e) {
|
|
144
|
+
plusFail({ errMsg: 'uploadFile:fail' });
|
|
145
|
+
plusTask?.abort();
|
|
146
|
+
}
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
// #endif
|
|
150
|
+
// 链路 2:uni.uploadFile(默认链路)
|
|
151
|
+
const task = uni.uploadFile({
|
|
152
|
+
url,
|
|
153
|
+
filePath,
|
|
154
|
+
file,
|
|
155
|
+
name,
|
|
156
|
+
formData,
|
|
157
|
+
success: (res) => {
|
|
158
|
+
success?.({ statusCode: res.statusCode, data: String(res.data ?? '') });
|
|
159
|
+
},
|
|
160
|
+
fail: (err) => {
|
|
161
|
+
fail?.(err);
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
getTask?.(task);
|
|
165
|
+
}
|
|
166
|
+
/** 处理上传结果:成功 / token 过期重试 / 失败 */
|
|
167
|
+
handleUploadResult(params, cosHost, statusCode, body, resolve, reject) {
|
|
168
|
+
if (statusCode === 200) {
|
|
169
|
+
resolve({ Location: `${cosHost}/${params.Key}` });
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const resBody = String(body || '');
|
|
173
|
+
const codeMatch = resBody.match(/<Code>([^<>]+)<\/Code>/);
|
|
174
|
+
if (codeMatch && codeMatch[1] === 'ExpiredToken' && data.expire_time !== 0) {
|
|
175
|
+
data.expire_time = 0;
|
|
176
|
+
checkRefreshToken()
|
|
177
|
+
.then(() => {
|
|
178
|
+
this.uploadFile(params)
|
|
179
|
+
.then((e) => {
|
|
180
|
+
resolve(e);
|
|
181
|
+
})
|
|
182
|
+
.catch((e) => {
|
|
183
|
+
reject(e);
|
|
184
|
+
});
|
|
185
|
+
})
|
|
186
|
+
.catch((e) => {
|
|
187
|
+
reject(e);
|
|
188
|
+
});
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const err = {
|
|
192
|
+
code: statusCode,
|
|
193
|
+
msg: 'Upload Fail',
|
|
194
|
+
};
|
|
195
|
+
const msgMatch = resBody.match(/<Message>([^<>]+)<\/Message>/);
|
|
196
|
+
if (msgMatch) {
|
|
197
|
+
err.msg = msgMatch[1];
|
|
198
|
+
}
|
|
199
|
+
reject(err);
|
|
200
|
+
}
|
|
24
201
|
async uploadFile(params) {
|
|
25
202
|
const { Bucket, Region, Key, FilePath, File } = params;
|
|
203
|
+
const cosHost = `${Bucket}.cos.${Region}.myqcloud.com`;
|
|
26
204
|
return new Promise((resolve, reject) => {
|
|
27
|
-
|
|
28
|
-
const now = data.create_time || Math.round(Date.now() / 1000);
|
|
29
|
-
const exp = now + 1800; // 30分钟过期
|
|
30
|
-
const qKeyTime = now + ';' + exp;
|
|
31
|
-
const qSignAlgorithm = 'sha1';
|
|
32
|
-
const qAk = data.secret_id;
|
|
33
|
-
const policyData = {
|
|
34
|
-
expiration: new Date(exp * 1000).toISOString(),
|
|
35
|
-
conditions: [
|
|
36
|
-
{ 'q-sign-algorithm': qSignAlgorithm },
|
|
37
|
-
{ 'q-ak': qAk },
|
|
38
|
-
{ 'q-sign-time': qKeyTime },
|
|
39
|
-
{ bucket: Bucket },
|
|
40
|
-
{ key: Key },
|
|
41
|
-
],
|
|
42
|
-
};
|
|
43
|
-
const policy = JSON.stringify(policyData);
|
|
44
|
-
const signKey = HmacSHA1(qKeyTime, data.secret_key).toString(Crypto.enc.Hex);
|
|
45
|
-
const stringToSign = SHA1(policy).toString(Crypto.enc.Hex);
|
|
46
|
-
const qSignature = HmacSHA1(stringToSign, signKey).toString(Crypto.enc.Hex);
|
|
47
|
-
const FormData = {
|
|
48
|
-
key: Key,
|
|
49
|
-
policy: Base64.stringify(Crypto.enc.Utf8.parse(policy)),
|
|
50
|
-
success_action_status: 200,
|
|
51
|
-
'x-cos-security-token': data.session_token,
|
|
52
|
-
'q-sign-algorithm': qSignAlgorithm,
|
|
53
|
-
'q-ak': qAk,
|
|
54
|
-
'q-key-time': qKeyTime,
|
|
55
|
-
'q-signature': qSignature,
|
|
56
|
-
};
|
|
57
|
-
const task = uni.uploadFile({
|
|
205
|
+
this.uploadHandler({
|
|
58
206
|
url: `https://${cosHost}`,
|
|
59
207
|
filePath: FilePath,
|
|
60
208
|
file: File,
|
|
61
209
|
name: 'file',
|
|
62
|
-
formData:
|
|
210
|
+
formData: this.getFormData(Bucket, Key),
|
|
211
|
+
getTask: params.getTask,
|
|
63
212
|
success: (res) => {
|
|
64
|
-
|
|
65
|
-
resolve({ Location: `${cosHost}/${Key}` });
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
const { data: e, statusCode } = res;
|
|
69
|
-
const codeMatch = e.match(/<Code>([^<>]+)<\/Code>/);
|
|
70
|
-
if (codeMatch && codeMatch[1] === 'ExpiredToken' && data.expire_time !== 0) {
|
|
71
|
-
data.expire_time = 0;
|
|
72
|
-
checkRefreshToken()
|
|
73
|
-
.then(() => {
|
|
74
|
-
this.uploadFile(params)
|
|
75
|
-
.then((e) => {
|
|
76
|
-
resolve(e);
|
|
77
|
-
})
|
|
78
|
-
.catch((e) => {
|
|
79
|
-
reject(e);
|
|
80
|
-
});
|
|
81
|
-
})
|
|
82
|
-
.catch((e) => {
|
|
83
|
-
reject(e);
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
const err = {
|
|
88
|
-
code: statusCode,
|
|
89
|
-
msg: 'Upload Fail',
|
|
90
|
-
};
|
|
91
|
-
const msgMatch = e.match(/<Message>([^<>]+)<\/Message>/);
|
|
92
|
-
if (msgMatch) {
|
|
93
|
-
err.msg = msgMatch[1];
|
|
94
|
-
}
|
|
95
|
-
reject(err);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
213
|
+
this.handleUploadResult(params, cosHost, res.statusCode, res.data, resolve, reject);
|
|
98
214
|
},
|
|
99
215
|
fail: (err) => {
|
|
100
216
|
reject({
|
|
@@ -102,7 +218,6 @@ class COS {
|
|
|
102
218
|
});
|
|
103
219
|
},
|
|
104
220
|
});
|
|
105
|
-
params.getTask?.(task);
|
|
106
221
|
});
|
|
107
222
|
}
|
|
108
223
|
}
|
package/lib/utils/navigate.d.ts
CHANGED
package/lib/utils/navigate.js
CHANGED
|
@@ -48,6 +48,19 @@ const navigate = function (url = '', type = 'navigateTo') {
|
|
|
48
48
|
webviewPage = _webviewPage;
|
|
49
49
|
navigateOptions = rest;
|
|
50
50
|
}
|
|
51
|
+
if (opts['appId']) {
|
|
52
|
+
// #ifdef APP-PLUS
|
|
53
|
+
// 打开其他小程序
|
|
54
|
+
if (uni['sendHostEvent']) {
|
|
55
|
+
uni.sendHostEvent('openUniMP', {
|
|
56
|
+
appid: opts['appId'],
|
|
57
|
+
path: url.replace(/\//, ''),
|
|
58
|
+
});
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
// #endif
|
|
62
|
+
url = `${opts['appId']}:/${url}`;
|
|
63
|
+
}
|
|
51
64
|
const indexPage = getPage('index').replace(/^\/+/, '');
|
|
52
65
|
const loginPage = getPage('login');
|
|
53
66
|
const { isLogin } = uni.$store?.getters || {};
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zfqh/uniapp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.24",
|
|
4
4
|
"description": "uniapp公共模块",
|
|
5
5
|
"author": "yinjiazeng@163.com",
|
|
6
|
-
"license": "
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
7
|
"main": "lib/index.js",
|
|
8
8
|
"types": "lib/index.d.ts",
|
|
9
9
|
"publishConfig": {
|
|
@@ -22,11 +22,10 @@
|
|
|
22
22
|
"docs",
|
|
23
23
|
"lib",
|
|
24
24
|
"types",
|
|
25
|
-
"CHANGELOG.md",
|
|
26
25
|
"README.md"
|
|
27
26
|
],
|
|
28
27
|
"dependencies": {
|
|
29
|
-
"@gmcb/uv-ui": "0.3.
|
|
28
|
+
"@gmcb/uv-ui": "0.3.8",
|
|
30
29
|
"@tencentcloud/chat-uikit-engine": "^2.3.2",
|
|
31
30
|
"@tencentcloud/tui-core": "^2.3.2",
|
|
32
31
|
"crypto-js": "^4.2.0",
|
|
@@ -45,5 +44,5 @@
|
|
|
45
44
|
"@types/qs": "^6.9.16",
|
|
46
45
|
"@types/url-parse": "^1.4.11"
|
|
47
46
|
},
|
|
48
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "aa7b85e9ac9a07244607eee648b37981bac588be"
|
|
49
48
|
}
|