更新界面 可以部署一版了
This commit is contained in:
parent
07347cba09
commit
488001574a
@ -1,9 +1,14 @@
|
|||||||
import React from 'react'
|
import React, {useEffect} from 'react'
|
||||||
import './assets/global.scss'
|
import './assets/global.scss'
|
||||||
import {AppRouter} from "./pages/Router.tsx";
|
import {AppRouter} from "./pages/Router.tsx";
|
||||||
|
import {useUserinfoStore} from "./store/userinfoStore.ts";
|
||||||
|
|
||||||
|
|
||||||
export function App() {
|
export function App() {
|
||||||
|
const {init} = useUserinfoStore();
|
||||||
|
useEffect(()=>{
|
||||||
|
init(); // 初始化用户信息
|
||||||
|
}, [])
|
||||||
return (<div>
|
return (<div>
|
||||||
<AppRouter/>
|
<AppRouter/>
|
||||||
</div>)
|
</div>)
|
||||||
|
24
front/components/AppList/index.tsx
Normal file
24
front/components/AppList/index.tsx
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import {List, Space} from "@douyinfe/semi-ui"
|
||||||
|
import {Link} from "react-router-dom";
|
||||||
|
import {formatDate} from "../../../utils/date.ts";
|
||||||
|
import {AppModel} from "../../../model";
|
||||||
|
|
||||||
|
export const AppList = (props: {
|
||||||
|
list: AppModel[];
|
||||||
|
onItemClick?: (app: AppModel) => void;
|
||||||
|
}) => {
|
||||||
|
return (<div className="app-list-wrapper">
|
||||||
|
{props.list.map(it => (
|
||||||
|
<div key={it.id} className="list-link-item flex space-between" onClick={() =>{
|
||||||
|
props.onItemClick?.(it)
|
||||||
|
}}>
|
||||||
|
<Space className="space">
|
||||||
|
<span>{it.id}</span>
|
||||||
|
<span>{it.title}</span>
|
||||||
|
<span>{formatDate(it.create_time)}</span>
|
||||||
|
</Space>
|
||||||
|
<span>进入</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>)
|
||||||
|
}
|
@ -1,13 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
|
|
||||||
export type ResultProps = {
|
|
||||||
extra: React.ReactNode;
|
|
||||||
title: React.ReactNode;
|
|
||||||
status: number | string;
|
|
||||||
};
|
|
||||||
export const Result: React.FC<ResultProps> = (props) => {
|
|
||||||
return <div>
|
|
||||||
<div className="title">{props.title}</div>
|
|
||||||
<div className="extra">{props.extra}</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
38
front/components/Result/index.tsx
Normal file
38
front/components/Result/index.tsx
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import React from "react";
|
||||||
|
import './result.scss'
|
||||||
|
import {CheckCircleFilled} from "../icons/CheckCircleFilled.tsx";
|
||||||
|
import {NotFound} from "../icons/NotFound.tsx";
|
||||||
|
|
||||||
|
type Status = 'success' | 'error' | 'info' | 'warning' | '404' | '403' | '500';
|
||||||
|
export type ResultProps = {
|
||||||
|
extra?: React.ReactNode;
|
||||||
|
title?: React.ReactNode;
|
||||||
|
subTitle?: React.ReactNode;
|
||||||
|
icon?: React.ReactNode;
|
||||||
|
status?: Status //number | string;
|
||||||
|
};
|
||||||
|
export const IconMap: {
|
||||||
|
[key in Status]: React.ReactNode
|
||||||
|
} = {
|
||||||
|
success: <CheckCircleFilled/>,
|
||||||
|
error: <CheckCircleFilled/>,
|
||||||
|
info: <CheckCircleFilled/>,
|
||||||
|
warning: <CheckCircleFilled/>,
|
||||||
|
// error: CloseCircleFilled,
|
||||||
|
// info: ExclamationCircleFilled,
|
||||||
|
// warning: WarningFilled,
|
||||||
|
'404': <NotFound/>,
|
||||||
|
'500': <NotFound/>,
|
||||||
|
'403': <NotFound/>,
|
||||||
|
// '500': serverError,
|
||||||
|
// '403': unauthorized,
|
||||||
|
};
|
||||||
|
export const Index: React.FC<ResultProps> = (props) => {
|
||||||
|
const icon = props.icon || (props.status ? IconMap[props.status] : <></>)
|
||||||
|
return <div className="result-wrapper">
|
||||||
|
<div className="icon">{icon}</div>
|
||||||
|
<div className="title">{props.title}</div>
|
||||||
|
{props.subTitle && <div className="sub-title">{props.subTitle}</div>}
|
||||||
|
<div className="extra">{props.extra}</div>
|
||||||
|
</div>
|
||||||
|
}
|
26
front/components/Result/result.scss
Normal file
26
front/components/Result/result.scss
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
.result-wrapper {
|
||||||
|
text-align: center;
|
||||||
|
padding: 48px 32px;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
color:#52c41a;
|
||||||
|
font-size: 72px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: rgba(0, 0, 0, 0.88);
|
||||||
|
font-size: 24px;
|
||||||
|
line-height: 1.3333333333333333;
|
||||||
|
margin-block: 8px;
|
||||||
|
}
|
||||||
|
.sub-title{
|
||||||
|
color: rgba(0, 0, 0, 0.45);
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.5714285714285714;
|
||||||
|
}
|
||||||
|
|
||||||
|
.extra {
|
||||||
|
margin: 24px 0 0 0;
|
||||||
|
}
|
||||||
|
}
|
16
front/components/icons/CheckCircleFilled.tsx
Normal file
16
front/components/icons/CheckCircleFilled.tsx
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export type SvgProps = {} & React.SVGProps<SVGElement>;
|
||||||
|
export const CheckCircleFilled: React.FC<SvgProps> = (props) => {
|
||||||
|
return (<svg
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
focusable="false"
|
||||||
|
data-icon="check-circle"
|
||||||
|
width="1em" height="1em"
|
||||||
|
fill="currentColor"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 01-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z"></path>
|
||||||
|
</svg>)
|
||||||
|
}
|
157
front/components/icons/NotFound.tsx
Normal file
157
front/components/icons/NotFound.tsx
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export const NotFound: React.FC = () => {
|
||||||
|
return (<svg width="252" height="294">
|
||||||
|
<defs>
|
||||||
|
<path d="M0 .387h251.772v251.772H0z"></path>
|
||||||
|
</defs>
|
||||||
|
<g fill="none" fill-rule="evenodd">
|
||||||
|
<g transform="translate(0 .012)">
|
||||||
|
<mask fill="#fff"></mask>
|
||||||
|
<path
|
||||||
|
d="M0 127.32v-2.095C0 56.279 55.892.387 124.838.387h2.096c68.946 0 124.838 55.892 124.838 124.838v2.096c0 68.946-55.892 124.838-124.838 124.838h-2.096C55.892 252.16 0 196.267 0 127.321"
|
||||||
|
fill="#E4EBF7" mask="url(#b)"></path>
|
||||||
|
</g>
|
||||||
|
<path d="M39.755 130.84a8.276 8.276 0 1 1-16.468-1.66 8.276 8.276 0 0 1 16.468 1.66" fill="#FFF"></path>
|
||||||
|
<path d="M36.975 134.297l10.482 5.943M48.373 146.508l-12.648 10.788" stroke="#FFF" stroke-width="2"></path>
|
||||||
|
<path
|
||||||
|
d="M39.875 159.352a5.667 5.667 0 1 1-11.277-1.136 5.667 5.667 0 0 1 11.277 1.136M57.588 143.247a5.708 5.708 0 1 1-11.358-1.145 5.708 5.708 0 0 1 11.358 1.145M99.018 26.875l29.82-.014a4.587 4.587 0 1 0-.003-9.175l-29.82.013a4.587 4.587 0 1 0 .003 9.176M110.424 45.211l29.82-.013a4.588 4.588 0 0 0-.004-9.175l-29.82.013a4.587 4.587 0 1 0 .004 9.175"
|
||||||
|
fill="#FFF"></path>
|
||||||
|
<path
|
||||||
|
d="M112.798 26.861v-.002l15.784-.006a4.588 4.588 0 1 0 .003 9.175l-15.783.007v-.002a4.586 4.586 0 0 0-.004-9.172M184.523 135.668c-.553 5.485-5.447 9.483-10.931 8.93-5.485-.553-9.483-5.448-8.93-10.932.552-5.485 5.447-9.483 10.932-8.93 5.485.553 9.483 5.447 8.93 10.932"
|
||||||
|
fill="#FFF"></path>
|
||||||
|
<path d="M179.26 141.75l12.64 7.167M193.006 156.477l-15.255 13.011" stroke="#FFF" stroke-width="2"></path>
|
||||||
|
<path
|
||||||
|
d="M184.668 170.057a6.835 6.835 0 1 1-13.6-1.372 6.835 6.835 0 0 1 13.6 1.372M203.34 153.325a6.885 6.885 0 1 1-13.7-1.382 6.885 6.885 0 0 1 13.7 1.382"
|
||||||
|
fill="#FFF"></path>
|
||||||
|
<path
|
||||||
|
d="M151.931 192.324a2.222 2.222 0 1 1-4.444 0 2.222 2.222 0 0 1 4.444 0zM225.27 116.056a2.222 2.222 0 1 1-4.445 0 2.222 2.222 0 0 1 4.444 0zM216.38 151.08a2.223 2.223 0 1 1-4.446-.001 2.223 2.223 0 0 1 4.446 0zM176.917 107.636a2.223 2.223 0 1 1-4.445 0 2.223 2.223 0 0 1 4.445 0zM195.291 92.165a2.223 2.223 0 1 1-4.445 0 2.223 2.223 0 0 1 4.445 0zM202.058 180.711a2.223 2.223 0 1 1-4.446 0 2.223 2.223 0 0 1 4.446 0z"
|
||||||
|
stroke="#FFF" stroke-width="2"></path>
|
||||||
|
<path stroke="#FFF" stroke-width="2"
|
||||||
|
d="M214.404 153.302l-1.912 20.184-10.928 5.99M173.661 174.792l-6.356 9.814h-11.36l-4.508 6.484M174.941 125.168v-15.804M220.824 117.25l-12.84 7.901-15.31-7.902V94.39"></path>
|
||||||
|
<path
|
||||||
|
d="M166.588 65.936h-3.951a4.756 4.756 0 0 1-4.743-4.742 4.756 4.756 0 0 1 4.743-4.743h3.951a4.756 4.756 0 0 1 4.743 4.743 4.756 4.756 0 0 1-4.743 4.742"
|
||||||
|
fill="#FFF"></path>
|
||||||
|
<path
|
||||||
|
d="M174.823 30.03c0-16.281 13.198-29.48 29.48-29.48 16.28 0 29.48 13.199 29.48 29.48 0 16.28-13.2 29.48-29.48 29.48-16.282 0-29.48-13.2-29.48-29.48"
|
||||||
|
fill="#1677ff"></path>
|
||||||
|
<path
|
||||||
|
d="M205.952 38.387c.5.5.785 1.142.785 1.928s-.286 1.465-.785 1.964c-.572.5-1.214.75-2 .75-.785 0-1.429-.285-1.929-.785-.572-.5-.82-1.143-.82-1.929s.248-1.428.82-1.928c.5-.5 1.144-.75 1.93-.75.785 0 1.462.25 1.999.75m4.285-19.463c1.428 1.249 2.143 2.963 2.143 5.142 0 1.712-.427 3.13-1.219 4.25-.067.096-.137.18-.218.265-.416.429-1.41 1.346-2.956 2.699a5.07 5.07 0 0 0-1.428 1.75 5.207 5.207 0 0 0-.536 2.357v.5h-4.107v-.5c0-1.357.215-2.536.714-3.5.464-.964 1.857-2.464 4.178-4.536l.43-.5c.643-.785.964-1.643.964-2.535 0-1.18-.358-2.108-1-2.785-.678-.68-1.643-1.001-2.858-1.001-1.536 0-2.642.464-3.357 1.43-.37.5-.621 1.135-.76 1.904a1.999 1.999 0 0 1-1.971 1.63h-.004c-1.277 0-2.257-1.183-1.98-2.43.337-1.518 1.02-2.78 2.073-3.784 1.536-1.5 3.607-2.25 6.25-2.25 2.32 0 4.214.607 5.642 1.894"
|
||||||
|
fill="#FFF"></path>
|
||||||
|
<path
|
||||||
|
d="M52.04 76.131s21.81 5.36 27.307 15.945c5.575 10.74-6.352 9.26-15.73 4.935-10.86-5.008-24.7-11.822-11.577-20.88"
|
||||||
|
fill="#FFB594"></path>
|
||||||
|
<path
|
||||||
|
d="M90.483 67.504l-.449 2.893c-.753.49-4.748-2.663-4.748-2.663l-1.645.748-1.346-5.684s6.815-4.589 8.917-5.018c2.452-.501 9.884.94 10.7 2.278 0 0 1.32.486-2.227.69-3.548.203-5.043.447-6.79 3.132-1.747 2.686-2.412 3.624-2.412 3.624"
|
||||||
|
fill="#FFC6A0"></path>
|
||||||
|
<path
|
||||||
|
d="M128.055 111.367c-2.627-7.724-6.15-13.18-8.917-15.478-3.5-2.906-9.34-2.225-11.366-4.187-1.27-1.231-3.215-1.197-3.215-1.197s-14.98-3.158-16.828-3.479c-2.37-.41-2.124-.714-6.054-1.405-1.57-1.907-2.917-1.122-2.917-1.122l-7.11-1.383c-.853-1.472-2.423-1.023-2.423-1.023l-2.468-.897c-1.645 9.976-7.74 13.796-7.74 13.796 1.795 1.122 15.703 8.3 15.703 8.3l5.107 37.11s-3.321 5.694 1.346 9.109c0 0 19.883-3.743 34.921-.329 0 0 3.047-2.546.972-8.806.523-3.01 1.394-8.263 1.736-11.622.385.772 2.019 1.918 3.14 3.477 0 0 9.407-7.365 11.052-14.012-.832-.723-1.598-1.585-2.267-2.453-.567-.736-.358-2.056-.765-2.717-.669-1.084-1.804-1.378-1.907-1.682"
|
||||||
|
fill="#FFF"></path>
|
||||||
|
<path
|
||||||
|
d="M101.09 289.998s4.295 2.041 7.354 1.021c2.821-.94 4.53.668 7.08 1.178 2.55.51 6.874 1.1 11.686-1.26-.103-5.51-6.889-3.98-11.96-6.713-2.563-1.38-3.784-4.722-3.598-8.799h-9.402s-1.392 10.52-1.16 14.573"
|
||||||
|
fill="#CBD1D1"></path>
|
||||||
|
<path
|
||||||
|
d="M101.067 289.826s2.428 1.271 6.759.653c3.058-.437 3.712.481 7.423 1.031 3.712.55 10.724-.069 11.823-.894.413 1.1-.343 2.063-.343 2.063s-1.512.603-4.812.824c-2.03.136-5.8.291-7.607-.503-1.787-1.375-5.247-1.903-5.728-.241-3.918.95-7.355-.286-7.355-.286l-.16-2.647z"
|
||||||
|
fill="#2B0849"></path>
|
||||||
|
<path d="M108.341 276.044h3.094s-.103 6.702 4.536 8.558c-4.64.618-8.558-2.303-7.63-8.558"
|
||||||
|
fill="#A4AABA"></path>
|
||||||
|
<path
|
||||||
|
d="M57.542 272.401s-2.107 7.416-4.485 12.306c-1.798 3.695-4.225 7.492 5.465 7.492 6.648 0 8.953-.48 7.423-6.599-1.53-6.12.266-13.199.266-13.199h-8.669z"
|
||||||
|
fill="#CBD1D1"></path>
|
||||||
|
<path
|
||||||
|
d="M51.476 289.793s2.097 1.169 6.633 1.169c6.083 0 8.249-1.65 8.249-1.65s.602 1.114-.619 2.165c-.993.855-3.597 1.591-7.39 1.546-4.145-.048-5.832-.566-6.736-1.168-.825-.55-.687-1.58-.137-2.062"
|
||||||
|
fill="#2B0849"></path>
|
||||||
|
<path
|
||||||
|
d="M58.419 274.304s.033 1.519-.314 2.93c-.349 1.42-1.078 3.104-1.13 4.139-.058 1.151 4.537 1.58 5.155.034.62-1.547 1.294-6.427 1.913-7.252.619-.825-4.903-2.119-5.624.15"
|
||||||
|
fill="#A4AABA"></path>
|
||||||
|
<path
|
||||||
|
d="M99.66 278.514l13.378.092s1.298-54.52 1.853-64.403c.554-9.882 3.776-43.364 1.002-63.128l-12.547-.644-22.849.78s-.434 3.966-1.195 9.976c-.063.496-.682.843-.749 1.365-.075.585.423 1.354.32 1.966-2.364 14.08-6.377 33.104-8.744 46.677-.116.666-1.234 1.009-1.458 2.691-.04.302.211 1.525.112 1.795-6.873 18.744-10.949 47.842-14.277 61.885l14.607-.014s2.197-8.57 4.03-16.97c2.811-12.886 23.111-85.01 23.111-85.01l3.016-.521 1.043 46.35s-.224 1.234.337 2.02c.56.785-.56 1.123-.392 2.244l.392 1.794s-.449 7.178-.898 11.89c-.448 4.71-.092 39.165-.092 39.165"
|
||||||
|
fill="#7BB2F9"></path>
|
||||||
|
<path d="M76.085 221.626c1.153.094 4.038-2.019 6.955-4.935M106.36 225.142s2.774-1.11 6.103-3.883"
|
||||||
|
stroke="#648BD8" stroke-width="1.051" stroke-linecap="round" stroke-linejoin="round"></path>
|
||||||
|
<path d="M107.275 222.1s2.773-1.11 6.102-3.884" stroke="#648BD8" stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"></path>
|
||||||
|
<path
|
||||||
|
d="M74.74 224.767s2.622-.591 6.505-3.365M86.03 151.634c-.27 3.106.3 8.525-4.336 9.123M103.625 149.88s.11 14.012-1.293 15.065c-2.219 1.664-2.99 1.944-2.99 1.944M99.79 150.438s.035 12.88-1.196 24.377M93.673 175.911s7.212-1.664 9.431-1.664M74.31 205.861a212.013 212.013 0 0 1-.979 4.56s-1.458 1.832-1.009 3.776c.449 1.944-.947 2.045-4.985 15.355-1.696 5.59-4.49 18.591-6.348 27.597l-.231 1.12M75.689 197.807a320.934 320.934 0 0 1-.882 4.754M82.591 152.233L81.395 162.7s-1.097.15-.5 2.244c.113 1.346-2.674 15.775-5.18 30.43M56.12 274.418h13.31"
|
||||||
|
stroke="#648BD8" stroke-width="1.051" stroke-linecap="round" stroke-linejoin="round"></path>
|
||||||
|
<path
|
||||||
|
d="M116.241 148.22s-17.047-3.104-35.893.2c.158 2.514-.003 4.15-.003 4.15s14.687-2.818 35.67-.312c.252-2.355.226-4.038.226-4.038"
|
||||||
|
fill="#192064"></path>
|
||||||
|
<path
|
||||||
|
d="M106.322 151.165l.003-4.911a.81.81 0 0 0-.778-.815c-2.44-.091-5.066-.108-7.836-.014a.818.818 0 0 0-.789.815l-.003 4.906a.81.81 0 0 0 .831.813c2.385-.06 4.973-.064 7.73.017a.815.815 0 0 0 .842-.81"
|
||||||
|
fill="#FFF"></path>
|
||||||
|
<path
|
||||||
|
d="M105.207 150.233l.002-3.076a.642.642 0 0 0-.619-.646 94.321 94.321 0 0 0-5.866-.01.65.65 0 0 0-.63.647v3.072a.64.64 0 0 0 .654.644 121.12 121.12 0 0 1 5.794.011c.362.01.665-.28.665-.642"
|
||||||
|
fill="#192064"></path>
|
||||||
|
<path
|
||||||
|
d="M100.263 275.415h12.338M101.436 270.53c.006 3.387.042 5.79.111 6.506M101.451 264.548a915.75 915.75 0 0 0-.015 4.337M100.986 174.965l.898 44.642s.673 1.57-.225 2.692c-.897 1.122 2.468.673.898 2.243-1.57 1.57.897 1.122 0 3.365-.596 1.489-.994 21.1-1.096 35.146"
|
||||||
|
stroke="#648BD8" stroke-width="1.051" stroke-linecap="round" stroke-linejoin="round"></path>
|
||||||
|
<path
|
||||||
|
d="M46.876 83.427s-.516 6.045 7.223 5.552c11.2-.712 9.218-9.345 31.54-21.655-.786-2.708-2.447-4.744-2.447-4.744s-11.068 3.11-22.584 8.046c-6.766 2.9-13.395 6.352-13.732 12.801M104.46 91.057l.941-5.372-8.884-11.43-5.037 5.372-1.74 7.834a.321.321 0 0 0 .108.32c.965.8 6.5 5.013 14.347 3.544a.332.332 0 0 0 .264-.268"
|
||||||
|
fill="#FFC6A0"></path>
|
||||||
|
<path
|
||||||
|
d="M93.942 79.387s-4.533-2.853-2.432-6.855c1.623-3.09 4.513 1.133 4.513 1.133s.52-3.642 3.121-3.642c.52-1.04 1.561-4.162 1.561-4.162s11.445 2.601 13.526 3.121c0 5.203-2.304 19.424-7.84 19.861-8.892.703-12.449-9.456-12.449-9.456"
|
||||||
|
fill="#FFC6A0"></path>
|
||||||
|
<path
|
||||||
|
d="M113.874 73.446c2.601-2.081 3.47-9.722 3.47-9.722s-2.479-.49-6.64-2.05c-4.683-2.081-12.798-4.747-17.48.976-9.668 3.223-2.05 19.823-2.05 19.823l2.713-3.021s-3.935-3.287-2.08-6.243c2.17-3.462 3.92 1.073 3.92 1.073s.637-2.387 3.581-3.342c.355-.71 1.036-2.674 1.432-3.85a1.073 1.073 0 0 1 1.263-.704c2.4.558 8.677 2.019 11.356 2.662.522.125.871.615.82 1.15l-.305 3.248z"
|
||||||
|
fill="#520038"></path>
|
||||||
|
<path
|
||||||
|
d="M104.977 76.064c-.103.61-.582 1.038-1.07.956-.489-.083-.801-.644-.698-1.254.103-.61.582-1.038 1.07-.956.488.082.8.644.698 1.254M112.132 77.694c-.103.61-.582 1.038-1.07.956-.488-.083-.8-.644-.698-1.254.103-.61.582-1.038 1.07-.956.488.082.8.643.698 1.254"
|
||||||
|
fill="#552950"></path>
|
||||||
|
<path stroke="#DB836E" stroke-width="1.118" stroke-linecap="round" stroke-linejoin="round"
|
||||||
|
d="M110.13 74.84l-.896 1.61-.298 4.357h-2.228"></path>
|
||||||
|
<path d="M110.846 74.481s1.79-.716 2.506.537" stroke="#5C2552" stroke-width="1.118" stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"></path>
|
||||||
|
<path d="M92.386 74.282s.477-1.114 1.113-.716c.637.398 1.274 1.433.558 1.99-.717.556.159 1.67.159 1.67"
|
||||||
|
stroke="#DB836E" stroke-width="1.118" stroke-linecap="round" stroke-linejoin="round"></path>
|
||||||
|
<path d="M103.287 72.93s1.83 1.113 4.137.954" stroke="#5C2552" stroke-width="1.118" stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"></path>
|
||||||
|
<path
|
||||||
|
d="M103.685 81.762s2.227 1.193 4.376 1.193M104.64 84.308s.954.398 1.511.318M94.693 81.205s2.308 7.4 10.424 7.639"
|
||||||
|
stroke="#DB836E" stroke-width="1.118" stroke-linecap="round" stroke-linejoin="round"></path>
|
||||||
|
<path d="M81.45 89.384s.45 5.647-4.935 12.787M69 82.654s-.726 9.282-8.204 14.206" stroke="#E4EBF7"
|
||||||
|
stroke-width="1.101" stroke-linecap="round" stroke-linejoin="round"></path>
|
||||||
|
<path d="M129.405 122.865s-5.272 7.403-9.422 10.768" stroke="#E4EBF7" stroke-width="1.051"
|
||||||
|
stroke-linecap="round" stroke-linejoin="round"></path>
|
||||||
|
<path d="M119.306 107.329s.452 4.366-2.127 32.062" stroke="#E4EBF7" stroke-width="1.101"
|
||||||
|
stroke-linecap="round" stroke-linejoin="round"></path>
|
||||||
|
<path
|
||||||
|
d="M150.028 151.232h-49.837a1.01 1.01 0 0 1-1.01-1.01v-31.688c0-.557.452-1.01 1.01-1.01h49.837c.558 0 1.01.453 1.01 1.01v31.688a1.01 1.01 0 0 1-1.01 1.01"
|
||||||
|
fill="#F2D7AD"></path>
|
||||||
|
<path d="M150.29 151.232h-19.863v-33.707h20.784v32.786a.92.92 0 0 1-.92.92" fill="#F4D19D"></path>
|
||||||
|
<path
|
||||||
|
d="M123.554 127.896H92.917a.518.518 0 0 1-.425-.816l6.38-9.113c.193-.277.51-.442.85-.442h31.092l-7.26 10.371z"
|
||||||
|
fill="#F2D7AD"></path>
|
||||||
|
<path fill="#CC9B6E" d="M123.689 128.447H99.25v-.519h24.169l7.183-10.26.424.298z"></path>
|
||||||
|
<path
|
||||||
|
d="M158.298 127.896h-18.669a2.073 2.073 0 0 1-1.659-.83l-7.156-9.541h19.965c.49 0 .95.23 1.244.622l6.69 8.92a.519.519 0 0 1-.415.83"
|
||||||
|
fill="#F4D19D"></path>
|
||||||
|
<path fill="#CC9B6E"
|
||||||
|
d="M157.847 128.479h-19.384l-7.857-10.475.415-.31 7.7 10.266h19.126zM130.554 150.685l-.032-8.177.519-.002.032 8.177z"></path>
|
||||||
|
<path fill="#CC9B6E"
|
||||||
|
d="M130.511 139.783l-.08-21.414.519-.002.08 21.414zM111.876 140.932l-.498-.143 1.479-5.167.498.143zM108.437 141.06l-2.679-2.935 2.665-3.434.41.318-2.397 3.089 2.384 2.612zM116.607 141.06l-.383-.35 2.383-2.612-2.397-3.089.41-.318 2.665 3.434z"></path>
|
||||||
|
<path
|
||||||
|
d="M154.316 131.892l-3.114-1.96.038 3.514-1.043.092c-1.682.115-3.634.23-4.789.23-1.902 0-2.693 2.258 2.23 2.648l-2.645-.596s-2.168 1.317.504 2.3c0 0-1.58 1.217.561 2.58-.584 3.504 5.247 4.058 7.122 3.59 1.876-.47 4.233-2.359 4.487-5.16.28-3.085-.89-5.432-3.35-7.238"
|
||||||
|
fill="#FFC6A0"></path>
|
||||||
|
<path
|
||||||
|
d="M153.686 133.577s-6.522.47-8.36.372c-1.836-.098-1.904 2.19 2.359 2.264 3.739.15 5.451-.044 5.451-.044"
|
||||||
|
stroke="#DB836E" stroke-width="1.051" stroke-linecap="round" stroke-linejoin="round"></path>
|
||||||
|
<path d="M145.16 135.877c-1.85 1.346.561 2.355.561 2.355s3.478.898 6.73.617" stroke="#DB836E"
|
||||||
|
stroke-width="1.051" stroke-linecap="round" stroke-linejoin="round"></path>
|
||||||
|
<path
|
||||||
|
d="M151.89 141.71s-6.28.111-6.73-2.132c-.223-1.346.45-1.402.45-1.402M146.114 140.868s-1.103 3.16 5.44 3.533M151.202 129.932v3.477M52.838 89.286c3.533-.337 8.423-1.248 13.582-7.754"
|
||||||
|
stroke="#DB836E" stroke-width="1.051" stroke-linecap="round" stroke-linejoin="round"></path>
|
||||||
|
<path
|
||||||
|
d="M168.567 248.318a6.647 6.647 0 0 1-6.647-6.647v-66.466a6.647 6.647 0 1 1 13.294 0v66.466a6.647 6.647 0 0 1-6.647 6.647"
|
||||||
|
fill="#5BA02E"></path>
|
||||||
|
<path
|
||||||
|
d="M176.543 247.653a6.647 6.647 0 0 1-6.646-6.647v-33.232a6.647 6.647 0 1 1 13.293 0v33.232a6.647 6.647 0 0 1-6.647 6.647"
|
||||||
|
fill="#92C110"></path>
|
||||||
|
<path
|
||||||
|
d="M186.443 293.613H158.92a3.187 3.187 0 0 1-3.187-3.187v-46.134a3.187 3.187 0 0 1 3.187-3.187h27.524a3.187 3.187 0 0 1 3.187 3.187v46.134a3.187 3.187 0 0 1-3.187 3.187"
|
||||||
|
fill="#F2D7AD"></path>
|
||||||
|
<path d="M88.979 89.48s7.776 5.384 16.6 2.842" stroke="#E4EBF7" stroke-width="1.101" stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"></path>
|
||||||
|
</g>
|
||||||
|
</svg>)
|
||||||
|
}
|
@ -9,6 +9,7 @@
|
|||||||
}
|
}
|
||||||
.panelTitle{
|
.panelTitle{
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
.panelExtra{
|
.panelExtra{
|
||||||
|
|
||||||
@ -18,4 +19,4 @@
|
|||||||
padding:10px;
|
padding:10px;
|
||||||
border-radius: 4px;;
|
border-radius: 4px;;
|
||||||
}
|
}
|
||||||
.noPadding{padding:0;}
|
.noPadding{padding:0;}
|
||||||
|
@ -4,7 +4,7 @@ import ReactDOM from 'react-dom/client';
|
|||||||
import {App} from './App'
|
import {App} from './App'
|
||||||
|
|
||||||
ReactDOM.createRoot(document.querySelector('#root')!).render(
|
ReactDOM.createRoot(document.querySelector('#root')!).render(
|
||||||
<React.StrictMode>
|
// <React.StrictMode>
|
||||||
<App/>
|
<App/>
|
||||||
</React.StrictMode>
|
// </React.StrictMode>
|
||||||
)
|
)
|
||||||
|
@ -3,7 +3,8 @@ import {BrowserRouter, HashRouter, Navigate, Route, Routes, useNavigate} from "r
|
|||||||
import {APP_CONFIG} from "../config.ts";
|
import {APP_CONFIG} from "../config.ts";
|
||||||
import {Button} from "@douyinfe/semi-ui";
|
import {Button} from "@douyinfe/semi-ui";
|
||||||
import DefaultPage from "./index";
|
import DefaultPage from "./index";
|
||||||
import {Result} from "../components/Result.tsx";
|
import {Index} from "../components/Result";
|
||||||
|
import {DashboardIndex} from "./dashboard";
|
||||||
|
|
||||||
const routerMode: 'browser' | 'hash' | string = APP_CONFIG.ROUTER_MODE;
|
const routerMode: 'browser' | 'hash' | string = APP_CONFIG.ROUTER_MODE;
|
||||||
|
|
||||||
@ -15,7 +16,7 @@ const WebRouter: React.FC<{
|
|||||||
|
|
||||||
const NotFound: React.FC = () => {
|
const NotFound: React.FC = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
return <Result
|
return <Index
|
||||||
status="404"
|
status="404"
|
||||||
title="页面不存在或无法找到所请求的资源"
|
title="页面不存在或无法找到所请求的资源"
|
||||||
// subTitle="Sorry, the page you visited does not exist."
|
// subTitle="Sorry, the page you visited does not exist."
|
||||||
@ -25,6 +26,7 @@ export const AppRouter = () => (<WebRouter>
|
|||||||
<div className="page-body-content">
|
<div className="page-body-content">
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<DefaultPage/>}/>
|
<Route path="/" element={<DefaultPage/>}/>
|
||||||
|
<Route path="/dashboard" element={<DashboardIndex/>}/>
|
||||||
<Route path="*" element={<NotFound/>}/>
|
<Route path="*" element={<NotFound/>}/>
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
|
130
front/pages/dashboard/index.tsx
Normal file
130
front/pages/dashboard/index.tsx
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
import React from "react";
|
||||||
|
import {Panel} from "../../components/panel";
|
||||||
|
import {AppList} from "../../components/AppList";
|
||||||
|
import {AppModel, EventDataModel, EventModel} from "../../../model";
|
||||||
|
import {appList, appEventList, appEventDataList} from "../../service/api.app.ts";
|
||||||
|
import './style.scss'
|
||||||
|
import {Space, Table} from "@douyinfe/semi-ui";
|
||||||
|
import {formatDate} from "../../../utils/date.ts";
|
||||||
|
import {useInterval} from "ahooks";
|
||||||
|
|
||||||
|
export const DashboardIndex: React.FC = () => {
|
||||||
|
// 数据
|
||||||
|
const [apps, setApps] = React.useState<AppModel[]>([]);
|
||||||
|
const [currentAppID, setCurrentAppID] = React.useState<number>(0);
|
||||||
|
const [events, setEvents] = React.useState<EventModel[]>([]);
|
||||||
|
const [eventDataList, setEventDataList] = React.useState<EventDataModel[]>([]);
|
||||||
|
const [page, setPage] = React.useState<number>(1);
|
||||||
|
const [dataTotal, setDataTotal] = React.useState<number>(0);
|
||||||
|
|
||||||
|
const eventDataColumns = [
|
||||||
|
{
|
||||||
|
title: '编号',
|
||||||
|
dataIndex: 'id',
|
||||||
|
width: 60
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '事件',
|
||||||
|
dataIndex: 'title',
|
||||||
|
width: 80
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '路径',
|
||||||
|
dataIndex: 'path',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '访问者浏览器',
|
||||||
|
ellipsis: true,
|
||||||
|
dataIndex: 'browser'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '来源',
|
||||||
|
dataIndex: 'ip',
|
||||||
|
width: 80
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '分辨率',
|
||||||
|
dataIndex: 'resolution',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '日期',
|
||||||
|
dataIndex: 'create_time',
|
||||||
|
render: (text: string) => formatDate(text),
|
||||||
|
width: 180
|
||||||
|
},
|
||||||
|
]
|
||||||
|
// 加载应用所有的事件
|
||||||
|
const getAppEvents = () => {
|
||||||
|
appEventList(currentAppID).then(list => setEvents(list))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载引用所有事件上报的数据
|
||||||
|
const loadAppEventsAndDataList = (page = 1) => {
|
||||||
|
appEventDataList({
|
||||||
|
appId: currentAppID,
|
||||||
|
pageSize: 10,
|
||||||
|
page
|
||||||
|
}).then(list => {
|
||||||
|
setEventDataList(list)
|
||||||
|
setPage(page)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getAppEventAndData = ()=>{
|
||||||
|
if (currentAppID > 0) {
|
||||||
|
getAppEvents()
|
||||||
|
loadAppEventsAndDataList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 10s 自动刷新
|
||||||
|
useInterval(loadAppEventsAndDataList, 10000)
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
appList().then(list => setApps(list))
|
||||||
|
}, [])
|
||||||
|
React.useEffect(getAppEventAndData, [currentAppID])
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="dashboard container">
|
||||||
|
<div>
|
||||||
|
<h1>Dashboard</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Panel title="我的应用" noPadding>
|
||||||
|
<AppList
|
||||||
|
list={apps}
|
||||||
|
onItemClick={(it) => setCurrentAppID(it.id)}
|
||||||
|
/>
|
||||||
|
</Panel>
|
||||||
|
{currentAppID > 0 && <>
|
||||||
|
<Panel title="事件列表" noPadding>
|
||||||
|
<div className="app-list-wrapper">
|
||||||
|
{events.map(it => (
|
||||||
|
<div key={it.id} className="list-link-item flex space-between">
|
||||||
|
<Space className="space">
|
||||||
|
<span>{it.id}</span>
|
||||||
|
<span>{it.title}</span>
|
||||||
|
</Space>
|
||||||
|
<span>查看</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Panel>
|
||||||
|
<Panel title="事件数据">
|
||||||
|
<div>
|
||||||
|
<Table columns={eventDataColumns} dataSource={eventDataList} pagination={{
|
||||||
|
currentPage: page,
|
||||||
|
pageSize: 10,
|
||||||
|
total: dataTotal,
|
||||||
|
onPageChange: loadAppEventsAndDataList,
|
||||||
|
hideOnSinglePage: true
|
||||||
|
}}/>
|
||||||
|
</div>
|
||||||
|
</Panel>
|
||||||
|
</>}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
9
front/pages/dashboard/style.scss
Normal file
9
front/pages/dashboard/style.scss
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.app-list-wrapper{
|
||||||
|
.list-link-item{
|
||||||
|
padding:10px;
|
||||||
|
border-bottom: solid 1px #eee;
|
||||||
|
&:last-child{
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import React, {useRef, useState} from "react";
|
import React, {useEffect, useRef, useState} from "react";
|
||||||
import {IconGithubLogo, IconWeibo} from "@douyinfe/semi-icons";
|
import {IconGithubLogo, IconWeibo} from "@douyinfe/semi-icons";
|
||||||
import css from './index.module.scss'
|
import css from './index.module.scss'
|
||||||
import {LoginComponent} from "../../components/LoginComponent.tsx";
|
import {LoginComponent} from "../../components/LoginComponent.tsx";
|
||||||
@ -11,13 +11,12 @@ const DefaultPage: React.FC = () => {
|
|||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const {login} = useUserinfoStore()
|
const {login, userinfo} = useUserinfoStore()
|
||||||
|
|
||||||
const onFinish = async (values: any) => {
|
const onFinish = async (values: any) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const user = await login(values)
|
const user = await login(values)
|
||||||
setVisible(true);
|
|
||||||
navigate('/dashboard')
|
navigate('/dashboard')
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// 登录失败
|
// 登录失败
|
||||||
@ -30,8 +29,12 @@ const DefaultPage: React.FC = () => {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const [visible, setVisible] = useState(false);
|
|
||||||
const hideModal = () => setVisible(false)
|
useEffect(() => {
|
||||||
|
if (userinfo && userinfo.id > 0) {
|
||||||
|
navigate('/dashboard')
|
||||||
|
}
|
||||||
|
}, [userinfo])
|
||||||
|
|
||||||
return (<div className={css.index}>
|
return (<div className={css.index}>
|
||||||
{/*<LoginComponent/>*/}
|
{/*<LoginComponent/>*/}
|
||||||
|
22
front/service/api.app.ts
Normal file
22
front/service/api.app.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import {get, post} from "./request.ts";
|
||||||
|
import {AppModel, EventDataModel, EventModel, UserModel} from "../../model";
|
||||||
|
|
||||||
|
// 获取用户归属应用列表
|
||||||
|
export function appList() {
|
||||||
|
return get<AppModel[]>('/api/app/list')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据应用id获取应用所有的事件列表
|
||||||
|
export function appEventList(appId: number) {
|
||||||
|
return get<EventModel[]>('/api/app/event', {appId})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据应用id获取应用所有的事件数据列表
|
||||||
|
export function appEventDataList(params: {
|
||||||
|
appId: number;
|
||||||
|
eventId?: number;
|
||||||
|
page?: number;
|
||||||
|
pageSize?: number;
|
||||||
|
}) {
|
||||||
|
return get<EventDataModel[]>('/api/app/event-data', params)
|
||||||
|
}
|
@ -59,8 +59,22 @@ Axios.interceptors.response.use(res => {
|
|||||||
return Promise.reject(err)
|
return Promise.reject(err)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 将data对象转化为url参数
|
||||||
|
|
||||||
|
function dataToQueryString(data: any) {
|
||||||
|
if (!data) return '';
|
||||||
|
return Object.keys(data).map(key => {
|
||||||
|
return encodeURIComponent(key) + '=' + encodeURIComponent(data[key])
|
||||||
|
}).join('&')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export function request<T>(url: string, method: RequestMethod, data: any = null, getOriginResult = false) {
|
export function request<T>(url: string, method: RequestMethod, data: any = null, getOriginResult = false) {
|
||||||
return new Promise<T>((resolve, reject) => {
|
return new Promise<T>((resolve, reject) => {
|
||||||
|
if (method == 'get' && data) {
|
||||||
|
url += `?${dataToQueryString(data)}`
|
||||||
|
data = null
|
||||||
|
}
|
||||||
Axios.request<APIResponse<T>>({
|
Axios.request<APIResponse<T>>({
|
||||||
url,
|
url,
|
||||||
method,
|
method,
|
||||||
@ -103,10 +117,10 @@ export function uploadFile<T>(url: string, file: File, data: any = {}, returnOri
|
|||||||
return request<T>(url, 'post', formData, returnOrigin)
|
return request<T>(url, 'post', formData, returnOrigin)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function post<T>(url: string, data: any = {}) {
|
export function post<T>(url: string, data: any = null) {
|
||||||
return request<T>(url, 'post', data)
|
return request<T>(url, 'post', data)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get<T>(url: string, data: any = {}) {
|
export function get<T>(url: string, data: any = null) {
|
||||||
return request<T>(url, 'get', data)
|
return request<T>(url, 'get', data)
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ export const useUserinfoStore = create<{
|
|||||||
/**
|
/**
|
||||||
* 初始化用户数据
|
* 初始化用户数据
|
||||||
*/
|
*/
|
||||||
init: () => Promise<void>;
|
init: () => void;
|
||||||
}>((set, _, _state) => {
|
}>((set, _, _state) => {
|
||||||
return {
|
return {
|
||||||
userinfo: {
|
userinfo: {
|
||||||
@ -43,20 +43,28 @@ export const useUserinfoStore = create<{
|
|||||||
init: () => {
|
init: () => {
|
||||||
const state = _state.getState()
|
const state = _state.getState()
|
||||||
if (state.token) {
|
if (state.token) {
|
||||||
return Promise.resolve()
|
return;
|
||||||
}
|
}
|
||||||
const token = Storage.get<string>(LOGIN_TOKEN_KEY);
|
const token = Storage.get<string>(LOGIN_TOKEN_KEY);
|
||||||
return new Promise<void>((resolve) => {
|
if (token) {
|
||||||
if (token) {
|
getInfo().then((info) => {
|
||||||
getInfo().then((info) => {
|
set({
|
||||||
set({
|
userinfo: info,
|
||||||
userinfo: info,
|
token
|
||||||
token
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
})
|
||||||
resolve();
|
}
|
||||||
});
|
// return new Promise<void>((resolve) => {
|
||||||
|
// if (token) {
|
||||||
|
// getInfo().then((info) => {
|
||||||
|
// set({
|
||||||
|
// userinfo: info,
|
||||||
|
// token
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// resolve();
|
||||||
|
// });
|
||||||
},
|
},
|
||||||
logout: () => {
|
logout: () => {
|
||||||
return new Promise<void>((resolve) => {
|
return new Promise<void>((resolve) => {
|
||||||
|
@ -17,6 +17,8 @@ export type EventDataModel = {
|
|||||||
uid: number;
|
uid: number;
|
||||||
uuid: number;
|
uuid: number;
|
||||||
type: 'pv' | 'uv' | string;
|
type: 'pv' | 'uv' | string;
|
||||||
|
title:string;
|
||||||
|
description:string;
|
||||||
location: string;
|
location: string;
|
||||||
resolution: string;
|
resolution: string;
|
||||||
browser: string;
|
browser: string;
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
"@douyinfe/semi-ui": "^2.41.3",
|
"@douyinfe/semi-ui": "^2.41.3",
|
||||||
"@emotion/css": "^11.11.2",
|
"@emotion/css": "^11.11.2",
|
||||||
"@types/express": "^4.17.17",
|
"@types/express": "^4.17.17",
|
||||||
|
"@types/md5": "^2.3.2",
|
||||||
"@types/mocha": "^10.0.1",
|
"@types/mocha": "^10.0.1",
|
||||||
"@types/mysql": "^2.15.21",
|
"@types/mysql": "^2.15.21",
|
||||||
"@types/node": "^20.4.9",
|
"@types/node": "^20.4.9",
|
||||||
@ -24,6 +25,7 @@
|
|||||||
"@types/react-dom": "^18.2.7",
|
"@types/react-dom": "^18.2.7",
|
||||||
"@types/supertest": "^2.0.12",
|
"@types/supertest": "^2.0.12",
|
||||||
"@vitejs/plugin-react": "^4.0.4",
|
"@vitejs/plugin-react": "^4.0.4",
|
||||||
|
"ahooks": "^3.7.8",
|
||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
"dayjs": "^1.11.9",
|
"dayjs": "^1.11.9",
|
||||||
"mocha": "^10.2.0",
|
"mocha": "^10.2.0",
|
||||||
@ -39,7 +41,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
|
"md5": "^2.3.0",
|
||||||
"mysql": "^2.18.1",
|
"mysql": "^2.18.1",
|
||||||
|
"redis": "^4.6.7",
|
||||||
"ts-node": "^10.9.1"
|
"ts-node": "^10.9.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
@ -1,4 +1,4 @@
|
|||||||
import { InitServerOption } from "./types";
|
import {InitServerOption} from "./types";
|
||||||
// import { createServer as createServerOrigin } from "http";
|
// import { createServer as createServerOrigin } from "http";
|
||||||
// import express = require("express");
|
// import express = require("express");
|
||||||
import * as express from "express";
|
import * as express from "express";
|
||||||
@ -8,9 +8,23 @@ export function createServer(options: Partial<InitServerOption>, callback?: () =
|
|||||||
const app = express();
|
const app = express();
|
||||||
// 将请求体转换为JSON格式
|
// 将请求体转换为JSON格式
|
||||||
app.use(express.json())
|
app.use(express.json())
|
||||||
app.use(express.urlencoded({ extended: true }))
|
app.use(express.urlencoded({extended: true}))
|
||||||
// 监听端口
|
// 监听端口
|
||||||
app.listen(options.port, callback);
|
app.listen(options.port, callback);
|
||||||
|
// 添加允许跨域中间件
|
||||||
|
app.use(function (req, res, next) {
|
||||||
|
const method = req.method.toLowerCase();
|
||||||
|
res.header("Access-Control-Allow-Origin", "*");
|
||||||
|
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
|
||||||
|
// res.header("Access-Control-Allow-Credentials", "true");
|
||||||
|
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
|
||||||
|
if (method === 'options') {
|
||||||
|
res.status(200).end('OK');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
app.get('/ping', (_req, res) => {
|
app.get('/ping', (_req, res) => {
|
||||||
res.appendHeader('app-ping', 'pong')
|
res.appendHeader('app-ping', 'pong')
|
||||||
res.send('pong')
|
res.send('pong')
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
import { Response, Request } from 'express'
|
import {Response, Request} from 'express'
|
||||||
|
import {IncomingHttpHeaders} from "http";
|
||||||
|
import {UserModel} from "../../model";
|
||||||
|
|
||||||
export type InitServerOption = {
|
export type InitServerOption = {
|
||||||
port: number;
|
port: number;
|
||||||
host: string;
|
host: string;
|
||||||
@ -11,8 +14,9 @@ export type RouteHandleFunctionParam = {
|
|||||||
query: Record<string, any>;
|
query: Record<string, any>;
|
||||||
body: Record<string, any>;
|
body: Record<string, any>;
|
||||||
method: HttpMethod;
|
method: HttpMethod;
|
||||||
headers: Record<string, string>;
|
user?: UserModel | null;
|
||||||
|
headers: IncomingHttpHeaders;
|
||||||
res: Response<any, Record<string, any>>
|
res: Response<any, Record<string, any>>
|
||||||
req: Request
|
req: Request
|
||||||
}
|
}
|
||||||
export type RouteHandleFunction = (params: RouteHandleFunctionParam) => void | Promise<void>;
|
export type RouteHandleFunction = (params: RouteHandleFunctionParam) => void | Promise<void>;
|
||||||
|
@ -2,21 +2,42 @@ import {Application, Request, Response} from "express";
|
|||||||
import {RouteHandleFunction, RouteHandleFunctionParam} from "../core/types";
|
import {RouteHandleFunction, RouteHandleFunctionParam} from "../core/types";
|
||||||
import {home} from "./home";
|
import {home} from "./home";
|
||||||
import {appList, reportToServer, appEvent, eventData} from "./reportor";
|
import {appList, reportToServer, appEvent, eventData} from "./reportor";
|
||||||
import {getUserInfo, loginHandler} from "./user.ts";
|
import {decodeUserToken, getUserInfo, loginHandler} from "./user.ts";
|
||||||
|
|
||||||
|
const excludes = [
|
||||||
|
'/home',
|
||||||
|
'/api/report',
|
||||||
|
]
|
||||||
|
|
||||||
//
|
//
|
||||||
function createRoute(handler: RouteHandleFunction) {
|
function createRoute(handler: RouteHandleFunction) {
|
||||||
return (req: Request, res: Response<any, Record<string, any>>) => {
|
return (req: Request, res: Response<any, Record<string, any>>) => {
|
||||||
// console.log('params', req.params, req.query, req.body)
|
// console.log('params', req.headers)
|
||||||
handler({
|
const params = {
|
||||||
path: req.path,
|
path: req.path,
|
||||||
param: req.params,
|
param: req.params,
|
||||||
query: req.query,
|
query: req.query,
|
||||||
body: req.body,
|
body: req.body,
|
||||||
method: req.method,
|
method: req.method,
|
||||||
headers: {},
|
headers: req.headers,
|
||||||
res,
|
res,
|
||||||
req
|
req
|
||||||
|
};
|
||||||
|
const path = req.path;
|
||||||
|
console.log('request path:', path)
|
||||||
|
if (excludes.includes(path)) {
|
||||||
|
return handler(params);
|
||||||
|
}
|
||||||
|
const token = req.headers.authorization
|
||||||
|
if (!token) {
|
||||||
|
res.send({code: 403, message: '请先登录'})
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
decodeUserToken(token).then(user => {
|
||||||
|
handler({
|
||||||
|
...params,
|
||||||
|
user: typeof (user) == "string" ? JSON.parse(user) : user
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,37 +1,46 @@
|
|||||||
import { RouteHandleFunction } from "../core/types";
|
import {RouteHandleFunction} from "../core/types";
|
||||||
import { listAppByUID } from "../service/app";
|
import {listAppByUID, listAppEvent, listAppEventData} from "../service/app";
|
||||||
import { reportEvent } from "../service/report-service";
|
import {reportEvent} from "../service/report-service";
|
||||||
|
|
||||||
|
|
||||||
export const reportToServer: RouteHandleFunction = ({
|
export const reportToServer: RouteHandleFunction =
|
||||||
param, res
|
({
|
||||||
}) => {
|
body, res
|
||||||
reportEvent(param).then(() => {
|
}) => {
|
||||||
res.send('got and saved!')
|
reportEvent(body).then(() => {
|
||||||
}).catch((e: Error) => {
|
res.send('got and saved!')
|
||||||
console.log(e)
|
}).catch((e: Error) => {
|
||||||
res.send('got but not saved!')
|
console.log(e)
|
||||||
});
|
res.send('got but not saved!')
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export const appList: RouteHandleFunction = async ({
|
export const appList: RouteHandleFunction =
|
||||||
param, res
|
async ({
|
||||||
}) => {
|
param, res
|
||||||
const apps = await listAppByUID(1);
|
}) => {
|
||||||
res.send({ code: 0, data: apps })
|
const apps = await listAppByUID(1);
|
||||||
}
|
res.send({code: 0, data: apps})
|
||||||
|
}
|
||||||
|
|
||||||
export const appEvent: RouteHandleFunction = async ({
|
export const appEvent: RouteHandleFunction =
|
||||||
query, res, param, body
|
async ({
|
||||||
}) => {
|
query, res, param, body
|
||||||
|
}) => {
|
||||||
|
const events = await listAppEvent(query.appId)
|
||||||
|
res.send({
|
||||||
|
code: 0,
|
||||||
|
data: events
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
res.send({
|
export const eventData: RouteHandleFunction =
|
||||||
query, param, body
|
async ({
|
||||||
})
|
query, res
|
||||||
}
|
}) => {
|
||||||
|
const data = await listAppEventData(Number(query.appId), Number(query.page), Number(query.pageSize))
|
||||||
export const eventData: RouteHandleFunction = ({
|
res.send({
|
||||||
param, res
|
code: 0,
|
||||||
}) => {
|
data
|
||||||
res.send(JSON.stringify(param))
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,22 @@
|
|||||||
import {RouteHandleFunction} from "../core/types.ts";
|
import {RouteHandleFunction} from "../core/types.ts";
|
||||||
import {login} from "../service/app.ts";
|
import {login} from "../service/app.ts";
|
||||||
import {UserModel} from "../../model";
|
import {UserModel} from "../../model";
|
||||||
|
import {getFromRedis, setToRedis} from "../service/redis.ts";
|
||||||
|
|
||||||
export function encodeUserToken(user: UserModel) {
|
export function encodeUserToken(user: UserModel) {
|
||||||
if (user == null) throw new Error('user is null')
|
if (user == null) throw new Error('user is null')
|
||||||
const token = JSON.stringify(user)
|
// const token = JSON.stringify(user)
|
||||||
return btoa(encodeURIComponent(token));
|
const token = btoa(user.id + ':' + Date.now())
|
||||||
|
setToRedis('app-report:user:' + token, JSON.stringify(user)).then(() => console.log('setToRedis success'));
|
||||||
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function decodeUserToken(token: string) {
|
export function decodeUserToken(token: string) {
|
||||||
// 将token转回UserModel对象数据
|
// 将token转回UserModel对象数据
|
||||||
const user = decodeURIComponent(atob(token));
|
// const user = decodeURIComponent(atob(token));
|
||||||
return JSON.parse(user) as UserModel
|
console.log('decodeUserToken token==>app-report:user:', token)
|
||||||
|
return getFromRedis<UserModel>('app-report:user:' + token)
|
||||||
|
// return JSON.parse(user) as UserModel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -38,8 +43,14 @@ export const loginHandler: RouteHandleFunction
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const getUserInfo: RouteHandleFunction =
|
export const getUserInfo: RouteHandleFunction =
|
||||||
({headers, res}) => {
|
async ({headers,user, res}) => {
|
||||||
const token = headers.Authorization
|
const token = headers.authorization
|
||||||
const user = decodeUserToken(token)
|
if (!token) {
|
||||||
res.send({code: 0, message: '登录成功', data: user})
|
res.send({code: 403, message: '请先登录'})
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!user) {
|
||||||
|
res.send({code: 403, message: '请先登录'})
|
||||||
|
}
|
||||||
|
res.send({code: 0, message: 'success', data: user})
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ export function listAppEvent(id: number) {
|
|||||||
|
|
||||||
// 查询应用所有的事件数据
|
// 查询应用所有的事件数据
|
||||||
export function listAppEventData(id: number, page = 1, pageSize = 10) {
|
export function listAppEventData(id: number, page = 1, pageSize = 10) {
|
||||||
return selectArray<EventModel>('select * from events_data where app_id=? limit ?,?',
|
return selectArray<EventModel>('select d.*,e.title,e.type,e.description from events_data d,events e where d.event_id = e.id and d.app_id=? limit ?,?',
|
||||||
[id, (page - 1) * pageSize, pageSize])
|
[id, (page - 1) * pageSize, pageSize])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ export async function selectOne<T>(sql: string, params: any = null) {
|
|||||||
// 统计数据
|
// 统计数据
|
||||||
export async function queryCount(sql: string, params: any = null) {
|
export async function queryCount(sql: string, params: any = null) {
|
||||||
const obj = await selectOne<{ [key: string]: number }>(sql, params);
|
const obj = await selectOne<{ [key: string]: number }>(sql, params);
|
||||||
if(!obj) return 0;
|
if (!obj) return 0;
|
||||||
const keys = Object.keys(obj);
|
const keys = Object.keys(obj);
|
||||||
return obj[keys[0]];
|
return obj[keys[0]];
|
||||||
}
|
}
|
||||||
@ -68,13 +68,14 @@ export async function isExist(sql: string, params: any) {
|
|||||||
|
|
||||||
function executeSQL<T>(sql: string, params: any) {
|
function executeSQL<T>(sql: string, params: any) {
|
||||||
return new Promise<T>((resolve, reject) => {
|
return new Promise<T>((resolve, reject) => {
|
||||||
pool.query(sql, params, (err, ret) => {
|
const q = pool.query(sql, params, (err, ret) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(err)
|
reject(err)
|
||||||
} else {
|
} else {
|
||||||
resolve(ret)
|
resolve(ret)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
console.log('[SQL]: ' + q.sql,params)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
32
service/service/redis.ts
Normal file
32
service/service/redis.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import {createClient} from 'redis';
|
||||||
|
|
||||||
|
const client = createClient();
|
||||||
|
|
||||||
|
client.on('error', err => console.log('Redis Client', err));
|
||||||
|
|
||||||
|
client.connect().then(() => {
|
||||||
|
console.log('connected to redis success')
|
||||||
|
})
|
||||||
|
|
||||||
|
export async function setToRedis(key: string, value: any, expire?: number) {
|
||||||
|
if (!value) throw new Error('value is required');
|
||||||
|
await client.set(key, JSON.stringify(value))
|
||||||
|
if (expire) await client.expire(key, expire);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// export async function getString(key: string) {
|
||||||
|
// const data = await client.get(key);
|
||||||
|
// if (!data) return null;
|
||||||
|
// return data;
|
||||||
|
// }
|
||||||
|
|
||||||
|
export async function getFromRedis<T>(key: string) {
|
||||||
|
const data = await client.get(key);
|
||||||
|
if (!data) return null;
|
||||||
|
console.log('getFromRedis=>',typeof(data),data)
|
||||||
|
return JSON.parse(data) as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出客户端)
|
||||||
|
export default client;
|
@ -1,19 +1,16 @@
|
|||||||
import { PvUvModel } from "../../model";
|
import { PvUvModel } from "../../model";
|
||||||
import { isExist, insertAndGetInsertId } from './mysql'
|
import { isExist, insertAndGetInsertId } from './mysql'
|
||||||
|
|
||||||
const table = {
|
|
||||||
pv_uv: 'pv_uv'
|
|
||||||
}
|
|
||||||
export async function reportEvent(data: Partial<PvUvModel>) {
|
export async function reportEvent(data: Partial<PvUvModel>) {
|
||||||
//pv:用户每次打开一个页面便记录1次PV,多次打开同一页面则浏览量累计。
|
//pv:用户每次打开一个页面便记录1次PV,多次打开同一页面则浏览量累计。
|
||||||
//uv:1天内同一访客的多次访问只记录为一个访客。通过IP和cookie是判断UV值的两种方式。
|
//uv:1天内同一访客的多次访问只记录为一个访客。通过IP和cookie是判断UV值的两种方式。
|
||||||
const { type } = data;
|
const { type } = data;
|
||||||
if (type == 'uv') {
|
if (type == 'uv') {
|
||||||
// 判断今日的数据是否已经存在
|
// 判断今日的数据是否已经存在
|
||||||
const existsToday = await isExist('select count(*) _ from pv_uv where DATE(created_at) = CURDATE() and uuid=?', [data.uuid])
|
const existsToday = await isExist('select count(*) _ from events_data where DATE(created_at) = CURDATE() and uuid=?', [data.uuid])
|
||||||
if (existsToday) {
|
if (existsToday) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await insertAndGetInsertId('pv_uv', data)
|
await insertAndGetInsertId('events_data', data)
|
||||||
}
|
}
|
||||||
|
140
yarn.lock
140
yarn.lock
@ -564,6 +564,40 @@
|
|||||||
"@jridgewell/resolve-uri" "^3.1.0"
|
"@jridgewell/resolve-uri" "^3.1.0"
|
||||||
"@jridgewell/sourcemap-codec" "^1.4.14"
|
"@jridgewell/sourcemap-codec" "^1.4.14"
|
||||||
|
|
||||||
|
"@redis/bloom@1.2.0":
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.npmmirror.com/@redis/bloom/-/bloom-1.2.0.tgz#d3fd6d3c0af3ef92f26767b56414a370c7b63b71"
|
||||||
|
integrity sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==
|
||||||
|
|
||||||
|
"@redis/client@1.5.8":
|
||||||
|
version "1.5.8"
|
||||||
|
resolved "https://registry.npmmirror.com/@redis/client/-/client-1.5.8.tgz#a375ba7861825bd0d2dc512282b8bff7b98dbcb1"
|
||||||
|
integrity sha512-xzElwHIO6rBAqzPeVnCzgvrnBEcFL1P0w8P65VNLRkdVW8rOE58f52hdj0BDgmsdOm4f1EoXPZtH4Fh7M/qUpw==
|
||||||
|
dependencies:
|
||||||
|
cluster-key-slot "1.1.2"
|
||||||
|
generic-pool "3.9.0"
|
||||||
|
yallist "4.0.0"
|
||||||
|
|
||||||
|
"@redis/graph@1.1.0":
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.npmmirror.com/@redis/graph/-/graph-1.1.0.tgz#cc2b82e5141a29ada2cce7d267a6b74baa6dd519"
|
||||||
|
integrity sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==
|
||||||
|
|
||||||
|
"@redis/json@1.0.4":
|
||||||
|
version "1.0.4"
|
||||||
|
resolved "https://registry.npmmirror.com/@redis/json/-/json-1.0.4.tgz#f372b5f93324e6ffb7f16aadcbcb4e5c3d39bda1"
|
||||||
|
integrity sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==
|
||||||
|
|
||||||
|
"@redis/search@1.1.3":
|
||||||
|
version "1.1.3"
|
||||||
|
resolved "https://registry.npmmirror.com/@redis/search/-/search-1.1.3.tgz#b5a6837522ce9028267fe6f50762a8bcfd2e998b"
|
||||||
|
integrity sha512-4Dg1JjvCevdiCBTZqjhKkGoC5/BcB7k9j99kdMnaXFXg8x4eyOIVg9487CMv7/BUVkFLZCaIh8ead9mU15DNng==
|
||||||
|
|
||||||
|
"@redis/time-series@1.0.4":
|
||||||
|
version "1.0.4"
|
||||||
|
resolved "https://registry.npmmirror.com/@redis/time-series/-/time-series-1.0.4.tgz#af85eb080f6934580e4d3b58046026b6c2b18717"
|
||||||
|
integrity sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==
|
||||||
|
|
||||||
"@remix-run/router@1.8.0":
|
"@remix-run/router@1.8.0":
|
||||||
version "1.8.0"
|
version "1.8.0"
|
||||||
resolved "https://registry.npmmirror.com/@remix-run/router/-/router-1.8.0.tgz#e848d2f669f601544df15ce2a313955e4bf0bafc"
|
resolved "https://registry.npmmirror.com/@remix-run/router/-/router-1.8.0.tgz#e848d2f669f601544df15ce2a313955e4bf0bafc"
|
||||||
@ -634,6 +668,16 @@
|
|||||||
resolved "https://registry.npmmirror.com/@types/http-errors/-/http-errors-2.0.1.tgz#20172f9578b225f6c7da63446f56d4ce108d5a65"
|
resolved "https://registry.npmmirror.com/@types/http-errors/-/http-errors-2.0.1.tgz#20172f9578b225f6c7da63446f56d4ce108d5a65"
|
||||||
integrity sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==
|
integrity sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==
|
||||||
|
|
||||||
|
"@types/js-cookie@^2.x.x":
|
||||||
|
version "2.2.7"
|
||||||
|
resolved "https://registry.npmmirror.com/@types/js-cookie/-/js-cookie-2.2.7.tgz#226a9e31680835a6188e887f3988e60c04d3f6a3"
|
||||||
|
integrity sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==
|
||||||
|
|
||||||
|
"@types/md5@^2.3.2":
|
||||||
|
version "2.3.2"
|
||||||
|
resolved "https://registry.npmmirror.com/@types/md5/-/md5-2.3.2.tgz#529bb3f8a7e9e9f621094eb76a443f585d882528"
|
||||||
|
integrity sha512-v+JFDu96+UYJ3/UWzB0mEglIS//MZXgRaJ4ubUPwOM0gvLc/kcQ3TWNYwENEK7/EcXGQVrW8h/XqednSjBd/Og==
|
||||||
|
|
||||||
"@types/mime@*":
|
"@types/mime@*":
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.npmmirror.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10"
|
resolved "https://registry.npmmirror.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10"
|
||||||
@ -767,6 +811,27 @@ acorn@^8.4.1:
|
|||||||
resolved "https://registry.npmmirror.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5"
|
resolved "https://registry.npmmirror.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5"
|
||||||
integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==
|
integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==
|
||||||
|
|
||||||
|
ahooks-v3-count@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.npmmirror.com/ahooks-v3-count/-/ahooks-v3-count-1.0.0.tgz#ddeb392e009ad6e748905b3cbf63a9fd8262ca80"
|
||||||
|
integrity sha512-V7uUvAwnimu6eh/PED4mCDjE7tokeZQLKlxg9lCTMPhN+NjsSbtdacByVlR1oluXQzD3MOw55wylDmQo4+S9ZQ==
|
||||||
|
|
||||||
|
ahooks@^3.7.8:
|
||||||
|
version "3.7.8"
|
||||||
|
resolved "https://registry.npmmirror.com/ahooks/-/ahooks-3.7.8.tgz#3fa3c491cd153e884a32b0c4192fc72cf84c4332"
|
||||||
|
integrity sha512-e/NMlQWoCjaUtncNFIZk3FG1ImSkV/JhScQSkTqnftakRwdfZWSw6zzoWSG9OMYqPNs2MguDYBUFFC6THelWXA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.21.0"
|
||||||
|
"@types/js-cookie" "^2.x.x"
|
||||||
|
ahooks-v3-count "^1.0.0"
|
||||||
|
dayjs "^1.9.1"
|
||||||
|
intersection-observer "^0.12.0"
|
||||||
|
js-cookie "^2.x.x"
|
||||||
|
lodash "^4.17.21"
|
||||||
|
resize-observer-polyfill "^1.5.1"
|
||||||
|
screenfull "^5.0.0"
|
||||||
|
tslib "^2.4.1"
|
||||||
|
|
||||||
ansi-colors@4.1.1:
|
ansi-colors@4.1.1:
|
||||||
version "4.1.1"
|
version "4.1.1"
|
||||||
resolved "https://registry.npmmirror.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
|
resolved "https://registry.npmmirror.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
|
||||||
@ -967,6 +1032,11 @@ chalk@^4.1.0:
|
|||||||
ansi-styles "^4.1.0"
|
ansi-styles "^4.1.0"
|
||||||
supports-color "^7.1.0"
|
supports-color "^7.1.0"
|
||||||
|
|
||||||
|
charenc@0.0.2:
|
||||||
|
version "0.0.2"
|
||||||
|
resolved "https://registry.npmmirror.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
|
||||||
|
integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==
|
||||||
|
|
||||||
chokidar@3.5.3, "chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.2:
|
chokidar@3.5.3, "chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.2:
|
||||||
version "3.5.3"
|
version "3.5.3"
|
||||||
resolved "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
|
resolved "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
|
||||||
@ -1001,6 +1071,11 @@ clsx@^1.1.1:
|
|||||||
resolved "https://registry.npmmirror.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12"
|
resolved "https://registry.npmmirror.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12"
|
||||||
integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==
|
integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==
|
||||||
|
|
||||||
|
cluster-key-slot@1.1.2:
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.npmmirror.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz#88ddaa46906e303b5de30d3153b7d9fe0a0c19ac"
|
||||||
|
integrity sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==
|
||||||
|
|
||||||
color-convert@^1.9.0:
|
color-convert@^1.9.0:
|
||||||
version "1.9.3"
|
version "1.9.3"
|
||||||
resolved "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
|
resolved "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
|
||||||
@ -1105,6 +1180,11 @@ create-require@^1.1.0:
|
|||||||
resolved "https://registry.npmmirror.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
|
resolved "https://registry.npmmirror.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
|
||||||
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
|
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
|
||||||
|
|
||||||
|
crypt@0.0.2:
|
||||||
|
version "0.0.2"
|
||||||
|
resolved "https://registry.npmmirror.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
|
||||||
|
integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==
|
||||||
|
|
||||||
csstype@^3.0.2:
|
csstype@^3.0.2:
|
||||||
version "3.1.2"
|
version "3.1.2"
|
||||||
resolved "https://registry.npmmirror.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b"
|
resolved "https://registry.npmmirror.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b"
|
||||||
@ -1122,7 +1202,7 @@ date-fns@^2.29.3:
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.21.0"
|
"@babel/runtime" "^7.21.0"
|
||||||
|
|
||||||
dayjs@^1.11.9:
|
dayjs@^1.11.9, dayjs@^1.9.1:
|
||||||
version "1.11.9"
|
version "1.11.9"
|
||||||
resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.9.tgz#9ca491933fadd0a60a2c19f6c237c03517d71d1a"
|
resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.9.tgz#9ca491933fadd0a60a2c19f6c237c03517d71d1a"
|
||||||
integrity sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==
|
integrity sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==
|
||||||
@ -1395,6 +1475,11 @@ function-bind@^1.1.1:
|
|||||||
resolved "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
resolved "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||||
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
||||||
|
|
||||||
|
generic-pool@3.9.0:
|
||||||
|
version "3.9.0"
|
||||||
|
resolved "https://registry.npmmirror.com/generic-pool/-/generic-pool-3.9.0.tgz#36f4a678e963f4fdb8707eab050823abc4e8f5e4"
|
||||||
|
integrity sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==
|
||||||
|
|
||||||
gensync@^1.0.0-beta.2:
|
gensync@^1.0.0-beta.2:
|
||||||
version "1.0.0-beta.2"
|
version "1.0.0-beta.2"
|
||||||
resolved "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
resolved "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
||||||
@ -1537,6 +1622,11 @@ inherits@2, inherits@2.0.4, inherits@~2.0.3:
|
|||||||
resolved "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
resolved "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||||
|
|
||||||
|
intersection-observer@^0.12.0:
|
||||||
|
version "0.12.2"
|
||||||
|
resolved "https://registry.npmmirror.com/intersection-observer/-/intersection-observer-0.12.2.tgz#4a45349cc0cd91916682b1f44c28d7ec737dc375"
|
||||||
|
integrity sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==
|
||||||
|
|
||||||
ipaddr.js@1.9.1:
|
ipaddr.js@1.9.1:
|
||||||
version "1.9.1"
|
version "1.9.1"
|
||||||
resolved "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
|
resolved "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
|
||||||
@ -1554,6 +1644,11 @@ is-binary-path@~2.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
binary-extensions "^2.0.0"
|
binary-extensions "^2.0.0"
|
||||||
|
|
||||||
|
is-buffer@~1.1.6:
|
||||||
|
version "1.1.6"
|
||||||
|
resolved "https://registry.npmmirror.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
||||||
|
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
|
||||||
|
|
||||||
is-core-module@^2.13.0:
|
is-core-module@^2.13.0:
|
||||||
version "2.13.0"
|
version "2.13.0"
|
||||||
resolved "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db"
|
resolved "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db"
|
||||||
@ -1598,6 +1693,11 @@ isarray@~1.0.0:
|
|||||||
resolved "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
resolved "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||||
integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==
|
integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==
|
||||||
|
|
||||||
|
js-cookie@^2.x.x:
|
||||||
|
version "2.2.1"
|
||||||
|
resolved "https://registry.npmmirror.com/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8"
|
||||||
|
integrity sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==
|
||||||
|
|
||||||
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
|
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
resolved "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||||
@ -1676,6 +1776,15 @@ make-error@^1.1.1:
|
|||||||
resolved "https://registry.npmmirror.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
|
resolved "https://registry.npmmirror.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
|
||||||
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
|
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
|
||||||
|
|
||||||
|
md5@^2.3.0:
|
||||||
|
version "2.3.0"
|
||||||
|
resolved "https://registry.npmmirror.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f"
|
||||||
|
integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==
|
||||||
|
dependencies:
|
||||||
|
charenc "0.0.2"
|
||||||
|
crypt "0.0.2"
|
||||||
|
is-buffer "~1.1.6"
|
||||||
|
|
||||||
media-typer@0.3.0:
|
media-typer@0.3.0:
|
||||||
version "0.3.0"
|
version "0.3.0"
|
||||||
resolved "https://registry.npmmirror.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
resolved "https://registry.npmmirror.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
||||||
@ -2088,6 +2197,18 @@ readdirp@~3.6.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
picomatch "^2.2.1"
|
picomatch "^2.2.1"
|
||||||
|
|
||||||
|
redis@^4.6.7:
|
||||||
|
version "4.6.7"
|
||||||
|
resolved "https://registry.npmmirror.com/redis/-/redis-4.6.7.tgz#c73123ad0b572776223f172ec78185adb72a6b57"
|
||||||
|
integrity sha512-KrkuNJNpCwRm5vFJh0tteMxW8SaUzkm5fBH7eL5hd/D0fAkzvapxbfGPP/r+4JAXdQuX7nebsBkBqA2RHB7Usw==
|
||||||
|
dependencies:
|
||||||
|
"@redis/bloom" "1.2.0"
|
||||||
|
"@redis/client" "1.5.8"
|
||||||
|
"@redis/graph" "1.1.0"
|
||||||
|
"@redis/json" "1.0.4"
|
||||||
|
"@redis/search" "1.1.3"
|
||||||
|
"@redis/time-series" "1.0.4"
|
||||||
|
|
||||||
regenerator-runtime@^0.14.0:
|
regenerator-runtime@^0.14.0:
|
||||||
version "0.14.0"
|
version "0.14.0"
|
||||||
resolved "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45"
|
resolved "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45"
|
||||||
@ -2155,6 +2276,11 @@ scheduler@^0.23.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
loose-envify "^1.1.0"
|
loose-envify "^1.1.0"
|
||||||
|
|
||||||
|
screenfull@^5.0.0:
|
||||||
|
version "5.2.0"
|
||||||
|
resolved "https://registry.npmmirror.com/screenfull/-/screenfull-5.2.0.tgz#6533d524d30621fc1283b9692146f3f13a93d1ba"
|
||||||
|
integrity sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==
|
||||||
|
|
||||||
scroll-into-view-if-needed@^2.2.24:
|
scroll-into-view-if-needed@^2.2.24:
|
||||||
version "2.2.31"
|
version "2.2.31"
|
||||||
resolved "https://registry.npmmirror.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz#d3c482959dc483e37962d1521254e3295d0d1587"
|
resolved "https://registry.npmmirror.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz#d3c482959dc483e37962d1521254e3295d0d1587"
|
||||||
@ -2377,7 +2503,7 @@ ts-node@^10.9.1:
|
|||||||
v8-compile-cache-lib "^3.0.1"
|
v8-compile-cache-lib "^3.0.1"
|
||||||
yn "3.1.1"
|
yn "3.1.1"
|
||||||
|
|
||||||
tslib@^2.0.0:
|
tslib@^2.0.0, tslib@^2.4.1:
|
||||||
version "2.6.2"
|
version "2.6.2"
|
||||||
resolved "https://registry.npmmirror.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
|
resolved "https://registry.npmmirror.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
|
||||||
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
|
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
|
||||||
@ -2478,16 +2604,16 @@ y18n@^5.0.5:
|
|||||||
resolved "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
|
resolved "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
|
||||||
integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
|
integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
|
||||||
|
|
||||||
|
yallist@4.0.0, yallist@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||||
|
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||||
|
|
||||||
yallist@^3.0.2:
|
yallist@^3.0.2:
|
||||||
version "3.1.1"
|
version "3.1.1"
|
||||||
resolved "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
|
resolved "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
|
||||||
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
|
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
|
||||||
|
|
||||||
yallist@^4.0.0:
|
|
||||||
version "4.0.0"
|
|
||||||
resolved "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
|
||||||
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
|
||||||
|
|
||||||
yaml@^1.10.0:
|
yaml@^1.10.0:
|
||||||
version "1.10.2"
|
version "1.10.2"
|
||||||
resolved "https://registry.npmmirror.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
resolved "https://registry.npmmirror.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user