| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- <template>
- <el-dialog
- title="输入公式"
- :visible="visible"
- width="850px"
- top="20vh"
- :show-close="false"
- :close-on-press-escape="false"
- :close-on-click-modal="false"
- @close="dialogClose"
- >
- <el-input
- v-model="math"
- type="textarea"
- :autosize="{ minRows: 4, maxRows: 8 }"
- resize="none"
- placeholder="请输入公式"
- @input="renderMathDialog"
- />
- <el-tabs v-model="activeTab" type="card">
- <el-tab-pane
- v-for="(macros, category) in mathMacrosListByCategory"
- :key="category"
- :label="categoryList[category]"
- >
- <div class="math-macros">
- <span
- v-for="macro in macros"
- :key="macro"
- :ref="macro"
- :class="['macros-item', `${macro}`]"
- @click="insertMacro(macro)"
- >
- {{ computedMacrosText(macro) }}
- </span>
- </div>
- </el-tab-pane>
- </el-tabs>
- <div ref="mathContainer" class="formula-render" v-html="math"></div>
- <template slot="footer">
- <el-button size="medium" @click="dialogClose">取消</el-button>
- <el-button type="primary" size="medium" @click="mathConfirm">确定</el-button>
- </template>
- </el-dialog>
- </template>
- <script>
- import {
- mathMacrosListByCategory,
- onlyMultiMacros,
- onlyAlignMacros,
- commonMacros,
- categoryList,
- } from '@/views/book/courseware/data/richText';
- export default {
- name: 'MathDialog',
- props: {
- visible: {
- type: Boolean,
- default: false,
- },
- },
- data() {
- return {
- math: '',
- activeTab: '0', // 用于控制选中的标签页
- mathMacrosListByCategory,
- categoryList,
- openNumber: 0, // 用于控制 MathJax 渲染
- };
- },
- watch: {
- visible(newVal) {
- if (newVal) {
- this.openNumber += 1;
- this.$nextTick(() => {
- const macrosRefs = Object.values(mathMacrosListByCategory)
- .flat()
- .map((macro) => this.$refs[macro]);
- window.MathJax.typesetPromise(macrosRefs).catch((err) => {
- console.error('MathJax 初始化失败:', err);
- });
- });
- } else {
- this.math = '';
- this.activeTab = '0';
- }
- },
- },
- methods: {
- dialogClose() {
- this.$emit('update:visible', false);
- this.$emit('close');
- },
- mathConfirm() {
- this.$emit('confirm', this.math);
- this.dialogClose();
- },
- computedMacrosText(macro) {
- if (onlyMultiMacros.includes(macro.split(' ')[0])) {
- return `\\begin{multline}\\${macro}\\end{multline}`;
- }
- if (onlyAlignMacros.includes(macro.split('{')[0])) {
- return `\\begin{align}\\${macro}\\end{align}`;
- }
- if (commonMacros.includes(macro)) {
- return macro;
- }
- return `$\\${macro}$`;
- },
- /**
- * 插入宏到公式中
- * @param {string} macro - 宏字符串
- */
- insertMacro(macro) {
- let _macro = macro.trim();
- let math = this.math || '';
- // 去除首尾空白
- math = math.trim();
- // 如果宏是多行公式
- if (onlyMultiMacros.includes(_macro.split(' ')[0])) {
- _macro = `begin{multline}\\${_macro}\\end{multline}`;
- }
- if (onlyAlignMacros.includes(_macro.split('{')[0])) {
- _macro = `begin{align}\\${_macro}\\end{align}`;
- }
- // 判断头部和尾部是否有$
- let hasHead = math.startsWith('$');
- let hasTail = math.endsWith('$');
- if (!hasHead) math = `$${math}`;
- if (!hasTail) math += '$';
- // 将宏插入到末尾$前
- if (commonMacros.includes(_macro)) {
- math = math.replace(/\$$/, ` ${_macro}$`);
- } else {
- math = math.replace(/\$$/, ` \\${_macro}$`);
- }
- this.math = math;
- this.renderMathDialog();
- },
- async renderMathDialog() {
- this.dialogMathValidate = false;
- await this.$nextTick();
- try {
- await window.MathJax.typesetPromise([this.$refs.mathContainer]);
- let mathRes = this.$refs.mathContainer.innerHTML;
- if (mathRes && mathRes.indexOf('merror') === -1) this.dialogMathValidate = true;
- } catch (err) {
- console.error('公式渲染失败:', err);
- }
- },
- },
- };
- </script>
- <style lang="scss" scoped>
- .el-dialog {
- :deep &__body {
- display: flex;
- flex-direction: column;
- row-gap: 12px;
- .math-macros {
- display: flex;
- flex-wrap: wrap;
- gap: 8px 12px;
- align-items: center;
- max-height: 300px;
- overflow: auto;
- .macros-item {
- padding: 4px;
- cursor: pointer;
- border: $border;
- border-radius: 4px;
- :deep .MathJax {
- font-size: 24px !important;
- }
- }
- }
- .formula-render {
- min-height: 50px;
- padding: 15px;
- margin-top: 8px;
- background: #f8f9fa;
- border: 1px solid #e9ecef;
- border-radius: 4px;
- }
- }
- }
- </style>
|