File size: 6,924 Bytes
5378afe
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
<script setup lang="ts">
import { ref, watchEffect } from 'vue'
import type { Task, TaskGenerateRequest } from '@/types/task.d.ts'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Switch } from '@/components/ui/switch'
import { Textarea } from '@/components/ui/textarea'
import { toast } from '@/components/ui/toast'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'

type FormMode = 'create' | 'edit'
type EmittedData = TaskGenerateRequest | Partial<Task>

const props = defineProps<{
  mode: FormMode
  initialData?: Task | null
  accountOptions?: { name: string; path: string }[]
  defaultAccount?: string
}>()

const emit = defineEmits<{
  (e: 'submit', data: EmittedData): void
}>()

const form = ref<EmittedData>({})

// Initialize form based on mode and initialData
watchEffect(() => {
  if (props.mode === 'edit' && props.initialData) {
    form.value = {
      ...props.initialData,
      account_state_file: props.initialData.account_state_file || '',
      free_shipping: props.initialData.free_shipping ?? true,
      new_publish_option: props.initialData.new_publish_option || '__none__',
      region: props.initialData.region || '江苏/南京/全南京',
    }
  } else {
    form.value = {
      task_name: '',
      keyword: '',
      description: '',
      max_pages: 3,
      personal_only: true,
      min_price: undefined,
      max_price: undefined,
      cron: '',
      account_state_file: props.defaultAccount || '',
      free_shipping: true,
      new_publish_option: '__none__',
      region: '',
    }
  }
})

function handleSubmit() {
  // Basic validation
  if (!form.value.task_name || !form.value.keyword || !form.value.description) {
    toast({
      title: '信息不完整',
      description: '任务名称、关键词和详细需求不能为空。',
      variant: 'destructive',
    })
    return
  }

  // Filter out fields that shouldn't be sent in update requests
  const { id, is_running, ...submitData } = form.value as any
  if (submitData.account_state_file === '') {
    submitData.account_state_file = null
  }
  if (typeof submitData.region === 'string') {
    const normalized = submitData.region
      .trim()
      .split('/')
      .map((part: string) => part.trim().replace(/(省|市)$/u, ''))
      .filter((part: string) => part.length > 0)
      .join('/')
    submitData.region = normalized
  }
  if (submitData.new_publish_option === '__none__') {
    submitData.new_publish_option = ''
  }
  emit('submit', submitData)
}
</script>

<template>
  <form id="task-form" @submit.prevent="handleSubmit">
    <div class="grid gap-6 py-4">
      <div class="grid grid-cols-4 items-center gap-4">
        <Label for="task-name" class="text-right">任务名称</Label>
        <Input id="task-name" v-model="form.task_name" class="col-span-3" placeholder="例如:索尼 A7M4 相机" required />
      </div>
      <div class="grid grid-cols-4 items-center gap-4">
        <Label for="keyword" class="text-right">搜索关键词</Label>
        <Input id="keyword" v-model="form.keyword" class="col-span-3" placeholder="例如:a7m4" required />
      </div>
      <div class="grid grid-cols-4 items-center gap-4">
        <Label for="description" class="text-right">详细需求</Label>
        <Textarea
          id="description"
          v-model="form.description"
          class="col-span-3"
          placeholder="请用自然语言详细描述你的购买需求,AI将根据此描述生成分析标准..."
          required
        />
      </div>
      <div class="grid grid-cols-4 items-center gap-4">
        <Label class="text-right">价格范围</Label>
        <div class="col-span-3 flex items-center gap-2">
          <Input type="number" v-model="form.min_price as any" placeholder="最低价" />
          <span>-</span>
          <Input type="number" v-model="form.max_price as any" placeholder="最高价" />
        </div>
      </div>
      <div class="grid grid-cols-4 items-center gap-4">
        <Label for="max-pages" class="text-right">搜索页数</Label>
        <Input id="max-pages" v-model.number="form.max_pages" type="number" class="col-span-3" />
      </div>
      <div class="grid grid-cols-4 items-center gap-4">
        <Label for="cron" class="text-right">定时规则</Label>
        <Input id="cron" v-model="form.cron as any" class="col-span-3" placeholder="分 时 日 月 周 (例如: 0 8 * * *)" />
      </div>
      <div class="grid grid-cols-4 items-center gap-4">
        <Label class="text-right">绑定账号</Label>
        <div class="col-span-3">
          <Select v-model="form.account_state_file">
            <SelectTrigger>
              <SelectValue placeholder="未绑定(自动选择)" />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="">未绑定(自动选择)</SelectItem>
              <SelectItem v-for="account in accountOptions || []" :key="account.path" :value="account.path">
                {{ account.name }}
              </SelectItem>
            </SelectContent>
          </Select>
        </div>
      </div>
      <div class="grid grid-cols-4 items-center gap-4">
        <Label for="personal-only" class="text-right">仅个人卖家</Label>
        <Switch id="personal-only" v-model="form.personal_only" />
      </div>
      <div class="grid grid-cols-4 items-center gap-4">
        <Label class="text-right">是否包邮</Label>
        <Switch v-model="form.free_shipping" />
      </div>
      <div class="grid grid-cols-4 items-center gap-4">
        <Label class="text-right">新发布范围</Label>
        <div class="col-span-3">
          <Select v-model="form.new_publish_option as any">
            <SelectTrigger>
              <SelectValue placeholder="不筛选(默认)" />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="__none__">不筛选(默认)</SelectItem>
              <SelectItem value="最新">最新</SelectItem>
              <SelectItem value="1天内">1天内</SelectItem>
              <SelectItem value="3天内">3天内</SelectItem>
              <SelectItem value="7天内">7天内</SelectItem>
              <SelectItem value="14天内">14天内</SelectItem>
            </SelectContent>
          </Select>
        </div>
      </div>
      <div class="grid grid-cols-4 items-center gap-4">
        <Label class="text-right">区域筛选(默认不填)</Label>
        <div class="col-span-3 space-y-1">
          <Input
            v-model="form.region as any"
            placeholder="例如: 浙江/杭州/滨江区 或 浙江/杭州/全杭州 或 上海/徐汇区"
          />
          <p class="text-xs text-gray-500">区域筛选会导致满足条件的商品数量很少</p>
        </div>
      </div>
    </div>
  </form>
</template>