Feat: Frontend Pages

前端页面初始化,暂时只有三个页面,代码还比较粗糙
This commit is contained in:
奇趣保罗 2022-04-12 00:26:08 +08:00
parent 50f76e3947
commit 0fb853a1bd
13 changed files with 2190 additions and 87 deletions

View File

@ -2,9 +2,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="src/favicon.svg" />
<link rel="icon" href="/src/images/icon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
<title>保罗 API Next</title>
<link href="https://fastly.jsdelivr.net/gh/FortAwesome/Font-Awesome/css/font-awesome.min.css" rel="stylesheet" type="text/css">
</head>
<body>
<div id="root"></div>

View File

@ -12,11 +12,13 @@
"@midwayjs/hooks-kit": "^3.0.0",
"@midwayjs/koa": "^3.3.0",
"@midwayjs/rpc": "^3.0.0",
"@prisma/client": "^3.12.0",
"ahooks": "^3.3.0",
"isomorphic-unfetch": "^3.1.0",
"lodash": "^4.17.21",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "^6.3.0",
"redis": "^4.0.6"
},
"devDependencies": {
@ -25,6 +27,10 @@
"@types/react": "^17.0.44",
"@types/react-dom": "^17.0.15",
"@vitejs/plugin-react": "^1.3.0",
"prisma": "^3.12.0",
"typescript": "^4.6.3"
},
"prisma": {
"seed": "ts-node prisma/seed.ts"
}
}

View File

@ -0,0 +1,51 @@
// React
import React, { useState } from "react";
// UI
import { Link } from "react-router-dom";
import Avatar from "../../images/avatar.jpg";
// Components
function Aside() {
const [sideOpen, setSideOpen] = useState(false);
const toggleClick = () => {
setSideOpen(!sideOpen);
}
return (
<aside className={sideOpen ? "sidebar active" : "sidebar"}>
<div className="toggle" onClick={toggleClick}></div>
<div className="wrapper">
<div className="header">
<h1>API</h1>
</div>
<nav className="menu">
<a href="https://paul.ren" title="保罗的小窝"><i className="fa fa-home"></i></a>
<a href="https://paugram.com" target="_blank" title="保罗的博客"><i className="fa fa-book"></i></a>
<a href="https://paul.ren/project" title="保罗的项目"><i className="fa fa-magic"></i></a>
<nav className="has-child">
<Link to="/" title="保罗的 API"><i className="fa fa-gears"></i>API</Link>
<nav className="sub-menu">
<Link to="/netease"></Link>
<Link to="/wallpaper"></Link>
<Link to="/acgm"></Link>
{/* <Link to="/acgm">Gravatar 解析</Link> */}
<Link to="/bing"></Link>
</nav>
</nav>
</nav>
<div className="user-area no-login">
<img src={Avatar} alt="头像" />
<span className="username"></span>
</div>
</div>
</aside>
)
}
export default Aside;

BIN
src/images/avatar.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

