Commit 1c23049e authored by wyuer's avatar wyuer

adslder

parent 842fa941
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
import React from "react"; import React from "react";
import AddFolder from "@/components/AddFolder"; import AddFolder from "@/components/AddFolder";
import AddFileInfo from "@/components/AddFileInfo"; import AddFileInfo from "@/components/AddCollection";
import Cards from "@/components/Cards"; import Cards from "@/components/Cards";
import { useRequest } from "ahooks"; import { useRequest } from "ahooks";
import { getFetch } from "@/lib/doFetch"; import { getFetch } from "@/lib/doFetch";
......
// RESTFUl api 匹配带路由参数
import response from "@/lib/res";
import prisma from "@/lib/prisma";
// R -> Read One
export async function GET(request, { params }) {
const slug = params.slug;
try {
const collection = await prisma.collection.findUnique({
where: {
id: parseInt(slug),
},
include: {
folder: true,
},
});
return response(collection);
} catch (error) {
return response(error, "err");
}
}
//U -> Update
export async function PUT(request, { params }) {
const body = await request.json();
const slug = params.slug;
try {
const res = await prisma.collection.update({
where: { id: parseInt(slug) },
data: { ...body },
});
return response({ ...res },"更新成功");
} catch (error) {
return response(error, "err");
}
}
//D -> Delete
export async function DELETE(request, { params }) {
const slug = params.slug;
try {
const res = await prisma.collection.delete({
where: { id: parseInt(slug) },
});
return response({ ...res },'删除成功');
} catch (error) {
return response(error, "err");
}
}
// RESTFUl api 匹配无路由参数
import prisma from "@/lib/prisma";
import response from "@/lib/res";
// C -> Create
export async function POST(request) {
const body = await request.json();
//获取body参数
const res = await prisma.collection.create({
data: { ...body },
});
return response({ ...res }, "新建成功");
}
// R -> Read
export async function GET(request, { params }) {
// query is "hello" for /api/search?query=hello
// const slug = params.slug; // 路由参数
try {
const collections = await prisma.collection.findMany({
where: {
parentId: null, // 根目录
},
include: {
folder: true,
},
});
return response(collections);
} catch (error) {
return response(error, "err");
}
}
...@@ -26,9 +26,11 @@ export async function GET(request, { params }) { ...@@ -26,9 +26,11 @@ export async function GET(request, { params }) {
}, },
include: { include: {
collections: true, collections: true,
folders: true, folders: true
}, }
}); });
return response(folders); return response(folders);
} catch (error) { } catch (error) {
return response(error, "err"); return response(error, "err");
......
"use client";
import { getFetch } from "@/lib/doFetch";
import { useRequest } from "ahooks";
import { Button } from "@nextui-org/react";
import { ArrowLeftOutlined } from "@ant-design/icons";
import EditFolder from "@/components/EditFolder";
import DeleteFolder from "@/components/DeleteFolder";
import { useRouter } from "next/navigation";
const columns = [
{ name: "code", label: "编码" },
{ name: "faultType", label: "故障类型" },
{ name: "fault", label: "故障" },
{ name: "faultJudge", label: "判断条件" },
{ name: "faultReason", label: "故障原因" },
{ name: "faultFn", label: "解决方案" },
{ name: "faultMessage", label: "故障描述" },
];
export default function Detail({ params }) {
//params.slug 路由传参获取
const router = useRouter();
const { data, refreshAsync } = useRequest(
async () => {
let res = await getFetch({
url: "/api/collection/" + params.slug,
params: {},
});
return res?.data;
},
{
refreshDeps: [params.slug],
}
);
return (
<div className="flex w-full flex-col">
<div className="flex gap-4">
<Button
isIconOnly
color="primary"
variant="faded"
aria-label="Take a add"
onPress={() => {
router.back();
}}
>
<ArrowLeftOutlined></ArrowLeftOutlined>
</Button>
<Button color="primary" variant="flat">
{data?.name}
</Button>
<EditFolder data={data} refresh={refreshAsync}/>
<DeleteFolder data={data} refresh={refreshAsync}/>
</div>
<ul class="divide-y divide-gray-200">
{columns?.map((it) => {
return (
<li class="flex items-center py-4" key={it?.name}>
<div class="ml-4">
<div class="text-sm font-medium text-gray-900">{it?.label}</div>
<div class="text-sm text-gray-500">{data?.[it?.name]}</div>
</div>
</li>
);
})}
</ul>
</div>
);
}
...@@ -8,7 +8,11 @@ import { ArrowLeftOutlined } from "@ant-design/icons"; ...@@ -8,7 +8,11 @@ import { ArrowLeftOutlined } from "@ant-design/icons";
import EditFolder from "@/components/EditFolder"; import EditFolder from "@/components/EditFolder";
import DeleteFolder from "@/components/DeleteFolder"; import DeleteFolder from "@/components/DeleteFolder";
import AddFolder from "@/components/AddFolder"; import AddFolder from "@/components/AddFolder";
import AddCollection from '@/components/AddCollection';
import Cards from "@/components/Cards"; import Cards from "@/components/Cards";
import Collections from "@/components/Collections";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
export default function Detail({ folder, params }) { export default function Detail({ folder, params }) {
...@@ -72,10 +76,16 @@ export default function Detail({ folder, params }) { ...@@ -72,10 +76,16 @@ export default function Detail({ folder, params }) {
type={"icon"} type={"icon"}
></AddFolder> ></AddFolder>
<Divider orientation="vertical" /> <Divider orientation="vertical" />
<AddCollection
refresh={refreshAsync}
parentId={params.slug}
type={"icon"}
/>
</div> </div>
<div className="mt-8"> <div className="mt-8 flex flex-wrap gap-2">
<Cards list={data?.folders ?? []}></Cards> <Cards list={data?.folders ?? []}></Cards>
<Collections list={data?.collections ?? []}></Collections>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -2,8 +2,10 @@ ...@@ -2,8 +2,10 @@
import React from "react"; import React from "react";
import AddFolder from "@/components/AddFolder"; import AddFolder from "@/components/AddFolder";
import AddFileInfo from "@/components/AddFileInfo"; import AddCollection from "@/components/AddCollection";
import Cards from "@/components/Cards"; import Cards from "@/components/Cards";
import Collections from "@/components/Collections";
import { useRequest } from "ahooks"; import { useRequest } from "ahooks";
import { getFetch } from "@/lib/doFetch"; import { getFetch } from "@/lib/doFetch";
...@@ -14,13 +16,20 @@ export default function Home(props) { ...@@ -14,13 +16,20 @@ export default function Home(props) {
return res?.data ?? []; return res?.data ?? [];
}); });
const collection = useRequest(async () => {
const res = await getFetch({ url: "/api/collection", params: {} });
return res?.data ?? [];
});
return ( return (
<div> <div>
<div className="flex gap-4"> <div className="flex gap-4">
<AddFolder refresh={refreshAsync} /> <AddFolder refresh={refreshAsync} />
<AddFileInfo refresh={refreshAsync} /> <AddCollection refresh={collection?.refreshAsync} />
</div> </div>
<div className="flex gap-4">
<Cards list={data ?? []} /> <Cards list={data ?? []} />
<Collections list={collection?.data ?? []} />
</div>
</div> </div>
); );
} }
...@@ -17,7 +17,7 @@ export function Providers({ children }) { ...@@ -17,7 +17,7 @@ export function Providers({ children }) {
return ( return (
<NextUIProvider navigate={router.push}> <NextUIProvider navigate={router.push}>
<div className="flex w-full flex-col mb-4"> {/* <div className="flex w-full flex-col mb-4">
<Tabs <Tabs
aria-label="Options" aria-label="Options"
radius={"full"} radius={"full"}
...@@ -30,11 +30,8 @@ export function Providers({ children }) { ...@@ -30,11 +30,8 @@ export function Providers({ children }) {
<Tab key="/" title={"首页"}></Tab> <Tab key="/" title={"首页"}></Tab>
<Tab key="/login" title={"login"}></Tab> <Tab key="/login" title={"login"}></Tab>
<Tab key="/detail" title={"detail"}></Tab> <Tab key="/detail" title={"detail"}></Tab>
</Tabs> </Tabs>
</div> </div> */}
{/* <Link href="/">首页</Link>
<Link href="/detail">DOC</Link> */}
{children} {children}
</NextUIProvider> </NextUIProvider>
); );
......
import React from "react";
import {
Modal,
ModalContent,
ModalHeader,
ModalBody,
ModalFooter,
Button,
useDisclosure,
Input,
Avatar,
Textarea,
} from "@nextui-org/react";
import { AiFillPlusSquare } from "react-icons/ai";
import { useForm } from "react-hook-form";
import { doFetch } from "@/lib/doFetch";
import UploadImage from "./UploadImage";
export default function AddCollection({ refresh, parentId, type }) {
const { isOpen, onOpen, onOpenChange } = useDisclosure();
const { register, handleSubmit, control, setValue } = useForm();
const handleButtonClick = async (close) => {
// 手动触发表单提交
handleSubmit(onSubmit)();
await refresh();
close();
};
const onSubmit = async (data) => {
return await doFetch({
url: "/api/collection",
params: { ...data, parentId:parentId ?parseInt(parentId): null },
});
};
return (
<>
{type === "icon" ? (
<Button
isIconOnly
color="primary"
variant="faded"
aria-label="Take a add"
onPress={onOpen}
>
<AiFillPlusSquare style={{ fontSize: "20px" }} />
</Button>
) : (
<Button
radius="full"
className="bg-gradient-to-tr from-green-500 to-blue-500 text-white shadow-lg mb-4"
onPress={onOpen}
>
<AiFillPlusSquare />
添加知识库
</Button>
)}
<Modal
isOpen={isOpen}
backdrop={"blur"}
onOpenChange={onOpenChange}
motionProps={{
variants: {
enter: {
y: 0,
opacity: 1,
transition: {
duration: 0.3,
ease: "easeOut",
},
},
exit: {
y: -20,
opacity: 0,
transition: {
duration: 0.2,
ease: "easeIn",
},
},
},
}}
>
<ModalContent>
{(onClose) => (
<>
<ModalHeader className="flex flex-col gap-1">
添加知识库
</ModalHeader>
<ModalBody>
<form action="" className="flex flex-col gap-4">
<Input
type="text"
label="知识库名称"
name="name"
isRequired
{...register("name", { required: true, maxLength: 20 })}
/>
<Input
type="text"
label="编码"
name="code"
{...register("code", { required: true, maxLength: 20 })}
/>
<Input
type="text"
label="故障类型"
name="faultType"
{...register("faultType", {
required: true,
maxLength: 20,
})}
/>
<Input
type="text"
label="故障"
name="fault"
{...register("fault", { required: true, maxLength: 20 })}
/>
<Textarea
type="text"
label="判断条件"
name="faultJudge"
{...register("faultJudge", {
required: true,
maxLength: 20,
})}
/>
<Textarea
type="text"
label="故障原因"
name="faultReason"
{...register("faultReason", {
required: true,
maxLength: 20,
})}
/>
<Textarea
type="text"
label="解决方案"
name="faultFn"
{...register("faultFn", { required: true, maxLength: 20 })}
/>
<Textarea
type="text"
label="故障描述"
name="faultMessage"
{...register("faultMessage", {
required: true,
maxLength: 20,
})}
/>
</form>
</ModalBody>
<ModalFooter>
<Button color="danger" variant="light" onPress={onClose}>
取消
</Button>
<Button
color="primary"
onPress={() => {
handleButtonClick(onClose);
}}
>
提交
</Button>
</ModalFooter>
</>
)}
</ModalContent>
</Modal>
</>
);
}
...@@ -16,7 +16,7 @@ export default memo(({ list }) => { ...@@ -16,7 +16,7 @@ export default memo(({ list }) => {
{list?.map?.((item, index) => ( {list?.map?.((item, index) => (
<Card <Card
shadow="sm" shadow="sm"
className="w-[170px]" className="w-[220px]"
key={index} key={index}
isPressable isPressable
onPress={() => { onPress={() => {
...@@ -30,7 +30,7 @@ export default memo(({ list }) => { ...@@ -30,7 +30,7 @@ export default memo(({ list }) => {
radius="lg" radius="lg"
width="100%" width="100%"
alt={item.name} alt={item.name}
className="w-full object-cover h-[140px]" className="w-full object-cover h-[180px]"
src={item.poster} src={item.poster}
fallbackSrc="/folder.png" fallbackSrc="/folder.png"
/> />
......
/* eslint-disable import/no-anonymous-default-export */
/* eslint-disable react/display-name */
import React, { memo } from "react";
import { Card, CardBody, CardFooter, Image, Button } from "@nextui-org/react";
import { difftime } from "@/lib/time";
import { useRouter } from "next/navigation";
export default memo(({ list }) => {
const router = useRouter();
return (
<div className="gap-2 flex flex-wrap">
{list?.map?.((item, index) => (
<Card
shadow="sm"
className="w-[220px]"
key={index}
isPressable
onPress={() => {
router.push("/collectiondetail/" + item.id);
}}
>
<CardBody className="overflow-visible p-0">
<div
className="w-full object-cover h-[180px] flex justify-center items-center bg-gradient-to-r from-cyan-500 to-blue-500"
>
<span className="bg-clip-text text-transparent text-white text-lg">
{item?.name?.substring(0,4).toUpperCase()}
</span>
</div>
</CardBody>
<CardFooter className="text-small justify-between">
<b>{item.name}</b>
<p className="text-default-500">{difftime(item.createdAt)}</p>
</CardFooter>
</Card>
))}
</div>
);
});
import React from "react"; import React, { useEffect } from "react";
import { import {
Modal, Modal,
ModalContent, ModalContent,
...@@ -8,38 +8,27 @@ import { ...@@ -8,38 +8,27 @@ import {
Button, Button,
useDisclosure, useDisclosure,
Input, Input,
Avatar,
} from "@nextui-org/react"; } from "@nextui-org/react";
import { AiFillPlusSquare } from "react-icons/ai"; import { useForm, Controller } from "react-hook-form";
import { useForm } from "react-hook-form"; import { delFetch, doFetch, putFetch } from "@/lib/doFetch";
import { doFetch } from "@/lib/doFetch";
import UploadImage from "./UploadImage"; import UploadImage from "./UploadImage";
import { BsTrash3Fill } from "react-icons/bs";
import { useRouter } from "next/navigation";
export default function AddFileInfo({refresh}) { export default function DeleteFolder({ refresh, data }) {
const { isOpen, onOpen, onOpenChange } = useDisclosure(); const { isOpen, onOpen, onOpenChange } = useDisclosure();
const { register, handleSubmit, control, setValue } = useForm(); const router = useRouter();
const handleButtonClick = async (close) => { const handleButtonClick = async (close) => {
// 手动触发表单提交 await delFetch({url:"/api/folder/"+data.id})
handleSubmit(onSubmit)(); router.back(); // 返回上一页
await refresh();
close();
}; };
const onSubmit = async (data) => {
return await doFetch({ url: "/api/folder", params: data });
};
return ( return (
<> <>
<Button <Button isIconOnly color="danger" aria-label="Like" onPress={onOpen}>
radius="full" <BsTrash3Fill style={{ fontSize: "18px" }} />
className="bg-gradient-to-tr from-green-500 to-blue-500 text-white shadow-lg mb-4"
onPress={onOpen}
>
<AiFillPlusSquare />
添加文件
</Button> </Button>
<Modal <Modal
isOpen={isOpen} isOpen={isOpen}
...@@ -70,37 +59,25 @@ export default function AddFileInfo({refresh}) { ...@@ -70,37 +59,25 @@ export default function AddFileInfo({refresh}) {
{(onClose) => ( {(onClose) => (
<> <>
<ModalHeader className="flex flex-col gap-1"> <ModalHeader className="flex flex-col gap-1">
添加文件 是否删除该文件夹
</ModalHeader> </ModalHeader>
<ModalBody> <ModalBody>
<form action=""> <p>
<input type="hidden" {...register("poster")} /> 仅可删除空文件夹
<div className="flex justify-center items-center flex-col mb-8"> </p>
<UploadImage
control={control}
setValue={setValue}
></UploadImage>
</div>
<Input
type="text"
label="文件夹"
name="name"
{...register("name", { required: true, maxLength: 20 })}
/>
</form>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button color="danger" variant="light" onPress={onClose}> <Button color="danger" variant="light" onPress={onClose}>
取消 取消
</Button> </Button>
<Button <Button
color="primary" color="danger"
onPress={() => { onPress={() => {
handleButtonClick(onClose); handleButtonClick(onClose);
}} }}
> >
提交 删除
</Button> </Button>
</ModalFooter> </ModalFooter>
</> </>
......
import React from "react";
import {
Modal,
ModalContent,
ModalHeader,
ModalBody,
ModalFooter,
Button,
useDisclosure,
Input,
Avatar,
Textarea,
} from "@nextui-org/react";
import { AiFillPlusSquare } from "react-icons/ai";
import { useForm } from "react-hook-form";
import { doFetch } from "@/lib/doFetch";
import UploadImage from "./UploadImage";
export default function AddCollection({ refresh, parentId, type }) {
const { isOpen, onOpen, onOpenChange } = useDisclosure();
const { register, handleSubmit, control, setValue } = useForm();
const handleButtonClick = async (close) => {
// 手动触发表单提交
handleSubmit(onSubmit)();
await refresh();
close();
};
const onSubmit = async (data) => {
return await doFetch({
url: "/api/collection",
params: { ...data, parentId:parentId ?parseInt(parentId): null },
});
};
return (
<>
{type === "icon" ? (
<Button
isIconOnly
color="primary"
variant="faded"
aria-label="Take a add"
onPress={onOpen}
>
<AiFillPlusSquare style={{ fontSize: "20px" }} />
</Button>
) : (
<Button
radius="full"
className="bg-gradient-to-tr from-green-500 to-blue-500 text-white shadow-lg mb-4"
onPress={onOpen}
>
<AiFillPlusSquare />
添加知识库
</Button>
)}
<Modal
isOpen={isOpen}
backdrop={"blur"}
onOpenChange={onOpenChange}
motionProps={{
variants: {
enter: {
y: 0,
opacity: 1,
transition: {
duration: 0.3,
ease: "easeOut",
},
},
exit: {
y: -20,
opacity: 0,
transition: {
duration: 0.2,
ease: "easeIn",
},
},
},
}}
>
<ModalContent>
{(onClose) => (
<>
<ModalHeader className="flex flex-col gap-1">
添加知识库
</ModalHeader>
<ModalBody>
<form action="" className="flex flex-col gap-4">
<Input
type="text"
label="知识库名称"
name="name"
isRequired
{...register("name", { required: true, maxLength: 20 })}
/>
<Input
type="text"
label="编码"
name="code"
{...register("code", { required: true, maxLength: 20 })}
/>
<Input
type="text"
label="故障类型"
name="faultType"
{...register("faultType", {
required: true,
maxLength: 20,
})}
/>
<Input
type="text"
label="故障"
name="fault"
{...register("fault", { required: true, maxLength: 20 })}
/>
<Textarea
type="text"
label="判断条件"
name="faultJudge"
{...register("faultJudge", {
required: true,
maxLength: 20,
})}
/>
<Textarea
type="text"
label="故障原因"
name="faultReason"
{...register("faultReason", {
required: true,
maxLength: 20,
})}
/>
<Textarea
type="text"
label="解决方案"
name="faultFn"
{...register("faultFn", { required: true, maxLength: 20 })}
/>
<Textarea
type="text"
label="故障描述"
name="faultMessage"
{...register("faultMessage", {
required: true,
maxLength: 20,
})}
/>
</form>
</ModalBody>
<ModalFooter>
<Button color="danger" variant="light" onPress={onClose}>
取消
</Button>
<Button
color="primary"
onPress={() => {
handleButtonClick(onClose);
}}
>
提交
</Button>
</ModalFooter>
</>
)}
</ModalContent>
</Modal>
</>
);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment