auto-sync: 2026-05-20 22:56:37
This commit is contained in:
@@ -606,3 +606,59 @@ export default function TaskModal() {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// 项目归属选择器
|
||||
function ProjectSelector({ taskId, currentProject, projects }: {
|
||||
taskId: string; currentProject: string | null; projects: Record<string, any>;
|
||||
}) {
|
||||
const [moving, setMoving] = useState(false);
|
||||
const pid = currentProject || '';
|
||||
const projName = projects[pid]?.name || pid || '未知项目';
|
||||
|
||||
const handleMove = async (targetPid: string) => {
|
||||
if (targetPid === pid || !pid) return;
|
||||
setMoving(true);
|
||||
try {
|
||||
const res = await fetch(`/api/projects/${pid}/tasks/${taskId}/move`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ target_project_id: targetPid }),
|
||||
});
|
||||
if (res.ok) {
|
||||
const toast = useStore.getState().toast;
|
||||
toast(`✅ 已移动到 ${projects[targetPid]?.name || targetPid}`);
|
||||
useStore.getState().loadV2Tasks();
|
||||
} else {
|
||||
const d = await res.json();
|
||||
useStore.getState().toast(d.detail || '移动失败', 'err');
|
||||
}
|
||||
} catch {
|
||||
useStore.getState().toast('网络错误', 'err');
|
||||
}
|
||||
setMoving(false);
|
||||
};
|
||||
|
||||
const otherProjects = Object.entries(projects).filter(([p]) => p !== pid && !p.startsWith('_'));
|
||||
|
||||
return (
|
||||
<span style={{ position: 'relative', display: 'inline-block' }}>
|
||||
<span style={{ cursor: 'pointer', borderBottom: '1px dashed var(--muted)' }} title="点击切换项目归属">
|
||||
📁 {projName}
|
||||
</span>
|
||||
<select
|
||||
disabled={moving}
|
||||
onChange={(e) => { if (e.target.value) handleMove(e.target.value); }}
|
||||
defaultValue=""
|
||||
style={{
|
||||
position: 'absolute', inset: 0, opacity: 0, cursor: 'pointer',
|
||||
fontSize: 12, border: 'none', background: 'transparent',
|
||||
}}
|
||||
>
|
||||
<option value="" disabled>移动到...</option>
|
||||
{otherProjects.map(([p, info]) => (
|
||||
<option key={p} value={p}>{info.name || p}</option>
|
||||
))}
|
||||
</select>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user