|
@@ -0,0 +1,247 @@
|
|
|
+<template>
|
|
|
+ <el-dialog
|
|
|
+ :visible="visible"
|
|
|
+ width="800px"
|
|
|
+ custom-class="multilingual-fill-dialog"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ @close="closeDialog"
|
|
|
+ >
|
|
|
+ <div class="multilingual-fill">
|
|
|
+ <div class="left-menu">
|
|
|
+ <span class="title">多语言</span>
|
|
|
+ <ul class="lang-list">
|
|
|
+ <li
|
|
|
+ v-for="{ code } in selectedLangList"
|
|
|
+ :key="code"
|
|
|
+ :class="['lang-item', { active: curLang === code }]"
|
|
|
+ @click="curLang = code"
|
|
|
+ >
|
|
|
+ {{ langList.find((item) => item.code === code).name }}
|
|
|
+ </li>
|
|
|
+ <li class="lang-item" @click="showAddLang">
|
|
|
+ <i class="el-icon-plus"></i>
|
|
|
+ <span>增加语种</span>
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="right-content">
|
|
|
+ <div class="operator">
|
|
|
+ <div class="operator-left">
|
|
|
+ <span class="btn" @click="isShowOriginal = !isShowOriginal">
|
|
|
+ <i v-show="!isShowOriginal" class="el-icon-view"></i>
|
|
|
+ <SvgIcon v-show="isShowOriginal" :size="12" icon-class="eye-invisible" />
|
|
|
+ <span>{{ isShowOriginal ? '隐藏原文' : '显示原文' }}</span>
|
|
|
+ </span>
|
|
|
+ <span class="btn primary" @click="submitTranslation">
|
|
|
+ <span>提交译文</span>
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ <i class="el-icon-close" @click="closeDialog"></i>
|
|
|
+ </div>
|
|
|
+ <div class="content">
|
|
|
+ <el-input v-show="isShowOriginal" :value="text" type="textarea" :rows="27" resize="none" :readonly="true" />
|
|
|
+ <el-input
|
|
|
+ v-for="lang in selectedLangList"
|
|
|
+ v-show="curLang === lang.code"
|
|
|
+ :key="lang.code"
|
|
|
+ v-model="lang.translation"
|
|
|
+ type="textarea"
|
|
|
+ :rows="27"
|
|
|
+ resize="none"
|
|
|
+ placeholder="输入译文"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <UpdateLang :visible.sync="langVisible" :selected-langs="selectedLangList" @update-langs="handleUpdateLangs" />
|
|
|
+ </el-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import UpdateLang from './UpdateLang.vue';
|
|
|
+
|
|
|
+import { langList } from '@/views/book/courseware/data/common';
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'MultilingualFill',
|
|
|
+ components: {
|
|
|
+ UpdateLang,
|
|
|
+ },
|
|
|
+ props: {
|
|
|
+ visible: {
|
|
|
+ type: Boolean,
|
|
|
+ required: true,
|
|
|
+ },
|
|
|
+ text: {
|
|
|
+ type: String,
|
|
|
+ default: '',
|
|
|
+ },
|
|
|
+ translations: {
|
|
|
+ type: Array,
|
|
|
+ default: () => [],
|
|
|
+ },
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ langList,
|
|
|
+ selectedLangList: [
|
|
|
+ { code: 'en', translation: '' },
|
|
|
+ { code: 'fr', translation: '' },
|
|
|
+ { code: 'de', translation: '' },
|
|
|
+ { code: 'es', translation: '' },
|
|
|
+ { code: 'it', translation: '' },
|
|
|
+ { code: 'pt', translation: '' },
|
|
|
+ { code: 'ko', translation: '' },
|
|
|
+ { code: 'ja', translation: '' },
|
|
|
+ ],
|
|
|
+ noSelectedLangList: ['ru', 'ar', 'tr', 'nl', 'pl', 'sv', 'el'],
|
|
|
+ curLang: 'en',
|
|
|
+ isShowOriginal: true, // 是否显示原文
|
|
|
+ langVisible: false,
|
|
|
+ };
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ translations: {
|
|
|
+ handler(newVal) {
|
|
|
+ if (!newVal || !Array.isArray(newVal) || newVal.length === 0) return;
|
|
|
+ this.selectedLangList = newVal.map(({ code, translation }) => ({
|
|
|
+ code,
|
|
|
+ translation,
|
|
|
+ }));
|
|
|
+ },
|
|
|
+ immediate: true,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ closeDialog() {
|
|
|
+ this.$emit('update:visible', false);
|
|
|
+ },
|
|
|
+ showAddLang() {
|
|
|
+ this.langVisible = true;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 处理语言更新
|
|
|
+ * @param {Array} langs
|
|
|
+ */
|
|
|
+ handleUpdateLangs(langs) {
|
|
|
+ const newLangs = langs.filter((item) => !this.selectedLangList.map((i) => i.code).includes(item));
|
|
|
+ const removedLangs = this.selectedLangList.map((i) => i.code).filter((item) => !langs.includes(item));
|
|
|
+
|
|
|
+ this.selectedLangList = [
|
|
|
+ ...this.selectedLangList.filter((item) => !removedLangs.includes(item.code)),
|
|
|
+ ...newLangs.map((item) => ({ code: item, translation: '' })),
|
|
|
+ ];
|
|
|
+ },
|
|
|
+ submitTranslation() {
|
|
|
+ this.$emit('submit-translation', this.selectedLangList);
|
|
|
+ this.closeDialog();
|
|
|
+ },
|
|
|
+ },
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+@use 'sass:color';
|
|
|
+
|
|
|
+.el-dialog__wrapper {
|
|
|
+ :deep .multilingual-fill-dialog {
|
|
|
+ > .el-dialog__header {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ > .el-dialog__body {
|
|
|
+ height: 650px;
|
|
|
+ padding: 12px 16px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.multilingual-fill {
|
|
|
+ display: flex;
|
|
|
+ column-gap: 8px;
|
|
|
+
|
|
|
+ .left-menu {
|
|
|
+ width: 90px;
|
|
|
+
|
|
|
+ .title {
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #333;
|
|
|
+ }
|
|
|
+
|
|
|
+ .lang-list {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ row-gap: 8px;
|
|
|
+ height: 585px;
|
|
|
+ margin-top: 12px;
|
|
|
+ overflow: auto;
|
|
|
+
|
|
|
+ .lang-item {
|
|
|
+ padding: 4px 8px;
|
|
|
+ text-align: center;
|
|
|
+ cursor: pointer;
|
|
|
+ background-color: #f5f5f5;
|
|
|
+ border-radius: 4px;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background-color: #e0e0e0;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.active {
|
|
|
+ color: #fff;
|
|
|
+ background-color: $main-color;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .right-content {
|
|
|
+ flex: 1;
|
|
|
+
|
|
|
+ .operator {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ margin-bottom: 8px;
|
|
|
+
|
|
|
+ &-left {
|
|
|
+ display: flex;
|
|
|
+ column-gap: 8px;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ .btn {
|
|
|
+ display: flex;
|
|
|
+ column-gap: 4px;
|
|
|
+ align-items: center;
|
|
|
+ padding: 6px 12px;
|
|
|
+ font-size: 12px;
|
|
|
+ cursor: pointer;
|
|
|
+ background-color: #f5f5f5;
|
|
|
+ border-radius: 4px;
|
|
|
+
|
|
|
+ &.primary {
|
|
|
+ color: #fff;
|
|
|
+ background-color: $main-color;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background-color: color.adjust($main-color, $lightness: -5%);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ i {
|
|
|
+ font-weight: bold;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .content {
|
|
|
+ display: flex;
|
|
|
+ column-gap: 8px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|