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
Unverified
Commit
97bbb7c8
authored
Jul 08, 2026
by
CaIon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat(pricing): enhance dynamic pricing calculations with group selection support
parent
28e0115a
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
221 additions
and
160 deletions
+221
-160
web/default/src/features/pricing/components/model-card-grid.tsx
+2
-0
web/default/src/features/pricing/components/model-card.tsx
+112
-91
web/default/src/features/pricing/components/pricing-columns.tsx
+19
-7
web/default/src/features/pricing/components/pricing-table.tsx
+4
-1
web/default/src/features/pricing/index.tsx
+2
-0
web/default/src/features/pricing/lib/dynamic-price.ts
+6
-14
web/default/src/features/pricing/lib/model-helpers.ts
+57
-2
web/default/src/features/pricing/lib/price.ts
+19
-45
No files found.
web/default/src/features/pricing/components/model-card-grid.tsx
View file @
97bbb7c8
...
...
@@ -36,6 +36,7 @@ export interface ModelCardGridProps {
usdExchangeRate
?:
number
tokenUnit
?:
TokenUnit
showRechargePrice
?:
boolean
selectedGroup
?:
string
}
export
function
ModelCardGrid
(
props
:
ModelCardGridProps
)
{
...
...
@@ -81,6 +82,7 @@ export function ModelCardGrid(props: ModelCardGridProps) {
priceRate=
{
props
.
priceRate
}
usdExchangeRate=
{
props
.
usdExchangeRate
}
showRechargePrice=
{
props
.
showRechargePrice
}
selectedGroup=
{
props
.
selectedGroup
}
perf=
{
perfMap
.
get
(
model
.
model_name
||
''
)
}
onClick=
{
()
=>
props
.
onModelClick
(
model
.
model_name
||
''
)
}
/>
...
...
web/default/src/features/pricing/components/model-card.tsx
View file @
97bbb7c8
...
...
@@ -17,7 +17,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
For commercial licensing, please contact support@quantumnous.com
*/
import
{
ChevronRight
,
Copy
}
from
'lucide-react'
import
{
memo
}
from
'react'
import
{
memo
,
type
ReactNode
}
from
'react'
import
{
useTranslation
}
from
'react-i18next'
import
{
StatusBadge
}
from
'@/components/status-badge'
...
...
@@ -43,6 +43,7 @@ export interface ModelCardProps {
usdExchangeRate
?:
number
tokenUnit
?:
TokenUnit
showRechargePrice
?:
boolean
selectedGroup
?:
string
perf
?:
ModelPerfBadgeData
}
...
...
@@ -71,7 +72,10 @@ export const ModelCard = memo(function ModelCard(props: ModelCardProps) {
showRechargePrice
,
priceRate
,
usdExchangeRate
,
groupRatioMultiplier
:
getDynamicDisplayGroupRatio
(
props
.
model
),
groupRatioMultiplier
:
getDynamicDisplayGroupRatio
(
props
.
model
,
props
.
selectedGroup
),
})
:
null
...
...
@@ -87,6 +91,111 @@ export const ModelCard = memo(function ModelCard(props: ModelCardProps) {
copyToClipboard
(
props
.
model
.
model_name
||
''
)
}
let
priceSummary
:
ReactNode
if
(
dynamicSummary
)
{
if
(
dynamicSummary
.
isSpecialExpression
)
{
priceSummary
=
(
<
span
className=
'min-w-0'
>
<
span
className=
'text-amber-700 dark:text-amber-300'
>
{
t
(
'Special billing expression'
)
}
</
span
>
<
code
className=
'text-muted-foreground/70 mt-0.5 line-clamp-1 block font-mono text-[11px] break-all'
>
{
dynamicSummary
.
rawExpression
}
</
code
>
</
span
>
)
}
else
if
(
dynamicSummary
.
primaryEntries
.
length
>
0
)
{
priceSummary
=
(
<>
{
dynamicSummary
.
primaryEntries
.
map
((
entry
)
=>
(
<
span
key=
{
entry
.
key
}
className=
'text-muted-foreground whitespace-nowrap'
>
{
t
(
entry
.
shortLabel
)
}{
' '
}
<
span
className=
'text-foreground font-mono font-semibold'
>
{
entry
.
formatted
}
</
span
>
/
{
tokenUnitLabel
}
</
span
>
))
}
</>
)
}
else
{
priceSummary
=
(
<
span
className=
'text-muted-foreground text-xs'
>
{
t
(
'Dynamic Pricing'
)
}
</
span
>
)
}
}
else
if
(
isTokenBased
)
{
priceSummary
=
(
<>
<
span
className=
'text-muted-foreground whitespace-nowrap'
>
{
t
(
'Input'
)
}{
' '
}
<
span
className=
'text-foreground font-mono font-semibold'
>
{
formatPrice
(
props
.
model
,
'input'
,
tokenUnit
,
showRechargePrice
,
priceRate
,
usdExchangeRate
,
props
.
selectedGroup
)
}
</
span
>
/
{
tokenUnitLabel
}
</
span
>
<
span
className=
'text-muted-foreground whitespace-nowrap'
>
{
t
(
'Output'
)
}{
' '
}
<
span
className=
'text-foreground font-mono font-semibold'
>
{
formatPrice
(
props
.
model
,
'output'
,
tokenUnit
,
showRechargePrice
,
priceRate
,
usdExchangeRate
,
props
.
selectedGroup
)
}
</
span
>
/
{
tokenUnitLabel
}
</
span
>
{
hasCachedPrice
&&
(
<
span
className=
'text-muted-foreground/60 whitespace-nowrap'
>
{
t
(
'Cached'
)
}{
' '
}
<
span
className=
'font-mono'
>
{
formatPrice
(
props
.
model
,
'cache'
,
tokenUnit
,
showRechargePrice
,
priceRate
,
usdExchangeRate
,
props
.
selectedGroup
)
}
</
span
>
</
span
>
)
}
</>
)
}
else
{
priceSummary
=
(
<
span
className=
'text-muted-foreground whitespace-nowrap'
>
<
span
className=
'text-foreground font-mono font-semibold'
>
{
formatRequestPrice
(
props
.
model
,
showRechargePrice
,
priceRate
,
usdExchangeRate
,
props
.
selectedGroup
)
}
</
span
>
{
' '
}
/
{
t
(
'request'
)
}
</
span
>
)
}
return
(
<
div
className=
{
cn
(
...
...
@@ -109,95 +218,7 @@ export const ModelCard = memo(function ModelCard(props: ModelCardProps) {
{
props
.
model
.
model_name
}
</
h3
>
<
div
className=
'mt-0.5 flex flex-wrap items-baseline gap-x-2 gap-y-0.5 text-xs sm:mt-1 sm:gap-x-3'
>
{
dynamicSummary
?
(
dynamicSummary
.
isSpecialExpression
?
(
<
span
className=
'min-w-0'
>
<
span
className=
'text-amber-700 dark:text-amber-300'
>
{
t
(
'Special billing expression'
)
}
</
span
>
<
code
className=
'text-muted-foreground/70 mt-0.5 line-clamp-1 block font-mono text-[11px] break-all'
>
{
dynamicSummary
.
rawExpression
}
</
code
>
</
span
>
)
:
dynamicSummary
.
primaryEntries
.
length
>
0
?
(
<>
{
dynamicSummary
.
primaryEntries
.
map
((
entry
)
=>
(
<
span
key=
{
entry
.
key
}
className=
'text-muted-foreground whitespace-nowrap'
>
{
t
(
entry
.
shortLabel
)
}{
' '
}
<
span
className=
'text-foreground font-mono font-semibold'
>
{
entry
.
formatted
}
</
span
>
/
{
tokenUnitLabel
}
</
span
>
))
}
</>
)
:
(
<
span
className=
'text-muted-foreground text-xs'
>
{
t
(
'Dynamic Pricing'
)
}
</
span
>
)
)
:
isTokenBased
?
(
<>
<
span
className=
'text-muted-foreground whitespace-nowrap'
>
{
t
(
'Input'
)
}{
' '
}
<
span
className=
'text-foreground font-mono font-semibold'
>
{
formatPrice
(
props
.
model
,
'input'
,
tokenUnit
,
showRechargePrice
,
priceRate
,
usdExchangeRate
)
}
</
span
>
/
{
tokenUnitLabel
}
</
span
>
<
span
className=
'text-muted-foreground whitespace-nowrap'
>
{
t
(
'Output'
)
}{
' '
}
<
span
className=
'text-foreground font-mono font-semibold'
>
{
formatPrice
(
props
.
model
,
'output'
,
tokenUnit
,
showRechargePrice
,
priceRate
,
usdExchangeRate
)
}
</
span
>
/
{
tokenUnitLabel
}
</
span
>
{
hasCachedPrice
&&
(
<
span
className=
'text-muted-foreground/60 whitespace-nowrap'
>
{
t
(
'Cached'
)
}{
' '
}
<
span
className=
'font-mono'
>
{
formatPrice
(
props
.
model
,
'cache'
,
tokenUnit
,
showRechargePrice
,
priceRate
,
usdExchangeRate
)
}
</
span
>
</
span
>
)
}
</>
)
:
(
<
span
className=
'text-muted-foreground whitespace-nowrap'
>
<
span
className=
'text-foreground font-mono font-semibold'
>
{
formatRequestPrice
(
props
.
model
,
showRechargePrice
,
priceRate
,
usdExchangeRate
)
}
</
span
>
{
' '
}
/
{
t
(
'request'
)
}
</
span
>
)
}
{
priceSummary
}
</
div
>
</
div
>
</
div
>
...
...
web/default/src/features/pricing/components/pricing-columns.tsx
View file @
97bbb7c8
...
...
@@ -16,7 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
For commercial licensing, please contact support@quantumnous.com
*/
import
{
type
ColumnDef
}
from
'@tanstack/react-table'
import
type
{
ColumnDef
}
from
'@tanstack/react-table'
import
{
useTranslation
}
from
'react-i18next'
import
{
...
...
@@ -51,6 +51,7 @@ export interface PricingColumnsOptions {
priceRate
?:
number
usdExchangeRate
?:
number
showRechargePrice
?:
boolean
selectedGroup
?:
string
}
export
function
usePricingColumns
(
...
...
@@ -62,6 +63,7 @@ export function usePricingColumns(
priceRate
=
1
,
usdExchangeRate
=
1
,
showRechargePrice
=
false
,
selectedGroup
,
}
=
options
const
tokenUnitLabel
=
tokenUnit
===
'K'
?
'1K'
:
'1M'
...
...
@@ -124,7 +126,10 @@ export function usePricingColumns(
showRechargePrice
,
priceRate
,
usdExchangeRate
,
groupRatioMultiplier
:
getDynamicDisplayGroupRatio
(
model
),
groupRatioMultiplier
:
getDynamicDisplayGroupRatio
(
model
,
selectedGroup
),
})
if
(
dynamicSummary
)
{
...
...
@@ -186,7 +191,8 @@ export function usePricingColumns(
tokenUnit
,
showRechargePrice
,
priceRate
,
usdExchangeRate
usdExchangeRate
,
selectedGroup
)
)
const
outputPrice
=
stripTrailingZeros
(
...
...
@@ -196,7 +202,8 @@ export function usePricingColumns(
tokenUnit
,
showRechargePrice
,
priceRate
,
usdExchangeRate
usdExchangeRate
,
selectedGroup
)
)
...
...
@@ -219,7 +226,8 @@ export function usePricingColumns(
model
,
showRechargePrice
,
priceRate
,
usdExchangeRate
usdExchangeRate
,
selectedGroup
)
)
...
...
@@ -247,7 +255,10 @@ export function usePricingColumns(
showRechargePrice
,
priceRate
,
usdExchangeRate
,
groupRatioMultiplier
:
getDynamicDisplayGroupRatio
(
model
),
groupRatioMultiplier
:
getDynamicDisplayGroupRatio
(
model
,
selectedGroup
),
})
if
(
dynamicSummary
)
{
...
...
@@ -291,7 +302,8 @@ export function usePricingColumns(
tokenUnit
,
showRechargePrice
,
priceRate
,
usdExchangeRate
usdExchangeRate
,
selectedGroup
)
)
...
...
web/default/src/features/pricing/components/pricing-table.tsx
View file @
97bbb7c8
...
...
@@ -16,7 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
For commercial licensing, please contact support@quantumnous.com
*/
import
{
type
Row
,
type
PaginationState
}
from
'@tanstack/react-table'
import
type
{
Row
,
PaginationState
}
from
'@tanstack/react-table'
import
{
useState
,
useCallback
}
from
'react'
import
{
useTranslation
}
from
'react-i18next'
...
...
@@ -38,6 +38,7 @@ export interface PricingTableProps {
usdExchangeRate
?:
number
tokenUnit
?:
TokenUnit
showRechargePrice
?:
boolean
selectedGroup
?:
string
onModelClick
?:
(
modelName
:
string
)
=>
void
}
...
...
@@ -50,6 +51,7 @@ export function PricingTable(props: PricingTableProps) {
usdExchangeRate
=
1
,
tokenUnit
=
DEFAULT_TOKEN_UNIT
,
showRechargePrice
=
false
,
selectedGroup
,
onModelClick
,
}
=
props
...
...
@@ -63,6 +65,7 @@ export function PricingTable(props: PricingTableProps) {
priceRate
,
usdExchangeRate
,
showRechargePrice
,
selectedGroup
,
})
const
{
table
}
=
useDataTable
({
...
...
web/default/src/features/pricing/index.tsx
View file @
97bbb7c8
...
...
@@ -130,6 +130,7 @@ export function Pricing() {
usdExchangeRate=
{
usdExchangeRate
}
tokenUnit=
{
tokenUnit
}
showRechargePrice=
{
showRechargePrice
}
selectedGroup=
{
groupFilter
}
/>
)
}
...
...
@@ -141,6 +142,7 @@ export function Pricing() {
usdExchangeRate=
{
usdExchangeRate
}
tokenUnit=
{
tokenUnit
}
showRechargePrice=
{
showRechargePrice
}
selectedGroup=
{
groupFilter
}
onModelClick=
{
handleModelClick
}
/>
)
...
...
web/default/src/features/pricing/lib/dynamic-price.ts
View file @
97bbb7c8
...
...
@@ -28,6 +28,7 @@ import {
type
BillingVar
,
type
ParsedTier
,
}
from
'./billing-expr'
import
{
getDisplayGroupRatio
}
from
'./model-helpers'
type
DynamicPriceOptions
=
{
tokenUnit
:
TokenUnit
...
...
@@ -65,20 +66,11 @@ export function isDynamicPricingModel(model: PricingModel): boolean {
return
model
.
billing_mode
===
'tiered_expr'
&&
Boolean
(
model
.
billing_expr
)
}
export
function
getDynamicDisplayGroupRatio
(
model
:
PricingModel
):
number
{
const
groups
=
Array
.
isArray
(
model
.
enable_groups
)
?
model
.
enable_groups
:
[]
const
ratios
=
model
.
group_ratio
||
{}
if
(
groups
.
length
===
0
)
return
1
let
minRatio
=
Number
.
POSITIVE_INFINITY
for
(
const
group
of
groups
)
{
const
ratio
=
ratios
[
group
]
if
(
ratio
!==
undefined
&&
ratio
<
minRatio
)
{
minRatio
=
ratio
}
}
return
minRatio
===
Number
.
POSITIVE_INFINITY
?
1
:
minRatio
export
function
getDynamicDisplayGroupRatio
(
model
:
PricingModel
,
selectedGroup
?:
string
):
number
{
return
getDisplayGroupRatio
(
model
,
selectedGroup
)
}
function
applyRechargeRate
(
...
...
web/default/src/features/pricing/lib/model-helpers.ts
View file @
97bbb7c8
...
...
@@ -16,7 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
For commercial licensing, please contact support@quantumnous.com
*/
import
{
EXCLUDED_GROUPS
,
QUOTA_TYPE_VALUES
}
from
'../constants'
import
{
EXCLUDED_GROUPS
,
FILTER_ALL
,
QUOTA_TYPE_VALUES
}
from
'../constants'
import
type
{
PricingModel
}
from
'../types'
// ----------------------------------------------------------------------------
...
...
@@ -40,10 +40,65 @@ export function getAvailableGroups(
}
/**
* Read a configured group ratio while preserving valid zero ratios.
*/
export
function
getConfiguredGroupRatio
(
groupRatio
:
Record
<
string
,
number
>
,
group
:
string
):
number
{
const
ratio
=
groupRatio
[
group
]
return
typeof
ratio
===
'number'
&&
Number
.
isFinite
(
ratio
)
?
ratio
:
1
}
/**
* Resolve the group ratio used by model square summary prices.
*
* When no specific group is selected, the model square shows the best price
* available to the viewer. When a group filter is active, it mirrors classic
* and shows that group's price.
*/
export
function
getDisplayGroupRatio
(
model
:
PricingModel
,
selectedGroup
?:
string
):
number
{
const
modelEnableGroups
=
Array
.
isArray
(
model
.
enable_groups
)
?
model
.
enable_groups
:
[]
const
groupRatio
=
model
.
group_ratio
||
{}
if
(
selectedGroup
&&
selectedGroup
!==
FILTER_ALL
&&
modelEnableGroups
.
includes
(
selectedGroup
)
)
{
return
getConfiguredGroupRatio
(
groupRatio
,
selectedGroup
)
}
if
(
modelEnableGroups
.
length
===
0
)
{
return
1
}
let
minRatio
=
Number
.
POSITIVE_INFINITY
for
(
const
group
of
modelEnableGroups
)
{
const
ratio
=
groupRatio
[
group
]
if
(
typeof
ratio
===
'number'
&&
Number
.
isFinite
(
ratio
)
&&
ratio
<
minRatio
)
{
minRatio
=
ratio
}
}
return
minRatio
===
Number
.
POSITIVE_INFINITY
?
1
:
minRatio
}
/**
* Replace model placeholder in endpoint path
*/
export
function
replaceModelInPath
(
path
:
string
,
modelName
:
string
):
string
{
return
path
.
replace
(
/
\{
model
\}
/g
,
modelName
)
return
path
.
replace
All
(
'{model}'
,
modelName
)
}
/**
...
...
web/default/src/features/pricing/lib/price.ts
View file @
97bbb7c8
...
...
@@ -20,6 +20,7 @@ import { formatCurrencyFromUSD } from '@/lib/currency'
import
{
QUOTA_TYPE_VALUES
,
TOKEN_UNIT_DIVISORS
}
from
'../constants'
import
type
{
PricingModel
,
TokenUnit
,
PriceType
}
from
'../types'
import
{
getConfiguredGroupRatio
,
getDisplayGroupRatio
}
from
'./model-helpers'
// ----------------------------------------------------------------------------
// Price Calculation Utilities
...
...
@@ -36,11 +37,11 @@ export function stripTrailingZeros(formatted: string): string {
const
[,
symbol
,
number
,
suffix
]
=
match
// Remove commas for processing
const
cleanNumber
=
number
.
replace
(
/,/g
,
''
)
const
cleanNumber
=
number
.
replace
All
(
','
,
''
)
// Convert to number and back to remove trailing zeros
const
parsed
=
parseFloat
(
cleanNumber
)
if
(
isNaN
(
parsed
))
return
formatted
const
parsed
=
Number
.
parseFloat
(
cleanNumber
)
if
(
Number
.
isNaN
(
parsed
))
return
formatted
// Convert to string, which automatically removes trailing zeros
let
result
=
parsed
.
toString
()
...
...
@@ -54,27 +55,6 @@ export function stripTrailingZeros(formatted: string): string {
}
/**
* Find minimum group ratio from enabled groups
*/
function
getMinGroupRatio
(
enableGroups
:
string
[],
groupRatio
:
Record
<
string
,
number
>
):
number
{
if
(
enableGroups
.
length
===
0
)
return
1
let
minRatio
=
Number
.
POSITIVE_INFINITY
for
(
const
group
of
enableGroups
)
{
const
ratio
=
groupRatio
[
group
]
if
(
ratio
!==
undefined
&&
ratio
<
minRatio
)
{
minRatio
=
ratio
}
}
return
minRatio
===
Number
.
POSITIVE_INFINITY
?
1
:
minRatio
}
/**
* Calculate token price in USD.
*
* Returns NaN when the required ratio field is missing/null so callers can
...
...
@@ -95,26 +75,26 @@ function calculateTokenPrice(
case
'cache'
:
return
hasRatio
(
model
.
cache_ratio
)
?
base
*
Number
(
model
.
cache_ratio
)
:
NaN
:
N
umber
.
N
aN
case
'create_cache'
:
return
hasRatio
(
model
.
create_cache_ratio
)
?
base
*
Number
(
model
.
create_cache_ratio
)
:
NaN
:
N
umber
.
N
aN
case
'image'
:
return
hasRatio
(
model
.
image_ratio
)
?
base
*
Number
(
model
.
image_ratio
)
:
NaN
:
N
umber
.
N
aN
case
'audio_input'
:
return
hasRatio
(
model
.
audio_ratio
)
?
base
*
Number
(
model
.
audio_ratio
)
:
NaN
:
N
umber
.
N
aN
case
'audio_output'
:
return
hasRatio
(
model
.
audio_ratio
)
&&
hasRatio
(
model
.
audio_completion_ratio
)
?
base
*
Number
(
model
.
audio_ratio
)
*
Number
(
model
.
audio_completion_ratio
)
:
NaN
:
N
umber
.
N
aN
}
}
...
...
@@ -167,19 +147,16 @@ export function formatPrice(
tokenUnit
:
TokenUnit
,
showWithRecharge
=
false
,
priceRate
=
1
,
usdExchangeRate
=
1
usdExchangeRate
=
1
,
selectedGroup
?:
string
):
string
{
if
(
model
.
quota_type
===
QUOTA_TYPE_VALUES
.
REQUEST
)
{
return
'-'
}
const
enableGroups
=
Array
.
isArray
(
model
.
enable_groups
)
?
model
.
enable_groups
:
[]
const
groupRatio
=
model
.
group_ratio
||
{}
const
minRatio
=
getMinGroupRatio
(
enableGroups
,
groupRatio
)
const
displayGroupRatio
=
getDisplayGroupRatio
(
model
,
selectedGroup
)
let
priceInUSD
=
calculateTokenPrice
(
model
,
type
,
min
Ratio
)
let
priceInUSD
=
calculateTokenPrice
(
model
,
type
,
displayGroup
Ratio
)
priceInUSD
=
applyRechargeRate
(
priceInUSD
,
showWithRecharge
,
...
...
@@ -212,7 +189,7 @@ export function formatGroupPrice(
return
'-'
}
const
ratio
=
g
roupRatio
[
group
]
||
1
const
ratio
=
g
etConfiguredGroupRatio
(
groupRatio
,
group
)
let
priceInUSD
=
calculateTokenPrice
(
model
,
type
,
ratio
)
priceInUSD
=
applyRechargeRate
(
...
...
@@ -245,7 +222,7 @@ export function formatFixedPrice(
return
'-'
}
const
ratio
=
g
roupRatio
[
group
]
||
1
const
ratio
=
g
etConfiguredGroupRatio
(
groupRatio
,
group
)
let
priceInUSD
=
(
model
.
model_price
||
0
)
*
ratio
priceInUSD
=
applyRechargeRate
(
...
...
@@ -269,19 +246,16 @@ export function formatRequestPrice(
model
:
PricingModel
,
showWithRecharge
=
false
,
priceRate
=
1
,
usdExchangeRate
=
1
usdExchangeRate
=
1
,
selectedGroup
?:
string
):
string
{
if
(
model
.
quota_type
!==
QUOTA_TYPE_VALUES
.
REQUEST
)
{
return
'-'
}
const
enableGroups
=
Array
.
isArray
(
model
.
enable_groups
)
?
model
.
enable_groups
:
[]
const
groupRatio
=
model
.
group_ratio
||
{}
const
minRatio
=
getMinGroupRatio
(
enableGroups
,
groupRatio
)
const
displayGroupRatio
=
getDisplayGroupRatio
(
model
,
selectedGroup
)
let
priceInUSD
=
(
model
.
model_price
||
0
)
*
min
Ratio
let
priceInUSD
=
(
model
.
model_price
||
0
)
*
displayGroup
Ratio
priceInUSD
=
applyRechargeRate
(
priceInUSD
,
...
...
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