59 |
60 |
{
63 | setLeave(true);
64 | setTimeout((): void => {
65 | setLeave(false);
66 | }, 300);
67 | setVisible(false);
68 | }}
69 | />
70 | {children}
71 |
72 |
73 | ) : (
74 | <>>
75 | );
76 |
77 | return typeof document !== "undefined"
78 | ? ReactDom.createPortal(renderDom, document.body)
79 | : renderDom;
80 | });
81 |
--------------------------------------------------------------------------------
/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 |
130 | .closeBtn {
131 | width: 0.6875rem;
132 | height: 0.6875rem;
133 | top: 1.3125rem;
134 | right: 0.875rem;
135 | }
136 | }
137 | }
138 | }
139 |
140 | @include media-ipad {
141 | .popup {
142 | .popupContent {
143 | .titleArea {
144 | padding: 1.5rem 1.5625rem;
145 | }
146 | }
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/constants/enum.ts:
--------------------------------------------------------------------------------
1 | export enum Themes {
2 | light = "light",
3 | dark = "dark",
4 | }
5 |
6 | export enum Environment {
7 | pc = "pc",
8 | ipad = "ipad",
9 | mobile = "mobile",
10 | none = "none",
11 | }
12 |
13 | export enum Language {
14 | ch = "ch",
15 | en = "en",
16 | }
17 |
--------------------------------------------------------------------------------
/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/basic-features/typescript for more information.
6 |
--------------------------------------------------------------------------------
/next-i18next.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | i18n: {
3 | defaultLocale: 'zh-CN',
4 | locales: ['en', 'zh-CN'],
5 | },
6 | localePath: 'public/locales',
7 | defaultNS: [],
8 | debug: false,
9 | ns: ['header', 'main', 'footer']
10 | }
11 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const semi = require("@douyinfe/semi-next").default({});
4 | module.exports = semi({
5 | reactStrictMode: true,
6 | swcMinify: true,
7 | webpack: (config) => {
8 | config.resolve.alias = {
9 | ...config.resolve.alias,
10 | "@": path.resolve(__dirname),
11 | };
12 | return config;
13 | },
14 | images: {
15 | domains: ["127.0.0.1"],
16 | unoptimized: true
17 | },
18 | });
19 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "iotsharp-home",
3 | "version": "3.0.",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "debugger": "cross-env NODE_OPTIONS='--inspect' next dev",
8 | "build": "next build && next export",
9 | "start": "next start",
10 | "lint": "next lint"
11 | },
12 | "dependencies": {
13 | "@douyinfe/semi-next": "^2.17.1",
14 | "@douyinfe/semi-ui": "^2.17.1",
15 | "ahooks": "^3.7.4",
16 | "axios": "^0.27.2",
17 | "classnames": "^2.3.1",
18 | "lodash": "^4.17.21",
19 | "next": "13.1.1",
20 | "next-connect": "^0.13.0",
21 | "react": "^18.2.0",
22 | "react-dom": "^18.2.0",
23 | "react-i18next": "^12.1.1",
24 | "showdown": "^2.1.0"
25 | },
26 | "devDependencies": {
27 | "@commitlint/cli": "^17.0.3",
28 | "@commitlint/config-conventional": "^17.0.3",
29 | "@types/lodash": "^4.14.182",
30 | "@types/node": "18.6.1",
31 | "@types/react": "18.0.15",
32 | "@types/react-dom": "18.0.6",
33 | "cross-env": "^7.0.3",
34 | "eslint": "8.20.0",
35 | "eslint-config-next": "12.2.3",
36 | "husky": "^8.0.1",
37 | "sass": "^1.54.0",
38 | "typescript": "4.7.4",
39 | "typescript-plugin-css-modules": "^3.4.0"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/pages/_app.tsx:
--------------------------------------------------------------------------------
1 | import type {AppContext, AppProps} from 'next/app';
2 | import App from 'next/app';
3 | import React from 'react';
4 | import type {ILayoutProps} from '@/components/layout';
5 | import Layout from '@/components/layout';
6 | import Head from 'next/head';
7 | import {getIsMobile, getIsSupportWebp} from '@/utils';
8 | import {ThemeContextProvider} from '@/stores/theme';
9 | import {UserAgentProvider} from '@/stores/userAgent';
10 | import {LanguageContextProvider} from '@/stores/language';
11 | import './global.scss';
12 |
13 | export interface IComponentProps {
14 | isMobile?: boolean;
15 | isSupportWebp?: boolean;
16 | }
17 |
18 | const MyApp = (data: AppProps & ILayoutProps & IComponentProps): JSX.Element => {
19 | const {Component, pageProps, navbarData, footerData, isMobile, isSupportWebp} = data;
20 | return (
21 |
22 |
23 |
IoTSharp官网
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | );
40 | };
41 |
42 | MyApp.getInitialProps = async (context: AppContext) => {
43 | const pageProps = await App.getInitialProps(context);
44 |
45 | return {
46 | ...pageProps,
47 | isMobile: getIsMobile(context),
48 | isSupportWebp: getIsSupportWebp(context),
49 | };
50 | };
51 |
52 | export default MyApp;
53 |
--------------------------------------------------------------------------------
/pages/_document.tsx:
--------------------------------------------------------------------------------
1 | import {Head, Html, Main, NextScript} from 'next/document';
2 | import Script from 'next/script';
3 | import React from 'react';
4 |
5 | export default function Document() {
6 | return (
7 |
8 |
12 |
17 |
18 |
19 | );
20 | }
21 |
--------------------------------------------------------------------------------
/pages/api/layout.ts:
--------------------------------------------------------------------------------
1 | import type {NextApiRequest, NextApiResponse} from 'next';
2 | import {ILayoutProps} from '../../components/layout';
3 | import {isEmpty} from 'lodash';
4 |
5 | const getLayoutData = (req: NextApiRequest, res: NextApiResponse