Files
ai-write/src/components/DocumentSelectorModal.vue
empty b063afb2a1 refactor: 完成全局 emoji 到 SVG 图标迁移
- IconLibrary 新增 6 个图标: star, lightbulb, pin, clipboard, microphone, bookmark
- 迁移 12 个组件中的 emoji 为 IconLibrary 组件
- 更新 paradigms.js 中的 icon 字段为图标名称
- 修复深度模式开关点击无效的问题 (改用 Vue 动态类绑定)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 03:25:08 +08:00

161 lines
5.1 KiB
Vue

<template>
<div v-if="visible" class="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
<div class="bg-slate-800 rounded-lg w-[500px] max-h-[70vh] overflow-hidden border border-slate-600 flex flex-col">
<!-- 头部 -->
<div class="p-4 border-b border-slate-700 flex items-center justify-between shrink-0">
<h3 class="text-lg font-bold text-white flex items-center gap-2">
<IconLibrary name="folder" :size="18" /> 选择文稿
</h3>
<button @click="$emit('close')" class="text-slate-400 hover:text-white">
<IconLibrary name="close" :size="18" />
</button>
</div>
<!-- 筛选 -->
<div class="px-4 py-2 border-b border-slate-700 flex gap-2 shrink-0">
<button
v-for="filter in statusFilters"
:key="filter.value"
@click="currentFilter = filter.value"
:class="['text-xs px-2 py-1 rounded transition',
currentFilter === filter.value
? 'bg-blue-600 text-white'
: 'bg-slate-700 text-slate-300 hover:bg-slate-600']"
>
{{ filter.label }}
</button>
</div>
<!-- 文稿列表 -->
<div class="flex-1 overflow-y-auto p-4 space-y-2 min-h-0">
<div v-if="filteredDocuments.length === 0" class="text-center text-slate-500 py-8">
<div class="w-12 h-12 flex items-center justify-center mx-auto mb-2">
<IconLibrary name="document" :size="32" />
</div>
<p class="text-sm">暂无文稿</p>
</div>
<div
v-for="doc in filteredDocuments"
:key="doc.id"
@click="selectDocument(doc)"
:class="['p-3 rounded-lg border cursor-pointer transition',
selectedDocId === doc.id
? 'bg-blue-900/30 border-blue-500'
: 'bg-slate-900/50 border-slate-700 hover:border-slate-500']"
>
<div class="flex items-start justify-between mb-1">
<h4 class="font-medium text-white text-sm truncate flex-1">{{ doc.title }}</h4>
<span :class="['text-xs px-1.5 py-0.5 rounded ml-2',
doc.status === 'draft' ? 'bg-yellow-900/50 text-yellow-300' :
doc.status === 'published' ? 'bg-green-900/50 text-green-300' : 'bg-slate-700 text-slate-400']">
{{ doc.status === 'draft' ? '草稿' : doc.status === 'published' ? '已发布' : '已归档' }}
</span>
</div>
<p class="text-xs text-slate-500 line-clamp-2">{{ doc.content?.substring(0, 100) || '无内容' }}...</p>
<div class="flex items-center justify-between text-xs text-slate-600 mt-2">
<span>{{ doc.word_count || doc.content?.length || 0 }} </span>
<span>{{ formatDate(doc.updated_at) }}</span>
</div>
</div>
</div>
<!-- 底部操作 -->
<div class="p-4 border-t border-slate-700 flex gap-3 shrink-0">
<button
@click="$emit('close')"
class="flex-1 py-2 rounded bg-slate-600 text-white hover:bg-slate-500 transition"
>
取消
</button>
<button
@click="confirmSelect"
:disabled="!selectedDocId"
class="flex-1 py-2 rounded bg-blue-600 text-white hover:bg-blue-500 transition disabled:opacity-50 disabled:cursor-not-allowed"
>
确认选择
</button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed, watch } from 'vue'
import IconLibrary from './icons/IconLibrary.vue'
const props = defineProps({
visible: Boolean
})
const emit = defineEmits(['close', 'select'])
// 状态
const documents = ref([])
const selectedDocId = ref(null)
const currentFilter = ref('all')
// 筛选选项
const statusFilters = [
{ value: 'all', label: '全部' },
{ value: 'draft', label: '草稿' },
{ value: 'published', label: '已发布' },
{ value: 'archived', label: '已归档' }
]
// 筛选后的文稿
const filteredDocuments = computed(() => {
if (currentFilter.value === 'all') {
return documents.value
}
return documents.value.filter(d => d.status === currentFilter.value)
})
// 加载文稿
const loadDocuments = async () => {
try {
const { getAllDocuments } = await import('../db/index.js')
documents.value = getAllDocuments()
} catch (error) {
console.error('加载文稿失败:', error)
}
}
// 选择文稿
const selectDocument = (doc) => {
selectedDocId.value = selectedDocId.value === doc.id ? null : doc.id
}
// 确认选择
const confirmSelect = () => {
const doc = documents.value.find(d => d.id === selectedDocId.value)
if (doc) {
emit('select', doc)
}
}
// 格式化日期
const formatDate = (dateStr) => {
if (!dateStr) return ''
const date = new Date(dateStr)
return date.toLocaleDateString('zh-CN', { month: 'short', day: 'numeric' })
}
// 监听可见性变化
watch(() => props.visible, (val) => {
if (val) {
selectedDocId.value = null
loadDocuments()
}
})
</script>
<style scoped>
.line-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
</style>