@cloudbase/weda-ui 3.1.4 → 3.1.9

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.
@@ -94,6 +94,9 @@
94
94
  "title": "数据源",
95
95
  "x-index": 50,
96
96
  "x-component": "chart-datasource-select",
97
+ "x-props": {
98
+ "data-hidebind": true
99
+ },
97
100
  "x-component-props": {
98
101
  "postChange": {
99
102
  "addOrUpdateComponentDataBinds": {
@@ -301,7 +304,8 @@
301
304
  "target": "*(xIsCountEmpty)",
302
305
  "condition": "{{ $self.value && ($self.value.format !=='datetime' && $self.value.format !=='date') }}"
303
306
  }
304
- ]
307
+ ],
308
+ "remarks": "X轴数值字段选择"
305
309
  },
306
310
  "xStatistics": {
307
311
  "title": "统计维度",
@@ -341,7 +345,8 @@
341
345
  "target": "*(groupKey)",
342
346
  "condition": "{{ (!$self.value || !$self.value.numValue || $self.value.numValue.length<=1) && !!$self.__datasourceName }}"
343
347
  }
344
- ]
348
+ ],
349
+ "remarks": "Y轴数值字段选择"
345
350
  },
346
351
  "groupKey": {
347
352
  "type": "object",
@@ -581,7 +586,8 @@
581
586
  "title": "显示数值",
582
587
  "type": "boolean",
583
588
  "x-index": 310,
584
- "default": true
589
+ "default": true,
590
+ "remarks": "数值(Y轴)显示数值"
585
591
  },
586
592
  "dataTagShow": {
587
593
  "x-index": 320,
@@ -594,7 +600,8 @@
594
600
  "title": "显示数值",
595
601
  "type": "boolean",
596
602
  "x-index": 330,
597
- "default": true
603
+ "default": true,
604
+ "remarks": "数据标签显示数值"
598
605
  },
599
606
  "unitShow": {
600
607
  "x-index": 340,
@@ -43,6 +43,9 @@
43
43
  "dataSource": {
44
44
  "type": "object",
45
45
  "title": "数据源",
46
+ "x-props": {
47
+ "data-hidebind": true
48
+ },
46
49
  "x-index": 40,
47
50
  "x-component": "chart-datasource-select",
48
51
  "x-component-props": {
@@ -244,7 +247,8 @@
244
247
  "target": "*(xIsCountEmpty)",
245
248
  "condition": "{{ $self.value && ($self.value.format !=='datetime' && $self.value.format !=='date') }}"
246
249
  }
247
- ]
250
+ ],
251
+ "remarks": "X轴数值字段选择"
248
252
  },
249
253
  "xStatistics": {
250
254
  "title": "统计维度",
@@ -283,7 +287,8 @@
283
287
  "condition": "{{ (!$self.value || !$self.value.numValue || $self.value.numValue.length<=1) && !!$self.__datasourceName }}"
284
288
  }
285
289
  ],
286
- "x-datasource-method-reset": {}
290
+ "x-datasource-method-reset": {},
291
+ "remarks": "Y轴数值字段选择"
287
292
  },
288
293
  "groupKey": {
289
294
  "type": "object",
@@ -527,7 +532,8 @@
527
532
  "type": "boolean",
528
533
  "x-index": 300,
529
534
  "default": true,
530
- "x-category": "高级属性"
535
+ "x-category": "高级属性",
536
+ "remarks": "数值(Y轴)字段选择"
531
537
  },
532
538
  "dataTagShow": {
533
539
  "x-index": 310,
@@ -542,7 +548,8 @@
542
548
  "type": "boolean",
543
549
  "x-index": 320,
544
550
  "default": true,
545
- "x-category": "高级属性"
551
+ "x-category": "高级属性",
552
+ "remarks": "数据标签字段选择"
546
553
  },
547
554
  "unitShow": {
548
555
  "x-index": 330,
@@ -45,6 +45,9 @@
45
45
  "title": "数据源",
46
46
  "x-index": 40,
47
47
  "x-component": "chart-datasource-select",
48
+ "x-props": {
49
+ "data-hidebind": true
50
+ },
48
51
  "x-component-props": {
49
52
  "postChange": {
50
53
  "addOrUpdateComponentDataBinds": {
@@ -242,7 +245,8 @@
242
245
  "target": "*(xIsCountEmpty)",
243
246
  "condition": "{{ $self.value && ($self.value.format !=='datetime' && $self.value.format !=='date') }}"
244
247
  }
245
- ]
248
+ ],
249
+ "remarks": "X轴数值字段选择"
246
250
  },
247
251
  "xStatistics": {
248
252
  "title": "统计维度",
@@ -274,7 +278,8 @@
274
278
  "isMethod": true,
275
279
  "dataSourceNamePropKey": "dataSource",
276
280
  "maxFieldCount": 1
277
- }
281
+ },
282
+ "remarks": "Y轴数值字段选择"
278
283
  },
279
284
  "legendShow": {
280
285
  "x-index": 120,
@@ -355,7 +360,8 @@
355
360
  "type": "boolean",
356
361
  "x-index": 170,
357
362
  "default": true,
358
- "x-category": "高级属性"
363
+ "x-category": "高级属性",
364
+ "remarks": "数据标签字段选择"
359
365
  },
