Showing
31 changed files
with
1171 additions
and
0 deletions
.eslintrc.cjs
0 → 100644
1 | +module.exports = { | ||
2 | + root: true, | ||
3 | + env: { browser: true, es2020: true }, | ||
4 | + extends: [ | ||
5 | + 'eslint:recommended', | ||
6 | + 'plugin:@typescript-eslint/recommended', | ||
7 | + 'plugin:react-hooks/recommended', | ||
8 | + ], | ||
9 | + ignorePatterns: ['dist', '.eslintrc.cjs'], | ||
10 | + parser: '@typescript-eslint/parser', | ||
11 | + plugins: ['react-refresh'], | ||
12 | + rules: { | ||
13 | + 'react-refresh/only-export-components': [ | ||
14 | + 'warn', | ||
15 | + { allowConstantExport: true }, | ||
16 | + ], | ||
17 | + }, | ||
18 | +} |
README.md
0 → 100644
1 | +# React + TypeScript + Vite | ||
2 | + | ||
3 | +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. | ||
4 | + | ||
5 | +Currently, two official plugins are available: | ||
6 | + | ||
7 | +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh | ||
8 | +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh | ||
9 | + | ||
10 | +## Expanding the ESLint configuration | ||
11 | + | ||
12 | +If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: | ||
13 | + | ||
14 | +- Configure the top-level `parserOptions` property like this: | ||
15 | + | ||
16 | +```js | ||
17 | +export default tseslint.config({ | ||
18 | + languageOptions: { | ||
19 | + // other options... | ||
20 | + parserOptions: { | ||
21 | + project: ['./tsconfig.node.json', './tsconfig.app.json'], | ||
22 | + tsconfigRootDir: import.meta.dirname, | ||
23 | + }, | ||
24 | + }, | ||
25 | +}) | ||
26 | +``` | ||
27 | + | ||
28 | +- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked` | ||
29 | +- Optionally add `...tseslint.configs.stylisticTypeChecked` | ||
30 | +- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config: | ||
31 | + |
index.html
0 → 100644
1 | +<!doctype html> | ||
2 | +<html lang="en"> | ||
3 | + <head> | ||
4 | + <meta charset="UTF-8" /> | ||
5 | + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
6 | + <title></title> | ||
7 | + <link rel="icon" href="./seat_logo.png" type="image/x-icon" /> | ||
8 | + </head> | ||
9 | + <body> | ||
10 | + <div id="root"></div> | ||
11 | + <script type="module" src="/src/main.tsx"></script> | ||
12 | + </body> | ||
13 | +</html> |
package.json
0 → 100644
1 | +{ | ||
2 | + "name": "sxjx-h5", | ||
3 | + "private": true, | ||
4 | + "version": "0.0.0", | ||
5 | + "type": "module", | ||
6 | + "scripts": { | ||
7 | + "dev": "vite", | ||
8 | + "build": "tsc -b && vite build", | ||
9 | + "lint": "eslint .", | ||
10 | + "preview": "vite preview" | ||
11 | + }, | ||
12 | + "dependencies": { | ||
13 | + "antd-mobile": "^5.38.1", | ||
14 | + "antd-mobile-icons": "^0.3.0", | ||
15 | + "axios": "^1.7.9", | ||
16 | + "react": "^18.3.1", | ||
17 | + "react-dom": "^18.3.1", | ||
18 | + "react-router-dom": "^7.1.1" | ||
19 | + }, | ||
20 | + "devDependencies": { | ||
21 | + "@eslint/js": "^9.17.0", | ||
22 | + "@types/node": "^22.10.5", | ||
23 | + "@types/react": "^18.3.18", | ||
24 | + "@types/react-dom": "^18.3.5", | ||
25 | + "@vitejs/plugin-react": "^4.3.4", | ||
26 | + "eslint": "^9.17.0", | ||
27 | + "eslint-plugin-react-hooks": "^5.0.0", | ||
28 | + "eslint-plugin-react-refresh": "^0.4.16", | ||
29 | + "globals": "^15.14.0", | ||
30 | + "less": "^4.2.1", | ||
31 | + "less-loader": "^12.2.0", | ||
32 | + "postcss-px-to-viewport": "^1.1.1", | ||
33 | + "typescript": "~5.6.2", | ||
34 | + "typescript-eslint": "^8.18.2", | ||
35 | + "vite": "^5.3.4" | ||
36 | + } | ||
37 | +} |
public/seat_logo.png
0 → 100644
190 Bytes
public/vite.svg
0 → 100644
1 | +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg> |
src/assets/react.svg
0 → 100644
1 | +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg> |
src/components/nav-bar/back_icon_b.png
0 → 100644
681 Bytes
src/components/nav-bar/back_icon_w.png
0 → 100644
512 Bytes
src/components/nav-bar/index.less
0 → 100644
1 | +.nav-bar-box { | ||
2 | + position: fixed; | ||
3 | + top: 0; | ||
4 | + left: 0; | ||
5 | + right: 0; | ||
6 | + height: calc( | ||
7 | + 88px + constant(safe-area-inset-top) | ||
8 | + ); /* 直接扩展高度,因为padding-bottom是内边距 */ | ||
9 | + height: calc(88px + env(safe-area-inset-top)); /* 直接扩展高度 */ | ||
10 | + padding-top: constant(safe-area-inset-top); /*兼容 iOS<11.2 */ | ||
11 | + padding-top: env(safe-area-inset-top); /* 兼容iOS>= 11.2*/ | ||
12 | + background: #fff; | ||
13 | + z-index: 98; | ||
14 | + .adm-nav-bar { | ||
15 | + height: 88px; | ||
16 | + padding: 0 12px; | ||
17 | + .adm-nav-bar-left { | ||
18 | + .adm-nav-bar-back { | ||
19 | + padding: 0; | ||
20 | + .back-icon { | ||
21 | + display: block; | ||
22 | + width: 48px; | ||
23 | + height: 48px; | ||
24 | + background: url('./back_icon_b.png') center center no-repeat; | ||
25 | + background-size: cover; | ||
26 | + &.white { | ||
27 | + background: url('./back_icon_w.png') center center no-repeat; | ||
28 | + background-size: cover; | ||
29 | + } | ||
30 | + } | ||
31 | + .custom-icon { | ||
32 | + width: 16px; | ||
33 | + height: 16px; | ||
34 | + font-size: 16px; | ||
35 | + } | ||
36 | + } | ||
37 | + } | ||
38 | + .adm-nav-bar-title { | ||
39 | + font-size: 32px; | ||
40 | + color: #242835; | ||
41 | + text-align: center; | ||
42 | + font-weight: 600; | ||
43 | + } | ||
44 | + .adm-nav-bar-right { | ||
45 | + } | ||
46 | + } | ||
47 | +} | ||
48 | + | ||
49 | +.sx-fixed-back { | ||
50 | + position: fixed; | ||
51 | + right: 15px; | ||
52 | + bottom: 210px; | ||
53 | + z-index: 999; // 不被其它dom覆盖 | ||
54 | + width: 52px; | ||
55 | + height: 52px; | ||
56 | + display: flex; | ||
57 | + align-items: center; | ||
58 | + justify-content: center; | ||
59 | + border-radius: 50%; | ||
60 | + .icon-fixed-back { | ||
61 | + width: 22px; | ||
62 | + height: 22px; | ||
63 | + } | ||
64 | +} | ||
65 | + | ||
66 | +.sx-left-bottom { | ||
67 | + position: fixed; | ||
68 | + width: 214px; | ||
69 | + height: 214px; | ||
70 | + left: -107px; | ||
71 | + bottom: -107px; | ||
72 | + border-radius: 50%; | ||
73 | + z-index: 999; | ||
74 | + text-align: right; | ||
75 | + | ||
76 | + &_wrap { | ||
77 | + display: inline-block; | ||
78 | + margin: 40px 53px 0 0; | ||
79 | + text-align: center; | ||
80 | + //border: 1px solid red; | ||
81 | + | ||
82 | + &__icon { | ||
83 | + width: 18px; | ||
84 | + height: 18px; | ||
85 | + color: #fff; | ||
86 | + } | ||
87 | + | ||
88 | + &__text { | ||
89 | + color: #fff; | ||
90 | + } | ||
91 | + } | ||
92 | + | ||
93 | + &_wrapFocus { | ||
94 | + .sx-left-bottom_wrap__icon, | ||
95 | + .sx-left-bottom_wrap__text { | ||
96 | + color: #3499ff; | ||
97 | + } | ||
98 | + } | ||
99 | +} | ||
100 | + | ||
101 | +.sx-left-center { | ||
102 | + position: fixed; | ||
103 | + width: 24px; | ||
104 | + height: 52px; | ||
105 | + bottom: 120px; | ||
106 | + border-radius: 0 52px 52px 0; | ||
107 | + background: rgba(52, 153, 255, 0.1); | ||
108 | + z-index: 999; | ||
109 | + text-align: right; | ||
110 | + | ||
111 | + &_wrap { | ||
112 | + display: inline-block; | ||
113 | + color: #3a9cfe; | ||
114 | + margin: 15px 10px 0 0; | ||
115 | + transform: scale(1.4); | ||
116 | + } | ||
117 | +} |
src/components/nav-bar/index.tsx
0 → 100644
1 | +import React, { useEffect } from 'react'; | ||
2 | +import { NavBar } from 'antd-mobile'; | ||
3 | +import './index.less'; | ||
4 | +import { useNavigate } from 'react-router-dom'; | ||
5 | + | ||
6 | +interface NavBarProps { | ||
7 | + rightInfo?: any; | ||
8 | + showBack?: any; | ||
9 | + title?: any; | ||
10 | + isWhite?: any; // 是否是白色返回箭头 | ||
11 | + style?: any; | ||
12 | + backContent?: any; | ||
13 | + hiddenHead?: boolean; | ||
14 | + customBack?: { | ||
15 | + icon: any; | ||
16 | + onClick: () => void; | ||
17 | + }; | ||
18 | +} | ||
19 | + | ||
20 | +const NavBarSec: React.FC<NavBarProps> = (props) => { | ||
21 | + const navigate = useNavigate(); | ||
22 | + // @ts-ignore | ||
23 | + const title = props?.title || ''; | ||
24 | + const backContent = props?.backContent || ''; | ||
25 | + const right = props?.rightInfo; | ||
26 | + const showBack = props?.showBack; | ||
27 | + | ||
28 | + const style = props?.style; | ||
29 | + | ||
30 | + | ||
31 | + const back = () => { | ||
32 | + navigate(-1); // 回退到上一个页面 | ||
33 | + }; | ||
34 | + | ||
35 | + useEffect(() => { | ||
36 | + //放入回调函数中请自行取掉setTimeout | ||
37 | + setTimeout(function () { | ||
38 | + // 兼容微信浏览器更新title | ||
39 | + //利用iframe的onload事件刷新页面 | ||
40 | + document.title = title; | ||
41 | + const iframe = document.createElement('iframe'); | ||
42 | + iframe.style.visibility = 'hidden'; | ||
43 | + iframe.style.width = '1px'; | ||
44 | + iframe.style.height = '1px'; | ||
45 | + iframe.onload = function () { | ||
46 | + setTimeout(function () { | ||
47 | + document.body.removeChild(iframe); | ||
48 | + }, 0); | ||
49 | + }; | ||
50 | + document.body.appendChild(iframe); | ||
51 | + }, 0); | ||
52 | + | ||
53 | + }, [title]); | ||
54 | + | ||
55 | + // @ts-ignore | ||
56 | + return <div className={'nav-bar-box'}> | ||
57 | + <NavBar | ||
58 | + backArrow={ | ||
59 | + props.customBack?.icon ? ( | ||
60 | + <i className={'custom-icon'}>{props.customBack?.icon}</i> | ||
61 | + ) : showBack ? ( | ||
62 | + <i className={`back-icon ${props?.isWhite ? 'white' : ''}`} /> | ||
63 | + ) : '' | ||
64 | + } | ||
65 | + onBack={props.customBack?.onClick || back} | ||
66 | + right={right} | ||
67 | + style={style} | ||
68 | + back={backContent} | ||
69 | + > | ||
70 | + {title} | ||
71 | + </NavBar> | ||
72 | + </div>; | ||
73 | +}; | ||
74 | + | ||
75 | +export default NavBarSec; |
src/index.less
0 → 100644
1 | +:root { | ||
2 | + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; | ||
3 | + line-height: 1.5; | ||
4 | + font-weight: 400; | ||
5 | + | ||
6 | + color-scheme: light dark; | ||
7 | + color: rgba(255, 255, 255, 0.87); | ||
8 | + background-color: #242424; | ||
9 | + | ||
10 | + font-synthesis: none; | ||
11 | + text-rendering: optimizeLegibility; | ||
12 | + -webkit-font-smoothing: antialiased; | ||
13 | + -moz-osx-font-smoothing: grayscale; | ||
14 | +} | ||
15 | + | ||
16 | +a { | ||
17 | + font-weight: 500; | ||
18 | + color: #646cff; | ||
19 | + text-decoration: inherit; | ||
20 | +} | ||
21 | +a:hover { | ||
22 | + color: #535bf2; | ||
23 | +} | ||
24 | + | ||
25 | +body { | ||
26 | + margin: 0; | ||
27 | + min-height: 100vh; | ||
28 | + background: pink; | ||
29 | +} | ||
30 | + | ||
31 | +h1 { | ||
32 | + font-size: 3.2em; | ||
33 | + line-height: 1.1; | ||
34 | +} | ||
35 | + | ||
36 | +p { | ||
37 | + margin: 0; | ||
38 | +} | ||
39 | + | ||
40 | +button { | ||
41 | + border-radius: 8px; | ||
42 | + border: 1px solid transparent; | ||
43 | + padding: 0.6em 1.2em; | ||
44 | + font-size: 1em; | ||
45 | + font-weight: 500; | ||
46 | + font-family: inherit; | ||
47 | + background-color: #1a1a1a; | ||
48 | + cursor: pointer; | ||
49 | + transition: border-color 0.25s; | ||
50 | +} | ||
51 | +button:hover { | ||
52 | + border-color: #646cff; | ||
53 | +} | ||
54 | +button:focus, | ||
55 | +button:focus-visible { | ||
56 | + outline: 4px auto -webkit-focus-ring-color; | ||
57 | +} | ||
58 | + | ||
59 | +@media (prefers-color-scheme: light) { | ||
60 | + :root { | ||
61 | + color: #213547; | ||
62 | + background-color: #ffffff; | ||
63 | + } | ||
64 | + a:hover { | ||
65 | + color: #747bff; | ||
66 | + } | ||
67 | + button { | ||
68 | + background-color: #f9f9f9; | ||
69 | + } | ||
70 | +} | ||
71 | + | ||
72 | +#root { | ||
73 | + background: #fff; | ||
74 | +} | ||
75 | + | ||
76 | +/* Webkit 浏览器(Chrome, Safari, Edge) */ | ||
77 | +::-webkit-scrollbar { | ||
78 | + width: 5px; /* 或者 height: 12px; 对于水平滚动条 */ | ||
79 | +} | ||
80 | + | ||
81 | +::-webkit-scrollbar-thumb { | ||
82 | + background-color: #1D295B; /* 滚动条的颜色 */ | ||
83 | + border-radius: 6px; /* 滚动条的圆角 */ | ||
84 | +} | ||
85 | + | ||
86 | + | ||
87 | +::-webkit-scrollbar-track { | ||
88 | + background-color: #314484; /* 滚动条轨道的颜色 */ | ||
89 | + border-radius: 6px; /* 轨道的圆角 */ | ||
90 | +} | ||
91 | + | ||
92 | + | ||
93 | +// 一行省略 | ||
94 | +.omit1 { | ||
95 | + word-break: break-all; | ||
96 | + text-overflow: ellipsis; | ||
97 | + display: -webkit-box; | ||
98 | + -webkit-box-orient: vertical; | ||
99 | + -webkit-line-clamp: 1; | ||
100 | + overflow: hidden; | ||
101 | + overflow-wrap:break-word; | ||
102 | + word-break: break-all; | ||
103 | +} | ||
104 | + | ||
105 | +// 两行省略 | ||
106 | +.omit2 { | ||
107 | + word-break: break-all; | ||
108 | + text-overflow: ellipsis; | ||
109 | + display: -webkit-box; | ||
110 | + -webkit-box-orient: vertical; | ||
111 | + -webkit-line-clamp: 2; | ||
112 | + overflow: hidden; | ||
113 | + overflow-wrap:break-word; | ||
114 | + word-break: break-all; | ||
115 | +} | ||
116 | + | ||
117 | +// 三行省略 | ||
118 | +.omit3 { | ||
119 | + overflow: hidden; | ||
120 | + text-overflow: ellipsis; | ||
121 | + display: -webkit-box; | ||
122 | + -webkit-line-clamp: 3; | ||
123 | + -webkit-box-orient: vertical; | ||
124 | + overflow-wrap:break-word; | ||
125 | + word-break: break-all; | ||
126 | +} | ||
127 | +//四行省略 | ||
128 | +.omit4 { | ||
129 | + overflow: hidden; | ||
130 | + text-overflow: ellipsis; | ||
131 | + display: -webkit-box; | ||
132 | + -webkit-line-clamp: 4; | ||
133 | + -webkit-box-orient: vertical; | ||
134 | + overflow-wrap:break-word; | ||
135 | + word-break: break-all; | ||
136 | +} | ||
137 | + | ||
138 | +//四行省略 | ||
139 | +.omit5 { | ||
140 | + overflow: hidden; | ||
141 | + text-overflow: ellipsis; | ||
142 | + display: -webkit-box; | ||
143 | + -webkit-line-clamp: 5; | ||
144 | + -webkit-box-orient: vertical; | ||
145 | + overflow-wrap:break-word; | ||
146 | + word-break: break-all; | ||
147 | +} | ||
148 | + | ||
149 | +// 六行省略 | ||
150 | +.omit6 { | ||
151 | + overflow: hidden; | ||
152 | + text-overflow: ellipsis; | ||
153 | + display: -webkit-box; | ||
154 | + -webkit-line-clamp: 6; | ||
155 | + -webkit-box-orient: vertical; | ||
156 | + overflow-wrap:break-word; | ||
157 | + word-break: break-all; | ||
158 | +} | ||
159 | + | ||
160 | +.sxjx-content-main { | ||
161 | + background: #f7f7f7; | ||
162 | + height: 100vh; | ||
163 | + width: 100vw; | ||
164 | + box-sizing: border-box; | ||
165 | +} | ||
166 | + | ||
167 | + | ||
168 | +// 有头部有底部 | ||
169 | +.sxjx-layout-main { | ||
170 | + padding-top: calc(88px + constant(safe-area-inset-top)); | ||
171 | + padding-top: calc(88px + env(safe-area-inset-top)); | ||
172 | + padding-bottom: calc(120px + constant(safe-area-inset-bottom)); | ||
173 | + padding-bottom: calc(120px + env(safe-area-inset-bottom)); | ||
174 | +} | ||
175 | + | ||
176 | +// 有头部没有底部 | ||
177 | +.sxjx-layout-main-unfoot { | ||
178 | + padding-top: calc(88px + constant(safe-area-inset-top)); | ||
179 | + padding-top: calc(88px + env(safe-area-inset-top)); | ||
180 | +} | ||
181 | + | ||
182 | +// 没有头部有底部 | ||
183 | +.sxjx-layout-main-unhead { | ||
184 | + padding-bottom: calc(120px + constant(safe-area-inset-bottom)); | ||
185 | + padding-bottom: calc(120px + env(safe-area-inset-bottom)); | ||
186 | +} |
src/main.tsx
0 → 100644
src/pages/errorPage.tsx
0 → 100644
1 | +import { useRouteError } from "react-router-dom"; | ||
2 | + | ||
3 | +export default function ErrorPage() { | ||
4 | + const error:any = useRouteError(); | ||
5 | + console.error(error); | ||
6 | + | ||
7 | + return ( | ||
8 | + <div id="error-page"> | ||
9 | + <h1>Oops!</h1> | ||
10 | + <p>Sorry, an unexpected error has occurred.</p> | ||
11 | + <p> | ||
12 | + <i>{error?.statusText || error?.message}</i> | ||
13 | + </p> | ||
14 | + </div> | ||
15 | + ); | ||
16 | +} |
src/pages/production-detail/index.tsx
0 → 100644
1 | +import React from 'react' | ||
2 | +import './style.less' | ||
3 | +import NavBar from '@/components/nav-bar' | ||
4 | +import {baseColorPrimary} from "@/utils/common"; | ||
5 | +import {hexToRgba} from "@/utils/utils"; | ||
6 | + | ||
7 | + | ||
8 | +const ProductionManagement: React.FC = () => { | ||
9 | + | ||
10 | + const list = [ | ||
11 | + { | ||
12 | + id: '1', | ||
13 | + name: '车顶生产线A' | ||
14 | + }, | ||
15 | + { | ||
16 | + id: '2', | ||
17 | + name: '车顶生产线B' | ||
18 | + }, | ||
19 | + { | ||
20 | + id: '3', | ||
21 | + name: '车顶生产线C' | ||
22 | + }, | ||
23 | + { | ||
24 | + id: '4', | ||
25 | + name: '车顶生产线D' | ||
26 | + }, | ||
27 | + { | ||
28 | + id: '5', | ||
29 | + name: '车顶生产线E' | ||
30 | + }, | ||
31 | + { | ||
32 | + id: '6', | ||
33 | + name: '车顶生产线F' | ||
34 | + }, | ||
35 | + { | ||
36 | + id: '7', | ||
37 | + name: '车顶生产线G' | ||
38 | + }, | ||
39 | + { | ||
40 | + id: '8', | ||
41 | + name: '车顶生产线H' | ||
42 | + }, | ||
43 | + { | ||
44 | + id: '9', | ||
45 | + name: '车顶生产线I' | ||
46 | + }, | ||
47 | + { | ||
48 | + id: '10', | ||
49 | + name: '车顶生产线J' | ||
50 | + }, | ||
51 | + { | ||
52 | + id: '11', | ||
53 | + name: '车顶生产线K' | ||
54 | + }, | ||
55 | + { | ||
56 | + id: '12', | ||
57 | + name: '车顶生车顶生车顶生产线L' | ||
58 | + }, | ||
59 | + { | ||
60 | + id: '13', | ||
61 | + name: '车顶生产线M' | ||
62 | + }, | ||
63 | + { | ||
64 | + id: '14', | ||
65 | + name: '车顶生产线N' | ||
66 | + } | ||
67 | + ] | ||
68 | + | ||
69 | + | ||
70 | + return ( | ||
71 | + <div className={'sxjx-content-main sxjx-layout-main-unfoot'}> | ||
72 | + <div className={'production-management'}> | ||
73 | + <NavBar title={'上产线管理'}/> | ||
74 | + <div className={'production-management_list'}> | ||
75 | + { | ||
76 | + list?.map((item: any) => { | ||
77 | + return <div | ||
78 | + key={item?.id} | ||
79 | + className={'production-management_list-item'} | ||
80 | + style={{backgroundColor: hexToRgba(baseColorPrimary, 0.6)}} | ||
81 | + > | ||
82 | + {item?.name} | ||
83 | + </div> | ||
84 | + }) | ||
85 | + } | ||
86 | + </div> | ||
87 | + </div> | ||
88 | + </div> | ||
89 | + ) | ||
90 | +} | ||
91 | + | ||
92 | +export default ProductionManagement; |
src/pages/production-detail/style.less
0 → 100644
1 | +.production-management { | ||
2 | + background: #f7f7f7; | ||
3 | + | ||
4 | + &_list { | ||
5 | + padding: 60px; | ||
6 | + display: flex; | ||
7 | + flex-wrap: wrap; | ||
8 | + | ||
9 | + &-item { | ||
10 | + font-size: 28px; | ||
11 | + width: 312px; | ||
12 | + height: 312px; | ||
13 | + color: #fff; | ||
14 | + margin-right: 60px; | ||
15 | + margin-bottom: 60px; | ||
16 | + cursor: pointer; | ||
17 | + border-radius: 12px; | ||
18 | + display: flex; | ||
19 | + align-items: center; | ||
20 | + justify-content: center; | ||
21 | + line-height: 40px; | ||
22 | + padding: 20px; | ||
23 | + box-sizing: border-box; | ||
24 | + text-align: center; | ||
25 | + | ||
26 | + &:nth-child(5n) { | ||
27 | + margin-right: 0; | ||
28 | + } | ||
29 | + } | ||
30 | + } | ||
31 | +} |
src/pages/production-list/index.tsx
0 → 100644
1 | +import React, {useEffect, useState} from 'react' | ||
2 | +import './style.less' | ||
3 | +import NavBar from '@/components/nav-bar' | ||
4 | +import {baseColorPrimary} from "@/utils/common"; | ||
5 | +import {hexToRgba} from "@/utils/utils"; | ||
6 | +import _mp4 from './mp4.png'; | ||
7 | +import _pdf from './pdf.png'; | ||
8 | + | ||
9 | +import { useSearchParams } from "react-router-dom"; | ||
10 | + | ||
11 | + | ||
12 | +const ProductionList: React.FC = () => { | ||
13 | + const [title, setTitle] = useState<string>(''); | ||
14 | + // 因是hook,必须写在组件的顶部执行,useSearchParams() 返回的是数组 | ||
15 | + const [params] = useSearchParams(); | ||
16 | + console.log('ProductionList===params', params) | ||
17 | + // 通过 get 方法获取目标参数 | ||
18 | + const name = params.get("name") || ""; | ||
19 | + | ||
20 | + useEffect(() => { | ||
21 | + if (name) { | ||
22 | + setTitle(name) | ||
23 | + } | ||
24 | + }, [name]) | ||
25 | + | ||
26 | + const list = [ | ||
27 | + { | ||
28 | + id: '1', | ||
29 | + name: '工艺流程指导文件', | ||
30 | + type: 'pdf' | ||
31 | + }, | ||
32 | + { | ||
33 | + id: '2', | ||
34 | + name: '设备操作指导文件', | ||
35 | + type: 'mp4' | ||
36 | + }, | ||
37 | + { | ||
38 | + id: '3', | ||
39 | + name: '工艺流程指导文件2', | ||
40 | + type: 'pdf' | ||
41 | + }, | ||
42 | + { | ||
43 | + id: '4', | ||
44 | + name: '工艺流程指导文件3', | ||
45 | + type: 'pdf' | ||
46 | + }, | ||
47 | + { | ||
48 | + id: '5', | ||
49 | + name: '工艺流程指导文件4', | ||
50 | + type: 'pdf' | ||
51 | + }, | ||
52 | + { | ||
53 | + id: '6', | ||
54 | + name: '工艺流程指导文件5', | ||
55 | + type: 'pdf' | ||
56 | + }, | ||
57 | + { | ||
58 | + id: '7', | ||
59 | + name: '设备操作指导文件2', | ||
60 | + type: 'mp4' | ||
61 | + }, | ||
62 | + { | ||
63 | + id: '8', | ||
64 | + name: '设备设备设备设备设备设备设备操作指导文件3', | ||
65 | + type: 'mp4' | ||
66 | + }, | ||
67 | + { | ||
68 | + id: '9', | ||
69 | + name: '设备操作指导文件4', | ||
70 | + type: 'mp4' | ||
71 | + }, | ||
72 | + { | ||
73 | + id: '10', | ||
74 | + name: '设备操作指导文件5', | ||
75 | + type: 'mp4' | ||
76 | + }, | ||
77 | + { | ||
78 | + id: '11', | ||
79 | + name: '设备操作指导文件6', | ||
80 | + type: 'mp4' | ||
81 | + }, | ||
82 | + { | ||
83 | + id: '12', | ||
84 | + name: '设备操作指导文件7', | ||
85 | + type: 'mp4' | ||
86 | + }, | ||
87 | + { | ||
88 | + id: '13', | ||
89 | + name: '设备操作指导文件8', | ||
90 | + type: 'mp4' | ||
91 | + }, | ||
92 | + { | ||
93 | + id: '14', | ||
94 | + name: '设备操作指导文件9', | ||
95 | + type: 'mp4' | ||
96 | + }, | ||
97 | + { | ||
98 | + id: '15', | ||
99 | + name: '设备操作指导文件10', | ||
100 | + type: 'mp4' | ||
101 | + } | ||
102 | + ] | ||
103 | + | ||
104 | + | ||
105 | + return ( | ||
106 | + <div className={'sxjx-content-main sxjx-layout-main-unfoot'}> | ||
107 | + <div className={'production-list'}> | ||
108 | + <NavBar title={title} showBack={true}/> | ||
109 | + <div className={'production-list_list'}> | ||
110 | + { | ||
111 | + list?.map((item: any) => { | ||
112 | + return <div | ||
113 | + key={item?.id} | ||
114 | + className={'production-list_list-item'} | ||
115 | + style={{backgroundColor: hexToRgba(baseColorPrimary, 0.6)}} | ||
116 | + > | ||
117 | + <img className={'production-list_list-item-img'} src={item?.type === 'mp4' ? _mp4 : _pdf}/> | ||
118 | + <div className={'omit2 production-list_list-item-name'}> | ||
119 | + {item?.name} | ||
120 | + </div> | ||
121 | + </div> | ||
122 | + }) | ||
123 | + } | ||
124 | + </div> | ||
125 | + </div> | ||
126 | + </div> | ||
127 | + ) | ||
128 | +} | ||
129 | + | ||
130 | +export default ProductionList; |
src/pages/production-list/mp4.png
0 → 100644
8.72 KB
src/pages/production-list/pdf.png
0 → 100644
10.4 KB
src/pages/production-list/style.less
0 → 100644
1 | +.production-list { | ||
2 | + background: #f7f7f7; | ||
3 | + | ||
4 | + &_list { | ||
5 | + padding: 60px; | ||
6 | + display: flex; | ||
7 | + flex-wrap: wrap; | ||
8 | + | ||
9 | + &-item { | ||
10 | + width: 312px; | ||
11 | + height: 312px; | ||
12 | + color: #fff; | ||
13 | + margin-right: 60px; | ||
14 | + margin-bottom: 60px; | ||
15 | + cursor: pointer; | ||
16 | + border-radius: 12px; | ||
17 | + display: flex; | ||
18 | + align-items: center; | ||
19 | + justify-content: center; | ||
20 | + padding: 20px; | ||
21 | + box-sizing: border-box; | ||
22 | + text-align: center; | ||
23 | + flex-direction: column; | ||
24 | + | ||
25 | + &:nth-child(5n) { | ||
26 | + margin-right: 0; | ||
27 | + } | ||
28 | + | ||
29 | + &-img { | ||
30 | + width: 60px; | ||
31 | + height: 60px; | ||
32 | + margin-bottom: 30px; | ||
33 | + } | ||
34 | + | ||
35 | + &-name { | ||
36 | + font-size: 28px; | ||
37 | + height: 80px; | ||
38 | + line-height: 40px; | ||
39 | + } | ||
40 | + } | ||
41 | + } | ||
42 | +} |
src/pages/production-management/index.tsx
0 → 100644
1 | +import React from 'react' | ||
2 | +import './style.less' | ||
3 | +import NavBar from "@/components/nav-bar" | ||
4 | +import {baseColorPrimary} from "@/utils/common"; | ||
5 | +import {hexToRgba} from "@/utils/utils"; | ||
6 | +import { useNavigate } from "react-router-dom"; | ||
7 | + | ||
8 | + | ||
9 | +const ProductionManagement: React.FC = () => { | ||
10 | + const navigate = useNavigate(); | ||
11 | + | ||
12 | + const list = [ | ||
13 | + { | ||
14 | + id: '1', | ||
15 | + name: '车顶生产线A' | ||
16 | + }, | ||
17 | + { | ||
18 | + id: '2', | ||
19 | + name: '车顶生产线B' | ||
20 | + }, | ||
21 | + { | ||
22 | + id: '3', | ||
23 | + name: '车顶生产线C' | ||
24 | + }, | ||
25 | + { | ||
26 | + id: '4', | ||
27 | + name: '车顶生产线D' | ||
28 | + }, | ||
29 | + { | ||
30 | + id: '5', | ||
31 | + name: '车顶生产线E' | ||
32 | + }, | ||
33 | + { | ||
34 | + id: '6', | ||
35 | + name: '车顶生产线F' | ||
36 | + }, | ||
37 | + { | ||
38 | + id: '7', | ||
39 | + name: '车顶生产线G' | ||
40 | + }, | ||
41 | + { | ||
42 | + id: '8', | ||
43 | + name: '车顶生产线H' | ||
44 | + }, | ||
45 | + { | ||
46 | + id: '9', | ||
47 | + name: '车顶生产线I' | ||
48 | + }, | ||
49 | + { | ||
50 | + id: '10', | ||
51 | + name: '车顶生产线J' | ||
52 | + }, | ||
53 | + { | ||
54 | + id: '11', | ||
55 | + name: '车顶生产线K' | ||
56 | + }, | ||
57 | + { | ||
58 | + id: '12', | ||
59 | + name: '车顶生车顶生车顶生产线L' | ||
60 | + }, | ||
61 | + { | ||
62 | + id: '13', | ||
63 | + name: '车顶生产线M' | ||
64 | + }, | ||
65 | + { | ||
66 | + id: '14', | ||
67 | + name: '车顶生产线N' | ||
68 | + } | ||
69 | + ]; | ||
70 | + | ||
71 | + const toProductionList = (item: any) => { | ||
72 | + console.log('toProductionList-item', item) | ||
73 | + navigate(`/production/list?id=${item?.id}&name=${item?.name}`); | ||
74 | + } | ||
75 | + | ||
76 | + | ||
77 | + return ( | ||
78 | + <div className={'sxjx-content-main sxjx-layout-main-unfoot'}> | ||
79 | + <div className={'production-management'}> | ||
80 | + <NavBar title={'生产线管理'}/> | ||
81 | + <div className={'production-management_list'}> | ||
82 | + { | ||
83 | + list?.map((item: any) => { | ||
84 | + return <div | ||
85 | + key={item?.id} | ||
86 | + className={'production-management_list-item'} | ||
87 | + style={{backgroundColor: hexToRgba(baseColorPrimary, 0.6)}} | ||
88 | + onClick={() => toProductionList(item)} | ||
89 | + > | ||
90 | + {item?.name} | ||
91 | + </div> | ||
92 | + }) | ||
93 | + } | ||
94 | + </div> | ||
95 | + </div> | ||
96 | + </div> | ||
97 | + ) | ||
98 | +} | ||
99 | + | ||
100 | +export default ProductionManagement; |
src/pages/production-management/style.less
0 → 100644
1 | +.production-management { | ||
2 | + background: #f7f7f7; | ||
3 | + | ||
4 | + &_list { | ||
5 | + padding: 60px; | ||
6 | + display: flex; | ||
7 | + flex-wrap: wrap; | ||
8 | + | ||
9 | + &-item { | ||
10 | + font-size: 28px; | ||
11 | + width: 312px; | ||
12 | + height: 312px; | ||
13 | + color: #fff; | ||
14 | + margin-right: 60px; | ||
15 | + margin-bottom: 60px; | ||
16 | + cursor: pointer; | ||
17 | + border-radius: 12px; | ||
18 | + display: flex; | ||
19 | + align-items: center; | ||
20 | + justify-content: center; | ||
21 | + line-height: 40px; | ||
22 | + padding: 20px; | ||
23 | + box-sizing: border-box; | ||
24 | + text-align: center; | ||
25 | + | ||
26 | + &:nth-child(5n) { | ||
27 | + margin-right: 0; | ||
28 | + } | ||
29 | + } | ||
30 | + } | ||
31 | +} |
src/router.tsx
0 → 100644
1 | +import {createHashRouter} from 'react-router-dom'; | ||
2 | +import ErrorPage from "./pages/errorPage"; | ||
3 | +import ProductionManagement from "./pages/production-management"; | ||
4 | +import ProductionList from "./pages/production-list"; | ||
5 | +import ProductionDetail from "./pages/production-detail"; | ||
6 | + | ||
7 | + | ||
8 | +const routers = [ | ||
9 | + { | ||
10 | + path: '/', // 生产线管理 | ||
11 | + element: <ProductionManagement />, | ||
12 | + errorElement: <ErrorPage />, | ||
13 | + }, | ||
14 | + { | ||
15 | + path: '/production/management', // 生产线管理 | ||
16 | + element: <ProductionManagement />, | ||
17 | + errorElement: <ErrorPage />, | ||
18 | + }, | ||
19 | + { | ||
20 | + path: '/production/list', // 生产线明细 | ||
21 | + element: <ProductionList />, | ||
22 | + errorElement: <ErrorPage />, | ||
23 | + }, | ||
24 | + { | ||
25 | + path: '/production/detail', // 生产线详情 | ||
26 | + element: <ProductionDetail />, | ||
27 | + errorElement: <ErrorPage />, | ||
28 | + }, | ||
29 | +]; | ||
30 | + | ||
31 | +export default createHashRouter(routers) |
src/utils/common.tsx
0 → 100644
src/utils/request.tsx
0 → 100644
1 | +import axios from 'axios'; | ||
2 | +import {currentCorpCode, _baseUrl} from "./common" | ||
3 | + | ||
4 | +// 创建axios实例 | ||
5 | +const service = axios.create({ | ||
6 | + baseURL: _baseUrl, // 你可以通过.env文件设置API的基础URL | ||
7 | + timeout: 5000 // 请求超时时间 | ||
8 | +}); | ||
9 | + | ||
10 | +// 请求拦截器 | ||
11 | +service.interceptors.request.use( | ||
12 | + config => { | ||
13 | + // 在发送请求之前做些什么,例如设置请求头 | ||
14 | + // if (store.getters.token) { | ||
15 | + // config.headers['X-Token'] = getToken(); | ||
16 | + // } | ||
17 | + console.log('config---2', config) | ||
18 | + return config; | ||
19 | + }, | ||
20 | + error => { | ||
21 | + // 对请求错误做些什么 | ||
22 | + console.error('请求拦截器错误:', error); // for debug | ||
23 | + Promise.reject(error); | ||
24 | + } | ||
25 | +); | ||
26 | + | ||
27 | +// 响应拦截器 | ||
28 | +service.interceptors.response.use( | ||
29 | + response => { | ||
30 | + /** | ||
31 | + * 可以在这里对响应数据做点什么 | ||
32 | + */ | ||
33 | + const res = response.data; | ||
34 | + if (res?.success || res?.code === 200) { | ||
35 | + return res.data; | ||
36 | + } else { | ||
37 | + // 如果后端有统一的错误码处理,可以在这里统一处理 | ||
38 | + console.error('接口错误:', res.message); | ||
39 | + // 你可以抛出一个错误,或者返回一个错误对象 | ||
40 | + // throw new Error(res.message || 'Error'); | ||
41 | + return Promise.reject(new Error(res.message || 'Error')); | ||
42 | + } | ||
43 | + }, | ||
44 | + error => { | ||
45 | + console.error('响应拦截器错误:', error); | ||
46 | + // 对响应错误做点什么 | ||
47 | + return Promise.reject(error); | ||
48 | + } | ||
49 | +); | ||
50 | + | ||
51 | +// 封装get请求 | ||
52 | +export function get(url: string, params = {}, customHeaders?: any, notCorpCode?: boolean) { | ||
53 | + | ||
54 | + const _params = notCorpCode ? { | ||
55 | + ...params, | ||
56 | + } : { | ||
57 | + corpCode: currentCorpCode(), | ||
58 | + ...params, | ||
59 | + } | ||
60 | + return service.get(url, {params: _params, headers: customHeaders}) | ||
61 | + | ||
62 | +} | ||
63 | + | ||
64 | +// 封装post请求 | ||
65 | +export function post(url: string, params = {}, data = {}, customHeaders?: any, notCorpCode?: boolean) { | ||
66 | + const _params = notCorpCode ? { | ||
67 | + ...params, | ||
68 | + } : { | ||
69 | + corpCode: currentCorpCode(), | ||
70 | + ...params, | ||
71 | + } | ||
72 | + return service.post(url, data, {params: _params, headers: customHeaders}) | ||
73 | +} |
src/utils/utils.tsx
0 → 100644
1 | + | ||
2 | +// 十六进制颜色 转换成 rgba | ||
3 | +export const hexToRgba = (hex: string | null | undefined, alpha: any) => { | ||
4 | + let r: string | number = 0, g: string | number = 0, b: string | number = 0; | ||
5 | + | ||
6 | + // 3 digits | ||
7 | + if (hex?.length == 4) { | ||
8 | + r = "0x" + hex?.[1] + hex?.[1]; | ||
9 | + g = "0x" + hex?.[2] + hex?.[2]; | ||
10 | + b = "0x" + hex?.[3] + hex?.[3]; | ||
11 | + // 6 digits | ||
12 | + } else if (hex?.length == 7) { | ||
13 | + r = "0x" + hex?.[1] + hex?.[2]; | ||
14 | + g = "0x" + hex?.[3] + hex?.[4]; | ||
15 | + b = "0x" + hex?.[5] + hex?.[6]; | ||
16 | + } | ||
17 | + | ||
18 | + return "rgba(" + +r + "," + +g + "," + +b + "," + alpha + ")"; | ||
19 | +} | ||
20 | + | ||
21 | +// // 使用示例 | ||
22 | +// const hexColor = "#ff5733"; // 16进制颜色 | ||
23 | +// const opacity = 0.5; // 透明度(0.0 到 1.0) | ||
24 | +// const rgbaColor = hexToRgba(hexColor, opacity); | ||
25 | +// console.log(rgbaColor); // 输出: "rgba(255, 87, 51, 0.5)" | ||
26 | + | ||
27 | +export function setFavicon (logoPath: string) { | ||
28 | + const link = document.createElement('link'); | ||
29 | + link.rel = 'icon'; | ||
30 | + link.href = logoPath; | ||
31 | + document.head.appendChild(link); | ||
32 | +} |
src/vite-env.d.ts
0 → 100644
1 | +/// <reference types="vite/client" /> |
tsconfig.app.json
0 → 100644
1 | +{ | ||
2 | + "compilerOptions": { | ||
3 | + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", | ||
4 | + "target": "ES2020", | ||
5 | + "useDefineForClassFields": true, | ||
6 | + "lib": ["ES2020", "DOM", "DOM.Iterable"], | ||
7 | + "module": "ESNext", | ||
8 | + "skipLibCheck": true, | ||
9 | + | ||
10 | + /* Bundler mode */ | ||
11 | + "moduleResolution": "bundler", | ||
12 | + "allowImportingTsExtensions": true, | ||
13 | + "isolatedModules": true, | ||
14 | + "moduleDetection": "force", | ||
15 | + "noEmit": true, | ||
16 | + "jsx": "react-jsx", | ||
17 | + | ||
18 | + /* Linting */ | ||
19 | + "strict": true, | ||
20 | + "noUnusedLocals": true, | ||
21 | + "noUnusedParameters": true, | ||
22 | + "noFallthroughCasesInSwitch": true, | ||
23 | + "noUncheckedSideEffectImports": true | ||
24 | + }, | ||
25 | + "include": ["src"] | ||
26 | +} |
tsconfig.json
0 → 100644
tsconfig.node.json
0 → 100644
1 | +{ | ||
2 | + "compilerOptions": { | ||
3 | + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", | ||
4 | + "target": "ES2022", | ||
5 | + "lib": ["ES2023"], | ||
6 | + "module": "ESNext", | ||
7 | + "skipLibCheck": true, | ||
8 | + | ||
9 | + /* Bundler mode */ | ||
10 | + "moduleResolution": "bundler", | ||
11 | + "allowImportingTsExtensions": true, | ||
12 | + "isolatedModules": true, | ||
13 | + "moduleDetection": "force", | ||
14 | + "noEmit": true, | ||
15 | + | ||
16 | + /* Linting */ | ||
17 | + "strict": true, | ||
18 | + "noUnusedLocals": true, | ||
19 | + "noUnusedParameters": true, | ||
20 | + "noFallthroughCasesInSwitch": true, | ||
21 | + "noUncheckedSideEffectImports": true | ||
22 | + }, | ||
23 | + "include": ["vite.config.ts"] | ||
24 | +} |
vite.config.ts
0 → 100644
1 | +import {defineConfig} from 'vite' | ||
2 | +import react from '@vitejs/plugin-react' | ||
3 | +import {resolve} from 'path'; | ||
4 | +import postCssPxToViewport from 'postcss-px-to-viewport'; | ||
5 | + | ||
6 | +const _pxToViewPort = { | ||
7 | + viewportWidth: 1920, // 视窗的宽度,对应的是我们设计稿的宽度,一般是750 | ||
8 | + viewportHeight: 1080, // 视窗的高度,根据750设备的宽度来指定,一般指定1334,也可以不配置 | ||
9 | + unitPrecision: 5, // 指定`px`转换为视窗单位值的小数位数(很多时候无法整除) | ||
10 | + viewportUnit: 'vw', // 指定需要转换成的视窗单位,建议使用vw | ||
11 | + selectorBlackList: [], // 指定不转换为视窗单位的类,可以自定义,可以无限添加,建议定义一至两个通用的类名 | ||
12 | + minPixelValue: 1, // 小于或等于`1px`不转换为视窗单位,你也可以设置为你想要的值 | ||
13 | + mediaQuery: false, // 允许在媒体查询中转换`px` | ||
14 | +} | ||
15 | + | ||
16 | +// https://vitejs.dev/config/ | ||
17 | +export default defineConfig({ | ||
18 | + base: "./", | ||
19 | + plugins: [react()], | ||
20 | + resolve: { | ||
21 | + alias: { | ||
22 | + '@': resolve(__dirname, '/src') | ||
23 | + }, | ||
24 | + extensions: ['.js', '.jsx', '.ts', '.tsx', '.less'] | ||
25 | + }, | ||
26 | + css: { | ||
27 | + preprocessorOptions: { | ||
28 | + less: { | ||
29 | + // 这里可以配置less的特定选项 | ||
30 | + } | ||
31 | + }, | ||
32 | + postcss: { | ||
33 | + plugins: [postCssPxToViewport(_pxToViewPort)] | ||
34 | + } | ||
35 | + }, | ||
36 | +}) |