This commit is contained in:
2023-02-16 22:57:46 +08:00
parent 4bbdac8abe
commit 4ebe5026ed
6 changed files with 99 additions and 20 deletions

2
.gitignore vendored
View File

@@ -1,6 +1,8 @@
/html.html /html.html
/json /json
/hours.json /hours.json
/regular.json
/record.json
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies # dependencies

View File

@@ -11,10 +11,15 @@ interface ConflictsTmp {
interface IndexToElement { interface IndexToElement {
[index: string]: HTMLInputElement; [index: string]: HTMLInputElement;
} }
interface IndexToCell {
[index: string]: HTMLTableCellElement;
}
const indexToElement: IndexToElement = {}; const indexToElement: IndexToElement = {};
const indexToCell: IndexToCell = {};
const conflicts: Conflicts = {}; const conflicts: Conflicts = {};
const marks: (HTMLInputElement | null)[][] = []; const marks: (HTMLInputElement | null)[][] = [];
const tds: (HTMLTableCellElement | null)[][] = [];
const downloadObjectAsJson = (exportObj: any, exportName: string) => { const downloadObjectAsJson = (exportObj: any, exportName: string) => {
const dataStr = const dataStr =
@@ -33,6 +38,8 @@ const Timetable = ({
disableNetwork = false, disableNetwork = false,
disableConflictCheck = false, disableConflictCheck = false,
replaceInputType = "checkbox", replaceInputType = "checkbox",
apiRecordEndPoint = "/api/record",
openRecordMode = false,
}) => { }) => {
const [editable, setEditable] = React.useState(true); const [editable, setEditable] = React.useState(true);
const ref = React.useRef(); const ref = React.useRef();
@@ -102,6 +109,8 @@ const Timetable = ({
// empty marks // empty marks
marks.length = 0; marks.length = 0;
// empty tds
tds.length = 0;
const table = target.children[0]; const table = target.children[0];
table.setAttribute("border", "1"); table.setAttribute("border", "1");
@@ -112,8 +121,9 @@ const Timetable = ({
for (const tr_index in tbody.children) { for (const tr_index in tbody.children) {
const tr = tbody.children[tr_index]; const tr = tbody.children[tr_index];
const row: (HTMLInputElement | null)[] = []; const row: (HTMLInputElement | null)[] = [];
const rowTD: (HTMLTableCellElement | null)[] = [];
for (const td_index in tr.children) { for (const td_index in tr.children) {
const td = tr.children[td_index]; const td: HTMLTableCellElement = tr.children[td_index];
if (td.tagName !== "TD") continue; if (td.tagName !== "TD") continue;
if (td.getAttribute("bgcolor")?.toUpperCase() !== "#39CEFF") { if (td.getAttribute("bgcolor")?.toUpperCase() !== "#39CEFF") {
row.push(null); row.push(null);
@@ -135,10 +145,13 @@ const Timetable = ({
td.innerHTML = ""; td.innerHTML = "";
td.appendChild(input); td.appendChild(input);
indexToElement[index] = input; indexToElement[index] = input;
indexToCell[index] = td;
row.push(input); row.push(input);
rowTD.push(td);
} }
marks.push(row); marks.push(row);
tds.push(rowTD);
// console.log("marks", marks); // console.log("marks", marks);
} }
@@ -159,7 +172,20 @@ const Timetable = ({
}; };
const refresh = async () => { const refresh = async () => {
const json = await get(`/api/record?name=${user}`); const json = await get(`${apiRecordEndPoint}?name=${user}`);
if (openRecordMode) {
for (const index in json) {
const input = indexToElement[index];
const td= indexToCell[index];
if (json[index] !== user) {
td.innerHTML = json[index]
} else {
input.checked = true;
input.disabled = true;
}
}
return;
}
const occupied: string[] = json.occupied; const occupied: string[] = json.occupied;
const myselect: string[] = json.myselect; const myselect: string[] = json.myselect;
console.log(json); console.log(json);
@@ -172,6 +198,7 @@ const Timetable = ({
const includes = myselect.includes(index); const includes = myselect.includes(index);
indexToElement[index].checked = includes; indexToElement[index].checked = includes;
// after checked, find conflicts input // after checked, find conflicts input
if (disableConflictCheck) continue;
if (includes) { if (includes) {
for (const input of conflicts[index]) { for (const input of conflicts[index]) {
if (input.name === index) continue; if (input.name === index) continue;
@@ -232,7 +259,7 @@ const Timetable = ({
overflow: "scroll", overflow: "scroll",
}} }}
onInput={handleInput} onInput={handleInput}
></div> ></div>{" "}
<div style={{ display: "none" }} id="download-dom"></div> <div style={{ display: "none" }} id="download-dom"></div>
</> </>
); );

View File

@@ -1,4 +1,6 @@
export default { const obj = {
begin: false, begin: false,
limit: 2, limit: 2,
} token: process.env.TOKEN || "woshimima",
};
export default obj;

16
pages/api/regular.ts Normal file
View File

@@ -0,0 +1,16 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { regular } from "@/store";
import config from "@/config";
export default function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === "POST") {
if (req.headers.token !== config.token) {
res.status(403).json({
error: "wrong token",
});
return;
}
regular.update(req.body);
}
res.status(200).json(regular.get());
}

32
pages/regular.tsx Normal file
View File

@@ -0,0 +1,32 @@
import React from "react";
import Head from "next/head";
import Timetable from "@/components/Timetable";
import UserInputWrap from "@/components/UserInputWrap";
const ReportPage = () => {
const [user, setUser] = React.useState("");
const [begin, setBegin] = React.useState(false);
return (
<>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main>
<UserInputWrap setUser={setUser}>
<Timetable
user={user}
disableConflictCheck={true}
disableNetwork={true}
apiRecordEndPoint="/api/regular"
openRecordMode={true}
/>
</UserInputWrap>
</main>
</>
);
};
export default ReportPage;

View File

@@ -1,4 +1,4 @@
import fs from "fs"; import fs, { readFileSync } from "fs";
import { MongoClient } from "mongodb"; import { MongoClient } from "mongodb";
import util from "util"; import util from "util";
@@ -6,9 +6,15 @@ const write = util.promisify(fs.writeFile);
const read = util.promisify(fs.readFile); const read = util.promisify(fs.readFile);
class Store { class Store {
filename: string;
record: Record<string, string>; record: Record<string, string>;
constructor() { constructor(filename: string) {
this.record = {}; this.filename = filename;
try {
this.record = JSON.parse(readFileSync(filename, "utf8"));
} catch {
this.record = {};
}
} }
public get() { public get() {
return this.record; return this.record;
@@ -19,15 +25,8 @@ class Store {
public delete(key: string) { public delete(key: string) {
delete this.record[key]; delete this.record[key];
} }
public update(record: Record<string, string>) { public async update(record: Record<string, string>) {
for (const key in record) { await write(this.filename, JSON.stringify(this.record), "utf8");
this.record[key] = record[key];
}
for (const key in this.record) {
if (record[key] === undefined) {
delete this.record[key];
}
}
} }
} }
@@ -52,4 +51,5 @@ class HTML {
} }
export const html = new HTML(); export const html = new HTML();
export const store = new Store(); export const store = new Store("store.json");
export const regular = new Store("regular.json");