Trae根据原型设计稿生成微信小程序密码输入框的踩坑记录

一、需求描述

最近经常使用Trae生成一些小组件和功能代码(对Trae赶兴趣的可以看之前的文章《TraeAi上手体验》),刚好在用uniapp开发微信小程序时需要开发一个输入密码的弹框组件,于是想用Trae来实现。原型设计稿如下:
在这里插入图片描述

二、Trae生成的雏形组件

经过一次描述附加原型设计图后,Trae给我生成了初始代码,预览如下:

在这里插入图片描述

在微信开发者工具中使用似乎是可以的,它还细心的额外给我增加了对确认按钮的激活条件(多选框需要至少选一个),这个激活条件我是没有体现在需求描述上的,但实际也是需要的。

然而,在实际使用的时候,会发现以下问题:

①它在界面上使用了4个input输入框,当输入框为空时再按下backspace键,无法触发@input或者@keyup,导致无法将光标回退到上一个输入框。同时,因为使用了4个不同的input输入框,导致在输入后光标自动移动到下一个输入框时会引起输入法键盘的闪动。

②input上虽然设置了type=“number”,但在微信开发者工具中,还是能输入其它字符。

③虽然它在弹窗关闭时对所有输入变量进行了重置,但再次打开弹框时,多选的checkbox组件依然显示之前的勾选状态,而没有被重新初始化为未勾选状态。

④需求描述和原型设计稿中都有右上角关闭的描述,但实际没有显示弹窗的右上角的关闭按钮(其实代码是有生成,但它给的关闭图片并不存在,图片路径却不是随机的,而似乎有根据项目使用的cdn来生成,所以差点让我信以为真)

三、问题修复

上面4个问题中,第一个问题是最主要的,也是比较麻烦的。

在保留4个input输入框的方式下,最初为了解决当输入框为空时再按下backspace键,无法触发@input的问题时,Trae想到了插入零宽字符\u200B的方案:

在这里插入图片描述

但在实际测试过程中,会导致输入的数字无法正常显示。

经过几次尝试,如果在不改变实现方式,也就是保留4个input输入框的方式下,无法解决事件触发及输入法键盘闪动的问题。于是Trae给出来用“4个普通view元素+隐藏的input”的方式来实现密码输入:

在这里插入图片描述

主要改动说明:

1. 移除了多个输入框,改用一个隐藏的真实输入框
2. 添加了显示用的密码框
3. 简化了输入处理逻辑
4. 在关闭弹窗时增加了状态重置
5. 优化了样式结构,确保隐藏输入框覆盖整个输入区域

经过上述修改,输入法闪动的问题解决了,backspace回退的问题也解决了。但是引入了一个新的问题:

由于真实的输入框是覆盖在上层,虽然它也设置了opacity: 0;,在微信开发者工具中没有发现什么问题,但是在Android真机上却显示了输入框的文字和闪烁的光标。

输入框文字可以用css样式进行隐藏,但光标却始终无法隐藏:

Trae给出的几次方案:

方案一:
在这里插入图片描述

 .real-password-input {
	position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100rpx;
    opacity: 0;
    z-index: 1;
    background: transparent;
    color: transparent;
    caret-color: transparent;
  }

方案二:

在这里插入图片描述

 .real-password-input {
	pointer-events: none;  /* 添加这行 */
}

方案三:

在这里插入图片描述

  .real-password-input {
    position: absolute;
    top: -9999rpx;  // 将输入框移出可视区域
    left: -9999rpx;
    width: 100%;
    height: 100rpx;
    opacity: 0;
    z-index: 1;
    background: transparent;
    color: transparent;
  }

当然还有deepseek给出的unselectable=“on” ,readonly(微信小程序input没有这个属性),disabled,这些方案都不行。

最终为了不让光标显示出来,那么只能采用方案三,但方案三有个问题,就是如果输入完成,输入法的键盘消失后,如果想再次输入该怎么办?能否再次点击那4个输入框来唤起输入法的键盘呢?

一般我们使用input来获取焦点是这样的input.focus(),但在uniapp微信小程序的开发中,实际上发现这样是无效的。当然同时也发现了,在弹框出现后如果想让input自动获得焦点,也同样不能使用这样的方式,哪怕你设置了setTimeout延时:

在这里插入图片描述
好在Trae最终给出了另一个方案:

在这里插入图片描述
通过focus的设置,解决了在弹窗显示时自动获取焦点的问题。那么对于点击密码输入框自动获取焦点的解决是否也可以通过改变focus属性的方式实现呢?答案是可以的,只不过这时候我们加上了setTimeout的包裹:

const handlePasswordInputClick = () => {
  isFocus.value = false
  setTimeout(() => {
    isFocus.value = true
  }, 100)
}

