123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- <template>
- <div class="pinyin-area">
- <div v-for="(paragraph, i) in paragraphList" :key="i" class="pinyin-paragraph">
- <span
- v-for="(sentence, j) in paragraph"
- :key="j"
- class="pinyin-sentence"
- :style="{ 'align-items': pinyinPosition === 'top' ? 'flex-end' : 'flex-start' }"
- >
- <span v-for="(item, k) in sentence" :key="k" class="pinyin-text">
- <span
- :class="{ active: visible && word_index == k && paragraph_index === i && sentence_index === j }"
- :title="isPreview ? '' : '点击校对'"
- :style="{
- cursor: isPreview ? '' : 'pointer',
- 'align-items': k == 0 ? 'flex-start' : 'center',
- }"
- @click="correctPinyin(item, i, j, k)"
- >
- <span v-if="pinyinPosition === 'top'" class="pinyin">{{ item.pinyin.replace(/\s+/g, '') }}</span>
- <span class="py-char" :style="{ ...item.activeTextStyle }">{{ item.text }}</span>
- <span v-if="pinyinPosition !== 'top'" class="pinyin">{{ item.pinyin.replace(/\s+/g, '') }}</span>
- </span>
- </span>
- </span>
- </div>
- <CorrectPinyin
- :visible.sync="visible"
- :select-content="selectContent"
- :component-type="componentType"
- @fillTonePinyin="fillTonePinyin"
- />
- <el-dialog
- ref="optimizedDialog"
- title=""
- :visible.sync="noteDialogVisible"
- width="680px"
- :style="dialogStyle"
- :close-on-click-modal="false"
- destroy-on-close
- @close="noteDialogVisible = false"
- >
- <span v-html="sanitizeHTML(note)"></span>
- </el-dialog>
- </div>
- </template>
- <script>
- import CorrectPinyin from '@/views/book/courseware/create/components/base/common/CorrectPinyin.vue';
- import { sanitizeHTML } from '@/utils/common';
- export default {
- name: 'PinyinText',
- components: {
- CorrectPinyin,
- },
- props: {
- paragraphList: {
- type: Array,
- required: true,
- },
- pinyinPosition: {
- type: String,
- required: true,
- },
- isPreview: {
- type: Boolean,
- default: false,
- },
- componentType: {
- type: String,
- default: '',
- },
- },
- data() {
- return {
- sanitizeHTML,
- paragraph_list: [],
- visible: false,
- selectContent: {},
- paragraph_index: 0,
- sentence_index: 0,
- word_index: 0,
- noteDialogVisible: false,
- note: '',
- dialogStyle: {
- position: 'fixed',
- top: '0',
- left: '0',
- margin: '0',
- },
- };
- },
- methods: {
- // 校对拼音
- correctPinyin(item, i, j, k) {
- if (this.isPreview) {
- if (item.note) {
- this.note = item.note;
- this.noteDialogVisible = true;
- this.$nextTick(() => {
- const dialogElement = this.$refs.optimizedDialog;
- // 确保对话框DOM已渲染
- if (!dialogElement) {
- return;
- }
- // 获取对话框内容区域的DOM元素
- const dialogContent = dialogElement.$el.querySelector('.el-dialog');
- if (!dialogContent) {
- return;
- }
- const dialogRect = dialogContent.getBoundingClientRect();
- const dialogWidth = dialogRect.width;
- const dialogHeight = dialogRect.height;
- const padding = 10; // 安全边距
- const clickX = event.clientX;
- const clickY = event.clientY;
- const windowWidth = window.innerWidth;
- const windowHeight = window.innerHeight;
- // 水平定位 - 中心对齐
- let left = clickX - dialogWidth / 2;
- // 边界检查
- left = Math.max(padding, Math.min(left, windowWidth - dialogWidth - padding));
- // 垂直定位 - 点击位置作为下边界中心
- let top = clickY - dialogHeight;
- // 上方空间不足时,改为向下展开
- if (top < padding) {
- top = clickY + padding;
- // 如果向下展开会超出屏幕,则贴底部显示
- if (top + dialogHeight > windowHeight - padding) {
- top = windowHeight - dialogHeight - padding;
- }
- }
- this.dialogStyle = {
- position: 'fixed',
- top: `${top - 20}px`,
- left: `${left}px`,
- margin: '0',
- transform: 'none',
- };
- });
- }
- return;
- } // 如果是预览模式,不操作
- if (item) {
- this.visible = true;
- this.selectContent = item;
- this.paragraph_index = i;
- this.sentence_index = j;
- this.word_index = k;
- }
- },
- // 回填校对后的拼音
- fillTonePinyin(dataContent) {
- this.$emit('fillCorrectPinyin', {
- selectContent: dataContent,
- i: this.paragraph_index,
- j: this.sentence_index,
- k: this.word_index,
- });
- },
- },
- };
- </script>
- <style lang="scss" scoped>
- .pinyin-area {
- .pinyin-paragraph {
- .pinyin-sentence {
- .pinyin-text {
- padding: 0 2px;
- font-size: 16px;
- text-wrap: pretty;
- hanging-punctuation: allow-end;
- > span {
- display: inline-flex;
- flex-direction: column;
- align-items: center;
- }
- .py-char {
- ruby-align: center;
- }
- .pinyin {
- font-family: 'PINYIN-B';
- font-size: 12px;
- font-weight: lighter;
- line-height: 12px;
- color: $font-color;
- }
- }
- }
- }
- .active {
- color: rgb(242, 85, 90) !important;
- }
- }
- </style>
- <style lang="scss">
- .pinyin-area + .pinyin-area {
- margin-top: 4px;
- }
- </style>
|