feat(仪表板): 流媒体组件优化

This commit is contained in:
wangjiahao 2024-05-15 23:11:19 +08:00
parent cb34fb6659
commit 9988985e64
12 changed files with 230 additions and 18 deletions

View File

@ -1 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1712630540622" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4351" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M885.333333 177.066667C838.4 104.533333 697.6 136.533333 652.8 149.333333c-8.533333 2.133333-19.2 4.266667-32 8.533334-40.533333-17.066667-87.466667-25.6-134.4-25.6-200.533333 0-362.666667 162.133333-362.666667 362.666666 0 51.2 10.666667 98.133333 27.733334 140.8-36.266667 117.333333-29.866667 194.133333 21.333333 234.666667 23.466667 19.2 51.2 25.6 81.066667 25.6 59.733333 0 123.733333-27.733333 157.866666-46.933333 23.466667 4.266667 49.066667 8.533333 74.666667 8.533333 130.133333 0 245.333333-68.266667 309.333333-172.8h-106.666666c-51.2 53.333333-121.6 87.466667-202.666667 87.466667-104.533333 0-194.133333-57.6-241.066667-142.933334 85.333333-241.066667 281.6-343.466667 373.333334-379.733333 68.266667 36.266667 119.466667 100.266667 136.533333 179.2H467.2v85.333333h381.866667v-19.2c0-40.533333-6.4-78.933333-19.2-115.2 49.066667-68.266667 93.866667-147.2 55.466666-202.666666z m-70.4 44.8s4.266667 17.066667-27.733333 66.133333c-17.066667-25.6-38.4-49.066667-61.866667-70.4 44.8-4.266667 81.066667-4.266667 89.6 4.266667zM298.666667 802.133333c-29.866667 8.533333-57.6 10.666667-70.4 0-4.266667-2.133333-17.066667-17.066667-10.666667-68.266666 23.466667 27.733333 51.2 49.066667 81.066667 68.266666zM209.066667 497.066667v-4.266667c0-153.6 123.733333-277.333333 277.333333-277.333333h2.133333c-93.866667 53.333333-202.666667 142.933333-279.466666 281.6z" p-id="4352"></path></svg> <?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg fill="#3370FF" t="1712630540622" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4351" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M885.333333 177.066667C838.4 104.533333 697.6 136.533333 652.8 149.333333c-8.533333 2.133333-19.2 4.266667-32 8.533334-40.533333-17.066667-87.466667-25.6-134.4-25.6-200.533333 0-362.666667 162.133333-362.666667 362.666666 0 51.2 10.666667 98.133333 27.733334 140.8-36.266667 117.333333-29.866667 194.133333 21.333333 234.666667 23.466667 19.2 51.2 25.6 81.066667 25.6 59.733333 0 123.733333-27.733333 157.866666-46.933333 23.466667 4.266667 49.066667 8.533333 74.666667 8.533333 130.133333 0 245.333333-68.266667 309.333333-172.8h-106.666666c-51.2 53.333333-121.6 87.466667-202.666667 87.466667-104.533333 0-194.133333-57.6-241.066667-142.933334 85.333333-241.066667 281.6-343.466667 373.333334-379.733333 68.266667 36.266667 119.466667 100.266667 136.533333 179.2H467.2v85.333333h381.866667v-19.2c0-40.533333-6.4-78.933333-19.2-115.2 49.066667-68.266667 93.866667-147.2 55.466666-202.666666z m-70.4 44.8s4.266667 17.066667-27.733333 66.133333c-17.066667-25.6-38.4-49.066667-61.866667-70.4 44.8-4.266667 81.066667-4.266667 89.6 4.266667zM298.666667 802.133333c-29.866667 8.533333-57.6 10.666667-70.4 0-4.266667-2.133333-17.066667-17.066667-10.666667-68.266666 23.466667 27.733333 51.2 49.066667 81.066667 68.266666zM209.066667 497.066667v-4.266667c0-153.6 123.733333-277.333333 277.333333-277.333333h2.133333c-93.866667 53.333333-202.666667 142.933333-279.466666 281.6z" p-id="4352"></path></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -1 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1715769658859" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4704" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M1023.853735 948.673618v75.25325H596.248536V948.673618zM511.926868 0.073132a511.926868 511.926868 0 0 1 511.926867 511.926868h-75.253249a436.600486 436.600486 0 1 0-436.600486 436.600486h5.119269v75.253249h-5.119269a511.926868 511.926868 0 1 1 0-1023.853735z m511.926867 803.505785v75.25325H596.248536v-75.180117zM362.590487 290.116269l192.11884 110.941866 192.11884 110.941865-192.11884 110.941865-192.11884 110.941866V290.189402zM1023.853735 658.484217v75.399514H596.248536V658.630481zM437.843737 420.438223v182.831024l79.202399-45.780888 79.2024-45.707756-79.2024-45.707756z" p-id="4705"></path></svg> <?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1715769658859" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4704" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M1023.853735 948.673618v75.25325H596.248536V948.673618zM511.926868 0.073132a511.926868 511.926868 0 0 1 511.926867 511.926868h-75.253249a436.600486 436.600486 0 1 0-436.600486 436.600486h5.119269v75.253249h-5.119269a511.926868 511.926868 0 1 1 0-1023.853735z m511.926867 803.505785v75.25325H596.248536v-75.180117zM362.590487 290.116269l192.11884 110.941866 192.11884 110.941865-192.11884 110.941865-192.11884 110.941866V290.189402zM1023.853735 658.484217v75.399514H596.248536V658.630481zM437.843737 420.438223v182.831024l79.202399-45.780888 79.2024-45.707756-79.2024-45.707756z" p-id="4705" fill="#3370FF"></path></svg>

