diff --git a/react-ui/src/assets/img/popover-bg.png b/react-ui/src/assets/img/popover-bg.png new file mode 100644 index 00000000..d783c637 Binary files /dev/null and b/react-ui/src/assets/img/popover-bg.png differ diff --git a/react-ui/src/iconfont/iconfont.js b/react-ui/src/iconfont/iconfont.js index d7576e9c..75c1b755 100644 --- a/react-ui/src/iconfont/iconfont.js +++ b/react-ui/src/iconfont/iconfont.js @@ -1 +1 @@ -window._iconfont_svg_string_4511447='',(t=>{var a=(h=(h=document.getElementsByTagName("script"))[h.length-1]).getAttribute("data-injectcss"),h=h.getAttribute("data-disable-injectsvg");if(!h){var l,z,v,i,o,m=function(a,h){h.parentNode.insertBefore(a,h)};if(a&&!t.__iconfont__svg__cssinject__){t.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}l=function(){var a,h=document.createElement("div");h.innerHTML=t._iconfont_svg_string_4511447,(h=h.getElementsByTagName("svg")[0])&&(h.setAttribute("aria-hidden","true"),h.style.position="absolute",h.style.width=0,h.style.height=0,h.style.overflow="hidden",h=h,(a=document.body).firstChild?m(h,a.firstChild):a.appendChild(h))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(l,0):(z=function(){document.removeEventListener("DOMContentLoaded",z,!1),l()},document.addEventListener("DOMContentLoaded",z,!1)):document.attachEvent&&(v=l,i=t.document,o=!1,d(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,p())})}function p(){o||(o=!0,v())}function d(){try{i.documentElement.doScroll("left")}catch(a){return void setTimeout(d,50)}p()}})(window); \ No newline at end of file +window._iconfont_svg_string_4511447='',(t=>{var a=(h=(h=document.getElementsByTagName("script"))[h.length-1]).getAttribute("data-injectcss"),h=h.getAttribute("data-disable-injectsvg");if(!h){var l,z,v,i,o,m=function(a,h){h.parentNode.insertBefore(a,h)};if(a&&!t.__iconfont__svg__cssinject__){t.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}l=function(){var a,h=document.createElement("div");h.innerHTML=t._iconfont_svg_string_4511447,(h=h.getElementsByTagName("svg")[0])&&(h.setAttribute("aria-hidden","true"),h.style.position="absolute",h.style.width=0,h.style.height=0,h.style.overflow="hidden",h=h,(a=document.body).firstChild?m(h,a.firstChild):a.appendChild(h))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(l,0):(z=function(){document.removeEventListener("DOMContentLoaded",z,!1),l()},document.addEventListener("DOMContentLoaded",z,!1)):document.attachEvent&&(v=l,i=t.document,o=!1,d(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,p())})}function p(){o||(o=!0,v())}function d(){try{i.documentElement.doScroll("left")}catch(a){return void setTimeout(d,50)}p()}})(window); \ No newline at end of file diff --git a/react-ui/src/pages/HyperParameter/components/CreateForm/ParameterRange/index.less b/react-ui/src/pages/HyperParameter/components/CreateForm/ParameterRange/index.less index d49089f5..61091050 100644 --- a/react-ui/src/pages/HyperParameter/components/CreateForm/ParameterRange/index.less +++ b/react-ui/src/pages/HyperParameter/components/CreateForm/ParameterRange/index.less @@ -1,13 +1,47 @@ .parameter-range { - width: 300px; - &__list { - width: 100%; - max-height: 300px; - overflow-x: visible; - overflow-y: auto; + width: 360px; + &__type { + margin-bottom: 10px; + color: @text-color-secondary; + font-size: @font-size-input; + &::before { + display: inline-block; + color: @error-color; + font-size: 14px; + font-family: SimSun, sans-serif; + line-height: 1; + content: '*'; + margin-inline-end: 4px; + } + } + &__desc { + margin-bottom: 20px; + padding: 4px 8px; + color: @text-color-tertiary; + font-size: 13px; + background: rgba(62, 96, 163, 0.05); + border-radius: 6px; } - &__button { - margin-bottom: 0; - text-align: center; + &__form { + width: 100%; + &__list { + width: 100%; + max-height: 300px; + overflow-x: visible; + overflow-y: auto; + } + &__space { + flex: none; + width: 22px; + color: @text-color-tertiary; + font-size: @font-size-input; + line-height: 32px; + text-align: center; + } + &__button { + width: 100%; + margin-bottom: 0; + text-align: center; + } } } diff --git a/react-ui/src/pages/HyperParameter/components/CreateForm/ParameterRange/index.tsx b/react-ui/src/pages/HyperParameter/components/CreateForm/ParameterRange/index.tsx index 240e90e6..e4b700c9 100644 --- a/react-ui/src/pages/HyperParameter/components/CreateForm/ParameterRange/index.tsx +++ b/react-ui/src/pages/HyperParameter/components/CreateForm/ParameterRange/index.tsx @@ -1,16 +1,16 @@ import { MinusCircleOutlined, PlusCircleOutlined } from '@ant-design/icons'; import { Button, Flex, Form, Input, InputNumber } from 'antd'; -import { ParameterType, getFormOptions } from '../utils'; +import { ParameterType, getFormOptions, parameterTooltip } from '../utils'; import styles from './index.less'; type ParameterRangeProps = { - type?: ParameterType; + type: ParameterType; value?: any[]; onCancel?: () => void; onConfirm?: (value: any[]) => void; }; -function ParameterRange({ type, value, onCancel, onConfirm }: ParameterRangeProps) { +function ParameterRange({ type, value, onConfirm }: ParameterRangeProps) { const [form] = Form.useForm(); const isList = type === ParameterType.Choice || type === ParameterType.Grid; const formOptions = getFormOptions(type, value); @@ -33,108 +33,119 @@ function ParameterRange({ type, value, onCancel, onConfirm }: ParameterRangeProp }; return ( -
- {isList ? ( -
- - {(fields, { add, remove }) => ( - <> - {fields.map(({ key, name, ...restField }, index) => ( - - - - - - - {index === fields.length - 1 && ( +
+
{type}
+
{parameterTooltip[type]}
+ + {isList ? ( +
+ + {(fields, { add, remove }) => ( + <> + {fields.map(({ key, name, ...restField }, index) => ( + + + + + - )} + {index === fields.length - 1 && ( + + )} + - - ))} - {fields.length === 0 && ( - - + ))} + {fields.length === 0 && ( + + + + )} + + )} + +
+ ) : ( + + {formOptions.map((item, index) => { + return ( + <> + + - )} - - )} - -
- ) : ( - formOptions.map((item) => { - return ( - - - - ); - }) - )} - - - - - + {index !== formOptions.length - 1 && ( + + {index === 0 ? '-' : ' '} + + )} + + ); + })} +
+ )} + + + + +
); } diff --git a/react-ui/src/pages/HyperParameter/components/CreateForm/PopParameterRange/index.less b/react-ui/src/pages/HyperParameter/components/CreateForm/PopParameterRange/index.less index 1d8609d3..92080c3e 100644 --- a/react-ui/src/pages/HyperParameter/components/CreateForm/PopParameterRange/index.less +++ b/react-ui/src/pages/HyperParameter/components/CreateForm/PopParameterRange/index.less @@ -1,14 +1,23 @@ .parameter-range { + border-radius: 18px; + box-shadow: 0px 3px 10px rgba(22, 100, 255, 0.15); :global { - .ant-popover-inner { - padding: 20px 20px 12px; - } - .ant-popconfirm-description { - padding-top: 20px; - } + .ant-popover-content { + .ant-popover-inner { + width: 400px; + padding: 20px 20px 12px; + background-image: url(@/assets/img/popover-bg.png); + background-repeat: no-repeat; + background-position: top left; + background-size: 100% auto; + } + .ant-popconfirm-description { + margin-top: 20px; + } - .ant-popconfirm-buttons { - display: none; + .ant-popconfirm-buttons { + display: none; + } } } @@ -58,3 +67,17 @@ } } } + +.parameter-range-title { + color: @text-color; + font-weight: 500; + font-size: @font-size-content; +} + +.parameter-range-title-icon { + color: @text-color-secondary; + + &:hover { + color: @text-color; + } +} diff --git a/react-ui/src/pages/HyperParameter/components/CreateForm/PopParameterRange/index.tsx b/react-ui/src/pages/HyperParameter/components/CreateForm/PopParameterRange/index.tsx index eb647f3a..b5db36b9 100644 --- a/react-ui/src/pages/HyperParameter/components/CreateForm/PopParameterRange/index.tsx +++ b/react-ui/src/pages/HyperParameter/components/CreateForm/PopParameterRange/index.tsx @@ -1,6 +1,6 @@ import KFIcon from '@/components/KFIcon'; import { isEmpty } from '@/utils'; -import { Popconfirm, Typography } from 'antd'; +import { Flex, Popconfirm, Typography } from 'antd'; import classNames from 'classnames'; import { useEffect, useRef, useState } from 'react'; import ParameterRange from '../ParameterRange'; @@ -8,7 +8,7 @@ import { ParameterType } from '../utils'; import styles from './index.less'; type ParameterRangeProps = { - type?: ParameterType; + type: ParameterType; value?: any[]; onChange?: (value: any[]) => void; }; @@ -58,18 +58,11 @@ function PopParameterRange({ type, value, onChange }: ParameterRangeProps) {
} disabled={disabled} description={ - + } - okText="确定" - cancelText="取消" overlayClassName={styles['parameter-range']} icon={null} open={open} @@ -95,4 +88,18 @@ function PopParameterRange({ type, value, onChange }: ParameterRangeProps) { ); } +function PopconfirmTitle({ title, onClose }: { title: string; onClose: () => void }) { + return ( + + {title} + + + ); +} + export default PopParameterRange; diff --git a/react-ui/src/pages/HyperParameter/components/CreateForm/index.less b/react-ui/src/pages/HyperParameter/components/CreateForm/index.less index 5c91d2fc..06bbd5b7 100644 --- a/react-ui/src/pages/HyperParameter/components/CreateForm/index.less +++ b/react-ui/src/pages/HyperParameter/components/CreateForm/index.less @@ -41,7 +41,7 @@ &::before { display: inline-block; - color: #c73131; + color: @error-color; font-size: 14px; font-family: SimSun, sans-serif; line-height: 1; diff --git a/react-ui/src/pages/HyperParameter/components/CreateForm/utils.ts b/react-ui/src/pages/HyperParameter/components/CreateForm/utils.ts index f3f92555..558637e9 100644 --- a/react-ui/src/pages/HyperParameter/components/CreateForm/utils.ts +++ b/react-ui/src/pages/HyperParameter/components/CreateForm/utils.ts @@ -38,6 +38,27 @@ export const axParameterOptions = ['fixed', 'range', 'choice'].map((name) => ({ value: name, })); +export const parameterTooltip: Record = { + [ParameterType.Uniform]: '在 low 和 high 之间均匀采样浮点数', + [ParameterType.QUniform]: '在 low 和 high 之间均匀采样浮点数,四舍五入到 q 的倍数', + [ParameterType.LogUniform]: '在 low 和 high 之间均匀采样浮点数,对数空间采样', + [ParameterType.QLogUniform]: + '在 low 和 high 之间均匀采样浮点数,对数空间采样并四舍五入到 q 的倍数', + [ParameterType.Randn]: '在均值为 m,方差为 s 的正态分布中进行随机浮点数抽样', + [ParameterType.QRandn]: + '在均值为 m,方差为 s 的正态分布中进行随机浮点数抽样,四舍五入到 q 的倍数', + [ParameterType.RandInt]: '在 low(包括)到 high(不包括)之间均匀采样整数', + [ParameterType.QRandInt]: + '在 low(包括)到 high(不包括)之间均匀采样整数,四舍五入到 q 的倍数(包括 high)', + [ParameterType.LogRandInt]: '在 low(包括)到 high(不包括)之间对数空间上均匀采样整数', + [ParameterType.QLogRandInt]: + '在 low(包括)到 high(不包括)之间对数空间上均匀采样整数,并四舍五入到 q 的倍数', + [ParameterType.Choice]: '从指定的选项中采样一个选项', + [ParameterType.Grid]: '对选项进行网格搜索,每个值都将被采样', + [ParameterType.Range]: '在 low 和 high 范围内采样取值', + [ParameterType.Fixed]: '固定取值', +}; + export type ParameterData = { label: string; name: string; @@ -69,12 +90,12 @@ export const getFormOptions = (type?: ParameterType, value?: number[]): Paramete case ParameterType.Range: return [ { - name: 'min', + name: 'low', label: '最小值', value: numbers?.[0], }, { - name: 'max', + name: 'high', label: '最大值', value: numbers?.[1], }, @@ -85,12 +106,12 @@ export const getFormOptions = (type?: ParameterType, value?: number[]): Paramete case ParameterType.QLogRandInt: return [ { - name: 'min', + name: 'low', label: '最小值', value: numbers?.[0], }, { - name: 'max', + name: 'high', label: '最大值', value: numbers?.[1], }, @@ -103,12 +124,12 @@ export const getFormOptions = (type?: ParameterType, value?: number[]): Paramete case ParameterType.Randn: return [ { - name: 'mean', + name: 'm', label: '均值', value: numbers?.[0], }, { - name: 'std', + name: 's', label: '方差', value: numbers?.[1], }, @@ -116,12 +137,12 @@ export const getFormOptions = (type?: ParameterType, value?: number[]): Paramete case ParameterType.QRandn: return [ { - name: 'mean', + name: 'm', label: '均值', value: numbers?.[0], }, { - name: 'std', + name: 's', label: '方差', value: numbers?.[1], },