feat(plan): 新增 AmountKeyboard 数字键盘输入组件
创建 AmountKeyboard 组件替代 AmountInput 输入框,实现数字键盘交互:
核心功能:
- 点击弹出数字键盘(右列模式,包含小数点)
- 金额显示弹窗(渐变背景 + 装饰圆圈)
- 输入验证(1个小数点,2位小数)
- 千分位分隔符显示
- 集成 GlobalPopupManager 解决嵌套弹窗层级
技术实现:
- nut-number-keyboard @input 事件(单字符传递)
- 字符累加逻辑:String(inputValue) + String(val)
- 输入验证:split('.') 检查小数点和小数位数量
- toFixed(2) 确保保存格式一致性
- watch(showKeyboard) 同步键盘和弹窗状态
问题解决:
1. Vue渲染错误:使用 kebab-case 组件名
2. 键盘被底部按钮遮挡:使用 GlobalPopupManager
3. 单字符输入:实现字符累加
4. 字符串相加变数字相加:显式 String() 转换
5. 输入验证阻塞:初始化为空字符串
6. 保存格式问题:使用 toFixed(2)
7. 自动关闭bug:时间判断过滤
8. 状态同步:watch 同步关闭金额弹窗
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Showing
6 changed files
with
314 additions
and
12 deletions
| ... | @@ -5,6 +5,109 @@ | ... | @@ -5,6 +5,109 @@ |
| 5 | 5 | ||
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | +## [2026-02-09] - 新增 AmountKeyboard 数字键盘输入组件 | ||
| 9 | + | ||
| 10 | +### 新增 | ||
| 11 | +- 创建 AmountKeyboard.vue 组件,替代 AmountInput 输入框 | ||
| 12 | +- 实现数字键盘(nut-number-keyboard)点击触发 | ||
| 13 | +- 新增金额显示弹窗(页面中间显示输入内容,渐变背景设计) | ||
| 14 | +- 集成 GlobalPopupManager 解决嵌套弹窗层级问题 | ||
| 15 | +- 实现字符累加逻辑,支持连续录入(123) | ||
| 16 | +- 添加输入验证(1个小数点,2位小数) | ||
| 17 | +- 添加千分位分隔符显示 | ||
| 18 | +- 实现 toFixed(2) 确保保存格式一致性 | ||
| 19 | +- 防止点击遮罩关闭弹窗 | ||
| 20 | +- 添加 watch(showKeyboard) 同步键盘和弹窗状态 | ||
| 21 | + | ||
| 22 | +### 功能特点 | ||
| 23 | +- 点击输入框弹出数字键盘(右列模式,包含小数点) | ||
| 24 | +- 金额显示弹窗(渐变背景 + 装饰圆圈 + 大号字体) | ||
| 25 | +- 输入验证(限制1个小数点,2位小数) | ||
| 26 | +- 连续输入支持(字符累加,字符串类型安全) | ||
| 27 | +- 状态同步(键盘关闭时自动关闭金额弹窗) | ||
| 28 | +- 多币种支持(CNY、USD、HKD、EUR) | ||
| 29 | + | ||
| 30 | +### 技术实现 | ||
| 31 | +- 使用 nut-number-keyboard 的 @input 事件(单字符传递) | ||
| 32 | +- 字符累加:`String(inputValue.value) + String(val)` | ||
| 33 | +- 输入验证:split('.') 检查小数点和小数位数量 | ||
| 34 | +- 初始化:空字符串(非"0.00")避免验证冲突 | ||
| 35 | +- 保存:parseFloat(yuan.toFixed(2)) 确保格式 | ||
| 36 | +- 单位转换:内部存储为分(整数),显示为元(带2位小数) | ||
| 37 | + | ||
| 38 | +### 问题解决 | ||
| 39 | +1. Vue渲染错误:使用正确的 kebab-case 组件名 `nut-number-keyboard` | ||
| 40 | +2. 键盘被底部按钮遮挡:使用 GlobalPopupManager 解决嵌套弹窗层级 | ||
| 41 | +3. 单字符输入:实现字符累加逻辑 | ||
| 42 | +4. 字符串相加变成数字相加(1+2=3):显式使用 String() 转换 | ||
| 43 | +5. 输入验证阻塞:初始化为空字符串而非 "0.00" | ||
| 44 | +6. 保存格式问题:使用 toFixed(2) 确保 "12.00" 格式 | ||
| 45 | +7. 自动关闭bug:添加时间判断过滤(500ms内) | ||
| 46 | +8. 状态同步:watch(showKeyboard) 同步关闭金额弹窗 | ||
| 47 | + | ||
| 48 | +### 影响文件 | ||
| 49 | +- src/components/PlanFields/AmountKeyboard.vue(新增) | ||
| 50 | +- src/components/PlanTemplates/LifeInsuranceTemplate.vue(使用新组件) | ||
| 51 | +- src/components/PlanTemplates/CriticalIllnessTemplate.vue(使用新组件) | ||
| 52 | +- src/components/PlanTemplates/SavingsTemplate.vue(使用新组件) | ||
| 53 | +- docs/lessons-learned.md(添加经验教训记录) | ||
| 54 | + | ||
| 55 | +**详细信息**: | ||
| 56 | +- **影响文件**: 见上文 | ||
| 57 | +- **技术栈**: Vue 3, Taro 4, NutUI, GlobalPopupManager | ||
| 58 | +- **测试状态**: ✅ 已通过 | ||
| 59 | +- **备注**: 替代原有的 AmountInput 组件,老组件保留用于测试 | ||
| 60 | + | ||
| 61 | +--- | ||
| 62 | + | ||
| 63 | +## [2026-02-08] - 实现全局弹窗管理器解决嵌套弹窗遮挡问题 | ||
| 64 | + | ||
| 65 | +### 新增 | ||
| 66 | +- 创建 GlobalPopupManager 全局弹窗管理器 | ||
| 67 | +- 实现 useParentPopup 和 useGlobalPopup 接口 | ||
| 68 | +- 新增 PlanPopupNew 父弹窗组件(支持全局管理) | ||
| 69 | +- 新增 DatePickerGlobal 日期选择器(支持全局管理) | ||
| 70 | +- 新增 SelectPickerGlobal 下拉选择器(支持全局管理) | ||
| 71 | +- 新增 AgePickerGlobal 年龄选择器(支持全局管理) | ||
| 72 | + | ||
| 73 | +### 优化 | ||
| 74 | +- 子弹窗打开时自动隐藏父弹窗底部按钮 | ||
| 75 | +- 所有子弹窗关闭时自动恢复底部按钮 | ||
| 76 | +- 支持多个子弹窗同时打开 | ||
| 77 | +- 支持多层弹窗嵌套(弹窗套弹窗) | ||
| 78 | +- 使用 watch 监听全局状态,解决组件挂载时序问题 | ||
| 79 | + | ||
| 80 | +### 问题原因 | ||
| 81 | +**NutUI 嵌套弹窗的 z-index 层级问题**: | ||
| 82 | +- 父弹窗和子弹窗都是 `position: fixed` 定位 | ||
| 83 | +- 即使子弹窗 `z-index` 更高,也无法遮挡父弹窗的非子元素(如底部按钮) | ||
| 84 | +- 底部按钮在 DOM 结构上与子弹窗同级,会覆盖子弹窗内容 | ||
| 85 | + | ||
| 86 | +### 解决方案 | ||
| 87 | +**核心策略**:全局弹窗管理器协调父弹窗和子弹窗状态 | ||
| 88 | + | ||
| 89 | +1. **子弹窗注册**:每个子弹窗组件挂载时注册,获得唯一 ID | ||
| 90 | +2. **激活/停用**:子弹窗打开时激活,关闭时停用 | ||
| 91 | +3. **状态同步**:管理器通知父弹窗隐藏/显示底部按钮 | ||
| 92 | +4. **响应式更新**:父弹窗通过 watch 监听全局状态变化 | ||
| 93 | + | ||
| 94 | +### 迁移工作 | ||
| 95 | +- 更新 PlanFormContainer 使用 PlanPopupNew | ||
| 96 | +- 更新所有计划模板(LifeInsuranceTemplate、CriticalIllnessTemplate、SavingsTemplate)使用 Global 版本字段组件 | ||
| 97 | + | ||
| 98 | +### 影响文件 | ||
| 99 | +- src/components/PlanFormContainer.vue | ||
| 100 | +- src/components/PlanPopupNew.vue | ||
| 101 | +- src/components/PlanFields/GlobalPopupManager.js | ||
| 102 | +- src/components/PlanFields/DatePickerGlobal.vue | ||
| 103 | +- src/components/PlanFields/SelectPickerGlobal.vue | ||
| 104 | +- src/components/PlanFields/AgePickerGlobal.vue | ||
| 105 | +- src/components/PlanTemplates/LifeInsuranceTemplate.vue | ||
| 106 | +- src/components/PlanTemplates/CriticalIllnessTemplate.vue | ||
| 107 | +- src/components/PlanTemplates/SavingsTemplate.vue | ||
| 108 | + | ||
| 109 | +--- | ||
| 110 | + | ||
| 8 | ## [2026-02-08] - 修复计划书表单重置和数据同步问题 | 111 | ## [2026-02-08] - 修复计划书表单重置和数据同步问题 |
| 9 | 112 | ||
| 10 | ### 修复 | 113 | ### 修复 | ... | ... |
| ... | @@ -1945,21 +1945,220 @@ const USE_MOCK_DATA = true // 容易导致生产环境误用 | ... | @@ -1945,21 +1945,220 @@ const USE_MOCK_DATA = true // 容易导致生产环境误用 |
| 1945 | 1945 | ||
| 1946 | --- | 1946 | --- |
| 1947 | 1947 | ||
| 1948 | +## 组件开发案例:AmountKeyboard 数字键盘组件 ⭐ 新增 | ||
| 1949 | + | ||
| 1950 | +### 问题描述 | ||
| 1951 | + | ||
| 1952 | +需要创建一个保额输入组件,点击后弹出数字键盘进行输入,而不是直接使用输入框。 | ||
| 1953 | + | ||
| 1954 | +### 遇到的坑和解决方案 | ||
| 1955 | + | ||
| 1956 | +#### 坑 1: Vue 渲染错误 - Invalid vnode type | ||
| 1957 | + | ||
| 1958 | +**错误信息**: | ||
| 1959 | +``` | ||
| 1960 | +[Vue warn]: Invalid vnode type when creating vnode: undefined | ||
| 1961 | +``` | ||
| 1962 | + | ||
| 1963 | +**原因**: 使用了错误的组件名 `nut-numberkeyboard` (驼峰式) | ||
| 1964 | + | ||
| 1965 | +**解决方案**: 使用正确的 kebab-case 命名 `<nut-number-keyboard>` | ||
| 1966 | + | ||
| 1967 | +**官方示例**: | ||
| 1968 | +```vue | ||
| 1969 | +<nut-number-keyboard v-model:visible="show" type="rightColumn" /> | ||
| 1970 | +``` | ||
| 1971 | + | ||
| 1972 | +--- | ||
| 1973 | + | ||
| 1974 | +#### 坑 2: 键盘被底部按钮遮挡 | ||
| 1975 | + | ||
| 1976 | +**现象**: 数字键盘的底部按钮被页面底部按钮遮挡 | ||
| 1977 | + | ||
| 1978 | +**错误尝试**: 使用 `z-index` CSS 调整(无效) | ||
| 1979 | + | ||
| 1980 | +**正确方案**: 使用 GlobalPopupManager 系统 | ||
| 1981 | +```javascript | ||
| 1982 | +import { useGlobalPopup } from './GlobalPopupManager.js' | ||
| 1983 | + | ||
| 1984 | +const { registerPopup, activatePopup, deactivatePopup } = useGlobalPopup() | ||
| 1985 | + | ||
| 1986 | +// 注册弹窗 | ||
| 1987 | +const keyboardPopupId = ref(null) | ||
| 1988 | +onMounted(() => { | ||
| 1989 | + keyboardPopupId.value = registerPopup() | ||
| 1990 | +}) | ||
| 1991 | + | ||
| 1992 | +// 监听键盘状态 | ||
| 1993 | +watch(showKeyboard, (newValue) => { | ||
| 1994 | + if (newValue) { | ||
| 1995 | + activatePopup(keyboardPopupId.value) | ||
| 1996 | + } else { | ||
| 1997 | + deactivatePopup(keyboardPopupId.value) | ||
| 1998 | + } | ||
| 1999 | +}) | ||
| 2000 | +``` | ||
| 2001 | + | ||
| 2002 | +--- | ||
| 2003 | + | ||
| 2004 | +#### 坑 3: 数字输入只能录入单个数字 | ||
| 2005 | + | ||
| 2006 | +**现象**: 输入 "123" 时,只显示最后一个数字 | ||
| 2007 | + | ||
| 2008 | +**原因**: `nut-number-keyboard` 的 `@input` 事件传入的是单个字符,需要累加 | ||
| 2009 | + | ||
| 2010 | +**错误代码**: | ||
| 2011 | +```javascript | ||
| 2012 | +const onInput = (val) => { | ||
| 2013 | + inputValue.value = val // ❌ 直接替换 | ||
| 2014 | +} | ||
| 2015 | +``` | ||
| 2016 | + | ||
| 2017 | +**正确代码**: | ||
| 2018 | +```javascript | ||
| 2019 | +const onInput = (val) => { | ||
| 2020 | + if (!inputValue.value) { | ||
| 2021 | + inputValue.value = String(val) | ||
| 2022 | + } else { | ||
| 2023 | + inputValue.value = String(inputValue.value) + String(val) | ||
| 2024 | + } | ||
| 2025 | +} | ||
| 2026 | +``` | ||
| 2027 | + | ||
| 2028 | +--- | ||
| 2029 | + | ||
| 2030 | +#### 坑 4: 输入验证导致无法输入 | ||
| 2031 | + | ||
| 2032 | +**现象**: 初始化为 "0.00" 后,所有输入都被忽略 | ||
| 2033 | + | ||
| 2034 | +**原因**: 验证逻辑判断 `parts[1].length >= 2`,认为已有2位小数 | ||
| 2035 | + | ||
| 2036 | +**解决方案**: 初始化时使用空字符串,而不是 "0.00" | ||
| 2037 | +```javascript | ||
| 2038 | +const openKeyboard = () => { | ||
| 2039 | + if (props.modelValue !== null && props.modelValue !== undefined) { | ||
| 2040 | + inputValue.value = (props.modelValue / 100).toFixed(2) | ||
| 2041 | + } else { | ||
| 2042 | + inputValue.value = '' // ✅ 空字符串,不是 '0.00' | ||
| 2043 | + } | ||
| 2044 | +} | ||
| 2045 | +``` | ||
| 2046 | + | ||
| 2047 | +**验证逻辑**: | ||
| 2048 | +```javascript | ||
| 2049 | +const onInput = (val) => { | ||
| 2050 | + // 检查小数点 | ||
| 2051 | + if (val === '.' && inputValue.value.includes('.')) { | ||
| 2052 | + return // 已有小数点,忽略 | ||
| 2053 | + } | ||
| 2054 | + | ||
| 2055 | + // 检查小数位 | ||
| 2056 | + if (val >= '0' && val <= '9') { | ||
| 2057 | + const parts = inputValue.value.split('.') | ||
| 2058 | + if (parts.length === 2 && parts[1]?.length >= 2) { | ||
| 2059 | + return // 已有2位小数,忽略 | ||
| 2060 | + } | ||
| 2061 | + } | ||
| 2062 | + | ||
| 2063 | + // 累加输入 | ||
| 2064 | + if (!inputValue.value) { | ||
| 2065 | + inputValue.value = String(val) | ||
| 2066 | + } else { | ||
| 2067 | + inputValue.value = String(inputValue.value) + String(val) | ||
| 2068 | + } | ||
| 2069 | +} | ||
| 2070 | +``` | ||
| 2071 | + | ||
| 2072 | +--- | ||
| 2073 | + | ||
| 2074 | +#### 坑 5: 键盘自动关闭问题 | ||
| 2075 | + | ||
| 2076 | +**现象**: 键盘刚打开就立即关闭 | ||
| 2077 | + | ||
| 2078 | +**原因**: `@close` 事件在打开时被误触发 | ||
| 2079 | + | ||
| 2080 | +**解决方案**: 添加时间判断,过滤误触发 | ||
| 2081 | +```javascript | ||
| 2082 | +const keyboardOpenTime = ref(0) | ||
| 2083 | + | ||
| 2084 | +watch(showKeyboard, (newValue) => { | ||
| 2085 | + if (newValue) { | ||
| 2086 | + keyboardOpenTime.value = Date.now() // 记录打开时间 | ||
| 2087 | + } | ||
| 2088 | +}) | ||
| 2089 | + | ||
| 2090 | +const onClose = () => { | ||
| 2091 | + const timeSinceOpen = Date.now() - keyboardOpenTime.value | ||
| 2092 | + if (timeSinceOpen < 500) { | ||
| 2093 | + return // 忽略误触发 | ||
| 2094 | + } | ||
| 2095 | + showKeyboard.value = false | ||
| 2096 | +} | ||
| 2097 | +``` | ||
| 2098 | + | ||
| 2099 | +**最终方案**: 移除 `@close` 监听,在 `watch(showKeyboard)` 中同步关闭金额弹窗 | ||
| 2100 | + | ||
| 2101 | +--- | ||
| 2102 | + | ||
| 2103 | +#### 坑 6: 字符串累加被当作数字相加 | ||
| 2104 | + | ||
| 2105 | +**现象**: 输入 1、2、3 后显示 6(1+2+3) | ||
| 2106 | + | ||
| 2107 | +**原因**: JavaScript `+=` 运算符将字符串当作数字相加 | ||
| 2108 | + | ||
| 2109 | +**解决方案**: 确保两边都是字符串类型 | ||
| 2110 | +```javascript | ||
| 2111 | +inputValue.value = String(inputValue.value) + String(val) | ||
| 2112 | +``` | ||
| 2113 | + | ||
| 2114 | +--- | ||
| 2115 | + | ||
| 2116 | +#### 坑 7: 保存后再次编辑显示问题 | ||
| 2117 | + | ||
| 2118 | +**问题**: 保存 "12.23",删除后保存变成 "12" 而不是 "12.00" | ||
| 2119 | + | ||
| 2120 | +**原因**: `parseFloat("12")` 丢失小数点后的零 | ||
| 2121 | + | ||
| 2122 | +**解决方案**: 使用 `toFixed(2)` 保留两位小数 | ||
| 2123 | +```javascript | ||
| 2124 | +const onConfirm = () => { | ||
| 2125 | + let yuan = parseFloat(inputValue.value || '0') | ||
| 2126 | + if (!Number.isNaN(yuan)) { | ||
| 2127 | + const formattedYuan = parseFloat(yuan.toFixed(2)) | ||
| 2128 | + const cents = Math.round(formattedYuan * 100) | ||
| 2129 | + emit('update:modelValue', cents) | ||
| 2130 | + } | ||
| 2131 | +} | ||
| 2132 | +``` | ||
| 2133 | + | ||
| 2134 | +--- | ||
| 2135 | + | ||
| 2136 | +### ✅ 最终实现要点 | ||
| 2137 | + | ||
| 2138 | +1. **组件结构**: 点击区域 + 金额弹窗 + 数字键盘三层结构 | ||
| 2139 | +2. **事件处理**: `@input` 累加,`@delete` 删除,`@confirm` 保存 | ||
| 2140 | +3. **输入验证**: 限制小数点(1个)和小数位(2位) | ||
| 2141 | +4. **状态管理**: `watch(showKeyboard)` 同步关闭金额弹窗 | ||
| 2142 | +5. **美观设计**: 渐变背景 + 圆形装饰 + 大号数字显示 | ||
| 2143 | + | ||
| 2144 | +--- | ||
| 2145 | + | ||
| 1948 | ## 总结 | 2146 | ## 总结 |
| 1949 | 2147 | ||
| 1950 | ### 🎯 核心经验 | 2148 | ### 🎯 核心经验 |
| 1951 | 2149 | ||
| 1952 | 1. **"第 3 次出现原则"**: 代码重复 3 次时必须抽取 | 2150 | 1. **"第 3 次出现原则"**: 代码重复 3 次时必须抽取 |
| 1953 | 2. **NutUI 陷阱**: textarea、IconFont 等组件有坑,优先使用原生组件 | 2151 | 2. **NutUI 陷阱**: textarea、IconFont 等组件有坑,优先使用原生组件 |
| 1954 | -3. **静态资源**: SVG 图标必须使用 `import` 导入 | 2152 | +3. **⭐ 数字键盘组件**: `@input` 传入单个字符需要累加,注意类型转换 |
| 1955 | -4. **样式策略**: TailwindCSS(80%) + Less(20%) 混合使用 | 2153 | +4. **静态资源**: SVG 图标必须使用 `import` 导入 |
| 1956 | -5. **性能优化**: `shallowRef` + `markRaw` 处理组件对象响应式 | 2154 | +5. **样式策略**: TailwindCSS(80%) + Less(20%) 混合使用 |
| 1957 | -6. **代码质量**: 强制 JSDoc 注释,统一命名规范 | 2155 | +6. **性能优化**: `shallowRef` + `markRaw` 处理组件对象响应式 |
| 1958 | -7. **API 调用规范**: ⚠️ **不要使用 `fn()` 包装 API,直接调用并自己处理错误** | 2156 | +7. **代码质量**: 强制 JSDoc 注释,统一命名规范 |
| 1959 | -8. **架构设计**: 分层清晰,职责单一 | 2157 | +8. **API 调用规范**: ⚠️ **不要使用 `fn()` 包装 API,直接调用并自己处理错误** |
| 1960 | -9. **跨页面通信**: ⭐ **使用事件总线模式,LoadMoreList 页面避免使用 `useDidShow`**(防止意外刷新) | 2158 | +9. **架构设计**: 分层清晰,职责单一 |
| 1961 | -10. **Mock 数据切换**: ⭐ **使用环境变量 `process.env.NODE_ENV` 自动判断,禁止硬编码** | 2159 | +10. **跨页面通信**: ⭐ **使用事件总线模式,LoadMoreList 页面避免使用 `useDidShow`**(防止意外刷新) |
| 1962 | -11. **⚠️ 写代码前必查**: 先搜索项目中是否有类似实现,保持写法一致 | 2160 | +11. **Mock 数据切换**: ⭐ **使用环境变量 `process.env.NODE_ENV` 自动判断,禁止硬编码** |
| 2161 | +12. **⚠️ 写代码前必查**: 先搜索项目中是否有类似实现,保持写法一致 | ||
| 1963 | 2162 | ||
| 1964 | ### 📚 推荐阅读 | 2163 | ### 📚 推荐阅读 |
| 1965 | 2164 | ... | ... |
src/components/PlanFields/AmountKeyboard.vue
0 → 100644
This diff is collapsed. Click to expand it.
| ... | @@ -83,7 +83,7 @@ | ... | @@ -83,7 +83,7 @@ |
| 83 | import { reactive, watch } from 'vue' | 83 | import { reactive, watch } from 'vue' |
| 84 | import Taro from '@tarojs/taro' | 84 | import Taro from '@tarojs/taro' |
| 85 | import PlanFieldAgePicker from '../PlanFields/AgePickerGlobal.vue' | 85 | import PlanFieldAgePicker from '../PlanFields/AgePickerGlobal.vue' |
| 86 | -import PlanFieldAmount from '../PlanFields/AmountInput.vue' | 86 | +import PlanFieldAmount from '../PlanFields/AmountKeyboard.vue' |
| 87 | import PlanFieldDatePicker from '../PlanFields/DatePickerGlobal.vue' | 87 | import PlanFieldDatePicker from '../PlanFields/DatePickerGlobal.vue' |
| 88 | import PlanFieldRadio from '../PlanFields/RadioGroup.vue' | 88 | import PlanFieldRadio from '../PlanFields/RadioGroup.vue' |
| 89 | import PlanFieldSelect from '../PlanFields/SelectPickerGlobal.vue' | 89 | import PlanFieldSelect from '../PlanFields/SelectPickerGlobal.vue' | ... | ... |
| ... | @@ -83,7 +83,7 @@ | ... | @@ -83,7 +83,7 @@ |
| 83 | import { reactive, watch, toRefs } from 'vue' | 83 | import { reactive, watch, toRefs } from 'vue' |
| 84 | import Taro from '@tarojs/taro' | 84 | import Taro from '@tarojs/taro' |
| 85 | import PlanFieldAgePicker from '../PlanFields/AgePickerGlobal.vue' | 85 | import PlanFieldAgePicker from '../PlanFields/AgePickerGlobal.vue' |
| 86 | -import PlanFieldAmount from '../PlanFields/AmountInput.vue' | 86 | +import PlanFieldAmount from '../PlanFields/AmountKeyboard.vue' |
| 87 | import PlanFieldDatePicker from '../PlanFields/DatePickerGlobal.vue' | 87 | import PlanFieldDatePicker from '../PlanFields/DatePickerGlobal.vue' |
| 88 | import PlanFieldRadio from '../PlanFields/RadioGroup.vue' | 88 | import PlanFieldRadio from '../PlanFields/RadioGroup.vue' |
| 89 | import PlanFieldSelect from '../PlanFields/SelectPickerGlobal.vue' | 89 | import PlanFieldSelect from '../PlanFields/SelectPickerGlobal.vue' | ... | ... |
| ... | @@ -208,7 +208,7 @@ | ... | @@ -208,7 +208,7 @@ |
| 208 | import { reactive, watch, computed } from 'vue' | 208 | import { reactive, watch, computed } from 'vue' |
| 209 | import Taro from '@tarojs/taro' | 209 | import Taro from '@tarojs/taro' |
| 210 | import PlanFieldAgePicker from '../PlanFields/AgePickerGlobal.vue' | 210 | import PlanFieldAgePicker from '../PlanFields/AgePickerGlobal.vue' |
| 211 | -import PlanFieldAmount from '../PlanFields/AmountInput.vue' | 211 | +import PlanFieldAmount from '../PlanFields/AmountKeyboard.vue' |
| 212 | import PlanFieldDatePicker from '../PlanFields/DatePickerGlobal.vue' | 212 | import PlanFieldDatePicker from '../PlanFields/DatePickerGlobal.vue' |
| 213 | import PlanFieldRadio from '../PlanFields/RadioGroup.vue' | 213 | import PlanFieldRadio from '../PlanFields/RadioGroup.vue' |
| 214 | import PlanFieldSelect from '../PlanFields/SelectPickerGlobal.vue' | 214 | import PlanFieldSelect from '../PlanFields/SelectPickerGlobal.vue' | ... | ... |
-
Please register or login to post a comment