uni-app——uni-app 小程序 之 【按钮失效问题排查(前端+后端)】

一、问题背景

在某业务流程系统中,当业务单据进入特定待处理状态后,用户需要在对应操作页面完成核心操作,点击页面中的两个关键操作按钮(提交类、完结类)以推进流程流转。

然而实际操作时,两个按钮均出现报错提示,无法正常触发流程跳转,业务无法继续推进。

二、问题复现

操作步骤:

  1. 登录系统账号(具备对应操作权限)
  2. 进入业务单据列表,找到一条处于特定待处理状态的单据
  3. 点击进入该单据的操作详情页面
  4. 填写页面所需基础信息、上传相关附件
  5. 点击页面中的提交类或完结类按钮
  6. 结果:按钮点击后报错,流程无法流转到下一节点,操作失败。

三、问题分析

经过多轮排查,发现问题并非单一环节导致,而是涉及前端和后端两层,属于接口调用、参数传递及数据校验的联动异常,具体分析如下:

  1. 前端:页面加载时未获取核心业务数据

操作详情页面进入后,未先调用查询接口获取单据关联的核心数据,直接使用空值的关键标识调用操作接口,导致后端无法查询到对应业务记录,接口调用失败。

// 错误写法:关键标识未在页面加载时从接口获取,初始为空
const keyId = ref(‘’)

const submitOperation = async () => {
// keyId 为空,直接调用接口会导致后端查询失败
await submitAction({
keyId: keyId.value, // ‘’ 空字符串,无法匹配业务记录
operationData: data.value,
operationType: type.value,
})
}

  1. 前端:页面跳转参数传递错误

单据列表页跳转到操作详情页时,传递的参数为单据数字ID,但后端操作接口需要的是业务唯一流水号(而非数字ID),参数类型不匹配导致接口无法识别。

// 错误写法:传递了数字ID,与后端接口要求的流水号不匹配
uni.navigateTo({
url: /pages/business/operationDetail?id=${detail.id},
})

  1. 后端:接口缺少空值校验防御

后端操作接口在查询业务记录时,未对数据库返回结果做非空判断,当接收前端传递的空关键标识或错误参数时,查询结果为null,直接调用后续方法导致空指针异常,接口报错。

java.lang.NullPointerException: Cannot invoke
“BusinessVO.getRelatedData()” because “business” is null

四、解决方案

针对前后端两层问题,分别制定修复方案,核心是确保参数传递正确、数据加载时序合理、接口具备防御能力,具体如下:

方案一:页面加载时先获取核心业务数据(核心修复)

进入操作详情页面后,优先调用查询接口获取单据关联的核心数据,确认关键标识获取成功后,再允许用户进行提交操作,避免空值调用接口。

// api/business.js - 新增查询核心数据接口
export function getBusinessData(data) {
return http({
url: ‘/business/getBySerialNo’,
method: ‘GET’,
data,
})
}

方案二:修复页面跳转参数,与后端接口对齐

单据列表页跳转时,传递后端接口所需的业务流水号,而非数字ID,确保参数类型和含义匹配。

// 修复前:传递数字ID,与接口要求不符
const handleJumpToDetail = () => {
uni.navigateTo({
url: /pages/business/operationDetail?id=${detail.id},
})
}

// 修复后:传递业务流水号,与后端接口要求对齐
const handleJumpToDetail = () => {
const businessSerialNo = businessDetail.value.serialNo
if (!businessSerialNo) {
uni.showToast({ title: ‘缺少业务流水号’, icon: ‘none’ })
return
}
uni.navigateTo({
url: /pages/business/operationDetail?serialNo=${businessSerialNo},
})
}

方案三:提交操作前增加关键数据校验

在点击提交按钮时,先校验核心业务标识(keyId)是否已获取、必填信息是否完整,避免无效接口调用。

const submitOperation = async () => {
// 校验核心标识:确保已获取到业务数据
if (!keyId.value) {
uni.showToast({ title: ‘业务数据未加载,请稍后重试’, icon: ‘none’ })
return
}

// 校验必填操作数据
if (!operationData.value || operationData.value <= 0) {
uni.showToast({ title: ‘请输入有效的操作数据’, icon: ‘none’ })
return
}

try {
uni.showLoading({ title: ‘提交中…’, mask: true })

// 构造附件数据,适配接口要求 const attachments = uploadedImages.value.map((img) => ({ fileId: img.fileId || 0, fileName: img.fileName || '', fileUrl: img.serverFileUrl || img.url || '', fileKey: img.fileKey || '', fileSize: img.size || 0, fileType: img.type || '', })) const result = await submitAction({ keyId: keyId.value, operationData: operationData.value, operationType: operationType.value, operationRemark: remark.value, attachments, }) uni.hideLoading() if (result) { uni.showToast({ title: '操作提交成功', icon: 'success' }) setTimeout(() => { fetchBusinessData() // 刷新页面数据 uni.navigateBack() // 返回上一页 }, 1500) } 

} catch (error) {
uni.hideLoading()
uni.showToast({ title: error.message || ‘提交失败’, icon: ‘none’ })
}
}