第一个问题终于解决,剩下的三个问题中的第三个问题checkbox组件勾选状态重置问题,Trae最终也给出了解决办法:

在这里插入图片描述

最终得到的完整代码如下:

<template>
  <uni-popup ref="popup" type="center" :mask-click="false" @change="handlePopupChange">
    <view class="share-popup">
      <view class="share-popup-header">
        <text class="share-popup-title">分享xx记录</text>
        <uni-icons type="closeempty" size="20" color="#118170" class="popup-detail-header__close"
        @click="handleClose" />
      </view>
      
      <view class="share-content">
        <view class="share-tip">选择分享内容,并设置查看密码后,对方通过输入密码就能查看到患者分享的记录内容了~</view>
        
        <view class="share-options">
          <checkbox-group @change="handleShareOptionChange">
            <label v-for="(item, index) in shareOptions" :key="item.value" class="share-option-item">
              <checkbox 
                :value="item.value" 
                color="#00D997" 
                :checked="checkedStatus[index]"
              />
              <text>{{item.label}}</text>
            </label>
          </checkbox-group>
        </view>

        <view class="password-section">
          <view class="password-title">输入密码</view>
          <view class="password-input-group" @click="handlePasswordGroupClick">
            <view 
              v-for="(item, index) in 4" 
              :key="index"
              class="password-input"
              @click="handlePasswordInputClick"
            >
              {{ password[index] }}
            </view>
            <input 
              type="number"
              maxlength="4"
              v-model="realPassword"
              class="real-password-input"
              @input="handlePasswordInput"
              ref="passwordInput"
              :focus="isFocus" 
            />
          </view>
        </view>

        <button 
          class="confirm-btn" 
          :class="{'confirm-btn-active': isValid}"
          :disabled="!isValid"
          @click="handleConfirm"
        >
          确认
        </button>
      </view>
    </view>
  </uni-popup>
</template>

<script setup>
import { ref, computed, nextTick } from 'vue'

const popup = ref(null)
const password = ref(['','','',''])
const realPassword = ref('')
const selectedOptions = ref([])
const passwordInput = ref(null)
const isFocus = ref(false)
const checkedStatus = ref(new Array(3).fill(false))

const shareOptions = [
  { label: '选项1, value: '1' },
  { label: '选项2', value: '2' },
  { label: '选项3', value: '3' }
]

const isValid = computed(() => {
  return password.value.every(v => v !== '') && selectedOptions.value.length > 0
})

const handlePasswordInput = (e) => {
  const value = e.detail.value
  if (!/^\d*$/.test(value)) {
    nextTick(() => {
      realPassword.value = realPassword.value.replace(/\D/g, '')
    })
    return
  }
  const valueArray = value.split('')
  password.value = new Array(4).fill('').map((_, index) => valueArray[index] || '')

  // 当输入满4位数时,自动失去焦点
  if (value.length === 4) {
    isFocus.value = false
  }
}

const handlePasswordGroupClick = () => {
  const input = passwordInput.value
  if (input) {
    input.focus()
  }
}

const handleShareOptionChange = (e) => {
  selectedOptions.value = e.detail.value
  checkedStatus.value = shareOptions.map(option => selectedOptions.value.includes(option.value))
}

const handleConfirm = () => {
  popup.value.close()
}

const handleClose = () => {
  popup.value.close()
}

const resetState = () => {
  password.value = ['','','','']
  realPassword.value = ''
  selectedOptions.value = []
  checkedStatus.value = new Array(3).fill(false)
}

const handlePopupChange = (e) => {
  isFocus.value = e.show
  if (!e.show) {
    resetState()
  }
}

const show = () => {
  resetState()
  nextTick(() => {
    popup.value.open()
  })
}

const handlePasswordInputClick = () => {
  isFocus.value = false
  setTimeout(() => {
    isFocus.value = true
  }, 100)
}

defineExpose({
  show
})
</script>

<style lang="scss" scoped>
.share-popup {
  width: 622rpx;
  background: #FFFFFF;
  border-radius: 24rpx;
  padding: 40rpx;

  &-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 30rpx;
  }

  &-title {
    font-size: 36rpx;
    font-weight: 500;
    color: #1A1A1A;
  }

  &-close {
    width: 48rpx;
    height: 48rpx;
  }
}

.share-content {
  .share-tip {
    font-size: 26rpx;
    color: #999999;
    line-height: 37rpx;
    margin-bottom: 30rpx;
  }
}

.share-options {
  margin-bottom: 40rpx;
  
  .share-option-item {
    display: flex;
    align-items: center;
    margin-bottom: 20rpx;
    font-size: 30rpx;
    color: #1A1A1A;
  }
}

