Web/vueVersion/src/pages/InChannel/components/Settings/index.vue (137 lines of code) (raw):

<template> <Modal open :footer="null" wrap-class-name="settings" :width="680" @cancel="onCancel" > <Row style="height: 500"> <Col :span="7" class="settingMenu"> <Menu :selected-keys="[activeTab]" :items="menus" @click="onChangeTab" /> </Col> <Col class="settingDetail" :span="17"> <Title :level="5"> {{ activeMenu.label }} <Text v-if="activeMenu.tip" class="tip" type="secondary"> ({{ activeMenu.tip }}) </Text> </Title> <Divider /> <General v-if="activeTab === 'general'" /> <Video v-else-if="activeTab === 'video'" :close="close" /> <Audio v-else-if="activeTab === 'audio'" /> <ScreenShare v-else-if="activeTab === 'share'" :close="close" /> <External v-else-if="activeTab === 'external'" /> <Metrics v-else-if="activeTab === 'metrics'" /> <GroupList v-else-if="activeTab === 'group'" /> </Col> </Row> </Modal> </template> <script lang="ts" setup> import { Col, Modal, Row, Typography, Menu, Divider, MenuProps } from 'ant-design-vue'; import Icon from '~/components/Icon'; import { useChannel } from '~/hooks/channel'; import General from './General.vue'; import Audio from './Audio.vue'; import Video from './Video.vue'; import ScreenShare from './ScreenShare.vue'; import External from './External.vue'; import Metrics from './Metrics.vue'; import GroupList from './Group/List.vue'; import { computed, ref, h } from 'vue'; import { useChannelInfo } from '~/store'; const { Title, Text } = Typography; const props = defineProps(['close']); const menus = [ { label: '通用', icon: h(Icon, { type: "icon-icon_x_Settings" }), key: 'general', }, { label: '视频', icon: h(Icon, { type: "icon-XDS_FrameMeetingLine" }), key: 'video', }, { label: '音频', icon: h(Icon, { type: "icon-XDS_Mute2" }), key: 'audio', }, { label: '共享屏幕', icon: h(Icon, { type: "icon-XDS_share_screen1" }), key: 'share', }, { label: '分组讨论', icon: h(Icon, { type: "icon-XDS_Confm" }), key: 'group', }, { label: '外部源', icon: h(Icon, { type: "icon-XDS_Documents" }), key: 'external', tip: '仅在当前窗口打开时生效', }, { label: '质量监测', icon: h(Icon, { type: "icon-data_usage_20" }), key: 'metrics', }, ]; const activeTab = ref('general'); const channelInfo = useChannelInfo(); const { publish, unpublish } = useChannel(); const publishStateSnapshot = ref({ camera: channelInfo.publishedTracks.has(channelInfo.cameraTrack?.getTrackId()), mic: channelInfo.publishedTracks.has(channelInfo.micTrack?.getTrackId()), }); const onUnloadExternal = async () => { const tracksToUnpublish: any[] = [ channelInfo.customAudioTrack, channelInfo.customVideoTrack, ].filter((item) => item && channelInfo.publishedTracks.has(item.getTrackId())); if (tracksToUnpublish.length) { await unpublish(tracksToUnpublish); } const tracksToPublish: any[] = []; if ( channelInfo.cameraTrack && !channelInfo.publishedTracks.has(channelInfo.cameraTrack.getTrackId()) && publishStateSnapshot.value.camera ) { tracksToPublish.push(channelInfo.cameraTrack); } if ( channelInfo.micTrack && !channelInfo.publishedTracks.has(channelInfo.micTrack.getTrackId()) && publishStateSnapshot.value.mic ) { tracksToPublish.push(channelInfo.micTrack); } if (tracksToPublish.length) { await publish(tracksToPublish); } }; const activeMenu = computed(() => { return menus.find((item) => item.key === activeTab.value); }); const onChangeTab: MenuProps['onClick'] = (e) => { if (activeTab.value === 'external') { onUnloadExternal(); } activeTab.value = e.key as string; }; const onCancel = () => { if (activeTab.value === 'external') { onUnloadExternal(); } props.close(); }; </script> <style lang="less"> @import url('./index.module.less'); </style>