hookehuyr

fix(弹框控制): 修复未完成表单弹框状态管理问题

修复弹框状态在不同表单间切换时未正确重置的问题
添加表单code参数跟踪确保弹框状态与当前表单匹配
新增调试页面用于测试弹框状态管理功能
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>弹框状态调试工具</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
}
.container {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
color: #333;
text-align: center;
}
.status-section {
margin: 20px 0;
padding: 15px;
background: #f8f9fa;
border-radius: 5px;
border-left: 4px solid #007bff;
}
.button-group {
display: flex;
gap: 10px;
margin: 20px 0;
flex-wrap: wrap;
}
button {
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 14px;
transition: background-color 0.3s;
}
.btn-primary {
background-color: #007bff;
color: white;
}
.btn-primary:hover {
background-color: #0056b3;
}
.btn-warning {
background-color: #ffc107;
color: #212529;
}
.btn-warning:hover {
background-color: #e0a800;
}
.btn-danger {
background-color: #dc3545;
color: white;
}
.btn-danger:hover {
background-color: #c82333;
}
.alert {
padding: 10px;
margin: 10px 0;
border-radius: 5px;
}
.alert-success {
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.alert-info {
background-color: #d1ecf1;
color: #0c5460;
border: 1px solid #bee5eb;
}
</style>
</head>
<body>
<div class="container">
<h1>未完成表单弹框调试工具</h1>
<div class="alert alert-info">
<strong>说明:</strong>此工具用于调试"您还未完成的表单"弹框的显示状态。如果弹框不显示,可能是因为已经显示过或者表单代码发生了变化。
</div>
<div class="status-section">
<h3>当前状态</h3>
<div id="status"></div>
</div>
<div class="status-section">
<div id="cookies"></div>
</div>
<div class="button-group">
<button class="btn-primary" onclick="checkStatus()">刷新状态</button>
<button class="btn-warning" onclick="resetDialogState()">重置弹框状态</button>
<button class="btn-danger" onclick="clearAllData()">清除所有数据</button>
</div>
<div id="message"></div>
</div>
<script>
function checkStatus() {
const dialogShown = sessionStorage.getItem('unfinished_form_dialog_shown');
const dialogCode = sessionStorage.getItem('unfinished_form_dialog_code');
const statusDiv = document.getElementById('status');
statusDiv.innerHTML = `
<p><strong>弹框状态:</strong> ${dialogShown === 'true' ? '已显示过' : '未显示'}</p>
<p><strong>记录的表单Code:</strong> ${dialogCode || '无'}</p>
<p><strong>SessionStorage弹框值:</strong> ${dialogShown || '无'}</p>
<p><strong>SessionStorage代码值:</strong> ${dialogCode || '无'}</p>
`;
// 检查Cookie状态
const cookies = document.cookie.split(';');
const cookieDiv = document.getElementById('cookies');
let cookieInfo = '<h3>相关Cookie信息:</h3>';
if (cookies.length === 1 && cookies[0] === '') {
cookieInfo += '<p>无Cookie数据</p>';
} else {
cookies.forEach(cookie => {
const [name, value] = cookie.trim().split('=');
if (name && value) {
cookieInfo += `<p><strong>${name}:</strong> ${decodeURIComponent(value)}</p>`;
}
});
}
cookieDiv.innerHTML = cookieInfo;
}
function resetDialogState() {
sessionStorage.removeItem('unfinished_form_dialog_shown');
sessionStorage.removeItem('unfinished_form_dialog_code');
showMessage('弹框状态已重置!现在可以重新显示弹框了。', 'success');
checkStatus();
}
function clearAllData() {
// 清除所有sessionStorage
sessionStorage.clear();
// 清除所有cookies(注意:只能清除当前域名下的cookies)
const cookies = document.cookie.split(';');
cookies.forEach(cookie => {
const eqPos = cookie.indexOf('=');
const name = eqPos > -1 ? cookie.substr(0, eqPos).trim() : cookie.trim();
if (name) {
document.cookie = name + '=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/';
}
});
showMessage('所有数据已清除!包括SessionStorage和Cookies。', 'success');
checkStatus();
}
function showMessage(text, type) {
const messageDiv = document.getElementById('message');
messageDiv.innerHTML = `<div class="alert alert-${type}">${text}</div>`;
setTimeout(() => {
messageDiv.innerHTML = '';
}, 3000);
}
// 页面加载时自动检查状态
window.onload = function() {
checkStatus();
};
</script>
</body>
</html>
\ No newline at end of file
......@@ -28,6 +28,7 @@ import { getFormSettingAPI } from "@/api/form.js";
import { showDialog, showConfirmDialog } from 'vant';
// import fp3 from '@/utils/fp3';
import { Updater } from '@/utils/versionUpdater';
import { resetDialogState } from '@/utils/dialogControl.js';
// 使用 include + pinia 状态管理动态缓存页面
const store = mainStore();
......@@ -63,6 +64,9 @@ const is_wx = computed(() => wxInfo().isWeiXin);
const is_iframe = computed(() => window.self !== window.top);
onMounted(async () => {
// 重置弹框状态,确保每次访问页面时都能正常显示未完成表单弹框
resetDialogState();
const code = getUrlParams(location.href) ? getUrlParams(location.href).code : '';
const model = getUrlParams(location.href) ? getUrlParams(location.href).model : '';
const data_id = getUrlParams(location.href) ? getUrlParams(location.href).data_id : '';
......
/*
* @Date: 2022-05-26 13:57:28
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-09-10 10:26:45
* @LastEditTime: 2025-09-11 17:13:53
* @FilePath: /data-table/src/router.js
* @Description: 文件描述
*/
......@@ -11,7 +11,7 @@ import asyncRoutesArr from "./mock/routes"
import generateRoutes from './utils/generateRoute'
import { Loading } from "vant";
import Cookies from 'js-cookie';
import { showUnfinishedFormDialog } from '@/utils/dialogControl.js';
import { showUnfinishedFormDialog, resetDialogState } from '@/utils/dialogControl.js';
import { getCycleListAPI } from '@/api/cycle';
// TAG: 路由配置表
......@@ -86,6 +86,11 @@ const checkCycleSelection = (to) => {
};
router.beforeEach((to, from, next) => {
// 当访问不同的表单时(code参数不同),重置弹框状态
if (to.query.code && from.query.code && to.query.code !== from.query.code) {
resetDialogState();
}
// 使用404为中转页面,避免动态路由没有渲染出来,控制台报警告问题
if (to.path == '/404' && to.redirectedFrom != undefined) {
// 模拟异步操作
......@@ -150,7 +155,8 @@ router.beforeEach((to, from, next) => {
// 用户选择删除,删除cookie并跳转
Cookies.remove(to.query.code);
next();
}
},
to.query.code
);
} else {
next();
......@@ -170,12 +176,12 @@ router.beforeEach((to, from, next) => {
query: to.query,
params: to.params
};
// 调试信息:检查保存的路由对象
console.log('保存到sessionStorage的目标路由:', targetRoute);
console.log('目标路由查询参数:', targetRoute.query);
console.log('目标路由code参数:', targetRoute.query.code);
sessionStorage.setItem('cycle_target_route', JSON.stringify(targetRoute));
// 直接跳转,不使用next
router.push({
......@@ -198,7 +204,8 @@ router.beforeEach((to, from, next) => {
// 用户选择删除,删除cookie并跳转
Cookies.remove(to.query.code);
next();
}
},
to.query.code
);
} else {
next();
......
/*
* @Date: 2025-09-10 10:54:52
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-09-11 17:13:28
* @FilePath: /data-table/src/utils/dialogControl.js
* @Description: 文件描述
*/
import { showConfirmDialog } from 'vant';
import { styleColor } from '@/constant.js';
// 弹框显示状态管理
const DIALOG_SHOWN_KEY = 'unfinished_form_dialog_shown';
const DIALOG_CODE_KEY = 'unfinished_form_dialog_code';
/**
* 检查弹框是否已经显示过
* @param {string} currentCode - 当前表单的code参数
* @returns {boolean} 是否已显示过
*/
export function hasDialogShown() {
return sessionStorage.getItem(DIALOG_SHOWN_KEY) === 'true';
export function hasDialogShown(currentCode) {
const isShown = sessionStorage.getItem(DIALOG_SHOWN_KEY) === 'true';
const lastCode = sessionStorage.getItem(DIALOG_CODE_KEY);
// 如果当前code与上次显示弹框的code不同,则重置状态
if (currentCode && lastCode && currentCode !== lastCode) {
resetDialogState();
return false;
}
return isShown;
}
/**
* 标记弹框已显示
* @param {string} currentCode - 当前表单的code参数
*/
export function markDialogShown() {
export function markDialogShown(currentCode) {
sessionStorage.setItem(DIALOG_SHOWN_KEY, 'true');
if (currentCode) {
sessionStorage.setItem(DIALOG_CODE_KEY, currentCode);
}
}
/**
......@@ -24,17 +46,19 @@ export function markDialogShown() {
*/
export function resetDialogState() {
sessionStorage.removeItem(DIALOG_SHOWN_KEY);
sessionStorage.removeItem(DIALOG_CODE_KEY);
}
/**
* 显示未完成表单确认弹框(带全局控制)
* @param {Function} onConfirm - 确认回调
* @param {Function} onCancel - 取消回调
* @param {string} currentCode - 当前表单的code参数
* @returns {Promise|null} 如果已显示过则返回null,否则返回弹框Promise
*/
export function showUnfinishedFormDialog(onConfirm, onCancel) {
export function showUnfinishedFormDialog(onConfirm, onCancel, currentCode) {
// 如果已经显示过,直接执行确认回调
if (hasDialogShown()) {
if (hasDialogShown(currentCode)) {
if (onConfirm) {
onConfirm();
}
......@@ -42,7 +66,7 @@ export function showUnfinishedFormDialog(onConfirm, onCancel) {
}
// 标记为已显示
markDialogShown();
markDialogShown(currentCode);
// 显示弹框
return showConfirmDialog({
......@@ -62,4 +86,4 @@ export function showUnfinishedFormDialog(onConfirm, onCancel) {
onCancel();
}
});
}
\ No newline at end of file
}
......
......@@ -189,7 +189,8 @@ const checkUnfinishedForm = (route) => {
cycle_selected: '1'
}
});
}
},
route.query.code
);
} else {
// 没有未完成的表单,直接跳转
......
......@@ -198,6 +198,7 @@ import { useRoute } from "vue-router";
import { queryFormAPI, postVerifyPasswordAPI, getVolunteerSourceLeaderAPI } from "@/api/form.js";
import { addFormDataAPI, queryFormDataAPI, modiFormDataAPI, flowFormDataAPI } from "@/api/data.js";
import { showSuccessToast, showFailToast, showConfirmDialog, showToast } from "vant";
import { resetDialogState } from "@/utils/dialogControl.js";
import { wxInfo, getUrlParams, formatDate, prettyLog } from "@/utils/tools";
import { styleColor } from "@/constant.js";
import { sharePage } from '@/composables/useShare.js'
......@@ -1067,6 +1068,8 @@ const submitStatus = ref(false); // 表单提交按钮状态
const successHandle = () => { // 表单成功提交后续操作
// 删除存在cookie, 提交成功后删除
Cookies.remove($route.query.code);
// 清理弹框状态,表单提交成功后重置
resetDialogState();
//在 iframe 中调用父页面中定义的变量 - Doris需要自由控制
let getChildVal = parent.parent.getChildVal;
if (getChildVal) {
......