<template> <q-dialog persistent v-model="show_dialog" @show="onShow" @before-hide="resetData" @keydown=" (evt) => { if (!loading && evt.keyCode == 27) { show_dialog = false; } } " > <q-card class="overflow-hidden" style="max-width: 70vw"> <q-form @submit="onSubmit"> <q-card-section class="q-ma-none q-pa-sm"> <div class="row"> <div class="col-auto text-h6"> {{ $t("subtitle") }} </div> <q-space /> <q-btn :loading="loading" flat round icon="close" color="red" :disable="loading" v-close-popup > <q-tooltip> {{ $t("close") }} </q-tooltip> </q-btn> </div> </q-card-section> <q-separator /> <q-card-section class="scroll" style="width: 70vw"> <q-list> <q-item v-if="false"> <q-item-section> <q-input :label="$t('background color')" v-model="subtitle.background" :disable="subtitle.background_transparent" :rules="['anyColor']" hint="" > <template v-slot:append> <q-icon name="colorize" class="cursor-pointer"> <q-popup-proxy transition-show="scale" transition-hide="scale" > <q-color v-model="subtitle.background" /> </q-popup-proxy> </q-icon> </template> </q-input> </q-item-section> <q-item-section> <q-checkbox :label="$t('background transparent')" v-model="subtitle.background_transparent" /> </q-item-section> </q-item> <q-item> <q-item-section> <q-select :label="$t('move speed')" v-model="subtitle.x_speed" :options="[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 20]" ></q-select> </q-item-section> <q-item-section> <q-input type="number" :label="$t('width')" maxlength="4" max="7680" min="0" v-model="subtitle.width" /> </q-item-section> </q-item> <q-item> <q-item-section> <q-input type="number" :label="$t('pos x')" maxlength="4" max="7680" min="0" v-model="subtitle.x" /> </q-item-section> <q-item-section> <q-input type="number" :label="$t('pos y')" maxlength="4" max="2160" min="0" v-model="subtitle.y_offset" /> </q-item-section> </q-item> <q-item> <q-item-section> <q-checkbox :label="$t('enable subtitle')" v-model="subtitle.show" /> </q-item-section> </q-item> <q-separator inset /> <q-item style="height: 50vh"> <q-item-section :style="{ 'align-items': loading ? 'center' : 'unset', }" > <editor v-if="!loading" class="fit" tinymce-script-src="tinymce/tinymce.min.js" :init="editor_config" v-model="subtitle.text" @init="(event, editor) => editorInited(event, editor)" /> <q-spinner v-else color="primary" size="5em" :thickness="2" /> </q-item-section> </q-item> </q-list> </q-card-section> <q-separator /> <q-card-actions align="right"> <q-btn :loading="loading" flat :label="$t('Cancel')" no-caps color="primary" v-close-popup /> <q-btn ref="accept" flat :label="$t('Accept')" no-caps :loading="loading" type="submit" color="primary" /> </q-card-actions> </q-form> </q-card> </q-dialog> </template> <script lang="ts"> import { defineComponent, ref, Ref, reactive, watch, computed, onMounted, onBeforeUnmount, nextTick, } from "vue"; import { useStore } from "src/store"; import { useQuasar, dom as DomUtil } from "quasar"; import { useI18n } from "vue-i18n"; import GlobalData from "src/common/GlobalData"; import SubtitleEntity from "src/entities/SubtitleEntity"; import Editor from "@tinymce/tinymce-vue"; export default defineComponent({ name: "ComponentSubtitleDialog", components: { Editor, }, setup() { let $store = useStore(); let $q = useQuasar(); let $t = useI18n(); const i18n = useI18n(); let show_dialog = ref(false); let loading = ref(false); let subtitle = ref(new SubtitleEntity()); const fontOptions: number[] = []; for (let i = 9; i <= 300; i += 3) { fontOptions.push(i); } const get_font_size_formarts = () => { let result = ""; for (const item of fontOptions) { result += item + "pt "; } return result; }; const editor_config = reactive({ plugins: [ "fullscreen", /*'lists link image paste help wordcount'*/ ], mobile: { menubar: true, }, font_size_formats: get_font_size_formarts(), skin: "tinymce-5", language: i18n.locale.value == "zh-CN" ? "zh_CN" : "en_US", menubar: false, branding: false, toolbar_mode: "wrap", toolbar: // "fullscreen | code undo redo restoredraft | cut copy paste pastetext | fontsize| forecolor backcolor bold italic underline strikethrough | alignleft aligncenter alignright alignjustify |subscript superscript removeformat", "fullscreen | fontsize| forecolor backcolor bold italic underline strikethrough | subscript superscript removeformat", }); return { show_dialog, loading, subtitle, editor_config, async showDialog() { show_dialog.value = true; loading.value = true; try { let response = await GlobalData.getInstance() .getCurrentClient() ?.getSubtitle(); if (response) { try { const temp = response.subtitle; for (const item of Object.keys(subtitle.value)) { if (typeof (<any>temp)[item] != "undefined") { (<any>subtitle.value)[item] = (<any>temp)[item]; } } } catch { subtitle.value = response.subtitle; } } } catch (e) { console.log(e); show_dialog.value = false; } loading.value = false; }, editorInited(event: any, editor: any) { editor.execCommand("FontSize", false, "60pt"); }, onShow() { let success = false; const checkZIndex = () => { document.querySelectorAll(".tox ").forEach((item) => { if (item && item.classList.contains("tox-tinymce-aux")) { DomUtil.css(item, { zIndex: "99999", }); success = true; } }); }; const checkZIndexAsync = () => { checkZIndex(); setTimeout(() => { if (!success) { checkZIndexAsync(); } else { console.log("subtitle initialize success"); } }, 50); }; checkZIndexAsync(); }, resetData() { loading.value = false; }, async onSubmit() { loading.value = true; try { subtitle.value.y_offset = parseInt( subtitle.value.y_offset.toString() ); subtitle.value.x_speed = parseInt(subtitle.value.x_speed.toString()); subtitle.value.x = parseInt(subtitle.value.x.toString()); subtitle.value.width = parseInt(subtitle.value.width.toString()); GlobalData.getInstance() .getCurrentClient() ?.setSubtitle(subtitle.value); $q.notify({ color: "positive", icon: "done", message: $t.t("set subtitle success") + "!", position: "top", timeout: 1500, }); show_dialog.value = false; } catch {} }, }; }, }); </script>