editor 富文本编辑器上传图片,视频功能更新

This commit is contained in:
ktianc 2023-08-08 11:08:30 +08:00
parent cf6a60ad3a
commit 6360dff110
10 changed files with 103 additions and 19 deletions

View File

@ -2,7 +2,7 @@
import { ElCard, ElButton } from 'element-plus'
import { propTypes } from '@/utils/propTypes'
import { useDesign } from '@/hooks/web/useDesign'
import { ref, onMounted, defineEmits } from 'vue'
import { ref, onMounted } from 'vue'
import { Sticky } from '@/components/Sticky'
import { useI18n } from '@/hooks/web/useI18n'
const { t } = useI18n()
@ -15,9 +15,11 @@ defineProps({
title: propTypes.string.def(''),
message: propTypes.string.def('')
})
const emit = defineEmits(['back'])
const offset = ref(85)
const contentDetailWrap = ref()
onMounted(() => {
offset.value = contentDetailWrap.value.getBoundingClientRect().top
})

View File

@ -6,6 +6,9 @@ import { propTypes } from '@/utils/propTypes'
import { isNumber } from '@/utils/is'
import { ElMessage } from 'element-plus'
import { useLocaleStore } from '@/store/modules/locale'
import { uploadImageToOSS, uploadVideoToOSS } from '@/api/vadmin/system/files'
// editor https://www.wangeditor.com/v5/getting-started.html
const localeStore = useLocaleStore()
@ -79,7 +82,48 @@ const editorConfig = computed((): IEditorConfig => {
},
autoFocus: false,
scroll: true,
uploadImgShowBase64: true
uploadImgShowBase64: true,
MENU_CONF: {
uploadImage: {
//
// https://www.wangeditor.com/v5/menu-config.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E4%B8%8A%E4%BC%A0
async customUpload(file: File, insertFn: InsertImageType) {
//
if (!['image/jpeg', 'image/gif', 'image/png'].includes(file.type)) {
return ElMessage.error(`${file.name}上传失败:上传图片只能是 JPG/GIF/PNG/ 格式!`)
}
if (!(file.size / 1024 / 1024 < 2)) {
return ElMessage.error(`${file.name}上传失败:上传图片大小不能超过 2MB!`)
}
// url
const formData = new FormData()
formData.append('file', file)
formData.append('path', 'editor/image')
const res = await uploadImageToOSS(formData)
insertFn(res.data, '', res.data)
}
},
uploadVideo: {
//
// https://www.wangeditor.com/v5/menu-config.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%8A%9F%E8%83%BD-1
async customUpload(file: File, insertFn: InsertVideoType) {
//
if (!['video/mp4', 'video/mpeg'].includes(file.type)) {
return ElMessage.error(`${file.name}上传失败:上传视频只能是 mp4/mpeg/ 格式!`)
}
if (!(file.size / 1024 / 1024 < 5)) {
return ElMessage.error(`${file.name}上传失败:上传视频大小不能超过 5MB!`)
}
// url
const formData = new FormData()
formData.append('file', file)
formData.append('path', 'editor/video')
const res = await uploadVideoToOSS(formData)
insertFn(res.data, '')
}
}
}
},
props.editorConfig || {}
)

View File

