Skip to content

Commit bb2b7ff

Browse files
committed
营销:增加商城装修组件【视频播放】
1 parent fa710b5 commit bb2b7ff

File tree

6 files changed

+169
-25
lines changed

6 files changed

+169
-25
lines changed

src/components/DiyEditor/components/ComponentContainerProperty.vue

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
:label="data.label"
2727
:prop="data.prop"
2828
:label-width="node.level === 1 ? '80px' : '62px'"
29-
class="tree-form-item w-full m-b-0!"
29+
class="w-full m-b-0!"
3030
>
3131
<el-slider
3232
v-model="formData[data.prop]"
@@ -40,6 +40,7 @@
4040
</el-form-item>
4141
</template>
4242
</el-tree>
43+
<slot name="style" :formData="formData"></slot>
4344
</el-form>
4445
</el-card>
4546
</el-tab-pane>
@@ -153,12 +154,10 @@ const handleSliderChange = (prop: string) => {
153154
</script>
154155

155156
<style scoped lang="scss">
156-
.tree-form-item {
157-
:deep(.el-slider__runway) {
158-
margin-right: 16px;
159-
}
160-
:deep(.el-input-number) {
161-
width: 50px;
162-
}
157+
:deep(.el-slider__runway) {
158+
margin-right: 16px;
159+
}
160+
:deep(.el-input-number) {
161+
width: 50px;
163162
}
164163
</style>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
2+
3+
/** 视频播放属性 */
4+
export interface VideoPlayerProperty {
5+
// 视频链接
6+
videoUrl: string
7+
// 封面链接
8+
posterUrl: string
9+
// 是否自动播放
10+
autoplay: boolean
11+
// 组件样式
12+
style: VideoPlayerStyle
13+
}
14+
15+
// 视频播放样式
16+
export interface VideoPlayerStyle extends ComponentStyle {
17+
// 视频高度
18+
height: number
19+
}
20+
21+
// 定义组件
22+
export const component = {
23+
id: 'VideoPlayer',
24+
name: '视频播放',
25+
icon: 'ep:video-play',
26+
property: {
27+
videoUrl: '',
28+
posterUrl: '',
29+
autoplay: false,
30+
style: {
31+
bgType: 'color',
32+
bgColor: '#fff',
33+
marginBottom: 8,
34+
height: 300
35+
} as ComponentStyle
36+
}
37+
} as DiyComponent<VideoPlayerProperty>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<template>
2+
<div class="w-full" :style="{ height: `${property.style.height}px` }">
3+
<el-image class="w-full w-full" :src="property.posterUrl" v-if="property.posterUrl" />
4+
<video
5+
v-else
6+
class="w-full w-full"
7+
:src="property.videoUrl"
8+
:poster="property.posterUrl"
9+
:autoplay="property.autoplay"
10+
controls
11+
></video>
12+
</div>
13+
</template>
14+
<script setup lang="ts">
15+
import { VideoPlayerProperty } from './config'
16+
17+
/** 视频播放 */
18+
defineOptions({ name: 'VideoPlayer' })
19+
20+
defineProps<{ property: VideoPlayerProperty }>()
21+
</script>
22+
23+
<style scoped lang="scss">
24+
/* 图片 */
25+
img {
26+
width: 100%;
27+
height: 100%;
28+
display: block;
29+
}
30+
</style>
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<template>
2+
<ComponentContainerProperty v-model="formData.style">
3+
<template #style="{ formData }">
4+
<el-form-item label="高度" prop="height">
5+
<el-slider
6+
v-model="formData.height"
7+
:max="500"
8+
:min="100"
9+
show-input
10+
input-size="small"
11+
:show-input-controls="false"
12+
/>
13+
</el-form-item>
14+
</template>
15+
<el-form label-width="80px" :model="formData">
16+
<el-form-item label="上传视频" prop="videoUrl">
17+
<UploadFile
18+
v-model="formData.videoUrl"
19+
:file-type="['mp4']"
20+
:limit="1"
21+
:file-size="100"
22+
class="min-w-80px"
23+
/>
24+
</el-form-item>
25+
<el-form-item label="上传封面" prop="posterUrl">
26+
<UploadImg
27+
v-model="formData.posterUrl"
28+
draggable="false"
29+
height="80px"
30+
width="100%"
31+
class="min-w-80px"
32+
>
33+
<template #tip> 建议宽度750 </template>
34+
</UploadImg>
35+
</el-form-item>
36+
<el-form-item label="自动播放" prop="autoplay">
37+
<el-switch v-model="formData.autoplay" />
38+
</el-form-item>
39+
</el-form>
40+
</ComponentContainerProperty>
41+
</template>
42+
43+
<script setup lang="ts">
44+
import { VideoPlayerProperty } from './config'
45+
import { usePropertyForm } from '@/components/DiyEditor/util'
46+
47+
// 视频播放属性面板
48+
defineOptions({ name: 'VideoPlayerProperty' })
49+
50+
const props = defineProps<{ modelValue: VideoPlayerProperty }>()
51+
const emit = defineEmits(['update:modelValue'])
52+
const { formData } = usePropertyForm(props.modelValue, emit)
53+
</script>
54+
55+
<style scoped lang="scss"></style>

src/components/DiyEditor/util.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ export const PAGE_LIBS = [
109109
'TitleBar'
110110
]
111111
},
112-
{ name: '图文组件', extended: true, components: ['ImageBar', 'Carousel'] },
112+
{ name: '图文组件', extended: true, components: ['ImageBar', 'Carousel', 'VideoPlayer'] },
113113
{ name: '商品组件', extended: true, components: ['ProductCard'] },
114114
{
115115
name: '会员组件',

src/components/UploadFile/src/UploadFile.vue

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,22 +33,18 @@
3333
</div>
3434
</template>
3535
<script lang="ts" setup>
36-
import { PropType } from 'vue'
37-
3836
import { propTypes } from '@/utils/propTypes'
3937
import { getAccessToken, getTenantId } from '@/utils/auth'
4038
import type { UploadInstance, UploadUserFile, UploadProps, UploadRawFile } from 'element-plus'
39+
import { isArray, isString } from '@/utils/is'
4140
4241
defineOptions({ name: 'UploadFile' })
4342
4443
const message = useMessage() // 消息弹窗
4544
const emit = defineEmits(['update:modelValue'])
4645
4746
const props = defineProps({
48-
modelValue: {
49-
type: Array as PropType<UploadUserFile[]>,
50-
required: true
51-
},
47+
modelValue: propTypes.oneOfType<string | string[]>([String, Array<String>]).isRequired,
5248
title: propTypes.string.def('文件上传'),
5349
updateUrl: propTypes.string.def(import.meta.env.VITE_UPLOAD_URL),
5450
fileType: propTypes.array.def(['doc', 'xls', 'ppt', 'txt', 'pdf']), // 文件类型, 例如['png', 'jpg', 'jpeg']
@@ -62,7 +58,7 @@ const props = defineProps({
6258
const valueRef = ref(props.modelValue)
6359
const uploadRef = ref<UploadInstance>()
6460
const uploadList = ref<UploadUserFile[]>([])
65-
const fileList = ref<UploadUserFile[]>(props.modelValue)
61+
const fileList = ref<UploadUserFile[]>([])
6662
const uploadNumber = ref<number>(0)
6763
const uploadHeaders = ref({
6864
Authorization: 'Bearer ' + getAccessToken(),
@@ -109,7 +105,7 @@ const handleFileSuccess: UploadProps['onSuccess'] = (res: any): void => {
109105
fileList.value = fileList.value.concat(uploadList.value)
110106
uploadList.value = []
111107
uploadNumber.value = 0
112-
emit('update:modelValue', listToString(fileList.value))
108+
emitUpdateModelValue()
113109
}
114110
}
115111
// 文件数超出提示
@@ -125,20 +121,47 @@ const handleRemove = (file) => {
125121
const findex = fileList.value.map((f) => f.name).indexOf(file.name)
126122
if (findex > -1) {
127123
fileList.value.splice(findex, 1)
128-
emit('update:modelValue', listToString(fileList.value))
124+
emitUpdateModelValue()
129125
}
130126
}
131127
const handlePreview: UploadProps['onPreview'] = (uploadFile) => {
132128
console.log(uploadFile)
133129
}
134-
// 对象转成指定字符串分隔
135-
const listToString = (list: UploadUserFile[], separator?: string) => {
136-
let strs = ''
137-
separator = separator || ','
138-
for (let i in list) {
139-
strs += list[i].url + separator
130+
131+
// 监听模型绑定值变动
132+
watch(
133+
() => props.modelValue,
134+
() => {
135+
const files: string[] = []
136+
// 情况1:字符串
137+
if (isString(props.modelValue)) {
138+
// 情况1.1:逗号分隔的多值
139+
if (props.modelValue.includes(',')) {
140+
files.concat(props.modelValue.split(','))
141+
} else {
142+
files.push(props.modelValue)
143+
}
144+
} else if (isArray(props.modelValue)) {
145+
// 情况2:字符串
146+
files.concat(props.modelValue)
147+
} else {
148+
throw new Error('不支持的 modelValue 类型')
149+
}
150+
fileList.value = files.map((url: string) => {
151+
return { url, name: url.substring(url.lastIndexOf('/') + 1) } as UploadUserFile
152+
})
153+
},
154+
{ immediate: true }
155+
)
156+
// 发送文件链接列表更新
157+
const emitUpdateModelValue = () => {
158+
// 情况1:数组结果
159+
let result: string | string[] = fileList.value.map((file) => file.url!)
160+
// 情况2:逗号分隔的字符串
161+
if (isString(props.modelValue)) {
162+
result = result.join(',')
140163
}
141-
return strs != '' ? strs.substr(0, strs.length - 1) : ''
164+
emit('update:modelValue', result)
142165
}
143166
</script>
144167
<style scoped lang="scss">

0 commit comments

Comments
 (0)