<template>
|
<div class="rich-edit-wrapper">
|
<div v-for="(item, index) in props.modelValue" :key="index" class="rich-edit-item-wrapper">
|
<div class="rich-edit-item-top">
|
<el-tooltip placement="top-start" content="上移">
|
<el-button
|
:disabled="index == 0"
|
class="rich-edit-item-top-button"
|
circle
|
type="primary"
|
icon="Top"
|
@click="handleMoveUp(index)"
|
></el-button>
|
</el-tooltip>
|
<el-tooltip placement="top-start" content="下移">
|
<el-button
|
:disabled="index == props.modelValue.length - 1"
|
class="rich-edit-item-top-button"
|
circle
|
type="primary"
|
icon="Bottom"
|
@click="handleMoveDown(index)"
|
></el-button>
|
</el-tooltip>
|
<el-tooltip placement="top-start" content="删除">
|
<el-button
|
:disabled="props.modelValue.length <= 1"
|
class="rich-edit-item-top-button"
|
circle
|
type="primary"
|
icon="Delete"
|
@click="handleDelete(index)"
|
></el-button>
|
</el-tooltip>
|
</div>
|
<div class="rich-edit-item">
|
<FieldTextArea
|
v-if="item.type === EditorType.Text"
|
v-model="item.content"
|
placeholder="请输入文本"
|
:maxlength="maxLength"
|
></FieldTextArea>
|
<ReadAbleImage v-else-if="item.type === EditorType.Image" :src="setOSSLink(item.path)" />
|
<video-player
|
v-else-if="item.type === EditorType.Video"
|
class="video-player-box"
|
playsinline
|
:options="{
|
aspectRatio: '16:9',
|
autoplay: false,
|
muted: false,
|
language: 'en',
|
fluid: false,
|
poster: '', // 封面地址
|
controls: true,
|
controlBar: {
|
timeDivider: false, // 当前时间和持续时间的分隔符
|
durationDisplay: false, // 显示持续时间
|
remainingTimeDisplay: false, // 是否显示剩余时间功能
|
fullscreenToggle: true, // 是否显示全屏按钮
|
},
|
sources: [
|
{
|
type: 'video/mp4', // 类型
|
src: setOSSLink(item.path), // url地址
|
},
|
],
|
}"
|
src="/src/assets/boleclound.png"
|
/>
|
</div>
|
</div>
|
|
<div class="rich-edit-actions">
|
<el-button type="primary" icon="Plus" round @click="handleAddTextEditor">添加文本</el-button>
|
<BlFileUpload
|
accept="jpg/jpeg,png"
|
:show-file-list="false"
|
:on-success="uploadImageSuccess"
|
:showTip="false"
|
class="uploader-btn-wrapper"
|
>
|
<el-button type="primary" icon="Plus" round>添加图片</el-button>
|
</BlFileUpload>
|
<BlFileUpload
|
:accept="'avi,mp4,wmv,mpg,mpg,mov,ram,swf,flv'"
|
:show-file-list="false"
|
:on-success="uploadVideoSuccess"
|
:showTip="false"
|
class="uploader-btn-wrapper"
|
>
|
<el-button type="primary" icon="Plus" round>添加视频</el-button>
|
</BlFileUpload>
|
</div>
|
</div>
|
</template>
|
|
<script setup lang="ts">
|
import { FieldTextArea, ReadAbleImage, BlFileUpload } from '@bole-core/components';
|
import { VideoPlayer } from '@videojs-player/vue';
|
import { EditorType, EmptyTextEditorItem } from '@/constants';
|
import { setOSSLink } from '@/utils';
|
|
defineOptions({
|
name: 'RichEdit',
|
});
|
|
type Props = {
|
modelValue?: API.IntroInfo[];
|
maxLength?: number;
|
};
|
|
const props = withDefaults(defineProps<Props>(), {
|
modelValue: () => [] as API.IntroInfo[],
|
});
|
|
function handleMoveUp(index: number) {
|
[props.modelValue[index], props.modelValue[index - 1]] = [
|
props.modelValue[index - 1],
|
props.modelValue[index],
|
];
|
props.modelValue.forEach((item, index) => {
|
item.sequence = index;
|
});
|
}
|
|
function handleMoveDown(index: number) {
|
[props.modelValue[index + 1], props.modelValue[index]] = [
|
props.modelValue[index],
|
props.modelValue[index + 1],
|
];
|
props.modelValue.forEach((item, index) => {
|
item.sequence = index;
|
});
|
}
|
|
function handleDelete(index: number) {
|
// eslint-disable-next-line vue/no-mutating-props
|
props.modelValue.splice(index, 1);
|
}
|
|
const createLastSequence = () => {
|
const lastSequence = props.modelValue[props.modelValue.length - 1]?.sequence ?? 0;
|
return lastSequence + 1;
|
};
|
|
function handleAddTextEditor() {
|
// eslint-disable-next-line vue/no-mutating-props
|
props.modelValue.push({
|
...EmptyTextEditorItem,
|
sequence: createLastSequence(),
|
});
|
}
|
|
function uploadImageSuccess(res) {
|
console.log('file: ', res);
|
// eslint-disable-next-line vue/no-mutating-props
|
props.modelValue.push({
|
type: EditorType.Image,
|
path: res.path,
|
sequence: createLastSequence(),
|
});
|
}
|
|
function uploadVideoSuccess(res) {
|
console.log('file: ', res);
|
// eslint-disable-next-line vue/no-mutating-props
|
props.modelValue.push({
|
type: EditorType.Video,
|
path: res.path,
|
sequence: createLastSequence(),
|
});
|
}
|
</script>
|
|
<style lang="scss" scoped>
|
@use '@/style/common.scss' as *;
|
|
.rich-edit-wrapper {
|
width: 100%;
|
|
.rich-edit-item-wrapper {
|
margin-bottom: 16px;
|
|
.rich-edit-item-top {
|
margin-bottom: 6px;
|
}
|
|
.rich-edit-item-top-button {
|
width: 24px;
|
height: 24px !important;
|
font-size: 12px;
|
}
|
|
.video-player-box {
|
margin-bottom: 14px;
|
padding-top: 0 !important;
|
width: 400px;
|
height: 150px;
|
}
|
}
|
|
.uploader-btn-wrapper {
|
display: inline-flex;
|
vertical-align: middle;
|
margin-left: 10px;
|
width: auto !important;
|
}
|
}
|
</style>
|