diff --git a/config/config.ts b/config/config.ts index 39a2e4de..a79256c0 100644 --- a/config/config.ts +++ b/config/config.ts @@ -11,6 +11,14 @@ export default defineConfig({ 'root-entry-name': 'variable', cssVar: true, hashed: false, + components: { + Input: { + inputFontSize: 12 + }, + Table: { + cellFontSize: 12 + } + }, token: { colorPrimary: '#2fbf85', borderRadius: 20, @@ -32,4 +40,4 @@ export default defineConfig({ layout: false, routes, npmClient: 'pnpm' -}); +}) as any; diff --git a/src/assets/styles/menu.less b/src/assets/styles/menu.less index a123f1eb..a1f0cd83 100644 --- a/src/assets/styles/menu.less +++ b/src/assets/styles/menu.less @@ -1,15 +1,26 @@ .ant-pro-layout { .ant-pro-sider { padding: 10px; - &.ant-layout-sider { - background: var(--color-white-1); - } + &.ant-layout-sider { + background: var(--color-white-1); + } .ant-layout-sider-children { background-color: var(--color-fill-1); border-inline: none; - border-radius: 32px; + border-radius: var(--menu-border-radius-base); padding-inline: 16px; padding-block-end: 12px; } + .umi-plugin-layout-right { + width: 100%; + .umi-plugin-layout-action { + padding: 12px; + width: 100%; + border-radius: var(--menu-border-radius-base); + &:hover { + background-color: var(--color-white-1); + } + } + } } -} \ No newline at end of file +} diff --git a/src/components/page-tools/index.less b/src/components/page-tools/index.less new file mode 100644 index 00000000..87fec37f --- /dev/null +++ b/src/components/page-tools/index.less @@ -0,0 +1,6 @@ +.page-tools { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 70px; +} diff --git a/src/components/page-tools/index.tsx b/src/components/page-tools/index.tsx new file mode 100644 index 00000000..a05e743b --- /dev/null +++ b/src/components/page-tools/index.tsx @@ -0,0 +1,33 @@ +import { useMemo } from 'react'; +import styles from './index.less'; + +type PageToolsProps = { + left?: React.ReactNode; + right?: React.ReactNode; + marginBottom?: number; + marginTop?: number; +}; + +const PageTools: React.FC = (props) => { + const { left, right, marginBottom, marginTop } = props; + + const newStyle: Record = useMemo(() => { + const style: Record = {}; + if (marginBottom) { + style.marginBottom = `${marginBottom}px`; + } + if (marginTop) { + style.marginTop = `${marginTop}px`; + } + return style; + }, [marginBottom, marginTop]); + + return ( +
+
{left}
+
{right}
+
+ ); +}; + +export default PageTools; diff --git a/src/components/seal-form/components/wrapper.less b/src/components/seal-form/components/wrapper.less index f8f2d7b1..b164e4ee 100644 --- a/src/components/seal-form/components/wrapper.less +++ b/src/components/seal-form/components/wrapper.less @@ -18,6 +18,10 @@ cursor: not-allowed; &:hover { border-color: var(--ant-color-border); + :global(.ant-input-search-button) { + border-color: var(--ant-color-border) !important; + color: var(--ant-color-text-description) !important; + } } } @@ -70,7 +74,7 @@ align-items: center; border: none; box-shadow: none; - height: @inputheight; + height: @inputheight !important; } :global(.ant-select-selector) { border: none !important; @@ -79,7 +83,7 @@ box-shadow: none !important; } :global(.ant-select-selection-item) { - height: @inputheight; + height: @inputheight !important; } :global( .ant-select-outlined.ant-select-disabled:not(.ant-select-customize-input) @@ -96,7 +100,7 @@ box-shadow: none; padding-block: 5px; padding-inline: 12px; - height: @inputheight; + height: @inputheight !important; } :global(.ant-input-number) { display: flex; @@ -104,7 +108,7 @@ border: none; box-shadow: none; padding: 0; - height: @inputheight; + height: @inputheight !important; } :global(.ant-input-outlined) { &.seal-textarea { @@ -115,7 +119,7 @@ background-color: transparent; } :global(input.ant-input-number-input) { - height: @inputheight; + height: @inputheight !important; padding-block: 5px; padding-inline: 12px; } @@ -148,6 +152,7 @@ border-left: var(--ant-line-width) var(--ant-line-type) var(--ant-color-border); } + :global(.ant-input-number-handler-wrap) { top: -20px; height: @wrapheight - 2px; diff --git a/src/components/seal-form/input-number.tsx b/src/components/seal-form/input-number.tsx index 7a74a4c2..02606270 100644 --- a/src/components/seal-form/input-number.tsx +++ b/src/components/seal-form/input-number.tsx @@ -56,10 +56,11 @@ const SealInputNumber: React.FC = ( handleChange(e)} + onChange={handleChange} > ); diff --git a/src/components/seal-form/input-search.tsx b/src/components/seal-form/input-search.tsx index df81cfff..25be4bfe 100644 --- a/src/components/seal-form/input-search.tsx +++ b/src/components/seal-form/input-search.tsx @@ -65,10 +65,11 @@ const SealInputSearch: React.FC = (props) => { handleChange(e)} + onChange={handleChange} > ); diff --git a/src/components/seal-form/password.tsx b/src/components/seal-form/password.tsx index ba166686..1be691ff 100644 --- a/src/components/seal-form/password.tsx +++ b/src/components/seal-form/password.tsx @@ -50,9 +50,10 @@ const SealPassword: React.FC = (props) => { handleChange(e)} + onChange={handleChange} > ); diff --git a/src/components/seal-form/seal-input.tsx b/src/components/seal-form/seal-input.tsx index 8fa92ff4..629b4acb 100644 --- a/src/components/seal-form/seal-input.tsx +++ b/src/components/seal-form/seal-input.tsx @@ -1,7 +1,7 @@ import type { InputProps } from 'antd'; import { Form, Input } from 'antd'; import type { TextAreaProps } from 'antd/es/input/TextArea'; -import { useEffect, useRef, useState } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; import Wrapper from './components/wrapper'; import SealInputNumber from './input-number'; import SealInputSearch from './input-search'; @@ -9,7 +9,16 @@ import SealPassword from './password'; import { SealFormItemProps } from './types'; const SealTextArea: React.FC = (props) => { - const { label, placeholder, style, ...rest } = props; + const { + label, + placeholder, + onChange, + onFocus, + onBlur, + onInput, + style, + ...rest + } = props; const [isFocus, setIsFocus] = useState(false); const inputRef = useRef(null); const { status } = Form.Item.useStatus(); @@ -20,32 +29,44 @@ const SealTextArea: React.FC = (props) => { } }, [props.value]); - const handleClickWrapper = () => { + const handleClickWrapper = useCallback(() => { if (!props.disabled && !isFocus) { inputRef.current?.focus?.(); setIsFocus(true); } - }; + }, [props.disabled, isFocus]); - const handleChange = (e: any) => { - props.onChange?.(e); - }; + const handleChange = useCallback( + (e: any) => { + onChange?.(e); + }, + [onChange] + ); - const handleOnFocus = (e: any) => { - setIsFocus(true); - props.onFocus?.(e); - }; + const handleOnFocus = useCallback( + (e: any) => { + setIsFocus(true); + onFocus?.(e); + }, + [onFocus] + ); - const handleOnBlur = (e: any) => { - if (!inputRef.current?.input?.value) { - setIsFocus(false); - props.onBlur?.(e); - } - }; + const handleOnBlur = useCallback( + (e: any) => { + if (!inputRef.current?.input?.value) { + setIsFocus(false); + onBlur?.(e); + } + }, + [onBlur] + ); - const handleInput = (e: any) => { - props.onInput?.(e); - }; + const handleInput = useCallback( + (e: any) => { + onInput?.(e); + }, + [onInput] + ); return ( = (props) => { handleChange(e)} + onChange={handleChange} > ); diff --git a/src/components/seal-form/seal-select.tsx b/src/components/seal-form/seal-select.tsx index 3d05eb3c..807c24e4 100644 --- a/src/components/seal-form/seal-select.tsx +++ b/src/components/seal-form/seal-select.tsx @@ -60,7 +60,7 @@ const SealSelect: React.FC = (props) => { onFocus={handleOnFocus} onBlur={handleOnBlur} onSearch={handleOnSearch} - onChange={(val, options) => handleChange(val, options)} + onChange={handleChange} > {children} diff --git a/src/global.less b/src/global.less index ac098b2d..c193860b 100644 --- a/src/global.less +++ b/src/global.less @@ -1,5 +1,7 @@ html { --color-fill-1: rgba(0, 0, 0, 0.04); + // --color-fill-1: #f3f6fa; + --color-fill-2: #fff; --color-fill-2: #fff; --color-fill-3: #f3f6fa; --menu-border-radius-base: 32px; @@ -11,6 +13,8 @@ html { --color-bg-light-1: #f0fff6; --font-size-base: 12px; --ant-color-fill-secondary: rgba(0, 0, 0, 0.06); + --table-td-radius: 24px; + --checkbox-border-radius: 4px; // --color-text-1: #000; --seal-transition-func: cubic-bezier(0, 0, 1, 1); @@ -39,8 +43,12 @@ html { &.ant-btn { --ant-button-content-font-size-lg: 13px; - --ant-button-content-font-size: 13px; - --ant-button-content-font-size-sm: 13px; + --ant-button-content-font-size: 12px; + --ant-button-content-font-size-sm: 12px; + } + + &.ant-table-css-var { + --ant-table-row-hover-bg: #e6e6e6; } } @@ -57,6 +65,7 @@ html { --ant-input-input-font-size: var(--font-size-base); --ant-input-input-font-size-lg: var(--font-size-base); --ant-input-input-font-size-sm: var(--font-size-base); + --ant-input-padding-inline-lg: 14px; } .css-var-r0.ant-select-css-var { --ant-select-option-active-bg: var(--color-fill-1); @@ -69,7 +78,52 @@ body * { } body { + .ant-checkbox { + .ant-checkbox-inner { + border-radius: var(--checkbox-border-radius) !important; + } + } + + // table + .ant-table-wrapper .ant-table-selection-column { + padding-inline-start: 16px !important; + } + .ant-table-container .ant-table-content table { + border-spacing: 0 20px; + .ant-table-thead th.ant-table-column-sort { + background-color: transparent; + } + .ant-checkbox { + .ant-checkbox-inner::after { + display: flex !important; + } + } + .ant-checkbox-indeterminate .ant-checkbox-inner:after { + display: flex !important; + } + tr > th { + background-color: var(--color-white-1); + border: none; + padding-block: 0px; + } + tr > td { + background-color: var(--color-fill-1); + border-bottom: none; + height: 70px; + &:first-child { + border-top-left-radius: var(--table-td-radius); + border-bottom-left-radius: var(--table-td-radius); + } + &:last-child { + border-top-right-radius: var(--table-td-radius); + border-bottom-right-radius: var(--table-td-radius); + } + } + } // input + .ant-input-css-var.ant-input { + height: 40px; + } .ant-input-outlined.ant-input-status-error:not(.ant-input-disabled) { border: none; box-shadow: none; diff --git a/src/hooks/use-table-row-selection.ts b/src/hooks/use-table-row-selection.ts new file mode 100644 index 00000000..1a87c04c --- /dev/null +++ b/src/hooks/use-table-row-selection.ts @@ -0,0 +1,16 @@ +import { useState } from 'react'; + +export default function useTableRowSelection() { + const [selectedRowKeys, setSelectedRowKeys] = useState([]); + + const onSelectChange = (selectedRowKeys: React.Key[]) => { + setSelectedRowKeys(selectedRowKeys); + }; + + const rowSelection = { + selectedRowKeys, + onChange: onSelectChange + }; + + return rowSelection; +} diff --git a/src/pages/models/index.tsx b/src/pages/models/index.tsx index 2119ca4c..5d4fd72d 100644 --- a/src/pages/models/index.tsx +++ b/src/pages/models/index.tsx @@ -1,16 +1,108 @@ +import PageTools from '@/components/page-tools'; +import useTableRowSelection from '@/hooks/use-table-row-selection'; +import { PlusOutlined, SyncOutlined } from '@ant-design/icons'; import { PageContainer } from '@ant-design/pro-components'; +import { Button, Input, Progress, Space, Table } from 'antd'; +const { Column } = Table; + +const dataSource = [ + { + key: '1', + name: 'llama3:latest', + createTime: '2021-09-01 12:00:00' + }, + { + key: '2', + name: 'meta-llama/Meta-Llama-3-8B', + createTime: '2021-09-01 12:00:00' + }, + { + key: '3', + name: 'apple/OpenELM-3B-Instructor', + createTime: '2021-09-01 12:00:00' + } +]; + +const columns = [ + { + title: '姓名', + dataIndex: 'name', + key: 'name' + }, + { + title: '年龄', + dataIndex: 'age', + key: 'age' + }, + { + title: '住址', + dataIndex: 'address', + key: 'address' + } +]; const Dashboard: React.FC = () => { + const rowSelection = useTableRowSelection(); return ( -
Models
+ + + + + } + right={ +
+ +
+ } + >
+ + { + return ( + <> + {text} + + + ); + }} + /> + a.createTime - b.createTime} + /> + { + return ; + }} + /> +
); }; -export default Dashboard; \ No newline at end of file +export default Dashboard; diff --git a/src/pages/playground/components/chatContent.tsx b/src/pages/playground/components/chatContent.tsx index fb649535..d9129da8 100644 --- a/src/pages/playground/components/chatContent.tsx +++ b/src/pages/playground/components/chatContent.tsx @@ -1,6 +1,11 @@ import avatar from '@/assets/images/avatar.png'; import logo from '@/assets/images/logo.png'; -import { CopyOutlined, DislikeOutlined, EditOutlined, SyncOutlined } from '@ant-design/icons'; +import { + CopyOutlined, + DislikeOutlined, + EditOutlined, + SyncOutlined +} from '@ant-design/icons'; import { Button, Space, Tooltip } from 'antd'; import chatStyle from './chat-style.less'; import ChatEmpty from './chatEmpty'; diff --git a/src/pages/playground/components/messageInput.tsx b/src/pages/playground/components/messageInput.tsx index e50d1515..6c83d546 100644 --- a/src/pages/playground/components/messageInput.tsx +++ b/src/pages/playground/components/messageInput.tsx @@ -1,26 +1,43 @@ -import { Input,Button} from 'antd'; -import { useState } from 'react'; import { SendOutlined } from '@ant-design/icons'; -import './message-input.less' +import { Button, Input } from 'antd'; +import { useState } from 'react'; +import './message-input.less'; const MessageInput: React.FC = () => { const { TextArea } = Input; - const [message, setMessage] = useState('') - const handleInputChange = (value:string) => { - setMessage(value) - } + const [message, setMessage] = useState(''); + const handleInputChange = (value: string) => { + setMessage(value); + }; const handleSendMessage = () => { - console.log('send message:', message) - } + console.log('send message:', message); + }; const SendButton: React.FC = () => { - return - } + return ( + + ); + }; return (
- - + + + +
); }; -export default MessageInput; \ No newline at end of file +export default MessageInput;