web-上传组件、富文本组件

This commit is contained in:
2025-10-20 11:25:34 +08:00
parent f137d7d720
commit 2f1835bdbf
12 changed files with 1608 additions and 445 deletions

View File

@@ -107,7 +107,7 @@ import Quill from 'quill';
import { FileUpload } from '@/components/file';
import type { SysFile } from '@/types';
import { FILE_DOWNLOAD_URL } from '@/config';
import { ImageResize } from '@/utils/quill-resize';
import { registerImageResize } from '@/utils/quill-resize';
// Quill 样式已在 main.ts 中全局引入
interface Props {
@@ -204,7 +204,10 @@ function initQuill() {
const node = super.create() as HTMLVideoElement;
node.setAttribute('src', value);
node.setAttribute('controls', 'true');
node.setAttribute('style', 'max-width: 100%; display: block; margin: 12px auto;');
node.setAttribute('class', 'custom-video');
node.setAttribute('data-custom-video', 'true');
// 视频默认居中显示
node.setAttribute('style', 'max-width: 100%; display: block; margin: 0 auto;');
return node;
}
@@ -213,7 +216,33 @@ function initQuill() {
}
}
// 自定义图片 Blot与文字同行显示
const InlineEmbed: any = Quill.import('blots/embed');
class CustomImageBlot extends InlineEmbed {
static blotName = 'customImage';
static tagName = 'img';
static create(value: string) {
const node = super.create() as HTMLImageElement;
node.setAttribute('src', value);
node.setAttribute('class', 'custom-image');
node.setAttribute('data-custom-image', 'true');
// 图片与文字同行显示
node.setAttribute('style', 'max-width: 100%; display: inline-block; vertical-align: bottom;');
return node;
}
static value(node: HTMLImageElement) {
return node.getAttribute('src');
}
}
Quill.register(VideoBlot);
Quill.register(CustomImageBlot);
// 注册图片/视频拉伸模块
registerImageResize();
// 配置选项
const options = {
@@ -249,7 +278,17 @@ function initQuill() {
matchVisual: false
},
// 启用图片/视频缩放模块
imageResize: ImageResize
imageResize: {
onResizeEnd: () => {
console.log('🔄 图片/视频拉伸结束,强制更新内容');
// 强制触发内容更新
if (quillInstance) {
const html = quillInstance.root.innerHTML;
emit('update:modelValue', html);
emit('change', html);
}
}
}
},
placeholder: props.placeholder,
readOnly: props.readOnly || props.disabled
@@ -369,12 +408,12 @@ function handleUploadSuccess(files: SysFile[]) {
// 根据类型插入内容
if (uploadType.value === 'image') {
// 插入图片
quillInstance!.insertEmbed(range.index, 'image', downloadUrl);
// 插入自定义图片(与文字同行显示)
quillInstance!.insertEmbed(range.index, 'customImage', downloadUrl);
// 移动光标到图片后面
quillInstance!.setSelection(range.index + 1);
} else if (uploadType.value === 'video') {
// 插入自定义视频(使用 customVideo 而不是默认的 video
// 插入自定义视频(单行居中显示
quillInstance!.insertEmbed(range.index, 'customVideo', downloadUrl);
// 移动光标到视频后面
quillInstance!.setSelection(range.index + 1);
@@ -464,50 +503,93 @@ defineExpose({
}
}
// 图片样式 - 默认内联显示,底部对齐
img {
max-width: 100%;
height: auto;
display: inline-block;
vertical-align: bottom;
}
// 视频容器样式
// 视频容器样式 - 默认内联显示,底部对齐
iframe, video {
max-width: 100%;
height: auto;
display: inline-block;
vertical-align: bottom;
}
// 自定义视频默认样式 - 单行居中显示
.custom-video {
max-width: 100%;
height: auto;
display: block;
margin: 12px auto; // 默认居中
margin: 0 auto;
}
// 自定义图片默认样式 - 与文字同行显示
.custom-image {
max-width: 100%;
height: auto;
display: inline-block;
vertical-align: bottom;
}
// Quill 视频包装器
.ql-video {
display: block;
display: inline-block;
max-width: 100%;
}
// 支持对齐方式
// 支持对齐方式 - 图片和视频分别处理
.ql-align-center {
text-align: center;
text-align: center !important;
iframe, video, .ql-video {
margin-left: auto;
margin-right: auto;
// 视频始终居中显示
video, .custom-video {
display: block !important;
margin-left: auto !important;
margin-right: auto !important;
}
// 图片跟随文字对齐
img, .custom-image {
display: inline-block !important;
vertical-align: bottom !important;
}
}
.ql-align-right {
text-align: right;
text-align: right !important;
iframe, video, .ql-video {
margin-left: auto;
margin-right: 0;
// 视频始终居中显示
video, .custom-video {
display: block !important;
margin-left: auto !important;
margin-right: auto !important;
}
// 图片跟随文字对齐
img, .custom-image {
display: inline-block !important;
vertical-align: bottom !important;
}
}
.ql-align-left {
text-align: left;
text-align: left !important;
iframe, video, .ql-video {
margin-left: 0;
margin-right: auto;
// 视频始终居中显示
video, .custom-video {
display: block !important;
margin-left: auto !important;
margin-right: auto !important;
}
// 图片跟随文字对齐
img, .custom-image {
display: inline-block !important;
vertical-align: bottom !important;
}
}