Compare commits

...

14 Commits

Author SHA1 Message Date
dayjoy
10d37978dd feat: 将 tocoModals 重命名为 tocoOverlays 以支持更多浮层类型 2025-05-09 16:27:16 +08:00
dayjoy
58406d2d54 fix: update theme import and algorithm handling in App component 2025-05-06 16:26:52 +08:00
jackycheng
aca60e107d fix: message theme 2025-05-06 15:57:04 +08:00
jackycheng
ea43542878 fix: primaryColor覆盖问题 2025-05-06 14:25:58 +08:00
dayjoy
f3fbbcc4ab feat(theme): 添加主题配置文件并集成到应用中 2025-05-06 14:22:07 +08:00
jackycheng
ceb48abc16 fix: 点击logo回到首页 2025-02-14 17:22:20 +08:00
jackycheng
f18aa76676 fix: menu parse 2025-02-14 10:49:38 +08:00
jackycheng
1216e08bb9 fix: @df/toco-ui => @toco-design/components 2025-01-08 11:18:06 +08:00
jackycheng
f2cba9f5c4 fix: dep 2024-12-29 12:16:42 +08:00
jackycheng
03a6d711c3 fix: 类型修正 2024-12-27 15:15:06 +08:00
jackycheng
aa8707cf6f fix: tsconfig alias 2024-12-27 15:14:10 +08:00
jackycheng
dc3228d313 fix: 限制react-intl的版本在6.6.x,更高版本会有@formatjs/fast-memoize 的sourcemap报错 2024-12-27 15:13:18 +08:00
jackycheng
4c3d3e0489 fix: 去掉eslint的prettier规则,生成的工程会因为这些规则大量报错 2024-12-27 15:12:54 +08:00
jackycheng
91a97ffb93 fix: 移动目录 2024-12-26 16:14:44 +08:00
57 changed files with 91 additions and 81 deletions

View File

