更换@实现
This commit is contained in:
parent
7db3163b81
commit
d0769d91da
|
@ -0,0 +1,2 @@
|
|||
node_modules
|
||||
build
|
10
package.json
10
package.json
|
@ -3,15 +3,18 @@
|
|||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@craco/craco": "^7.1.0",
|
||||
"@material-tailwind/react": "2.0.4",
|
||||
"data-struct-js": "^0.0.15",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-router-dom": "^6.15.0",
|
||||
"react-scripts": "5.0.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"start": "craco start",
|
||||
"build": "craco build",
|
||||
"test": "craco test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
|
@ -33,6 +36,7 @@
|
|||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||
"tailwindcss": "3.3.2"
|
||||
}
|
||||
}
|
||||
|
|
155
src/App.js
155
src/App.js
|
@ -1,138 +1,29 @@
|
|||
import { Typography, Card } from "@material-tailwind/react";
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
|
||||
import Home from "@/page/Home"
|
||||
import { DefaultSpeedDial } from "@/components/DefaultSpeedDial"
|
||||
|
||||
import { DialogDefault } from "@/components/DialogDefault"
|
||||
|
||||
import { BrowserRouter, Route, Routes } from "react-router-dom"
|
||||
|
||||
export default function App() {
|
||||
const NotFound = () => {
|
||||
return <div>你来到了没有知识的荒原</div>
|
||||
}
|
||||
return (
|
||||
<div className="relative grid min-h-[100vh] w-screen p-8">
|
||||
<div className="flex flex-col-reverse items-center justify-between gap-4 self-start md:flex-row">
|
||||
<Card className="h-max w-max border border-blue-gray-50 py-4 px-5 shadow-lg shadow-blue-gray-900/5">
|
||||
<code className="text-blue-gray-900">
|
||||
Get started by editing <strong>src/App.js</strong>
|
||||
</code>
|
||||
</Card>
|
||||
<Card className="h-max w-max flex-row items-center border border-blue-gray-50 font-semibold text-blue-gray-900 shadow-lg shadow-blue-gray-900/5">
|
||||
<img src="/logo512.png" alt="React Logo" className="ml-4 h-7 w-7" />
|
||||
<div className="py-4 pl-4 pr-5">CRA Template</div>
|
||||
</Card>
|
||||
</div>
|
||||
<div className="flex-col gap-2 pt-56 pb-40 text-center">
|
||||
<Typography variant="h1" color="blue-gray">
|
||||
Material Tailwind React
|
||||
</Typography>
|
||||
<Typography variant="lead" color="blue-gray" className="opacity-70">
|
||||
An easy to use components library for Tailwind CSS and React.
|
||||
</Typography>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 gap-4 self-end md:grid-cols-2 lg:grid-cols-4">
|
||||
<a
|
||||
href="https://www.material-tailwind.com/docs/react/accordion?ref=template-cra"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Card
|
||||
shadow={false}
|
||||
className="border border-blue-gray-50 py-4 px-5 shadow-xl shadow-transparent transition-all hover:-translate-y-4 hover:border-blue-gray-100/60 hover:shadow-blue-gray-900/5"
|
||||
>
|
||||
<Typography variant="h5" color="blue-gray" className="mb-3 flex items-center gap-3">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth={2}
|
||||
stroke="currentColor"
|
||||
className="h-6 w-6"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M6.429 9.75L2.25 12l4.179 2.25m0-4.5l5.571 3 5.571-3m-11.142 0L2.25 7.5 12 2.25l9.75 5.25-4.179 2.25m0 0L21.75 12l-4.179 2.25m0 0l4.179 2.25L12 21.75 2.25 16.5l4.179-2.25m11.142 0l-5.571 3-5.571-3"
|
||||
/>
|
||||
</svg>
|
||||
Documentation
|
||||
</Typography>
|
||||
<Typography color="blue-gray" className="font-normal opacity-70">
|
||||
Find everything you need to know about Material Tailwind in our official
|
||||
documentation.
|
||||
</Typography>
|
||||
</Card>
|
||||
</a>
|
||||
<a
|
||||
href="https://www.material-tailwind.com/blocks?ref=template-cra"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Card
|
||||
shadow={false}
|
||||
className="border border-blue-gray-50 py-4 px-5 shadow-xl shadow-transparent transition-all hover:-translate-y-4 hover:border-blue-gray-100/60 hover:shadow-blue-gray-900/5"
|
||||
>
|
||||
<Typography variant="h5" color="blue-gray" className="mb-3 flex items-center gap-3">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth={2}
|
||||
stroke="currentColor"
|
||||
className="h-6 w-6"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M21 7.5l-2.25-1.313M21 7.5v2.25m0-2.25l-2.25 1.313M3 7.5l2.25-1.313M3 7.5l2.25 1.313M3 7.5v2.25m9 3l2.25-1.313M12 12.75l-2.25-1.313M12 12.75V15m0 6.75l2.25-1.313M12 21.75V19.5m0 2.25l-2.25-1.313m0-16.875L12 2.25l2.25 1.313M21 14.25v2.25l-2.25 1.313m-13.5 0L3 16.5v-2.25"
|
||||
/>
|
||||
</svg>
|
||||
Blocks
|
||||
</Typography>
|
||||
<Typography color="blue-gray" className="font-normal opacity-70">
|
||||
Ready-to-use section, like Hero, Blog, Pricing, and more, for building projects in no
|
||||
time!
|
||||
</Typography>
|
||||
</Card>
|
||||
</a>
|
||||
<a
|
||||
href="https://github.com/creativetimofficial/material-tailwind?ref=template-cra"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Card
|
||||
shadow={false}
|
||||
className="border border-blue-gray-50 py-4 px-5 shadow-xl shadow-transparent transition-all hover:-translate-y-4 hover:border-blue-gray-100/60 hover:shadow-blue-gray-900/5"
|
||||
>
|
||||
<Typography variant="h5" color="blue-gray" className="mb-3 flex items-center gap-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24">
|
||||
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
|
||||
</svg>
|
||||
Github
|
||||
</Typography>
|
||||
<Typography color="blue-gray" className="font-normal opacity-70">
|
||||
Contributions are always welcome, you can check out the Github repository for more.
|
||||
</Typography>
|
||||
</Card>
|
||||
</a>
|
||||
<a
|
||||
href="https://github.com/creativetimofficial/material-tailwind?ref=template-cra"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Card
|
||||
shadow={false}
|
||||
className="border border-blue-gray-50 py-4 px-5 shadow-xl shadow-transparent transition-all hover:-translate-y-4 hover:border-blue-gray-100/60 hover:shadow-blue-gray-900/5"
|
||||
>
|
||||
<Typography variant="h5" color="blue-gray" className="mb-3 flex items-center gap-3">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 50 50"
|
||||
width="28px"
|
||||
height="28px"
|
||||
>
|
||||
<path d="M 41.625 10.769531 C 37.644531 7.566406 31.347656 7.023438 31.078125 7.003906 C 30.660156 6.96875 30.261719 7.203125 30.089844 7.589844 C 30.074219 7.613281 29.9375 7.929688 29.785156 8.421875 C 32.417969 8.867188 35.652344 9.761719 38.578125 11.578125 C 39.046875 11.867188 39.191406 12.484375 38.902344 12.953125 C 38.710938 13.261719 38.386719 13.429688 38.050781 13.429688 C 37.871094 13.429688 37.6875 13.378906 37.523438 13.277344 C 32.492188 10.15625 26.210938 10 25 10 C 23.789063 10 17.503906 10.15625 12.476563 13.277344 C 12.007813 13.570313 11.390625 13.425781 11.101563 12.957031 C 10.808594 12.484375 10.953125 11.871094 11.421875 11.578125 C 14.347656 9.765625 17.582031 8.867188 20.214844 8.425781 C 20.0625 7.929688 19.925781 7.617188 19.914063 7.589844 C 19.738281 7.203125 19.34375 6.960938 18.921875 7.003906 C 18.652344 7.023438 12.355469 7.566406 8.320313 10.8125 C 6.214844 12.761719 2 24.152344 2 34 C 2 34.175781 2.046875 34.34375 2.132813 34.496094 C 5.039063 39.605469 12.972656 40.941406 14.78125 41 C 14.789063 41 14.800781 41 14.8125 41 C 15.132813 41 15.433594 40.847656 15.621094 40.589844 L 17.449219 38.074219 C 12.515625 36.800781 9.996094 34.636719 9.851563 34.507813 C 9.4375 34.144531 9.398438 33.511719 9.765625 33.097656 C 10.128906 32.683594 10.761719 32.644531 11.175781 33.007813 C 11.234375 33.0625 15.875 37 25 37 C 34.140625 37 38.78125 33.046875 38.828125 33.007813 C 39.242188 32.648438 39.871094 32.683594 40.238281 33.101563 C 40.601563 33.515625 40.5625 34.144531 40.148438 34.507813 C 40.003906 34.636719 37.484375 36.800781 32.550781 38.074219 L 34.378906 40.589844 C 34.566406 40.847656 34.867188 41 35.1875 41 C 35.199219 41 35.210938 41 35.21875 41 C 37.027344 40.941406 44.960938 39.605469 47.867188 34.496094 C 47.953125 34.34375 48 34.175781 48 34 C 48 24.152344 43.785156 12.761719 41.625 10.769531 Z M 18.5 30 C 16.566406 30 15 28.210938 15 26 C 15 23.789063 16.566406 22 18.5 22 C 20.433594 22 22 23.789063 22 26 C 22 28.210938 20.433594 30 18.5 30 Z M 31.5 30 C 29.566406 30 28 28.210938 28 26 C 28 23.789063 29.566406 22 31.5 22 C 33.433594 22 35 23.789063 35 26 C 35 28.210938 33.433594 30 31.5 30 Z" />
|
||||
</svg>
|
||||
Discord
|
||||
</Typography>
|
||||
<Typography color="blue-gray" className="font-normal opacity-70">
|
||||
Join our Discord server to get help and suggest new features for Material Tailwind.
|
||||
</Typography>
|
||||
</Card>
|
||||
</a>
|
||||
</div>
|
||||
<BrowserRouter>
|
||||
<Routes>
|
||||
<Route path="/" element={<Home />} />
|
||||
<Route path="/home" element={<Home />} />
|
||||
<Route path="/NotFound" element={<NotFound />} />
|
||||
{/* <Route path="/about" element={<About />} />
|
||||
<Route path="/dashboard" element={<Dashboard />} /> */}
|
||||
</Routes>
|
||||
<div className=" bottom-5 right-10 fixed">
|
||||
<DefaultSpeedDial></DefaultSpeedDial>
|
||||
</div>
|
||||
</BrowserRouter>
|
||||
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { Queue} from 'data-struct-js'
|
||||
/**
|
||||
* ws类
|
||||
*/
|
||||
class ReactWebsocket {
|
||||
constructor() {
|
||||
//首次使用构造器实例
|
||||
if (!ReactWebsocket.instance) {
|
||||
this.ws=new WebSocket("ws://127.0.0.1:1323/ws");
|
||||
this.callbackMap= new Map();
|
||||
this.noMessageSent= new Queue();
|
||||
this.ws.onmessage=((evt)=>{this.OnMessage(evt)})
|
||||
this.ws.onopen=((evt)=>{this.OnOpen(evt)})
|
||||
this.ws.onclose = function(event) {
|
||||
console.log("WebSocket is closed now.");
|
||||
};
|
||||
//将this挂载到SingletonApple这个类的instance属性上
|
||||
ReactWebsocket.instance = this;
|
||||
}
|
||||
return ReactWebsocket.instance;
|
||||
}
|
||||
/**
|
||||
* 发送ws
|
||||
* @param {string} method 方法 string
|
||||
* @param {*} data 数据 obj
|
||||
* @param {function} callback 回调函数 function
|
||||
*/
|
||||
sendMessage(method,data,callback) {
|
||||
let uuid=uuidv4()
|
||||
let res = { method, data, uuid }
|
||||
let result = JSON.stringify(res);
|
||||
// console.log(result)
|
||||
this.callbackMap.set(uuid,callback)
|
||||
if(this.ws.readyState==1){
|
||||
this.ws.send(result);
|
||||
}else{
|
||||
this.noMessageSent.enqueue(result)
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* 关闭ws
|
||||
* @param {*} code
|
||||
* @param {*} reason
|
||||
*/
|
||||
closeSocket(code, reason) {
|
||||
this.ws.close(code, reason);
|
||||
}
|
||||
/**
|
||||
* 监听ws消息
|
||||
* @param {*} res
|
||||
*/
|
||||
OnMessage(res){
|
||||
let obj=JSON.parse(res.data)
|
||||
if(this.callbackMap.has(obj.uuid)){
|
||||
let callback=this.callbackMap.get(obj.uuid)
|
||||
callback(obj)
|
||||
this.callbackMap.delete(obj.uuid)
|
||||
}else{
|
||||
//广播
|
||||
}
|
||||
|
||||
}
|
||||
OnOpen(evt){
|
||||
while(1){
|
||||
let result = this.noMessageSent.dequeue()
|
||||
if(result){
|
||||
this.ws.send(result)
|
||||
}else{
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
export default ReactWebsocket;
|
|
@ -0,0 +1,70 @@
|
|||
import {
|
||||
Card,
|
||||
Typography,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemPrefix,
|
||||
ListItemSuffix,
|
||||
Chip,
|
||||
} from "@material-tailwind/react";
|
||||
import {
|
||||
PresentationChartBarIcon,
|
||||
ShoppingBagIcon,
|
||||
UserCircleIcon,
|
||||
Cog6ToothIcon,
|
||||
InboxIcon,
|
||||
PowerIcon,
|
||||
} from "@heroicons/react/24/solid";
|
||||
|
||||
export function DefaultSidebar() {
|
||||
return (
|
||||
<Card className="h-[calc(100vh-2rem)] w-full max-w-[20rem] p-4 shadow-xl shadow-blue-gray-900/5">
|
||||
<div className="mb-2 p-4">
|
||||
<Typography variant="h5" color="blue-gray">
|
||||
Sidebar
|
||||
</Typography>
|
||||
</div>
|
||||
<List>
|
||||
<ListItem>
|
||||
<ListItemPrefix>
|
||||
<PresentationChartBarIcon className="h-5 w-5" />
|
||||
</ListItemPrefix>
|
||||
Dashboard
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<ListItemPrefix>
|
||||
<ShoppingBagIcon className="h-5 w-5" />
|
||||
</ListItemPrefix>
|
||||
E-Commerce
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<ListItemPrefix>
|
||||
<InboxIcon className="h-5 w-5" />
|
||||
</ListItemPrefix>
|
||||
Inbox
|
||||
<ListItemSuffix>
|
||||
<Chip value="14" size="sm" variant="ghost" color="blue-gray" className="rounded-full" />
|
||||
</ListItemSuffix>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<ListItemPrefix>
|
||||
<UserCircleIcon className="h-5 w-5" />
|
||||
</ListItemPrefix>
|
||||
Profile
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<ListItemPrefix>
|
||||
<Cog6ToothIcon className="h-5 w-5" />
|
||||
</ListItemPrefix>
|
||||
Settings
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<ListItemPrefix>
|
||||
<PowerIcon className="h-5 w-5" />
|
||||
</ListItemPrefix>
|
||||
Log Out
|
||||
</ListItem>
|
||||
</List>
|
||||
</Card>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
import {
|
||||
IconButton,
|
||||
SpeedDial,
|
||||
SpeedDialHandler,
|
||||
SpeedDialContent,
|
||||
SpeedDialAction,
|
||||
} from "@material-tailwind/react";
|
||||
import {
|
||||
PlusIcon,
|
||||
HomeIcon,
|
||||
CogIcon,
|
||||
Square3Stack3DIcon,
|
||||
} from "@heroicons/react/24/outline";
|
||||
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
DialogHeader,
|
||||
DialogBody,
|
||||
DialogFooter,
|
||||
Input,
|
||||
} from "@material-tailwind/react";
|
||||
|
||||
import React, { useCallback,useState } from 'react';
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
import ReactWebsocket from "@/api/websocket"
|
||||
|
||||
export function DefaultSpeedDial() {
|
||||
|
||||
const socket = new ReactWebsocket()
|
||||
|
||||
const navigate = useNavigate()
|
||||
/**
|
||||
*
|
||||
* @param path string 地址 ex '/home'
|
||||
*/
|
||||
const handleClick = useCallback((path) => {
|
||||
navigate(path)
|
||||
});
|
||||
|
||||
|
||||
const [open, setOpen] = React.useState(false);
|
||||
|
||||
const handleOpen = () => setOpen(!open);
|
||||
|
||||
const [NameValue, setNameValue] = useState('');
|
||||
const [MacValue, setMacValue] = useState('');
|
||||
|
||||
const AddItemClick = useCallback(() => {
|
||||
// socket.sendMessage('add', {name:NameValue,mac:MacValue}, function () { updata() })
|
||||
socket.sendMessage('add', {name:NameValue,mac:MacValue}, function () { })
|
||||
handleOpen()
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<SpeedDial>
|
||||
<SpeedDialHandler>
|
||||
<IconButton size="lg" className="rounded-full">
|
||||
<PlusIcon className="h-5 w-5 transition-transform group-hover:rotate-45" />
|
||||
</IconButton>
|
||||
</SpeedDialHandler>
|
||||
<SpeedDialContent>
|
||||
<SpeedDialAction>
|
||||
<HomeIcon onClick={() => handleClick("/home")} className="h-5 w-5" />
|
||||
</SpeedDialAction>
|
||||
<SpeedDialAction>
|
||||
<CogIcon onClick={() => handleClick("/")} className="h-5 w-5" />
|
||||
</SpeedDialAction>
|
||||
<SpeedDialAction>
|
||||
<Square3Stack3DIcon onClick={handleOpen} className="h-5 w-5" />
|
||||
</SpeedDialAction>
|
||||
</SpeedDialContent>
|
||||
</SpeedDial>
|
||||
<Dialog size="xs" open={open} handler={handleOpen}>
|
||||
<DialogHeader>添加一个wol</DialogHeader>
|
||||
<DialogBody divider>
|
||||
<div className="flex w-100 flex-col items-end gap-6">
|
||||
<Input size="md" label="别名" value={NameValue} onChange={e => {setNameValue(e.target.value);}} />
|
||||
<Input size="md" label="mac地址" value={MacValue} onChange={e => {setMacValue(e.target.value);}} />
|
||||
</div>
|
||||
</DialogBody>
|
||||
<DialogFooter>
|
||||
<Button
|
||||
variant="text"
|
||||
color="red"
|
||||
onClick={handleOpen}
|
||||
className="mr-1"
|
||||
>
|
||||
<span>取消</span>
|
||||
</Button>
|
||||
<Button variant="gradient" color="green" onClick={handleOpen}>
|
||||
<span>确认</span>
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</Dialog>
|
||||
</>
|
||||
|
||||
);
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
import React from "react";
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
DialogHeader,
|
||||
DialogBody,
|
||||
DialogFooter,
|
||||
Input,
|
||||
} from "@material-tailwind/react";
|
||||
|
||||
export function DialogDefault() {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
|
||||
const handleOpen = () => setOpen(!open);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button onClick={handleOpen} variant="gradient">
|
||||
Open Dialog
|
||||
</Button>
|
||||
<Dialog size="xs" open={open} handler={handleOpen}>
|
||||
<DialogHeader>添加一个wol</DialogHeader>
|
||||
<DialogBody divider>
|
||||
<div className="flex w-100 flex-col items-end gap-6">
|
||||
<Input size="md" label="别名" />
|
||||
<Input size="md" label="mac地址" />
|
||||
</div>
|
||||
</DialogBody>
|
||||
<DialogFooter>
|
||||
<Button
|
||||
variant="text"
|
||||
color="red"
|
||||
onClick={handleOpen}
|
||||
className="mr-1"
|
||||
>
|
||||
<span>取消</span>
|
||||
</Button>
|
||||
<Button variant="gradient" color="green" onClick={handleOpen}>
|
||||
<span>确认</span>
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</Dialog>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
import {
|
||||
Card,
|
||||
CardHeader,
|
||||
CardBody,
|
||||
CardFooter,
|
||||
Typography,
|
||||
Input,
|
||||
Checkbox,
|
||||
Button,
|
||||
} from "@material-tailwind/react";
|
||||
|
||||
export function LoginCard() {
|
||||
return (
|
||||
<Card className="w-96">
|
||||
<CardHeader
|
||||
variant="gradient"
|
||||
color="gray"
|
||||
className="mb-4 grid h-28 place-items-center"
|
||||
>
|
||||
<Typography variant="h3" color="white">
|
||||
Sign In
|
||||
</Typography>
|
||||
</CardHeader>
|
||||
<CardBody className="flex flex-col gap-4">
|
||||
<Input label="Email" size="lg" />
|
||||
<Input label="Password" size="lg" />
|
||||
<div className="-ml-2.5">
|
||||
<Checkbox label="Remember Me" />
|
||||
</div>
|
||||
</CardBody>
|
||||
<CardFooter className="pt-0">
|
||||
<Button variant="gradient" fullWidth>
|
||||
Sign In
|
||||
</Button>
|
||||
<Typography variant="small" className="mt-6 flex justify-center">
|
||||
Don't have an account?
|
||||
<Typography
|
||||
as="a"
|
||||
href="#signup"
|
||||
variant="small"
|
||||
color="blue-gray"
|
||||
className="ml-1 font-bold"
|
||||
>
|
||||
Sign up
|
||||
</Typography>
|
||||
</Typography>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
import React, { useState, useCallback, useEffect } from 'react';
|
||||
import useWebSocket, { ReadyState } from 'react-use-websocket';
|
||||
|
||||
export const WebSocketDemo = () => {
|
||||
//Public API that will echo messages sent to it back to the client
|
||||
const [socketUrl, setSocketUrl] = useState('ws://127.0.0.1:1323/ws');
|
||||
const [messageHistory, setMessageHistory] = useState([]);
|
||||
|
||||
const { sendMessage, lastMessage, readyState } = useWebSocket(socketUrl);
|
||||
|
||||
useEffect(() => {
|
||||
if (lastMessage !== null) {
|
||||
setMessageHistory((prev) => prev.concat(lastMessage));
|
||||
}
|
||||
}, [lastMessage, setMessageHistory]);
|
||||
|
||||
const handleClickChangeSocketUrl = useCallback(
|
||||
() => setSocketUrl('ws://127.0.0.1:1323/ws'),
|
||||
[]
|
||||
);
|
||||
|
||||
const handleClickSendMessage = useCallback(() => sendMessage('Hello'), []);
|
||||
|
||||
const connectionStatus = {
|
||||
[ReadyState.CONNECTING]: 'Connecting',
|
||||
[ReadyState.OPEN]: 'Open',
|
||||
[ReadyState.CLOSING]: 'Closing',
|
||||
[ReadyState.CLOSED]: 'Closed',
|
||||
[ReadyState.UNINSTANTIATED]: 'Uninstantiated',
|
||||
}[readyState];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<button onClick={handleClickChangeSocketUrl}>
|
||||
Click Me to change Socket Url
|
||||
</button>
|
||||
<button
|
||||
onClick={handleClickSendMessage}
|
||||
disabled={readyState !== ReadyState.OPEN}
|
||||
>
|
||||
Click Me to send 'Hello'
|
||||
</button>
|
||||
<span>The WebSocket is currently {connectionStatus}</span>
|
||||
{lastMessage ? <span>Last message: {lastMessage.data}</span> : null}
|
||||
<ul>
|
||||
{messageHistory.map((message, idx) => (
|
||||
<span key={idx}>{message ? message.data : null}</span>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,47 @@
|
|||
import { Typography, Card, CardBody, CardFooter, Button } from "@material-tailwind/react";
|
||||
import ReactWebsocket from "@/api/websocket"
|
||||
import React, { useCallback } from 'react';
|
||||
export default function WolItem(props) {
|
||||
const { id, mac, name, updata } = props;
|
||||
const socket = new ReactWebsocket()
|
||||
function isMACAddress(strMac) {
|
||||
var reg = /^([0-9a-fA-F]{2})(([/\s:][0-9a-fA-F]{2}){5})$/;
|
||||
if (reg.test(strMac)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const handleClickSendMessage = useCallback(() => {
|
||||
if (!isMACAddress(mac)) {
|
||||
console.log("mac输入错误");
|
||||
return;
|
||||
}
|
||||
socket.sendMessage('start', {mac}, function () { })
|
||||
}, []);
|
||||
const deleteItem = useCallback(() => {
|
||||
socket.sendMessage('del', {id}, function () { updata() })
|
||||
}, []);
|
||||
const EdiItem = useCallback(() => {
|
||||
socket.sendMessage('del', {id}, function () { updata() })
|
||||
}, []);
|
||||
return (
|
||||
<div className="p-6">
|
||||
<Card className="mt-6 w-96 border border-blue-gray-50 py-4 px-5 shadow-xl shadow-transparent transition-all hover:-translate-y-4 hover:border-blue-gray-100/60 hover:shadow-blue-gray-900/5">
|
||||
<CardBody>
|
||||
<Typography variant="h5" color="blue-gray" className="mb-2">
|
||||
{name}
|
||||
</Typography>
|
||||
<Typography>
|
||||
MAC:{mac}
|
||||
</Typography>
|
||||
</CardBody>
|
||||
<CardFooter className="pt-0 ">
|
||||
<Button className="w-50" onClick={handleClickSendMessage}>发送wol数据</Button>
|
||||
<Button className="w-20 mx-1 " color="amber">编辑</Button>
|
||||
<Button className="w-20" onClick={deleteItem} color="amber">删除</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
import WolItem from "@/components/WolItem"
|
||||
import ReactWebsocket from "@/api/websocket"
|
||||
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
|
||||
|
||||
export default function Home() {
|
||||
const socket = new ReactWebsocket()
|
||||
const [wolarray, setWolarray] = useState([]);
|
||||
useEffect(() => {
|
||||
updata()
|
||||
}, []);
|
||||
const updata = useCallback(() => {
|
||||
socket.sendMessage('getall', '', function (eve) { setWolarray(eve.data[0]) })
|
||||
});
|
||||
return (
|
||||
<div >
|
||||
<div className="flex flex-wrap justify-between">
|
||||
{wolarray.map((item, index) => (
|
||||
<WolItem key={index} mac={item.Mac} name={item.Name} id={item.ID} updata={updata}></WolItem>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue