ResearchWorkspace.vue 2.43 KB
<script setup lang="ts">
import ResearchTaskForm from '@/components/research/ResearchTaskForm.vue'
import ResearchTaskPanels from '@/components/research/ResearchTaskPanels.vue'
import type { ResearchOptions, ResearchTask, ResearchTaskDraft } from '@/types'

interface SummaryItem {
  label: string
  value: string
}

defineProps<{
  draft: ResearchTaskDraft
  options: ResearchOptions
  activeTask: ResearchTask | null
  tasks: ResearchTask[]
  summaryItems: SummaryItem[]
  searchQuery: string
  loading: boolean
  saving: boolean
}>()

defineEmits<{
  'update:draft': [value: ResearchTaskDraft]
  'update:searchQuery': [value: string]
  save: []
  activate: [taskId: string]
  syncCrawler: []
  search: []
}>()
</script>

<template>
  <aside class="research-shell archive-panel">
    <div class="research-shell__head">
      <div>
        <p class="archive-kicker">Dossier Workspace</p>
        <h3 class="archive-card-title">场馆任务编辑区</h3>
        <p class="archive-copy">
          在这里维护唯一一份研究上下文,保存后可继续同步到采集中心和引擎工作台。
        </p>
      </div>

      <div class="research-shell__actions">
        <button class="archive-button--ghost" type="button" :disabled="saving" @click="$emit('save')">
          {{ saving ? '保存中' : '保存任务' }}
        </button>
        <button class="archive-button" type="button" :disabled="loading" @click="$emit('syncCrawler')">
          同步到爬虫
        </button>
      </div>
    </div>

    <ResearchTaskForm
      :draft="draft"
      :options="options"
      :search-query="searchQuery"
      :loading="loading"
      @update:draft="$emit('update:draft', $event)"
      @update:search-query="$emit('update:searchQuery', $event)"
      @search="$emit('search')"
    />

    <div class="archive-divider" />

    <ResearchTaskPanels
      :active-task="activeTask"
      :tasks="tasks"
      :summary-items="summaryItems"
      @activate="$emit('activate', $event)"
    />
  </aside>
</template>

<style scoped>
.research-shell,
.research-shell__head,
.research-shell__actions {
  display: grid;
  gap: 18px;
}

.research-shell {
  position: sticky;
  top: 122px;
  align-self: start;
}

.research-shell__actions {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (max-width: 1360px) {
  .research-shell {
    position: static;
  }
}

@media (max-width: 820px) {
  .research-shell__actions {
    grid-template-columns: 1fr;
  }
}
</style>