@cloudbase/weda-ui-mp 3.15.8 → 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.
Files changed (29) hide show
  1. package/components/chart/ec-canvas/ec-canvas.js +1 -25
  2. package/components/form/select/dropdown-select/index.js +8 -0
  3. package/components/form/select/dropdown-select/index.wxml +1 -1
  4. package/components/form/selectMultiple/dropdown-select/index.js +15 -17
  5. package/components/form/selectMultiple/dropdown-select/index.wxml +1 -1
  6. package/components/form/selectMultiple/index.js +29 -7
  7. package/components/form/selectMultiple/index.wxml +2 -1
  8. package/components/form/uploaderFile/index.js +23 -220
  9. package/components/form/uploaderFile/upload.js +283 -0
  10. package/components/richText/copy/index.wxss +45 -48
  11. package/components/wd-ad/index.js +101 -5
  12. package/components/wd-ad/index.wxml +2 -0
  13. package/components/wd-select/index.js +18 -14
  14. package/components/wd-select/index.wxml +7 -3
  15. package/components/wd-select/select/dropdown-select/index.js +192 -0
  16. package/components/wd-select/select/dropdown-select/index.json +4 -0
  17. package/components/wd-select/select/dropdown-select/index.wxml +37 -0
  18. package/components/wd-select/select/dropdown-select/index.wxss +329 -0
  19. package/components/wd-select/select/formats-util.js +12 -1
  20. package/components/wd-select/select/index.js +208 -344
  21. package/components/wd-select/select/index.json +1 -1
  22. package/components/wd-select/select/index.wxml +16 -16
  23. package/components/wd-select-multiple/index.js +16 -8
  24. package/components/wd-select-multiple/index.json +1 -1
  25. package/components/wd-select-multiple/index.wxml +6 -2
  26. package/components/wd-upload-image/index.js +148 -4
  27. package/components/wd-upload-image/index.wxml +5 -0
  28. package/package.json +1 -1
  29. package/utils/platform.js +27 -8