360
366
  "isPercent": {
361
367
  "title": "显示百分比",
@@ -7,21 +7,21 @@
7
7
  "default": "标题",
8
8
  "title": "标题",
9
9
  "x-category": "基础属性",
10
- "x-index": 1
10
+ "x-index": 10
11
11
  },
12
12
  "labelVisible": {
13
13
  "type": "boolean",
14
14
  "default": true,
15
15
  "title": "是否显示标题",
16
16
  "x-category": "基础属性",
17
- "x-index": 2
17
+ "x-index": 20
18
18
  },
19
19
  "requiredFlag": {
20
20
  "type": "boolean",
21
21
  "default": false,
22
22
  "title": "是否显示必填标记",
23
23
  "x-category": "基础属性",
24
- "x-index": 3
24
+ "x-index": 30
25
25
  },
26
26
  "layout": {
27
27
  "title": "布局方式",
@@ -38,35 +38,42 @@
38
38
  }
39
39
  ],
40
40
  "x-category": "基础属性",
41
- "x-index": 4
41
+ "x-index": 40
42
42
  },
43
43
  "name": {
44
44
  "type": "string",
45
45
  "default": "formRichText",
46
46
  "title": "提交后台所用字段",
47
47
  "x-category": "基础属性",
48
- "x-index": 5
48
+ "x-index": 50
49
49
  },
50
50
  "value": {
51
51
  "type": "string",
52
52
  "default": "",
53
53
  "title": "初始值",
54
54
  "x-category": "基础属性",
55
- "x-index": 6
55
+ "x-index": 60
56
56
  },
57
57
  "readOnly": {
58
58
  "type": "boolean",
59
59
  "default": false,
60
60
  "title": "是否只读",
61
61
  "x-category": "基础属性",
62
- "x-index": 7
62
+ "display": false,
63
+ "x-index": 70
64
+ },
65
+ "disabled": {
66
+ "type": "boolean",
67
+ "title": "禁用",
68
+ "default": false,
69
+ "x-index": 75
63
70
  },
64
71
  "maxSize": {
65
72
  "type": "number",
66
73
  "default": 10,
67
74
  "title": "单张图片最大(M)",
68
75
  "x-category": "基础属性",
69
- "x-index": 8
76
+ "x-index": 80
70
77
  },
71
78
  "acceptTypes": {
72
79
  "type": "array",
@@ -105,8 +112,9 @@
105
112
  }
106
113
  ]
107
114
  },
115
+ "display": false,
108
116
  "x-category": "基础属性",
109
- "x-index": 9
117
+ "x-index": 90
110
118
  }
111
119
  }
112
120
  },
@@ -3,6 +3,21 @@ export const sortBy = (props) => {
3
3
  return a[props] - b[props];
4
4
  };
5
5
  };
6
+ const platMaps = {
7
+ PCWEB: 'PC端',
8
+ MOBILEWEB: '移动端',
9
+ MP: '小程序',
10
+ WEB: 'WEB端',
11
+ };
12
+ const platTranslate = (platforms = []) => {
13
+ const platRemark = [];
14
+ if (platforms && platforms.length > 0) {
15
+ platforms.forEach((e) => {
16
+ platRemark.push(platMaps[e]);
17
+ });
18
+ }
19
+ return platRemark;
20
+ };
6
21
  export const objFormat = (args, type, origin) => {
7
22
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
8
23
  //判断属性title值是否为拓展写法
@@ -16,9 +31,9 @@ export const objFormat = (args, type, origin) => {
16
31
  description: ((_e = args[i]) === null || _e === void 0 ? void 0 : _e.remarks) || '-',
17
32
  platforms: args[i]['x-platforms']
18
33
  ? args[i]['x-platforms'].indexOf('MP') > -1
19
- ? '小程序端'
34
+ ? '小程序'
20
35
  : args[i]['x-platforms'].indexOf('WEB') > -1
21
- ? 'web端'
36
+ ? 'WEB端'
22
37
  : '兼容三端'
23
38
  : '兼容三端',
24
39
  });
@@ -30,11 +45,15 @@ export const objFormat = (args, type, origin) => {
30
45
  args[i]['x-component'] == 'Divider') {
31
46
  continue;
32
47
  }
