ResearchTaskForm.vue 5 KB
<script setup lang="ts">
import { computed } from 'vue'

import type { ResearchOptions, ResearchTaskDraft } from '@/types'

const props = defineProps<{
  draft: ResearchTaskDraft
  options: ResearchOptions
  searchQuery: string
  loading: boolean
}>()

const emit = defineEmits<{
  'update:draft': [value: ResearchTaskDraft]
  'update:searchQuery': [value: string]
  search: []
}>()

const draftModel = computed({
  get: () => props.draft,
  set: (value: ResearchTaskDraft) => emit('update:draft', value),
})

const queryModel = computed({
  get: () => props.searchQuery,
  set: (value: string) => emit('update:searchQuery', value),
})

function updateField<K extends keyof ResearchTaskDraft>(key: K, value: ResearchTaskDraft[K]) {
  draftModel.value = {
    ...draftModel.value,
    [key]: value,
  }
}
</script>

<template>
  <div class="research-form">
    <div class="research-grid">
      <label class="field">
        <span class="archive-kicker">Venue Identity</span>
        <input
          class="archive-field"
          :value="draft.venue_name"
          type="text"
          placeholder="例如:王府井艺云数字艺术中心"
          @input="updateField('venue_name', ($event.target as HTMLInputElement).value)"
        />
      </label>

      <label class="field">
        <span class="archive-kicker">Geographic Location</span>
        <input
          class="archive-field"
          :value="draft.city"
          type="text"
          placeholder="例如:北京"
          @input="updateField('city', ($event.target as HTMLInputElement).value)"
        />
      </label>

      <label class="field">
        <span class="archive-kicker">Venue Type</span>
        <select
          class="archive-field"
          :value="draft.venue_type"
          @change="updateField('venue_type', ($event.target as HTMLSelectElement).value)"
        >
          <option
            v-for="item in options.venue_types"
            :key="item.value"
            :value="item.value"
          >
            {{ item.label }}
          </option>
        </select>
      </label>

      <label class="field">
        <span class="archive-kicker">Research Focus</span>
        <select
          class="archive-field"
          :value="draft.research_focus"
          @change="updateField('research_focus', ($event.target as HTMLSelectElement).value)"
        >
          <option
            v-for="item in options.research_focuses"
            :key="item.value"
            :value="item.value"
          >
            {{ item.label }}
          </option>
        </select>
      </label>

      <label class="field">
        <span class="archive-kicker">Observation Cycle</span>
        <select
          class="archive-field"
          :value="draft.time_range"
          @change="updateField('time_range', ($event.target as HTMLSelectElement).value)"
        >
          <option
            v-for="item in options.time_ranges"
            :key="item.value"
            :value="item.value"
          >
            {{ item.label }}
          </option>
        </select>
      </label>

      <label class="field field--wide">
        <span class="archive-kicker">Competitive Benchmarks</span>
        <textarea
          class="archive-textarea"
          :value="draft.benchmark_venues_text"
          placeholder="支持多行或逗号分隔"
          @input="updateField('benchmark_venues_text', ($event.target as HTMLTextAreaElement).value)"
        />
      </label>

      <label class="field field--wide">
        <span class="archive-kicker">Special Requirements</span>
        <textarea
          class="archive-textarea"
          :value="draft.notes"
          placeholder="例如:重点关注排队体验、讲解质量、社交传播亮点等"
          @input="updateField('notes', ($event.target as HTMLTextAreaElement).value)"
        />
      </label>
    </div>

    <div class="command-box">
      <label class="field field--wide">
        <span class="archive-kicker">Curatorial Instructions</span>
        <textarea
          class="archive-textarea command-textarea"
          :value="queryModel"
          placeholder="系统会基于场馆任务自动生成研究指令,也可以在这里做人工补充。"
          @input="queryModel = ($event.target as HTMLTextAreaElement).value"
        />
      </label>

      <button
        class="archive-button command-button"
        type="button"
        :disabled="loading"
        @click="$emit('search')"
      >
        {{ loading ? '处理中' : '启动研究' }}
      </button>
    </div>
  </div>
</template>

<style scoped>
.research-form,
.research-grid,
.command-box {
  display: grid;
  gap: 18px;
}

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

.field {
  display: grid;
  gap: 10px;
}

.field--wide {
  grid-column: 1 / -1;
}

.command-box {
  grid-template-columns: 1fr auto;
  align-items: end;
}

.command-textarea {
  min-height: 148px;
}

.command-button {
  min-width: 168px;
}

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