From 2b1e3fc76e3b6d1c88ef20194db42de16291155b Mon Sep 17 00:00:00 2001 From: awesomeYG <993631441@qq.com> Date: Fri, 22 Dec 2023 22:57:50 +0800 Subject: [PATCH] feat: home page --- next.config.js | 17 +- package-lock.json | 771 ++++++++++++++++++- package.json | 4 +- public/cnzz.js | 4 +- src/asset/tag/dev.svg | 25 + src/asset/tag/dev_check.svg | 25 + src/asset/tag/encode.svg | 24 + src/asset/tag/encode_check.svg | 24 + src/asset/tag/encryption.svg | 22 + src/asset/tag/encryption_check.svg | 22 + src/asset/tag/hot.svg | 23 + src/asset/tag/hot_check.svg | 23 + src/asset/tag/hover_red_like.svg | 12 + src/asset/tag/image.svg | 23 + src/asset/tag/image_check.svg | 23 + src/asset/tag/json.svg | 24 + src/asset/tag/json_check.svg | 24 + src/asset/tag/like.svg | 24 + src/asset/tag/like_check.svg | 24 + src/asset/tag/no_like.png | Bin 0 -> 27577 bytes src/asset/tag/other.svg | 23 + src/asset/tag/other_check.svg | 23 + src/asset/tag/red_like.png | Bin 0 -> 1282 bytes src/asset/tag/red_like_check.png | Bin 0 -> 1336 bytes src/asset/tag/text.svg | 26 + src/asset/tag/text_check.svg | 26 + src/components/Button/index.tsx | 2 +- src/components/LikeIcon/index.tsx | 50 ++ src/components/MenuView/components.tsx | 137 ---- src/components/MenuView/index.tsx | 264 +------ src/components/ToolCard/index.tsx | 34 + src/components/Tools/home.tsx | 118 --- src/components/Tools/index.tsx | 3 +- src/constant/color.ts | 10 +- src/hooks/useAnchor.tsx | 22 + src/hooks/useLikeList.tsx | 24 + src/icon/Copy.tsx | 2 +- src/layouts/Header/components.tsx | 20 + src/layouts/Header/index.tsx | 151 ++++ src/layouts/LoginLayout/copyright.tsx | 53 -- src/layouts/LoginLayout/index.tsx | 36 - src/layouts/Logo/index.tsx | 45 -- src/layouts/Navbar/components.tsx | 43 -- src/layouts/Navbar/index.tsx | 33 - src/layouts/Navbar/items/menu/index.tsx | 87 --- src/layouts/Navbar/items/menu/item.tsx | 96 --- src/layouts/Navbar/items/menu/mobileView.tsx | 166 ---- src/layouts/Navbar/items/menu/panel.tsx | 152 ---- src/layouts/SideBar/components.tsx | 20 + src/layouts/SideBar/index.tsx | 47 ++ src/pages/_app.tsx | 53 +- src/pages/aes.tsx | 2 +- src/pages/ascii.tsx | 2 +- src/pages/base64.tsx | 4 +- src/pages/case_convert.tsx | 2 +- src/pages/hash.tsx | 2 +- src/pages/img2base64.tsx | 2 +- src/pages/index.tsx | 100 ++- src/pages/jsontocsv.tsx | 2 +- src/pages/radix_convert.tsx | 2 +- src/pages/random.tsx | 4 +- src/pages/uncolor.tsx | 2 +- src/pages/unix.tsx | 4 +- src/pages/urlencoder.tsx | 2 +- src/pages/word_count.tsx | 2 +- src/styles/colors.ts | 6 +- src/styles/global.css | 10 +- src/styles/static/slick-theme.css | 2 +- src/utils/tags.ts | 74 ++ src/utils/tools.ts | 47 +- 70 files changed, 1894 insertions(+), 1281 deletions(-) create mode 100644 src/asset/tag/dev.svg create mode 100644 src/asset/tag/dev_check.svg create mode 100644 src/asset/tag/encode.svg create mode 100644 src/asset/tag/encode_check.svg create mode 100644 src/asset/tag/encryption.svg create mode 100644 src/asset/tag/encryption_check.svg create mode 100644 src/asset/tag/hot.svg create mode 100644 src/asset/tag/hot_check.svg create mode 100644 src/asset/tag/hover_red_like.svg create mode 100644 src/asset/tag/image.svg create mode 100644 src/asset/tag/image_check.svg create mode 100644 src/asset/tag/json.svg create mode 100644 src/asset/tag/json_check.svg create mode 100644 src/asset/tag/like.svg create mode 100644 src/asset/tag/like_check.svg create mode 100644 src/asset/tag/no_like.png create mode 100644 src/asset/tag/other.svg create mode 100644 src/asset/tag/other_check.svg create mode 100644 src/asset/tag/red_like.png create mode 100644 src/asset/tag/red_like_check.png create mode 100644 src/asset/tag/text.svg create mode 100644 src/asset/tag/text_check.svg create mode 100644 src/components/LikeIcon/index.tsx delete mode 100644 src/components/MenuView/components.tsx create mode 100644 src/components/ToolCard/index.tsx delete mode 100644 src/components/Tools/home.tsx create mode 100644 src/hooks/useAnchor.tsx create mode 100644 src/hooks/useLikeList.tsx create mode 100644 src/layouts/Header/components.tsx create mode 100644 src/layouts/Header/index.tsx delete mode 100644 src/layouts/LoginLayout/copyright.tsx delete mode 100644 src/layouts/LoginLayout/index.tsx delete mode 100644 src/layouts/Logo/index.tsx delete mode 100644 src/layouts/Navbar/components.tsx delete mode 100644 src/layouts/Navbar/index.tsx delete mode 100644 src/layouts/Navbar/items/menu/index.tsx delete mode 100644 src/layouts/Navbar/items/menu/item.tsx delete mode 100644 src/layouts/Navbar/items/menu/mobileView.tsx delete mode 100644 src/layouts/Navbar/items/menu/panel.tsx create mode 100644 src/layouts/SideBar/components.tsx create mode 100644 src/layouts/SideBar/index.tsx create mode 100644 src/utils/tags.ts diff --git a/next.config.js b/next.config.js index cb41d95..ec07ce3 100644 --- a/next.config.js +++ b/next.config.js @@ -1,8 +1,9 @@ /** @type {import('next').NextConfig} */ const withPlugins = require('next-compose-plugins'); const withTM = require('next-transpile-modules')(['react-syntax-highlighter']); +const withFonts = require('next-fonts'); -const nextConfig = withPlugins([withTM], { +const nextConfig = withPlugins([withFonts, withTM], { reactStrictMode: false, output: 'export', images: { @@ -11,14 +12,14 @@ const nextConfig = withPlugins([withTM], { basePath: '/tools', async redirects() { return [ - { - source: '/', - destination: '/tools', - basePath: false, - permanent: true - } + { + source: '/', + destination: '/tools', + basePath: false, + permanent: true + } ] -} + } }); module.exports = nextConfig; diff --git a/package-lock.json b/package-lock.json index bf74635..d2b227d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "@mui/material": "^5.13.0", "@tanstack/react-query": "^4.29.7", "ace-builds": "^1.32.2", + "ahooks": "^3.7.8", "axios": "^1.4.0", "big-integer": "^1.6.52", "crypto-js": "^4.2.0", @@ -62,7 +63,8 @@ "eslint-plugin-next": "^0.0.0", "eslint-plugin-prettier": "^5.1.0", "husky": "^8.0.0", - "lint-staged": "^15.2.0" + "lint-staged": "^15.2.0", + "next-fonts": "^1.5.1" }, "engines": { "node": ">=16.0.0", @@ -1045,6 +1047,70 @@ "resolved": "https://registry.npmmirror.com/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==" }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "peer": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmmirror.com/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dev": true, + "peer": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true, + "peer": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "dev": true, + "peer": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@mui/base": { "version": "5.0.0-beta.28", "resolved": "https://registry.npmmirror.com/@mui/base/-/base-5.0.0-beta.28.tgz", @@ -1581,6 +1647,35 @@ "@types/ms": "*" } }, + "node_modules/@types/eslint": { + "version": "8.56.0", + "resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-FlsN0p4FhuYRjIxpbdXovvHQhtlG05O1GG/RNWvdAxTboR438IOTwmrY/vLA+Xfgg06BTkP045M3vpFwTMv1dg==", + "dev": true, + "peer": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmmirror.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "peer": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true, + "peer": true + }, "node_modules/@types/extend": { "version": "3.0.4", "resolved": "https://registry.npmmirror.com/@types/extend/-/extend-3.0.4.tgz", @@ -1594,6 +1689,17 @@ "@types/unist": "^2" } }, + "node_modules/@types/js-cookie": { + "version": "2.2.7", + "resolved": "https://registry.npmmirror.com/@types/js-cookie/-/js-cookie-2.2.7.tgz", + "integrity": "sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmmirror.com/@types/json5/-/json5-0.0.29.tgz", @@ -1778,6 +1884,181 @@ "node": "^16.0.0 || >=18.0.0" } }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.6", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.6", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.6", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "peer": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "peer": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.6", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.6", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.6", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.6", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "peer": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmmirror.com/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "peer": true + }, "node_modules/ace-builds": { "version": "1.32.2", "resolved": "https://registry.npmmirror.com/ace-builds/-/ace-builds-1.32.2.tgz", @@ -1794,6 +2075,16 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "dev": true, + "peer": true, + "peerDependencies": { + "acorn": "^8" + } + }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -1810,6 +2101,34 @@ "node": ">=0.8" } }, + "node_modules/ahooks": { + "version": "3.7.8", + "resolved": "https://registry.npmmirror.com/ahooks/-/ahooks-3.7.8.tgz", + "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" + }, + "engines": { + "node": ">=8.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/ahooks-v3-count": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/ahooks-v3-count/-/ahooks-v3-count-1.0.0.tgz", + "integrity": "sha512-V7uUvAwnimu6eh/PED4mCDjE7tokeZQLKlxg9lCTMPhN+NjsSbtdacByVlR1oluXQzD3MOw55wylDmQo4+S9ZQ==" + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz", @@ -1821,6 +2140,15 @@ "uri-js": "^4.2.2" } }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, "node_modules/ansi-escapes": { "version": "6.2.0", "resolved": "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-6.2.0.tgz", @@ -2077,6 +2405,15 @@ "node": ">=0.6" } }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmmirror.com/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/bplist-parser": { "version": "0.2.0", "resolved": "https://registry.npmmirror.com/bplist-parser/-/bplist-parser-0.2.0.tgz", @@ -2109,6 +2446,25 @@ "node": ">=8" } }, + "node_modules/browserslist": { + "version": "4.22.2", + "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "dev": true, + "peer": true, + "dependencies": { + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, "node_modules/buffer-from": { "version": "0.1.2", "resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-0.1.2.tgz", @@ -2227,6 +2583,16 @@ "resolved": "https://registry.npmmirror.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==" }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.0" + } + }, "node_modules/classnames": { "version": "2.3.2", "resolved": "https://registry.npmmirror.com/classnames/-/classnames-2.3.2.tgz", @@ -2520,6 +2886,11 @@ "node": ">=8" } }, + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz", @@ -2779,11 +3150,27 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/electron-to-chromium": { + "version": "1.4.616", + "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.616.tgz", + "integrity": "sha512-1n7zWYh8eS0L9Uy+GskE0lkBUNK83cXTVJI0pU3mGprFsbfSdAc15VTFbo+A+Bq4pwstmL30AVcEU3Fo463lNg==", + "dev": true, + "peer": true + }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/enhanced-resolve": { "version": "5.15.0", "resolved": "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", @@ -2874,6 +3261,13 @@ "safe-array-concat": "^1.0.1" } }, + "node_modules/es-module-lexer": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-1.4.1.tgz", + "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", + "dev": true, + "peer": true + }, "node_modules/es-set-tostringtag": { "version": "2.0.2", "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", @@ -3346,6 +3740,16 @@ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", "dev": true }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/execa": { "version": "7.2.0", "resolved": "https://registry.npmmirror.com/execa/-/execa-7.2.0.tgz", @@ -3445,6 +3849,22 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmmirror.com/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz", @@ -4160,6 +4580,11 @@ "node": ">= 0.4" } }, + "node_modules/intersection-observer": { + "version": "0.12.2", + "resolved": "https://registry.npmmirror.com/intersection-observer/-/intersection-observer-0.12.2.tgz", + "integrity": "sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==" + }, "node_modules/is-alphabetical": { "version": "1.0.4", "resolved": "https://registry.npmmirror.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz", @@ -4543,6 +4968,34 @@ "set-function-name": "^2.0.1" } }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmmirror.com/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/jiti": { "version": "1.21.0", "resolved": "https://registry.npmmirror.com/jiti/-/jiti-1.21.0.tgz", @@ -4558,6 +5011,11 @@ "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", "peer": true }, + "node_modules/js-cookie": { + "version": "2.2.1", + "resolved": "https://registry.npmmirror.com/js-cookie/-/js-cookie-2.2.1.tgz", + "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==" + }, "node_modules/js-sdsl": { "version": "4.4.2", "resolved": "https://registry.npmmirror.com/js-sdsl/-/js-sdsl-4.4.2.tgz", @@ -4846,6 +5304,42 @@ "node": ">=18.0.0" } }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/loader-utils/node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz", @@ -4860,8 +5354,7 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "node_modules/lodash.camelcase": { "version": "4.3.0", @@ -5672,6 +6165,13 @@ "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "peer": true + }, "node_modules/next": { "version": "14.0.4", "resolved": "https://registry.npmmirror.com/next/-/next-14.0.4.tgz", @@ -5723,6 +6223,19 @@ "resolved": "https://registry.npmmirror.com/next-compose-plugins/-/next-compose-plugins-2.2.1.tgz", "integrity": "sha512-OjJ+fV15FXO2uQXQagLD4C0abYErBjyjE0I0FHpOEIB8upw0hg1ldFP6cqHTJBH1cZqy96OeR3u1dJ+Ez2D4Bg==" }, + "node_modules/next-fonts": { + "version": "1.5.1", + "resolved": "https://registry.npmmirror.com/next-fonts/-/next-fonts-1.5.1.tgz", + "integrity": "sha512-pgEJ40xO1oRhM6RqhQJ9CzuZOFp6Zq+aAD/V1P9sq/wdepvLzhFxDm3lCZNoE7+78NSuMKgT6b1qeXSsqWuUMQ==", + "dev": true, + "dependencies": { + "file-loader": "^6.0.0", + "url-loader": "^4.0.0" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, "node_modules/next-transpile-modules": { "version": "10.0.1", "resolved": "https://registry.npmmirror.com/next-transpile-modules/-/next-transpile-modules-10.0.1.tgz", @@ -5731,6 +6244,13 @@ "enhanced-resolve": "^5.10.0" } }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true, + "peer": true + }, "node_modules/normalize-package-data": { "version": "3.0.3", "resolved": "https://registry.npmmirror.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz", @@ -6169,6 +6689,16 @@ "node": ">=8" } }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "peer": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, "node_modules/rc-resize-observer": { "version": "1.4.0", "resolved": "https://registry.npmmirror.com/rc-resize-observer/-/rc-resize-observer-1.4.0.tgz", @@ -6914,6 +7444,28 @@ "loose-envify": "^1.1.0" } }, + "node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/screenfull": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/screenfull/-/screenfull-5.2.0.tgz", + "integrity": "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmmirror.com/semver/-/semver-7.5.4.tgz", @@ -6928,6 +7480,16 @@ "node": ">=10" } }, + "node_modules/serialize-javascript": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "dev": true, + "peer": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, "node_modules/set-function-length": { "version": "1.1.1", "resolved": "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.1.1.tgz", @@ -7044,6 +7606,34 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "peer": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "peer": true + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/space-separated-tokens": { "version": "2.0.2", "resolved": "https://registry.npmmirror.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", @@ -7363,6 +7953,63 @@ "node": ">=6" } }, + "node_modules/terser": { + "version": "5.26.0", + "resolved": "https://registry.npmmirror.com/terser/-/terser-5.26.0.tgz", + "integrity": "sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ==", + "dev": true, + "peer": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.9", + "resolved": "https://registry.npmmirror.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", + "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", + "dev": true, + "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.17", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.16.8" + }, + "engines": { + "node": ">= 10.13.0" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "peer": true + }, "node_modules/text-extensions": { "version": "2.4.0", "resolved": "https://registry.npmmirror.com/text-extensions/-/text-extensions-2.4.0.tgz", @@ -7650,6 +8297,23 @@ "node": ">=8" } }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "peer": true, + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz", @@ -7658,6 +8322,29 @@ "punycode": "^2.1.0" } }, + "node_modules/url-loader": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/url-loader/-/url-loader-4.1.1.tgz", + "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "mime-types": "^2.1.27", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "peerDependencies": { + "file-loader": "*", + "webpack": "^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "file-loader": { + "optional": true + } + } + }, "node_modules/use-sync-external-store": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", @@ -7730,6 +8417,84 @@ "node": ">=10.13.0" } }, + "node_modules/webpack": { + "version": "5.89.0", + "resolved": "https://registry.npmmirror.com/webpack/-/webpack-5.89.0.tgz", + "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmmirror.com/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "peer": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index c703958..a24a9cd 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "@mui/material": "^5.13.0", "@tanstack/react-query": "^4.29.7", "ace-builds": "^1.32.2", + "ahooks": "^3.7.8", "axios": "^1.4.0", "big-integer": "^1.6.52", "crypto-js": "^4.2.0", @@ -78,6 +79,7 @@ "eslint-plugin-next": "^0.0.0", "eslint-plugin-prettier": "^5.1.0", "husky": "^8.0.0", - "lint-staged": "^15.2.0" + "lint-staged": "^15.2.0", + "next-fonts": "^1.5.1" } } diff --git a/public/cnzz.js b/public/cnzz.js index eda09d7..b33a41a 100644 --- a/public/cnzz.js +++ b/public/cnzz.js @@ -2,8 +2,8 @@ if ( [ 'rivers.chaitin.cn', 'dev.rivers.ctopt.cn', - '127.0.0.1', - 'localhost', + // '127.0.0.1', + // 'localhost', ].includes(document.domain) ) { window.is_river = true; diff --git a/src/asset/tag/dev.svg b/src/asset/tag/dev.svg new file mode 100644 index 0000000..319fbd8 --- /dev/null +++ b/src/asset/tag/dev.svg @@ -0,0 +1,25 @@ + + + 开发工具(未选中) + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/asset/tag/dev_check.svg b/src/asset/tag/dev_check.svg new file mode 100644 index 0000000..aaf8ccc --- /dev/null +++ b/src/asset/tag/dev_check.svg @@ -0,0 +1,25 @@ + + + 开发工具(选中) + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/asset/tag/encode.svg b/src/asset/tag/encode.svg new file mode 100644 index 0000000..0deadf3 --- /dev/null +++ b/src/asset/tag/encode.svg @@ -0,0 +1,24 @@ + + + 编码解码(未选中) + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/asset/tag/encode_check.svg b/src/asset/tag/encode_check.svg new file mode 100644 index 0000000..d18a955 --- /dev/null +++ b/src/asset/tag/encode_check.svg @@ -0,0 +1,24 @@ + + + 编码解码(选中) + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/asset/tag/encryption.svg b/src/asset/tag/encryption.svg new file mode 100644 index 0000000..259832b --- /dev/null +++ b/src/asset/tag/encryption.svg @@ -0,0 +1,22 @@ + + + 加密解密(未选中) + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/asset/tag/encryption_check.svg b/src/asset/tag/encryption_check.svg new file mode 100644 index 0000000..236a9a2 --- /dev/null +++ b/src/asset/tag/encryption_check.svg @@ -0,0 +1,22 @@ + + + 加密解密(选中) + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/asset/tag/hot.svg b/src/asset/tag/hot.svg new file mode 100644 index 0000000..9383ebf --- /dev/null +++ b/src/asset/tag/hot.svg @@ -0,0 +1,23 @@ + + + 热门工具(未选中) 2 + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/asset/tag/hot_check.svg b/src/asset/tag/hot_check.svg new file mode 100644 index 0000000..29f12c1 --- /dev/null +++ b/src/asset/tag/hot_check.svg @@ -0,0 +1,23 @@ + + + 热门工具(选中) 2 + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/asset/tag/hover_red_like.svg b/src/asset/tag/hover_red_like.svg new file mode 100644 index 0000000..dede3ee --- /dev/null +++ b/src/asset/tag/hover_red_like.svg @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/src/asset/tag/image.svg b/src/asset/tag/image.svg new file mode 100644 index 0000000..36d1098 --- /dev/null +++ b/src/asset/tag/image.svg @@ -0,0 +1,23 @@ + + + 图像处理(未选中) + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/asset/tag/image_check.svg b/src/asset/tag/image_check.svg new file mode 100644 index 0000000..7aa9d6f --- /dev/null +++ b/src/asset/tag/image_check.svg @@ -0,0 +1,23 @@ + + + 图像处理(选中) + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/asset/tag/json.svg b/src/asset/tag/json.svg new file mode 100644 index 0000000..dbb819c --- /dev/null +++ b/src/asset/tag/json.svg @@ -0,0 +1,24 @@ + + + json (未选中) + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/asset/tag/json_check.svg b/src/asset/tag/json_check.svg new file mode 100644 index 0000000..e89ffe2 --- /dev/null +++ b/src/asset/tag/json_check.svg @@ -0,0 +1,24 @@ + + + json (选中) + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/asset/tag/like.svg b/src/asset/tag/like.svg new file mode 100644 index 0000000..6564274 --- /dev/null +++ b/src/asset/tag/like.svg @@ -0,0 +1,24 @@ + + + 我的收藏(未选中) + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/asset/tag/like_check.svg b/src/asset/tag/like_check.svg new file mode 100644 index 0000000..d812add --- /dev/null +++ b/src/asset/tag/like_check.svg @@ -0,0 +1,24 @@ + + + 我的收藏(选中) + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/asset/tag/no_like.png b/src/asset/tag/no_like.png new file mode 100644 index 0000000000000000000000000000000000000000..28191f11258b6cee8b1a0e0bef017e8337d3e127 GIT binary patch literal 27577 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¨ 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 F{|}z~jQ#)s literal 0 HcmV?d00001 diff --git a/src/asset/tag/other.svg b/src/asset/tag/other.svg new file mode 100644 index 0000000..8a65f70 --- /dev/null +++ b/src/asset/tag/other.svg @@ -0,0 +1,23 @@ + + + 杂项(未选中) + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/asset/tag/other_check.svg b/src/asset/tag/other_check.svg new file mode 100644 index 0000000..8f3f5ad --- /dev/null +++ b/src/asset/tag/other_check.svg @@ -0,0 +1,23 @@ + + + 杂项(选中) + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/asset/tag/red_like.png b/src/asset/tag/red_like.png new file mode 100644 index 0000000000000000000000000000000000000000..ee015f1fc2cccf7f5e6a10e793992ec2b1a0e151 GIT binary patch literal 1282 zcmV+d1^xPoP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR919H0XL1ONa40RR918~^|S0A#)Nq5uE{Y)M2xR7efIR?SmeRTRJX-S?7E z^7wcrp;)w~gCz825?Wf@sdWb3vFoO*ZXiU)(Q)U-UH%6*4r1uWjr;-bG%R$Z6mSR- zWZHz%p(Y^#i6nVn*LNP?*OwR?%8X|5&N;vHmE8L~=LMlwpDuY?0^A#%`jCK9FDzF< zx_viXAdwWFdJDXk!2ru(XpbC=a?E{@POf5ccrrvWe)Hm0?@v}$=6&$sJMzpB?Kz|?=#RTStTcC>D|HDO;D^8@Quv$J0o;NyTIn*p&{MH$`B46=mww&;SHE|2NcgN<);EEqZpys%wP&+ae`iNmpbZ$v-7 zWCLv!xHl+7l>Ox$B1Nxv_T8ej!qQ=zJhY>GKL8fkao&;Xa3CD-vw;>0J0x(~#6p~5 z7&`aTZjtDOY~Cq_l>+CBjCJ}(yY7VVm$KQ^KL?MHU!J_k`NnP#0qxZD%Vj8FCpxQv z4lMKbkD_XR<1gjR_S%z;r- zHFcHJV z+>*5@fDJ6DodlKv+pNP`Utd3SqN3KW3ND)CfIc}bcduP1@WUBUN^ogy{+Sgo24g`s zp|2|NFUlQdk{LF=rzKiE=D0lbwL%LW8i60 zio^$$x^Ayth;w_~nf=wTo}ZS}jGu`xi9~{XoF9BwQ)xdE$X;b5`HQl@^3>IT)1xcu z6;I#wz!#t1-%F)Zw7EgE-S!uX!!tgL)rh%(sY|afmA1ca*ay7i$U)C9p zyMysT9qEG>fQcbcRN{FpFZ-_)Q>lc;0$)c0VbX=HPt*8-ijjnx5i6>mSoSs{; z?@$~w$x%5WhX*GA*5u$zB-%OhhV+m`7?2(OZ7` z6YqH&LN3&RT2PZUgL-yDFcuaTbc$#RbZTfK$n$(yF4TgW&KeC3osR!Xw|8Q@217&U zj9#ev&6lI!93$(v2_hAa#|7!woVD$jv-YZ5HfdN8yikr+U1qi|?HP6D11Mk}dmiN_ sO;Z|X&5k#f3j#^!*XI6kV*k7TH_N%Z@WydzU;qFB07*qoM6N<$f-TQZc>n+a literal 0 HcmV?d00001 diff --git a/src/asset/tag/red_like_check.png b/src/asset/tag/red_like_check.png new file mode 100644 index 0000000000000000000000000000000000000000..22a7ccfab700121d970b73da2d5167c9a58f438c GIT binary patch literal 1336 zcmV-81;_e{P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR919H0XL1ONa40RR918~^|S0A#)Nq5uE{qDe$SR7efIR?BN#WfVW>-bva- z3`jLl3nFBtf=d?){sBHJqGs|mh%U?`#iHP*3yXqC9|^YBCYD;IF|C-!ByE%~x)5~X zQm8w@F06|*Em>qT$=sRa@0{;3_fDqOl^@)E-+BFh=bY~`A!-?{vdj$#t#uIH?vRo> zn9xa3e&!Un)LJ6`^z?)|$nwAeU9c?nyI6#j$lTz%R-%M%cTSr^mH8nT21U*eOVF__ z4IHEjAE%9kXj8w`eHA8`;K|p|Q6(931~^m_q%v)`fI>1~z7Yj1;O2(Rqr6J;h|G*k z1s%%|<)3MTpEf?gMd+=L;Sz0-Hy{xt(M*bF6Mpp~YXZ)o4nCoyGwhmGX{H}b0kJnK zmy3v;Fcxd^Y0Ap*<5bD6Q-*+yHhE;OJ5&(nLZGa?@eplR{-j#cO*NSG%X9`njo;&U zzB(2IWu^Zws?o#F$sAmO1*r^I7nlR_smk2oEd=gy=$^rtJZl8;a@x5MD>r0%^a9Y! z?a(b79~}1Bbxvb9lP%izh}sl&G-p2t*%QIT4HP~`)zUgu(@V5_PY-`|hWV2(n2*h1 zGt(h#;vK4X91i|>o#p%f8}gky{Oz2O$Ic-OoDygC@2v0E`pB6#`sR+1XW0qNBO{)tAUy2$Jd6C)_K|nYKB8=8xFkI&T7Z& z+U?{Q{@~0rESGWVRhi%LLQvb&bF>8Jx)}nkMia8q zVbpeq>O90B<7OP0VV=VK+TGKGz)Sen`P_-OLtvy1ihIqnSRSW_oT3K!>hNsflXRR1 zXHVZNE^qr!gt9WRi?&yPrA(fr211m`W~`N1lHaKJfv5Pn6I*%kcI$s7l%?_uIIYV@ zVBnr4U!|@aA|T$+<6mEHM-+4gLb*DCSD9W$C9fd!XHiL7s6?x>R$`88K-F`yU@csS z?kD)n$*W6QuAiKf<3Kz?sFzACE zFP_(hD)5@A}n@Tz|#%~p7yJva`0A>}aPOEBH^<8ugV6}{$ zg!-uJkDrlXZY3$SPkr%O5}J%(hol7YEn}yqmR_;;=!+d*Z99Qng}jIte3X*iy;R!O ui(l + + 文字处理(未选中) + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/asset/tag/text_check.svg b/src/asset/tag/text_check.svg new file mode 100644 index 0000000..7431db7 --- /dev/null +++ b/src/asset/tag/text_check.svg @@ -0,0 +1,26 @@ + + + 文字处理(选中) + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/components/Button/index.tsx b/src/components/Button/index.tsx index 942405d..682f820 100644 --- a/src/components/Button/index.tsx +++ b/src/components/Button/index.tsx @@ -105,7 +105,7 @@ const ButtonStyle: { [key in ButtonType]: object } = { }, }, highlight: { - background: 'linear-gradient(270deg, #11AF60 0%, #52C41A 100%)', + background: 'linear-gradient(270deg, #11AF60 0%, rgba(52, 90, 255, 1) 100%)', boxShadow: '0px 10px 30px 0px rgba(82,196,26,0.2)', color: '#fff', }, diff --git a/src/components/LikeIcon/index.tsx b/src/components/LikeIcon/index.tsx new file mode 100644 index 0000000..fed025d --- /dev/null +++ b/src/components/LikeIcon/index.tsx @@ -0,0 +1,50 @@ +import RedTag from '@/asset/tag/red_like.png'; +import RedTagCheck from '@/asset/tag/red_like_check.png'; +import HoverRedTagCheck from '@/asset/tag/hover_red_like.svg'; +import { LikeContext } from '@/hooks/useLikeList'; +import React, { useContext, useMemo } from 'react'; +import { Box } from '@mui/material'; + +const LikeIcon: React.FC<{ path: string, style: React.CSSProperties }> = (props) => { + const { path, style = {} } = props + const { likeList, updateLikeList } = useContext(LikeContext) + + const hanldeLike = (event: React.MouseEvent, path: string) => { + event.preventDefault() + if (typeof window !== 'undefined' && window.localStorage) { + try { + let newLike = [] + if (likeList?.includes(path)) { + newLike = likeList.filter(item => item !== path) + } else { + newLike = [...(likeList || []), path] + } + updateLikeList(newLike) + } finally { + console.log('Get like list error') + } + } + } + const isCheck = useMemo(() => { + return likeList?.includes(path) + }, [likeList, path]) + + return ( + hanldeLike(event, path)}/> + ); +}; + +export default LikeIcon; diff --git a/src/components/MenuView/components.tsx b/src/components/MenuView/components.tsx deleted file mode 100644 index 966894d..0000000 --- a/src/components/MenuView/components.tsx +++ /dev/null @@ -1,137 +0,0 @@ -import { defaultText, grayBg, grayBorder, grayText } from '@/constant'; -import { Box } from '@mui/material'; -import { styled } from '@mui/material/styles'; - -export const MenuPage = styled(Box)(() => ({ - display: 'flex', - height: '100% ', - backgroundColor: grayBg, - borderTop: `1px solid ${grayBorder}`, - paddingBottom: '16px', - paddingRight: '16px', - '& .Mui-selected': { - backgroundColor: 'rgba(0, 0, 0, 0.04)!important', - }, -})); - -export const Main = styled('div')(() => ({ - flex: 1, - padding: '24px', - paddingBottom: '0', - overflowY: 'auto', - display: 'flex', - flexDirection: 'column', - gap: '24px', - '& code, & code *': { - fontFamily: 'Mono', - }, - '& code .linenumber': { - backgroundColor: 'rgba(82, 196, 26, 0.08)', - marginRight: '24px', - paddingRight: '5px!important', - minWidth: '2em!important', - }, - '& pre': { - borderRadius: '4px', - minHeight: '150px', - }, -})); - -export const SideMenu = styled('div')(() => ({ - display: 'flex', - flexDirection: 'column', - alignItems: 'stretch', - padding: '16px 16px 0 16px', - gap: '8px', - height: '100%', -})); - -export const SubMenu = styled('div', { - shouldForwardProp: (prop) => prop !== 'expand' && prop !== 'height', -})<{ expand: string; height: number | string }>(({ expand, height }) => ({ - display: 'flex', - flexDirection: 'column', - alignItems: 'stretch', - gap: '12px', - height: 0, - transition: 'height 0.2s linear', - overflow: 'hidden', - ...(expand === 'true' && { - height: height ?? 'auto', - transition: 'height 0.2s linear', - }), -})); - -export const Breadcrumbs = styled('div')(() => ({ - display: 'flex', - alignItems: 'center', - width: '100%', - gap: '4px', - marginTop: '16px', -})); - -export const BreadcrumbsItem = styled(Box)(() => ({ - color: grayText, - cursor: 'pointer', - '&:hover': { - color: defaultText, - }, - fontSize: '14px', -})); - -export const ToolsIcon = styled(Box)(() => ({ - width: '60px', - height: '60px', - background: 'linear-gradient(180deg, #230970 0%, #1C0254 100%)', - borderRadius: '8px', -})); - -export const Tag = styled('div', { - shouldForwardProp: (prop) => prop !== 'highlight', -})<{ highlight: 'true' | 'false' }>(({ highlight }) => ({ - display: 'inline-block', - width: '24px', - lineHeight: '14px', - fontSize: '10px', - borderRadius: '4px', - textAlign: 'center', - color: '#fff', - backgroundColor: '#FF665D', - ...(highlight === 'true' && { color: '#FF665D', backgroundColor: '#fff' }), -})); - -export const ScrollY = styled('div')(() => ({ - height: '100%', - overflow: 'auto', - ...(navigator?.userAgent?.indexOf('Chrome') != -1 && { overflow: 'overlay' }), -})); - -export const SubTitle = styled('div')(() => ({ - height: '20px', - padding: '12px', - background: 'rgba(30, 111, 255, 0.1)', - borderRadius: '4px', -})); - -export const Container = styled(Box)(() => ({ - background: '#fff', - borderRadius: '4px', - boxShadow: '0px 4px 10px 0px rgba(145,158,171,0.1)', - overflow: 'auto', - minHeight: '100%', - '& > *': { - '@media(min-width: 1520px)': { - marginLeft: 'auto', - marginRight: 'auto', - }, - }, - '& > .MuiGrid-container': { - '@media(min-width: 1520px)': { - marginLeft: 'auto!important', - marginRight: 'auto!important', - '& > .MuiGrid-item:first-of-type': { - paddingLeft: '0!important', - }, - }, - }, -})); diff --git a/src/components/MenuView/index.tsx b/src/components/MenuView/index.tsx index 74758ed..b4f65ee 100644 --- a/src/components/MenuView/index.tsx +++ b/src/components/MenuView/index.tsx @@ -1,25 +1,14 @@ -import { defaultTextClick, secondaryClick } from '@/constant'; +import { grayText } from '@/constant'; import { usePath } from '@/hooks'; -import { AllTags, Tags, Tool, routesMenu } from '@/utils/tools'; -import ErrorIcon from '@mui/icons-material/Error'; -import SearchIcon from '@mui/icons-material/Search'; +import { allTags } from '@/utils/tags'; +import { Tool, allTools } from '@/utils/tools'; import { Box, - Button, - Grid, - IconButton, - InputBase, - ListItemText, Paper, - Typography, + Stack, + Typography } from '@mui/material'; -import List from '@mui/material/List'; -import ListItemButton from '@mui/material/ListItemButton'; -import Head from 'next/head'; -import { useRouter } from 'next/router'; -import React, { useEffect, useMemo } from 'react'; -import { Container, Main, MenuPage, SideMenu } from './components'; -import Link from 'next/link'; +import React from 'react'; export interface MenuProps { children: React.ReactElement; @@ -31,224 +20,41 @@ const ifChecked = (currentPath: string, itemPath: string) => { const MenuView: React.FC = ({ children }) => { const { path } = usePath(); - const [tags, setTags] = React.useState([]); - const [tools, setTools] = React.useState(routesMenu); - const [searchText, setSearchText] = React.useState(''); - const [openStaus, setOpenStatus] = React.useState( - routesMenu.map((item) => true) - ); - const router = useRouter(); - - const currentItem = useMemo(() => { - const _item = routesMenu.find((item) => item.path === path); - if (_item) return _item; - }, [path]); - const checkTags = (tag: Tags) => { - const _index = tags.findIndex((item) => item === tag); - const _tags = [...tags]; - if (_index >= 0) { - _tags.splice(_index, 1); - } else { - _tags.push(tag); - } - setTags(_tags); - }; - - useEffect(() => { - let toolsFilter: Tool[] = []; - if (tags.length) - toolsFilter = routesMenu.filter((item) => - item.tags.some((tag) => tags.includes(tag)) - ); - else toolsFilter = routesMenu; - setTools( - toolsFilter.filter((item) => { - return ( - item.label.toUpperCase().includes(searchText?.toUpperCase()) || - item.subTitle.toUpperCase().includes(searchText?.toUpperCase()) - ); - }) - ); - }, [tags, searchText]); + const [tool] = React.useState(allTools.find(item => item.path === path)); return ( - <> - - {currentItem?.label + ' - 长亭百川云工具库'} - - - - - + + + - - - - - setSearchText(event.target.value)} - placeholder='输入关键词搜索工具' - inputProps={{ 'aria-label': 'search icons' }} - sx={{ grow: 1, fontSize: '12px' }} - /> - - - {AllTags.map((item) => ( - - ))} - - - - {tools.map((item, index) => ( - - - - - - ))} - - - -
- - - - - - - {currentItem?.label} - - - - {currentItem?.subTitle ? ( - - - {currentItem?.subTitle} - - ) : null} - - - - - {children} - -
-
- + {tool?.label} + +
+ + {allTags.filter(tag => tool?.tags.includes(tag.name)).map(tag => {tag.label})} + + + {tool?.subTitle} + {children} + ); }; diff --git a/src/components/ToolCard/index.tsx b/src/components/ToolCard/index.tsx new file mode 100644 index 0000000..6aac4bd --- /dev/null +++ b/src/components/ToolCard/index.tsx @@ -0,0 +1,34 @@ +import { Tag } from "@/utils/tags" +import { Tool } from "@/utils/tools" +import { Avatar, CardHeader, Typography } from "@mui/material" +import LikeIcon from "../LikeIcon" +import { grayText2 } from "@/constant" + +export const ToolCard = (props: { tool: Tool, tag?: Tag, showStar?: boolean }) => { + const { tool, tag, showStar = true } = props + return ( + <> + + {tool.label[0]} + + } + action={ + + } + title={tool.label} + /> + {tool.subTitle} + + ) +} \ No newline at end of file diff --git a/src/components/Tools/home.tsx b/src/components/Tools/home.tsx deleted file mode 100644 index 3b7da73..0000000 --- a/src/components/Tools/home.tsx +++ /dev/null @@ -1,118 +0,0 @@ -import { - Autocomplete, - Box, - Button, - IconButton, - Paper, - Stack, - TextField, - Typography, -} from '@mui/material'; - -import { primary } from '@/constant'; -import { AllTags, routesMenu, type Tool } from '@/utils/tools'; -import SearchIcon from '@mui/icons-material/Search'; -import Link from 'next/link'; -import { useRouter } from 'next/router'; -import { useState } from 'react'; - -export default function App() { - const router = useRouter(); - - // const [searchText, setSearchText] = useState('') - const [tools] = useState(routesMenu); - const [tags] = useState<(typeof AllTags)[number][]>(AllTags); - - return ( - - - - - X - - TOOLS - - - - menu.filter((item) => { - return ( - item.label - .toUpperCase() - .includes(state.inputValue?.toUpperCase()) || - item.subTitle - .toUpperCase() - .includes(state.inputValue?.toUpperCase()) - ); - }) - } - onInputChange={(v: any) => { - setTimeout(() => { - const item = routesMenu.find((item) => - [v.target.textContent, v.target.value].includes(item.label) - ); - if (item) { - router.push(item.path); - } - }); - }} - options={routesMenu} - sx={{ height: '100%' }} - renderInput={(params) => ( - - - - - - - )} - /> - - - - {tags.map((section) => [ - - - {section.label} - , - - {tools - .filter((tool) => tool.tags.includes(section.name)) - .map((item) => ( - - - - ))} - , - ])} - - - ); -} diff --git a/src/components/Tools/index.tsx b/src/components/Tools/index.tsx index 3c4b0eb..2934244 100644 --- a/src/components/Tools/index.tsx +++ b/src/components/Tools/index.tsx @@ -18,7 +18,7 @@ export const ToolsForm = styled(Box)(() => ({ pt: '10px', display: 'flex', flexDirection: 'column', - width: '838px', + margin: 'auto', gap: 16, '& .MuiOutlinedInput-root': { @@ -35,7 +35,6 @@ export const ToolsForm = styled(Box)(() => ({ width: '155px', color: defaultTextClick, fontSize: '14px', - maxWidth: '838px', }, '& .MuiOutlinedInput-notchedOutline': { borderColor: '#E3E8EF', diff --git a/src/constant/color.ts b/src/constant/color.ts index 404b5c6..bda3d69 100644 --- a/src/constant/color.ts +++ b/src/constant/color.ts @@ -1,4 +1,4 @@ -export const primary = '#52C41A'; +export const primary = 'rgba(52, 90, 255, 1)'; export const primaryHover = '#73D13C'; export const primaryClick = '#389E0E'; @@ -10,7 +10,7 @@ export const secondary = '#ECF9E6'; export const secondaryHover = '#F3FDEE'; export const secondaryClick = '#DAE8D4'; -export const special = 'linear-gradient(270deg, #11AF60 0%, #52C41A 100%)'; +export const special = 'linear-gradient(270deg, #11AF60 0%, rgba(52, 90, 255, 1) 100%)'; export const dangerHover = 'linear-gradient(225deg, #FF1F1F 0%, #F78900 100%)'; export const disabled = '#F7F7F7'; @@ -31,12 +31,12 @@ export const leastTextClick = '#737373'; export const disabledText = '#BFBFBF'; export const specialText = '#737971'; -export const success = '#52C41A'; +export const success = 'rgba(52, 90, 255, 1)'; export const warning = '#FFBF00'; export const error = '#FF1F1F'; -export const grayText = '#0B310440'; -export const grayText2 = '#97A4B0'; +export const grayText = '#0B2562'; +export const grayText2 = 'rgba(11,37,98,0.5)'; export const errorText = '#FF1F1F'; export const infoText = '#2F7CE9'; diff --git a/src/hooks/useAnchor.tsx b/src/hooks/useAnchor.tsx new file mode 100644 index 0000000..13bc791 --- /dev/null +++ b/src/hooks/useAnchor.tsx @@ -0,0 +1,22 @@ +import { useLocalStorageState } from 'ahooks'; +import { createContext, useState } from "react"; + +export interface Anchor { + anchor: string; + updateAnchor: (value: string) => void; +} + +export const AnchorContext = createContext(null as any); + +export const AnchorContextProvider = ({ children }: any) => { + const [anchor, setAnchor] = useState(''); + const updateAnchor = (newValue: string) => { + setAnchor(newValue) + }; + const contextValue = { + anchor, + updateAnchor, + }; + + return {children}; +}; \ No newline at end of file diff --git a/src/hooks/useLikeList.tsx b/src/hooks/useLikeList.tsx new file mode 100644 index 0000000..a195037 --- /dev/null +++ b/src/hooks/useLikeList.tsx @@ -0,0 +1,24 @@ +import { useLocalStorageState } from 'ahooks'; +import { createContext, useState } from "react"; + +export interface Like { + likeList: string[]; + updateLikeList: (value: string[]) => void; +} + +export const LikeContext = createContext(null as any); + +export const LikeContextProvider = ({ children }: any) => { + const [localList = [], setLocalList] = useLocalStorageState('like_list', { defaultValue: [] }) + const [likeList, setValue] = useState(localList); + const updateLikeList = (newValue: string[]) => { + setValue(newValue); + setLocalList(newValue) + }; + const contextValue = { + likeList, + updateLikeList, + }; + + return {children}; +}; \ No newline at end of file diff --git a/src/icon/Copy.tsx b/src/icon/Copy.tsx index 355e8e5..78820d2 100644 --- a/src/icon/Copy.tsx +++ b/src/icon/Copy.tsx @@ -10,7 +10,7 @@ export const Copy = (props: SvgIconProps) => { ({ + background: 'linear-gradient(180deg, rgba(255, 182, 85, 0.2) 0%, rgba(255, 58, 116, 0.2) 100%)', + filter: 'blur(1px)', + width: '14px', + height: '14px', + borderRadius: '50%', + justifyContent: 'center', + alignItems: 'center', + marginLeft: 'auto', +})); +export const IssueIcon = styled(Box)(() => ({ + width: '8px', + height: '8px', + borderRadius: '50%', + background: 'linear-gradient(141deg, #FFB655 0%, #FF3A74 100%)', +})); diff --git a/src/layouts/Header/index.tsx b/src/layouts/Header/index.tsx new file mode 100644 index 0000000..b066be4 --- /dev/null +++ b/src/layouts/Header/index.tsx @@ -0,0 +1,151 @@ +import { usePath } from '@/hooks'; +import { Tags } from '@/utils/tags'; +import { Tool, allTools } from '@/utils/tools'; +import GitHubIcon from '@mui/icons-material/GitHub'; +import SearchIcon from '@mui/icons-material/Search'; +import { + Autocomplete, + Box, + Paper, + Stack, + TextField, + Typography +} from '@mui/material'; +import Link from 'next/link'; +import { useRouter } from 'next/router'; +import React, { useEffect, useMemo } from 'react'; +import { IssueIcon, IssueIconWrap } from './components'; +import { ToolCard } from '@/components/ToolCard'; + +const ifChecked = (currentPath: string, itemPath: string) => { + return currentPath === itemPath; +}; + +const Header: React.FC<{}> = () => { + const { path } = usePath(); + const [tags, setTags] = React.useState([]); + const [tools, setTools] = React.useState(allTools); + const [openSearch, setOpenSearch] = React.useState(false); + const [searchText, setSearchText] = React.useState(''); + + const [openStaus, setOpenStatus] = React.useState( + allTools.map((item) => true) + ); + const router = useRouter(); + + const currentItem = useMemo(() => { + const _item = allTools.find((item) => item.path === path); + if (_item) return _item; + }, [path]); + const checkTags = (tag: Tags) => { + const _index = tags.findIndex((item) => item === tag); + const _tags = [...tags]; + if (_index >= 0) { + _tags.splice(_index, 1); + } else { + _tags.push(tag); + } + setTags(_tags); + }; + + useEffect(() => { + let toolsFilter: Tool[] = []; + if (tags.length) + toolsFilter = allTools.filter((item) => + item.tags.some((tag) => tags.includes(tag)) + ); + else toolsFilter = allTools; + setTools( + toolsFilter.filter((item) => { + return ( + item.label.toUpperCase().includes(searchText?.toUpperCase()) || + item.subTitle.toUpperCase().includes(searchText?.toUpperCase()) + ); + }) + ); + }, [tags, searchText]); + + return ( + + + 百川在线工具箱 + + + + + + 工具不够?提个需求 + + + setOpenSearch(false)} + onOpen={() => setOpenSearch(true)} + filterOptions={(menu, state) => + menu.filter((item) => { + return ( + item.label + .toUpperCase() + .includes(state.inputValue?.toUpperCase()) || + item.subTitle + .toUpperCase() + .includes(state.inputValue?.toUpperCase()) + ); + }) + } + onInputChange={(v: any) => { + const item = allTools.find((item) => + [v.target.textContent, v.target.value].includes(item.label) + ); + }} + options={allTools} + renderOption={(props: object, option: Tool, state: object, ownerState: object) => ( + + setOpenSearch(false)}> + + + + )} + sx={{ height: '100%' }} + renderInput={(params) => ( + + + + + )} + /> + + + ); +}; + +export default Header; diff --git a/src/layouts/LoginLayout/copyright.tsx b/src/layouts/LoginLayout/copyright.tsx deleted file mode 100644 index b4d0468..0000000 --- a/src/layouts/LoginLayout/copyright.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import React, { useCallback } from 'react'; -import emblem from '@/asset/img/emblem.webp'; -import { ImageIcon } from '@/icon'; -import { Stack, SxProps } from '@mui/material'; -import Text from '@/components/Text'; -import { useMobileView } from '@/hooks'; -import { Side_Margin } from '@/styles/colors'; - -const Copyright: React.FC<{ sx?: SxProps; fontColor?: string }> = ({ - sx, - fontColor, -}) => { - const isMobile = useMobileView(); - - const openBeianLink = useCallback(() => { - window.open('https://beian.miit.gov.cn/#/Integrated/recordQuery', '_blank'); - }, []); - - return ( - - - Copyright ©2022 北京长亭未来科技有限公司 - - a': { color: 'inherit' }, - }} - onClick={openBeianLink} - > - - 京ICP备 19035216号-1 - - - ); -}; - -export default Copyright; diff --git a/src/layouts/LoginLayout/index.tsx b/src/layouts/LoginLayout/index.tsx deleted file mode 100644 index 9b1a5a8..0000000 --- a/src/layouts/LoginLayout/index.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import React from 'react'; -import Navbar from '@/layouts/Navbar'; -import { Stack } from '@mui/material'; -import Copyright from './copyright'; -import { useMobileView } from '@/hooks'; -import banner1 from '@/asset/img/banner1.webp'; -import mobile_login from '@/asset/img/mobile_login.webp'; -import Image from 'next/image'; - -const LoginLayout: React.FC<{ children: React.ReactNode }> = ({ children }) => { - const isMobile = useMobileView(); - return ( - <> - - - background - {children} - - - - ); -}; - -export default LoginLayout; diff --git a/src/layouts/Logo/index.tsx b/src/layouts/Logo/index.tsx deleted file mode 100644 index 60234b5..0000000 --- a/src/layouts/Logo/index.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import React, { useCallback } from 'react'; -import { styled } from '@mui/material/styles'; -import { useNavigateParams } from '@/hooks'; -import { Logo as CompanyLogo } from '@/icon'; -import Text from '@/components/Text'; -import { useMobileView } from '@/hooks'; -import { primary, defaultText } from '@/styles/colors'; - -const LogoComponent = styled('a')(({ theme }) => ({ - display: 'flex', - userSelect: 'none', - margin: '8px', - marginRight: '60px', - fontSize: '20px', - cursor: 'pointer', - [theme.breakpoints.down('sm')]: { - margin: '24px 8px', - marginRight: '0px', - }, -})); - -const Logo: React.FC = () => { - const navigate = useNavigateParams(); - const isMobile = useMobileView(); - - const toHome = useCallback(() => navigate('/'), [navigate]); - - return ( - - - - 长亭百川云平台 - - - ); -}; - -export default Logo; diff --git a/src/layouts/Navbar/components.tsx b/src/layouts/Navbar/components.tsx deleted file mode 100644 index 6a7f8d1..0000000 --- a/src/layouts/Navbar/components.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import React from 'react'; -import { styled } from '@mui/material/styles'; - -export interface BarProps { - children: React.ReactNode; - view?: 'default' | 'login'; - id?: string; -} - -const BarBase = styled('div', { - shouldForwardProp: (prop) => prop !== 'view', -})<{ view?: 'default' | 'login' }>(({ theme, view = 'default' }) => ({ - width: '100%', - position: 'fixed', - top: '0px', - zIndex: theme.zIndex.drawer + 3, - // boxShadow: theme.shadows[4], - backgroundColor: view === 'default' ? 'rgba(255,255,255,0.6)' : 'transparent', - backdropFilter: 'blur(4px)', - [theme.breakpoints.down('sm')]: { - zIndex: theme.zIndex.drawer - 1, - }, -})); -const BarContent = styled('div')(({ theme }) => ({ - display: 'flex', - alignItems: 'center', - height: '64px', - justifyContent: 'flex-start', - margin: `0 28px`, - marginRight: '0', - [theme.breakpoints.down('sm')]: { marginLeft: '12px' }, -})); - -const Bar: React.FC = (props) => { - const { children, view, id } = props; - return ( - - {children} - - ); -}; - -export default Bar; diff --git a/src/layouts/Navbar/index.tsx b/src/layouts/Navbar/index.tsx deleted file mode 100644 index b81f207..0000000 --- a/src/layouts/Navbar/index.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React from 'react'; -import Bar from './components'; -import Logo from '@/layouts/Logo'; -import NavMenu from './items/menu'; -import { ApplicationInfo } from '@/types'; - -interface NavBarMenuData { - apps: ApplicationInfo[]; -} - -const renderNavContent = (menuData: ApplicationInfo[]) => { - return [, ]; -}; - -const DefaultNavbar: React.FC = ({ apps }) => { - return ( - - {renderNavContent(apps)} - - ); -}; - -const LoginNavbar: React.FC<{}> = () => { - return ( - - - - ); -}; - -const Navbar = { default: DefaultNavbar, login: LoginNavbar }; - -export default Navbar; diff --git a/src/layouts/Navbar/items/menu/index.tsx b/src/layouts/Navbar/items/menu/index.tsx deleted file mode 100644 index 8ec0e2b..0000000 --- a/src/layouts/Navbar/items/menu/index.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import { useMobileView } from '@/hooks'; -import { ApplicationInfo, NavMenuProps } from '@/types'; -import DehazeIcon from '@mui/icons-material/Dehaze'; -import { styled } from '@mui/material/styles'; -import { useRouter } from 'next/router'; -import React, { useCallback, useState } from 'react'; -import MenuItem from './item'; -import MobilPanel from './mobileView'; -import NavPanel from './panel'; - -const NavMenuComponent = styled('div')(() => ({ - display: 'flex', - gap: '40px', -})); - -const menu: NavMenuProps[] = [ - { title: '最新活动', link: '/' }, - { title: '产品', expand: true }, -]; - -const NavMenu: React.FC<{ apps: ApplicationInfo[] }> = ({ apps }) => { - const isMobile = useMobileView(); - const router = useRouter(); - const [panelContent, setPanelContent] = useState(); - const [openMobile, setOpenMobile] = useState(false); - const [openPanel, setOpenPanel] = useState(false); - - const handleOpen = useCallback( - (open: boolean) => () => { - setOpenMobile(open); - }, - [] - ); - - const handleClickMenu = useCallback( - (link?: string) => () => { - if (link) { - router.push(link); - } - }, - [router] - ); - - const handleShowPanel = useCallback( - (menuContent: NavMenuProps) => () => { - if (menuContent?.expand) setOpenPanel(true); - }, - [] - ); - - const handleLeavePanel = useCallback(() => { - setOpenPanel(false); - }, []); - - return ( - <> - {isMobile ? ( - - ) : ( - - {menu?.map((menuitem, index) => ( - - ))} - - )} - - {isMobile && ( - - )} - - ); -}; - -export default NavMenu; diff --git a/src/layouts/Navbar/items/menu/item.tsx b/src/layouts/Navbar/items/menu/item.tsx deleted file mode 100644 index 92a9b27..0000000 --- a/src/layouts/Navbar/items/menu/item.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import { ArrowDown } from '@/icon'; -import { defaultText, primary, secondaryText } from '@/styles/colors'; -import { styled, SxProps } from '@mui/material/styles'; -import React from 'react'; - -export interface MenuItemProps { - title: string | React.ReactElement; - subTitle?: string; - highlight?: string | boolean; - hoverview?: string | boolean; - expand?: string | boolean; - sx?: SxProps; - icon?: React.ReactElement; - onClick?: () => void; - onHover?: () => void; - onLeave?: () => void; -} - -const MenuItemComponent = styled('div', { - shouldForwardProp: (prop) => prop !== 'hightlight' && prop !== 'expand', -})>( - ({ highlight, hoverview }) => ({ - fontSize: 16, - fontWeight: 'bold', - color: highlight === 'true' ? primary : defaultText, - lineHeight: '22px', - ...(hoverview === 'true' && { - transition: 'color 0.1s linear', - }), - transition: 'color 0.1s linear', - display: 'flex', - alignItems: 'center', - - '& > svg': { - display: 'inline-block', - marginLeft: '8px', - transformOrigin: 'center', - transition: 'transform 0.1s linear', - }, - '&:hover': { - ...(hoverview === 'true' && { - color: primary, - transition: 'color 0.1s linear', - }), - '& > svg': { - transform: 'rotate(0.5turn)', - transition: 'transform 0.1s linear', - }, - }, - }) -); - -const MenuItemContent = styled('div')(() => ({ - fontSize: 'inherit', - color: secondaryText, -})); - -const MenuItemWrapper = styled('div')(() => ({ - display: 'flex', - flexDirection: 'column', - cursor: 'pointer', -})); - -const MenuItem: React.FC = (props) => { - const { - title, - subTitle, - highlight, - expand, - sx, - onClick, - onHover, - onLeave, - hoverview, - icon, - } = props; - return ( - - - {icon} - {title} - {expand && } - - {subTitle && {subTitle}} - - ); -}; - -export default MenuItem; diff --git a/src/layouts/Navbar/items/menu/mobileView.tsx b/src/layouts/Navbar/items/menu/mobileView.tsx deleted file mode 100644 index a93400b..0000000 --- a/src/layouts/Navbar/items/menu/mobileView.tsx +++ /dev/null @@ -1,166 +0,0 @@ -import search_icon from '@/asset/img/search_icon.webp'; -import { useDebounce } from '@/hooks'; -import { Side_Margin, grayLight, primary } from '@/styles/colors'; -import { ApplicationInfo } from '@/types'; -import ClearIcon from '@mui/icons-material/Clear'; -import { Drawer, TextField } from '@mui/material'; -import { styled } from '@mui/material/styles'; -import Image, { StaticImageData } from 'next/image'; -import { useRouter } from 'next/router'; -import React, { useCallback, useEffect, useState } from 'react'; -import MenuItem from './item'; -import { NavPanelProps } from './panel'; - -const PanelContent = styled('div')(() => ({ - display: 'flex', - flexDirection: 'column', - width: '100%', - padding: `${parseInt(Side_Margin) / 2}% ${Side_Margin}`, - justifyContent: 'flex-start', - gap: 20, -})); - -const Content = styled('div')(() => ({ - display: 'flex', - gap: 40, -})); - -const Header = styled('div')(() => ({ - display: 'flex', - justifyContent: 'flex-end', - alignItems: 'center', -})); - -const ContentCol = styled('div')(() => ({ - display: 'flex', - flexDirection: 'column', - height: '100%', - justifyContent: 'flex-start', - alignItems: 'stretch', - gap: 20, -})); - -export const Icon = ({ - style, - src, -}: { - style?: React.CSSProperties; - src: string | StaticImageData; -}) => { - return ( - search - ); -}; - -const ContentCard = styled('div')(() => ({ - padding: '12px 24px', - transition: 'background-color 0.2s linear', - '&:hover': { - backgroundColor: grayLight, - transition: 'background-color 0.2s linear', - }, -})); - -const NavPanel: React.FC = (props) => { - const { open, onClose, apps } = props; - const [menuContent, setMenuContent] = useState([]); - const [input, setInput] = useState(''); - const debounceInput = useDebounce(input, 500); - const router = useRouter(); - - const handleSearch = useCallback( - (search: string) => { - if (apps && search.length > 0) { - const data = JSON.parse(JSON.stringify(apps)) as ApplicationInfo[]; - const searchResult = data?.filter((item) => item.name.includes(search)); - setMenuContent([...searchResult]); - } else { - setMenuContent(apps); - } - }, - [apps] - ); - - const toWorkbench = useCallback( - (app: ApplicationInfo) => () => { - if (app?.scope) { - router.push(`/landing/${app?.scope}`); - } else { - router.push('/workbench'); - } - onClose?.(); - }, - [onClose, router] - ); - - const handleSetInput = useCallback((event: React.ChangeEvent) => { - const target = event.target as HTMLInputElement; - const input = target?.value?.trim(); - setInput(input ?? ''); - }, []); - - useEffect(() => { - handleSearch(debounceInput); - }, [debounceInput, handleSearch]); - - return ( - - -
- -
- - ), - }} - /> - - - {menuContent?.map((contentItem, index) => ( - - - - ))} - - -
-
- ); -}; - -export default NavPanel; diff --git a/src/layouts/Navbar/items/menu/panel.tsx b/src/layouts/Navbar/items/menu/panel.tsx deleted file mode 100644 index 3296f8c..0000000 --- a/src/layouts/Navbar/items/menu/panel.tsx +++ /dev/null @@ -1,152 +0,0 @@ -import search_icon from '@/asset/img/search_icon.webp'; -import { useDebounce } from '@/hooks'; -import { Side_Margin, grayLight } from '@/styles/colors'; -import { ApplicationInfo } from '@/types'; -import { Drawer, TextField } from '@mui/material'; -import { styled } from '@mui/material/styles'; -import Image, { StaticImageData } from 'next/image'; -import { useRouter } from 'next/router'; -import React, { useCallback, useEffect, useState } from 'react'; -import MenuItem from './item'; - -export interface NavPanelProps { - open: boolean; - onClose?: () => void; - apps: ApplicationInfo[]; -} - -const PanelContent = styled('div')(() => ({ - display: 'flex', - flexDirection: 'column', - width: '100%', - padding: `${parseInt(Side_Margin) / 1.5}% ${Side_Margin}`, - paddingTop: `calc(${parseInt(Side_Margin) / 4}% + 64px)`, - justifyContent: 'flex-start', - gap: 20, -})); - -const Content = styled('div')(() => ({ - display: 'flex', - gap: 40, - flexWrap: 'wrap', - alignItems: 'stretch', -})); - -export const Icon = ({ - style, - src, -}: { - style?: React.CSSProperties; - src: string | StaticImageData; -}) => { - return ( - search - ); -}; - -const ContentCard = styled('div')(() => ({ - flex: '0 0 220px', - padding: '12px 24px', - transition: 'background-color 0.2s linear', - '&:hover': { - backgroundColor: grayLight, - transition: 'background-color 0.2s linear', - }, -})); - -const NavPanel: React.FC = (props) => { - const { open, onClose, apps } = props; - const [menuContent, setMenuContent] = useState(apps ?? []); - const [input, setInput] = useState(''); - const router = useRouter(); - const debounceInput = useDebounce(input, 500); - - const handleSearch = useCallback( - (search: string) => { - if (apps && search.length > 0) { - const data = JSON.parse(JSON.stringify(apps)) as ApplicationInfo[]; - const searchResult = data?.filter((item) => item.name.includes(search)); - setMenuContent([...searchResult]); - } else { - setMenuContent(apps); - } - }, - [apps] - ); - - const handleSetInput = useCallback((event: React.ChangeEvent) => { - const target = event.target as HTMLInputElement; - const input = target?.value?.trim(); - setInput(input ?? ''); - }, []); - - const toWorkbench = useCallback( - (app: ApplicationInfo) => () => { - if (app?.scope) { - router.push(`/landing/${app?.scope}`); - } else { - router.push('/workbench'); - } - onClose?.(); - }, - [router, onClose] - ); - - useEffect(() => { - handleSearch(debounceInput); - }, [debounceInput, handleSearch]); - - return ( - - - - ), - }} - /> - - {menuContent?.map((item, index) => ( - - - - ))} - - - - ); -}; - -export default NavPanel; diff --git a/src/layouts/SideBar/components.tsx b/src/layouts/SideBar/components.tsx new file mode 100644 index 0000000..0ab79a7 --- /dev/null +++ b/src/layouts/SideBar/components.tsx @@ -0,0 +1,20 @@ +import { defaultText, grayBg, grayBorder, grayText } from '@/constant'; +import { Box, Stack } from '@mui/material'; +import { styled } from '@mui/material/styles'; + +export const IssueIconWrap = styled(Stack)(() => ({ + background: 'linear-gradient(180deg, rgba(255, 182, 85, 0.2) 0%, rgba(255, 58, 116, 0.2) 100%)', + filter: 'blur(1px)', + width: '14px', + height: '14px', + borderRadius: '50%', + justifyContent: 'center', + alignItems: 'center', + marginLeft: 'auto', +})); +export const IssueIcon = styled(Box)(() => ({ + width: '8px', + height: '8px', + borderRadius: '50%', + background: 'linear-gradient(141deg, #FFB655 0%, #FF3A74 100%)', +})); diff --git a/src/layouts/SideBar/index.tsx b/src/layouts/SideBar/index.tsx new file mode 100644 index 0000000..5dc185d --- /dev/null +++ b/src/layouts/SideBar/index.tsx @@ -0,0 +1,47 @@ +import { grayText } from '@/constant/color'; +import { AnchorContext } from '@/hooks/useAnchor'; +import { allTags } from '@/utils/tags'; +import { + Box, + Button, + Link, + Paper, + Stack, + Typography +} from '@mui/material'; +import Image from 'next/image'; +import React, { useContext, useEffect, useState } from 'react'; + +const SideBar: React.FC<{}> = () => { + const { anchor } = useContext(AnchorContext) + const [checkAnchor, setChectAnchor] = useState('') + useEffect(() => { + setChectAnchor(anchor) + }, [anchor]) + return ( + + + {allTags.map(item => + setChectAnchor(item.name)} href={'/tools#' + item.name} sx={{ alignSelf: 'stretch' }} className='custom-link'> + + + )} + + + ); +}; + +export default SideBar; diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index d6e40c1..320eec4 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -7,11 +7,19 @@ import '@/styles/static/swiper.css'; import theme from '@/styles/theme'; import createEmotionCache from '@/utils/emotionCache'; import { CacheProvider } from '@emotion/react'; -import { ThemeProvider } from '@mui/material'; +import { Box, Stack, ThemeProvider } from '@mui/material'; import CssBaseline from '@mui/material/CssBaseline'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import PropTypes from 'prop-types'; +import Header from '@/layouts/Header'; +import SideBar from '@/layouts/SideBar'; +import { LikeContextProvider } from '@/hooks/useLikeList'; +import { AnchorContextProvider } from '@/hooks/useAnchor'; +import { usePath } from '@/hooks'; +import { useMemo } from 'react'; +import { allTools } from '@/utils/tools'; +import Head from 'next/head'; const clientSideEmotionCache = createEmotionCache(); @@ -19,24 +27,45 @@ const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false, refetchOnWindowFocus: false } }, }); + export default function App({ Component, emotionCache = clientSideEmotionCache, }: any) { + const { path } = usePath() + + const currentItem = useMemo(() => { + return allTools.find(item => item.path === path) + }, [path]) return ( <> - - - + + + + + + + + - - - - - + + + + +
+ + + + + + + + + + ); } diff --git a/src/pages/aes.tsx b/src/pages/aes.tsx index 02f3284..fc40a3a 100644 --- a/src/pages/aes.tsx +++ b/src/pages/aes.tsx @@ -101,7 +101,7 @@ const AES: React.FC = () => { gap: '18px', maxWidth: '1020px', fontFamily: 'Mono', - width: '838px', + mx: 'auto', }} > diff --git a/src/pages/ascii.tsx b/src/pages/ascii.tsx index b1f107e..f5f0bea 100644 --- a/src/pages/ascii.tsx +++ b/src/pages/ascii.tsx @@ -112,7 +112,7 @@ const Hash: React.FC = () => { gap: '18px', maxWidth: '1020px', fontFamily: 'Mono', - width: '838px', + mx: 'auto', }} > diff --git a/src/pages/base64.tsx b/src/pages/base64.tsx index c46dbdb..124bce2 100644 --- a/src/pages/base64.tsx +++ b/src/pages/base64.tsx @@ -66,9 +66,9 @@ const Base64: React.FC = () => { sx={{ mt: '24px', gap: '18px', - maxWidth: '1020px', + // maxWidth: '1020px', fontFamily: 'Mono', - width: '838px', + mx: 'auto', }} > diff --git a/src/pages/case_convert.tsx b/src/pages/case_convert.tsx index 1c7f6cf..ed66d6c 100644 --- a/src/pages/case_convert.tsx +++ b/src/pages/case_convert.tsx @@ -16,7 +16,7 @@ const CaseConvert: React.FC = () => { gap: '18px', maxWidth: '1020px', fontFamily: 'Mono', - width: '838px', + mx: 'auto', }} > diff --git a/src/pages/hash.tsx b/src/pages/hash.tsx index 7ba6a68..4265836 100644 --- a/src/pages/hash.tsx +++ b/src/pages/hash.tsx @@ -85,7 +85,7 @@ const Hash: React.FC = () => { gap: '18px', maxWidth: '1020px', fontFamily: 'Mono', - width: '838px', + mx: 'auto', }} > diff --git a/src/pages/img2base64.tsx b/src/pages/img2base64.tsx index f8ed443..5796440 100644 --- a/src/pages/img2base64.tsx +++ b/src/pages/img2base64.tsx @@ -90,7 +90,7 @@ const ImgBase64: React.FC = () => { gap: '18px', maxWidth: '1020px', fontFamily: 'Mono', - width: '838px', + mx: 'auto', }} > diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 35e8521..844f1fe 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,3 +1,99 @@ -import Home from '@/components/Tools/home'; +import { + Avatar, + Box, + Card, + CardHeader, + Paper, + Stack, + Typography +} from '@mui/material'; -export default Home; +import LikeIcon from '@/components/LikeIcon'; +import { grayText2 } from '@/constant'; +import { LikeContext } from '@/hooks/useLikeList'; +import { Tag, Tags, allTags } from '@/utils/tags'; +import { Tool, allTools } from '@/utils/tools'; +import Image from 'next/image'; +import Link from 'next/link'; +import { useContext, useEffect, useMemo, useRef } from 'react'; + +import NoLike from '@/asset/tag/no_like.png'; +import { AnchorContext } from '@/hooks/useAnchor'; +import { ToolCard } from '@/components/ToolCard'; + +export default function App() { + const { updateAnchor } = useContext(AnchorContext) + const { likeList } = useContext(LikeContext) + const mainPageRef = useRef(null) + + useEffect(() => { + const handleScroll = () => { + if (!mainPageRef.current?.children) return + const scrollPosition = mainPageRef?.current.scrollTop; + for (let liElement of mainPageRef?.current.children) { + const liTop = liElement.offsetTop; + const liBottom = liTop + liElement.offsetHeight; + + if (scrollPosition >= liTop - 100 && scrollPosition < liBottom - 100) { + const liId = liElement.getAttribute('id'); + updateAnchor(liId) + break; + } + } + }; + mainPageRef.current?.addEventListener('scroll', handleScroll); + return () => { + mainPageRef.current?.removeEventListener('scroll', handleScroll); + updateAnchor('') + }; + }, []); + + const tagAndTools = useMemo(() => { + const addLikeTagForTools = allTools.map(item => { + if (likeList?.includes(item.path)) return ({ ...item, tags: [...item.tags, Tags.LIKE] }) + return item + }) + return allTags.map(tag => { + (tag as any).tools = addLikeTagForTools.filter(tool => tool.tags.includes(tag.name)) + return tag + }) + }, [likeList]) + + return ( + + { + tagAndTools.map(tag => ( + + {tag.label} + + { + ((tag as any).tools.length ? + (tag as any).tools.map((tool: any) => ( + + + + + + )) : + no_like + ) + } + + + ) + ) + } + + ); +} diff --git a/src/pages/jsontocsv.tsx b/src/pages/jsontocsv.tsx index a07398b..5da4fde 100644 --- a/src/pages/jsontocsv.tsx +++ b/src/pages/jsontocsv.tsx @@ -136,7 +136,7 @@ const JSONToCSV = () => { gap: '18px', maxWidth: '1020px', fontFamily: 'Mono', - width: '838px', + mx: 'auto', '.rc-table': { border: '1px solid #eee', diff --git a/src/pages/radix_convert.tsx b/src/pages/radix_convert.tsx index fb93db6..7ba05d0 100644 --- a/src/pages/radix_convert.tsx +++ b/src/pages/radix_convert.tsx @@ -146,7 +146,7 @@ const RadixConvert: React.FC = () => { gap: '18px', maxWidth: '1020px', fontFamily: 'Mono', - width: '838px', + mx: 'auto', }} > diff --git a/src/pages/random.tsx b/src/pages/random.tsx index 92683e2..eb3fb8f 100644 --- a/src/pages/random.tsx +++ b/src/pages/random.tsx @@ -107,8 +107,8 @@ const Random: React.FC = () => { return ( - - + +
diff --git a/src/pages/uncolor.tsx b/src/pages/uncolor.tsx index 55cc0e7..746578a 100644 --- a/src/pages/uncolor.tsx +++ b/src/pages/uncolor.tsx @@ -96,7 +96,7 @@ const ImgBase64: React.FC = () => { gap: '18px', maxWidth: '1020px', fontFamily: 'Mono', - width: '838px', + mx: 'auto', }} > diff --git a/src/pages/unix.tsx b/src/pages/unix.tsx index 192e5a7..9b77bbc 100644 --- a/src/pages/unix.tsx +++ b/src/pages/unix.tsx @@ -237,7 +237,7 @@ const Unix: React.FC = () => { > { diff --git a/src/pages/urlencoder.tsx b/src/pages/urlencoder.tsx index 6cc0733..837f1f0 100644 --- a/src/pages/urlencoder.tsx +++ b/src/pages/urlencoder.tsx @@ -63,7 +63,7 @@ const URLEncoder: React.FC = () => { gap: '18px', maxWidth: '1020px', fontFamily: 'Mono', - width: '838px', + mx: 'auto', }} > diff --git a/src/pages/word_count.tsx b/src/pages/word_count.tsx index 9233c37..87dce16 100644 --- a/src/pages/word_count.tsx +++ b/src/pages/word_count.tsx @@ -94,7 +94,7 @@ const WordCount: React.FC = () => { gap: '18px', maxWidth: '1020px', fontFamily: 'Mono', - width: '838px', + mx: 'auto', }} > diff --git a/src/styles/colors.ts b/src/styles/colors.ts index 56bac18..4ba72cc 100644 --- a/src/styles/colors.ts +++ b/src/styles/colors.ts @@ -1,4 +1,4 @@ -export const primary = '#52C41A'; +export const primary = 'rgba(52, 90, 255, 1)'; export const primaryHover = '#73D13C'; export const primaryClick = '#389E0E'; @@ -10,7 +10,7 @@ export const secondary = '#ECF9E6'; export const secondaryHover = '#F3FDEE'; export const secondaryClick = '#DAE8D4'; -export const special = 'linear-gradient(270deg, #11AF60 0%, #52C41A 100%)'; +export const special = 'linear-gradient(270deg, #11AF60 0%, rgba(52, 90, 255, 1) 100%)'; export const dangerHover = 'linear-gradient(225deg, #FF1F1F 0%, #F78900 100%)'; export const disabled = '#F7F7F7'; @@ -31,7 +31,7 @@ export const leastTextClick = '#737373'; export const disabledText = '#BFBFBF'; export const specialText = '#737971'; -export const success = '#52C41A'; +export const success = 'rgba(52, 90, 255, 1)'; export const warning = '#FFBF00'; export const error = '#FF1F1F'; diff --git a/src/styles/global.css b/src/styles/global.css index 2eac3a1..30a0b58 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -4,7 +4,7 @@ #SM_BTN_1 { width: auto !important; - background-color: #52c41a !important; + background-color: rgba(52, 90, 255, 1) !important; } .sm-txt { @@ -36,4 +36,12 @@ body, html { overflow: auto !important; + background: rgba(247, 249, 252, 1); } + +@font-face { + font-family: "Mono"; + font-weight: 250; + src: url('/Mono.ttf') format("truetype"); + font-display: swap; +} \ No newline at end of file diff --git a/src/styles/static/slick-theme.css b/src/styles/static/slick-theme.css index 3ec2a3b..1b9195b 100644 --- a/src/styles/static/slick-theme.css +++ b/src/styles/static/slick-theme.css @@ -181,5 +181,5 @@ } .slick-dots li.slick-active button:before { opacity: 1; - color: #52c41aff; + color: rgba(52, 90, 255, 1)ff; } diff --git a/src/utils/tags.ts b/src/utils/tags.ts new file mode 100644 index 0000000..c2ae9af --- /dev/null +++ b/src/utils/tags.ts @@ -0,0 +1,74 @@ + +import icon_encode from '@/asset/tag/encode.svg'; +import icon_encode_check from '@/asset/tag/encode_check.svg'; +import icon_encryption from '@/asset/tag/encryption.svg'; +import icon_encryption_check from '@/asset/tag/encryption_check.svg'; +import icon_hot from '@/asset/tag/hot.svg'; +import icon_hot_check from '@/asset/tag/hot_check.svg'; +import icon_like from '@/asset/tag/like.svg'; +import icon_like_check from '@/asset/tag/like_check.svg'; +import icon_text from '@/asset/tag/text.svg'; +import icon_text_check from '@/asset/tag/text_check.svg'; +import dev from '@/asset/tag/dev.svg'; +import dev_check from '@/asset/tag/dev_check.svg'; +import other from '@/asset/tag/other.svg'; +import other_check from '@/asset/tag/other_check.svg'; +import json from '@/asset/tag/json.svg'; +import json_check from '@/asset/tag/json_check.svg'; + +export enum Tags { + CODE = 'code', + TEXT = 'text', + DEV = 'dev', + PASSWORD = 'password', + JSON = 'json', + OTHER = 'other', + HOT = 'hot', + LIKE = 'like', +} +const tagColor = [ + ['rgba(245, 117, 130, 1)', 'rgba(245, 117, 130, 0.2)',], + ['rgba(17, 35, 90, 1)', 'rgba(17, 35, 90, 0.2)',], + ['rgba(117, 106, 182, 1)', 'rgba(117, 106, 182, 0.2)',], + ['rgba(123, 211, 234, 1)', 'rgba(123, 211, 234, 0.2)',], + ['rgba(125, 10, 10, 1)', 'rgba(125, 10, 10, 0.2)',], + ['rgba(95, 134, 112, 1)', 'rgba(95, 134, 112, 0.2)',], + ['rgba(57, 36, 103, 1)', 'rgba(57, 36, 103, 0.2)',], + ['rgba(89, 111, 183, 1)', 'rgba(89, 111, 183, 0.2)',], + ['rgba(172, 135, 197, 1)', 'rgba(172, 135, 197, 0.2)',], + ['rgba(191, 49, 49, 1)', 'rgba(191, 49, 49, 0.2)',], + ['rgba(56, 135, 190, 1)', 'rgba(56, 135, 190, 0.2)',], + ['rgba(255, 152, 0, 1)', 'rgba(255, 152, 0, 0.2)',], + ['rgba(93, 53, 135, 1)', 'rgba(93, 53, 135, 0.2)',], + ['rgba(198, 207, 155, 1)', 'rgba(198, 207, 155, 0.2)',], + ['rgba(184, 0, 0, 1)', 'rgba(184, 0, 0, 0.2)',], + ['rgba(56, 65, 157, 1)', 'rgba(56, 65, 157, 0.2)',], + ['rgba(205, 141, 122, 1)', 'rgba(205, 141, 122, 0.2)',], + ['rgba(255, 214, 102, 1)', 'rgba(255, 214, 102, 0.2)',], + ['rgba(248, 141, 72, 1)', 'rgba(248, 141, 72, 0.2)',], + ['rgba(184, 137, 234, 1)', 'rgba(184, 137, 234, 0.2)',], + ['rgba(242, 115, 181, 1)', 'rgba(242, 115, 181, 0.2)',], + ['rgba(69, 218, 209, 1)', 'rgba(69, 218, 209, 0.2)',], + ['rgba(64, 169, 255, 1)', 'rgba(64, 169, 255, 0.2)',], + ['rgba(200, 167, 134, 1)', 'rgba(200, 167, 134, 0.2)',], +] + +export type Tag = { + name: Tags, icon: string, icon_check: string, label: string, bg_color: string, avatar_color: string +} +export const allTags: Tag[] = [ + { name: Tags.HOT, icon: icon_hot, icon_check: icon_hot_check, label: '热门工具', bg_color: '', avatar_color: '' }, + { name: Tags.LIKE, icon: icon_like, icon_check: icon_like_check, label: '我的收藏', bg_color: '', avatar_color: '' }, + { name: Tags.CODE, icon: icon_encode, icon_check: icon_encode_check, label: '编码转码', bg_color: '', avatar_color: '' }, + { name: Tags.DEV, icon: dev, icon_check: dev_check, label: '开发', bg_color: '', avatar_color: '' }, + { name: Tags.TEXT, icon: icon_text, icon_check: icon_text_check, label: '文字处理', bg_color: '', avatar_color: '' }, + { name: Tags.PASSWORD, icon: icon_encryption, icon_check: icon_encryption_check, label: '密码学', bg_color: '', avatar_color: '' }, + { name: Tags.JSON, icon: json, icon_check: json_check, label: 'JSON', bg_color: '', avatar_color: '' }, + { name: Tags.OTHER, icon: other, icon_check: other_check, label: '杂项', bg_color: '', avatar_color: '' }, +].map((item, index) => { + const [avatarColor, bgColor] = tagColor[index] + item.bg_color = bgColor + item.avatar_color = avatarColor + return item +}); + diff --git a/src/utils/tools.ts b/src/utils/tools.ts index 4fc4f49..4554c1d 100644 --- a/src/utils/tools.ts +++ b/src/utils/tools.ts @@ -1,52 +1,33 @@ -import OtherIcon from '@mui/icons-material/AutoAwesome'; -import CodeIcon from '@mui/icons-material/Code'; -import DataArrayIcon from '@mui/icons-material/DataArray'; -import DeveloperModeIcon from '@mui/icons-material/DeveloperMode'; -import LockIcon from '@mui/icons-material/Lock'; -import TextSnippetIcon from '@mui/icons-material/TextSnippet'; - -export enum Tags { - CODE = 'code', - TEXT = 'text', - DEV = 'dev', - PASSWORD = 'password', - JSON = 'json', - OTHER = 'other', -} - -export const AllTags = [ - { name: Tags.CODE, icon: CodeIcon, label: '编码转码' }, - { name: Tags.DEV, icon: DeveloperModeIcon, label: '开发' }, - { name: Tags.TEXT, icon: TextSnippetIcon, label: '文字处理' }, - { name: Tags.PASSWORD, icon: LockIcon, label: '密码学' }, - { name: Tags.JSON, icon: DataArrayIcon, label: 'JSON' }, - { name: Tags.OTHER, icon: OtherIcon, label: '杂项' }, -]; +import { Tags } from "./tags"; export type Tool = { label: string; tags: Tags[]; path: string; subTitle: string; + key: string[] }; -export const routesMenu: Tool[] = [ +export const allTools: Tool[] = [ { label: 'URL 编解码', tags: [Tags.CODE], path: '/urlencoder', + key: [], subTitle: 'URL 编码解码小工具。', }, { label: 'Base64 编解码', - tags: [Tags.CODE], + tags: [Tags.CODE, Tags.HOT], path: '/base64', + key: [], subTitle: 'Base64 编码解码小工具。', }, { label: '图片转 Base64', tags: [Tags.CODE], path: '/img2base64', + key: [], subTitle: '图片的 BASE64 编码就是将图片数据编码成字符串,使用该字符串代替图片地址,从而不需要使用图片的 URL 地址。', }, @@ -54,6 +35,7 @@ export const routesMenu: Tool[] = [ label: '进制转换', tags: [Tags.CODE], path: '/radix_convert', + key: [], subTitle: '进制转换小工具,支持二进制、八进制、十进制、十六进制等之间的互相转换。', }, @@ -61,18 +43,21 @@ export const routesMenu: Tool[] = [ label: '字数统计', tags: [Tags.TEXT], path: '/word_count', + key: [], subTitle: '字数统计小工具,支持中文、英文、数字、标点符号等的统计。', }, { label: '大小写转换', tags: [Tags.TEXT], path: '/case_convert', + key: [], subTitle: '大小写转换小工具,支持大写、小写、首字母大写、大小写互转等。', }, { label: 'Unix 时间戳转换', - tags: [Tags.DEV], + tags: [Tags.DEV, Tags.HOT], path: '/unix', + key: [], subTitle: 'Unix 时间戳是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数,不考虑闰秒。', }, @@ -80,37 +65,43 @@ export const routesMenu: Tool[] = [ label: 'ASCII 码表', tags: [Tags.DEV], path: '/ascii', + key: [], subTitle: 'ASCII 码查询表。', }, { label: '密码哈希', tags: [Tags.PASSWORD], path: '/hash', + key: [], subTitle: '在线 MD5,SHA256 哈希算法计算小工具。', }, { label: 'AES 加解密', tags: [Tags.PASSWORD], path: '/aes', + key: [], subTitle: '在线 AES 算法加解密工具。', }, { label: 'JSON 转 CSV', tags: [Tags.JSON], path: '/jsontocsv', + key: [], subTitle: 'JSON 转 CSV 和 EXCEL 小工具。', }, { label: '随机数/密码生成', - tags: [Tags.OTHER], + tags: [Tags.OTHER, Tags.HOT], path: '/random', + key: [], subTitle: '该功能由浏览器在本地完成,您的任何输入都不会提交到服务端。', }, { label: '图片去色', tags: [Tags.OTHER], path: '/uncolor', + key: [], subTitle: '将彩色图片转换为黑白图片', }, ];