富文本内新增:插入视频,上传视频

This commit is contained in:
王创世 2025-04-16 10:38:48 +08:00
parent 776dbb5c69
commit be7c359f6c
2 changed files with 82 additions and 49 deletions

View File

@ -140,9 +140,6 @@ const toolbarConfig = {
showLinkImg: false, showLinkImg: false,
uploadImgShowBase64: true, uploadImgShowBase64: true,
excludeKeys: [ excludeKeys: [
'insertVideo', //
'uploadVideo',
'group-video',
'insertImage',// 'insertImage',//
'insertLink',// 'insertLink',//
'insertTable',// 'insertTable',//
@ -172,6 +169,25 @@ const editorConfig = {
koiNoticeError('图片限制为1M请调整好再上传'); koiNoticeError('图片限制为1M请调整好再上传');
} }
}, },
},
uploadVideo: {
maxFileSize: 50 * 1024 * 1024,
server: import.meta.env.VITE_WEB_BASE_API + '/api/common/upload',
fieldName: 'file',
meta: {
association_id: 0,
},
customInsert(res, insertFn) { // TS
// customInsert(res, insertFn) { // JS
// res
console.log(res);
// res url alt href
insertFn(res.data.fullurl, '', '')
}, onError: (file, err, res) => {
if (err.message.indexOf('exceeds maximum allowed size') !== -1) {
koiNoticeError('视频限制为50M请调整好再上传');
}
},
} }
} }
} }

View File

