From f45915324679f6ea296359047e441f45c3c3aa60 Mon Sep 17 00:00:00 2001 From: afc163 Date: Tue, 8 Jul 2025 19:04:39 +0800 Subject: [PATCH 01/21] Update README.md --- README.md | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/README.md b/README.md index 5baa78f9..37ebbd72 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Language : 🇺🇸 | [🇨🇳](./README.zh-CN.md) | [🇷🇺](./README.ru-RU.md) | [🇹🇷](./README.tr-TR.md) | [🇯🇵](./README.ja-JP.md) | [🇫🇷](./README.fr-FR.md) | [🇵🇹](./README.pt-BR.md) | [🇸🇦](./README.ar-DZ.md) | [🇪🇸](./README.es-ES.md) +Language: 🇺🇸 | [🇨🇳](./README.zh-CN.md) | [🇷🇺](./README.ru-RU.md) | [🇹🇷](./README.tr-TR.md) | [🇯🇵](./README.ja-JP.md) | [🇫🇷](./README.fr-FR.md) | [🇵🇹](./README.pt-BR.md) | [🇸🇦](./README.ar-DZ.md) | [🇪🇸](./README.es-ES.md)

Ant Design Pro

@@ -22,14 +22,6 @@ An out-of-box UI solution for enterprise applications as a React boilerplate. - ChangeLog: http://pro.ant.design/docs/changelog - FAQ: http://pro.ant.design/docs/faq -## 5.0 is out! 🎉🎉🎉 - -[Ant Design Pro 5.0.0](https://github.com/ant-design/ant-design-pro/issues/8656) - -## Translation Recruitment :loudspeaker: - -We need your help: https://github.com/ant-design/ant-design-pro/issues/120 - ## Features - :bulb: **TypeScript**: A language for application-scale JavaScript From 5753706db99d77b8ebaded962a11c8d1fe6f249d Mon Sep 17 00:00:00 2001 From: afc163 Date: Tue, 8 Jul 2025 22:34:04 +0800 Subject: [PATCH 02/21] test: add @types/node in devDeps --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 2b9b616e..039e12c2 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,8 @@ "typescript": "^5.6.3", "umi-presets-pro": "^2.0.3", "umi-serve": "^1.9.11", - "@biomejs/biome": "^2.0.6" + "@biomejs/biome": "^2.0.6", + "@types/node": "^24.0.10" }, "engines": { "node": ">=20.0.0" From fe31163b33ae43ea6f730d281622cec57f1d2ed7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 01:52:41 +0800 Subject: [PATCH 03/21] chore(deps): bump dawidd6/action-download-artifact (#11395) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afc163 --- .github/workflows/preview-deploy.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/preview-deploy.yml b/.github/workflows/preview-deploy.yml index 35cfb5ba..21a07cc1 100644 --- a/.github/workflows/preview-deploy.yml +++ b/.github/workflows/preview-deploy.yml @@ -19,7 +19,7 @@ jobs: if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' steps: - name: download pr artifact - uses: dawidd6/action-download-artifact@v4 + uses: dawidd6/action-download-artifact@v6 with: workflow: ${{ github.event.workflow_run.workflow_id }} name: pr @@ -29,7 +29,7 @@ jobs: run: echo "::set-output name=id::$( Date: Mon, 14 Jul 2025 11:18:18 +0800 Subject: [PATCH 04/21] docs: Update screenshot --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 37ebbd72..8d23e4c9 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,8 @@ An out-of-box UI solution for enterprise applications as a React boilerplate. [![Checked with Biome](https://img.shields.io/badge/Checked_with-Biome-60a5fa?style=flat&logo=biome)](https://biomejs.dev) [![](https://badgen.net/badge/icon/Ant%20Design?icon=https://gw.alipayobjects.com/zos/antfincdn/Pp4WPgVDB3/KDpgvguMpGfqaHPjicRK.svg&label)](https://ant.design/) -![](https://github.com/user-attachments/assets/fde29061-3d9a-4397-8ac2-397b0e033ef5) +light theme preview +dark theme preview From a1b37b4630c772f7d7f7243474acab6152b284dd Mon Sep 17 00:00:00 2001 From: ice <49827327+coding-ice@users.noreply.github.com> Date: Wed, 22 Oct 2025 12:18:40 +0800 Subject: [PATCH 05/21] chore: add biome tooling and format codebase (#11572) --- biome.json | 25 ++++---- mock/listTableList.ts | 38 ++++------- mock/notices.ts | 6 +- mock/requestRecord.mock.js | 63 +++++++------------ mock/user.ts | 6 +- package.json | 1 + public/scripts/loading.js | 2 +- src/app.tsx | 3 +- .../center/components/Applications/index.tsx | 30 +++++---- .../center/components/Articles/index.tsx | 17 ++--- .../account/settings/components/base.tsx | 39 +++++++----- src/pages/list/basic-list/index.tsx | 50 ++++++++------- src/pages/list/mock/index.ts | 2 +- src/pages/list/search/articles/index.tsx | 62 +++++++++--------- src/pages/list/table-list/service.ts | 2 - .../login/__snapshots__/login.test.tsx.snap | 58 ++++++++--------- types/cache/mock/login.mock.cache.js | 63 +++++++------------ 17 files changed, 211 insertions(+), 256 deletions(-) diff --git a/biome.json b/biome.json index 2f4e4e0c..8d4ab507 100644 --- a/biome.json +++ b/biome.json @@ -4,17 +4,17 @@ "ignoreUnknown": true, "includes": [ "**/*", - "!**/.umi/**", - "!**/.umi-production/**", - "!**/.umi-test/**", - "!**/.umi-test-production/**", - "!**/src/services/**", - "!**/mock/**", - "!**/dist/**", - "!**/server/**", - "!**/public/**", - "!**/coverage/**", - "!**/node_modules/**", + "!**/.umi", + "!**/.umi-production", + "!**/.umi-test", + "!**/.umi-test-production", + "!**/src/services", + "!**/mock", + "!**/dist", + "!**/server", + "!**/public", + "!**/coverage", + "!**/node_modules", "!biome.json" ] }, @@ -30,7 +30,8 @@ "noExplicitAny": "off" }, "correctness": { - "useExhaustiveDependencies": "off" + "useExhaustiveDependencies": "off", + "useUniqueElementIds": "off" }, "a11y": { "noStaticElementInteractions": "off", diff --git a/mock/listTableList.ts b/mock/listTableList.ts index dd88bf91..ddb857c2 100644 --- a/mock/listTableList.ts +++ b/mock/listTableList.ts @@ -34,10 +34,7 @@ let tableListDataSource = genList(1, 100); function getRule(req: Request, res: Response, u: string) { let realUrl = u; - if ( - !realUrl || - Object.prototype.toString.call(realUrl) !== '[object String]' - ) { + if (!realUrl || Object.prototype.toString.call(realUrl) !== '[object String]') { realUrl = req.url; } const { current = 1, pageSize = 10 } = req.query; @@ -81,25 +78,21 @@ function getRule(req: Request, res: Response, u: string) { }; if (Object.keys(filter).length > 0) { dataSource = dataSource.filter((item) => { - return (Object.keys(filter) as Array).some( - (key) => { - if (!filter[key]) { - return true; - } - if (filter[key].includes(`${item[key]}`)) { - return true; - } - return false; - }, - ); + return (Object.keys(filter) as Array).some((key) => { + if (!filter[key]) { + return true; + } + if (filter[key].includes(`${item[key]}`)) { + return true; + } + return false; + }); }); } } if (params.name) { - dataSource = dataSource.filter((data) => - data?.name?.includes(params.name || ''), - ); + dataSource = dataSource.filter((data) => data?.name?.includes(params.name || '')); } const result = { data: dataSource, @@ -114,10 +107,7 @@ function getRule(req: Request, res: Response, u: string) { function postRule(req: Request, res: Response, u: string, b: Request) { let realUrl = u; - if ( - !realUrl || - Object.prototype.toString.call(realUrl) !== '[object String]' - ) { + if (!realUrl || Object.prototype.toString.call(realUrl) !== '[object String]') { realUrl = req.url; } @@ -126,9 +116,7 @@ function postRule(req: Request, res: Response, u: string, b: Request) { switch (method) { case 'delete': - tableListDataSource = tableListDataSource.filter( - (item) => key.indexOf(item.key) === -1, - ); + tableListDataSource = tableListDataSource.filter((item) => key.indexOf(item.key) === -1); break; case 'post': (() => { diff --git a/mock/notices.ts b/mock/notices.ts index d8963113..a8a28d9b 100644 --- a/mock/notices.ts +++ b/mock/notices.ts @@ -85,8 +85,7 @@ const getNotices = (_req: Request, res: Response) => { { id: '000000010', title: '第三方紧急代码变更', - description: - '冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务', + description: '冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务', extra: '马上到期', status: 'urgent', type: 'event', @@ -102,8 +101,7 @@ const getNotices = (_req: Request, res: Response) => { { id: '000000012', title: 'ABCD 版本发布', - description: - '冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务', + description: '冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务', extra: '进行中', status: 'processing', type: 'event', diff --git a/mock/requestRecord.mock.js b/mock/requestRecord.mock.js index 7c8f0de5..6c59e198 100644 --- a/mock/requestRecord.mock.js +++ b/mock/requestRecord.mock.js @@ -2,8 +2,7 @@ module.exports = { 'GET /api/currentUser': { data: { name: 'Serati Ma', - avatar: - 'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png', userid: '00000001', email: 'antdesign@alipay.com', signature: '海纳百川,有容乃大', @@ -34,8 +33,7 @@ module.exports = { key: 99, disabled: false, href: 'https://ant.design', - avatar: - 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', name: 'TradeCode 99', owner: '曲丽丽', desc: '这是一段描述', @@ -49,8 +47,7 @@ module.exports = { key: 98, disabled: false, href: 'https://ant.design', - avatar: - 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', name: 'TradeCode 98', owner: '曲丽丽', desc: '这是一段描述', @@ -64,8 +61,7 @@ module.exports = { key: 97, disabled: false, href: 'https://ant.design', - avatar: - 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', name: 'TradeCode 97', owner: '曲丽丽', desc: '这是一段描述', @@ -79,8 +75,7 @@ module.exports = { key: 96, disabled: true, href: 'https://ant.design', - avatar: - 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', name: 'TradeCode 96', owner: '曲丽丽', desc: '这是一段描述', @@ -94,8 +89,7 @@ module.exports = { key: 95, disabled: false, href: 'https://ant.design', - avatar: - 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', name: 'TradeCode 95', owner: '曲丽丽', desc: '这是一段描述', @@ -109,8 +103,7 @@ module.exports = { key: 94, disabled: false, href: 'https://ant.design', - avatar: - 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', name: 'TradeCode 94', owner: '曲丽丽', desc: '这是一段描述', @@ -124,8 +117,7 @@ module.exports = { key: 93, disabled: false, href: 'https://ant.design', - avatar: - 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', name: 'TradeCode 93', owner: '曲丽丽', desc: '这是一段描述', @@ -139,8 +131,7 @@ module.exports = { key: 92, disabled: false, href: 'https://ant.design', - avatar: - 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', name: 'TradeCode 92', owner: '曲丽丽', desc: '这是一段描述', @@ -154,8 +145,7 @@ module.exports = { key: 91, disabled: false, href: 'https://ant.design', - avatar: - 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', name: 'TradeCode 91', owner: '曲丽丽', desc: '这是一段描述', @@ -169,8 +159,7 @@ module.exports = { key: 90, disabled: true, href: 'https://ant.design', - avatar: - 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', name: 'TradeCode 90', owner: '曲丽丽', desc: '这是一段描述', @@ -184,8 +173,7 @@ module.exports = { key: 89, disabled: false, href: 'https://ant.design', - avatar: - 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', name: 'TradeCode 89', owner: '曲丽丽', desc: '这是一段描述', @@ -199,8 +187,7 @@ module.exports = { key: 88, disabled: false, href: 'https://ant.design', - avatar: - 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', name: 'TradeCode 88', owner: '曲丽丽', desc: '这是一段描述', @@ -214,8 +201,7 @@ module.exports = { key: 87, disabled: false, href: 'https://ant.design', - avatar: - 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', name: 'TradeCode 87', owner: '曲丽丽', desc: '这是一段描述', @@ -229,8 +215,7 @@ module.exports = { key: 86, disabled: false, href: 'https://ant.design', - avatar: - 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', name: 'TradeCode 86', owner: '曲丽丽', desc: '这是一段描述', @@ -244,8 +229,7 @@ module.exports = { key: 85, disabled: false, href: 'https://ant.design', - avatar: - 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', name: 'TradeCode 85', owner: '曲丽丽', desc: '这是一段描述', @@ -259,8 +243,7 @@ module.exports = { key: 84, disabled: true, href: 'https://ant.design', - avatar: - 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', name: 'TradeCode 84', owner: '曲丽丽', desc: '这是一段描述', @@ -274,8 +257,7 @@ module.exports = { key: 83, disabled: false, href: 'https://ant.design', - avatar: - 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', name: 'TradeCode 83', owner: '曲丽丽', desc: '这是一段描述', @@ -289,8 +271,7 @@ module.exports = { key: 82, disabled: false, href: 'https://ant.design', - avatar: - 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', name: 'TradeCode 82', owner: '曲丽丽', desc: '这是一段描述', @@ -304,8 +285,7 @@ module.exports = { key: 81, disabled: false, href: 'https://ant.design', - avatar: - 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', name: 'TradeCode 81', owner: '曲丽丽', desc: '这是一段描述', @@ -319,8 +299,7 @@ module.exports = { key: 80, disabled: false, href: 'https://ant.design', - avatar: - 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', name: 'TradeCode 80', owner: '曲丽丽', desc: '这是一段描述', diff --git a/mock/user.ts b/mock/user.ts index 06125bf5..2c78c5bb 100644 --- a/mock/user.ts +++ b/mock/user.ts @@ -20,8 +20,7 @@ const { ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION } = process.env; * current user access, if is '', user need login * 如果是 pro 的预览,默认是有权限的 */ -let access = - ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION === 'site' ? 'admin' : ''; +let access = ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION === 'site' ? 'admin' : ''; const getAccess = () => { return access; @@ -46,8 +45,7 @@ export default { success: true, data: { name: 'Serati Ma', - avatar: - 'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png', + avatar: 'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png', userid: '00000001', email: 'antdesign@alipay.com', signature: '海纳百川,有容乃大', diff --git a/package.json b/package.json index 039e12c2..3e07ce98 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "lint": "npm run biome:lint && npm run tsc", "lint-staged": "lint-staged", "biome:lint": "npx @biomejs/biome lint", + "biome": "biome check --write", "openapi": "max openapi", "prepare": "husky", "preview": "npm run build && max preview --port 8000", diff --git a/public/scripts/loading.js b/public/scripts/loading.js index a4fdb3d5..16e3ff4a 100644 --- a/public/scripts/loading.js +++ b/public/scripts/loading.js @@ -2,7 +2,7 @@ * loading 占位 * 解决首次加载时白屏的问题 */ -(function () { +(() => { const _root = document.querySelector('#root'); if (_root && _root.innerHTML === '') { _root.innerHTML = ` diff --git a/src/app.tsx b/src/app.tsx index 96483655..621489e9 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -16,8 +16,7 @@ import defaultSettings from '../config/defaultSettings'; import { errorConfig } from './requestErrorConfig'; import '@ant-design/v5-patch-for-react-19'; -const isDev = - process.env.NODE_ENV === 'development' || process.env.CI; +const isDev = process.env.NODE_ENV === 'development' || process.env.CI; const loginPath = '/user/login'; /** diff --git a/src/pages/account/center/components/Applications/index.tsx b/src/pages/account/center/components/Applications/index.tsx index e8c273f5..2cf4d832 100644 --- a/src/pages/account/center/components/Applications/index.tsx +++ b/src/pages/account/center/components/Applications/index.tsx @@ -11,6 +11,7 @@ import React from 'react'; import type { ListItemDataType } from '../../data.d'; import { queryFakeList } from '../../service'; import useStyles from './index.style'; + export function formatWan(val: number) { const v = val * 1; if (!v || Number.isNaN(v)) return ''; @@ -35,19 +36,13 @@ export function formatWan(val: number) { } return result; } -const Applications: React.FC = () => { - const { styles: stylesApplications } = useStyles(); - // 获取tab列表数据 - const { data: listData } = useRequest(() => { - return queryFakeList({ - count: 30, - }); - }); - const CardInfo: React.FC<{ - activeUser: React.ReactNode; - newUser: React.ReactNode; - }> = ({ activeUser, newUser }) => ( +const CardInfo: React.FC<{ + activeUser: React.ReactNode; + newUser: React.ReactNode; +}> = ({ activeUser, newUser }) => { + const { styles: stylesApplications } = useStyles(); + return (

活跃用户

