排班工具

This commit is contained in:
2023-02-16 03:01:04 +08:00
parent 3ec781cc76
commit 3b23b09909
8 changed files with 675 additions and 21 deletions

View File

@@ -1,5 +1,6 @@
import React from "react";
import { get, post } from "@/common";
import { collection } from "@/store";
interface Conflicts {
[index: string]: HTMLInputElement[];
@@ -15,7 +16,24 @@ const indexToElement: IndexToElement = {};
const conflicts: Conflicts = {};
const marks: (HTMLInputElement | null)[][] = [];
const Timetable = ({ user }) => {
const downloadObjectAsJson = (exportObj: any, exportName: string) => {
const dataStr =
"data:text/json;charset=utf-8," +
encodeURIComponent(JSON.stringify(exportObj));
const downloadAnchorNode = document.createElement("a");
downloadAnchorNode.setAttribute("href", dataStr);
downloadAnchorNode.setAttribute("download", `${exportName}.json`);
document.body.appendChild(downloadAnchorNode); // required for firefox
downloadAnchorNode.click();
downloadAnchorNode.remove();
};
const Timetable = ({
user,
disableNetwork = false,
disableConflictCheck = false,
replaceInputType = "checkbox",
}) => {
const [editable, setEditable] = React.useState(true);
const ref = React.useRef();
@@ -23,6 +41,8 @@ const Timetable = ({ user }) => {
const target: HTMLInputElement = event.target;
console.log("select", target.name, target.checked);
if (disableConflictCheck) return;
const changedInputs: any = [];
// find whether there are checked input in conflict
for (const input of conflicts[target.name]) {
@@ -47,6 +67,9 @@ const Timetable = ({ user }) => {
}
}
}
if (disableNetwork) return;
// post request
const json = await post("/api/record", {
name: target.name,
@@ -74,11 +97,12 @@ const Timetable = ({ user }) => {
return false;
}
console.log(target.innerHTML);
// turn off editable
setEditable(false);
// empty marks
marks.length = 0;
const table = target.children[0];
table.setAttribute("border", "1");
@@ -105,7 +129,7 @@ const Timetable = ({ user }) => {
// mount click event
const input = document.createElement("input");
input.setAttribute("type", "checkbox");
input.setAttribute("type", replaceInputType);
input.onchange = handleSelect;
input.name = index;
td.innerHTML = "";
@@ -115,6 +139,7 @@ const Timetable = ({ user }) => {
row.push(input);
}
marks.push(row);
// console.log("marks", marks);
}
// resolve conflicts
@@ -156,13 +181,15 @@ const Timetable = ({ user }) => {
}
};
React.useEffect(() => {
if (disableNetwork) return;
const interval = setInterval(() => {
refresh();
}, 1000);
return () => {
clearInterval(interval);
};
});
}, []);
React.useEffect(() => {
const main = async () => {
@@ -176,7 +203,27 @@ const Timetable = ({ user }) => {
return (
<>
<button onClick={refresh}>Test</button>
<button
onClick={async () => {
console.log("download marks", marks);
const data = {
user,
selections: {},
};
for (const row of marks) {
for (const input of row) {
if (input === null) continue;
if (input.value !== "") {
data.selections[input.name] = parseFloat(input.value);
}
}
}
console.log(data);
downloadObjectAsJson(data, user);
}}
>
DownloadSelection
</button>
<span>Login as {user}</span>
<div
ref={ref}
@@ -186,6 +233,7 @@ const Timetable = ({ user }) => {
}}
onInput={handleInput}
></div>
<div style={{ display: "none" }} id="download-dom"></div>
</>
);
};