fix(Price): 组件传入异常信息直接原样返回#3440
Conversation
功能说明本次更改为价格组件添加了"原始价格"渲染逻辑。当 变更清单
代码审查工作量评估🎯 2 (简单) | ⏱️ ~12 分钟 相关联的拉取请求
建议审查人
兔子之歌
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
src/packages/price/price.taro.tsx (1)
42-52:isRenderPriceRaw为 true 时把price置为''可保留,但建议补一行注释说明用意。当前
renderRawContent直接渲染originalPrice,并不读取price,因此第 50 行的return ''在功能上是无关紧要的占位,但读者容易误以为它会影响渲染。可加一行注释(或干脆早返回原值)以避免后续维护者误删/误改:♻️ 建议
const price = useMemo(() => { - if (isRenderPriceRaw) return '' + // raw 模式下 price 不会参与渲染,仅占位避免后续 toString/replace 抛错 + if (isRenderPriceRaw) return '' return originalPrice.toString().replace(/[^\d.]/g, '') }, [originalPrice, isRenderPriceRaw])另外建议为
shouldRenderPriceAsRaw与本组件的 raw 分支补充单测,至少覆盖:纯文本、含 CJK 区间表达式、纯数字字符串、number类型、空字符串等场景,避免后续重构回归。🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/packages/price/price.taro.tsx` around lines 42 - 52, The code sets price to '' when isRenderPriceRaw is true, which is functionally unnecessary because renderRawContent reads originalPrice directly; add a clear inline comment next to the isRenderPriceRaw check or the price useMemo explaining that returning '' is an intentional placeholder to avoid using the sanitized price when originalPrice should be rendered verbatim (mentioning isRenderPriceRaw, price, originalPrice and renderRawContent), or alternatively change the early branch to return originalPrice to make intent explicit; also add unit tests for shouldRenderPriceAsRaw and the component's raw branch covering pure text, CJK range expressions, numeric strings, number inputs and empty string cases to prevent regressions.src/utils/should-render-price-raw.ts (1)
4-10:hasNoExtractablePrice中第 8 行为冗余判断。第 7 行
!/\d/.test(t)已覆盖「字符串不含数字」的全部情况;只要t含有任意数字字符,第 8 行的t.replace(/[^\d.]/g, '')必然包含该数字、不可能等于''。即第 8 行永远不会被命中,属于死代码,可考虑精简:♻️ 建议简化
function hasNoExtractablePrice(s: string) { const t = s.trim() if (!t) return true if (!/\d/.test(t)) return true - if (t.replace(/[^\d.]/g, '') === '') return true return false }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/utils/should-render-price-raw.ts` around lines 4 - 10, The function hasNoExtractablePrice contains a redundant check: after trimming and testing if the string contains any digit (in hasNoExtractablePrice), the subsequent check using t.replace(/[^\d.]/g, '') === '' can never be true and should be removed; update the function (hasNoExtractablePrice) to simply trim, return true if empty, then return true if !/\d/.test(t), and otherwise return false, removing the dead-code branch.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/packages/price/price.taro.tsx`:
- Line 8: The web Price component (price.tsx) must mirror the Taro fix: import
shouldRenderPriceAsRaw and renderRawContent and add an isRenderPriceRaw branch
so anomalous strings are returned raw instead of being stripped and formatted.
In src/packages/price/price.tsx locate the render logic around the current
formatThousands/formatDecimal usage (the blocks referenced at ~108-155 and
~176-193) and before applying numeric formatting compute const isRenderPriceRaw
= shouldRenderPriceAsRaw(price); if true, return renderRawContent(price) (or use
the same render path as price.taro.tsx), otherwise proceed with existing
formatThousands/formatDecimal behavior.
In `@src/utils/should-render-price-raw.ts`:
- Around line 12-26: The current shouldRenderPriceAsRaw logic (in
shouldRenderPriceAsRaw) is too narrow: change the detection to treat inputs that
contain CJK or any semantic non-numeric characters (anything other than digits,
dot, whitespace and allowed currency symbols) as raw so single-number phrases
like "100元起", "约100元" or "起价100" return true; implement this by replacing the
"at least two numbers + CJK between" check with a regex or predicate that
returns true if t contains a CJK character (expand CJK from CJK =
/[\u4E00-\u9FFF]/ to a wider Unicode-aware class or use Unicode properties like
\p{Script=Han} plus Hiragana/Katakana/Hangul as needed) or contains characters
not matching /^[\d.\s¥$€£¢¥元-]*$/; keep hasNoExtractablePrice behavior unchanged
and ensure callers that strip numbers (originalPrice.toString().replace(...))
are avoided when shouldRenderPriceAsRaw returns true.
---
Nitpick comments:
In `@src/packages/price/price.taro.tsx`:
- Around line 42-52: The code sets price to '' when isRenderPriceRaw is true,
which is functionally unnecessary because renderRawContent reads originalPrice
directly; add a clear inline comment next to the isRenderPriceRaw check or the
price useMemo explaining that returning '' is an intentional placeholder to
avoid using the sanitized price when originalPrice should be rendered verbatim
(mentioning isRenderPriceRaw, price, originalPrice and renderRawContent), or
alternatively change the early branch to return originalPrice to make intent
explicit; also add unit tests for shouldRenderPriceAsRaw and the component's raw
branch covering pure text, CJK range expressions, numeric strings, number inputs
and empty string cases to prevent regressions.
In `@src/utils/should-render-price-raw.ts`:
- Around line 4-10: The function hasNoExtractablePrice contains a redundant
check: after trimming and testing if the string contains any digit (in
hasNoExtractablePrice), the subsequent check using t.replace(/[^\d.]/g, '') ===
'' can never be true and should be removed; update the function
(hasNoExtractablePrice) to simply trim, return true if empty, then return true
if !/\d/.test(t), and otherwise return false, removing the dead-code branch.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 2c6a20f4-41db-4e18-9d3c-5a061295c9c1
📒 Files selected for processing (2)
src/packages/price/price.taro.tsxsrc/utils/should-render-price-raw.ts
| import { useRtl } from '@/packages/configprovider/index.taro' | ||
| import { TaroPriceProps, PriceColorEnum } from '@/types' | ||
| import { harmony } from '@/utils/taro/platform' | ||
| import { shouldRenderPriceAsRaw } from '@/utils/should-render-price-raw' |
There was a problem hiding this comment.
Web 版 price.tsx 未同步该修复,跨端行为将不一致。
本次只在 price.taro.tsx 引入 shouldRenderPriceAsRaw 与 renderRawContent;从提供的 src/packages/price/price.tsx:108-155 可以看到 web 版仍直接使用 formatThousands(price) / formatDecimal(price) 的格式化路径,并没有 raw 渲染分支。这意味着同样传入异常字符串(如 "10元起到200元")时,小程序/鸿蒙端会原样输出,而 H5 端会被 replace(/[^\d.]/g, '') 清洗后渲染为错误数字(如 10.200),违反 PR 标题「组件传入异常信息直接原样返回」的承诺。
建议在 src/packages/price/price.tsx 中按相同模式加上 isRenderPriceRaw 判定与 raw 渲染分支,保持双端一致。
Also applies to: 176-193
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/packages/price/price.taro.tsx` at line 8, The web Price component
(price.tsx) must mirror the Taro fix: import shouldRenderPriceAsRaw and
renderRawContent and add an isRenderPriceRaw branch so anomalous strings are
returned raw instead of being stripped and formatted. In
src/packages/price/price.tsx locate the render logic around the current
formatThousands/formatDecimal usage (the blocks referenced at ~108-155 and
~176-193) and before applying numeric formatting compute const isRenderPriceRaw
= shouldRenderPriceAsRaw(price); if true, return renderRawContent(price) (or use
the same render path as price.taro.tsx), otherwise proceed with existing
formatThousands/formatDecimal behavior.
| export function shouldRenderPriceAsRaw(s: string) { | ||
| if (hasNoExtractablePrice(s)) { | ||
| return true | ||
| } | ||
| const t = s.trim() | ||
| if (!CJK.test(t)) return false | ||
| const matches = Array.from(t.matchAll(RE_NUM)) | ||
| if (matches.length < 2) return false | ||
| const a = matches[0] | ||
| const b = matches[1] | ||
| const i0 = a.index! | ||
| const i1 = b.index! | ||
| const between = t.slice(i0 + a[0].length, i1) | ||
| return CJK.test(between) | ||
| } |
There was a problem hiding this comment.
判定规则较窄,部分常见异常入参不会进入原样渲染分支。
当前规则要求「至少两个数字 + 第一/第二个数字之间存在 CJK」。对于单数字 + CJK 的常见异常文案(如 "100元起"、"起价100"、"约100元"、"暂无报价 100 起"),不会命中 raw 分支,仍会走 originalPrice.toString().replace(/[^\d.]/g, ''),导致只显示一个被剥离上下文的数字,与「异常信息原样返回」的目标不一致。
如果产品意图是「字符串里只要明显不是单一价格就原样渲染」,可考虑改成更宽松的判定,例如:当字符串包含 CJK(或除 \d、.、空白、货币符以外的语义字符)时即视为 raw。请确认期望覆盖范围;若有意只覆盖区间型表达,可忽略本条。
此外 CJK = /[\u4E00-\u9FFF]/ 仅覆盖基本 CJK 区段,不包含扩展 A/B、假名、谚文等;如果未来要兼容日韩文文案需要扩展该范围。
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/utils/should-render-price-raw.ts` around lines 12 - 26, The current
shouldRenderPriceAsRaw logic (in shouldRenderPriceAsRaw) is too narrow: change
the detection to treat inputs that contain CJK or any semantic non-numeric
characters (anything other than digits, dot, whitespace and allowed currency
symbols) as raw so single-number phrases like "100元起", "约100元" or "起价100" return
true; implement this by replacing the "at least two numbers + CJK between" check
with a regex or predicate that returns true if t contains a CJK character
(expand CJK from CJK = /[\u4E00-\u9FFF]/ to a wider Unicode-aware class or use
Unicode properties like \p{Script=Han} plus Hiragana/Katakana/Hangul as needed)
or contains characters not matching /^[\d.\s¥$€£¢¥元-]*$/; keep
hasNoExtractablePrice behavior unchanged and ensure callers that strip numbers
(originalPrice.toString().replace(...)) are avoided when shouldRenderPriceAsRaw
returns true.
🤔 这个变动的性质是?
🔗 相关 Issue
💡 需求背景和解决方案
☑️ 请求合并前的自查清单
Summary by CodeRabbit
Bug Fixes