@@ -59,6 +54,17 @@ const Applications: React.FC = () => {
); +}; + +const Applications: React.FC = () => { + const { styles: stylesApplications } = useStyles(); + // 获取tab列表数据 + const { data: listData } = useRequest(() => { + return queryFakeList({ + count: 30, + }); + }); + return ( rowKey="id" diff --git a/src/pages/account/center/components/Articles/index.tsx b/src/pages/account/center/components/Articles/index.tsx index d2a69eee..896ba3c2 100644 --- a/src/pages/account/center/components/Articles/index.tsx +++ b/src/pages/account/center/components/Articles/index.tsx @@ -7,16 +7,17 @@ import { queryFakeList } from '../../service'; import ArticleListContent from '../ArticleListContent'; import useStyles from './index.style'; +const IconText: React.FC<{ + icon: React.ReactNode; + text: React.ReactNode; +}> = ({ icon, text }) => ( + + {icon} {text} + +); + const Articles: React.FC = () => { const { styles } = useStyles(); - const IconText: React.FC<{ - icon: React.ReactNode; - text: React.ReactNode; - }> = ({ icon, text }) => ( - - {icon} {text} - - ); // 获取tab列表数据 const { data: listData } = useRequest(() => { diff --git a/src/pages/account/settings/components/base.tsx b/src/pages/account/settings/components/base.tsx index 5fe63cb9..a295b518 100644 --- a/src/pages/account/settings/components/base.tsx +++ b/src/pages/account/settings/components/base.tsx @@ -29,23 +29,7 @@ const validatorPhone = ( const BaseView: React.FC = () => { const { styles } = useStyles(); - // 头像组件 方便以后独立,增加裁剪之类的功能 - const AvatarView = ({ avatar }: { avatar: string }) => ( - <> -
头像
-
- avatar -
- -
- -
-
- - ); + const { data: currentUser, loading } = useRequest(() => { return queryCurrent(); }); @@ -232,3 +216,24 @@ const BaseView: React.FC = () => { ); }; export default BaseView; + +const AvatarView = ({ avatar }: { avatar: string }) => { + const { styles } = useStyles(); + + return ( + <> +
头像
+
+ avatar +
+ +
+ +
+
+ + ); +}; diff --git a/src/pages/list/basic-list/index.tsx b/src/pages/list/basic-list/index.tsx index 3ac9e29a..af97803c 100644 --- a/src/pages/list/basic-list/index.tsx +++ b/src/pages/list/basic-list/index.tsx @@ -154,29 +154,31 @@ export const BasicList: FC = () => { /> ); - const MoreBtn: React.FC<{ - item: BasicListItemDataType; - }> = ({ item }) => ( - editAndDelete(key, item), - items: [ - { - key: 'edit', - label: '编辑', - }, - { - key: 'delete', - label: '删除', - }, - ], - }} - > - - 更多 - - - ); + + const renderMoreBtn = (item: BasicListItemDataType) => { + return ( + editAndDelete(key, item), + items: [ + { + key: 'edit', + label: '编辑', + }, + { + key: 'delete', + label: '删除', + }, + ], + }} + > + + 更多 + + + ); + }; + const handleDone = () => { setDone(false); setVisible(false); @@ -237,7 +239,7 @@ export const BasicList: FC = () => { > 编辑 , - , + renderMoreBtn(item), ]} > ({ value: `cat${index + 1}`, diff --git a/src/pages/list/search/articles/index.tsx b/src/pages/list/search/articles/index.tsx index 868a11cf..df44ede0 100644 --- a/src/pages/list/search/articles/index.tsx +++ b/src/pages/list/search/articles/index.tsx @@ -21,6 +21,37 @@ const FormItem = Form.Item; const pageSize = 5; +const IconText: React.FC<{ + type: string; + text: React.ReactNode; +}> = ({ type, text }) => { + switch (type) { + case 'star-o': + return ( + + + {text} + + ); + case 'like-o': + return ( + + + {text} + + ); + case 'message': + return ( + + + {text} + + ); + default: + return null; + } +}; + const Articles: FC = () => { const [form] = Form.useForm(); @@ -68,37 +99,6 @@ const Articles: FC = () => { }, ]; - const IconText: React.FC<{ - type: string; - text: React.ReactNode; - }> = ({ type, text }) => { - switch (type) { - case 'star-o': - return ( - - - {text} - - ); - case 'like-o': - return ( - - - {text} - - ); - case 'message': - return ( - - - {text} - - ); - default: - return null; - } - }; - const formItemLayout = { wrapperCol: { xs: { span: 24 }, diff --git a/src/pages/list/table-list/service.ts b/src/pages/list/table-list/service.ts index 29168469..046cdcb4 100644 --- a/src/pages/list/table-list/service.ts +++ b/src/pages/list/table-list/service.ts @@ -1,5 +1,3 @@ -// @ts-ignore -/* eslint-disable */ import { request } from '@umijs/max'; import type { TableListItem } from './data'; diff --git a/src/pages/user/login/__snapshots__/login.test.tsx.snap b/src/pages/user/login/__snapshots__/login.test.tsx.snap index a9134557..b4c7ec93 100644 --- a/src/pages/user/login/__snapshots__/login.test.tsx.snap +++ b/src/pages/user/login/__snapshots__/login.test.tsx.snap @@ -1,9 +1,9 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`Login Page should login success 1`] = `
Date: Wed, 22 Oct 2025 18:28:38 +0800 Subject: [PATCH 06/21] chore: tailwind CSS setup (#11576) * chore: tailwind CSS setup * test: update login button snapshot to include loading state --- biome.json | 3 ++- config/config.ts | 3 +++ package.json | 3 ++- .../login/__snapshots__/login.test.tsx.snap | 25 ++++++++++++++++++- tailwind.config.js | 3 +++ tailwind.css | 3 +++ 6 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 tailwind.config.js create mode 100644 tailwind.css diff --git a/biome.json b/biome.json index 8d4ab507..cee7317f 100644 --- a/biome.json +++ b/biome.json @@ -27,7 +27,8 @@ "rules": { "recommended": true, "suspicious": { - "noExplicitAny": "off" + "noExplicitAny": "off", + "noUnknownAtRules": "off" }, "correctness": { "useExhaustiveDependencies": "off", diff --git a/config/config.ts b/config/config.ts index a0e4bd7d..1314ba01 100644 --- a/config/config.ts +++ b/config/config.ts @@ -144,6 +144,7 @@ export default defineConfig({ // 解决首次加载时白屏的问题 { src: join(PUBLIC_PATH, 'scripts/loading.js'), async: true }, ], + //================ pro 插件配置 ================= presets: ['umi-presets-pro'], /** @@ -166,6 +167,7 @@ export default defineConfig({ projectName: 'swagger', }, ], + mock: { include: ['mock/**/*', 'src/pages/**/_mock.ts'], }, @@ -181,4 +183,5 @@ export default defineConfig({ define: { 'process.env.CI': process.env.CI, }, + tailwindcss: {}, }); diff --git a/package.json b/package.json index 3e07ce98..8b7579eb 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,8 @@ "umi-presets-pro": "^2.0.3", "umi-serve": "^1.9.11", "@biomejs/biome": "^2.0.6", - "@types/node": "^24.0.10" + "@types/node": "^24.0.10", + "tailwindcss": "^3" }, "engines": { "node": ">=20.0.0" diff --git a/src/pages/user/login/__snapshots__/login.test.tsx.snap b/src/pages/user/login/__snapshots__/login.test.tsx.snap index b4c7ec93..dd02b8ad 100644 --- a/src/pages/user/login/__snapshots__/login.test.tsx.snap +++ b/src/pages/user/login/__snapshots__/login.test.tsx.snap @@ -382,10 +382,33 @@ exports[`Login Page should login success 1`] = `
+ } + className={styles.formResult} + /> + )} + + ); +}; +export default OperationModal; diff --git a/src/pages/list/basic-list/data.d.ts b/src/pages/list/basic-list/data.d.ts new file mode 100644 index 00000000..f1cfa668 --- /dev/null +++ b/src/pages/list/basic-list/data.d.ts @@ -0,0 +1,29 @@ +export type Member = { + avatar: string; + name: string; + id: string; +}; + +export type BasicListItemDataType = { + id: string; + owner: string; + title: string; + avatar: string; + cover: string; + status: 'normal' | 'exception' | 'active' | 'success'; + percent: number; + logo: string; + href: string; + body?: any; + updatedAt: number; + createdAt: number; + subDescription: string; + description: string; + activeUser: number; + newUser: number; + star: number; + like: number; + message: number; + content: string; + members: Member[]; +}; diff --git a/src/pages/list/basic-list/service.ts b/src/pages/list/basic-list/service.ts new file mode 100644 index 00000000..99eb3541 --- /dev/null +++ b/src/pages/list/basic-list/service.ts @@ -0,0 +1,50 @@ +import { request } from '@umijs/max'; +import type { BasicListItemDataType } from './data.d'; + +type ParamsType = { + count?: number; +} & Partial; + +export async function queryFakeList( + params: ParamsType, +): Promise<{ data: { list: BasicListItemDataType[] } }> { + return request('/api/get_list', { + params, + }); +} + +export async function removeFakeList( + params: ParamsType, +): Promise<{ data: { list: BasicListItemDataType[] } }> { + return request('/api/post_fake_list', { + method: 'POST', + data: { + ...params, + method: 'delete', + }, + }); +} + +export async function addFakeList( + params: ParamsType, +): Promise<{ data: { list: BasicListItemDataType[] } }> { + return request('/api/post_fake_list', { + method: 'POST', + data: { + ...params, + method: 'post', + }, + }); +} + +export async function updateFakeList( + params: ParamsType, +): Promise<{ data: { list: BasicListItemDataType[] } }> { + return request('/api/post_fake_list', { + method: 'POST', + data: { + ...params, + method: 'update', + }, + }); +} diff --git a/src/pages/list/basic-list/style.style.ts b/src/pages/list/basic-list/style.style.ts new file mode 100644 index 00000000..7e120666 --- /dev/null +++ b/src/pages/list/basic-list/style.style.ts @@ -0,0 +1,141 @@ +import { createStyles } from 'antd-style'; + +const useStyles = createStyles(({ token }) => { + return { + standardList: { + '.ant-card-head': { borderBottom: 'none' }, + '.ant-card-head-title': { padding: '24px 0', lineHeight: '32px' }, + '.ant-card-extra': { padding: '24px 0' }, + '.ant-list-pagination': { marginTop: '24px', textAlign: 'right' }, + '.ant-avatar-lg': { width: '48px', height: '48px', lineHeight: '48px' }, + [`@media screen and (max-width: ${token.screenXS}px)`]: { + '.ant-list-item-content': { + display: 'block', + flex: 'none', + width: '100%', + }, + '.ant-list-item-action': { + marginLeft: '0', + }, + }, + }, + headerInfo: { + position: 'relative', + textAlign: 'center', + '& > span': { + display: 'inline-block', + marginBottom: '4px', + color: token.colorTextSecondary, + fontSize: token.fontSize, + lineHeight: '22px', + }, + '& > p': { + margin: '0', + color: token.colorTextHeading, + fontSize: '24px', + lineHeight: '32px', + }, + '& > em': { + position: 'absolute', + top: '0', + right: '0', + width: '1px', + height: '56px', + backgroundColor: token.colorSplit, + }, + [`@media screen and (max-width: ${token.screenSM}px)`]: { + marginBottom: '16px', + '& > em': { + display: 'none', + }, + }, + }, + listContent: { + fontSize: '0', + [`@media screen and (max-width: ${token.screenXS}px)`]: { + marginLeft: '0', + '& > div': { + marginLeft: '0', + }, + }, + [`@media screen and (max-width: ${token.screenMD}px)`]: { + '& > div': { + display: 'block', + }, + '& > div:last-child': { + top: '0', + width: '100%', + }, + }, + [`@media screen and (max-width: ${token.screenLG}px) and (min-width: @screen-md)`]: + { + '& > div': { + display: 'block', + }, + '& > div:last-child': { + top: '0', + width: '100%', + }, + }, + [`@media screen and (max-width: ${token.screenXL}px)`]: { + '& > div': { + marginLeft: '24px', + }, + '& > div:last-child': { + top: '0', + }, + }, + '@media screen and (max-width: 1400px)': { + textAlign: 'right', + '& > div:last-child': { + top: '0', + }, + }, + }, + listContentItem: { + display: 'inline-block', + marginLeft: '40px', + color: token.colorTextSecondary, + fontSize: token.fontSize, + verticalAlign: 'middle', + '> span': { lineHeight: '20px' }, + '> p': { marginTop: '4px', marginBottom: '0', lineHeight: '22px' }, + }, + extraContentSearch: { + width: '272px', + marginLeft: '16px', + [`@media screen and (max-width: ${token.screenSM}px)`]: { + width: '100%', + marginLeft: '0', + }, + }, + listCard: { + [`@media screen and (max-width: ${token.screenXS}px)`]: { + '.ant-card-head-title': { + overflow: 'open', + }, + }, + [`@media screen and (max-width: ${token.screenMD}px)`]: { + '.ant-radio-group': { + display: 'block', + marginBottom: '8px', + }, + }, + }, + standardListForm: { + '.ant-form-item': { + marginBottom: '12px', + '&:last-child': { + marginBottom: '32px', + paddingTop: '4px', + }, + }, + }, + formResult: { + width: '100%', + "[class^='title']": { marginBottom: '8px' }, + }, + }; +}); + +export default useStyles; diff --git a/src/pages/list/basic-list/utils/utils.style.ts b/src/pages/list/basic-list/utils/utils.style.ts new file mode 100644 index 00000000..0ad5e64a --- /dev/null +++ b/src/pages/list/basic-list/utils/utils.style.ts @@ -0,0 +1,6 @@ +import { createStyles } from 'antd-style'; + +const useStyles = createStyles(() => { + return {}; +}); +export default useStyles; diff --git a/src/pages/user/login/__snapshots__/login.test.tsx.snap b/src/pages/user/login/__snapshots__/login.test.tsx.snap index dd02b8ad..8cc10ba8 100644 --- a/src/pages/user/login/__snapshots__/login.test.tsx.snap +++ b/src/pages/user/login/__snapshots__/login.test.tsx.snap @@ -3,7 +3,7 @@ exports[`Login Page should login success 1`] = `
- Powered by Ant Desgin + Powered by Ant Design
@@ -607,7 +581,7 @@ exports[`Login Page should show login form 1`] = `
@@ -931,9 +905,6 @@ exports[`Login Page should show login form 1`] = ` id="autoLogin" type="checkbox" /> -
- Powered by Ant Desgin + Powered by Ant Design
From 38febe063e24bdd29cec9aea2203ef2557d5144b Mon Sep 17 00:00:00 2001 From: afc163 Date: Wed, 4 Mar 2026 12:22:16 +0800 Subject: [PATCH 08/21] fix: resolve lint errors for antd v6 compatibility - Use node: protocol for fs and path imports in scripts/simple.js - Replace deprecated hideRequiredMark with requiredMark={false} - Replace Steps.Step with Steps items prop for antd v6 - Add missing data.d.ts for table-list service - Fix formRef type in step-form using Form.useForm() Co-Authored-By: Claude Opus 4.6 --- scripts/simple.js | 8 +- .../account/settings/components/base.tsx | 2 +- src/pages/form/advanced-form/index.tsx | 2 +- src/pages/form/basic-form/index.tsx | 2 +- src/pages/form/step-form/index.tsx | 12 ++- src/pages/list/table-list/data.d.ts | 14 +++ src/pages/profile/advanced/index.tsx | 15 ++- src/pages/result/success/index.tsx | 102 +++++++++--------- 8 files changed, 87 insertions(+), 70 deletions(-) create mode 100644 src/pages/list/table-list/data.d.ts diff --git a/scripts/simple.js b/scripts/simple.js index 6f9ec69e..cefc6c10 100644 --- a/scripts/simple.js +++ b/scripts/simple.js @@ -8,8 +8,8 @@ * - 替换路由配置为简单版 */ -const fs = require('fs'); -const path = require('path'); +const fs = require('node:fs'); +const path = require('node:path'); // 需要删除的页面目录 const pageDirsToDelete = [ @@ -108,14 +108,14 @@ function updatePackageJson() { } // 移除 simple 脚本 - if (pkg.scripts && pkg.scripts.simple) { + if (pkg.scripts?.simple) { delete pkg.scripts.simple; console.log('✓ 已移除 simple 脚本'); modified = true; } if (modified) { - fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n'); + fs.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`); console.log('✓ 已更新 package.json'); } else { console.log('- package.json 无需更新'); diff --git a/src/pages/account/settings/components/base.tsx b/src/pages/account/settings/components/base.tsx index a295b518..66dd0a2c 100644 --- a/src/pages/account/settings/components/base.tsx +++ b/src/pages/account/settings/components/base.tsx @@ -65,7 +65,7 @@ const BaseView: React.FC = () => { ...currentUser, phone: currentUser?.phone.split('-'), }} - hideRequiredMark + requiredMark={false} > > = () => { return ( { return ( diff --git a/src/pages/form/basic-form/index.tsx b/src/pages/form/basic-form/index.tsx index 7d053f99..b2a44aca 100644 --- a/src/pages/form/basic-form/index.tsx +++ b/src/pages/form/basic-form/index.tsx @@ -30,7 +30,7 @@ const BasicForm: FC> = () => { > = () => { receiverMode: 'alipay', }); const [current, setCurrent] = useState(0); - const formRef = useRef(null); + const [form] = Form.useForm(); return ( @@ -99,7 +99,9 @@ const StepForm: React.FC> = () => { }} > - formRef={formRef} + formRef={{ + current: form, + }} title="填写转账信息" initialValues={stepData} onFinish={async (values) => { @@ -218,7 +220,7 @@ const StepForm: React.FC> = () => { { setCurrent(0); - formRef.current?.resetFields(); + form.resetFields(); }} > diff --git a/src/pages/list/table-list/data.d.ts b/src/pages/list/table-list/data.d.ts new file mode 100644 index 00000000..209056e6 --- /dev/null +++ b/src/pages/list/table-list/data.d.ts @@ -0,0 +1,14 @@ +export type TableListItem = { + key: number; + disabled?: boolean; + href: string; + avatar: string; + name: string; + owner: string; + desc: string; + callNo: number; + status: 0 | 1 | 2 | 3; + updatedAt: string; + createdAt: string; + progress: number; +}; diff --git a/src/pages/profile/advanced/index.tsx b/src/pages/profile/advanced/index.tsx index f0d00c1c..c2833833 100644 --- a/src/pages/profile/advanced/index.tsx +++ b/src/pages/profile/advanced/index.tsx @@ -32,8 +32,6 @@ import type { AdvancedProfileData } from './data.d'; import { queryAdvancedProfile } from './service'; import useStyles from './style.style'; -const { Step } = Steps; - const action = ( {({ isMobile }) => { @@ -349,12 +347,13 @@ const Advanced: FC = () => { direction={isMobile ? 'vertical' : 'horizontal'} progressDot={customDot} current={1} - > - - - - - + items={[ + { title: '创建项目', description: desc1 }, + { title: '部门初审', description: desc2 }, + { title: '财务复核' }, + { title: '完成' }, + ]} + /> )} diff --git a/src/pages/result/success/index.tsx b/src/pages/result/success/index.tsx index bf45bd09..ba1f00ce 100644 --- a/src/pages/result/success/index.tsx +++ b/src/pages/result/success/index.tsx @@ -3,8 +3,6 @@ import { GridContent } from '@ant-design/pro-components'; import { Button, Card, Descriptions, Result, Steps } from 'antd'; import useStyles from './index.style'; -const { Step } = Steps; - export default () => { const { styles } = useStyles(); const desc1 = ( @@ -60,54 +58,58 @@ export default () => {
- - - 创建项目 - - } - description={desc1} - /> - - 部门初审 - - } - description={desc2} - /> - - 财务复核 - - } - /> - - 完成 - - } - /> - + + 创建项目 + + ), + description: desc1, + }, + { + title: ( + + 部门初审 + + ), + description: desc2, + }, + { + title: ( + + 财务复核 + + ), + }, + { + title: ( + + 完成 + + ), + }, + ]} + /> ); const extra = ( From 73509b24e64b513e4db79430445eca0ea0c8a1df Mon Sep 17 00:00:00 2001 From: afc163 Date: Wed, 4 Mar 2026 12:27:03 +0800 Subject: [PATCH 09/21] fix: fix type error in _mock.ts for city lookup Co-Authored-By: Claude Opus 4.6 --- src/pages/account/settings/_mock.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/account/settings/_mock.ts b/src/pages/account/settings/_mock.ts index 4e786929..4bec6c1b 100644 --- a/src/pages/account/settings/_mock.ts +++ b/src/pages/account/settings/_mock.ts @@ -10,8 +10,9 @@ function getProvince(_: Request, res: Response) { } function getCity(req: Request, res: Response) { + const province = req.params.province; return res.json({ - data: city[req.params.province], + data: city[province as keyof typeof city], }); } From e21ccee87176ce4b355a93a4e23cff8f0bc37ee6 Mon Sep 17 00:00:00 2001 From: afc163 Date: Thu, 5 Mar 2026 10:35:58 +0800 Subject: [PATCH 10/21] Update src/pages/account/settings/components/base.tsx Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- src/pages/account/settings/components/base.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/account/settings/components/base.tsx b/src/pages/account/settings/components/base.tsx index 66dd0a2c..4031876d 100644 --- a/src/pages/account/settings/components/base.tsx +++ b/src/pages/account/settings/components/base.tsx @@ -63,7 +63,7 @@ const BaseView: React.FC = () => { }} initialValues={{ ...currentUser, - phone: currentUser?.phone.split('-'), + phone: currentUser?.phone?.split('-'), }} requiredMark={false} > From 33833440e0ae394ca5f3294b5b10d87ad2d50825 Mon Sep 17 00:00:00 2001 From: afc163 Date: Thu, 5 Mar 2026 10:43:08 +0800 Subject: [PATCH 11/21] refactor: convert class components to functional components - Convert Yuan.tsx to FC with useRef + useEffect - Convert MonitorMap to FC with useState + useEffect - Convert autoHeight HOC to functional component - Convert WaterWave to FC with proper animation cleanup Co-Authored-By: Claude Opus 4.6 --- .../components/Charts/WaterWave/index.tsx | 158 +++++------ src/pages/dashboard/analysis/utils/Yuan.tsx | 40 +-- .../components/Charts/WaterWave/index.tsx | 158 +++++------ .../monitor/components/Charts/autoHeight.tsx | 57 ++-- .../monitor/components/Map/index.tsx | 267 +++++++++--------- 5 files changed, 316 insertions(+), 364 deletions(-) diff --git a/src/pages/dashboard/analysis/components/Charts/WaterWave/index.tsx b/src/pages/dashboard/analysis/components/Charts/WaterWave/index.tsx index 62ee38db..b75f723d 100644 --- a/src/pages/dashboard/analysis/components/Charts/WaterWave/index.tsx +++ b/src/pages/dashboard/analysis/components/Charts/WaterWave/index.tsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import { useEffect, useRef, useState } from 'react'; import autoHeight from '../../../../monitor/components/Charts/autoHeight'; /* eslint no-return-assign: 0 */ @@ -12,57 +12,25 @@ export type WaterWaveProps = { percent: number; style?: React.CSSProperties; }; -class WaterWave extends Component { - state = { - radio: 1, - }; - timer: number = 0; - root: HTMLDivElement | undefined | null = null; - node: HTMLCanvasElement | undefined | null = null; - componentDidMount() { - this.renderChart(); - this.resize(); - window.addEventListener( - 'resize', - () => { - requestAnimationFrame(() => this.resize()); - }, - { - passive: true, - }, - ); - } - componentDidUpdate(props: WaterWaveProps) { - const { percent } = this.props; - if (props.percent !== percent) { - // 不加这个会造成绘制缓慢 - this.renderChart('update'); - } - } - componentWillUnmount() { - cancelAnimationFrame(this.timer); - if (this.node) { - this.node.innerHTML = ''; - } - window.removeEventListener('resize', this.resize); - } - resize = () => { - if (this.root) { - const { height = 1 } = this.props; - const { offsetWidth } = this.root.parentNode as HTMLElement; - this.setState({ - radio: offsetWidth < height ? offsetWidth / height : 1, - }); - } - }; - renderChart(type?: string) { - const { percent, color = '#1890FF' } = this.props; + +const WaterWave: React.FC = ({ + title, + color = '#1890FF', + height = 1, + percent, +}) => { + const [radio, setRadio] = useState(1); + const timerRef = useRef(0); + const rootRef = useRef(null); + const nodeRef = useRef(null); + + const renderChart = (type?: string) => { const data = percent / 100; - cancelAnimationFrame(this.timer); - if (!this.node || (data !== 0 && !data)) { + cancelAnimationFrame(timerRef.current); + if (!nodeRef.current || (data !== 0 && !data)) { return; } - const canvas = this.node; + const canvas = nodeRef.current; const ctx = canvas.getContext('2d'); if (!ctx) { return; @@ -179,47 +147,69 @@ class WaterWave extends Component { sp += 0.07; drawSin(); } - this.timer = requestAnimationFrame(render); + timerRef.current = requestAnimationFrame(render); }; render(); - } - render() { - const { radio } = this.state; - const { percent, title, height = 1 } = this.props; - return ( + }; + + const resize = () => { + if (rootRef.current) { + const { offsetWidth } = rootRef.current.parentNode as HTMLElement; + setRadio(offsetWidth < height ? offsetWidth / height : 1); + } + }; + + useEffect(() => { + renderChart(); + resize(); + const handleResize = () => { + requestAnimationFrame(resize); + }; + window.addEventListener('resize', handleResize, { passive: true }); + + return () => { + window.removeEventListener('resize', handleResize); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + useEffect(() => { + renderChart('update'); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [percent]); + + useEffect(() => { + return () => { + cancelAnimationFrame(timerRef.current); + }; + }, []); + + return ( +
{ - this.root = n; + style={{ + width: height, + height, + overflow: 'hidden', }} + > + +
+
-
- { - this.node = n; - }} - width={height * 2} - height={height * 2} - /> -
-
- {title && {title}} -

{percent}%

-
+ {title && {title}} +

{percent}%

- ); - } -} +
+ ); +}; + export default autoHeight()(WaterWave); diff --git a/src/pages/dashboard/analysis/utils/Yuan.tsx b/src/pages/dashboard/analysis/utils/Yuan.tsx index a541e7b4..516d59fa 100644 --- a/src/pages/dashboard/analysis/utils/Yuan.tsx +++ b/src/pages/dashboard/analysis/utils/Yuan.tsx @@ -1,33 +1,17 @@ -import React from 'react'; +import { useEffect, useRef } from 'react'; import { yuan } from '../components/Charts'; -/** 减少使用 dangerouslySetInnerHTML */ -export default class Yuan extends React.Component<{ - children: string | number; -}> { - main: HTMLSpanElement | undefined | null = null; - - componentDidMount() { - this.renderToHtml(); - } - componentDidUpdate() { - this.renderToHtml(); - } +/** 减少使用 dangerouslySetInnerHTML */ +const Yuan: React.FC<{ children: string | number }> = ({ children }) => { + const spanRef = useRef(null); - renderToHtml = () => { - const { children } = this.props; - if (this.main) { - this.main.innerHTML = yuan(children); + useEffect(() => { + if (spanRef.current) { + spanRef.current.innerHTML = yuan(children); } - }; + }, [children]); + + return ; +}; - render() { - return ( - { - this.main = ref; - }} - /> - ); - } -} +export default Yuan; diff --git a/src/pages/dashboard/monitor/components/Charts/WaterWave/index.tsx b/src/pages/dashboard/monitor/components/Charts/WaterWave/index.tsx index 90ad3eab..81f76dcb 100644 --- a/src/pages/dashboard/monitor/components/Charts/WaterWave/index.tsx +++ b/src/pages/dashboard/monitor/components/Charts/WaterWave/index.tsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import { useEffect, useRef, useState } from 'react'; import autoHeight from '../autoHeight'; /* eslint no-return-assign: 0 */ @@ -12,57 +12,25 @@ export type WaterWaveProps = { percent: number; style?: React.CSSProperties; }; -class WaterWave extends Component { - state = { - radio: 1, - }; - timer: number = 0; - root: HTMLDivElement | undefined | null = null; - node: HTMLCanvasElement | undefined | null = null; - componentDidMount() { - this.renderChart(); - this.resize(); - window.addEventListener( - 'resize', - () => { - requestAnimationFrame(() => this.resize()); - }, - { - passive: true, - }, - ); - } - componentDidUpdate(props: WaterWaveProps) { - const { percent } = this.props; - if (props.percent !== percent) { - // 不加这个会造成绘制缓慢 - this.renderChart('update'); - } - } - componentWillUnmount() { - cancelAnimationFrame(this.timer); - if (this.node) { - this.node.innerHTML = ''; - } - window.removeEventListener('resize', this.resize); - } - resize = () => { - if (this.root) { - const { height = 1 } = this.props; - const { offsetWidth } = this.root.parentNode as HTMLElement; - this.setState({ - radio: offsetWidth < height ? offsetWidth / height : 1, - }); - } - }; - renderChart(type?: string) { - const { percent, color = '#1890FF' } = this.props; + +const WaterWave: React.FC = ({ + title, + color = '#1890FF', + height = 1, + percent, +}) => { + const [radio, setRadio] = useState(1); + const timerRef = useRef(0); + const rootRef = useRef(null); + const nodeRef = useRef(null); + + const renderChart = (type?: string) => { const data = percent / 100; - cancelAnimationFrame(this.timer); - if (!this.node || (data !== 0 && !data)) { + cancelAnimationFrame(timerRef.current); + if (!nodeRef.current || (data !== 0 && !data)) { return; } - const canvas = this.node; + const canvas = nodeRef.current; const ctx = canvas.getContext('2d'); if (!ctx) { return; @@ -179,47 +147,69 @@ class WaterWave extends Component { sp += 0.07; drawSin(); } - this.timer = requestAnimationFrame(render); + timerRef.current = requestAnimationFrame(render); }; render(); - } - render() { - const { radio } = this.state; - const { percent, title, height = 1 } = this.props; - return ( + }; + + const resize = () => { + if (rootRef.current) { + const { offsetWidth } = rootRef.current.parentNode as HTMLElement; + setRadio(offsetWidth < height ? offsetWidth / height : 1); + } + }; + + useEffect(() => { + renderChart(); + resize(); + const handleResize = () => { + requestAnimationFrame(resize); + }; + window.addEventListener('resize', handleResize, { passive: true }); + + return () => { + window.removeEventListener('resize', handleResize); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + useEffect(() => { + renderChart('update'); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [percent]); + + useEffect(() => { + return () => { + cancelAnimationFrame(timerRef.current); + }; + }, []); + + return ( +
{ - this.root = n; + style={{ + width: height, + height, + overflow: 'hidden', }} + > + +
+
-
- { - this.node = n; - }} - width={height * 2} - height={height * 2} - /> -
-
- {title && {title}} -

{percent}%

-
+ {title && {title}} +

{percent}%

- ); - } -} +
+ ); +}; + export default autoHeight()(WaterWave); diff --git a/src/pages/dashboard/monitor/components/Charts/autoHeight.tsx b/src/pages/dashboard/monitor/components/Charts/autoHeight.tsx index c5af01b7..9c9fa3c4 100644 --- a/src/pages/dashboard/monitor/components/Charts/autoHeight.tsx +++ b/src/pages/dashboard/monitor/components/Charts/autoHeight.tsx @@ -1,8 +1,6 @@ -import React from 'react'; +import React, { useEffect, useRef, useState } from 'react'; -export type IReactComponent

