feat: 完善范式润色功能和相关组件
- 新增范式选择模态框 (ParadigmSelectorModal) - 新增差异标注面板 (DiffAnnotationPanel) - 新增精确差异处理工具 (preciseDiff.js) - 更新各面板组件支持范式润色功能 - 更新范式配置文件 (paradigms.js) - 更新依赖配置 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,17 +2,9 @@
|
||||
<aside class="w-[400px] flex flex-col border-r border-slate-700 bg-slate-800 shrink-0 h-screen">
|
||||
<!-- 头部 -->
|
||||
<header class="p-4 border-b border-slate-700 flex items-center justify-between shrink-0">
|
||||
<div class="flex items-center gap-4">
|
||||
<h1 class="font-bold text-lg text-white flex items-center gap-2">
|
||||
<span class="text-2xl">✍️</span> 写作范式分析
|
||||
</h1>
|
||||
<button
|
||||
@click="switchPage('writer')"
|
||||
class="text-xs px-2 py-1 rounded bg-slate-700 text-slate-300 hover:bg-slate-600 transition"
|
||||
>
|
||||
返回写作
|
||||
</button>
|
||||
</div>
|
||||
<h1 class="font-bold text-lg text-white flex items-center gap-2">
|
||||
<span class="text-2xl">🎯</span> 写作范式分析
|
||||
</h1>
|
||||
<span class="text-xs px-2 py-1 rounded bg-blue-900 text-blue-300 border border-blue-700">Pro版</span>
|
||||
</header>
|
||||
|
||||
@@ -219,159 +211,33 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 写作约束(高级) -->
|
||||
<div>
|
||||
<label class="block text-sm text-slate-400 mb-2">写作约束(每行一条)</label>
|
||||
<!-- ⭐ 核心字段:完整 Prompt -->
|
||||
<div class="border-t border-slate-700 pt-4 mt-4">
|
||||
<label class="block text-sm text-slate-400 mb-2 flex items-center gap-2">
|
||||
<span>✨</span> 完整 Prompt(核心字段)
|
||||
<span class="text-xs text-slate-500 font-normal">粘贴您的完整提示词</span>
|
||||
</label>
|
||||
<textarea
|
||||
v-model="editForm.constraintsInput"
|
||||
rows="4"
|
||||
class="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none transition resize-none font-mono"
|
||||
placeholder="如: 开篇必须明确阐述问题 结尾需总结核心要点"
|
||||
v-model="editForm.specializedPrompt"
|
||||
rows="12"
|
||||
class="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none transition resize-y font-mono leading-relaxed"
|
||||
placeholder="在此粘贴您的完整 Prompt...
|
||||
|
||||
示例:
|
||||
# Role
|
||||
你是一个具有较高政治敏感性的AI助手...
|
||||
|
||||
# 任务目标
|
||||
你需要逐一分析文章中的每一条问题...
|
||||
|
||||
# 检查步骤
|
||||
1. 检查问题表述的清晰度
|
||||
2. 深度分析思想根源
|
||||
..."
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<!-- 维度配置(新架构) -->
|
||||
<div class="border-t border-slate-700 pt-4 mt-4">
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<label class="text-sm text-slate-400 font-medium">📐 维度配置(高级)</label>
|
||||
<button
|
||||
@click="toggleDimensionEditor"
|
||||
class="text-xs text-blue-400 hover:text-blue-300"
|
||||
>
|
||||
{{ showDimensionEditor ? '收起' : '展开' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="showDimensionEditor" class="space-y-3">
|
||||
<!-- 维度集选择 -->
|
||||
<div>
|
||||
<label class="block text-xs text-slate-500 mb-1">选择维度集模板</label>
|
||||
<select
|
||||
v-model="editForm.dimensionSetId"
|
||||
@change="onDimensionSetChange"
|
||||
class="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 outline-none"
|
||||
>
|
||||
<option :value="null">不使用维度集</option>
|
||||
<option v-for="ds in dimensionSetOptions" :key="ds.id" :value="ds.id">
|
||||
{{ ds.name }} - {{ ds.description }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 维度列表编辑 -->
|
||||
<div v-if="editForm.dimensions.length > 0">
|
||||
<label class="block text-xs text-slate-500 mb-2">维度列表(可编辑)</label>
|
||||
<div class="space-y-2 max-h-60 overflow-y-auto">
|
||||
<div
|
||||
v-for="(dim, index) in editForm.dimensions"
|
||||
:key="dim.id || index"
|
||||
class="bg-slate-900/50 rounded p-2 border border-slate-700"
|
||||
>
|
||||
<div class="flex items-center gap-2 mb-1">
|
||||
<input
|
||||
v-model="dim.name"
|
||||
class="flex-1 bg-slate-800 border border-slate-600 rounded px-2 py-1 text-xs"
|
||||
placeholder="维度名称"
|
||||
/>
|
||||
<button
|
||||
@click="removeDimension(index)"
|
||||
class="text-red-400 hover:text-red-300 text-xs px-1"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
<input
|
||||
v-model="dim.focus"
|
||||
class="w-full bg-slate-800 border border-slate-600 rounded px-2 py-1 text-xs text-slate-400"
|
||||
placeholder="关注重点(如:理想信念、宗旨意识)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
@click="addDimension"
|
||||
class="mt-2 text-xs text-green-400 hover:text-green-300 flex items-center gap-1"
|
||||
>
|
||||
<span>+</span> 添加维度
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 快速添加维度 -->
|
||||
<div v-else class="text-center py-4 text-slate-500 text-xs">
|
||||
<p>选择一个维度集模板,或手动添加维度</p>
|
||||
<button
|
||||
@click="addDimension"
|
||||
class="mt-2 text-green-400 hover:text-green-300"
|
||||
>
|
||||
+ 添加自定义维度
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 素材库配置(新增) -->
|
||||
<div class="border-t border-slate-700 pt-4 mt-4">
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<label class="text-sm text-slate-400 font-medium">📚 素材库配置</label>
|
||||
<button
|
||||
@click="toggleReferenceEditor"
|
||||
class="text-xs text-blue-400 hover:text-blue-300"
|
||||
>
|
||||
{{ showReferenceEditor ? '收起' : '展开' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="showReferenceEditor" class="space-y-3">
|
||||
<!-- 自动匹配开关 -->
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-xs text-slate-500">自动匹配相关素材</span>
|
||||
<label class="relative inline-flex items-center cursor-pointer">
|
||||
<input type="checkbox" v-model="editForm.autoMatchRefs" class="sr-only peer">
|
||||
<div class="w-9 h-5 bg-slate-600 peer-focus:ring-2 peer-focus:ring-blue-500 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-blue-600"></div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- 素材类型筛选 -->
|
||||
<div>
|
||||
<label class="block text-xs text-slate-500 mb-2">手动选择素材(按类型)</label>
|
||||
<div class="flex flex-wrap gap-1 mb-2">
|
||||
<button
|
||||
v-for="type in referenceTypes"
|
||||
:key="type.id"
|
||||
@click="filterReferencesByType(type.id)"
|
||||
:class="['text-xs px-2 py-1 rounded transition',
|
||||
selectedRefType === type.id
|
||||
? 'bg-blue-600 text-white'
|
||||
: 'bg-slate-700 text-slate-300 hover:bg-slate-600']"
|
||||
>
|
||||
{{ type.icon }} {{ type.name }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 素材列表 -->
|
||||
<div class="max-h-40 overflow-y-auto space-y-1">
|
||||
<div
|
||||
v-for="ref in filteredReferences"
|
||||
:key="ref.id"
|
||||
@click="toggleReference(ref.id)"
|
||||
:class="['p-2 rounded cursor-pointer border transition text-xs',
|
||||
editForm.selectedRefs.includes(ref.id)
|
||||
? 'bg-blue-900/30 border-blue-500'
|
||||
: 'bg-slate-900/50 border-slate-700 hover:border-slate-500']"
|
||||
>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="font-medium text-white">{{ ref.title }}</span>
|
||||
<span v-if="editForm.selectedRefs.includes(ref.id)" class="text-green-400">✓</span>
|
||||
</div>
|
||||
<div class="text-slate-500 text-[10px] mt-1">{{ ref.excerptCount }} 条可引用内容</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 已选素材摘要 -->
|
||||
<div v-if="editForm.selectedRefs.length > 0" class="text-xs text-slate-400">
|
||||
已选择 {{ editForm.selectedRefs.length }} 个素材
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-xs text-slate-500 mt-2">
|
||||
💡 提示:这是 AI 调用时的核心指令。完整的 Prompt 应包含角色、目标、步骤和输出格式。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -401,17 +267,14 @@ import { storeToRefs } from 'pinia'
|
||||
import { useAppStore } from '../stores/app'
|
||||
import { useDatabaseStore } from '../stores/database.js'
|
||||
import DeepSeekAPI from '../api/deepseek.js'
|
||||
import { getParadigmList, getParadigmDimensions } from '../config/paradigms.js'
|
||||
import { getDimensionSetList, getDimensionSetById } from '../config/dimensionSets.js'
|
||||
import { getLogicParadigmList } from '../config/logicParadigms.js'
|
||||
import { REFERENCE_TYPES } from '../config/references.js'
|
||||
import { getParadigmList } from '../config/paradigms.js'
|
||||
|
||||
const appStore = useAppStore()
|
||||
const { analysisText, isAnalyzing } = storeToRefs(appStore)
|
||||
|
||||
// 数据库 Store
|
||||
const dbStore = useDatabaseStore()
|
||||
const { references: dbReferences, isInitialized: dbInitialized } = storeToRefs(dbStore)
|
||||
const { isInitialized: dbInitialized } = storeToRefs(dbStore)
|
||||
|
||||
// 选中的范式
|
||||
const selectedParadigm = ref(null)
|
||||
@@ -434,54 +297,10 @@ const editForm = reactive({
|
||||
description: '',
|
||||
tagsInput: '',
|
||||
tagClass: 'bg-blue-900/30 text-blue-300',
|
||||
constraintsInput: '',
|
||||
// 新架构:维度配置
|
||||
dimensionSetId: null,
|
||||
dimensions: [],
|
||||
// 素材库配置
|
||||
autoMatchRefs: true,
|
||||
selectedRefs: []
|
||||
// ⭐ 核心字段:完整 Prompt
|
||||
specializedPrompt: ''
|
||||
})
|
||||
|
||||
// 维度编辑器状态
|
||||
const showDimensionEditor = ref(false)
|
||||
|
||||
// 素材编辑器状态
|
||||
const showReferenceEditor = ref(false)
|
||||
const selectedRefType = ref('all')
|
||||
|
||||
// 使用数据库中的素材数据
|
||||
const allReferences = computed(() => {
|
||||
return dbReferences.value.map(ref => ({
|
||||
id: ref.id,
|
||||
type: ref.type,
|
||||
title: ref.title,
|
||||
source: ref.source,
|
||||
tags: ref.tags,
|
||||
excerptCount: ref.excerpts?.length || 0
|
||||
}))
|
||||
})
|
||||
|
||||
const filteredReferences = computed(() => {
|
||||
if (selectedRefType.value === 'all') {
|
||||
return allReferences.value
|
||||
}
|
||||
return allReferences.value.filter(ref => ref.type === selectedRefType.value)
|
||||
})
|
||||
|
||||
// 素材类型选项
|
||||
const referenceTypes = [
|
||||
{ id: 'all', name: '全部', icon: '📚' },
|
||||
{ id: REFERENCE_TYPES.POLICY, name: '政策文件', icon: '📄' },
|
||||
{ id: REFERENCE_TYPES.SPEECH, name: '领导讲话', icon: '🎙️' },
|
||||
{ id: REFERENCE_TYPES.CASE, name: '典型案例', icon: '📌' },
|
||||
{ id: REFERENCE_TYPES.QUOTE, name: '金句警句', icon: '✨' },
|
||||
{ id: REFERENCE_TYPES.REGULATION, name: '党规党纪', icon: '📖' }
|
||||
]
|
||||
|
||||
// 维度集选项
|
||||
const dimensionSetOptions = getDimensionSetList()
|
||||
|
||||
// 图标选项
|
||||
const iconOptions = ['📝', '💻', '📊', '🚀', '📚', '🏛️', '🔥', '🏢', '💡', '🎯', '📋', '✨']
|
||||
|
||||
@@ -495,6 +314,7 @@ const colorOptions = [
|
||||
{ label: '青色', class: 'bg-cyan-900/30 text-cyan-300' }
|
||||
]
|
||||
|
||||
|
||||
// 初始化范式列表
|
||||
const initParadigms = () => {
|
||||
// 先加载默认范式
|
||||
@@ -538,28 +358,13 @@ const openEditModal = (paradigm) => {
|
||||
editForm.description = paradigm.description || ''
|
||||
editForm.tagsInput = (paradigm.tags || []).join(', ')
|
||||
editForm.tagClass = paradigm.tagClass || 'bg-blue-900/30 text-blue-300'
|
||||
editForm.constraintsInput = (paradigm.systemConstraints || []).join('\n')
|
||||
// ⭐ 核心字段:加载完整 Prompt
|
||||
editForm.specializedPrompt = paradigm.specializedPrompt || ''
|
||||
|
||||
// 加载维度配置
|
||||
editForm.dimensionSetId = paradigm.dimensionSetId || null
|
||||
if (paradigm.dimensionSetId) {
|
||||
const dimSet = getDimensionSetById(paradigm.dimensionSetId)
|
||||
editForm.dimensions = dimSet ? JSON.parse(JSON.stringify(dimSet.dimensions)) : []
|
||||
} else if (paradigm.customDimensions) {
|
||||
editForm.dimensions = JSON.parse(JSON.stringify(paradigm.customDimensions))
|
||||
} else {
|
||||
editForm.dimensions = []
|
||||
}
|
||||
|
||||
// 加载素材配置
|
||||
editForm.autoMatchRefs = paradigm.autoMatchRefs !== false // 默认为true
|
||||
editForm.selectedRefs = paradigm.selectedRefs ? [...paradigm.selectedRefs] : []
|
||||
|
||||
showDimensionEditor.value = false
|
||||
showReferenceEditor.value = false
|
||||
showEditModal.value = true
|
||||
}
|
||||
|
||||
|
||||
// 关闭弹窗
|
||||
const closeEditModal = () => {
|
||||
showEditModal.value = false
|
||||
@@ -573,84 +378,15 @@ const resetEditForm = () => {
|
||||
editForm.description = ''
|
||||
editForm.tagsInput = ''
|
||||
editForm.tagClass = 'bg-blue-900/30 text-blue-300'
|
||||
editForm.constraintsInput = ''
|
||||
editForm.dimensionSetId = null
|
||||
editForm.dimensions = []
|
||||
// 素材配置重置
|
||||
editForm.autoMatchRefs = true
|
||||
editForm.selectedRefs = []
|
||||
showDimensionEditor.value = false
|
||||
showReferenceEditor.value = false
|
||||
// ⭐ 核心字段重置
|
||||
editForm.specializedPrompt = ''
|
||||
}
|
||||
|
||||
// 切换维度编辑器显示
|
||||
const toggleDimensionEditor = () => {
|
||||
showDimensionEditor.value = !showDimensionEditor.value
|
||||
}
|
||||
|
||||
// 维度集变更时更新维度列表
|
||||
const onDimensionSetChange = () => {
|
||||
if (editForm.dimensionSetId) {
|
||||
const dimSet = getDimensionSetById(editForm.dimensionSetId)
|
||||
if (dimSet) {
|
||||
// 深拷贝维度列表,允许用户编辑
|
||||
editForm.dimensions = JSON.parse(JSON.stringify(dimSet.dimensions))
|
||||
}
|
||||
} else {
|
||||
editForm.dimensions = []
|
||||
}
|
||||
}
|
||||
|
||||
// 添加自定义维度
|
||||
const addDimension = () => {
|
||||
editForm.dimensions.push({
|
||||
id: `custom-dim-${Date.now()}`,
|
||||
name: '',
|
||||
focus: ''
|
||||
})
|
||||
}
|
||||
|
||||
// 删除维度
|
||||
const removeDimension = (index) => {
|
||||
editForm.dimensions.splice(index, 1)
|
||||
}
|
||||
|
||||
// 切换素材编辑器显示
|
||||
const toggleReferenceEditor = () => {
|
||||
showReferenceEditor.value = !showReferenceEditor.value
|
||||
}
|
||||
|
||||
// 按类型筛选素材(通过修改selectedRefType触发computed重新计算)
|
||||
const filterReferencesByType = (typeId) => {
|
||||
selectedRefType.value = typeId
|
||||
}
|
||||
|
||||
// 切换素材选中状态
|
||||
const toggleReference = (refId) => {
|
||||
const index = editForm.selectedRefs.indexOf(refId)
|
||||
if (index === -1) {
|
||||
editForm.selectedRefs.push(refId)
|
||||
} else {
|
||||
editForm.selectedRefs.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
// 保存范式
|
||||
const saveParadigm = () => {
|
||||
const tags = editForm.tagsInput.split(',').map(t => t.trim()).filter(t => t)
|
||||
const constraints = editForm.constraintsInput.split('\n').map(c => c.trim()).filter(c => c)
|
||||
|
||||
// 处理维度配置
|
||||
const dimensionConfig = {
|
||||
dimensionSetId: editForm.dimensionSetId,
|
||||
customDimensions: editForm.dimensions.length > 0 ? editForm.dimensions : null
|
||||
}
|
||||
|
||||
// 处理素材配置
|
||||
const referenceConfig = {
|
||||
autoMatchRefs: editForm.autoMatchRefs,
|
||||
selectedRefs: editForm.selectedRefs
|
||||
}
|
||||
|
||||
if (isAddMode.value) {
|
||||
// 新增自定义范式
|
||||
@@ -658,20 +394,12 @@ const saveParadigm = () => {
|
||||
id: `custom-${Date.now()}`,
|
||||
icon: editForm.icon,
|
||||
name: editForm.name,
|
||||
description: editForm.description,
|
||||
description: editForm.description || editForm.specializedPrompt.substring(0, 100) + '...',
|
||||
tags,
|
||||
tagClass: editForm.tagClass,
|
||||
systemConstraints: constraints,
|
||||
isCustom: true,
|
||||
// 新架构:维度配置
|
||||
...dimensionConfig,
|
||||
// 素材配置
|
||||
...referenceConfig,
|
||||
logicParadigms: {
|
||||
problemSection: 'progressive-problem',
|
||||
analysisSection: 'deep-attribution',
|
||||
remediationSection: 'remediation'
|
||||
}
|
||||
// ⭐ 核心字段:完整 Prompt
|
||||
specializedPrompt: editForm.specializedPrompt
|
||||
}
|
||||
|
||||
paradigms.value.push(newParadigm)
|
||||
@@ -692,11 +420,8 @@ const saveParadigm = () => {
|
||||
description: editForm.description,
|
||||
tags,
|
||||
tagClass: editForm.tagClass,
|
||||
systemConstraints: constraints,
|
||||
// 新架构:维度配置
|
||||
...dimensionConfig,
|
||||
// 素材配置
|
||||
...referenceConfig
|
||||
// ⭐ 核心字段:完整 Prompt
|
||||
specializedPrompt: editForm.specializedPrompt
|
||||
}
|
||||
|
||||
paradigms.value[index] = updatedParadigm
|
||||
@@ -721,11 +446,7 @@ const saveParadigm = () => {
|
||||
description: editForm.description,
|
||||
tags,
|
||||
tagClass: editForm.tagClass,
|
||||
systemConstraints: constraints,
|
||||
// 新架构:维度配置
|
||||
...dimensionConfig,
|
||||
// 素材配置
|
||||
...referenceConfig
|
||||
specializedPrompt: editForm.specializedPrompt
|
||||
}
|
||||
localStorage.setItem('paradigmCustomizations', JSON.stringify(customizations))
|
||||
}
|
||||
@@ -735,6 +456,7 @@ const saveParadigm = () => {
|
||||
closeEditModal()
|
||||
}
|
||||
|
||||
|
||||
// 删除自定义范式
|
||||
const deleteParadigm = (paradigm) => {
|
||||
if (!paradigm.isCustom) return
|
||||
|
||||
Reference in New Issue
Block a user