Before

Width:  |  Height:  |  Size: 937 B

After

Width:  |  Height:  |  Size: 953 B

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -444,7 +444,8 @@ const initOpenHandler = newWindow => {
<component-group <component-group
is-label is-label
themes="light" themes="light"
:base-width="215" placement="bottom"
:base-width="315"
icon-name="dv-media" icon-name="dv-media"
title="媒体" title="媒体"
> >

View File

@ -230,7 +230,13 @@ eventBus.on('clearCanvas', clearCanvas)
<component-group is-label :base-width="115" icon-name="dv-text" title="文本"> <component-group is-label :base-width="115" icon-name="dv-text" title="文本">
<text-group></text-group> <text-group></text-group>
</component-group> </component-group>
<component-group is-label :base-width="215" icon-name="dv-media" title="媒体"> <component-group
is-label
placement="bottom"
:base-width="315"
icon-name="dv-media"
title="媒体"
>
<media-group></media-group> <media-group></media-group>
</component-group> </component-group>
<component-group is-label :base-width="115" icon-name="dv-more-com" title="更多"> <component-group is-label :base-width="115" icon-name="dv-more-com" title="更多">

View File

@ -17,6 +17,10 @@ const props = defineProps({
themes: { themes: {
type: String, type: String,
default: 'dark' default: 'dark'
},
placement: {
type: String,
default: 'bottom-start'
} }
}) })
@ -25,7 +29,7 @@ const { title, iconName, baseWidth, themes } = toRefs(props)
<template> <template>
<el-popover <el-popover
placement="bottom-start" :placement="placement"
:width="baseWidth" :width="baseWidth"
trigger="click" trigger="click"
:show-arrow="false" :show-arrow="false"

View File

