Skip to content

Commit

Permalink
refactor: 抽出 ProfessionTable
Browse files Browse the repository at this point in the history
  • Loading branch information
huayemao committed Jun 23, 2024
1 parent 35021d4 commit ad18963
Show file tree
Hide file tree
Showing 7 changed files with 408 additions and 325 deletions.
77 changes: 62 additions & 15 deletions app/(content)/data-process/DBContext.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,33 @@
"use client";
import * as Comlink from "comlink";
import { createContext, useEffect, useState } from "react";
import {
createContext,
useCallback,
useContext,
useEffect,
useState,
} from "react";

export const DBContext = createContext<{
state: { dbWorker: Comlink.Remote<WorkerProxy> | null };
state: {
dbWorker: Comlink.Remote<WorkerProxy> | null;
activeDb: string | null;
dbs: string[];
baseTables: any[];
};
actions: {
refetch: () => void;
setActiveDb: (db: string) => void;
};
}>({
state: { dbWorker: null },
state: { dbWorker: null, dbs: [], baseTables: [], activeDb: null },
actions: {
refetch() {
{
}
},
setActiveDb() {},
},
});

interface WorkerProxy {
Expand All @@ -23,9 +45,15 @@ interface WorkerProxy {
}

export function DBContextProvider({ children }) {
const getTableSql = `select * from sqlite_schema where type = 'table';`;

const [dbWorker, setDbWorker] = useState<Comlink.Remote<WorkerProxy> | null>(
null
);
const [dbs, setDbs] = useState<string[]>([]);
const [activeDb, setActiveDb] = useState<string | null>(null);
const [baseTables, setBaseTables] = useState<any[]>([]);

// const [query, setQuery] = useState<any>("")
let needsSetup = true;

Expand All @@ -34,31 +62,50 @@ export function DBContextProvider({ children }) {
needsSetup = false;
const _dbWorker = new Worker(new URL("dbworker.js", import.meta.url));
const Myclass = Comlink.wrap<WorkerProxy>(_dbWorker);
new Myclass().then((_i) => {
setDbWorker(() => _i);
});
new Myclass()
.then((instance) => {
setDbWorker(() => instance);
return instance;
})
.then((instance) => {
instance.getDbs().then((dbs) => setDbs(dbs.map(decodeURIComponent)));
});
}
}, []);

let needFileWritten = true;
useEffect(() => {
if (needFileWritten) {
needFileWritten = false;
const _fileWorker = new Worker(new URL("fileworker.js", import.meta.url));
_fileWorker.postMessage(`this is a long text string.
Actually not that long.
But long enough to do a quick test.
`);
if (activeDb) {
const name = encodeURIComponent(activeDb);
dbWorker?.readWriteDB?.(name);
dbWorker?.execSql(getTableSql).then(setBaseTables);
}
}, [activeDb]);

const refetch = useCallback(async () => {
const dbs = await dbWorker?.getDbs();
if (!dbs) {
return setDbs([]);
}
setDbs(dbs.map(decodeURIComponent));
}, []);

// create the value for the context provider
const context = {
state: {
dbWorker,
dbs: dbs,
baseTables,
activeDb,
},
actions: {
refetch,
setActiveDb,
},
actions: {},
};

return <DBContext.Provider value={context}>{children}</DBContext.Provider>;
}

export const useDBContext = () => {
return useContext(DBContext);
};
94 changes: 94 additions & 0 deletions app/(content)/data-process/ProfessionTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
"use client";
import { useCallback, useEffect, useState } from "react";
import { useDBContext } from "./DBContext";
import { Table } from "./Table";
import { Field, JobGroup, Profession } from "./types";
import { parseProfessionJobCount } from "./util";