= - | React.ComponentClass

- | React.ClassicComponentClass

; +export type IReactComponent

= React.ComponentClass

| React.FC

; function computeHeight(node: HTMLDivElement) { const { style } = node; @@ -37,42 +35,35 @@ type AutoHeightProps = { function autoHeight() { return

( WrappedComponent: React.ComponentClass

| React.FC

, - ): React.ComponentClass

=> { - class AutoHeightComponent extends React.Component

{ - state = { - computedHeight: 0, - }; + ): React.FC

=> { + const AutoHeightComponent: React.FC

= (props) => { + const [computedHeight, setComputedHeight] = useState(0); + const rootRef = useRef(null); - root: HTMLDivElement | null = null; - - componentDidMount() { - const { height } = this.props; - if (!height && this.root) { - let h = getAutoHeight(this.root); - this.setState({ computedHeight: h }); + useEffect(() => { + const { height } = props; + if (!height && rootRef.current) { + let h = getAutoHeight(rootRef.current); + setComputedHeight(h); if (h < 1) { - h = getAutoHeight(this.root); - this.setState({ computedHeight: h }); + h = getAutoHeight(rootRef.current); + setComputedHeight(h); } } - } + }, [props]); + + const { height } = props; + const h = height || computedHeight; - handleRoot = (node: HTMLDivElement) => { - this.root = node; - }; + return ( +

+ {h > 0 && } +
+ ); + }; - render() { - const { height } = this.props; - const { computedHeight } = this.state; - const h = height || computedHeight; - return ( -
- {h > 0 && } -
- ); - } - } return AutoHeightComponent; }; } + export default autoHeight; diff --git a/src/pages/dashboard/monitor/components/Map/index.tsx b/src/pages/dashboard/monitor/components/Map/index.tsx index df155e1f..34be85f0 100644 --- a/src/pages/dashboard/monitor/components/Map/index.tsx +++ b/src/pages/dashboard/monitor/components/Map/index.tsx @@ -1,6 +1,6 @@ import { PageLoading } from '@ant-design/pro-components'; import { HeatmapLayer, MapboxScene, PointLayer } from '@antv/l7-react'; -import * as React from 'react'; +import { useEffect, useState } from 'react'; const colors = [ '#eff3ff', @@ -11,143 +11,140 @@ const colors = [ '#2171b5', '#084594', ]; -export default class MonitorMap extends React.Component { - state = { - data: null, - grid: null, - loading: false, - }; - public async componentDidMount() { - const [geoData, gridData] = await Promise.all([ - fetch( - 'https://gw.alipayobjects.com/os/bmw-prod/c5dba875-b6ea-4e88-b778-66a862906c93.json', - ).then((d) => d.json()), - fetch( - 'https://gw.alipayobjects.com/os/bmw-prod/8990e8b4-c58e-419b-afb9-8ea3daff2dd1.json', - ).then((d) => d.json()), - ]); - this.setState({ - data: geoData, - grid: gridData, - loading: true, - }); - } +export default function MonitorMap() { + const [data, setData] = useState[] | null>(null); + const [grid, setGrid] = useState[] | null>(null); + const [loading, setLoading] = useState(false); - public render() { - const { data, grid, loading } = this.state; - return loading === false ? ( - - ) : ( - - {grid && ( - - )} - {data && [ - { + async function fetchData() { + const [geoData, gridData] = await Promise.all([ + fetch( + 'https://gw.alipayobjects.com/os/bmw-prod/c5dba875-b6ea-4e88-b778-66a862906c93.json', + ).then((d) => d.json()), + fetch( + 'https://gw.alipayobjects.com/os/bmw-prod/8990e8b4-c58e-419b-afb9-8ea3daff2dd1.json', + ).then((d) => d.json()), + ]); + setData(geoData); + setGrid(gridData); + setLoading(true); + } + fetchData(); + }, []); + + return loading === false ? ( + + ) : ( + + {grid && ( + + )} + {data && [ + , - { - return v > 2000; + size: { + field: 'cum_conf', + type: 'log', }, - }} - size={{ - values: 12, - }} - style={{ - opacity: 1, - strokeOpacity: 1, - strokeWidth: 0, - }} - />, - ]} - - ); - } + }, + }} + color={{ + field: 'cum_conf', + values: colors, + }} + shape={{ + values: 'circle', + }} + active={{ + option: { + color: '#0c2c84', + }, + }} + size={{ + field: 'cum_conf', + values: [0, 30], + }} + style={{ + opacity: 0.8, + }} + />, + { + return v > 2000; + }, + }} + size={{ + values: 12, + }} + style={{ + opacity: 1, + strokeOpacity: 1, + strokeWidth: 0, + }} + />, + ]} + + ); } From 98c448215f7fc91b66f27ecfb159872959a8d48f Mon Sep 17 00:00:00 2001 From: afc163 Date: Thu, 5 Mar 2026 10:47:46 +0800 Subject: [PATCH 12/21] chore: add .claude/settings.local.json to gitignore Co-Authored-By: Claude Opus 4.6 --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 7237b34a..e54692b2 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,9 @@ package-lock.json functions/* .temp/** +# claude code local settings +.claude/settings.local.json + # umi .umi .umi-production From 23a62e564ab0778c0c45fa8c00bb68b51da1a9ad Mon Sep 17 00:00:00 2001 From: afc163 Date: Thu, 5 Mar 2026 11:06:20 +0800 Subject: [PATCH 13/21] Delete .claude/settings.local.json --- .claude/settings.local.json | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 .claude/settings.local.json diff --git a/.claude/settings.local.json b/.claude/settings.local.json deleted file mode 100644 index f6e2c55f..00000000 --- a/.claude/settings.local.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "permissions": { - "allow": [ - "Bash(git ls-tree:*)", - "Bash(npm show:*)", - "Bash(git merge:*)", - "Bash(git add:*)", - "Bash(git checkout:*)", - "Bash(ls:*)", - "Bash(git commit:*)", - "Bash(npm test:*)", - "Bash(npm install:*)", - "Bash(npm publish:*)", - "Bash(tnpm publish:*)" - ] - } -} From dc4ddb578621c4501ec9b61df211acf3cd3fc500 Mon Sep 17 00:00:00 2001 From: afc163 Date: Thu, 5 Mar 2026 10:53:09 +0800 Subject: [PATCH 14/21] docs: remove pro-cli usage, guide users to use npm run simple - Update README.md and README.zh-CN.md with new usage instructions - Remove multi-language README files (keep only EN and CN) - Remove @ant-design/pro-cli from devDependencies Co-Authored-By: Claude Opus 4.6 --- README.ar-DZ.md | 125 ------------------------------------------------ README.es-ES.md | 125 ------------------------------------------------ README.fr-FR.md | 125 ------------------------------------------------ README.ja-JP.md | 125 ------------------------------------------------ README.md | 39 +++++---------- README.pt-BR.md | 125 ------------------------------------------------ README.ru-RU.md | 125 ------------------------------------------------ README.tr-TR.md | 125 ------------------------------------------------ README.zh-CN.md | 48 +++++++++++++------ package.json | 1 - 10 files changed, 45 insertions(+), 918 deletions(-) delete mode 100644 README.ar-DZ.md delete mode 100644 README.es-ES.md delete mode 100644 README.fr-FR.md delete mode 100644 README.ja-JP.md delete mode 100644 README.pt-BR.md delete mode 100644 README.ru-RU.md delete mode 100644 README.tr-TR.md diff --git a/README.ar-DZ.md b/README.ar-DZ.md deleted file mode 100644 index 10976d68..00000000 --- a/README.ar-DZ.md +++ /dev/null @@ -1,125 +0,0 @@ -# Ant Design Pro - -اللغة: 🇺🇸 | [🇨🇳](./README.zh-CN.md) | [🇷🇺](./README.ru-RU.md) | [🇹🇷](./README.tr-TR.md) | [🇯🇵](./README.ja-JP.md) | [🇫🇷](./README.fr-FR.md) | [🇧🇷](./README.pt-BR.md) | [🇩🇿](./README.ar-DZ.md) | [🇪🇸](./README.es-ES.md) - -

Ant Design Pro

- -
- -حل واجهة مستخدم جاهز لتطبيقات المؤسسات مبني على React. - -[![CI](https://github.com/ant-design/ant-design-pro/actions/workflows/ci.yml/badge.svg)](https://github.com/ant-design/ant-design-pro/actions/workflows/ci.yml) -[![Preview Deploy](https://github.com/ant-design/ant-design-pro/actions/workflows/preview-deploy.yml/badge.svg)](https://github.com/ant-design/ant-design-pro/actions/workflows/preview-deploy.yml) -[![Build With Umi](https://img.shields.io/badge/build%20with-umi-028fe4.svg?style=flat-square)](http://umijs.org/) -[![Checked with Biome](https://img.shields.io/badge/Checked_with-Biome-60a5fa?style=flat&logo=biome)](https://biomejs.dev) -[![](https://badgen.net/badge/icon/Ant%20Design?icon=https://gw.alipayobjects.com/zos/antfincdn/Pp4WPgVDB3/KDpgvguMpGfqaHPjicRK.svg&label)](https://ant.design/) - -معاينة السمة الفاتحة -معاينة السمة الداكنة - -
- -- المعاينة: http://preview.pro.ant.design -- الصفحة الرئيسية: http://pro.ant.design -- التوثيق: http://pro.ant.design/docs/getting-started -- سجل التغييرات: http://pro.ant.design/docs/changelog -- الأسئلة الشائعة: http://pro.ant.design/docs/faq - -## الميزات - -- :bulb: **TypeScript**: لغة لتطبيقات JavaScript على نطاق واسع -- :scroll: **الكتل**: بناء الصفحات باستخدام قوالب الكتل -- :gem: **تصميم أنيق**: يتبع [مواصفات Ant Design](http://ant.design/) -- :triangular_ruler: **قوالب شائعة**: قوالب نموذجية لتطبيقات المؤسسات -- :rocket: **تطوير حديث**: أحدث تقنيات React/umi/dva/antd -- :iphone: **متجاوب**: مصمم لأحجام شاشات مختلفة -- :art: **تخصيص السمة**: سمة قابلة للتخصيص بإعداد بسيط -- :globe_with_meridians: **دعم اللغات**: حل i18n مدمج -- :gear: **أفضل الممارسات**: سير عمل قوي للحفاظ على صحة الكود -- :1234: **تطوير وهمي**: حل تطوير وهمي سهل الاستخدام -- :white_check_mark: **اختبار الواجهة**: أمان مع اختبارات الوحدة وe2e - -## القوالب - -``` -- لوحة القيادة - - تحليلات - - مراقبة - - مساحة العمل -- النماذج - - نموذج أساسي - - نموذج متعدد الخطوات - - نموذج متقدم -- القوائم - - جدول قياسي - - قائمة قياسية - - قائمة البطاقات - - قائمة البحث (مشروع/تطبيقات/مقال) -- الملف الشخصي - - ملف شخصي بسيط - - ملف شخصي متقدم -- الحساب - - مركز الحساب - - إعدادات الحساب -- النتائج - - نجاح - - فشل -- الاستثناءات - - 403 - - 404 - - 500 -- المستخدم - - تسجيل الدخول - - التسجيل - - نتيجة التسجيل -``` - -## الاستخدام - -### استخدام bash - -نوفر pro-cli لبدء المشروع بسرعة. - -```bash -# استخدم npm -npm i @ant-design/pro-cli -g -pro create myapp -``` - -اختر قالب pro. Simple هو القالب الأساسي الذي يوفر فقط المحتوى الأساسي لتشغيل الإطار. Complete يحتوي على جميع الكتل، وهو غير مناسب كقالب أساسي للتطوير الثانوي. - -```shell -? 🚀 مشروع كامل أم هيكل بسيط؟ (استخدم الأسهم) -➥ simple - complete -``` - -تهيئة مستودع Git: - -```shell -$ git init myapp -``` - -تثبيت التبعيات: - -```shell -$ cd myapp && tyarn -// أو -$ cd myapp && npm install -``` - -## المتصفحات المدعومة - -المتصفحات الحديثة. - -| [Edge](http://godban.github.io/browsers-support-badges/)
Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | [Opera](http://godban.github.io/browsers-support-badges/)
Opera | -| --- | --- | --- | --- | --- | -| Edge | آخر إصدارين | آخر إصدارين | آخر إصدارين | آخر إصدارين | - -## المساهمة - -أي مساهمة مرحب بها. إليك بعض الطرق للمساهمة في هذا المشروع: - -- استخدم Ant Design Pro في عملك اليومي. -- أرسل [issues](http://github.com/ant-design/ant-design-pro/issues) للإبلاغ عن الأخطاء أو طرح الأسئلة. -- اقترح [pull requests](http://github.com/ant-design/ant-design-pro/pulls) لتحسين الكود الخاص بنا. diff --git a/README.es-ES.md b/README.es-ES.md deleted file mode 100644 index 0ec0206d..00000000 --- a/README.es-ES.md +++ /dev/null @@ -1,125 +0,0 @@ -# Ant Design Pro - -Idioma: 🇺🇸 | [🇨🇳](./README.zh-CN.md) | [🇷🇺](./README.ru-RU.md) | [🇹🇷](./README.tr-TR.md) | [🇯🇵](./README.ja-JP.md) | [🇫🇷](./README.fr-FR.md) | [🇧🇷](./README.pt-BR.md) | [🇩🇿](./README.ar-DZ.md) | [🇪🇸](./README.es-ES.md) - -

Ant Design Pro

- -
- -Una solución de interfaz de usuario lista para usar para aplicaciones empresariales basada en React. - -[![CI](https://github.com/ant-design/ant-design-pro/actions/workflows/ci.yml/badge.svg)](https://github.com/ant-design/ant-design-pro/actions/workflows/ci.yml) -[![Preview Deploy](https://github.com/ant-design/ant-design-pro/actions/workflows/preview-deploy.yml/badge.svg)](https://github.com/ant-design/ant-design-pro/actions/workflows/preview-deploy.yml) -[![Build With Umi](https://img.shields.io/badge/build%20with-umi-028fe4.svg?style=flat-square)](http://umijs.org/) -[![Checked with Biome](https://img.shields.io/badge/Checked_with-Biome-60a5fa?style=flat&logo=biome)](https://biomejs.dev) -[![](https://badgen.net/badge/icon/Ant%20Design?icon=https://gw.alipayobjects.com/zos/antfincdn/Pp4WPgVDB3/KDpgvguMpGfqaHPjicRK.svg&label)](https://ant.design/) - -vista previa del tema claro -vista previa del tema oscuro - -
- -- Vista previa: http://preview.pro.ant.design -- Página principal: http://pro.ant.design -- Documentación: http://pro.ant.design/docs/getting-started -- Registro de cambios: http://pro.ant.design/docs/changelog -- Preguntas frecuentes: http://pro.ant.design/docs/faq - -## Características - -- :bulb: **TypeScript**: Un lenguaje para aplicaciones JavaScript a gran escala -- :scroll: **Bloques**: Construye páginas con plantillas de bloques -- :gem: **Diseño elegante**: Sigue la [especificación de Ant Design](http://ant.design/) -- :triangular_ruler: **Plantillas comunes**: Plantillas típicas para aplicaciones empresariales -- :rocket: **Desarrollo de vanguardia**: Stack de desarrollo más reciente con React/umi/dva/antd -- :iphone: **Responsivo**: Diseñado para diferentes tamaños de pantalla -- :art: **Tematización**: Tema personalizable con configuración sencilla -- :globe_with_meridians: **Internacionalización**: Solución i18n integrada -- :gear: **Buenas prácticas**: Flujo de trabajo sólido para mantener tu código saludable -- :1234: **Desarrollo mock**: Solución de desarrollo mock fácil de usar -- :white_check_mark: **Pruebas de UI**: Seguridad con pruebas unitarias y e2e - -## Plantillas - -``` -- Panel de control - - Analítica - - Monitorización - - Espacio de trabajo -- Formulario - - Formulario básico - - Formulario por pasos - - Formulario avanzado -- Lista - - Tabla estándar - - Lista estándar - - Lista de tarjetas - - Lista de búsqueda (Proyecto/Aplicaciones/Artículo) -- Perfil - - Perfil simple - - Perfil avanzado -- Cuenta - - Centro de cuenta - - Configuración de cuenta -- Resultado - - Éxito - - Fallo -- Excepción - - 403 - - 404 - - 500 -- Usuario - - Iniciar sesión - - Registrarse - - Resultado del registro -``` - -## Uso - -### Usar bash - -Proporcionamos pro-cli para inicializar rápidamente el proyecto. - -```bash -# usar npm -npm i @ant-design/pro-cli -g -pro create myapp -``` - -Elige la plantilla pro. Simple es la plantilla básica, que solo proporciona el contenido esencial para el funcionamiento del framework. Complete contiene todos los bloques, por lo que no es adecuada como plantilla base para desarrollo secundario. - -```shell -? 🚀 ¿Proyecto completo o un esqueleto simple? (Usa las flechas) -➥ simple - complete -``` - -Inicializa el repositorio Git: - -```shell -$ git init myapp -``` - -Instala las dependencias: - -```shell -$ cd myapp && tyarn -// o -$ cd myapp && npm install -``` - -## Navegadores soportados - -Navegadores modernos. - -| [Edge](http://godban.github.io/browsers-support-badges/)
Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | [Opera](http://godban.github.io/browsers-support-badges/)
Opera | -| --- | --- | --- | --- | --- | -| Edge | últimas 2 versiones | últimas 2 versiones | últimas 2 versiones | últimas 2 versiones | - -## Contribución - -Cualquier tipo de contribución es bienvenida. Aquí tienes algunos ejemplos de cómo puedes contribuir a este proyecto: - -- Usa Ant Design Pro en tu trabajo diario. -- Envía [issues](http://github.com/ant-design/ant-design-pro/issues) para informar de errores o hacer preguntas. -- Propón [pull requests](http://github.com/ant-design/ant-design-pro/pulls) para mejorar nuestro código. diff --git a/README.fr-FR.md b/README.fr-FR.md deleted file mode 100644 index 76c445a6..00000000 --- a/README.fr-FR.md +++ /dev/null @@ -1,125 +0,0 @@ -# Ant Design Pro - -Langue : 🇺🇸 | [🇨🇳](./README.zh-CN.md) | [🇷🇺](./README.ru-RU.md) | [🇹🇷](./README.tr-TR.md) | [🇯🇵](./README.ja-JP.md) | [🇫🇷](./README.fr-FR.md) | [🇧🇷](./README.pt-BR.md) | [🇩🇿](./README.ar-DZ.md) | [🇪🇸](./README.es-ES.md) - -

Ant Design Pro

- -
- -Une solution d'interface utilisateur prête à l'emploi pour les applications d'entreprise, basée sur React. - -[![CI](https://github.com/ant-design/ant-design-pro/actions/workflows/ci.yml/badge.svg)](https://github.com/ant-design/ant-design-pro/actions/workflows/ci.yml) -[![Preview Deploy](https://github.com/ant-design/ant-design-pro/actions/workflows/preview-deploy.yml/badge.svg)](https://github.com/ant-design/ant-design-pro/actions/workflows/preview-deploy.yml) -[![Build With Umi](https://img.shields.io/badge/build%20with-umi-028fe4.svg?style=flat-square)](http://umijs.org/) -[![Checked with Biome](https://img.shields.io/badge/Checked_with-Biome-60a5fa?style=flat&logo=biome)](https://biomejs.dev) -[![](https://badgen.net/badge/icon/Ant%20Design?icon=https://gw.alipayobjects.com/zos/antfincdn/Pp4WPgVDB3/KDpgvguMpGfqaHPjicRK.svg&label)](https://ant.design/) - -aperçu du thème clair -aperçu du thème sombre - -
- -- Aperçu : http://preview.pro.ant.design -- Page d'accueil : http://pro.ant.design -- Documentation : http://pro.ant.design/docs/getting-started -- Journal des modifications : http://pro.ant.design/docs/changelog -- FAQ : http://pro.ant.design/docs/faq - -## Fonctionnalités - -- :bulb: **TypeScript** : Un langage pour des applications JavaScript à grande échelle -- :scroll: **Blocs** : Construisez des pages avec des modèles de blocs -- :gem: **Design soigné** : Conforme à la [spécification Ant Design](http://ant.design/) -- :triangular_ruler: **Modèles courants** : Modèles typiques pour les applications d'entreprise -- :rocket: **Développement de pointe** : Stack de développement la plus récente avec React/umi/dva/antd -- :iphone: **Responsive** : Conçu pour différentes tailles d'écran -- :art: **Thématisation** : Thème personnalisable avec une configuration simple -- :globe_with_meridians: **Internationalisation** : Solution i18n intégrée -- :gear: **Bonnes pratiques** : Workflow solide pour garder votre code sain -- :1234: **Développement mock** : Solution de développement mock facile à utiliser -- :white_check_mark: **Tests UI** : Sécurité avec des tests unitaires et e2e - -## Modèles - -``` -- Tableau de bord - - Analytique - - Surveillance - - Espace de travail -- Formulaire - - Formulaire de base - - Formulaire par étapes - - Formulaire avancé -- Liste - - Tableau standard - - Liste standard - - Liste de cartes - - Liste de recherche (Projet/Applications/Article) -- Profil - - Profil simple - - Profil avancé -- Compte - - Centre de compte - - Paramètres du compte -- Résultat - - Succès - - Échec -- Exception - - 403 - - 404 - - 500 -- Utilisateur - - Connexion - - Inscription - - Résultat d'inscription -``` - -## Utilisation - -### Utiliser bash - -Nous fournissons pro-cli pour initialiser rapidement le projet. - -```bash -# utiliser npm -npm i @ant-design/pro-cli -g -pro create myapp -``` - -Choisissez le modèle pro. Simple est le modèle de base, qui ne fournit que le contenu de base pour le fonctionnement du framework. Complete contient tous les blocs, ce qui n'est pas adapté comme modèle de base pour un développement secondaire. - -```shell -? 🚀 Un projet complet ou un simple squelette ? (Utilisez les flèches) -➥ simple - complete -``` - -Initialisez le dépôt Git : - -```shell -$ git init myapp -``` - -Installez les dépendances : - -```shell -$ cd myapp && tyarn -// ou -$ cd myapp && npm install -``` - -## Navigateurs supportés - -Navigateurs modernes. - -| [Edge](http://godban.github.io/browsers-support-badges/)
Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | [Opera](http://godban.github.io/browsers-support-badges/)
Opera | -| --- | --- | --- | --- | --- | -| Edge | 2 dernières versions | 2 dernières versions | 2 dernières versions | 2 dernières versions | - -## Contribution - -Toute contribution est la bienvenue, voici quelques exemples de comment vous pouvez contribuer à ce projet : - -- Utilisez Ant Design Pro dans votre travail quotidien. -- Soumettez des [issues](http://github.com/ant-design/ant-design-pro/issues) pour signaler des bugs ou poser des questions. -- Proposez des [pull requests](http://github.com/ant-design/ant-design-pro/pulls) pour améliorer notre code. diff --git a/README.ja-JP.md b/README.ja-JP.md deleted file mode 100644 index 208d19ea..00000000 --- a/README.ja-JP.md +++ /dev/null @@ -1,125 +0,0 @@ -# Ant Design Pro - -言語: 🇺🇸 | [🇨🇳](./README.zh-CN.md) | [🇷🇺](./README.ru-RU.md) | [🇹🇷](./README.tr-TR.md) | [🇯🇵](./README.ja-JP.md) | [🇫🇷](./README.fr-FR.md) | [🇧🇷](./README.pt-BR.md) | [🇩🇿](./README.ar-DZ.md) | [🇪🇸](./README.es-ES.md) - -

Ant Design Pro

- -
- -エンタープライズアプリケーション向けの、Reactベースのすぐに使えるUIソリューション。 - -[![CI](https://github.com/ant-design/ant-design-pro/actions/workflows/ci.yml/badge.svg)](https://github.com/ant-design/ant-design-pro/actions/workflows/ci.yml) -[![Preview Deploy](https://github.com/ant-design/ant-design-pro/actions/workflows/preview-deploy.yml/badge.svg)](https://github.com/ant-design/ant-design-pro/actions/workflows/preview-deploy.yml) -[![Build With Umi](https://img.shields.io/badge/build%20with-umi-028fe4.svg?style=flat-square)](http://umijs.org/) -[![Checked with Biome](https://img.shields.io/badge/Checked_with-Biome-60a5fa?style=flat&logo=biome)](https://biomejs.dev) -[![](https://badgen.net/badge/icon/Ant%20Design?icon=https://gw.alipayobjects.com/zos/antfincdn/Pp4WPgVDB3/KDpgvguMpGfqaHPjicRK.svg&label)](https://ant.design/) - -ライトテーマのプレビュー -ダークテーマのプレビュー - -
- -- プレビュー: http://preview.pro.ant.design -- ホームページ: http://pro.ant.design -- ドキュメント: http://pro.ant.design/docs/getting-started -- 変更履歴: http://pro.ant.design/docs/changelog -- FAQ: http://pro.ant.design/docs/faq - -## 特徴 - -- :bulb: **TypeScript**: 大規模JavaScriptアプリケーション向けの言語 -- :scroll: **ブロック**: ブロックテンプレートでページを構築 -- :gem: **洗練されたデザイン**: [Ant Design仕様](http://ant.design/)に準拠 -- :triangular_ruler: **一般的なテンプレート**: 企業向けアプリケーションの典型的なテンプレート -- :rocket: **最新の開発環境**: React/umi/dva/antdの最新スタック -- :iphone: **レスポンシブ**: 様々な画面サイズに対応 -- :art: **テーマ**: シンプルな設定でカスタマイズ可能なテーマ -- :globe_with_meridians: **国際化**: 組み込みのi18nソリューション -- :gear: **ベストプラクティス**: 健全なコードを保つためのワークフロー -- :1234: **モック開発**: 使いやすいモック開発ソリューション -- :white_check_mark: **UIテスト**: ユニットテストとE2Eテストで安全に - -## テンプレート - -``` -- ダッシュボード - - 分析 - - モニター - - ワークスペース -- フォーム - - 基本フォーム - - ステップフォーム - - 高度なフォーム -- リスト - - 標準テーブル - - 標準リスト - - カードリスト - - 検索リスト(プロジェクト/アプリケーション/記事) -- プロフィール - - シンプルプロフィール - - 高度なプロフィール -- アカウント - - アカウントセンター - - アカウント設定 -- 結果 - - 成功 - - 失敗 -- 例外 - - 403 - - 404 - - 500 -- ユーザー - - ログイン - - 登録 - - 登録結果 -``` - -## 使い方 - -### bashを使う - -pro-cliを使って素早くプロジェクトを初期化できます。 - -```bash -# npmを使用 -npm i @ant-design/pro-cli -g -pro create myapp -``` - -proテンプレートを選択します。simpleは基本テンプレートで、フレームワークの基本的な内容のみを提供します。completeはすべてのブロックを含み、二次開発のベースとしては適していません。 - -```shell -? 🚀 フル機能かシンプルなスキャフォールドか?(矢印キーで選択) -➥ simple - complete -``` - -Gitリポジトリを初期化: - -```shell -$ git init myapp -``` - -依存関係をインストール: - -```shell -$ cd myapp && tyarn -// または -$ cd myapp && npm install -``` - -## 対応ブラウザ - -モダンブラウザ対応。 - -| [Edge](http://godban.github.io/browsers-support-badges/)
Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | [Opera](http://godban.github.io/browsers-support-badges/)
Opera | -| --- | --- | --- | --- | --- | -| Edge | 最新2バージョン | 最新2バージョン | 最新2バージョン | 最新2バージョン | - -## コントリビュート - -どんな形の貢献も歓迎します。以下はこのプロジェクトに貢献する例です: - -- 日常業務でAnt Design Proを使う -- [issues](http://github.com/ant-design/ant-design-pro/issues)でバグ報告や質問を投稿する -- [pull requests](http://github.com/ant-design/ant-design-pro/pulls)でコード改善を提案する diff --git a/README.md b/README.md index 0ceddc79..ba1c5941 100644 --- a/README.md +++ b/README.md @@ -74,40 +74,31 @@ An out-of-box UI solution for enterprise applications as a React boilerplate. ## Usage -### Use bash +### Get Started -We provide pro-cli to quickly initialize scaffolding. +Clone or download this repository to your local machine: ```bash -# use npm -npm i @ant-design/pro-cli -g -pro create myapp +git clone --depth=1 https://github.com/ant-design/ant-design-pro.git myapp +cd myapp ``` -Choose the pro template. Simple is the basic template, which only provides the basic content of the framework operation. Complete contains all blocks, which is not suitable for secondary development as a basic template. +### Installation -```shell -? 🚀 Full or a simple scaffold? (Use arrow keys) -❯ simple - complete +```bash +npm install ``` ### Development ```bash -# Install dependencies -npm install - # Start development server (full version by default) npm start - -# Build for production -npm run build ``` ### Simplify to Simple Version -If you want to simplify the project to a minimal version (removing extra blocks), run: +This project includes all blocks by default. If you need a minimal version, run: ```bash npm run simple @@ -121,18 +112,10 @@ This will: **Note**: This operation is irreversible and will permanently delete files. -Initialized Git repository: +### Build -```shell -$ git init myapp -``` - -Install dependencies: - -```shell -$ cd myapp && tyarn -// or -$ cd myapp && npm install +```bash +npm run build ``` ## Browsers support diff --git a/README.pt-BR.md b/README.pt-BR.md deleted file mode 100644 index 2041969a..00000000 --- a/README.pt-BR.md +++ /dev/null @@ -1,125 +0,0 @@ -# Ant Design Pro - -Idioma: 🇺🇸 | [🇨🇳](./README.zh-CN.md) | [🇷🇺](./README.ru-RU.md) | [🇹🇷](./README.tr-TR.md) | [🇯🇵](./README.ja-JP.md) | [🇫🇷](./README.fr-FR.md) | [🇧🇷](./README.pt-BR.md) | [🇩🇿](./README.ar-DZ.md) | [🇪🇸](./README.es-ES.md) - -

Ant Design Pro

- -
- -Uma solução de UI pronta para uso para aplicações empresariais baseada em React. - -[![CI](https://github.com/ant-design/ant-design-pro/actions/workflows/ci.yml/badge.svg)](https://github.com/ant-design/ant-design-pro/actions/workflows/ci.yml) -[![Preview Deploy](https://github.com/ant-design/ant-design-pro/actions/workflows/preview-deploy.yml/badge.svg)](https://github.com/ant-design/ant-design-pro/actions/workflows/preview-deploy.yml) -[![Build With Umi](https://img.shields.io/badge/build%20with-umi-028fe4.svg?style=flat-square)](http://umijs.org/) -[![Checked with Biome](https://img.shields.io/badge/Checked_with-Biome-60a5fa?style=flat&logo=biome)](https://biomejs.dev) -[![](https://badgen.net/badge/icon/Ant%20Design?icon=https://gw.alipayobjects.com/zos/antfincdn/Pp4WPgVDB3/KDpgvguMpGfqaHPjicRK.svg&label)](https://ant.design/) - -visualização do tema claro -visualização do tema escuro - -
- -- Visualizar: http://preview.pro.ant.design -- Página inicial: http://pro.ant.design -- Documentação: http://pro.ant.design/docs/getting-started -- Registro de alterações: http://pro.ant.design/docs/changelog -- FAQ: http://pro.ant.design/docs/faq - -## Funcionalidades - -- :bulb: **TypeScript**: Uma linguagem para aplicações JavaScript em larga escala -- :scroll: **Blocos**: Construa páginas com modelos de blocos -- :gem: **Design elegante**: Segue a [especificação do Ant Design](http://ant.design/) -- :triangular_ruler: **Modelos comuns**: Modelos típicos para aplicações empresariais -- :rocket: **Desenvolvimento de ponta**: Stack mais recente de React/umi/dva/antd -- :iphone: **Responsivo**: Projetado para diferentes tamanhos de tela -- :art: **Temas**: Tema personalizável com configuração simples -- :globe_with_meridians: **Internacionalização**: Solução i18n integrada -- :gear: **Boas práticas**: Workflow sólido para manter seu código saudável -- :1234: **Desenvolvimento mock**: Solução de mock fácil de usar -- :white_check_mark: **Teste de UI**: Segurança com testes unitários e e2e - -## Modelos - -``` -- Painel - - Analítico - - Monitoramento - - Espaço de trabalho -- Formulário - - Formulário básico - - Formulário em etapas - - Formulário avançado -- Lista - - Tabela padrão - - Lista padrão - - Lista de cartões - - Lista de busca (Projeto/Aplicações/Artigo) -- Perfil - - Perfil simples - - Perfil avançado -- Conta - - Central da conta - - Configurações da conta -- Resultado - - Sucesso - - Falha -- Exceção - - 403 - - 404 - - 500 -- Usuário - - Login - - Registro - - Resultado do registro -``` - -## Uso - -### Usando bash - -Fornecemos o pro-cli para inicializar rapidamente o projeto. - -```bash -# usar npm -npm i @ant-design/pro-cli -g -pro create myapp -``` - -Escolha o modelo pro. Simple é o modelo básico, que fornece apenas o conteúdo essencial para o funcionamento do framework. Complete contém todos os blocos, não sendo adequado como modelo base para desenvolvimento secundário. - -```shell -? 🚀 Projeto completo ou um esqueleto simples? (Use as setas) -➥ simple - complete -``` - -Inicialize o repositório Git: - -```shell -$ git init myapp -``` - -Instale as dependências: - -```shell -$ cd myapp && tyarn -// ou -$ cd myapp && npm install -``` - -## Navegadores suportados - -Navegadores modernos. - -| [Edge](http://godban.github.io/browsers-support-badges/)
Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | [Opera](http://godban.github.io/browsers-support-badges/)
Opera | -| --- | --- | --- | --- | --- | -| Edge | últimas 2 versões | últimas 2 versões | últimas 2 versões | últimas 2 versões | - -## Contribuindo - -Qualquer tipo de contribuição é bem-vinda. Aqui estão alguns exemplos de como você pode contribuir para este projeto: - -- Use o Ant Design Pro no seu trabalho diário. -- Envie [issues](http://github.com/ant-design/ant-design-pro/issues) para relatar bugs ou fazer perguntas. -- Proponha [pull requests](http://github.com/ant-design/ant-design-pro/pulls) para melhorar nosso código. diff --git a/README.ru-RU.md b/README.ru-RU.md deleted file mode 100644 index fbca4948..00000000 --- a/README.ru-RU.md +++ /dev/null @@ -1,125 +0,0 @@ -# Ant Design Pro - -Язык: 🇺🇸 | [🇨🇳](./README.zh-CN.md) | [🇷🇺](./README.ru-RU.md) | [🇹🇷](./README.tr-TR.md) | [🇯🇵](./README.ja-JP.md) | [🇫🇷](./README.fr-FR.md) | [🇧🇷](./README.pt-BR.md) | [🇩🇿](./README.ar-DZ.md) | [🇪🇸](./README.es-ES.md) - -

Ant Design Pro

- -
- -Готовое решение UI для корпоративных приложений на базе React. - -[![CI](https://github.com/ant-design/ant-design-pro/actions/workflows/ci.yml/badge.svg)](https://github.com/ant-design/ant-design-pro/actions/workflows/ci.yml) -[![Preview Deploy](https://github.com/ant-design/ant-design-pro/actions/workflows/preview-deploy.yml/badge.svg)](https://github.com/ant-design/ant-design-pro/actions/workflows/preview-deploy.yml) -[![Build With Umi](https://img.shields.io/badge/build%20with-umi-028fe4.svg?style=flat-square)](http://umijs.org/) -[![Checked with Biome](https://img.shields.io/badge/Checked_with-Biome-60a5fa?style=flat&logo=biome)](https://biomejs.dev) -[![](https://badgen.net/badge/icon/Ant%20Design?icon=https://gw.alipayobjects.com/zos/antfincdn/Pp4WPgVDB3/KDpgvguMpGfqaHPjicRK.svg&label)](https://ant.design/) - -светлая тема -тёмная тема - -
- -- Превью: http://preview.pro.ant.design -- Главная страница: http://pro.ant.design -- Документация: http://pro.ant.design/docs/getting-started -- Список изменений: http://pro.ant.design/docs/changelog -- FAQ: http://pro.ant.design/docs/faq - -## Возможности - -- :bulb: **TypeScript**: Язык для масштабируемых JavaScript-приложений -- :scroll: **Блоки**: Построение страниц с помощью шаблонов блоков -- :gem: **Элегантный дизайн**: Следует [спецификации Ant Design](http://ant.design/) -- :triangular_ruler: **Типовые шаблоны**: Типовые шаблоны для корпоративных приложений -- :rocket: **Современный стек**: Самые новые технологии React/umi/dva/antd -- :iphone: **Адаптивность**: Поддержка разных размеров экранов -- :art: **Темизация**: Кастомизация темы через простую конфигурацию -- :globe_with_meridians: **Интернационализация**: Встроенное решение i18n -- :gear: **Лучшие практики**: Надёжный workflow для поддержания качества кода -- :1234: **Мок-разработка**: Удобное решение для разработки с мок-данными -- :white_check_mark: **UI-тесты**: Безопасность с помощью unit и e2e тестов - -## Шаблоны - -``` -- Дашборд - - Аналитика - - Мониторинг - - Рабочее пространство -- Форма - - Базовая форма - - Многошаговая форма - - Продвинутая форма -- Список - - Стандартная таблица - - Стандартный список - - Список карточек - - Поисковый список (Проект/Приложения/Статья) -- Профиль - - Простой профиль - - Продвинутый профиль -- Аккаунт - - Центр аккаунта - - Настройки аккаунта -- Результат - - Успех - - Ошибка -- Исключения - - 403 - - 404 - - 500 -- Пользователь - - Вход - - Регистрация - - Результат регистрации -``` - -## Использование - -### Использование bash - -Мы предоставляем pro-cli для быстрой инициализации проекта. - -```bash -# использовать npm -npm i @ant-design/pro-cli -g -pro create myapp -``` - -Выберите шаблон pro. Simple — это базовый шаблон, который содержит только необходимый минимум для работы фреймворка. Complete включает все блоки и не подходит для вторичной разработки как базовый шаблон. - -```shell -? 🚀 Полный или простой шаблон? (Используйте стрелки) -➥ simple - complete -``` - -Инициализация репозитория Git: - -```shell -$ git init myapp -``` - -Установка зависимостей: - -```shell -$ cd myapp && tyarn -// или -$ cd myapp && npm install -``` - -## Поддержка браузеров - -Современные браузеры. - -| [Edge](http://godban.github.io/browsers-support-badges/)
Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | [Opera](http://godban.github.io/browsers-support-badges/)
Opera | -| --- | --- | --- | --- | --- | -| Edge | последние 2 версии | последние 2 версии | последние 2 версии | последние 2 версии | - -## Вклад - -Любой вклад приветствуется. Вот несколько способов, как вы можете помочь проекту: - -- Используйте Ant Design Pro в своей повседневной работе. -- Оставляйте [issues](http://github.com/ant-design/ant-design-pro/issues) для сообщений об ошибках или вопросов. -- Предлагайте [pull requests](http://github.com/ant-design/ant-design-pro/pulls) для улучшения кода. diff --git a/README.tr-TR.md b/README.tr-TR.md deleted file mode 100644 index 2cb2191e..00000000 --- a/README.tr-TR.md +++ /dev/null @@ -1,125 +0,0 @@ -# Ant Design Pro - -Dil: 🇺🇸 | [🇨🇳](./README.zh-CN.md) | [🇷🇺](./README.ru-RU.md) | [🇹🇷](./README.tr-TR.md) | [🇯🇵](./README.ja-JP.md) | [🇫🇷](./README.fr-FR.md) | [🇧🇷](./README.pt-BR.md) | [🇩🇿](./README.ar-DZ.md) | [🇪🇸](./README.es-ES.md) - -

Ant Design Pro

- -
- -React tabanlı kurumsal uygulamalar için kutudan çıkan bir UI çözümü. - -[![CI](https://github.com/ant-design/ant-design-pro/actions/workflows/ci.yml/badge.svg)](https://github.com/ant-design/ant-design-pro/actions/workflows/ci.yml) -[![Preview Deploy](https://github.com/ant-design/ant-design-pro/actions/workflows/preview-deploy.yml/badge.svg)](https://github.com/ant-design/ant-design-pro/actions/workflows/preview-deploy.yml) -[![Build With Umi](https://img.shields.io/badge/build%20with-umi-028fe4.svg?style=flat-square)](http://umijs.org/) -[![Checked with Biome](https://img.shields.io/badge/Checked_with-Biome-60a5fa?style=flat&logo=biome)](https://biomejs.dev) -[![](https://badgen.net/badge/icon/Ant%20Design?icon=https://gw.alipayobjects.com/zos/antfincdn/Pp4WPgVDB3/KDpgvguMpGfqaHPjicRK.svg&label)](https://ant.design/) - -açık tema önizlemesi -koyu tema önizlemesi - -
- -- Önizleme: http://preview.pro.ant.design -- Ana Sayfa: http://pro.ant.design -- Dokümantasyon: http://pro.ant.design/docs/getting-started -- Değişiklik Günlüğü: http://pro.ant.design/docs/changelog -- SSS: http://pro.ant.design/docs/faq - -## Özellikler - -- :bulb: **TypeScript**: Büyük ölçekli JavaScript uygulamaları için bir dil -- :scroll: **Bloklar**: Blok şablonlarıyla sayfa oluşturun -- :gem: **Şık Tasarım**: [Ant Design spesifikasyonuna](http://ant.design/) uygun -- :triangular_ruler: **Yaygın Şablonlar**: Kurumsal uygulamalar için tipik şablonlar -- :rocket: **En Yeni Geliştirme**: React/umi/dva/antd'nin en yeni geliştirme yığını -- :iphone: **Duyarlı**: Farklı ekran boyutları için tasarlandı -- :art: **Tema**: Basit yapılandırmayla özelleştirilebilir tema -- :globe_with_meridians: **Uluslararasılaştırma**: Dahili i18n çözümü -- :gear: **En İyi Uygulamalar**: Kodunuzu sağlıklı tutmak için sağlam iş akışı -- :1234: **Mock geliştirme**: Kullanımı kolay mock geliştirme çözümü -- :white_check_mark: **UI Testi**: Birim ve e2e testleriyle güvenli geliştirme - -## Şablonlar - -``` -- Gösterge Paneli - - Analitik - - İzleme - - Çalışma Alanı -- Form - - Temel Form - - Adım Adım Form - - Gelişmiş Form -- Liste - - Standart Tablo - - Standart Liste - - Kart Listesi - - Arama Listesi (Proje/Uygulamalar/Makale) -- Profil - - Basit Profil - - Gelişmiş Profil -- Hesap - - Hesap Merkezi - - Hesap Ayarları -- Sonuç - - Başarılı - - Başarısız -- İstisna - - 403 - - 404 - - 500 -- Kullanıcı - - Giriş - - Kayıt Ol - - Kayıt Sonucu -``` - -## Kullanım - -### Bash kullanımı - -Projeyi hızlıca başlatmak için pro-cli sağlıyoruz. - -```bash -# npm kullan -npm i @ant-design/pro-cli -g -pro create myapp -``` - -Pro şablonunu seçin. Simple, yalnızca temel framework içeriğini sağlayan temel şablondur. Complete, tüm blokları içerir ve ikincil geliştirme için temel şablon olarak uygun değildir. - -```shell -? 🚀 Tam veya basit bir iskelet mi? (Ok tuşlarını kullanın) -➥ simple - complete -``` - -Git deposunu başlatın: - -```shell -$ git init myapp -``` - -Bağımlılıkları yükleyin: - -```shell -$ cd myapp && tyarn -// veya -$ cd myapp && npm install -``` - -## Desteklenen Tarayıcılar - -Modern tarayıcılar. - -| [Edge](http://godban.github.io/browsers-support-badges/)
Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | [Opera](http://godban.github.io/browsers-support-badges/)
Opera | -| --- | --- | --- | --- | --- | -| Edge | son 2 sürüm | son 2 sürüm | son 2 sürüm | son 2 sürüm | - -## Katkı - -Her türlü katkı memnuniyetle karşılanır. Bu projeye katkıda bulunmanın bazı yolları şunlardır: - -- Ant Design Pro'yu günlük işinizde kullanın. -- Hataları bildirmek veya soru sormak için [issues](http://github.com/ant-design/ant-design-pro/issues) gönderin. -- Kodumuzu geliştirmek için [pull requests](http://github.com/ant-design/ant-design-pro/pulls) önerin. diff --git a/README.zh-CN.md b/README.zh-CN.md index 9cfd93e4..a06b71c3 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -77,28 +77,48 @@ Language : [🇺🇸](./README.md) | 🇨🇳 | [🇷🇺](./README.ru-RU.md) | ## 使用 -我们提供了 pro-cli 来快速的初始化脚手架。 +### 开始使用 + +克隆或下载本项目到本地: + +```bash +git clone --depth=1 https://github.com/ant-design/ant-design-pro.git myapp +cd myapp +``` + +### 安装依赖 + +```bash +npm install +``` + +### 开发 ```bash -# 使用 npm -npm i @ant-design/pro-cli -g -pro create myapp +# 启动开发服务器(默认为完整版) +npm start ``` -选择 pro 的模板,simple 是基础模板,只提供了框架运行的基本内容,complete 包含所有区块,不太适合当基础模板来进行二次开发。 +### 精简为简单版本 -```shell -? 🚀 要全量的还是一个简单的脚手架? (Use arrow keys) -❯ simple - complete +本项目默认包含所有区块。如果你需要一个最小化的版本,运行: + +```bash +npm run simple ``` -安装依赖: +这将会: +- 删除多余的页面目录(dashboard、form、list/*、profile、result、exception、account 等) +- 删除多余的 mock 文件 +- 替换路由为简单版本 +- 从 package.json 中移除多余的依赖 -```shell -$ cd myapp && tyarn -// 或 -$ cd myapp && npm install +**注意**:此操作不可逆,将永久删除文件。 + +### 构建 + +```bash +npm run build ``` 更多信息请参考 [使用文档](http://pro.ant.design/docs/getting-started)。 diff --git a/package.json b/package.json index 12dcbb76..e0703294 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,6 @@ "react-dom": "^19.2.4" }, "devDependencies": { - "@ant-design/pro-cli": "^3.3.0", "@commitlint/cli": "^20.1.0", "@commitlint/config-conventional": "^20.0.0", "@testing-library/dom": "^10.4.0", From a67eeea8b21d986d4a2ace85d1f2dcd874b17d00 Mon Sep 17 00:00:00 2001 From: afc163 Date: Thu, 5 Mar 2026 10:54:01 +0800 Subject: [PATCH 15/21] docs: update language links in README files Co-Authored-By: Claude Opus 4.6 --- README.md | 2 +- README.zh-CN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ba1c5941..0c47e18a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Language: 🇺🇸 | [🇨🇳](./README.zh-CN.md) | [🇷🇺](./README.ru-RU.md) | [🇹🇷](./README.tr-TR.md) | [🇯🇵](./README.ja-JP.md) | [🇫🇷](./README.fr-FR.md) | [🇵🇹](./README.pt-BR.md) | [🇸🇦](./README.ar-DZ.md) | [🇪🇸](./README.es-ES.md) +Language: 🇺🇸 | [🇨🇳](./README.zh-CN.md)

Ant Design Pro

diff --git a/README.zh-CN.md b/README.zh-CN.md index a06b71c3..8cc58499 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -1,4 +1,4 @@ -Language : [🇺🇸](./README.md) | 🇨🇳 | [🇷🇺](./README.ru-RU.md) | [🇹🇷](./README.tr-TR.md) | [🇯🇵](./README.ja-JP.md) | [🇫🇷](./README.fr-FR.md) | [🇵🇹](./README.pt-BR.md) | [🇸🇦](./README.ar-DZ.md) +Language : [🇺🇸](./README.md) | 🇨🇳

Ant Design Pro

From fa4db48a2a5193b7ce03b0f0ddc30bdc677d48a9 Mon Sep 17 00:00:00 2001 From: afc163 Date: Thu, 5 Mar 2026 11:09:42 +0800 Subject: [PATCH 16/21] refactor: remove pro-cli dependency and update initialization method - Remove create-umi config from package.json - Update i18n-remove script to use max instead of pro - Remove unused fetch-blocks locale keys from all language files - Update README.md and README.zh-CN.md with umi create instructions Co-Authored-By: Claude Opus 4.6 --- README.md | 13 ++++++++++++- README.zh-CN.md | 13 ++++++++++++- package.json | 31 +------------------------------ src/locales/bn-BD.ts | 3 --- src/locales/en-US.ts | 3 --- src/locales/fa-IR.ts | 3 --- src/locales/id-ID.ts | 3 --- src/locales/ja-JP.ts | 2 -- src/locales/zh-CN.ts | 2 -- 9 files changed, 25 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 0c47e18a..28f97bae 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,18 @@ An out-of-box UI solution for enterprise applications as a React boilerplate. ## Usage -### Get Started +### Get Started with Umi Create (Recommended) + +Create a new project using `umi create`: + +```bash +npx create-umi myapp +# Select "Ant Design Pro" template when prompted +cd myapp +npm install +``` + +### Or Clone Directly Clone or download this repository to your local machine: diff --git a/README.zh-CN.md b/README.zh-CN.md index 8cc58499..daa7457c 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -77,7 +77,18 @@ Language : [🇺🇸](./README.md) | 🇨🇳 ## 使用 -### 开始使用 +### 使用 Umi Create 创建项目(推荐) + +使用 `umi create` 创建新项目: + +```bash +npx create-umi myapp +# 选择 "Ant Design Pro" 模板 +cd myapp +npm install +``` + +### 或直接克隆 克隆或下载本项目到本地: diff --git a/package.json b/package.json index e0703294..35d59b58 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "deploy": "npm run build && npm run gh-pages", "dev": "npm run start:dev", "gh-pages": "gh-pages -d dist", - "i18n-remove": "pro i18n-remove --locale=zh-CN --write", + "i18n-remove": "max i18n-remove --locale=zh-CN --write", "postinstall": "max setup", "jest": "jest", "lint": "npm run biome:lint && npm run tsc", @@ -81,34 +81,5 @@ }, "engines": { "node": ">=20.0.0" - }, - "create-umi": { - "ignoreScript": [ - "docker*", - "functions*", - "site", - "generateMock" - ], - "ignoreDependencies": [ - "netlify*", - "serverless" - ], - "ignore": [ - ".dockerignore", - ".git", - ".github", - ".gitpod.yml", - "CODE_OF_CONDUCT.md", - "Dockerfile", - "Dockerfile.*", - "lambda", - "LICENSE", - "netlify.toml", - "README.*.md", - "azure-pipelines.yml", - "docker", - "CNAME", - "create-umi" - ] } } diff --git a/src/locales/bn-BD.ts b/src/locales/bn-BD.ts index 39207ef5..618cc783 100644 --- a/src/locales/bn-BD.ts +++ b/src/locales/bn-BD.ts @@ -12,9 +12,6 @@ export default { 'layout.user.link.privacy': 'গোপনীয়তা', 'layout.user.link.terms': 'শর্তাদি', 'app.preview.down.block': 'আপনার স্থানীয় প্রকল্পে এই পৃষ্ঠাটি ডাউনলোড করুন', - 'app.welcome.link.fetch-blocks': 'সমস্ত ব্লক পান', - 'app.welcome.link.block-list': - '`block` ডেভেলপমেন্ট এর উপর ভিত্তি করে দ্রুত স্ট্যান্ডার্ড, পৃষ্ঠাসমূহ তৈরি করুন।', ...globalHeader, ...menu, ...settingDrawer, diff --git a/src/locales/en-US.ts b/src/locales/en-US.ts index 93276ed7..09f0ef0e 100644 --- a/src/locales/en-US.ts +++ b/src/locales/en-US.ts @@ -12,9 +12,6 @@ export default { 'layout.user.link.privacy': 'Privacy', 'layout.user.link.terms': 'Terms', 'app.preview.down.block': 'Download this page to your local project', - 'app.welcome.link.fetch-blocks': 'Get all block', - 'app.welcome.link.block-list': - 'Quickly build standard, pages based on `block` development', ...globalHeader, ...menu, ...settingDrawer, diff --git a/src/locales/fa-IR.ts b/src/locales/fa-IR.ts index 123ba655..f743db30 100644 --- a/src/locales/fa-IR.ts +++ b/src/locales/fa-IR.ts @@ -12,9 +12,6 @@ export default { 'layout.user.link.privacy': 'حریم خصوصی', 'layout.user.link.terms': 'مقررات', 'app.preview.down.block': 'این صفحه را در پروژه محلی خود بارگیری کنید', - 'app.welcome.link.fetch-blocks': 'دریافت تمام بلوک', - 'app.welcome.link.block-list': - 'به سرعت صفحات استاندارد مبتنی بر توسعه "بلوک" را بسازید', ...globalHeader, ...menu, ...settingDrawer, diff --git a/src/locales/id-ID.ts b/src/locales/id-ID.ts index aecd2bdc..ae9a39f3 100644 --- a/src/locales/id-ID.ts +++ b/src/locales/id-ID.ts @@ -12,9 +12,6 @@ export default { 'layout.user.link.privacy': 'Privasi', 'layout.user.link.terms': 'Ketentuan', 'app.preview.down.block': 'Unduh halaman ini dalam projek lokal anda', - 'app.welcome.link.fetch-blocks': 'Dapatkan semua blok', - 'app.welcome.link.block-list': - 'Buat standar dengan cepat, halaman-halaman berdasarkan pengembangan `block`', ...globalHeader, ...menu, ...settingDrawer, diff --git a/src/locales/ja-JP.ts b/src/locales/ja-JP.ts index b2b8a1d4..f0d7eb79 100644 --- a/src/locales/ja-JP.ts +++ b/src/locales/ja-JP.ts @@ -13,8 +13,6 @@ export default { 'layout.user.link.terms': '利用規約', 'app.preview.down.block': 'このページをローカルプロジェクトにダウンロードしてください', - 'app.welcome.link.fetch-blocks': '', - 'app.welcome.link.block-list': '', ...globalHeader, ...menu, ...settingDrawer, diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts index 28c5d410..ce2ccd18 100644 --- a/src/locales/zh-CN.ts +++ b/src/locales/zh-CN.ts @@ -12,8 +12,6 @@ export default { 'layout.user.link.privacy': '隐私', 'layout.user.link.terms': '条款', 'app.preview.down.block': '下载此页面到本地项目', - 'app.welcome.link.fetch-blocks': '获取全部区块', - 'app.welcome.link.block-list': '基于 block 开发,快速构建标准页面', ...pages, ...globalHeader, ...menu, From 35897cd7d2d6470909e89c82ace73b0ff68d29bc Mon Sep 17 00:00:00 2001 From: afc163 Date: Thu, 5 Mar 2026 11:14:44 +0800 Subject: [PATCH 17/21] docs: remove create-umi instructions, use git clone directly Co-Authored-By: Claude Opus 4.6 --- README.md | 13 +------------ README.zh-CN.md | 13 +------------ 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 28f97bae..0c47e18a 100644 --- a/README.md +++ b/README.md @@ -74,18 +74,7 @@ An out-of-box UI solution for enterprise applications as a React boilerplate. ## Usage -### Get Started with Umi Create (Recommended) - -Create a new project using `umi create`: - -```bash -npx create-umi myapp -# Select "Ant Design Pro" template when prompted -cd myapp -npm install -``` - -### Or Clone Directly +### Get Started Clone or download this repository to your local machine: diff --git a/README.zh-CN.md b/README.zh-CN.md index daa7457c..8cc58499 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -77,18 +77,7 @@ Language : [🇺🇸](./README.md) | 🇨🇳 ## 使用 -### 使用 Umi Create 创建项目(推荐) - -使用 `umi create` 创建新项目: - -```bash -npx create-umi myapp -# 选择 "Ant Design Pro" 模板 -cd myapp -npm install -``` - -### 或直接克隆 +### 开始使用 克隆或下载本项目到本地: From 3a3b5a0c7c453b9d6ee7bf679a6110182c2c6d1c Mon Sep 17 00:00:00 2001 From: afc163 Date: Thu, 5 Mar 2026 11:38:26 +0800 Subject: [PATCH 18/21] chore: remove unused files - Remove src/services/swagger (unused API services) - Remove src/pages/list/table-list (routing points to different path) - Remove src/pages/form/step-form/service.ts (pure frontend form) - Remove src/pages/form/advanced-form/components/TableForm.tsx - Remove src/pages/account/settings/components/PhoneView.tsx - Remove src/pages/dashboard/analysis/components/Charts/MiniProgress - Remove WaterWave and autoHeight components (unused) Co-Authored-By: Claude Opus 4.6 --- .../account/settings/components/PhoneView.tsx | 39 --- .../components/Charts/MiniProgress/index.tsx | 48 ---- .../components/Charts/WaterWave/index.tsx | 215 -------------- .../components/Charts/WaterWave/index.tsx | 215 -------------- .../monitor/components/Charts/autoHeight.tsx | 69 ----- .../advanced-form/components/TableForm.tsx | 268 ------------------ src/pages/form/step-form/service.ts | 8 - src/pages/list/table-list/data.d.ts | 14 - src/pages/list/table-list/service.ts | 63 ---- src/services/swagger/index.ts | 12 - src/services/swagger/pet.ts | 153 ---------- src/services/swagger/store.ts | 48 ---- src/services/swagger/typings.d.ts | 112 -------- src/services/swagger/user.ts | 100 ------- 14 files changed, 1364 deletions(-) delete mode 100644 src/pages/account/settings/components/PhoneView.tsx delete mode 100644 src/pages/dashboard/analysis/components/Charts/MiniProgress/index.tsx delete mode 100644 src/pages/dashboard/analysis/components/Charts/WaterWave/index.tsx delete mode 100644 src/pages/dashboard/monitor/components/Charts/WaterWave/index.tsx delete mode 100644 src/pages/dashboard/monitor/components/Charts/autoHeight.tsx delete mode 100644 src/pages/form/advanced-form/components/TableForm.tsx delete mode 100644 src/pages/form/step-form/service.ts delete mode 100644 src/pages/list/table-list/data.d.ts delete mode 100644 src/pages/list/table-list/service.ts delete mode 100644 src/services/swagger/index.ts delete mode 100644 src/services/swagger/pet.ts delete mode 100644 src/services/swagger/store.ts delete mode 100644 src/services/swagger/typings.d.ts delete mode 100644 src/services/swagger/user.ts diff --git a/src/pages/account/settings/components/PhoneView.tsx b/src/pages/account/settings/components/PhoneView.tsx deleted file mode 100644 index 84ea4787..00000000 --- a/src/pages/account/settings/components/PhoneView.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Input } from 'antd'; -import React from 'react'; -import useStyles from './index.style'; - -type PhoneViewProps = { - value?: string; - onChange?: (value: string) => void; -}; -const PhoneView: React.FC = (props) => { - const { styles } = useStyles(); - const { value, onChange } = props; - let values = ['', '']; - if (value) { - values = value.split('-'); - } - return ( - <> - { - if (onChange) { - onChange(`${e.target.value}-${values[1]}`); - } - }} - /> - { - if (onChange) { - onChange(`${values[0]}-${e.target.value}`); - } - }} - value={values[1]} - /> - - ); -}; -export default PhoneView; diff --git a/src/pages/dashboard/analysis/components/Charts/MiniProgress/index.tsx b/src/pages/dashboard/analysis/components/Charts/MiniProgress/index.tsx deleted file mode 100644 index 5376e01c..00000000 --- a/src/pages/dashboard/analysis/components/Charts/MiniProgress/index.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { Tooltip } from 'antd'; -import React from 'react'; -export type MiniProgressProps = { - target: number; - targetLabel?: string; - color?: string; - size?: number; - percent?: number; - style?: React.CSSProperties; -}; -const MiniProgress: React.FC = ({ - targetLabel, - target, - color = 'rgb(19, 194, 194)', - size, - percent, -}) => { - return ( -
- -
- - -
-
-
-
- ); -}; -export default MiniProgress; diff --git a/src/pages/dashboard/analysis/components/Charts/WaterWave/index.tsx b/src/pages/dashboard/analysis/components/Charts/WaterWave/index.tsx deleted file mode 100644 index b75f723d..00000000 --- a/src/pages/dashboard/analysis/components/Charts/WaterWave/index.tsx +++ /dev/null @@ -1,215 +0,0 @@ -import { useEffect, useRef, useState } from 'react'; -import autoHeight from '../../../../monitor/components/Charts/autoHeight'; - -/* eslint no-return-assign: 0 */ -/* eslint no-mixed-operators: 0 */ -// riddle: https://riddle.alibaba-inc.com/riddles/2d9a4b90 - -export type WaterWaveProps = { - title: React.ReactNode; - color?: string; - height?: number; - percent: number; - style?: React.CSSProperties; -}; - -const WaterWave: React.FC = ({ - title, - color = '#1890FF', - height = 1, - percent, -}) => { - const [radio, setRadio] = useState(1); - const timerRef = useRef(0); - const rootRef = useRef(null); - const nodeRef = useRef(null); - - const renderChart = (type?: string) => { - const data = percent / 100; - cancelAnimationFrame(timerRef.current); - if (!nodeRef.current || (data !== 0 && !data)) { - return; - } - const canvas = nodeRef.current; - const ctx = canvas.getContext('2d'); - if (!ctx) { - return; - } - const canvasWidth = canvas.width; - const canvasHeight = canvas.height; - const radius = canvasWidth / 2; - const lineWidth = 2; - const cR = radius - lineWidth; - ctx.beginPath(); - ctx.lineWidth = lineWidth * 2; - const axisLength = canvasWidth - lineWidth; - const unit = axisLength / 8; - const range = 0.2; // 振幅 - let currRange = range; - const xOffset = lineWidth; - let sp = 0; // 周期偏移量 - let currData = 0; - const waveupsp = 0.005; // 水波上涨速度 - - let arcStack: number[][] = []; - const bR = radius - lineWidth; - const circleOffset = -(Math.PI / 2); - let circleLock = true; - for ( - let i = circleOffset; - i < circleOffset + 2 * Math.PI; - i += 1 / (8 * Math.PI) - ) { - arcStack.push([radius + bR * Math.cos(i), radius + bR * Math.sin(i)]); - } - const cStartPoint = arcStack.shift() as number[]; - ctx.strokeStyle = color; - ctx.moveTo(cStartPoint[0], cStartPoint[1]); - const drawSin = () => { - if (!ctx) { - return; - } - ctx.beginPath(); - ctx.save(); - const sinStack = []; - for (let i = xOffset; i <= xOffset + axisLength; i += 20 / axisLength) { - const x = sp + (xOffset + i) / unit; - const y = Math.sin(x) * currRange; - const dx = i; - const dy = 2 * cR * (1 - currData) + (radius - cR) - unit * y; - ctx.lineTo(dx, dy); - sinStack.push([dx, dy]); - } - const startPoint = sinStack.shift() as number[]; - ctx.lineTo(xOffset + axisLength, canvasHeight); - ctx.lineTo(xOffset, canvasHeight); - ctx.lineTo(startPoint[0], startPoint[1]); - const gradient = ctx.createLinearGradient(0, 0, 0, canvasHeight); - gradient.addColorStop(0, '#ffffff'); - gradient.addColorStop(1, color); - ctx.fillStyle = gradient; - ctx.fill(); - ctx.restore(); - }; - const render = () => { - if (!ctx) { - return; - } - ctx.clearRect(0, 0, canvasWidth, canvasHeight); - if (circleLock && type !== 'update') { - if (arcStack.length) { - const temp = arcStack.shift() as number[]; - ctx.lineTo(temp[0], temp[1]); - ctx.stroke(); - } else { - circleLock = false; - ctx.lineTo(cStartPoint[0], cStartPoint[1]); - ctx.stroke(); - arcStack = []; - ctx.globalCompositeOperation = 'destination-over'; - ctx.beginPath(); - ctx.lineWidth = lineWidth; - ctx.arc(radius, radius, bR, 0, 2 * Math.PI, true); - ctx.beginPath(); - ctx.save(); - ctx.arc(radius, radius, radius - 3 * lineWidth, 0, 2 * Math.PI, true); - ctx.restore(); - ctx.clip(); - ctx.fillStyle = color; - } - } else { - if (data >= 0.85) { - if (currRange > range / 4) { - const t = range * 0.01; - currRange -= t; - } - } else if (data <= 0.1) { - if (currRange < range * 1.5) { - const t = range * 0.01; - currRange += t; - } - } else { - if (currRange <= range) { - const t = range * 0.01; - currRange += t; - } - if (currRange >= range) { - const t = range * 0.01; - currRange -= t; - } - } - if (data - currData > 0) { - currData += waveupsp; - } - if (data - currData < 0) { - currData -= waveupsp; - } - sp += 0.07; - drawSin(); - } - timerRef.current = requestAnimationFrame(render); - }; - render(); - }; - - const resize = () => { - if (rootRef.current) { - const { offsetWidth } = rootRef.current.parentNode as HTMLElement; - setRadio(offsetWidth < height ? offsetWidth / height : 1); - } - }; - - useEffect(() => { - renderChart(); - resize(); - const handleResize = () => { - requestAnimationFrame(resize); - }; - window.addEventListener('resize', handleResize, { passive: true }); - - return () => { - window.removeEventListener('resize', handleResize); - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - useEffect(() => { - renderChart('update'); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [percent]); - - useEffect(() => { - return () => { - cancelAnimationFrame(timerRef.current); - }; - }, []); - - return ( -
-
- -
-
- {title && {title}} -

