feat(documents): rebuild project document workbench

This commit is contained in:
2026-07-24 12:16:02 +08:00
parent 366136cee9
commit 77beaebb30
73 changed files with 5867 additions and 1264 deletions

View File

@@ -27,11 +27,11 @@ import {
fetchProjects,
updateProject,
updateTask,
uploadSource,
} from '../api/projects'
import type { DocumentOpenIntent } from '../api/documents'
import type { SearchResultDTO } from '../api/search'
import { LoginPage } from '../pages/login'
import { ProjectActionModals, type CronDraft, type ProjectActionModal, type ProjectDraft, type SourceDraft, type TaskDraft } from '../pages/projects/project-action-modals'
import { ProjectActionModals, type CronDraft, type ProjectActionModal, type ProjectDraft, type TaskDraft } from '../pages/projects/project-action-modals'
import { SearchResultPreview } from '../pages/projects/search-result-preview'
import type { ProjectSettingsUpdate } from '../pages/projects/project-sidebar'
import { ProjectPage } from '../pages/workspace-home'
@@ -54,6 +54,7 @@ function App() {
const [actionLoading, setActionLoading] = useState(false)
const [activeModal, setActiveModal] = useState<ProjectActionModal>(null)
const [searchResultPreview, setSearchResultPreview] = useState<SearchResultDTO | null>(null)
const [documentIntent, setDocumentIntent] = useState<DocumentOpenIntent | null>(null)
const workspaceSearch = useWorkbenchSearch(session)
const handleListAISessions = useCallback((projectId: string, signal?: AbortSignal) => {
@@ -119,6 +120,17 @@ function App() {
return { ...result, refreshFailed: true }
}
}
setDocumentIntent({
intentId: crypto.randomUUID(),
mode: 'open',
projectId,
documentId: result.documentId,
sourceType: 'dataset',
sourceId: itemId,
})
selectActiveProject(projectId)
setActiveView('project')
setActiveChannel('documents')
return result
}, [session, workspaces])
@@ -238,22 +250,6 @@ function App() {
}, '任务已创建')
}
function handleUploadSource(draft: SourceDraft) {
if (!draft.file) {
Message.warning('请选择文件')
return
}
const file = draft.file
void runAction(async () => {
await uploadSource(requireSession(), requireActiveProject(), {
title: draft.title.trim(),
file,
})
await refreshAfterAction()
setActiveChannel('notes')
}, '文件已上传')
}
function handleCreateCronPlan(draft: CronDraft) {
if (!draft.title.trim()) {
Message.warning('请输入计划名称')
@@ -375,7 +371,16 @@ function App() {
setActiveView('project')
setActiveChannel(target.channel)
setActiveTaskID(target.openTask ? result.id : null)
if (result.type === 'note') setSelectedItem(result.title)
if (result.type === 'document') {
setDocumentIntent({
intentId: crypto.randomUUID(),
mode: 'open',
projectId: result.projectId,
documentId: result.id,
sourceType: 'search',
sourceId: result.id,
})
}
}
return (
@@ -389,6 +394,11 @@ function App() {
<ProjectPage
activeView={activeView}
activeWorkspace={activeWorkspace}
session={session}
documentIntent={documentIntent}
onDocumentIntentConsumed={(intentId) => {
setDocumentIntent((current) => current?.intentId === intentId ? null : current)
}}
workspaces={workspaces}
activeChannel={activeChannel}
activeTaskID={activeTaskID}
@@ -411,7 +421,6 @@ function App() {
onToggleTheme={() => setTheme(dark ? 'light' : 'dark')}
onCreateProject={() => setActiveModal('project')}
onCreateTask={() => setActiveModal('task')}
onUploadSource={() => setActiveModal('source')}
onCreateCronPlan={() => setActiveModal('cron')}
onUpdateWorkspaceTask={handleUpdateWorkspaceTask}
onUpdateProject={handleUpdateProject}
@@ -446,7 +455,6 @@ function App() {
onClose={() => setActiveModal(null)}
onCreateProject={handleCreateProject}
onCreateTask={handleCreateTask}
onUploadSource={handleUploadSource}
onCreateCronPlan={handleCreateCronPlan}
tagOptions={activeTagOptions}
/>
@@ -459,13 +467,13 @@ function App() {
function searchResultTarget(type: string): { channel: ChannelKey; openTask: boolean } | null {
if (type === 'project') return { channel: 'overview', openTask: false }
if (type === 'task') return { channel: 'tasks', openTask: true }
if (type === 'note') return { channel: 'notes', openTask: false }
if (type === 'document') return { channel: 'documents', openTask: false }
return null
}
function isAuthorizedExternalPreview(result: SearchResultDTO) {
return (
(result.type === 'task' || result.type === 'note')
(result.type === 'task' || result.type === 'document')
&& typeof result.projectId === 'string'
&& result.projectId.trim() !== ''
&& typeof result.title === 'string'