@@ -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: {
@@ -52,6 +52,14 @@ Component({
52
52
  type: Boolean,
53
53
  value: true,
54
54
  },
55
+ searchable: {
56
+ type: Boolean,
57
+ value: true,
58
+ },
59
+ filterable: {
60
+ type: Boolean,
61
+ value: false,
62
+ },
55
63
  },
56
64
  data: {
57
65
  height: '780rpx',
@@ -4,7 +4,7 @@
4
4
  <view wx:if="{{!focus}}" class="weda-ui-custom-picker__header">
5
5
  <button class="weda-ui-custom-picker__header-btn" bindtap="cancelPicker" data-clear="false">取消</button>
6
6
  </view>
7
- <view class="weda-ui-custom-search {{focus?'is-focused':''}}" style="{{focus? 'margin: 34rpx 32rpx 16rpx 32rpx':'margin: 20rpx 32rpx'}}">
7
+ <view wx:if="{{searchable}}" class="weda-ui-custom-search {{focus?'is-focused':''}}" style="{{focus? 'margin: 34rpx 32rpx 16rpx 32rpx':'margin: 20rpx 32rpx'}}">
8
8
  <view class="weda-ui-custom-search-box" bindtap="onFocus">
9
9
  <input class="weda-ui-input" focus="{{focus}}" bindfocus="onFocus" bindblur="onBlur" bindinput="bindinput" value="{{searchValue}}" hold-keyboard="true" bindconfirm="bindconfirm" />
10
10
  <view class="weda-ui-custom-search-box__label">
@@ -36,14 +36,18 @@ Component({
36
36
  type: Boolean,
37
37
  value: true,
38
38
  },
39
- staticSearchable: {
40
- type: Boolean,
41
- value: true,
42
- },
43
39
  selectedValue: {
44
40
  type: Array,
45
41
  value: [],
46
42
  },
43
+ searchable: {
44
+ type: Boolean,
45
+ value: true,
46
+ },
47
+ filterable: {
48
+ type: Boolean,
49
+ value: false,
50
+ },
47
51
  },
48
52
  data: {
49
53
  height: '390px',
@@ -53,18 +57,12 @@ Component({
53
57
  status: 0,
54
58
  showOption: [],
55
59
  searchPageNo: 1,
56
- timeId: '',
57
60
  pageNo: 1,
58
61
  selectedCache: [], // 缓存当前选中值
59
62
  },
60
63
 
61
64
  lifetimes: {
62
- detached() {
63
- const id = this.data.timeId;
64
- if (id !== '') {
65
- clearTimeout(id);
66
- }
67
- },
65
+ detached() {},
68
66
  },
69
67
  methods: {
70
68
  cancelPicker: function (e) {
@@ -179,9 +177,13 @@ Component({
179
177
  },
180
178
  },
181
179
  observers: {
182
- 'option,searchValue,staticSearchable': function (option, searchValue, staticSearchable) {
180
+ 'option,searchValue,filterable': function (option, searchValue, filterable) {
183
181
  const { ignoreCase } = this.properties;
184
- if (staticSearchable) {
182
+ if (filterable) {
183
+ this.setData({
184
+ showOption: option,
185
+ });
186
+ } else {
185
187
  const searchRange = option.filter((item) => {
186
188
  if (ignoreCase) {
187
189
  return String(item.label).toLowerCase().indexOf(searchValue.toLowerCase()) !== -1;
@@ -192,10 +194,6 @@ Component({
192
194
  showOption: searchRange,
193
195
  status: searchRange.length > 0 ? 0 : 3,
194
196
  });
195
- } else {
196
- this.setData({
197
- showOption: option,
198
- });
199
197
  }
200
198
  },
201
199
  selectedValue: function (selectedValue) {
@@ -6,7 +6,7 @@
6
6
  <button class="weda-ui-custom-picker__header-btn" bindtap="closeModal" data-clear="false">取消</button>
7
7
  <button class="weda-ui-custom-picker__header-btn" bindtap="confirmModal">确定</button>
8
8
  </view>
9
- <view class="weda-ui-custom-search {{focus?'is-focused':''}}" style="{{focus? 'margin: 34rpx 32rpx 16rpx 32rpx':'margin: 20rpx 32rpx'}}">
9
+ <view wx:if="{{searchable}}" class="weda-ui-custom-search {{focus?'is-focused':''}}" style="{{focus? 'margin: 34rpx 32rpx 16rpx 32rpx':'margin: 20rpx 32rpx'}}">
10
10
  <view class="weda-ui-custom-search-box" bindtap="onFocus">
11
11
  <input class="weda-ui-input" focus="{{focus}}" bindfocus="onFocus" bindblur="onBlur" bindinput="bindinput" value="{{searchValue}}" hold-keyboard="true" bindconfirm="bindconfirm" />
12
12
  <view class="weda-ui-custom-search-box__label multiple">
@@ -98,6 +98,26 @@ Component({
98
98
  type: Array,
99
99
  value: [],
100
100
  },
101
+ supportManyRelated: {
102
+ type: Boolean,
103
+ value: false,
104
+ },
105
+ queryCondition: {
106
+ type: null,
107
+ value: [],
108
+ },
109
+ sorter: {
110
+ type: Array,
111
+ value: [],
112
+ },
113
+ searchable: {
114
+ type: Boolean,
115
+ value: true,
116
+ },
117
+ filterable: {
118
+ type: Boolean,
119
+ value: false,
120
+ },
101
121
  },
102
122
  data: {
103
123
  cls: '',
@@ -112,15 +132,13 @@ Component({
112
132
  searchOption: [],
113
133
  width: '100%',
114
134
  isEmpty: true,
115
- preWhere: [], // 对比 where 监听
116
- whereEffected: [], // 每次请求都加上
117
135
  fetchTimed: null, // 防抖
118
136
  queryParam: { select: { $master: true } },
119
- staticSearchable: true,
137
+ _filterable: false,
120
138
  },
121
139
  lifetimes: {
122
140
  attached() {
123
- const { className, layout, disabled, range } = this.properties;
141
+ const { className, layout, disabled, range, filterable } = this.properties;
124
142
  const isFlex = layout !== 'vertical';
125
143
  const cls = classNames({
126
144
  'weda-ui': true,
@@ -144,6 +162,7 @@ Component({
144
162
  cls,
145
163
  subCls,
146
164
  displayValue,
165
+ _filterable: filterable,
147
166
  });
148
167
  },
149
168
  ready() {
@@ -172,9 +191,12 @@ Component({
172
191
  });
173
192
  },
174
193
  format: function (format) {
175
- this.setData({
176
- staticSearchable: !['many-many', 'one-many'].includes(format),
177
- });
194
+ if (['many-many', 'one-many'].includes(format)) {
195
+ // 关联关系,自定义查询规则,不走前端过滤
196
+ this.setData({
197
+ _filterable: true,
198
+ });
199
+ }
178
200
  },
179
201
  'value,range': function () {
180
202
  const { range, format } = this.properties;
@@ -13,6 +13,8 @@
13
13
  </view>
14
14
  <block wx:if="{{allPickerShow}}">
15
15
  <dropdownSelect
16
+ searchable="{{searchable}}"
17
+ filterable="{{_filterable}}"
16
18
  class="weui-picker__group weui-input"
17
19
  bindchange="onChange"
18
20
  bind:_childFetchData="_childFetchData"
@@ -24,7 +26,6 @@
24
26
  displayLabel="{{displayLabel}}"
25
27
  selectedValue="{{value}}"
26
28
  ignoreCase="{{ignoreCase}}"
27
- staticSearchable="{{staticSearchable}}"
28
29
  bind:search="onSearch"
29
30
  />
30
31
  </block>
@@ -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,