@ -4,16 +4,17 @@
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="8"> <el-col :span="8">
<div style="padding: 0px 20px 20px 0px;font-weight: 600">请在图片边框内选定区域</div> <div style="padding: 0px 20px 20px 0px;font-weight: 600">请在图片边框内选定区域</div>
<el-card :body-style="{padding:'0'}" style="padding: 0;position:relative;"> <el-card :body-style="{ padding: '0' }" style="padding: 0;position:relative;">
<div @mousedown="startDrag" @mousemove="onDrag" @mouseup="endDrag" @mouseleave="endDrag" style="width: 100%"> <div @mousedown="startDrag" @mousemove="onDrag" @mouseup="endDrag" @mouseleave="endDrag"
style="width: 100%">
<!-- 图片 --> <!-- 图片 -->
<img draggable="false" id="image-selector" :src="bmInfoData.bm_img" ref="image" alt="image" <img draggable="false" id="image-selector" :src="bmInfoData.bm_img" ref="image" alt="image"
@click="handleClick" @click="handleClick"
style="cursor: crosshair; position: relative; user-select: none; width: 100%; height: auto;" style="cursor: crosshair; position: relative; user-select: none; width: 100%; height: auto;"
@load="onImageLoad"/> @load="onImageLoad" />
<!-- 画布用于绘制矩形路径 --> <!-- 画布用于绘制矩形路径 -->
<canvas id="myCanvas" ref="canvas" :width="imageWidth" :height="imageHeight" <canvas id="myCanvas" ref="canvas" :width="imageWidth" :height="imageHeight"
style="position: absolute; top: 0; left: 0; pointer-events: none;"> style="position: absolute; top: 0; left: 0; pointer-events: none;">
</canvas> </canvas>
</div> </div>
</el-card> </el-card>
@ -21,29 +22,29 @@
<el-col :span="16"> <el-col :span="16">
<el-form :model="form" label-width="auto"> <el-form :model="form" label-width="auto">
<el-form-item label="新闻标题" required> <el-form-item label="新闻标题" required>
<el-input v-model="form.new_name" placeholder="请输入新闻标题" size="large"/> <el-input v-model="form.new_name" placeholder="请输入新闻标题" size="large" />
</el-form-item> </el-form-item>
<el-form-item label="新闻副标题"> <el-form-item label="新闻副标题">
<el-input v-model="form.subtitle" placeholder="请输入新闻副标题" size="large"/> <el-input v-model="form.subtitle" placeholder="请输入新闻副标题" size="large" />
</el-form-item> </el-form-item>
<el-form-item label="新闻记者" required> <el-form-item label="新闻记者" required>
<el-input v-model="form.reporter" placeholder="请输入新闻记者" size="large"/> <el-input v-model="form.reporter" placeholder="请输入新闻记者" size="large" />
</el-form-item> </el-form-item>
<el-form-item label="新闻坐标" required> <el-form-item label="新闻坐标" required>
<el-input disabled v-model="coordinate" placeholder="请选择新闻坐标" size="large"/> <el-input disabled v-model="coordinate" placeholder="请选择新闻坐标" size="large" />
<el-button class="mt-2" @click="allowClickTrue()">重新选择</el-button> <el-button class="mt-2" @click="allowClickTrue()">重新选择</el-button>
</el-form-item> </el-form-item>
<el-form-item label="媒体链接"> <el-form-item label="媒体链接">
<el-input v-model="form.video" placeholder="请输入媒体链接" size="large"/> <el-input v-model="form.video" placeholder="请输入媒体链接" size="large" />
</el-form-item> </el-form-item>
<el-form-item label="跳转链接"> <el-form-item label="跳转链接">
<el-input v-model="form.jump_link" placeholder="请输入跳转链接" size="large"/> <el-input v-model="form.jump_link" placeholder="请输入跳转链接" size="large" />
</el-form-item> </el-form-item>
<el-form-item label="新闻详情" required> <el-form-item label="新闻详情" required>
<el-card shadow="hover"> <el-card shadow="hover">
<Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" :defaultConfig="toolbarConfig"/> <Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" :defaultConfig="toolbarConfig" />
<Editor style="height: 300px; overflow-y: hidden;" v-model="form.content" :defaultConfig="editorConfig" <Editor style="height: 300px; overflow-y: hidden;" v-model="form.content" :defaultConfig="editorConfig"
@onCreated="handleCreated"/> @onCreated="handleCreated" />
</el-card> </el-card>
</el-form-item> </el-form-item>
<el-form-item label=" "> <el-form-item label=" ">
@ -59,24 +60,24 @@
<script setup lang="ts"> <script setup lang="ts">
import '@wangeditor/editor/dist/css/style.css' // css import '@wangeditor/editor/dist/css/style.css' // css
import {getAssets} from "@/utils/index.ts"; import { getAssets } from "@/utils/index.ts";
import {onBeforeUnmount, ref, shallowRef, onMounted, reactive, nextTick} from 'vue' import { onBeforeUnmount, ref, shallowRef, onMounted, reactive, nextTick } from 'vue'
import {Editor, Toolbar} from '@wangeditor/editor-for-vue' import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import {bmInfo, newsAdd, newsInfo, newsUpdate} from "@/api/system/post"; import { bmInfo, newsAdd, newsInfo, newsUpdate } from "@/api/system/post";
import {koiNoticeError, koiNoticeSuccess} from "@/utils/koi.ts"; import { koiNoticeError, koiNoticeSuccess } from "@/utils/koi.ts";
import {useRoute, useRouter} from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import useTabsStore from "@/stores/modules/tabs.ts"; // useRoute import useTabsStore from "@/stores/modules/tabs.ts"; // useRoute
const router = useRouter(); const router = useRouter();
const tabsStore = useTabsStore(); const tabsStore = useTabsStore();
const form = reactive({ const form = reactive({
new_name: '', new_name: '',
coordinate: '', coordinate: '',
coordinate_show:'', coordinate_show: '',
subtitle: '', subtitle: '',
reporter: '', reporter: '',
content: '', content: '',
video: '', video: '',
jump_link:'', jump_link: '',
}); });
/*新闻坐标 真实的*/ /*新闻坐标 真实的*/
const coordinate = ref(); const coordinate = ref();
@ -92,7 +93,7 @@ onMounted(() => {
}) })
const getNewsInfo = async () => { const getNewsInfo = async () => {
try { try {
const res: any = await newsInfo({id: id.value}); const res: any = await newsInfo({ id: id.value });
console.log("菜单数据表格数据->", res.data); console.log("菜单数据表格数据->", res.data);
form.new_name = res.data.new_name; form.new_name = res.data.new_name;
form.subtitle = res.data.subtitle; form.subtitle = res.data.subtitle;
@ -101,7 +102,7 @@ const getNewsInfo = async () => {
form.id = res.data.id; form.id = res.data.id;
form.bm_id = res.data.bm_id; form.bm_id = res.data.bm_id;
form.coordinate = res.data.coordinate; form.coordinate = res.data.coordinate;
form.coordinate_show=res.data.coordinate_show; form.coordinate_show = res.data.coordinate_show;
form.video = res.data.video; form.video = res.data.video;
form.jump_link = res.data.jump_link; form.jump_link = res.data.jump_link;
coordinate.value = res.data.coordinate; coordinate.value = res.data.coordinate;
@ -117,7 +118,7 @@ const getNewsInfo = async () => {
} }
const getBmInfo = async (bm_id) => { const getBmInfo = async (bm_id) => {
try { try {
const res: any = await bmInfo({id: bm_id}); const res: any = await bmInfo({ id: bm_id });
console.log("菜单数据表格数据->", res.data); console.log("菜单数据表格数据->", res.data);
bmInfoData.value = res.data; bmInfoData.value = res.data;
var coordArray = coordinateShow.value.split(","); var coordArray = coordinateShow.value.split(",");
@ -126,7 +127,7 @@ const getBmInfo = async (bm_id) => {
var yy1 = parseInt(sArray[1]); var yy1 = parseInt(sArray[1]);
var xx2 = parseInt(sArray[2]); var xx2 = parseInt(sArray[2]);
var yy2 = parseInt(sArray[3]); var yy2 = parseInt(sArray[3]);
s.value = {xx1, yy1, xx2, yy2}; s.value = { xx1, yy1, xx2, yy2 };
var x1 = parseInt(coordArray[0]); var x1 = parseInt(coordArray[0]);
var y1 = parseInt(coordArray[1]); var y1 = parseInt(coordArray[1]);
var x2 = parseInt(coordArray[2]); var x2 = parseInt(coordArray[2]);
@ -139,7 +140,7 @@ const getBmInfo = async (bm_id) => {
} }
} }
const updateDrawRectanglePath = (x1, y1, x2, y2) => { const updateDrawRectanglePath = (x1, y1, x2, y2) => {
rectCoordinates.value = {x1, y1, x2, y2}; rectCoordinates.value = { x1, y1, x2, y2 };
// //
rect.value = { rect.value = {
left: `${x1}px`, left: `${x1}px`,
@ -161,7 +162,7 @@ const updateDrawRectanglePath = (x1, y1, x2, y2) => {
/*文章保存*/ /*文章保存*/
const onSubmit = async () => { const onSubmit = async () => {
form.coordinate = coordinate.value; form.coordinate = coordinate.value;
form.coordinate_show=coordinateShow.value ; form.coordinate_show = coordinateShow.value;
console.log(form); console.log(form);
try { try {
const res: any = await newsUpdate(form); const res: any = await newsUpdate(form);
@ -179,9 +180,6 @@ const toolbarConfig = {
showLinkImg: false, showLinkImg: false,
uploadImgShowBase64: true, uploadImgShowBase64: true,
excludeKeys: [ excludeKeys: [
'insertVideo', //
'uploadVideo',
'group-video',
'insertImage',// 'insertImage',//
'insertLink',// 'insertLink',//
'insertTable',// 'insertTable',//
@ -206,11 +204,30 @@ const editorConfig = {
console.log(res); console.log(res);
// res url alt href // res url alt href
insertFn(res.data.fullurl, '', '') insertFn(res.data.fullurl, '', '')
}, onError:(file, err, res)=>{ }, onError: (file, err, res) => {
if(err.message.indexOf('exceeds maximum allowed size') !== -1){ if (err.message.indexOf('exceeds maximum allowed size') !== -1) {
koiNoticeError('图片限制为1M请调整好再上传'); koiNoticeError('图片限制为1M请调整好再上传');
} }
}, },
},
uploadVideo: {
maxFileSize: 50 * 1024 * 1024,
server: import.meta.env.VITE_WEB_BASE_API + '/api/common/upload',
fieldName: 'file',
meta: {
association_id: 0,
},
customInsert(res, insertFn) { // TS
// customInsert(res, insertFn) { // JS
// res
console.log(res);
// res url alt href
insertFn(res.data.fullurl, '', '')
}, onError: (file, err, res) => {
if (err.message.indexOf('exceeds maximum allowed size') !== -1) {
koiNoticeError('视频限制为50M请调整好再上传');
}
},
} }
} }
} }
@ -238,7 +255,7 @@ const imageWidth = ref(0); // 图片宽度
const imageHeight = ref(0); // const imageHeight = ref(0); //
const imageLoaded = ref(false); // const imageLoaded = ref(false); //
const isDragging = ref(false); // const isDragging = ref(false); //
const dragStart = ref({x: 0, y: 0}); // const dragStart = ref({ x: 0, y: 0 }); //
const allowClick = ref(true); // const allowClick = ref(true); //
const allowClickTrue = () => { const allowClickTrue = () => {
@ -274,8 +291,8 @@ const handleClick = (event) => {
const x = event.clientX - rect.left; const x = event.clientX - rect.left;
const y = event.clientY - rect.top; const y = event.clientY - rect.top;
// //
points.value.push({x, y}); points.value.push({ x, y });
showPoints.value.push({xx, yy}); showPoints.value.push({ xx, yy });
console.log(`Clicked at: (${x}, ${y})`); // console.log(`Clicked at: (${x}, ${y})`); //
console.log(`Clicked at a: (${xx}, ${yy})`); // console.log(`Clicked at a: (${xx}, ${yy})`); //
// canvas // canvas
@ -333,8 +350,8 @@ const showCalculateRectangle = () => {
const yy1 = Math.min(p1.yy, p2.yy, p3.yy, p4.yy); const yy1 = Math.min(p1.yy, p2.yy, p3.yy, p4.yy);
const xx2 = Math.max(p1.xx, p2.xx, p3.xx, p4.xx); const xx2 = Math.max(p1.xx, p2.xx, p3.xx, p4.xx);
const yy2 = Math.max(p1.yy, p2.yy, p3.yy, p4.yy); const yy2 = Math.max(p1.yy, p2.yy, p3.yy, p4.yy);
s.value = {xx1, yy1, xx2, yy2}; s.value = { xx1, yy1, xx2, yy2 };
console.log('s', s.value); console.log('s', s.value);
coordinate.value = `${xx1},${yy1},${xx2},${yy2}`; coordinate.value = `${xx1},${yy1},${xx2},${yy2}`;
}; };
// //
@ -346,7 +363,7 @@ const calculateRectangle = () => {
const x2 = Math.max(p1.x, p2.x, p3.x, p4.x); const x2 = Math.max(p1.x, p2.x, p3.x, p4.x);
const y2 = Math.max(p1.y, p2.y, p3.y, p4.y); const y2 = Math.max(p1.y, p2.y, p3.y, p4.y);
rectCoordinates.value = {x1, y1, x2, y2}; rectCoordinates.value = { x1, y1, x2, y2 };
// //
rect.value = { rect.value = {
@ -401,7 +418,7 @@ const startDrag = (event: MouseEvent) => {
if (rectCoordinates.value) { // if (rectCoordinates.value) { //
isDragging.value = true; isDragging.value = true;
allowClick.value = false; // allowClick.value = false; //
dragStart.value = {x: event.clientX, y: event.clientY}; dragStart.value = { x: event.clientX, y: event.clientY };
} }
}; };
@ -415,15 +432,15 @@ const onDrag = (event) => {
rectCoordinates.value.y1 += dy; rectCoordinates.value.y1 += dy;
rectCoordinates.value.x2 += dx; rectCoordinates.value.x2 += dx;
rectCoordinates.value.y2 += dy; rectCoordinates.value.y2 += dy;
console.log( s.value) console.log(s.value)
// //
s.value.xx1 += dx; s.value.xx1 += dx;
s.value.yy1 += dy; s.value.yy1 += dy;
s.value.xx2 += dx; s.value.xx2 += dx;
s.value.yy2 += dy; s.value.yy2 += dy;
coordinate.value = `${s.value.xx1},${s.value.yy1},${s.value.xx2},${s.value.yy2}`; coordinate.value = `${s.value.xx1},${s.value.yy1},${s.value.xx2},${s.value.yy2}`;
// //
dragStart.value = {x: event.clientX, y: event.clientY}; dragStart.value = { x: event.clientX, y: event.clientY };
// //
drawRectanglePath(rectCoordinates.value.x1, rectCoordinates.value.y1, rectCoordinates.value.x2, rectCoordinates.value.y2); drawRectanglePath(rectCoordinates.value.x1, rectCoordinates.value.y1, rectCoordinates.value.x2, rectCoordinates.value.y2);
} }