66 |
67 |
68 |
{
71 | setLeave(true);
72 | setTimeout((): void => {
73 | setLeave(false);
74 | }, 300);
75 | setVisible(false);
76 | }}
77 | />
78 | {children}
79 |
80 |
81 | ) : (
82 | <>>
83 | );
84 |
85 | return typeof document !== "undefined"
86 | ? ReactDom.createPortal(renderDom, document.body)
87 | : renderDom;
88 | });
89 |
--------------------------------------------------------------------------------
/pages/global.scss:
--------------------------------------------------------------------------------
1 | @import "~@douyinfe/semi-ui/dist/css/semi.min.css";
2 |
3 | html[data-theme="dark"] {
4 | --primary-color: #ffffff;
5 | --primary-background-color: rgba(14, 14, 14, 1);
6 | --footer-background-color: rgba(36, 36, 36, 1);
7 | --navbar-background-color: rgba(0, 0, 0, 0.5);
8 | --secondary-color: rgba(255, 255, 255, 0.5);
9 | --link-color: #34a8eb;
10 | --semi-page-active-color: rgb(84, 169, 255);
11 | --semi-page-active-background-color: rgba(84, 169, 255, 0.2);
12 | --semi-page-hover-background-color: rgb(23, 23, 23);
13 | --navbar-icon: url("../public/logo_dark.png");
14 | --theme-icon: url("../public/theme_dark.png");
15 | --popup-close-icon: url("../public/close.png");
16 | --popup-close-hover-background-color: #353535;
17 | --popup-content-background-color: #1f1f1f;
18 | --home-background-icon: url("../public/home_bg_dark.png");
19 | --home-background-icon-webp: url("../public/home_bg_dark.webp");
20 | }
21 |
22 | html[data-theme="light"] {
23 | --primary-color: #333333;
24 | --primary-background-color: rgba(255, 255, 255, 1);
25 | --footer-background-color: #f4f5f5;
26 | --navbar-background-color: rgba(255, 255, 255, 0.5);
27 | --secondary-color: #666666;
28 | --link-color: #0070f3;
29 | --semi-page-active-color: #333333;
30 | --semi-page-active-background-color: rgb(234, 245, 255);
31 | --semi-page-hover-background-color: rgb(244, 245, 245);
32 | --navbar-icon: url("../public/logo_light.png");
33 | --theme-icon: url("../public/theme_light.png");
34 | --popup-close-icon: url("../public/close_light.png");
35 | --popup-close-hover-background-color: #f5f5f5;
36 | --popup-content-background-color: #f4f5f5;
37 | --home-background-icon: url("../public/home_bg_light.png");
38 | --home-background-icon-webp: url("../public/home_bg_light.webp");
39 | }
40 |
41 | html,
42 | body {
43 | font-size: 16px;
44 | padding: 0;
45 | margin: 0;
46 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
47 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
48 | color: var(--primary-color);
49 | overflow: hidden;
50 | }
51 |
52 | a {
53 | color: inherit;
54 | text-decoration: none;
55 | }
56 |
57 | * {
58 | box-sizing: border-box;
59 | }
60 |
61 | .forbidScroll {
62 | height: 100vh;
63 | overflow: hidden;
64 | }
65 |
66 | #__next {
67 | height: 100vh;
68 | overflow: auto;
69 | }
70 |
--------------------------------------------------------------------------------
/components/popup/styles.module.scss:
--------------------------------------------------------------------------------
1 | @import "../../pages/media.scss";
2 |
3 | .popup {
4 | width: 100%;
5 | height: 100vh;
6 | display: flex;
7 | justify-content: center;
8 | align-items: center;
9 | position: fixed;
10 | top: 0;
11 | left: 0;
12 | z-index: 10000;
13 |
14 | .mask {
15 | width: inherit;
16 | height: inherit;
17 | position: fixed;
18 | background-color: #000;
19 | opacity: 0.5;
20 | top: 0;
21 | left: 0;
22 | z-index: 10;
23 | }
24 |
25 | .popupContent {
26 | position: relative;
27 | border-radius: 0.25rem;
28 | display: flex;
29 | flex-direction: column;
30 | align-items: center;
31 | justify-content: center;
32 | background-color: var(--popup-content-background-color);
33 | z-index: 20;
34 | min-width: 25rem;
35 | min-height: 25rem;
36 |
37 | .closeBtn {
38 | width: 2.125rem;
39 | height: 2.125rem;
40 | background-color: inherit;
41 | background-image: var(--popup-close-icon);
42 | background-position: center;
43 | background-size: 1rem 1rem;
44 | background-repeat: no-repeat;
45 | position: absolute;
46 | top: 1.1875rem;
47 | right: 1.1875rem;
48 | cursor: pointer;
49 | z-index: 100;
50 | }
51 |
52 | .closeBtn:hover {
53 | background-color: var(--popup-close-hover-background-color);
54 | }
55 | }
56 | }
57 |
58 | .enter {
59 | .mask {
60 | animation: maskFadeIn 0.2s;
61 | }
62 |
63 | .popupContent {
64 | animation: fadeIn 0.2s;
65 | }
66 | }
67 |
68 | .leave {
69 | .mask {
70 | animation: maskFadeOut 0.2s;
71 | opacity: 0;
72 | }
73 |
74 | .popupContent {
75 | animation: fadeOut 0.2s;
76 | transform: scale(0);
77 | }
78 | }
79 |
80 | @keyframes fadeIn {
81 | 0% {
82 | transform: scale(0);
83 | opacity: 0;
84 | }
85 |
86 | 100% {
87 | transform: scale(1);
88 | opacity: 1;
89 | }
90 | }
91 |
92 | @keyframes fadeOut {
93 | 0% {
94 | transform: scale(1);
95 | opacity: 1;
96 | }
97 |
98 | 100% {
99 | transform: scale(0);
100 | opacity: 0;
101 | }
102 | }
103 |
104 | @keyframes maskFadeIn {
105 | 0% {
106 | opacity: 0;
107 | }
108 |
109 | 100% {
110 | opacity: 0.5;
111 | }
112 | }
113 |
114 | @keyframes maskFadeOut {
115 | 0% {
116 | opacity: 0.5;
117 | }
118 |
119 | 100% {
120 | opacity: 0;
121 | }
122 | }
123 |
124 | @include media-mobile {
125 | .popup {
126 | .popupContent {
127 | min-width: 18.75rem;
128 | min-height: 18.75rem;
129 | .closeBtn {
130 | width: 0.6875rem;
131 | height: 0.6875rem;
132 | top: 1.3125rem;
133 | right: 0.875rem;
134 | }
135 | }
136 | }
137 | }
138 |
139 | @include media-ipad {
140 | .popup {
141 | .popupContent {
142 | .titleArea {
143 | padding: 1.5rem 1.5625rem;
144 | }
145 | }
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/components/footer/index.tsx:
--------------------------------------------------------------------------------
1 | import { FC } from "react";
2 | import Image from "next/image";
3 | import publicLogo from "@/public/public_logo.png";
4 | import styles from "./styles.module.scss";
5 | import cName from "classnames";
6 |
7 | interface ILink {
8 | label: string;
9 | link?: string;
10 | }
11 |
12 | interface ILinkList {
13 | title: string;
14 | list: ILink[];
15 | }
16 |
17 | interface IQRCode {
18 | image: string;
19 | text: string;
20 | }
21 |
22 | export interface IFooterProps {
23 | title: string;
24 | linkList: ILinkList[];
25 | qrCode: IQRCode;
26 | copyRight: string;
27 | siteNumber: string; // 站点备案号
28 | publicNumber: string; // 公安备案号
29 | }
30 |
31 | export const Footer: FC
= ({
32 | title,
33 | linkList,
34 | qrCode,
35 | copyRight,
36 | siteNumber,
37 | publicNumber,
38 | }) => {
39 | return (
40 |
41 |
42 |
{title}
43 |
44 | {linkList?.map((item, index) => {
45 | return (
46 |
47 |
{item.title}
48 |
49 | {item.list?.map((_item, _index) => {
50 | return (
51 |
{
57 | _item.link &&
58 | window.open(
59 | _item.link,
60 | "blank",
61 | "noopener=yes,noreferrer=yes"
62 | );
63 | }}
64 | key={`link${_index}`}
65 | >
66 | {_item.label}
67 |
68 | );
69 | })}
70 |
71 |
72 | );
73 | })}
74 |
75 |
76 |
77 |
78 |
79 |
85 |
86 |
{qrCode?.text}
87 |
88 |
89 |
{copyRight}
90 |
{siteNumber}
91 |
92 |
93 |
99 |
100 |
{publicNumber}
101 |
102 |
103 |
104 |
105 | );
106 | };
107 |
--------------------------------------------------------------------------------
/components/footer/styles.module.scss:
--------------------------------------------------------------------------------
1 | @import "../../pages/media.scss";
2 |
3 | .footer {
4 | font-size: 1rem;
5 | padding: 4.375rem 9.0625rem;
6 | background-color: var(--footer-background-color);
7 | .topArea {
8 | display: flex;
9 | justify-content: space-between;
10 | flex-wrap: wrap;
11 |
12 | .footerTitle {
13 | font-weight: 500;
14 | font-size: 2.25rem;
15 | line-height: 2.25rem;
16 | color: var(--primary-color);
17 | margin: 0;
18 | }
19 |
20 | .linkListArea {
21 | display: flex;
22 | .linkArea {
23 | display: flex;
24 | flex-direction: column;
25 | margin-left: 10rem;
26 | .title {
27 | font-weight: 500;
28 | font-size: 0.875rem;
29 | line-height: 1.25rem;
30 | color: var(--primary-color);
31 | margin-bottom: 2.5rem;
32 | word-break: keep-all;
33 | }
34 |
35 | .links {
36 | display: flex;
37 | flex-direction: column;
38 | font-weight: 400;
39 | font-size: 0.875rem;
40 | line-height: 1.25rem;
41 | word-break: keep-all;
42 |
43 | .link {
44 | color: var(--primary-color);
45 | cursor: pointer;
46 | margin-bottom: 1.5rem;
47 | }
48 |
49 | .disabled {
50 | color: var(--secondary-color);
51 | cursor: not-allowed;
52 | margin-bottom: 1.5rem;
53 | }
54 | }
55 | }
56 |
57 | .linkArea:first-of-type {
58 | margin-left: 0;
59 | }
60 | }
61 | }
62 |
63 | .bottomArea {
64 | display: flex;
65 | justify-content: space-between;
66 | .codeArea {
67 | display: flex;
68 | flex-direction: column;
69 | .text {
70 | color: var(--secondary-color);
71 | }
72 | }
73 | .numArea {
74 | color: var(--secondary-color);
75 | display: flex;
76 | flex-direction: column;
77 | align-items: flex-end;
78 | font-weight: 400;
79 | font-size: 0.875rem;
80 | line-height: 1.25rem;
81 |
82 | span {
83 | margin-bottom: 0.75rem;
84 | }
85 |
86 | .publicLogo {
87 | display: flex;
88 |
89 | .logo {
90 | margin-right: 0.25rem;
91 | }
92 | }
93 | }
94 | }
95 | }
96 |
97 | @media screen and (min-width: 48.6875rem) and (max-width: 54.125rem) {
98 | .footer {
99 | .topArea {
100 | .footerTitle {
101 | margin-bottom: 1.25rem;
102 | }
103 | }
104 | }
105 | }
106 |
107 | @media screen and (max-width: 48.6875rem) {
108 | .footer {
109 | .topArea {
110 | display: flex;
111 | flex-direction: column;
112 | align-items: center;
113 | .footerTitle {
114 | margin-bottom: 2.5rem;
115 | }
116 | .linkListArea {
117 | display: flex;
118 | flex-direction: column;
119 | text-align: center;
120 | .linkArea {
121 | margin-left: 0;
122 | }
123 | }
124 | }
125 |
126 | .bottomArea {
127 | display: flex;
128 | flex-direction: column;
129 | align-items: center;
130 |
131 | .codeArea {
132 | display: flex;
133 | flex-direction: column;
134 | align-items: center;
135 |
136 | .text {
137 | text-align: center;
138 | margin: 1.25rem 0;
139 | }
140 | }
141 |
142 | .numArea {
143 | align-items: center;
144 | text-align: center;
145 | }
146 | }
147 | }
148 | }
149 |
150 | // @include media-ipad {
151 | // }
152 |
--------------------------------------------------------------------------------
/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { useContext, useEffect, useRef, useState } from 'react';
2 | import type { GetServerSideProps, GetStaticProps, NextPage } from 'next';
3 | import styles from './index.module.scss';
4 | import cName from 'classnames';
5 | import { ThemeContext } from '@/stores/theme';
6 | import { Pagination } from '@douyinfe/semi-ui';
7 | import axios from 'axios';
8 | import { LOCALDOMAIN } from '@/utils';
9 | import { IArticleIntro } from './api/articleIntro';
10 | import App from 'next/app';
11 | import { IComponentProps } from './_app';
12 | import Link from 'next/link';
13 | import { useRouter } from 'next/router';
14 |
15 | interface IProps {
16 | title: string;
17 | description: string;
18 | articles: {
19 | list: {
20 | label: string;
21 | info: string;
22 | link: string;
23 | }[];
24 | total: number;
25 | };
26 | }
27 |
28 | const Home: NextPage = ({ title, description, articles, isSupportWebp }) => {
29 | const [content, setContent] = useState(articles);
30 | const mainRef = useRef(null);
31 | const { theme } = useContext(ThemeContext);
32 | const router = useRouter();
33 |
34 | useEffect(() => {
35 | mainRef.current?.classList.remove(styles.withAnimation);
36 | window.requestAnimationFrame(() => {
37 | mainRef.current?.classList.add(styles.withAnimation);
38 | });
39 | }, [theme]);
40 |
41 | return (
42 |
43 |
44 |
50 | {title}
51 | {description}
52 |
53 |
54 | {content?.list?.map((item, index) => (
55 |
56 |
57 |
{item.label} →
58 |
{item.info}
59 |
60 |
61 | //
{
65 | // router.push(item.link);
66 | // }}
67 | // >
68 | //
{item.label} →
69 | //
{item.info}
70 | //
71 | ))}
72 |
73 |
{
77 | axios
78 | .post(`${LOCALDOMAIN}/api/articleIntro`, {
79 | pageNo,
80 | pageSize: 6,
81 | })
82 | .then(({ data }) => {
83 | setContent({
84 | list: data.list.map((item: IArticleIntro) => ({
85 | label: item.label,
86 | info: item.info,
87 | link: `${LOCALDOMAIN}/article/${item.articleId}`,
88 | })),
89 | total: data.total,
90 | });
91 | });
92 | }}
93 | />
94 |
95 |
96 |
97 |
98 | );
99 | };
100 |
101 | Home.getInitialProps = async (context): Promise => {
102 | const { data: homeData } = await axios.get(`${LOCALDOMAIN}/api/home`);
103 | const { data: articleData } = await axios.post(`${LOCALDOMAIN}/api/articleIntro`, {
104 | pageNo: 1,
105 | pageSize: 6,
106 | });
107 |
108 | return {
109 | title: homeData.title,
110 | description: homeData.description,
111 | articles: {
112 | list: articleData.list.map((item: IArticleIntro) => ({
113 | label: item.label,
114 | info: item.info,
115 | link: `${LOCALDOMAIN}/article/${item.articleId}`,
116 | })),
117 | total: articleData.total,
118 | },
119 | };
120 | };
121 |
122 | // export const getServerSideProps: GetServerSideProps = async context => {
123 | // const { data: homeData } = await axios.get(`${LOCALDOMAIN}/api/home`);
124 | // const { data: articleData } = await axios.post(`${LOCALDOMAIN}/api/articleIntro`, {
125 | // pageNo: 1,
126 | // pageSize: 6,
127 | // });
128 |
129 | // return {
130 | // props: {
131 | // title: homeData.title,
132 | // description: homeData.description,
133 | // articles: {
134 | // list: articleData.list.map((item: IArticleIntro) => ({
135 | // label: item.label,
136 | // info: item.info,
137 | // link: `${LOCALDOMAIN}/article/${item.articleId}`,
138 | // })),
139 | // total: articleData.total,
140 | // },
141 | // },
142 | // };
143 | // };
144 |
145 | // export const getStaticProps: GetStaticProps = async context => {
146 | // const { data: homeData } = await axios.get(`${LOCALDOMAIN}/api/home`);
147 | // const { data: articleData } = await axios.post(`${LOCALDOMAIN}/api/articleIntro`, {
148 | // pageNo: 1,
149 | // pageSize: 6,
150 | // });
151 |
152 | // return {
153 | // props: {
154 | // title: homeData.title,
155 | // description: homeData.description,
156 | // articles: {
157 | // list: articleData.list.map((item: IArticleIntro) => ({
158 | // label: item.label,
159 | // info: item.info,
160 | // link: `${LOCALDOMAIN}/article/${item.articleId}`,
161 | // })),
162 | // total: articleData.total,
163 | // },
164 | // },
165 | // };
166 | // };
167 |
168 | export default Home;
169 |
--------------------------------------------------------------------------------
/pages/index.module.scss:
--------------------------------------------------------------------------------
1 | @import "./media.scss";
2 |
3 | @mixin initStatus {
4 | transform: translate3d(0, 2.5rem, 0);
5 | opacity: 0;
6 | }
7 |
8 | @mixin finalStatus {
9 | -webkit-transform: none;
10 | transform: none;
11 | opacity: 1;
12 | }
13 |
14 | .container {
15 | padding: 0 2rem;
16 | color: var(--primary-color);
17 |
18 | .main {
19 | min-height: 100vh;
20 | padding: 4rem 0;
21 | flex: 1;
22 | display: flex;
23 | flex-direction: column;
24 | justify-content: center;
25 | align-items: center;
26 | .header {
27 | background-image: var(--home-background-icon);
28 | background-size: 18.75rem 18.75rem;
29 | background-repeat: no-repeat;
30 | width: 18.75rem;
31 | height: 18.75rem;
32 | }
33 |
34 | .headerWebp {
35 | background-image: var(--home-background-icon-webp);
36 | }
37 |
38 | .top {
39 | display: flex;
40 | }
41 |
42 | .title a {
43 | color: var(--link-color);
44 | text-decoration: none;
45 | }
46 |
47 | .title a:hover,
48 | .title a:focus,
49 | .title a:active {
50 | text-decoration: underline;
51 | }
52 |
53 | .title {
54 | margin: 0;
55 | line-height: 1.15;
56 | font-size: 4rem;
57 | }
58 |
59 | .title,
60 | .description {
61 | text-align: center;
62 | }
63 |
64 | .description {
65 | margin: 4rem 0;
66 | line-height: 1.5;
67 | font-size: 1.5rem;
68 | }
69 |
70 | .grid {
71 | display: flex;
72 | align-items: flex-start;
73 | justify-content: flex-start;
74 | flex-wrap: wrap;
75 | max-width: 62.5rem;
76 | transition: 2s;
77 | min-height: 36.25rem;
78 | .card {
79 | margin: 1rem;
80 | padding: 1.5rem;
81 | text-align: left;
82 | color: inherit;
83 | text-decoration: none;
84 | border: 0.0625rem solid var(--footer-background-color);
85 | border-radius: 0.625rem;
86 | transition: color 0.15s ease, border-color 0.15s ease;
87 | max-width: 18.75rem;
88 | cursor: pointer;
89 | width: 18.75rem;
90 | height: 13.875rem;
91 | }
92 |
93 | .card:hover,
94 | .card:focus,
95 | .card:active {
96 | color: var(--link-color);
97 | border-color: var(--link-color);
98 | }
99 |
100 | .card h2 {
101 | margin: 0 0 1rem 0;
102 | font-size: 1.5rem;
103 | }
104 |
105 | .card p {
106 | margin: 0;
107 | font-size: 1.25rem;
108 | line-height: 1.5;
109 | }
110 | }
111 |
112 | .paginationArea {
113 | width: 62.5rem;
114 | display: flex;
115 | justify-content: flex-end;
116 | padding: 20px 0;
117 |
118 | :global {
119 | .semi-page-item {
120 | color: var(--primary-color);
121 | opacity: 0.7;
122 | }
123 |
124 | .semi-page-item:hover {
125 | background-color: var(--semi-page-hover-background-color);
126 | }
127 |
128 | .semi-page-item-active {
129 | color: var(--semi-page-active-color);
130 | background-color: var(--semi-page-active-background-color);
131 | }
132 |
133 | .semi-page-item-active:hover {
134 | color: var(--semi-page-active-color);
135 | background-color: var(--semi-page-active-background-color);
136 | }
137 | }
138 | }
139 | }
140 |
141 | .withAnimation {
142 | .title {
143 | animation: fadeInDown1 1s;
144 | }
145 |
146 | .description {
147 | animation: fadeInDown2 1s;
148 | }
149 |
150 | .card:nth-of-type(1) {
151 | animation: fadeInDown3 1s;
152 | }
153 |
154 | .card:nth-of-type(2) {
155 | animation: fadeInDown4 1s;
156 | }
157 |
158 | .card:nth-of-type(3) {
159 | animation: fadeInDown5 1s;
160 | }
161 |
162 | .card:nth-of-type(4) {
163 | animation: fadeInDown6 1s;
164 | }
165 |
166 | .card:nth-of-type(5) {
167 | animation: fadeInDown7 1s;
168 | }
169 |
170 | .card:nth-of-type(6) {
171 | animation: fadeInDown8 1s;
172 | }
173 | }
174 |
175 | @keyframes fadeInDown1 {
176 | 0% {
177 | @include initStatus;
178 | }
179 |
180 | 11% {
181 | @include initStatus;
182 | }
183 |
184 | 100% {
185 | @include finalStatus;
186 | }
187 | }
188 |
189 | @keyframes fadeInDown2 {
190 | 0% {
191 | @include initStatus;
192 | }
193 |
194 | 22% {
195 | @include initStatus;
196 | }
197 |
198 | 100% {
199 | @include finalStatus;
200 | }
201 | }
202 |
203 | @keyframes fadeInDown3 {
204 | 0% {
205 | @include initStatus;
206 | }
207 |
208 | 33% {
209 | @include initStatus;
210 | }
211 |
212 | 100% {
213 | @include finalStatus;
214 | }
215 | }
216 |
217 | @keyframes fadeInDown4 {
218 | 0% {
219 | @include initStatus;
220 | }
221 |
222 | 44% {
223 | @include initStatus;
224 | }
225 |
226 | 100% {
227 | @include finalStatus;
228 | }
229 | }
230 |
231 | @keyframes fadeInDown5 {
232 | 0% {
233 | @include initStatus;
234 | }
235 |
236 | 55% {
237 | @include initStatus;
238 | }
239 |
240 | 100% {
241 | @include finalStatus;
242 | }
243 | }
244 |
245 | @keyframes fadeInDown6 {
246 | 0% {
247 | @include initStatus;
248 | }
249 |
250 | 66% {
251 | @include initStatus;
252 | }
253 |
254 | 100% {
255 | @include finalStatus;
256 | }
257 | }
258 |
259 | @keyframes fadeInDown7 {
260 | 0% {
261 | @include initStatus;
262 | }
263 |
264 | 77% {
265 | @include initStatus;
266 | }
267 |
268 | 100% {
269 | @include finalStatus;
270 | }
271 | }
272 |
273 | @keyframes fadeInDown8 {
274 | 0% {
275 | @include initStatus;
276 | }
277 |
278 | 88% {
279 | @include initStatus;
280 | }
281 |
282 | 100% {
283 | @include finalStatus;
284 | }
285 | }
286 | }
287 |
288 | @include media-ipad {
289 | .container {
290 | .main {
291 | .grid {
292 | width: 95%;
293 | margin: auto;
294 | justify-content: center;
295 | }
296 | }
297 | }
298 | }
299 |
300 | @include media-mobile {
301 | .container {
302 | .main {
303 | .title {
304 | font-size: 1.75rem;
305 | line-height: 2.4375rem;
306 | }
307 | .description {
308 | font-size: 0.875rem;
309 | line-height: 1.5rem;
310 | margin: 2rem 0;
311 | }
312 | .grid {
313 | width: 95%;
314 | margin: auto;
315 | justify-content: center;
316 | .card {
317 | height: 10rem;
318 | h2 {
319 | font-size: 1.125rem;
320 | line-height: 1.5625rem;
321 | }
322 | p {
323 | font-size: 0.75rem;
324 | line-height: 1.625rem;
325 | }
326 | }
327 | }
328 | }
329 | }
330 | }
331 |
--------------------------------------------------------------------------------