├── .browserslistrc
├── .editorconfig
├── .github
└── workflows
│ ├── lint-ci.yml
│ └── sync.yml
├── .gitignore
├── .husky
├── .gitignore
├── commit-msg
└── pre-commit
├── .huxy
└── app.configs.js
├── .npmrc
├── .prettierignore
├── .versionrc.js
├── CHANGELOG.md
├── LICENSE
├── README.md
├── __tests__
└── add.test.js
├── app
├── apis
│ ├── apiList.js
│ ├── fetcher.js
│ ├── getApis.js
│ ├── report
│ │ ├── browserInfo.js
│ │ ├── fetchError.js
│ │ ├── pageError.js
│ │ ├── report.js
│ │ ├── reportButtom.jsx
│ │ └── routeChange.js
│ └── userMock.js
├── app.jsx
├── assets
│ ├── icons
│ │ ├── agile.png
│ │ ├── algorithm.png
│ │ ├── analysis.png
│ │ ├── api.png
│ │ ├── basketball.png
│ │ ├── bigdata.png
│ │ ├── brain.png
│ │ ├── chat.png
│ │ ├── checkup.png
│ │ ├── code.png
│ │ ├── coder.png
│ │ ├── cogwheel.png
│ │ ├── control.png
│ │ ├── css.png
│ │ ├── dashboard.png
│ │ ├── data-analysis.png
│ │ ├── data-modelling.png
│ │ ├── debug.png
│ │ ├── diagram.png
│ │ ├── digital.png
│ │ ├── flow.png
│ │ ├── html.png
│ │ ├── js.png
│ │ ├── light.png
│ │ ├── line-chart.png
│ │ ├── manufacturing.png
│ │ ├── map.png
│ │ ├── monitoring.png
│ │ ├── not-found.png
│ │ ├── organization.png
│ │ ├── production.png
│ │ ├── programming.png
│ │ ├── screen.png
│ │ ├── setting.png
│ │ ├── simulation.png
│ │ ├── time.png
│ │ ├── trend.png
│ │ ├── web-analysis.png
│ │ ├── work-home.png
│ │ └── write.png
│ ├── images
│ │ ├── github.svg
│ │ ├── logo.png
│ │ ├── metamask.svg
│ │ ├── user
│ │ │ ├── 1.png
│ │ │ ├── 2.png
│ │ │ ├── 3.png
│ │ │ ├── 4.png
│ │ │ ├── 5.png
│ │ │ ├── 6.png
│ │ │ ├── 7.png
│ │ │ └── 8.png
│ │ ├── wx.jpg
│ │ └── zys.svg
│ ├── lang
│ │ ├── en.png
│ │ └── zh.png
│ ├── styles.less
│ └── var.less
├── build
│ ├── .spa
│ ├── favicon.png
│ ├── img
│ │ ├── img_00ed15c3.png
│ │ ├── img_05d91403.png
│ │ ├── img_0bd8fceb.png
│ │ ├── img_11f7f8e1.png
│ │ ├── img_18156581.png
│ │ ├── img_1bf88407.png
│ │ ├── img_2bc2ed04.png
│ │ ├── img_3b260126.png
│ │ ├── img_4512a22a.png
│ │ ├── img_4542f85f.png
│ │ ├── img_47f2615a.png
│ │ ├── img_4a88e074.png
│ │ ├── img_4c3443c3.png
│ │ ├── img_534c19b0.png
│ │ ├── img_67c69369.png
│ │ ├── img_80fa61e6.png
│ │ ├── img_85dda956.png
│ │ ├── img_8c276863.png
│ │ ├── img_987c0fad.png
│ │ ├── img_98c65923.jpg
│ │ ├── img_ac6bf8c0.jpg
│ │ ├── img_b8ad20df.png
│ │ ├── img_bb332316.png
│ │ ├── img_bdef7b6c.png
│ │ ├── img_c50c8ae6.png
│ │ ├── img_c8f41c35.png
│ │ ├── img_cb9d1666.png
│ │ ├── img_cdbb0313.png
│ │ ├── img_d9039ae8.png
│ │ ├── img_d9a29b56.png
│ │ ├── img_dc353f92.png
│ │ ├── img_dc6d2254.png
│ │ ├── img_e4fdac22.png
│ │ ├── img_eed84d91.png
│ │ ├── img_f2223441.png
│ │ └── img_f98c79fb.png
│ ├── index.html
│ ├── manifest.json
│ ├── robots.txt
│ ├── service-worker.js
│ └── src
│ │ └── images
│ │ ├── 144.png
│ │ ├── 192.png
│ │ ├── 512.png
│ │ └── 96.png
├── commons
│ ├── layout
│ │ ├── README.md
│ │ ├── components
│ │ │ ├── footer
│ │ │ │ ├── index.jsx
│ │ │ │ └── index.less
│ │ │ ├── mainTop
│ │ │ │ ├── index.jsx
│ │ │ │ └── index.less
│ │ │ ├── menuBottom
│ │ │ │ ├── index.jsx
│ │ │ │ └── index.less
│ │ │ ├── uiI18n
│ │ │ │ └── index.jsx
│ │ │ └── useFormatMenu
│ │ │ │ └── index.jsx
│ │ ├── configs.js
│ │ ├── index.jsx
│ │ ├── layout.jsx
│ │ └── utils
│ │ │ └── handleNavClick.js
│ └── styles
│ │ ├── base.less
│ │ ├── block.less
│ │ ├── common
│ │ ├── default.css
│ │ ├── icons.css
│ │ ├── resets.css
│ │ ├── style-block.less
│ │ ├── style-icon.less
│ │ └── tokens.css
│ │ ├── func
│ │ ├── angle.less
│ │ ├── arrow.less
│ │ ├── follow.less
│ │ └── tooltip.less
│ │ ├── global
│ │ └── index.less
│ │ └── index.less
├── components
│ ├── base
│ │ ├── button
│ │ │ ├── index.jsx
│ │ │ └── index.less
│ │ ├── checkbox
│ │ │ └── index.jsx
│ │ ├── input
│ │ │ ├── index.jsx
│ │ │ └── index.less
│ │ ├── menu
│ │ │ ├── index.jsx
│ │ │ └── index.less
│ │ ├── radio
│ │ │ └── index.jsx
│ │ ├── select
│ │ │ └── index.jsx
│ │ ├── textarea
│ │ │ ├── index.jsx
│ │ │ └── index.less
│ │ └── tooltip
│ │ │ └── index.jsx
│ ├── custom
│ │ ├── form.jsx
│ │ └── table.jsx
│ ├── customCollapse.jsx
│ ├── ellipsis.jsx
│ ├── fullScreen.jsx
│ ├── goBack.jsx
│ ├── icon.jsx
│ ├── icons
│ │ ├── add.jsx
│ │ ├── audio0.jsx
│ │ ├── audio1.jsx
│ │ ├── broom.jsx
│ │ ├── github.jsx
│ │ ├── image.jsx
│ │ ├── lock.jsx
│ │ ├── moon.jsx
│ │ ├── send.jsx
│ │ ├── sun.jsx
│ │ ├── user.jsx
│ │ ├── video.jsx
│ │ └── wechat.jsx
│ ├── intl.jsx
│ ├── maxSize.jsx
│ ├── notify.jsx
│ ├── panel
│ │ └── index.jsx
│ ├── row
│ │ └── index.jsx
│ ├── search.jsx
│ ├── searchForm
│ │ └── index.jsx
│ ├── settings
│ │ └── index.jsx
│ ├── skeletonContent
│ │ ├── index.jsx
│ │ └── index.less
│ └── themeModel.jsx
├── configs
│ ├── appTools.jsx
│ ├── index.js
│ ├── langList.jsx
│ ├── nav.jsx
│ ├── project.jsx
│ ├── router.js
│ ├── theme.js
│ └── themes
│ │ ├── dark.js
│ │ ├── dark1.js
│ │ ├── index.js
│ │ ├── light.js
│ │ ├── light1.js
│ │ ├── portal.js
│ │ ├── portal1.js
│ │ └── themes.js
├── globals
│ ├── getRouterAuth.js
│ └── registerPwa.js
├── hooks
│ ├── useFetchList.jsx
│ ├── useGetI18ns.jsx
│ ├── useGetProfile.jsx
│ └── useHandleList.jsx
├── i18ns
│ ├── en
│ │ ├── index.js
│ │ ├── login.js
│ │ ├── main.js
│ │ ├── nav.js
│ │ ├── router.js
│ │ └── theme.js
│ └── zh
│ │ ├── index.js
│ │ ├── login.js
│ │ ├── main.js
│ │ ├── nav.js
│ │ ├── router.js
│ │ └── theme.js
├── index.jsx
├── models
│ ├── animateObjs.js
│ ├── circleRing.jsx
│ ├── cssModels.js
│ ├── icons.js
│ ├── icons
│ │ ├── agile.png
│ │ ├── algorithm.png
│ │ ├── analysis.png
│ │ ├── api.png
│ │ ├── brain.png
│ │ ├── chat.png
│ │ ├── coder.png
│ │ ├── control.png
│ │ ├── dashboard.png
│ │ ├── data-analysis.png
│ │ ├── debug.png
│ │ ├── diagram.png
│ │ ├── digital.png
│ │ ├── light.png
│ │ ├── manufacturing.png
│ │ ├── monitoring.png
│ │ ├── not-found.png
│ │ ├── programming.png
│ │ ├── screen.png
│ │ ├── simulation.png
│ │ ├── trend.png
│ │ ├── web-analysis.png
│ │ └── write.png
│ ├── models.js
│ └── objs.js
├── public
│ ├── .spa
│ ├── favicon.png
│ ├── index.html
│ ├── manifest.json
│ ├── robots.txt
│ └── src
│ │ └── images
│ │ ├── 144.png
│ │ ├── 192.png
│ │ ├── 512.png
│ │ └── 96.png
├── routes
│ ├── defaultPermList.js
│ ├── index.js
│ ├── routerComp
│ │ ├── dynamicRoutes.js
│ │ └── staticRoutes.js
│ └── whiteList.js
├── store
│ ├── index.js
│ ├── names.js
│ └── stores.js
├── sw
│ └── index.js
├── utils
│ ├── configs.js
│ ├── confirmDesignPage.js
│ ├── formatTree.js
│ ├── getI18n.js
│ ├── getLang.js
│ ├── getRouterCfgs.js
│ ├── getTheme.js
│ ├── icons.js
│ ├── isAdmin.js
│ ├── patterns.js
│ ├── rules.js
│ ├── setStyleVar.js
│ ├── sizeRules.js
│ ├── sysThemeMode.js
│ └── utils.js
└── views
│ ├── 404
│ ├── index.jsx
│ └── index.less
│ ├── layout
│ ├── routes.js
│ └── src
│ │ └── index.jsx
│ ├── message
│ ├── routes.js
│ └── src
│ │ └── index.jsx
│ ├── payer
│ ├── routes.js
│ └── src
│ │ └── count
│ │ ├── ali.png
│ │ ├── member.jsx
│ │ ├── member.less
│ │ ├── order.jsx
│ │ ├── pay.jsx
│ │ ├── pay.less
│ │ └── wechat.png
│ ├── playground
│ ├── routes.js
│ └── src
│ │ ├── canvas
│ │ ├── 1.jpg
│ │ ├── draw.js
│ │ ├── drawText.js
│ │ ├── index.jsx
│ │ └── index.less
│ │ ├── configList
│ │ ├── configs.js
│ │ ├── getColumns.jsx
│ │ ├── mock
│ │ │ ├── data.js
│ │ │ ├── index.js
│ │ │ └── utils.js
│ │ ├── routes.js
│ │ └── src
│ │ │ ├── add.jsx
│ │ │ ├── auth.jsx
│ │ │ ├── index.jsx
│ │ │ ├── index.less
│ │ │ └── searchList
│ │ │ ├── formList.jsx
│ │ │ ├── index.jsx
│ │ │ └── list
│ │ │ ├── autoSizeList.jsx
│ │ │ ├── wrapList.jsx
│ │ │ └── wrapTable.jsx
│ │ ├── functions
│ │ ├── icons
│ │ │ ├── index.jsx
│ │ │ └── index.less
│ │ ├── modal
│ │ │ └── index.jsx
│ │ ├── panel
│ │ │ ├── index.jsx
│ │ │ └── index.less
│ │ ├── styles
│ │ │ ├── config.js
│ │ │ └── index.jsx
│ │ └── tools
│ │ │ └── index.jsx
│ │ ├── materials
│ │ ├── animation
│ │ │ └── index.jsx
│ │ ├── border
│ │ │ └── index.jsx
│ │ ├── chart
│ │ │ └── index.jsx
│ │ ├── shape
│ │ │ ├── index.jsx
│ │ │ └── taiji
│ │ │ │ ├── bagua
│ │ │ │ ├── gua
│ │ │ │ │ ├── configs.js
│ │ │ │ │ ├── index.jsx
│ │ │ │ │ └── index.less
│ │ │ │ ├── index.jsx
│ │ │ │ └── yao
│ │ │ │ │ ├── index.jsx
│ │ │ │ │ └── index.less
│ │ │ │ ├── index.jsx
│ │ │ │ └── index.less
│ │ └── text
│ │ │ └── index.jsx
│ │ ├── page
│ │ ├── routes.js
│ │ └── src
│ │ │ └── index.jsx
│ │ └── suspense
│ │ ├── errorboundary.jsx
│ │ ├── index.jsx
│ │ └── suspenseFns.js
│ └── user
│ ├── configs.js
│ ├── routes.js
│ └── src
│ ├── index.jsx
│ ├── index.less
│ ├── login.jsx
│ ├── profile.jsx
│ ├── setNewPwd.jsx
│ ├── signup.jsx
│ └── verifyEmail.jsx
├── babel.config.js
├── commitlint.config.js
├── doc
├── functions.md
├── src
│ ├── api.png
│ ├── apiTest.png
│ ├── auth.png
│ ├── demand.png
│ ├── doc.png
│ ├── editDemand.png
│ ├── email.png
│ ├── file.png
│ ├── lang.png
│ ├── layout.png
│ ├── log.png
│ ├── member.png
│ ├── message.png
│ ├── monitor.png
│ ├── order.png
│ ├── pageDesign.png
│ ├── pageView.png
│ ├── profile.png
│ ├── project.png
│ ├── router.png
│ ├── theme.png
│ └── user.png
└── tools.md
├── eslint.config.js
├── jest.config.js
├── package.json
├── postcss.config.js
├── prettier.config.js
└── stylelint.config.js
/.browserslistrc:
--------------------------------------------------------------------------------
1 | defaults
2 | not ie < 11
3 | last 2 versions
4 | > 1%
5 | last 2 iOS versions
6 | not dead
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 2
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
--------------------------------------------------------------------------------
/.github/workflows/lint-ci.yml:
--------------------------------------------------------------------------------
1 | name: Lint CI
2 | on:
3 | push:
4 | branches:
5 | - develop
6 | jobs:
7 | lint:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/checkout@v3
11 | - name: Install
12 | run: npm i
13 | - name: Lint
14 | run: npm run lint && npm run test
--------------------------------------------------------------------------------
/.github/workflows/sync.yml:
--------------------------------------------------------------------------------
1 | name: Sync to gitee
2 | on:
3 | push:
4 | branches:
5 | - develop
6 | jobs:
7 | sync:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: 同步到 gitee
11 | uses: wearerequired/git-mirror-action@master
12 | env:
13 | SSH_PRIVATE_KEY: ${{ secrets.GITEE_SERVER_KEY }}
14 | with:
15 | source-repo: git@github.com:ahyiru/huxy-admin.git
16 | destination-repo: git@gitee.com:yiru/huxy-admin.git
17 | - name: 部署到 Gitee Pages
18 | uses: yanglbme/gitee-pages-action@main
19 | with:
20 | gitee-username: yiru
21 | gitee-password: ${{ secrets.GITEE_SERVER_PASSWORD }}
22 | gitee-repo: yiru/huxy-admin
23 | branch: develop
24 | directory: app/build
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage
16 |
17 | # nyc test coverage
18 | .nyc_output
19 |
20 | # node-waf configuration
21 | .lock-wscript
22 |
23 | # Optional npm cache directory
24 | .npm
25 |
26 | # Optional REPL history
27 | .node_repl_history
28 |
29 | # Compiled binary addons (http://nodejs.org/api/addons.html)
30 | build/Release
31 |
32 | # Dependency directories
33 | node_modules
34 | jspm_packages
35 | bower_components
36 | typings
37 |
38 | # Editors
39 | .idea
40 | *.iml
41 |
42 | # OS metadata
43 | .DS_Store
44 | Thumbs.db
45 |
46 | # test
47 | __snapshots__
48 |
49 | # package-lock.json
50 | package-lock.json
51 |
52 | # pnpm-lock.yaml
53 | pnpm-lock.yaml
54 |
55 | # build
56 | dist
57 | build
58 |
59 | # redis
60 | *.rdb
61 |
62 | deadcode.json
63 |
--------------------------------------------------------------------------------
/.husky/.gitignore:
--------------------------------------------------------------------------------
1 | _
2 |
--------------------------------------------------------------------------------
/.husky/commit-msg:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # . "$(dirname "$0")/_/husky.sh"
3 |
4 | npx commitlint -e $1
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # . "$(dirname "$0")/_/husky.sh"
3 |
4 | npm run lint
5 |
6 | npm run test
--------------------------------------------------------------------------------
/.huxy/app.configs.js:
--------------------------------------------------------------------------------
1 | import DeadCodePlugin from 'webpack-deadcode-plugin';
2 |
3 | const app = {
4 | // HOST: 'http://localhost',
5 | PORT: 3000,
6 | PROD_PORT: 3001,
7 | PUBLIC_DIR: 'public',
8 | BUILD_DIR: 'build',
9 | DEV_ROOT_DIR: '/',
10 | PROD_ROOT_DIR: '/huxy-admin',
11 | projectName: '...',
12 | /* PROXY: {
13 | url: 'http://api.ihuxy.com',
14 | prefix: '/api',
15 | }, */
16 | envConfigs: {
17 | // 全局环境变量
18 | name: '项目名',
19 | _id: '其它属性',
20 | },
21 | };
22 |
23 | export default {
24 | app,
25 | webpack: (rootPath, appPath) => ({
26 | dev: {
27 | plugins: [
28 | new DeadCodePlugin({
29 | patterns: [`${appPath}/**/*.(js|jsx|css|less|json|png|jpg|jpeg)`],
30 | exclude: ['**/node_modules/**', '**/build/**', '**/draft/**'],
31 | log: 'none',
32 | exportJSON: rootPath,
33 | }),
34 | ],
35 | },
36 | prod: {
37 | copy: [
38 | {
39 | from: `${appPath}/public/.spa`,
40 | to: `${appPath}/build/.spa`,
41 | },
42 | ],
43 | },
44 | }),
45 | };
46 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | legacy-peer-deps = true
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | **/node_modules
2 | **/coverage
3 | **/build
4 | **/draft
5 |
--------------------------------------------------------------------------------
/.versionrc.js:
--------------------------------------------------------------------------------
1 | import configs from '@huxy/pack/config/version';
2 |
3 | export default configs({
4 | // customCfgs
5 | });
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 yiru
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/__tests__/add.test.js:
--------------------------------------------------------------------------------
1 | const sum = (a, b) => a + b;
2 |
3 | describe('add', () => {
4 | it ('adds 1 + 2 to equal 3', () => {
5 | expect(sum(1, 2)).toBe(3);
6 | });
7 | });
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/apis/apiList.js:
--------------------------------------------------------------------------------
1 | import fetcher from '@app/apis/report/fetchError';
2 | import {dlApi, suspense} from '@app/apis/fetcher';
3 | import getApis from '@app/apis/getApis';
4 | import {allUserMock, allUserSuspenseMock} from '@app/apis/userMock';
5 |
6 | const apiList = {
7 | allUserMock,
8 | };
9 |
10 | const suspenseApis = {
11 | allUserSuspenseMock,
12 | };
13 |
14 | const getSuspense = apis => {
15 | const susList = apis.filter(api => ['profile', 'allUser'].includes(api.name));
16 | susList.map(sus => {
17 | const {name, fnName, dataType, url, isDl, ...restApi} = sus;
18 | const fetchFn = isDl ? dlApi : suspense;
19 | const funcName = fnName ?? `${name}Suspense`;
20 | const paramsKey = dataType || restApi.method === 'post' ? 'data' : 'params';
21 | suspenseApis[funcName] = (data, ...rest) => fetchFn({...restApi, url: typeof url === 'function' ? url(data) : url, [paramsKey]: data, ...rest});
22 | });
23 | };
24 |
25 | export {suspenseApis};
26 |
27 | const getList = async () => {
28 | const {result} = await getApis();
29 | return result?.list ?? [];
30 | };
31 |
32 | export const getApiFn = async () => {
33 | let apis = [];
34 | try {
35 | apis = await getList();
36 | } catch (err) {}
37 | apis.map(api => {
38 | const {name, fnName, dataType, url, isDl, ...restApi} = api;
39 | const fetchFn = isDl ? dlApi : fetcher;
40 | const funcName = fnName ?? `${name}Fn`;
41 | const paramsKey = dataType || (restApi.method === 'post' ? 'data' : 'params');
42 | apiList[funcName] = (data, ...rest) => fetchFn({...restApi, url: typeof url === 'function' ? url(data) : url, [paramsKey]: data, ...rest});
43 | });
44 | getSuspense(apis);
45 | return apiList;
46 | };
47 |
48 | export default apiList;
49 |
--------------------------------------------------------------------------------
/app/apis/getApis.js:
--------------------------------------------------------------------------------
1 | import fetcher from './fetcher';
2 | import {defProject} from '@app/configs';
3 |
4 | // const getApis = () => fetcher({url: '/api/list', params: {projectId: defProject?._id, current: 1, size: 100}});
5 |
6 | const apiList = projectId => [
7 | {
8 | name: 'login',
9 | url: '/auth/login',
10 | method: 'post',
11 | },
12 | {
13 | name: 'logout',
14 | url: '/auth/logout',
15 | },
16 | {
17 | name: 'signup',
18 | url: '/auth/signup',
19 | method: 'post',
20 | },
21 | {
22 | name: 'profile',
23 | url: '/users/profile',
24 | method: 'get',
25 | },
26 | {
27 | name: 'allUser',
28 | url: '/users/allUser',
29 | },
30 | ];
31 |
32 | const getApis = () => ({result: {list: apiList(defProject?._id)}});
33 |
34 | export default getApis;
35 |
--------------------------------------------------------------------------------
/app/apis/report/browserInfo.js:
--------------------------------------------------------------------------------
1 | import {getOsInfo, getExplore} from '@huxy/utils';
2 | import {browserRouter} from '@app/configs';
3 |
4 | import pkg from '../../../package.json';
5 |
6 | const {type: osType, version: osVersion, model: osModel} = getOsInfo();
7 | const {type: browserType, version: browserVersion} = getExplore();
8 |
9 | const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
10 |
11 | const info = {
12 | osType,
13 | osVersion,
14 | osModel,
15 | browserType,
16 | browserVersion,
17 | language: window.navigator.language,
18 | netType: connection?.type,
19 | evn: browserRouter ? 'prod' : 'dev',
20 | appName: pkg.name,
21 | appVersion: pkg.version,
22 | };
23 |
24 | export default info;
25 |
--------------------------------------------------------------------------------
/app/apis/report/fetchError.js:
--------------------------------------------------------------------------------
1 | import fetcher from '@app/apis/fetcher';
2 |
3 | import report from './report';
4 |
5 | const whiteCode = [401, 403, 429];
6 | const whitePath = ['/report', '/auth'];
7 |
8 | const fetch = props =>
9 | fetcher(props).catch(err => {
10 | const {url} = props;
11 | const isPermission = !whiteCode.includes(err.code);
12 | const authedPath = !whitePath.find(path => url.includes(`${path}/`));
13 | if (isPermission && authedPath) {
14 | report({actionType: 'fetchError', text: err.message, value: url});
15 | }
16 | throw Error(err.message);
17 | });
18 |
19 | export default fetch;
20 |
--------------------------------------------------------------------------------
/app/apis/report/pageError.js:
--------------------------------------------------------------------------------
1 | import {HandleError} from '@huxy/components';
2 |
3 | import report from './report';
4 |
5 | const pageError = ({error}) => {
6 | const errStack = error?.message?.slice(0, 120).split('. ').slice(0, 2).join('. ');
7 | report({actionType: 'pageError', text: errStack});
8 | };
9 |
10 | const errorBoundary = props => ;
11 |
12 | export default errorBoundary;
13 |
--------------------------------------------------------------------------------
/app/apis/report/report.js:
--------------------------------------------------------------------------------
1 | import {getRoute} from '@huxy/router';
2 |
3 | import {browserRouter} from '@app/configs';
4 |
5 | import {isAuthed} from '@app/utils/utils';
6 |
7 | import apiList from '@app/apis/apiList';
8 |
9 | import info from './browserInfo';
10 |
11 | const report = params => {
12 | if (!browserRouter || !isAuthed()) {
13 | return;
14 | }
15 | const routeInfo = getRoute();
16 | const routes = routeInfo ? routeInfo.current.slice(-1)[0] ?? {} : {};
17 | const {path, name, ...restParams} = params;
18 | const currentPath = routes.path ?? path ?? '';
19 | const reportInfo = {
20 | ...info,
21 | ...restParams,
22 | route: browserRouter ? currentPath : currentPath.slice(1),
23 | routeName: routes.name ?? name,
24 | };
25 | apiList.addReportFn?.(reportInfo);
26 | };
27 |
28 | export default report;
29 |
--------------------------------------------------------------------------------
/app/apis/report/reportButtom.jsx:
--------------------------------------------------------------------------------
1 | import Button from '@app/components/base/button';
2 |
3 | import report from './report';
4 |
5 | const ReportButton = props => {
6 | const {value, label, text, description, onClick, ...rest} = props;
7 | const handleClick = e => {
8 | report({
9 | text: text || props.children,
10 | value,
11 | label,
12 | description,
13 | type: 'click',
14 | });
15 | onClick?.(e);
16 | };
17 | return ;
18 | };
19 |
20 | export default ReportButton;
21 |
--------------------------------------------------------------------------------
/app/apis/report/routeChange.js:
--------------------------------------------------------------------------------
1 | import {uuidv4} from '@huxy/utils';
2 |
3 | import report from './report';
4 |
5 | let prevUuid = null;
6 |
7 | window.addEventListener(
8 | 'beforeunload',
9 | e => {
10 | const isLogin = e.target.location.pathname.indexOf('/user/') === 0 || e.target.location.hash.indexOf('#/user/') === 0;
11 | if (!isLogin) {
12 | report({actionType: 'close', prevUuid});
13 | }
14 | },
15 | false,
16 | );
17 |
18 | const routeReport = params => {
19 | const uuid = uuidv4();
20 | report({actionType: 'routeChange', uuid, prevUuid, ...params});
21 | prevUuid = uuid;
22 | };
23 |
24 | export default routeReport;
25 |
--------------------------------------------------------------------------------
/app/app.jsx:
--------------------------------------------------------------------------------
1 | import {useEffect} from 'react';
2 | import {useRouter} from '@huxy/router';
3 | import {Spinner} from '@huxy/components';
4 | import {storage} from '@huxy/utils';
5 | import routerCfgs from '@app/configs/router';
6 | import sysThemeMode from '@app/utils/sysThemeMode';
7 | import getTheme from '@app/utils/getTheme';
8 | import getI18n from '@app/utils/getI18n';
9 | import useGetI18ns from '@app/hooks/useGetI18ns';
10 | import useGetProfile from '@app/hooks/useGetProfile';
11 | import {isAuthed} from '@app/utils/utils';
12 | import getRouterCfgs from '@app/utils/getRouterCfgs';
13 | import setStyleVar from '@app/utils/setStyleVar';
14 | import {langStore, themeStore} from '@app/store/stores';
15 |
16 | const ConfigProvider = ({routerCfgs}) => {
17 | const {output, loading, updateRouter} = useRouter(routerCfgs);
18 | useEffect(() => {
19 | const cancelTheme = themeStore.subscribe(setStyleVar);
20 | themeStore.setState(getTheme());
21 | sysThemeMode(themeStore.setState);
22 | const cancelLang = langStore.subscribe(async lang => {
23 | storage.set('language', lang);
24 | await getI18n();
25 | themeStore.setState(getTheme());
26 | updateRouter(getRouterCfgs());
27 | });
28 | return () => {
29 | cancelLang();
30 | cancelTheme();
31 | };
32 | }, []);
33 | return (
34 | <>
35 | {output}
36 | {loading ? : null}
37 | >
38 | );
39 | };
40 |
41 | const AuthedApp = props => {
42 | const [loading] = useGetProfile();
43 | if (loading) {
44 | return ;
45 | }
46 | return ;
47 | };
48 |
49 | const App = () => {
50 | const [loading] = useGetI18ns();
51 | if (loading) {
52 | return ;
53 | }
54 | return isAuthed() ? : ;
55 | };
56 |
57 | export default App;
58 |
--------------------------------------------------------------------------------
/app/assets/icons/agile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/agile.png
--------------------------------------------------------------------------------
/app/assets/icons/algorithm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/algorithm.png
--------------------------------------------------------------------------------
/app/assets/icons/analysis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/analysis.png
--------------------------------------------------------------------------------
/app/assets/icons/api.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/api.png
--------------------------------------------------------------------------------
/app/assets/icons/basketball.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/basketball.png
--------------------------------------------------------------------------------
/app/assets/icons/bigdata.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/bigdata.png
--------------------------------------------------------------------------------
/app/assets/icons/brain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/brain.png
--------------------------------------------------------------------------------
/app/assets/icons/chat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/chat.png
--------------------------------------------------------------------------------
/app/assets/icons/checkup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/checkup.png
--------------------------------------------------------------------------------
/app/assets/icons/code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/code.png
--------------------------------------------------------------------------------
/app/assets/icons/coder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/coder.png
--------------------------------------------------------------------------------
/app/assets/icons/cogwheel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/cogwheel.png
--------------------------------------------------------------------------------
/app/assets/icons/control.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/control.png
--------------------------------------------------------------------------------
/app/assets/icons/css.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/css.png
--------------------------------------------------------------------------------
/app/assets/icons/dashboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/dashboard.png
--------------------------------------------------------------------------------
/app/assets/icons/data-analysis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/data-analysis.png
--------------------------------------------------------------------------------
/app/assets/icons/data-modelling.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/data-modelling.png
--------------------------------------------------------------------------------
/app/assets/icons/debug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/debug.png
--------------------------------------------------------------------------------
/app/assets/icons/diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/diagram.png
--------------------------------------------------------------------------------
/app/assets/icons/digital.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/digital.png
--------------------------------------------------------------------------------
/app/assets/icons/flow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/flow.png
--------------------------------------------------------------------------------
/app/assets/icons/html.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/html.png
--------------------------------------------------------------------------------
/app/assets/icons/js.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/js.png
--------------------------------------------------------------------------------
/app/assets/icons/light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/light.png
--------------------------------------------------------------------------------
/app/assets/icons/line-chart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/line-chart.png
--------------------------------------------------------------------------------
/app/assets/icons/manufacturing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/manufacturing.png
--------------------------------------------------------------------------------
/app/assets/icons/map.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/map.png
--------------------------------------------------------------------------------
/app/assets/icons/monitoring.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/monitoring.png
--------------------------------------------------------------------------------
/app/assets/icons/not-found.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/not-found.png
--------------------------------------------------------------------------------
/app/assets/icons/organization.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/organization.png
--------------------------------------------------------------------------------
/app/assets/icons/production.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/production.png
--------------------------------------------------------------------------------
/app/assets/icons/programming.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/programming.png
--------------------------------------------------------------------------------
/app/assets/icons/screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/screen.png
--------------------------------------------------------------------------------
/app/assets/icons/setting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/setting.png
--------------------------------------------------------------------------------
/app/assets/icons/simulation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/simulation.png
--------------------------------------------------------------------------------
/app/assets/icons/time.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/time.png
--------------------------------------------------------------------------------
/app/assets/icons/trend.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/trend.png
--------------------------------------------------------------------------------
/app/assets/icons/web-analysis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/web-analysis.png
--------------------------------------------------------------------------------
/app/assets/icons/work-home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/work-home.png
--------------------------------------------------------------------------------
/app/assets/icons/write.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/icons/write.png
--------------------------------------------------------------------------------
/app/assets/images/github.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/assets/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/images/logo.png
--------------------------------------------------------------------------------
/app/assets/images/user/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/images/user/1.png
--------------------------------------------------------------------------------
/app/assets/images/user/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/images/user/2.png
--------------------------------------------------------------------------------
/app/assets/images/user/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/images/user/3.png
--------------------------------------------------------------------------------
/app/assets/images/user/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/images/user/4.png
--------------------------------------------------------------------------------
/app/assets/images/user/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/images/user/5.png
--------------------------------------------------------------------------------
/app/assets/images/user/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/images/user/6.png
--------------------------------------------------------------------------------
/app/assets/images/user/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/images/user/7.png
--------------------------------------------------------------------------------
/app/assets/images/user/8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/images/user/8.png
--------------------------------------------------------------------------------
/app/assets/images/wx.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/images/wx.jpg
--------------------------------------------------------------------------------
/app/assets/lang/en.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/lang/en.png
--------------------------------------------------------------------------------
/app/assets/lang/zh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/assets/lang/zh.png
--------------------------------------------------------------------------------
/app/assets/var.less:
--------------------------------------------------------------------------------
1 | @mainHeight: calc(var(--containerHeight) - var(--footerHeight) - var(--topHeight) - var(--breadHeight) - var(--frame-spacing) * 2);
2 |
--------------------------------------------------------------------------------
/app/build/.spa:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/.spa
--------------------------------------------------------------------------------
/app/build/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/favicon.png
--------------------------------------------------------------------------------
/app/build/img/img_00ed15c3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_00ed15c3.png
--------------------------------------------------------------------------------
/app/build/img/img_05d91403.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_05d91403.png
--------------------------------------------------------------------------------
/app/build/img/img_0bd8fceb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_0bd8fceb.png
--------------------------------------------------------------------------------
/app/build/img/img_11f7f8e1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_11f7f8e1.png
--------------------------------------------------------------------------------
/app/build/img/img_18156581.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_18156581.png
--------------------------------------------------------------------------------
/app/build/img/img_1bf88407.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_1bf88407.png
--------------------------------------------------------------------------------
/app/build/img/img_2bc2ed04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_2bc2ed04.png
--------------------------------------------------------------------------------
/app/build/img/img_3b260126.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_3b260126.png
--------------------------------------------------------------------------------
/app/build/img/img_4512a22a.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_4512a22a.png
--------------------------------------------------------------------------------
/app/build/img/img_4542f85f.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_4542f85f.png
--------------------------------------------------------------------------------
/app/build/img/img_47f2615a.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_47f2615a.png
--------------------------------------------------------------------------------
/app/build/img/img_4a88e074.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_4a88e074.png
--------------------------------------------------------------------------------
/app/build/img/img_4c3443c3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_4c3443c3.png
--------------------------------------------------------------------------------
/app/build/img/img_534c19b0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_534c19b0.png
--------------------------------------------------------------------------------
/app/build/img/img_67c69369.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_67c69369.png
--------------------------------------------------------------------------------
/app/build/img/img_80fa61e6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_80fa61e6.png
--------------------------------------------------------------------------------
/app/build/img/img_85dda956.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_85dda956.png
--------------------------------------------------------------------------------
/app/build/img/img_8c276863.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_8c276863.png
--------------------------------------------------------------------------------
/app/build/img/img_987c0fad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_987c0fad.png
--------------------------------------------------------------------------------
/app/build/img/img_98c65923.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_98c65923.jpg
--------------------------------------------------------------------------------
/app/build/img/img_ac6bf8c0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_ac6bf8c0.jpg
--------------------------------------------------------------------------------
/app/build/img/img_b8ad20df.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_b8ad20df.png
--------------------------------------------------------------------------------
/app/build/img/img_bb332316.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_bb332316.png
--------------------------------------------------------------------------------
/app/build/img/img_bdef7b6c.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_bdef7b6c.png
--------------------------------------------------------------------------------
/app/build/img/img_c50c8ae6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_c50c8ae6.png
--------------------------------------------------------------------------------
/app/build/img/img_c8f41c35.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_c8f41c35.png
--------------------------------------------------------------------------------
/app/build/img/img_cb9d1666.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_cb9d1666.png
--------------------------------------------------------------------------------
/app/build/img/img_cdbb0313.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_cdbb0313.png
--------------------------------------------------------------------------------
/app/build/img/img_d9039ae8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_d9039ae8.png
--------------------------------------------------------------------------------
/app/build/img/img_d9a29b56.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_d9a29b56.png
--------------------------------------------------------------------------------
/app/build/img/img_dc353f92.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_dc353f92.png
--------------------------------------------------------------------------------
/app/build/img/img_dc6d2254.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_dc6d2254.png
--------------------------------------------------------------------------------
/app/build/img/img_e4fdac22.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_e4fdac22.png
--------------------------------------------------------------------------------
/app/build/img/img_eed84d91.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_eed84d91.png
--------------------------------------------------------------------------------
/app/build/img/img_f2223441.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_f2223441.png
--------------------------------------------------------------------------------
/app/build/img/img_f98c79fb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/img/img_f98c79fb.png
--------------------------------------------------------------------------------
/app/build/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "huxy",
3 | "short_name": "huxy",
4 | "description": "huxy",
5 | "lang": "cn",
6 | "display": "standalone",
7 | "orientation": "any",
8 | "start_url": ".",
9 | "theme_color": "#313131",
10 | "background_color": "#313131",
11 | "icons": [
12 | {
13 | "src": "./src/images/96.png",
14 | "sizes": "96x96",
15 | "type": "image/png"
16 | },
17 | {
18 | "src": "./src/images/144.png",
19 | "sizes": "144x144",
20 | "type": "image/png"
21 | },
22 | {
23 | "src": "./src/images/192.png",
24 | "sizes": "192x192",
25 | "type": "image/png",
26 | "purpose": "any maskable"
27 | },
28 | {
29 | "src": "./src/images/512.png",
30 | "sizes": "512x512",
31 | "type": "image/png"
32 | }
33 | ]
34 | }
35 |
--------------------------------------------------------------------------------
/app/build/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow: /img/
--------------------------------------------------------------------------------
/app/build/src/images/144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/src/images/144.png
--------------------------------------------------------------------------------
/app/build/src/images/192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/src/images/192.png
--------------------------------------------------------------------------------
/app/build/src/images/512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/src/images/512.png
--------------------------------------------------------------------------------
/app/build/src/images/96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/build/src/images/96.png
--------------------------------------------------------------------------------
/app/commons/layout/README.md:
--------------------------------------------------------------------------------
1 | ## layout
2 |
3 | [](https://github.com/ahyiru/layout/blob/develop/LICENSE)
4 | [](https://www.npmjs.com/package/@huxy/layout)
5 | [](https://app.travis-ci.com/github/ahyiru/layout)
6 | [](http://ihuxy.com/)
7 |
8 | ### 功能
9 |
10 | 该 `layout` 框架是传统的中后台 `layout` 模板,提供了头部导航栏、菜单栏、底部栏、logo、面包屑等。
11 |
12 | - 支持菜单栏展示、隐藏,展开、缩小等配置。
13 | - 支持左侧垂直菜单、顶部水平菜单、水平垂直菜单组合。
14 | - 支持自适应屏幕。根据屏幕大小展开、缩小、隐藏菜单,头部信息展示方式切换。
15 | - 支持 nav 导航栏自定义。自定义导航信息、下拉信息、点击事件等。
16 |
17 | ### 使用
18 |
19 | 常用配置:
20 |
21 | - menuType: vertical | horizontal | compose, 默认 vertical。横纵菜单配置。
22 | - MenuBottom:菜单底部内容
23 | - MainTop:主页顶部内容。如:面包屑。
24 | - Footer:页面底部内容。
25 | - headerStyle、asideStyle、menuStyle、contentStyle:样式。
26 | - handleNavClick:导航栏点击事件。
27 | - leftList、rightList:左侧导航栏、右侧导航栏配置。
28 | - logo、title、Link:logo、标题、Link 组件 注入。
29 | - menuAnimate: Boolean | String, 默认 false。
30 |
--------------------------------------------------------------------------------
/app/commons/layout/components/footer/index.jsx:
--------------------------------------------------------------------------------
1 | import {Link} from '@huxy/router';
2 | import {getIntls} from '@app/components/intl';
3 |
4 | import './index.less';
5 |
6 | const Index = props => {
7 | const i18ns = getIntls('nav.footer', {});
8 | return (
9 |
10 |
18 |
19 | -
20 |
21 | {i18ns.about}
22 |
23 |
24 | -
25 |
26 | {i18ns.team}
27 |
28 |
29 | -
30 |
31 | {i18ns.contact}
32 |
33 |
34 |
35 |
36 | );
37 | };
38 | export default Index;
39 |
--------------------------------------------------------------------------------
/app/commons/layout/components/footer/index.less:
--------------------------------------------------------------------------------
1 | .footer-wrap {
2 | height: 100%;
3 | overflow: hidden;
4 | padding: 0 var(--frame-spacing);
5 | a,
6 | .link {
7 | padding: 0 6px;
8 | }
9 | .copyright {
10 | float: left;
11 | }
12 | .link-list {
13 | margin: 0;
14 | float: right;
15 | overflow: hidden;
16 | li {
17 | float: left;
18 | }
19 | }
20 | @media screen and (max-width: 768px) {
21 | .link-list {
22 | display: none;
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/app/commons/layout/components/mainTop/index.jsx:
--------------------------------------------------------------------------------
1 | import {Link} from '@huxy/router';
2 | // import TopRight from './topRight';
3 | import './index.less';
4 |
5 | const Index = ({current, Right}) => {
6 | current = current.filter(v => v.name);
7 | const name = (
8 |
9 |
10 | {current.slice(-1)[0]?.name}
11 |
12 |
13 | );
14 | const bread = current.map(({path, name}) => (
15 |
16 |
17 | {name}
18 |
19 |
20 | ));
21 | const isRightBread = current.length > 1;
22 | const leftBar = isRightBread ? name : bread;
23 | const rightBar = Right ? : isRightBread ? bread : null;
24 | return (
25 |
29 | );
30 | };
31 |
32 | export default Index;
33 |
--------------------------------------------------------------------------------
/app/commons/layout/components/mainTop/index.less:
--------------------------------------------------------------------------------
1 | .clear {
2 | &::after {
3 | clear: both;
4 | content: '';
5 | display: block;
6 | height: 0;
7 | visibility: hidden;
8 | }
9 | }
10 | .main-top {
11 | overflow: hidden;
12 | z-index: 3;
13 | // position:sticky;
14 | // top:calc(var(--headerHeight) + var(--frame-spacing));
15 | height: var(--breadHeight);
16 | line-height: var(--breadHeight);
17 | width: 100%;
18 | // background:var(--panelBgColor);
19 | // box-shadow:0 0 4px 2px rgba(0,0,0,.1);
20 | padding: 0 var(--frame-spacing);
21 | padding-top: 0.6rem;
22 | > ul {
23 | height: calc(var(--breadHeight) - var(--frame-spacing));
24 | line-height: calc(var(--breadHeight) - var(--frame-spacing));
25 | .clear();
26 | li {
27 | display: block;
28 | position: relative;
29 | .link {
30 | padding: 2px 8px;
31 | }
32 | .btn-bar {
33 | color: #f0f0f0;
34 | padding: 2px 14px;
35 | border: 1px solid var(--blue1);
36 | border-radius: 2px;
37 | background-color: var(--blue2);
38 | }
39 | }
40 | }
41 | .left-bar {
42 | float: left;
43 | li {
44 | float: left;
45 | }
46 | }
47 | .right-bar {
48 | float: right;
49 | li {
50 | float: left;
51 | }
52 | }
53 | .bread {
54 | li {
55 | &:not(:last-of-type) {
56 | margin-right: 0;
57 | &::after {
58 | content: '/';
59 | // content:"\203A";
60 | // margin-left:5px;
61 | font-weight: bolder;
62 | color: currentColor;
63 | font-size: 12px;
64 | vertical-align: bottom;
65 | }
66 | }
67 | }
68 | }
69 | .tools-bar {
70 | li {
71 | &:not(:last-of-type) {
72 | .link {
73 | &::before {
74 | content: '';
75 | position: absolute;
76 | left: 0;
77 | top: 10px;
78 | height: 20px;
79 | width: 1px;
80 | background-color: rgba(0, 0, 0, 0.2);
81 | }
82 | }
83 | }
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/app/commons/layout/components/menuBottom/index.jsx:
--------------------------------------------------------------------------------
1 | import {Link} from '@huxy/router';
2 | import {Anico} from '@huxy/components';
3 | import report from '@app/apis/report/report';
4 | import {getIntls} from '@app/components/intl';
5 |
6 | import './index.less';
7 |
8 | const Index = ({collapsed, setCollapsed, isSmall}) => {
9 | return (
10 |
11 | {isSmall ? null : (
12 |
{
15 | setCollapsed(!collapsed);
16 | report({
17 | actionType: 'click',
18 | category: 'menuBottom',
19 | text: 'collapsed',
20 | value: collapsed ? 'close' : 'open',
21 | });
22 | }}
23 | title="collapse"
24 | >
25 |
26 |
27 | )}
28 | {!isSmall && collapsed ? null : (
29 |
{
34 | report({
35 | actionType: 'click',
36 | category: 'menuBottom',
37 | text: '文档',
38 | value: 'doc',
39 | });
40 | }}
41 | >
42 | {getIntls('nav.left', {}).doc}
43 |
44 | )}
45 |
46 | );
47 | };
48 |
49 | export default Index;
50 |
--------------------------------------------------------------------------------
/app/commons/layout/components/menuBottom/index.less:
--------------------------------------------------------------------------------
1 | .menu-collapsed {
2 | display: flex;
3 | justify-content: space-between;
4 | // box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06) inset;
5 | height: var(--footerHeight);
6 | line-height: var(--footerHeight);
7 | border-top: 1px solid rgba(0, 0, 0, 0.06);
8 | overflow: hidden;
9 | // padding:10px 0;
10 | .collapsed-bar {
11 | display: block;
12 | margin: 0;
13 | width: var(--collapseWidth);
14 | // background-color:rgba(0,0,0,.1);
15 | // box-shadow:0 1px 4px rgba(0,0,0,0.1) inset;
16 | text-align: center;
17 | }
18 | .link-bar {
19 | padding: 0 10px;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/commons/layout/components/uiI18n/index.jsx:
--------------------------------------------------------------------------------
1 | import {ConfigProvider, App} from 'antd';
2 | import zhCN from 'antd/locale/zh_CN';
3 | import enUS from 'antd/locale/en_US';
4 | import {useLangStore, useThemeStore} from '@app/store/stores';
5 |
6 | const uiLang = {
7 | zh: zhCN,
8 | en: enUS,
9 | };
10 |
11 | const Index = props => {
12 | const [language] = useLangStore();
13 | const [theme] = useThemeStore();
14 | const colors = theme?.list?.colors ?? {};
15 | return (
16 |
32 | {props.children}
33 |
34 | );
35 | };
36 |
37 | export default Index;
38 |
--------------------------------------------------------------------------------
/app/commons/layout/components/useFormatMenu/index.jsx:
--------------------------------------------------------------------------------
1 | import {useRoute} from '@huxy/router';
2 | import {useMenuTypeStore} from '@app/store/stores';
3 |
4 | import {getSelected} from '@huxy/utils';
5 |
6 | const formatMenu = (menu, curPath, type, cb = null) => {
7 | const menuConfig = {
8 | vertical: [],
9 | horizontal: [],
10 | };
11 | if (type === 'horizontal') {
12 | menuConfig[type] = menu;
13 | return menuConfig;
14 | }
15 | if (type === 'compose') {
16 | const horizontal = menu.map(item => {
17 | const {children, ...rest} = item;
18 | if (item.path === curPath) {
19 | menuConfig.vertical = children;
20 | }
21 | return rest;
22 | });
23 | menuConfig.horizontal = menu.length > 0 ? horizontal : [];
24 | return menuConfig;
25 | }
26 | menuConfig.vertical = menu.length > 1 ? menu : menu[0]?.children;
27 | return menuConfig;
28 | };
29 |
30 | const useFormatMenu = props => {
31 | const {current, menu: menus} = useRoute();
32 | const [types] = useMenuTypeStore(props.menuType ?? {menu: 'vertical', header: ''});
33 |
34 | let menu = menus.find(({path}) => path === current[0]?.path)?.children ?? [];
35 | let firstLevel = 1;
36 |
37 | if (props.onlyCurrentMenu) {
38 | const selectedItems = getSelected(menu, props.onlyCurrentMenu, 'path');
39 | menu = selectedItems.slice(-1);
40 | firstLevel = current.length - selectedItems.length;
41 | }
42 |
43 | const {vertical, horizontal} = formatMenu(menu, current[firstLevel]?.path, types.menu);
44 |
45 | return [{vertical, horizontal, menu}, types.header === 'noHeader'];
46 | };
47 |
48 | export default useFormatMenu;
49 |
--------------------------------------------------------------------------------
/app/commons/layout/configs.js:
--------------------------------------------------------------------------------
1 | import {Link} from '@huxy/router';
2 | import MainTop from './components/mainTop';
3 | import MenuBottom from './components/menuBottom';
4 | import Footer from './components/footer';
5 | import handleNavClick from './utils/handleNavClick';
6 | import iconList from '@app/utils/icons';
7 | import logo from '@app/assets/images/logo.png';
8 |
9 | const menuAnimate = false;
10 |
11 | export {MainTop, MenuBottom, Footer, handleNavClick, iconList, logo, Link, menuAnimate};
12 |
--------------------------------------------------------------------------------
/app/commons/layout/index.jsx:
--------------------------------------------------------------------------------
1 | import UiI18n from './components/uiI18n';
2 | import Layout from './layout';
3 |
4 | const Index = props => (
5 |
6 |
7 |
8 | );
9 |
10 | export default Index;
11 |
--------------------------------------------------------------------------------
/app/commons/layout/layout.jsx:
--------------------------------------------------------------------------------
1 | import Layout from '@huxy/layout';
2 | import {i18nsStore} from '@app/store/stores';
3 | import getLang from '@app/utils/getLang';
4 | import {leftNav, rightNav} from '@app/configs/nav';
5 | import useFormatMenu from './components/useFormatMenu';
6 |
7 | import * as configs from './configs';
8 |
9 | const Index = props => {
10 | const i18ns = i18nsStore.getState();
11 | const language = getLang();
12 | const [menus, noHeader] = useFormatMenu(props);
13 | return ;
14 | };
15 |
16 | export default Index;
17 |
--------------------------------------------------------------------------------
/app/commons/layout/utils/handleNavClick.js:
--------------------------------------------------------------------------------
1 | import report from '@app/apis/report/report';
2 |
3 | const handleNavClick = (props, item) => {
4 | report({
5 | actionType: 'click',
6 | category: 'navbar',
7 | text: item.name || item.title || item.key,
8 | value: item.key || item.name,
9 | });
10 | const {handle, path, link} = item;
11 | if (typeof handle === 'function') {
12 | return handle(item);
13 | }
14 | if (link) {
15 | return window.open(link);
16 | }
17 | if (path) {
18 | return props.router.push(path);
19 | }
20 | };
21 |
22 | export default handleNavClick;
23 |
--------------------------------------------------------------------------------
/app/commons/styles/base.less:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 |
3 | @import './common/tokens.css';
4 |
5 | @import './common/resets.css';
6 |
7 | @import './common/icons.css';
8 |
9 | @import './common/default.css';
10 |
--------------------------------------------------------------------------------
/app/commons/styles/block.less:
--------------------------------------------------------------------------------
1 | @import './common/style-block.less';
2 |
3 | @import './common/style-icon.less';
4 |
--------------------------------------------------------------------------------
/app/commons/styles/common/default.css:
--------------------------------------------------------------------------------
1 | /* Works on Firefox */
2 | /* * {
3 | scrollbar-width: thin;
4 | scrollbar-color: rgba(0,0,0,.3) transparent;
5 | } */
6 |
7 | ::-webkit-scrollbar {
8 | width: 6px;
9 | height: 6px;
10 | }
11 |
12 | ::-webkit-scrollbar-track {
13 | border-radius: 6px;
14 | box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.1);
15 | background-color: transparent;
16 | }
17 |
18 | ::-webkit-scrollbar-thumb {
19 | border-radius: 6px;
20 | box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.1);
21 | background-color: rgba(0, 0, 0, 0.3);
22 | }
23 |
24 | ::-webkit-scrollbar-thumb:hover {
25 | background-color: rgba(0, 0, 0, 0.5);
26 | }
27 |
28 | ::-webkit-scrollbar-corner {
29 | background-color: rgba(0, 0, 0, 0.5);
30 | }
31 |
32 | :fullscreen {
33 | background: var(--appBgColor);
34 | }
35 |
36 | /*
37 | ::selection {
38 | color: #ffffff;
39 | background-color: #fa541c;
40 | }
41 | * {
42 | user-select: none;
43 | caret-color: #faad14;
44 | } */
45 |
--------------------------------------------------------------------------------
/app/commons/styles/common/tokens.css:
--------------------------------------------------------------------------------
1 | :root {
2 | /*colors*/
3 | --red1: #ef5350;
4 | --red2: #f44336;
5 | --red3: #e53935;
6 | --purple1: #ab47bc;
7 | --purple2: #9c27b0;
8 | --purple3: #8e24aa;
9 | --blue1: #42a5f5;
10 | --blue2: #2196f3;
11 | --blue3: #1e88e5;
12 | --teal1: #26a69a;
13 | --teal2: #009688;
14 | --teal3: #00897b;
15 | --green1: #66bb6a;
16 | --green2: #4caf50;
17 | --green3: #43a047;
18 | --yellow1: #ffee58;
19 | --yellow2: #ffeb3b;
20 | --yellow3: #fdd835;
21 | --orange1: #ffa726;
22 | --orange2: #ff9800;
23 | --orange3: #fb8c00;
24 | --grey1: #bdbdbd;
25 | --grey2: #9e9e9e;
26 | --grey3: #757575;
27 | --blueGrey1: #78909c;
28 | --blueGrey2: #607d8b;
29 | --blueGrey3: #546e7a;
30 | --lightText: #ffffff;
31 | --darkText: #000000;
32 |
33 | /*size*/
34 | --size: 1.4rem;
35 | --weight: 400;
36 | --color: #444444;
37 | --bgcolor: #eaeff2;
38 | --title-size: 1.6rem;
39 | --title-weight: 500;
40 | --title-color: #404040;
41 | --link-size: 1.4rem;
42 | --link-weight: 400;
43 | --link-color: #f0f0f0;
44 | --hover-color: #42a5f5;
45 | --hover-bgcolor: #eaeff2;
46 | --disabled-color: rgba(0, 0, 0, 0.25);
47 | --disabled-bgcolor: #f5f5f5;
48 |
49 | --space: 1.2rem;
50 | --h1: 2.6rem;
51 | --h2: 2.2rem;
52 | --h3: 1.8rem;
53 | --h4: 1.6rem;
54 | --h5: 1.4rem;
55 | --h6: 1.2rem;
56 | }
57 |
--------------------------------------------------------------------------------
/app/commons/styles/func/angle.less:
--------------------------------------------------------------------------------
1 | .angle(@angleSize: 6px, @width: 1px) {
2 | --pos: calc(@angleSize - @width) / 2;
3 | position: relative;
4 | display: inline-block;
5 | font-style: normal;
6 | float: right;
7 | cursor: pointer;
8 | height: 100%;
9 | width: 2 * @angleSize;
10 |
11 | &::before,
12 | &::after {
13 | content: '';
14 | display: block;
15 | position: absolute;
16 | border-radius: 1px;
17 | background-color: currentColor;
18 | height: @width;
19 | width: @angleSize;
20 | left: 0;
21 | transform-origin: 100% 50% 0;
22 | transition: all 0.3s;
23 | }
24 |
25 | &::before {
26 | left: 0;
27 | }
28 |
29 | &::after {
30 | left: calc(@width * 0.7);
31 | }
32 | }
33 |
34 | .angle-bt(@angleSize: 6px, @width: 1px) {
35 | .angle(@angleSize, @width);
36 |
37 | &::before,
38 | &::after {
39 | top: calc(50% + var(--pos));
40 | }
41 |
42 | &::before {
43 | transform: rotate(135deg);
44 | }
45 |
46 | &::after {
47 | transform: rotate(45deg);
48 | }
49 | }
50 |
51 | .angle-top(@angleSize: 6px, @width: 1px) {
52 | .angle(@angleSize, @width);
53 |
54 | &::before,
55 | &::after {
56 | top: calc(50% - var(--pos));
57 | }
58 |
59 | &::before {
60 | transform: rotate(225deg);
61 | }
62 |
63 | &::after {
64 | transform: rotate(-45deg);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/app/commons/styles/global/index.less:
--------------------------------------------------------------------------------
1 | /* global style*/
2 |
3 | .link {
4 | text-decoration: none;
5 | cursor: pointer;
6 | color: var(--linkColor);
7 | background-color: transparent;
8 | font-weight: 500;
9 | transition: color 0.3s;
10 | }
11 | .link:active,
12 | .link.active {
13 | color: var(--linkActiveColor, #42a5f5);
14 | }
15 | .link:hover {
16 | color: var(--linkHoverColor, #2196f3);
17 | }
18 | .link[disabled] {
19 | cursor: not-allowed;
20 | opacity: 0.7;
21 | }
22 | .link[disabled]:active,
23 | .link[disabled].active,
24 | .link[disabled]:hover {
25 | color: var(--linkColor);
26 | }
27 |
28 | @media screen and (max-width: 1024px) {
29 | .sm-hide {
30 | display: none;
31 | }
32 | }
33 |
34 | /*li {
35 | >a {
36 | .ellipsis();
37 | >span {
38 | .ellipsis();
39 | }
40 | }
41 | }*/
42 |
--------------------------------------------------------------------------------
/app/commons/styles/index.less:
--------------------------------------------------------------------------------
1 | @import './base.less';
2 | @import './block.less';
3 |
4 | @import './global/index.less';
5 |
--------------------------------------------------------------------------------
/app/components/base/button/index.jsx:
--------------------------------------------------------------------------------
1 | import * as styles from './index.less';
2 |
3 | const Index = ({className, type = '', size = '', ...rest}) => {
4 | const cls = ['h-btn', ...(className?.split(' ') ?? []), type, size]
5 | .filter(Boolean)
6 | .map(c => styles[c])
7 | .join(' ');
8 | return ;
9 | };
10 |
11 | export default Index;
12 |
--------------------------------------------------------------------------------
/app/components/base/checkbox/index.jsx:
--------------------------------------------------------------------------------
1 | const Index = ({options, value: selected, onChange, style, ...rest}) => {
2 | selected = typeof selected === 'string' ? [selected] : [...(selected || [])];
3 | return (
4 |
5 | {(options || []).map(({value, label}) => (
6 |
{
10 | e.stopPropagation();
11 | const index = selected.indexOf(value);
12 | index === -1 ? selected.push(value) : selected.splice(index, 1);
13 | onChange?.(selected, e);
14 | }}
15 | style={{display: 'flex', alignItems: 'center', marginRight: '12px', cursor: 'pointer'}}
16 | >
17 |
18 | {label || value}
19 |
20 | ))}
21 |
22 | );
23 | };
24 |
25 | export default Index;
26 |
--------------------------------------------------------------------------------
/app/components/base/input/index.jsx:
--------------------------------------------------------------------------------
1 | import {useState, useEffect} from 'react';
2 | import {message} from '@huxy/utils';
3 | import * as styles from './index.less';
4 |
5 | const minmaxRule = (value, min, max) => {
6 | if (min != null) {
7 | if (value < min) {
8 | return {
9 | val: min,
10 | msg: `最小值为 ${min}`,
11 | };
12 | }
13 | }
14 | if (max != null) {
15 | if (value > max) {
16 | return {
17 | val: max,
18 | msg: `最大值为 ${max}`,
19 | };
20 | }
21 | }
22 | return false;
23 | };
24 |
25 | const Index = ({className, value, onChange, onBlur, onPressEnter, ...rest}) => {
26 | const [val, setVal] = useState(value);
27 | const cls = ['h-input', ...(className?.split(' ') ?? [])]
28 | .filter(Boolean)
29 | .map(c => styles[c])
30 | .join(' ');
31 | useEffect(() => {
32 | setVal(value);
33 | }, [value]);
34 | const handleChange = e => {
35 | e.stopPropagation();
36 | const {value} = e.target;
37 | setVal(value);
38 | const {min, max} = rest;
39 | const hasError = minmaxRule(value, min, max);
40 | if (!hasError) {
41 | onChange?.(e, value);
42 | }
43 | };
44 | const handleBlur = e => {
45 | e.stopPropagation();
46 | const {value} = e.target;
47 | const {min, max} = rest;
48 | const hasError = minmaxRule(value, min, max);
49 | if (hasError) {
50 | const {val, msg} = hasError;
51 | message.warn(msg);
52 | setVal(val);
53 | setTimeout(() => onChange?.(e, val));
54 | }
55 | };
56 | const handleKeyDown = e => {
57 | if (e.keyCode === 13) {
58 | onPressEnter?.(e);
59 | }
60 | };
61 | return ;
62 | };
63 |
64 | export default Index;
65 |
--------------------------------------------------------------------------------
/app/components/base/input/index.less:
--------------------------------------------------------------------------------
1 | :local {
2 | .h-input {
3 | display: inline-block;
4 | width: 100%;
5 | min-width: 0;
6 | height: 32px;
7 | padding: 4px 11px;
8 | font-size: 1.4rem;
9 | line-height: 1.42857143;
10 | color: var(--appColor);
11 | background-color: var(--pageBgColor, --appBgColor);
12 | background-image: none;
13 | border: 1px solid var(--borderColor);
14 | border-radius: 4px;
15 | transition: all 0.3s;
16 |
17 | &::-webkit-input-placeholder {
18 | color: #bbbbbb;
19 | }
20 |
21 | &:hover,
22 | &:focus {
23 | border-color: var(--blue2);
24 | transition: all 0.3s;
25 |
26 | & + i,
27 | & + span {
28 | color: var(--blue2);
29 | }
30 | }
31 |
32 | &:focus {
33 | outline: 0;
34 | box-shadow: 0 0 0 2px rgba(49, 143, 250, 0.2);
35 | }
36 |
37 | &[disabled] {
38 | color: rgba(0, 0, 0, 0.25);
39 | border-color: #e5e5e5;
40 | background-color: #f5f5f5;
41 | cursor: not-allowed;
42 | }
43 |
44 | &:invalid {
45 | border-color: var(--red2);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/app/components/base/menu/index.jsx:
--------------------------------------------------------------------------------
1 | import {useRef} from 'react';
2 | import {traverItem} from '@huxy/utils';
3 | import {useClickAway, useUpdate} from '@huxy/use';
4 | import './index.less';
5 |
6 | const Index = ({data = []}) => {
7 | const rerender = useUpdate();
8 | const itemClick = (e, item) => {
9 | e.stopPropagation();
10 | traverItem(v => {
11 | if (item.value === v.value) {
12 | if (item.list?.length) {
13 | v.open = !item.open;
14 | } else {
15 | v.active = true;
16 | }
17 | } else {
18 | v.open = false;
19 | v.active = false;
20 | }
21 | })(data);
22 | rerender();
23 | };
24 |
25 | return (
26 |
27 |
28 | {data.map((li, i) => (
29 |
30 | ))}
31 |
32 |
33 | );
34 | };
35 |
36 | const LiItem = ({li, itemClick}) => {
37 | const liRef = useRef();
38 | useClickAway(() => liRef, e => li.open && itemClick(e, li));
39 | return (
40 | itemClick(e, li)}>
41 |
42 | {li.name}
43 | {li.list?.length ? : null}
44 |
45 | {li.list?.length ? (
46 |
47 | {li.list.map(item => (
48 | -
49 |
50 | {item.name}
51 |
52 |
53 | ))}
54 |
55 | ) : null}
56 |
57 | );
58 | };
59 |
60 | export default Index;
61 |
--------------------------------------------------------------------------------
/app/components/base/menu/index.less:
--------------------------------------------------------------------------------
1 | @import '~@app/commons/styles/func/angle.less';
2 | @import '~@app/commons/styles/func/arrow.less';
3 | @import '~@app/commons/styles/func/follow.less';
4 | @import '~@app/commons/styles/func/tooltip.less';
5 |
6 | @keyframes menu-animate-top-in {
7 | 0% {
8 | opacity: 0;
9 | visibility: hidden;
10 | transform: translate3d(0, -30px, 0);
11 | }
12 | 100% {
13 | opacity: 0.98;
14 | visibility: visible;
15 | transform: translate3d(0, 2px, 0);
16 | }
17 | }
18 |
19 | .menu-container {
20 | display: flex;
21 | align-items: center;
22 | justify-content: center;
23 | > li {
24 | position: relative;
25 | > .link {
26 | padding: 4px 12px;
27 | display: flex;
28 | align-items: center;
29 | justify-content: space-between;
30 | &.active {
31 | color: var(--blue2);
32 | }
33 | > i {
34 | display: block;
35 | margin-left: 4px;
36 | }
37 | }
38 | > ul {
39 | position: absolute;
40 | top: 100%;
41 | right: 0;
42 | width: 135px;
43 | box-shadow: 0 2px 6px var(--borderColor);
44 | padding: 10px 0;
45 | border-radius: 2px;
46 | z-index: 10;
47 | opacity: 0;
48 | visibility: hidden;
49 | display: none;
50 | .link {
51 | padding: 6px 20px;
52 | display: block;
53 | }
54 | }
55 | &.open {
56 | ul {
57 | display: block;
58 | animation: menu-animate-top-in 0.2s forwards;
59 | }
60 | }
61 | }
62 | }
63 |
64 | .menu-follow {
65 | .follow(3px,currentColor,10px);
66 | }
67 | .menu-angle-top {
68 | .angle-top(5px,1px);
69 | }
70 | .menu-angle-bt {
71 | .angle-bt(5px,1px);
72 | }
73 | .menu-arrow-lt {
74 | .arrow-lt(var(--navBgColor),var(--borderColor),8px,16px);
75 | right: auto;
76 | left: 0;
77 | }
78 | .menu-arrow-rt {
79 | .arrow-rt(var(--navBgColor),var(--borderColor),8px,16px);
80 | right: 0;
81 | left: auto;
82 | }
83 | .menu-tooltip {
84 | .tooltip-lb();
85 | }
86 |
--------------------------------------------------------------------------------
/app/components/base/radio/index.jsx:
--------------------------------------------------------------------------------
1 | const Index = ({options, value: checked, onChange, style, ...rest}) => (
2 |
3 | {(options || []).map(({value, label}) => (
4 |
onChange?.(value, e)} style={{display: 'flex', alignItems: 'center', marginRight: '12px', cursor: 'pointer'}}>
5 |
6 | {label || value}
7 |
8 | ))}
9 |
10 | );
11 |
12 | export default Index;
13 |
--------------------------------------------------------------------------------
/app/components/base/select/index.jsx:
--------------------------------------------------------------------------------
1 | const Index = ({options, ...rest}) => (
2 |
9 | );
10 |
11 | export default Index;
12 |
--------------------------------------------------------------------------------
/app/components/base/textarea/index.jsx:
--------------------------------------------------------------------------------
1 | import {useState, useEffect} from 'react';
2 | import {message} from '@huxy/utils';
3 | import * as styles from './index.less';
4 |
5 | const minmaxRule = (value, min, max) => {
6 | if (min != null) {
7 | if (value < min) {
8 | return {
9 | val: min,
10 | msg: `最小值为 ${min}`,
11 | };
12 | }
13 | }
14 | if (max != null) {
15 | if (value > max) {
16 | return {
17 | val: max,
18 | msg: `最大值为 ${max}`,
19 | };
20 | }
21 | }
22 | return false;
23 | };
24 |
25 | const TextArea = ({className, value, onChange, onBlur, border = true, ...rest}) => {
26 | const [val, setVal] = useState(value);
27 | const cls = ['h-textarea', border ? null : 'no-border', ...(className?.split(' ') ?? [])]
28 | .filter(Boolean)
29 | .map(c => styles[c])
30 | .join(' ');
31 | useEffect(() => {
32 | setVal(value);
33 | }, [value]);
34 | const handleChange = e => {
35 | e.stopPropagation();
36 | const {value} = e.target;
37 | setVal(value);
38 | const {min, max} = rest;
39 | const hasError = minmaxRule(value, min, max);
40 | if (!hasError) {
41 | onChange?.(e, value);
42 | }
43 | };
44 | const handleBlur = e => {
45 | e.stopPropagation();
46 | const {value} = e.target;
47 | const {min, max} = rest;
48 | const hasError = minmaxRule(value, min, max);
49 | if (hasError) {
50 | const {val, msg} = hasError;
51 | message.warn(msg);
52 | setVal(val);
53 | setTimeout(() => onChange?.(e, val));
54 | }
55 | };
56 | return ;
57 | };
58 |
59 | export default TextArea;
60 |
--------------------------------------------------------------------------------
/app/components/base/textarea/index.less:
--------------------------------------------------------------------------------
1 | :local {
2 | .h-textarea {
3 | display: inline-block;
4 | width: 100%;
5 | min-width: 0;
6 | min-height: 8rem;
7 | // height: 32px;
8 | padding: 4px 11px;
9 | font-size: 1.4rem;
10 | line-height: 1.42857143;
11 | color: var(--appColor);
12 | background-color: var(--pageBgColor, --appBgColor);
13 | background-image: none;
14 | border: 1px solid var(--borderColor);
15 | border-radius: 4px;
16 | transition: all 0.3s;
17 | resize: none;
18 |
19 | &::-webkit-input-placeholder {
20 | color: #bbbbbb;
21 | }
22 |
23 | &:hover,
24 | &:focus {
25 | border-color: var(--blue2);
26 | transition: all 0.3s;
27 |
28 | & + i {
29 | color: var(--blue2);
30 | }
31 | }
32 |
33 | &:focus {
34 | outline: 0;
35 | box-shadow: 0 0 0 2px rgba(49, 143, 250, 0.2);
36 | }
37 |
38 | &[disabled] {
39 | color: rgba(0, 0, 0, 0.25);
40 | border-color: #e5e5e5;
41 | background-color: #f5f5f5;
42 | cursor: not-allowed;
43 | }
44 |
45 | &:invalid {
46 | border-color: var(--red2);
47 | }
48 | &.no-border {
49 | border: 0;
50 | &:focus {
51 | box-shadow: none;
52 | }
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/app/components/base/tooltip/index.jsx:
--------------------------------------------------------------------------------
1 | const Index = ({children, title, placement}) => (
2 |
3 | {children}
4 |
5 | );
6 |
7 | export default Index;
8 |
--------------------------------------------------------------------------------
/app/components/customCollapse.jsx:
--------------------------------------------------------------------------------
1 | import {useHuxyStore} from '@huxy/router';
2 | import {useWinResize, useUpdateEffect} from '@huxy/use';
3 | import {Anico} from '@huxy/components';
4 |
5 | import report from '@app/apis/report/report';
6 |
7 | const CustomCollapse = ({item, ...rest}) => {
8 | const {width, height} = useWinResize();
9 | const [collapsed, setCollapsed] = useHuxyStore('huxy-collapse');
10 | useUpdateEffect(() => {
11 | document.documentElement.style.setProperty('--containerHeight', `${height}px`);
12 | }, [height]);
13 | return width <= 1024 ? (
14 | {
17 | e.stopPropagation();
18 | setCollapsed(!collapsed);
19 | report({
20 | actionType: 'click',
21 | category: 'menuBottom',
22 | text: 'minscreen-collapsed',
23 | value: collapsed ? 'close' : 'open',
24 | });
25 | }}
26 | title="minscreen-collapse"
27 | >
28 |
29 |
30 | ) : null;
31 | };
32 |
33 | export default CustomCollapse;
34 |
--------------------------------------------------------------------------------
/app/components/ellipsis.jsx:
--------------------------------------------------------------------------------
1 | import {Tooltip} from 'antd';
2 | import {Ellipsis} from '@huxy/components';
3 |
4 | const Index = ({children, ...rest}) => {
5 | return (
6 |
7 |
8 | {children}
9 |
10 |
11 | );
12 | };
13 |
14 | export default Index;
15 |
--------------------------------------------------------------------------------
/app/components/fullScreen.jsx:
--------------------------------------------------------------------------------
1 | import {FullscreenOutlined, FullscreenExitOutlined} from '@ant-design/icons';
2 | import {FullPage} from '@huxy/components';
3 |
4 | const Index = ({panel}) => ;
5 |
6 | export default Index;
7 |
--------------------------------------------------------------------------------
/app/components/goBack.jsx:
--------------------------------------------------------------------------------
1 | import Panel from '@app/components/panel';
2 | import Icon from '@app/components/icon';
3 | import Button from '@app/components/base/button';
4 |
5 | import Intls from '@app/components/intl';
6 |
7 | const containerStyle = {
8 | width: '100%',
9 | height: '100%',
10 | display: 'flex',
11 | justifyContent: 'space-between',
12 | alignItems: 'center',
13 | };
14 | const backStyle = {
15 | width: '100px',
16 | };
17 | const titleStyle = {
18 | width: '100%',
19 | paddingRight: '50px',
20 | fontSize: '1.6rem',
21 | fontWeight: 500,
22 | textAlign: 'center',
23 | };
24 | const actionStyle = {
25 | maxWidth: '500px',
26 | };
27 |
28 | const Index = ({back, title, actions = [], backText = '返回'}) => (
29 |
30 |
31 |
32 |
38 |
39 | {title &&
{title}
}
40 | {actions.length ? (
41 |
42 | {actions.map(({text, icon, className, style, ...rest}, i) => (
43 |
47 | ))}
48 |
49 | ) : null}
50 |
51 |
52 | );
53 |
54 | export default Index;
55 |
--------------------------------------------------------------------------------
/app/components/icon.jsx:
--------------------------------------------------------------------------------
1 | import {fixIcon} from '@huxy/components';
2 | import icons from '@app/utils/icons';
3 |
4 | export default fixIcon(icons);
5 |
--------------------------------------------------------------------------------
/app/components/icons/add.jsx:
--------------------------------------------------------------------------------
1 | const AddIcon = props => (
2 |
5 | );
6 |
7 | export default AddIcon;
8 |
--------------------------------------------------------------------------------
/app/components/icons/audio0.jsx:
--------------------------------------------------------------------------------
1 | const Audio0Icon = props => (
2 |
6 | );
7 |
8 | export default Audio0Icon;
9 |
--------------------------------------------------------------------------------
/app/components/icons/audio1.jsx:
--------------------------------------------------------------------------------
1 | const Audio1Icon = props => (
2 |
13 | );
14 |
15 | export default Audio1Icon;
16 |
--------------------------------------------------------------------------------
/app/components/icons/broom.jsx:
--------------------------------------------------------------------------------
1 | const BroomIcon = props => (
2 |
11 | );
12 |
13 | export default BroomIcon;
14 |
--------------------------------------------------------------------------------
/app/components/icons/github.jsx:
--------------------------------------------------------------------------------
1 | const GithubIcon = props => (
2 |
8 | );
9 |
10 | export default GithubIcon;
11 |
--------------------------------------------------------------------------------
/app/components/icons/image.jsx:
--------------------------------------------------------------------------------
1 | const ImageIcon = props => (
2 |
5 | );
6 |
7 | export default ImageIcon;
8 |
--------------------------------------------------------------------------------
/app/components/icons/lock.jsx:
--------------------------------------------------------------------------------
1 | const LockIcon = props => (
2 |
5 | );
6 |
7 | export default LockIcon;
8 |
--------------------------------------------------------------------------------
/app/components/icons/moon.jsx:
--------------------------------------------------------------------------------
1 | const MoonIcon = props => (
2 |
6 | );
7 |
8 | export default MoonIcon;
9 |
--------------------------------------------------------------------------------
/app/components/icons/send.jsx:
--------------------------------------------------------------------------------
1 | const SendIcon = props => (
2 |
8 | );
9 |
10 | export default SendIcon;
11 |
--------------------------------------------------------------------------------
/app/components/icons/sun.jsx:
--------------------------------------------------------------------------------
1 | const SunIcon = props => (
2 |
6 | );
7 |
8 | export default SunIcon;
9 |
--------------------------------------------------------------------------------
/app/components/icons/user.jsx:
--------------------------------------------------------------------------------
1 | const UserIcon = props => (
2 |
5 | );
6 |
7 | export default UserIcon;
8 |
--------------------------------------------------------------------------------
/app/components/icons/video.jsx:
--------------------------------------------------------------------------------
1 | const VideoIcon = props => (
2 |
6 | );
7 |
8 | export default VideoIcon;
9 |
--------------------------------------------------------------------------------
/app/components/icons/wechat.jsx:
--------------------------------------------------------------------------------
1 | const WechatIcon = props => (
2 |
6 | );
7 |
8 | export default WechatIcon;
9 |
--------------------------------------------------------------------------------
/app/components/intl.jsx:
--------------------------------------------------------------------------------
1 | import {useCallback} from 'react';
2 | import {useI18nsStore, i18nsStore} from '@app/store/stores';
3 |
4 | const Intls = ({keys, children}) => {
5 | const [i18ns] = useI18nsStore();
6 | return (keys && i18ns?.getValue(keys)) ?? children ?? '';
7 | };
8 |
9 | export const useIntls = () => {
10 | const [i18ns] = useI18nsStore();
11 | return useCallback((keys, def) => (keys && i18ns?.getValue(keys)) ?? def ?? '', [i18ns]);
12 | };
13 |
14 | export const getIntls = (keys, def) => (keys && i18nsStore.getState()?.getValue(keys)) ?? def ?? '';
15 |
16 | export default Intls;
17 |
--------------------------------------------------------------------------------
/app/components/maxSize.jsx:
--------------------------------------------------------------------------------
1 | import {PlusSquareOutlined, MinusSquareOutlined} from '@ant-design/icons';
2 | import {MaxSize} from '@huxy/components';
3 |
4 | const Index = ({panel}) => ;
5 |
6 | export default Index;
7 |
--------------------------------------------------------------------------------
/app/components/notify.jsx:
--------------------------------------------------------------------------------
1 | import {useEffect} from 'react';
2 | import {Badge} from 'antd';
3 | import {BellOutlined} from '@ant-design/icons';
4 | import {useRoute} from '@huxy/router';
5 | import apiList from '@app/apis/apiList';
6 | import {useNotifyStore} from '@app/store/stores';
7 |
8 | const Notify = props => {
9 | const {router} = useRoute();
10 | const [count, setCount] = useNotifyStore();
11 | useEffect(() => {
12 | const getMes = async () => {
13 | try {
14 | const {result} = await apiList.listMessageFn({current: 1, size: 100, status: 0});
15 | setCount(result.total);
16 | } catch (err) {}
17 | };
18 | getMes();
19 | }, []);
20 | const handleClick = e => {
21 | router.push('/messages');
22 | };
23 | return (
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | );
32 | };
33 |
34 | export default Notify;
35 |
--------------------------------------------------------------------------------
/app/components/panel/index.jsx:
--------------------------------------------------------------------------------
1 | import {Panel} from '@huxy/components';
2 |
3 | const Index = ({style, children, ...rest}) => (
4 |
5 | {children}
6 |
7 | );
8 |
9 | export default Index;
10 |
--------------------------------------------------------------------------------
/app/components/row/index.jsx:
--------------------------------------------------------------------------------
1 | import {Row as DefRow, Col as DefCol} from '@huxy/components';
2 |
3 | const rowCfg = {
4 | gutter: [12, 12],
5 | };
6 | const styles = {
7 | // '--gutter': 'calc(var(--frame-spacing) / 2)',
8 | // '--rowgap': 'calc(var(--frame-spacing) / 2)',
9 | };
10 |
11 | const colCfg = {
12 | sm: 12,
13 | xs: 12,
14 | };
15 |
16 | export const Row = ({children, style, ...rest}) => (
17 |
18 | {children}
19 |
20 | );
21 |
22 | export const Col = ({children, ...rest}) => (
23 |
24 | {children}
25 |
26 | );
27 |
--------------------------------------------------------------------------------
/app/components/search.jsx:
--------------------------------------------------------------------------------
1 | import {useRef} from 'react';
2 | import {SearchOutlined} from '@ant-design/icons';
3 | import Input from '@app/components/base/input';
4 |
5 | const GlobalSearch = props => {
6 | const searchValue = useRef();
7 | const onSearch = e => {
8 | e.stopPropagation();
9 | console.log(searchValue.current);
10 | };
11 | return (
12 |
13 | }
16 | onChange={e => (searchValue.current = e.target.value)}
17 | onPressEnter={onSearch}
18 | />
19 |
20 |
21 | );
22 | };
23 |
24 | export default GlobalSearch;
25 |
--------------------------------------------------------------------------------
/app/components/searchForm/index.jsx:
--------------------------------------------------------------------------------
1 | import {Form, Button} from 'antd';
2 | import {Grid} from '@huxy/components';
3 | import {validObj} from '@huxy/utils';
4 |
5 | const rowCfg = {
6 | gutter: [12, 12],
7 | style: {
8 | // justifyContent: 'flex-end',
9 | },
10 | };
11 |
12 | const colCfg = {
13 | xl: 2,
14 | lg: 3,
15 | md: 3,
16 | sm: 4,
17 | xs: 6,
18 | };
19 |
20 | const SearchForm = props => {
21 | const {submit, loading, children, handler, initialValues, ...rest} = props;
22 | const [form] = Form.useForm();
23 | return (
24 |
40 | );
41 | };
42 |
43 | export default SearchForm;
44 |
--------------------------------------------------------------------------------
/app/components/themeModel.jsx:
--------------------------------------------------------------------------------
1 | import {storage} from '@huxy/utils';
2 | import {useThemeStore} from '@app/store/stores';
3 | import getTheme from '@app/utils/getTheme';
4 | import MoonIcon from '@app/components/icons/moon';
5 | import SunIcon from '@app/components/icons/sun';
6 |
7 | const ThemeModel = props => {
8 | const {label, ...rest} = props;
9 | const [theme, setTheme] = useThemeStore();
10 | const {key} = theme;
11 |
12 | const handleClick = e => {
13 | // e.stopPropagation();
14 | const currentKey = key === 'dark' ? 'light' : 'dark';
15 | const current = getTheme(currentKey);
16 | storage.set('theme', current);
17 | setTheme(current);
18 | };
19 |
20 | return (
21 |
22 | {key === 'light' ? : }
23 | {label && {label}}
24 |
25 | );
26 | };
27 |
28 | export default ThemeModel;
29 |
--------------------------------------------------------------------------------
/app/configs/index.js:
--------------------------------------------------------------------------------
1 | const {browserRouter, basepath, PROXY, buildTime, ...rest} = process.env.configs ?? {};
2 |
3 | export {browserRouter, basepath, PROXY, buildTime};
4 |
5 | export const defProject = rest;
6 |
--------------------------------------------------------------------------------
/app/configs/langList.jsx:
--------------------------------------------------------------------------------
1 | import zh_icon from '@app/assets/lang/zh.png';
2 | import en_icon from '@app/assets/lang/en.png';
3 |
4 | const langList = [
5 | {
6 | key: 'zh',
7 | name: '中文',
8 | icon: zh_icon,
9 | },
10 | {
11 | key: 'en',
12 | name: 'English',
13 | icon: en_icon,
14 | },
15 | ];
16 |
17 | export default langList;
18 |
--------------------------------------------------------------------------------
/app/configs/router.js:
--------------------------------------------------------------------------------
1 | import {demoBackReg, confirmDesignPage} from '@app/utils/confirmDesignPage';
2 |
3 | import whiteList from '@app/routes/whiteList';
4 |
5 | import {isAuthed} from '@app/utils/utils';
6 |
7 | import {browserRouter, basepath} from '.';
8 |
9 | import errorBoundary from '@app/apis/report/pageError';
10 | import routeReport from '@app/apis/report/routeChange';
11 |
12 | const initPath = `${browserRouter ? '' : '#'}/`;
13 |
14 | const whiteRoutes = browserRouter ? whiteList : whiteList.map(path => `#${path}`);
15 |
16 | const beforeRender = (input, next) => {
17 | const {path, prevPath} = input;
18 | const validPath = path.split('?')[0];
19 | if (validPath === initPath) {
20 | return next({path: '/'});
21 | }
22 | /* if (!isAuthed() && !whiteRoutes.includes(validPath)) {
23 | return next({path: '/user/signin'});
24 | } */
25 | if (path !== prevPath && demoBackReg.test(prevPath)) {
26 | // designReg
27 | return confirmDesignPage(next);
28 | }
29 | next();
30 | };
31 |
32 | let listenRouteInit = false;
33 |
34 | const afterRender = output => {
35 | const {path, name, stay} = output;
36 | let firstLoadTime;
37 | if (!listenRouteInit) {
38 | firstLoadTime = stay;
39 | listenRouteInit = true;
40 | }
41 | if (!path.includes('/user/')) {
42 | routeReport({path, name, firstLoadTime});
43 | }
44 | };
45 |
46 | export default {
47 | browserRouter,
48 | beforeRender,
49 | basepath,
50 | errorBoundary,
51 | afterRender,
52 | };
53 |
--------------------------------------------------------------------------------
/app/configs/theme.js:
--------------------------------------------------------------------------------
1 | import {light, light1, dark, dark1, portal1, portal} from './themes';
2 |
3 | import * as themes from './themes/themes';
4 |
5 | const themeList = getIntls => [
6 | {
7 | name: getIntls('theme.light', 'light'),
8 | key: 'light',
9 | list: light,
10 | type: 'theme',
11 | },
12 | {
13 | name: getIntls('theme.light1', 'light1'),
14 | key: 'light1',
15 | list: light1,
16 | type: 'theme',
17 | },
18 | {
19 | name: getIntls('theme.dark', 'dark'),
20 | key: 'dark',
21 | list: dark,
22 | type: 'theme',
23 | },
24 | {
25 | name: getIntls('theme.dark1', 'dark1'),
26 | key: 'dark1',
27 | list: dark1,
28 | type: 'theme',
29 | },
30 | {
31 | name: getIntls('theme.portal', 'portal'),
32 | key: 'portal',
33 | list: portal,
34 | type: 'theme',
35 | },
36 | {
37 | name: getIntls('theme.portal1', 'portal1'),
38 | key: 'portal1',
39 | list: portal1,
40 | type: 'theme',
41 | },
42 | ...Object.keys(themes).map(key => ({
43 | name: key,
44 | key,
45 | list: themes[key],
46 | type: 'theme',
47 | })),
48 | ];
49 |
50 | export default themeList;
51 |
--------------------------------------------------------------------------------
/app/configs/themes/dark.js:
--------------------------------------------------------------------------------
1 | const sizes = {
2 | '--maxWidth': '100vw',
3 | '--menuWidth': '20.4rem',
4 | '--collapseWidth': '6rem',
5 | '--collapseMenuWidth': '16.4rem',
6 | '--headerHeight': '5.8rem',
7 | '--footerHeight': '4.3rem',
8 | '--breadHeight': '3.6rem',
9 | '--menuItemHeight': '4rem',
10 | };
11 | const colors = {
12 | '--appColor': '#ced4da',
13 | '--appBgColor': '#303841',
14 | '--bannerBgColor': '#37424c',
15 | '--navBgColor': '#3c4752',
16 | '--menuBgColor': '#37424c',
17 | '--panelBgColor': '#36404a',
18 | '--linkColor': '#ced4da',
19 | '--linkHoverColor': '#ffffff',
20 | '--linkActiveColor': '#ffffff',
21 | '--borderColor': '#424e5a',
22 | };
23 |
24 | export default {
25 | sizes,
26 | colors,
27 | };
28 |
--------------------------------------------------------------------------------
/app/configs/themes/dark1.js:
--------------------------------------------------------------------------------
1 | const sizes = {
2 | '--maxWidth': '100vw',
3 | '--menuWidth': '196px',
4 | '--collapseWidth': '60px',
5 | '--collapseMenuWidth': '160px',
6 | '--headerHeight': '56px',
7 | '--footerHeight': '40px',
8 | '--breadHeight': '40px',
9 | '--menuItemHeight': '45px',
10 | };
11 | const colors = {
12 | '--appColor': '#a6b0cf',
13 | '--appBgColor': '#222736',
14 | '--bannerBgColor': '#2a3042',
15 | '--navBgColor': '#262b3c',
16 | '--menuBgColor': '#2a3042',
17 | '--panelBgColor': '#2a3042',
18 | '--linkColor': '#a6b0cf',
19 | '--linkHoverColor': '#ffffff',
20 | '--linkActiveColor': '#ffffff',
21 | '--borderColor': '#424e5a',
22 | };
23 |
24 | export default {
25 | sizes,
26 | colors,
27 | };
28 |
--------------------------------------------------------------------------------
/app/configs/themes/index.js:
--------------------------------------------------------------------------------
1 | import dark from './dark';
2 | import dark1 from './dark1';
3 | import light from './light';
4 | import light1 from './light1';
5 | import portal from './portal';
6 | import portal1 from './portal1';
7 |
8 | export {dark, dark1, light, light1, portal, portal1};
9 |
--------------------------------------------------------------------------------
/app/configs/themes/light.js:
--------------------------------------------------------------------------------
1 | const sizes = {
2 | '--maxWidth': '100vw',
3 | '--menuWidth': '20.4rem',
4 | '--collapseWidth': '6rem',
5 | '--collapseMenuWidth': '16.4rem',
6 | '--headerHeight': '5.8rem',
7 | '--footerHeight': '4.3rem',
8 | '--breadHeight': '3.6rem',
9 | '--menuItemHeight': '4rem',
10 | };
11 | const colors = {
12 | '--appColor': '#495057',
13 | '--appBgColor': '#f8f8fb',
14 | '--bannerBgColor': '#2a3042',
15 | '--navBgColor': '#ffffff',
16 | '--menuBgColor': '#2a3042',
17 | '--panelBgColor': '#ffffff',
18 | '--linkColor': '#455a64',
19 | '--linkHoverColor': '#2196f3',
20 | '--linkActiveColor': '#42a5f5',
21 | '--asideLinkColor': '#f0f0f0',
22 | '--bannerLinkColor': '#f0f0f0',
23 | '--borderColor': '#eff2f7',
24 | };
25 |
26 | export default {
27 | sizes,
28 | colors,
29 | };
30 |
--------------------------------------------------------------------------------
/app/configs/themes/light1.js:
--------------------------------------------------------------------------------
1 | const sizes = {
2 | '--maxWidth': '100vw',
3 | '--menuWidth': '220px',
4 | '--collapseWidth': '68px',
5 | '--collapseMenuWidth': '180px',
6 | '--headerHeight': '60px',
7 | '--footerHeight': '50px',
8 | '--breadHeight': '50px',
9 | '--menuItemHeight': '48px',
10 | };
11 | const colors = {
12 | '--appColor': '#495057',
13 | '--appBgColor': '#f3f4f7',
14 | '--bannerBgColor': '#ffffff',
15 | '--navBgColor': '#fcfcfc',
16 | '--menuBgColor': '#ffffff',
17 | '--panelBgColor': '#ffffff',
18 | '--linkColor': '#495057',
19 | '--linkHoverColor': '#2196f3',
20 | '--linkActiveColor': '#42a5f5',
21 | '--borderColor': '#ebeef5',
22 | };
23 |
24 | export default {
25 | sizes,
26 | colors,
27 | };
28 |
--------------------------------------------------------------------------------
/app/configs/themes/portal.js:
--------------------------------------------------------------------------------
1 | const sizes = {
2 | '--maxWidth': '86vw',
3 | '--menuWidth': '200px',
4 | '--collapseWidth': '60px',
5 | '--collapseMenuWidth': '160px',
6 | '--headerHeight': '56px',
7 | '--footerHeight': '40px',
8 | '--breadHeight': '40px',
9 | '--menuItemHeight': '45px',
10 | };
11 | const colors = {
12 | '--appColor': '#495057',
13 | '--appBgColor': '#eaeff2',
14 | '--bannerBgColor': '#21364a',
15 | '--navBgColor': '#21364a',
16 | '--menuBgColor': '#ffffff',
17 | '--panelBgColor': '#ffffff',
18 | '--linkColor': '#495057',
19 | '--linkHoverColor': '#2196f3',
20 | '--linkActiveColor': '#42a5f5',
21 | '--headerLinkColor': '#ffffff',
22 | '--bannerLinkColor': '#ffffff',
23 | '--borderColor': '#eff2f7',
24 | };
25 |
26 | export default {
27 | sizes,
28 | colors,
29 | };
30 |
--------------------------------------------------------------------------------
/app/configs/themes/portal1.js:
--------------------------------------------------------------------------------
1 | const sizes = {
2 | '--maxWidth': '1310px',
3 | '--menuWidth': '200px',
4 | '--collapseWidth': '60px',
5 | '--collapseMenuWidth': '180px',
6 | '--headerHeight': '60px',
7 | '--footerHeight': '50px',
8 | '--breadHeight': '50px',
9 | '--menuItemHeight': '50px',
10 | };
11 | const colors = {
12 | '--appColor': '#495057',
13 | '--appBgColor': '#aab0c7',
14 | '--bannerBgColor': '#9575ce',
15 | '--navBgColor': '#9575ce',
16 | '--menuBgColor': '#ffffff',
17 | '--pageBgColor': '#e9edf0',
18 | '--panelBgColor': '#ffffff',
19 | '--linkColor': '#455a64',
20 | '--linkHoverColor': '#2196f3',
21 | '--linkActiveColor': '#42a5f5',
22 | '--headerLinkColor': '#f0f0f0',
23 | '--bannerLinkColor': '#f0f0f0',
24 | '--borderColor': '#d0d0d0',
25 | };
26 |
27 | export default {
28 | sizes,
29 | colors,
30 | };
31 |
--------------------------------------------------------------------------------
/app/configs/themes/themes.js:
--------------------------------------------------------------------------------
1 | const sizes = {
2 | '--maxWidth': '100vw',
3 | '--menuWidth': '220px',
4 | '--collapseWidth': '68px',
5 | '--collapseMenuWidth': '180px',
6 | '--headerHeight': '60px',
7 | '--footerHeight': '50px',
8 | '--breadHeight': '50px',
9 | '--menuItemHeight': '48px',
10 | };
11 | const color1 = {
12 | '--appColor': '#859abd',
13 | '--appBgColor': '#243550',
14 | '--bannerBgColor': '#334a60',
15 | '--navBgColor': '#243550',
16 | '--menuBgColor': '#334a60',
17 | '--panelBgColor': '#334a60',
18 | '--linkColor': '#859abd',
19 | '--linkHoverColor': '#ffffff',
20 | '--linkActiveColor': '#ffffff',
21 | '--bannerLinkColor': '#ffffff',
22 | '--borderColor': '#859abd',
23 | };
24 | const color2 = {
25 | '--appColor': '#24312b',
26 | '--appBgColor': '#f9f7f2',
27 | '--bannerBgColor': '#01170e',
28 | '--navBgColor': '#ffffff',
29 | '--menuBgColor': '#01170e',
30 | '--panelBgColor': '#ffffff',
31 | '--linkColor': '#24312b',
32 | '--linkHoverColor': '#dc6962',
33 | '--linkActiveColor': '#dc6962',
34 | '--bannerLinkColor': '#fbfbfb',
35 | '--asideLinkColor': '#f2f2f2',
36 | '--borderColor': '#ebeef5',
37 | };
38 | const color3 = {
39 | '--appColor': '#334a60',
40 | '--appBgColor': '#f2f2f2',
41 | '--bannerBgColor': '#e6e5f2',
42 | '--navBgColor': '#ffffff',
43 | '--menuBgColor': 'linear-gradient(to bottom, #e6e5f2, #4599cd)',
44 | '--panelBgColor': '#ffffff',
45 | '--linkColor': '#334a60',
46 | '--linkHoverColor': '#ab47bc',
47 | '--linkActiveColor': '#bc5090',
48 | '--borderColor': '#ebeef5',
49 | };
50 | const color4 = {
51 | '--appColor': '#21364a',
52 | '--appBgColor': '#c5cae9',
53 | '--bannerBgColor': '#e6e5f2',
54 | '--navBgColor': 'linear-gradient(to right,#4568dc, #b06ab3)',
55 | '--menuBgColor': 'linear-gradient(to bottom,#e6e5f2, #4599cd)',
56 | '--panelBgColor': 'linear-gradient(to right,#beb9db, #7eb0d5)',
57 | '--linkColor': '#21364a',
58 | '--linkHoverColor': '#fb8c00',
59 | '--linkActiveColor': '#fb8c00',
60 | '--headerLinkColor': '#fcfcfc',
61 | '--borderColor': 'rgba(0, 0, 0, 0.12)',
62 | };
63 |
64 | const theme1 = {sizes, colors: color1};
65 | const theme2 = {sizes, colors: color2};
66 | const theme3 = {sizes, colors: color3};
67 | const theme4 = {sizes, colors: color4};
68 |
69 | export {theme1, theme2, theme3, theme4};
70 |
--------------------------------------------------------------------------------
/app/globals/getRouterAuth.js:
--------------------------------------------------------------------------------
1 | import {getParams, storage} from '@huxy/utils';
2 |
3 | const getRouterAuth = () => {
4 | const {params} = getParams(location.href);
5 | if (params?.authed_token) {
6 | storage.set('token', params.authed_token);
7 | }
8 | };
9 |
10 | export default getRouterAuth;
11 |
--------------------------------------------------------------------------------
/app/globals/registerPwa.js:
--------------------------------------------------------------------------------
1 | const {isDev, configs} = process?.env ?? {};
2 |
3 | const registerPwa = () => {
4 | if (!isDev && 'serviceWorker' in navigator) {
5 | window.addEventListener('load', () => {
6 | navigator.serviceWorker
7 | .register(`${configs?.basepath ?? ''}/service-worker.js`)
8 | .then(registration => {
9 | // console.log('SW registered: ',registration);
10 | })
11 | .catch(registrationError => {
12 | // console.log('SW registration failed: ',registrationError);
13 | });
14 | });
15 | navigator.serviceWorker.addEventListener('controllerchange', () => {
16 | window.location.reload();
17 | });
18 | }
19 | };
20 |
21 | export default registerPwa;
22 |
--------------------------------------------------------------------------------
/app/hooks/useFetchList.jsx:
--------------------------------------------------------------------------------
1 | import {useCallback, useEffect, useRef} from 'react';
2 | import {useAsync} from '@huxy/use';
3 |
4 | const useFetchList = (fetchList, initParams = null, handleResult, commonParams = null) => {
5 | const [result, updateResult] = useAsync({});
6 | const isMounted = useRef(false);
7 | const update = useCallback(params => fetchList && updateResult({res: fetchList({...commonParams, ...params})}, handleResult), []);
8 | useEffect(() => {
9 | if (!isMounted.current) {
10 | isMounted.current = true;
11 | update({...initParams});
12 | }
13 | }, []);
14 | const {res} = result;
15 |
16 | return [{pending: res?.pending, data: res?.result}, update];
17 | };
18 |
19 | export default useFetchList;
20 |
--------------------------------------------------------------------------------
/app/hooks/useGetI18ns.jsx:
--------------------------------------------------------------------------------
1 | import {useState, useEffect} from 'react';
2 | import getI18n from '@app/utils/getI18n';
3 | import {getApiFn} from '@app/apis/apiList';
4 | import {langStore} from '@app/store/stores';
5 |
6 | const useGetI18ns = () => {
7 | const [loading, setLoading] = useState(true);
8 | useEffect(() => {
9 | const loadI18n = async () => {
10 | setLoading(true);
11 | try {
12 | await getApiFn();
13 | const {language} = await getI18n();
14 | langStore.setState(language);
15 | setLoading(false);
16 | } catch (err) {
17 | setLoading(false);
18 | }
19 | };
20 | loadI18n();
21 | }, []);
22 | return [loading];
23 | };
24 |
25 | export default useGetI18ns;
26 |
--------------------------------------------------------------------------------
/app/hooks/useGetProfile.jsx:
--------------------------------------------------------------------------------
1 | import {useState, useEffect} from 'react';
2 | import apiList from '@app/apis/apiList';
3 | import {logout} from '@app/utils/utils';
4 | import {defProject} from '@app/configs';
5 | import {userInfoStore, permissionStore, routersStore} from '@app/store/stores';
6 |
7 | const useGetProfile = () => {
8 | const {profileFn, listAuthFn, listRouterFn} = apiList;
9 | const [loading, setLoading] = useState(true);
10 | useEffect(() => {
11 | const getProfile = async () => {
12 | setLoading(true);
13 | try {
14 | const {code, result} = (await profileFn()) || {};
15 | if (!result) {
16 | logout(true);
17 | setLoading(false);
18 | return;
19 | }
20 | if (code === 200) {
21 | userInfoStore.setState(result);
22 | getAuths(result);
23 | }
24 | } catch (err) {
25 | setLoading(false);
26 | }
27 | };
28 | const getAuths = async profile => {
29 | try {
30 | const {code, result} = (await listAuthFn({uid: profile?._id})) || {};
31 | if (code === 200) {
32 | permissionStore.setState(result);
33 | getRouters(profile);
34 | }
35 | } catch (err) {
36 | setLoading(false);
37 | }
38 | };
39 | const getRouters = async profile => {
40 | try {
41 | const {code, result} = (await listRouterFn({projectId: profile?.projectId || defProject._id})) || {};
42 | setLoading(false);
43 | if (code === 200) {
44 | routersStore.setState(result);
45 | }
46 | } catch (err) {
47 | setLoading(false);
48 | }
49 | };
50 | getProfile();
51 | }, []);
52 | return [loading];
53 | };
54 |
55 | export default useGetProfile;
56 |
--------------------------------------------------------------------------------
/app/hooks/useHandleList.jsx:
--------------------------------------------------------------------------------
1 | import {useRef} from 'react';
2 | import useFetchList from './useFetchList';
3 |
4 | const useHandleList = (fetchList, initParams = null, handleResult, commonParams = null) => {
5 | const {current, size, ...rest} = initParams || {};
6 | const search = useRef(rest || {});
7 | const page = useRef({current: current || 1, size: size || 10});
8 | const [result, update] = useFetchList(fetchList, {...page.current, ...search.current}, handleResult, commonParams);
9 |
10 | const pageChange = (current, size) => {
11 | page.current = {current, size};
12 | update({
13 | ...page.current,
14 | ...search.current,
15 | });
16 | };
17 | const searchList = values => {
18 | search.current = values;
19 | page.current = {...page.current, current: 1};
20 | update({...page.current, ...search.current});
21 | };
22 | const handleUpdate = params => {
23 | const {current, size, ...rest} = params || {};
24 | page.current = {current: current ?? page.current.current, size: size ?? page.current.size};
25 | search.current = {...search.current, ...rest};
26 | update({...page.current, ...search.current});
27 | };
28 |
29 | return [result, handleUpdate, pageChange, searchList];
30 | };
31 |
32 | export default useHandleList;
33 |
--------------------------------------------------------------------------------
/app/i18ns/en/index.js:
--------------------------------------------------------------------------------
1 | import router from './router';
2 | import nav from './nav';
3 | import theme from './theme';
4 | import main from './main';
5 | import login from './login';
6 |
7 | const title = 'Huxy-Admin';
8 |
9 | export default {
10 | title,
11 | router,
12 | nav,
13 | theme,
14 | main,
15 | login,
16 | };
17 |
--------------------------------------------------------------------------------
/app/i18ns/en/login.js:
--------------------------------------------------------------------------------
1 | const login = {
2 | username: 'Username',
3 | password: 'Password',
4 | login: 'Login',
5 | visitor: 'Visitor',
6 | signup: 'Signup',
7 | forgetPwd: 'ForgetPwd',
8 | thirdParty: 'ThirdParty',
9 | email: 'Email',
10 | confirmPwd: 'ConfirmPwd',
11 | backLogin: 'BackLogin',
12 | signup_msg: 'Registration success!',
13 | signup_sub_msg: 'An activation link has been sent to your mailbox, please check for activation in time!',
14 | confirmEmail: 'ConfirmEmail',
15 | verifyEmail_msg: 'Verified successfully!',
16 | verifyEmail_sub_msg: 'A link to reset your password has been sent to your mailbox, please check it in time!',
17 | resetPwd: 'ResetPwd',
18 | };
19 |
20 | export default login;
21 |
--------------------------------------------------------------------------------
/app/i18ns/en/nav.js:
--------------------------------------------------------------------------------
1 | const nav = {
2 | left: {
3 | collapse: 'Collapse',
4 | projectList: 'ProjectList',
5 | doc: 'Doc',
6 | docs: 'Docs',
7 | files: 'Files',
8 | chat: 'Chat',
9 | chatbot: 'ChatBot',
10 | wechat: 'Wechat',
11 | followMe: 'FollowMe',
12 | },
13 | right: {
14 | user: 'Visitor',
15 | profile: 'Profile',
16 | settings: 'Setting',
17 | orders: 'Orders',
18 | logout: 'Logout',
19 | signin: 'Signin',
20 | language: 'Language',
21 | zh: '中文',
22 | en: 'English',
23 | themeList: 'ThemeList',
24 | github: 'Github',
25 | screenshot: 'Screenshot',
26 | screencapture_msg: 'Page screenshot download completed!',
27 | },
28 | footer: {
29 | copy: `©${new Date().getFullYear()} Huxy`,
30 | right: '京ICP备XXXXXXXX号-2',
31 | about: 'About',
32 | team: 'Team',
33 | contact: 'Contact',
34 | },
35 | };
36 |
37 | export default nav;
38 |
--------------------------------------------------------------------------------
/app/i18ns/en/theme.js:
--------------------------------------------------------------------------------
1 | const theme = {
2 | // theme name
3 | defaults: 'Defaults',
4 | dark: 'Dark',
5 | light: 'Light',
6 | portal: 'Portal',
7 | // fontSize
8 | fontSize: 'FontSize',
9 | // menuType
10 | menuType: 'MenuType',
11 | // size
12 | '--maxWidth': 'maxWidth',
13 | '--menuWidth': 'menuWidth',
14 | '--collapseWidth': 'collapseWidth',
15 | '--collapseMenuWidth': 'collapseMenuWidth',
16 | '--headerHeight': 'headerHeight',
17 | '--footerHeight': 'footerHeight',
18 | '--breadHeight': 'breadHeight',
19 | '--menuItemHeight': 'menuItemHeight',
20 | '--topbarHeight': 'topbarHeight',
21 | // color
22 | '--bannerBgColor': 'bannerBgColor',
23 | '--navBgColor': 'navBgColor',
24 | '--menuBgColor': 'menuBgColor',
25 | // '--deepMenuBgColor':'deepMenuBgColor',
26 | '--appBgColor': 'appBgColor',
27 | '--pageBgColor': 'pageBgColor',
28 | '--panelBgColor': 'panelBgColor',
29 | // '--footerBgColor':'footerBgColor',
30 | '--appColor': 'appColor',
31 | '--linkColor': 'linkColor',
32 | '--linkHoverColor': 'linkHoverColor',
33 | '--linkActiveColor': 'linkActiveColor',
34 | '--borderColor': 'borderColor',
35 | };
36 |
37 | export default theme;
38 |
--------------------------------------------------------------------------------
/app/i18ns/zh/index.js:
--------------------------------------------------------------------------------
1 | import router from './router';
2 | import nav from './nav';
3 | import theme from './theme';
4 | import main from './main';
5 | import login from './login';
6 |
7 | const title = 'Huxy-Admin';
8 |
9 | export default {
10 | title,
11 | router,
12 | nav,
13 | theme,
14 | main,
15 | login,
16 | };
17 |
--------------------------------------------------------------------------------
/app/i18ns/zh/login.js:
--------------------------------------------------------------------------------
1 | const login = {
2 | username: '用户名',
3 | password: '密码',
4 | login: '登录',
5 | visitor: '游客登录',
6 | signup: '注册',
7 | forgetPwd: '忘记密码',
8 | thirdParty: '第三方登录',
9 | email: '邮箱',
10 | confirmPwd: '确认密码',
11 | backLogin: '返回登录',
12 | signup_msg: '注册成功!',
13 | signup_sub_msg: '已向您的邮箱发送激活链接,请及时查收激活!',
14 | confirmEmail: '邮箱验证',
15 | verifyEmail_msg: '验证成功!',
16 | verifyEmail_sub_msg: '已向您的邮箱发送重置密码链接,请及时查收!',
17 | resetPwd: '重置密码',
18 | };
19 |
20 | export default login;
21 |
--------------------------------------------------------------------------------
/app/i18ns/zh/nav.js:
--------------------------------------------------------------------------------
1 | const nav = {
2 | left: {
3 | collapse: '切换',
4 | projectList: '项目列表',
5 | doc: '文档',
6 | docs: '文档系统',
7 | files: '文件系统',
8 | chat: '聊天室',
9 | chatbot: 'AI助手',
10 | wechat: '微信',
11 | followMe: '关注我',
12 | },
13 | right: {
14 | user: '游客',
15 | profile: '个人中心',
16 | settings: '设置',
17 | orders: '我的订单',
18 | logout: '退出',
19 | signin: '登录',
20 | language: '语言',
21 | zh: '中文',
22 | en: 'English',
23 | themeList: '主题',
24 | github: 'github',
25 | screenshot: '截屏',
26 | screencapture_msg: '页面截屏下载完成!',
27 | },
28 | footer: {
29 | copy: `©${new Date().getFullYear()} Huxy`,
30 | right: '京ICP备XXXXXXXX号-2',
31 | about: '关于',
32 | team: '团队',
33 | contact: '联系我们',
34 | },
35 | };
36 |
37 | export default nav;
38 |
--------------------------------------------------------------------------------
/app/i18ns/zh/router.js:
--------------------------------------------------------------------------------
1 | const router = {
2 | '/': '首页',
3 | '/404': '404',
4 | '/layout': '框架配置',
5 | '/monitor': '页面监控',
6 | '/files': '文件管理',
7 | '/profile': '个人中心',
8 | '/messages': '消息管理',
9 | '/md2html': '文档管理',
10 | '/bigscreen': '大屏',
11 | '/carmodel': '汽车模型',
12 | '/chatbot': 'AI助手',
13 | '/wschat': '聊天室',
14 | '/user': '登录注册',
15 | '/user/signin': '登录',
16 | '/user/signup': '注册',
17 | '/user/verifyEmail': '验证邮箱',
18 | '/user/setNewPwd': '重置密码',
19 | '/apps': 'Apps',
20 | '/apps/projects': '项目管理',
21 | '/apps/projects/add': '添加项目',
22 | '/apps/projects/edit/:projectId': '编辑项目',
23 | '/apps/projects/router/:projectId': '项目路由设置',
24 | '/apps/projects/router/:projectId/:routerId': '页面设计',
25 | '/apps/projects/api/:projectId': '项目接口管理',
26 | '/apps/projects/api/:projectId/add': '添加接口',
27 | '/apps/projects/api/:projectId/edit/:id': '编辑接口',
28 | '/apps/projects/api/:projectId/test/:id': '接口测试',
29 | '/apps/users': '用户管理',
30 | '/apps/users/add': '添加用户',
31 | '/apps/users/edit/:id': '编辑用户',
32 | '/apps/users/auth/:id': '路由权限设置',
33 | '/apps/apis': '接口管理',
34 | '/apps/apis/add': '添加接口',
35 | '/apps/apis/edit/:id': '编辑接口',
36 | '/apps/apis/test/:id': '接口测试',
37 | '/low-code': '低代码',
38 | '/preview': '预览',
39 | '/low-code/dom': '原生Dom',
40 | '/low-code/ui': 'UI组件',
41 | '/low-code/users': '业务组件',
42 | '/low-code/users/add': '新增用户',
43 | '/dashboard': '仪表盘',
44 | '/dashboard/screen1': '模板1',
45 | '/dashboard/bigscreen': '大屏',
46 | '/dashboard/carmodel': '汽车模型',
47 | '/prompt': 'Prompt',
48 | '/prompt/prompt': '提示列表',
49 | '/prompt/prompt/add': '新增提示',
50 | '/prompt/prompt/edit/:id': '编辑提示',
51 | '/payer': '会员管理',
52 | '/payer/count': '包次会员',
53 | '/payer/count/member': '开通会员',
54 | '/payer/count/order': '订单列表',
55 | '/payer/count/pay': '支付',
56 | '/payer/month': '包月会员',
57 | '/payer/month/member': '开通会员',
58 | '/payer/month/order': '订单列表',
59 | '/payer/month/pay': '支付',
60 | '/demand': '需求管理',
61 | '/demand/demand': '需求列表',
62 | '/demand/demand/add': '新增需求',
63 | '/demand/demand/edit/:id': '编辑需求',
64 | };
65 |
66 | export default router;
67 |
--------------------------------------------------------------------------------
/app/i18ns/zh/theme.js:
--------------------------------------------------------------------------------
1 | const theme = {
2 | // theme name
3 | defaults: '默认主题',
4 | dark: '深暗色',
5 | light: '浅亮色',
6 | portal: '门户',
7 | // fontSize
8 | fontSize: '字体大小',
9 | menuType: '菜单类型',
10 | // size
11 | '--maxWidth': '框架最大宽度',
12 | '--menuWidth': '侧边菜单宽度',
13 | '--collapseWidth': '菜单收缩宽度',
14 | '--collapseMenuWidth': '收缩菜单宽度',
15 | '--headerHeight': '头部高度',
16 | '--footerHeight': '底部高度',
17 | '--breadHeight': '面包屑高度',
18 | '--menuItemHeight': '菜单行高',
19 | '--topbarHeight': '顶部高度',
20 | // color
21 | '--bannerBgColor': 'banner背景色',
22 | '--navBgColor': 'nav背景色',
23 | '--menuBgColor': 'menu背景色',
24 | // '--deepMenuBgColor':'深层menu背景色',
25 | '--appBgColor': 'app背景色',
26 | '--pageBgColor': '页面背景色',
27 | '--panelBgColor': 'panel背景色',
28 | // '--footerBgColor':'底部背景色',
29 | '--appColor': 'app颜色',
30 | '--linkColor': '框架链接颜色',
31 | '--linkHoverColor': '链接hover颜色',
32 | '--linkActiveColor': '链接active颜色',
33 | '--borderColor': '边框颜色',
34 | };
35 |
36 | export default theme;
37 |
--------------------------------------------------------------------------------
/app/index.jsx:
--------------------------------------------------------------------------------
1 | import {createRoot} from 'react-dom/client';
2 |
3 | import App from './app';
4 |
5 | import getRouterAuth from '@app/globals/getRouterAuth';
6 | import registerPwa from '@app/globals/registerPwa';
7 |
8 | import '@app/commons/styles/index.less';
9 | import '@app/assets/styles.less';
10 |
11 | createRoot(document.getElementById('app')).render();
12 |
13 | getRouterAuth();
14 | registerPwa();
15 |
--------------------------------------------------------------------------------
/app/models/animateObjs.js:
--------------------------------------------------------------------------------
1 | import brain from './icons/brain.png';
2 | import trend from './icons/trend.png';
3 | import coder from './icons/coder.png';
4 | import dataAnalysis from './icons/data-analysis.png';
5 | import light from './icons/light.png';
6 | import debug from './icons/debug.png';
7 | import chat from './icons/chat.png';
8 |
9 | import CircleRing from './circleRing';
10 |
11 | const objs = [
12 | {
13 | value: 'centerTable',
14 | label: 'centerTable',
15 | icon: ,
16 | details: '',
17 | link: '',
18 | type: 'center',
19 | },
20 | {
21 | value: 'brain',
22 | label: 'GitHub',
23 | icon: brain,
24 | details: '',
25 | link: 'https://github.com/ahyiru',
26 | type: '',
27 | },
28 | {
29 | value: 'trend',
30 | label: 'NPM',
31 | icon: trend,
32 | details: '',
33 | link: 'https://www.npmjs.com/org/huxy',
34 | type: '',
35 | },
36 | {
37 | value: 'coder',
38 | label: 'Gitee',
39 | icon: coder,
40 | details: '',
41 | link: 'https://gitee.com/yiru',
42 | type: '',
43 | },
44 | {
45 | value: 'dataAnalysis',
46 | label: 'ihuxy',
47 | icon: dataAnalysis,
48 | details: '',
49 | link: 'https://ihuxy.com/',
50 | type: '',
51 | },
52 | {
53 | value: 'light',
54 | label: '专栏',
55 | icon: light,
56 | details: '',
57 | link: 'https://www.zhihu.com/column/c_1129074288602603520',
58 | type: '',
59 | },
60 | {
61 | value: 'debug',
62 | label: 'mern',
63 | icon: debug,
64 | details: '',
65 | link: 'https://github.com/ahyiru/mern',
66 | type: '',
67 | },
68 | {
69 | value: 'chat',
70 | label: '场景设计',
71 | icon: chat,
72 | details: '',
73 | link: 'https://mp.weixin.qq.com/s/A6_Robhv6kl3R_m9Z7yk3A',
74 | type: '',
75 | },
76 | ];
77 |
78 | export default objs;
79 |
--------------------------------------------------------------------------------
/app/models/circleRing.jsx:
--------------------------------------------------------------------------------
1 | import {rmUnit} from '@huxy/utils';
2 | import {Circle, Ring, Light} from '@huxy/materials';
3 |
4 | const centerStyle = {
5 | position: 'absolute',
6 | left: '50%',
7 | top: '50%',
8 | transform: 'translate(-50%, -50%)',
9 | };
10 |
11 | const CircleRing = ({height = '240px', padding = '30px', style}) => (
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | );
21 |
22 | export default props => (
23 |
24 |
25 |
26 |
27 | );
28 |
--------------------------------------------------------------------------------
/app/models/icons/agile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/agile.png
--------------------------------------------------------------------------------
/app/models/icons/algorithm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/algorithm.png
--------------------------------------------------------------------------------
/app/models/icons/analysis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/analysis.png
--------------------------------------------------------------------------------
/app/models/icons/api.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/api.png
--------------------------------------------------------------------------------
/app/models/icons/brain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/brain.png
--------------------------------------------------------------------------------
/app/models/icons/chat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/chat.png
--------------------------------------------------------------------------------
/app/models/icons/coder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/coder.png
--------------------------------------------------------------------------------
/app/models/icons/control.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/control.png
--------------------------------------------------------------------------------
/app/models/icons/dashboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/dashboard.png
--------------------------------------------------------------------------------
/app/models/icons/data-analysis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/data-analysis.png
--------------------------------------------------------------------------------
/app/models/icons/debug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/debug.png
--------------------------------------------------------------------------------
/app/models/icons/diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/diagram.png
--------------------------------------------------------------------------------
/app/models/icons/digital.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/digital.png
--------------------------------------------------------------------------------
/app/models/icons/light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/light.png
--------------------------------------------------------------------------------
/app/models/icons/manufacturing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/manufacturing.png
--------------------------------------------------------------------------------
/app/models/icons/monitoring.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/monitoring.png
--------------------------------------------------------------------------------
/app/models/icons/not-found.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/not-found.png
--------------------------------------------------------------------------------
/app/models/icons/programming.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/programming.png
--------------------------------------------------------------------------------
/app/models/icons/screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/screen.png
--------------------------------------------------------------------------------
/app/models/icons/simulation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/simulation.png
--------------------------------------------------------------------------------
/app/models/icons/trend.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/trend.png
--------------------------------------------------------------------------------
/app/models/icons/web-analysis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/web-analysis.png
--------------------------------------------------------------------------------
/app/models/icons/write.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/models/icons/write.png
--------------------------------------------------------------------------------
/app/models/models.js:
--------------------------------------------------------------------------------
1 | import icons from './icons';
2 | import objs from './objs';
3 |
4 | const models = objs.map(({icon, ...rest}) => ({...rest, icon: icons[icon]}));
5 |
6 | export default models;
7 |
--------------------------------------------------------------------------------
/app/public/.spa:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/public/.spa
--------------------------------------------------------------------------------
/app/public/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/public/favicon.png
--------------------------------------------------------------------------------
/app/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | <%= htmlWebpackPlugin.options.title %>
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "huxy",
3 | "short_name": "huxy",
4 | "description": "huxy",
5 | "lang": "cn",
6 | "display": "standalone",
7 | "orientation": "any",
8 | "start_url": ".",
9 | "theme_color": "#313131",
10 | "background_color": "#313131",
11 | "icons": [
12 | {
13 | "src": "./src/images/96.png",
14 | "sizes": "96x96",
15 | "type": "image/png"
16 | },
17 | {
18 | "src": "./src/images/144.png",
19 | "sizes": "144x144",
20 | "type": "image/png"
21 | },
22 | {
23 | "src": "./src/images/192.png",
24 | "sizes": "192x192",
25 | "type": "image/png",
26 | "purpose": "any maskable"
27 | },
28 | {
29 | "src": "./src/images/512.png",
30 | "sizes": "512x512",
31 | "type": "image/png"
32 | }
33 | ]
34 | }
35 |
--------------------------------------------------------------------------------
/app/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow: /img/
--------------------------------------------------------------------------------
/app/public/src/images/144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/public/src/images/144.png
--------------------------------------------------------------------------------
/app/public/src/images/192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/public/src/images/192.png
--------------------------------------------------------------------------------
/app/public/src/images/512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/public/src/images/512.png
--------------------------------------------------------------------------------
/app/public/src/images/96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/public/src/images/96.png
--------------------------------------------------------------------------------
/app/routes/defaultPermList.js:
--------------------------------------------------------------------------------
1 | const defaultPermList = [
2 | '/',
3 | '/404',
4 | '/layout',
5 | '/profile',
6 | '/messages',
7 | '/user',
8 | '/user/signin',
9 | '/user/signup',
10 | '/user/verifyEmail',
11 | '/user/setNewPwd',
12 | '/payer',
13 | '/payer/count',
14 | '/payer/count/member',
15 | '/payer/count/order',
16 | '/payer/count/pay',
17 | ];
18 |
19 | export default defaultPermList;
20 |
--------------------------------------------------------------------------------
/app/routes/index.js:
--------------------------------------------------------------------------------
1 | import {traverItem, arr2TreeByPath, mergeArr} from '@huxy/utils';
2 |
3 | import {notAdmin} from '@app/utils/isAdmin';
4 |
5 | import Icon from '@app/components/icon';
6 |
7 | import staticRoutes from './routerComp/staticRoutes';
8 | import dynamicRoutes from './routerComp/dynamicRoutes';
9 | import defaultPermList from './defaultPermList';
10 |
11 | const whiteList = ['/playground'];
12 |
13 | const getWhiteRoute = fullpath => whiteList.find(route => fullpath.indexOf(`${route}/`) !== 0 && route !== fullpath);
14 |
15 | const allRoutes = [
16 | {
17 | path: '/',
18 | component: () => import('@app/commons/layout'),
19 | children: dynamicRoutes,
20 | },
21 | ...staticRoutes,
22 | ];
23 |
24 | const routes = (routerList, nameList, permList, profile) => {
25 | const isAdmin = !notAdmin();
26 | const serverRoutes = traverItem(({denied, ...rest}) => {
27 | if (rest.parentId.length > 1) {
28 | rest.path = rest.path.replace(rest.parentId, '');
29 | }
30 | return rest;
31 | })(arr2TreeByPath(routerList || []));
32 |
33 | const fullList = mergeArr(allRoutes, serverRoutes, 'path');
34 |
35 | const permission = [...new Set([...(permList || []), ...defaultPermList])];
36 |
37 | return traverItem((item, parent) => {
38 | item.fullpath = [...parent, item]
39 | .map(item => item.path)
40 | .join('')
41 | .replace('//', '/');
42 | item.id = item._id;
43 | item.name = nameList?.[item.fullpath] ?? item.name;
44 | let icon = item.icon;
45 | if (icon && icon !== true) {
46 | item.icon = ;
47 | }
48 | if (typeof item.denied === 'function') {
49 | item.denied = item.denied();
50 | }
51 | if (!isAdmin && getWhiteRoute(item.fullpath)) {
52 | item.denied = item.denied || !permission.includes(item.fullpath);
53 | }
54 | })(fullList);
55 | };
56 |
57 | export default routes;
58 |
--------------------------------------------------------------------------------
/app/routes/routerComp/dynamicRoutes.js:
--------------------------------------------------------------------------------
1 | import layoutRoutes from '@app/views/layout/routes';
2 | import payerRoutes from '@app/views/payer/routes';
3 | import messageRoutes from '@app/views/message/routes';
4 | import playgroundRoutes from '@app/views/playground/routes';
5 |
6 | const profileRoutes = {
7 | path: '/profile',
8 | name: '个人中心',
9 | title: '个人中心',
10 | hideMenu: true,
11 | component: () => import('@app/views/user/src/profile'),
12 | };
13 |
14 | export default [layoutRoutes, payerRoutes, playgroundRoutes, ...messageRoutes, profileRoutes];
15 |
--------------------------------------------------------------------------------
/app/routes/routerComp/staticRoutes.js:
--------------------------------------------------------------------------------
1 | import userRoutes from '@app/views/user/routes';
2 |
3 | const routes = [
4 | ...userRoutes,
5 | {
6 | path: '/404',
7 | name: '404',
8 | component: import('@app/views/404'),
9 | hideMenu: true,
10 | },
11 | ];
12 |
13 | export default routes;
14 |
--------------------------------------------------------------------------------
/app/routes/whiteList.js:
--------------------------------------------------------------------------------
1 | import {traverItem} from '@huxy/utils';
2 | import staticRoutes from './routerComp/staticRoutes';
3 |
4 | const whiteList = ['/layout'];
5 |
6 | traverItem((item, parent) => {
7 | const path = `${parent.map(v => v.path).join('')}${item.path}`;
8 | whiteList.push(path);
9 | })(staticRoutes);
10 |
11 | export default whiteList;
12 |
--------------------------------------------------------------------------------
/app/store/index.js:
--------------------------------------------------------------------------------
1 | import {createStore, createContainer} from '@huxy/utils';
2 | import {createContainer as createUseContainer} from '@huxy/use';
3 |
4 | export const container = createStore();
5 |
6 | export const store = createContainer(container);
7 | export const useStore = createUseContainer(container);
8 |
--------------------------------------------------------------------------------
/app/store/names.js:
--------------------------------------------------------------------------------
1 | export const langName = 'lang-store';
2 | export const themeName = 'theme-store';
3 | export const menuTypeName = 'menuType-store';
4 | export const i18nsName = 'i18ns-store';
5 | export const userInfoName = 'userInfo-store';
6 | export const permissionName = 'permission-store';
7 | export const routersName = 'routers-store';
8 | export const notifyName = 'notify-store';
9 |
--------------------------------------------------------------------------------
/app/store/stores.js:
--------------------------------------------------------------------------------
1 | import {store, useStore} from '.';
2 | import {langName, themeName, menuTypeName, i18nsName, userInfoName, permissionName, routersName, notifyName} from './names';
3 |
4 | export const langStore = store(langName);
5 | export const menuTypeStore = store(menuTypeName);
6 | export const themeStore = store(themeName, {});
7 | export const i18nsStore = store(i18nsName, {});
8 | export const userInfoStore = store(userInfoName, {});
9 | export const permissionStore = store(permissionName, []);
10 | export const routersStore = store(routersName, []);
11 | export const notifyStore = store(notifyName, 0);
12 |
13 | export const useLangStore = initState => useStore(langName, initState);
14 | export const useMenuTypeStore = initState => useStore(menuTypeName, initState);
15 | export const useThemeStore = (initState = {}) => useStore(themeName, initState);
16 | export const useI18nsStore = (initState = {}) => useStore(i18nsName, initState);
17 | export const useUserInfoStore = (initState = {}) => useStore(userInfoName, initState);
18 | export const usePermissionStore = (initState = []) => useStore(permissionName, initState);
19 | export const useRoutersStore = (initState = []) => useStore(routersName, initState);
20 | export const useNotifyStore = (initState = 0) => useStore(notifyName, initState);
21 |
--------------------------------------------------------------------------------
/app/sw/index.js:
--------------------------------------------------------------------------------
1 | const initSW = () => {
2 | if (!process.env.isDev && 'serviceWorker' in navigator) {
3 | window.addEventListener('load', () => {
4 | navigator.serviceWorker
5 | .register(`${process.env.configs.basepath}/service-worker.js`)
6 | .then(registration => {
7 | // console.log('SW registered: ',registration);
8 | })
9 | .catch(registrationError => {
10 | // console.log('SW registration failed: ',registrationError);
11 | });
12 | });
13 | navigator.serviceWorker.addEventListener('controllerchange', () => {
14 | window.location.reload();
15 | });
16 | }
17 | };
18 |
19 | export default initSW;
20 |
--------------------------------------------------------------------------------
/app/utils/confirmDesignPage.js:
--------------------------------------------------------------------------------
1 | import {Modal} from 'antd';
2 | import {ExclamationCircleOutlined} from '@ant-design/icons';
3 |
4 | const {confirm} = Modal;
5 |
6 | export const designReg = /\/projects\/router\/[0-9a-z]+\/[0-9a-z]+/;
7 |
8 | export const demoBackReg = /\/playground\/utils\/list\/auth\/[0-9a-z]+/;
9 |
10 | export const confirmDesignPage = next => {
11 | confirm({
12 | title: '数据还未保存,是否确认离开?',
13 | icon: ,
14 | content: '',
15 | onOk() {
16 | next();
17 | },
18 | onCancel() {
19 | next(false);
20 | },
21 | });
22 | };
23 |
--------------------------------------------------------------------------------
/app/utils/formatTree.js:
--------------------------------------------------------------------------------
1 | import {traverItem, arr2TreeByPath, isValidArr} from '@huxy/utils';
2 | import Icon from '@app/components/icon';
3 |
4 | const formatTree = arr =>
5 | traverItem(item => {
6 | if (!isValidArr(item.children)) {
7 | item.isLeaf = true;
8 | }
9 | item.key = item.key || item.path;
10 | if (typeof item.icon === 'string') {
11 | item.iconKey = item.icon;
12 | }
13 | item.icon = ;
14 | })(arr2TreeByPath(arr));
15 |
16 | export default formatTree;
17 |
--------------------------------------------------------------------------------
/app/utils/getI18n.js:
--------------------------------------------------------------------------------
1 | import {getValue} from '@huxy/utils';
2 | import {i18nsStore} from '@app/store/stores';
3 | import getLang from './getLang';
4 |
5 | const getI18n = async () => {
6 | const language = getLang();
7 | let i18ns = await import(`@app/i18ns/${language}`);
8 | i18ns = i18ns.default ?? i18ns;
9 | Object.setPrototypeOf(i18ns, {getValue: keys => getValue(i18ns, keys)});
10 | i18nsStore.setState(i18ns);
11 | return {i18ns, language};
12 | };
13 |
14 | export default getI18n;
15 |
--------------------------------------------------------------------------------
/app/utils/getLang.js:
--------------------------------------------------------------------------------
1 | import {storage, sysLang} from '@huxy/utils';
2 |
3 | const getLang = () => storage.get('language') || sysLang();
4 |
5 | export default getLang;
6 |
--------------------------------------------------------------------------------
/app/utils/getRouterCfgs.js:
--------------------------------------------------------------------------------
1 | import {routersStore, i18nsStore, permissionStore} from '@app/store/stores';
2 |
3 | import routes from '@app/routes';
4 |
5 | const getRouterCfgs = () => {
6 | const i18ns = i18nsStore.getState();
7 | const permission = permissionStore.getState();
8 | const routerList = routersStore.getState();
9 | return {routers: routes(routerList, i18ns.router, permission), title: i18ns.title};
10 | };
11 |
12 | export default getRouterCfgs;
13 |
--------------------------------------------------------------------------------
/app/utils/getTheme.js:
--------------------------------------------------------------------------------
1 | import {storage} from '@huxy/utils';
2 | import getThemeList from '@app/configs/theme';
3 | import {getIntls} from '@app/components/intl';
4 | import {isDarkMode} from '@app/utils/sysThemeMode';
5 |
6 | const getTheme = (key = null) => {
7 | const themeList = typeof getThemeList === 'function' ? getThemeList(getIntls) : [];
8 | if (key != null) {
9 | return themeList.find(item => item.key === key) ?? themeList[0] ?? {};
10 | }
11 | const theme = storage.get('theme') ?? themeList[0] ?? {};
12 | return isDarkMode() ? themeList[0] ?? {} : theme;
13 | };
14 |
15 | export default getTheme;
16 |
--------------------------------------------------------------------------------
/app/utils/icons.js:
--------------------------------------------------------------------------------
1 | import * as icons from '@ant-design/icons';
2 |
3 | export default icons;
4 |
--------------------------------------------------------------------------------
/app/utils/isAdmin.js:
--------------------------------------------------------------------------------
1 | import {userInfoStore} from '@app/store/stores';
2 |
3 | export const profile = () => userInfoStore.getState();
4 |
5 | export const notAdmin = () => profile()?.role !== 5;
6 |
7 | export const isMember = () => profile()?.payCount;
8 |
--------------------------------------------------------------------------------
/app/utils/patterns.js:
--------------------------------------------------------------------------------
1 | export const customRequired = {
2 | pattern: /.+/,
3 | message: '请输入!',
4 | };
5 |
6 | export const required = {
7 | required: true,
8 | };
9 |
10 | // 标题
11 | export const titlePattern = {
12 | pattern: /^[\u4E00-\u9FA5A-Za-z0-9_.-\s]{2,32}$/,
13 | message: '长度为2-20不含特殊字符!',
14 | };
15 | // 用户名
16 | export const namePattern = {
17 | pattern: /^[\u4E00-\u9FA5A-Za-z0-9_]{2,20}$/,
18 | message: '长度为2-20不含特殊字符!',
19 | };
20 | // 邮箱
21 | export const emailPattern = {
22 | pattern: /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
23 | message: '邮箱格式不正确!',
24 | };
25 | // 密码
26 | export const passwordPattern = {
27 | pattern: /^(?![a-z]+$)(?![A-Z]+$)(?![\d]+$)[0-9a-zA-Z!@#$_]{8,20}$/,
28 | message: '密码长度为8-20个字符,并且至少包含数字、大小写字母中的两种,不含除 !@#$_ 以外的特殊字符!',
29 | };
30 |
31 | // 链接地址
32 | export const urlPattern = {
33 | pattern: /^https?:\/\/[^\s/?.#]+\.[^\s]+/,
34 | message: '请输入正确链接!',
35 | };
36 | // 路由地址
37 | export const pathPattern = {
38 | // pattern: /^(\/[\w#?&=:.-]*)+$/,
39 | pattern: /^(\/[\w#?&=:.-]+)+$/,
40 | message: '请输入正确路径!',
41 | };
42 | // 链接或路由地址
43 | export const urlOrPathPattern = {
44 | pattern: /^https?:\/\/[^\s/?.#]+\.[^\s]+|^(\/[\w#?&=:.-]+)+$/,
45 | message: '请输入正确路径!',
46 | };
47 | // 版本号格式必须为X.Y.Z
48 | export const versionPattern = {
49 | pattern: /^\d+(?:\.\d+){2}$/,
50 | message: '版本号格式必须为X.Y.Z!',
51 | };
52 | // linux文件夹路径
53 | export const linuxPathPattern = {
54 | pattern: /^\/(\w+\/?)*$/, // /^\/(?:[^/]+\/)*$/
55 | message: '请输入正确路径!',
56 | };
57 | // linux文件路径
58 | export const linuxFilePattern = {
59 | pattern: /^\/(\w+\/)*\w+\.\w+$/, // /^\/(?:[^/]+\/)*[^/]+$/
60 | message: '请输入正确路径!',
61 | };
62 | // window下文件夹路径
63 | export const windowPathPattern = {
64 | pattern: /^[a-zA-Z]:\\(?:\w+\\?)*$/,
65 | message: '请输入正确路径!',
66 | };
67 | // window下文件路径
68 | export const windowFilePattern = {
69 | pattern: /^[a-zA-Z]:\\(?:\w+\\)*\w+\.\w+$/,
70 | message: '请输入正确路径!',
71 | };
72 |
--------------------------------------------------------------------------------
/app/utils/rules.js:
--------------------------------------------------------------------------------
1 | import {required, customRequired, titlePattern, namePattern, emailPattern, passwordPattern, pathPattern, urlPattern} from './patterns';
2 |
3 | export const titleRule = [required, titlePattern];
4 | export const urlRule = [urlPattern];
5 | export const nameRule = [required, namePattern];
6 | export const emailRule = [required, emailPattern];
7 | export const passwordRule = [required, passwordPattern];
8 | export const roleRule = [{type: 'number', min: 0, max: 5, message: '取值范围0-5!'}];
9 |
10 | export const confirmRule = [
11 | required,
12 | ({getFieldValue}) => ({
13 | validator(rule, value) {
14 | if (getFieldValue('password') === value) {
15 | return Promise.resolve();
16 | }
17 | return Promise.reject('两次输入的密码不一致!');
18 | },
19 | }),
20 | ];
21 |
22 | export const pathRule = [required, pathPattern];
23 |
24 | export const customNameRule = [customRequired, namePattern];
25 | export const customEmailRule = [customRequired, emailPattern];
26 | export const customPasswordRule = [customRequired, passwordPattern];
27 |
28 | export const checkVolid = (rules, value) => {
29 | for (let i = 0, l = rules.length; i < l; i++) {
30 | const rule = rules[i];
31 | if (!rule.pattern.test(value)) {
32 | return rule.message;
33 | }
34 | }
35 | };
36 |
--------------------------------------------------------------------------------
/app/utils/setStyleVar.js:
--------------------------------------------------------------------------------
1 | import {setStyle, hex2rgba} from '@huxy/utils';
2 |
3 | const getRgb = rgb => {
4 | if (rgb.includes('rgb')) {
5 | const matched = rgb.match(/rgba?\((.+)\)/);
6 | if (matched) {
7 | return matched[1]
8 | .split(',')
9 | .map(v => v.trim())
10 | .slice(0, 3)
11 | .join();
12 | }
13 | }
14 | return rgb;
15 | };
16 |
17 | const setStyleVar = (theme, ele = document.documentElement) => {
18 | const navBgColor = theme?.list?.colors?.['--navBgColor'];
19 | const menuBgColor = theme?.list?.colors?.['--menuBgColor'];
20 | const navBgRgb = getRgb(hex2rgba(navBgColor));
21 | const menuBgRgb = getRgb(hex2rgba(menuBgColor));
22 | const styleVars = {...theme?.list?.colors, ...theme?.list?.sizes, '--navBgRgb': navBgRgb, '--menuBgRgb': menuBgRgb};
23 | styleVars['--appLinkColor'] = styleVars['--linkColor'];
24 | styleVars['--appLinkActiveColor'] = styleVars['--linkActiveColor'];
25 | styleVars['--appLinkHoverColor'] = styleVars['--linkHoverColor'];
26 | styleVars['--containerHeight'] = `${ele.clientHeight}px`;
27 | setStyle(ele, styleVars, true);
28 | };
29 |
30 | export default setStyleVar;
31 |
--------------------------------------------------------------------------------
/app/utils/sizeRules.js:
--------------------------------------------------------------------------------
1 | export const sizeRules = unit => {
2 | unit = unit === 'px' ? 'px' : 'rem';
3 | const b = unit === 'rem' ? 1 : 10;
4 | return {
5 | '--maxWidth': {
6 | // px: [800, 2000],
7 | [unit]: [80 * b, 200 * b],
8 | vw: [60, 100],
9 | },
10 | '--menuWidth': {
11 | // px: [100, 300],
12 | [unit]: [10 * b, 30 * b],
13 | },
14 | '--collapseWidth': {
15 | // px: [50, 100],
16 | [unit]: [5 * b, 10 * b],
17 | },
18 | '--collapseMenuWidth': {
19 | // px: [100, 300],
20 | [unit]: [10 * b, 30 * b],
21 | },
22 | '--headerHeight': {
23 | // px: [50, 100],
24 | [unit]: [5 * b, 10 * b],
25 | },
26 | '--footerHeight': {
27 | // px: [40, 100],
28 | [unit]: [4 * b, 10 * b],
29 | },
30 | '--breadHeight': {
31 | // px: [30, 80],
32 | [unit]: [3 * b, 8 * b],
33 | },
34 | '--menuItemHeight': {
35 | // px: [30, 80],
36 | [unit]: [3 * b, 8 * b],
37 | },
38 | };
39 | };
40 |
41 | export const fontSize = {
42 | rem: [8, 16],
43 | };
44 |
--------------------------------------------------------------------------------
/app/utils/sysThemeMode.js:
--------------------------------------------------------------------------------
1 | import getTheme from '@app/utils/getTheme';
2 |
3 | export const isDarkMode = () => window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
4 |
5 | const sysThemeMode = setTheme => {
6 | if (!window.matchMedia) {
7 | return;
8 | }
9 | const query = window.matchMedia('(prefers-color-scheme: dark)');
10 | query.addEventListener(
11 | 'change',
12 | e => {
13 | setTheme(getTheme());
14 | },
15 | false,
16 | );
17 | };
18 |
19 | export default sysThemeMode;
20 |
--------------------------------------------------------------------------------
/app/utils/utils.js:
--------------------------------------------------------------------------------
1 | import {storage, fixPath} from '@huxy/utils';
2 | import apiList from '@app/apis/apiList';
3 | import {basepath, browserRouter} from '@app/configs';
4 |
5 | export const goPage = (url = '') => (location.href = url ? fixPath(browserRouter ? `${basepath}${url}` : `${basepath}/#/${url}`) : basepath || '/');
6 |
7 | export const logout = isLogout => {
8 | try {
9 | !isLogout && apiList.logoutFn();
10 | } catch (err) {}
11 | storage.rm('token');
12 | goPage('/user/signin');
13 | };
14 |
15 | export const isAuthed = () => storage.get('token');
16 |
--------------------------------------------------------------------------------
/app/views/404/index.jsx:
--------------------------------------------------------------------------------
1 | import {IconAnimate} from '@huxy/materials';
2 | import darkTheme from '@app/configs/themes/dark';
3 | import notFound from '@app/models/icons/not-found.png';
4 | import animateObjs from '@app/models/animateObjs';
5 | import cssModels from '@app/models/cssModels';
6 |
7 | import './index.less';
8 |
9 | const Index = props => {
10 | return (
11 |
12 |
{props.inputPath} is not found
13 |
14 |

15 |
16 |
17 |
18 |
19 |
20 | );
21 | };
22 |
23 | export default Index;
24 |
--------------------------------------------------------------------------------
/app/views/404/index.less:
--------------------------------------------------------------------------------
1 | @keyframes icon-404-animate {
2 | 0% {
3 | transform: scale(1.2) translate(0, 60px);
4 | }
5 | 25% {
6 | transform: scale(1) translate(60px, 0);
7 | }
8 | 50% {
9 | transform: scale(0.8) translate(0, -60px);
10 | }
11 | 75% {
12 | transform: scale(1) translate(-60px, 0);
13 | }
14 | 100% {
15 | transform: scale(1.2) translate(0, 60px);
16 | }
17 | }
18 |
19 | .not-found-page {
20 | width: 100%;
21 | height: var(--containerHeight);
22 | position: relative;
23 | background: var(--appBgColor, rgba(0, 0, 0, 0.8));
24 | padding-top: 100px;
25 | overflow: hidden;
26 | // display: flex;
27 | // align-items: center;
28 | // justify-content: center;
29 | }
30 |
31 | .not-found-icon {
32 | width: 100px;
33 | height: 100px;
34 | margin: 0 auto;
35 | img {
36 | width: 100%;
37 | height: 100%;
38 | }
39 | transform: scale(1) translate(0, 0);
40 | animation: icon-404-animate 6s linear infinite;
41 | }
42 |
43 | .animation-info {
44 | position: relative;
45 | padding-top: 50px;
46 | }
47 |
--------------------------------------------------------------------------------
/app/views/layout/routes.js:
--------------------------------------------------------------------------------
1 | const routes = {
2 | path: '/layout',
3 | name: '框架配置',
4 | icon: 'LayoutOutlined',
5 | component: () => import('./src'),
6 | };
7 |
8 | export default routes;
9 |
--------------------------------------------------------------------------------
/app/views/message/routes.js:
--------------------------------------------------------------------------------
1 | const routes = [
2 | {
3 | path: '/messages',
4 | name: '消息管理',
5 | hideMenu: true,
6 | component: () => import('./src'),
7 | },
8 | ];
9 |
10 | export default routes;
11 |
--------------------------------------------------------------------------------
/app/views/payer/routes.js:
--------------------------------------------------------------------------------
1 | // import {notAdmin} from '@app/utils/isAdmin';
2 |
3 | const routes = {
4 | path: '/payer',
5 | name: '会员管理',
6 | icon: 'AccountBookOutlined',
7 | hideMenu: true,
8 | children: [
9 | {
10 | path: '/count',
11 | name: '包次会员',
12 | icon: 'FundViewOutlined',
13 | children: [
14 | {
15 | path: '/member',
16 | name: '开通会员',
17 | icon: 'ShoppingOutlined',
18 | component: () => import('./src/count/member'),
19 | },
20 | {
21 | path: '/order',
22 | name: '订单列表',
23 | icon: 'AuditOutlined',
24 | component: () => import('./src/count/order'),
25 | },
26 | {
27 | path: '/pay',
28 | name: '支付',
29 | icon: 'DollarOutlined',
30 | hideMenu: true,
31 | component: () => import('./src/count/pay'),
32 | },
33 | ],
34 | },
35 | ],
36 | };
37 |
38 | export default routes;
39 |
--------------------------------------------------------------------------------
/app/views/payer/src/count/ali.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/views/payer/src/count/ali.png
--------------------------------------------------------------------------------
/app/views/payer/src/count/member.less:
--------------------------------------------------------------------------------
1 | .count-card {
2 | display: flex;
3 | flex-direction: column;
4 | flex-wrap: wrap;
5 | align-items: center;
6 | justify-content: center;
7 | padding: 30px 20px 40px;
8 | border-radius: 4px;
9 | background-color: var(--panelBgColor);
10 | box-shadow: 0 0 3px 4px var(--appBgColor);
11 | font-size: 1.4rem;
12 | font-weight: 500;
13 | .order-title {
14 | font-size: 1.8rem;
15 | }
16 | .order-info {
17 | font-size: 1.6rem;
18 | font-weight: 600;
19 | color: #2196f3;
20 | }
21 | .order-desc {
22 | color: #999;
23 | }
24 | .order-role {
25 | padding: 10px 0;
26 | }
27 | .order-period {
28 | padding: 10px 0;
29 | }
30 | .order-cost {
31 | padding: 10px 0;
32 | .cost-num {
33 | font-size: 2.2rem;
34 | font-weight: 600;
35 | color: #fb8c00;
36 | }
37 | }
38 | }
39 |
40 | .member-info {
41 | i {
42 | font-size: 1.8rem;
43 | font-weight: 600;
44 | color: #fb8c00;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/views/payer/src/count/pay.less:
--------------------------------------------------------------------------------
1 | .count-page {
2 | font-size: 1.4rem;
3 | padding: 0 12px;
4 | .pay-wrap {
5 | display: flex;
6 | align-items: center;
7 | }
8 | .pay-title {
9 | margin-bottom: 12px;
10 | }
11 | .pay-tips {
12 | font-style: italic;
13 | color: #fb8c00;
14 | font-size: 1.6rem;
15 | margin: 12px 0;
16 | }
17 | .pay-item {
18 | padding: 12px 30px;
19 | border-radius: 4px;
20 | background-color: var(--panelBgColor);
21 | box-shadow: 0 0 3px 4px var(--appBgColor);
22 | max-width: 240px;
23 | text-align: center;
24 | h4 {
25 | margin: 12px 0;
26 | font-size: 2rem;
27 | }
28 | p {
29 | margin: 10px 0;
30 | font-size: 1.6rem;
31 | color: #999;
32 | }
33 | }
34 |
35 | .order-price {
36 | .price-num {
37 | font-size: 2.8rem;
38 | font-weight: 600;
39 | color: #2196f3;
40 | }
41 | }
42 | .order-desc {
43 | color: #999;
44 | }
45 | .order-role {
46 | padding: 10px 0;
47 | }
48 | .order-period {
49 | padding: 10px 0;
50 | }
51 | .order-cost {
52 | padding: 10px 0;
53 | .cost-num {
54 | font-size: 2.2rem;
55 | font-weight: 600;
56 | color: #fb8c00;
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/app/views/payer/src/count/wechat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/views/payer/src/count/wechat.png
--------------------------------------------------------------------------------
/app/views/playground/src/canvas/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/app/views/playground/src/canvas/1.jpg
--------------------------------------------------------------------------------
/app/views/playground/src/canvas/drawText.js:
--------------------------------------------------------------------------------
1 | import {getTouchPosition, setStyle} from '@huxy/utils';
2 |
3 | const createNote = (x, y, right, bottom) => {
4 | const textarea = document.createElement('textarea');
5 | const styles = {
6 | position: 'fixed',
7 | zIndex: 10001,
8 | width: '300px',
9 | height: '100px',
10 | };
11 | if (x + 300 > right) {
12 | styles.left = `${x - 300}px`;
13 | } else {
14 | styles.left = `${x}px`;
15 | }
16 | if (y + 100 > bottom) {
17 | styles.top = `${y - 100}px`;
18 | } else {
19 | styles.top = `${y}px`;
20 | }
21 | setStyle(textarea, styles);
22 | document.body.appendChild(textarea);
23 | return textarea;
24 | };
25 | const removeNote = note => {
26 | document.body.removeChild(note);
27 | };
28 |
29 | const drawText = (evt, canvas) => {
30 | const ctx = canvas.getContext('2d');
31 | const {touchX, touchY} = getTouchPosition(evt);
32 | const {left, top, right, bottom} = canvas.getBoundingClientRect();
33 | const textArea = createNote(touchX, touchY, right, bottom);
34 | textArea.focus();
35 | textArea.addEventListener(
36 | 'blur',
37 | event => {
38 | const txt = textArea.value;
39 | ctx.font = '12px 微软雅黑';
40 | ctx.fillStyle = 'red';
41 | ctx.fillText(txt, touchX - left, touchY - top);
42 | removeNote(textArea);
43 | // setCfg({type:'draw'});
44 | },
45 | false,
46 | );
47 | };
48 |
49 | export default drawText;
50 |
--------------------------------------------------------------------------------
/app/views/playground/src/canvas/index.less:
--------------------------------------------------------------------------------
1 | .page {
2 | position: relative;
3 | .tools-bar {
4 | padding: 10px 0;
5 | .tools-area {
6 | > div,
7 | > button,
8 | > span {
9 | margin-right: 8px;
10 | margin-bottom: 8px;
11 | display: inline-block;
12 | width: auto;
13 | }
14 | }
15 | }
16 | }
17 |
18 | .canvas-container {
19 | position: relative;
20 | width: 100%;
21 | height: 400px;
22 | background: #eee;
23 | canvas {
24 | // border:1px solid #333;
25 | position: absolute;
26 | left: 0;
27 | top: 0;
28 | z-index: 0;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/views/playground/src/configList/getColumns.jsx:
--------------------------------------------------------------------------------
1 | import Ellipsis from '@app/components/ellipsis';
2 |
3 | const defCols = () => ({render: text => {text}});
4 |
5 | const getColumns = (columns, colsCfg, initCols = defCols()) => columns.map(col => ({...initCols, ...col, ...colsCfg?.find(({dataIndex}) => dataIndex === col.dataIndex)}));
6 |
7 | export default getColumns;
8 |
9 | export const RenderItem = ({index, style, item, isItemLoaded}) => {
10 | let content;
11 | if (!isItemLoaded(index)) {
12 | content = 'Loading...';
13 | } else {
14 | content = item.name;
15 | }
16 | return (
17 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/app/views/playground/src/configList/mock/utils.js:
--------------------------------------------------------------------------------
1 | import {sleep, uuidv4} from '@huxy/utils';
2 |
3 | export const fakeFetch = async params => {
4 | await sleep();
5 | return {
6 | code: 200,
7 | message: 'success!',
8 | result: {},
9 | };
10 | };
11 |
12 | export const fakeList = (schema, num = 10) => [...Array(num)].map((item, index) => ({id: uuidv4(), ...schema}));
13 |
--------------------------------------------------------------------------------
/app/views/playground/src/configList/routes.js:
--------------------------------------------------------------------------------
1 | const routes = [
2 | {
3 | path: '/configList',
4 | name: 'configList',
5 | component: () => import('./src'),
6 | },
7 | {
8 | path: '/configList/add',
9 | name: '添加用户',
10 | hideMenu: true,
11 | component: () => import('./src/add'),
12 | },
13 | {
14 | path: '/configList/edit/:id',
15 | name: '编辑用户',
16 | component: () => import('./src/add'),
17 | },
18 | {
19 | path: '/configList/auth/:id',
20 | name: '路由权限设置',
21 | component: () => import('./src/auth'),
22 | },
23 | ];
24 |
25 | export default routes;
26 |
--------------------------------------------------------------------------------
/app/views/playground/src/configList/src/index.less:
--------------------------------------------------------------------------------
1 | .config-list {
2 | position: relative;
3 | .handle-bar {
4 | position: absolute;
5 | top: 0;
6 | right: 0;
7 | height: 32px;
8 | line-height: 32px;
9 | > .link {
10 | font-size: 18px;
11 | margin-left: 8px;
12 | padding: 2px 8px;
13 | border-radius: 4px;
14 | &.active {
15 | background: rgba(0, 0, 0, 0.15);
16 | }
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/app/views/playground/src/configList/src/searchList/formList.jsx:
--------------------------------------------------------------------------------
1 | import {Space, Button, Form, Input, Select, Radio, Checkbox} from 'antd';
2 | import {validObj, firstUpper} from '@huxy/utils';
3 |
4 | const defComp = {Input, Select, Radio, Checkbox};
5 |
6 | const FormList = props => {
7 | const {submit, loading, searchFormText = '搜索', reset = '重置', formList = [], compList = {}} = props;
8 | const comps = {...defComp, compList};
9 | const [form] = Form.useForm();
10 | return (
11 |
17 |
18 |
19 | );
20 | })}
21 |
22 |
23 |
26 | {reset && }
27 |
28 |
29 |
30 | );
31 | };
32 |
33 | export default FormList;
34 |
--------------------------------------------------------------------------------
/app/views/playground/src/configList/src/searchList/index.jsx:
--------------------------------------------------------------------------------
1 | import {Space, Button} from 'antd';
2 | import {Row, Col} from '@huxy/components';
3 | import Panel from '@app/components/panel';
4 | import SearchForm from './formList';
5 |
6 | import WrapTable from './list/wrapTable';
7 | import WrapList from './list/wrapList';
8 | import AutoSizeList from './list/autoSizeList';
9 | const compList = {
10 | table: WrapTable,
11 | list: WrapList,
12 | autoSize: AutoSizeList,
13 | };
14 |
15 | const Index = ({result, actionList, formList, columns, RenderItem, searchList, pageChange, rowSelection, paramsKey, rowKey = '_id', listType}) => {
16 | const List = compList[listType] ?? compList.table;
17 | return (
18 |
19 | {actionList?.length || formList?.length ? (
20 |
21 |
22 | {actionList?.length ? (
23 |
24 |
25 | {actionList.map(({key, type, label, icon, action, disabled}) => (
26 |
29 | ))}
30 |
31 |
32 | ) : null}
33 | {formList?.length ? (
34 |
35 |
36 |
37 | ) : null}
38 |
39 |
40 | ) : null}
41 |
42 |
43 |
44 |
45 |
46 |
47 | );
48 | };
49 |
50 | export default Index;
51 |
--------------------------------------------------------------------------------
/app/views/playground/src/configList/src/searchList/list/autoSizeList.jsx:
--------------------------------------------------------------------------------
1 | import AutoSizer from 'react-virtualized-auto-sizer';
2 | import WrapList from './wrapList';
3 |
4 | const AutoSizeList = props => (
5 |
6 |
{({height, width}) => }
7 |
8 | );
9 |
10 | export default AutoSizeList;
11 |
--------------------------------------------------------------------------------
/app/views/playground/src/configList/src/searchList/list/wrapList.jsx:
--------------------------------------------------------------------------------
1 | import {useEffect, useRef} from 'react';
2 | import {FixedSizeList as List} from 'react-window';
3 | import InfiniteLoader from 'react-window-infinite-loader';
4 |
5 | const Index = props => {
6 | const {result, pageChange, RenderItem, itemSize = 45, paramsKey, width = '100%', height = 600} = props;
7 | const {pending, data} = result;
8 | const {list = [], total = 1, size = 10, current = 1} = data || {};
9 |
10 | const handlePageChange = (start, end) => {
11 | if (pending) {
12 | return;
13 | }
14 | const current = ~~((end + 1) / size);
15 | pageChange?.(current, size);
16 | };
17 |
18 | const listRef = useRef(null);
19 | useEffect(() => {
20 | if (listRef.current) {
21 | listRef.current.resetloadMoreItemsCache?.();
22 | listRef.current._listRef?.scrollTo(0);
23 | }
24 | tempList.current = {};
25 | }, [paramsKey]);
26 |
27 | const tempList = useRef({
28 | [current]: list,
29 | });
30 | if (!pending) {
31 | tempList.current[current] = list;
32 | }
33 | const totalList = [];
34 | Object.keys(tempList.current).map(key => totalList.push(...tempList.current[key]));
35 |
36 | const len = totalList.length;
37 | const hasNextPage = len < total;
38 | const itemCount = hasNextPage ? len + size : len;
39 | const isItemLoaded = index => !hasNextPage || index < len;
40 |
41 | return (
42 |
43 | {({onItemsRendered, ref}) => (
44 |
45 | {({index, style}) => (typeof RenderItem === 'function' ? RenderItem({index, style, item: totalList[index], isItemLoaded}) : `${index}-${totalList[index].name}`)}
46 |
47 | )}
48 |
49 | );
50 | };
51 |
52 | export default Index;
53 |
--------------------------------------------------------------------------------
/app/views/playground/src/configList/src/searchList/list/wrapTable.jsx:
--------------------------------------------------------------------------------
1 | import {Table} from 'antd';
2 |
3 | const Index = props => {
4 | const {result, pageChange, columns, rowSelection, pagination, ...rest} = props;
5 | const {pending, data} = result;
6 | const {total, current, size, list} = data || {};
7 |
8 | const handlePageChange = (current, size) => {
9 | pageChange?.(current, size);
10 | };
11 |
12 | const selectionCfg = rowSelection
13 | ? {
14 | columnWidth: '30px',
15 | // selectedRowKeys: selectedRows.map((v) => v[rowKey]),
16 | // onChange: (selectedRowKeys, selectedRows) => {
17 | // setSelectedRows?.(selectedRows);
18 | // },
19 | // getCheckboxProps: (record) => ({
20 | // disabled: !profile.role && record[rowKey] !== profile[rowKey],
21 | // }),
22 | ...(typeof rowSelection === 'object' ? rowSelection : null),
23 | }
24 | : null;
25 |
26 | const paginationCfg =
27 | pagination === false
28 | ? false
29 | : {
30 | onShowSizeChange: handlePageChange,
31 | onChange: handlePageChange,
32 | showSizeChanger: true,
33 | showQuickJumper: true,
34 | total: total || 1,
35 | current: current || 1,
36 | pageSize: size || 10,
37 | pageSizeOptions: ['10', '20', '30', '40'],
38 | size: 'small',
39 | ...(typeof pagination === 'object' ? pagination : null),
40 | };
41 |
42 | return ;
43 | };
44 |
45 | export default Index;
46 |
--------------------------------------------------------------------------------
/app/views/playground/src/functions/icons/index.jsx:
--------------------------------------------------------------------------------
1 | import {Row, Col} from '@huxy/components';
2 | import {copyToClipboard, message} from '@huxy/utils';
3 |
4 | import './index.less';
5 | const icons = [
6 | 'plus',
7 | 'plus-circle',
8 | 'minus',
9 | 'close',
10 | 'close-circle',
11 | 'close-square',
12 | 'close-left',
13 | 'close-right',
14 | 'check',
15 | 'checked',
16 | 'left',
17 | 'right',
18 | 'dleft',
19 | 'dright',
20 | 'refresh',
21 | 'stop',
22 | 'time',
23 | 'history',
24 | 'loop',
25 | 'arrow-left',
26 | 'arrow-up',
27 | 'arrow-right',
28 | 'arrow-down',
29 | 'left-right',
30 | 'up-down',
31 | 'upload',
32 | 'download',
33 | 'waiting',
34 | 'wait',
35 | 'block',
36 | 'square',
37 | 'star',
38 | 'solid-start',
39 | 'circle-star',
40 | 'snow',
41 | 'radar',
42 | 'flag',
43 | 'solid-flag',
44 | 'heart',
45 | 'music',
46 | 'sun',
47 | 'knot',
48 | 'male',
49 | 'female',
50 | 'dmale',
51 | 'dfemale',
52 | 'polygon',
53 | 'forward',
54 | 'table',
55 | 'grid',
56 | 'quad',
57 | 'circle-left',
58 | 'circle-right',
59 | 'circle-bottom',
60 | 'circle-top',
61 | 'solid-box',
62 | 'box',
63 | 'caret-left',
64 | 'caret-right',
65 | 'round',
66 | 'solid-round',
67 | 'layout',
68 | 'circle-outer',
69 | 'border-outer',
70 | ];
71 |
72 | const Index = props => {
73 | const copyText = v => {
74 | copyToClipboard(v);
75 | message.success('拷贝成功!');
76 | };
77 | return (
78 |
79 |
80 | {icons.map((v, k) => (
81 |
82 | copyText(v)}>
83 |
84 | {v}
85 |
86 |
87 | ))}
88 |
89 |
90 | );
91 | };
92 |
93 | export default Index;
94 |
--------------------------------------------------------------------------------
/app/views/playground/src/functions/icons/index.less:
--------------------------------------------------------------------------------
1 | .page {
2 | &.icon-list {
3 | padding: 10px 20px;
4 | .ilist {
5 | text-align: center;
6 | padding: 10px 0;
7 | border: 1px solid #ececec;
8 | cursor: pointer;
9 | background-color: #fff;
10 | border-radius: 2px;
11 | transition: all 0.3s;
12 | color: #333;
13 | &:hover {
14 | box-shadow: 0 2px 6px #ddd;
15 | color: #00b4cf;
16 | transform: scale(1.02);
17 | }
18 | .icon-name {
19 | margin-top: 10px;
20 | display: block;
21 | }
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/views/playground/src/functions/panel/index.less:
--------------------------------------------------------------------------------
1 | .demo-panel-container {
2 | [class^='col-'] {
3 | > span {
4 | display: block;
5 | text-align: right;
6 | height: 100%;
7 | line-height: 32px;
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/app/views/playground/src/functions/styles/config.js:
--------------------------------------------------------------------------------
1 | export const typeList = [
2 | {
3 | key: '',
4 | name: '线',
5 | },
6 | {
7 | key: 'close',
8 | name: '关闭',
9 | },
10 | {
11 | key: 'right',
12 | name: '右箭头',
13 | },
14 | {
15 | key: 'bottom',
16 | name: '下箭头',
17 | },
18 | {
19 | key: 'play',
20 | name: '启动',
21 | },
22 | {
23 | key: 'play pause',
24 | name: '停止',
25 | },
26 | ];
27 |
28 | export const data = [
29 | {
30 | name: 'menu1',
31 | value: 'menu1',
32 | },
33 | {
34 | name: 'menu2',
35 | value: 'menu2',
36 | list: [
37 | {
38 | name: 'menu2-1',
39 | value: 'menu2-1',
40 | },
41 | {
42 | name: 'menu2-2',
43 | value: 'menu2-2',
44 | },
45 | ],
46 | },
47 | {
48 | name: 'menu3',
49 | value: 'menu3',
50 | list: [
51 | {
52 | name: 'menu3-1',
53 | value: 'menu3-1',
54 | },
55 | {
56 | name: 'menu3-2',
57 | value: 'menu3-2',
58 | },
59 | {
60 | name: 'menu3-3',
61 | value: 'menu3-3',
62 | },
63 | ],
64 | },
65 | {
66 | name: 'menu4',
67 | value: 'menu4',
68 | },
69 | ];
70 |
--------------------------------------------------------------------------------
/app/views/playground/src/functions/styles/index.jsx:
--------------------------------------------------------------------------------
1 | import {useState} from 'react';
2 | import {Spinner, Anico, LoadError, HandleError} from '@huxy/components';
3 | import {Row, Col} from '@app/components/row';
4 | import Panel from '@app/components/panel';
5 | import Ellipsis from '@app/components/ellipsis';
6 | import Button from '@app/components/base/button';
7 | import Menu from '@app/components/base/menu';
8 | import {typeList, data} from './config';
9 |
10 | const ErrorComp = ({state, name}) => {state[name]}
;
11 |
12 | const Index = props => {
13 | const [type, setType] = useState('');
14 | const [demoError, setDemoError] = useState({});
15 |
16 | return (
17 |
18 |
19 |
20 |
21 | 12233345657688967i8ijhfgrtrrfgthtgryhhyt
22 |
23 |
24 | 33333
25 |
26 |
27 | 12233345657688967i8ijhfgrtrrfgthtgryhhyt
28 |
29 |
30 |
31 |
32 |
33 |
36 |
37 | {typeList.map(({key, name}) => (
38 |
41 | ))}
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | {LoadError({error: 'load error demo'})}
53 |
54 |
55 |
56 | {demoError && }
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | );
66 | };
67 |
68 | export default Index;
69 |
--------------------------------------------------------------------------------
/app/views/playground/src/functions/tools/index.jsx:
--------------------------------------------------------------------------------
1 | import {useEffect, useRef} from 'react';
2 | import {watermark} from '@huxy/utils';
3 | import {Panel} from '@huxy/components';
4 | import {useEleResize} from '@huxy/use';
5 | import {Row, Col} from '@app/components/row';
6 |
7 | import SkeletonContent from '@app/components/skeletonContent';
8 |
9 | const Index = props => {
10 | const watermarkRef = useRef();
11 | const skeletonRef = useRef();
12 | const {width} = useEleResize(() => skeletonRef, 250);
13 |
14 | useEffect(() => {
15 | watermark({
16 | container: watermarkRef,
17 | });
18 | }, []);
19 | return (
20 |
21 |
22 |
23 |
24 | hello world
25 |
26 |
27 |
28 |
29 | (
34 |
35 | panelWidth: {width}
36 |
37 | ),
38 | ]}
39 | >
40 |
41 |
42 |
43 |
44 | );
45 | };
46 |
47 | export default Index;
48 |
--------------------------------------------------------------------------------
/app/views/playground/src/materials/animation/index.jsx:
--------------------------------------------------------------------------------
1 | import {IconAnimate, Css3dModel, Fliper, IconCarousel} from '@huxy/materials';
2 |
3 | import models from '@app/models/models';
4 |
5 | import animateObjs from '@app/models/animateObjs';
6 | import cssModels from '@app/models/cssModels';
7 |
8 | const box = {
9 | position: 'relative',
10 | minHeight: '100px',
11 | margin: '20px auto',
12 | background: 'rgba(0, 0, 0, 0.1)',
13 | padding: '15px',
14 | overflow: 'hidden',
15 | };
16 |
17 | const fliperStyle = {
18 | height: '200px',
19 | lineHeight: '200px',
20 | color: '#fff',
21 | textAlign: 'center',
22 | fontSize: '32px',
23 | };
24 |
25 | const Index = props => {
26 | return (
27 |
28 |
29 |
30 |
31 |
32 | 正面
}
34 | back={
反面
}
35 | style={{height: 200, width: 200, margin: '0 auto'}}
36 | />
37 |
38 |
39 |
40 |
41 |
42 | );
43 | };
44 |
45 | export default Index;
46 |
--------------------------------------------------------------------------------
/app/views/playground/src/materials/shape/index.jsx:
--------------------------------------------------------------------------------
1 | import {Time, Search, Location, Loading, Spot} from '@huxy/materials';
2 |
3 | import Taiji from './taiji';
4 | import Bagua from './taiji/bagua';
5 |
6 | const box = {
7 | position: 'relative',
8 | margin: '20px auto',
9 | background: 'rgba(0, 0, 0, 0.1)',
10 | padding: '25px',
11 | width: '320px',
12 | textAlign: 'center',
13 | };
14 |
15 | const Index = props => {
16 | return (
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | );
44 | };
45 |
46 | export default Index;
47 |
--------------------------------------------------------------------------------
/app/views/playground/src/materials/shape/taiji/bagua/gua/configs.js:
--------------------------------------------------------------------------------
1 | const configs = [
2 | {
3 | value: '一',
4 | label: '乾',
5 | yao: [1, 1, 1],
6 | position: 0,
7 | details: '乾三连',
8 | },
9 | {
10 | value: '二',
11 | label: '兑',
12 | yao: [0, 1, 1],
13 | position: 7,
14 | details: '兑上缺',
15 | },
16 | {
17 | value: '三',
18 | label: '离',
19 | yao: [1, 0, 1],
20 | position: 6,
21 | details: '离中虚',
22 | },
23 | {
24 | value: '四',
25 | label: '震',
26 | yao: [0, 0, 1],
27 | position: 5,
28 | details: '震仰盂',
29 | },
30 | {
31 | value: '五',
32 | label: '巽',
33 | yao: [1, 1, 0],
34 | position: 1,
35 | details: '巽下断',
36 | },
37 | {
38 | value: '六',
39 | label: '坎',
40 | yao: [0, 1, 0],
41 | position: 2,
42 | details: '坎中满',
43 | },
44 | {
45 | value: '七',
46 | label: '艮',
47 | yao: [1, 0, 0],
48 | position: 3,
49 | details: '艮覆碗',
50 | },
51 | {
52 | value: '八',
53 | label: '坤',
54 | yao: [0, 0, 0],
55 | position: 4,
56 | details: '坤六断',
57 | },
58 | ];
59 |
60 | export default configs;
61 |
--------------------------------------------------------------------------------
/app/views/playground/src/materials/shape/taiji/bagua/gua/index.jsx:
--------------------------------------------------------------------------------
1 | import configs from './configs';
2 | import Yao from '../yao';
3 |
4 | import * as styles from './index.less';
5 |
6 | const Index = ({yaoProps, rotate, height, width, style, ...rest}) => (
7 |
16 | {configs.map(({value, label, details, yao, position}) => (
17 |
18 |
{details}
19 |
{label}
20 |
{value}
21 |
22 |
23 | ))}
24 |
25 | );
26 |
27 | export default Index;
28 |
--------------------------------------------------------------------------------
/app/views/playground/src/materials/shape/taiji/bagua/gua/index.less:
--------------------------------------------------------------------------------
1 | :local {
2 | .huxy-gua-container {
3 | --width: 50px;
4 | position: absolute;
5 | top: 0;
6 | left: 0;
7 | width: 100%;
8 | height: 100%;
9 | .huxy-gua {
10 | height: var(--height, 100%);
11 | width: var(--width);
12 | position: absolute;
13 | top: 50%;
14 | left: 50%;
15 | transform: translate(-50%, -50%) rotate(45deg);
16 | transform-origin: center;
17 | text-align: center;
18 | transition: all 3s;
19 | .gua-desc,
20 | .gua-name {
21 | margin: 3px 0;
22 | }
23 | .gua-desc {
24 | font-size: 13px;
25 | font-weight: 500;
26 | }
27 | .gua-name {
28 | font-size: 20px;
29 | font-weight: 700;
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/views/playground/src/materials/shape/taiji/bagua/index.jsx:
--------------------------------------------------------------------------------
1 | import {useState} from 'react';
2 |
3 | import {Taiji} from '@huxy/materials';
4 |
5 | import Gua from './gua';
6 |
7 | const containerStyle = {
8 | height: '100%',
9 | position: 'relative',
10 | display: 'flex',
11 | alignItems: 'center',
12 | justifyContent: 'center',
13 | };
14 |
15 | const Index = props => {
16 | const [rotate, setRotate] = useState(0);
17 | return (
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
28 |
29 |
30 | );
31 | };
32 |
33 | export default Index;
34 |
--------------------------------------------------------------------------------
/app/views/playground/src/materials/shape/taiji/bagua/yao/index.jsx:
--------------------------------------------------------------------------------
1 | import * as styles from './index.less';
2 |
3 | const Index = ({yao = [], width, height, bgColor, style, ...rest}) => (
4 |
14 | {yao.map((item, i) => (
15 |
16 | ))}
17 |
18 | );
19 |
20 | export default Index;
21 |
--------------------------------------------------------------------------------
/app/views/playground/src/materials/shape/taiji/bagua/yao/index.less:
--------------------------------------------------------------------------------
1 | :local {
2 | .huxy-yao {
3 | --yao-width: 50px;
4 | --yao-height: 8px;
5 | --yao-bgColor: #000;
6 | .yang {
7 | margin: calc(var(--yao-height) + 2px) 0;
8 | width: var(--yao-width);
9 | height: var(--yao-height);
10 | background: var(--yao-bgColor);
11 | }
12 | .yin {
13 | margin: calc(var(--yao-height) + 2px) 0;
14 | height: var(--yao-height);
15 | position: relative;
16 | &::before,
17 | &::after {
18 | content: '';
19 | position: absolute;
20 | top: 0;
21 | width: calc(var(--yao-width) * 0.4);
22 | height: var(--yao-height);
23 | background: var(--yao-bgColor);
24 | }
25 | &::before {
26 | left: 0;
27 | }
28 | &::after {
29 | right: 0;
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/views/playground/src/materials/shape/taiji/index.jsx:
--------------------------------------------------------------------------------
1 | import {useState} from 'react';
2 |
3 | import {Taiji} from '@huxy/materials';
4 |
5 | import './index.less';
6 |
7 | const containerStyle = {
8 | height: '100%',
9 | position: 'relative',
10 | display: 'flex',
11 | alignItems: 'center',
12 | justifyContent: 'center',
13 | };
14 |
15 | const Index = props => {
16 | const [value, setValue] = useState(1);
17 | return (
18 |
19 |
20 |
21 |
22 |
23 | setValue(e.target.value)} /> turn
24 |
25 |
26 | );
27 | };
28 |
29 | export default Index;
30 |
--------------------------------------------------------------------------------
/app/views/playground/src/materials/shape/taiji/index.less:
--------------------------------------------------------------------------------
1 | @keyframes huxy-circle-animate-rotate {
2 | 0% {
3 | transform: rotate(90deg);
4 | }
5 | 100% {
6 | transform: rotate(var(--rotate));
7 | }
8 | }
9 |
10 | .huxy-circle-animate-rotate {
11 | --rotate: 450deg;
12 | transform: rotate(90deg);
13 | animation: huxy-circle-animate-rotate linear 1s infinite;
14 | }
15 |
--------------------------------------------------------------------------------
/app/views/playground/src/materials/text/index.jsx:
--------------------------------------------------------------------------------
1 | import {Text3d, TextFilter, TextLoading, TextMasked, RateScore} from '@huxy/materials';
2 | import objs from '@app/models/objs';
3 |
4 | const box = {
5 | position: 'relative',
6 | minHeight: '100px',
7 | margin: '20px auto',
8 | background: 'rgba(0, 0, 0, 0.1)',
9 | padding: '15px',
10 | };
11 |
12 | const Index = props => {
13 | return (
14 |
15 |
16 |
17 |
18 |
19 | Css materials
20 |
21 |
22 | Loading
23 |
24 |
25 | ★★★★★
26 |
27 |
28 | 当我们在写代码时,其实我们都在写一个故事,而场景就是故事中的每一个片段。
29 |
30 |
31 | );
32 | };
33 |
34 | export default Index;
35 |
--------------------------------------------------------------------------------
/app/views/playground/src/page/routes.js:
--------------------------------------------------------------------------------
1 | import Page from './src';
2 |
3 | const routes = [
4 | {
5 | path: '/page1-2',
6 | name: '二级菜单2',
7 | children: [
8 | {
9 | path: '/page1-2-1',
10 | name: '三级菜单1',
11 | icon: 'RobotOutlined',
12 | component: Page,
13 | },
14 | {
15 | path: '/page1-2-2',
16 | name: '三级菜单2',
17 | children: [
18 | {
19 | path: '/page1-2-2-1',
20 | name: '四级菜单1',
21 | component: Page,
22 | },
23 | {
24 | path: '/page1-2-2-2',
25 | name: '四级菜单1-disabled',
26 | component: Page,
27 | linkProps: {
28 | disabled: true,
29 | },
30 | },
31 | {
32 | path: '/page1-2-2-3',
33 | name: '四级菜单3-_blank',
34 | component: Page,
35 | linkProps: {
36 | target: '_blank',
37 | },
38 | },
39 | {
40 | path: '/page1-2-2-4',
41 | name: '四级菜单4-hideMenu',
42 | component: Page,
43 | hideMenu: true,
44 | },
45 | ],
46 | },
47 | ],
48 | },
49 | ];
50 |
51 | export default routes;
52 |
--------------------------------------------------------------------------------
/app/views/playground/src/page/src/index.jsx:
--------------------------------------------------------------------------------
1 | const Index = props => {props.inputPath}
;
2 |
3 | export default Index;
4 |
--------------------------------------------------------------------------------
/app/views/playground/src/suspense/suspenseFns.js:
--------------------------------------------------------------------------------
1 | import {wrapPromise, sleep} from '@huxy/utils';
2 |
3 | const sus1 = async params => {
4 | await sleep(2500);
5 | return {
6 | code: 200,
7 | msg: 'success',
8 | result: {
9 | name: 'huy',
10 | age: 18,
11 | },
12 | };
13 | };
14 | export const sus2 = async params => {
15 | await sleep(4000);
16 | return {
17 | code: 200,
18 | msg: 'success',
19 | result: {
20 | list: [
21 | {
22 | name: 'huy',
23 | },
24 | {
25 | name: 'yiru',
26 | },
27 | {
28 | name: 'test',
29 | },
30 | ],
31 | },
32 | };
33 | };
34 |
35 | export const susTest1 = params => wrapPromise(sus1(params));
36 |
37 | export const susTest2 = params => wrapPromise(sus2(params));
38 |
--------------------------------------------------------------------------------
/app/views/user/configs.js:
--------------------------------------------------------------------------------
1 | export {default as logo} from '@app/assets/images/logo.png';
2 | export {default as apiList} from '@app/apis/apiList';
3 | import * as rules from '@app/utils/rules';
4 | export const formRules = rules;
5 |
6 | export const githubConfigs = {
7 | github_client_id: '61721ef923095e006d18',
8 | github_oauth_url: 'https://github.com/login/oauth/authorize',
9 | };
10 |
11 | export const wechatConfigs = {
12 | appid: 'wx7f4df123f88372a5',
13 | wechat_oauth_url: 'https://open.weixin.qq.com/connect/oauth2/authorize',
14 | redirect_uri: 'https://ihuxy.com/user/signin',
15 | response_type: 'code',
16 | scope: 'snsapi_base', //'snsapi_userinfo',
17 | state: 'wechat',
18 | };
19 |
--------------------------------------------------------------------------------
/app/views/user/routes.js:
--------------------------------------------------------------------------------
1 | const routes = [
2 | {
3 | path: '/user',
4 | title: '登录注册',
5 | hideMenu: true,
6 | component: () => import('./src'),
7 | children: [
8 | {
9 | path: '/signin',
10 | name: '登录',
11 | title: '登录',
12 | component: () => import('./src/login'),
13 | },
14 | {
15 | path: '/signup',
16 | name: '注册',
17 | component: () => import('./src/signup'),
18 | },
19 | {
20 | path: '/verifyEmail',
21 | name: '验证邮箱',
22 | component: () => import('./src/verifyEmail'),
23 | },
24 | {
25 | path: '/setNewPwd',
26 | name: '重置密码',
27 | component: () => import('./src/setNewPwd'),
28 | },
29 | ],
30 | },
31 | ];
32 |
33 | export default routes;
34 |
--------------------------------------------------------------------------------
/app/views/user/src/index.jsx:
--------------------------------------------------------------------------------
1 | import {useEffect} from 'react';
2 | import {useWinResize} from '@huxy/use';
3 |
4 | import Intls from '@app/components/intl';
5 | import * as styles from './index.less';
6 | import {logo} from '../configs';
7 |
8 | const Index = props => {
9 | const {height} = useWinResize();
10 | useEffect(() => {
11 | document.documentElement.style.setProperty('--containerHeight', `${height}px`);
12 | }, [height]);
13 | return (
14 |
15 |
16 |
17 |
18 |

19 |
20 |
21 | Ihuxy
22 |
23 |
24 |
{props.children}
25 |
26 |
34 |
35 | );
36 | };
37 |
38 | export default Index;
39 |
--------------------------------------------------------------------------------
/app/views/user/src/setNewPwd.jsx:
--------------------------------------------------------------------------------
1 | import {useState} from 'react';
2 | import {Form, Input, Button} from 'antd';
3 | import {LockOutlined, LeftOutlined} from '@ant-design/icons';
4 | import {message} from '@huxy/utils';
5 | import {useIntls} from '@app/components/intl';
6 | import {goPage} from '@app/utils/utils';
7 | import {apiList, formRules} from '../configs';
8 |
9 | const {passwordRule, confirmRule} = formRules;
10 |
11 | const Index = props => {
12 | const getIntls = useIntls();
13 | const [pending, setPending] = useState(false);
14 | const onFinish = async values => {
15 | setPending(true);
16 | try {
17 | const query = props.params?.token;
18 | const {code, token, message: msg} = await apiList.setNewPwdFn({password: values.password, token: query});
19 | if (code === 200) {
20 | message.success(msg);
21 | // storage.set('token',token);
22 | // props.router.push('/');
23 | goPage();
24 | }
25 | } catch (err) {}
26 | setPending(false);
27 | };
28 |
29 | return (
30 | <>
31 |
33 | } type="password" placeholder={getIntls('login.password')} autoComplete="new-password" />
34 |
35 |
36 | } type="password" placeholder={getIntls('login.confirmPwd')} autoComplete="new-password" />
37 |
38 |
39 |
42 |
43 |
44 |
45 |
46 |
49 |
50 |
51 | >
52 | );
53 | };
54 |
55 | export default Index;
56 |
--------------------------------------------------------------------------------
/app/views/user/src/verifyEmail.jsx:
--------------------------------------------------------------------------------
1 | import {useState} from 'react';
2 | import {Form, Input, Button, Result} from 'antd';
3 | import {LeftOutlined, MailOutlined} from '@ant-design/icons';
4 | import {message} from '@huxy/utils';
5 | import Intls, {useIntls} from '@app/components/intl';
6 | import {apiList, formRules} from '../configs';
7 |
8 | const {emailRule} = formRules;
9 |
10 | const Index = props => {
11 | const getIntls = useIntls();
12 | const [hasVerify, setHasVerify] = useState(false);
13 | const [pending, setPending] = useState(false);
14 | const onFinish = async values => {
15 | setPending(true);
16 | try {
17 | const {code, message: msg} = await apiList.verifyEmailFn(values);
18 | if (code === 200) {
19 | message.success(msg);
20 | setHasVerify(true);
21 | // props.router.push('/');
22 | // location.href='/';
23 | }
24 | } catch (err) {}
25 | setPending(false);
26 | };
27 |
28 | return !hasVerify ? (
29 | <>
30 |
32 | } placeholder={getIntls('login.email')} />
33 |
34 |
35 |
38 |
39 |
40 |
41 |
42 |
45 |
46 |
47 | >
48 | ) : (
49 |
50 | (location.href = '/')}>
56 |
57 |
58 | }
59 | />
60 |
61 | );
62 | };
63 |
64 | export default Index;
65 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | import configs from '@huxy/pack/config/babel';
2 |
3 | export default api => configs(api, {
4 | // customCfgs
5 | });
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | import configs from '@huxy/pack/config/commitlint';
2 |
3 | export default configs({
4 | // customCfgs
5 | });
--------------------------------------------------------------------------------
/doc/src/api.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/doc/src/api.png
--------------------------------------------------------------------------------
/doc/src/apiTest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/doc/src/apiTest.png
--------------------------------------------------------------------------------
/doc/src/auth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/doc/src/auth.png
--------------------------------------------------------------------------------
/doc/src/demand.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/doc/src/demand.png
--------------------------------------------------------------------------------
/doc/src/doc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/doc/src/doc.png
--------------------------------------------------------------------------------
/doc/src/editDemand.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/doc/src/editDemand.png
--------------------------------------------------------------------------------
/doc/src/email.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/doc/src/email.png
--------------------------------------------------------------------------------
/doc/src/file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/doc/src/file.png
--------------------------------------------------------------------------------
/doc/src/lang.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/doc/src/lang.png
--------------------------------------------------------------------------------
/doc/src/layout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/doc/src/layout.png
--------------------------------------------------------------------------------
/doc/src/log.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/doc/src/log.png
--------------------------------------------------------------------------------
/doc/src/member.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/doc/src/member.png
--------------------------------------------------------------------------------
/doc/src/message.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/doc/src/message.png
--------------------------------------------------------------------------------
/doc/src/monitor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/doc/src/monitor.png
--------------------------------------------------------------------------------
/doc/src/order.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/doc/src/order.png
--------------------------------------------------------------------------------
/doc/src/pageDesign.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/doc/src/pageDesign.png
--------------------------------------------------------------------------------
/doc/src/pageView.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/doc/src/pageView.png
--------------------------------------------------------------------------------
/doc/src/profile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/doc/src/profile.png
--------------------------------------------------------------------------------
/doc/src/project.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/doc/src/project.png
--------------------------------------------------------------------------------
/doc/src/router.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/doc/src/router.png
--------------------------------------------------------------------------------
/doc/src/theme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/doc/src/theme.png
--------------------------------------------------------------------------------
/doc/src/user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahyiru/huxy-admin/b62e19956f13f977d3de783bd634d0ce55877012/doc/src/user.png
--------------------------------------------------------------------------------
/eslint.config.js:
--------------------------------------------------------------------------------
1 | import configs from '@huxy/pack/config/eslint';
2 |
3 | export default configs([
4 | // customCfgs
5 | ]);
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | import configs from '@huxy/pack/config/jest';
2 |
3 | export default configs({
4 | // customCfgs
5 | });
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "huxy-admin",
3 | "version": "1.7.1",
4 | "type": "module",
5 | "description": "Customizable admin template for efficient and convenient development of maintainable and scalable systems, providing customized software design and development.",
6 | "keywords": [
7 | "react",
8 | "low-code",
9 | "web-design",
10 | "scene-design",
11 | "json schema",
12 | "web3",
13 | "webgl",
14 | "webpack",
15 | "full-stack",
16 | "MERN",
17 | "customizable",
18 | "responsive",
19 | "admin",
20 | "template",
21 | "chatgpt",
22 | "AIGC",
23 | "llm",
24 | "langchain"
25 | ],
26 | "sideEffects": [
27 | "*.css",
28 | "*.less"
29 | ],
30 | "scripts": {
31 | "postinstall": "husky install",
32 | "start": "pack start",
33 | "build": "pack run build",
34 | "analyze": "pack run analyze",
35 | "server": "pack run server",
36 | "test": "pack test",
37 | "release": "pack release",
38 | "eslint": "pack eslint 'app/**/*.{js,jsx}'",
39 | "stylelint": "pack stylelint 'app/**/*.{css,less}'",
40 | "lint": "npm run eslint && npm run stylelint",
41 | "lint-fix": "pack eslint --fix 'app/**/*.{js,jsx}' && pack stylelint --fix 'app/**/*.{css,less}'",
42 | "prettier": "pack prettier 'app/**/*' --write --ignore-unknown && npm run lint-fix",
43 | "server-fix": "pack eslint --fix 'server/**/*.{js,jsx,mjs}'",
44 | "server-pre": "pack prettier 'server/**/*' --write --ignore-unknown && npm run server-fix"
45 | },
46 | "repository": {
47 | "type": "git",
48 | "url": "https://github.com/ahyiru/huxy-admin"
49 | },
50 | "license": "MIT",
51 | "devDependencies": {
52 | "@huxy/pack": "1.7.7",
53 | "husky": "^9.1.7",
54 | "webpack-deadcode-plugin": "^0.1.17"
55 | },
56 | "dependencies": {
57 | "@ant-design/icons": "^6.0.0",
58 | "@huxy/components": "^2.1.20",
59 | "@huxy/layout": "^2.1.12",
60 | "@huxy/materials": "^1.1.6",
61 | "@huxy/router": "^2.1.14",
62 | "@huxy/use": "^2.1.13",
63 | "@huxy/utils": "^2.1.14",
64 | "antd": "^5.25.3",
65 | "qrcode": "^1.5.4",
66 | "react": "19.1.0",
67 | "react-dom": "19.1.0",
68 | "react-virtualized-auto-sizer": "^1.0.26",
69 | "react-window": "^1.8.11",
70 | "react-window-infinite-loader": "^1.0.10"
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | import configs from '@huxy/pack/config/postcss';
2 |
3 | export default configs({
4 | // customCfgs
5 | });
--------------------------------------------------------------------------------
/prettier.config.js:
--------------------------------------------------------------------------------
1 | import configs from '@huxy/pack/config/prettier';
2 |
3 | export default configs({
4 | // customCfgs
5 | });
--------------------------------------------------------------------------------
/stylelint.config.js:
--------------------------------------------------------------------------------
1 | import configs from '@huxy/pack/config/stylelint';
2 |
3 | export default configs({
4 | // customCfgs
5 | });
--------------------------------------------------------------------------------