48
+ const titleName = args[i].title.indexOf('{{') != -1
49
+ ? (_h = args[i]) === null || _h === void 0 ? void 0 : _h.title.match(uuidReg)[1]
50
+ : (_j = args[i]) === null || _j === void 0 ? void 0 : _j.title;
33
51
  transformData.push({
34
52
  code: i,
35
- title: args[i].title.indexOf('{{') != -1
36
- ? (_h = args[i]) === null || _h === void 0 ? void 0 : _h.title.match(uuidReg)[1]
37
- : (_j = args[i]) === null || _j === void 0 ? void 0 : _j.title,
53
+ title: titleName +
54
+ (platTranslate(args[i]['x-platforms']).length > 0
55
+ ? '(' + platTranslate(args[i]['x-platforms']).join(',') + ')'
56
+ : ''),
38
57
  description: ((_k = args[i]) === null || _k === void 0 ? void 0 : _k.remarks) || '-',
39
58
  type: ((_l = args[i]) === null || _l === void 0 ? void 0 : _l.type) || '-',
40
59
  default: JSON.stringify((_m = args[i]) === null || _m === void 0 ? void 0 : _m.default) || '-',
@@ -0,0 +1,3 @@
1
+ .weapps__modal {
2
+ z-index: 5001 !important;
3
+ }
@@ -1,3 +1,4 @@
1
+ import './index.css';
1
2
  export default function showModal({ data }: {
2
3
  data: any;
3
4
  }): Promise<unknown>;
@@ -3,6 +3,7 @@ import * as React from 'react';
3
3
  import { forwardRef, useState, useEffect, useImperativeHandle } from 'react';
4
4
  import { Modal, Button, Text, ConfigProvider } from 'tea-component';
5
5
  import { noop } from '../../utils/constant';
6
+ import './index.css';
6
7
  const ModalShow = forwardRef(function ModalShow(props, ref) {
7
8
  const [visible, setVisible] = useState(false);
8
9
  // 渲染之后,马上显示
@@ -70,12 +70,6 @@ export function ImageUploaderH5({ title, maxUploadCount, maxSize = 10, acceptTyp
70
70
  setProgress(percentCompleted);
71
71
  };
72
72
  const uploadToTcb = (file) => {
73
- if ((file === null || file === void 0 ? void 0 : file.type.split('/')[0]) !== 'image') {
74
- weui.alert('请上传图片', {
75
- title: 'Image Type Error',
76
- });
77
- return false;
78
- }
79
73
  setUploading(true);
80
74
  getCloudInstance().then(async (tcb) => {
81
75
  var _a;
@@ -105,6 +99,29 @@ export function ImageUploaderH5({ title, maxUploadCount, maxSize = 10, acceptTyp
105
99
  ? IMAGE_TYPES
106
100
  : Array.from(new Set(acceptTypes));
107
101
  }, [acceptTypes]);
102
+ const islegalType = (files, accepts) => {
103
+ const illegalType = [];
104
+ let isImage = true;
105
+ for (const file of files) {
106
+ if ((file === null || file === void 0 ? void 0 : file.type.split('/')[0]) !== 'image') {
107
+ weui.alert('请上传图片', {
108
+ title: 'Image Type Error',
109
+ });
110
+ isImage = false;
111
+ break;
112
+ }
113
+ accepts.some((item) => item === (file === null || file === void 0 ? void 0 : file.type))
114
+ ? null
115
+ : illegalType.push(file === null || file === void 0 ? void 0 : file.type);
116
+ }
117
+ if (!isImage)
118
+ return false;
119
+ if (illegalType.length > 0) {
120
+ weui.alert('不支持上传' + Array.from(new Set(illegalType)).join(',') + '格式图片');
121
+ return false;
122
+ }
123
+ return true;
124
+ };
108
125
  const showAdd = React.useMemo(() => {
109
126
  if (single) {
110
127
  // single 模式时,仅当数组为空时显示
@@ -125,6 +142,8 @@ export function ImageUploaderH5({ title, maxUploadCount, maxSize = 10, acceptTyp
125
142
  "%")))),
126
143
  showAdd && (React.createElement("div", { className: "weui-uploader__input-box" }, !disabled && (React.createElement("input", { id: "uploaderInput", className: "weui-uploader__input", type: "file", accept: accepts.join(','), multiple: true, onChange: (e) => {
127
144
  const files = [...e.target.files];
145
+ if (!islegalType(files, accepts))
146
+ return;
128
147
  if (files.some((f) => f.size > maxSize * 1024 * 1024)) {
129
148
  weui.alert('请上传不超过10M的图片');
130
149
  return false;
@@ -150,7 +169,8 @@ function SingleImage({ src, deleteBySrc }) {
150
169
  React.useEffect(() => {
151
170
  const getSrc = async () => {
152
171
  try {
153
- const _src = await getTempFileURL(src);
172
+ const url = await getTempFileURL(src);
173
+ const _src = encodeURI(url);
154
174
  setRealSrc(_src);
155
175
  return _src;
156
176
  }
@@ -68,8 +68,36 @@ export function UploaderPCInner(props) {
68
68
  fileRef.current = fileIDList;
69
69
  }
70
70
  });
71
+ //验证上传文件类型是否合法
72
+ const islegalType = (files, accepts) => {
73
+ const illegalType = [];
74
+ let isImage = true;
75
+ for (const file of files) {
76
+ if ((file === null || file === void 0 ? void 0 : file.type.split('/')[0]) !== 'image') {
77
+ message.error({ content: '请上传图片' });
78
+ isImage = false;
79
+ break;
80
+ }
81
+ accepts.some((item) => item === (file === null || file === void 0 ? void 0 : file.type))
82
+ ? null
83
+ : illegalType.push(file === null || file === void 0 ? void 0 : file.type);
84
+ }
85
+ if (!isImage)
86
+ return false;
87
+ if (illegalType.length > 0) {
88
+ message.error({
89
+ content: '不支持上传' +
90
+ Array.from(new Set(illegalType)).join(',') +
91
+ '格式图片',
92
+ });
93
+ return false;
94
+ }
95
+ return true;
96
+ };
71
97
  // 方法:上传前,判断图片大小、数量是否满足,取消默认组件的上传事件,用自定义的 tcb 上传方法
72
98
  const beforeHandle = (file, fileList, isAccepted, error) => {
99
+ if (!islegalType(fileList, extraProps['accept']))
100
+ return;
73
101
  if (!isAccepted) {
74
102
  try {
75
103
  const errorList = [];
@@ -164,7 +192,8 @@ export const TcbImage = (props) => {
164
192
  React.useEffect(() => {
165
193
  const getSrc = async () => {
166
194
  try {
167
- const _src = await getTempFileURL(fileID);
195
+ const url = await getTempFileURL(fileID);
196
+ const _src = encodeURI(url);
168
197
  _src ? setSrc(_src) : setIsError(true);
169
198
  }
170
199
  catch (e) {
@@ -83,15 +83,29 @@ events = emptyObject, defaultValue, uploadPath = 'weda-uploader', single = true,
83
83
  ? ['*']
84
84
  : Array.from(new Set(acceptTypes));
85
85
  }, [acceptTypes]);
86
+ const islegalType = (files, accepts) => {
87
+ const illegalType = [];
88
+ for (const file of files) {
89
+ accepts.some((item) => item === (file === null || file === void 0 ? void 0 : file.type))
90
+ ? null
91
+ : illegalType.push(file === null || file === void 0 ? void 0 : file.type);
92
+ }
93
+ if (illegalType.length > 0) {
94
+ weui.alert('不支持上传' + Array.from(new Set(illegalType)).join(',') + '格式文件');
95
+ return false;
96
+ }
97
+ return true;
98
+ };
86
99
  // 上传后文件列表 fileIDList 改变事件,'add'|'delete'
87
100
  const handleChange = ({ fileID, uuid, type, size }) => {
88
101
  // 上传时新增事件
89
102
  if (type === 'add') {
90
103
  fileID && setFileSizeObj((obj) => ({ ...obj, [fileID]: size }));
91
- fileID && setfileIDList([...fileIDList, fileID]);
104
+ fileID && setfileIDList((fileIDList) => [...fileIDList, fileID]);
92
105
  }
93
106
  else {
94
- fileID && setfileIDList(fileIDList.filter((f) => f !== fileID));
107
+ fileID &&
108
+ setfileIDList((fileIDList) => fileIDList.filter((f) => f !== fileID));
95
109
  }
96
110
  uuid && setFileList((list) => list.filter((item) => uuid !== (item === null || item === void 0 ? void 0 : item._uuid)));
97
111
  };
@@ -120,6 +134,12 @@ events = emptyObject, defaultValue, uploadPath = 'weda-uploader', single = true,
120
134
  React.createElement("div", null, btnDisabled ? (React.createElement(Button, { type: "weak", className: classNames(`${CLASS_PREFIX}__btn--weak`), disabled: btnDisabled }, btnTitle)) : (React.createElement("div", null,
121
135
  React.createElement("input", { id: "uploaderInput", type: "file", "data-testid": "button-up", className: "weui-uploader-mobile__input", accept: accepts.join(','), multiple: !single, onChange: (e) => {
122
136
  const fileList = [...e.target.files];
137
+ //校验逻辑与图片有出入,文件类型限制为全部时,不设限
138
+ if (!(accepts.includes('*') ||
139
+ accepts.includes('') ||
140
+ accepts.length === 0) &&
141
+ !islegalType(fileList, accepts))
142
+ return;
123
143
  if (single && fileList.length > 1) {
124
144
  weui.alert(`上传文件总数不能超过1个`);
125
145
  return false;
@@ -68,6 +68,11 @@ acceptTypes = emptyArray, downloadVisible = true, deleteVisible = true, uploadPa
68
68
  });
69
69
  // 批量上传文件前置事件
70
70
  const handleBefore = (file, fileList, isAccepted, error) => {
71
+ if (!((acceptTypes === null || acceptTypes === void 0 ? void 0 : acceptTypes.includes('*')) ||
72
+ (acceptTypes === null || acceptTypes === void 0 ? void 0 : acceptTypes.includes('')) ||
73
+ (acceptTypes === null || acceptTypes === void 0 ? void 0 : acceptTypes.length) === 0) &&
74
+ !islegalType(fileList, uploadProps['accept']))
75
+ return;
71
76
  if (fileList.length + fileIDList.length > maxUploadCount) {
72
77
  message.warning({ content: `上传文件总数不能超过${maxUploadCount}个` });
73
78
  return false;
@@ -112,6 +117,24 @@ acceptTypes = emptyArray, downloadVisible = true, deleteVisible = true, uploadPa
112
117
  tips && (uploadProps['title'] = tips);
113
118
  maxSize && (uploadProps['maxSize'] = maxSize * 1024 * 1024);
114
119
  const btnDisabled = fileIDList.length >= maxUploadCount || (single && fileIDList.length > 0);
120
+ //验证上传文件类型是否合法
121
+ const islegalType = (files, accepts) => {
122
+ const illegalType = [];
123
+ for (const file of files) {
124
+ accepts.some((item) => item === (file === null || file === void 0 ? void 0 : file.type))
125
+ ? null
126
+ : illegalType.push(file === null || file === void 0 ? void 0 : file.type);
127
+ }
128
+ if (illegalType.length > 0) {
129
+ message.error({
130
+ content: '不支持上传' +
131
+ Array.from(new Set(illegalType)).join(',') +
132
+ '格式文件',
133
+ });
134
+ return false;
135
+ }
136
+ return true;
137
+ };
115
138
  return renderDecorator(React.createElement(ConfigProvider, { classPrefix: "wedatea2td" },
116
139
  React.createElement(FileContext.Provider, { value: {
117
140
  uploadPath,
@@ -121,9 +144,9 @@ acceptTypes = emptyArray, downloadVisible = true, deleteVisible = true, uploadPa
121
144
  isEdit,
122
145
  events,
123
146
  fileSizeObj,
124
- } },
125
- React.createElement("div", { className: `${CLASS_PREFIX}` },
126
- isEdit && (React.createElement("div", { className: `${CLASS_PREFIX}__input-box` }, disabled || btnDisabled ? (React.createElement(Button, { type: "weak", disabled: true }, btnTitle)) : (React.createElement(Upload, { ...uploadProps, beforeUpload: handleBefore },
147
+ }, "data-testid": "button-up" },
148
+ React.createElement("div", { className: `${CLASS_PREFIX}`, "data-testid": "UploadFilePc" },
149
+ isEdit && (React.createElement("div", { className: `${CLASS_PREFIX}__input-box` }, disabled || btnDisabled ? (React.createElement(Button, { type: "weak", disabled: true }, btnTitle)) : (React.createElement(Upload, { ...uploadProps, beforeUpload: handleBefore, "data-testid": "Upload" },
127
150
  React.createElement(Button, { type: "weak", className: `${CLASS_PREFIX}__btn--weak` }, btnTitle),
128
151
  !single && (React.createElement(Text, { theme: "weak", className: `${CLASS_PREFIX}__btn-descripe` }, "\u652F\u6301\u6279\u91CF\u4E0A\u4F20")))))),
129
152
  React.createElement(List, { split: "divide" },
@@ -27,6 +27,21 @@
27
27
  margin: 5PX 0PX 5PX 0PX !important;
28
28
  }
29
29
 
30
+ .weda-richText .bf-controlbar .control-item.button-indent-increase,
31
+ .weda-richText .bf-controlbar .control-item.button-indent-decrease,
32
+ .weda-richText .bf-controlbar .control-item[data-alignment='left'],
33
+ .weda-richText .bf-controlbar .control-item[data-alignment='center'],
34
+ .weda-richText .bf-controlbar .control-item[data-alignment='right'],
35
+ .weda-richText .bf-controlbar .control-item[data-alignment='justify'],
36
+ .weda-richText .bf-controlbar .control-item.link-editor-dropdown,
37
+ .weda-richText .bf-controlbar .control-item[data-title='清除链接'] {
38
+ margin-top: 0 !important;
39
+ }
40
+
41
+ .weda-richText .weda-formcells__content .weui-cell_form {
42
+ padding-top: 0;
43
+ }
44
+
30
45
  .weda-richText .headings-dropdown {
31
46
  min-width: auto !important;
32
47
  }
@@ -40,11 +55,6 @@
40
55
  min-width: auto !important;
41
56
  }
42
57
 
43
- .weda-richText .weda-formcells__content .weui-cell {
44
- padding-left: 0 !important;
45
- padding-right: 0 !important;
46
- }
47
-
48
58
  .weda-richText {
49
59
  width: 100%;
50
60
  }
@@ -89,5 +99,9 @@
89
99
  }
90
100
 
91
101
  .weda-richText .weda-formcells__content.weui-flex__item {
92
- margin-right: 2.28571rem;
102
+ margin-top: 1.14286rem;
103
+ }
104
+
105
+ .weda-richText .bf-font-size-dropdown {
106
+ min-width: 4.14286rem;
93
107
  }
@@ -21,14 +21,13 @@ declare function RichText({ id, style, className, events, label, labelVisible, v
21
21
  declare namespace RichText {
22
22
  var defaultProps: {
23
23
  events: {};
24
- style: {
25
- width: string;
26
- };
24
+ style: {};
27
25
  label: string;
28
26
  labelVisible: boolean;
29
27
  name: string;
30
28
  value: string;
31
29
  readOnly: boolean;
30
+ disabled: boolean;
32
31
  layout: string;
33
32
  requiredFlag: boolean;
34
33
  maxSize: number;
@@ -1,17 +1,19 @@
1
- import React, { useEffect, useMemo, useState } from 'react';
1
+ import React, { useEffect, useMemo, useRef, useState } from 'react';
2
2
  import { useSetState } from '../../utils/useSetState';
3
3
  import classNames from '../../utils/classnames';
4
- import Editor, { convertEditorStateToHTML } from 'kedao';
5
- import { ContentUtils } from 'kedao/lib/utils';
4
+ import Editor, { EditorState, convertEditorStateToHTML } from 'kedao';
5
+ import { insertMedias, handleKeyCommand } from 'kedao/lib/utils';
6
6
  import { createStateFromContent } from 'kedao/lib/editor';
7
- import { getCloudInstance, getTempFileURL } from '../../utils/tcb';
7
+ import { getCloudInstance } from '../../utils/tcb';
8
8
  import { message, Button, Input, Modal, Progress, Upload, Text, } from 'tea-component';
9
9
  import { v4 as uuidv4 } from 'uuid';
10
10
  import { defaultBase64 } from './const';
11
11
  import { renderDecorator } from '../form/renderDecorator';
12
12
  import { usePlatform } from '../../utils/platform';
13
13
  import './index.css';
14
+ import styleM from './richtext.module.css';
14
15
  import { useSyncedRef } from '@react-hookz/web';
16
+ import { useTempUrl } from '../../utils/use-cloud-id-temp-url';
15
17
  // 默认图片类型
16
18
  const IMAGE_TYPES = [
17
19
  'image/jpeg',
@@ -21,6 +23,36 @@ const IMAGE_TYPES = [
21
23
  'image/tiff',
22
24
  'image/svg+xml',
23
25
  ];
26
+ const defaultControls = [
27
+ 'undo',
28
+ 'redo',
29
+ 'separator',
30
+ 'headings',
31
+ 'separator',
32
+ 'font-size',
33
+ 'separator',
34
+ 'line-height',
35
+ 'letter-spacing',
36
+ 'text-color',
37
+ 'bold',
38
+ 'italic',
39
+ 'underline',
40
+ 'strike-through',
41
+ 'superscript',
42
+ 'subscript',
43
+ 'remove-styles',
44
+ 'emoji',
45
+ 'text-indent',
46
+ 'text-align',
47
+ 'list-ul',
48
+ 'list-ol',
49
+ 'blockquote',
50
+ 'code',
51
+ 'link',
52
+ 'hr',
53
+ 'media',
54
+ 'clear',
55
+ ];
24
56
  export default function RichText({
25
57
  // 系统属性
26
58
  id, style, className, events,
@@ -37,37 +69,75 @@ label, labelVisible, value: initialValue, readOnly, layout, requiredFlag, onChan
37
69
  const isH5 = platform === 'h5';
38
70
  const subCls = classNames({
39
71
  'weui-cell': isH5,
40
- 'weui-cell_active': isH5,
72
+ // 'weui-cell_active': isH5,
41
73
  'weui-cell_form': isH5,
42
74
  'weui-cell_disabled': isH5 && disabled,
43
75
  });
76
+ const previousValueRef = useRef();
44
77
  const onDataChange = function (value) {
45
- events.change && events.change({ value: value === '<p></p>' ? '' : value });
46
- if (onChange) {
47
- if (value === '<p></p>') {
48
- onChange('');
49
- }
50
- else {
51
- onChange(value);
78
+ if (previousValueRef.current !== value) {
79
+ events.change &&
80
+ events.change({ value: value === '<p></p>' ? '' : value });
81
+ if (onChange) {
82
+ if (value === '<p></p>') {
83
+ onChange('');
84
+ }
85
+ else {
86
+ onChange(value);
87
+ }
52
88
  }
53
89
  }
90
+ previousValueRef.current = value;
54
91
  };
55
92
  useEffect(() => {
56
93
  const state = createStateFromContent(initialValue, {});
57
94
  setEditorState(state);
58
95
  }, []);
59
- const extendControls = useMemo(() => {
60
- return [
61
- {
62
- key: 'richtext-uploader',
63
- type: 'component',
64
- component: (React.createElement(CustomUploader, { acceptTypes: acceptTypes, maxSize: maxSize, cloudPath: cloudPath, onChange: (url) => {
65
- const state = ContentUtils.insertMedias(latestEditorState.current, [{ type: 'IMAGE', url }]);
66
- setEditorState(state);
67
- } })),
68
- },
96
+ const excludeControls = useMemo(() => {
97
+ const result = [
98
+ 'media',
99
+ 'fullscreen',
100
+ 'line-height',
101
+ 'letter-spacing',
102
+ 'emoji',
103
+ 'superscript',
104
+ 'subscript',
69
105
  ];
70
- }, [setEditorState, acceptTypes, maxSize, cloudPath, ContentUtils]);
106
+ if (isH5) {
107
+ result.push('separator', 'undo', 'redo', 'blockquote', 'code', 'link', 'hr', 'list-ul', 'list-ol', 'hr', 'clear', 'text-indent',
108
+ // 'font-size',
109
+ 'headings', 'remove-styles', 'text-align');
110
+ }
111
+ return result;
112
+ }, [isH5]);
113
+ const extendControls = useMemo(() => {
114
+ if (!isH5) {
115
+ return [
116
+ {
117
+ key: 'richtext-uploader',
118
+ type: 'component',
119
+ component: (React.createElement(CustomUploader, { acceptTypes: acceptTypes, maxSize: maxSize, cloudPath: cloudPath, onChange: (url) => {
120
+ const state = insertMedias(latestEditorState.current, [
121
+ { type: 'IMAGE', url },
122
+ ]);
123
+ setEditorState((curState) => {
124
+ const currentSelection = curState.getSelection();
125
+ EditorState.forceSelection(state, currentSelection);
126
+ return state;
127
+ });
128
+ } })),
129
+ },
130
+ ];
131
+ }
132
+ }, [
133
+ acceptTypes,
134
+ maxSize,
135
+ cloudPath,
136
+ latestEditorState,
137
+ insertMedias,
138
+ setEditorState,
139
+ isH5,
140
+ ]);
71
141
  // 修改img显示逻辑
72
142
  const blockRenderFn = (contentBlock, { editor, editorState }) => {
73
143
  var _a;
@@ -87,12 +157,8 @@ label, labelVisible, value: initialValue, readOnly, layout, requiredFlag, onChan
87
157
  }
88
158
  };
89
159
  const richTextEl = (React.createElement("div", { className: subCls },
90
- React.createElement("div", { style: {
91
- border: '1px solid #d1d1d1',
92
- backgroundColor: '#fff',
93
- ...style,
94
- } },
95
- React.createElement(Editor, { key: id, value: editorState, readOnly: readOnly, language: "zh", blockRendererFn: blockRenderFn, onBlur: (s) => {
160
+ React.createElement("div", { style: style, className: styleM.richtextInner },
161
+ React.createElement(Editor, { key: id, value: editorState, readOnly: readOnly, disabled: disabled, language: "zh", blockRendererFn: blockRenderFn, onBlur: (s) => {
96
162
  setEditorState(s);
97
163
  const html = convertEditorStateToHTML(s, {});
98
164
  onDataChange(html);
@@ -101,11 +167,10 @@ label, labelVisible, value: initialValue, readOnly, layout, requiredFlag, onChan
101
167
  content: '富文本长度过长,可能导致保存失败',
102
168
  });
103
169
  }
104
- }, excludeControls: ['media', 'fullscreen'],
170
+ }, controls: defaultControls, excludeControls: excludeControls,
105
171
  /** @ts-ignore jsx */
106
172
  extendControls: extendControls, handleKeyCommand: (command, editState) => {
107
- const newState = ContentUtils.handleKeyCommand(editState, command);
108
- console.log(newState, editState, command);
173
+ const newState = handleKeyCommand(editState, command);
109
174
  if (newState) {
110
175
  setEditorState(newState);
111
176
  return true;
@@ -158,10 +223,8 @@ export const CustomUploader = (props) => {
158
223
  };
159
224
  return (React.createElement(React.Fragment, null,
160
225
  React.createElement("button", { role: "richtext", type: "button", "data-title": "\u5A92\u4F53\u4E0A\u4F20", className: "control-item button", onClick: () => setState({ visible: true }) },
161
- React.createElement("svg", { viewBox: "64 64 896 896", focusable: "false", "data-icon": "file-image", width: "1em", height: "1em", fill: "currentColor", "aria-hidden": "true" },
162
- React.createElement("path", { d: "M534 352V136H232v752h560V394H576a42 42 0 01-42-42zm-134 50c22.1 0 40 17.9 40 40s-17.9 40-40 40-40-17.9-40-40 17.9-40 40-40zm296 294H328.1c-6.7 0-10.4-7.7-6.3-12.9l99.8-127.2a8 8 0 0112.6 0l41.1 52.4 77.8-99.2a8.1 8.1 0 0112.7 0l136.5 174c4.1 5.2.4 12.9-6.3 12.9z", fill: "#e6f7ff" }),
163
- React.createElement("path", { d: "M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM602 137.8L790.2 326H602V137.8zM792 888H232V136h302v216a42 42 0 0042 42h216v494z", fill: "#006eff" }),
164
- React.createElement("path", { d: "M553.1 509.1l-77.8 99.2-41.1-52.4a8 8 0 00-12.6 0l-99.8 127.2a7.98 7.98 0 006.3 12.9H696c6.7 0 10.4-7.7 6.3-12.9l-136.5-174a8.1 8.1 0 00-12.7 0zM360 442a40 40 0 1080 0 40 40 0 10-80 0z", fill: "#006eff" }))),
226
+ React.createElement("svg", { width: "17", height: "16", viewBox: "0 0 17 16", fill: "none", xmlns: "http://www.w3.org/2000/svg" },
227
+ React.createElement("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M13.6205 1.61428V3.60631L15.6105 3.6063L15.6105 5.1063L13.6205 5.10631V7.08572H12.1205V5.10633L10.1391 5.10635L10.139 3.60635L12.1205 3.60633V1.61428H13.6205ZM8.84998 2.38572H2.49536C1.94308 2.38572 1.49536 2.83343 1.49536 3.38572V11.6761V13.3857C1.49536 13.403 1.4958 13.4201 1.49666 13.4372C1.5019 13.5405 1.52282 13.6397 1.5571 13.7324C1.69808 14.1138 2.06497 14.3857 2.49536 14.3857H4.49757H4.76178H12.4954C13.0476 14.3857 13.4954 13.938 13.4954 13.3857V13.2088L13.4954 13.2088V11.0909L13.4954 11.0909V8.38572H11.9954V9.59579L10.2484 7.85452L9.71895 7.32678L9.18948 7.85452L6.4372 10.5979L5.03662 9.20183L4.50715 8.67408L3.97769 9.20183L2.99536 10.181V3.88572H8.84998V2.38572ZM2.99536 12.8857V12.2988L4.50715 10.792L5.37481 11.6568L4.14188 12.8857H2.99536ZM11.9954 12.8857H6.26667L9.71895 9.44465L11.9954 11.7137V12.8857Z", fill: "#6A6F7B" }))),
165
228
  React.createElement(Modal, { onClose: () => {
166
229
  setState({ visible: false });
167
230
  }, visible: visible, maskClosable: true },
@@ -235,38 +298,28 @@ export const CustomUploader = (props) => {
235
298
  React.createElement(Text, { theme: "weak" }, "/\u62D6\u62FD\u5230\u6B64\u533A\u57DF")))))),
236
299
  uploading && (React.createElement(Progress, { style: { marginTop: '10px' }, percent: percent })))));
237
300
  };
301
+ const Img = React.memo(function Img(props) {
302
+ const { src, style, onError } = props;
303
+ const { data: realSrc, error } = useTempUrl(src);
304
+ const realstyle = useMemo(() => {
305
+ if (error) {
306
+ return { ...style, width: '80px' };
307
+ }
308
+ return style;
309
+ }, [error, style]);
310
+ return (React.createElement("img", { src: error ? defaultBase64 : realSrc, style: realstyle, onError: () => {
311
+ onError === null || onError === void 0 ? void 0 : onError();
312
+ } }));
313
+ });
314
+ const imgStyle = { maxWidth: '100%' };
238
315
  export const RichTextImg = ({ contentState, block }) => {
239
316
  const blockData = contentState.getEntity(block.getEntityAt(0)).getData();
240
317
  const { url } = blockData || {};
241
- const [src, setSrc] = React.useState('');
242
- const [width, setWidth] = React.useState('unset');
243
- useEffect(() => {
244
- const getSrc = async () => {
245
- try {
246
- if (url.includes('cloud://')) {
247
- const _src = await getTempFileURL(url);
248
- setSrc(_src || url);
249
- }
250
- else {
251
- setSrc(url);
252
- }
253
- }
254
- catch (e) {
255
- message.error({
256
- content: `显示图片失败:${e.message || '未知原因'}`,
257
- });
258
- }
259
- };
260
- getSrc();
261
- }, [url]);
262
- return (src && (React.createElement(React.Fragment, null,
318
+ return (url && (React.createElement(React.Fragment, null,
263
319
  React.createElement("div", { className: "bf-media" },
264
320
  React.createElement("div", { draggable: "true", className: "bf-image", style: { float: 'left' } },
265
321
  React.createElement("div", { style: { position: 'relative', display: 'inline-block' } },
266
- React.createElement("img", { src: src, style: { maxWidth: '100%', width }, onError: () => {
267
- setSrc(defaultBase64);
268
- setWidth('80px');
269
- } }),
322
+ React.createElement(Img, { src: url, style: imgStyle }),
270
323
  React.createElement("div", { className: "bf-pre-csize" }))),
271
324
  React.createElement("div", { style: {
272
325
  clear: 'both',
@@ -278,13 +331,14 @@ export const RichTextImg = ({ contentState, block }) => {
278
331
  RichText.defaultProps = {
279
332
  // 系统属性
280
333
  events: {},
281
- style: { width: '100%' },
334
+ style: {},
282
335
  // 组件属性
283
336
  label: '标题',
284
337
  labelVisible: true,
285
338
  name: 'formRichText',
286
339
  value: '',
287
- readOnly: false,
340
+ readOnly: true,
341
+ disabled: true,
288
342
  layout: 'vertical',
289
343
  requiredFlag: false,
290
344
  maxSize: 10,
@@ -0,0 +1,5 @@
1
+ .richtext_richtextInner__-9STf {
2
+ border: 0.07143rem solid #d1d1d1;
3
+ background-color: #fff;
4
+ width: 100%;
5
+ }
@@ -0,0 +1 @@
1
+ export declare function useTempUrl(cloudId: string): import("swr").SWRResponse<any, any>;
@@ -0,0 +1,13 @@
1
+ import useSWR from 'swr';
2
+ import { getTempFileURL } from './tcb';
3
+ export function useTempUrl(cloudId) {
4
+ const prefix = 'tcb:cloud-id:temp-url';
5
+ const key = `${prefix}:${cloudId}`;
6
+ return useSWR(key, async () => {
7
+ if (!cloudId.startsWith('cloud://')) {
8
+ return cloudId;
9
+ }
10
+ const tempUrl = await getTempFileURL(cloudId);
11
+ return tempUrl;
12
+ });
13
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudbase/weda-ui",
3
- "version": "3.1.4",
3
+ "version": "3.1.9",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index",
6
6
  "miniprogram": "mpdist",
@@ -64,12 +64,13 @@
64
64
  "dayjs": "^1.10.7",
65
65
  "destr": "^1.1.1",
66
66
  "echarts": "^5.3.0",
67
- "kedao": "0.1.13",
67
+ "kedao": "^0.1.24",
68
68
  "lodash.isequal": "^4.5.0",
69
69
  "object.fromentries": "^2.0.5",
70
70
  "prop-types": "^15.7.2",
71
71
  "react-easy-swipe": "0.0.22",
72
72
  "spark-md5": "^3.0.2",
73
+ "swr": "^1.3.0",
73
74
  "tdesign-icons-react": "0.0.8",
74
75
  "tea-component": "^2.7.3",
75
76
  "uuid": "8.3.2",