Yansen 2 年 前
コミット
7e8b32dc8f

+ 24
- 0
.gitignore ファイルの表示

@@ -0,0 +1,24 @@
1
+# Logs
2
+logs
3
+*.log
4
+npm-debug.log*
5
+yarn-debug.log*
6
+yarn-error.log*
7
+pnpm-debug.log*
8
+lerna-debug.log*
9
+
10
+node_modules
11
+dist
12
+dist-ssr
13
+*.local
14
+
15
+# Editor directories and files
16
+.vscode/*
17
+!.vscode/extensions.json
18
+.idea
19
+.DS_Store
20
+*.suo
21
+*.ntvs*
22
+*.njsproj
23
+*.sln
24
+*.sw?

+ 13
- 0
index.html ファイルの表示

@@ -0,0 +1,13 @@
1
+<!DOCTYPE html>
2
+<html lang="en">
3
+  <head>
4
+    <meta charset="UTF-8" />
5
+    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+    <title>Vite + React</title>
8
+  </head>
9
+  <body>
10
+    <div id="root"></div>
11
+    <script type="module" src="/src/main.jsx"></script>
12
+  </body>
13
+</html>

+ 27
- 0
package.json ファイルの表示

@@ -0,0 +1,27 @@
1
+{
2
+  "name": "vite-project",
3
+  "private": true,
4
+  "version": "0.0.0",
5
+  "type": "module",
6
+  "scripts": {
7
+    "dev": "vite",
8
+    "build": "vite build",
9
+    "preview": "vite preview"
10
+  },
11
+  "dependencies": {
12
+    "@zjxpcyc/react-tiny-store": "^2.0.1",
13
+    "antd": "^4.22.3",
14
+    "react": "18.1.0",
15
+    "react-dom": "18.1.0",
16
+    "react-router-dom": "6",
17
+    "react-transition-group": "^4.4.5"
18
+  },
19
+  "devDependencies": {
20
+    "@types/react": "^18.0.15",
21
+    "@types/react-dom": "^18.0.6",
22
+    "@vitejs/plugin-react": "^2.0.0",
23
+    "less": "^4.1.3",
24
+    "vite": "^3.0.0",
25
+    "vite-plugin-imp": "^2.2.0"
26
+  }
27
+}

+ 2381
- 0
pnpm-lock.yaml
ファイル差分が大きすぎるため省略します
ファイルの表示


+ 1
- 0
public/vite.svg ファイルの表示

@@ -0,0 +1 @@
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>

+ 41
- 0
src/App.css ファイルの表示

@@ -0,0 +1,41 @@
1
+#root {
2
+  max-width: 1280px;
3
+  margin: 0 auto;
4
+  padding: 2rem;
5
+  text-align: center;
6
+}
7
+
8
+.logo {
9
+  height: 6em;
10
+  padding: 1.5em;
11
+  will-change: filter;
12
+}
13
+.logo:hover {
14
+  filter: drop-shadow(0 0 2em #646cffaa);
15
+}
16
+.logo.react:hover {
17
+  filter: drop-shadow(0 0 2em #61dafbaa);
18
+}
19
+
20
+@keyframes logo-spin {
21
+  from {
22
+    transform: rotate(0deg);
23
+  }
24
+  to {
25
+    transform: rotate(360deg);
26
+  }
27
+}
28
+
29
+@media (prefers-reduced-motion: no-preference) {
30
+  a:nth-of-type(2) .logo {
31
+    animation: logo-spin infinite 20s linear;
32
+  }
33
+}
34
+
35
+.card {
36
+  padding: 2em;
37
+}
38
+
39
+.read-the-docs {
40
+  color: #888;
41
+}

+ 35
- 0
src/App.jsx ファイルの表示

@@ -0,0 +1,35 @@
1
+import { useState } from 'react'
2
+import { Button } from 'antd'
3
+import reactLogo from './assets/react.svg'
4
+import './App.css'
5
+
6
+function App() {
7
+  const [count, setCount] = useState(0)
8
+
9
+  return (
10
+    <div className="App">
11
+      <div>
12
+        <a href="https://vitejs.dev" target="_blank">
13
+          <img src="/vite.svg" className="logo" alt="Vite logo" />
14
+        </a>
15
+        <a href="https://reactjs.org" target="_blank">
16
+          <img src={reactLogo} className="logo react" alt="React logo" />
17
+        </a>
18
+      </div>
19
+      <h1>Vite + React</h1>
20
+      <div className="card">
21
+        <Button type='primary' onClick={() => setCount((count) => count + 1)}>
22
+          count is {count}
23
+        </Button>
24
+        <p>
25
+          Edit <code>src/App.jsx</code> and save to test HMR
26
+        </p>
27
+      </div>
28
+      <p className="read-the-docs">
29
+        Click on the Vite and React logos to learn more
30
+      </p>
31
+    </div>
32
+  )
33
+}
34
+
35
+export default App

+ 1
- 0
src/assets/react.svg ファイルの表示

@@ -0,0 +1 @@
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>

+ 35
- 0
src/index.css ファイルの表示

@@ -0,0 +1,35 @@
1
+html, body, #root {
2
+  width: 100%;
3
+  height: 100%;
4
+  margin: 0;
5
+}
6
+
7
+:root {
8
+  --theme-color: #fff;
9
+  --theme-front: #000;
10
+  --header-height: 64px;
11
+}
12
+
13
+.main-layout {
14
+  height: 100vh;
15
+  display: flex;
16
+  flex-direction: column;
17
+}
18
+
19
+.fixd-header {
20
+  width: 100%;
21
+  position: fixed;
22
+  top: 0;
23
+  height: var(--header-height);
24
+  line-height: var(--header-height);
25
+  z-index: 100;
26
+}
27
+
28
+.ant-layout {
29
+  background-color: #f0f2f5;
30
+}
31
+
32
+.layout-background {
33
+  background-color: var(--theme-color);
34
+  color: var(--theme-front);
35
+}

+ 18
- 0
src/layouts/AuthLayout/components/Container.jsx ファイルの表示

@@ -0,0 +1,18 @@
1
+import React from 'react';
2
+import { Layout, Spin } from 'antd';
3
+import { Outlet, useLocation } from "react-router-dom";
4
+import PageTransition from './PageTransition';
5
+
6
+const { Content } = Layout;
7
+
8
+export default (props) => {
9
+  const location = useLocation()
10
+
11
+  return (
12
+    <Content>
13
+      <PageTransition location={location}>
14
+        <Outlet />
15
+      </PageTransition>
16
+    </Content>
17
+  )
18
+}

+ 14
- 0
src/layouts/AuthLayout/components/Footer.jsx ファイルの表示

@@ -0,0 +1,14 @@
1
+import React from 'react';
2
+import { Layout, Spin } from 'antd';
3
+
4
+const { Footer } = Layout;
5
+
6
+const year = new Date().getFullYear();
7
+export default (props) => {
8
+
9
+  const copyRight = `南京云致 @${year}`
10
+
11
+  return (
12
+    <Footer style={{ textAlign: 'center' }}>{copyRight}</Footer>
13
+  )
14
+}

+ 13
- 0
src/layouts/AuthLayout/components/Header.jsx ファイルの表示

@@ -0,0 +1,13 @@
1
+import React from 'react';
2
+import { Layout, Spin } from 'antd';
3
+import Logo from './Logo';
4
+
5
+const { Header } = Layout;
6
+
7
+export default (props) => {
8
+  return (
9
+    <Header>
10
+      <Logo />
11
+    </Header>
12
+  )
13
+}

+ 7
- 0
src/layouts/AuthLayout/components/Logo.jsx ファイルの表示

@@ -0,0 +1,7 @@
1
+import React from 'react'
2
+
3
+export default (props) => {
4
+  return (
5
+    <div style={{ height: '64px' }}>Logo</div>
6
+  )
7
+}

+ 66
- 0
src/layouts/AuthLayout/components/Menus.jsx ファイルの表示

@@ -0,0 +1,66 @@
1
+import React, { useState } from 'react';
2
+import { useNavigate } from "react-router-dom";
3
+import { Menu } from 'antd';
4
+import routes from '@/routes/routes';
5
+
6
+// 菜单是否显示
7
+// 没有 menu 或者 menu.title 为空, 或者 menu.hidden = true 的 都不显示
8
+const isShow = item => item.menu && item.title && !item.menu.hidden;
9
+
10
+const hasChildren = (list) => {
11
+  if (!list || list.length < 1) return false;
12
+
13
+  // 如果子元素全部都是不显示的, 说明子菜单不需要显示
14
+  return list.filter(it => !isShow(it)).length !== list.length;
15
+}
16
+
17
+const getPath = (parent, current = '') => {
18
+  if (current.indexOf('/') === 0 || current.indexOf('http') === 0) return current;
19
+  return `${parent}/${current}`.replace(/\/\//g, '/');
20
+}
21
+
22
+const getItems = (dts = [], fullPath = '/') => {
23
+  return dts.map(item => {
24
+    // 没有 menu 或者 menu.title 为空, 或者 menu.hidden = true 的 都不显示
25
+    if (!item.menu || !item.menu.title || item.menu.hidden) return false;
26
+    
27
+    const path = getPath(fullPath, item.path)
28
+    const children = hasChildren(item.children) ? getItems(item.children, path) : false;
29
+
30
+    return Object.assign(
31
+      {
32
+        key: path,
33
+        label: item.menu.title,
34
+        title: item.menu.title,
35
+      },
36
+      children && { children },
37
+    )
38
+  }).filter(Boolean);
39
+}
40
+
41
+const linkTo = url => {
42
+  const a = document.createElement('a');
43
+  a.href = item.key;
44
+  a.target = '_blank';
45
+  a.click();
46
+}
47
+
48
+export default (props) => {
49
+  const { theme } = props;
50
+
51
+  const navigate = useNavigate();
52
+  const items = getItems(routes[0].children);
53
+
54
+  const onClick = (item) => {
55
+    // http 开头说明是外部链接
56
+    if (item.key.indexOf('http') === 0) {
57
+      linkTo(item.key);
58
+    } else {
59
+      navigate(item.key);
60
+    }
61
+  }
62
+
63
+  return (
64
+    <Menu theme={theme} items={items} onClick={onClick} />
65
+  )
66
+}

+ 21
- 0
src/layouts/AuthLayout/components/PageTransition/index.jsx ファイルの表示

@@ -0,0 +1,21 @@
1
+import { TransitionGroup, CSSTransition } from 'react-transition-group';
2
+import './style.less';
3
+
4
+export default (props) => {
5
+  const { location } = props;
6
+  const currentURL = location.pathname + location.search;
7
+
8
+  return (
9
+    <TransitionGroup component={null}>
10
+      <CSSTransition
11
+        key={currentURL}
12
+        addEndListener={(node, done) => node.addEventListener("transitionend", done, false)}
13
+        classNames="page-fade"
14
+      >
15
+        <div>
16
+          {props.children}
17
+        </div>
18
+      </CSSTransition>
19
+    </TransitionGroup>
20
+  );
21
+}

+ 21
- 0
src/layouts/AuthLayout/components/PageTransition/style.less ファイルの表示

@@ -0,0 +1,21 @@
1
+
2
+.page-fade-enter {
3
+  opacity: 0;
4
+  transform: translateY(10%);
5
+}
6
+.page-fade-enter-active {
7
+  opacity: 1;
8
+  transform: translateY(0%);
9
+}
10
+.page-fade-exit {
11
+  opacity: 1;
12
+  transform: translateY(0%);
13
+}
14
+.page-fade-exit-active {
15
+  opacity: 0;
16
+  transform: translateY(10%);
17
+}
18
+.page-fade-enter-active,
19
+.page-fade-exit-active {
20
+  transition: opacity 300ms, transform 300ms;
21
+}

+ 13
- 0
src/layouts/AuthLayout/components/RequireLogin.jsx ファイルの表示

@@ -0,0 +1,13 @@
1
+import React, { useState } from 'react'
2
+import { useLocation, Navigate } from "react-router-dom"
3
+
4
+export default (props) => {
5
+  const { user } = props
6
+  const location = useLocation()
7
+
8
+  return props.children
9
+
10
+  // return !user || !user.isLoged ?
11
+  //   <Navigate to="/login" state={{ from: location }} replace /> :
12
+  //   props.children
13
+}

+ 16
- 0
src/layouts/AuthLayout/components/SiderBar.jsx ファイルの表示

@@ -0,0 +1,16 @@
1
+import React from 'react';
2
+import { Layout, Spin } from 'antd';
3
+import { useModel } from '@/store'
4
+import Menus from './Menus';
5
+
6
+const { Sider } = Layout;
7
+
8
+export default (props) => {
9
+  const { theme } = useModel('system');
10
+
11
+  return (
12
+    <Sider className='layout-background' theme={theme} collapsible >
13
+      <Menus theme={theme}/>
14
+    </Sider>
15
+  )
16
+}

+ 34
- 0
src/layouts/AuthLayout/index.jsx ファイルの表示

@@ -0,0 +1,34 @@
1
+import React from 'react';
2
+import { Layout, Spin } from 'antd';
3
+import { useModel } from '@/store'
4
+import RequireLogin from './components/RequireLogin';
5
+import SiderBar from './components/SiderBar';
6
+import Header from './components/Header';
7
+import Container from './components/Container';
8
+import Footer from './components/Footer';
9
+import useReady from './useReady';
10
+
11
+const { Content } = Layout;
12
+
13
+export default (props) => {
14
+  const [user] = useModel();
15
+  // const isReady = useReady(user)
16
+  const isReady = true
17
+
18
+  return (
19
+    <Spin spinning={!isReady}>
20
+      <RequireLogin>
21
+        <div className='main-layout'>
22
+          <Header />
23
+          <Layout>
24
+            <SiderBar />
25
+            <Layout>
26
+              <Container />
27
+              <Footer />
28
+            </Layout>
29
+          </Layout>
30
+        </div>
31
+      </RequireLogin>
32
+    </Spin>
33
+  );
34
+}

+ 14
- 0
src/layouts/AuthLayout/useReady.jsx ファイルの表示

@@ -0,0 +1,14 @@
1
+import React, { useState, useEffect } from 'react'
2
+
3
+export default function useReady(user) {
4
+  const [isReady, setReady] = useState(false)
5
+  const isLogined = user && user.isLogined
6
+
7
+  useEffect(() => {
8
+    if (!isReady && !isLogined) {
9
+      // fetchCurrent
10
+    }
11
+  }, [isReady, isLogined])
12
+
13
+  return isLogined || isReady || true
14
+}

+ 11
- 0
src/main.jsx ファイルの表示

@@ -0,0 +1,11 @@
1
+import React from 'react'
2
+import ReactDOM from 'react-dom/client'
3
+import Router from './routes/Router'
4
+import './index.css'
5
+import { Provider } from './store'
6
+
7
+ReactDOM.createRoot(document.getElementById('root')).render(
8
+  <Provider>
9
+    <Router />
10
+  </Provider>
11
+)

+ 7
- 0
src/pages/Home.jsx ファイルの表示

@@ -0,0 +1,7 @@
1
+import React from 'react'
2
+
3
+export default (props) => {
4
+  return (
5
+    <div>adfasdfasdfasdf</div>
6
+  )
7
+}

+ 12
- 0
src/routes/Router.jsx ファイルの表示

@@ -0,0 +1,12 @@
1
+import { HashRouter, useRoutes } from "react-router-dom";
2
+import routes from './routes'
3
+
4
+const Routes = () => useRoutes(routes);
5
+
6
+export default (props) => {
7
+  return (
8
+    <HashRouter>
9
+      <Routes />
10
+    </HashRouter>
11
+  )
12
+}

+ 33
- 0
src/routes/routes.jsx ファイルの表示

@@ -0,0 +1,33 @@
1
+import AuthLayout from "@/layouts/AuthLayout"
2
+import Home from "@/pages/Home"
3
+
4
+export default [
5
+  {
6
+    path: "/",
7
+    element: <AuthLayout />,
8
+    children: [
9
+      {
10
+        path: "",
11
+        element: <Home />,
12
+        menu: {
13
+          title: '首页',
14
+          hidden: true,
15
+        },
16
+      },
17
+      {
18
+        path: "index",
19
+        element: <Home />,
20
+        menu: {
21
+          title: 'Index',
22
+        },
23
+      },
24
+      {
25
+        path: "home",
26
+        element: <Home />,
27
+        menu: {
28
+          title: 'Home',
29
+        },
30
+      }
31
+    ],
32
+  },
33
+]

+ 12
- 0
src/store/index.js ファイルの表示

@@ -0,0 +1,12 @@
1
+import { createStore } from "@zjxpcyc/react-tiny-store";
2
+import useSystem from "./models/system";
3
+
4
+const store = createStore({
5
+  system: useSystem,
6
+});
7
+
8
+export default store
9
+export const useModel = store.useModel
10
+export const addModel = store.addModel
11
+export const removeModel = store.removeModel
12
+export const Provider = store.Provider

+ 33
- 0
src/store/models/system.js ファイルの表示

@@ -0,0 +1,33 @@
1
+import { useCallback } from "react";
2
+import { useState } from "react";
3
+
4
+const setRootCssVar = (key, val) => {
5
+  document.documentElement.style.setProperty(key, val);
6
+}
7
+
8
+export default function useSystem() {
9
+  const [theme, setTheme] = useState('light');
10
+  const [config, setConfig] = useState({});
11
+
12
+  const updateTheme = useCallback((t) => {
13
+    setTheme(t);
14
+    switch (t) {
15
+      case 'dark':
16
+        setRootCssVar('--theme-color', '#001529');
17
+        setRootCssVar('--theme-front', '#fff');
18
+        break;
19
+      case 'light':
20
+      default:
21
+        setRootCssVar('--theme-color', '#fff');
22
+        setRootCssVar('--theme-front', '#000');
23
+        break;
24
+    }
25
+  }, [])
26
+
27
+  return {
28
+    theme,
29
+    updateTheme,
30
+    config,
31
+    setConfig,
32
+  }
33
+}

+ 32
- 0
vite.config.js ファイルの表示

@@ -0,0 +1,32 @@
1
+import { defineConfig } from 'vite'
2
+import path from "path"
3
+import react from '@vitejs/plugin-react'
4
+import vitePluginImp from 'vite-plugin-imp'
5
+
6
+// https://vitejs.dev/config/
7
+export default defineConfig({
8
+  plugins: [
9
+    react(),
10
+    vitePluginImp({
11
+      libList: [
12
+        {
13
+          libName: 'antd',
14
+          style: (name) => `antd/es/${name}/style`,
15
+        }
16
+      ]
17
+    })
18
+  ],
19
+  resolve: {
20
+    alias: [
21
+      { find: '@', replacement: path.resolve(__dirname, 'src') },
22
+    ],
23
+  },
24
+  css: {
25
+    preprocessorOptions: {
26
+      less: {
27
+        // modifyVars: { 'primary-color': '#13c2c2' },
28
+        javascriptEnabled: true,
29
+      },
30
+    },
31
+  },
32
+})