方案四:按业务状态加载对应数据,优化加载逻辑

仅在单据处于特定待处理状态或已完成状态时,才获取相关操作数据,避免无效接口调用,提升页面加载效率。

const loadBusinessDetail = async (id) => {
try {
const response = await getBusinessDetail({ id })

businessDetail.value = response // 仅在单据到达目标操作节点时,获取相关操作数据 // status: 3=待处理, 4=已完成(根据实际业务状态定义) const hasReachedTargetNode = response.status === 3 || response.status === 4 if ( response.businessType === 1 && response.serialNo && hasReachedTargetNode ) { try { const businessData = await getBusinessData({ serialNo: response.serialNo, }) if (businessData) { businessInfo.value = businessData.businessInfo || businessData operationRecords.value = businessData.operationRecords || [] } } catch (err) { console.warn('获取业务操作数据失败:', err) } } 

} catch (error) {
uni.showToast({ title: ‘加载单据详情失败’, icon: ‘none’ })
}
}

方案五:后端增加空值校验,避免空指针异常

后端接口中,对数据库查询结果、前端传递参数进行严格校验,增加空值防御,返回明确的错误提示,便于前端排查问题。

public ResponseDTO submitAction(OperationDTO dto) {
// 根据前端传递的核心标识查询业务记录
BusinessVO business = businessMapper.selectById(dto.getKeyId());

// 修复:增加空值校验,返回明确错误提示 if (business == null) { return ResponseDTO.error("业务记录不存在,请检查参数是否正确"); } // 校验操作数据有效性 if (dto.getOperationData() == null || dto.getOperationData().compareTo(BigDecimal.ZERO) <= 0) { return ResponseDTO.error("操作数据必须大于0"); } // 校验操作数据不超过允许范围(根据实际业务逻辑) BigDecimal allowRange = business.getRelatedData().subtract(business.getUsedData()); if (dto.getOperationData().compareTo(allowRange) > 0) { return ResponseDTO.error("操作数据不能超过允许范围"); } // 执行核心业务操作逻辑... return ResponseDTO.success("操作成功"); 

}

五、修复前后对比

修复前(错误流程)

用户进入操作详情页面

直接展示表单(核心标识 keyId 为空)

用户填写信息并点击提交

调用 submitAction(keyId=‘’)

后端查不到业务记录 → 空指针异常 → 前端报错

修复后(正确流程)

用户进入操作详情页面(携带 serialNo 流水号参数)

调用 getBusinessData(serialNo) 获取核心业务数据

存储 keyId,展示相关数据、历史记录

用户填写信息并点击提交

校验 keyId 非空、操作数据有效

调用 submitAction(keyId=有效标识)

后端查到业务记录 → 空值校验通过 → 操作成功 → 流程流转

六、最佳实践总结

  1. 页面核心数据必须从接口加载,禁止依赖硬编码或空值

// 错误:硬编码数据或初始空值,无法适配动态业务场景
const relatedData = ref(100000)
const keyId = ref(‘’)

// 正确:页面加载时主动调用接口获取,确保数据有效性
onLoad(() => {
fetchBusinessData() // 先获取数据,再开放操作权限
})

  1. 页面跳转参数必须与后端接口要求对齐

不同接口可能需要不同类型的标识(数字ID、唯一流水号、字符串编码等),跳转前需确认目标页面调用的接口所需参数类型,避免参数不匹配导致接口失效。

  1. 提交类操作前必须校验关键数据

任何提交、确认类操作,都需先校验核心标识、必填信息的完整性和有效性,减少无效接口调用,提升用户体验,同时降低后端异常压力。

// 提交前必做校验,避免无效调用
if (!keyId.value) {
showToast(‘核心数据未加载完成,请重试’)
return
}

  1. 后端接口必须做好空值防御和参数校验

任何从数据库查询的结果都可能为null,调用其方法前必须做非空判断;同时对前端传递的参数进行有效性校验,避免空指针、非法参数等异常,返回清晰的错误提示。

  1. 前后端接口调用需遵循正确时序

移动端、小程序等场景中,接口调用时序至关重要。进入业务操作页面后,应先调用查询接口获取必要的业务数据,再允许用户触发操作接口,避免时序错乱导致的操作失败。


关键词:业务流程、按钮失效、页面参数传递、接口调用时序、NullPointerException、空值校验

适用场景:各类业务流程系统、操作类页面、多节点状态流转场景,涉及前后端接口联动的开发场景。

Read more

机器人系统十年演进

