营销:增加商城装修组件【视频播放】
This commit is contained in:
parent
fa710b560d
commit
bb2b7ffd03
@ -26,7 +26,7 @@
|
||||
:label="data.label"
|
||||
:prop="data.prop"
|
||||
:label-width="node.level === 1 ? '80px' : '62px'"
|
||||
class="tree-form-item w-full m-b-0!"
|
||||
class="w-full m-b-0!"
|
||||
>
|
||||
<el-slider
|
||||
v-model="formData[data.prop]"
|
||||
@ -40,6 +40,7 @@
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-tree>
|
||||
<slot name="style" :formData="formData"></slot>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</el-tab-pane>
|
||||
@ -153,12 +154,10 @@ const handleSliderChange = (prop: string) => {
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.tree-form-item {
|
||||
:deep(.el-slider__runway) {
|
||||
margin-right: 16px;
|
||||
}
|
||||
:deep(.el-input-number) {
|
||||
width: 50px;
|
||||
}
|
||||
:deep(.el-slider__runway) {
|
||||
margin-right: 16px;
|
||||
}
|
||||
:deep(.el-input-number) {
|
||||
width: 50px;
|
||||
}
|
||||
</style>
|
||||
|
@ -0,0 +1,37 @@
|
||||
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
|
||||
|
||||
/** 视频播放属性 */
|
||||
export interface VideoPlayerProperty {
|
||||
// 视频链接
|
||||
videoUrl: string
|
||||
// 封面链接
|
||||
posterUrl: string
|
||||
// 是否自动播放
|
||||
autoplay: boolean
|
||||
// 组件样式
|
||||
style: VideoPlayerStyle
|
||||
}
|
||||
|
||||
// 视频播放样式
|
||||
export interface VideoPlayerStyle extends ComponentStyle {
|
||||
// 视频高度
|
||||
height: number
|
||||
}
|
||||
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'VideoPlayer',
|
||||
name: '视频播放',
|
||||
icon: 'ep:video-play',
|
||||
property: {
|
||||
videoUrl: '',
|
||||
posterUrl: '',
|
||||
autoplay: false,
|
||||
style: {
|
||||
bgType: 'color',
|
||||
bgColor: '#fff',
|
||||
marginBottom: 8,
|
||||
height: 300
|
||||
} as ComponentStyle
|
||||
}
|
||||
} as DiyComponent<VideoPlayerProperty>
|
@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<div class="w-full" :style="{ height: `${property.style.height}px` }">
|
||||
<el-image class="w-full w-full" :src="property.posterUrl" v-if="property.posterUrl" />
|
||||
<video
|
||||
v-else
|
||||
class="w-full w-full"
|
||||
:src="property.videoUrl"
|
||||
:poster="property.posterUrl"
|
||||
:autoplay="property.autoplay"
|
||||
controls
|
||||
></video>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { VideoPlayerProperty } from './config'
|
||||
|
||||
/** 视频播放 */
|
||||
defineOptions({ name: 'VideoPlayer' })
|
||||
|
||||
defineProps<{ property: VideoPlayerProperty }>()
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
/* 图片 */
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<ComponentContainerProperty v-model="formData.style">
|
||||
<template #style="{ formData }">
|
||||
<el-form-item label="高度" prop="height">
|
||||
<el-slider
|
||||
v-model="formData.height"
|
||||
:max="500"
|
||||
:min="100"
|
||||
show-input
|
||||
input-size="small"
|
||||
:show-input-controls="false"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<el-form label-width="80px" :model="formData">
|
||||
<el-form-item label="上传视频" prop="videoUrl">
|
||||
<UploadFile
|
||||
v-model="formData.videoUrl"
|
||||
:file-type="['mp4']"
|
||||
:limit="1"
|
||||
:file-size="100"
|
||||
class="min-w-80px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="上传封面" prop="posterUrl">
|
||||
<UploadImg
|
||||
v-model="formData.posterUrl"
|
||||
draggable="false"
|
||||
height="80px"
|
||||
width="100%"
|
||||
class="min-w-80px"
|
||||
>
|
||||
<template #tip> 建议宽度750 </template>
|
||||
</UploadImg>
|
||||
</el-form-item>
|
||||
<el-form-item label="自动播放" prop="autoplay">
|
||||
<el-switch v-model="formData.autoplay" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ComponentContainerProperty>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { VideoPlayerProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
|
||||
// 视频播放属性面板
|
||||
defineOptions({ name: 'VideoPlayerProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: VideoPlayerProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
@ -109,7 +109,7 @@ export const PAGE_LIBS = [
|
||||
'TitleBar'
|
||||
]
|
||||
},
|
||||
{ name: '图文组件', extended: true, components: ['ImageBar', 'Carousel'] },
|
||||
{ name: '图文组件', extended: true, components: ['ImageBar', 'Carousel', 'VideoPlayer'] },
|
||||
{ name: '商品组件', extended: true, components: ['ProductCard'] },
|
||||
{
|
||||
name: '会员组件',
|
||||
|
@ -33,11 +33,10 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { PropType } from 'vue'
|
||||
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { getAccessToken, getTenantId } from '@/utils/auth'
|
||||
import type { UploadInstance, UploadUserFile, UploadProps, UploadRawFile } from 'element-plus'
|
||||
import { isArray, isString } from '@/utils/is'
|
||||
|
||||
defineOptions({ name: 'UploadFile' })
|
||||
|
||||
@ -45,10 +44,7 @@ const message = useMessage() // 消息弹窗
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Array as PropType<UploadUserFile[]>,
|
||||
required: true
|
||||
},
|
||||
modelValue: propTypes.oneOfType<string | string[]>([String, Array<String>]).isRequired,
|
||||
title: propTypes.string.def('文件上传'),
|
||||
updateUrl: propTypes.string.def(import.meta.env.VITE_UPLOAD_URL),
|
||||
fileType: propTypes.array.def(['doc', 'xls', 'ppt', 'txt', 'pdf']), // 文件类型, 例如['png', 'jpg', 'jpeg']
|
||||
@ -62,7 +58,7 @@ const props = defineProps({
|
||||
const valueRef = ref(props.modelValue)
|
||||
const uploadRef = ref<UploadInstance>()
|
||||
const uploadList = ref<UploadUserFile[]>([])
|
||||
const fileList = ref<UploadUserFile[]>(props.modelValue)
|
||||
const fileList = ref<UploadUserFile[]>([])
|
||||
const uploadNumber = ref<number>(0)
|
||||
const uploadHeaders = ref({
|
||||
Authorization: 'Bearer ' + getAccessToken(),
|
||||
@ -109,7 +105,7 @@ const handleFileSuccess: UploadProps['onSuccess'] = (res: any): void => {
|
||||
fileList.value = fileList.value.concat(uploadList.value)
|
||||
uploadList.value = []
|
||||
uploadNumber.value = 0
|
||||
emit('update:modelValue', listToString(fileList.value))
|
||||
emitUpdateModelValue()
|
||||
}
|
||||
}
|
||||
// 文件数超出提示
|
||||
@ -125,20 +121,47 @@ const handleRemove = (file) => {
|
||||
const findex = fileList.value.map((f) => f.name).indexOf(file.name)
|
||||
if (findex > -1) {
|
||||
fileList.value.splice(findex, 1)
|
||||
emit('update:modelValue', listToString(fileList.value))
|
||||
emitUpdateModelValue()
|
||||
}
|
||||
}
|
||||
const handlePreview: UploadProps['onPreview'] = (uploadFile) => {
|
||||
console.log(uploadFile)
|
||||
}
|
||||
// 对象转成指定字符串分隔
|
||||
const listToString = (list: UploadUserFile[], separator?: string) => {
|
||||
let strs = ''
|
||||
separator = separator || ','
|
||||
for (let i in list) {
|
||||
strs += list[i].url + separator
|
||||
|
||||
// 监听模型绑定值变动
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
() => {
|
||||
const files: string[] = []
|
||||
// 情况1:字符串
|
||||
if (isString(props.modelValue)) {
|
||||
// 情况1.1:逗号分隔的多值
|
||||
if (props.modelValue.includes(',')) {
|
||||
files.concat(props.modelValue.split(','))
|
||||
} else {
|
||||
files.push(props.modelValue)
|
||||
}
|
||||
} else if (isArray(props.modelValue)) {
|
||||
// 情况2:字符串
|
||||
files.concat(props.modelValue)
|
||||
} else {
|
||||
throw new Error('不支持的 modelValue 类型')
|
||||
}
|
||||
fileList.value = files.map((url: string) => {
|
||||
return { url, name: url.substring(url.lastIndexOf('/') + 1) } as UploadUserFile
|
||||
})
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
// 发送文件链接列表更新
|
||||
const emitUpdateModelValue = () => {
|
||||
// 情况1:数组结果
|
||||
let result: string | string[] = fileList.value.map((file) => file.url!)
|
||||
// 情况2:逗号分隔的字符串
|
||||
if (isString(props.modelValue)) {
|
||||
result = result.join(',')
|
||||
}
|
||||
return strs != '' ? strs.substr(0, strs.length - 1) : ''
|
||||
emit('update:modelValue', result)
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
|
Loading…
Reference in New Issue
Block a user