feat: complete project workspace tags and notes UI

This commit is contained in:
2026-07-21 00:46:09 +08:00
parent 54958382f1
commit c613d4c997
28 changed files with 1621 additions and 284 deletions

View File

@@ -1,5 +1,5 @@
import { useEffect, useState } from 'react'
import { Input, Modal, Space, Switch, Typography } from '@arco-design/web-react'
import { Input, Modal, Select, Space, Switch, Typography } from '@arco-design/web-react'
const { Text } = Typography
const { TextArea } = Input
@@ -8,6 +8,9 @@ export type ProjectActionModal = 'project' | 'task' | 'source' | 'cron' | null
export type ProjectDraft = {
name: string
identifier: string
icon: string
background: string
description: string
}
@@ -15,6 +18,7 @@ export type TaskDraft = {
title: string
description: string
dueAt: string
tag: string
}
export type SourceDraft = {
@@ -37,6 +41,7 @@ export function ProjectActionModals({
onCreateTask,
onUploadSource,
onCreateCronPlan,
tagOptions,
}: {
activeModal: ProjectActionModal
loading: boolean
@@ -45,16 +50,17 @@ export function ProjectActionModals({
onCreateTask: (draft: TaskDraft) => void
onUploadSource: (draft: SourceDraft) => void
onCreateCronPlan: (draft: CronDraft) => void
tagOptions: string[]
}) {
const [project, setProject] = useState<ProjectDraft>({ name: '', description: '' })
const [task, setTask] = useState<TaskDraft>({ title: '', description: '', dueAt: '' })
const [project, setProject] = useState<ProjectDraft>({ name: '', identifier: '', icon: '', background: '', description: '' })
const [task, setTask] = useState<TaskDraft>({ title: '', description: '', dueAt: '', tag: '' })
const [source, setSource] = useState<SourceDraft>({ title: '', file: null })
const [cron, setCron] = useState<CronDraft>({ title: '', schedule: '0 9 * * *', enabled: true, nextRunAt: '' })
useEffect(() => {
if (activeModal === null) {
setProject({ name: '', description: '' })
setTask({ title: '', description: '', dueAt: '' })
setProject({ name: '', identifier: '', icon: '', background: '', description: '' })
setTask({ title: '', description: '', dueAt: '', tag: '' })
setSource({ title: '', file: null })
setCron({ title: '', schedule: '0 9 * * *', enabled: true, nextRunAt: '' })
}
@@ -76,7 +82,19 @@ export function ProjectActionModals({
<Input placeholder="例如:项目 A3" value={project.name} onChange={(name) => setProject((draft) => ({ ...draft, name }))} />
</label>
<label>
<Text></Text>
<Text></Text>
<Input placeholder="例如A3 / EXP / DATA" value={project.identifier} onChange={(identifier) => setProject((draft) => ({ ...draft, identifier }))} />
</label>
<label>
<Text></Text>
<Input placeholder="例如A3 / 🚀 / compass" value={project.icon} onChange={(icon) => setProject((draft) => ({ ...draft, icon }))} />
</label>
<label>
<Text></Text>
<Input placeholder="例如:#165DFF 或背景图片 URL" value={project.background} onChange={(background) => setProject((draft) => ({ ...draft, background }))} />
</label>
<label>
<Text></Text>
<TextArea rows={4} placeholder="项目目标、背景或协作说明" value={project.description} onChange={(description) => setProject((draft) => ({ ...draft, description }))} />
</label>
</Space>
@@ -103,6 +121,19 @@ export function ProjectActionModals({
<Text></Text>
<Input placeholder="2026-07-21T09:30:00Z可留空" value={task.dueAt} onChange={(dueAt) => setTask((draft) => ({ ...draft, dueAt }))} />
</label>
<label>
<Text></Text>
<Select
allowCreate
placeholder="选择或输入标签"
value={task.tag}
onChange={(tag) => setTask((draft) => ({ ...draft, tag }))}
>
{tagOptions.map((tag) => (
<Select.Option key={tag} value={tag}>{tag}</Select.Option>
))}
</Select>
</label>
</Space>
</Modal>