fix(modal): resolve premature modal closing caused by unsupported click.self in wechat miniprogram
这个提交包含在:
@@ -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');
|
||||
|
||||
在新工单中引用
屏蔽一个用户