刘光辉
3 小时以前 cf11e63b659afcc9792ab3e395f1b45d844431a8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<script lang="ts" setup>
import type { FormulaValidation } from '#/api/x/eln/formulas';
 
import { computed, onMounted, ref, watch } from 'vue';
 
defineOptions({ name: 'ElnFormulaPreview' });
 
const props = defineProps<{ validation?: FormulaValidation }>();
const previewElement = ref<HTMLElement>();
let renderSequence = 0;
 
const hasValidationError = computed(() => props.validation?.diagnostics.some((diagnostic) => diagnostic.severity === 'ERROR') || false);
const errorText = computed(() =>
  (props.validation?.diagnostics || [])
    .filter((diagnostic) => diagnostic.severity === 'ERROR')
    .map((diagnostic) => diagnostic.message || diagnostic.code || '公式校验失败')
    .join(';'),
);
const latex = computed(() => (hasValidationError.value ? null : props.validation?.latex?.trim() || null));
 
onMounted(() => void renderPreview());
watch(latex, () => void renderPreview(), { flush: 'post' });
 
async function renderPreview() {
  const sequence = ++renderSequence;
  if (!latex.value || !previewElement.value) {
    previewElement.value?.replaceChildren();
    return;
  }
  const currentLatex = latex.value;
  try {
    const { default: katex } = await import('katex');
    await import('katex/dist/katex.min.css');
    if (sequence !== renderSequence || latex.value !== currentLatex || !previewElement.value) return;
    previewElement.value.replaceChildren();
    katex.render(currentLatex, previewElement.value, { displayMode: true, strict: 'warn', throwOnError: false, trust: false });
  } catch {
    if (sequence === renderSequence) previewElement.value?.replaceChildren();
  }
}
</script>
 
<template>
  <div class="formula-preview">
    <a-alert v-if="errorText" :message="errorText" show-icon type="error" />
    <div v-else-if="!latex" class="formula-preview__empty">等待公式校验结果</div>
    <div v-show="latex" ref="previewElement" class="formula-preview__surface"></div>
  </div>
</template>
 
<style lang="scss" scoped>
.formula-preview {
  height: 100%;
}
 
.formula-preview__surface {
  min-height: 120px;
  padding: 24px 12px;
  overflow: auto;
}
 
.formula-preview__empty {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 120px;
  color: var(--text-color-secondary);
}
</style>