| @@ -9,7 +9,7 @@ const Settings: ProLayoutProps & { | |||||
| } = { | } = { | ||||
| locale: 'zh-CN', | locale: 'zh-CN', | ||||
| navTheme: 'light', | navTheme: 'light', | ||||
| // 拂晓蓝 | |||||
| colorPrimary: '#514cf9', | |||||
| // layout: 'mix', | // layout: 'mix', | ||||
| contentWidth: 'Fluid', | contentWidth: 'Fluid', | ||||
| fixedHeader: false, | fixedHeader: false, | ||||
| @@ -60,14 +60,17 @@ | |||||
| "not ie <= 10" | "not ie <= 10" | ||||
| ], | ], | ||||
| "dependencies": { | "dependencies": { | ||||
| "@ant-design/colors": "~7.2.1", | |||||
| "@ant-design/icons": "^5.0.0", | "@ant-design/icons": "^5.0.0", | ||||
| "@ant-design/pro-components": "^2.4.4", | "@ant-design/pro-components": "^2.4.4", | ||||
| "@ant-design/use-emotion-css": "1.0.4", | "@ant-design/use-emotion-css": "1.0.4", | ||||
| "@antv/g6": "^4.8.24", | "@antv/g6": "^4.8.24", | ||||
| "@antv/hierarchy": "^0.6.12", | "@antv/hierarchy": "^0.6.12", | ||||
| "@ctrl/tinycolor": "~4.1.0", | |||||
| "@types/crypto-js": "^4.2.2", | "@types/crypto-js": "^4.2.2", | ||||
| "@umijs/route-utils": "^4.0.1", | "@umijs/route-utils": "^4.0.1", | ||||
| "antd": "~5.21.4", | "antd": "~5.21.4", | ||||
| "antd-style": "~3.7.1", | |||||
| "caniuse-lite": "~1.0.30001707", | "caniuse-lite": "~1.0.30001707", | ||||
| "classnames": "^2.3.2", | "classnames": "^2.3.2", | ||||
| "crypto-js": "^4.2.0", | "crypto-js": "^4.2.0", | ||||
| @@ -192,7 +192,7 @@ export const antd: RuntimeAntdConfig = (memo) => { | |||||
| colorPrimary: themes['primaryColor'], | colorPrimary: themes['primaryColor'], | ||||
| colorPrimaryHover: themes['primaryHoverColor'], | colorPrimaryHover: themes['primaryHoverColor'], | ||||
| colorPrimaryActive: themes['primaryActiveColor'], | colorPrimaryActive: themes['primaryActiveColor'], | ||||
| colorPrimaryBg: 'rgba(81, 76, 249, 0.07)', | |||||
| // colorPrimaryBg: 'rgba(81, 76, 249, 0.07)', | |||||
| colorSuccess: themes['successColor'], | colorSuccess: themes['successColor'], | ||||
| colorError: themes['errorColor'], | colorError: themes['errorColor'], | ||||
| colorWarning: themes['warningColor'], | colorWarning: themes['warningColor'], | ||||
| @@ -0,0 +1,25 @@ | |||||
| body { | |||||
| .kf-primary-button.ant-btn-color-primary.ant-btn-variant-link { | |||||
| background-color: .addAlpha(@primary-color, 0.07) [] !important; | |||||
| } | |||||
| .kf-default-button.ant-btn-color-default.ant-btn-variant-link { | |||||
| background-color: .addAlpha(@text-color-secondary, 0.07) [] !important; | |||||
| } | |||||
| .kf-danger-button.ant-btn-color-danger.ant-btn-variant-link { | |||||
| background-color: .addAlpha(@error-color, 0.07) [] !important; | |||||
| } | |||||
| .ant-btn-color-default.ant-btn-variant-link.kf-default-button:not(:disabled):not( | |||||
| .ant-btn-disabled | |||||
| ):hover { | |||||
| color: .addAlpha(@text-color-secondary, 0.5) []; | |||||
| } | |||||
| .ant-btn-color-default.ant-btn-variant-link.kf-default-button:not(:disabled):not( | |||||
| .ant-btn-disabled | |||||
| ):active { | |||||
| color: @text-color-secondary; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,75 @@ | |||||
| import themes from '@/styles/theme.less'; | |||||
| import { addAlpha, derivePrimaryStates } from '@/utils/color'; | |||||
| import { Button, ButtonProps } from 'antd'; | |||||
| import { createStyles } from 'antd-style'; | |||||
| import './index.less'; | |||||
| type KFColor = 'primary' | 'default' | 'danger'; | |||||
| export interface KFButtonProps extends ButtonProps { | |||||
| kfColor?: KFColor; | |||||
| } | |||||
| const useStyles = createStyles(({ token, css }) => ({ | |||||
| primary: css` | |||||
| color: ${token.colorPrimary} !important; | |||||
| background-color: ${addAlpha(themes['primaryColor'], 0.07)} !important; | |||||
| &:hover { | |||||
| color: ${token.colorPrimaryHover} !important; | |||||
| } | |||||
| &:active { | |||||
| color: ${token.colorPrimaryActive} !important; | |||||
| } | |||||
| `, | |||||
| default: css` | |||||
| color: ${themes['textColorSecondary']} !important; | |||||
| background-color: ${addAlpha(themes['textColorSecondary'], 0.07)} !important; | |||||
| &:hover { | |||||
| color: ${derivePrimaryStates(themes['textColorSecondary']).colorPrimaryHover} !important; | |||||
| } | |||||
| &:active { | |||||
| color: ${derivePrimaryStates(themes['textColorSecondary']).colorPrimaryActive} !important; | |||||
| } | |||||
| `, | |||||
| danger: css` | |||||
| color: ${themes['errorColor']} !important; | |||||
| background-color: ${addAlpha(themes['errorColor'], 0.07)} !important; | |||||
| &:hover { | |||||
| color: ${derivePrimaryStates(themes['errorColor']).colorPrimaryHover} !important; | |||||
| } | |||||
| &:active { | |||||
| color: ${derivePrimaryStates(themes['errorColor']).colorPrimaryActive} !important; | |||||
| } | |||||
| `, | |||||
| })); | |||||
| function KFButton({ kfColor = 'default', className, ...rest }: KFButtonProps) { | |||||
| const { styles, cx } = useStyles(); | |||||
| let style = ''; | |||||
| switch (kfColor) { | |||||
| case 'primary': | |||||
| style = styles.primary; | |||||
| break; | |||||
| case 'default': | |||||
| style = styles.default; | |||||
| break; | |||||
| case 'danger': | |||||
| style = styles.danger; | |||||
| break; | |||||
| default: | |||||
| break; | |||||
| } | |||||
| return ( | |||||
| <Button {...rest} className={cx(className, style)} color={kfColor} variant="link"></Button> | |||||
| ); | |||||
| } | |||||
| export default KFButton; | |||||
| @@ -0,0 +1,97 @@ | |||||
| /* | |||||
| * @Author: 赵伟 | |||||
| * @Date: 2025-09-02 09:52:50 | |||||
| * @Description: 兼容 Antd 颜色设置 | |||||
| */ | |||||
| // 安装依赖:npm i @ant-design/colors | |||||
| import { generate } from '@ant-design/colors'; | |||||
| import { TinyColor } from '@ctrl/tinycolor'; | |||||
| type Options = { | |||||
| /** 是否使用暗色算法(需传背景色,默认按 AntD 暗色背景) */ | |||||
| dark?: boolean; | |||||
| backgroundColor?: string; // 仅 dark 为 true 时生效 | |||||
| }; | |||||
| export function derivePrimaryStates(seed: string, opts: Options = {}) { | |||||
| const { dark = false, backgroundColor = '#141414' } = opts; | |||||
| const palette = generate(seed, dark ? { theme: 'dark', backgroundColor } : undefined); | |||||
| return { | |||||
| // 基础主色 | |||||
| colorPrimary: palette[5], // 主色(第 6 阶) | |||||
| // 状态 | |||||
| colorPrimaryHover: palette[4], // hover(第 5 阶) | |||||
| colorPrimaryActive: palette[6], // active(第 7 阶) | |||||
| colorPrimaryTextHover: palette[4], // 文本 hover | |||||
| colorPrimaryTextActive: palette[6], // 文本 active | |||||
| // 背景 | |||||
| colorPrimaryBg: palette[0], // 浅背景(第 1 阶) | |||||
| colorPrimaryBgHover: palette[1], // 背景 hover(第 2 阶) | |||||
| // 边框 | |||||
| colorPrimaryBorder: palette[2], // 普通边框(第 3 阶) | |||||
| colorPrimaryBorderHover: palette[3], // 边框 hover(第 4 阶) | |||||
| // 文本 | |||||
| colorPrimaryText: palette[5], // 主文本(等同于 colorPrimary) | |||||
| // 备用(有时用于选中态阴影/描边) | |||||
| colorPrimaryShadow: palette[6], | |||||
| }; | |||||
| } | |||||
| export function derivePrimaryStates2(color: string) { | |||||
| const base = new TinyColor(color); | |||||
| return { | |||||
| colorPrimaryHover: base.lighten(10).toHexString(), | |||||
| colorPrimaryActive: base.darken(10).toHexString(), | |||||
| }; | |||||
| } | |||||
| /** | |||||
| * 给颜色值添加透明度. | |||||
| * | |||||
| * @param color - 颜色值, #ff0000、#888 或者 rgb(255, 0, 0) | |||||
| * @param alpha - 透明的,0~1 | |||||
| * @return 颜色值,rgba | |||||
| */ | |||||
| export function addAlpha(color: string, alpha: number): string { | |||||
| const alphaFixed = Math.max(0, Math.min(1, alpha)); // 保证在 [0,1] | |||||
| // #rrggbb 或 #rgb | |||||
| if (color.startsWith('#')) { | |||||
| let r: number, g: number, b: number; | |||||
| if (color.length === 4) { | |||||
| // #rgb | |||||
| r = parseInt(color[1] + color[1], 16); | |||||
| g = parseInt(color[2] + color[2], 16); | |||||
| b = parseInt(color[3] + color[3], 16); | |||||
| } else if (color.length === 7) { | |||||
| // #rrggbb | |||||
| r = parseInt(color.slice(1, 3), 16); | |||||
| g = parseInt(color.slice(3, 5), 16); | |||||
| b = parseInt(color.slice(5, 7), 16); | |||||
| } else { | |||||
| throw new Error('Invalid hex color format'); | |||||
| } | |||||
| return `rgba(${r}, ${g}, ${b}, ${alphaFixed})`; | |||||
| } | |||||
| // rgb(r,g,b) | |||||
| const rgbMatch = color.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/i); | |||||
| if (rgbMatch) { | |||||
| const r = parseInt(rgbMatch[1], 10); | |||||
| const g = parseInt(rgbMatch[2], 10); | |||||
| const b = parseInt(rgbMatch[3], 10); | |||||
| return `rgba(${r}, ${g}, ${b}, ${alphaFixed})`; | |||||
| } | |||||
| throw new Error('Unsupported color format'); | |||||
| } | |||||