@ -57,6 +57,13 @@ const handleDragEnd = e => {
drag-info="DeVideo&DeVideo" drag-info="DeVideo&DeVideo"
v-on:click="newComponent('DeVideo')" v-on:click="newComponent('DeVideo')"
></drag-component> ></drag-component>
<drag-component
:themes="themes"
icon="icon-stream"
label="流媒体"
drag-info="DeStreamMedia&DeStreamMedia"
v-on:click="newComponent('DeStreamMedia')"
></drag-component>
</div> </div>
</template> </template>

View File

@ -166,7 +166,15 @@ export const commonAttr = {
maintainRadio: false, // 布局时保持宽高比例 maintainRadio: false, // 布局时保持宽高比例
aspectRatio: 1, // 锁定时的宽高比例 aspectRatio: 1, // 锁定时的宽高比例
isShow: true, // 是否显示组件 isShow: true, // 是否显示组件
collapseName: ['position', 'background', 'style', 'picture', 'frameLinks', 'videoLinks'], // 编辑组件时记录当前使用的是哪个折叠面板再次回来时恢复上次打开的折叠面板优化用户体验 collapseName: [
'position',
'background',
'style',
'picture',
'frameLinks',
'videoLinks',
'streamLinks'
], // 编辑组件时记录当前使用的是哪个折叠面板再次回来时恢复上次打开的折叠面板优化用户体验
linkage: { linkage: {
duration: 0, // 过渡持续时间 duration: 0, // 过渡持续时间
data: [ data: [

View File

@ -4,10 +4,13 @@
<el-collapse-item <el-collapse-item
:effect="themes" :effect="themes"
title="流媒体信息" title="流媒体信息"
name="videoLinks" name="streamLinks"
v-if="curComponent && curComponent.videoLinks" v-if="curComponent && curComponent.streamMediaLinks"
> >
<video-links :link-info="curComponent.videoLinks" :themes="themes"></video-links> <stream-media-links
:link-info="curComponent.streamMediaLinks"
:themes="themes"
></stream-media-links>
</el-collapse-item> </el-collapse-item>
</CommonAttr> </CommonAttr>
</div> </div>
@ -18,6 +21,7 @@ import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import CommonAttr from '@/custom-component/common/CommonAttr.vue' import CommonAttr from '@/custom-component/common/CommonAttr.vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import VideoLinks from '@/custom-component/de-video/VideoLinks.vue' import VideoLinks from '@/custom-component/de-video/VideoLinks.vue'
import StreamMediaLinks from '@/custom-component/de-stream-media/StreamMediaLinks.vue'
const dvMainStore = dvMainStoreWithOut() const dvMainStore = dvMainStoreWithOut()
const { curComponent } = storeToRefs(dvMainStore) const { curComponent } = storeToRefs(dvMainStore)
withDefaults( withDefaults(

View File

@ -12,20 +12,19 @@
:controls="inScreen" :controls="inScreen"
muted muted
/> />
<div v-if="editMode === 'edit'" class="stream-mask edit-mask-stream" />
</div> </div>
<div v-else class="info-stream-class"> <div v-else class="info-stream-class">
<span>{{ $t('panel.link_add_tips_pre') }}</span> <span>{{ t('visualization.stream_media_add_tips') }}</span>
<i class="icon iconfont icon-chaolianjie" />
<span>{{ $t('panel.stream_media_add_tips') }}</span>
</div> </div>
</el-row> </el-row>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import flvjs from 'flv.js' import flvjs from 'flv.js'
import '@/style/custom-theme.css' import '@/style/custom-theme.css'
import { onMounted, reactive, toRefs } from 'vue' import { onMounted, reactive, toRefs, getCurrentInstance } from 'vue'
import { useEmitt } from '@/hooks/web/useEmitt' import { useEmitt } from '@/hooks/web/useEmitt'
import { useI18n } from '@/hooks/web/useI18n'
const { t } = useI18n()
const props = defineProps({ const props = defineProps({
propValue: { propValue: {
@ -57,6 +56,7 @@ const props = defineProps({
}) })
const { propValue, element, editMode } = toRefs(props) const { propValue, element, editMode } = toRefs(props)
let currentInstance
const state = reactive({ const state = reactive({
pOption: element.value.streamMediaLinks[element.value.streamMediaLinks.videoType], pOption: element.value.streamMediaLinks[element.value.streamMediaLinks.videoType],
@ -65,18 +65,20 @@ const state = reactive({
}) })
onMounted(() => { onMounted(() => {
currentInstance = getCurrentInstance()
useEmitt({ useEmitt({
name: 'streamMediaLinksChange-' + element.value.id, name: 'streamMediaLinksChange-' + element.value.id,
callback: function () { callback: function () {
initOption() initOption()
} }
}) })
initOption()
}) })
const initOption = () => { const initOption = () => {
if (flvjs.isSupported() && state.pOption.url) { if (flvjs.isSupported() && state.pOption.url) {
destroyPlayer() destroyPlayer()
const video = this.$refs['player-' + element.value.id] const video = currentInstance.proxy.$refs['player-' + element.value.id]
if (video) { if (video) {
try { try {
state.flvPlayer = flvjs.createPlayer(state.pOption, { state.flvPlayer = flvjs.createPlayer(state.pOption, {
@ -109,10 +111,11 @@ const destroyPlayer = () => {
.info-stream-class { .info-stream-class {
text-align: center; text-align: center;
height: 100%; height: 100%;
width: 100%;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
background-color: rgba(245, 245, 220, 0.3); background-color: rgba(245, 245, 220, 0.1);
font-size: 12px; font-size: 12px;
color: #000000; color: #000000;
} }

View File

@ -0,0 +1,179 @@
<template>
<el-row>
<el-form :effect="themes" ref="form" size="mini" style="width: 100%">
<el-form-item :effect="themes" :label="t('visualization.video_type')">
<el-radio-group :effect="themes" v-model="state.streamMediaInfoTemp.videoType">
<el-radio :effect="themes" :label="'flv'">FLV</el-radio>
</el-radio-group>
</el-form-item>
<el-row v-if="state.streamMediaInfoTemp.videoType === 'flv'" style="display: block">
<el-form-item :effect="themes" :label="t('visualization.is_live')">
<el-radio-group
:effect="themes"
@change="onChange"
v-model="state.streamMediaInfoTemp[state.streamMediaInfoTemp.videoType].isLive"
>
<el-radio :effect="themes" :label="true">{{ t('visualization.yes') }}</el-radio>
<el-radio :effect="themes" :label="false">{{ t('visualization.no') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
:effect="themes"
v-if="!state.streamMediaInfoTemp[state.streamMediaInfoTemp.videoType].isLive"
:label="t('visualization.play_frequency')"
>
<el-radio-group
:effect="themes"
@change="onChange"
v-model="state.streamMediaInfoTemp[state.streamMediaInfoTemp.videoType].loop"
>
<el-radio :effect="themes" :label="false">{{ t('visualization.play_once') }}</el-radio>
<el-radio :effect="themes" :label="true">{{ t('visualization.play_circle') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :effect="themes" :label="t('visualization.video_links')">
<el-input
:effect="themes"
v-model="state.streamMediaInfoTemp[state.streamMediaInfoTemp.videoType].url"
@blur="onChange"
/>
<span class="tips-class"> Tips:{{ t('visualization.live_tips') }} </span>
</el-form-item>
</el-row>
</el-form>
</el-row>
</template>
<script setup lang="ts">
import { reactive, ref, toRefs, watch, computed } from 'vue'
import { dvMainStoreWithOut } from '../../store/modules/data-visualization/dvMain'
import { storeToRefs } from 'pinia/dist/pinia'
import { checkAddHttp, deepCopy } from '../../utils/utils'
import { snapshotStoreWithOut } from '../../store/modules/data-visualization/snapshot'
import { useI18n } from '../../hooks/web/useI18n'
import { useEmitt } from '@/hooks/web/useEmitt'
const dvMainStore = dvMainStoreWithOut()
const { curComponent, curActiveTabInner } = storeToRefs(dvMainStore)
const snapshotStore = snapshotStoreWithOut()
const emits = defineEmits(['close'])
const popover = ref(null)
const { t } = useI18n()
const props = defineProps({
themes: {
type: String,
required: true,
default: 'dark'
},
linkInfo: {
type: Object,
required: true
},
//
attrPosition: {
type: String,
required: false,
default: 'panel'
}
})
const { linkInfo, attrPosition } = toRefs(props)
const state = reactive({
streamMediaInfoTemp: {
videoType: 'flv',
flv: {
type: 'flv',
isLive: false,
cors: true, //
loop: true,
autoplay: false
// url: null //
}
}
})
const init = () => {
state.streamMediaInfoTemp = deepCopy(linkInfo.value)
}
const onChange = () => {
state.streamMediaInfoTemp[state.streamMediaInfoTemp.videoType].url = checkAddHttp(
state.streamMediaInfoTemp[state.streamMediaInfoTemp.videoType].url
)
if (attrPosition.value === 'panel') {
curComponent.value.streamMediaLinks = state.streamMediaInfoTemp
} else {
curActiveTabInner.value.streamMediaLinks = state.streamMediaInfoTemp
}
snapshotStore.recordSnapshotCache()
useEmitt().emitter.emit('streamMediaLinksChange-' + curComponent.value.id)
}
init()
watch(
linkInfo.value,
() => {
init()
},
{ deep: true }
)
</script>
<style lang="less" scoped>
.slot-class {
color: white;
}
.bottom {
margin-top: 20px;
text-align: center;
}
.ellipsis-area {
margin-left: 10px;
margin-right: 10px;
overflow: hidden; /*超出部分隐藏*/
white-space: nowrap; /*不换行*/
text-overflow: ellipsis; /*超出部分文字以...显示*/
background-color: #f7f8fa;
color: #3d4d66;
font-size: 12px;
line-height: 24px;
height: 24px;
border-radius: 3px;
}
.select-filed {
margin-left: 10px;
margin-right: 10px;
overflow: hidden; /*超出部分隐藏*/
white-space: nowrap; /*不换行*/
text-overflow: ellipsis; /*超出部分文字以...显示*/
color: #3d4d66;
font-size: 12px;
line-height: 35px;
height: 35px;
border-radius: 3px;
}
.tips-class {
color: #909399;
font-size: 8px;
margin-left: 3px;
}
.hint-icon {
cursor: pointer;
font-size: 14px;
color: #646a73;
&.hint-icon--dark {
color: #a6a6a6;
}
}
.data-area-label {
display: flex;
flex-direction: row;
align-items: center;
}
</style>

View File

@ -1888,7 +1888,7 @@ export default {
yes: '是', yes: '是',
no: '否', no: '否',
live_tips: '优先HTTPS链接', live_tips: '优先HTTPS链接',
stream_media_add_tips: '添加流媒体信息...', stream_media_add_tips: '请在右侧添加流媒体信息...',
stream_mobile_tips: 'IOS终端可能无法显示', stream_mobile_tips: 'IOS终端可能无法显示',
json_params_error: '第三方参数解析失败请检查参数格式是否正确', json_params_error: '第三方参数解析失败请检查参数格式是否正确',
inner_padding: '内边距', inner_padding: '内边距',