BIN
src/images/icon.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -1,39 +1,320 @@
body {
@charset "UTF-8";
/* ----
# Paul API
# By: Dreamer-Paul
# Last Update: 2021.12.16
保罗的首页作品和 API 页通用模板
本代码为奇趣保罗原创并遵守 MIT 开源协议欢迎访问我的博客https://paugram.com
---- */
/* 0 - 全局
-------------------------------- */
:root{
--primary: #009688;
--secondly: #2ecc71;
}
body{
margin-left: 10em;
padding: 1em 1.5em;
}
h1, h2, h3{ font-weight: lighter }
button{
padding: 0;
font: inherit;
outline: none;
cursor: pointer;
}
.radius-full{ border-radius: 100% }
/* 1 - 页眉
-------------------------------- */
.sidebar{
top: 0;
left: 0;
bottom: 0;
z-index: 2;
color: #fff;
width: 10em;
position: fixed;
background-color: #3498db;
background-color: var(--primary);
transition: transform .3s;
}
.sidebar .header{
padding: 1em;
background: rgba(255, 255, 255, .2);
}
.sidebar h1{
font-size: 1.3em;
text-align: center;
}
.sidebar i{
width: 1em;
margin-right: .75em;
}
.sidebar hr{
margin: 0;
font-family: 'Avenir', Helvetica, Arial, -apple-system, BlinkMacSystemFont,
'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans',
'Droid Sans', 'Helvetica Neue', sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
border-color: rgba(0, 0, 0, .15);
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
.app {
min-height: 100vh;
margin: 6rem 0;
}
.logo {
width: 300px;
}
.app {
.sidebar .wrapper{
height: 100%;
display: flex;
overflow-y: auto;
flex-direction: column;
align-items: center;
}
.sidebar .wrapper::-webkit-scrollbar{ width: 0 }
.sidebar nav a{
padding: 1em;
display: block;
color: rgba(255, 255, 255, .9);
}
.sidebar nav i{
opacity: .8;
transition: transform .3s;
}
.lambda {
display: inline-block;
box-sizing: border-box;
padding: 4px 8px;
background-color: #e3e3e3;
border-radius: 4px;
margin-right: 8px;
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
.sidebar nav a:hover{ background: rgba(0, 0, 0, .2) }
.sidebar nav a:hover i{ transform: scale(1.2); }
.sidebar a.active, .sidebar .has-child > a{
position: relative;
background: rgba(0, 0, 0, .1);
}
.sidebar a.active:before ,.sidebar .has-child > a:before{
right: 0;
content: '';
position: absolute;
border: .75em solid transparent;
border-right-color: #fff;
}
.sidebar .sub-menu a{ padding: .75em 1em }
@media screen and (max-width: 600px){
body{ margin-left: 0 }
.sidebar{
transform: translateX(-10em);
}
.sidebar.active{
transform: translateX(0);
box-shadow: .25em 0 .5em rgba(0, 0, 0, .2);
}
aside .toggle{
top: 0;
left: 10em;
z-index: 3;
color: #fff;
width: 2.5em;
height: 2.5em;
cursor: pointer;
position: absolute;
text-align: center;
background-color: var(--primary);
box-shadow: .25em 0 .5em rgba(0, 0, 0, .2);
}
aside .toggle:before{
content: "\f0c9";
line-height: 2.5em;
font-family: "FontAwesome";
}
.sidebar.active .toggle{
background-color: #2ecc71;
background-color: var(--secondly);
}
}
.sidebar .menu{
flex: 1 1 auto;
}
.sidebar .user-area{
cursor: pointer;
user-select: none;
padding: .75em 1em;
transition: background .3s;
border-top: 1px solid rgba(0, 0, 0, .15);
}
.sidebar .user-area:hover{ background: rgba(0, 0, 0, .2) }
.sidebar .user-area img{
width: 2em;
border-radius: 66%;
border: 2px solid #fff;
}
.sidebar .user-area .username{
margin-left: .5em;
vertical-align: middle;
}
/* 2 - 正文
-------------------------------- */
main, footer{
margin: auto;
max-width: 45em;
}
main .header{
padding: 1em;
text-align: center;
margin-bottom: 3em;
border-bottom: 1px solid #eee;
}
main .header h1{ font-size: 2em }
main .header h2{ color: #666; font-size: 1.25em }
main .post{
margin-bottom: 3em;
}
main .post a{
text-decoration: 1px dashed underline;
text-underline-offset: 0.1em;
}
main .post h3{
margin-top: 3em;
position: relative;
}
main .post > h3:after{
content: "";
width: 1.5em;
height: 2px;
display: block;
margin-top: .25em;
background-color: #2ecc71;
background-color: var(--secondly);
}
main .post h3:first-child{ margin-top: 0 }
main .post img{ border-radius: .5em }
main .box{
height: 100%;
color: #fff;
display: block;
padding: 2em 1em;
text-align: center;
transition: background .3s;
animation: fade-in-top .3s backwards;
}
main .box.first{
background: #2ecc71;
animation-delay: .2s;
}
main .box.first:hover{ background: #27ae60 }
main .box.second{
background: #3498db;
animation-delay: .4s;
}
main .box.second:hover{ background: #2980b9 }
main .box.third{
background: #f1c40f;
animation-delay: .6s;
}
main .box.third:hover{ background: #f39c12 }
main .box.fourth{
background: #e74c3c;
animation-delay: .8s;
}
main .box.fourth:hover{ background: #c0392b }
main .box.fifth{
background: #9b59b6;
animation-delay: 1s;
}
main .box.fifth:hover{ background: #8e44ad }
main .box.sixth{
background: #1abc9c;
animation-delay: 1.2s;
}
main .box.sixth:hover{ background: #16a085 }
main .box.seventh{
background: #e67e22;
animation-delay: 1.4s;
}
main .box.seventh:hover{ background: #d35400 }
main .box.eighth{
background: #95a5a6;
animation-delay: 1.6s;
}
main .box.eighth:hover{ background: #7f8c8d }
main .box i{ margin-right: .5em }
main .box h3:before{ content: normal }
main kplayer{ margin-bottom: 1em; }
main .comments{
margin-bottom: 3em;
}
/* 3 - 页尾
------------------------------ */
footer{
color: #666;
padding: 1em 0;
text-align: center;
border-top: 1px solid #eee;
}
.server-flag{
top: 0;
right: 0;
z-index: 6;
color: #fff;
cursor: help;
position: fixed;
background: orangered;
padding: 2em 5em .5em 5em;
transform-origin: top right;
transform: rotate(45deg) translateX(50%);
}
/* 4 - 附加
------------------------------ */
.gt-meta{
margin-top: 0;
padding-top: 0;
}
.gt-copyright{ display: none }
.token.comment, .token.block-comment, .token.prolog, .token.doctype, .token.cdata{ color: slategray }
.token.punctuation{ color: #f8f8f2 }
.token.namespace { opacity: .7 }
.token.property, .token.tag, .token.function-name, .token.constant, .token.symbol, .token.deleted{ color: #f92672 }
.token.boolean, .token.number { color: #ae81ff }
.token.selector, .token.attr-name, .token.string, .token.char, .token.function, .token.builtin, .token.inserted{ color: #a6e22e }
.token.operator, .token.entity, .token.url, .token.variable{ color: #f8f8f2 }
.token.atrule, .token.attr-value, .token.class-name{ color: #e6db74 }
.token.keyword { color: #66d9ef }
.token.regex, .token.important{ color: #fd971f }
.language-css .token.string, .style .token.string { color: #28b9be }
.token.important, .token.bold { font-weight: bold }
.token.italic { font-style: italic }
.token.entity { cursor: help }
.token.important { font-weight: normal }

View File

@ -1,60 +1,28 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { useRequest } from 'ahooks';
import { getDate } from './api/date';
import fetchGithubStars from './api/star';
import { getBookByParams, getBookByQuery } from './api/book';
import './index.css';
import React from "react";
import ReactDOM from "react-dom";
import "./kico.css";
import "./index.css";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Aside from "./components/Layout/Aside";
import Home from "./pages/index";
import Wallpaper from "./pages/wallpaper";
import Bing from "./pages/bing";
function App() {
const { data: date } = useRequest(() => getDate());
const { data: repo, loading } = useRequest(() =>
fetchGithubStars('midwayjs/midway')
);
const { data: book } = useRequest(() =>
getBookByParams({ params: { id: '1' } })
);
const { data: book2 } = useRequest(() =>
getBookByQuery({ query: { id: '2' } })
);
return (
<div className="app">
<img src="/logo.png" className="logo" />
<h2>Hello Midway Hooks</h2>
<p style={{ textAlign: 'center' }}>
Edit <code>src/api/*.ts</code> and watch it change.
<br />
You can also open Devtools to see the request details.
</p>
<div>
<p>
<span className="lambda">λ GET</span>
<span className="lambda">getDate()</span>
<span>Server Date: {date}</span>
</p>
<p>
<span className="lambda">λ POST</span>
<span className="lambda">fetchStars('midwayjs/midway')</span>
<span>Github Stars: {loading ? 'Fetching...' : repo.stars}</span>
</p>
<p>
<span className="lambda">λ GET</span>
<span className="lambda">
{`getBookByParams({ params: { id: '1' } })`}
</span>
<span>Book title: {book?.title}</span>
</p>
<p>
<span className="lambda">λ GET</span>
<span className="lambda">
{`getBookByQuery({ query: { id: '2' } })`}
</span>
<span>Book title: {book2?.title}</span>
</p>
</div>
</div>
<Router>
<Aside />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/wallpaper" element={<Wallpaper />} />
<Route path="/bing" element={<Bing />} />
<Route path="*" element={<div>404</div>} />
</Routes>
</Router>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
ReactDOM.render(<App />, document.getElementById("root"));

1471
src/kico.css Normal file

File diff suppressed because it is too large Load Diff

81
src/pages/bing.tsx Normal file
View File

@ -0,0 +1,81 @@
// React
import React from "react";
// Components
function Bing() {
return (
<main>
<section className="header">
<h1></h1>
<h2></h2>
</section>
<article className="post">
<h3>使</h3>
<p> <code>https://api.paugram.com/bing/</code> 可自动跳转到对应的壁纸</p>
<p>使 API <a href="https://api.paugram.com/notice"></a></p>
<p> API </p>
<h3></h3>
<div className="ks-table text-nowrap">
<table>
<thead>
<tr>
<td></td>
<td></td>
</tr>
</thead>
<tbody>
<tr>
<td>info</td>
<td> JSON </td>
</tr>
</tbody>
</table>
</div>
<h3></h3>
<p></p>
<pre><code>https://api.paugram.com/bing</code></pre>
<p>使 JSON </p>
<pre className="language-javascript"><code>{`https://api.paugram.com/bing/?info
// 返回的是:
{
"link":"https://cn.bing.com/th?id=OHR.QatarMuseum_EN-US2624327100_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp",
"copyright":"National Museum of Qatar in Doha, Qatar (© Hasan Zaidi/Shutterstock)",
}</code></pre>
<p>使 API</p>
<pre className="language-css"><code>body{
background: url("https://api.paugram.com/bing/") center/cover no-repeat;
}`}
</code></pre>
<p>使 API</p>
<pre className="language-css"><code>{`body:before{
top: 0;
left: 0;
right: 0;
bottom: 0;
opacity: .3;
z-index: -1;
content: "";
position: fixed;
background: url(https://api.paugram.com/bing/) center/cover;
}`}
</code></pre>
<h3></h3>
<p>使 <code>img</code> </p>
<p><img src={`//${location.host}/api/bing`} /></p>
<h3></h3>
<ul>
<li><a href="https://bing.com" rel="nofollow" target="_blank">Bing</a></li>
</ul>
</article>
</main>
)
}
export default Bing;

71
src/pages/index.tsx Normal file
View File

@ -0,0 +1,71 @@
import React from "react";
import { useRequest } from 'ahooks';
import { getDate } from '../api/date';
import fetchGithubStars from '../api/star';
import { getBookByParams, getBookByQuery } from '../api/book';
import getStat from "../api/stat";
function Index() {
const { data: date } = useRequest(() => getDate());
// const { data: repo, loading } = useRequest(() =>
// fetchGithubStars('midwayjs/midway')
// );
const { data: book } = useRequest(() =>
getBookByParams({ params: { id: '1' } })
);
const { data: book2 } = useRequest(() =>
getBookByQuery({ query: { id: '2' } })
);
const { data: stat } = useRequest(() => getStat());
return (
<main>
<img src="/logo.png" className="logo" />
<h2>Hello Midway Hooks</h2>
<p style={{ textAlign: 'center' }}>
Edit <code>src/api/*.ts</code> and watch it change.
<br />
You can also open Devtools to see the request details.
</p>
<div>
<p>
<span className="lambda">λ GET</span>
<span className="lambda">getDate()</span>
<span>Server Date: {date}</span>
</p>
<p>
<span className="lambda">λ POST</span>
<span className="lambda">fetchStars('midwayjs/midway')</span>
{/* <span>Github Stars: {loading ? 'Fetching...' : repo.stars}</span> */}
</p>
<div>
{
stat?.data && Object.keys(stat.data).map((item) => (
<p key={item}>{item}: {stat.data[item]}</p>
))
}
</div>
<p>
<span className="lambda">λ GET</span>
<span className="lambda">
{`getBookByParams({ params: { id: '1' } })`}
</span>
<span>Book title: {book?.title}</span>
</p>
<p>
<span className="lambda">λ GET</span>
<span className="lambda">
{`getBookByQuery({ query: { id: '2' } })`}
</span>
<span>Book title: {book2?.title}</span>
</p>
</div>
</main>
)
}
export default Index;

173
src/pages/wallpaper.tsx Normal file
View File

@ -0,0 +1,173 @@
// React
import React from "react";
// UI
import HelpExample from "../images/help/wallpaper-pr-example.jpg";
import HelpRequire from "../images/help/wallpaper-pr-require.jpg";
// Components
function Wallpaper() {
return (
<main>
<section className="header">
<h1></h1>
<h2> Single </h2>
</section>
<article className="post">
<h3></h3>
<p> API <a href="https://github.com/Dreamer-Paul/Anime-Wallpaper" target="_blank">Anime-Wallpaper</a> PRCommit </p>
<blockquote> API使 API Git </blockquote>
<p> PR </p>
<ul>
<li>/</li>
<li></li>
<li> 50%</li>
<li></li>
<li> <code>1920 x 1080</code> <code>.jpg</code> </li>
</ul>
<p><img src={HelpExample} style={{ border: "1px solid #ddd" }} alt="提交须知" /></p>
<p><img src={HelpRequire} alt="提交须知" /></p>
<p>Commit </p>
<pre><code>Add 5 Images
</code></pre>
<h3>使</h3>
<p> <code>https://api.paugram.com/wallpaper/</code> 可自动跳转到对应的壁纸(由于运营成本限制,目前本 API 借助 图床/CDN 等平台托管图片。欢迎给予资源赞助~</p>
<p>使 API <a href="https://api.paugram.com/notice"></a></p>
<p> API </p>
<h3></h3>
<div className="ks-table text-nowrap">
<table>
<thead>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</thead>
<tbody>
<tr>
<td>source</td>
<td><code>sm</code> <code>cp</code> <code>sina</code> <code>paul</code></td>
<td> sm.ms </td>
</tr>
<tr>
<td>category</td>
<td><code>us</code> <code>jp</code> <code>cn</code></td>
<td></td>
</tr>
</tbody>
</table>
</div>
<h3></h3>
<div className="ks-table text-nowrap">
<table>
<thead>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</thead>
<tbody>
<tr>
<td>sm</td>
<td><em className="green"></em></td>
<td>sm.ms 访</td>
</tr>
<tr>
<td>gt</td>
<td><em className="green"></em></td>
<td>Gitee Pages </td>
</tr>
<tr>
<td>sina</td>
<td><em className="green"></em></td>
<td></td>
</tr>
<tr>
<td>gh</td>
<td><em className="green"></em></td>
<td> GitHub JSDelivr </td>
</tr>
</tbody>
</table>
</div>
<h3></h3>
<div className="ks-table text-nowrap">
<table>
<thead>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><em className="red"></em></td>
<td></td>
</tr>
<tr>
<td>2</td>
<td><em className="red"></em></td>
<td></td>
</tr>
<tr>
<td>3</td>
<td><em className="red"></em></td>
<td></td>
</tr>
</tbody>
</table>
</div>
<h3></h3>
<p>使 sm.ms </p>
<pre><code>https://api.paugram.com/wallpaper/?source=sm</code></pre>
<p>使</p>
<pre><code>https://api.paugram.com/wallpaper/?source=sina&category=us</code></pre>
<p>使 API</p>
<pre className="language-css"><code>{`body{
background: url("https://api.paugram.com/wallpaper/") center/cover no-repeat;
}`}
</code></pre>
<p>使 API</p>
<pre className="language-css"><code>{`body:before{
top: 0;
left: 0;
right: 0;
bottom: 0;
opacity: .3;
z-index: -1;
content: "";
position: fixed;
background: url(https://api.paugram.com/wallpaper/) center/cover;
}`}
</code></pre>
<h3></h3>
<p>使 <code>img</code> </p>
<p><img src={`//${location.host}/api/wallpaper`} style={{ border: "1px solid #ddd" }} alt="示例" /></p>
<h3></h3>
<ul>
<li><a href="https://sm.ms" rel="nofollow" target="_blank">SM.MS</a></li>
<li><a href="https://github.com/Dreamer-Paul/Anime-Wallpaper" rel="nofollow" target="_blank">GitHub</a></li>
<li><a href="https://www.jsdelivr.com" rel="nofollow" target="_blank">JSDelivr</a></li>
<li><a href="https://gitee.com" rel="nofollow" target="_blank">Gitee Pages</a></li>
</ul>
</article>
</main>
)
}
export default Wallpaper;