'commit'
This commit is contained in:
@@ -12,6 +12,7 @@ createApp({
|
||||
window.addEventListener('resize', () => {
|
||||
isMobile.value = window.innerWidth <= 768;
|
||||
if (chartInstance) chartInstance.resize();
|
||||
if (trendChartInstance) trendChartInstance.resize();
|
||||
});
|
||||
|
||||
// ==========================================
|
||||
@@ -35,7 +36,9 @@ createApp({
|
||||
const priceTableRows = ref([]);
|
||||
const hourlyPricesByOperator = ref({});
|
||||
let chartInstance = null;
|
||||
let trendChartInstance = null;
|
||||
const chartType = ref('line');
|
||||
const trendDays = ref(7);
|
||||
|
||||
// ECharts Initialization
|
||||
const initChart = () => {
|
||||
@@ -49,6 +52,17 @@ createApp({
|
||||
}
|
||||
};
|
||||
|
||||
const initTrendChart = () => {
|
||||
const dom = document.getElementById("trendChart");
|
||||
if (dom && !trendChartInstance) {
|
||||
if (typeof echarts === 'undefined') {
|
||||
console.error("ECharts not loaded");
|
||||
return;
|
||||
}
|
||||
trendChartInstance = echarts.init(dom);
|
||||
}
|
||||
};
|
||||
|
||||
const renderChart = () => {
|
||||
if (!chartInstance) return;
|
||||
|
||||
@@ -152,6 +166,65 @@ createApp({
|
||||
}
|
||||
};
|
||||
|
||||
const loadTrendData = async () => {
|
||||
try {
|
||||
const res = await axios.get(apiBase.value + "/api/operators/price-trends?days=" + trendDays.value);
|
||||
if (res && res.data) {
|
||||
renderTrendChart(res.data);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Failed to load trend data:", e);
|
||||
}
|
||||
};
|
||||
|
||||
const renderTrendChart = (data) => {
|
||||
if (!trendChartInstance) initTrendChart();
|
||||
if (!trendChartInstance) return;
|
||||
|
||||
const option = {
|
||||
backgroundColor: 'transparent',
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
backgroundColor: 'rgba(30, 41, 59, 0.9)',
|
||||
borderColor: '#334155',
|
||||
textStyle: { color: '#f1f5f9' }
|
||||
},
|
||||
legend: {
|
||||
data: data.series.map(s => s.name),
|
||||
textStyle: { color: "#94a3b8" },
|
||||
top: 10
|
||||
},
|
||||
grid: { left: 50, right: 30, top: 60, bottom: 40 },
|
||||
xAxis: {
|
||||
type: "category",
|
||||
data: data.dates.map(d => d.split('-').slice(1).join('/')), // Show MM/DD
|
||||
axisLine: { lineStyle: { color: "#475569" } },
|
||||
axisLabel: { color: "#94a3b8" }
|
||||
},
|
||||
yAxis: {
|
||||
type: "value",
|
||||
name: "元/度",
|
||||
nameTextStyle: { color: "#94a3b8" },
|
||||
axisLine: { lineStyle: { color: "#475569" } },
|
||||
axisLabel: { color: "#94a3b8" },
|
||||
splitLine: { lineStyle: { color: "#334155", type: 'dashed' } },
|
||||
min: (value) => (value.min * 0.95).toFixed(2),
|
||||
max: (value) => (value.max * 1.05).toFixed(2)
|
||||
},
|
||||
series: data.series.map(s => ({
|
||||
name: s.name,
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
symbol: 'circle',
|
||||
symbolSize: 6,
|
||||
data: s.data,
|
||||
emphasis: { focus: 'series' }
|
||||
}))
|
||||
};
|
||||
|
||||
trendChartInstance.setOption(option, true);
|
||||
};
|
||||
|
||||
const exportAllPrices = async () => {
|
||||
try{
|
||||
exporting.value = true;
|
||||
@@ -244,48 +317,102 @@ createApp({
|
||||
return '#f1f5f9'; // Slate-100
|
||||
};
|
||||
|
||||
// 内置简易 Markdown 解析器
|
||||
// Configure Marked
|
||||
if (typeof marked !== 'undefined') {
|
||||
marked.use({
|
||||
gfm: true,
|
||||
breaks: true
|
||||
});
|
||||
}
|
||||
|
||||
// 降级用的简易 Markdown 解析器
|
||||
const simpleMarkdown = (text) => {
|
||||
if (!text) return '';
|
||||
let lines = text.split('\n');
|
||||
let html = '';
|
||||
let inList = false;
|
||||
|
||||
const parseInline = (str) => {
|
||||
return str
|
||||
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
|
||||
.replace(/`(.*?)`/g, '<code style="background:#f1f5f9; padding:2px 4px; border-radius:4px; color:#334155;">$1</code>');
|
||||
.replace(/`(.*?)`/g, '<code style="background:rgba(148, 163, 184, 0.1); padding:2px 4px; border-radius:4px;">$1</code>');
|
||||
};
|
||||
|
||||
for (let line of lines) {
|
||||
let trimmed = line.trim();
|
||||
if (!trimmed) continue;
|
||||
|
||||
if (!trimmed) {
|
||||
if (inList) { html += '</ul>'; inList = false; }
|
||||
html += '<br>';
|
||||
continue;
|
||||
}
|
||||
if (trimmed.startsWith('### ')) {
|
||||
if (inList) { html += '</ul>'; inList = false; }
|
||||
html += `<h3>${parseInline(trimmed.substring(4))}</h3>`;
|
||||
}
|
||||
else if (trimmed.startsWith('- ') || /^\d+\./.test(trimmed)) {
|
||||
} else if (trimmed.startsWith('- ') || /^\d+\./.test(trimmed)) {
|
||||
if (!inList) { html += '<ul>'; inList = true; }
|
||||
let content = trimmed.replace(/^(- |\d+\. )/, '');
|
||||
html += `<li>${parseInline(content)}</li>`;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (inList) { html += '</ul>'; inList = false; }
|
||||
html += `<p style="margin-bottom:8px;">${parseInline(trimmed)}</p>`;
|
||||
html += `<p>${parseInline(trimmed)}</p>`;
|
||||
}
|
||||
}
|
||||
if (inList) html += '</ul>';
|
||||
return html;
|
||||
};
|
||||
|
||||
// 增强的 Markdown & LaTeX 解析器
|
||||
const renderMarkdownAndLatex = (text) => {
|
||||
if (!text) return '';
|
||||
|
||||
try {
|
||||
// 1. 处理 LaTeX (简单替换,先处理 $$ 再处理 $)
|
||||
let processedText = text;
|
||||
|
||||
// 处理块级 LaTeX: $$ ... $$
|
||||
processedText = processedText.replace(/\$\$\s*([\s\S]*?)\s*\$\$/g, (match, formula) => {
|
||||
try {
|
||||
if (typeof katex !== 'undefined') {
|
||||
return '<div class="katex-block">' + katex.renderToString(formula, { displayMode: true, throwOnError: false }) + '</div>';
|
||||
}
|
||||
return match;
|
||||
} catch (e) {
|
||||
return match;
|
||||
}
|
||||
});
|
||||
|
||||
// 处理行内 LaTeX: $ ... $
|
||||
processedText = processedText.replace(/\$([^\$\n]+?)\$/g, (match, formula) => {
|
||||
try {
|
||||
if (typeof katex !== 'undefined') {
|
||||
return katex.renderToString(formula, { displayMode: false, throwOnError: false });
|
||||
}
|
||||
return match;
|
||||
} catch (e) {
|
||||
return match;
|
||||
}
|
||||
});
|
||||
|
||||
// 2. 使用 marked 解析 Markdown
|
||||
if (typeof marked !== 'undefined') {
|
||||
return marked.parse(processedText);
|
||||
} else {
|
||||
// 降级使用之前的 simpleMarkdown
|
||||
return simpleMarkdown(processedText);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Markdown/LaTeX rendering error:', e);
|
||||
return text;
|
||||
}
|
||||
};
|
||||
|
||||
const renderedAiText = computed(() => {
|
||||
return simpleMarkdown(aiText.value);
|
||||
return renderMarkdownAndLatex(aiText.value);
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
initChart();
|
||||
initTrendChart();
|
||||
loadAllOperatorsPrices();
|
||||
loadTrendData();
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -299,9 +426,11 @@ createApp({
|
||||
priceTableRows,
|
||||
hourlyPricesByOperator,
|
||||
chartType,
|
||||
trendDays,
|
||||
|
||||
// Actions
|
||||
loadAllOperatorsPrices,
|
||||
loadTrendData,
|
||||
exportAllPrices,
|
||||
exportAiReport,
|
||||
startAiAnalysis,
|
||||
|
||||
@@ -15,53 +15,96 @@ createApp({
|
||||
const summaryLoading = ref(false);
|
||||
const summaryText = ref('');
|
||||
|
||||
// Simple Markdown Parser (Zero Dependency)
|
||||
// 降级用的简易 Markdown 解析器
|
||||
const simpleMarkdown = (text) => {
|
||||
if (!text) return '';
|
||||
let lines = text.split('\n');
|
||||
let html = '';
|
||||
let inList = false;
|
||||
|
||||
// Helper: Parse inline styles
|
||||
const parseInline = (str) => {
|
||||
return str
|
||||
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>') // Bold
|
||||
.replace(/`(.*?)`/g, '<code style="background:#f1f5f9; padding:2px 4px; border-radius:4px;">$1</code>'); // Code
|
||||
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
|
||||
.replace(/`(.*?)`/g, '<code style="background:rgba(148, 163, 184, 0.1); padding:2px 4px; border-radius:4px;">$1</code>');
|
||||
};
|
||||
|
||||
for (let line of lines) {
|
||||
let trimmed = line.trim();
|
||||
if (!trimmed) continue;
|
||||
|
||||
// Headers
|
||||
if (!trimmed) {
|
||||
if (inList) { html += '</ul>'; inList = false; }
|
||||
html += '<br>';
|
||||
continue;
|
||||
}
|
||||
if (trimmed.startsWith('### ')) {
|
||||
if (inList) { html += '</ul>'; inList = false; }
|
||||
html += `<h3 style="margin-top:16px; margin-bottom:8px; font-weight:bold; font-size:1.1em;">${parseInline(trimmed.substring(4))}</h3>`;
|
||||
}
|
||||
// Lists
|
||||
else if (trimmed.startsWith('- ') || /^\d+\./.test(trimmed)) {
|
||||
if (!inList) { html += '<ul style="padding-left:20px; margin:0;">'; inList = true; }
|
||||
html += `<h3>${parseInline(trimmed.substring(4))}</h3>`;
|
||||
} else if (trimmed.startsWith('- ') || /^\d+\./.test(trimmed)) {
|
||||
if (!inList) { html += '<ul>'; inList = true; }
|
||||
let content = trimmed.replace(/^(- |\d+\. )/, '');
|
||||
html += `<li style="margin-bottom:4px;">${parseInline(content)}</li>`;
|
||||
}
|
||||
// Paragraphs
|
||||
else {
|
||||
html += `<li>${parseInline(content)}</li>`;
|
||||
} else {
|
||||
if (inList) { html += '</ul>'; inList = false; }
|
||||
html += `<p style="margin-bottom:8px;">${parseInline(trimmed)}</p>`;
|
||||
html += `<p>${parseInline(trimmed)}</p>`;
|
||||
}
|
||||
}
|
||||
if (inList) html += '</ul>';
|
||||
return html;
|
||||
};
|
||||
|
||||
// Configure Marked
|
||||
if (typeof marked !== 'undefined') {
|
||||
marked.use({
|
||||
gfm: true,
|
||||
breaks: true
|
||||
});
|
||||
}
|
||||
|
||||
// 增强的 Markdown & LaTeX 解析器
|
||||
const renderMarkdownAndLatex = (text) => {
|
||||
if (!text) return '';
|
||||
|
||||
try {
|
||||
// 1. 处理 LaTeX (简单替换,先处理 $$ 再处理 $)
|
||||
let processedText = text;
|
||||
|
||||
// 处理块级 LaTeX: $$ ... $$
|
||||
processedText = processedText.replace(/\$\$\s*([\s\S]*?)\s*\$\$/g, (match, formula) => {
|
||||
try {
|
||||
if (typeof katex !== 'undefined') {
|
||||
return '<div class="katex-block">' + katex.renderToString(formula, { displayMode: true, throwOnError: false }) + '</div>';
|
||||
}
|
||||
return match;
|
||||
} catch (e) {
|
||||
return match;
|
||||
}
|
||||
});
|
||||
|
||||
// 处理行内 LaTeX: $ ... $
|
||||
processedText = processedText.replace(/\$([^\$\n]+?)\$/g, (match, formula) => {
|
||||
try {
|
||||
if (typeof katex !== 'undefined') {
|
||||
return katex.renderToString(formula, { displayMode: false, throwOnError: false });
|
||||
}
|
||||
return match;
|
||||
} catch (e) {
|
||||
return match;
|
||||
}
|
||||
});
|
||||
|
||||
// 2. 使用 marked 解析 Markdown
|
||||
if (typeof marked !== 'undefined') {
|
||||
return marked.parse(processedText);
|
||||
} else {
|
||||
// 降级使用之前的 simpleMarkdown
|
||||
return simpleMarkdown(processedText);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Markdown/LaTeX rendering error:', e);
|
||||
return text;
|
||||
}
|
||||
};
|
||||
|
||||
const renderedSummary = computed(() => {
|
||||
if (!summaryText.value) return '';
|
||||
try {
|
||||
return simpleMarkdown(summaryText.value);
|
||||
} catch (e) {
|
||||
console.error("Simple markdown error:", e);
|
||||
return summaryText.value;
|
||||
}
|
||||
return renderMarkdownAndLatex(summaryText.value);
|
||||
});
|
||||
|
||||
// Methods
|
||||
|
||||
144
static/js/haibao.js
Normal file
144
static/js/haibao.js
Normal file
@@ -0,0 +1,144 @@
|
||||
const { createApp, ref, onMounted } = Vue;
|
||||
|
||||
const app = createApp({
|
||||
setup() {
|
||||
const prompt = ref('');
|
||||
const generating = ref(false);
|
||||
const refining = ref(false);
|
||||
const currentImage = ref(null);
|
||||
const historyList = ref([]);
|
||||
const presets = ['清明节', '春节', '国庆十一', '端午节', '中秋节', '绿色出行', '低碳生活', '未来科技充电站'];
|
||||
|
||||
// Load history
|
||||
const loadHistory = async () => {
|
||||
try {
|
||||
const res = await axios.get('/haibao/history');
|
||||
historyList.value = res.data;
|
||||
// If history exists, show the latest one as current
|
||||
if (historyList.value.length > 0 && !currentImage.value) {
|
||||
currentImage.value = historyList.value[0];
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to load history', e);
|
||||
ElementPlus.ElMessage.error('加载历史记录失败');
|
||||
}
|
||||
};
|
||||
|
||||
// Refine Prompt
|
||||
const handleRefine = async () => {
|
||||
if (!prompt.value.trim()) {
|
||||
ElementPlus.ElMessage.warning('请先输入一些关键词');
|
||||
return;
|
||||
}
|
||||
|
||||
refining.value = true;
|
||||
const originalPrompt = prompt.value;
|
||||
let isFirstChunk = true;
|
||||
|
||||
try {
|
||||
const response = await fetch('/haibao/refine', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ prompt: originalPrompt })
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const reader = response.body.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
|
||||
while (true) {
|
||||
const { value, done } = await reader.read();
|
||||
if (done) break;
|
||||
|
||||
const text = decoder.decode(value, { stream: true });
|
||||
|
||||
if (isFirstChunk) {
|
||||
prompt.value = '';
|
||||
isFirstChunk = false;
|
||||
}
|
||||
prompt.value += text;
|
||||
}
|
||||
|
||||
ElementPlus.ElMessage.success('创意扩写完成');
|
||||
} catch (e) {
|
||||
console.error('Refine failed', e);
|
||||
ElementPlus.ElMessage.error('扩写失败: ' + e.message);
|
||||
} finally {
|
||||
refining.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// Generate
|
||||
const handleGenerate = async () => {
|
||||
if (!prompt.value.trim()) {
|
||||
ElementPlus.ElMessage.warning('请输入提示词');
|
||||
return;
|
||||
}
|
||||
|
||||
generating.value = true;
|
||||
try {
|
||||
const res = await axios.post('/haibao/generate', {
|
||||
prompt: prompt.value
|
||||
});
|
||||
|
||||
currentImage.value = res.data;
|
||||
ElementPlus.ElMessage.success('生成成功');
|
||||
// Insert new item to history locally to avoid delay
|
||||
historyList.value.unshift(res.data);
|
||||
} catch (e) {
|
||||
console.error('Generation failed', e);
|
||||
ElementPlus.ElMessage.error('生成失败: ' + (e.response?.data?.detail || e.message));
|
||||
} finally {
|
||||
generating.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// Use preset
|
||||
const usePreset = (text) => {
|
||||
prompt.value = text;
|
||||
};
|
||||
|
||||
// View history item
|
||||
const viewHistory = (item) => {
|
||||
currentImage.value = item;
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
};
|
||||
|
||||
// Copy Scheme
|
||||
const copyScheme = async () => {
|
||||
if (!currentImage.value || !currentImage.value.scheme_content) return;
|
||||
try {
|
||||
await navigator.clipboard.writeText(currentImage.value.scheme_content);
|
||||
ElementPlus.ElMessage.success('文案已复制到剪贴板');
|
||||
} catch (err) {
|
||||
console.error('Failed to copy text: ', err);
|
||||
ElementPlus.ElMessage.error('复制失败,请手动复制');
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
loadHistory();
|
||||
});
|
||||
|
||||
return {
|
||||
prompt,
|
||||
generating,
|
||||
currentImage,
|
||||
historyList,
|
||||
presets,
|
||||
handleGenerate,
|
||||
handleRefine,
|
||||
usePreset,
|
||||
viewHistory,
|
||||
copyScheme
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
app.use(ElementPlus);
|
||||
app.mount('#app');
|
||||
@@ -168,34 +168,104 @@ createApp({
|
||||
|
||||
// Configure Marked
|
||||
if (typeof marked !== 'undefined') {
|
||||
marked.use({
|
||||
gfm: true,
|
||||
breaks: true,
|
||||
renderer: {
|
||||
code(code, language) {
|
||||
if (language === 'echarts') {
|
||||
const id = 'chart-' + Math.random().toString(36).substr(2, 9);
|
||||
return `<div class="echarts-container" id="${id}" style="width: 100%; height: 400px; margin: 20px 0; background: rgba(30, 41, 59, 0.5); border: 1px solid rgba(148, 163, 184, 0.1); border-radius: 12px; padding: 20px;" data-config="${encodeURIComponent(code)}"></div>`;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
const renderer = new marked.Renderer();
|
||||
const oldCode = renderer.code.bind(renderer);
|
||||
renderer.code = function(code, language) {
|
||||
if (language === 'echarts') {
|
||||
const id = 'chart-' + Math.random().toString(36).substr(2, 9);
|
||||
return `<div class="echarts-container" id="${id}" style="width: 100%; height: 400px; margin: 20px 0; background: rgba(30, 41, 59, 0.5); border: 1px solid rgba(148, 163, 184, 0.1); border-radius: 12px; padding: 20px;" data-config="${encodeURIComponent(code)}"></div>`;
|
||||
}
|
||||
return oldCode(code, language);
|
||||
};
|
||||
marked.setOptions({
|
||||
renderer: renderer,
|
||||
gfm: true,
|
||||
breaks: true
|
||||
});
|
||||
}
|
||||
|
||||
const renderedResult = computed(() => {
|
||||
if (!queryResult.value) return '';
|
||||
try {
|
||||
// Remove escapes that might break markdown
|
||||
const cleanText = queryResult.value.replace(/\\([\*_`#\[\]\(\)!>-])/g, '$1');
|
||||
if (typeof marked !== 'undefined') {
|
||||
return marked.parse(cleanText);
|
||||
// 降级用的简易 Markdown 解析器
|
||||
const simpleMarkdown = (text) => {
|
||||
if (!text) return '';
|
||||
let lines = text.split('\n');
|
||||
let html = '';
|
||||
let inList = false;
|
||||
const parseInline = (str) => {
|
||||
return str
|
||||
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
|
||||
.replace(/`(.*?)`/g, '<code style="background:rgba(148, 163, 184, 0.1); padding:2px 4px; border-radius:4px;">$1</code>');
|
||||
};
|
||||
for (let line of lines) {
|
||||
let trimmed = line.trim();
|
||||
if (!trimmed) {
|
||||
if (inList) { html += '</ul>'; inList = false; }
|
||||
html += '<br>';
|
||||
continue;
|
||||
}
|
||||
if (trimmed.startsWith('### ')) {
|
||||
if (inList) { html += '</ul>'; inList = false; }
|
||||
html += `<h3>${parseInline(trimmed.substring(4))}</h3>`;
|
||||
} else if (trimmed.startsWith('- ') || /^\d+\./.test(trimmed)) {
|
||||
if (!inList) { html += '<ul>'; inList = true; }
|
||||
let content = trimmed.replace(/^(- |\d+\. )/, '');
|
||||
html += `<li>${parseInline(content)}</li>`;
|
||||
} else {
|
||||
if (inList) { html += '</ul>'; inList = false; }
|
||||
html += `<p>${parseInline(trimmed)}</p>`;
|
||||
}
|
||||
return cleanText;
|
||||
} catch (e) {
|
||||
console.error('Markdown parsing error:', e);
|
||||
return queryResult.value;
|
||||
}
|
||||
if (inList) html += '</ul>';
|
||||
return html;
|
||||
};
|
||||
|
||||
// 增强的 Markdown & LaTeX 解析器
|
||||
const renderMarkdownAndLatex = (text) => {
|
||||
if (!text) return '';
|
||||
|
||||
try {
|
||||
// 1. 处理 LaTeX (简单替换,先处理 $$ 再处理 $)
|
||||
let processedText = text;
|
||||
|
||||
// 处理块级 LaTeX: $$ ... $$
|
||||
processedText = processedText.replace(/\$\$\s*([\s\S]*?)\s*\$\$/g, (match, formula) => {
|
||||
try {
|
||||
if (typeof katex !== 'undefined') {
|
||||
return '<div class="katex-block">' + katex.renderToString(formula, { displayMode: true, throwOnError: false }) + '</div>';
|
||||
}
|
||||
return match;
|
||||
} catch (e) {
|
||||
return match;
|
||||
}
|
||||
});
|
||||
|
||||
// 处理行内 LaTeX: $ ... $
|
||||
processedText = processedText.replace(/\$([^\$\n]+?)\$/g, (match, formula) => {
|
||||
try {
|
||||
if (typeof katex !== 'undefined') {
|
||||
return katex.renderToString(formula, { displayMode: false, throwOnError: false });
|
||||
}
|
||||
return match;
|
||||
} catch (e) {
|
||||
return match;
|
||||
}
|
||||
});
|
||||
|
||||
// 2. 使用 marked 解析 Markdown
|
||||
if (typeof marked !== 'undefined') {
|
||||
// 直接解析处理后的文本,marked 会处理 Markdown 转义
|
||||
return marked.parse(processedText);
|
||||
} else {
|
||||
// 降级使用之前的 simpleMarkdown
|
||||
return simpleMarkdown(processedText);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Markdown/LaTeX rendering error:', e);
|
||||
return text;
|
||||
}
|
||||
};
|
||||
|
||||
const renderedResult = computed(() => {
|
||||
return renderMarkdownAndLatex(queryResult.value);
|
||||
});
|
||||
|
||||
watch(queryResult, () => {
|
||||
|
||||
Reference in New Issue
Block a user