export function ProfessionTable() {
const {
state: { dbWorker, activeDb, baseTables },
} = useDBContext();

const [data, setData] = useState<any[]>();

const parseAlltables = useCallback(async () => {
const jobTables: string[] = [];
for (const { name: tableName } of baseTables) {
console.log(dbWorker);
const cols = (await dbWorker!.execSql(
`PRAGMA table_info(${tableName});`
)) as Field[];
console.log(cols);

if (
["职位代码", "专业要求"].every((s) =>
cols.map((e) => e.name).includes(s)
)
) {
jobTables.push(tableName);
}
}

return await Promise.all(jobTables.map(parseTable));

async function parseTable(tableName: string) {
let jobGroupsByProfession: JobGroup[] = [];
let professions: Profession[] = [];
const professionsSql = `select '${tableName}' as tableName,count(*) as cnt, 专业要求, GROUP_CONCAT(职位代码) AS ids from ${tableName} group by 专业要求 having 学历要求 like '%本科%' order by cnt desc;`;

return dbWorker
?.execSql(professionsSql)
.then((res) => (jobGroupsByProfession = res))
.then(() => dbWorker?.execSql(`select * from 本科专业目录;`))
.then((res) => {
professions = res.filter(
(e) => !["▲", "★"].some((s) => JSON.stringify(e).includes(s))
);
})
.then(() => {
console.log(jobGroupsByProfession);
jobGroupsByProfession.forEach(parseProfessionJobCount(professions));
return professions;
});
}
}, [dbWorker]);

useEffect(() => {
if (!dbWorker) {
return;
}

parseAlltables().then((res) => {
console.log(res);
setData(res[0]);
// const baseCnt = jobGroupsByProfession.find(
// (e) => e.专业要求 == "不限"
// )?.cnt;
// console.log(baseCnt);
// console.log(
// `红牌专业 ${professions.filter((e) => e.岗位数 == baseCnt).length}`
// );
// console.table(
// professions
// .sort((a, b) => a.岗位数 - b.岗位数)
// .slice(0, 100)
// .map((e) => ({
// ...e,
// 除不限外岗位数: e.岗位数 - (baseCnt || 0),
// }))
// );
// console.log("top 100");
// console.log(
// professions
// .sort((a, b) => b.岗位数 - a.岗位数)
// .map((e) => ({
// ...e,
// 除不限外岗位数: e.岗位数 - (baseCnt || 0),
// }))
// );
});
}, [dbWorker]);

return <>{data && <Table data={data.slice(0, 50)}></Table>}</>;
}
108 changes: 108 additions & 0 deletions app/(content)/data-process/Table.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
"use client";
import { ActionDropdown } from "@/components/ActionDropdown";
import { isValidURL } from "@/lib/utils";
import mime from "mime";
import { useEffect, useMemo } from "react";

export function Table({ data }: { data: any[]; }) {
const tableData = useMemo(() => {
const headers = Object.keys(data[0]);
const rows = data;
return { headers, rows };
}, [data]);

const isEllipsisActive = (e) => {
return e.offsetWidth < e.scrollWidth;
};

useEffect(() => {
document
.querySelectorAll("table [data-nui-tooltip] .overflow-ellipsis")
.forEach((e) => {
if (!isEllipsisActive(e)) {
e.parentElement!.removeAttribute("data-nui-tooltip");
}
});
}, [data]);

return (
<table className="w-full overflow-x-auto whitespace-nowrap">
<colgroup>
{tableData.headers.map((e) => (
<col className="w-[20%]" key={e}></col>
))}
</colgroup>
<thead>
<tr className="bg-muted-50 dark:bg-muted-900">
{tableData.headers.map((e) => (
<th
className="bg-transparent py-4 px-3 text-start font-sans text-xs font-medium uppercase text-muted-400 tracking-wide "
key={e}
>
<div
data-nui-tooltip={e}
className="max-w-[8em] min-w-[4em] overflow-hidden overflow-ellipsis"
>
{e}
</div>
</th>
))}
<th className="bg-transparent py-4 px-3 text-start font-sans text-xs font-medium uppercase text-muted-400 tracking-wide ">
操作
</th>
</tr>
</thead>
<tbody>
{tableData.rows.map((e, i) => {
return (
<tr
className="border-b border-muted-200 transition-colors duration-300 last:border-none hover:bg-muted-200/40 dark:border-muted-800 dark:hover:bg-muted-900/60"
key={i}
>
{Object.entries(e).map(([key, value], i) => {
if (isValidURL(value) &&
mime.getType(value as string)?.startsWith("image")) {
return (
<td
data-nui-tooltip={value}
valign="middle"
className="border-t border-muted-200 py-4 px-3 font-sans font-normal dark:border-muted-800 text-sm text-muted-400 dark:text-muted-500"
key={key}
>
<img
src={("/api/files?href=" + value) as string}
crossOrigin=""
className="w-36 max-w-[9rem] h-auto object-contain" />
</td>
);
}
return (
<td
valign="middle"
className="border-t border-muted-200 py-4 px-3 font-sans font-normal dark:border-muted-800 text-sm text-muted-400 dark:text-muted-500"
key={key}
>
<div data-nui-tooltip={value}>
<span className="inline-block max-w-[8em] min-w-[4em] overflow-hidden overflow-ellipsis">
{value as string}
</span>
</div>
</td>
);
})}

<td
valign="middle"
className="border-t border-muted-200 py-4 px-3 font-sans font-normal dark:border-muted-800 text-sm text-muted-400 dark:text-muted-500"
>
<ActionDropdown>
<></>
</ActionDropdown>
</td>
</tr>
);
})}
</tbody>
</table>
);
}
27 changes: 0 additions & 27 deletions app/(content)/data-process/fileworker.js

This file was deleted.

Loading

0 comments on commit ad18963

Please sign in to comment.