数据结构优化

This commit is contained in:
李琦
2026-01-20 19:59:50 +08:00
parent cf8b89f731
commit ec4f5a9856
6 changed files with 216 additions and 105 deletions

View File

@@ -381,8 +381,8 @@ md.renderer.rules.fence = function (tokens, idx) {
const lines = token.content.trimEnd().split('\n')
const lineNumbers = lines.map((_, i) => i + 1).join('\n')
// SVG Icon 手动嵌入,不使用 Icon 组件
const copyIconSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>`
// 修复1: 显式定义的 SVG Icon颜色更亮 (text-white/70),去除复杂 opacity 类
const copyIconSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: block;"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>`
return `
<div class="ios-code-container my-6 md:my-10 rounded-lg md:rounded-xl overflow-hidden shadow-2xl bg-[#1e1e1e] border border-white/5 relative group/code text-sm">
@@ -396,10 +396,10 @@ md.renderer.rules.fence = function (tokens, idx) {
<div class="text-[10px] md:text-xs text-white/30 font-mono select-none uppercase tracking-wider">${langName || 'TEXT'}</div>
</div>
<!-- 修复: 在移动端始终显示(opacity-100),桌面端 Hover 显示 -->
<button class="copy-btn flex items-center gap-1.5 px-2 py-1 rounded hover:bg-white/10 transition-all cursor-pointer opacity-100 md:opacity-0 md:group-hover/code:opacity-100" aria-label="Copy code">
<span class="text-white/40">${copyIconSvg}</span>
<span class="text-[10px] md:text-xs text-white/40 font-medium">复制</span>
<!-- 修复2: 复制按钮始终可见,增加点击热区,颜色加深 -->
<button class="copy-btn flex items-center gap-1.5 px-2 py-1 rounded hover:bg-white/10 transition-all cursor-pointer opacity-100" aria-label="Copy code">
<span class="text-white/70">${copyIconSvg}</span>
<span class="text-[10px] md:text-xs text-white/70 font-medium">复制</span>
</button>
</div>
@@ -408,9 +408,9 @@ md.renderer.rules.fence = function (tokens, idx) {
<pre class="font-mono text-xs md:text-sm leading-relaxed" style="margin:0;">${lineNumbers}</pre>
</div>
<!-- 修复: 添加 whitespace-pre 到 code 标签,确保不换行 -->
<div class="code-block-wrapper flex-1 overflow-x-auto py-3 md:py-4 px-3 md:px-4 bg-[#1e1e1e] min-w-0 w-full">
<pre class="hljs !bg-transparent !m-0 !p-0 !rounded-none !overflow-visible"><code class="!font-mono text-xs md:text-sm leading-relaxed block !whitespace-pre">${highlighted}</code></pre>
<!-- 修复3: 强制添加 style="white-space: pre; overflow-x: auto" 确保滑动 -->
<div class="code-block-wrapper flex-1 py-3 md:py-4 px-3 md:px-4 bg-[#1e1e1e] min-w-0 w-full" style="overflow-x: auto; -webkit-overflow-scrolling: touch;">
<pre class="hljs !bg-transparent !m-0 !p-0 !rounded-none !overflow-visible"><code class="!font-mono text-xs md:text-sm leading-relaxed block" style="white-space: pre;">${highlighted}</code></pre>
</div>
</div>
</div>
@@ -506,7 +506,7 @@ const addCopyListeners = () => {
const text = codeElement.innerText
await navigator.clipboard.writeText(text)
const originalContent = newBtn.innerHTML
const checkIconSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-green-400"><polyline points="20 6 9 17 4 12"/></svg>`
const checkIconSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-green-400" style="display: block;"><polyline points="20 6 9 17 4 12"/></svg>`
newBtn.innerHTML = `<span>${checkIconSvg}</span><span class="text-green-400 text-[10px] md:text-xs font-medium">已复制</span>`
setTimeout(() => {
newBtn.innerHTML = originalContent
@@ -603,24 +603,22 @@ onBeforeUnmount(() => {
border-radius: 0 !important;
box-shadow: none !important;
border: none !important;
white-space: pre !important; /* 关键:强制不自动换行 */
/* 确保这里也强制 pre */
white-space: pre !important;
}
:deep(.prose code) {
font-family: 'SF Mono', Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
white-space: pre !important; /* 关键:强制不自动换行 */
}
/* 覆盖 highlight.js 或其他样式可能带来的换行 */
:deep(.code-block-wrapper pre code) {
white-space: pre !important;
word-wrap: normal !important;
overflow-wrap: normal !important;
}
/* 允许容器横向滚动 */
:deep(.code-block-wrapper) {
-webkit-overflow-scrolling: touch; /* iOS 惯性滚动 */
-webkit-overflow-scrolling: touch;
}
:deep(.prose :not(pre) > code) {
@@ -629,7 +627,8 @@ onBeforeUnmount(() => {
padding: 0.2em 0.4em;
border-radius: 0.3em;
font-weight: 500;
word-break: break-word; /* 内联代码允许换行,防止撑开 */
/* 内联代码依然需要换行 */
word-break: break-word;
}
:deep(.prose h1), :deep(.prose h2), :deep(.prose h3) {

View File

@@ -299,14 +299,6 @@ const uvTrendOption = computed(() => ({
}]
}))
// 所有省份列表(用于设置默认值)
const allProvinces = [
'北京', '天津', '河北', '山西', '内蒙古', '辽宁', '吉林', '黑龙江',
'上海', '江苏', '浙江', '安徽', '福建', '江西', '山东', '河南',
'湖北', '湖南', '广东', '广西', '海南', '重庆', '四川', '贵州',
'云南', '西藏', '陕西', '甘肃', '青海', '宁夏', '新疆', '台湾', '香港', '澳门'
]
// 所有省份完整名称列表(用于匹配地图数据)
const allProvincesFullNames = [
'北京市', '天津市', '河北省', '山西省', '内蒙古自治区', '辽宁省', '吉林省', '黑龙江省',