@ -173,7 +173,7 @@ export const useTable = <T = any>(config?: UseTableConfig<T>) => {
// 如果为 false则说明是点击按钮则获取当前选择行数据进行删除
delListApi: async (
multiple: boolean,
ids: string[] | number[] | number = [],
ids: string[] | number[] | number | string = [],
message = true
) => {
const tableRef = await getTable()

3
kinit-admin/src/types/editor.d.ts vendored Normal file
View File

@ -0,0 +1,3 @@
type InsertImageType = (url: string, alt: string, href: string) => void
type InsertVideoType = (url: string, poster: string = '') => void

View File

@ -11,7 +11,7 @@ from fastapi.security import OAuth2PasswordBearer
"""
系统版本
"""
VERSION = "1.10.3"
VERSION = "1.10.4"
"""安全警告: 不要在生产中打开调试运行!"""
DEBUG = True

View File

@ -282,8 +282,6 @@ class UserDal(DalBase):
更新当前用户头像
"""
result = await AliyunOSS(BucketConf(**settings.ALIYUN_OSS)).upload_image("avatar", file)
if not result:
raise CustomException(msg="上传失败", code=status.HTTP_ERROR)
user.avatar = result
await self.flush(user)
return result

View File

@ -113,8 +113,18 @@ async def get_dict_detail(data_id: int, auth: Auth = Depends(AllUserAuth())):
@app.post("/upload/image/to/oss", summary="上传图片到阿里云OSS")
async def upload_image_to_oss(file: UploadFile, path: str = Form(...)):
result = await AliyunOSS(BucketConf(**ALIYUN_OSS)).upload_image(path, file)
if not result:
return ErrorResponse(msg="上传失败")
return SuccessResponse(result)
@app.post("/upload/video/to/oss", summary="上传视频到阿里云OSS")
async def upload_video_to_oss(file: UploadFile, path: str = Form(...)):
result = await AliyunOSS(BucketConf(**ALIYUN_OSS)).upload_video(path, file)
return SuccessResponse(result)
@app.post("/upload/file/to/oss", summary="上传文件到阿里云OSS")
async def upload_file_to_oss(file: UploadFile, path: str = Form(...)):
result = await AliyunOSS(BucketConf(**ALIYUN_OSS)).upload_file(path, file)
return SuccessResponse(result)

View File

@ -11,7 +11,9 @@ from fastapi import UploadFile
from pydantic import BaseModel
import oss2 # 安装依赖库pip install oss2
from oss2.models import PutObjectResult
from core.exception import CustomException
from core.logger import logger
from utils import status
from utils.file.compress.cpressJPG import compress_jpg_png
from utils.file.file_manage import FileManage
from utils.file.file_base import FileBase
@ -45,15 +47,19 @@ class AliyunOSS(FileBase):
self.bucket = oss2.Bucket(auth, bucket.endpoint, bucket.bucket)
self.baseUrl = bucket.baseUrl
async def upload_image(self, path: str, file: UploadFile, compress: bool = False) -> str:
async def upload_image(self, path: str, file: UploadFile, compress: bool = False, max_size: int = 10) -> str:
"""
上传图片
:param path: path由包含文件后缀不包含Bucket名称组成的Object完整路径例如abc/efg/123.jpg
:param file: 文件对象
:param compress: 是否压缩该文件
:param max_size: 图片文件最大值单位 MB默认 10MB
:return: 上传后的文件oss链接
"""
# 验证图片类型
await self.validate_file(file, max_size, self.IMAGE_ACCEPT)
# 生成文件路径
path = self.generate_path(path, file.filename)
if compress:
# 压缩图片
@ -63,14 +69,23 @@ class AliyunOSS(FileBase):
file_data = f.read()
else:
file_data = await file.read()
result = self.bucket.put_object(path, file_data)
assert isinstance(result, PutObjectResult)
if result.status != 200:
logger.error(f"图片上传到OSS失败状态码{result.status}")
print("图片上传路径", path)
print(f"图片上传到OSS失败状态码{result.status}")
return ""
return self.baseUrl + path
return await self.__upload_file_to_oss(path, file_data)
async def upload_video(self, path: str, file: UploadFile, max_size: int = 100) -> str:
"""
上传视频
:param path: path由包含文件后缀不包含Bucket名称组成的Object完整路径例如abc/efg/123.jpg
:param file: 文件对象
:param max_size: 视频文件最大值单位 MB默认 100MB
:return: 上传后的文件oss链接
"""
# 验证图片类型
await self.validate_file(file, max_size, self.VIDEO_ACCEPT)
# 生成文件路径
path = self.generate_path(path, file.filename)
file_data = await file.read()
return await self.__upload_file_to_oss(path, file_data)
async def upload_file(self, path: str, file: UploadFile) -> str:
"""
@ -82,9 +97,19 @@ class AliyunOSS(FileBase):
"""
path = self.generate_path(path, file.filename)
file_data = await file.read()
return await self.__upload_file_to_oss(path, file_data)
async def __upload_file_to_oss(self, path: str, file_data: bytes) -> str:
"""
上传文件到OSS
:param path: path由包含文件后缀不包含Bucket名称组成的Object完整路径例如abc/efg/123.jpg
:param file_data: 文件数据
:return: 上传后的文件oss链接
"""
result = self.bucket.put_object(path, file_data)
assert isinstance(result, PutObjectResult)
if result.status != 200:
logger.error(f"文件上传到OSS失败状态码{result.status}")
return ""
raise CustomException("上传文件失败", code=status.HTTP_ERROR)
return self.baseUrl + path

View File

@ -17,7 +17,7 @@ from utils import status
class FileBase:
IMAGE_ACCEPT = ["image/png", "image/jpeg", "image/gif", "image/x-icon"]
VIDEO_ACCEPT = ["audio/mp4", "video/mp4", "video/mpeg"]
VIDEO_ACCEPT = ["video/mp4", "video/mpeg"]
ALL_ACCEPT = [*IMAGE_ACCEPT, *VIDEO_ACCEPT]
@classmethod

View File

@ -16,10 +16,12 @@ https://api.ip138.com/ip/?ip=58.16.180.3&datatype=jsonp&token=cc87f3c77747bccbaa
aiohttp 异步请求文档https://docs.aiohttp.org/en/stable/client_quickstart.html
"""
from aiohttp import TCPConnector
from application.settings import IP_PARSE_TOKEN, IP_PARSE_ENABLE
import aiohttp
from core.logger import logger
from pydantic import BaseModel
from typing import Optional
class IPLocationOut(BaseModel):