爱色哥:不止一面,点亮你的色彩人生
操作后功能未生效问题的排查与解决问题背景在开发审批流程功能时遇到一个
常见问题审批状态的数据点击撤回后功能没有生效。
具体表现为点击撤回到草稿箱按钮后操作没有生效点击彻底删除后数据没有被删除反而出现在草稿箱中问题复现操作步骤提交一条审批申请在待审批状态下点击撤回按钮期望数据回到草稿箱但实际没有生效点击彻底删除数据没有删除反而出现在草稿箱问题分析通过代码分析发现问题主要出在以下几个方面
操作后页面未刷新从编辑/操作页面返回列表页时列表页的onLoad生命周期不会重新触发导致数据未刷新。
API 调用后缺少状态同步撤回和删除操作调用 API 成功后前端状态没有正确更新。
接口参数传递错误删除和撤回接口需要的参数格式不正确导致后端处理失败但前端显示成功。
解决方案方案一添加 onShow 生命周期刷新数据问题小程序/App 中页面返回时不触发onLoad只触发onShow。
script setup import { ref } from vue; import { onLoad, onShow } from dcloudio/uni-app; const listData ref([]); const isFirstLoad ref(true); const currentStatus ref(pending); // pending/draft/deleted // 加载列表数据 const loadListData async () { try { const response await getApprovalList({ status: currentStatus.value, pageNum: 1, pageSize: 20, }); listData.value response.list || []; } catch (error) { console.error(加载失败:, error); } }; // 页面首次加载 onLoad((options) { if (options.status) { currentStatus.value options.status; } loadListData(); }); // 页面显示时刷新关键修复点 onShow(() { // 跳过首次加载避免重复请求 if (isFirstLoad.value) { isFirstLoad.value false; return; } // 从其他页面返回时重新加载数据 loadListData(); }); /script方案二撤回功能的正确实现script setup import { ref } from vue; // 撤回到草稿箱 const handleWithdraw async (item) { try { // 显示确认弹窗 const confirmed await showConfirmDialog({ title: 确认撤回, content: 撤回后将移至草稿箱确定要撤回吗, }); if (!confirmed) return; // 显示加载状态 showLoading(撤回中...); // 调用撤回接口 - 注意参数格式 const result await withdrawApproval({ instanceId: item.id, reason: 用户主动撤回, }); hideLoading(); if (result.success) { showToast(撤回成功); // 方式1从列表中移除该项推荐 const index listData.value.findIndex((i) i.id item.id); if (index -
{ listData.value.splice(index,
; } // 方式2或者重新加载列表 // await loadListData(); } else { showToast(result.message || 撤回失败); } } catch (error) { hideLoading(); showToast(操作失败请重试); console.error(撤回失败:, error); } }; /script方案三删除功能的正确实现script setup // 彻底删除 const handleDelete async (item) { try { const confirmed await showConfirmDialog({ title: 确认删除, content: 删除后将无法恢复确定要删除吗, }); if (!confirmed) return; showLoading(删除中...); // 关键确保传递正确的参数 const result await deleteApproval({ instanceId: item.id, deleteType: permanent, // 彻底删除标识 }); hideLoading(); if (result.success) { showToast(删除成功); // 从列表中移除 listData.value listData.value.filter((i) i.id ! item.id); // 如果列表为空可以显示空状态或返回上一页 if (listData.value.length
{ showEmptyState(); } } else { // 关键正确处理失败情况 showToast(result.message || 删除失败); } } catch (error) { hideLoading(); // 不要静默失败要给用户反馈 showToast(删除失败请重试); console.error(删除失败:, error); } }; /script方案四统一的操作结果处理// utils/approval.tsinterfaceOperationResult{success:boolean;message?:string;data?:any;}// 统一的操作处理函数exportasyncfunctionhandleApprovalOperation(operationType:withdraw|delete|submit,params:{instanceId:string|number;[key:string]:any},callbacks:{onSuccess?:(data:any)void;onError?:(error:any)void;onFinally?:()void;}{}):PromiseOperationResult{constoperationMap{withdraw:{api:withdrawApproval,loadingText:撤回中...,successText:撤回成功,},delete:{api:deleteApproval,loadingText:删除中...,successText:删除成功,},submit:{api:submitApproval,loadingText:提交中...,successText:提交成功,},};constoperationoperationMap[operationType];if(!operation){return{success:false,message:未知操作类型};}try{showLoading(operation.loadingText);constresultawaitoperation.api(params);hideLoading();if(result.success||result.code
{showToast(operation.successText);callbacks.onSuccess?.(result.data);return{success:true,data:result.data};}else{consterrorMsgresult.message||操作失败;showToast(errorMsg);callbacks.onError?.(newError(errorMsg));return{success:false,message:errorMsg};}}catch(error:any){hideLoading();consterrorMsgerror.message||网络异常请重试;showToast(errorMsg);callbacks.onError?.(error);return{success:false,message:errorMsg};}finally{callbacks.onFinally?.();}}// 使用示例consthandleWithdrawasync(item){constresultawaithandleApprovalOperation(withdraw,{instanceId:item.id},{onSuccess:(){// 从列表中移除listData.valuelistData.value.filter((i)i.id!item.id);},});};方案五API 接口层的错误处理// api/approval.tsimport{http}from/utils/request;// 撤回审批exportfunctionwithdrawApproval(data:{instanceId:number|string;reason?:string}){returnhttp({url:/approval/instance/withdraw,method:POST,data:{instanceId:Number(data.instanceId),// 确保类型正确reason:data.reason||,},});}// 删除审批exportfunctiondeleteApproval(data:{instanceId:number|string;deleteType?:string}){returnhttp({url:/approval/instance/delete,method:POST,data:{instanceId:Number(data.instanceId),// 确保类型正确deleteType:data.deleteType||permanent,},});}// 请求拦截器中添加响应处理http.interceptors.response.use((response){const{code,data,message}response.data;// 统一处理业务错误码if(code!200code!
{// 不要静默处理返回错误信息returnPromise.reject({success:false,code,message:message||请求失败,data:null,});}return{success:true,code,message,data,};},(error){// 网络错误处理console.error(请求错误:,error);returnPromise.reject({success:false,code:-1,message:error.message||网络异常,data:null,});});方案六完整的列表页面示例template view classapproval-list !-- 状态标签页 -- view classtabs view v-fortab in tabs :keytab.value :class[tab-item, { active: currentStatus tab.value }] clickswitchTab(tab.value) text v-iftab.count classcount/text /view /view !-- 列表内容 -- scroll-view scroll-y classlist-container scrolltolowerloadMore refresher-enabled :refresher-triggeredisRefreshing refresherrefreshonRefresh view v-iflistData.length 0 view v-foritem in listData :keyitem.id classapproval-item view classitem-header text classtitle/text text :class[status, item.status]/text /view view classitem-content text申请时间/text text申请金额¥/text /view !-- 操作按钮 -- view classitem-actions !-- 待审批状态可撤回 -- button v-ifitem.status pending classbtn btn-withdraw clickhandleWithdraw(item) 撤回 /button !-- 草稿状态可编辑和删除 -- template v-ifitem.status draft button classbtn btn-edit clickhandleEdit(item)编辑/button button classbtn btn-delete clickhandleDelete(item)删除/button /template /view /view /view !-- 空状态 -- view v-else classempty-state image src/static/empty.png classempty-image / text暂无数据/text /view /scroll-view /view /template script setup import { ref, computed } from vue; import { onLoad, onShow } from dcloudio/uni-app; import { getApprovalList, withdrawApproval, deleteApproval } from /api/approval; const tabs [ { label: 待审批, value: pending, count: 0 }, { label: 草稿箱, value: draft, count: 0 }, { label: 已完成, value: completed, count: 0 }, ]; const currentStatus ref(pending); const listData ref([]); const isRefreshing ref(false); const isFirstLoad ref(true); const pageNum ref(
; const hasMore ref(true); // 加载列表 const loadListData async (isLoadMore false) { try { if (!isLoadMore) { pageNum.value 1; hasMore.value true; } const response await getApprovalList({ status: currentStatus.value, pageNum: pageNum.value, pageSize: 20, }); const newList response.list || []; if (isLoadMore) { listData.value [...listData.value, ...newList]; } else { listData.value newList; } hasMore.value newList.length 20; } catch (error) { console.error(加载失败:, error); uni.showToast({ title: 加载失败, icon: none }); } }; // 切换标签 const switchTab (status) { if (currentStatus.value status) return; currentStatus.value status; loadListData(); }; // 下拉刷新 const onRefresh async () { isRefreshing.value true; await loadListData(); isRefreshing.value false; }; // 加载更多 const loadMore () { if (!hasMore.value) return; pageNum.value; loadListData(true); }; // 撤回操作 const handleWithdraw async (item) { try { const [error] await uni.showModal({ title: 确认撤回, content: 撤回后将移至草稿箱确定吗, }); if (error || !error.confirm) return; uni.showLoading({ title: 撤回中... }); const result await withdrawApproval({ instanceId: item.id }); uni.hideLoading(); if (result.success) { uni.showToast({ title: 撤回成功, icon: success }); // 从当前列表移除 listData.value listData.value.filter((i) i.id ! item.id); } else { uni.showToast({ title: result.message || 撤回失败, icon: none }); } } catch (error) { uni.hideLoading(); uni.showToast({ title: 操作失败, icon: none }); } }; // 删除操作 const handleDelete async (item) { try { const [error, res] await uni.showModal({ title: 确认删除, content: 删除后无法恢复确定吗, }); if (error || !res.confirm) return; uni.showLoading({ title: 删除中... }); const result await deleteApproval({ instanceId: item.id, deleteType: permanent, }); uni.hideLoading(); if (result.success) { uni.showToast({ title: 删除成功, icon: success }); listData.value listData.value.filter((i) i.id ! item.id); } else { uni.showToast({ title: result.message || 删除失败, icon: none }); } } catch (error) { uni.hideLoading(); uni.showToast({ title: 操作失败, icon: none }); } }; // 编辑 const handleEdit (item) { uni.navigateTo({ url: /pages/approval/edit?id${item.id}, }); }; // 获取状态文本 const getStatusText (status) { const map { pending: 待审批, draft: 草稿, completed: 已完成, rejected: 已驳回, }; return map[status] || status; }; // 生命周期 onLoad(() { loadListData(); }); // 关键页面显示时刷新数据 onShow(() { if (isFirstLoad.value) { isFirstLoad.value false; return; } // 从编辑页返回时刷新 loadListData(); }); /script style langscss scoped .approval-list { min-height: 100vh; background: #f5f5f5; } .tabs { display: flex; background: #fff; padding: 20rpx; gap: 20rpx; .tab-item { flex: 1; text-align: center; padding: 16rpx; border-radius: 8rpx; background: #f0f0f0; font-size: 28rpx; .active { background: #1890ff; color: #fff; } .count { margin-left: 8rpx; font-size: 24rpx; } } } .approval-item { background: #fff; margin: 20rpx; padding: 24rpx; border-radius: 12rpx; .item-header { display: flex; justify-content: space-between; margin-bottom: 16rpx; .title { font-size: 32rpx; font-weight: 500; } .status { font-size: 24rpx; padding: 4rpx 12rpx; border-radius: 4rpx; .pending { background: #fff7e6; color: #fa8c16; } .draft { background: #f0f0f0; color: #666; } } } .item-actions { display: flex; gap: 16rpx; margin-top: 20rpx; padding-top: 20rpx; border-top: 1rpx solid #eee; .btn { flex: 1; font-size: 28rpx; padding: 16rpx; border-radius: 8rpx; border: none; .btn-withdraw { background: #fff7e6; color: #fa8c16; } .btn-edit { background: #e6f7ff; color: #1890ff; } .btn-delete { background: #fff1f0; color: #ff4d4f; } } } } .empty-state { display: flex; flex-direction: column; align-items: center; padding: 100rpx; color: #999; } /style最佳实践
总结
操作后必须更新前端状态API 调用成功后及时更新本地列表数据不要依赖页面刷新主动移除或修改列表项
正确处理页面生命周期小程序/App 使用onShow而非仅onLoad避免首次加载重复请求
完善的错误处理API 失败时给用户明确反馈不要静默失败
参数类型检查确保instanceId等参数类型正确后端可能要求数字类型前端传字符串会导致失败
用户体验优化操作前显示确认弹窗操作中显示 loading操作后显示结果提示关键词审批撤回、删除功能、状态同步、页面刷新、onShow生命周期适用场景审批流程、工单系统、任务管理等需要状态操作的业务场景
真实双人插画视频素材高清观看免费-真实双人插画视频素材高清观看免费应用