{percent}%

-
-
- ); -}; - -export default autoHeight()(WaterWave); diff --git a/src/pages/dashboard/monitor/components/Charts/WaterWave/index.tsx b/src/pages/dashboard/monitor/components/Charts/WaterWave/index.tsx deleted file mode 100644 index 81f76dcb..00000000 --- a/src/pages/dashboard/monitor/components/Charts/WaterWave/index.tsx +++ /dev/null @@ -1,215 +0,0 @@ -import { useEffect, useRef, useState } from 'react'; -import autoHeight from '../autoHeight'; - -/* eslint no-return-assign: 0 */ -/* eslint no-mixed-operators: 0 */ -// riddle: https://riddle.alibaba-inc.com/riddles/2d9a4b90 - -export type WaterWaveProps = { - title: React.ReactNode; - color?: string; - height?: number; - percent: number; - style?: React.CSSProperties; -}; - -const WaterWave: React.FC = ({ - title, - color = '#1890FF', - height = 1, - percent, -}) => { - const [radio, setRadio] = useState(1); - const timerRef = useRef(0); - const rootRef = useRef(null); - const nodeRef = useRef(null); - - const renderChart = (type?: string) => { - const data = percent / 100; - cancelAnimationFrame(timerRef.current); - if (!nodeRef.current || (data !== 0 && !data)) { - return; - } - const canvas = nodeRef.current; - const ctx = canvas.getContext('2d'); - if (!ctx) { - return; - } - const canvasWidth = canvas.width; - const canvasHeight = canvas.height; - const radius = canvasWidth / 2; - const lineWidth = 2; - const cR = radius - lineWidth; - ctx.beginPath(); - ctx.lineWidth = lineWidth * 2; - const axisLength = canvasWidth - lineWidth; - const unit = axisLength / 8; - const range = 0.2; // 振幅 - let currRange = range; - const xOffset = lineWidth; - let sp = 0; // 周期偏移量 - let currData = 0; - const waveupsp = 0.005; // 水波上涨速度 - - let arcStack: number[][] = []; - const bR = radius - lineWidth; - const circleOffset = -(Math.PI / 2); - let circleLock = true; - for ( - let i = circleOffset; - i < circleOffset + 2 * Math.PI; - i += 1 / (8 * Math.PI) - ) { - arcStack.push([radius + bR * Math.cos(i), radius + bR * Math.sin(i)]); - } - const cStartPoint = arcStack.shift() as number[]; - ctx.strokeStyle = color; - ctx.moveTo(cStartPoint[0], cStartPoint[1]); - const drawSin = () => { - if (!ctx) { - return; - } - ctx.beginPath(); - ctx.save(); - const sinStack = []; - for (let i = xOffset; i <= xOffset + axisLength; i += 20 / axisLength) { - const x = sp + (xOffset + i) / unit; - const y = Math.sin(x) * currRange; - const dx = i; - const dy = 2 * cR * (1 - currData) + (radius - cR) - unit * y; - ctx.lineTo(dx, dy); - sinStack.push([dx, dy]); - } - const startPoint = sinStack.shift() as number[]; - ctx.lineTo(xOffset + axisLength, canvasHeight); - ctx.lineTo(xOffset, canvasHeight); - ctx.lineTo(startPoint[0], startPoint[1]); - const gradient = ctx.createLinearGradient(0, 0, 0, canvasHeight); - gradient.addColorStop(0, '#ffffff'); - gradient.addColorStop(1, color); - ctx.fillStyle = gradient; - ctx.fill(); - ctx.restore(); - }; - const render = () => { - if (!ctx) { - return; - } - ctx.clearRect(0, 0, canvasWidth, canvasHeight); - if (circleLock && type !== 'update') { - if (arcStack.length) { - const temp = arcStack.shift() as number[]; - ctx.lineTo(temp[0], temp[1]); - ctx.stroke(); - } else { - circleLock = false; - ctx.lineTo(cStartPoint[0], cStartPoint[1]); - ctx.stroke(); - arcStack = []; - ctx.globalCompositeOperation = 'destination-over'; - ctx.beginPath(); - ctx.lineWidth = lineWidth; - ctx.arc(radius, radius, bR, 0, 2 * Math.PI, true); - ctx.beginPath(); - ctx.save(); - ctx.arc(radius, radius, radius - 3 * lineWidth, 0, 2 * Math.PI, true); - ctx.restore(); - ctx.clip(); - ctx.fillStyle = color; - } - } else { - if (data >= 0.85) { - if (currRange > range / 4) { - const t = range * 0.01; - currRange -= t; - } - } else if (data <= 0.1) { - if (currRange < range * 1.5) { - const t = range * 0.01; - currRange += t; - } - } else { - if (currRange <= range) { - const t = range * 0.01; - currRange += t; - } - if (currRange >= range) { - const t = range * 0.01; - currRange -= t; - } - } - if (data - currData > 0) { - currData += waveupsp; - } - if (data - currData < 0) { - currData -= waveupsp; - } - sp += 0.07; - drawSin(); - } - timerRef.current = requestAnimationFrame(render); - }; - render(); - }; - - const resize = () => { - if (rootRef.current) { - const { offsetWidth } = rootRef.current.parentNode as HTMLElement; - setRadio(offsetWidth < height ? offsetWidth / height : 1); - } - }; - - useEffect(() => { - renderChart(); - resize(); - const handleResize = () => { - requestAnimationFrame(resize); - }; - window.addEventListener('resize', handleResize, { passive: true }); - - return () => { - window.removeEventListener('resize', handleResize); - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - useEffect(() => { - renderChart('update'); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [percent]); - - useEffect(() => { - return () => { - cancelAnimationFrame(timerRef.current); - }; - }, []); - - return ( -
-
- -
-
- {title && {title}} -

