pro-wang-plugin-upload-attachment
Version:
wangEditor 上传附件
162 lines (135 loc) • 4 kB
text/typescript
/**
* @description helper fns
* @author wangfupeng
*/
import Uppy, { UppyFile } from '@uppy/core'
import { IDomEditor } from '@wangeditor/editor'
import { createUploader } from '@wangeditor/editor'
import { AttachmentElement } from '../custom-types'
import { IUploadConfigForAttachment } from './config'
function getUploadAttachmentMenuConfig(editor: IDomEditor): IUploadConfigForAttachment {
// 获取配置,见 `./config.js`
return editor.getMenuConfig('uploadAttachment') as IUploadConfigForAttachment
}
/**
* 插入 attachment 节点
* @param fileName fileName
* @param link link
*/
export function insertAttachment(editor: IDomEditor, fileName: string, link: string) {
if (!fileName || !link) return
// 还原选区
editor.restoreSelection()
// 插入节点
const attachmentElem: AttachmentElement = {
type: 'attachment',
fileName,
link,
children: [{ text: '' }],
}
editor.insertNode(attachmentElem)
editor.move(1)
// 回调
const { onInsertedAttachment } = getUploadAttachmentMenuConfig(editor)
if (onInsertedAttachment) onInsertedAttachment(attachmentElem)
}
/**
* 上传附件文件
* @param editor editor
* @param files files
*/
export async function uploadAttachments(editor: IDomEditor, files: FileList | null) {
if (files == null) return
const fileList = Array.prototype.slice.call(files)
// 获取菜单配置
const { customUpload } = getUploadAttachmentMenuConfig(editor)
// 按顺序上传
for await (const file of fileList) {
// 上传
if (customUpload) {
// 自定义上传
await customUpload(file, (fileName: string, link: string) =>
insertAttachment(editor, fileName, link)
)
} else {
// 默认上传
await uploadFile(editor, file)
}
}
}
/**
* 上传文件
* @param editor editor
* @param file file
*/
async function uploadFile(editor: IDomEditor, file: File) {
const uppy = getUppy(editor)
const { name, type, size } = file
uppy.addFile({
name,
type,
size,
data: file,
})
await uppy.upload()
}
// 存储 editor uppy 的关系 - 缓存 uppy ,不重复创建
const EDITOR_TO_UPPY_MAP = new WeakMap<IDomEditor, Uppy>()
/**
* 获取 uppy 实例(并通过 editor 缓存)
* @param editor editor
*/
function getUppy(editor: IDomEditor): Uppy {
// 从缓存中获取
let uppy = EDITOR_TO_UPPY_MAP.get(editor)
if (uppy != null) return uppy
const menuConfig = getUploadAttachmentMenuConfig(editor)
const { onSuccess, onProgress, onFailed, customInsert, onError } = menuConfig
// 上传完成之后
const successHandler = (file: UppyFile, res: any) => {
// 预期 res 格式:
// 成功:{ errno: 0, data: { url } }
// 失败:{ errno: !0, message: '失败信息' }
if (customInsert) {
// 用户自定义插入文件,此时 res 格式可能不符合预期
customInsert(res, file, (fileName: string, link: string) =>
insertAttachment(editor, fileName, link)
)
return
}
const { errno = 1, data = {} } = res
if (errno !== 0) {
console.error(`'${file.name}' upload failed`, res)
// failed 回调
onFailed(file, res)
return
}
const { url = '' } = data
insertAttachment(editor, file.name, url)
// success 回调
onSuccess(file, res)
}
// progress 显示进度条
const progressHandler = (progress: number) => {
editor.showProgressBar(progress)
// 回调函数
onProgress && onProgress(progress)
}
// onError 提示错误
const errorHandler = (file: any, err: any, res: any) => {
const fileName = file.name
console.error(`'${fileName} upload error`, err, res)
// 回调函数
onError && onError(file, err, res)
}
// 创建 uppy
uppy = createUploader({
...menuConfig,
onProgress: progressHandler,
onSuccess: successHandler,
onError: errorHandler,
})
// 缓存 uppy
EDITOR_TO_UPPY_MAP.set(editor, uppy)
return uppy
}