欢迎光临
我们一直在努力

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

一、问题背景

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

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

二、问题复现

操作步骤:

  • 登录系统账号(具备对应操作权限)

  • 进入业务单据列表,找到一条处于特定待处理状态的单据

  • 点击进入该单据的操作详情页面

  • 填写页面所需基础信息、上传相关附件

  • 点击页面中的提交类或完结类按钮

  • 结果:按钮点击后报错,流程无法流转到下一节点,操作失败。

  • 三、问题分析

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

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

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

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

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

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

  • 后端:接口缺少空值校验防御
  • 后端操作接口在查询业务记录时,未对数据库返回结果做非空判断,当接收前端传递的空关键标识或错误参数时,查询结果为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=有效标识)

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

    六、最佳实践总结

  • 页面核心数据必须从接口加载,禁止依赖硬编码或空值
  • // 错误:硬编码数据或初始空值,无法适配动态业务场景
    const relatedData = ref(100000)
    const keyId = ref(‘’)

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

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

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

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

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

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


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

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

    赞(0)
    未经允许不得转载:171主机测评 » uni-app——uni-app 小程序 之 【按钮失效问题排查(前端+后端)】
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址