当前位置: 首页 > article >正文

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 = falsesetTimeout(() => {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.valueif (!/^\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.valueif (input) {input.focus()}
}const handleShareOptionChange = (e) => {selectedOptions.value = e.detail.valuecheckedStatus.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.showif (!e.show) {resetState()}
}const show = () => {resetState()nextTick(() => {popup.value.open()})
}const handlePasswordInputClick = () => {isFocus.value = falsesetTimeout(() => {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>

四、后续

上面我们通过改变focus属性的方式解决了在弹窗显示时自动获取焦点的问题,但后面我们发现这种方式能否生效与弹窗显示的方式有关:

①当用户通过点击的交互方式触发显示弹框时,通过改变focus属性的方式可以让input自动获得焦点,在移动端表现为输入法的软键盘被唤起,在微信开发者工具中表现为直接可以输入数字显示到输入框中。

②当弹框是通过脚本唤起,而非用户交互的结果时,通过改变focus属性的方式,在开发者工具中无法自动获得焦点,但在移动端可以自动获得焦点,不过对focus属性的改变最好是在弹框显示的回调里通过setTimeout进行设置,否则可能会无法生效(比如在iphone上会出现):

const handlePopupChange = (e) => {setTimeout(() => {isFocus.value = e.show}, 100)
}

相关文章:

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

一、需求描述 最近经常使用Trae生成一些小组件和功能代码&#xff08;对Trae赶兴趣的可以看之前的文章《TraeAi上手体验》&#xff09;&#xff0c;刚好在用uniapp开发微信小程序时需要开发一个输入密码的弹框组件&#xff0c;于是想用Trae来实现。原型设计稿如下&#xff1a;…...

软件测试丨Docker与虚拟机架构对比分析

Docker 与虚拟机&#xff08;VM&#xff09;在架构上有显著区别&#xff0c;主要体现在资源利用、性能、隔离性和启动时间等方面。以下是两者的主要架构区别&#xff1a; 1. 架构层次 Docker: 主机操作系统&#xff1a;Docker 直接运行在宿主机的操作系统上。Docker 引擎&…...

在VsCode中选择conda编译器环境

当vscode出现始终在激活一个已经不存在的虚拟环境&#xff0c;可选择手动将其调换 在 Visual Studio Code (VSCode) 中选择 Python 虚拟环境的步骤如下&#xff1a; 确保安装了 Python 插件&#xff1a;首先&#xff0c;你需要确保已经安装了适用于 VSCode 的 Python 插件。你…...

微信小程序 - 条件渲染(wx:if、hidden)与列表渲染(wx:for)

一、条件渲染概述 条件渲染用于根据特定条件决定是否渲染某部分内容 微信小程序提供了两种方式实现条件渲染&#xff0c;分别是 wx:if、hidden 二、条件渲染 1、wx:if &#xff08;1&#xff09;基本介绍 wx:if 根据 condition 的真假决定是否渲染该组件及其子组件 condit…...

【STL】4.<list>

list 前言list容器一.list初始化二.常用函数三.排序 总结 前言 stl系列主要讲述有关stl的文章&#xff0c;使用STL可以大大提高程序开发的效率和代码的可维护性&#xff0c;且在算法比赛中&#xff0c;STL可以帮助我们更方便地实现各种算法。提高我们的效率。 list容器 要使用…...

华为AP 4050DN-HD的FIT AP模式改为FAT AP,家用FAT基本配置

在某鱼买了两台华为AP 4050DN-HD , AP是二手的 , 在AC上上过线 , 所以就不能开机自选为FIP模式了 我没有AC无线控制器 , 就是买一个自己玩 , AP又是FIT瘦AP模式 ,所以我就想把AP的瘦AP模式改为FAT胖AP模式 1. 准备工作 1.1下载好对应软件&#xff0c;进入到 企业业务网站去下…...

vue 设置生产 开发 测试环境

在 Vue.js 中&#xff0c;可以通过配置不同的环境变量来区分生产、开发和测试环境的请求。一般情况下&#xff0c;我们使用 webpack 或 Vite 进行构建&#xff0c;它们都支持环境变量的配置。 以下是如何在 Vue 项目中配置不同环境的请求&#xff1a; 1. 配置 .env 文件 在项…...

vue3+ts+uniapp+unibest 微信小程序(第二篇)—— 图文详解自定义背景图页面布局、普通页面布局、分页表单页面布局

文章目录 简介一、自定义背景图布局1.1 效果预览1.2 实现思路1.3 custom-page 组件全量代码1.4 页面使用 二、普通页面布局2.1 效果预览2.2 实现思路2.3 公共样式部分2.4 页面使用 三、分页表单页面布局3.1 效果预览3.2 实现思路3.3 页面代码 简介 开发工具&#xff1a;VsCode…...

虚拟机缩放比例问题处理

上班打开虚拟机的样子。 最开始判断可能是vmtools 异常重启安装后发现没有效果 通过 xrandr 功能查询显示器信息获取显示器名 设置显示器 同时设置分辨率 也可以同时设置刷新率 注意下图中设置的关键字...

bean的管理-03.第三方bean

一.第三方bean的定义 对于我们自己定义的类&#xff0c;如果想要将其注入到IOC容器当中&#xff0c;可以使用Component&#xff0c;Controller&#xff0c;Service&#xff0c;Repository注解。但是对于第三方的类来说&#xff0c;并不能使用以上注解来定义&#xff0c;因此我…...

【Python 入门基础】—— 人工智能“超级引擎”,AI界的“瑞士军刀”,

欢迎来到ZyyOvO的博客✨&#xff0c;一个关于探索技术的角落&#xff0c;记录学习的点滴&#x1f4d6;&#xff0c;分享实用的技巧&#x1f6e0;️&#xff0c;偶尔还有一些奇思妙想&#x1f4a1; 本文由ZyyOvO原创✍️&#xff0c;感谢支持❤️&#xff01;请尊重原创&#x1…...

DeepSeek-R1-Zero:基于基础模型的强化学习

注&#xff1a;此文章内容均节选自充电了么创始人&#xff0c;CEO兼CTO陈敬雷老师的新书《自然语言处理原理与实战》&#xff08;人工智能科学与技术丛书&#xff09;【陈敬雷编著】【清华大学出版社】 文章目录 DeepSeek大模型技术系列四DeepSeek大模型技术系列四》DeepSeek-…...

(dp 买入股票的最佳时机)leetcode 121

题目 题解的dp数组 0列是负数&#xff0c;这里我改成正数不再相加而是相减获取利润 class Solution { public:int maxProfit(vector<int>& prices) {int nprices.size();vector<vector<int>>dp(n,vector<int>(2));dp[0][0]prices[0];dp[0][1]0;//0…...

由 Mybatis 源码畅谈软件设计(三):简单查询 SQL 执行流程

大家好&#xff0c;我是 方圆。SQL 查询是 Mybatis 中的核心流程&#xff0c;本节我们来介绍简单 SQL 的执行流程&#xff0c;过程会比较长&#xff0c;期间会认识很多重要的组件&#xff0c;比如 SqlSession、四大处理器&#xff08;Executor、StatementHandler、ParameterHan…...

项目实践 之 pdf简历的解析和填充(若依+vue3)

文章目录 环境背景最终效果前端讲解左侧模块解析右侧上传模块解析前端步骤 后端讲解代码前端 环境背景 若依前后端分离框架 vue最后边附有代码哦 最终效果 前端讲解 左侧模块解析 1、左侧表单使用el-form 注意&#xff1a; 1、prop出现的字段&#xff0c;需要保证是该类所…...

C语言机试编程题

编写版本&#xff1a;vc2022 1.求最大/小值 #include<stdio.h> int main(){int a[50],n;int max, min;printf("请输入您要输入几个数");scanf_s("%d", &n);printf("请输入您要比较的%d个数\n",n);for (int i 0; i<n; i) {scanf_…...

lowagie(itext)老版本手绘PDF,包含页码、水印、图片、复选框、复杂行列合并、行高设置等。

入口类&#xff1a;exportPdf package xcsy.qms.webapi.service;import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.alibaba.nacos.common.utils.StringUtils; import com.ibm.icu.text.RuleBasedNumberFormat; import com.lowagie…...

第002文-kali虚拟机安全与网络配置

1、kali系统介绍 kali是一个基于Linux kernel的操作系统&#xff0c;由BackTrack(简称BT)发展而来。BackTrack是2006年推出的一个用于渗透测试及黑客攻防的专用平台&#xff0c;基于Knoppix(linux的一个发行版)开发。BackTrack版本周期&#xff1a;2006年的起始版本BackTrack …...

软件工程复试专业课-软件生命周期

文章目录 软件过程模型瀑布模型模型图特点优缺点改进后的瀑布模型 快速原型模型模型图优缺点 增量模型&#xff08;迭代-递增模型&#xff09;原型图与瀑布和快速原型的区别优缺点风险更大的增量模型 螺旋模型简介模型图优缺点 喷泉模型模型图优缺点 编码修补模型敏捷过程优缺点…...

DILLEMA:扩散模型+大语言模型,多模态数据增强框架

引言&#xff1a;深度学习模型的鲁棒性测试需要全面且多样化的测试数据。现有的方法通常基于简单的数据增强技术或生成对抗网络&#xff0c;但这些方法在生成真实且多样化的测试数据集方面存在局限性。为了克服这些限制&#xff0c;DILLEMA框架应运而生&#xff0c;旨在通过结合…...

OpenBMC:BmcWeb app获取socket

OpenBMC:BmcWeb app.run-CSDN博客 app对象在run函数中调用了setupSocket() static std::vector<Acceptor> setupSocket() {std::vector<Acceptor> acceptors;char** names = nullptr;int listenFdCount = sd_listen_fds_with_names(0, &names);BMCWEB_LOG_DE…...

突破加速度计的精度与量程瓶颈:HEROS-GAN技术

在当今科技飞速发展的背景下&#xff0c;低成本传感器的应用范围日益扩大。然而&#xff0c;低成本加速度计由于其固有的限制——如信号噪声显著和动态范围狭窄——往往难以满足高精度应用场景的需求。哈尔滨工业大学的研究团队最近提出了一项名为HEROS-GAN&#xff08;Honed-E…...

C++程序员内功修炼——Linux C/C++编程技术汇总

在软件开发的宏大版图中&#xff0c;C 语言宛如一座巍峨的高山&#xff0c;吸引着无数开发者攀登探索。而 Linux 操作系统&#xff0c;以其开源、稳定、高效的特性&#xff0c;成为了众多开发者钟爱的开发平台。将 C 与 Linux 相结合&#xff0c;就如同为开发者配备了一把无坚不…...

苍穹外卖-阿里云OSS文件上传

苍穹外卖-阿里云OSS文件上传 一、阿里云OSS简介**获取AccessKey**获取enpoint 二、代码实现1 引入依赖2 定义OSS相关配置2.1 application-dev.yml2.2 application.yml 3 读取OSS配置3.1 AliOssProperties 4 生成OSS工具类对象4.1 AliOssUtil4.2 OssConfiguration2.5 CommonCont…...

C# 中 Array、ArrayList 和 List 的比较

C# 中 Array、ArrayList 和 List 的比较 在 C# 中&#xff0c;Array、ArrayList 和 List<T> 都用于存储和管理数据集合&#xff0c;但它们在类型安全性、性能、灵活性和使用场景上存在显著差异。以下是对这三种集合的详细比较&#xff1a; 1. 概述 特性ArrayArrayList…...

DeepSeek 提示词:常见指令类型

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…...

商业AI模型新篇章:Granite 3.2引领行业创新

摘要 Granite 3.2 是一款专为商业环境设计的人工智能模型&#xff0c;旨在提高AI驱动应用的信任度和可扩展性。该模型从零开始构建&#xff0c;采用最新的密集型架构&#xff0c;支持12种语言&#xff0c;覆盖11个不同领域。通过其先进的技术&#xff0c;Granite 3.2 不仅增强了…...

Spring boot中的@ConfigurationProperties注解

Spring boot中的ConfigurationProperties注解 ConfigurationProperties 是 Spring Boot 提供的一个强大注解&#xff0c;用于将配置文件&#xff08;如 application.properties 或 application.yml&#xff09;中的配置绑定到一个 Java 对象中。它不仅简化了配置管理&#xff…...

Rust中的异步编程:构建简单的网页爬虫

一、什么是Rust中的Futures和Async&#xff1f; 在Rust中&#xff0c;异步编程基于future&#xff08;未来&#xff09;的概念。一个future表示一个当前可能不可用&#xff0c;但将来某个时候可以获得的值。Rust中的Future特征定义了这一概念&#xff0c;任何实现了该特征的类…...

springai系列(二)从0开始搭建和接入azure-openai实现智能问答

文章目录 前言1.从0开始搭建项目2.进入微软openai申请key3.配置application.yaml4.编写controller5.测试源码下载地址总结 前言 之前使用openai的官网的api需要科学上网&#xff0c;但是我们可以使用其他的代理间接实现使用chatgpt的相关模型&#xff0c;解决这个问题。比如:本…...