Skip to content

Commit

Permalink
feat: 优化数据处理页面 table 样式、自动获取表名和列名
Browse files Browse the repository at this point in the history
  • Loading branch information
huayemao committed Jun 21, 2024
1 parent e464631 commit 8f27306
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 72 deletions.
175 changes: 114 additions & 61 deletions app/(content)/data-process/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"use client";
import { ActionDropdown } from "@/components/ActionDropdown";
import { isValidURL } from "@/lib/utils";
import {
BaseButton,
Expand All @@ -13,6 +14,15 @@ import mime from "mime";
import { useContext, useEffect, useMemo, useState } from "react";
import { DBContext } from "./DBContext";

interface Field {
cid: number;
name: string;
type?: string; // TypeScript 中的 ? 表示该属性是可选的
notnull: number;
dflt_value: any; // 使用 any 类型来表示可以是任何值,包括 null
pk: number;
}

export default function Home() {
const {
state: { dbWorker },
Expand All @@ -22,6 +32,13 @@ export default function Home() {
const [error, setError] = useState("");
const [query, setQuery] = useState("");
const [dbs, setDbs] = useState<string[]>([]);
const [activeDb, setActiveDb] = useState<string>();
const [cols, setCols] = useState<Field[]>();
const [tables, setTables] = useState<any[]>();

const defaultTable = useMemo(() => {
return tables?.[0].name as string;
}, [tables]);

useEffect(() => {
if (dbWorker && !!query) {
Expand All @@ -34,6 +51,20 @@ export default function Home() {
dbWorker?.getDbs?.()?.then((dbs) => setDbs(dbs.map(decodeURIComponent)));
}, [dbWorker]);

useEffect(() => {
if (activeDb) {
const name = encodeURIComponent(activeDb);
dbWorker?.readWriteDB?.(name);
dbWorker
?.execSql(`select * from sqlite_schema where type = 'table';`)
.then(setTables);
}
}, [activeDb]);

useEffect(() => {
dbWorker?.execSql(`PRAGMA table_info(${defaultTable})`).then(setCols);
}, [defaultTable]);

const tableData = useMemo(() => {
const headers = lines.length ? Object.keys(lines[0]) : [];
const rows = lines;
Expand All @@ -51,11 +82,7 @@ export default function Home() {
title={e}
end={
<div className="flex items-center gap-4">
<BaseButton
onClick={() => {
dbWorker?.readWriteDB?.(encodeURIComponent(e));
}}
>
<BaseButton onClick={() => e != activeDb && setActiveDb(e)}>
选择
</BaseButton>
<BaseButtonClose
Expand Down Expand Up @@ -94,80 +121,106 @@ export default function Home() {
<pre>
select * from sqlite_schema;
<br />
select * from 测试 limit 100;
{defaultTable && <>select * from {defaultTable} limit 20;</>}
<br />
{defaultTable && `PRAGMA table_info(${defaultTable})`}
<br />
</pre>
<br />
{cols?.map((e) => e.name)}
</BaseCard>
<BaseCard className="col-span-12">
<BaseTextarea
rows={5}
defaultValue={"select * from 测试 limit 100;"}
defaultValue={
defaultTable && `select * from ${defaultTable} limit 20;`
}
onChange={(v) => setQuery(v)}
// onInput={(e) => {
// const target = e.target as HTMLTextAreaElement;
// // console.log((e.target).value)
// setQuery(target.value);
// }}
/>
</BaseCard>
<BaseCard className="w-full overflow-x-auto col-span-12">
<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">
{lines.length ? (
<table className="w-full overflow-x-auto whitespace-nowrap">
<colgroup>
{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"
<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}
>
{e}
</div>
<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 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}
</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
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}
>
<div className="max-w-[8em] min-w-[4em] overflow-hidden overflow-ellipsis">
{value as string}
</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"
key={key}
>
<img src={'/api/files?href='+value as string} crossOrigin="" className="w-36 max-w-[9rem] h-auto object-contain"/>
<ActionDropdown>
<></>
</ActionDropdown>
</td>
}
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}
>
<div className="max-w-[8em] min-w-[4em] overflow-hidden overflow-ellipsis">
{value as string}
</div>
</td>
);
})}
</tr>
);
})}
</tbody>
</table>
</tr>
);
})}
</tbody>
</table>
) : null}
</BaseCard>
</div>

Expand Down
15 changes: 4 additions & 11 deletions app/admin/files/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import prisma from "@/lib/prisma";
import {
BaseButtonIcon,
BaseCard,
BaseDropdown,
BaseDropdownItem,
BaseList,
BaseListItem,
} from "@shuriken-ui/react";
import { EllipsisIcon, FileIcon, TrashIcon } from "lucide-react";
import { FileIcon, TrashIcon } from "lucide-react";
import { ActionDropdown } from "../../../components/ActionDropdown";
import { UploadForm } from "../../../components/UploadForm";

export default async function UploadTest() {
Expand All @@ -27,17 +26,11 @@ export default async function UploadTest() {
key={e.id}
title={e.name}
end={
<BaseDropdown
renderButton={
<BaseButtonIcon size="sm" rounded="full" className="h-5 w-5">
<EllipsisIcon></EllipsisIcon>
</BaseButtonIcon>
}
>
<ActionDropdown>
<BaseDropdownItem>
<TrashIcon></TrashIcon>
</BaseDropdownItem>
</BaseDropdown>
</ActionDropdown>
}
>
<FileIcon className="h-6 w-6"></FileIcon>
Expand Down
14 changes: 14 additions & 0 deletions components/ActionDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { BaseButtonIcon, BaseDropdown } from "@shuriken-ui/react";
import { EllipsisIcon } from "lucide-react";

export const ActionDropdown = ({ children }) => {
return (
<BaseDropdown
renderButton={<BaseButtonIcon size="sm" rounded="full" className="h-5 w-5">
<EllipsisIcon></EllipsisIcon>
</BaseButtonIcon>}
>
{children}
</BaseDropdown>
);
};

0 comments on commit 8f27306

Please sign in to comment.