Conversation
在 global.d.ts 文件中添加 WdGuide 组件的类型声明,确保 TypeScript 项目中可以正确识别该组件。 添加引导组件主逻辑
- 将 offset、borderRadius、padding、bottomSafetyOffset 和 topSafetyOffset 的类型从数组修改为 Number - 这种更改提高了类型定义的准确性和一致性,确保了更好的类型检查和代码质量
- 将 border-radius、padding、bottom-safety-offset 和 top-safety-offset 属性的类型从 string / number 修改为 number - 优化文档中属性类型的准确性,提高开发者体验
- 修改 highlightStyle 和 popoverStyle 计算属性,优化样式对象的创建方式 - 移除多余的空行和注释,提高代码整洁度 - 调整 updateElementInfo、getEffectiveBoundaries、checkScrollNeeds 等函数的结构,提升可读性 - 优化 scrollUp 和 scrollDown 函数中的变量赋值和注释
- 丰富了自定义功能,包括引导内容、高亮区域、按钮等 - 优化了引导步骤的控制逻辑,支持双向绑定当前步骤 - 调整了高亮区域和引导内容的样式,提升了用户体验 - 增加了组件的响应式处理,适应不同平台和屏幕尺寸 - 优化了代码结构,提高了组件的可维护性和可测试性
- 将 manifest.json 中的 appid 从 "wxf81518e7b11ea8d8" 更改为 "wx18107b71aa1672e2"
- 添加了向导组件的单元测试文件 - 实现了对向导组件各项功能的测试,包括基本渲染、隐藏状态、步骤内容渲染、按钮显示和功能、自定义文本和样式、事件触发等 - 模拟了 uni 对象和元素查询,以适应uni-app环境 wd-guide 去除多余的打印 修复menuButtonInfo的ts报错
- 移除了多处 console.log 调试日志,清理无用输出 - 为 menuButtonInfo 添加了更精确的类型定义 - 删除了未使用的计算属性 watch
- 提取公共的默认样式函数 getDefaultStyle - 提取公共的高亮样式计算函数 calculateHighlightStyle - 使用 computed 属性优化高亮样式和元素信息的计算 - 简化代码结构,提高可维护性和可读性
- 优化了引导组件的滚动逻辑,确保滚动到顶部后再显示引导步骤 - 添加了系统信息更新功能,提高元素定位的准确性 - 修复了某些场景下引导步骤显示异常的问题 - 优化了代码结构,提高了组件的可维护性 - 修复重复调用导致位置计算偏差问题
- 将 controlCurrent.value 的初始值从 6 修改为 2 - 优化了控制指南的起始步骤,提高了用户体验
- 将 guide 组件重命名为 tour 组件 - 更新了相关文件和代码中的 guide 引用,改为 tour - 调整了部分样式和命名以适应新的组件名称
- 移除旧的引导组件代码和文档 - 更新类型定义,使用通用的类型构造函数 - 优化组件属性定义,使用统一的类型创建方法 - 删除冗余的属性类型和默认值定义
- 将 guide-show 动画名称改为 tour-show,统一动画命名风格 - 此更改不影响功能,仅用于提升代码一致性和可维护性
- 新增中英文文档侧边栏目录 - 修改演示组件入口位置,确保导航一致性
- 调整标题结构,将“介绍”合并为描述文字,“基本用法”更名为“基本使用” - 统一代码块语言标识为 html,并更新 v-model 为 :model-value 以符合 Vue 3 写法 - 补充插槽、属性和方法的说明,优化自定义内容与样式的描述 - 规范化 props 类型标注,统一数值类属性类型为 number - 更新事件参数格式,移除冗余字段说明 - 更新本地化标题文本,保持中英文一致
- 在 H5 环境中使用 useLockScroll 返回的 lock 和 unlock 方法以正确控制滚动锁定 - 为 popoverStyle 增加更精确的 TypeScript 类型定义,提升代码可维护性 - 新增对 useLockScroll 的 mock 实现,完善组件单元测试覆盖
该提交移除了 `src/subPages/tour/index.vue` 文件中的所有内容,包括模板、脚本和样式部分。这可能是因为该页面不再需要,或其功能已被迁移至其他位置。
- 新增 filterable 属性支持本地和远程搜索功能 - 新增 refresher-enabled 属性支持下拉刷新 - 新增 scroll-to-lower-enabled 属性支持上拉加载更多 - 新增 search、refresh、scroll-to-lower 等事件 - 新增 stopRefresh 等方法 - 新增搜索和空数据插槽 - 添加本地搜索和远程搜索示例文档 - 添加下拉刷新和上拉加载示例文档 - 添加综合案例展示搜索+刷新+加载功能
移除了 getCurrentColData 和 getAllColData 方法的文档说明, 这些方法已在组件中移除。
- 在文档导航中添加 DragSort 拖拽排序组件链接 - 添加英文和中文国际化配置 - 配置页面路由和导航标题 - 在首页组件列表中注册新组件 - 在全局类型定义中声明组件类型
- 在中文文档导航中添加DragSort拖拽排序组件链接 - 添加国际化词条:en-US.json和zh-CN.json中的dragSort翻译 - 配置pages.json注册dragSort页面路径和样式设置 - 在首页组件中注册dragSort组件入口 - 在全局类型定义中声明WdDragSort、WdDragSortItem和WdDragHandle组件类型
- 在文档导航中添加 QRCode 组件链接 - 添加英文和中文本地化词条 - 配置页面路由和导航栏标题 - 更新首页组件列表 - 移除未使用的错误处理导入 - 在全局类型声明中注册 WdQrCode 组件
|
@Xiabaiyou is attempting to deploy a commit to the weisheng's projects Team on Vercel. A member of the Team first needs to authorize it. |
✅ Deploy Preview for wot-design-uni ready!Built without sensitive environment variables
To edit notification comments on pull requests, go to your Netlify project configuration. |
简述添加了三个新组件(Tour 导览、DragSort 拖拽排序、QRCode 二维码),扩展了 ColPicker 组件以支持搜索和下拉刷新功能,并更新了相应的文档、导航菜单和国际化配置。 更改
序列图sequenceDiagram
participant User
participant DragSort Component
participant Item Manager
participant Child Item
participant DOM
User->>DragSort Component: 触发长按或拖动
DragSort Component->>Item Manager: onDragStart(index)
Item Manager->>Item Manager: 计算布局槽位、初始偏移
Item Manager->>Child Item: 发出 drag-start 事件
User->>Child Item: 移动手指
Child Item->>DragSort Component: onDragMove(touch)
DragSort Component->>Item Manager: 更新拖动增量、边界判定
Item Manager->>Item Manager: 检查交换/移动逻辑<br/>(checkSwap)
Item Manager->>DOM: 更新项目样式/z-index
DragSort Component->>DragSort Component: 触发自动滚动(边界检测)
User->>Child Item: 松开手指
Child Item->>DragSort Component: onDragEnd()
DragSort Component->>Item Manager: 解析最终位置、应用排序
Item Manager->>Item Manager: 发出 change/update:modelValue
DragSort Component->>User: 返回最终顺序
sequenceDiagram
participant User
participant Tour Component
participant DOM Query
participant Scroll Manager
participant Step Renderer
User->>Tour Component: 设置 v-model(true)、steps 数据
Tour Component->>DOM Query: 查询目标元素位置
DOM Query-->>Tour Component: 返回元素 rect
Tour Component->>Scroll Manager: 检查是否需要滚动<br/>确保元素可见
Scroll Manager->>Scroll Manager: 计算滚动方向和距离
Scroll Manager-->>Tour Component: 滚动完成
Tour Component->>Step Renderer: 渲染高亮区域和 Popover
Step Renderer->>Step Renderer: 根据元素位置<br/>计算 popover 朝向(上/下)
Step Renderer-->>Tour Component: 渲染完成
User->>Step Renderer: 点击"下一步"按钮
Step Renderer->>Tour Component: 触发 next 事件
Tour Component->>Tour Component: 更新 currentIndex
Tour Component->>DOM Query: 查询下一个目标元素
DOM Query-->>Tour Component: 返回新位置
Tour Component->>Scroll Manager: 滚动到新目标
Tour Component->>Step Renderer: 重新渲染新步骤
预估代码审查工作量🎯 5 (Critical) | ⏱️ ~120 分钟 可能相关的 PR
建议审查者
诗歌
✨ 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: 11
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
🤖 Fix all issues with AI agents
In `@src/locale/en-US.json`:
- Around line 1648-1657: The JSON contains duplicate keys that silently override
earlier translations: the new "dian-zhuang" (value "Dots") duplicates an
existing "dian-zhuang" (value "Punctate") and "yuan-jiao" (value "Rounded")
duplicates an existing "yuan-jiao" (value "rounded corners"); resolve by either
reusing the existing keys if the meanings truly match or renaming the
QR-code-specific keys (for example change "dian-zhuang" → "dian-zhuang-qrcode"
and "yuan-jiao" → "yuan-jiao-qrcode") and update any code that references the
new keys accordingly to prevent silent overwrites.
In `@src/subPages/dragSort/Index.vue`:
- Around line 2-9: The current code sets :style="{ pointerEvents: canScrollY ?
'auto' : 'none' }" on the scroll-view which blocks all touch events (including
drag touchmove/touchend) when canScrollY is false; change the approach to stop
using pointerEvents to disable scrolling — instead bind scroll-y to canScrollY
(or a dedicated isScrollingEnabled flag) so the scroll behavior toggles without
blocking child touch events, or condition pointerEvents on a drag-specific flag
(e.g., isDragging) so only non-drag interactions are affected; also fix the
commented page-meta ternary to use the correct overflow values and logic (e.g.,
"overflow:" + (canScrollY ? 'auto' : 'hidden')) and reference canScrollY and the
scroll-view element when making these changes.
In `@src/uni_modules/wot-design-uni/components/wd-drag-sort/wd-drag-sort.vue`:
- Around line 322-334: The timer initDebounceTimer set inside the watchers for
modelValue and children can fire after the component is destroyed and call
dragInit in an unmounted context; update onBeforeUnmount to clear and nullify
initDebounceTimer (similar to updateTimer/silentTimer) and remove any scheduled
callbacks so dragInit won't run post-unmount — locate the initDebounceTimer
variable and the onBeforeUnmount block and add a clearTimeout(initDebounceTimer)
followed by initDebounceTimer = null within that block.
In `@src/uni_modules/wot-design-uni/components/wd-qr-code/qrcode.d.ts`:
- Around line 1-21: Add type declarations for all publicly exported symbols from
qrcode.js: declare functions createQRCodeData(text: string, options?:
{typeNumber?: number; errorCorrectLevel?: number}): boolean[][] (or appropriate
matrix type), getTypeNumber(text: string, errorCorrectLevel: number): number,
and getUTF8Length(text: string): number; declare classes QRCodeModel,
QR8bitByte, QRBitBuffer, QRPolynomial, QRRSBlock with their public constructors
and method signatures used by consumers; declare utility objects QRMath and
QRUtil with their exposed methods/properties; and add enums QRMode and
QRMaskPattern with the exported members; ensure each declaration is exported
(export declare ...) and that types/return values match the implementations of
generateQRCode, createQRCodeData, getTypeNumber, and getUTF8Length so the d.ts
fully covers the module's public API.
In `@src/uni_modules/wot-design-uni/components/wd-qr-code/qrcode.js`:
- Around line 468-482: PATTERN_POSITION_TABLE only contains entries for versions
1–10 causing getPatternPosition to return empty for versions 11+, breaking
alignment pattern placement; update PATTERN_POSITION_TABLE to include the full
set of position arrays for QR versions 1–40 (the same complete table used in the
original/standard implementation) so getPatternPosition(version) returns the
correct coordinates for versions 11–40; locate PATTERN_POSITION_TABLE in
qrcode.js and replace the truncated array with the complete pattern position
table from the QR specification (ensuring indices align with version numbers)
and remove the need for the fallback empty array.
- Around line 388-411: RS_BLOCK_TABLE currently only contains entries for QR
versions 1–4 causing getRsBlockTable and getRSBlocks to index out of range for
versions >4; fix by replacing RS_BLOCK_TABLE with the complete RS block table
for versions 1–40 (each version must provide four records for error correction
levels L/M/Q/H) or load the canonical table from a trusted source, ensuring the
array length covers all 40 versions so getRsBlockTable(version) and
getRSBlocks(...) never return undefined; verify symbols RS_BLOCK_TABLE,
getRsBlockTable, and getRSBlocks are updated/compatible with the new data shape.
- Around line 1136-1141: getUTF8Length currently compares replacedText.length (a
number) to sText (a string), so the BOM adjustment is always applied; change the
comparison to compare numeric lengths (replace the condition replacedText.length
!== sText with replacedText.length !== sText.length) so the 3-byte BOM is only
added when the encoded length differs from the original length (ensure this
change is made inside the getUTF8Length function where replacedText is
computed).
- Around line 1153-1176: The loop in getTypeNumber uses for (let i = 0, len =
QRCodeLimitLength.length; i <= len; i++) which allows i to equal len and thus
index past the end of QRCodeLimitLength; change the loop condition to i < len so
it iterates only valid indices, keeping the existing logic that reads
QRCodeLimitLength[i][...] (refer to getTypeNumber, QRCodeLimitLength,
QRErrorCorrectLevel, and the nType increment).
- Around line 120-152: In _encodeUTF8(), fix UTF-8 encoding edge cases: iterate
over this.data using codePointAt and advance the index correctly to handle
surrogate pairs (so characters outside BMP produce a single code point), replace
charCodeAt usage with codePointAt when building code and ensure you increment i
by 1 extra when encountering a surrogate pair; change the boundary checks to use
>= for 0x80 and 0x800 so code >= 0x80 and code >= 0x800 map to 2- and 3-byte
UTF-8 respectively; keep pushing the produced bytes into this.parsedData and
retain the BOM insertion check (adjust if you prefer BOM based on encoding
flag).
In `@src/uni_modules/wot-design-uni/components/wd-qr-code/wd-qr-code.vue`:
- Around line 269-274: The gradient stop calculation divides by (len - 1) which
becomes zero when props.gradientColors.length === 1; update the logic in
wd-qr-code.vue where gradientColors is iterated (the block that calls
grad.addColorStop) to handle the single-color case explicitly: if len === 1,
call grad.addColorStop(0, props.gradientColors[0]) (or a fixed valid offset like
0.0/1.0) instead of computing index/(len-1); otherwise keep the existing loop
using index/(len-1). Ensure you reference props.gradientColors and
grad.addColorStop in the modified block.
In `@src/uni_modules/wot-design-uni/components/wd-tour/types.ts`:
- Around line 80-98: The props prevText, nextText, skipText and finishText
currently hardcode Chinese strings; update their default values to pull from the
project's existing locale system (the same helper used by picker/messageBox)
instead of makeStringProp('上一步')/…; use the locale helper used across the
codebase to resolve keys like 'tour.prev','tour.next','tour.skip','tour.finish'
(with fallback values if locale entry missing) and replace the makeStringProp
defaults for prevText, nextText, skipText and finishText accordingly so the
component respects the app's internationalization.
🟡 Minor comments (22)
docs/.vitepress/locales/en-US.ts-230-234 (1)
230-234:⚠️ Potential issue | 🟡 Minoren-US 侧边栏缺少 DragSort 和 QRCode 导航项。
zh-CN 侧边栏新增了 Tour、DragSort 和 QRCode 三个组件的导航入口,但 en-US 侧边栏仅添加了 Tour。请在 en-US 侧边栏中补充 DragSort 和 QRCode 的导航项,保持两个语言版本的一致性。
docs/component/drag-sort.md-107-107 (1)
107-107:⚠️ Potential issue | 🟡 Minor文档代码示例中 CSS overflow 值错误。
'overflow'不是overflow属性的有效 CSS 值。此处回退值应为'auto'或'visible'。建议修复
- <page-meta :page-style="'overflow:' + (isScrollViewDragging ? 'hidden' : 'overflow')"> + <page-meta :page-style="'overflow:' + (isScrollViewDragging ? 'hidden' : 'auto')">docs/component/drag-sort.md-193-198 (1)
193-198:⚠️ Potential issue | 🟡 Minor局部滚动示例中
canScrollY的赋值逻辑疑似反转。拖拽开始时应禁用滚动(
canScrollY = false),拖拽结束时应恢复滚动(canScrollY = true),当前逻辑与预期相反。建议修复
const handleDragStart = (index) => { - canScrollY.value = true + canScrollY.value = false } const handleDragEnd = (index) => { - canScrollY.value = false + canScrollY.value = true }docs/component/drag-sort.md-126-154 (1)
126-154:⚠️ Potential issue | 🟡 Minor页面滚动示例中
isScrollViewDragging未声明。
handleDragStart和handleDragEnd中引用了isScrollViewDragging,但在<script setup>中缺少声明。建议修复
const scrollTop = ref(0) const currentScrollTop = ref(0) +const isScrollViewDragging = ref(false)src/uni_modules/wot-design-uni/locale/lang/zh-HK.ts-40-40 (1)
40-40:⚠️ Potential issue | 🟡 Minor
colPicker.search的繁体中文翻译'請輸入'(请输入)与英文'Search'语义不一致。英文版使用的是
'Search',繁体中文更合适的翻译应为'搜尋'或'搜索',而非'請輸入'(这更适合作为 placeholder 使用)。建议核实其他语言的翻译并统一语义。src/locale/zh-CN.json-1648-1657 (1)
1648-1657:⚠️ Potential issue | 🟡 MinorJSON 中存在重复键名,且新增键未按字母顺序排列。
"dian-zhuang"(第 1652 行)与第 376 行重复"yuan-jiao"(第 1653 行)与第 1453 行重复JSON 规范下重复键的行为取决于解析器实现(通常后者覆盖前者),但这会造成维护困惑。建议移除重复项,并将新增的 QR code 相关键按字母顺序插入到文件中对应的位置,与文件现有排序规则保持一致。
src/uni_modules/wot-design-uni/components/wd-drag-sort/utils.ts-132-132 (1)
132-132:⚠️ Potential issue | 🟡 Minor
substr已被标记为废弃,请改用substring或slice。♻️ 建议修改
- const random = Math.random().toString(36).substr(2, 5) + const random = Math.random().toString(36).substring(2, 7)docs/component/tour.md-1-1 (1)
1-1:⚠️ Potential issue | 🟡 Minor文档标题与组件名不一致。
文件名为
tour.md,组件名为wd-tour,但标题写的是 "Guide 漫游组件"。根据 PR 提交记录,组件已从guide重命名为tour,标题应同步更新为 "Tour 漫游组件"。建议修改
-# Guide 漫游组件 +# Tour 漫游组件src/subPages/qrCode/Index.vue-19-19 (1)
19-19:⚠️ Potential issue | 🟡 Minor硬编码中文标题,应使用
$t()国际化。Line 19 的
title="Logo 样式"和 Line 49 的title="背景图片"直接使用了中文字符串,与其他demo-block使用$t()的方式不一致。建议统一使用 i18n 键。src/subPages/qrCode/Index.vue-27-27 (1)
27-27:⚠️ Potential issue | 🟡 Minor使用了不存在的组件属性
logo-border-radiusDemo 中第 27 行使用的
logo-border-radius在组件中不存在。组件仅定义了logo-radius(用于设置 Logo 圆角)。建议改用logo-radius="6"替代。src/pages.json-1345-1374 (1)
1345-1374:⚠️ Potential issue | 🟡 Minor
dragSort和qrCode页面未使用国际化占位符其他所有页面在
//#ifndefMP条件下使用%xxx-title%格式的国际化占位符,但dragSort和qrCode直接硬编码了中文标题。这会导致非小程序平台的多语言支持缺失。♻️ 建议修改
// `#ifndef` MP - "navigationBarTitleText": "DragSort 拖拽排序" + "navigationBarTitleText": "%dragsort-title%" // `#endif`// `#ifndef` MP - "navigationBarTitleText": "QRCode 二维码" + "navigationBarTitleText": "%qrcode-title%" // `#endif`src/uni_modules/wot-design-uni/components/wd-drag-sort-item/wd-drag-sort-item.vue-101-111 (1)
101-111:⚠️ Potential issue | 🟡 Minor
isReady变为false时调用空init()无实际作用此 watcher 在
isReady变为false时通过setTimeout调用init(),但init()是空函数。如果此处确实需要在父组件重置后重新初始化(例如重新测量 DOM),应补充实际逻辑;否则应移除此 watcher。tests/components/wd-tour.test.ts-175-175 (1)
175-175:⚠️ Potential issue | 🟡 Minor
// ... existing code ...注释看起来像是误留的占位符此注释通常用于代码差异展示,不应出现在实际测试文件中。如果此处确实有被省略的测试用例,请补充;否则请移除此行。
src/uni_modules/wot-design-uni/components/wd-col-picker/wd-col-picker.vue-639-645 (1)
639-645:⚠️ Potential issue | 🟡 Minor
stopRefresh中残留console.log调试日志第 644 行的
console.log('[wd-col-picker] 停止刷新状态')是调试代码,不应保留在组件正式发布代码中。移除调试日志
function stopRefresh() { refreshTriggered.value = false - console.log('[wd-col-picker] 停止刷新状态') }tests/components/wd-tour.test.ts-42-45 (1)
42-45:⚠️ Potential issue | 🟡 Minor
Object.defineProperty缺少configurable: true,可能污染其他测试套件未设置
configurable: true意味着此全局uni对象在测试运行期间无法被重新定义或删除。如果其他测试文件也需要定义不同的unimock,可能会抛出TypeError: Cannot redefine property: uni。建议添加 configurable
Object.defineProperty(global, 'uni', { - value: mockUni + value: mockUni, + configurable: true, + writable: true })src/uni_modules/wot-design-uni/components/wd-col-picker/wd-col-picker.vue-113-117 (1)
113-117:⚠️ Potential issue | 🟡 Minor空状态文案
"暂无内容"硬编码了中文,未使用国际化组件内其他字符串均通过
translate()实现国际化(如translate('placeholder')、translate('select')等),但第 115 行的空状态提示直接写了中文字符串"暂无内容"。应添加对应的 locale key 并使用translate函数。建议使用国际化
<slot name="empty"> - <wd-status-tip image="content" tip="暂无内容" /> + <wd-status-tip image="content" :tip="translate('empty')" /> </slot>需要在对应的 locale 文件中添加
empty的翻译。src/subPages/colPicker/Index.vue-623-657 (1)
623-657:⚠️ Potential issue | 🟡 Minor
DB数组声明后从未使用,闭包缓存逻辑未生效
getComplexMockData使用 IIFE 创建闭包,声明了TOTAL_COUNT和DB数组(第 625-626 行),但实际数据在每次调用时通过fullTable重新生成,DB从未被填充或读取。注释说"使用闭包缓存'数据库'",但实际并未实现缓存。移除未使用的 DB 或实现实际缓存
const getComplexMockData = (() => { const TOTAL_COUNT = 100 - const DB: any[] = [] return (colIndex: number, page: number, pageSize: number = 15, keyword: string = '') => {src/subPages/tour/Index.vue-308-343 (1)
308-343:⚠️ Potential issue | 🟡 Minor各
startXxxTour函数对scrollToTop()的await使用不一致
startBasicTour(第 308 行)使用了await scrollToTop()+nextTick,而startMaskNextTour(第 315 行)、startCustomMaskTour(第 320 行)等函数直接调用scrollToTop()而不等待。这可能导致 tour 在页面滚动完成前就开始显示,引发高亮定位不准确的问题。建议统一使用 await
-function startMaskNextTour() { - scrollToTop() - showClickMaskTour.value = true +async function startMaskNextTour() { + await scrollToTop() + nextTick(() => { + showClickMaskTour.value = true + }) }其他 start 函数同理。
docs/component/col-picker.md-632-641 (1)
632-641:⚠️ Potential issue | 🟡 Minor模板中
filterType应使用 kebab-casefilter-type以保持文档一致性。第 635 行使用了 camelCase
filterType="remote",而属性表(第 893 行)文档中描述为filter-type。HTML 模板示例建议统一使用 kebab-case 写法。🔧 建议修改
- filterType="remote" + filter-type="remote"src/uni_modules/wot-design-uni/components/wd-drag-sort/wd-drag-sort.vue-718-722 (1)
718-722:⚠️ Potential issue | 🟡 Minor
getItemStyle在部分分支返回undefined,类型不一致。第 716 行
if (slotIdx === undefined) return {}返回空对象,但第 721 行if (!slot || !originalRect) return隐式返回undefined。调用方可能期望返回值始终为对象类型。🔧 建议统一返回空对象
- if (!slot || !originalRect) return + if (!slot || !originalRect) return {}docs/component/col-picker.md-896-900 (1)
896-900:⚠️ Potential issue | 🟡 Minor
refresher-background和refresher-default-style属性在表格中重复定义了。第 896-897 行已经定义了
refresher-default-style和refresher-background,第 899-900 行又重复定义了一次,需要删除重复项。🔧 建议移除重复行
| scroll-to-lower-enabled| 是否开启上拉加载更多 | boolean | - | false | - | -| refresher-background | 下拉刷新区域背景颜色 | string | - | transparent | - | -| refresher-default-style| 下拉刷新默认样式 | string | 'black' / 'white' / 'none' | 'white' | - |src/uni_modules/wot-design-uni/components/wd-tour/wd-tour.vue-77-79 (1)
77-79:⚠️ Potential issue | 🟡 Minor移除未使用的
lock和unlock解构变量。
useLockScroll通过内部 watch 机制自动管理滚动锁定,无需显式调用解构出的lock和unlock函数。建议删除第 78 行的这两个变量以保持代码整洁。
🧹 Nitpick comments (35)
docs/.vitepress/locales/zh-CN.ts (2)
238-241: 格式不一致:Tour 条目缺少换行和空格。
},{应拆分为独立行,并与文件中其他条目保持相同的缩进风格。建议的格式修正
- },{ - link:'/component/tour', + }, + { + link: '/component/tour', text: 'Tour 漫游' }
413-417: 格式不一致:DragSort 条目缩进与周围代码不匹配。此处使用了 6 空格缩进,而文件中其他条目均使用 12 空格缩进。
建议的格式修正
}, { - link: '/component/drag-sort', - text: 'DragSort 拖拽排序' - } + link: '/component/drag-sort', + text: 'DragSort 拖拽排序' + }.hbuilderx/launch.json (1)
1-9: IDE 特定配置文件不宜提交到仓库。
.hbuilderx/launch.json是 HBuilderX 的本地启动配置,属于开发者个人 IDE 设置。建议将.hbuilderx/添加到.gitignore中,与现有的.idea/和.project等 IDE 配置保持一致,避免不同开发者之间的配置冲突。src/locale/en-US.json (1)
972-972: Key 命名风格不一致:使用了下划线。
"remote_down-and-load-more"混合使用了下划线和连字符,而文件中其他 key 统一使用连字符(kebab-case)。建议改为"remote-down-and-load-more"以保持一致性。src/uni_modules/wot-design-uni/components/wd-tour/types.ts (1)
133-136:highlightStyle未使用 helper 函数定义,与其他 prop 风格不一致。其他布尔/数字/字符串 prop 均使用了
makeBooleanProp/makeNumberProp/makeStringProp等 helper,此处直接手写了{ type: Object as PropType<...>, default: () => ({}) }。建议考虑增加一个makeObjectProphelper 或至少保持一致的写法风格。src/uni_modules/wot-design-uni/components/wd-qr-code/types.ts (2)
1-1: 缺少makeBooleanProp的导入,导致enableGradient使用了原始写法。
enableGradient(第 35 行)直接使用{ type: Boolean, default: false }而非makeBooleanProp(false),原因是未导入该 helper。建议补充导入并统一写法。♻️ 建议修改
-import { baseProps, makeNumberProp, makeStringProp, makeArrayProp } from '../common/props' +import { baseProps, makeBooleanProp, makeNumberProp, makeStringProp, makeArrayProp } from '../common/props'第 35 行相应修改:
- enableGradient: { type: Boolean, default: false }, + enableGradient: makeBooleanProp(false),
3-55: 缺少QrCodeProps类型导出。对比
wd-tour/types.ts和wd-drag-sort-item/types.ts,它们都导出了对应的 Props 类型(如export type TourProps = typeof tourProps)。此文件缺少类似的类型导出,会影响消费方的类型推导。♻️ 建议在文件末尾补充
+ +export type QrCodeProps = typeof qrCodePropssrc/uni_modules/wot-design-uni/components/wd-drag-sort/utils.ts (2)
7-16: 项目中已存在throttle实现(common/util.ts第 661-686 行),此处新增了一个简化版本。
common/util.ts中的throttle支持尾部触发(trailing edge),而此版本仅支持前沿触发(leading edge),延迟期间的调用会被静默丢弃。如果这是有意为之(drag-sort 场景需要更简单的节流),建议加一行注释说明差异;否则考虑复用已有实现以避免重复。
65-70:moveArrayItem和swapArrayItem均未校验索引边界。当
fromIndex或toIndex越界时,moveArrayItem的splice会返回空数组导致插入undefined,swapArrayItem则会静默写入undefined。如果调用方已保证索引合法可以接受,但建议至少加个防御性检查或在 JSDoc 中注明前置条件。src/uni_modules/wot-design-uni/locale/lang/tr-TR.ts (1)
55-56: 翻译语义与其他语言略有不同,请确认是否符合预期。土耳其语
search: 'Ara'表示"搜索",而大多数其他语言使用的是"请输入"语义(如中文请输入、德语Bitte eingeben)。作为搜索输入框的 placeholder,两种风格都可以接受,但如果希望保持跨语言一致性,可以考虑使用'Lütfen girin'(请输入)。src/uni_modules/wot-design-uni/components/wd-tour/index.scss (2)
37-45:border-radius单位不一致:rpxvspx。Line 40 使用了
16rpx,而文件其余地方(如 line 31border-radius: 8px、line 57border-radius: 4px)统一使用px。建议确认是否有意使用rpx,否则应统一单位以保持一致性。
63-83:next__default和finish__default样式完全相同,可考虑复用。这两个块的样式定义完全一致(
font-size、border-radius、padding、background-color、color、white-space),可以抽取为一个公共样式或 mixin 来减少重复。src/uni_modules/wot-design-uni/components/wd-drag-sort/index.scss (2)
12-19: 占位符样式中使用了硬编码颜色值
rgba(0, 0, 0, 0.05)和#ddd是硬编码的颜色值,其他组件(如 dark 主题下的 col-picker)使用了 SCSS 变量。建议将这些颜色提取为变量以支持主题定制和深色模式。
1-24: 缺少深色模式 (.wot-theme-dark) 样式参考
wd-col-picker/index.scss等其他组件,均提供了.wot-theme-dark下的样式覆盖。当前拖拽排序组件在深色模式下占位符的浅色背景和边框可能不协调。src/uni_modules/wot-design-uni/components/wd-col-picker/index.scss (1)
113-113: 移除注释掉的代码
// height: $-col-picker-list-height;已被注释,高度现在由__list-scroll-view承担。建议删除此行以保持代码整洁。♻️ 建议修改
`@include` e(list) { - // height: $-col-picker-list-height; padding-bottom: $-col-picker-list-padding-bottom;src/uni_modules/wot-design-uni/components/wd-col-picker/types.ts (2)
185-191:ColPickerHandleScrollToLowerOption中的isRefresh字段语义不清
isRefresh出现在"上拉加载更多"的选项类型中,语义上容易与下拉刷新混淆。建议确认该字段的用途并在注释中说明清楚,或考虑更具描述性的命名(例如isInitialLoad、shouldReset等)。
143-173: 新增 ColPicker 搜索和刷新能力的属性定义,整体 LGTM新增的
filterable、filterType、refresherEnabled、scrollToLowerEnabled等属性定义清晰,注释充分。一个小的不一致:
refresherDefaultStyle(Line 166-169)使用了内联对象定义,而非复用makeStringProp工具函数。虽然功能正确,但与周围属性定义风格不统一。src/subPages/dragSort/Index.vue (2)
294-313: 两个演示块共用同一个list10,交互会互相影响"固定元素 (Sortable) move"(第 274 行)和 "固定元素 (Sortable) swap"(第 294 行)都绑定了
v-model="list10"。在一个演示块中拖拽排序后,另一个演示块的列表顺序也会同步改变,可能不是预期行为。建议使用独立的数据源
const list10 = ref(generateList(6, '固定')) +const list10Swap = ref(generateList(6, '固定'))第 297 行改为:
- v-model="list10" + v-model="list10Swap"第 305 行也做相应替换。
480-482:Math.random() - 0.5作为比较函数的 shuffle 算法有偏差
Array.sort(() => Math.random() - 0.5)不是均匀随机洗牌,不同浏览器引擎的排序实现会导致不同程度的偏差。对于 demo 页面影响不大,但可以考虑使用 Fisher-Yates 算法。Fisher-Yates 洗牌
function shuffleList() { - listProgrammatic.value = [...listProgrammatic.value].sort(() => Math.random() - 0.5) + const arr = [...listProgrammatic.value] + for (let i = arr.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)) + ;[arr[i], arr[j]] = [arr[j], arr[i]] + } + listProgrammatic.value = arr }tests/components/wd-tour.test.ts (2)
59-81:vi.clearAllMocks()已清除所有 mock,后续mockClear()是多余的
vi.clearAllMocks()会清除所有 mock 函数的调用记录和实现,因此第 62 行的mockUni.createSelectorQuery.mockClear()是冗余的。同时,第 63-80 行的mockImplementation与文件顶部(第 15-32 行)的初始 mock 实现完全相同,可以考虑提取为共享工厂函数以减少重复。
84-97: 整体测试结构合理,覆盖了核心交互场景测试覆盖了基本渲染、按钮导航、事件发射、插槽自定义、样式属性和错误处理等关键场景,结构清晰。不过整个测试套件大量使用
await new Promise(resolve => setTimeout(resolve, N))来等待异步操作,这使得测试运行较慢且在 CI 环境下可能不稳定。如果后续有时间,可以考虑使用vi.useFakeTimers()+vi.advanceTimersByTime()来加速和稳定测试。src/uni_modules/wot-design-uni/components/wd-drag-sort-item/wd-drag-sort-item.vue (2)
178-193:init()函数体为空,相关调用均为无效代码
init()函数除了if (!parent) return之外没有任何逻辑,但它被onMounted中的setTimeout(第 189 行)和isReadywatcher(第 107 行)调用。注释说明了这是因为useChildren/defineExpose后不再需要手动传递,但遗留的空函数和调用增加了认知复杂度。建议清理死代码
-/** - * 初始化,注册到 manager - */ -const init = () => { - if (!parent) return - // 将 getRect 方法传递给 manager - 使用 useChildren/defineExpose 后不再需要手动传递 - // 但是父组件依赖于监听 children 或手动初始化 - // 父组件在 dragInit 中调用 child.getRect() -} - -let initTimer: ReturnType<typeof setTimeout> | null = null - -onMounted(() => { - // 延时确保 DOM 渲染完成 - initTimer = setTimeout(() => { - init() - initTimer = null - }, 100) -}) +onMounted(() => { + // useChildren/defineExpose 处理了注册逻辑 + // 父组件在 dragInit 中调用 child.getRect() +})同时可以移除
isReadywatcher 中对init()的调用,以及onBeforeUnmount中对initTimer的清理。
33-33:useSlots已导入并调用,但slots变量未被使用第 33 行导入了
useSlots,第 49 行调用了const slots = useSlots(),但slots在组件中从未被引用。Also applies to: 49-49
src/subPages/colPicker/Index.vue (2)
766-771: 文件中有两个onMounted钩子,相距 600+ 行第一个
onMounted在第 129 行,第二个在第 766 行。虽然 Vue 3 支持多次注册onMounted,但将它们分散在文件中降低了可读性和可维护性。建议合并到一处。合并 onMounted
onMounted(async () => { toast.loading(t('shu-ju-jia-zai-zhong')) await sleep() toast.close() value2.value = ['150000', '150100', '150121'] getMockData(0, 1).then((data) => { columnsAsync.value = [data] pageMap.value[0] = 1 }) + + // 初始化综合案例第一列数据 + pageMapComplex.value[0] = 1 + getComplexMockData(0, 1).then((data) => { + columnsComplex.value = [data] + }) })然后移除第 766-771 行的第二个
onMounted。
279-293:columnChangeLocal与columnChange1逻辑完全相同第 279-293 行的
columnChangeLocal和第 213-227 行的columnChange1实现完全一致,可以直接复用。复用已有函数
-const columnChangeLocal: ColPickerColumnChange = ({ selectedItem, resolve, finish }) => { - const areaData = findChildrenByCode(colPickerData, selectedItem.value) - if (areaData && areaData.length) { - resolve( - areaData.map((item) => { - return { - value: item.value, - label: item.text - } - }) - ) - } else { - finish() - } -} +const columnChangeLocal = columnChange1src/uni_modules/wot-design-uni/components/wd-drag-sort/types.ts (1)
26-39:DragSortProvide接口中大量使用any类型,削弱了类型安全
register、onDragStart、onDragMove、getPosition、getItemStyle、getCurrentPosition等方法的参数和返回值均为any。虽然拖拽场景下数据结构可能较灵活,但定义具体类型(如TouchInfo、Rect、ItemStyle等接口)能提高开发体验和编译期错误检查。示例:定义具体类型
+export interface DragTouchInfo { + clientX: number + clientY: number +} + +export interface DragRect { + left: number + top: number + width: number + height: number +} + export type DragSortProvide = { props: DragSortProps isReady: Ref<boolean> draggedIndex: Ref<number> - register: (index: number, helper: any, sortable: boolean) => void + register: (index: number, helper: { getRect: () => Promise<DragRect | null> }, sortable: boolean) => void unregister: (index: number) => void - onDragStart: (index: number, touch: any) => void - onDragMove: (touch: any) => void + onDragStart: (index: number, touch: DragTouchInfo) => void + onDragMove: (touch: DragTouchInfo) => void onDragEnd: () => void - getPosition: (index: number) => any - getItemStyle: (index: number) => any - getCurrentPosition: (index: number) => any + getPosition: (index: number) => DragRect | null + getItemStyle: (index: number) => Record<string, string> | null + getCurrentPosition: (index: number) => DragRect | null componentId: string }src/subPages/tour/Index.vue (2)
347-367:handleFinish和handleSkip实现完全相同,存在代码重复两个函数的逻辑一模一样——都是将所有 tour 的显示状态重置为
false。可以提取为一个公共函数。合并为共用函数
+function closeTours() { + showBasicTour.value = false + showClickMaskTour.value = false + showCustomMaskTour.value = false + showNoMaskTour.value = false + showCustomHighlightTour.value = false + showCustomContentTour.value = false + showControlTour.value = false +} + function handleFinish() { console.log('引导完成') - showBasicTour.value = false - showClickMaskTour.value = false - showCustomMaskTour.value = false - showNoMaskTour.value = false - showCustomHighlightTour.value = false - showCustomContentTour.value = false - showControlTour.value = false + closeTours() } function handleSkip() { console.log('引导跳过') - showBasicTour.value = false - showClickMaskTour.value = false - showCustomMaskTour.value = false - showNoMaskTour.value = false - showCustomHighlightTour.value = false - showCustomContentTour.value = false - showControlTour.value = false + closeTours() }
182-182: 导入了watch但未使用第 182 行
import { ref, watch, nextTick } from 'vue'中的watch在脚本中没有被引用。-import { ref, watch, nextTick } from 'vue' +import { ref, nextTick } from 'vue'src/uni_modules/wot-design-uni/components/wd-tour/wd-tour.vue (2)
314-340:calculateTipPosition中存在大量注释代码,应清理。第 318-326 行包含多段注释掉的逻辑(MP 平台菜单按钮处理和
topOffset相关代码)。如果这些是未来计划实现的功能,建议使用 TODO 注释标记;如果已弃用,建议直接移除以保持代码整洁。
372-390:handleFinish和handleSkip存在重复逻辑,建议提取公共方法。两个方法都执行了相同的重置操作(
currentIndex = 0、oldscrollTop = 0、emit('update:modelValue', false)),仅 emit 的事件名和参数不同。可以提取公共的关闭逻辑减少重复。♻️ 建议提取公共方法
+function closeTour() { + currentIndex.value = 0 + oldscrollTop.value = 0 + emit('update:modelValue', false) +} + function handleFinish() { emit('finish', { current: currentIndex.value, total: props.steps.length }) - currentIndex.value = 0 - oldscrollTop.value = 0 - emit('update:modelValue', false) + closeTour() } function handleSkip() { emit('skip', { current: currentIndex.value, total: props.steps.length }) - currentIndex.value = 0 - oldscrollTop.value = 0 - emit('update:modelValue', false) + closeTour() }src/uni_modules/wot-design-uni/components/wd-qr-code/wd-qr-code.vue (3)
51-83:customStyle计算属性过于复杂,建议简化。当前实现包含 JSON 字符串检测和解析逻辑(第 66-77 行),但这种
{color: red}格式既不是合法 JSON 也不是合法 CSS。其他组件(如wd-divider)的customStyle处理更为简洁。建议简化为仅处理对象和字符串两种情况。♻️ 建议简化
const customStyle = computed(() => { const style = props.customStyle - - // 如果是空值,返回空字符串 - if (!style) { - return '' - } - - // 如果是对象,转换为字符串 - if (typeof style === 'object') { - return objToStyle(style) - } - - // 如果是字符串,直接使用(已经是 CSS 样式字符串) - if (typeof style === 'string') { - // 尝试检测是否是 JSON 字符串 - const trimmed = style.trim() - if (trimmed.startsWith('{') && trimmed.endsWith('}')) { - try { - const styleObj = JSON.parse(trimmed) - return objToStyle(styleObj) - } catch (e) { - // JSON 解析失败,但仍可能是有效的 CSS 字符串(如 {color: red} 这种非标准写法) - console.warn('customStyle looks like JSON but parse failed, using as CSS string') - return style - } - } - // 普通 CSS 字符串,直接使用 - return style - } - - return '' + if (!style) return '' + if (typeof style === 'object') return objToStyle(style) + return String(style) })
16-16:addUnit已导入但未使用。第 16 行导入了
addUnit,但在整个文件中没有被调用。♻️ 建议移除未使用的导入
-import { uuid, addUnit, objToStyle } from '../common/util' +import { uuid, objToStyle } from '../common/util'
536-551:handleImageSrc中微信平台的try/catch是无效逻辑。第 538-545 行:
fs.accessSync(src)成功时设置img.src = src,失败时 catch 块同样设置img.src = src。两个分支行为完全相同,try/catch没有实际作用。src/uni_modules/wot-design-uni/components/wd-drag-sort/wd-drag-sort.vue (1)
139-145: 将状态附加到函数对象上不是好的模式,建议使用独立变量。
(dragInit as any).retryCount将重试计数器挂载到函数对象上,同样的模式在onDragMove中也使用了(onDragMove as any).lastTime(第 537-538 行)。这种做法破坏了类型安全,不易维护。建议使用模块级别的变量替代。♻️ 建议使用独立变量
+let retryCount = 0 + const retryLayout = () => { - if (!(dragInit as any).retryCount) (dragInit as any).retryCount = 0 - if ((dragInit as any).retryCount < 3) { - ;(dragInit as any).retryCount++ + if (retryCount < 3) { + retryCount++ setTimeout(() => dragInit(), 50) } }并在
handleLayout中成功后重置:- ;(dragInit as any).retryCount = 0 + retryCount = 0src/uni_modules/wot-design-uni/components/wd-qr-code/qrcode.js (1)
1242-1259: ESM 文件中混用 CommonJSmodule.exports可能导致构建问题。该文件使用 ES module
export语法(第 1225-1240 行),同时在第 1243-1259 行通过module.exports进行 CommonJS 导出。在 uni-app 的构建系统中,.js文件可能被作为 ESM 模块处理,此时module变量未定义,虽然有typeof module !== 'undefined'保护不会报错,但这段代码实际上是多余的死代码。
| "qrcode-er-wei-ma": "QRCode", | ||
| "zi-ding-yi-chi-cun": "Custom Size", | ||
| "dai-logo": "With Logo", | ||
| "dao-chu-tu-pian": "Export Image", | ||
| "dian-zhuang": "Dots", | ||
| "yuan-jiao": "Rounded", | ||
| "ye-hua": "Liquid", | ||
| "dao-chu-jie-guo": "Export Result:", | ||
| "dao-chu-cheng-gong": "Export Success", | ||
| "dao-chu-shi-bai": "Export Failed" |
There was a problem hiding this comment.
重复的 JSON key 会静默覆盖已有翻译值。
"dian-zhuang"(第 1652 行值为 "Dots")与已有的第 376 行(值为 "Punctate")重复;"yuan-jiao"(第 1653 行值为 "Rounded")与已有的第 1453 行(值为 "rounded corners")重复。JSON 规范中后出现的 key 会覆盖前者,可能导致已有 UI 文案被意外修改。
建议为 QR code 场景的新 key 添加后缀以避免冲突,例如 "dian-zhuang-qrcode" 和 "yuan-jiao-qrcode",或复用已有 key(如果语义确实一致则只保留一个值)。
🤖 Prompt for AI Agents
In `@src/locale/en-US.json` around lines 1648 - 1657, The JSON contains duplicate
keys that silently override earlier translations: the new "dian-zhuang" (value
"Dots") duplicates an existing "dian-zhuang" (value "Punctate") and "yuan-jiao"
(value "Rounded") duplicates an existing "yuan-jiao" (value "rounded corners");
resolve by either reusing the existing keys if the meanings truly match or
renaming the QR-code-specific keys (for example change "dian-zhuang" →
"dian-zhuang-qrcode" and "yuan-jiao" → "yuan-jiao-qrcode") and update any code
that references the new keys accordingly to prevent silent overwrites.
| <!-- <page-meta :page-style="'overflow:' + (canScrollY ? 'hidden' : 'overflow')"></page-meta> --> | ||
| <page-wraper> | ||
| <scroll-view | ||
| scroll-y | ||
| style="height: calc(100vh - env(safe-area-inset-bottom))" | ||
| :style="{ pointerEvents: canScrollY ? 'auto' : 'none' }" | ||
| :scroll-top="currentScrollTop" | ||
| @scroll="onScroll" |
There was a problem hiding this comment.
pointerEvents: 'none' 会在拖拽过程中阻断所有触摸事件
当 canScrollY 为 false 时(即 MP/APP-PLUS 平台拖拽期间),pointerEvents 被设为 'none',这不仅会阻止滚动,还会阻断 scroll-view 内所有子元素的触摸事件,包括正在进行的拖拽操作本身。这可能导致 touchmove 和 touchend 事件无法正常触发。
另外,第 2 行被注释的 page-meta 中三元表达式逻辑是反的:canScrollY ? 'hidden' : 'overflow'——当可以滚动时反而设置 hidden,且 'overflow' 不是有效的 overflow 属性值,应为 'auto' 或 'scroll'。
建议修复 pointerEvents 方向
- :style="{ pointerEvents: canScrollY ? 'auto' : 'none' }"
+ :style="{ overflow: canScrollY ? 'auto' : 'hidden' }"如果必须通过 pointerEvents 控制,应确保拖拽中的 item 不受影响,或者考虑使用 scroll-view 的 scroll-y 属性动态切换。
🤖 Prompt for AI Agents
In `@src/subPages/dragSort/Index.vue` around lines 2 - 9, The current code sets
:style="{ pointerEvents: canScrollY ? 'auto' : 'none' }" on the scroll-view
which blocks all touch events (including drag touchmove/touchend) when
canScrollY is false; change the approach to stop using pointerEvents to disable
scrolling — instead bind scroll-y to canScrollY (or a dedicated
isScrollingEnabled flag) so the scroll behavior toggles without blocking child
touch events, or condition pointerEvents on a drag-specific flag (e.g.,
isDragging) so only non-drag interactions are affected; also fix the commented
page-meta ternary to use the correct overflow values and logic (e.g.,
"overflow:" + (canScrollY ? 'auto' : 'hidden')) and reference canScrollY and the
scroll-view element when making these changes.
| // 组件销毁前清除定时器 | ||
| onBeforeUnmount(() => { | ||
| uni.offWindowResize(onWindowResize) | ||
| stopAutoScroll() | ||
| if (updateTimer) { | ||
| clearTimeout(updateTimer) | ||
| updateTimer = null | ||
| } | ||
| if (silentTimer) { | ||
| clearTimeout(silentTimer) | ||
| silentTimer = null | ||
| } | ||
| }) |
There was a problem hiding this comment.
initDebounceTimer 未在 onBeforeUnmount 中清理,可能导致组件销毁后回调执行。
第 97 行声明的 initDebounceTimer 在 modelValue 和 children 的 watch 中被设置(第 765、779 行),但 onBeforeUnmount 中未清除该定时器。如果组件在定时器触发前被销毁,dragInit() 会在已卸载的组件上下文中执行。
🐛 建议在 onBeforeUnmount 中清理
onBeforeUnmount(() => {
uni.offWindowResize(onWindowResize)
stopAutoScroll()
+ if (initDebounceTimer) {
+ clearTimeout(initDebounceTimer)
+ initDebounceTimer = null
+ }
if (updateTimer) {
clearTimeout(updateTimer)
updateTimer = null
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // 组件销毁前清除定时器 | |
| onBeforeUnmount(() => { | |
| uni.offWindowResize(onWindowResize) | |
| stopAutoScroll() | |
| if (updateTimer) { | |
| clearTimeout(updateTimer) | |
| updateTimer = null | |
| } | |
| if (silentTimer) { | |
| clearTimeout(silentTimer) | |
| silentTimer = null | |
| } | |
| }) | |
| // 组件销毁前清除定时器 | |
| onBeforeUnmount(() => { | |
| uni.offWindowResize(onWindowResize) | |
| stopAutoScroll() | |
| if (initDebounceTimer) { | |
| clearTimeout(initDebounceTimer) | |
| initDebounceTimer = null | |
| } | |
| if (updateTimer) { | |
| clearTimeout(updateTimer) | |
| updateTimer = null | |
| } | |
| if (silentTimer) { | |
| clearTimeout(silentTimer) | |
| silentTimer = null | |
| } | |
| }) |
🤖 Prompt for AI Agents
In `@src/uni_modules/wot-design-uni/components/wd-drag-sort/wd-drag-sort.vue`
around lines 322 - 334, The timer initDebounceTimer set inside the watchers for
modelValue and children can fire after the component is destroyed and call
dragInit in an unmounted context; update onBeforeUnmount to clear and nullify
initDebounceTimer (similar to updateTimer/silentTimer) and remove any scheduled
callbacks so dragInit won't run post-unmount — locate the initDebounceTimer
variable and the onBeforeUnmount block and add a clearTimeout(initDebounceTimer)
followed by initDebounceTimer = null within that block.
| export declare const QRErrorCorrectLevel: { | ||
| L: number | ||
| M: number | ||
| Q: number | ||
| H: number | ||
| } | ||
|
|
||
| export interface QRCodeResult { | ||
| modules: boolean[][] | ||
| moduleCount: number | ||
| typeNumber: number | ||
| errorCorrectLevel: number | ||
| } | ||
|
|
||
| export declare function generateQRCode( | ||
| text: string, | ||
| options?: { | ||
| typeNumber?: number | ||
| errorCorrectLevel?: number | ||
| } | ||
| ): QRCodeResult |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
fd "qrcode\.js" --path-separator '/' -x cat -n {}Repository: Moonofweisheng/wot-design-uni
Length of output: 37808
类型声明缺失多个导出的声明
根据 qrcode.js 的实现,该模块导出了多个函数和类,但当前 .d.ts 文件中仅声明了 QRErrorCorrectLevel、QRCodeResult 和 generateQRCode。缺失的导出包括:
createQRCodeData()— 返回二维码数据矩阵getTypeNumber()— 根据文本和纠错等级获取版本号getUTF8Length()— 计算UTF-8编码长度- 内部类:
QRCodeModel、QR8bitByte、QRBitBuffer、QRPolynomial、QRRSBlock - 工具对象:
QRMath、QRUtil - 枚举:
QRMode、QRMaskPattern
请为所有公开导出的 API 补充类型声明。
🤖 Prompt for AI Agents
In `@src/uni_modules/wot-design-uni/components/wd-qr-code/qrcode.d.ts` around
lines 1 - 21, Add type declarations for all publicly exported symbols from
qrcode.js: declare functions createQRCodeData(text: string, options?:
{typeNumber?: number; errorCorrectLevel?: number}): boolean[][] (or appropriate
matrix type), getTypeNumber(text: string, errorCorrectLevel: number): number,
and getUTF8Length(text: string): number; declare classes QRCodeModel,
QR8bitByte, QRBitBuffer, QRPolynomial, QRRSBlock with their public constructors
and method signatures used by consumers; declare utility objects QRMath and
QRUtil with their exposed methods/properties; and add enums QRMode and
QRMaskPattern with the exported members; ensure each declaration is exported
(export declare ...) and that types/return values match the implementations of
generateQRCode, createQRCodeData, getTypeNumber, and getUTF8Length so the d.ts
fully covers the module's public API.
| _encodeUTF8() { | ||
| for (let i = 0, l = this.data.length; i < l; i++) { | ||
| const code = this.data.charCodeAt(i) | ||
| const byteArray = [] | ||
|
|
||
| if (code > 0x10000) { | ||
| // 4字节UTF-8 | ||
| byteArray[0] = 0xf0 | ((code & 0x1c0000) >>> 18) | ||
| byteArray[1] = 0x80 | ((code & 0x3f000) >>> 12) | ||
| byteArray[2] = 0x80 | ((code & 0xfc0) >>> 6) | ||
| byteArray[3] = 0x80 | (code & 0x3f) | ||
| } else if (code > 0x800) { | ||
| // 3字节UTF-8 | ||
| byteArray[0] = 0xe0 | ((code & 0xf000) >>> 12) | ||
| byteArray[1] = 0x80 | ((code & 0xfc0) >>> 6) | ||
| byteArray[2] = 0x80 | (code & 0x3f) | ||
| } else if (code > 0x80) { | ||
| // 2字节UTF-8 | ||
| byteArray[0] = 0xc0 | ((code & 0x7c0) >>> 6) | ||
| byteArray[1] = 0x80 | (code & 0x3f) | ||
| } else { | ||
| // 1字节ASCII | ||
| byteArray[0] = code | ||
| } | ||
|
|
||
| this.parsedData.push(...byteArray) | ||
| } | ||
|
|
||
| // 添加UTF-8 BOM(如果需要) | ||
| if (this.parsedData.length !== this.data.length) { | ||
| this.parsedData.unshift(191, 187, 239) | ||
| } | ||
| } |
There was a problem hiding this comment.
UTF-8 编码存在多个边界值错误。
- 第 125 行:
charCodeAt()返回 16 位值(0-65535),code > 0x10000永远不成立。对于 BMP 以外的字符(如 emoji),JavaScript 使用代理对,需要用codePointAt()配合正确的迭代来处理 4 字节 UTF-8。 - 第 136 行:
code > 0x80应为code >= 0x80,因为码点0x80本身就需要 2 字节 UTF-8 编码(0xC2 0x80),当前逻辑会将其错误地当作 1 字节 ASCII 处理。 - 第 131 行:
code > 0x800同样应为code >= 0x800。
🐛 建议修复边界值
- if (code > 0x10000) {
+ if (code > 0xFFFF) {
+ // 注意:charCodeAt 无法返回 > 0xFFFF 的值,此分支需要使用 codePointAt
// 4字节UTF-8
byteArray[0] = 0xf0 | ((code & 0x1c0000) >>> 18)
byteArray[1] = 0x80 | ((code & 0x3f000) >>> 12)
byteArray[2] = 0x80 | ((code & 0xfc0) >>> 6)
byteArray[3] = 0x80 | (code & 0x3f)
- } else if (code > 0x800) {
+ } else if (code >= 0x800) {
// 3字节UTF-8
- } else if (code > 0x80) {
+ } else if (code >= 0x80) {
// 2字节UTF-8🤖 Prompt for AI Agents
In `@src/uni_modules/wot-design-uni/components/wd-qr-code/qrcode.js` around lines
120 - 152, In _encodeUTF8(), fix UTF-8 encoding edge cases: iterate over
this.data using codePointAt and advance the index correctly to handle surrogate
pairs (so characters outside BMP produce a single code point), replace
charCodeAt usage with codePointAt when building code and ensure you increment i
by 1 extra when encountering a surrogate pair; change the boundary checks to use
>= for 0x80 and 0x800 so code >= 0x80 and code >= 0x800 map to 2- and 3-byte
UTF-8 respectively; keep pushing the produced bytes into this.parsedData and
retain the BOM insertion check (adjust if you prefer BOM based on encoding
flag).
| const QRUtil = { | ||
| /** 位置探测图形位置表 */ | ||
| PATTERN_POSITION_TABLE: [ | ||
| [], | ||
| [6, 18], | ||
| [6, 22], | ||
| [6, 26], | ||
| [6, 30], | ||
| [6, 34], | ||
| [6, 22, 38], | ||
| [6, 24, 42], | ||
| [6, 26, 46], | ||
| [6, 28, 50] | ||
| // 完整表见原代码 | ||
| ], |
There was a problem hiding this comment.
PATTERN_POSITION_TABLE 仅包含版本 1-10 的数据,版本 11-40 缺失。
与 RS_BLOCK_TABLE 同样的问题,getPatternPosition 在版本 11+ 时会返回空数组(第 539 行的 || [] fallback),导致校正图形位置缺失,生成的二维码在版本 11 以上将不符合规范,可能无法被扫码器正确识别。
🤖 Prompt for AI Agents
In `@src/uni_modules/wot-design-uni/components/wd-qr-code/qrcode.js` around lines
468 - 482, PATTERN_POSITION_TABLE only contains entries for versions 1–10
causing getPatternPosition to return empty for versions 11+, breaking alignment
pattern placement; update PATTERN_POSITION_TABLE to include the full set of
position arrays for QR versions 1–40 (the same complete table used in the
original/standard implementation) so getPatternPosition(version) returns the
correct coordinates for versions 11–40; locate PATTERN_POSITION_TABLE in
qrcode.js and replace the truncated array with the complete pattern position
table from the QR specification (ensuring indices align with version numbers)
and remove the need for the fallback empty array.
| function getUTF8Length(sText) { | ||
| const replacedText = encodeURI(sText) | ||
| .toString() | ||
| .replace(/%[0-9a-fA-F]{2}/g, 'a') | ||
| return replacedText.length + (replacedText.length !== sText ? 3 : 0) | ||
| } |
There was a problem hiding this comment.
getUTF8Length 中类型比较错误,BOM 长度始终被添加。
第 1140 行 replacedText.length !== sText 比较的是 number 和 string,由于类型不同,此条件永远为 true,导致 BOM 的 3 个字节始终被加到长度计算中。这会使纯 ASCII 文本的长度计算也多 3 个字节,可能选择了过高的版本号。
🐛 建议修复
- return replacedText.length + (replacedText.length !== sText ? 3 : 0)
+ return replacedText.length + (replacedText.length !== sText.length ? 3 : 0)🤖 Prompt for AI Agents
In `@src/uni_modules/wot-design-uni/components/wd-qr-code/qrcode.js` around lines
1136 - 1141, getUTF8Length currently compares replacedText.length (a number) to
sText (a string), so the BOM adjustment is always applied; change the comparison
to compare numeric lengths (replace the condition replacedText.length !== sText
with replacedText.length !== sText.length) so the 3-byte BOM is only added when
the encoded length differs from the original length (ensure this change is made
inside the getUTF8Length function where replacedText is computed).
| for (let i = 0, len = QRCodeLimitLength.length; i <= len; i++) { | ||
| let nLimit = 0 | ||
|
|
||
| switch (nCorrectLevel) { | ||
| case QRErrorCorrectLevel.L: | ||
| nLimit = QRCodeLimitLength[i][0] | ||
| break | ||
| case QRErrorCorrectLevel.M: | ||
| nLimit = QRCodeLimitLength[i][1] | ||
| break | ||
| case QRErrorCorrectLevel.Q: | ||
| nLimit = QRCodeLimitLength[i][2] | ||
| break | ||
| case QRErrorCorrectLevel.H: | ||
| nLimit = QRCodeLimitLength[i][3] | ||
| break | ||
| } | ||
|
|
||
| if (length <= nLimit) { | ||
| break | ||
| } else { | ||
| nType++ | ||
| } | ||
| } |
There was a problem hiding this comment.
getTypeNumber 循环条件 i <= len 导致数组越界访问。
第 1153 行 for (let i = 0, len = QRCodeLimitLength.length; i <= len; i++) 会在最后一次迭代访问 QRCodeLimitLength[40](数组只有 40 个元素,索引 0-39),导致 QRCodeLimitLength[i][0] 抛出 TypeError: Cannot read properties of undefined。
🐛 建议修复
- for (let i = 0, len = QRCodeLimitLength.length; i <= len; i++) {
+ for (let i = 0, len = QRCodeLimitLength.length; i < len; i++) {🤖 Prompt for AI Agents
In `@src/uni_modules/wot-design-uni/components/wd-qr-code/qrcode.js` around lines
1153 - 1176, The loop in getTypeNumber uses for (let i = 0, len =
QRCodeLimitLength.length; i <= len; i++) which allows i to equal len and thus
index past the end of QRCodeLimitLength; change the loop condition to i < len so
it iterates only valid indices, keeping the existing logic that reads
QRCodeLimitLength[i][...] (refer to getTypeNumber, QRCodeLimitLength,
QRErrorCorrectLevel, and the nType increment).
| if (props.gradientColors && props.gradientColors.length > 0) { | ||
| // 使用颜色列表 | ||
| const len = props.gradientColors.length | ||
| props.gradientColors.forEach((color, index) => { | ||
| grad.addColorStop(index / (len - 1), color) | ||
| }) |
There was a problem hiding this comment.
gradientColors 仅有 1 个元素时会产生除零错误。
当 props.gradientColors.length === 1 时,第 273 行 index / (len - 1) 会计算 0 / 0 = NaN,导致 addColorStop(NaN, color) 抛出异常或产生无效渐变。
🐛 建议修复
if (props.gradientColors && props.gradientColors.length > 0) {
// 使用颜色列表
const len = props.gradientColors.length
- props.gradientColors.forEach((color, index) => {
- grad.addColorStop(index / (len - 1), color)
- })
+ if (len === 1) {
+ grad.addColorStop(0, props.gradientColors[0])
+ } else {
+ props.gradientColors.forEach((color, index) => {
+ grad.addColorStop(index / (len - 1), color)
+ })
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (props.gradientColors && props.gradientColors.length > 0) { | |
| // 使用颜色列表 | |
| const len = props.gradientColors.length | |
| props.gradientColors.forEach((color, index) => { | |
| grad.addColorStop(index / (len - 1), color) | |
| }) | |
| if (props.gradientColors && props.gradientColors.length > 0) { | |
| // 使用颜色列表 | |
| const len = props.gradientColors.length | |
| if (len === 1) { | |
| grad.addColorStop(0, props.gradientColors[0]) | |
| } else { | |
| props.gradientColors.forEach((color, index) => { | |
| grad.addColorStop(index / (len - 1), color) | |
| }) | |
| } |
🤖 Prompt for AI Agents
In `@src/uni_modules/wot-design-uni/components/wd-qr-code/wd-qr-code.vue` around
lines 269 - 274, The gradient stop calculation divides by (len - 1) which
becomes zero when props.gradientColors.length === 1; update the logic in
wd-qr-code.vue where gradientColors is iterated (the block that calls
grad.addColorStop) to handle the single-color case explicitly: if len === 1,
call grad.addColorStop(0, props.gradientColors[0]) (or a fixed valid offset like
0.0/1.0) instead of computing index/(len-1); otherwise keep the existing loop
using index/(len-1). Ensure you reference props.gradientColors and
grad.addColorStop in the modified block.
| /** | ||
| * 上一步按钮文字 | ||
| */ | ||
| prevText: makeStringProp('上一步'), | ||
|
|
||
| /** | ||
| * 下一步按钮文字 | ||
| */ | ||
| nextText: makeStringProp('下一步'), | ||
|
|
||
| /** | ||
| * 跳过按钮文字 | ||
| */ | ||
| skipText: makeStringProp('跳过'), | ||
|
|
||
| /** | ||
| * 完成按钮文字 | ||
| */ | ||
| finishText: makeStringProp('完成'), |
There was a problem hiding this comment.
按钮文字默认值硬编码了中文,不支持国际化。
项目已有完善的 locale 国际化体系(如 en-US.ts、zh-HK.ts 等),但 prevText、nextText、skipText、finishText 的默认值直接写死为中文字符串。建议参照其他组件(如 picker、messageBox)的做法,将这些文本纳入 locale 系统,以便多语言环境下正常显示。
🤖 Prompt for AI Agents
In `@src/uni_modules/wot-design-uni/components/wd-tour/types.ts` around lines 80 -
98, The props prevText, nextText, skipText and finishText currently hardcode
Chinese strings; update their default values to pull from the project's existing
locale system (the same helper used by picker/messageBox) instead of
makeStringProp('上一步')/…; use the locale helper used across the codebase to
resolve keys like 'tour.prev','tour.next','tour.skip','tour.finish' (with
fallback values if locale entry missing) and replace the makeStringProp defaults
for prevText, nextText, skipText and finishText accordingly so the component
respects the app's internationalization.
🤔 这个 PR 的性质是?(至少选择一个)
🔗 相关 Issue
💡 需求背景和解决方案
☑️ 请求合并前的自查清单
Summary by CodeRabbit
发布说明
新功能
文档和国际化