Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
new-api
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
bd6b7286
authored
Mar 04, 2026
by
CaIon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: enhance PricingTags and SelectableButtonGroup with new badge styles and color variants
parent
6f818574
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
131 additions
and
52 deletions
+131
-52
web/src/components/common/ui/SelectableButtonGroup.jsx
+8
-23
web/src/components/table/model-pricing/filter/PricingEndpointTypes.jsx
+1
-2
web/src/components/table/model-pricing/filter/PricingGroups.jsx
+4
-4
web/src/components/table/model-pricing/filter/PricingQuotaTypes.jsx
+1
-0
web/src/components/table/model-pricing/filter/PricingTags.jsx
+1
-2
web/src/components/table/model-pricing/filter/PricingVendors.jsx
+1
-3
web/src/components/table/model-pricing/layout/PricingSidebar.jsx
+9
-9
web/src/components/table/model-pricing/modal/components/FilterModalContent.jsx
+10
-9
web/src/index.css
+96
-0
No files found.
web/src/components/common/ui/SelectableButtonGroup.jsx
View file @
bd6b7286
...
...
@@ -23,7 +23,6 @@ import { useContainerWidth } from '../../../hooks/common/useContainerWidth';
import
{
Divider
,
Button
,
Tag
,
Row
,
Col
,
Collapsible
,
...
...
@@ -46,6 +45,7 @@ import { IconChevronDown, IconChevronUp } from '@douyinfe/semi-icons';
* @param {number} collapseHeight 折叠时的高度,默认200
* @param {boolean} withCheckbox 是否启用前缀 Checkbox 来控制激活状态
* @param {boolean} loading 是否处于加载状态
* @param {string} variant 颜色变体: 'violet' | 'teal' | 'amber' | 'rose' | 'green',不传则使用默认蓝色
*/
const
SelectableButtonGroup
=
({
title
,
...
...
@@ -58,6 +58,7 @@ const SelectableButtonGroup = ({
collapseHeight
=
200
,
withCheckbox
=
false
,
loading
=
false
,
variant
,
})
=>
{
const
[
isOpen
,
setIsOpen
]
=
useState
(
false
);
const
[
skeletonCount
]
=
useState
(
12
);
...
...
@@ -178,9 +179,6 @@ const SelectableButtonGroup = ({
)
:
(
<
Row
gutter=
{
gutterSize
}
style=
{
{
lineHeight
:
'32px'
,
...
style
}
}
>
{
items
.
map
((
item
)
=>
{
const
isDisabled
=
item
.
disabled
||
(
typeof
item
.
tagCount
===
'number'
&&
item
.
tagCount
===
0
);
const
isActive
=
Array
.
isArray
(
activeValue
)
?
activeValue
.
includes
(
item
.
value
)
:
activeValue
===
item
.
value
;
...
...
@@ -194,13 +192,11 @@ const SelectableButtonGroup = ({
}
}
theme=
{
isActive
?
'light'
:
'outline'
}
type=
{
isActive
?
'primary'
:
'tertiary'
}
disabled=
{
isDisabled
}
className=
'sbg-button'
icon=
{
<
Checkbox
checked=
{
isActive
}
onChange=
{
()
=>
onChange
(
item
.
value
)
}
disabled=
{
isDisabled
}
style=
{
{
pointerEvents
:
'auto'
}
}
/>
}
...
...
@@ -210,14 +206,9 @@ const SelectableButtonGroup = ({
{
item
.
icon
&&
<
span
className=
'sbg-icon'
>
{
item
.
icon
}
</
span
>
}
<
ConditionalTooltipText
text=
{
item
.
label
}
/>
{
item
.
tagCount
!==
undefined
&&
shouldShowTags
&&
(
<
Tag
className=
'sbg-tag'
color=
'white'
shape=
'circle'
size=
'small'
>
<
span
className=
{
`sbg-badge ${isActive ? 'sbg-badge-active' : ''}`
}
>
{
item
.
tagCount
}
</
Tag
>
</
span
>
)
}
</
div
>
</
Button
>
...
...
@@ -231,22 +222,16 @@ const SelectableButtonGroup = ({
onClick=
{
()
=>
onChange
(
item
.
value
)
}
theme=
{
isActive
?
'light'
:
'outline'
}
type=
{
isActive
?
'primary'
:
'tertiary'
}
disabled=
{
isDisabled
}
className=
'sbg-button'
style=
{
{
width
:
'100%'
}
}
>
<
div
className=
'sbg-content'
>
{
item
.
icon
&&
<
span
className=
'sbg-icon'
>
{
item
.
icon
}
</
span
>
}
<
ConditionalTooltipText
text=
{
item
.
label
}
/>
{
item
.
tagCount
!==
undefined
&&
shouldShowTags
&&
(
<
Tag
className=
'sbg-tag'
color=
'white'
shape=
'circle'
size=
'small'
>
{
item
.
tagCount
!==
undefined
&&
shouldShowTags
&&
item
.
tagCount
!==
''
&&
(
<
span
className=
{
`sbg-badge ${isActive ? 'sbg-badge-active' : ''}`
}
>
{
item
.
tagCount
}
</
Tag
>
</
span
>
)
}
</
div
>
</
Button
>
...
...
@@ -258,7 +243,7 @@ const SelectableButtonGroup = ({
return
(
<
div
className=
{
`mb-8 ${containerWidth <= 400 ? 'sbg-compact' : ''}`
}
className=
{
`mb-8 ${containerWidth <= 400 ? 'sbg-compact' : ''}
${variant ? `
sbg
-
variant
-
$
{
variant
}
` : ''}
`
}
ref=
{
containerRef
}
>
{
title
&&
(
...
...
web/src/components/table/model-pricing/filter/PricingEndpointTypes.jsx
View file @
bd6b7286
...
...
@@ -76,7 +76,6 @@ const PricingEndpointTypes = ({
value
:
'all'
,
label
:
t
(
'全部端点'
),
tagCount
:
getEndpointTypeCount
(
'all'
),
disabled
:
models
.
length
===
0
,
},
...
availableEndpointTypes
.
map
((
endpointType
)
=>
{
const
count
=
getEndpointTypeCount
(
endpointType
);
...
...
@@ -84,7 +83,6 @@ const PricingEndpointTypes = ({
value
:
endpointType
,
label
:
getEndpointTypeLabel
(
endpointType
),
tagCount
:
count
,
disabled
:
count
===
0
,
};
}),
];
...
...
@@ -96,6 +94,7 @@ const PricingEndpointTypes = ({
activeValue=
{
filterEndpointType
}
onChange=
{
setFilterEndpointType
}
loading=
{
loading
}
variant=
'green'
t=
{
t
}
/>
);
...
...
web/src/components/table/model-pricing/filter/PricingGroups.jsx
View file @
bd6b7286
...
...
@@ -52,20 +52,19 @@ const PricingGroups = ({
.
length
;
let
ratioDisplay
=
''
;
if
(
g
===
'all'
)
{
ratioDisplay
=
t
(
'全部'
);
//
ratioDisplay = t('全部');
}
else
{
const
ratio
=
groupRatio
[
g
];
if
(
ratio
!==
undefined
&&
ratio
!==
null
)
{
ratioDisplay
=
`
x
${
ratio
}
`
;
ratioDisplay
=
`
${
ratio
}
x
`
;
}
else
{
ratioDisplay
=
'
x1
'
;
ratioDisplay
=
'
1x
'
;
}
}
return
{
value
:
g
,
label
:
g
===
'all'
?
t
(
'全部分组'
)
:
g
,
tagCount
:
ratioDisplay
,
disabled
:
modelCount
===
0
,
};
});
...
...
@@ -76,6 +75,7 @@ const PricingGroups = ({
activeValue=
{
filterGroup
}
onChange=
{
setFilterGroup
}
loading=
{
loading
}
variant=
'teal'
t=
{
t
}
/>
);
...
...
web/src/components/table/model-pricing/filter/PricingQuotaTypes.jsx
View file @
bd6b7286
...
...
@@ -52,6 +52,7 @@ const PricingQuotaTypes = ({
activeValue=
{
filterQuotaType
}
onChange=
{
setFilterQuotaType
}
loading=
{
loading
}
variant=
'amber'
t=
{
t
}
/>
);
...
...
web/src/components/table/model-pricing/filter/PricingTags.jsx
View file @
bd6b7286
...
...
@@ -78,7 +78,6 @@ const PricingTags = ({
value
:
'all'
,
label
:
t
(
'全部标签'
),
tagCount
:
getTagCount
(
'all'
),
disabled
:
models
.
length
===
0
,
},
];
...
...
@@ -88,7 +87,6 @@ const PricingTags = ({
value
:
tag
,
label
:
tag
,
tagCount
:
count
,
disabled
:
count
===
0
,
});
});
...
...
@@ -102,6 +100,7 @@ const PricingTags = ({
activeValue=
{
filterTag
}
onChange=
{
setFilterTag
}
loading=
{
loading
}
variant=
'rose'
t=
{
t
}
/>
);
...
...
web/src/components/table/model-pricing/filter/PricingVendors.jsx
View file @
bd6b7286
...
...
@@ -83,7 +83,6 @@ const PricingVendors = ({
value
:
'all'
,
label
:
t
(
'全部供应商'
),
tagCount
:
getVendorCount
(
'all'
),
disabled
:
models
.
length
===
0
,
},
];
...
...
@@ -96,7 +95,6 @@ const PricingVendors = ({
label
:
vendor
,
icon
:
icon
?
getLobeHubIcon
(
icon
,
16
)
:
null
,
tagCount
:
count
,
disabled
:
count
===
0
,
});
});
...
...
@@ -107,7 +105,6 @@ const PricingVendors = ({
value
:
'unknown'
,
label
:
t
(
'未知供应商'
),
tagCount
:
count
,
disabled
:
count
===
0
,
});
}
...
...
@@ -121,6 +118,7 @@ const PricingVendors = ({
activeValue=
{
filterVendor
}
onChange=
{
setFilterVendor
}
loading=
{
loading
}
variant=
'violet'
t=
{
t
}
/>
);
...
...
web/src/components/table/model-pricing/layout/PricingSidebar.jsx
View file @
bd6b7286
...
...
@@ -113,15 +113,6 @@ const PricingSidebar = ({
t=
{
t
}
/>
<
PricingTags
filterTag=
{
filterTag
}
setFilterTag=
{
setFilterTag
}
models=
{
tagModels
}
allModels=
{
categoryProps
.
models
}
loading=
{
loading
}
t=
{
t
}
/>
<
PricingGroups
filterGroup=
{
filterGroup
}
setFilterGroup=
{
handleGroupClick
}
...
...
@@ -140,6 +131,15 @@ const PricingSidebar = ({
t=
{
t
}
/>
<
PricingTags
filterTag=
{
filterTag
}
setFilterTag=
{
setFilterTag
}
models=
{
tagModels
}
allModels=
{
categoryProps
.
models
}
loading=
{
loading
}
t=
{
t
}
/>
<
PricingEndpointTypes
filterEndpointType=
{
filterEndpointType
}
setFilterEndpointType=
{
setFilterEndpointType
}
...
...
web/src/components/table/model-pricing/modal/components/FilterModalContent.jsx
View file @
bd6b7286
...
...
@@ -96,15 +96,6 @@ const FilterModalContent = ({ sidebarProps, t }) => {
t=
{
t
}
/>
<
PricingTags
filterTag=
{
filterTag
}
setFilterTag=
{
setFilterTag
}
models=
{
tagModels
}
allModels=
{
categoryProps
.
models
}
loading=
{
loading
}
t=
{
t
}
/>
<
PricingGroups
filterGroup=
{
filterGroup
}
setFilterGroup=
{
setFilterGroup
}
...
...
@@ -123,6 +114,16 @@ const FilterModalContent = ({ sidebarProps, t }) => {
t=
{
t
}
/>
<
PricingTags
filterTag=
{
filterTag
}
setFilterTag=
{
setFilterTag
}
models=
{
tagModels
}
allModels=
{
categoryProps
.
models
}
loading=
{
loading
}
t=
{
t
}
/>
<
PricingEndpointTypes
filterEndpointType=
{
filterEndpointType
}
setFilterEndpointType=
{
setFilterEndpointType
}
...
...
web/src/index.css
View file @
bd6b7286
...
...
@@ -344,6 +344,102 @@ code {
text-overflow
:
ellipsis
;
}
/* Badge for count/multiplier in filter buttons */
.sbg-badge
{
display
:
inline-flex
;
align-items
:
center
;
justify-content
:
center
;
flex-shrink
:
0
;
min-width
:
18px
;
height
:
18px
;
padding
:
0
6px
;
border-radius
:
9px
;
font-size
:
11px
;
font-weight
:
600
;
font-variant-numeric
:
tabular-nums
;
line-height
:
1
;
background-color
:
var
(
--semi-color-fill-0
);
color
:
var
(
--semi-color-text-2
);
transition
:
background-color
0.15s
ease
,
color
0.15s
ease
;
}
.sbg-badge-active
{
background-color
:
var
(
--semi-color-primary-light-active
);
color
:
var
(
--semi-color-primary
);
}
/* ---- SelectableButtonGroup color variants ---- */
.sbg-variant-violet
{
--semi-color-primary
:
#6d28d9
;
--semi-color-primary-light-default
:
rgba
(
124
,
58
,
237
,
0.08
);
--semi-color-primary-light-hover
:
rgba
(
124
,
58
,
237
,
0.15
);
--semi-color-primary-light-active
:
rgba
(
124
,
58
,
237
,
0.22
);
}
.sbg-variant-teal
{
--semi-color-primary
:
#0f766e
;
--semi-color-primary-light-default
:
rgba
(
20
,
184
,
166
,
0.08
);
--semi-color-primary-light-hover
:
rgba
(
20
,
184
,
166
,
0.15
);
--semi-color-primary-light-active
:
rgba
(
20
,
184
,
166
,
0.22
);
}
.sbg-variant-amber
{
--semi-color-primary
:
#b45309
;
--semi-color-primary-light-default
:
rgba
(
245
,
158
,
11
,
0.08
);
--semi-color-primary-light-hover
:
rgba
(
245
,
158
,
11
,
0.15
);
--semi-color-primary-light-active
:
rgba
(
245
,
158
,
11
,
0.22
);
}
.sbg-variant-rose
{
--semi-color-primary
:
#be123c
;
--semi-color-primary-light-default
:
rgba
(
244
,
63
,
94
,
0.08
);
--semi-color-primary-light-hover
:
rgba
(
244
,
63
,
94
,
0.15
);
--semi-color-primary-light-active
:
rgba
(
244
,
63
,
94
,
0.22
);
}
.sbg-variant-green
{
--semi-color-primary
:
#047857
;
--semi-color-primary-light-default
:
rgba
(
16
,
185
,
129
,
0.08
);
--semi-color-primary-light-hover
:
rgba
(
16
,
185
,
129
,
0.15
);
--semi-color-primary-light-active
:
rgba
(
16
,
185
,
129
,
0.22
);
}
/* Dark mode: lighter text, slightly stronger backgrounds */
html
.dark
.sbg-variant-violet
{
--semi-color-primary
:
#a78bfa
;
--semi-color-primary-light-default
:
rgba
(
139
,
92
,
246
,
0.14
);
--semi-color-primary-light-hover
:
rgba
(
139
,
92
,
246
,
0.22
);
--semi-color-primary-light-active
:
rgba
(
139
,
92
,
246
,
0.3
);
}
html
.dark
.sbg-variant-teal
{
--semi-color-primary
:
#2dd4bf
;
--semi-color-primary-light-default
:
rgba
(
45
,
212
,
191
,
0.14
);
--semi-color-primary-light-hover
:
rgba
(
45
,
212
,
191
,
0.22
);
--semi-color-primary-light-active
:
rgba
(
45
,
212
,
191
,
0.3
);
}
html
.dark
.sbg-variant-amber
{
--semi-color-primary
:
#fbbf24
;
--semi-color-primary-light-default
:
rgba
(
251
,
191
,
36
,
0.14
);
--semi-color-primary-light-hover
:
rgba
(
251
,
191
,
36
,
0.22
);
--semi-color-primary-light-active
:
rgba
(
251
,
191
,
36
,
0.3
);
}
html
.dark
.sbg-variant-rose
{
--semi-color-primary
:
#fb7185
;
--semi-color-primary-light-default
:
rgba
(
251
,
113
,
133
,
0.14
);
--semi-color-primary-light-hover
:
rgba
(
251
,
113
,
133
,
0.22
);
--semi-color-primary-light-active
:
rgba
(
251
,
113
,
133
,
0.3
);
}
html
.dark
.sbg-variant-green
{
--semi-color-primary
:
#34d399
;
--semi-color-primary-light-default
:
rgba
(
52
,
211
,
153
,
0.14
);
--semi-color-primary-light-hover
:
rgba
(
52
,
211
,
153
,
0.22
);
--semi-color-primary-light-active
:
rgba
(
52
,
211
,
153
,
0.3
);
}
/* Tabs组件样式 */
.semi-tabs-content
{
padding
:
0
!important
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment