Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions NutUI-React_组件标准白皮书.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ NutUI 的演进伴随着移动端技术的演进,从移动端到跨端,从 V
定义组件 Props 前,**必须(MUST)**继承全局抽象类型 `BasicComponent`(或 `MiniProgramBasicProps` 等多端公共类型),确保组件基础能力的统一。

2. **强类型声明与规范**:

- **禁止 `any`**:Props 参数需使用显式联合类型,严禁使用 `any` 逃避类型检查。
- **事件命名**:对外事件统一以 `onXXX`(小驼峰)命名。
- **精简通信**:事件通信仅传递必要数据,避免携带冗余的组件实例或私有变量。
Expand Down Expand Up @@ -150,7 +149,6 @@ export const Button = React.forwardRef<HTMLButtonElement, Partial<ButtonProps>>(
### 5.4 组件防御与容灾红线

1. **防阻断式崩溃**:

- 针对入参异常、异步失败、逻辑边界等风险点,必须内置 `try-catch` 或提供兜底 UI。
- 组件内部错误不得外溢导致整个前端应用白屏死机。

Expand Down
1 change: 1 addition & 0 deletions src/packages/price/doc.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ import { Price } from '@nutui/nutui-react'
| position | The symbol appear before or after the price,`before`、`after` | `string` | `before` |
| size | Size,`xlarge` \| `large` \| `normal` \| `small` | `string` | `normal` |
| line | Line-through price | `boolean` | `false` |
| raw | When enabled, if price contains invalid characters, it is displayed as-is without formatting | `boolean` | `false` |

## Theming

Expand Down
1 change: 1 addition & 0 deletions src/packages/price/doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ import { Price } from '@nutui/nutui-react'
| position | 符号显示在价格前或者后,`before`、`after` | `string` | `before` |
| size | 价格尺寸,`xlarge` \| `large` \| `normal` \| `small` | `string` | `normal` |
| line | 是否划线价 | `boolean` | `false` |
| raw | 开启后,当 price 包含非法字符时,原样展示,不做格式化处理 | `boolean` | `false` |

## 主题定制

Expand Down
1 change: 1 addition & 0 deletions src/packages/price/doc.taro.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ import { Price } from '@nutui/nutui-react-taro'
| position | 符号显示在价格前或者后,`before`、`after` | `string` | `before` |
| size | 价格尺寸,`xlarge` \| `large` \| `normal` \| `small` | `string` | `normal` |
| line | 是否划线价 | `boolean` | `false` |
| raw | 开启后,当 price 包含非法字符时,原样展示,不做格式化处理 | `boolean` | `false` |

## 主题定制

Expand Down
1 change: 1 addition & 0 deletions src/packages/price/doc.zh-TW.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ import { Price } from '@nutui/nutui-react'
| position | 符號顯示在價格前或者後,`before`、`after` | `string` | `before` |
| size | 價格尺寸,`xlarge` \| `large` \| `normal` \| `small` | `string` | `normal` |
| line | 是否劃線價 | `boolean` | `false` |
| raw | 開啟後,當 price 包含非法字符時,原樣展示,不做格式化處理 | `boolean` | `false` |

## 主題定製

Expand Down
18 changes: 13 additions & 5 deletions src/packages/price/price.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import classNames from 'classnames'
import { ComponentDefaults } from '@/utils/typings'
import { useRtl } from '@/packages/configprovider/index'
import { WebPriceProps, PriceColorEnum } from '@/types'
import { shouldRenderPriceAsRaw } from '@/utils/should-render-price-raw'
import {
shouldRenderPriceAsRaw,
hasNonPriceChars,
} from '@/utils/should-render-price-raw'

const defaultProps = {
...ComponentDefaults,
Expand All @@ -15,6 +18,7 @@ const defaultProps = {
position: 'before',
size: 'normal',
line: false,
raw: false,
} as WebPriceProps
export const Price: FunctionComponent<Partial<WebPriceProps>> = (props) => {
const {
Expand All @@ -26,6 +30,7 @@ export const Price: FunctionComponent<Partial<WebPriceProps>> = (props) => {
position,
size,
line,
raw,
className,
style,
...rest
Expand All @@ -39,9 +44,12 @@ export const Price: FunctionComponent<Partial<WebPriceProps>> = (props) => {
const rtl = useRtl()
const isRenderPriceRaw = useMemo(
() =>
typeof originalPrice === 'string' &&
shouldRenderPriceAsRaw(originalPrice),
[originalPrice]
(typeof originalPrice === 'string' &&
shouldRenderPriceAsRaw(originalPrice)) ||
(raw &&
typeof originalPrice === 'string' &&
hasNonPriceChars(originalPrice)),
[originalPrice, raw]
)

const price = useMemo(() => {
Expand Down Expand Up @@ -82,7 +90,7 @@ export const Price: FunctionComponent<Partial<WebPriceProps>> = (props) => {
}

const formatDecimal = (decimalNum: any) => {
if (Number(decimalNum) === 0) {
if (Number(decimalNum) === 0 && !checkPoint(decimalNum)) {
decimalNum = 0
}

Expand Down
3 changes: 3 additions & 0 deletions src/utils/should-render-price-raw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const RE_NUM = /\d+(?:\.\d+)?/g
// 价格合法字符:数字、小数点、负号、大写货币代码(HK USD EUR 等)、常见货币符号 Unicode 区块(含全角 ¥)
const PRICE_CHARS = /^[\d.\-A-Z¥¥$€£₩₹₽₺₴₪฿\u20A0-\u20CF\uFE69\uFF04\uFFE5]*$/

// 无法提取出有效价格时直接按原文展示,避免把纯文案误格式化成 0 或空串
function hasNoExtractablePrice(s: string) {
const t = s.trim()
if (!t) return true
Expand All @@ -11,6 +12,7 @@ function hasNoExtractablePrice(s: string) {
return false
}

// 只有两段数字之间出现非法字符时,才认为该字符串应走原样渲染
export function shouldRenderPriceAsRaw(s: string) {
if (hasNoExtractablePrice(s)) {
return true
Expand All @@ -26,6 +28,7 @@ export function shouldRenderPriceAsRaw(s: string) {
return !PRICE_CHARS.test(between)
}

// 提供给 Price.raw 开关:调用方可用它判断整串是否包含非法字符
export function hasNonPriceChars(s: string): boolean {
return !PRICE_CHARS.test(s)
}
Loading