✨ feat: enhance SelectableButtonGroup with checkbox support and refactor pricing display settings (#1365)
- Add withCheckbox prop to SelectableButtonGroup component for checkbox-prefixed buttons - Support both single value and array activeValue for multi-selection scenarios - Refactor PricingDisplaySettings to use consistent SelectableButtonGroup styling - Replace Switch components with checkbox-enabled SelectableButtonGroup - Replace Select dropdown with SelectableButtonGroup for currency selection - Maintain unified UI/UX across all pricing filter components - Add proper JSDoc documentation for new withCheckbox functionality This improves visual consistency and provides a more cohesive user experience in the model pricing filter interface.
This commit is contained in:
@@ -19,7 +19,7 @@ For commercial licensing, please contact support@quantumnous.com
|
|||||||
|
|
||||||
import React, { useState, useRef } from 'react';
|
import React, { useState, useRef } from 'react';
|
||||||
import { useIsMobile } from '../../../hooks/common/useIsMobile';
|
import { useIsMobile } from '../../../hooks/common/useIsMobile';
|
||||||
import { Divider, Button, Tag, Row, Col, Collapsible } from '@douyinfe/semi-ui';
|
import { Divider, Button, Tag, Row, Col, Collapsible, Checkbox } from '@douyinfe/semi-ui';
|
||||||
import { IconChevronDown, IconChevronUp } from '@douyinfe/semi-icons';
|
import { IconChevronDown, IconChevronUp } from '@douyinfe/semi-icons';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -27,12 +27,13 @@ import { IconChevronDown, IconChevronUp } from '@douyinfe/semi-icons';
|
|||||||
*
|
*
|
||||||
* @param {string} title 标题
|
* @param {string} title 标题
|
||||||
* @param {Array<{value:any,label:string,icon?:React.ReactNode,tagCount?:number}>} items 按钮项
|
* @param {Array<{value:any,label:string,icon?:React.ReactNode,tagCount?:number}>} items 按钮项
|
||||||
* @param {*} activeValue 当前激活的值
|
* @param {*|Array} activeValue 当前激活的值,可以是单个值或数组(多选)
|
||||||
* @param {(value:any)=>void} onChange 选择改变回调
|
* @param {(value:any)=>void} onChange 选择改变回调
|
||||||
* @param {function} t i18n
|
* @param {function} t i18n
|
||||||
* @param {object} style 额外样式
|
* @param {object} style 额外样式
|
||||||
* @param {boolean} collapsible 是否支持折叠,默认true
|
* @param {boolean} collapsible 是否支持折叠,默认true
|
||||||
* @param {number} collapseHeight 折叠时的高度,默认200
|
* @param {number} collapseHeight 折叠时的高度,默认200
|
||||||
|
* @param {boolean} withCheckbox 是否启用前缀 Checkbox 来控制激活状态
|
||||||
*/
|
*/
|
||||||
const SelectableButtonGroup = ({
|
const SelectableButtonGroup = ({
|
||||||
title,
|
title,
|
||||||
@@ -42,7 +43,8 @@ const SelectableButtonGroup = ({
|
|||||||
t = (v) => v,
|
t = (v) => v,
|
||||||
style = {},
|
style = {},
|
||||||
collapsible = true,
|
collapsible = true,
|
||||||
collapseHeight = 200
|
collapseHeight = 200,
|
||||||
|
withCheckbox = false
|
||||||
}) => {
|
}) => {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
@@ -82,7 +84,52 @@ const SelectableButtonGroup = ({
|
|||||||
const contentElement = (
|
const contentElement = (
|
||||||
<Row gutter={[8, 8]} style={{ lineHeight: '32px', ...style }} ref={contentRef}>
|
<Row gutter={[8, 8]} style={{ lineHeight: '32px', ...style }} ref={contentRef}>
|
||||||
{items.map((item) => {
|
{items.map((item) => {
|
||||||
const isActive = activeValue === item.value;
|
const isActive = Array.isArray(activeValue)
|
||||||
|
? activeValue.includes(item.value)
|
||||||
|
: activeValue === item.value;
|
||||||
|
|
||||||
|
// 当启用前缀 Checkbox 时,按钮本身不可点击,仅 Checkbox 可控制状态切换
|
||||||
|
if (withCheckbox) {
|
||||||
|
return (
|
||||||
|
<Col
|
||||||
|
{...(isMobile
|
||||||
|
? { span: 12 }
|
||||||
|
: { xs: 24, sm: 24, md: 24, lg: 12, xl: 8 }
|
||||||
|
)}
|
||||||
|
key={item.value}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
onClick={() => { /* disabled */ }}
|
||||||
|
theme={isActive ? 'light' : 'outline'}
|
||||||
|
type={isActive ? 'primary' : 'tertiary'}
|
||||||
|
icon={
|
||||||
|
<Checkbox
|
||||||
|
checked={isActive}
|
||||||
|
onChange={() => onChange(item.value)}
|
||||||
|
style={{ pointerEvents: 'auto' }}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
style={{ width: '100%', cursor: 'default' }}
|
||||||
|
>
|
||||||
|
{item.icon && (
|
||||||
|
<span style={{ marginRight: 4 }}>{item.icon}</span>
|
||||||
|
)}
|
||||||
|
<span style={{ marginRight: item.tagCount !== undefined ? 4 : 0 }}>{item.label}</span>
|
||||||
|
{item.tagCount !== undefined && (
|
||||||
|
<Tag
|
||||||
|
color='white'
|
||||||
|
shape="circle"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
{item.tagCount}
|
||||||
|
</Tag>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</Col>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认行为
|
||||||
return (
|
return (
|
||||||
<Col
|
<Col
|
||||||
{...(isMobile
|
{...(isMobile
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ For commercial licensing, please contact support@quantumnous.com
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Divider, Switch, Select, Tooltip } from '@douyinfe/semi-ui';
|
import { Tooltip } from '@douyinfe/semi-ui';
|
||||||
|
import SelectableButtonGroup from '../../../common/ui/SelectableButtonGroup';
|
||||||
import { IconHelpCircle } from '@douyinfe/semi-icons';
|
import { IconHelpCircle } from '@douyinfe/semi-icons';
|
||||||
|
|
||||||
const PricingDisplaySettings = ({
|
const PricingDisplaySettings = ({
|
||||||
@@ -30,51 +31,69 @@ const PricingDisplaySettings = ({
|
|||||||
setShowRatio,
|
setShowRatio,
|
||||||
t
|
t
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
const items = [
|
||||||
<div className="mb-6">
|
{
|
||||||
<Divider margin='12px' align='left'>
|
value: 'recharge',
|
||||||
{t('显示设置')}
|
label: t('以充值价格显示')
|
||||||
</Divider>
|
},
|
||||||
<div className="px-2">
|
{
|
||||||
<div className="flex items-center justify-between mb-3">
|
value: 'ratio',
|
||||||
<span className="text-sm text-gray-700">{t('以充值价格显示')}</span>
|
label: (
|
||||||
<Switch
|
<span className="flex items-center gap-1">
|
||||||
checked={showWithRecharge}
|
{t('显示倍率')}
|
||||||
onChange={setShowWithRecharge}
|
<Tooltip content={t('倍率是用于系统计算不同模型的最终价格用的,如果您不理解倍率,请忽略')}>
|
||||||
size="small"
|
<IconHelpCircle
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{showWithRecharge && (
|
|
||||||
<div className="mt-2 mb-3">
|
|
||||||
<div className="text-xs text-gray-500 mb-1">{t('货币单位')}</div>
|
|
||||||
<Select
|
|
||||||
value={currency}
|
|
||||||
onChange={setCurrency}
|
|
||||||
size="small"
|
size="small"
|
||||||
className="w-full"
|
style={{ color: 'var(--semi-color-text-2)', cursor: 'help' }}
|
||||||
>
|
/>
|
||||||
<Select.Option value="USD">USD ($)</Select.Option>
|
</Tooltip>
|
||||||
<Select.Option value="CNY">CNY (¥)</Select.Option>
|
</span>
|
||||||
</Select>
|
),
|
||||||
</div>
|
}
|
||||||
)}
|
];
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<div className="flex items-center gap-1">
|
const currencyItems = [
|
||||||
<span className="text-sm text-gray-700">{t('显示倍率')}</span>
|
{ value: 'USD', label: 'USD ($)' },
|
||||||
<Tooltip content={t('倍率是用于系统计算不同模型的最终价格用的,如果您不理解倍率,请忽略')}>
|
{ value: 'CNY', label: 'CNY (¥)' }
|
||||||
<IconHelpCircle
|
];
|
||||||
size="small"
|
|
||||||
style={{ color: 'var(--semi-color-text-2)', cursor: 'help' }}
|
const handleChange = (value) => {
|
||||||
/>
|
if (value === 'recharge') {
|
||||||
</Tooltip>
|
setShowWithRecharge(!showWithRecharge);
|
||||||
</div>
|
} else if (value === 'ratio') {
|
||||||
<Switch
|
setShowRatio(!showRatio);
|
||||||
checked={showRatio}
|
}
|
||||||
onChange={setShowRatio}
|
};
|
||||||
size="small"
|
|
||||||
/>
|
const getActiveValues = () => {
|
||||||
</div>
|
const activeValues = [];
|
||||||
</div>
|
if (showWithRecharge) activeValues.push('recharge');
|
||||||
|
if (showRatio) activeValues.push('ratio');
|
||||||
|
return activeValues;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<SelectableButtonGroup
|
||||||
|
title={t('显示设置')}
|
||||||
|
items={items}
|
||||||
|
activeValue={getActiveValues()}
|
||||||
|
onChange={handleChange}
|
||||||
|
withCheckbox
|
||||||
|
collapsible={false}
|
||||||
|
t={t}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{showWithRecharge && (
|
||||||
|
<SelectableButtonGroup
|
||||||
|
title={t('货币单位')}
|
||||||
|
items={currencyItems}
|
||||||
|
activeValue={currency}
|
||||||
|
onChange={setCurrency}
|
||||||
|
collapsible={false}
|
||||||
|
t={t}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user