.password-section {
  .password-title {
    font-size: 30rpx;
    color: #1A1A1A;
    margin-bottom: 20rpx;
  }

  .password-input-group {
    display: flex;
    justify-content: space-between;
    margin-bottom: 40rpx;
    position: relative;
  }

  .password-input {
    width: 100rpx;
    height: 100rpx;
    background: #F5F5F5;
    border-radius: 12rpx;
    text-align: center;
    font-size: 36rpx;
    line-height: 100rpx;
    cursor: pointer;
  }

  .real-password-input {
    position: absolute;
    top: -9999px;
    left: -9999px;
    width: 1rpx;
    height: 1rpx;
    opacity: 0;
    z-index: 1;
    background: transparent;
    color: transparent;
    caret-color: transparent;
  }
}

.confirm-btn {
  width: 100%;
  height: 88rpx;
  background: #CCCCCC;
  border-radius: 44rpx;
  color: #FFFFFF;
  font-size: 32rpx;
  display: flex;
  align-items: center;
  justify-content: center;

  &-active {
    background: linear-gradient(132deg, #00D997 0%, #00D57D 100%);
  }
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/978721.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

斩波放大器

目录 简介 自稳零斩波放大器 噪声 简介 双极性放大器的失调电压为25 μV&#xff0c;漂移为0.1 μV/C。斩波放大器尽管存在一些不利影 响&#xff0c;但可提供低于5 μV的失调电压&#xff0c;而且不会出现明显的失调漂移&#xff0c; 以下图1给出了基本的斩波放大器电路图。…

windows设置暂停更新时长

windows设置暂停更新时长 win11与win10修改注册表操作一致 &#xff0c;系统界面不同 1.打开注册表 2.在以下路径 \HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings 右键新建 DWORD 32位值&#xff0c;名称为FlightSettingsMaxPauseDays 根据需求填写数…

DIALOGPT:大规模生成式预训练用于对话响应生成

摘要 我们提出了一个大规模、可调节的神经对话响应生成模型&#xff0c;DIALOGPT&#xff08;对话生成预训练变换器&#xff09;。该模型训练于从2005年至2017年间Reddit评论链中提取的1.47亿次类似对话的交流&#xff0c;DIALOGPT扩展了Hugging Face的PyTorch变换器&#xff…

Mac端不显示正常用户名,变成192的解决方法

今天打开终端&#xff0c;本应该显示机器名的&#xff0c;但是此时显示了192。 问题原因&#xff1a; 当路由器的DNS使用默认的 192.168.1.1 或 192.168.0.1 的时候 Terminal 里的计算机名 会变成 localhost。当路由器的DNS使用自定义的 例如 运营商的DNS 或者 公共DNS的时候 …

SD 卡无屏安装启动树莓派5

最近想用一下树莓派5&#xff0c;拿出来一看&#xff0c;是 Micro-HMDI 的接口&#xff0c;手头正好没有这个接口线&#xff0c;便研究如何在没有显示屏的情况下&#xff0c;安装启动树莓派。 一、使用 Raspberry Pi Imager 烧录 SD 卡 选择 Raspberry Pi Imager 来烧录 SD 卡…

Xlua 编译 Windows、UWP、Android、iOS 平台支持库

Xlua 编译 Windows、UWP、Android、iOS 平台支持库 Windows&#xff1a; 安装 Visual Studio&#xff08;推荐 2017 或更高版本&#xff09; 安装 CMake&#xff08;https://cmake.org/&#xff09; macOS&#xff1a; 安装 Xcode 和命令行工具 安装 CMake 检查 cmake 是否安…

npm : 无法加载文件 E:\ProgramFiles\Nodejs\npm.ps1,因为在此系统上禁止运行脚本。

这个错误是因为 Windows 系统的 PowerShell 执行策略 限制了脚本的运行。默认情况下&#xff0c;PowerShell 的执行策略是 Restricted&#xff0c;即禁止运行任何脚本。以下是解决该问题的步骤&#xff1a; 1. 检查当前执行策略 打开 PowerShell&#xff08;管理员权限&#x…

基于专利合作地址匹配的数据构建区域协同矩阵

文章目录 地区地址提取完成的处理代码 在专利合作申请表中&#xff0c;有多家公司合作申请。在专利权人地址中&#xff0c; 有多个公司的地址信息。故想利用这里多个地址。想用这里的地址来代表区域之间的专利合作情况代表区域之间的协同、协作情况。 下图是专利合作表的一部分…

若依vue plus环境搭建

继前面文章若依系统环境搭建记录-CSDN博客 把ruoyi vue plus也摸索了下。 作者是疯狂的狮子&#xff0c;dromara/RuoYi-Vue-Plus 初始化文档&#xff1a;项目初始化&#xff0c;环境搭建的视频&#xff1a;RuoYi-Vue-Plus 5.0 搭建与运行_哔哩哔哩_bilibili 上来就列出了一…

在ubuntu如何安装samba软件?

我们在开发过程中&#xff0c;经常修改代码&#xff0c;可以安装samba文件来实现&#xff0c;把ubuntu的存储空间指定为我们win上的一个磁盘&#xff0c;然后我们在或者磁盘里面创建.c文件&#xff0c;进行代码修改和编写。samba能将linux的文件目录直接映射到windows&#xff…

论文阅读笔记:Deep Face Recognition: A Survey

论文阅读笔记&#xff1a;Deep Face Recognition: A Survey 1 介绍2 总览2.1 人脸识别组件2.1.1 人脸处理2.1.2 深度特征提取2.1.3 基于深度特征的人脸对比 3 网络结构和损失函数3.1 判别损失函数的演化3.1.1 基于欧式距离的损失3.1.2 基于角度/余弦边距的损失3.1.3 Softmax损失…

使用 Polars 进行人工智能医疗数据分析(ICU数据基本测试篇)

引言 在医疗领域&#xff0c;数据就是生命的密码&#xff0c;每一个数据点都可能蕴含着拯救生命的关键信息。特别是在 ICU 这样的重症监护场景中&#xff0c;医生需要实时、准确地了解患者的病情变化&#xff0c;以便做出及时有效的治疗决策。而随着医疗技术的飞速发展&#x…

Fiddler在Windows下抓包Https

文章目录 1.Fiddler Classic 配置2.配置浏览器代理自动代理手动配置浏览器代理 3.抓取移动端 HTTPS 流量&#xff08;可选&#xff09;解决抓取 HTTPS 失败问题1.Fiddler证书过期了 默认情况下&#xff0c;Fiddler 无法直接解密 HTTPS 流量。需要开启 HTTPS 解密&#xff1a; 1…

Anaconda安装 超详细版 (2025版)

目录 第一步&#xff1a;下载anaconda安装包 官网下载&#xff1a;Anaconda | Built to Advance Open Source AI 清华大学镜像站下载&#xff08;速度较快&#xff09; 第二步&#xff1a;安装anaconda 第三步&#xff1a;验证安装 扩展 创建conda基本环境 激活conda环…

想知道两轮差速方形底盘 URDF 咋做,ROS2 配 Rviz 咋显示吗?看这里!

视频讲解 想知道两轮差速方形底盘 URDF 咋做&#xff0c;ROS2 配 Rviz 咋显示吗&#xff1f;看这里&#xff01; 模型概述 一个方形底盘和两个差速驱动轮 URDF 代码 <?xml version"1.0" encoding"utf-8"?> <robot name"diff"> …

轻量化网络设计|ShuffleNet:深度学习中的轻量化革命

一、引言 在深度学习中&#xff0c;卷积神经网络&#xff08;Convolutional Neural Networks&#xff0c;CNN&#xff09;无疑是大家最耳熟能详的算法之一。自诞生以来&#xff0c;CNN 在图像分类、目标检测、语义分割等众多计算机视觉任务中取得了令人瞩目的成就&#xff0c;…

最好Wordpree+Apache+PHP安装教程

前提需要 PHP的安装最少需要7.4以上Mysql的安装&#xff0c;直接默认最新版就行APache服务器&#xff08;HTTP服务器&#xff0c;只有用这个你的软件才能在服务器上运行&#xff09; 安装apache 安装 sudo apt install apache2查看防火墙 sudo ufw app list如果有 Apache那…

Linux实操——在服务器上直接从百度网盘下载(/上传)文件

Linux Linux实操——在服务器上直接从百度网盘下载&#xff08;/上传&#xff09;文件 文章目录 Linux前言一、下载并安装bypy工具二、认证并授权网盘账号三、将所需文件转移至目的文件夹下四、下载文件五、上传文件六、更换绑定的百度云盘账户 前言 最近收到一批很大的数据&…

一周一个Unity小游戏2D反弹球游戏 - 移动的弹板(触屏版)

前言 上文中实现了用鼠标移动控制弹板的移动&#xff0c;本文将实现手指触屏时弹板跟随手指移动的功能&#xff0c;并通过使用Unity自带的Device Simulator Devices Package来验证和模拟触屏设备的使用场景。 安装Device Simulator Devices Package 打开Unity Package Manager&…

DeepSeek 开源狂欢周(一)FlashMLA:高效推理加速新时代

上周末&#xff0c;DeepSeek在X平台&#xff08;Twitter&#xff09;宣布将开启连续一周的开源&#xff0c;整个开源社区为之沸腾&#xff0c;全球AI爱好者纷纷为关注。没错&#xff0c;这是一场由DeepSeek引领的开源盛宴&#xff0c;推翻了传统推理加速的种种限制。这周一&…