{percent}%

-
-
- ); -}; - -export default autoHeight()(WaterWave); diff --git a/src/pages/dashboard/monitor/components/Charts/autoHeight.tsx b/src/pages/dashboard/monitor/components/Charts/autoHeight.tsx deleted file mode 100644 index 9c9fa3c4..00000000 --- a/src/pages/dashboard/monitor/components/Charts/autoHeight.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react'; - -export type IReactComponent

= React.ComponentClass

| React.FC

; - -function computeHeight(node: HTMLDivElement) { - const { style } = node; - style.height = '100%'; - const totalHeight = parseInt(`${getComputedStyle(node).height}`, 10); - const padding = - parseInt(`${getComputedStyle(node).paddingTop}`, 10) + - parseInt(`${getComputedStyle(node).paddingBottom}`, 10); - return totalHeight - padding; -} - -function getAutoHeight(n: HTMLDivElement) { - if (!n) { - return 0; - } - - const node = n; - - let height = computeHeight(node); - const parentNode = node.parentNode as HTMLDivElement; - if (parentNode) { - height = computeHeight(parentNode); - } - - return height; -} - -type AutoHeightProps = { - height?: number; -}; - -function autoHeight() { - return

( - WrappedComponent: React.ComponentClass

| React.FC

, - ): React.FC

=> { - const AutoHeightComponent: React.FC

= (props) => { - const [computedHeight, setComputedHeight] = useState(0); - const rootRef = useRef(null); - - useEffect(() => { - const { height } = props; - if (!height && rootRef.current) { - let h = getAutoHeight(rootRef.current); - setComputedHeight(h); - if (h < 1) { - h = getAutoHeight(rootRef.current); - setComputedHeight(h); - } - } - }, [props]); - - const { height } = props; - const h = height || computedHeight; - - return ( -

- {h > 0 && } -
- ); - }; - - return AutoHeightComponent; - }; -} - -export default autoHeight; diff --git a/src/pages/form/advanced-form/components/TableForm.tsx b/src/pages/form/advanced-form/components/TableForm.tsx deleted file mode 100644 index e42f0fe9..00000000 --- a/src/pages/form/advanced-form/components/TableForm.tsx +++ /dev/null @@ -1,268 +0,0 @@ -import { PlusOutlined } from '@ant-design/icons'; -import { Button, Divider, Input, message, Popconfirm, Table } from 'antd'; -import type { FC } from 'react'; -import React, { useState } from 'react'; -import useStyles from '../style.style'; - -type TableFormDateType = { - key: string; - workId?: string; - name?: string; - department?: string; - isNew?: boolean; - editable?: boolean; -}; -type TableFormProps = { - value?: TableFormDateType[]; - onChange?: (value: TableFormDateType[]) => void; -}; -const TableForm: FC = ({ value, onChange }) => { - const { styles } = useStyles(); - const [clickedCancel, setClickedCancel] = useState(false); - const [loading, setLoading] = useState(false); - const [index, setIndex] = useState(0); - const [cacheOriginData, setCacheOriginData] = useState>( - {}, - ); - const [data, setData] = useState(value); - const getRowByKey = (key: string, newData?: TableFormDateType[]) => - (newData || data)?.filter((item) => item.key === key)[0]; - const toggleEditable = ( - e: React.MouseEvent | React.KeyboardEvent, - key: string, - ) => { - e.preventDefault(); - const newData = data?.map((item) => ({ - ...item, - })); - const target = getRowByKey(key, newData); - if (target) { - // 进入编辑状态时保存原始数据 - if (!target.editable) { - cacheOriginData[key] = { - ...target, - }; - setCacheOriginData(cacheOriginData); - } - target.editable = !target.editable; - setData(newData); - } - }; - const newMember = () => { - const newData = - data?.map((item) => ({ - ...item, - })) || []; - newData.push({ - key: `NEW_TEMP_ID_${index}`, - workId: '', - name: '', - department: '', - editable: true, - isNew: true, - }); - setIndex(index + 1); - setData(newData); - }; - const remove = (key: string) => { - const newData = data?.filter( - (item) => item.key !== key, - ) as TableFormDateType[]; - setData(newData); - if (onChange) { - onChange(newData); - } - }; - const handleFieldChange = ( - e: React.ChangeEvent, - fieldName: keyof TableFormDateType, - key: string, - ) => { - const newData = [...(data as TableFormDateType[])]; - const target = getRowByKey(key, newData); - if (target?.[fieldName]) { - target[fieldName as 'key'] = e.target.value; - setData(newData); - } - }; - const saveRow = (e: React.MouseEvent | React.KeyboardEvent, key: string) => { - e.persist(); - setLoading(true); - setTimeout(() => { - if (clickedCancel) { - setClickedCancel(false); - return; - } - const target = getRowByKey(key) || ({} as any); - if (!target.workId || !target.name || !target.department) { - message.error('请填写完整成员信息。'); - (e.target as HTMLInputElement).focus(); - setLoading(false); - return; - } - delete target.isNew; - toggleEditable(e, key); - if (onChange) { - onChange(data as TableFormDateType[]); - } - setLoading(false); - }, 500); - }; - const handleKeyPress = (e: React.KeyboardEvent, key: string) => { - if (e.key === 'Enter') { - saveRow(e, key); - } - }; - const cancel = (e: React.MouseEvent, key: string) => { - setClickedCancel(true); - e.preventDefault(); - const newData = [...(data as TableFormDateType[])]; - // 编辑前的原始数据 - let cacheData = []; - cacheData = newData.map((item) => { - if (item.key === key) { - if (cacheOriginData[key]) { - const originItem = { - ...item, - ...cacheOriginData[key], - editable: false, - }; - delete cacheOriginData[key]; - setCacheOriginData(cacheOriginData); - return originItem; - } - } - return item; - }); - setData(cacheData); - setClickedCancel(false); - }; - const columns = [ - { - title: '成员姓名', - dataIndex: 'name', - key: 'name', - width: '20%', - render: (text: string, record: TableFormDateType) => { - if (record.editable) { - return ( - handleFieldChange(e, 'name', record.key)} - onKeyPress={(e) => handleKeyPress(e, record.key)} - placeholder="成员姓名" - /> - ); - } - return text; - }, - }, - { - title: '工号', - dataIndex: 'workId', - key: 'workId', - width: '20%', - render: (text: string, record: TableFormDateType) => { - if (record.editable) { - return ( - handleFieldChange(e, 'workId', record.key)} - onKeyPress={(e) => handleKeyPress(e, record.key)} - placeholder="工号" - /> - ); - } - return text; - }, - }, - { - title: '所属部门', - dataIndex: 'department', - key: 'department', - width: '40%', - render: (text: string, record: TableFormDateType) => { - if (record.editable) { - return ( - handleFieldChange(e, 'department', record.key)} - onKeyPress={(e) => handleKeyPress(e, record.key)} - placeholder="所属部门" - /> - ); - } - return text; - }, - }, - { - title: '操作', - key: 'action', - render: (_text: string, record: TableFormDateType) => { - if (!!record.editable && loading) { - return null; - } - if (record.editable) { - if (record.isNew) { - return ( - - saveRow(e, record.key)}>添加 - - remove(record.key)} - > - 删除 - - - ); - } - return ( - - saveRow(e, record.key)}>保存 - - cancel(e, record.key)}>取消 - - ); - } - return ( - - toggleEditable(e, record.key)}>编辑 - - remove(record.key)} - > - 删除 - - - ); - }, - }, - ]; - return ( - <> - - loading={loading} - columns={columns} - dataSource={data} - pagination={false} - rowClassName={(record) => (record.editable ? styles.editable : '')} - /> - - - ); -}; -export default TableForm; diff --git a/src/pages/form/step-form/service.ts b/src/pages/form/step-form/service.ts deleted file mode 100644 index 5834a574..00000000 --- a/src/pages/form/step-form/service.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { request } from '@umijs/max'; - -export async function fakeSubmitForm(params: any) { - return request('/api/stepForm', { - method: 'POST', - data: params, - }); -} diff --git a/src/pages/list/table-list/data.d.ts b/src/pages/list/table-list/data.d.ts deleted file mode 100644 index 209056e6..00000000 --- a/src/pages/list/table-list/data.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -export type TableListItem = { - key: number; - disabled?: boolean; - href: string; - avatar: string; - name: string; - owner: string; - desc: string; - callNo: number; - status: 0 | 1 | 2 | 3; - updatedAt: string; - createdAt: string; - progress: number; -}; diff --git a/src/pages/list/table-list/service.ts b/src/pages/list/table-list/service.ts deleted file mode 100644 index 046cdcb4..00000000 --- a/src/pages/list/table-list/service.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { request } from '@umijs/max'; -import type { TableListItem } from './data'; - -/** 获取规则列表 GET /api/rule */ -export async function rule( - params: { - // query - /** 当前的页码 */ - current?: number; - /** 页面的容量 */ - pageSize?: number; - }, - options?: { [key: string]: any }, -) { - return request<{ - data: TableListItem[]; - /** 列表的内容总数 */ - total?: number; - success?: boolean; - }>('/api/rule', { - method: 'GET', - params: { - ...params, - }, - ...(options || {}), - }); -} - -/** 新建规则 PUT /api/rule */ -export async function updateRule( - data: { [key: string]: any }, - options?: { [key: string]: any }, -) { - return request('/api/rule', { - data, - method: 'PUT', - ...(options || {}), - }); -} - -/** 新建规则 POST /api/rule */ -export async function addRule( - data: { [key: string]: any }, - options?: { [key: string]: any }, -) { - return request('/api/rule', { - data, - method: 'POST', - ...(options || {}), - }); -} - -/** 删除规则 DELETE /api/rule */ -export async function removeRule( - data: { key: number[] }, - options?: { [key: string]: any }, -) { - return request>('/api/rule', { - data, - method: 'DELETE', - ...(options || {}), - }); -} diff --git a/src/services/swagger/index.ts b/src/services/swagger/index.ts deleted file mode 100644 index 83cf97ca..00000000 --- a/src/services/swagger/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-ignore -/* eslint-disable */ -// API 更新时间: -// API 唯一标识: -import * as pet from './pet'; -import * as store from './store'; -import * as user from './user'; -export default { - pet, - store, - user, -}; diff --git a/src/services/swagger/pet.ts b/src/services/swagger/pet.ts deleted file mode 100644 index b887475a..00000000 --- a/src/services/swagger/pet.ts +++ /dev/null @@ -1,153 +0,0 @@ -// @ts-ignore -/* eslint-disable */ -import { request } from '@umijs/max'; - -/** Update an existing pet PUT /pet */ -export async function updatePet(body: API.Pet, options?: { [key: string]: any }) { - return request('/pet', { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - }, - data: body, - ...(options || {}), - }); -} - -/** Add a new pet to the store POST /pet */ -export async function addPet(body: API.Pet, options?: { [key: string]: any }) { - return request('/pet', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - data: body, - ...(options || {}), - }); -} - -/** Find pet by ID Returns a single pet GET /pet/${param0} */ -export async function getPetById( - // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) - params: API.getPetByIdParams, - options?: { [key: string]: any }, -) { - const { petId: param0, ...queryParams } = params; - return request(`/pet/${param0}`, { - method: 'GET', - params: { ...queryParams }, - ...(options || {}), - }); -} - -/** Updates a pet in the store with form data POST /pet/${param0} */ -export async function updatePetWithForm( - // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) - params: API.updatePetWithFormParams, - body: { name?: string; status?: string }, - options?: { [key: string]: any }, -) { - const { petId: param0, ...queryParams } = params; - const formData = new FormData(); - - Object.keys(body).forEach((ele) => { - const item = (body as any)[ele]; - - if (item !== undefined && item !== null) { - formData.append( - ele, - typeof item === 'object' && !(item instanceof File) ? JSON.stringify(item) : item, - ); - } - }); - - return request(`/pet/${param0}`, { - method: 'POST', - params: { ...queryParams }, - data: formData, - ...(options || {}), - }); -} - -/** Deletes a pet DELETE /pet/${param0} */ -export async function deletePet( - // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) - params: API.deletePetParams & { - // header - api_key?: string; - }, - options?: { [key: string]: any }, -) { - const { petId: param0, ...queryParams } = params; - return request(`/pet/${param0}`, { - method: 'DELETE', - headers: {}, - params: { ...queryParams }, - ...(options || {}), - }); -} - -/** uploads an image POST /pet/${param0}/uploadImage */ -export async function uploadFile( - // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) - params: API.uploadFileParams, - body: { additionalMetadata?: string; file?: string }, - file?: File, - options?: { [key: string]: any }, -) { - const { petId: param0, ...queryParams } = params; - const formData = new FormData(); - - if (file) { - formData.append('file', file); - } - - Object.keys(body).forEach((ele) => { - const item = (body as any)[ele]; - - if (item !== undefined && item !== null) { - formData.append( - ele, - typeof item === 'object' && !(item instanceof File) ? JSON.stringify(item) : item, - ); - } - }); - - return request(`/pet/${param0}/uploadImage`, { - method: 'POST', - params: { ...queryParams }, - data: formData, - requestType: 'form', - ...(options || {}), - }); -} - -/** Finds Pets by status Multiple status values can be provided with comma separated strings GET /pet/findByStatus */ -export async function findPetsByStatus( - // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) - params: API.findPetsByStatusParams, - options?: { [key: string]: any }, -) { - return request('/pet/findByStatus', { - method: 'GET', - params: { - ...params, - }, - ...(options || {}), - }); -} - -/** Finds Pets by tags Muliple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. GET /pet/findByTags */ -export async function findPetsByTags( - // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) - params: API.findPetsByTagsParams, - options?: { [key: string]: any }, -) { - return request('/pet/findByTags', { - method: 'GET', - params: { - ...params, - }, - ...(options || {}), - }); -} diff --git a/src/services/swagger/store.ts b/src/services/swagger/store.ts deleted file mode 100644 index b9c689a6..00000000 --- a/src/services/swagger/store.ts +++ /dev/null @@ -1,48 +0,0 @@ -// @ts-ignore -/* eslint-disable */ -import { request } from '@umijs/max'; - -/** Returns pet inventories by status Returns a map of status codes to quantities GET /store/inventory */ -export async function getInventory(options?: { [key: string]: any }) { - return request>('/store/inventory', { - method: 'GET', - ...(options || {}), - }); -} - -/** Place an order for a pet POST /store/order */ -export async function placeOrder(body: API.Order, options?: { [key: string]: any }) { - return request('/store/order', { - method: 'POST', - data: body, - ...(options || {}), - }); -} - -/** Find purchase order by ID For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions GET /store/order/${param0} */ -export async function getOrderById( - // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) - params: API.getOrderByIdParams, - options?: { [key: string]: any }, -) { - const { orderId: param0, ...queryParams } = params; - return request(`/store/order/${param0}`, { - method: 'GET', - params: { ...queryParams }, - ...(options || {}), - }); -} - -/** Delete purchase order by ID For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors DELETE /store/order/${param0} */ -export async function deleteOrder( - // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) - params: API.deleteOrderParams, - options?: { [key: string]: any }, -) { - const { orderId: param0, ...queryParams } = params; - return request(`/store/order/${param0}`, { - method: 'DELETE', - params: { ...queryParams }, - ...(options || {}), - }); -} diff --git a/src/services/swagger/typings.d.ts b/src/services/swagger/typings.d.ts deleted file mode 100644 index d06bcfcb..00000000 --- a/src/services/swagger/typings.d.ts +++ /dev/null @@ -1,112 +0,0 @@ -declare namespace API { - type ApiResponse = { - code?: number; - type?: string; - message?: string; - }; - - type Category = { - id?: number; - name?: string; - }; - - type deleteOrderParams = { - /** ID of the order that needs to be deleted */ - orderId: number; - }; - - type deletePetParams = { - api_key?: string; - /** Pet id to delete */ - petId: number; - }; - - type deleteUserParams = { - /** The name that needs to be deleted */ - username: string; - }; - - type findPetsByStatusParams = { - /** Status values that need to be considered for filter */ - status: ('available' | 'pending' | 'sold')[]; - }; - - type findPetsByTagsParams = { - /** Tags to filter by */ - tags: string[]; - }; - - type getOrderByIdParams = { - /** ID of pet that needs to be fetched */ - orderId: number; - }; - - type getPetByIdParams = { - /** ID of pet to return */ - petId: number; - }; - - type getUserByNameParams = { - /** The name that needs to be fetched. Use user1 for testing. */ - username: string; - }; - - type loginUserParams = { - /** The user name for login */ - username: string; - /** The password for login in clear text */ - password: string; - }; - - type Order = { - id?: number; - petId?: number; - quantity?: number; - shipDate?: string; - /** Order Status */ - status?: 'placed' | 'approved' | 'delivered'; - complete?: boolean; - }; - - type Pet = { - id?: number; - category?: Category; - name: string; - photoUrls: string[]; - tags?: Tag[]; - /** pet status in the store */ - status?: 'available' | 'pending' | 'sold'; - }; - - type Tag = { - id?: number; - name?: string; - }; - - type updatePetWithFormParams = { - /** ID of pet that needs to be updated */ - petId: number; - }; - - type updateUserParams = { - /** name that need to be updated */ - username: string; - }; - - type uploadFileParams = { - /** ID of pet to update */ - petId: number; - }; - - type User = { - id?: number; - username?: string; - firstName?: string; - lastName?: string; - email?: string; - password?: string; - phone?: string; - /** User Status */ - userStatus?: number; - }; -} diff --git a/src/services/swagger/user.ts b/src/services/swagger/user.ts deleted file mode 100644 index 4dd6f421..00000000 --- a/src/services/swagger/user.ts +++ /dev/null @@ -1,100 +0,0 @@ -// @ts-ignore -/* eslint-disable */ -import { request } from '@umijs/max'; - -/** Create user This can only be done by the logged in user. POST /user */ -export async function createUser(body: API.User, options?: { [key: string]: any }) { - return request('/user', { - method: 'POST', - data: body, - ...(options || {}), - }); -} - -/** Get user by user name GET /user/${param0} */ -export async function getUserByName( - // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) - params: API.getUserByNameParams, - options?: { [key: string]: any }, -) { - const { username: param0, ...queryParams } = params; - return request(`/user/${param0}`, { - method: 'GET', - params: { ...queryParams }, - ...(options || {}), - }); -} - -/** Updated user This can only be done by the logged in user. PUT /user/${param0} */ -export async function updateUser( - // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) - params: API.updateUserParams, - body: API.User, - options?: { [key: string]: any }, -) { - const { username: param0, ...queryParams } = params; - return request(`/user/${param0}`, { - method: 'PUT', - params: { ...queryParams }, - data: body, - ...(options || {}), - }); -} - -/** Delete user This can only be done by the logged in user. DELETE /user/${param0} */ -export async function deleteUser( - // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) - params: API.deleteUserParams, - options?: { [key: string]: any }, -) { - const { username: param0, ...queryParams } = params; - return request(`/user/${param0}`, { - method: 'DELETE', - params: { ...queryParams }, - ...(options || {}), - }); -} - -/** Creates list of users with given input array POST /user/createWithArray */ -export async function createUsersWithArrayInput( - body: API.User[], - options?: { [key: string]: any }, -) { - return request('/user/createWithArray', { - method: 'POST', - data: body, - ...(options || {}), - }); -} - -/** Creates list of users with given input array POST /user/createWithList */ -export async function createUsersWithListInput(body: API.User[], options?: { [key: string]: any }) { - return request('/user/createWithList', { - method: 'POST', - data: body, - ...(options || {}), - }); -} - -/** Logs user into the system GET /user/login */ -export async function loginUser( - // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) - params: API.loginUserParams, - options?: { [key: string]: any }, -) { - return request('/user/login', { - method: 'GET', - params: { - ...params, - }, - ...(options || {}), - }); -} - -/** Logs out current logged in user session GET /user/logout */ -export async function logoutUser(options?: { [key: string]: any }) { - return request('/user/logout', { - method: 'GET', - ...(options || {}), - }); -} From bcdb73891c13a5f57d349d0fb0ee670b78d408cb Mon Sep 17 00:00:00 2001 From: afc163 Date: Thu, 5 Mar 2026 12:18:54 +0800 Subject: [PATCH 19/21] fix: replace rc-util with @rc-component/util - Update ChartCard to use @rc-component/util/es/omit - Update TagSelect components to use @rc-component/util - Add @rc-component/util as dependency Co-Authored-By: Claude Opus 4.6 --- package.json | 3 ++- .../dashboard/analysis/components/Charts/ChartCard/index.tsx | 2 +- .../list/search/applications/components/TagSelect/index.tsx | 2 +- src/pages/list/search/articles/components/TagSelect/index.tsx | 2 +- src/pages/list/search/projects/components/TagSelect/index.tsx | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 35d59b58..6350a082 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "@ant-design/pro-components": "3.1.2-0", "@antv/l7": "^2.22.7", "@antv/l7-react": "^2.4.3", + "@rc-component/util": "^1.9.0", "antd": "^6.2.2", "antd-style": "^4.1.0", "clsx": "^2.1.1", @@ -51,6 +52,7 @@ "react-dom": "^19.2.4" }, "devDependencies": { + "@biomejs/biome": "^2.1.1", "@commitlint/cli": "^20.1.0", "@commitlint/config-conventional": "^20.0.0", "@testing-library/dom": "^10.4.0", @@ -64,7 +66,6 @@ "@types/react-helmet": "^6.1.11", "@umijs/lint": "^4.6.13", "@umijs/max": "^4.6.25", - "@biomejs/biome": "^2.1.1", "cross-env": "^10.1.0", "express": "^5.2.0", "gh-pages": "^6.1.1", diff --git a/src/pages/dashboard/analysis/components/Charts/ChartCard/index.tsx b/src/pages/dashboard/analysis/components/Charts/ChartCard/index.tsx index fe4194d5..6241b931 100644 --- a/src/pages/dashboard/analysis/components/Charts/ChartCard/index.tsx +++ b/src/pages/dashboard/analysis/components/Charts/ChartCard/index.tsx @@ -1,7 +1,7 @@ +import omit from '@rc-component/util/es/omit'; import { Card } from 'antd'; import type { CardProps } from 'antd/es/card'; import classNames from 'classnames'; -import omit from 'rc-util/lib/omit'; import React from 'react'; import useStyles from './index.style'; diff --git a/src/pages/list/search/applications/components/TagSelect/index.tsx b/src/pages/list/search/applications/components/TagSelect/index.tsx index 4c0baf0d..100067ee 100644 --- a/src/pages/list/search/applications/components/TagSelect/index.tsx +++ b/src/pages/list/search/applications/components/TagSelect/index.tsx @@ -1,7 +1,7 @@ import { DownOutlined, UpOutlined } from '@ant-design/icons'; +import { useMergedState } from '@rc-component/util'; import { Tag } from 'antd'; import classNames from 'classnames'; -import { useMergedState } from 'rc-util'; import React, { type FC, useState } from 'react'; import useStyles from './index.style'; diff --git a/src/pages/list/search/articles/components/TagSelect/index.tsx b/src/pages/list/search/articles/components/TagSelect/index.tsx index 4c0baf0d..100067ee 100644 --- a/src/pages/list/search/articles/components/TagSelect/index.tsx +++ b/src/pages/list/search/articles/components/TagSelect/index.tsx @@ -1,7 +1,7 @@ import { DownOutlined, UpOutlined } from '@ant-design/icons'; +import { useMergedState } from '@rc-component/util'; import { Tag } from 'antd'; import classNames from 'classnames'; -import { useMergedState } from 'rc-util'; import React, { type FC, useState } from 'react'; import useStyles from './index.style'; diff --git a/src/pages/list/search/projects/components/TagSelect/index.tsx b/src/pages/list/search/projects/components/TagSelect/index.tsx index 4c0baf0d..100067ee 100644 --- a/src/pages/list/search/projects/components/TagSelect/index.tsx +++ b/src/pages/list/search/projects/components/TagSelect/index.tsx @@ -1,7 +1,7 @@ import { DownOutlined, UpOutlined } from '@ant-design/icons'; +import { useMergedState } from '@rc-component/util'; import { Tag } from 'antd'; import classNames from 'classnames'; -import { useMergedState } from 'rc-util'; import React, { type FC, useState } from 'react'; import useStyles from './index.style'; From 5fe12223d75236c1a97f4939eaf7f9e88efd488f Mon Sep 17 00:00:00 2001 From: afc163 Date: Thu, 5 Mar 2026 14:06:08 +0800 Subject: [PATCH 20/21] chore: restore create-umi config field Co-Authored-By: Claude Opus 4.6 --- package.json | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/package.json b/package.json index 6350a082..ab9e9de4 100644 --- a/package.json +++ b/package.json @@ -82,5 +82,34 @@ }, "engines": { "node": ">=20.0.0" + }, + "create-umi": { + "ignoreScript": [ + "docker*", + "functions*", + "site", + "generateMock" + ], + "ignoreDependencies": [ + "netlify*", + "serverless" + ], + "ignore": [ + ".dockerignore", + ".git", + ".github", + ".gitpod.yml", + "CODE_OF_CONDUCT.md", + "Dockerfile", + "Dockerfile.*", + "lambda", + "LICENSE", + "netlify.toml", + "README.*.md", + "azure-pipelines.yml", + "docker", + "CNAME", + "create-umi" + ] } } From 28e98b23340162cbcf22e61259208efd0f6d3334 Mon Sep 17 00:00:00 2001 From: afc163 Date: Sat, 7 Mar 2026 10:25:54 +0800 Subject: [PATCH 21/21] perf: optimize React hooks and fix event listener issues - Account settings: fix event listener closure capturing stale state - ActiveChart: remove unnecessary requestAnimationFrame wrapper, memoize sorted values - TagSelect: memoize getAllTags() result, use Set for O(1) lookups Co-Authored-By: Claude Opus 4.6 --- src/pages/account/settings/index.tsx | 22 +++++------ .../monitor/components/ActiveChart/index.tsx | 39 ++++++++++--------- .../components/TagSelect/index.tsx | 38 +++++++++--------- .../articles/components/TagSelect/index.tsx | 38 +++++++++--------- .../projects/components/TagSelect/index.tsx | 38 +++++++++--------- 5 files changed, 88 insertions(+), 87 deletions(-) diff --git a/src/pages/account/settings/index.tsx b/src/pages/account/settings/index.tsx index 3b0a3402..fc59fbf2 100644 --- a/src/pages/account/settings/index.tsx +++ b/src/pages/account/settings/index.tsx @@ -1,6 +1,6 @@ import { GridContent } from '@ant-design/pro-components'; import { Menu } from 'antd'; -import React, { useLayoutEffect, useRef, useState } from 'react'; +import React, { useCallback, useLayoutEffect, useRef, useState } from 'react'; import BaseView from './components/base'; import BindingView from './components/binding'; import NotificationView from './components/notification'; @@ -25,7 +25,8 @@ const Settings: React.FC = () => { selectKey: 'base', }); const dom = useRef(null); - const resize = () => { + + const resize = useCallback(() => { requestAnimationFrame(() => { if (!dom.current) { return; @@ -38,21 +39,20 @@ const Settings: React.FC = () => { if (window.innerWidth < 768 && offsetWidth > 400) { mode = 'horizontal'; } - setInitConfig({ - ...initConfig, + setInitConfig((prev) => ({ + ...prev, mode: mode as SettingsState['mode'], - }); + })); }); - }; + }, []); + useLayoutEffect(() => { - if (dom.current) { - window.addEventListener('resize', resize); - resize(); - } + window.addEventListener('resize', resize); + resize(); return () => { window.removeEventListener('resize', resize); }; - }, []); + }, [resize]); const getMenu = () => { return Object.keys(menuMap).map((item) => ({ key: item, diff --git a/src/pages/dashboard/monitor/components/ActiveChart/index.tsx b/src/pages/dashboard/monitor/components/ActiveChart/index.tsx index 006807d4..1a6197de 100644 --- a/src/pages/dashboard/monitor/components/ActiveChart/index.tsx +++ b/src/pages/dashboard/monitor/components/ActiveChart/index.tsx @@ -1,6 +1,6 @@ import { Area } from '@ant-design/plots'; import { Statistic } from 'antd'; -import { useCallback, useEffect, useRef, useState } from 'react'; +import { useEffect, useMemo, useRef, useState } from 'react'; import useStyles from './index.style'; function fixedZero(val: number) { @@ -19,27 +19,31 @@ function getActiveData() { const ActiveChart = () => { const timerRef = useRef(null); - const requestRef = useRef(null); const { styles } = useStyles(); const [activeData, setActiveData] = useState<{ x: string; y: number }[]>([]); - const loopData = useCallback(() => { - requestRef.current = requestAnimationFrame(() => { - timerRef.current = window.setTimeout(() => { - setActiveData(getActiveData()); - loopData(); - }, 2000); - }); - }, []); useEffect(() => { + const loopData = () => { + setActiveData(getActiveData()); + timerRef.current = window.setTimeout(loopData, 2000); + }; loopData(); return () => { - clearTimeout(timerRef.current as number); - if (requestRef.current) { - cancelAnimationFrame(requestRef.current); + if (timerRef.current) { + clearTimeout(timerRef.current); } }; - }, [loopData]); + }, []); + + // Memoize max and median to avoid double sort on every render + const { maxValue, medianValue } = useMemo(() => { + if (!activeData.length) return { maxValue: 0, medianValue: 0 }; + const sorted = [...activeData].sort((a, b) => a.y - b.y); + return { + maxValue: sorted[sorted.length - 1]?.y ?? 0, + medianValue: sorted[Math.floor(sorted.length / 2)]?.y ?? 0, + }; + }, [activeData]); return (
@@ -65,11 +69,8 @@ const ActiveChart = () => { {activeData && (
-

{[...activeData].sort()[activeData.length - 1]?.y + 200} 亿元

-

- {[...activeData].sort()[Math.floor(activeData.length / 2)]?.y}{' '} - 亿元 -

+

{maxValue + 200} 亿元

+

{medianValue} 亿元

diff --git a/src/pages/list/search/applications/components/TagSelect/index.tsx b/src/pages/list/search/applications/components/TagSelect/index.tsx index 100067ee..80107cd2 100644 --- a/src/pages/list/search/applications/components/TagSelect/index.tsx +++ b/src/pages/list/search/applications/components/TagSelect/index.tsx @@ -2,7 +2,7 @@ import { DownOutlined, UpOutlined } from '@ant-design/icons'; import { useMergedState } from '@rc-component/util'; import { Tag } from 'antd'; import classNames from 'classnames'; -import React, { type FC, useState } from 'react'; +import React, { type FC, useMemo, useState } from 'react'; import useStyles from './index.style'; const { CheckableTag } = Tag; @@ -75,33 +75,33 @@ const TagSelect: FC & { node?.type && (node.type.isTagSelectOption || node.type.displayName === 'TagSelectOption'); - const getAllTags = () => { + + // Memoize all tags to avoid recalculating on every render + const allTags = useMemo(() => { const childrenArray = React.Children.toArray( children, ) as TagSelectOptionElement[]; - const checkedTags = childrenArray + return childrenArray .filter((child) => isTagSelectOption(child)) .map((child) => child.props.value); - return checkedTags || []; - }; + }, [children]); + + // Use Set for O(1) lookups + const valueSet = useMemo(() => new Set(value || []), [value]); + const onSelectAll = (checked: boolean) => { - let checkedTags: (string | number)[] = []; - if (checked) { - checkedTags = getAllTags(); - } - setValue(checkedTags); + setValue(checked ? [...allTags] : []); }; const handleTagChange = (tag: string | number, checked: boolean) => { - const checkedTags: (string | number)[] = [...(value || [])]; - const index = checkedTags.indexOf(tag); - if (checked && index === -1) { - checkedTags.push(tag); - } else if (!checked && index > -1) { - checkedTags.splice(index, 1); + const checkedTags = new Set(value || []); + if (checked) { + checkedTags.add(tag); + } else { + checkedTags.delete(tag); } - setValue(checkedTags); + setValue([...checkedTags]); }; - const checkedAll = getAllTags().length === value?.length; + const checkedAll = allTags.length === value?.length && allTags.length > 0; const { expandText = '展开', collapseText = '收起', @@ -128,7 +128,7 @@ const TagSelect: FC & { return React.cloneElement(child, { key: `tag-select-${child.props.value}`, value: child.props.value, - checked: value && value.indexOf(child.props.value) > -1, + checked: valueSet.has(child.props.value), onChange: handleTagChange, }); } diff --git a/src/pages/list/search/articles/components/TagSelect/index.tsx b/src/pages/list/search/articles/components/TagSelect/index.tsx index 100067ee..80107cd2 100644 --- a/src/pages/list/search/articles/components/TagSelect/index.tsx +++ b/src/pages/list/search/articles/components/TagSelect/index.tsx @@ -2,7 +2,7 @@ import { DownOutlined, UpOutlined } from '@ant-design/icons'; import { useMergedState } from '@rc-component/util'; import { Tag } from 'antd'; import classNames from 'classnames'; -import React, { type FC, useState } from 'react'; +import React, { type FC, useMemo, useState } from 'react'; import useStyles from './index.style'; const { CheckableTag } = Tag; @@ -75,33 +75,33 @@ const TagSelect: FC & { node?.type && (node.type.isTagSelectOption || node.type.displayName === 'TagSelectOption'); - const getAllTags = () => { + + // Memoize all tags to avoid recalculating on every render + const allTags = useMemo(() => { const childrenArray = React.Children.toArray( children, ) as TagSelectOptionElement[]; - const checkedTags = childrenArray + return childrenArray .filter((child) => isTagSelectOption(child)) .map((child) => child.props.value); - return checkedTags || []; - }; + }, [children]); + + // Use Set for O(1) lookups + const valueSet = useMemo(() => new Set(value || []), [value]); + const onSelectAll = (checked: boolean) => { - let checkedTags: (string | number)[] = []; - if (checked) { - checkedTags = getAllTags(); - } - setValue(checkedTags); + setValue(checked ? [...allTags] : []); }; const handleTagChange = (tag: string | number, checked: boolean) => { - const checkedTags: (string | number)[] = [...(value || [])]; - const index = checkedTags.indexOf(tag); - if (checked && index === -1) { - checkedTags.push(tag); - } else if (!checked && index > -1) { - checkedTags.splice(index, 1); + const checkedTags = new Set(value || []); + if (checked) { + checkedTags.add(tag); + } else { + checkedTags.delete(tag); } - setValue(checkedTags); + setValue([...checkedTags]); }; - const checkedAll = getAllTags().length === value?.length; + const checkedAll = allTags.length === value?.length && allTags.length > 0; const { expandText = '展开', collapseText = '收起', @@ -128,7 +128,7 @@ const TagSelect: FC & { return React.cloneElement(child, { key: `tag-select-${child.props.value}`, value: child.props.value, - checked: value && value.indexOf(child.props.value) > -1, + checked: valueSet.has(child.props.value), onChange: handleTagChange, }); } diff --git a/src/pages/list/search/projects/components/TagSelect/index.tsx b/src/pages/list/search/projects/components/TagSelect/index.tsx index 100067ee..80107cd2 100644 --- a/src/pages/list/search/projects/components/TagSelect/index.tsx +++ b/src/pages/list/search/projects/components/TagSelect/index.tsx @@ -2,7 +2,7 @@ import { DownOutlined, UpOutlined } from '@ant-design/icons'; import { useMergedState } from '@rc-component/util'; import { Tag } from 'antd'; import classNames from 'classnames'; -import React, { type FC, useState } from 'react'; +import React, { type FC, useMemo, useState } from 'react'; import useStyles from './index.style'; const { CheckableTag } = Tag; @@ -75,33 +75,33 @@ const TagSelect: FC & { node?.type && (node.type.isTagSelectOption || node.type.displayName === 'TagSelectOption'); - const getAllTags = () => { + + // Memoize all tags to avoid recalculating on every render + const allTags = useMemo(() => { const childrenArray = React.Children.toArray( children, ) as TagSelectOptionElement[]; - const checkedTags = childrenArray + return childrenArray .filter((child) => isTagSelectOption(child)) .map((child) => child.props.value); - return checkedTags || []; - }; + }, [children]); + + // Use Set for O(1) lookups + const valueSet = useMemo(() => new Set(value || []), [value]); + const onSelectAll = (checked: boolean) => { - let checkedTags: (string | number)[] = []; - if (checked) { - checkedTags = getAllTags(); - } - setValue(checkedTags); + setValue(checked ? [...allTags] : []); }; const handleTagChange = (tag: string | number, checked: boolean) => { - const checkedTags: (string | number)[] = [...(value || [])]; - const index = checkedTags.indexOf(tag); - if (checked && index === -1) { - checkedTags.push(tag); - } else if (!checked && index > -1) { - checkedTags.splice(index, 1); + const checkedTags = new Set(value || []); + if (checked) { + checkedTags.add(tag); + } else { + checkedTags.delete(tag); } - setValue(checkedTags); + setValue([...checkedTags]); }; - const checkedAll = getAllTags().length === value?.length; + const checkedAll = allTags.length === value?.length && allTags.length > 0; const { expandText = '展开', collapseText = '收起', @@ -128,7 +128,7 @@ const TagSelect: FC & { return React.cloneElement(child, { key: `tag-select-${child.props.value}`, value: child.props.value, - checked: value && value.indexOf(child.props.value) > -1, + checked: valueSet.has(child.props.value), onChange: handleTagChange, }); }