vue-editify 0.1.22 → 0.1.23
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/examples/App.vue +8 -2
- package/lib/components/button/button.vue.d.ts +3 -3
- package/lib/components/button/props.d.ts +1 -1
- package/lib/components/checkbox/checkbox.vue.d.ts +3 -3
- package/lib/components/checkbox/props.d.ts +1 -1
- package/lib/components/colors/colors.vue.d.ts +3 -3
- package/lib/components/colors/props.d.ts +1 -1
- package/lib/components/insertImage/insertImage.vue.d.ts +6 -6
- package/lib/components/insertImage/props.d.ts +2 -2
- package/lib/components/insertLink/insertLink.vue.d.ts +3 -3
- package/lib/components/insertLink/props.d.ts +2 -2
- package/lib/components/insertTable/insertTable.vue.d.ts +3 -3
- package/lib/components/insertTable/props.d.ts +2 -2
- package/lib/components/insertVideo/insertVideo.vue.d.ts +6 -6
- package/lib/components/insertVideo/props.d.ts +2 -2
- package/lib/components/menu/menu.vue.d.ts +3 -3
- package/lib/components/menu/props.d.ts +1 -1
- package/lib/components/toolbar/props.d.ts +1 -1
- package/lib/components/toolbar/toolbar.vue.d.ts +3 -3
- package/lib/core/rule.d.ts +1 -1
- package/lib/core/tool.d.ts +19 -9
- package/lib/editify/editify.vue.d.ts +12 -3
- package/lib/editify/props.d.ts +6 -2
- package/lib/editify.es.js +576 -178
- package/lib/editify.umd.js +1 -1
- package/lib/index.d.ts +7 -4
- package/lib/plugins/attachment/index.d.ts +17 -0
- package/lib/plugins/attachment/insertAttachment/insertAttachment.vue.d.ts +83 -0
- package/lib/plugins/attachment/insertAttachment/props.d.ts +38 -0
- package/lib/style.css +1 -1
- package/package.json +1 -1
- package/src/components/button/button.vue +4 -1
- package/src/components/button/props.ts +1 -1
- package/src/components/checkbox/props.ts +1 -1
- package/src/components/colors/colors.vue +1 -1
- package/src/components/colors/props.ts +1 -1
- package/src/components/insertImage/insertImage.vue +12 -10
- package/src/components/insertImage/props.ts +2 -2
- package/src/components/insertLink/insertLink.vue +1 -1
- package/src/components/insertLink/props.ts +2 -2
- package/src/components/insertTable/props.ts +2 -2
- package/src/components/insertVideo/insertVideo.vue +12 -10
- package/src/components/insertVideo/props.ts +2 -2
- package/src/components/menu/menu.vue +28 -13
- package/src/components/menu/props.ts +1 -1
- package/src/components/toolbar/props.ts +1 -1
- package/src/components/toolbar/toolbar.vue +3 -4
- package/src/core/function.ts +5 -5
- package/src/core/rule.ts +1 -1
- package/src/core/tool.ts +24 -11
- package/src/editify/editify.less +27 -0
- package/src/editify/editify.vue +50 -6
- package/src/editify/props.ts +9 -2
- package/src/icon/iconfont.css +4 -0
- package/src/icon/iconfont.ttf +0 -0
- package/src/icon/iconfont.woff +0 -0
- package/src/index.ts +13 -8
- package/src/locale/en_US.ts +9 -1
- package/src/locale/zh_CN.ts +9 -1
- package/src/plugins/attachment/images/attachment.png +0 -0
- package/src/plugins/attachment/index.ts +121 -0
- package/src/plugins/attachment/insertAttachment/insertAttachment.less +135 -0
- package/src/plugins/attachment/insertAttachment/insertAttachment.vue +189 -0
- package/src/plugins/attachment/insertAttachment/props.ts +48 -0
package/src/locale/zh_CN.ts
CHANGED
@@ -84,5 +84,13 @@ export const zh_CN: ObjectType = {
|
|
84
84
|
alignJustify: '两端对齐',
|
85
85
|
defaultLineHeight: '默认行高',
|
86
86
|
auto: '自适应',
|
87
|
-
fullScreen: '全屏'
|
87
|
+
fullScreen: '全屏',
|
88
|
+
|
89
|
+
//插件语言配置
|
90
|
+
insertAttachment: '插入附件',
|
91
|
+
uploadAttachment: '上传附件',
|
92
|
+
remoteAttachment: '远程地址',
|
93
|
+
attachmentUrlPlaceholder: '请输入远程地址',
|
94
|
+
downloadAttachment: '点击下载附件',
|
95
|
+
attachmentDownloadName: '附件'
|
88
96
|
}
|
Binary file
|
@@ -0,0 +1,121 @@
|
|
1
|
+
import { ComponentInternalInstance, h } from 'vue'
|
2
|
+
import { AlexEditor, AlexElement } from 'alex-editor'
|
3
|
+
import { PluginType } from '../../core/tool'
|
4
|
+
import Layer from '../../components/layer/layer.vue'
|
5
|
+
import Button from '../../components/button/button.vue'
|
6
|
+
import Icon from '../../components/icon/icon.vue'
|
7
|
+
import InsertAttachment from './insertAttachment/insertAttachment.vue'
|
8
|
+
import { InsertAttachmentUploadErrorType } from './insertAttachment/props'
|
9
|
+
import { event as DapEvent, common as DapCommon } from 'dap-util'
|
10
|
+
|
11
|
+
export type AttachmentOptionsType = {
|
12
|
+
//排序
|
13
|
+
sequence?: number
|
14
|
+
//工具提示内容
|
15
|
+
title?: string
|
16
|
+
//按钮是否显示左侧边框
|
17
|
+
leftBorder?: boolean
|
18
|
+
//按钮是否显示右侧边框
|
19
|
+
rightBorder?: boolean
|
20
|
+
//定义可选择的文件类型,默认不限制类型,设定此参数后选择文件时会自动过滤非符合的文件类型
|
21
|
+
accept?: 'rar' | 'zip' | 'txt' | 'image' | 'video' | 'audio' | 'html' | 'doc' | 'xml' | 'js' | 'json' | 'ppt' | 'pdf' | null
|
22
|
+
//支持的类型数组
|
23
|
+
allowedFileType?: string[]
|
24
|
+
//是否多选
|
25
|
+
multiple?: boolean
|
26
|
+
//选择的单个文件最大值,单位kb,不设置将不限制
|
27
|
+
maxSize?: number
|
28
|
+
//选择的单个文件最小值,单位kb,不设置将不限制
|
29
|
+
minSize?: number
|
30
|
+
//是否自定义上传附件
|
31
|
+
customUpload?: (files: File[]) => string[] | Promise<string[]>
|
32
|
+
//处理上传附件异常
|
33
|
+
handleError?: (error: InsertAttachmentUploadErrorType, file: File) => void
|
34
|
+
}
|
35
|
+
|
36
|
+
export const attachment = (options?: AttachmentOptionsType) => {
|
37
|
+
if (!DapCommon.isObject(options)) {
|
38
|
+
options = {}
|
39
|
+
}
|
40
|
+
const plugin: PluginType = (editifyInstance: ComponentInternalInstance, color: string | null, editTrans: (key: string) => any) => {
|
41
|
+
return {
|
42
|
+
//附件菜单项配置
|
43
|
+
menu: {
|
44
|
+
sequence: {
|
45
|
+
attachment: options!.sequence || 100
|
46
|
+
},
|
47
|
+
extends: {
|
48
|
+
attachment: {
|
49
|
+
type: 'select',
|
50
|
+
title: options!.title || editTrans('insertAttachment'),
|
51
|
+
leftBorder: options!.leftBorder,
|
52
|
+
rightBorder: options!.rightBorder,
|
53
|
+
default: () => h(Icon, { value: 'attachment' }),
|
54
|
+
layer: (_name: string, btnInstance: InstanceType<typeof Button>) =>
|
55
|
+
h(InsertAttachment, {
|
56
|
+
color: color,
|
57
|
+
accept: options!.accept,
|
58
|
+
allowedFileType: options!.allowedFileType || [],
|
59
|
+
multiple: !!options!.multiple,
|
60
|
+
maxSize: options!.maxSize,
|
61
|
+
minSize: options!.minSize,
|
62
|
+
customUpload: options!.customUpload,
|
63
|
+
handleError: options!.handleError,
|
64
|
+
onChange: () => {
|
65
|
+
;(<InstanceType<typeof Layer>>btnInstance.$refs.layerRef).setPosition()
|
66
|
+
},
|
67
|
+
onInsert: (url: string) => {
|
68
|
+
//创建元素
|
69
|
+
const attachmentElement = new AlexElement('closed', 'span', { 'data-attachment': url, contenteditable: 'false' }, null, null)
|
70
|
+
const editor = <AlexEditor>editifyInstance.exposed!.editor.value
|
71
|
+
//插入编辑器
|
72
|
+
editor.insertElement(attachmentElement)
|
73
|
+
//移动光标到新插入的元素
|
74
|
+
editor.range!.anchor.moveToEnd(attachmentElement)
|
75
|
+
editor.range!.focus.moveToEnd(attachmentElement)
|
76
|
+
editor.formatElementStack()
|
77
|
+
editor.domRender()
|
78
|
+
editor.rangeRender()
|
79
|
+
btnInstance.show = false
|
80
|
+
}
|
81
|
+
})
|
82
|
+
}
|
83
|
+
}
|
84
|
+
},
|
85
|
+
//找到附件元素点击下载
|
86
|
+
updateView: () => {
|
87
|
+
const editor = <AlexEditor>editifyInstance.exposed!.editor.value
|
88
|
+
AlexElement.flatElements(editor.stack).forEach(el => {
|
89
|
+
if (el.parsedom == 'span' && el.hasMarks() && el.marks!['data-attachment']) {
|
90
|
+
DapEvent.off(<HTMLElement>el.elm, 'click')
|
91
|
+
DapEvent.on(<HTMLElement>el.elm, 'click', () => {
|
92
|
+
const url = el.marks!['data-attachment']
|
93
|
+
const a = document.createElement('a')
|
94
|
+
a.setAttribute('href', url)
|
95
|
+
a.setAttribute('download', editTrans('attachmentDownloadName'))
|
96
|
+
a.click()
|
97
|
+
})
|
98
|
+
}
|
99
|
+
})
|
100
|
+
},
|
101
|
+
//span含有data-attachment的元素设为自闭合元素
|
102
|
+
customParseNode: (el: AlexElement) => {
|
103
|
+
if (el.hasMarks() && el.marks!['data-attachment'] && el.parsedom == 'span') {
|
104
|
+
el.type = 'closed'
|
105
|
+
}
|
106
|
+
return el
|
107
|
+
},
|
108
|
+
//span元素粘贴保留data-attachment
|
109
|
+
pasteKeepMarks: {
|
110
|
+
'data-attachment': ['span']
|
111
|
+
},
|
112
|
+
//设置元素的title属性标记
|
113
|
+
renderRule: (el: AlexElement) => {
|
114
|
+
if (el.type == 'closed' && el.hasMarks() && el.marks!['data-attachment']) {
|
115
|
+
el.marks!['title'] = editTrans('downloadAttachment')
|
116
|
+
}
|
117
|
+
}
|
118
|
+
}
|
119
|
+
}
|
120
|
+
return plugin
|
121
|
+
}
|
@@ -0,0 +1,135 @@
|
|
1
|
+
.editify-attachment {
|
2
|
+
display: block;
|
3
|
+
width: 280px;
|
4
|
+
padding: 10px 14px;
|
5
|
+
|
6
|
+
.editify-attachment-header {
|
7
|
+
display: flex;
|
8
|
+
justify-content: flex-start;
|
9
|
+
align-items: center;
|
10
|
+
width: 100%;
|
11
|
+
margin-bottom: 20px;
|
12
|
+
position: relative;
|
13
|
+
padding-bottom: 6px;
|
14
|
+
|
15
|
+
.editify-attachment-header-slider {
|
16
|
+
position: absolute;
|
17
|
+
width: 50px;
|
18
|
+
height: 2px;
|
19
|
+
border-radius: 2px;
|
20
|
+
left: 0;
|
21
|
+
bottom: 0;
|
22
|
+
transition: left 200ms;
|
23
|
+
|
24
|
+
&.editify-upload {
|
25
|
+
left: 5px;
|
26
|
+
}
|
27
|
+
|
28
|
+
&.editify-remote {
|
29
|
+
left: 85px;
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
.editify-attachment-header-item {
|
34
|
+
display: block;
|
35
|
+
text-align: center;
|
36
|
+
font-size: @font-size;
|
37
|
+
color: @font-color;
|
38
|
+
opacity: 0.8;
|
39
|
+
transition: all 200ms;
|
40
|
+
width: 60px;
|
41
|
+
overflow: hidden;
|
42
|
+
white-space: nowrap;
|
43
|
+
text-overflow: ellipsis;
|
44
|
+
|
45
|
+
&:hover {
|
46
|
+
opacity: 1;
|
47
|
+
cursor: pointer;
|
48
|
+
}
|
49
|
+
|
50
|
+
&:first-child {
|
51
|
+
margin-right: 20px;
|
52
|
+
}
|
53
|
+
|
54
|
+
&.editify-active {
|
55
|
+
opacity: 1;
|
56
|
+
color: @font-color-dark;
|
57
|
+
}
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
.editify-attachment-remote {
|
62
|
+
display: block;
|
63
|
+
width: 100%;
|
64
|
+
|
65
|
+
input {
|
66
|
+
appearance: none;
|
67
|
+
-webkit-appearance: none;
|
68
|
+
-moz-appearance: none;
|
69
|
+
display: block;
|
70
|
+
width: 100%;
|
71
|
+
margin: 0 0 10px 0;
|
72
|
+
padding: 4px 2px;
|
73
|
+
border: none;
|
74
|
+
font-size: @font-size;
|
75
|
+
color: @font-color;
|
76
|
+
border-bottom: 1px solid @border-color;
|
77
|
+
line-height: 1.5;
|
78
|
+
transition: border-color 500ms;
|
79
|
+
background-color: transparent;
|
80
|
+
outline: none;
|
81
|
+
box-sizing: border-box;
|
82
|
+
|
83
|
+
&::-webkit-input-placeholder,
|
84
|
+
&::placeholder {
|
85
|
+
color: @font-color-disabled;
|
86
|
+
font-family: inherit;
|
87
|
+
font-size: inherit;
|
88
|
+
vertical-align: middle;
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
.editify-attachment-remote-footer {
|
93
|
+
display: flex;
|
94
|
+
justify-content: flex-end;
|
95
|
+
align-items: center;
|
96
|
+
width: 100%;
|
97
|
+
font-size: @font-size;
|
98
|
+
opacity: 0.8;
|
99
|
+
transition: all 200ms;
|
100
|
+
|
101
|
+
&:hover {
|
102
|
+
cursor: pointer;
|
103
|
+
opacity: 1;
|
104
|
+
}
|
105
|
+
}
|
106
|
+
}
|
107
|
+
|
108
|
+
.editify-attachment-upload {
|
109
|
+
display: flex;
|
110
|
+
justify-content: center;
|
111
|
+
align-items: center;
|
112
|
+
width: 100%;
|
113
|
+
padding: 15px 0;
|
114
|
+
font-size: 36px;
|
115
|
+
opacity: 0.8;
|
116
|
+
transition: all 200ms;
|
117
|
+
position: relative;
|
118
|
+
|
119
|
+
&:hover {
|
120
|
+
cursor: pointer;
|
121
|
+
opacity: 1;
|
122
|
+
}
|
123
|
+
|
124
|
+
input {
|
125
|
+
opacity: 0;
|
126
|
+
position: absolute;
|
127
|
+
left: 0;
|
128
|
+
top: 0;
|
129
|
+
width: 100%;
|
130
|
+
height: 100%;
|
131
|
+
z-index: 1;
|
132
|
+
cursor: pointer;
|
133
|
+
}
|
134
|
+
}
|
135
|
+
}
|
@@ -0,0 +1,189 @@
|
|
1
|
+
<template>
|
2
|
+
<div class="editify-attachment">
|
3
|
+
<div class="editify-attachment-header">
|
4
|
+
<div @click="current = 'upload'" class="editify-attachment-header-item" :class="{ 'editify-active': current == 'upload' }" :style="activeStyle('upload')">{{ $editTrans('uploadAttachment') }}</div>
|
5
|
+
<div @click="current = 'remote'" class="editify-attachment-header-item" :class="{ 'editify-active': current == 'remote' }" :style="activeStyle('remote')">{{ $editTrans('remoteAttachment') }}</div>
|
6
|
+
<div class="editify-attachment-header-slider" :class="'editify-' + current" :style="{ backgroundColor: color || '' }"></div>
|
7
|
+
</div>
|
8
|
+
<!-- 网络图片 -->
|
9
|
+
<div class="editify-attachment-remote" v-if="current == 'remote'">
|
10
|
+
<input v-model.trim="remoteUrl" :placeholder="$editTrans('attachmentUrlPlaceholder')" @blur="handleInputBlur" @focus="handleInputFocus" />
|
11
|
+
<div class="editify-attachment-remote-footer" :style="{ color: color || '' }">
|
12
|
+
<span @click="insertRemoteAttachment">{{ $editTrans('insert') }}</span>
|
13
|
+
</div>
|
14
|
+
</div>
|
15
|
+
<!-- 上传图片 -->
|
16
|
+
<div class="editify-attachment-upload" v-else>
|
17
|
+
<Icon value="upload"></Icon>
|
18
|
+
<input :multiple="multiple" :accept="acceptValue" @change="selectFile" type="file" />
|
19
|
+
</div>
|
20
|
+
</div>
|
21
|
+
</template>
|
22
|
+
<script setup lang="ts">
|
23
|
+
import { file as DapFile } from 'dap-util'
|
24
|
+
import Icon from '../../../components/icon/icon.vue'
|
25
|
+
import { InsertAttachmentProps } from './props'
|
26
|
+
import { computed, inject, ref, watch } from 'vue'
|
27
|
+
import { ObjectType } from '../../../core/tool'
|
28
|
+
|
29
|
+
defineOptions({
|
30
|
+
name: 'InsertAttachment'
|
31
|
+
})
|
32
|
+
const props = defineProps(InsertAttachmentProps)
|
33
|
+
const emits = defineEmits(['change', 'insert'])
|
34
|
+
|
35
|
+
const $editTrans = inject<(key: string) => any>('$editTrans')!
|
36
|
+
|
37
|
+
//当前展示的面板,取值remote和upload
|
38
|
+
const current = ref<'remote' | 'upload'>('upload')
|
39
|
+
//远程图片链接
|
40
|
+
const remoteUrl = ref<string>('')
|
41
|
+
|
42
|
+
const activeStyle = computed<(name: 'remote' | 'upload') => ObjectType>(() => {
|
43
|
+
return (name: 'remote' | 'upload') => {
|
44
|
+
if (current.value == name) {
|
45
|
+
return {
|
46
|
+
color: props.color
|
47
|
+
}
|
48
|
+
}
|
49
|
+
return {}
|
50
|
+
}
|
51
|
+
})
|
52
|
+
const acceptValue = computed<string | undefined>(() => {
|
53
|
+
if (props.accept === 'rar') {
|
54
|
+
return 'application/x-rar-compressed'
|
55
|
+
}
|
56
|
+
if (props.accept === 'zip') {
|
57
|
+
return 'application/x-zip-compressed'
|
58
|
+
}
|
59
|
+
if (props.accept === 'txt') {
|
60
|
+
return 'text/plain'
|
61
|
+
}
|
62
|
+
if (props.accept === 'image') {
|
63
|
+
return 'image/*'
|
64
|
+
}
|
65
|
+
if (props.accept === 'video') {
|
66
|
+
return 'video/*'
|
67
|
+
}
|
68
|
+
if (props.accept === 'audio') {
|
69
|
+
return 'aduio/*'
|
70
|
+
}
|
71
|
+
if (props.accept === 'html') {
|
72
|
+
return 'text/html'
|
73
|
+
}
|
74
|
+
if (props.accept === 'doc') {
|
75
|
+
return 'application/msword'
|
76
|
+
}
|
77
|
+
if (props.accept === 'xml') {
|
78
|
+
return 'text/xml'
|
79
|
+
}
|
80
|
+
if (props.accept === 'js') {
|
81
|
+
return 'text/javascript'
|
82
|
+
}
|
83
|
+
if (props.accept === 'json') {
|
84
|
+
return 'application/json'
|
85
|
+
}
|
86
|
+
if (props.accept === 'ppt') {
|
87
|
+
return 'application/vnd.ms-powerpoint'
|
88
|
+
}
|
89
|
+
if (props.accept === 'pdf') {
|
90
|
+
return 'application/pdf'
|
91
|
+
}
|
92
|
+
})
|
93
|
+
|
94
|
+
//获取文件后缀
|
95
|
+
const getSuffix = (file: File) => {
|
96
|
+
const index = file.name.lastIndexOf('.')
|
97
|
+
if (index <= 0) {
|
98
|
+
return ''
|
99
|
+
}
|
100
|
+
return file.name.substring(index + 1)
|
101
|
+
}
|
102
|
+
//输入框获取焦点
|
103
|
+
const handleInputFocus = (e: Event) => {
|
104
|
+
if (props.color) {
|
105
|
+
;(<HTMLInputElement>e.currentTarget).style.borderColor = props.color
|
106
|
+
}
|
107
|
+
}
|
108
|
+
//输入框失去焦点
|
109
|
+
const handleInputBlur = (e: Event) => {
|
110
|
+
;(<HTMLInputElement>e.currentTarget).style.borderColor = ''
|
111
|
+
}
|
112
|
+
//插入网络文件
|
113
|
+
const insertRemoteAttachment = () => {
|
114
|
+
emits('insert', remoteUrl.value)
|
115
|
+
}
|
116
|
+
//选择文件
|
117
|
+
const selectFile = async (e: Event) => {
|
118
|
+
const inputEle = <HTMLInputElement>e.currentTarget
|
119
|
+
const files = inputEle.files
|
120
|
+
if (!files || !files.length) {
|
121
|
+
return
|
122
|
+
}
|
123
|
+
let filterFiles = []
|
124
|
+
for (let i = 0; i < files.length; i++) {
|
125
|
+
const file = files[i]
|
126
|
+
const suffix = getSuffix(file)
|
127
|
+
const isMatch =
|
128
|
+
props.allowedFileType && Array.isArray(props.allowedFileType) && props.allowedFileType.length
|
129
|
+
? props.allowedFileType.some(item => {
|
130
|
+
return item.toLocaleLowerCase() == suffix.toLocaleLowerCase()
|
131
|
+
})
|
132
|
+
: true
|
133
|
+
//后缀不符合
|
134
|
+
if (!isMatch) {
|
135
|
+
//如果自定义了异常处理
|
136
|
+
if (typeof props.handleError == 'function') {
|
137
|
+
props.handleError('suffixError', file)
|
138
|
+
}
|
139
|
+
continue
|
140
|
+
}
|
141
|
+
//超过最大值
|
142
|
+
if (props.maxSize && file.size / 1024 > props.maxSize) {
|
143
|
+
//如果自定义了异常处理
|
144
|
+
if (typeof props.handleError == 'function') {
|
145
|
+
props.handleError('maxSizeError', file)
|
146
|
+
}
|
147
|
+
continue
|
148
|
+
}
|
149
|
+
//没达到最小值
|
150
|
+
if (props.minSize && file.size / 1024 < props.minSize) {
|
151
|
+
//如果自定义了异常处理
|
152
|
+
if (typeof props.handleError == 'function') {
|
153
|
+
props.handleError('minSizeError', file)
|
154
|
+
}
|
155
|
+
continue
|
156
|
+
}
|
157
|
+
filterFiles.push(file)
|
158
|
+
}
|
159
|
+
//有文件可上传
|
160
|
+
if (filterFiles.length) {
|
161
|
+
let attachments = []
|
162
|
+
//自定义上传方法
|
163
|
+
if (typeof props.customUpload == 'function') {
|
164
|
+
attachments = (await props.customUpload(filterFiles)) || []
|
165
|
+
}
|
166
|
+
//默认上传方法
|
167
|
+
else {
|
168
|
+
for (let i = 0; i < filterFiles.length; i++) {
|
169
|
+
const url = await DapFile.dataFileToBase64(filterFiles[i])
|
170
|
+
attachments.push(url)
|
171
|
+
}
|
172
|
+
}
|
173
|
+
attachments.forEach(url => {
|
174
|
+
emits('insert', url)
|
175
|
+
})
|
176
|
+
}
|
177
|
+
//清空文件选择框
|
178
|
+
inputEle.value = ''
|
179
|
+
}
|
180
|
+
|
181
|
+
//监听current变更触发change事件
|
182
|
+
watch(
|
183
|
+
() => current.value,
|
184
|
+
() => {
|
185
|
+
emits('change')
|
186
|
+
}
|
187
|
+
)
|
188
|
+
</script>
|
189
|
+
<style scoped src="./insertAttachment.less"></style>
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import { ExtractPublicPropTypes, PropType } from 'vue'
|
2
|
+
|
3
|
+
export type InsertAttachmentUploadErrorType = 'suffixError' | 'maxSizeError' | 'minSizeError'
|
4
|
+
|
5
|
+
export const InsertAttachmentProps = {
|
6
|
+
//主题色
|
7
|
+
color: {
|
8
|
+
type: String as PropType<string | null>,
|
9
|
+
default: ''
|
10
|
+
},
|
11
|
+
//可选择的文件类型
|
12
|
+
accept: {
|
13
|
+
type: String as PropType<'rar' | 'zip' | 'txt' | 'image' | 'video' | 'audio' | 'html' | 'doc' | 'xml' | 'js' | 'json' | 'ppt' | 'pdf' | null>,
|
14
|
+
default: null
|
15
|
+
},
|
16
|
+
//支持的类型数组
|
17
|
+
allowedFileType: {
|
18
|
+
type: Array as PropType<string[]>,
|
19
|
+
default: null
|
20
|
+
},
|
21
|
+
//是否支持多选
|
22
|
+
multiple: {
|
23
|
+
type: Boolean,
|
24
|
+
default: false
|
25
|
+
},
|
26
|
+
//单个文件最大值
|
27
|
+
maxSize: {
|
28
|
+
type: Number,
|
29
|
+
default: null
|
30
|
+
},
|
31
|
+
//单个文件最小值
|
32
|
+
minSize: {
|
33
|
+
type: Number,
|
34
|
+
default: null
|
35
|
+
},
|
36
|
+
//是否自定义上传附件
|
37
|
+
customUpload: {
|
38
|
+
type: Function as PropType<(files: File[]) => string[] | Promise<string[]>>,
|
39
|
+
default: null
|
40
|
+
},
|
41
|
+
//处理上传附件异常
|
42
|
+
handleError: {
|
43
|
+
type: Function as PropType<(error: InsertAttachmentUploadErrorType, file: File) => void>,
|
44
|
+
default: null
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
export type InsertAttachmentPropsType = ExtractPublicPropTypes<typeof InsertAttachmentProps>
|