@@ -5,41 +5,27 @@ module.exports = {
'eslint:recommended', 'eslint:recommended',
'plugin:react/recommended', 'plugin:react/recommended',
'plugin:@typescript-eslint/recommended', 'plugin:@typescript-eslint/recommended',
'prettier',
'prettier/prettier',
'plugin:prettier/recommended',
'plugin:react-hooks/recommended', 'plugin:react-hooks/recommended',
'plugin:json/recommended', 'plugin:json/recommended',
], ],
parser: '@typescript-eslint/parser', parser: '@typescript-eslint/parser',
plugins: ['react', '@typescript-eslint', 'simple-import-sort'], plugins: ['react', '@typescript-eslint'],
rules: { rules: {
'prettier/prettier': ['error', { singleQuote: true }],
'@typescript-eslint/no-unused-vars': [ '@typescript-eslint/no-unused-vars': [
'off', 'off',
{ argsIgnorePattern: ['^_', 'tocoServices'] }, { argsIgnorePattern: ['^_', 'tocoServices'] },
], ],
'simple-import-sort/exports': 'error', '@typescript-eslint/no-non-null-assertion': 'off',
"@typescript-eslint/ban-types": 'off',
'react-hooks/exhaustive-deps': 'error', 'react-hooks/exhaustive-deps': 'error',
'react/react-in-jsx-scope': 'off', 'react/react-in-jsx-scope': 'off',
'react/prop-types': 'off', 'react/prop-types': 'off',
'@typescript-eslint/no-non-null-assertion': 'off', 'react/no-children-prop': 'off',
'import/no-anonymous-default-export': 'off',
}, },
overrides: [ overrides: [
{ {
files: ['**/*.js'], files: ['**/*.config.js'],
rules: {
'react/no-children-prop': 'off',
},
},
{
files: ['**/*.json'],
rules: {
'prettier/prettier': ['error', { singleQuote: false }],
},
},
{
files: ['**/*.config.js', '**/setupProxy.js', 'script/**/*.js'],
rules: { rules: {
'@typescript-eslint/no-var-requires': 'off', '@typescript-eslint/no-var-requires': 'off',
}, },
@@ -47,6 +33,6 @@ module.exports = {
], ],
globals: { globals: {
tocoRefs: true, tocoRefs: true,
tocoModals: true, tocoOverlays: true,
}, },
}; };

View File

View File

@@ -55,7 +55,7 @@
navigate页面跳转方法用法navigate('/path') navigate页面跳转方法用法navigate('/path')
tocoServices页面的请求 tocoServices页面的请求
tocoRefs页面上所有带 id 组件的 refs tocoRefs页面上所有带 id 组件的 refs
tocoModals页面上所有带 id 弹窗的 refs tocoOverlays页面上所有带 id 弹窗/抽屉等浮层的 refs
``` ```
## 目录结构 ## 目录结构

View File

@@ -10,37 +10,31 @@
}, },
"dependencies": { "dependencies": {
"@ant-design/icons": "^5.5.1", "@ant-design/icons": "^5.5.1",
"@df/toco-ui": "{{uiVersion}}", "@toco-design/components": "{{uiVersion}}",
"@reduxjs/toolkit": "^1.9.7", "@reduxjs/toolkit": "^1.9.7",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.5.2",
"axios": "^1.7.2", "axios": "^1.7.2",
"classnames": "^2.5.1", "classnames": "^2.5.1",
"path-to-regexp": "^8.2.0", "path-to-regexp": "^8.2.0",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-intl": "^6.6.2", "react-intl": "~6.6.2",
"react-redux": "^8.1.3", "react-redux": "^8.1.3",
"react-router-dom": "^6.22.2", "react-router-dom": "^6.22.2"
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
}, },
"devDependencies": { "devDependencies": {
"@craco/craco": "^7.1.0", "@craco/craco": "^7.1.0",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.5.2",
"@types/jest": "^27.5.2", "@types/jest": "^27.5.2",
"@types/node": "^17.0.45", "@types/node": "^17.0.45",
"@types/react": "^18.2.60", "@types/react": "^18.2.60",
"@types/react-dom": "^18.2.19", "@types/react-dom": "^18.2.19",
"craco-alias": "^3.0.1", "craco-alias": "^3.0.1",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-json": "^3.1.0", "eslint-plugin-json": "^3.1.0",
"eslint-plugin-prettier": "^5.1.3", "react-scripts": "5.0.1",
"eslint-plugin-simple-import-sort": "^12.0.0", "typescript": "^5",
"prettier": "^3.2.5", "web-vitals": "^2.1.4"
"prettier-plugin-organize-imports": "^3.2.4",
"prettier-plugin-packagejson": "^2.4.12",
"typescript": "^5"
}, },
"browserslist": { "browserslist": {
"production": [ "production": [

View File

Before

Width:  |  Height:  |  Size: 156 KiB

After

Width:  |  Height:  |  Size: 156 KiB

View File

Before

Width:  |  Height:  |  Size: 202 KiB

After

Width:  |  Height:  |  Size: 202 KiB

View File

Before

Width:  |  Height:  |  Size: 149 KiB

After

Width:  |  Height:  |  Size: 149 KiB

View File

Before

Width:  |  Height:  |  Size: 138 KiB

After

Width:  |  Height:  |  Size: 138 KiB

View File

@@ -1,5 +1,5 @@
import { customValueTypeMap } from '@/components'; import { customValueTypeMap } from '@components';
import { ConfigProvider, App as TocoApp, theme } from '@df/toco-ui'; import { ConfigProvider, App as TocoApp, theme as antTheme, ProConfigProvider } from '@toco-design/components';
import { Router } from '@remix-run/router'; import { Router } from '@remix-run/router';
import enUS from 'antd/locale/en_US'; import enUS from 'antd/locale/en_US';
import zhCN from 'antd/locale/zh_CN'; import zhCN from 'antd/locale/zh_CN';
@@ -10,14 +10,13 @@ import { RouterProvider } from 'react-router-dom';
import { Locale, Theme } from './enum'; import { Locale, Theme } from './enum';
import { useAppSelector } from './hooks'; import { useAppSelector } from './hooks';
import * as langs from './langs'; import * as langs from './langs';
import globalMessage from './message';
import { store } from './store'; import { store } from './store';
import appTheme from './theme';
const { darkAlgorithm } = theme; const { darkAlgorithm } = antTheme;
const AppInternal: React.FC<{ router: Router }> = (props) => { const AppInternal: React.FC<{ router: Router }> = (props) => {
const { router } = props; const { router } = props;
const { message } = TocoApp.useApp();
const locale = useAppSelector((state) => state.common.locale); const locale = useAppSelector((state) => state.common.locale);
const theme = useAppSelector((state) => state.common.theme); const theme = useAppSelector((state) => state.common.theme);
@@ -33,21 +32,29 @@ const AppInternal: React.FC<{ router: Router }> = (props) => {
}; };
const themeConfig = useMemo(() => { const themeConfig = useMemo(() => {
const algorithmArr = Array.isArray(appTheme.algorithm) ? appTheme.algorithm : appTheme.algorithm ? [appTheme.algorithm] : [];
if (theme === Theme.DARK) {
if (!algorithmArr.includes(antTheme.darkAlgorithm)) {
algorithmArr.push(antTheme.darkAlgorithm);
}
} else {
const index = algorithmArr.indexOf(antTheme.darkAlgorithm);
if (index > -1) {
algorithmArr.splice(index, 1);
}
}
return { return {
algorithm: theme === Theme.DARK ? [darkAlgorithm] : [], algorithm: algorithmArr,
cssVar: true, cssVar: appTheme.cssVar ?? true,
token: primaryColor token: primaryColor
? { ? {
...appTheme.token,
colorPrimary: primaryColor, colorPrimary: primaryColor,
} }
: undefined, : appTheme.token,
}; };
}, [primaryColor, theme]); }, [primaryColor, theme]);
useEffect(() => {
globalMessage.setMessage(message);
}, [message]);
useEffect(() => { useEffect(() => {
document.documentElement.setAttribute( document.documentElement.setAttribute(
'data-color-scheme', 'data-color-scheme',
@@ -60,9 +67,12 @@ const AppInternal: React.FC<{ router: Router }> = (props) => {
<ConfigProvider <ConfigProvider
locale={antdLocaleMap[locale]} locale={antdLocaleMap[locale]}
theme={themeConfig} theme={themeConfig}
valueTypeMap={customValueTypeMap}
> >
<ProConfigProvider valueTypeMap={customValueTypeMap}>
<TocoApp style={{ height: '100%' }}>
<RouterProvider router={router} /> <RouterProvider router={router} />
</TocoApp>
</ProConfigProvider>
</ConfigProvider> </ConfigProvider>
</IntlProvider> </IntlProvider>
); );
@@ -71,9 +81,7 @@ const AppInternal: React.FC<{ router: Router }> = (props) => {
const App: React.FC<{ router: Router }> = (props) => { const App: React.FC<{ router: Router }> = (props) => {
return ( return (
<StoreProvider store={store}> <StoreProvider store={store}>
<TocoApp style={{ height: '100%' }}>
<AppInternal {...props} /> <AppInternal {...props} />
</TocoApp>
</StoreProvider> </StoreProvider>
); );
}; };

View File

@@ -2,7 +2,7 @@
* 使message api * 使message api
* toco-ui/antd message无法直接全局使用 * toco-ui/antd message无法直接全局使用
*/ */
import { message as tocoMessage } from '@df/toco-ui'; import { message as tocoMessage } from '@toco-design/components';
type Message = ReturnType<typeof tocoMessage.useMessage>[0]; type Message = ReturnType<typeof tocoMessage.useMessage>[0];

7
src/app/theme.ts Normal file
View File

@@ -0,0 +1,7 @@
import { ThemeConfig, theme } from '@toco-design/components';
const appTheme: ThemeConfig = {
};
export default appTheme;

View File

@@ -3,7 +3,7 @@
declare global { declare global {
var tocoRefs: Record<string, any>; var tocoRefs: Record<string, any>;
var tocoModals: Record<string, any>; var tocoOverlays: Record<string, any>;
} }
export {}; export {};

View File

@@ -1,5 +1,5 @@
import '@/style/index.css'; import '@/style/index.css';
import { tocoGlobal } from '@df/toco-ui'; import { tocoGlobal } from '@toco-design/components';
import React from 'react'; import React from 'react';
import { createRoot } from 'react-dom/client'; import { createRoot } from 'react-dom/client';
import App from './app'; import App from './app';
@@ -22,4 +22,4 @@ reportWebVitals();
// global variables // global variables
globalThis.tocoRefs = tocoGlobal.getRefs(); globalThis.tocoRefs = tocoGlobal.getRefs();
globalThis.tocoModals = tocoGlobal.getModals(); globalThis.tocoOverlays = tocoGlobal.getOverlays();

View File

@@ -14,6 +14,7 @@
} }
height: var(--header-height); height: var(--header-height);
padding: 16px; padding: 16px;
cursor: pointer;
.icon { .icon {
display: flex; display: flex;

View File

@@ -1,9 +1,11 @@
import { Theme } from '@/app/enum'; import { Theme } from '@/app/enum';
import { useAppSelector } from '@/app/hooks'; import { useAppSelector } from '@/app/hooks';
import globalMessage from '@/app/message';
import { SettingOutlined } from '@ant-design/icons'; import { SettingOutlined } from '@ant-design/icons';
import { Button, Image, Popover } from '@df/toco-ui'; import { App, Button, Image, Popover } from '@toco-design/components';
import classNames from 'classnames'; import classNames from 'classnames';
import { useMemo } from 'react'; import { useCallback, useEffect, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import styles from './index.module.css'; import styles from './index.module.css';
import { HeaderOnly, HeaderSider, SiderOnly } from './layouts'; import { HeaderOnly, HeaderSider, SiderOnly } from './layouts';
import Settings from './settings'; import Settings from './settings';
@@ -22,6 +24,12 @@ type LayoutProps = {
const Layout: React.FC<LayoutProps> = (props) => { const Layout: React.FC<LayoutProps> = (props) => {
const { type: typeProp } = props; const { type: typeProp } = props;
const theme = useAppSelector((state) => state.common.theme); const theme = useAppSelector((state) => state.common.theme);
const navigate = useNavigate();
const { message } = App.useApp();
useEffect(() => {
globalMessage.setMessage(message);
}, [message]);
const Component = useMemo(() => { const Component = useMemo(() => {
const type = typeProp ?? LayoutType.Default; const type = typeProp ?? LayoutType.Default;
@@ -37,6 +45,10 @@ const Layout: React.FC<LayoutProps> = (props) => {
return HeaderSider; return HeaderSider;
}, [typeProp]); }, [typeProp]);
const gotoHome = useCallback(() => {
navigate('/');
}, [navigate]);
return ( return (
<SuspenseLayout> <SuspenseLayout>
<Component <Component
@@ -45,6 +57,7 @@ const Layout: React.FC<LayoutProps> = (props) => {
logo={ logo={
<div <div
className={classNames(styles.logo, { dark: theme === Theme.DARK })} className={classNames(styles.logo, { dark: theme === Theme.DARK })}
onClick={gotoHome}
> >
<Image <Image
className={styles.icon} className={styles.icon}

View File

@@ -1,7 +1,6 @@
import { Theme } from '@/app/enum'; import { Theme } from '@/app/enum';
import { routerConfig } from '@/router'; import { routerConfig } from '@/router';
import { Layout, Menu, MenuProps } from '@df/toco-ui'; import { Layout, Menu, MenuProps } from '@toco-design/components';
import { SelectInfo } from 'rc-menu/lib/interface';
import React, { useCallback, useEffect, useMemo, useState } from 'react'; import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { Outlet, useMatches, useNavigate } from 'react-router-dom'; import { Outlet, useMatches, useNavigate } from 'react-router-dom';
import { LayoutProps } from '.'; import { LayoutProps } from '.';
@@ -26,7 +25,8 @@ const HeaderOnly: React.FC<LayoutProps> = (props) => {
}, []); }, []);
const onKeyChange = useCallback( const onKeyChange = useCallback(
(info: SelectInfo) => { (...args: Parameters<Required<MenuProps>['onSelect']>) => {
const info = args[0];
const keys = info.keyPath; const keys = info.keyPath;
setSelectedKeys(info.keyPath); setSelectedKeys(info.keyPath);
navigate(keys.reverse().join('/')); navigate(keys.reverse().join('/'));

View File

@@ -1,7 +1,6 @@
import { Theme } from '@/app/enum'; import { Theme } from '@/app/enum';
import { routerConfig } from '@/router'; import { routerConfig } from '@/router';
import { Layout, Menu, MenuProps } from '@df/toco-ui'; import { Layout, Menu, MenuProps } from '@toco-design/components';
import { SelectInfo } from 'rc-menu/lib/interface';
import React, { useCallback, useEffect, useMemo, useState } from 'react'; import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { Outlet, useMatches, useNavigate } from 'react-router-dom'; import { Outlet, useMatches, useNavigate } from 'react-router-dom';
import { LayoutProps } from '.'; import { LayoutProps } from '.';
@@ -37,7 +36,8 @@ const HeaderSider: React.FC<LayoutProps> = (props) => {
}, []); }, []);
const onHeaderKeyChange = useCallback( const onHeaderKeyChange = useCallback(
(info: SelectInfo) => { (...args: Parameters<Required<MenuProps>['onSelect']>) => {
const info = args[0];
setHeaderKey(info.key); setHeaderKey(info.key);
navigate(info.key); navigate(info.key);
}, },
@@ -50,7 +50,8 @@ const HeaderSider: React.FC<LayoutProps> = (props) => {
}, [headerKey]); }, [headerKey]);
const onSiderKeyChange = useCallback( const onSiderKeyChange = useCallback(
(info: SelectInfo) => { (...args: Parameters<Required<MenuProps>['onSelect']>) => {
const info = args[0];
const keys = info.keyPath; const keys = info.keyPath;
setSiderSelectedKeys(info.keyPath); setSiderSelectedKeys(info.keyPath);
const parts = [headerKey, ...keys]; const parts = [headerKey, ...keys];

View File

@@ -1,7 +1,6 @@
import { Theme } from '@/app/enum'; import { Theme } from '@/app/enum';
import { routerConfig } from '@/router'; import { routerConfig } from '@/router';
import { Layout, Menu, MenuProps } from '@df/toco-ui'; import { Layout, Menu, MenuProps } from '@toco-design/components';
import { SelectInfo } from 'rc-menu/lib/interface';
import React, { useCallback, useEffect, useMemo, useState } from 'react'; import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { Outlet, useMatches, useNavigate } from 'react-router-dom'; import { Outlet, useMatches, useNavigate } from 'react-router-dom';
import { LayoutProps } from '.'; import { LayoutProps } from '.';
@@ -34,7 +33,8 @@ const SiderOnly: React.FC<LayoutProps> = (props) => {
}, []); }, []);
const onKeyChange = useCallback( const onKeyChange = useCallback(
(info: SelectInfo) => { (...args: Parameters<Required<MenuProps>['onSelect']>) => {
const info = args[0];
const keys = info.keyPath; const keys = info.keyPath;
setSelectedKeys(info.keyPath); setSelectedKeys(info.keyPath);
navigate(keys.reverse().join('/')); navigate(keys.reverse().join('/'));

View File

@@ -1,5 +1,5 @@
import { RootRoute } from '@/router'; import { RootRoute } from '@/router';
import { MenuProps } from '@df/toco-ui'; import { MenuProps } from '@toco-design/components';
import { parse } from 'path-to-regexp'; import { parse } from 'path-to-regexp';
import { UIMatch } from 'react-router-dom'; import { UIMatch } from 'react-router-dom';
@@ -28,7 +28,7 @@ export const parseMenuItems = (
return { return {
key: removeLeadingSlashes(item.path), key: removeLeadingSlashes(item.path),
label: item.menu.title, label: item.menu.title,
children: children && children.length > 0 ? children : 0, children: children && children.length > 0 ? children : undefined,
}; };
}) })
.filter((p) => !!p); .filter((p) => !!p);

View File

@@ -6,7 +6,7 @@ import {
} from '@/app/common'; } from '@/app/common';
import { Locale, Theme } from '@/app/enum'; import { Locale, Theme } from '@/app/enum';
import { useAppDispatch, useAppSelector } from '@/app/hooks'; import { useAppDispatch, useAppSelector } from '@/app/hooks';
import { Radio, RadioChangeEvent, Tooltip } from '@df/toco-ui'; import { Radio, RadioChangeEvent, Tooltip } from '@toco-design/components';
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { FormattedMessage, useIntl } from 'react-intl'; import { FormattedMessage, useIntl } from 'react-intl';
import ColorContainer, { changeColor } from './color'; import ColorContainer, { changeColor } from './color';

View File

@@ -1,4 +1,4 @@
import { Spin as AntSpin, SpinProps } from '@df/toco-ui'; import { Spin as AntSpin, SpinProps } from '@toco-design/components';
const Spin = (props: SpinProps) => { const Spin = (props: SpinProps) => {
const { size = 'default' } = props; const { size = 'default' } = props;
const sizeMap = { const sizeMap = {

View File

@@ -17,7 +17,11 @@
"jsx": "react-jsx", "jsx": "react-jsx",
"baseUrl": "./src", "baseUrl": "./src",
"paths": { "paths": {
"@/*": ["./*"] "@/*": ["./*"],
"@components": ["./components"],
"@components/*": ["./components/*"],
"@pages": ["./pages"],
"@pages/*": ["./pages/*"]
} }
}, },
"include": ["src"] "include": ["src"]

View File

@@ -1,4 +0,0 @@
projectName: toco
uiVersion: 0.1.36
iconFontSrc: ""
layout: Default