|
@@ -6,18 +6,87 @@
|
|
|
<span v-html="sanitizeHTML(data.stem)"></span>
|
|
|
</div>
|
|
|
<div v-if="isEnable(data.property.is_enable_description)" class="description">{{ data.description }}</div>
|
|
|
- <div class="dialogue">{{ data.dialogue }}</div>
|
|
|
+ <div class="dialogue-wrapper">
|
|
|
+ <ul>
|
|
|
+ <li v-for="(item, i) in dialogue" :key="i" :style="{ flexDirection: item.dir }" class="dialogue-item">
|
|
|
+ <span class="name">{{ item.name }}</span>
|
|
|
+ <div class="content">
|
|
|
+ <template v-if="item.type === 'text'">
|
|
|
+ {{ item.content }}
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <el-input v-model="item.content" />
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
+import { getRandomNumber } from '@/utils';
|
|
|
import PreviewMixin from './components/PreviewMixin';
|
|
|
|
|
|
export default {
|
|
|
name: 'DialoguePreview',
|
|
|
mixins: [PreviewMixin],
|
|
|
data() {
|
|
|
- return {};
|
|
|
+ return {
|
|
|
+ dialogue: [], // 对话列表
|
|
|
+ };
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ 'data.dialogue': {
|
|
|
+ handler() {
|
|
|
+ let dir = 'row';
|
|
|
+ let preName = '';
|
|
|
+ this.dialogue = this.data.dialogue
|
|
|
+ // 用换行分割 this.data.dialogue
|
|
|
+ .split('\n')
|
|
|
+ // 过滤掉空行
|
|
|
+ .filter((item) => item.trim() !== '')
|
|
|
+ .map((item) => {
|
|
|
+ // 分割对话中的人物和对话内容
|
|
|
+ const match = item.match(/(\S+)[::](.+)/);
|
|
|
+ if (match) {
|
|
|
+ let name = match[1];
|
|
|
+ if (preName.length === 0 || preName !== name) {
|
|
|
+ dir = preName.length === 0 ? 'row' : dir === 'row' ? 'row-reverse' : 'row';
|
|
|
+ }
|
|
|
+ preName = name;
|
|
|
+ let content = match[2];
|
|
|
+ let isFill = /_{3,}/.test(content);
|
|
|
+
|
|
|
+ return {
|
|
|
+ name,
|
|
|
+ content: isFill ? '' : content,
|
|
|
+ dir,
|
|
|
+ mark: isFill ? getRandomNumber() : '',
|
|
|
+ type: isFill ? 'input' : 'text',
|
|
|
+ };
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .filter((item) => item);
|
|
|
+ },
|
|
|
+ deep: true,
|
|
|
+ immediate: true,
|
|
|
+ },
|
|
|
+ dialogue: {
|
|
|
+ handler() {
|
|
|
+ this.answer.answer_list = this.dialogue
|
|
|
+ .map(({ type, mark, content }) => {
|
|
|
+ if (type === 'text') return;
|
|
|
+ return {
|
|
|
+ content,
|
|
|
+ mark,
|
|
|
+ };
|
|
|
+ })
|
|
|
+ .filter((item) => item);
|
|
|
+ },
|
|
|
+ deep: true,
|
|
|
+ immediate: true,
|
|
|
+ },
|
|
|
},
|
|
|
methods: {},
|
|
|
};
|
|
@@ -29,8 +98,28 @@ export default {
|
|
|
.dialogue-preview {
|
|
|
@include preview;
|
|
|
|
|
|
- .dialogue {
|
|
|
- white-space: pre-line;
|
|
|
+ .dialogue-wrapper {
|
|
|
+ padding: 24px;
|
|
|
+ background-color: #f9f8f9;
|
|
|
+ border-radius: 16px;
|
|
|
+
|
|
|
+ ul {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ row-gap: 24px;
|
|
|
+
|
|
|
+ .dialogue-item {
|
|
|
+ display: flex;
|
|
|
+ column-gap: 16px;
|
|
|
+
|
|
|
+ .content {
|
|
|
+ padding: 8px 16px;
|
|
|
+ color: #000;
|
|
|
+ background-color: #fff;
|
|
|
+ border-radius: 8px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
</style>
|