fix(modal): resolve premature modal closing caused by unsupported click.self in wechat miniprogram

这个提交包含在:
xcbyy
2026-10-13 16:54:55 +08:00
父节点 d08acc052a
当前提交 56e672219e
共有 8 个文件被更改,包括 86 次插入 和 22 次删除

查看文件

@@ -288,8 +288,8 @@
</view>
<!-- 敏感商圈智能风控友好预检弹窗 (P1安全风控) -->
<view class="risk-modal-mask" v-if="riskModalVisible" @click.self="riskModalVisible = false">
<view class="risk-modal-box">
<view class="risk-modal-mask" v-if="riskModalVisible" @click="riskModalVisible = false">
<view class="risk-modal-box" @click.stop="stopPropagation">
<view class="risk-modal-header">
<image class="risk-shield-icon" :src="ICONS.shield" mode="aspectFit" />
<text class="risk-title">同城线下组局安全风控提示</text>
@@ -376,6 +376,12 @@ const calcTotalFee = computed(() => {
return Number(form.value.totalFee) || 0;
});
const stopPropagation = (e) => {
if (e && typeof e.stopPropagation === 'function') {
e.stopPropagation();
}
};
const riskModalVisible = ref(false);
const recommendPublicZones = ref([
'北京市朝阳区三里屯太古里 (AAA公开商圈)',

查看文件

@@ -194,8 +194,8 @@
</view>
<!-- 房主追加金额/改价弹窗 -->
<view class="adjust-modal-mask" v-if="adjustModalVisible" @click.self="closeAdjustModal">
<view class="adjust-modal-content">
<view class="adjust-modal-mask" v-if="adjustModalVisible" @click="closeAdjustModal">
<view class="adjust-modal-content" @click.stop="stopPropagation">
<view class="modal-header">
<view class="modal-title-box">
<text class="modal-title">{{ modalMode === 'APPEND' ? '房主追加金额' : '房主手动调整出价' }}</text>
@@ -438,6 +438,12 @@ onUnmounted(() => {
uni.$off('theme-change', onThemeChanged);
});
const stopPropagation = (e) => {
if (e && typeof e.stopPropagation === 'function') {
e.stopPropagation();
}
};
const activity = ref({
id: '',
title: '同城生活组局',

查看文件

@@ -259,8 +259,8 @@
</view>
<!-- 动态互动评论区抽屉组件 -->
<view class="comment-drawer-mask" v-if="commentDrawerVisible" @click.self="closeCommentDrawer">
<view class="comment-drawer-content">
<view class="comment-drawer-mask" v-if="commentDrawerVisible" @click="closeCommentDrawer">
<view class="comment-drawer-content" @click.stop="stopPropagation">
<view class="drawer-header">
<view class="drawer-header-left">
<text class="drawer-title">动态评论</text>
@@ -317,8 +317,8 @@
</view>
<!-- 社区置顶公告与公约详情弹窗 -->
<view class="notice-modal-mask" v-if="noticeModalVisible" @click.self="closeNoticeDetailModal">
<view class="notice-modal-content">
<view class="notice-modal-mask" v-if="noticeModalVisible" @click="closeNoticeDetailModal">
<view class="notice-modal-content" @click.stop="stopPropagation">
<view class="modal-header">
<view class="modal-header-left">
<view class="modal-badge">{{ communityNotice.tag || '置顶推荐' }}</view>

查看文件

@@ -184,8 +184,8 @@
</view>
<!-- 举报不良行为弹窗 -->
<view class="review-modal-mask" v-if="reportModalVisible" @click.self="closeReportModal">
<view class="review-modal-content">
<view class="review-modal-mask" v-if="reportModalVisible" @click="closeReportModal">
<view class="review-modal-content" @click.stop="stopPropagation">
<view class="modal-header">
<view class="modal-header-left">
<text class="modal-title">举报违规行为</text>
@@ -264,6 +264,12 @@ onUnmounted(() => {
uni.$off('theme-change', onThemeChanged);
});
const stopPropagation = (e) => {
if (e && typeof e.stopPropagation === 'function') {
e.stopPropagation();
}
};
const isLoading = ref(true);
const isFav = ref(false);
const expert = ref({

查看文件

@@ -244,8 +244,8 @@
</view>
<!-- 参与人身份核验确认卡弹窗 (Modal) -->
<view class="verify-modal-mask" v-if="showConfirmModal" @click.self="showConfirmModal = false">
<view class="verify-modal-content">
<view class="verify-modal-mask" v-if="showConfirmModal" @click="showConfirmModal = false">
<view class="verify-modal-content" @click.stop="stopPropagation">
<view class="modal-header">
<text class="modal-title">参与人身份核验确认</text>
<view class="badge-ready">门票有效</view>
@@ -343,8 +343,8 @@
</view>
<!-- 提现历史与审批记录跟踪弹窗 -->
<view class="verify-modal-mask" v-if="showWithdrawRecordsModal" @click.self="showWithdrawRecordsModal = false">
<view class="verify-modal-content withdraw-records-modal">
<view class="verify-modal-mask" v-if="showWithdrawRecordsModal" @click="showWithdrawRecordsModal = false">
<view class="verify-modal-content withdraw-records-modal" @click.stop="stopPropagation">
<view class="modal-header">
<text class="modal-title">提现记录与审批状态</text>
<view class="btn-close btn-active" @click="showWithdrawRecordsModal = false">
@@ -420,6 +420,12 @@ const todayIncome = ref('0.00');
const todayOrdersCount = ref(0);
const waitingVerifyCount = ref(0);
const stopPropagation = (e) => {
if (e && typeof e.stopPropagation === 'function') {
e.stopPropagation();
}
};
// 多维收益统计走势状态
const trendPeriod = ref('daily');
const trendMetric = ref('income');

查看文件

@@ -196,8 +196,8 @@
</view>
<!-- 优惠券选择弹窗 -->
<view class="coupon-modal-mask" v-if="couponModalVisible" @click.self="closeCouponModal">
<view class="coupon-modal-content">
<view class="coupon-modal-mask" v-if="couponModalVisible" @click="closeCouponModal">
<view class="coupon-modal-content" @click.stop="stopPropagation">
<view class="modal-header">
<text class="modal-title">选择优惠券</text>
<view class="modal-close" @click="closeCouponModal">
@@ -269,6 +269,12 @@ onUnmounted(() => {
uni.$off('theme-change', onThemeChanged);
});
const stopPropagation = (e) => {
if (e && typeof e.stopPropagation === 'function') {
e.stopPropagation();
}
};
const loadUserWallet = async () => {
try {
const u = await getUserProfile(1001);

查看文件

@@ -110,8 +110,8 @@
</view>
<!-- 评价大神服务体验交互弹窗 -->
<view class="review-modal-mask" v-if="reviewModalVisible" @click.self="closeReviewModal">
<view class="review-modal-content">
<view class="review-modal-mask" v-if="reviewModalVisible" @click="closeReviewModal">
<view class="review-modal-content" @click.stop="stopPropagation">
<view class="modal-header">
<view class="modal-header-left">
<text class="modal-title">服务体验评价</text>
@@ -184,8 +184,8 @@
</view>
<!-- 退款与售后仲裁申诉工单弹窗 -->
<view class="review-modal-mask" v-if="refundModalVisible" @click.self="closeRefundModal">
<view class="review-modal-content refund-modal-content">
<view class="review-modal-mask" v-if="refundModalVisible" @click="closeRefundModal">
<view class="review-modal-content refund-modal-content" @click.stop="stopPropagation">
<view class="modal-header">
<view class="modal-header-left">
<text class="modal-title">申请退款与仲裁</text>
@@ -263,8 +263,8 @@
</view>
<!-- 举报不良行为弹窗 -->
<view class="review-modal-mask" v-if="reportModalVisible" @click.self="closeReportModal">
<view class="review-modal-content report-modal-content">
<view class="review-modal-mask" v-if="reportModalVisible" @click="closeReportModal">
<view class="review-modal-content report-modal-content" @click.stop="stopPropagation">
<view class="modal-header">
<view class="modal-header-left">
<text class="modal-title">举报不良陪玩</text>
@@ -373,6 +373,12 @@ const navStyle = computed(() => {
};
});
const stopPropagation = (e) => {
if (e && typeof e.stopPropagation === 'function') {
e.stopPropagation();
}
};
const handleBack = () => {
const pages = getCurrentPages();
if (pages && pages.length > 1) {

查看文件

@@ -1074,6 +1074,34 @@ describe('ContentSecurityService & Compliance Architecture (TDD 微信内容安
expect(content).toContain('ICONS.chevronRight');
});
it('全端弹窗遮罩层严禁使用微信小程序不兼容的 @click.self 且内部卡片必须使用 stopPropagation 阻断冒泡', () => {
const orderListPath = path.join(rootDir, 'pwuniapp', 'pages', 'order', 'list.vue');
const orderCreatePath = path.join(rootDir, 'pwuniapp', 'pages', 'order', 'create.vue');
const expertDetailPath = path.join(rootDir, 'pwuniapp', 'pages', 'expert', 'detail.vue');
const expertWorkspacePath = path.join(rootDir, 'pwuniapp', 'pages', 'expert', 'workspace.vue');
const communityPath = path.join(rootDir, 'pwuniapp', 'pages', 'community', 'index.vue');
const orderListContent = fs.readFileSync(orderListPath, 'utf-8');
expect(orderListContent).not.toContain('@click.self');
expect(orderListContent).toContain('@click.stop="stopPropagation"');
const orderCreateContent = fs.readFileSync(orderCreatePath, 'utf-8');
expect(orderCreateContent).not.toContain('@click.self');
expect(orderCreateContent).toContain('@click.stop="stopPropagation"');
const expertDetailContent = fs.readFileSync(expertDetailPath, 'utf-8');
expect(expertDetailContent).not.toContain('@click.self');
expect(expertDetailContent).toContain('@click.stop="stopPropagation"');
const expertWorkspaceContent = fs.readFileSync(expertWorkspacePath, 'utf-8');
expect(expertWorkspaceContent).not.toContain('@click.self');
expect(expertWorkspaceContent).toContain('@click.stop="stopPropagation"');
const communityContent = fs.readFileSync(communityPath, 'utf-8');
expect(communityContent).not.toContain('@click.self');
expect(communityContent).toContain('@click.stop="stopPropagation"');
});
it('所有状态持久化修复代码与测试严禁包含任何系统 Emoji 违规字符', () => {
const actDetailPath = path.join(rootDir, 'pwuniapp', 'pages', 'activity', 'detail.vue');
const ticketPath = path.join(rootDir, 'pwuniapp', 'pages', 'activity', 'my-ticket.vue');