@ebiz/designer-components 0.1.54 → 0.1.56
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/dist/designer-components.css +1 -1
- package/dist/index.mjs +53424 -32359
- package/package.json +4 -2
- package/src/components/EbizRichTextEditor.vue +276 -0
- package/src/components/EbizSApprovalProcess.vue +6 -1
- package/src/components/senior/EbizSForm/item.vue +59 -2
- package/src/index.js +4 -1
- package/src/views/EbizSForm/index.vue +10 -23
- package/src/utils/upload.ts +0 -126
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ebiz/designer-components",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.56",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -25,7 +25,9 @@
|
|
|
25
25
|
"unplugin-auto-import": "^19.0.0",
|
|
26
26
|
"unplugin-vue-components": "^28.0.0",
|
|
27
27
|
"vue": "^3.5.13",
|
|
28
|
-
"vue-router": "^4.2.5"
|
|
28
|
+
"vue-router": "^4.2.5",
|
|
29
|
+
"@wangeditor/editor": "^5.1.23",
|
|
30
|
+
"@wangeditor/editor-for-vue": "^5.1.12"
|
|
29
31
|
},
|
|
30
32
|
"devDependencies": {
|
|
31
33
|
"@opentiny/tiny-engine-mock": "^2.1.0",
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="ebiz-rich-text-editor" style="border: 1px solid #ccc">
|
|
3
|
+
<Toolbar
|
|
4
|
+
style="border-bottom: 1px solid #ccc"
|
|
5
|
+
:editor="editorRef"
|
|
6
|
+
:defaultConfig="mergedToolbarConfig"
|
|
7
|
+
:mode="mode"
|
|
8
|
+
/>
|
|
9
|
+
<Editor
|
|
10
|
+
:style="{height: `${height}px`, overflowY: 'hidden'}"
|
|
11
|
+
v-model="computedModelValue"
|
|
12
|
+
:defaultConfig="mergedEditorConfig"
|
|
13
|
+
:mode="mode"
|
|
14
|
+
@onCreated="handleCreated"
|
|
15
|
+
@onChange="handleChange"
|
|
16
|
+
@onDestroyed="handleDestroyed"
|
|
17
|
+
@onFocus="handleFocus"
|
|
18
|
+
@onBlur="handleBlur"
|
|
19
|
+
@customAlert="handleCustomAlert"
|
|
20
|
+
@customPaste="handleCustomPaste"
|
|
21
|
+
/>
|
|
22
|
+
</div>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<script>
|
|
26
|
+
/**
|
|
27
|
+
* @displayName 富文本编辑器
|
|
28
|
+
* @description 基于WangEditor的富文本编辑器组件,支持图片和视频上传
|
|
29
|
+
* @category 表单组件
|
|
30
|
+
* @name EbizRichTextEditor
|
|
31
|
+
*/
|
|
32
|
+
export default {
|
|
33
|
+
name: "EbizRichTextEditor"
|
|
34
|
+
}
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<script setup>
|
|
38
|
+
import '@wangeditor/editor/dist/css/style.css'
|
|
39
|
+
import { defineProps, defineEmits, computed, ref, shallowRef, onBeforeUnmount, onMounted } from 'vue'
|
|
40
|
+
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
|
|
41
|
+
// import { upload } from '../utils/upload'
|
|
42
|
+
|
|
43
|
+
// 编辑器实例,必须用 shallowRef
|
|
44
|
+
const editorRef = shallowRef()
|
|
45
|
+
|
|
46
|
+
// 编辑器内容
|
|
47
|
+
const valueHtml = ref('')
|
|
48
|
+
|
|
49
|
+
// 编辑器模式
|
|
50
|
+
const mode = ref('default') // 或 'simple'
|
|
51
|
+
|
|
52
|
+
const props = defineProps({
|
|
53
|
+
/**
|
|
54
|
+
* 绑定的值
|
|
55
|
+
*/
|
|
56
|
+
modelValue: {
|
|
57
|
+
type: String,
|
|
58
|
+
default: ''
|
|
59
|
+
},
|
|
60
|
+
/**
|
|
61
|
+
* 是否禁用
|
|
62
|
+
*/
|
|
63
|
+
disabled: {
|
|
64
|
+
type: Boolean,
|
|
65
|
+
default: false
|
|
66
|
+
},
|
|
67
|
+
/**
|
|
68
|
+
* 是否只读
|
|
69
|
+
*/
|
|
70
|
+
readonly: {
|
|
71
|
+
type: Boolean,
|
|
72
|
+
default: false
|
|
73
|
+
},
|
|
74
|
+
/**
|
|
75
|
+
* 占位文本
|
|
76
|
+
*/
|
|
77
|
+
placeholder: {
|
|
78
|
+
type: String,
|
|
79
|
+
default: '请输入内容...'
|
|
80
|
+
},
|
|
81
|
+
/**
|
|
82
|
+
* 编辑器高度
|
|
83
|
+
*/
|
|
84
|
+
height: {
|
|
85
|
+
type: [String, Number],
|
|
86
|
+
default: 300
|
|
87
|
+
},
|
|
88
|
+
/**
|
|
89
|
+
* 工具栏配置
|
|
90
|
+
*/
|
|
91
|
+
toolbarConfig: {
|
|
92
|
+
type: Object,
|
|
93
|
+
default: () => ({})
|
|
94
|
+
},
|
|
95
|
+
/**
|
|
96
|
+
* 编辑器配置
|
|
97
|
+
*/
|
|
98
|
+
editorConfig: {
|
|
99
|
+
type: Object,
|
|
100
|
+
default: () => ({})
|
|
101
|
+
},
|
|
102
|
+
/**
|
|
103
|
+
* 图片上传路径
|
|
104
|
+
*/
|
|
105
|
+
imagePath: {
|
|
106
|
+
type: String,
|
|
107
|
+
default: 'editor'
|
|
108
|
+
},
|
|
109
|
+
/**
|
|
110
|
+
* 视频上传路径
|
|
111
|
+
*/
|
|
112
|
+
videoPath: {
|
|
113
|
+
type: String,
|
|
114
|
+
default: 'video'
|
|
115
|
+
},
|
|
116
|
+
/**
|
|
117
|
+
* 最大长度
|
|
118
|
+
*/
|
|
119
|
+
maxLength: {
|
|
120
|
+
type: Number,
|
|
121
|
+
default: undefined
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const emit = defineEmits([
|
|
126
|
+
'update:modelValue',
|
|
127
|
+
'change',
|
|
128
|
+
'focus',
|
|
129
|
+
'blur',
|
|
130
|
+
'created',
|
|
131
|
+
'destroyed'
|
|
132
|
+
]);
|
|
133
|
+
|
|
134
|
+
// 计算属性处理v-model双向绑定
|
|
135
|
+
const computedModelValue = computed({
|
|
136
|
+
get: () => props.modelValue,
|
|
137
|
+
set: (val) => {
|
|
138
|
+
emit('update:modelValue', val);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// 合并工具栏配置
|
|
143
|
+
const mergedToolbarConfig = computed(() => {
|
|
144
|
+
return {
|
|
145
|
+
...props.toolbarConfig
|
|
146
|
+
};
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// 合并编辑器配置
|
|
150
|
+
const mergedEditorConfig = computed(() => {
|
|
151
|
+
return {
|
|
152
|
+
placeholder: props.placeholder,
|
|
153
|
+
readOnly: props.disabled || props.readonly,
|
|
154
|
+
maxLength: props.maxLength,
|
|
155
|
+
MENU_CONF: {
|
|
156
|
+
uploadImage: {
|
|
157
|
+
customUpload(file, insertFn) {
|
|
158
|
+
|
|
159
|
+
upload({
|
|
160
|
+
path: props.imagePath,
|
|
161
|
+
file: {
|
|
162
|
+
name: file.name,
|
|
163
|
+
raw: file
|
|
164
|
+
},
|
|
165
|
+
onSuccess: (res) => {
|
|
166
|
+
insertFn(res.url, '', '');
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
uploadVideo: {
|
|
172
|
+
customUpload(file, insertFn) {
|
|
173
|
+
upload({
|
|
174
|
+
path: props.videoPath,
|
|
175
|
+
file: {
|
|
176
|
+
name: file.name,
|
|
177
|
+
raw: file
|
|
178
|
+
},
|
|
179
|
+
onSuccess: (res) => {
|
|
180
|
+
insertFn(res.url, '', '');
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
...props.editorConfig?.MENU_CONF
|
|
186
|
+
},
|
|
187
|
+
...props.editorConfig
|
|
188
|
+
};
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// 编辑器创建完成回调
|
|
192
|
+
const handleCreated = (editor) => {
|
|
193
|
+
editorRef.value = editor; // 记录编辑器实例
|
|
194
|
+
emit('created', editor);
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
// 内容变化事件
|
|
198
|
+
const handleChange = (editor) => {
|
|
199
|
+
emit('change', editor.getHtml());
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
// 销毁事件
|
|
203
|
+
const handleDestroyed = (editor) => {
|
|
204
|
+
emit('destroyed', editor);
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
// 获得焦点事件
|
|
208
|
+
const handleFocus = (editor) => {
|
|
209
|
+
emit('focus', editor);
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
// 失去焦点事件
|
|
213
|
+
const handleBlur = (editor) => {
|
|
214
|
+
emit('blur', editor);
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
// 自定义提示事件
|
|
218
|
+
const handleCustomAlert = (info, type) => {
|
|
219
|
+
console.log(`【自定义提示】${type} - ${info}`);
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
// 自定义粘贴事件
|
|
223
|
+
const handleCustomPaste = (editor, event, callback) => {
|
|
224
|
+
console.log('ClipboardEvent 粘贴事件对象', event);
|
|
225
|
+
// 返回值(注意,vue 事件的返回值,不能用 return)
|
|
226
|
+
callback(true); // true 继续默认的粘贴行为
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
// 组件销毁时,销毁编辑器实例
|
|
230
|
+
onBeforeUnmount(() => {
|
|
231
|
+
const editor = editorRef.value;
|
|
232
|
+
if (editor === null) return;
|
|
233
|
+
editor.destroy();
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// 暴露编辑器实例和方法
|
|
237
|
+
defineExpose({
|
|
238
|
+
editor: editorRef,
|
|
239
|
+
insertText: (text) => {
|
|
240
|
+
if (editorRef.value) {
|
|
241
|
+
editorRef.value.insertText(text);
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
getHtml: () => {
|
|
245
|
+
if (editorRef.value) {
|
|
246
|
+
return editorRef.value.getHtml();
|
|
247
|
+
}
|
|
248
|
+
return '';
|
|
249
|
+
},
|
|
250
|
+
getText: () => {
|
|
251
|
+
if (editorRef.value) {
|
|
252
|
+
return editorRef.value.getText();
|
|
253
|
+
}
|
|
254
|
+
return '';
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
</script>
|
|
258
|
+
|
|
259
|
+
<style scoped>
|
|
260
|
+
.ebiz-rich-text-editor {
|
|
261
|
+
border-radius: var(--td-radius-default);
|
|
262
|
+
overflow: hidden;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.ebiz-rich-text-editor :deep(.w-e-text-container) {
|
|
266
|
+
z-index: 1; /* 避免编辑区域遮挡其他元素 */
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.ebiz-rich-text-editor :deep(.w-e-toolbar) {
|
|
270
|
+
z-index: 2; /* 确保工具栏在编辑区域之上 */
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.ebiz-rich-text-editor :deep(.w-e-text-placeholder) {
|
|
274
|
+
color: var(--td-text-color-placeholder);
|
|
275
|
+
}
|
|
276
|
+
</style>
|
|
@@ -436,7 +436,12 @@ const getOperationTypeText = (approver) => {
|
|
|
436
436
|
case 'TRANSFER':
|
|
437
437
|
return '转审'
|
|
438
438
|
case 'ADD_SIGN':
|
|
439
|
-
|
|
439
|
+
const operationData = JSON.parse(approver.operation.operationData || '{}')
|
|
440
|
+
if (operationData.position == 'before') {
|
|
441
|
+
return "向前加签";
|
|
442
|
+
}
|
|
443
|
+
return '已同意并加签'
|
|
444
|
+
// return '加签'
|
|
440
445
|
case 'REJECT':
|
|
441
446
|
return '驳回'
|
|
442
447
|
case 'RETURN':
|
|
@@ -121,6 +121,23 @@
|
|
|
121
121
|
@change="handleChange" />
|
|
122
122
|
</template>
|
|
123
123
|
|
|
124
|
+
<!-- 富文本编辑器 -->
|
|
125
|
+
<template v-else-if="type === 'rich-text'">
|
|
126
|
+
<ebiz-rich-text-editor
|
|
127
|
+
v-model="computedModelValue"
|
|
128
|
+
:placeholder="placeholder || '请输入内容'"
|
|
129
|
+
:disabled="disabled"
|
|
130
|
+
:readonly="readonly"
|
|
131
|
+
:height="editorHeight"
|
|
132
|
+
:toolbar-config="editorToolbarConfig"
|
|
133
|
+
:editor-config="editorConfig"
|
|
134
|
+
:image-path="editorImagePath"
|
|
135
|
+
:video-path="editorVideoPath"
|
|
136
|
+
:max-length="maxLength"
|
|
137
|
+
@change="handleChange"
|
|
138
|
+
/>
|
|
139
|
+
</template>
|
|
140
|
+
|
|
124
141
|
<!-- 子表格 -->
|
|
125
142
|
<template v-else-if="type === 'table'">
|
|
126
143
|
<div class="ebiz-form-table">
|
|
@@ -239,7 +256,7 @@ export default {
|
|
|
239
256
|
</script>
|
|
240
257
|
|
|
241
258
|
<script setup>
|
|
242
|
-
import { defineProps, defineEmits, computed, watch } from 'vue';
|
|
259
|
+
import { defineProps, defineEmits, computed, watch, onMounted } from 'vue';
|
|
243
260
|
import {
|
|
244
261
|
FormItem as TFormItem,
|
|
245
262
|
Input as TInput,
|
|
@@ -263,6 +280,7 @@ import EbizRemoteSelect from '../../EbizRemoteSelect.vue';
|
|
|
263
280
|
import EbizEmployeeSelector from '../../EbizEmployeeSelector.vue';
|
|
264
281
|
import EbizDepartmentSelector from '../../EbizDepartmentSelector.vue';
|
|
265
282
|
import { EbizUpload } from '../../../index.js'
|
|
283
|
+
import EbizRichTextEditor from '../../EbizRichTextEditor.vue';
|
|
266
284
|
|
|
267
285
|
const props = defineProps({
|
|
268
286
|
/**
|
|
@@ -275,7 +293,7 @@ const props = defineProps({
|
|
|
275
293
|
validator: (val) => [
|
|
276
294
|
'input', 'number', 'textarea', 'select', 'date', 'datetime', 'time', 'radio',
|
|
277
295
|
'checkbox', 'switch', 'slider', 'upload', 'cascader', 'tree-select',
|
|
278
|
-
'color-picker', 'employee', 'dept', 'table'
|
|
296
|
+
'color-picker', 'employee', 'dept', 'table', 'rich-text'
|
|
279
297
|
].includes(val)
|
|
280
298
|
},
|
|
281
299
|
/**
|
|
@@ -649,6 +667,41 @@ const props = defineProps({
|
|
|
649
667
|
addButtonText: {
|
|
650
668
|
type: String,
|
|
651
669
|
default: '添加数据'
|
|
670
|
+
},
|
|
671
|
+
/**
|
|
672
|
+
* 富文本编辑器高度
|
|
673
|
+
*/
|
|
674
|
+
editorHeight: {
|
|
675
|
+
type: [String, Number],
|
|
676
|
+
default: 300
|
|
677
|
+
},
|
|
678
|
+
/**
|
|
679
|
+
* 富文本编辑器工具栏配置
|
|
680
|
+
*/
|
|
681
|
+
editorToolbarConfig: {
|
|
682
|
+
type: Object,
|
|
683
|
+
default: () => ({})
|
|
684
|
+
},
|
|
685
|
+
/**
|
|
686
|
+
* 富文本编辑器配置
|
|
687
|
+
*/
|
|
688
|
+
editorConfig: {
|
|
689
|
+
type: Object,
|
|
690
|
+
default: () => ({})
|
|
691
|
+
},
|
|
692
|
+
/**
|
|
693
|
+
* 富文本图片上传路径
|
|
694
|
+
*/
|
|
695
|
+
editorImagePath: {
|
|
696
|
+
type: String,
|
|
697
|
+
default: 'editor'
|
|
698
|
+
},
|
|
699
|
+
/**
|
|
700
|
+
* 富文本视频上传路径
|
|
701
|
+
*/
|
|
702
|
+
editorVideoPath: {
|
|
703
|
+
type: String,
|
|
704
|
+
default: 'video'
|
|
652
705
|
}
|
|
653
706
|
});
|
|
654
707
|
|
|
@@ -804,6 +857,10 @@ watch(
|
|
|
804
857
|
},
|
|
805
858
|
{ deep: true }
|
|
806
859
|
);
|
|
860
|
+
|
|
861
|
+
// 组件挂载时初始化文件列表
|
|
862
|
+
onMounted(() => {
|
|
863
|
+
});
|
|
807
864
|
</script>
|
|
808
865
|
|
|
809
866
|
<style scoped>
|
package/src/index.js
CHANGED
|
@@ -100,6 +100,7 @@ import EbizFileList from './components/EbizFileList.vue'
|
|
|
100
100
|
import EbizDetailView from './components/EbizDetailView.vue'
|
|
101
101
|
import EbizDetailItem from './components/EbizDetailItem.vue'
|
|
102
102
|
import EbizPdfViewer from './components/EbizPdfViewer.vue'
|
|
103
|
+
import EbizRichTextEditor from './components/EbizRichTextEditor.vue'
|
|
103
104
|
|
|
104
105
|
// 导出组件
|
|
105
106
|
export {
|
|
@@ -242,5 +243,7 @@ export {
|
|
|
242
243
|
EbizDetailView,
|
|
243
244
|
EbizDetailItem,
|
|
244
245
|
// PDF预览组件
|
|
245
|
-
EbizPdfViewer
|
|
246
|
+
EbizPdfViewer,
|
|
247
|
+
// 富文本编辑器组件
|
|
248
|
+
EbizRichTextEditor
|
|
246
249
|
}
|
|
@@ -4,12 +4,7 @@
|
|
|
4
4
|
<div class="demo-section">
|
|
5
5
|
<h3>基础表单示例</h3>
|
|
6
6
|
<div class="demo-block">
|
|
7
|
-
<ebiz-s-form
|
|
8
|
-
ref="basicFormRef"
|
|
9
|
-
:data="formData"
|
|
10
|
-
:rules="formRules"
|
|
11
|
-
show-error-message
|
|
12
|
-
@success="handleSuccess"
|
|
7
|
+
<ebiz-s-form ref="basicFormRef" :data="formData" :rules="formRules" show-error-message @success="handleSuccess"
|
|
13
8
|
@error="handleError">
|
|
14
9
|
<ebiz-s-form-item label="姓名" name="name" type="input" placeholder="请输入姓名"></ebiz-s-form-item>
|
|
15
10
|
<ebiz-s-form-item label="年龄" name="age" type="number" placeholder="请输入年龄"></ebiz-s-form-item>
|
|
@@ -17,6 +12,10 @@
|
|
|
17
12
|
<ebiz-s-form-item label="爱好" name="hobbies" type="checkbox" :options="hobbyOptions"></ebiz-s-form-item>
|
|
18
13
|
<ebiz-s-form-item label="职业" name="occupation" type="select" :options="occupationOptions"></ebiz-s-form-item>
|
|
19
14
|
<ebiz-s-form-item label="出生日期" name="birthday" type="date"></ebiz-s-form-item>
|
|
15
|
+
|
|
16
|
+
<ebiz-s-form-item v-model="formData.richText" label="富文本" name="richText" type="rich-text"></ebiz-s-form-item>
|
|
17
|
+
|
|
18
|
+
|
|
20
19
|
{{ formData.bio }}
|
|
21
20
|
<ebiz-s-form-item v-model="formData.bio" label="简介" name="bio" type="table" :tableColumns="[
|
|
22
21
|
{ name: '名称', key: 'name' },
|
|
@@ -33,16 +32,9 @@
|
|
|
33
32
|
<t-button @click="openEditFormWithData">打开编辑表单(预设数据)</t-button>
|
|
34
33
|
<t-button @click="openEditFormWithId">打开编辑表单(加载详情)</t-button>
|
|
35
34
|
</t-space>
|
|
36
|
-
<ebiz-s-form
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
:detail-api-config="detailApiConfig"
|
|
40
|
-
:rules="editFormRules"
|
|
41
|
-
show-error-message
|
|
42
|
-
reset-on-success
|
|
43
|
-
@success="handleEditSuccess"
|
|
44
|
-
@error="handleEditError"
|
|
45
|
-
@detail-loaded="handleDetailLoaded">
|
|
35
|
+
<ebiz-s-form ref="editFormRef" :api-config="submitApiConfig" :detail-api-config="detailApiConfig"
|
|
36
|
+
:rules="editFormRules" show-error-message reset-on-success @success="handleEditSuccess"
|
|
37
|
+
@error="handleEditError" @detail-loaded="handleDetailLoaded">
|
|
46
38
|
<ebiz-s-form-item label="ID" name="id" type="input" disabled></ebiz-s-form-item>
|
|
47
39
|
<ebiz-s-form-item label="标题" name="title" type="input" placeholder="请输入标题"></ebiz-s-form-item>
|
|
48
40
|
<ebiz-s-form-item label="内容" name="body" type="textarea" placeholder="请输入内容"></ebiz-s-form-item>
|
|
@@ -54,10 +46,7 @@
|
|
|
54
46
|
<div class="demo-section">
|
|
55
47
|
<h3>行内表单示例</h3>
|
|
56
48
|
<div class="demo-block">
|
|
57
|
-
<ebiz-s-form
|
|
58
|
-
:data="inlineFormData"
|
|
59
|
-
layout="inline"
|
|
60
|
-
label-width="60px">
|
|
49
|
+
<ebiz-s-form :data="inlineFormData" layout="inline" label-width="60px">
|
|
61
50
|
<ebiz-s-form-item label="用户名" name="username" type="input" placeholder="请输入用户名"></ebiz-s-form-item>
|
|
62
51
|
<ebiz-s-form-item label="密码" name="password" type="input" placeholder="请输入密码"></ebiz-s-form-item>
|
|
63
52
|
</ebiz-s-form>
|
|
@@ -84,9 +73,7 @@
|
|
|
84
73
|
<div class="demo-section">
|
|
85
74
|
<h3>顶部标签表单示例</h3>
|
|
86
75
|
<div class="demo-block">
|
|
87
|
-
<ebiz-s-form
|
|
88
|
-
:data="topLabelFormData"
|
|
89
|
-
label-align="top">
|
|
76
|
+
<ebiz-s-form :data="topLabelFormData" label-align="top">
|
|
90
77
|
<ebiz-s-form-item label="邮箱" name="email" type="input" placeholder="请输入邮箱"></ebiz-s-form-item>
|
|
91
78
|
<ebiz-s-form-item label="手机号" name="phone" type="input" placeholder="请输入手机号"></ebiz-s-form-item>
|
|
92
79
|
<ebiz-s-form-item label="是否启用" name="enabled" type="switch"></ebiz-s-form-item>
|
package/src/utils/upload.ts
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import {request} from "./request";
|
|
2
|
-
import COS from "cos-js-sdk-v5";
|
|
3
|
-
import OSS from "ali-oss";
|
|
4
|
-
import moment from "moment/moment";
|
|
5
|
-
|
|
6
|
-
const defaultOnPercent = () => {
|
|
7
|
-
}
|
|
8
|
-
const defaultOnSuccess = () => {
|
|
9
|
-
}
|
|
10
|
-
const defaultOnFail = () => {
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const upload = (options: any) => {
|
|
14
|
-
const path: string = options.path;
|
|
15
|
-
const file: any = options.file;
|
|
16
|
-
const onPercent: Function = options.onProgress || defaultOnPercent;
|
|
17
|
-
const onSuccess: Function = options.onSuccess || defaultOnSuccess;
|
|
18
|
-
const onFail: Function = options.onFail || defaultOnFail;
|
|
19
|
-
|
|
20
|
-
let credentials: any, url;
|
|
21
|
-
request.get({
|
|
22
|
-
url: "/file/getSecretKey"
|
|
23
|
-
}).then((res) => {
|
|
24
|
-
if (res.oss_type === 'ALIYUN') {
|
|
25
|
-
const client = new OSS({
|
|
26
|
-
// yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
|
|
27
|
-
region: res.region,
|
|
28
|
-
// 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
|
|
29
|
-
accessKeyId: res.accessKeyId,
|
|
30
|
-
accessKeySecret: res.accessKeySecret,
|
|
31
|
-
// 从STS服务获取的安全令牌(SecurityToken)。
|
|
32
|
-
stsToken: res.securityToken,
|
|
33
|
-
// 刷新临时访问凭证的时间间隔,单位为毫秒。
|
|
34
|
-
refreshSTSTokenInterval: 300000,
|
|
35
|
-
// 填写Bucket名称。
|
|
36
|
-
bucket: res.bucket
|
|
37
|
-
});
|
|
38
|
-
const options = {
|
|
39
|
-
mime: "json",
|
|
40
|
-
headers: {"Content-Type": "text/plain"},
|
|
41
|
-
};
|
|
42
|
-
client.put(handleUploadName("img", path, file.name), file.raw, options).then((uploadRes: any) => {
|
|
43
|
-
console.log(uploadRes)
|
|
44
|
-
// 创建一个 URL 对象
|
|
45
|
-
const urlObj = new URL(uploadRes.url);
|
|
46
|
-
// 从 URL 对象中获取路径部分
|
|
47
|
-
const url = res.host + urlObj.pathname.substring(1);
|
|
48
|
-
|
|
49
|
-
request.get({
|
|
50
|
-
url: "/file/getAccessUrl",
|
|
51
|
-
params: {
|
|
52
|
-
url,
|
|
53
|
-
}
|
|
54
|
-
}).then(res => {
|
|
55
|
-
console.log(res)
|
|
56
|
-
onSuccess({url: res})
|
|
57
|
-
})
|
|
58
|
-
}).catch((e: any) => {
|
|
59
|
-
onFail(e)
|
|
60
|
-
});
|
|
61
|
-
} else {
|
|
62
|
-
credentials = res.credentials;
|
|
63
|
-
let cos = new COS({
|
|
64
|
-
getAuthorization: function (options, callback) {
|
|
65
|
-
callback({
|
|
66
|
-
TmpSecretId: credentials.tmpSecretId,
|
|
67
|
-
TmpSecretKey: credentials.tmpSecretKey,
|
|
68
|
-
SecurityToken: credentials.sessionToken,
|
|
69
|
-
StartTime: credentials.startTime,
|
|
70
|
-
ExpiredTime: credentials.expiredTime
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
cos.uploadFile(
|
|
75
|
-
{
|
|
76
|
-
Bucket: credentials.bucket,
|
|
77
|
-
Region: credentials.region,
|
|
78
|
-
Key: handleUploadName("img", path, file.name),
|
|
79
|
-
Body: file.raw,
|
|
80
|
-
SliceSize: 1024 * 1024 * 5 /* 触发分块上传的阈值,超过5MB使用分块上传,小于5MB使用简单上传。可自行设置,非必须 */,
|
|
81
|
-
onProgress: (progressData) => {
|
|
82
|
-
if (!!onPercent) {
|
|
83
|
-
onPercent({file, percent: progressData.percent});
|
|
84
|
-
}
|
|
85
|
-
},
|
|
86
|
-
onFileFinish: (err, data, options) => {
|
|
87
|
-
url = credentials.path + "/" + options.Key;
|
|
88
|
-
request.get({
|
|
89
|
-
url: "/file/getAccessUrl",
|
|
90
|
-
params: {
|
|
91
|
-
url,
|
|
92
|
-
}
|
|
93
|
-
}).then(res => {
|
|
94
|
-
console.log(res)
|
|
95
|
-
onPercent({file, percent: 100});
|
|
96
|
-
onSuccess({url: res})
|
|
97
|
-
})
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
|
-
function (err, data) {
|
|
101
|
-
onFail(err)
|
|
102
|
-
}
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
// 规范上传图片格式
|
|
111
|
-
const handleUploadName = function (type: string, path: string, file_name: string) {
|
|
112
|
-
// /img/类型(avatar/category/article)/年月日/md5(文件名+随机字符串+毫秒数)+时间.文件后缀
|
|
113
|
-
let newFileName =
|
|
114
|
-
type +
|
|
115
|
-
'/' +
|
|
116
|
-
path +
|
|
117
|
-
'/' +
|
|
118
|
-
moment(new Date()).format('YYMMDD') +
|
|
119
|
-
'/' +
|
|
120
|
-
file_name.split(file_name.substring(file_name.lastIndexOf('.')))[0] +
|
|
121
|
-
Math.random().toString(36).substring(2) +
|
|
122
|
-
Date.now() +
|
|
123
|
-
moment(new Date()).format('HHmm') +
|
|
124
|
-
file_name.substring(file_name.lastIndexOf('.'));
|
|
125
|
-
return newFileName;
|
|
126
|
-
};
|