form-driver 0.2.4 → 0.3.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "form-driver",
3
- "version": "0.2.4",
3
+ "version": "0.3.0",
4
4
  "description": "An efficient framework for creating forms.",
5
5
  "license": "MIT",
6
6
  "authors": [
@@ -14,7 +14,7 @@
14
14
  "b": "npm run clean && npm run build",
15
15
  "i": "yarn",
16
16
  "ri": "rm -rf node_modules && npm run i",
17
- "pub": "git pull && git add . && git commit -m 'update' & npm run b && npm version patch && npm publish && git push",
17
+ "pub": "npm run b && git pull && git add . && git commit -m 'update' && npm version patch && npm publish && git push",
18
18
  "patch": "npm version patch && npm publish && git push",
19
19
  "submodule": "git submodule update --init",
20
20
  "ut-pull": "cd ./demo/src/ut_autoTest/ut_case && git pull",
@@ -56,6 +56,7 @@
56
56
  "dependencies": {
57
57
  "@ant-design/icons": "^4.3.0",
58
58
  "@babel/runtime": "^7.9.2",
59
+ "ali-oss": "^6.17.1",
59
60
  "lodash": "^4.17.20",
60
61
  "antd": "4.18.7",
61
62
  "antd-mobile": "^2.3.4",
@@ -51,7 +51,10 @@ import { AKvSet } from '../ui/editor/basic/AKvSet';
51
51
  import { ACascadePicker } from '../ui/editor/basic/ACascadePicker';
52
52
  import { MCascadeType } from '../types/MCascadeType';
53
53
  import editorMap from './editorMap';
54
+ import OssUpload from "../plugins/ossUpload/index";
54
55
 
56
+ // 在 m3 中注册oss上传插件
57
+ assembly.addType(OssUpload);
55
58
 
56
59
  let init = false;
57
60
  /**
@@ -0,0 +1,276 @@
1
+ import React from "react";
2
+ import OSS from 'ali-oss';
3
+ import { Upload, Row, Col, Button, Tooltip, Modal, List, Progress, Divider, message } from 'antd';
4
+ import { CloseOutlined, CaretRightOutlined } from '@ant-design/icons';
5
+ import { Ajax, Viewer } from "../../index";
6
+ import './index.less';
7
+
8
+
9
+ class OssUpload extends Viewer {
10
+ constructor(p) {
11
+ super(p);
12
+ this.state = {
13
+ isBeforeUploadExecuted: false,
14
+ fileListStatus: [],
15
+ ossOption: {},
16
+ attachmentVisible: false,
17
+ loading: false,
18
+ keyPath: '',
19
+ resList: (super.getValue() || []).map((item, index) => {
20
+ if (!item.uid) item.uid = index
21
+ return item
22
+ })
23
+ }
24
+ this.options = Object.assign({
25
+ changeHandle: () => { },
26
+ resFormat: res => res,
27
+ srcFormat: src => src,
28
+ multipartUploadConf: {
29
+ parallel: 3,
30
+ partSize: 1024 * 1024 * 2,
31
+ timeout: 30000,
32
+ }
33
+ }, p.schema.props)
34
+ }
35
+
36
+ changeFileList = (list) => {
37
+ console.log('changeFileList', list)
38
+ this.setState({
39
+ resList: list
40
+ })
41
+ super.changeValue(list)
42
+ }
43
+
44
+ componentDidMount() {
45
+ const { oss_upload_token } = this.options
46
+ if (oss_upload_token) {
47
+ const createOss = () => {
48
+ if (oss_upload_token) {
49
+ // 该接口需要返回 OSS 的实例化配置信息
50
+ Ajax.get(oss_upload_token.url, oss_upload_token.params).then(({ data }) => {
51
+ console.log('oss_upload_token', data)
52
+ this.setState({ keyPath: data.keyPath })
53
+ this._client = new OSS({
54
+ ...data,
55
+ stsToken: data.securityToken
56
+ })
57
+ })
58
+ }
59
+ };
60
+ createOss();
61
+ // 保持 oss 连接
62
+ this._timer = window.setInterval(createOss, 55 * 60 * 1000);
63
+ }
64
+ }
65
+
66
+ cancleUpload = () => {
67
+ if (this._client) this._client.cancel();
68
+ this.setState({ loading: false });
69
+ }
70
+
71
+ componentWillUnmount() {
72
+ window.clearInterval(this._timer);
73
+ // 关闭页面的时候取消上传
74
+ this.cancleUpload();
75
+ this._client = null
76
+ }
77
+
78
+ onRemove = (file) => {
79
+ const list = this.state.resList?.filter(i => file.uid !== i.uid)
80
+ this.changeFileList(list)
81
+ }
82
+
83
+ // 自动断点续传
84
+ upload = (name, file, config) => {
85
+ const { multipartUploadConf } = this.options
86
+ const { fileListStatus, resList } = this.state
87
+ return this._client.multipartUpload(name, file, config)
88
+ .then(res => {
89
+ console.log('this._client.multipartUpload: result:', res)
90
+ // 单个上传成功, 记录了到结果
91
+ this.changeFileList([...resList, {
92
+ uid: file.uid,
93
+ name: file.name,
94
+ keyPath: res.name
95
+ }]);
96
+ })
97
+ .catch(async e => {
98
+ if (e && e.name && e.name === 'cancel') {
99
+ return
100
+ } else {
101
+ const current = fileListStatus.find(item => item.file.uid === file.uid)
102
+ if (current.count <= 100) {
103
+ this.setState({
104
+ fileListStatus: fileListStatus.map(item => {
105
+ if (item.file.uid === file.uid) {
106
+ item.count = item.count + 1;
107
+ }
108
+ return item
109
+ })
110
+ })
111
+ // 自动续传
112
+ this.upload(name, file, {
113
+ progress: (p, checkpoint) => this.progress(p, checkpoint, file),
114
+ checkpoint: current.checkpoint,
115
+ ...multipartUploadConf
116
+ })
117
+ } else {
118
+ this.setState({
119
+ fileListStatus: fileListStatus.map(item => {
120
+ if (item.file.uid === file.uid) {
121
+ item.breakName = name;
122
+ item.breakFile = file;
123
+ item.status = 'exception';
124
+ }
125
+ return item
126
+ })
127
+ })
128
+ }
129
+ }
130
+ });
131
+ }
132
+
133
+ // 进度条
134
+ progress = (p, checkpoint, file) => {
135
+ const { fileListStatus } = this.state
136
+ this.setState({
137
+ fileListStatus: fileListStatus.map(item => {
138
+ if (item.file.uid === file.uid) {
139
+ item.percent = Math.floor(p * 100)
140
+ item.checkpoint = checkpoint
141
+ }
142
+ return item
143
+ })
144
+ })
145
+ return function (done) {
146
+ done();
147
+ };
148
+ }
149
+
150
+ element() {
151
+ const { multiple = false, accept = '', multipartUploadConf, maxSize, maxAmount } = this.options
152
+ const { loading, fileListStatus, keyPath, attachmentVisible, resList } = this.state
153
+
154
+ // 上传配置
155
+ const uploadProps = {
156
+ multiple,
157
+ accept,
158
+ onRemove: this.onRemove,
159
+ customRequest: async ({ file }) => {
160
+ // 一个个上传的
161
+ console.log('customRequest->fileList:', file)
162
+ this.setState({ loading: true });
163
+ await this.upload(`${keyPath}/${file.name}`, file, {
164
+ progress: (p, checkpoint) => this.progress(p, checkpoint, file),
165
+ ...multipartUploadConf
166
+ })
167
+ this.setState({ loading: false });
168
+ },
169
+ beforeUpload: (file, fileList) => {
170
+ // 这里可以拿到上传的所有文件
171
+ console.log('beforeUpload->fileList:', file, fileList)
172
+ if (fileList.length >= maxAmount) {
173
+ message.error(`已达到文件数量上限(${maxAmount}个),请删除后上传`);
174
+ return false
175
+ }
176
+ if (file.size > maxSize * 1024 * 1024) {
177
+ message.error(`文件大小超过${maxSize}MB,请压缩后上传`);
178
+ return false
179
+ }
180
+ this.setState({
181
+ fileList,
182
+ fileListStatus: fileList.map(item => ({ file: item, count: 1, percent: 0 })),
183
+ attachmentVisible: true,
184
+ })
185
+ }
186
+ };
187
+
188
+ return (
189
+ <div>
190
+ <Upload disabled={loading} {...uploadProps} fileList={resList}>
191
+ <Button disabled={loading} loading={loading}>点击上传</Button>
192
+ </Upload>
193
+ {/* 上传弹窗 */}
194
+ <div
195
+ className={'m3-plugin-ossupload-progress-modal'}
196
+ style={{ visibility: attachmentVisible ? 'visible' : 'hidden', zIndex: 999 }}
197
+ >
198
+ <Row>
199
+ <Col span={20}>附件上传</Col>
200
+ <Col span={4} className={'cancel-icon'}>
201
+ <CloseOutlined onClick={() => {
202
+ if (this._client && loading) {
203
+ Modal.confirm({
204
+ content: '有文件正在上传中,关闭此窗口将中断文件上传!',
205
+ onText: '关闭',
206
+ maskClosable: false,
207
+ onOk: () => {
208
+ this.cancleUpload()
209
+ this.setState({
210
+ fileList: [],
211
+ fileListStatus: [],
212
+ attachmentVisible: false
213
+ })
214
+ }
215
+ })
216
+ } else {
217
+ this.setState({
218
+ fileList: [],
219
+ fileListStatus: [],
220
+ attachmentVisible: false
221
+ })
222
+ }
223
+ }} />
224
+ </Col>
225
+ </Row>
226
+ <Divider className={'divider'} />
227
+ <div className={'progress-list'}>{
228
+ fileListStatus && fileListStatus.length > 0 ?
229
+ <List
230
+ dataSource={fileListStatus}
231
+ renderItem={item => {
232
+ return <div className={'upload-progress-box'}>
233
+ <div style={{ width: '110px' }}>
234
+ <Tooltip title={item.file.name}>
235
+ <span className={'file-name'}>{item.file.name}</span>
236
+ </Tooltip>
237
+ </div>
238
+ <div style={{ width: '230px', paddingLeft: '20px' }}>
239
+ <Progress
240
+ percent={item?.percent}
241
+ status={item?.status || ''}
242
+ />
243
+ </div>
244
+ <span
245
+ style={{
246
+ width: '5px',
247
+ visibility: item.status === 'exception' ? 'visible' : 'hidden',
248
+ pointerEvents: item.status === 'exception' ? 'auto' : 'none',
249
+ }}
250
+ className='link-text'
251
+ onClick={() => {
252
+ if (item?.status === 'exception') {
253
+ item.status = ''
254
+ this.upload(item.breakName, item.breakFile, {
255
+ progress: (p, checkpoint) => this.progress(p, checkpoint, item.file),
256
+ checkpoint: item.checkpoint,
257
+ ...multipartUploadConf
258
+ })
259
+ }
260
+ }}
261
+ >
262
+ {
263
+ attachmentVisible && item.status === 'exception' && item.percent < 100 ? <CaretRightOutlined style={{ color: 'black', marginTop: '5px' }} /> : ' '
264
+ }
265
+ </span>
266
+ </div>
267
+ }}
268
+ /> : <div className={'none'}>暂无数据</div>
269
+ }</div>
270
+ </div>
271
+ </div>
272
+ )
273
+ }
274
+ }
275
+
276
+ export default OssUpload
@@ -0,0 +1,27 @@
1
+ import { Assembly, Validator,EmtpyType, MType, MFieldSchemaAnonymity } from "../../index";
2
+ import _ from "lodash";
3
+
4
+ const { validateRequired, validateStringMinMax, generateRegexValidate } = Validator
5
+
6
+ const OssUploadType: MType = _.assign({}, EmtpyType, {
7
+ validators: [validateRequired, generateRegexValidate(/[^\s]|(^$)/, "不能全都填空格"), validateStringMinMax],
8
+
9
+ createDefaultValue: (assembly:Assembly, s:MFieldSchemaAnonymity):any =>{
10
+ return s.defaultValue ?? "";
11
+ },
12
+
13
+ toReadable: (assembly:Assembly, s:MFieldSchemaAnonymity, vs:any):string => {
14
+ if(_.isNil(vs)){
15
+ return assembly.theme.READABLE_BLANK;
16
+ }
17
+
18
+ if(!_.isString(vs)){
19
+ return assembly.theme.READABLE_INVALID;
20
+ }
21
+
22
+ return vs;
23
+ },
24
+
25
+ });
26
+
27
+ export default OssUploadType
@@ -0,0 +1,18 @@
1
+ import React from "react";
2
+ import { BaseViewer } from "../../index";
3
+
4
+ class OssUploadViewer extends BaseViewer {
5
+ [x: string]: any;
6
+ element() {
7
+ const arr = this.getValue() || []
8
+ return <div>
9
+ {
10
+ arr.map(i => {
11
+ return <div key={i.uid}><a target='_blank' href={i.url}>{i.name}</a></div>
12
+ })
13
+ }
14
+ </div>
15
+ }
16
+ }
17
+
18
+ export default OssUploadViewer
@@ -0,0 +1,53 @@
1
+ .m3-plugin-ossupload-progress-modal {
2
+ display: block;
3
+ position: fixed;
4
+ right: 30px;
5
+ bottom: 30px;
6
+ width: 400px;
7
+ padding: 14px 24px 24px 24px;
8
+ border-radius: 5px;
9
+ background-color: #fff;
10
+ box-shadow: 2px 2px 24px 2px rgba(0, 0, 0, 0.1);
11
+
12
+ .cancel-icon {
13
+ text-align: right;
14
+ }
15
+
16
+ .divider {
17
+ width: calc(100% + 48px);
18
+ margin: 4px -24px 12px -24px
19
+ }
20
+
21
+ .link-text {
22
+ color: #1890ff;
23
+ cursor: pointer;
24
+ transition: color 0.3s;
25
+ pointer-events: auto;
26
+ }
27
+
28
+ .progress-list {
29
+ min-height: 30px;
30
+ max-height: 400px;
31
+ overflow-y: scroll;
32
+
33
+ .upload-progress-box {
34
+ display: flex;
35
+
36
+ .file-name {
37
+ cursor: default;
38
+ width: 110px;
39
+ overflow: hidden;
40
+ white-space: nowrap;
41
+ text-overflow: ellipsis;
42
+ display: inline-block;
43
+ }
44
+ }
45
+
46
+ .none {
47
+ width: 100%;
48
+ height: 100%;
49
+ text-align: center;
50
+ line-height: 30px;
51
+ }
52
+ }
53
+ }
@@ -0,0 +1,10 @@
1
+ import OssUpload from './OssUpload.jsx';
2
+ import OssUploadType from './OssUploadType';
3
+ import OssUploadViewer from './OssUploadViewer';
4
+
5
+ export default {
6
+ name: 'ossupload',
7
+ type: OssUploadType,
8
+ editor: OssUpload,
9
+ readable: OssUploadViewer
10
+ }
@@ -0,0 +1,3 @@
1
+ import { MType } from "../../index";
2
+ declare const OssUploadType: MType;
3
+ export default OssUploadType;
@@ -0,0 +1,7 @@
1
+ /// <reference types="react" />
2
+ import { BaseViewer } from "../../index";
3
+ declare class OssUploadViewer extends BaseViewer {
4
+ [x: string]: any;
5
+ element(): JSX.Element;
6
+ }
7
+ export default OssUploadViewer;
@@ -0,0 +1,8 @@
1
+ import OssUploadViewer from './OssUploadViewer';
2
+ declare const _default: {
3
+ name: string;
4
+ type: import("../../index.js").MType;
5
+ editor: any;
6
+ readable: typeof OssUploadViewer;
7
+ };
8
+ export default _default;