| | |
| | | @blur="saveEdit" |
| | | @keydown.enter="saveEdit" |
| | | /> |
| | | |
| | | |
| | | <!-- 如果不在编辑,显示文本 --> |
| | | <div |
| | | v-else |
| | |
| | | /> |
| | | <!-- 数字人(有则显示) --> |
| | | <el-image |
| | | v-if="element.digitalHuman?.show && element.digitalHuman?.host" |
| | | v-if=" |
| | | element.digitalHuman?.show && |
| | | element.digitalHuman?.host && |
| | | element.digitalHuman?.host.fixVideoUrl !== null && |
| | | element.digitalHuman?.host.pictureUrl !== null && |
| | | element.digitalHuman?.host.videoUrl !== null |
| | | " |
| | | class="host" |
| | | :style="{ |
| | | width: element.digitalHuman.w * (thumViewSize.width / 800) + 'px', |
| | |
| | | :src="selectPPT.pictureUrl" |
| | | style="z-index: 1" |
| | | /> |
| | | |
| | | |
| | | <!-- 画中画 --> |
| | | <Vue3DraggableResizable |
| | | :key="selectPPT.digitalHuman.x + '-' + selectPPT.digitalHuman.y" |
| | |
| | | </Vue3DraggableResizable> |
| | | <!-- 数字人 --> |
| | | <Vue3DraggableResizable |
| | | v-if="selectPPT.digitalHuman.show == true && selectPPT.digitalHuman?.host" |
| | | v-if=" |
| | | selectPPT.digitalHuman.show == true && |
| | | selectPPT.digitalHuman?.host && |
| | | selectPPT.digitalHuman.host !== null && |
| | | selectPPT.digitalHuman?.host.fixVideoUrl !== null && |
| | | selectPPT.digitalHuman?.host.pictureUrl !== null && |
| | | selectPPT.digitalHuman?.host.videoUrl !== null |
| | | " |
| | | :parent="false" |
| | | :lockAspectRatio="true" |
| | | :minW="350" |
| | |
| | | </el-icon> |
| | | </Vue3DraggableResizable> |
| | | <Vue3DraggableResizable |
| | | v-if="selectPPT.digitalHuman.show == false && selectPPT.digitalHuman?.host" |
| | | v-if=" |
| | | selectPPT.digitalHuman.show == false && |
| | | selectPPT.digitalHuman?.host && |
| | | selectPPT.digitalHuman.host !== null && |
| | | selectPPT.digitalHuman?.host.fixVideoUrl !== null && |
| | | selectPPT.digitalHuman?.host.pictureUrl !== null && |
| | | selectPPT.digitalHuman?.host.videoUrl !== null |
| | | " |
| | | :parent="false" |
| | | :lockAspectRatio="true" |
| | | :minW="350" |
| | |
| | | </el-select> |
| | | </div> |
| | | </div> |
| | | <div class="SoundModelArea" v-loading="soundLoading"> |
| | | <div class="SoundModelArea" v-loading="soundLoading" v-show="ChangeSoundTypeList?.value === 2 " > |
| | | <div class="SoundModelAreaBox" v-for="(value, key, index) in audioList" :key="index"> |
| | | <div class="SoundClassTit"> |
| | | <el-divider content-position="center"> {{ languageClass(key) }} </el-divider> |
| | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="ButtonArea"> |
| | | <div class="ButtonArea" v-show="ChangeSoundTypeList?.value === 2" > |
| | | <el-button type="primary" @click="submitForm">{{ t('common.ok') }}</el-button> |
| | | </div> |
| | | </div> |
| | |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | |
| | | <script lang="ts" setup> |
| | | import { ref, reactive, onMounted, computed, watch, nextTick, shallowRef } from 'vue' |
| | | import draggable from 'vuedraggable' |
| | |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { DICT_TYPE, getIntDictOptions, getStrDictOptions } from '@/utils/dict' |
| | | import { any } from 'vue-types' |
| | | |
| | | |
| | | const editorHtml = useEditorHtml() |
| | | const router = useRouter() |
| | | const route = useRoute() |
| | |
| | | } |
| | | const hostValue = ref({}) |
| | | const chooseHost = (item) => { |
| | | if (PPTArr.value.length === 0) { |
| | | message.warning('请先上传ppt') |
| | | return false |
| | | } |
| | | |
| | | // 数字人默认所有页,没有当前页选项 |
| | | hostValue.value = item |
| | | chooseHost1(2) |
| | |
| | | hostList.value.forEach((el) => { |
| | | el.isActive = el.id === host.id |
| | | }) |
| | | |
| | | |
| | | const pagesToUpdate = applyAllHost.value ? PPTArr.value : [selectPPT.value] |
| | | |
| | | |
| | | pagesToUpdate.forEach((page) => { |
| | | page.digitalHuman.host = host |
| | | initHumanPositon(host, page.digitalHuman) |
| | | }) |
| | | |
| | | selectPPT.value = PPTArr.value[0] |
| | | } |
| | | const saveEdit = () => { |
| | | isEditing.value = false |
| | |
| | | width: 800, |
| | | height: (800 * 9) / 16 |
| | | }) |
| | | |
| | | |
| | | const thumViewSize = reactive({ |
| | | width: 152, |
| | | height: (152 * 9) / 16 |
| | | }) |
| | | |
| | | |
| | | const digitalHumanSize = reactive({ |
| | | width: 640, |
| | | height: 360 |
| | | }) |
| | | |
| | | |
| | | const scaleRatio = computed(() => ({ |
| | | width: courseInfo.value.width / viewSize.width, |
| | | height: courseInfo.value.height / viewSize.height |
| | | })) |
| | | |
| | | |
| | | const courseInfo = ref({ |
| | | id: 0, |
| | | accountId: userId.value, |
| | |
| | | width: 1920, |
| | | height: 1080 |
| | | }) |
| | | |
| | | |
| | | watch( |
| | | () => courseInfo.value.aspect, |
| | | (newAspect) => { |
| | |
| | | courseInfo.value.height = newAspect === '16:9' ? 1080 : 1920 |
| | | } |
| | | ) |
| | | |
| | | |
| | | const state = reactive({ |
| | | dragging: false |
| | | }) |
| | | |
| | | |
| | | const TEMPLATE_PRESETS = ref([]) |
| | | const templates = ref([]) |
| | | const selectTemplate = ref([]) |
| | | |
| | | |
| | | const tabs1 = [ |
| | | { |
| | | itemName: t('courseCenter.model'), |
| | |
| | | itemValue: '1' |
| | | } |
| | | ] |
| | | const tabs1ActiveNum = ref('') |
| | | const tabs1ActiveNum = ref('0') |
| | | const tabs2ActiveNum = ref('') |
| | | const tabs2 = [ |
| | | { |
| | |
| | | queryParams1.zg = tabs4ActiveNum.value |
| | | getList1() |
| | | } |
| | | |
| | | |
| | | const tabs2Click = (item) => { |
| | | tabs2ActiveNum.value = item.itemValue |
| | | getList() |
| | | } |
| | | |
| | | |
| | | const tabs3Click = (item) => { |
| | | tabs3ActiveNum.value = item.itemValue |
| | | getList() |
| | | } |
| | | |
| | | |
| | | const rightTools = reactive([ |
| | | { |
| | | name: t('courseCenter.template'), |
| | |
| | | // isActive: false |
| | | // } |
| | | ]) |
| | | |
| | | |
| | | const showHeadImageTool = ref(false) |
| | | const showDigitalHumanTool = ref(false) |
| | | // 声音 |
| | |
| | | templateSelection.value = template |
| | | console.log(templateSelection.value) |
| | | } |
| | | |
| | | |
| | | const handleTemplateSelection1 = (index) => { |
| | | if (index == 2) { |
| | | applyAllTemplate.value = true |
| | |
| | | getList1() |
| | | } else if (item.name == t('courseCenter.sound')) { |
| | | // 声音的处理 selectAudio |
| | | |
| | | |
| | | if (selectLanguage.value === undefined) { |
| | | // 获取语言种类 |
| | | getLanguageList() |
| | |
| | | audioType.value = list |
| | | changeAudio.value = list[0].value |
| | | } |
| | | |
| | | |
| | | // 可选的声音类别列表 |
| | | const SoundTypeList = ref() |
| | | // 当前选择的声音类别 |
| | |
| | | ChangeSoundTypeList.value = { ...res[0] } |
| | | } |
| | | if (ChangeSoundTypeList.value === undefined) { |
| | | // 获取可选的声音类型列表 |
| | | GetSoundTypeList() |
| | | // 获取可选的声音类型列表 |
| | | GetSoundTypeList() |
| | | } |
| | | //可选的声音模型的声音类别列表 |
| | | const SoundvoiceTypeList = ref() |
| | |
| | | } |
| | | }) |
| | | console.log(LanguageArr) |
| | | |
| | | |
| | | audioList.value = LanguageArr |
| | | total.value = data.total |
| | | if (selectList.value !== undefined && selectList.value !== null) { |
| | |
| | | SoundcurrentAudio.value.pause() |
| | | SoundcurrentAudio.value = null |
| | | } |
| | | |
| | | |
| | | // 重置当前播放状态 |
| | | if (SoundcurrentlyPlaying.value) { |
| | | SoundcurrentlyPlaying.value.isPlay = false |
| | |
| | | SoundTypeList.value.forEach((element) => { |
| | | if (element.value === event) { |
| | | ChangeSoundTypeList.value = { ...element } |
| | | |
| | | |
| | | if (selectList.value !== undefined && selectList.value !== null) { |
| | | selectList.value = null //初始化 |
| | | } |
| | |
| | | SoundcurrentAudio.value.pause() |
| | | SoundcurrentAudio.value = null |
| | | } |
| | | |
| | | |
| | | // 重置当前播放状态 |
| | | if (SoundcurrentlyPlaying.value) { |
| | | SoundcurrentlyPlaying.value.isPlay = false |
| | |
| | | message.warning('请选择声音模型') |
| | | return false |
| | | } |
| | | |
| | | |
| | | selectAudio(selectList.value) |
| | | } else if (ChangeSoundTypeList.value.value === 1) { |
| | | // 清除选中的音频 |
| | |
| | | // item.isSelect = false |
| | | // }) |
| | | // } |
| | | |
| | | |
| | | // 停止当前播放的音频 |
| | | if (SoundcurrentAudio.value) { |
| | | SoundcurrentAudio.value.pause() |
| | | SoundcurrentAudio.value = null |
| | | } |
| | | |
| | | |
| | | // 重置当前播放状态 |
| | | if (SoundcurrentlyPlaying.value) { |
| | | SoundcurrentlyPlaying.value.isPlay = false |
| | | SoundcurrentlyPlaying.value = null |
| | | } |
| | | |
| | | |
| | | selectAudio(undefined) |
| | | } |
| | | // 记录用户选择的声音信息 |
| | |
| | | type: ChangeSoundTypeList.value, //类型 |
| | | model: selectList.value !== undefined ? selectList.value : '' //声音模型 |
| | | } |
| | | |
| | | |
| | | message.success('声音模型确定成功') |
| | | |
| | | // SoundTool.value = false |
| | | |
| | | |
| | | // rightTools.forEach((child) => { |
| | | // if (child.name == '声音' || child.name == 'sound') { |
| | | // child.isActive = false |
| | |
| | | } |
| | | }) |
| | | } |
| | | |
| | | |
| | | // 音频管理 |
| | | const SoundcurrentAudio = ref<HTMLAudioElement | null>(null) |
| | | const SoundcurrentlyPlaying = ref<any>(null) |
| | | |
| | | |
| | | const playAudio = async (item: any) => { |
| | | // 如果点击的是当前正在播放的项目,则暂停 |
| | | if (SoundcurrentlyPlaying.value && SoundcurrentlyPlaying.value.id === item.id) { |
| | | SoundpauseAudio(item) |
| | | return |
| | | } |
| | | |
| | | |
| | | // 停止当前播放的音频 |
| | | if (SoundcurrentAudio.value) { |
| | | SoundcurrentAudio.value.pause() |
| | | SoundcurrentAudio.value = null |
| | | } |
| | | |
| | | |
| | | // 如果之前有播放的项目,重置其状态 |
| | | if (SoundcurrentlyPlaying.value) { |
| | | SoundcurrentlyPlaying.value.isPlay = false |
| | | } |
| | | |
| | | |
| | | // 设置新的播放项目 |
| | | SoundcurrentlyPlaying.value = item |
| | | item.isPlay = true |
| | | |
| | | |
| | | // 创建新的音频对象并播放 |
| | | SoundcurrentAudio.value = new Audio(item.auditionUrl) |
| | | SoundcurrentAudio.value.play() |
| | | |
| | | |
| | | // 添加播放结束事件监听 |
| | | SoundcurrentAudio.value.addEventListener('ended', () => { |
| | | item.isPlay = false |
| | |
| | | SoundcurrentAudio.value = null |
| | | }) |
| | | } |
| | | |
| | | |
| | | const SoundpauseAudio = (item: any) => { |
| | | if ( |
| | | SoundcurrentAudio.value && |
| | |
| | | SoundcurrentlyPlaying.value = null |
| | | } |
| | | } |
| | | |
| | | |
| | | const PPTArr = ref([]) |
| | | const percentagePPT = ref(0) |
| | | const showLeftList = ref(true) |
| | | |
| | | |
| | | //是否进行过删除操作 |
| | | const DeleteD = ref(false) |
| | | |
| | | |
| | | const selectPPT = ref({ |
| | | pictureUrl: '', |
| | | innerPicture: { |
| | |
| | | host: null |
| | | } |
| | | }) |
| | | |
| | | |
| | | const videoText = ref(0) |
| | | const videoDuration = ref('') |
| | | |
| | | |
| | | watch( |
| | | () => PPTArr.value, |
| | | (val) => { |
| | | if (!val) return |
| | | |
| | | |
| | | videoText.value = val.reduce((prev, curr) => { |
| | | if (!curr.pptRemark) return prev |
| | | const plainText = curr.pptRemark.replace(/<[^>]+>/g, '') |
| | | return prev + plainText.length |
| | | }, 0) |
| | | |
| | | |
| | | let videoTime = (videoText.value / 200) * 60 |
| | | videoDuration.value = formateVideoTime(Math.ceil(videoTime)) |
| | | }, |
| | | { deep: true } |
| | | ) |
| | | |
| | | |
| | | const formateVideoTime = (times: any) => { |
| | | let hours: any = parseInt(`${times / 60 / 60}`) |
| | | let restMinutes: any = parseInt(`${(times / 60) % 60}`) |
| | | let seconds: any = parseInt(`${times % 60}`) |
| | | |
| | | |
| | | if (hours < 10) hours = '0' + hours |
| | | if (restMinutes < 10) restMinutes = '0' + restMinutes |
| | | if (seconds < 10) seconds = '0' + seconds |
| | | |
| | | |
| | | return hours + ':' + restMinutes + ':' + seconds |
| | | } |
| | | |
| | | |
| | | const uploadRef = ref() |
| | | const headers = { |
| | | Accept: 'application/json, text/plain, */*', |
| | | Authorization: 'Bearer ' + getAccessToken(), |
| | | 'tenant-id': getTenantId() |
| | | } |
| | | |
| | | |
| | | const uploadFileObj = reactive({ |
| | | filename: '', |
| | | size: 0, |
| | |
| | | extInfo: '{"addMode":true,"docType":1,"pptNotes":true,"pptContent":false,"notesPolish":false}', |
| | | resolveType: 1 |
| | | }) |
| | | |
| | | |
| | | //智能讲稿组件begin |
| | | //添加ref |
| | | const rewriterRef = ref() |
| | |
| | | file.uid = genFileId() |
| | | uploadRef.value!.handleStart(file) |
| | | } |
| | | |
| | | |
| | | const handleChange = (files) => { |
| | | const extension = files.name.split('.').pop().toLowerCase() |
| | | uploadFileObj.docType = extension === 'pdf' ? 2 : 1 |
| | | uploadFileObj.filename = files.name |
| | | uploadFileObj.size = files.size |
| | | } |
| | | |
| | | |
| | | const uploadExplainRef = ref() |
| | | const handleSuccess = (rawFile) => { |
| | | message.success('上传成功!') |
| | |
| | | uploadExplainRef.value.open() |
| | | uploadRef.value!.clearFiles() |
| | | } |
| | | |
| | | |
| | | const handleError = (err) => { |
| | | message.error('上传失败,请重试') |
| | | console.error('Upload error:', err) |
| | | } |
| | | |
| | | |
| | | const uploadSubmit = (uploadForm) => { |
| | | pptTemplateApi.createPPT(uploadFileObj).then((res) => { |
| | | if (res) { |
| | |
| | | } |
| | | }) |
| | | } |
| | | |
| | | |
| | | const chooseTemplate = (currTemplate) => { |
| | | console.log('currTemplate', currTemplate) |
| | | selectTemplate.value = cloneDeep(currTemplate) |
| | |
| | | currTemplate.isActive = true |
| | | applyTemplate() |
| | | } |
| | | |
| | | |
| | | const schedulePPTTimer = ref() |
| | | const schedulePPT = (id) => { |
| | | percentagePPT.value = 0 |
| | |
| | | item.businessId = generateUUID() |
| | | item.width = courseInfo.value.width |
| | | item.height = courseInfo.value.height |
| | | |
| | | |
| | | // 初始化独立的数字人配置 |
| | | item.digitalHuman = { |
| | | show: true, |
| | |
| | | active: false, |
| | | host: selectHost.value |
| | | } |
| | | |
| | | |
| | | let ppturl = item.pictureUrl |
| | | if (selectTemplate.value.showBackground) { |
| | | item.pictureUrl = selectTemplate.value.bgImage |
| | | } else { |
| | | item.pictureUrl = '' |
| | | } |
| | | |
| | | |
| | | if (item.pictureUrl && selectTemplate.value.showPpt) { |
| | | item.innerPicture = { |
| | | name: '画中画', |
| | |
| | | } |
| | | } |
| | | }) |
| | | |
| | | |
| | | PPTArr.value = res |
| | | PPTArr.value[0].isActive = true |
| | | selectPPT.value = PPTArr.value[0] |
| | | showLeftList.value = true |
| | | clearInterval(schedulePPTTimer.value) |
| | | |
| | | |
| | | //ppt人脸校验 |
| | | PPtIsHaveFace() |
| | | |
| | | |
| | | //轮询保存课程 |
| | | /** |
| | | * 后端数据库压力过大,暂时停止定时保存 |
| | |
| | | }) |
| | | }, 2000) |
| | | } |
| | | |
| | | |
| | | const cancelAnalyze = () => { |
| | | showLeftList.value = true |
| | | clearInterval(schedulePPTTimer.value) |
| | | } |
| | | |
| | | |
| | | const copyDocument = (item, index) => { |
| | | ElMessageBox.confirm('是否复制该页面?', '提示', { |
| | | confirmButtonText: '是', |
| | |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | |
| | | const deleteDocument = (item) => { |
| | | ElMessageBox.confirm('是否删除该页面?', '提示', { |
| | | confirmButtonText: '是', |
| | |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | |
| | | const deleteDigitalHuman = () => { |
| | | selectPPT.value.digitalHuman.show = false |
| | | } |
| | | |
| | | |
| | | const deleteInnerPicture = () => { |
| | | selectPPT.value.innerPicture.src = '' |
| | | } |
| | | |
| | | |
| | | const deleteMore = () => { |
| | | let selected = PPTArr.value.filter((child) => child.isChecked == true) |
| | | if (selected.length == 0) { |
| | |
| | | PPTArr.value = PPTArr.value.filter((child) => child.isChecked !== true) |
| | | } |
| | | } |
| | | |
| | | |
| | | const hostList = ref([]) |
| | | const loading = ref(true) |
| | | const total = ref(0) |
| | |
| | | zg: '' |
| | | }) |
| | | const selectHost = ref(null) |
| | | |
| | | |
| | | const getList = async () => { |
| | | loading.value = true |
| | | try { |
| | |
| | | data.list.forEach((item) => { |
| | | item.isActive = false |
| | | }) |
| | | |
| | | |
| | | hostList.value = data.list |
| | | if (hostList.value.length > 0 && !selectHost.value) { |
| | | selectHost.value = hostList.value[0] |
| | | console.log('selectHost.value', selectHost.value) |
| | | if (selectHost.value !== null) { |
| | | selectHost.value.fixVideoUrl = null |
| | | selectHost.value.pictureUrl = null |
| | | selectHost.value.videoUrl = null |
| | | selectHost.value.id = null |
| | | } |
| | | // 更新当前选中PPT的数字人 |
| | | if (selectPPT.value) { |
| | | selectPPT.value.digitalHuman.host = selectHost.value |
| | | } |
| | | } |
| | | |
| | | |
| | | total.value = data.total |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | |
| | | // 所有数字人形象 |
| | | const AllHumanList = ref<any[]>([]) |
| | | // 获取所有数字人形象 |
| | | const GetAllHumanList = () => { |
| | | let query = { |
| | | pageNo: 1, |
| | | pageSize: 100, |
| | | type: '0', |
| | | gender: tabs2ActiveNum.value, |
| | | posture: tabs3ActiveNum.value, |
| | | status: 0 |
| | | } |
| | | GetHumanList(query) |
| | | query.type = '1' |
| | | GetHumanList(query) |
| | | } |
| | | // 获取单类数字人形象 |
| | | const GetHumanList = async (query) => { |
| | | let data = await pptTemplateApi.pageList(query) |
| | | AllHumanList.value = [...AllHumanList.value, ...data.list] |
| | | } |
| | | |
| | | const choosePPt = (item) => { |
| | | PPTArr.value.forEach((child) => { |
| | | child.isActive = child.id === item.id |
| | | }) |
| | | selectPPT.value = item |
| | | } |
| | | |
| | | |
| | | // const chooseHost = (item) => { |
| | | // hostList.value.forEach((el) => { |
| | | // el.isActive = el.id === item.id |
| | |
| | | digitalHuman.y = viewSize.height - digitalHuman.h |
| | | } |
| | | } |
| | | |
| | | |
| | | const audioSelect = ref() |
| | | const audioSelectData = ref() |
| | | |
| | | |
| | | const openSelect = () => { |
| | | audioSelect.value.open() |
| | | } |
| | | |
| | | |
| | | const selectAudio = (data) => { |
| | | console.log(data) |
| | | audioSelectData.value = data |
| | |
| | | }) |
| | | } |
| | | } |
| | | |
| | | |
| | | const coursesCreate = () => { |
| | | const params = { |
| | | accountId: userId.value |
| | |
| | | } |
| | | }) |
| | | } |
| | | |
| | | |
| | | const saveTime = ref() |
| | | |
| | | |
| | | const getSaveTime = () => { |
| | | const date = new Date() |
| | | let h: any = date.getHours() |
| | | let m: any = date.getMinutes() |
| | | let s: any = date.getSeconds() |
| | | |
| | | |
| | | if (h < 10) h = '0' + h |
| | | if (m < 10) m = '0' + m |
| | | if (s < 10) s = '0' + s |
| | | |
| | | |
| | | return h + ':' + m + ':' + s |
| | | } |
| | | |
| | | |
| | | const warningDialog = ref() |
| | | |
| | | |
| | | const voiceData = reactive({ |
| | | show: false, |
| | | speechRate: 1, |
| | |
| | | 2: '2' |
| | | } |
| | | }) |
| | | |
| | | |
| | | const removeHtmlTags = (html) => { |
| | | const parser = new DOMParser() |
| | | const doc = parser.parseFromString(html, 'text/html') |
| | | return doc.body.textContent || '' |
| | | } |
| | | |
| | | |
| | | const saveSubmit = async (type) => { |
| | | console.log('是否删除', DeleteD.value) |
| | | |
| | | if (ChangeSoundTypeList.value.value === 2) { |
| | | //此时为通用 |
| | | if (selectList.value === undefined || selectList.value === null) { |
| | | message.warning('请选择声音模型') |
| | | return false |
| | | } |
| | | } |
| | | |
| | | |
| | | if (!PPTArr.value || PPTArr.value.length === 0) { |
| | | message.warning('场景为空,请先上传PPT!') |
| | | return false |
| | | } |
| | | |
| | | |
| | | if ( |
| | | selectPPT.value.digitalHuman.host === null || |
| | | selectPPT.value.digitalHuman?.host.fixVideoUrl === null || |
| | | selectPPT.value.digitalHuman?.host.pictureUrl === null || |
| | | selectPPT.value.digitalHuman?.host.videoUrl === null |
| | | ) { |
| | | message.error('请先选择数字人') |
| | | return |
| | | } |
| | | |
| | | //人脸校验 |
| | | while (!IsEndCheckFace.value) {} //一个空循环,主要为了避免极端情况下当用户点击保存按钮或者视频合成按钮时,人脸校验未完成的问题 |
| | | if (IsHaveFace.value && !DeleteD.value) { |
| | | message.warning('当前ppt中存在人脸元素,为方便后续视频生成,请去除该元素') |
| | | return |
| | | } |
| | | |
| | | |
| | | //保存课程 |
| | | let saveSubmitForm = { |
| | | accountId: courseInfo.value.accountId, |
| | |
| | | thumbnail: '', |
| | | subtitlesStyle: '{}' |
| | | } |
| | | |
| | | |
| | | saveSubmitForm.id = courseInfo.value.id |
| | | |
| | | |
| | | const scenes = [] |
| | | const pageInfo = { |
| | | docInfo: { |
| | |
| | | }, |
| | | scenes: [] |
| | | } |
| | | |
| | | |
| | | let thumbnail = '' |
| | | |
| | | |
| | | PPTArr.value.forEach((item, index) => { |
| | | try { |
| | | pageInfo.scenes.push(item.businessId) |
| | | if (index === 0) { |
| | | thumbnail = item.pictureUrl |
| | | } |
| | | |
| | | |
| | | item.pptRemark = removeHtmlTags(item.pptRemark) |
| | | |
| | | |
| | | const formatItem = { |
| | | background: { |
| | | backgroundType: item.backgroundType, |
| | |
| | | }, |
| | | businessId: item.businessId |
| | | } |
| | | |
| | | |
| | | scenes.push(formatItem) |
| | | } catch (error) { |
| | | console.error(`处理第 ${index + 1} 个场景时出错:`, error) |
| | | throw error |
| | | } |
| | | }) |
| | | |
| | | |
| | | saveSubmitForm.pageInfo = JSON.stringify(pageInfo) |
| | | saveSubmitForm.thumbnail = thumbnail |
| | | saveSubmitForm.scenes = cloneDeep(scenes) |
| | | |
| | | |
| | | if (type == 'save') { |
| | | if (DeleteD.value) { |
| | | //如果进行过ppt删除操作则需要进行二次查看 |
| | |
| | | return |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | try { |
| | | const res = await pptTemplateApi.coursesSave(JSON.stringify(saveSubmitForm)) |
| | | if (res) { |
| | |
| | | } |
| | | } else { |
| | | try { |
| | | |
| | | if ( |
| | | ChangeSoundTypeList.value?.value === undefined || |
| | | selectLanguage.value?.value === undefined |
| | |
| | | message.error('请先选择语种与声音类型') |
| | | return |
| | | } |
| | | |
| | | |
| | | if (ChangeSoundTypeList.value.value === 2) { |
| | | //此时为通用 |
| | | if (selectList.value === undefined || selectList.value === null) { |
| | | message.warning('请选择声音模型,并点击确定按钮确定所选声音模型') |
| | | return false |
| | | } |
| | | |
| | | if (audioSelectData.value == undefined) { |
| | | message.warning('请点击确定按钮确定所选声音模型') |
| | | return false |
| | | } |
| | | } |
| | | |
| | | const saveResult = await saveSubmit('save') |
| | | if (!saveResult) { |
| | | message.error('保存失败,请重试后再合成视频') |
| | | return |
| | | } |
| | | |
| | | |
| | | let warningStrArr = [] |
| | | for (let i = 0; i < PPTArr.value.length; i++) { |
| | | const item = PPTArr.value[i] |
| | | console.log(item) |
| | | // 校验背景宽高 |
| | | if (!item.width || !item.height) { |
| | | message.warning('背景尺寸无效,请检查宽高设置,或者重新选择模板') |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | if (warningStrArr.length > 0) { |
| | | warningDialog.value.open(warningStrArr.map((warning) => `<div>${warning}</div>`).join('')) |
| | | return |
| | | } |
| | | |
| | | |
| | | try { |
| | | const res = await pptTemplateApi.megerMedia(saveSubmitForm) |
| | | if (res) { |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | const applyTemplate = (ppt = null) => { |
| | | const template = selectTemplate.value |
| | | let template = selectTemplate.value |
| | | console.log('template', selectTemplate.value) |
| | | const pptList = applyAllTemplate.value ? PPTArr.value : [selectPPT.value] |
| | | |
| | | |
| | | pptList.forEach((item) => { |
| | | const originalPPT = item.innerPicture?.src || item.pictureUrl |
| | | console.log(template) |
| | | item.pictureUrl = template.bgImage |
| | | item.digitalHuman.show = template.showDigitalHuman |
| | | item.digitalHuman.w = template.humanW |
| | | item.digitalHuman.h = template.humanH |
| | | item.digitalHuman.x = template.humanX |
| | | item.digitalHuman.y = template.humanY |
| | | PPTArr.value.forEach((otherItem) => { |
| | | if (otherItem.templateId === item.templateId) { |
| | | otherItem.width = item.width |
| | | otherItem.height = item.height |
| | | } |
| | | }) |
| | | if (template.showPpt) { |
| | | item.innerPicture = { |
| | | name: '画中画', |
| | | src: originalPPT, |
| | | cover: template.bgImage, |
| | | width: template.pptW, |
| | | height: template.pptH, |
| | | top: template.pptY, |
| | | marginLeft: template.pptX, |
| | | category: 1, |
| | | depth: 1, |
| | | businessId: generateUUID(), |
| | | entityType: 1, |
| | | originHeight: courseInfo.value.height, |
| | | originWidth: courseInfo.value.width, |
| | | entityId: 1, |
| | | templateId: template.id |
| | | } |
| | | item.pictureUrl = template.bgImage |
| | | item.digitalHuman.show = template.showDigitalHuman |
| | | item.digitalHuman.w = template.humanW |
| | | item.digitalHuman.h = template.humanH |
| | | item.digitalHuman.x = template.humanX |
| | | item.digitalHuman.y = template.humanY |
| | | PPTArr.value.forEach((otherItem) => { |
| | | if (otherItem.templateId === item.templateId) { |
| | | otherItem.width = item.width |
| | | otherItem.height = item.height |
| | | } |
| | | }) |
| | | if (template.showPpt) { |
| | | item.innerPicture = { |
| | | name: '画中画', |
| | | src: originalPPT, |
| | | cover: template.bgImage, |
| | | width: template.pptW, |
| | | height: template.pptH, |
| | | top: template.pptY, |
| | | marginLeft: template.pptX, |
| | | category: 1, |
| | | depth: 1, |
| | | businessId: generateUUID(), |
| | | entityType: 1, |
| | | originHeight: courseInfo.value.height, |
| | | originWidth: courseInfo.value.width, |
| | | entityId: 1, |
| | | templateId: template.id |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | |
| | | |
| | | const replaceDialog = ref(null) |
| | | |
| | | |
| | | const openReplaceDialog = () => { |
| | | replaceDialog.value.open() |
| | | } |
| | | |
| | | |
| | | const escapeRegExp = (string) => { |
| | | return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') |
| | | } |
| | | |
| | | |
| | | const handleReplacement = (replacements) => { |
| | | PPTArr.value.forEach((item) => { |
| | | if (item.pptRemark) { |
| | |
| | | }) |
| | | message.success('批量替换成功!') |
| | | } |
| | | |
| | | |
| | | const showAudioPlay = ref(false) |
| | | const showAudioPlay1 = ref(false) |
| | | const startAudioPlay = ref(false) |
| | | const textareaRef = ref() |
| | | const selectTextarea = ref('') |
| | | |
| | | |
| | | const audioExceed = () => { |
| | | message.warning('最多上传一个声音驱动文件!') |
| | | } |
| | | |
| | | const currentAudio = ref() |
| | | |
| | | const createAudio = async () => { |
| | | if (ChangeSoundTypeList.value?.value === undefined || selectLanguage.value?.value === undefined || selectLanguage.value.value === 'all_Language' ) { |
| | | message.error('请先选择语种与声音类型') |
| | | return |
| | | } |
| | | |
| | | if (ChangeSoundTypeList.value.value === 2) { |
| | | //此时为通用 |
| | | if (selectList.value === undefined || selectList.value === null) { |
| | | message.warning('请选择声音模型') |
| | | return false |
| | | } |
| | | } |
| | | |
| | | if( ChangeSoundTypeList.value.value === 1 ){ |
| | | if( selectPPT.value.digitalHuman.host === null || selectPPT.value.digitalHuman.host.id === undefined || selectPPT.value.digitalHuman.host.id === null ){ |
| | | message.warning('请选择数字人') |
| | | return false |
| | | } |
| | | } |
| | | |
| | | const currentAudio = ref() |
| | | |
| | | const createAudio = async () => { |
| | | |
| | | const text = editorRef.value.getText() |
| | | if (!text) { |
| | | message.warning('请输入需要试听文本的内容…') |
| | | return false |
| | | } |
| | | |
| | | |
| | | if ( |
| | | ChangeSoundTypeList.value?.value === undefined || |
| | | selectLanguage.value?.value === undefined || |
| | | selectLanguage.value.value === 'all_Language' |
| | | ) { |
| | | message.error('请先选择语种与声音类型') |
| | | return |
| | | } |
| | | |
| | | console.log(ChangeSoundTypeList.value.value) |
| | | console.log(selectList.value) |
| | | |
| | | if (ChangeSoundTypeList.value.value === 2) { |
| | | //此时为通用 |
| | | if (selectList.value === undefined || selectList.value === null) { |
| | | message.warning('请选择声音模型,并点击确定按钮确定所选声音模型') |
| | | return false |
| | | } |
| | | |
| | | if (audioSelectData.value == undefined) { |
| | | message.warning('请点击确定按钮确定所选声音模型') |
| | | return false |
| | | } |
| | | } |
| | | |
| | | if (ChangeSoundTypeList.value.value === 1) { |
| | | if ( |
| | | selectPPT.value.digitalHuman.host === null || |
| | | selectPPT.value.digitalHuman.host.id === undefined || |
| | | selectPPT.value.digitalHuman.host.id === null |
| | | ) { |
| | | message.warning('请选择数字人') |
| | | return false |
| | | } |
| | | } |
| | | |
| | | const truncatedText = text.length > 100 ? text.substring(0, 100) : text |
| | | |
| | | |
| | | const params = { |
| | | text: truncatedText, |
| | | humanId: selectPPT.value.digitalHuman?.host?.id || null, |
| | | voiceId: audioSelectData.value == undefined ? null : audioSelectData.value[0].id, |
| | | language: selectLanguage.value?.value |
| | | } |
| | | |
| | | |
| | | if (ChangeSoundTypeList.value.value === 2) { |
| | | //此时选取了声音模型 |
| | | params.humanId = null |
| | | } else if (ChangeSoundTypeList.value.value === 1) { |
| | | params.voiceId = null |
| | | } |
| | | |
| | | |
| | | try { |
| | | showAudioPlay1.value = true |
| | | const res = await pptTemplateApi.createAudio(params) |
| | | |
| | | |
| | | if (res && !res.error) { |
| | | showAudioPlay1.value = false |
| | | showAudioPlay.value = true |
| | | |
| | | |
| | | currentAudio.value = new Audio(res) |
| | | currentAudio.value.addEventListener('ended', () => { |
| | | showAudioPlay.value = false |
| | | currentAudio.value = null |
| | | }) |
| | | |
| | | |
| | | currentAudio.value.play() |
| | | } else { |
| | | showAudioPlay1.value = false |
| | |
| | | showAudioPlay1.value = false |
| | | } |
| | | } |
| | | |
| | | |
| | | const pauseAudio = () => { |
| | | currentAudio.value.pause() |
| | | currentAudio.value = null |
| | | showAudioPlay.value = false |
| | | } |
| | | |
| | | |
| | | const currentAudioFile = ref() |
| | | |
| | | |
| | | const audioPlay = (file) => { |
| | | if (!file.response.data) { |
| | | message.error('未获取到文件') |
| | | return |
| | | } |
| | | |
| | | |
| | | if (currentAudioFile.value) { |
| | | currentAudioFile.value.pause() |
| | | currentAudioFile.value.currentTime = 0 |
| | | } |
| | | |
| | | |
| | | const audio = new Audio(file.response.data) |
| | | currentAudioFile.value = audio |
| | | |
| | | |
| | | audio.addEventListener('ended', () => { |
| | | cancelAudio() |
| | | }) |
| | | |
| | | |
| | | startAudioPlay.value = true |
| | | audio.play() |
| | | } |
| | | |
| | | |
| | | const cancelAudio = () => { |
| | | if (currentAudioFile.value) { |
| | | currentAudioFile.value.pause() |
| | |
| | | } |
| | | startAudioPlay.value = false |
| | | } |
| | | |
| | | |
| | | const goBack = () => { |
| | | if (PPTArr.value.length == 0) { |
| | | pptTemplateApi.coursesDelete(courseInfo.value.id).then((res) => { |
| | |
| | | router.go(-1) |
| | | } |
| | | } |
| | | |
| | | |
| | | const editorRef = shallowRef() |
| | | const editorConfig = { placeholder: '请输入内容...' } |
| | | |
| | | |
| | | const handleCreated = (editor) => { |
| | | editorRef.value = editor |
| | | } |
| | | |
| | | |
| | | const dialogVisible = ref(false) |
| | | const textList = ref([]) |
| | | |
| | | |
| | | const handleWord = () => { |
| | | editorRef.value.focus() |
| | | selectTextarea.value = editorRef.value.getSelectionText() |
| | |
| | | message.warning(`${selectTextarea.value}不是多音字`) |
| | | } |
| | | } |
| | | |
| | | |
| | | const handleTag = (name) => { |
| | | dialogVisible.value = false |
| | | const node = { |
| | |
| | | const onDragMove = (evt, data) => { |
| | | console.log(evt) |
| | | console.log(data) |
| | | |
| | | |
| | | // 限制坐标 |
| | | if (data.x < -100) { |
| | | data.x = -100 // 可以设置最小坐标为 -100 |
| | |
| | | data.y = -100 // 可以设置最小坐标为 -100 |
| | | } |
| | | } |
| | | |
| | | |
| | | const getCourseDetail = async (id) => { |
| | | const res = await pptTemplateApi.coursesDetail(id) |
| | | console.log( "res当前信息", res ) |
| | | console.log('res当前信息', res) |
| | | if (res) { |
| | | courseInfo.value = res |
| | | |
| | | if (res.scenes && res.scenes.length > 0) { |
| | | res.scenes.forEach((item) => { |
| | | item.isActive = false |
| | | item.isActive = false |
| | | item.isChecked = false |
| | | item.pictureUrl = item.background.src |
| | | item.pptRemark = editorHtml.parseElemHtml(item.background.pptRemark) |
| | | item.backgroundType = item.background.backgroundType |
| | | item.width = item.background.width |
| | | item.height = item.background.height |
| | | |
| | | |
| | | const hostInfo = item.components.find((p) => p.category == 2) |
| | | if (hostInfo) { |
| | | item.digitalHuman = { |
| | |
| | | h: hostInfo.height / scaleRatio.value.height, |
| | | active: false, |
| | | host: { |
| | | ...hostList.value.find((h) => h.code === hostInfo.entityId), |
| | | ...AllHumanList.value.find((h) => h.code === hostInfo.entityId), |
| | | code: hostInfo.entityId, |
| | | type: hostInfo.entityType |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | const innerPicture = item.components.find((p) => p.category == 1) |
| | | if (innerPicture) { |
| | | item.innerPicture = { |
| | |
| | | } |
| | | } |
| | | }) |
| | | |
| | | |
| | | PPTArr.value = res.scenes |
| | | PPTArr.value[0].isActive = true |
| | | selectPPT.value = PPTArr.value[0] |
| | | |
| | | |
| | | PPTArr.value.forEach((scene, index) => { |
| | | if (res.scenes[index].voice) { |
| | | scene.selectAudio = res.scenes[index].voice |
| | |
| | | } |
| | | scene.uploadAudioUrl = res.scenes[index].audioDriver?.audioUrl |
| | | }) |
| | | |
| | | |
| | | if (PPTArr.value[0].audioDriver?.fileName && PPTArr.value[0].audioDriver?.audioUrl) { |
| | | selectPPT.value.fileList = [ |
| | | { |
| | |
| | | } |
| | | ] |
| | | } |
| | | |
| | | |
| | | // 设置音频选择数据 |
| | | const firstScene = res.scenes[0] |
| | | if (firstScene.voice) { |
| | |
| | | ] |
| | | } |
| | | } |
| | | |
| | | |
| | | const pageInfo = res.pageInfo ? JSON.parse(res.pageInfo) : '' |
| | | uploadFileObj.filename = pageInfo ? pageInfo.docInfo.fileName : '' |
| | | uploadFileObj.size = pageInfo ? pageInfo.docInfo.fileSize : '' |
| | |
| | | showDigitalHuman: item.showDigitalHuman === 1, |
| | | showPpt: item.showPpt === 1 |
| | | })) |
| | | |
| | | |
| | | templates.value = TEMPLATE_PRESETS.value.map((template) => cloneDeep(template)) |
| | | selectTemplate.value = cloneDeep(templates.value[0]) |
| | | |
| | | |
| | | await getList() |
| | | |
| | | |
| | | GetAllHumanList() |
| | | |
| | | if (route.query.id) { |
| | | await getCourseDetail(route.query.id) |
| | | } else { |
| | | coursesCreate() |
| | | } |
| | | }) |
| | | |
| | | |
| | | onUnmounted(() => { |
| | | if (schedulePPTTimer.value) { |
| | | clearInterval(schedulePPTTimer.value) |
| | |
| | | } |
| | | }) |
| | | </script> |
| | | |
| | | |
| | | <style scoped lang="scss"> |
| | | .pages { |
| | | height: 100%; |
| | | background-color: #f5f7fa; |
| | | } |
| | | |
| | | |
| | | .minddle-host-image { |
| | | z-index: 5; |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | |
| | | .template-top { |
| | | display: flex; |
| | | height: 60px; |
| | |
| | | border: 1px solid #ebeef5; |
| | | box-shadow: 0 3px 6px rgb(175 175 175 / 16%); |
| | | justify-content: space-between; |
| | | |
| | | |
| | | .top-left { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | |
| | | .top-icon { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | |
| | | .back-text { |
| | | margin-right: 20px; |
| | | margin-left: 10px; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | |
| | | span { |
| | | margin: 0 25px; |
| | | } |
| | | } |
| | | |
| | | |
| | | .top-right { |
| | | span { |
| | | margin: 0 20px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | .template-main { |
| | | display: flex; |
| | | height: calc(100% - 82px); |
| | | padding: 10px; |
| | | justify-content: space-around; |
| | | |
| | | |
| | | .template-left { |
| | | position: relative; |
| | | width: 180px; |
| | | background-color: #fff; |
| | | border: 1px solid #ebeef5; |
| | | box-shadow: 0 3px 6px rgb(175 175 175 / 16%); |
| | | |
| | | |
| | | .page { |
| | | margin: 0; |
| | | |
| | | |
| | | div { |
| | | padding: 5px 10px; |
| | | margin: 0; |
| | | line-height: 30px; |
| | | border-bottom: 1px solid #ebeef5; |
| | | } |
| | | |
| | | |
| | | .line { |
| | | width: 30px; |
| | | height: 3px; |
| | |
| | | margin: 0; |
| | | background-color: aqua; |
| | | } |
| | | |
| | | |
| | | .upload-demo { |
| | | text-align: center; |
| | | } |
| | | } |
| | | |
| | | |
| | | .left-upload-setting { |
| | | display: flex; |
| | | height: calc(100% - 86px); |
| | |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | |
| | | |
| | | div { |
| | | line-height: 40px; |
| | | } |
| | | |
| | | |
| | | ::v-deep(.el-progress-bar) { |
| | | width: 180px; |
| | | } |
| | | |
| | | |
| | | .el-button { |
| | | margin: 20px 0; |
| | | } |
| | | } |
| | | |
| | | |
| | | .image-list { |
| | | height: calc(100% - 70px); |
| | | padding: 10px; |
| | | overflow: hidden auto; |
| | | border-bottom: 1px solid #ebeef5; |
| | | |
| | | |
| | | .list { |
| | | position: relative; |
| | | height: calc(152px * 9 / 16); |
| | | margin: 20px 0; |
| | | box-sizing: content-box; |
| | | |
| | | |
| | | .list-index { |
| | | position: absolute; |
| | | top: 10px; |
| | |
| | | background: #122121; |
| | | border-radius: 5px; |
| | | } |
| | | |
| | | |
| | | .background { |
| | | position: absolute; |
| | | width: 100%; |
| | |
| | | height: 100%; |
| | | background-color: rgba(0, 0, 0, 0); |
| | | } |
| | | |
| | | |
| | | .ppt-bg { |
| | | z-index: 2; |
| | | } |
| | | |
| | | |
| | | .host { |
| | | position: absolute; |
| | | z-index: 3; |
| | | } |
| | | |
| | | |
| | | .icon-content { |
| | | position: absolute; |
| | | top: 0; |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | .page-btn { |
| | | position: absolute; |
| | | bottom: 10px; |
| | |
| | | padding: 0 10px; |
| | | } |
| | | } |
| | | |
| | | |
| | | .template-middle { |
| | | display: flex; |
| | | width: 56%; |
| | |
| | | flex-grow: 1; |
| | | flex-direction: column; |
| | | justify-content: flex-start; |
| | | |
| | | |
| | | .middle-top { |
| | | padding: 5px 20px; |
| | | } |
| | | |
| | | |
| | | .main-box { |
| | | display: flex; |
| | | padding: 10px 20px; |
| | | border: 1px solid #ebeef5; |
| | | justify-content: center; |
| | | |
| | | |
| | | .main-image-box { |
| | | position: relative; |
| | | border: 1px solid #ebeef5; |
| | | box-sizing: content-box; |
| | | } |
| | | |
| | | |
| | | .list { |
| | | position: relative; |
| | | display: flex; |
| | | width: 95%; |
| | | justify-content: center; |
| | | } |
| | | |
| | | |
| | | .ppt-bg { |
| | | z-index: 2; |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | |
| | | .host { |
| | | position: absolute; |
| | | right: 0; |
| | |
| | | width: 300px; |
| | | } |
| | | } |
| | | |
| | | |
| | | .voice-main { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | padding: 10px; |
| | | |
| | | |
| | | .media-box { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | } |
| | | |
| | | |
| | | .audio-upload { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | height: 200px; |
| | | } |
| | | |
| | | |
| | | .middle-textarea { |
| | | padding: 5px 20px; |
| | | } |
| | | |
| | | |
| | | .tool-box { |
| | | display: flex; |
| | | padding: 10px; |
| | | border-top: 1px solid #ebeef5; |
| | | justify-content: space-between; |
| | | |
| | | |
| | | .tool-btn { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | } |
| | | |
| | | |
| | | .audio-play { |
| | | position: absolute; |
| | | top: 0; |
| | |
| | | flex-direction: column; |
| | | } |
| | | } |
| | | |
| | | |
| | | .template-right { |
| | | position: relative; |
| | | width: 20%; |
| | | background-color: #fff; |
| | | box-shadow: 0 3px 6px rgb(175 175 175 / 16%); |
| | | |
| | | |
| | | .tabs-1 { |
| | | display: flex; |
| | | justify-content: space-around; |
| | | padding: 10px 30px; |
| | | border-bottom: 1px solid #ebeef5; |
| | | |
| | | |
| | | .tabs-item { |
| | | width: 50px; |
| | | font-size: 14px; |
| | | text-align: center; |
| | | cursor: pointer; |
| | | |
| | | |
| | | span { |
| | | display: block; |
| | | width: 50px; |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | .tabs-2 { |
| | | display: flex; |
| | | padding: 10px; |
| | | justify-content: space-around; |
| | | |
| | | |
| | | div { |
| | | width: 60px; |
| | | height: 30px; |
| | |
| | | cursor: pointer; |
| | | border-radius: 5px; |
| | | } |
| | | |
| | | |
| | | .tabs-active { |
| | | color: #fff !important; |
| | | background-color: #409eff; |
| | | } |
| | | } |
| | | |
| | | |
| | | .apply-all { |
| | | position: absolute; |
| | | bottom: 80px; |
| | |
| | | width: 100%; |
| | | justify-content: center; |
| | | } |
| | | |
| | | |
| | | .host-list { |
| | | height: 80%; |
| | | overflow-y: auto; |
| | | border-top: 1px solid #ebeef5; |
| | | |
| | | |
| | | .host-item { |
| | | position: relative; |
| | | display: inline-block; |
| | |
| | | margin: 5px 0; |
| | | margin-left: 10px; |
| | | cursor: pointer; |
| | | |
| | | |
| | | .background { |
| | | position: absolute; |
| | | top: 0; |
| | |
| | | height: 100%; |
| | | background-color: #f0f1fa; |
| | | } |
| | | |
| | | |
| | | .host-name { |
| | | position: absolute; |
| | | bottom: 10px; |
| | |
| | | background: rgb(225 225 225 / 70%); |
| | | border-radius: 5px; |
| | | } |
| | | |
| | | |
| | | .ppt-bg { |
| | | z-index: 2; |
| | | width: 100%; |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | .image-setting { |
| | | padding: 10px 20px; |
| | | |
| | | |
| | | .img-setting { |
| | | display: flex; |
| | | align-items: center; |
| | | line-height: 40px; |
| | | |
| | | |
| | | .setting-label { |
| | | width: 120px; |
| | | } |
| | | |
| | | |
| | | ::v-deep(.el-input) { |
| | | width: 170px; |
| | | margin-left: 10px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | .template-list { |
| | | height: 90%; |
| | | overflow-y: auto; |
| | | border-top: 1px solid #ebeef5; |
| | | |
| | | |
| | | .template-item { |
| | | position: relative; |
| | | display: inline-block; |
| | |
| | | position: absolute; |
| | | z-index: 2; |
| | | } |
| | | |
| | | |
| | | .human-image { |
| | | position: absolute; |
| | | z-index: 3; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | .background { |
| | | position: absolute; |
| | | top: 0; |
| | |
| | | height: 100%; |
| | | //background-color: #f0f1fa; |
| | | } |
| | | |
| | | |
| | | .template-tool { |
| | | width: 60px; |
| | | padding: 10px; |
| | | background-color: #fff; |
| | | box-shadow: 0 3px 6px rgb(175 175 175 / 16%); |
| | | |
| | | |
| | | .tool-item { |
| | | display: flex; |
| | | padding: 10px 20px; |
| | | cursor: pointer; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | |
| | | |
| | | img { |
| | | width: 32px; |
| | | height: 32px; |
| | | } |
| | | |
| | | |
| | | .tool-name { |
| | | width: 60px; |
| | | margin-top: 6px; |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | ::v-deep(.el-pagination) { |
| | | position: absolute; |
| | | bottom: 0; |
| | | } |
| | | |
| | | |
| | | ::-webkit-scrollbar { |
| | | width: 4px; |
| | | } |
| | | |
| | | |
| | | ::-webkit-scrollbar-thumb { |
| | | background-color: #888; |
| | | border-radius: 6px; |
| | | } |
| | | |
| | | |
| | | ::-webkit-scrollbar-track { |
| | | background-color: #f2f2f2; |
| | | border-radius: 6px; |
| | | } |
| | | |
| | | |
| | | .voice-card { |
| | | z-index: 1000 !important; |
| | | } |
| | | |
| | | |
| | | .voice-card :deep(.el-card__body) { |
| | | padding: 0; |
| | | } |
| | | |
| | | |
| | | .speech-slider { |
| | | &:deep(.el-slider__bar) { |
| | | display: none; |
| | | } |
| | | |
| | | |
| | | &:deep(.el-slider__runway) { |
| | | height: 2px; |
| | | } |
| | | |
| | | |
| | | &:deep(.el-slider__button-wrapper) { |
| | | top: -17px; |
| | | } |
| | | |
| | | |
| | | &:deep(.el-slider__marks-stop) { |
| | | top: -5px; |
| | | width: 12px; |
| | |
| | | .dialog-footer { |
| | | float: right; |
| | | } |
| | | |
| | | |
| | | // 声音部分 |
| | | .SoundArea { |
| | | margin-top: 16px; |
| | |
| | | height: 86%; |
| | | margin: 10px 0; |
| | | overflow-y: scroll; |
| | | |
| | | |
| | | .SoundModelAreaBox { |
| | | width: 100%; |
| | | .SoundClassTit { |
| | |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | | </style> |