feat: add dynamic report item rows

This commit is contained in:
Codex 2026-05-07 22:39:58 +08:00
parent 5434d1b283
commit ab2f3dc093
3 changed files with 96 additions and 16 deletions

View File

@ -61,10 +61,53 @@ button {
gap: 8px;
}
.item-group h2 { margin: 0; }
.item-group-head {
display: flex;
justify-content: space-between;
gap: 12px;
align-items: center;
}
.item-group [data-list] {
display: grid;
gap: 8px;
}
.item-row {
display: grid;
grid-template-columns: 32px minmax(0, 1fr) 36px;
gap: 8px;
align-items: center;
}
.item-index {
color: #5b6472;
text-align: right;
}
.add-item, .remove-item {
width: 36px;
height: 36px;
padding: 0;
display: inline-flex;
align-items: center;
justify-content: center;
}
.add-item {
border: 1px solid #2563eb;
background: #fff;
color: #2563eb;
font-size: 22px;
line-height: 1;
}
.remove-item {
border: 1px solid #e5e7eb;
background: #fff;
color: #6b7280;
font-size: 20px;
line-height: 1;
}
.remove-item:hover {
border-color: #fecaca;
color: #b91c1c;
background: #fef2f2;
}
.previous-plan {
display: grid;
gap: 10px;

View File

@ -71,22 +71,18 @@ def submit_page(current_date: str, session: dict[str, str] | None = None) -> byt
<label><input type="radio" name="report_status" value="need_help"> 需要支持</label>
</fieldset>
<section class="item-group">
<h2>今日完成</h2>
<div data-list="today_done">
<input placeholder="1.">
<input placeholder="2.">
<input placeholder="3.">
<input placeholder="4.">
<div class="item-group-head">
<h2>今日完成</h2>
<button class="add-item" type="button" data-add-list="today_done" aria-label="添加今日完成">+</button>
</div>
<div data-list="today_done"></div>
</section>
<section class="item-group">
<h2>明日计划</h2>
<div data-list="tomorrow_plan">
<input placeholder="1.">
<input placeholder="2.">
<input placeholder="3.">
<input placeholder="4.">
<div class="item-group-head">
<h2>明日计划</h2>
<button class="add-item" type="button" data-add-list="tomorrow_plan" aria-label="添加明日计划">+</button>
</div>
<div data-list="tomorrow_plan"></div>
</section>
<label>遇到的问题<textarea name="blockers" rows="3" placeholder="没有可以不填"></textarea></label>
<label>需要协助<textarea name="help_needed" rows="3" placeholder="没有可以不填"></textarea></label>
@ -136,15 +132,47 @@ function collectItems(name) {{
return values.map((value, index) => `${{index + 1}}. ${{value}}`).join("\\n");
}}
function renumberItems(name) {{
Array.from(document.querySelectorAll(`[data-list="${{name}}"] .item-row`)).forEach((row, index) => {{
row.querySelector(".item-index").textContent = `${{index + 1}}.`;
row.querySelector("input").placeholder = ` ${{index + 1}} `;
}});
}}
function addItem(name, value = "") {{
const list = document.querySelector(`[data-list="${{name}}"]`);
const row = document.createElement("div");
row.className = "item-row";
row.innerHTML = `
<span class="item-index"></span>
<input value="${{escapeHtml(value)}}" autocomplete="off">
<button class="remove-item" type="button" aria-label="删除这一条">×</button>
`;
row.querySelector(".remove-item").addEventListener("click", () => {{
if (list.querySelectorAll(".item-row").length <= 1) {{
row.querySelector("input").value = "";
return;
}}
row.remove();
renumberItems(name);
}});
list.appendChild(row);
renumberItems(name);
}}
function resetItems(name, values = []) {{
const list = document.querySelector(`[data-list="${{name}}"]`);
list.innerHTML = "";
const items = values.length ? values : ["", "", ""];
items.forEach((value) => addItem(name, value));
}}
function fillItemInputs(name, text) {{
const inputs = Array.from(document.querySelectorAll(`[data-list="${{name}}"] input`));
const lines = String(text || "")
.split(/\\n+/)
.map((line) => line.replace(/^\\s*\\d+[\\.)]\\s*/, "").trim())
.filter(Boolean);
inputs.forEach((input, index) => {{
input.value = lines[index] || "";
}});
resetItems(name, lines);
}}
function renderHistory(data) {{
@ -205,6 +233,11 @@ async function loadPreviousPlan() {{
document.querySelector("#load-history").addEventListener("click", loadHistory);
document.querySelector("#report-date").addEventListener("change", loadPreviousPlan);
document.querySelectorAll("[data-add-list]").forEach((button) => {{
button.addEventListener("click", () => {{
addItem(button.dataset.addList);
}});
}});
document.querySelector("#use-previous-plan").addEventListener("click", () => {{
fillItemInputs("today_done", document.querySelector("#previous-plan-content").textContent);
}});
@ -232,6 +265,8 @@ document.querySelector("#report-form").addEventListener("submit", async (event)
}}
}});
resetItems("today_done");
resetItems("tomorrow_plan");
loadHistory();
loadPreviousPlan();
</script>""",

View File

@ -68,6 +68,8 @@ class WebTest(unittest.TestCase):
self.assertIn("每日工作汇报", submit)
self.assertIn("今日状态", submit)
self.assertIn('data-list="today_done"', submit)
self.assertIn('data-add-list="today_done"', submit)
self.assertIn('resetItems("today_done")', submit)
self.assertIn("我的历史日报", submit)
db.upsert_employee(