机器人系统十年演进全景(2015-2025):从专用执行机械到通用具身智能体的全栈革命 2015-2025年,是全球机器人产业完成底层范式重构的黄金十年。机器人系统从**“硬件驱动、预编程、封闭专用的工业执行机械”,彻底跃迁为“软件定义、AI驱动、开放通用的具身智能体”**,完成了从机械自动化到智能自主化的本质跨越。这十年,机器人系统的硬件体系、软件架构、算法范式、安全体系、部署模式实现了全栈式重构,同时中国机器人产业完成了从完全技术跟随、核心环节100%进口依赖,到全栈自主可控、全球技术与市场双领跑的历史性逆转。 本文系统梳理机器人系统十年间的四次代际跃迁、核心维度的本质变化、关键技术里程碑,与此前感知、定位、规控、软件架构、VLA等核心子系统的演进形成完整的系统级闭环。 一、机器人系统十年演进的四大代际阶段 机器人系统的十年演进,始终与产业需求、AI技术、算力发展深度同频,沿着**「封闭专用单机系统→模块化分布式系统→云边端一体化全栈系统→具身原生端云协同系统」**的核心主线推进,每个阶段的系统设计、核心能力、产业价值都发生了本质变化。 1. 2015-2017

【读点论文】Metric3D v2: A Versatile Monocular Geometric Foundation Model for Zero-shot MD and SNE坐标系变换

【读点论文】Metric3D v2: A Versatile Monocular Geometric Foundation Model for Zero-shot MD and SNE坐标系变换

Metric3D v2: A Versatile Monocular Geometric Foundation Model for Zero-shot Metric Depth and Surface Normal Estimation Abstract * Metric3D v2是一个几何基础模型,用于从一幅图像中进行零样本深度和表面法线估计,这对度量3D恢复至关重要。虽然深度和法线在几何上是相关的,并且高度互补,但它们存在不同的挑战。最先进的(SoTA)单目深度方法通过学习仿射不变深度来实现零样本泛化,同时,由于缺乏大规模标记数据,SoTA法线估计方法的零样本性能有限。为了解决这些问题,我们提出了度量深度估计和表面法线估计的解决方案。对于度量深度估计,我们指出,零样本单视图模型的关键在于解决各种相机模型和大规模数据训练的度量模糊性。我们提出了一个规范的相机空间转换模块,它明确地解决了模糊性问题,可以毫不费力地插入到现有的单目模型中。 * 对于表面法向估计,我们提出了一个联合深度-法向优化模块,从度量深度中提取多样化的数据知识,使法向估计器能够超越法向标签进行学习。配备了这

目标检测数据集 第133期-基于yolo标注格式的无人机航拍人员搜救检测数据集(含免费分享)

目标检测数据集 第133期-基于yolo标注格式的无人机航拍人员搜救检测数据集(含免费分享)

目录 目标检测数据集 第133期-基于yolo标注格式的无人机航拍人员搜救检测数据集(含免费分享) 超实用无人机航拍人员搜救检测数据集分享,助力计算机视觉研究! 1、背景 2、数据详情 2.1 数据集规模与结构 2.2 标注类别 2.3 场景多样性 3、应用场景 3.1 应急搜救辅助系统 3.2 无人机智能监控与巡查 3.3 计算机视觉算法研究 3.4 灾害评估与灾后重建 4、使用申明 目标检测数据集 第133期-基于yolo标注格式的无人机航拍人员搜救检测数据集(含免费分享) 超实用无人机航拍人员搜救检测数据集分享,助力计算机视觉研究! 1、背景 在自然灾害、事故灾难等突发场景中,人员搜救是应急响应的核心任务。传统搜救方式受地形、天气、视野等条件限制,效率与安全性面临挑战。无人机航拍技术凭借其机动性强、

人形机器人:百万亿美元赛道的终极逻辑从“万物皆可机器人化”到“人形机器人是终极通用平台”

人形机器人:百万亿美元赛道的终极逻辑从“万物皆可机器人化”到“人形机器人是终极通用平台”

人形机器人:百万亿美元赛道的终极逻辑 从“万物皆可机器人化”到“人形机器人是终极通用平台” 一、用户洞察的深刻性:为什么“百万亿美元”不是夸张 “未来汽车也可以发展成为人形机器人控制的智能汽车,可以说现有的一切工业制造可以人形机器人化,因此人形机器人是百万亿美元的赛道。” 这个洞察触及了人形机器人产业的终极本质——它不是单一产品,而是重塑一切物理世界交互方式的通用平台。 让我们用数字说话: 可被“人形机器人化”的领域当前全球市场规模人形机器人化后的潜在价值汽车产业3万亿美元汽车成为“人形机器人的移动座舱”工业制造15万亿美元工厂成为“人形机器人集群的协作网络”商业服务10万亿美元商场、酒店、餐厅成为“人形机器人服务场景”家庭经济20万亿美元家庭成为“人形机器人的生活空间”医疗康养8万亿美元医院成为“人形机器人辅助诊疗平台”特种作业5万亿美元危险环境成为“人形机器人专属作业区”教育科研4万亿美元实验室、教室成为“人形机器人教学空间”农业矿业6万亿美元田间、矿井成为“人形机器人作业场”物流运输7万亿美元仓库、港口成为“人形机器人调度中心”国防安保2万亿美元战场、边境成为“