11import { useState , useEffect } from 'react' ;
22import { X } from 'lucide-react' ;
33import { useGlobalStore , type Automation } from '../stores/global.store' ;
4- import { createAutomation , updateAutomation , listAutomations } from '../lib/core-api' ;
4+ import { createAutomation , updateAutomation } from '../lib/core-api' ;
55
66interface AutomationFormProps {
77 automationId : string | null ;
@@ -32,7 +32,12 @@ const WEEKDAYS = [
3232 { value : '0' , label : '周日' } ,
3333] ;
3434
35- export function AutomationForm ( { automationId, defaultProjectCwd, onClose, onSaved } : AutomationFormProps ) {
35+ export function AutomationForm ( {
36+ automationId,
37+ defaultProjectCwd,
38+ onClose,
39+ onSaved,
40+ } : AutomationFormProps ) {
3641 const automations = useGlobalStore ( ( s ) => s . agent . automations ) ;
3742 const existing = automationId ? automations . find ( ( a : Automation ) => a . id === automationId ) : null ;
3843
@@ -46,7 +51,9 @@ export function AutomationForm({ automationId, defaultProjectCwd, onClose, onSav
4651 const [ intervalUnit , setIntervalUnit ] = useState < 'hours' | 'minutes' > ( 'hours' ) ;
4752 const [ customCron , setCustomCron ] = useState ( existing ?. cron ?? '' ) ;
4853 const [ timezone , setTimezone ] = useState ( existing ?. timezone ?? 'Asia/Shanghai' ) ;
49- const [ sandbox , setSandbox ] = useState < 'readonly' | 'workspace-write' > ( existing ?. sandbox ?? 'workspace-write' ) ;
54+ const [ sandbox , setSandbox ] = useState < 'readonly' | 'workspace-write' > (
55+ existing ?. sandbox ?? 'workspace-write'
56+ ) ;
5057 const [ projectCwd , setProjectCwd ] = useState ( existing ?. projectCwd ?? defaultProjectCwd ) ;
5158 const [ runOnce , setRunOnce ] = useState ( existing ?. runOnce ?? false ) ;
5259 const [ saving , setSaving ] = useState ( false ) ;
@@ -161,49 +168,62 @@ export function AutomationForm({ automationId, defaultProjectCwd, onClose, onSav
161168 }
162169 }
163170
171+ const inputClass =
172+ 'w-full px-3 py-2 bg-[var(--bg-base)] border border-[var(--border-card)] rounded-lg text-[13px] text-[var(--text-primary)] focus:outline-none focus:border-[var(--accent-primary)] transition-colors' ;
173+ const selectClass =
174+ 'w-full px-3 py-2 bg-[var(--bg-base)] border border-[var(--border-card)] rounded-lg text-[13px] text-[var(--text-primary)] focus:outline-none focus:border-[var(--accent-primary)] transition-colors' ;
175+ const labelClass = 'block text-[12px] text-[var(--text-muted)] mb-1.5' ;
176+
164177 return (
165- < div className = "fixed inset-0 bg-black/50 flex items-center justify-center z-50" >
166- < div className = "bg-[#252525] rounded-lg border border-[#333] w-full max-w-md mx-4 max-h-[90vh] overflow-y-auto" >
167- < div className = "flex items-center justify-between px-4 py-3 border-b border-[#333]" >
168- < h3 className = "text-sm font-medium" > { automationId ? '编辑自动化任务' : '新建自动化任务' } </ h3 >
169- < button onClick = { onClose } className = "p-1 hover:bg-[#333] rounded transition-colors" >
178+ < div className = "fixed inset-0 bg-black/60 flex items-center justify-center z-50" >
179+ < div className = "bg-[var(--bg-panel)] rounded-xl border border-[var(--border-default)] w-full max-w-md mx-4 max-h-[85vh] overflow-y-auto shadow-2xl" >
180+ < div className = "flex items-center justify-between px-5 py-4 border-b border-[var(--border-default)]" >
181+ < h3 className = "text-[14px] font-medium text-[var(--text-title)]" >
182+ { automationId ? '编辑自动化任务' : '新建自动化任务' }
183+ </ h3 >
184+ < button
185+ onClick = { onClose }
186+ className = "p-1.5 rounded-lg hover:bg-[var(--bg-hover)] text-[var(--text-placeholder)] hover:text-[var(--text-primary)] transition-colors"
187+ >
170188 < X size = { 16 } />
171189 </ button >
172190 </ div >
173191
174- < form onSubmit = { handleSubmit } className = "p-4 space-y-4" >
192+ < form onSubmit = { handleSubmit } className = "p-5 space-y-4" >
175193 { error && (
176- < div className = "text-xs text-red-400 bg-red-900/20 px-3 py-2 rounded" > { error } </ div >
194+ < div className = "text-[12px] text-red-500 bg-red-500/10 px-3 py-2 rounded-lg" >
195+ { error }
196+ </ div >
177197 ) }
178198
179199 < div >
180- < label className = "block text-xs text-gray-400 mb-1" > 名称</ label >
200+ < label className = { labelClass } > 名称</ label >
181201 < input
182202 type = "text"
183203 value = { name }
184204 onChange = { ( e ) => setName ( e . target . value ) }
185- className = "w-full px-3 py-2 bg-[#1a1a1a] border border-[#333] rounded text-sm focus:outline-none focus:border-blue-500"
205+ className = { inputClass }
186206 placeholder = "每日报告"
187207 />
188208 </ div >
189209
190210 < div >
191- < label className = "block text-xs text-gray-400 mb-1" > 任务描述 (发送给 Agent)</ label >
211+ < label className = { labelClass } > 任务描述 (发送给 Agent)</ label >
192212 < textarea
193213 value = { description }
194214 onChange = { ( e ) => setDescription ( e . target . value ) }
195215 rows = { 3 }
196- className = "w-full px-3 py-2 bg-[#1a1a1a] border border-[#333] rounded text-sm focus:outline-none focus:border-blue-500 resize-none"
216+ className = { ` ${ inputClass } resize-none` }
197217 placeholder = "请检查项目状态并生成日报"
198218 />
199219 </ div >
200220
201221 < div >
202- < label className = "block text-xs text-gray-400 mb-1" > 触发频率</ label >
222+ < label className = { labelClass } > 触发频率</ label >
203223 < select
204224 value = { frequency }
205225 onChange = { ( e ) => setFrequency ( e . target . value as FrequencyType ) }
206- className = "w-full px-3 py-2 bg-[#1a1a1a] border border-[#333] rounded text-sm focus:outline-none focus:border-blue-500"
226+ className = { selectClass }
207227 >
208228 < option value = "daily" > 每天</ option >
209229 < option value = "weekly" > 每周</ option >
@@ -214,27 +234,27 @@ export function AutomationForm({ automationId, defaultProjectCwd, onClose, onSav
214234 </ div >
215235
216236 { frequency === 'daily' && (
217- < div className = "flex gap-2 " >
237+ < div className = "flex gap-3 " >
218238 < div className = "flex-1" >
219- < label className = "block text-xs text-gray-400 mb-1" > 小时</ label >
239+ < label className = { labelClass } > 小时</ label >
220240 < input
221241 type = "number"
222242 min = "0"
223243 max = "23"
224244 value = { hour }
225245 onChange = { ( e ) => setHour ( e . target . value ) }
226- className = "w-full px-3 py-2 bg-[#1a1a1a] border border-[#333] rounded text-sm focus:outline-none focus:border-blue-500"
246+ className = { inputClass }
227247 />
228248 </ div >
229249 < div className = "flex-1" >
230- < label className = "block text-xs text-gray-400 mb-1" > 分钟</ label >
250+ < label className = { labelClass } > 分钟</ label >
231251 < input
232252 type = "number"
233253 min = "0"
234254 max = "59"
235255 value = { minute }
236256 onChange = { ( e ) => setMinute ( e . target . value ) }
237- className = "w-full px-3 py-2 bg-[#1a1a1a] border border-[#333] rounded text-sm focus:outline-none focus:border-blue-500"
257+ className = { inputClass }
238258 />
239259 </ div >
240260 </ div >
@@ -243,62 +263,64 @@ export function AutomationForm({ automationId, defaultProjectCwd, onClose, onSav
243263 { frequency === 'weekly' && (
244264 < >
245265 < div >
246- < label className = "block text-xs text-gray-400 mb-1" > 星期</ label >
266+ < label className = { labelClass } > 星期</ label >
247267 < select
248268 value = { weekday }
249269 onChange = { ( e ) => setWeekday ( e . target . value ) }
250- className = "w-full px-3 py-2 bg-[#1a1a1a] border border-[#333] rounded text-sm focus:outline-none focus:border-blue-500"
270+ className = { selectClass }
251271 >
252272 { WEEKDAYS . map ( ( d ) => (
253- < option key = { d . value } value = { d . value } > { d . label } </ option >
273+ < option key = { d . value } value = { d . value } >
274+ { d . label }
275+ </ option >
254276 ) ) }
255277 </ select >
256278 </ div >
257- < div className = "flex gap-2 " >
279+ < div className = "flex gap-3 " >
258280 < div className = "flex-1" >
259- < label className = "block text-xs text-gray-400 mb-1" > 小时</ label >
281+ < label className = { labelClass } > 小时</ label >
260282 < input
261283 type = "number"
262284 min = "0"
263285 max = "23"
264286 value = { hour }
265287 onChange = { ( e ) => setHour ( e . target . value ) }
266- className = "w-full px-3 py-2 bg-[#1a1a1a] border border-[#333] rounded text-sm focus:outline-none focus:border-blue-500"
288+ className = { inputClass }
267289 />
268290 </ div >
269291 < div className = "flex-1" >
270- < label className = "block text-xs text-gray-400 mb-1" > 分钟</ label >
292+ < label className = { labelClass } > 分钟</ label >
271293 < input
272294 type = "number"
273295 min = "0"
274296 max = "59"
275297 value = { minute }
276298 onChange = { ( e ) => setMinute ( e . target . value ) }
277- className = "w-full px-3 py-2 bg-[#1a1a1a] border border-[#333] rounded text-sm focus:outline-none focus:border-blue-500"
299+ className = { inputClass }
278300 />
279301 </ div >
280302 </ div >
281303 </ >
282304 ) }
283305
284306 { frequency === 'interval' && (
285- < div className = "flex gap-2 " >
307+ < div className = "flex gap-3 " >
286308 < div className = "flex-1" >
287- < label className = "block text-xs text-gray-400 mb-1" > 间隔</ label >
309+ < label className = { labelClass } > 间隔</ label >
288310 < input
289311 type = "number"
290312 min = "1"
291313 value = { intervalValue }
292314 onChange = { ( e ) => setIntervalValue ( e . target . value ) }
293- className = "w-full px-3 py-2 bg-[#1a1a1a] border border-[#333] rounded text-sm focus:outline-none focus:border-blue-500"
315+ className = { inputClass }
294316 />
295317 </ div >
296318 < div className = "flex-1" >
297- < label className = "block text-xs text-gray-400 mb-1" > 单位</ label >
319+ < label className = { labelClass } > 单位</ label >
298320 < select
299321 value = { intervalUnit }
300322 onChange = { ( e ) => setIntervalUnit ( e . target . value as 'hours' | 'minutes' ) }
301- className = "w-full px-3 py-2 bg-[#1a1a1a] border border-[#333] rounded text-sm focus:outline-none focus:border-blue-500"
323+ className = { selectClass }
302324 >
303325 < option value = "hours" > 小时</ option >
304326 < option value = "minutes" > 分钟</ option >
@@ -308,65 +330,69 @@ export function AutomationForm({ automationId, defaultProjectCwd, onClose, onSav
308330 ) }
309331
310332 { frequency === 'once' && (
311- < div className = "flex gap-2 " >
333+ < div className = "flex gap-3 " >
312334 < div className = "flex-1" >
313- < label className = "block text-xs text-gray-400 mb-1" > 小时</ label >
335+ < label className = { labelClass } > 小时</ label >
314336 < input
315337 type = "number"
316338 min = "0"
317339 max = "23"
318340 value = { hour }
319341 onChange = { ( e ) => setHour ( e . target . value ) }
320- className = "w-full px-3 py-2 bg-[#1a1a1a] border border-[#333] rounded text-sm focus:outline-none focus:border-blue-500"
342+ className = { inputClass }
321343 />
322344 </ div >
323345 < div className = "flex-1" >
324- < label className = "block text-xs text-gray-400 mb-1" > 分钟</ label >
346+ < label className = { labelClass } > 分钟</ label >
325347 < input
326348 type = "number"
327349 min = "0"
328350 max = "59"
329351 value = { minute }
330352 onChange = { ( e ) => setMinute ( e . target . value ) }
331- className = "w-full px-3 py-2 bg-[#1a1a1a] border border-[#333] rounded text-sm focus:outline-none focus:border-blue-500"
353+ className = { inputClass }
332354 />
333355 </ div >
334356 </ div >
335357 ) }
336358
337359 { frequency === 'custom' && (
338360 < div >
339- < label className = "block text-xs text-gray-400 mb-1" > Cron 表达式</ label >
361+ < label className = { labelClass } > Cron 表达式</ label >
340362 < input
341363 type = "text"
342364 value = { customCron }
343365 onChange = { ( e ) => setCustomCron ( e . target . value ) }
344- className = "w-full px-3 py-2 bg-[#1a1a1a] border border-[#333] rounded text-sm focus:outline-none focus:border-blue-500 font-mono"
366+ className = { ` ${ inputClass } font-mono` }
345367 placeholder = "0 9 * * *"
346368 />
347- < p className = "text-xs text-gray-500 mt-1" > 格式: 分 时 日 月 周</ p >
369+ < p className = "text-[11px] text-[var(--text-disabled)] mt-1.5" >
370+ 格式: 分 时 日 月 周
371+ </ p >
348372 </ div >
349373 ) }
350374
351375 < div >
352- < label className = "block text-xs text-gray-400 mb-1" > 时区</ label >
376+ < label className = { labelClass } > 时区</ label >
353377 < select
354378 value = { timezone }
355379 onChange = { ( e ) => setTimezone ( e . target . value ) }
356- className = "w-full px-3 py-2 bg-[#1a1a1a] border border-[#333] rounded text-sm focus:outline-none focus:border-blue-500"
380+ className = { selectClass }
357381 >
358382 { TIMEZONES . map ( ( tz ) => (
359- < option key = { tz } value = { tz } > { tz } </ option >
383+ < option key = { tz } value = { tz } >
384+ { tz }
385+ </ option >
360386 ) ) }
361387 </ select >
362388 </ div >
363389
364390 < div >
365- < label className = "block text-xs text-gray-400 mb-1" > 沙箱模式</ label >
391+ < label className = { labelClass } > 沙箱模式</ label >
366392 < select
367393 value = { sandbox }
368394 onChange = { ( e ) => setSandbox ( e . target . value as 'readonly' | 'workspace-write' ) }
369- className = "w-full px-3 py-2 bg-[#1a1a1a] border border-[#333] rounded text-sm focus:outline-none focus:border-blue-500"
395+ className = { selectClass }
370396 >
371397 < option value = "workspace-write" > workspace-write (可读写)</ option >
372398 < option value = "readonly" > readonly (只读)</ option >
@@ -375,12 +401,12 @@ export function AutomationForm({ automationId, defaultProjectCwd, onClose, onSav
375401
376402 { ! automationId && (
377403 < div >
378- < label className = "block text-xs text-gray-400 mb-1" > 项目路径</ label >
404+ < label className = { labelClass } > 项目路径</ label >
379405 < input
380406 type = "text"
381407 value = { projectCwd }
382408 onChange = { ( e ) => setProjectCwd ( e . target . value ) }
383- className = "w-full px-3 py-2 bg-[#1a1a1a] border border-[#333] rounded text-sm focus:outline-none focus:border-blue-500 font-mono"
409+ className = { ` ${ inputClass } font-mono` }
384410 placeholder = "/home/user/project"
385411 />
386412 </ div >
@@ -392,25 +418,25 @@ export function AutomationForm({ automationId, defaultProjectCwd, onClose, onSav
392418 id = "runOnce"
393419 checked = { runOnce }
394420 onChange = { ( e ) => setRunOnce ( e . target . checked ) }
395- className = "rounded border-[#333 ]"
421+ className = "rounded border-[var(--border-card) ]"
396422 />
397- < label htmlFor = "runOnce" className = "text-xs text-gray-400 " >
423+ < label htmlFor = "runOnce" className = "text-[12px] text-[var(--text-muted)] " >
398424 执行一次后自动删除
399425 </ label >
400426 </ div >
401427
402- < div className = "flex justify-end gap-2 pt-2 " >
428+ < div className = "flex justify-end gap-2 pt-3 border-t border-[var(--border-default)] " >
403429 < button
404430 type = "button"
405431 onClick = { onClose }
406- className = "px-4 py-2 text-sm bg-[#333] hover:bg-[#444 ] rounded transition-colors"
432+ className = "px-4 py-2 text-[13px] bg-[var(--bg-card)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover) ] rounded-lg transition-colors border border-[var(--border-card)] "
407433 >
408434 取消
409435 </ button >
410436 < button
411437 type = "submit"
412438 disabled = { saving }
413- className = "px-4 py-2 text-sm bg-blue-600 hover:bg-blue-700 rounded transition-colors disabled:opacity-50"
439+ className = "px-4 py-2 text-[13px] bg-[var(--accent-primary)] text-white rounded-lg hover:opacity-90 transition-opacity disabled:opacity-50"
414440 >
415441 { saving ? '保存中...' : '保存' }
416442 </ button >
0 commit comments