fix: 修复对照检查页面多项问题

1. 修复「导入范式要求」按钮不显示 - activeParadigm 是对象而非 ID
2. 左右两侧支持多选段落 - 点击切换选中状态
3. 中间指示器显示选中段落数量
4. 多选段落合并后一起发送给 AI 分析
This commit is contained in:
empty
2026-01-08 16:14:53 +08:00
parent f5c66e1712
commit 05664047e4

View File

@@ -55,13 +55,16 @@
@click="selectLeftParagraph(idx)"
:class="[
'p-3 rounded-lg border cursor-pointer transition-all',
selectedLeftIdx === idx
selectedLeftIdxs.includes(idx)
? 'bg-amber-900/30 border-amber-500 ring-2 ring-amber-500/30'
: 'bg-slate-800/50 border-slate-700 hover:border-amber-500/50'
]"
>
<div class="flex items-start gap-2">
<span class="text-xs text-amber-500/70 shrink-0 mt-0.5">{{ idx + 1 }}.</span>
<span :class="['text-xs shrink-0 mt-0.5 w-5 h-5 rounded flex items-center justify-center',
selectedLeftIdxs.includes(idx) ? 'bg-amber-500 text-white' : 'text-amber-500/70']">
{{ selectedLeftIdxs.includes(idx) ? '✓' : (idx + 1) }}
</span>
<p class="text-sm text-slate-300 whitespace-pre-wrap">{{ para }}</p>
</div>
</div>
@@ -76,16 +79,18 @@
</div>
<!-- 中间对应关系指示器 -->
<div class="w-16 flex flex-col items-center justify-center bg-slate-800/50 shrink-0">
<div v-if="selectedLeftIdx !== null && selectedRightIdx !== null" class="flex flex-col items-center gap-2">
<div class="w-20 flex flex-col items-center justify-center bg-slate-800/50 shrink-0">
<div v-if="selectedLeftIdxs.length > 0 && selectedRightIdxs.length > 0" class="flex flex-col items-center gap-2">
<div class="text-xs text-amber-400 font-medium">{{ selectedLeftIdxs.length }} </div>
<div class="w-3 h-3 rounded-full bg-amber-500"></div>
<div class="w-0.5 h-8 bg-gradient-to-b from-amber-500 to-blue-500"></div>
<span class="text-xs text-slate-500 writing-mode-vertical"></span>
<div class="w-0.5 h-8 bg-gradient-to-b from-blue-500 to-blue-500"></div>
<div class="w-0.5 h-6 bg-gradient-to-b from-amber-500 to-blue-500"></div>
<span class="text-xs text-slate-400 px-1 py-0.5 bg-slate-700 rounded"></span>
<div class="w-0.5 h-6 bg-gradient-to-b from-blue-500 to-blue-500"></div>
<div class="w-3 h-3 rounded-full bg-blue-500"></div>
<div class="text-xs text-blue-400 font-medium">{{ selectedRightIdxs.length }} </div>
</div>
<div v-else class="text-center px-2">
<span class="text-xs text-slate-600">选中<br/>两侧段落</span>
<span class="text-xs text-slate-600">点击选中<br/>多个段落</span>
</div>
</div>
@@ -110,13 +115,16 @@
@click="selectRightParagraph(idx)"
:class="[
'p-3 rounded-lg border cursor-pointer transition-all',
selectedRightIdx === idx
selectedRightIdxs.includes(idx)
? 'bg-blue-900/30 border-blue-500 ring-2 ring-blue-500/30'
: 'bg-slate-800/50 border-slate-700 hover:border-blue-500/50'
]"
>
<div class="flex items-start gap-2">
<span class="text-xs text-blue-500/70 shrink-0 mt-0.5">{{ idx + 1 }}.</span>
<span :class="['text-xs shrink-0 mt-0.5 w-5 h-5 rounded flex items-center justify-center',
selectedRightIdxs.includes(idx) ? 'bg-blue-500 text-white' : 'text-blue-500/70']">
{{ selectedRightIdxs.includes(idx) ? '✓' : (idx + 1) }}
</span>
<p class="text-sm text-slate-300 whitespace-pre-wrap">{{ para }}</p>
</div>
<!-- 检查结果标记 -->
@@ -202,7 +210,6 @@
import { ref, computed } from 'vue'
import { storeToRefs } from 'pinia'
import { useAppStore } from '../stores/app'
import { PARADIGMS } from '../config/paradigms'
const appStore = useAppStore()
const { activeParadigm } = storeToRefs(appStore)
@@ -211,32 +218,28 @@ const { activeParadigm } = storeToRefs(appStore)
const leftContent = ref('')
const rightContent = ref('')
// 选中状态
const selectedLeftIdx = ref(null)
const selectedRightIdx = ref(null)
// 选中状态(改为数组支持多选)
const selectedLeftIdxs = ref([])
const selectedRightIdxs = ref([])
// 检查状态
const isComparing = ref(false)
const lastCheckResult = ref(null)
const checkResults = ref({})
// 范式相关
// 范式相关activeParadigm 是对象,不是 ID
const hasParadigmRules = computed(() => {
if (!activeParadigm.value) return false
const paradigm = PARADIGMS[activeParadigm.value]
return paradigm && (paradigm.expertGuidelines || paradigm.systemConstraints)
const p = activeParadigm.value
return p && (p.expertGuidelines || p.systemConstraints || p.validationRules)
})
const activeParadigmName = computed(() => {
if (!activeParadigm.value) return ''
const paradigm = PARADIGMS[activeParadigm.value]
return paradigm?.name || ''
return activeParadigm.value?.name || ''
})
// 导入范式写作要求
const importParadigmRules = () => {
if (!activeParadigm.value) return
const paradigm = PARADIGMS[activeParadigm.value]
const paradigm = activeParadigm.value
if (!paradigm) return
const rules = []
@@ -282,24 +285,49 @@ const rightParagraphs = computed(() => {
.filter(p => p.length > 0)
})
// 是否可以检查
// 是否可以检查(两侧都至少选中一段)
const canCompare = computed(() => {
return selectedLeftIdx.value !== null && selectedRightIdx.value !== null
return selectedLeftIdxs.value.length > 0 && selectedRightIdxs.value.length > 0
})
// 选择段落
// 选择段落(多选切换)
const selectLeftParagraph = (idx) => {
selectedLeftIdx.value = selectedLeftIdx.value === idx ? null : idx
const i = selectedLeftIdxs.value.indexOf(idx)
if (i === -1) {
selectedLeftIdxs.value.push(idx)
} else {
selectedLeftIdxs.value.splice(i, 1)
}
}
const selectRightParagraph = (idx) => {
selectedRightIdx.value = selectedRightIdx.value === idx ? null : idx
const i = selectedRightIdxs.value.indexOf(idx)
if (i === -1) {
selectedRightIdxs.value.push(idx)
} else {
selectedRightIdxs.value.splice(i, 1)
}
}
// 获取选中的段落文本(多选合并)
const getSelectedLeftText = () => {
return selectedLeftIdxs.value
.sort((a, b) => a - b)
.map(i => leftParagraphs.value[i])
.join('\n\n')
}
const getSelectedRightText = () => {
return selectedRightIdxs.value
.sort((a, b) => a - b)
.map(i => rightParagraphs.value[i])
.join('\n\n')
}
// 清除选择
const clearSelection = () => {
selectedLeftIdx.value = null
selectedRightIdx.value = null
selectedLeftIdxs.value = []
selectedRightIdxs.value = []
lastCheckResult.value = null
}
@@ -312,8 +340,8 @@ const goBack = () => {
const runCompare = async () => {
if (!canCompare.value) return
const requirement = leftParagraphs.value[selectedLeftIdx.value]
const content = rightParagraphs.value[selectedRightIdx.value]
const requirement = getSelectedLeftText()
const content = getSelectedRightText()
isComparing.value = true
lastCheckResult.value = null
@@ -321,10 +349,10 @@ const runCompare = async () => {
try {
const prompt = `你是一个严格的写作质检专家。请对比以下"写作要求"和"写作内容",判断内容是否符合要求。
# 写作要求
# 写作要求(共 ${selectedLeftIdxs.value.length} 段)
${requirement}
# 写作内容
# 写作内容(共 ${selectedRightIdxs.value.length} 段)
${content}
# 输出要求