@cloudbase/weda-ui-mp 3.16.0 → 3.17.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.
@@ -1,33 +1,9 @@
1
1
  import WxCanvas from './wx-canvas';
2
2
  import * as echarts from '../common/lib/echarts.min';
3
+ import { compareVersion } from '../../../utils/platform';
3
4
 
4
5
  let ctx;
5
6
 
6
- function compareVersion(v1, v2) {
7
- v1 = v1.split('.');
8
- v2 = v2.split('.');
9
- const len = Math.max(v1.length, v2.length);
10
-
11
- while (v1.length < len) {
12
- v1.push('0');
13
- }
14
- while (v2.length < len) {
15
- v2.push('0');
16
- }
17
-
18
- for (let i = 0; i < len; i++) {
19
- const num1 = parseInt(v1[i]);
20
- const num2 = parseInt(v2[i]);
21
-
22
- if (num1 > num2) {
23
- return 1;
24
- } else if (num1 < num2) {
25
- return -1;
26
- }
27
- }
28
- return 0;
29
- }
30
-
31
7
  Component({
32
8
  properties: {
33
9
  canvasId: {
@@ -1,7 +1,6 @@
1
- import { getCloudInstance, getTempFileURL, getDefaultUploadPath } from '../../../utils/tcb';
2
- import { transSize, randomStr } from '../../../utils/platform';
1
+ import { getTempFileURL } from '../../../utils/tcb';
3
2
  import equal from '../../../utils/deepEqual';
4
-
3
+ import { upload, handleUpload, getName, initUploadInstance } from './upload';
5
4
  Component({
6
5
  options: {
7
6
  virtualHost: true,
@@ -97,214 +96,9 @@ Component({
97
96
  { text: '拍照或录像', value: 2 },
98
97
  { text: '选取聊天文件', value: 3 },
99
98
  ],
99
+ uploadInstance: {},
100
100
  },
101
101
  methods: {
102
- // 批量上传文件前置事件
103
- handleBefore: function (files = []) {
104
- if (this.data.files.length + files.length > this.data.maxCount) {
105
- wx.showToast({
106
- title: `上传文件总数不能超过${this.data.maxCount}个`,
107
- icon: 'none',
108
- duration: 2000,
109
- });
110
- return false;
111
- }
112
- if (this.properties.maxSize && files.some((f) => f.size > this.properties.maxSize * 1024 * 1024)) {
113
- wx.showToast({
114
- title: `上传文件大小不能超过${this.properties.maxSize}M`,
115
- icon: 'none',
116
- duration: 2000,
117
- });
118
- return false;
119
- }
120
- if (files.some((f) => f.size > 500 * 1024 * 1024)) {
121
- wx.showToast({
122
- title: `上传文件大小不能超过500M`,
123
- icon: 'none',
124
- duration: 2000,
125
- });
126
- return false;
127
- }
128
- return true;
129
- },
130
- //上传文件过程
131
- uploadFile: async function () {
132
- //文件上传的函数,
133
- wx.chooseMessageFile({
134
- count: this.data.maxCount,
135
- type: 'all',
136
- success: async (files) => {
137
- await this.handleUpload(files?.tempFiles);
138
- },
139
- fail(e) {
140
- this.triggerEvent('error', e.detail);
141
- },
142
- });
143
- },
144
- //拍摄或从手机相册中选择图片或视频
145
- chooseMedia: async function (value) {
146
- wx.chooseMedia({
147
- count: this.data.maxCount,
148
- sourceType: value === 1 ? ['album'] : ['camera'],
149
- maxDuration: 60,
150
- success: async (files) => {
151
- await this.handleUpload(files?.tempFiles);
152
- },
153
- fail(e) {
154
- this.triggerEvent('error', e.detail);
155
- },
156
- });
157
- },
158
- getName: function (hf) {
159
- const uuidReg = /[0-9a-f]{8}([0-9a-f]{4}){3}[0-9a-f]{12}-/;
160
- const lastIndex = String(hf).lastIndexOf('/');
161
- const name = String(hf).slice(lastIndex + 1);
162
- const label = name.replace(uuidReg, '');
163
- return label;
164
- },
165
- handleUpload: async function (files, reload = false) {
166
- var _this = this;
167
- if (!this.handleBefore(files)) return;
168
-
169
- const callbacks = this.data.callbacks;
170
- let shouldUploadToCos = true;
171
- if (typeof callbacks?.beforeUpload === 'function') {
172
- try {
173
- const mgr = wx.getFileSystemManager();
174
- const ret = await callbacks.beforeUpload({
175
- tempFilePaths: files.map((f) => f.path || f.tempFilePath),
176
- base64Uri: files.map((f) => {
177
- const content = mgr.readFileSync(f.path || f.tempFilePath);
178
- return `data:;base64,${wx.arrayBufferToBase64(content)}`;
179
- }),
180
- });
181
- if (typeof ret === 'boolean') {
182
- shouldUploadToCos = ret;
183
- } else if (Array.Array(ret) && ret.every((i) => typeof i === 'string')) {
184
- files = ret.map((path, idx) => {
185
- files[idx].path = path;
186
- });
187
- }
188
- } catch (err) {
189
- console.error('上传前处理函数抛错', err);
190
- shouldUploadToCos = false;
191
- }
192
- }
193
- if (shouldUploadToCos === false) {
194
- return false;
195
- }
196
-
197
- const initFiles = files.map((i) => ({
198
- ...i,
199
- percent: '0',
200
- cloudPath: null,
201
- name: i?.name || this.getName(i?.tempFilePath),
202
- filePath: i?.path || i?.tempFilePath || null,
203
- size: transSize(i?.size),
204
- status: 'pending',
205
- }));
206
- let filelsList = reload ? this.data.files : [...this.data.files, ...initFiles];
207
- this.setData({
208
- files: filelsList,
209
- });
210
- Promise.all(
211
- initFiles.map(async (tempFile) => {
212
- return new Promise(function (resolve) {
213
- _this.handleUploadFile({
214
- _tempFile: tempFile,
215
- onSuccess: (res) => {
216
- filelsList = filelsList.map((i) => (i.filePath === res.filePath ? res : i));
217
- _this.triggerEvent('success', {
218
- value: res.cloudPath,
219
- file: res,
220
- });
221
- resolve(res);
222
- },
223
- onProgressUpdate: (res) => {
224
- filelsList = filelsList.map((i) => (i.filePath === res.filePath ? res : i));
225
- _this.setData({
226
- files: filelsList,
227
- });
228
- },
229
- onFail: (res, error) => {
230
- filelsList = filelsList.map((i) => (i.filePath === res.filePath ? res : i));
231
- _this.triggerEvent('error', error.detail);
232
- resolve(res);
233
- },
234
- });
235
- });
236
- }),
237
- ).then((res) => {
238
- const result = filelsList.map((i) => res.find((j) => j.filePath === i.filePath) || i);
239
- const cloudPathList = result.filter((i) => i.cloudPath).map((j) => j.cloudPath);
240
- this.setData({
241
- files: result,
242
- urls: cloudPathList,
243
- cloudFile: cloudPathList,
244
- });
245
- _this.handleChange(cloudPathList);
246
- });
247
- },
248
- handleUploadFile: async function ({ _tempFile, onSuccess, onProgressUpdate, onFail }) {
249
- const tempFile = {
250
- ..._tempFile,
251
- };
252
- const uploadPath = 'weda-uploader';
253
- const _uploadPath = await getDefaultUploadPath(uploadPath);
254
- const filenameRegex = /[^a-zA-Z0-9\u4e00-\u9fff-*!_.]/g;
255
- const cloudPath = `${_uploadPath}/${randomStr()}-${tempFile.name?.replace(filenameRegex, '-')}`;
256
- try {
257
- const tcb = await getCloudInstance();
258
- const uploadTask = await tcb.uploadFile({
259
- cloudPath: cloudPath,
260
- filePath: tempFile.path || tempFile.tempFilePath,
261
- success(res) {
262
- tempFile.cloudPath = res.fileID;
263
- tempFile.percent = 100;
264
- tempFile.status = 'success';
265
- if (onSuccess) {
266
- onSuccess(tempFile);
267
- }
268
- },
269
- fail(e) {
270
- tempFile.status = 'fail';
271
- wx.showModal({
272
- title: '上传失败,请重试',
273
- content: e.message,
274
- showCancel: false,
275
- });
276
- onFail(tempFile, {
277
- detail: e,
278
- });
279
- },
280
- });
281
- if (typeof uploadTask.onProgressUpdate === 'function') {
282
- uploadTask.onProgressUpdate((res) => {
283
- tempFile.percent = String(res.progress);
284
- tempFile.status = res.progress == 100 ? 'success' : 'uploading';
285
- tempFile.uploaded = transSize(res.totalBytesSent);
286
- if (onProgressUpdate) {
287
- onProgressUpdate(tempFile);
288
- }
289
- });
290
- } else {
291
- tempFile.percent = '100';
292
- tempFile.status = 'success';
293
- tempFile.cloudPath = uploadTask.fileID;
294
- onSuccess(tempFile);
295
- }
296
- } catch (e) {
297
- tempFile.status = 'fail';
298
- wx.showModal({
299
- title: '上传失败,请重试',
300
- content: e.message,
301
- showCancel: false,
302
- });
303
- if (onFail) {
304
- onFail(tempFile, e);
305
- }
306
- }
307
- },
308
102
  onDelete: function (e) {
309
103
  let newUrls = [];
310
104
  if (this.data.urls.length == 0) {
@@ -332,17 +126,14 @@ Component({
332
126
  },
333
127
 
334
128
  // change 事件
335
- handleChange: function (values) {
336
- let value = values;
337
- if (this.properties.single) {
338
- value = values[0] ?? '';
339
- }
129
+ handleChange: function (value) {
340
130
  this.setData({ oldValue: value });
341
131
  this.triggerEvent('change', { value });
342
132
  },
343
133
 
344
134
  reload: function (e) {
345
- this.handleUpload([e.target.dataset.item], true);
135
+ const { uploadInstance } = this.data;
136
+ handleUpload([e.target.dataset.item], uploadInstance, true);
346
137
  },
347
138
  downloadFile: async function (e) {
348
139
  const path = e.target.dataset.item?.cloudPath;
@@ -397,19 +188,31 @@ Component({
397
188
  this.setData({
398
189
  showActionsheet: false,
399
190
  });
191
+ const { disabled, maxCount, files, maxSize } = this.data;
192
+ let config = { disabled, count: maxCount, maxSize, action: 'CHOOSE_MEDIA' };
193
+
400
194
  switch (e?.detail?.value) {
401
195
  // 照片图库
402
196
  case 1:
403
- // 拍照或录像
404
- // eslint-disable-next-line no-fallthrough
197
+ // 拍照或录像
198
+ //从手机相册中选择图片或视频
199
+ config.sourceType = ['album'];
200
+ break;
405
201
  case 2:
406
- this.chooseMedia(e?.detail?.value);
202
+ // 拍摄
203
+ config.sourceType = ['camera'];
407
204
  break;
408
205
  // 选取聊天文件
409
206
  case 3:
410
- this.uploadFile();
207
+ config.type = 'all';
208
+ config.action = 'CHOOSE_MESSAGE_FILE';
209
+ break;
210
+ default:
411
211
  break;
412
212
  }
213
+ const uploadInstance = initUploadInstance({ config, previewFile: files }, this);
214
+ this.setData({ uploadInstance });
215
+ upload(uploadInstance);
413
216
  },
414
217
  },
415
218
  observers: {
@@ -430,7 +233,7 @@ Component({
430
233
  for (let f of values) {
431
234
  if (f.startsWith('cloud:')) {
432
235
  const hf = await getTempFileURL(f);
433
- const label = this.getName(hf);
236
+ const label = getName(hf);
434
237
  const httpFile = {
435
238
  name: label,
436
239
  cloudPath: f,
@@ -0,0 +1,283 @@
1
+ import { transSize, randomStr } from '../../../utils/platform';
2
+ import { getCloudInstance, getDefaultUploadPath } from '../../../utils/tcb';
3
+
4
+ const ACTION = { CHOOSE_MEDIA: 'chooseMedia', CHOOSE_MESSAGE_FILE: 'chooseMessageFile' };
5
+
6
+ // 选择文件
7
+ const chooseFile = ({ action = 'CHOOSE_MEDIA', config, success, fail }) => {
8
+ let _config = { count: 9, maxDuration: 60 };
9
+
10
+ switch (action) {
11
+ case ACTION['CHOOSE_MEDIA']:
12
+ _config = {
13
+ mediaType: ['image'],
14
+ sourceType: ['album'],
15
+ ...config,
16
+ };
17
+ break;
18
+ case ACTION['CHOOSE_MESSAGE_FILE']:
19
+ _config = {
20
+ type: 'all',
21
+ ...config,
22
+ };
23
+ break;
24
+ default:
25
+ _config = { ...config };
26
+ break;
27
+ }
28
+
29
+ wx[ACTION[action]]({
30
+ ..._config,
31
+ success,
32
+ fail,
33
+ });
34
+ };
35
+
36
+ export const getName = (hf) => {
37
+ const uuidReg = /[0-9a-f]{8}([0-9a-f]{4}){3}[0-9a-f]{12}-/;
38
+ const lastIndex = String(hf).lastIndexOf('/');
39
+ const name = String(hf).slice(lastIndex + 1);
40
+ const label = name.replace(uuidReg, '');
41
+ return label;
42
+ };
43
+
44
+ // 批量上传文件前置事件
45
+ const handleBefore = (files, uploadInstance) => {
46
+ const { count: maxCount, maxSize } = uploadInstance.config;
47
+ const previewFile = uploadInstance.getPreviewFile();
48
+ if (previewFile.length + files.length > maxCount) {
49
+ wx.showToast({
50
+ title: `上传文件总数不能超过${maxCount}个`,
51
+ icon: 'none',
52
+ duration: 2000,
53
+ });
54
+ return false;
55
+ }
56
+ if (maxSize && files.some((f) => f.size > maxSize * 1024 * 1024)) {
57
+ wx.showToast({
58
+ title: `上传文件大小不能超过${maxSize}M`,
59
+ icon: 'none',
60
+ duration: 2000,
61
+ });
62
+ return false;
63
+ }
64
+ return true;
65
+ };
66
+
67
+ // 上传
68
+ export const handleUpload = async (files, uploadInstance, reload = false) => {
69
+ if (!handleBefore(files, uploadInstance)) return;
70
+
71
+ let shouldUploadToCos = true;
72
+ if (typeof uploadInstance?.beforeUpload === 'function') {
73
+ try {
74
+ const mgr = wx.getFileSystemManager();
75
+ const ret = await uploadInstance.beforeUpload({
76
+ tempFilePaths: files.map((f) => f.path || f.tempFilePath),
77
+ base64Uri: files.map((f) => {
78
+ const content = mgr.readFileSync(f.path || f.tempFilePath);
79
+ return `data:;base64,${wx.arrayBufferToBase64(content)}`;
80
+ }),
81
+ });
82
+ if (typeof ret === 'boolean') {
83
+ shouldUploadToCos = ret;
84
+ } else if (Array.isArray(ret) && ret.every((i) => typeof i === 'string')) {
85
+ files = ret.map((path, idx) => {
86
+ files[idx].path = path;
87
+ });
88
+ }
89
+ } catch (err) {
90
+ console.error('上传前处理函数抛错', err);
91
+ shouldUploadToCos = false;
92
+ }
93
+ }
94
+ if (!shouldUploadToCos) {
95
+ return;
96
+ }
97
+
98
+ const initFiles = files.map((i) => ({
99
+ ...i,
100
+ percent: '0',
101
+ cloudPath: null,
102
+ name: i?.name || getName(i?.tempFilePath),
103
+ filePath: i?.path || i?.tempFilePath || null,
104
+ size: transSize(i?.size),
105
+ status: 'pending',
106
+ }));
107
+ const previewFile = uploadInstance.getPreviewFile();
108
+ let filelsList = reload ? previewFile : [...previewFile, ...initFiles];
109
+ // 更新预览文件
110
+ uploadInstance.updatePreviewFile(filelsList);
111
+ return Promise.all(
112
+ initFiles.map(async (tempFile) => {
113
+ return new Promise(function (resolve) {
114
+ handleUploadFile({
115
+ uploadPath: uploadInstance.config.uploadPath,
116
+ customUploadPath: uploadInstance.config.customUploadPath,
117
+ _tempFile: tempFile,
118
+ onSuccess: (res) => {
119
+ filelsList = filelsList.map((i) => (i.filePath === res.filePath ? res : i));
120
+ uploadInstance.updatePreviewFile(filelsList);
121
+ uploadInstance.onSuccess(res);
122
+ resolve(res);
123
+ },
124
+ onProgressUpdate: (res) => {
125
+ filelsList = filelsList.map((i) => (i.filePath === res.filePath ? res : i));
126
+ uploadInstance.updatePreviewFile(filelsList);
127
+ },
128
+ onFail: (res, error) => {
129
+ filelsList = filelsList.map((i) => (i.filePath === res.filePath ? res : i));
130
+ uploadInstance.updatePreviewFile(filelsList);
131
+ uploadInstance.onFail(res, error);
132
+ resolve(res);
133
+ },
134
+ });
135
+ });
136
+ }),
137
+ ).then((res) => {
138
+ const result = filelsList.map((i) => res.find((j) => j.filePath === i.filePath) || i);
139
+
140
+ uploadInstance.onComplete(result);
141
+ });
142
+ };
143
+
144
+ //
145
+ const sanitizeFilename = (filename, replacement = '') => {
146
+ return (
147
+ filename
148
+ // 移除非法字符
149
+ // eslint-disable-next-line no-control-regex
150
+ .replace(/[<>.:"\\|?*\x00-\x1F]/g, replacement)
151
+ // 处理Windows保留文件名(CON, PRN等)
152
+ .replace(/^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(\..*)?$/i, replacement)
153
+ // 移除开头和结尾的点,空格,反斜杠(Windows不允许)
154
+ .replace(/^[. /]+/, '')
155
+ .replace(/[. /]+$/, '')
156
+ // 可选:限制长度
157
+ .slice(0, 255)
158
+ );
159
+ };
160
+ // 上传到云存储
161
+ const handleUploadFile = async ({
162
+ uploadPath = 'weda-uploader',
163
+ _tempFile,
164
+ onSuccess,
165
+ onProgressUpdate,
166
+ onFail,
167
+ customUploadPath,
168
+ }) => {
169
+ const tempFile = {
170
+ ..._tempFile,
171
+ };
172
+ let _uploadPath = await getDefaultUploadPath(uploadPath);
173
+ if (customUploadPath) {
174
+ _uploadPath = `${_uploadPath}/${sanitizeFilename(customUploadPath, '')}`;
175
+ }
176
+ const filenameRegex = /[^a-zA-Z0-9\u4e00-\u9fff-*!_.]/g;
177
+ const cloudPath = `${_uploadPath}/${randomStr()}-${tempFile.name?.replace(filenameRegex, '-')}`;
178
+ try {
179
+ const tcb = await getCloudInstance();
180
+ const uploadTask = await tcb.uploadFile({
181
+ cloudPath: cloudPath,
182
+ filePath: tempFile.path || tempFile.tempFilePath,
183
+ success(res) {
184
+ tempFile.cloudPath = res.fileID;
185
+ tempFile.percent = 100;
186
+ tempFile.status = 'success';
187
+ if (onSuccess) {
188
+ onSuccess(tempFile);
189
+ }
190
+ },
191
+ fail(e) {
192
+ tempFile.status = 'fail';
193
+ wx.showModal({
194
+ title: '上传失败,请重试',
195
+ content: e.message,
196
+ showCancel: false,
197
+ });
198
+ onFail(tempFile, e);
199
+ },
200
+ });
201
+ if (typeof uploadTask.onProgressUpdate === 'function') {
202
+ uploadTask.onProgressUpdate((res) => {
203
+ tempFile.percent = String(res.progress);
204
+ tempFile.status = res.progress == 100 ? 'success' : 'uploading';
205
+ tempFile.uploaded = transSize(res.totalBytesSent);
206
+ if (onProgressUpdate) {
207
+ onProgressUpdate(tempFile);
208
+ }
209
+ });
210
+ } else {
211
+ tempFile.percent = '100';
212
+ tempFile.status = 'success';
213
+ tempFile.cloudPath = uploadTask.fileID;
214
+ onSuccess(tempFile);
215
+ }
216
+ } catch (e) {
217
+ tempFile.status = 'fail';
218
+ wx.showModal({
219
+ title: '上传失败,请重试',
220
+ content: e.message,
221
+ showCancel: false,
222
+ });
223
+ if (onFail) {
224
+ onFail(tempFile, e);
225
+ }
226
+ }
227
+ };
228
+
229
+ export const upload = (uploadInstance) => {
230
+ const { config, onSuccess, onFail } = uploadInstance;
231
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
232
+ const { action, disabled, maxSize, ..._config } = config;
233
+ if (disabled) return;
234
+ const success = (res) => {
235
+ const result = handleUpload(res.tempFiles, uploadInstance);
236
+ onSuccess(result);
237
+ };
238
+ const fail = (e) => {
239
+ onFail(e);
240
+ };
241
+
242
+ chooseFile({ action, config: _config, success, fail });
243
+ };
244
+
245
+ export const initUploadInstance = ({ action, config, previewFile }, _this) => {
246
+ let uploadInstance = {
247
+ action,
248
+ config: { disabled: false, maxSize: 500, count: 9, maxDuration: 60, ...config },
249
+ previewFile,
250
+ updatePreviewFile(files) {
251
+ _this.setData({ files });
252
+ },
253
+ getPreviewFile() {
254
+ const { files } = _this.data;
255
+ return files;
256
+ },
257
+ onComplete(result) {
258
+ const cloudPathList = result.filter((i) => i.cloudPath).map((j) => j.cloudPath);
259
+ _this.setData({
260
+ files: result,
261
+ urls: cloudPathList,
262
+ cloudFile: cloudPathList,
263
+ });
264
+ let _value = cloudPathList;
265
+ if (_this.data.single) {
266
+ _value = cloudPathList[0] ?? '';
267
+ }
268
+ _this.handleChange(_value);
269
+ },
270
+ onSuccess(res) {
271
+ _this.triggerEvent('success', {
272
+ value: res.cloudPath,
273
+ file: res,
274
+ });
275
+ },
276
+ onFail(e) {
277
+ _this.triggerEvent('error', e);
278
+ },
279
+ beforeUpload: _this.data.callbacks?.beforeUpload,
280
+ };
281
+
282
+ return uploadInstance;
283
+ };
@@ -2,6 +2,8 @@
2
2
  import handleEvents from '../../utils/handleEvents';
3
3
  import { commonCompBehavior } from '../../utils/common-behavior';
4
4
  import { WD_PREFIX } from '../../utils/constant';
5
+ import { compareVersion } from '../../utils/platform';
6
+ import { errorHandler } from '../../utils/error';
5
7
 
6
8
  Component({
7
9
  options: { virtualHost: true },
@@ -37,12 +39,21 @@ Component({
37
39
  type: Number,
38
40
  value: 5,
39
41
  },
42
+ multiton: {
43
+ type: Boolean,
44
+ value: false,
45
+ },
46
+ disableFallbackSharePage: {
47
+ type: Boolean,
48
+ value: false,
49
+ },
40
50
  },
41
51
  data: {
42
52
  _adType: 'banner',
43
53
  _gridCount: 5,
44
54
  _adIntervals: null,
45
55
  classPrefix: WD_PREFIX,
56
+ rewardedVideoAd: null,
46
57
  },
47
58
  methods: {
48
59
  ...handleEvents([
@@ -50,17 +61,102 @@ Component({
50
61
  { name: 'error', title: '广告加载失败' },
51
62
  { name: 'close', title: '广告被关闭' },
52
63
  ]),
64
+ checkSdkVersion() {
65
+ let canUseRewardedVideoAd = true;
66
+ if (wx.canIUse('getAppBaseInfo')) {
67
+ const appBaseInfo = wx.getAppBaseInfo();
68
+ canUseRewardedVideoAd = compareVersion(appBaseInfo.SDKVersion, '2.8.1') >= 0;
69
+ } else {
70
+ const version = wx.getSystemInfoSync().SDKVersion;
71
+ canUseRewardedVideoAd = compareVersion(version, '2.8.1') >= 0;
72
+ }
73
+ return canUseRewardedVideoAd;
74
+ },
75
+ createRewardedVideoAd() {
76
+ if (this.data.rewardedVideoAd) {
77
+ this.destroy();
78
+ }
79
+ const canUseRewardedVideoAd = this.checkSdkVersion();
80
+
81
+ if (wx.createRewardedVideoAd && canUseRewardedVideoAd) {
82
+ const { unitId, multiton, disableFallbackSharePage } = this.data;
83
+ const rewardedVideoAd = wx.createRewardedVideoAd({ adUnitId: unitId, multiton, disableFallbackSharePage });
84
+ rewardedVideoAd.onLoad(() => {
85
+ this.triggerEvent('load');
86
+ });
87
+ rewardedVideoAd.onError((error) => {
88
+ const { comErrorInfo } = errorHandler({
89
+ id: this.id,
90
+ code: 'WdAd.createRewardedVideoAd',
91
+ error: error,
92
+ });
93
+ this.triggerEvent('error', { error: comErrorInfo });
94
+ });
95
+ rewardedVideoAd.onClose((res) => {
96
+ this.triggerEvent('close', res);
97
+ });
98
+ this.setData({ rewardedVideoAd });
99
+ } else {
100
+ const { comErrorInfo } = errorHandler({
101
+ id: this.id,
102
+ code: 'WdAd.createRewardedVideoAd',
103
+ message: '当前基础库版本低于2.8.1,不支持激励视频广告功能',
104
+ });
105
+ this.triggerEvent('error', { error: comErrorInfo });
106
+ }
107
+ },
108
+ destroy() {
109
+ this.data.rewardedVideoAd?.destroy();
110
+ this.setData({
111
+ rewardedVideoAd: null,
112
+ });
113
+ },
114
+ show() {
115
+ const { rewardedVideoAd } = this.data;
116
+ rewardedVideoAd?.show().catch(() => {
117
+ rewardedVideoAd
118
+ .load()
119
+ .then(() => rewardedVideoAd.show())
120
+ .catch((error) => {
121
+ const { comErrorInfo } = errorHandler({
122
+ id: this.id,
123
+ code: 'WdAd.showRewardedVideoAd',
124
+ error: error,
125
+ });
126
+ this.triggerEvent('error', { error: comErrorInfo });
127
+ });
128
+ });
129
+ },
130
+ updateWidgetAPI() {
131
+ this.setReadonlyAttributes?.({
132
+ rewardedVideoAd: this.data.rewardedVideoAd,
133
+ show: this.show.bind(this),
134
+ });
135
+ },
53
136
  },
54
137
  observers: {
55
138
  // 规范取值
56
139
  'adType,adIntervals,gridCount': function (adType, adIntervals, gridCount) {
57
- const _adType = ['banner', 'video', 'grid'].includes(adType)
58
- ? adType
59
- : 'banner';
60
- const _adIntervals =
61
- Number(adIntervals) >= 30 ? Number(adIntervals) : null;
140
+ const _adType = ['banner', 'video', 'grid', 'rewardedVideoAd'].includes(adType) ? adType : 'banner';
141
+ const _adIntervals = Number(adIntervals) >= 30 ? Number(adIntervals) : null;
62
142
  const _gridCount = gridCount == 8 ? 8 : 5;
63
143
  this.setData({ _adType, _gridCount, _adIntervals });
64
144
  },
145
+ rewardedVideoAd: function () {
146
+ this.updateWidgetAPI();
147
+ },
148
+ 'adType,unitId,multiton,disableFallbackSharePage': function () {
149
+ this.createRewardedVideoAd();
150
+ },
151
+ },
152
+ lifetimes: {
153
+ attached() {
154
+ if (this.data.adType === 'rewardedVideoAd') {
155
+ this.createRewardedVideoAd();
156
+ }
157
+ },
158
+ detached() {
159
+ this.destroy();
160
+ },
65
161
  },
66
162
  });
@@ -1,3 +1,5 @@
1
1
  <view id="{{id}}" style="{{style}}" class="{{classPrefix}}-ad {{classPrefix}}-mp-ad {{classPrefix}}-ad--{{_adType}} {{className}} ">
2
+ <block wx:if="{{_adType!=='rewardedVideoAd'}}">
2
3
  <ad unit-id="{{unitId}}" ad-intervals="{{_adIntervals}}" ad-type="{{_adType}}" ad-theme="{{adTheme}}" grid-count="{{_gridCount}}" bindload="load" binderror="error" bindclose="close"></ad>
4
+ </block>
3
5
  </view>
@@ -3,6 +3,7 @@ import formFieldBehavior from '../form-field-behavior/form-field-behavior';
3
3
  import itemBehavior from '../form-field-behavior/item-behavior';
4
4
  import isEqual from '../../utils/deepEqual';
5
5
  import { convertSingleValue } from '../../utils/platform';
6
+ import { upload } from '../form/uploaderFile/upload';
6
7
 
7
8
  Component({
8
9
  options: {
@@ -39,6 +40,15 @@ Component({
39
40
  type: Object,
40
41
  value: null,
41
42
  },
43
+ template: {
44
+ type: String,
45
+ value: 'normal',
46
+ },
47
+ },
48
+ data: {
49
+ files: [],
50
+ uploadInstance: {},
51
+ config: { count: 9, maxDuration: 60 },
42
52
  },
43
53
  methods: {
44
54
  initValue: function () {
@@ -48,17 +58,151 @@ Component({
48
58
  this.setData({ value: v });
49
59
  }
50
60
  },
61
+ mapPreviewFile: function (files) {
62
+ return files.map((i) => ({
63
+ ...i,
64
+ progress: i.percent,
65
+ loading: i.status !== 'success',
66
+ cloudId: i.cloudId || i.cloudPath,
67
+ tempUrl: i.tempFilePath,
68
+ }));
69
+ },
70
+ initUploadInstance: function ({ action, config }) {
71
+ const { files } = this.data;
72
+ const _this = this;
73
+ let uploadInstance = {
74
+ action,
75
+ config: { ...config },
76
+ previewFile: files,
77
+ updatePreviewFile(files) {
78
+ _this.setData({ files: _this.mapPreviewFile(files) });
79
+ },
80
+ getPreviewFile() {
81
+ const { files } = _this.data;
82
+ return files;
83
+ },
84
+ onComplete(result) {
85
+ const files = _this.mapPreviewFile(result);
86
+ _this.setData({
87
+ files,
88
+ });
89
+ const cloudPathList = files.map((i) => i.cloudId).filter((j) => !!j);
90
+ let _value = cloudPathList;
91
+ if (_this.data.single) {
92
+ _value = cloudPathList[0] ?? '';
93
+ }
94
+ _this.handleChange({ detail: { value: _value } });
95
+ },
96
+ onSuccess(res) {
97
+ _this.triggerEvent('success', {
98
+ value: res.cloudPath,
99
+ file: res,
100
+ });
101
+ },
102
+ onFail(e) {
103
+ _this.triggerEvent('error', e);
104
+ },
105
+ beforeUpload: _this.data.callbacks?.beforeUpload,
106
+ };
107
+
108
+ return uploadInstance;
109
+ },
110
+ setConfig: function (_config) {
111
+ const { single, maxUploadCount, config } = this.data;
112
+ const _maxUploadCount = _config.maxUploadCount ?? maxUploadCount;
113
+ // eslint-disable-next-line @typescript-eslint/no-magic-numbers
114
+ const maxCount = single ? 1 : _maxUploadCount;
115
+ const res = { ...config, count: maxCount, ..._config };
116
+ this.setData({ config: res });
117
+ },
118
+ deleteHandle: function ({ cloudId }) {
119
+ const { files, single } = this.data;
120
+ const fileList = files.filter((d) => d.cloudId !== cloudId);
121
+ this.setData({ files: fileList });
122
+
123
+ let value = fileList.map((i) => i?.cloudId).filter((j) => !!j);
124
+
125
+ value = single ? value[0] || '' : value;
126
+
127
+ this.handleChange({ detail: { value: value } });
128
+ },
129
+ setConfigHandle: function ({ config }) {
130
+ this.setConfig(config);
131
+ },
132
+ init: function () {
133
+ const { config } = this.data;
134
+ const uploadInstance = this.initUploadInstance({ action: 'CHOOSE_MEDIA', config });
135
+ this.setData({ uploadInstance });
136
+
137
+ this.setReadonlyAttributes &&
138
+ this.setReadonlyAttributes({
139
+ upload: (_uploadInstance = uploadInstance) => {
140
+ upload(_uploadInstance);
141
+ },
142
+ delete: this.deleteHandle.bind(this),
143
+ uploadInstance,
144
+ setConfig: this.setConfigHandle.bind(this),
145
+ });
146
+ },
147
+ updatePreviewFile: function () {
148
+ const { files } = this.data;
149
+ this.setReadonlyAttributes &&
150
+ this.setReadonlyAttributes({
151
+ previewFile: files,
152
+ });
153
+ },
51
154
  },
52
155
  observers: {
53
- 'name, value, label, required, visible, disabled, readOnly, sourceType':
54
- function () {
55
- this.updateWidgetAPI();
56
- },
156
+ 'name, value, label, required, visible, disabled, readOnly, sourceType': function () {
157
+ this.updateWidgetAPI();
158
+ },
159
+ 'disabled,sourceType,maxUploadCount,sizeType,single': function (disabled, sourceType, maxUploadCount, sizeType) {
160
+ const config = {
161
+ disabled,
162
+ sourceType,
163
+ maxUploadCount,
164
+ sizeType,
165
+ };
166
+ this.setConfig(config);
167
+ },
168
+ config: function () {
169
+ this.init();
170
+ },
171
+ files: function () {
172
+ this.updatePreviewFile();
173
+ },
174
+ value: function (value) {
175
+ const _value = [].concat(value).filter((d) => typeof d === 'string' && d !== '');
176
+
177
+ const previewFileMap = this.data.files.reduce((acc, obj) => {
178
+ acc[obj?.cloudId] = obj; // 使用 cloudId 作为新对象的 key
179
+ return acc;
180
+ }, {});
181
+ if (_value.some((i) => !previewFileMap[i])) {
182
+ const previewFile = _value?.length
183
+ ? _value.map((i) => ({
184
+ progress: 100,
185
+ loading: false,
186
+ cloudId: i,
187
+ tempUrl: '',
188
+ }))
189
+ : [];
190
+ this.setData({ files: previewFile });
191
+ }
192
+ },
57
193
  },
58
194
  lifetimes: {
59
195
  attached: function () {
60
196
  this.initValue();
197
+ const { disabled, sourceType, sizeType } = this.data;
198
+ this.setConfig({ disabled, maxDuration: 60, sourceType, sizeType });
199
+
61
200
  this.updateWidgetAPI();
62
201
  },
202
+ ready: function () {
203
+ this.triggerEvent('onReady', {
204
+ uploadInstance: this.data.uploadInstance,
205
+ });
206
+ },
63
207
  },
64
208
  });
@@ -19,6 +19,10 @@
19
19
  size="{{size}}"
20
20
  borderedH5="{{borderedH5}}"
21
21
  >
22
+ <block wx:if="{{template==='custom'}}">
23
+ <slot></slot>
24
+ </block>
25
+ <block wx:else>
22
26
  <old-image-uploader
23
27
  labelVisible="{{false}}"
24
28
  acceptTypes="{{acceptTypes}}"
@@ -41,5 +45,6 @@
41
45
  bind:success="handleEvent"
42
46
  bind:error="handleEvent"
43
47
  />
48
+ </block>
44
49
  </wd-form-item>
45
50
  </block>
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "miniprogram": "./",
4
4
  "packageManager": "yarn@3.0.2",
5
5
  "dependencies": {},
6
- "version": "3.16.0",
6
+ "version": "3.17.0",
7
7
  "main": "./",
8
8
  "publishConfig": {
9
9
  "access": "public"
package/utils/platform.js CHANGED
@@ -58,11 +58,7 @@ export const getWhereList = (where) => {
58
58
  }
59
59
  let [rel, val] = [REL_DICT[item2?.rel] || item2?.rel, item2?.value];
60
60
  // 去掉空字符串、undefined(接口不支持)、对象类型(接口不支持)
61
- if (
62
- val === '' ||
63
- val === undefined ||
64
- Object.prototype.toString.call(val) === '[object Object]'
65
- ) {
61
+ if (val === '' || val === undefined || Object.prototype.toString.call(val) === '[object Object]') {
66
62
  return;
67
63
  }
68
64
  if ('_begin_with' === rel) {
@@ -115,9 +111,7 @@ export const randomStr = (len = 32) => {
115
111
  * 转换枚举值
116
112
  */
117
113
  export const convertLegacyEnum = (prop, enumObj, defaultValue) => {
118
- const enumValue = enumObj.map((i) => i.value).includes(prop)
119
- ? prop
120
- : enumObj[0].value;
114
+ const enumValue = enumObj.map((i) => i.value).includes(prop) ? prop : enumObj[0].value;
121
115
  if (defaultValue !== undefined) return enumValue || defaultValue;
122
116
  return enumValue;
123
117
  };
@@ -160,3 +154,28 @@ export const convertSingleValue = (value, single) => {
160
154
  }
161
155
  return v;
162
156
  };
157
+
158
+ export const compareVersion = (v1, v2) => {
159
+ v1 = v1.split('.');
160
+ v2 = v2.split('.');
161
+ const len = Math.max(v1.length, v2.length);
162
+
163
+ while (v1.length < len) {
164
+ v1.push('0');
165
+ }
166
+ while (v2.length < len) {
167
+ v2.push('0');
168
+ }
169
+
170
+ for (let i = 0; i < len; i++) {
171
+ const num1 = parseInt(v1[i]);
172
+ const num2 = parseInt(v2[i]);
173
+
174
+ if (num1 > num2) {
175
+ return 1;
176
+ } else if (num1 < num2) {
177
+ return -1;
178
+ }
179
+ }
180
+ return 0;
181
+ };