diff --git a/static/app.js b/static/app.js index 8894db9..c85919f 100644 --- a/static/app.js +++ b/static/app.js @@ -170,6 +170,23 @@ window.createSales = (event) => createResource(event, "sales"); window.createProposal = (event) => createResource(event, "proposals"); window.createOperation = (event) => createResource(event, "operations"); window.createProduct = (event) => createResource(event, "products"); +window.createTask = (event, projectId) => createTask(event, projectId); + +async function createTask(event, projectId) { + event.preventDefault(); + const form = event.currentTarget; + const data = Object.fromEntries(new FormData(form).entries()); + data.project_id = projectId; + try { + await api("/api/tasks", { method: "POST", body: JSON.stringify({ data }) }); + form.reset(); + form.classList.add("hidden"); + await load(); + showTaskModal(projectId); + } catch (error) { + alert("创建失败:" + error.message); + } +} window.createFinance = (event) => createResource(event, "finance"); window.switchTab = switchTab; @@ -208,14 +225,31 @@ function showTaskModal(projectId) { const project = state.data.operations.find((x) => x.id === projectId); const tasks = (state.data.tasks || []).filter((t) => t.project_id === projectId); const phases = ["项目准备", "项目执行", "项目验收", "验收完毕"]; - document.querySelector("#taskModal").innerHTML = `

${project.project_name} · 任务清单

${phases.map((phase) => { + document.querySelector("#taskModal").innerHTML = `

${project.project_name} · 任务清单

+ + ${phases.map((phase) => { const pt = tasks.filter((t) => t.phase === phase); - return `
${phase}${pt.length}
${pt.length ? pt.map((t) => `
${t.task}
`).join("") : `
暂无任务
`}
`; + return `
${phase}${pt.length}
${pt.length ? pt.map((t) => `
${t.task}
`).join("") : `
暂无任务
`}
`; }).join("")}
`; document.querySelector("#taskModal").classList.add("active"); if (window.lucide) window.lucide.createIcons(); } -window.closeTaskModal = () => document.querySelector("#taskModal").classList.remove("active"); +window.closeTaskModal = () => { + document.querySelector("#taskModal").classList.remove("active"); + document.querySelector("#taskModal").innerHTML = ""; +}; function renderProposals() { const proposalRows = state.data.proposals.map((p) => [p.customer_or_project_name, p.version, badge(p.status), p.files.length + " 个"]); diff --git a/static/styles.css b/static/styles.css index bf4c92b..07e1ee6 100644 --- a/static/styles.css +++ b/static/styles.css @@ -535,6 +535,18 @@ td { .task-dot { display: flex; color: #4b4d54; } .task-name { color: #c5c6ca; font-size: 13px; } .task-none { color: #4b4d54; font-size: 13px; padding: 12px 14px; text-align: center; border-top: 1px solid #24272d; } +.task-form { + background: #141518; border: 1px solid #2a2d34; border-radius: 8px; + padding: 14px; margin-bottom: 16px; +} +.task-field { display: flex; flex-direction: column; gap: 4px; } +.task-field span { color: #6b6d75; font-size: 12px; } +.task-field input, .task-field select, .task-field textarea { + background: #1e2025; border: 1px solid #2a2d34; border-radius: 6px; + color: #e4e5e7; font-size: 13px; padding: 6px 10px; outline: none; +} +.task-field input:focus, .task-field select:focus, .task-field textarea:focus { border-color: #4a6cf7; } +.col-span-2 { grid-column: span 2; } .task-group-add { display: block; width: 100%; padding: 10px; text-align: center; color: #6b6d75; font-size: 13px; background: none; border: none;