fix(admin): prevent edit modal from closing immediately on tap

Fix the card types management edit modal that was closing immediately after opening due to event propagation. Added .stop modifier to all action button tap handlers (edit, toggle, delete) to prevent bubbling to parent modal-mask element.

- Changed @tap="openEdit(ct)" to @tap.stop="openEdit(ct)"
- Changed @tap="toggleActive(ct)" to @tap.stop="toggleActive(ct)"
- Changed @tap="confirmDelete(ct)" to @tap.stop="confirmDelete(ct)"

This fixes the bug where the edit modal would open and close in the same event cycle, making it impossible to edit card types.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
richarjiang
2026-04-05 12:53:03 +08:00
parent b6986ba30c
commit a85270efd4
2 changed files with 135 additions and 3 deletions

132
CARD_TYPES_BUG_FIX.md Normal file
View File

@@ -0,0 +1,132 @@
# Card Types Edit Modal Bug Fix
## Bug Description
When a user taps the **[编辑]** (Edit) button in the card types admin page, the edit modal opens briefly but **closes immediately** in the same event cycle. This makes it impossible to edit card types.
### Root Cause
The bug was caused by Vue event propagation/bubbling:
1. User taps edit button → `@tap="openEdit(ct)"` fires
2. `openEdit()` sets `showModal.value = true`
3. Modal is rendered and displayed
4. The tap event **bubbles up** to the parent modal-mask element
5. Modal-mask has `@tap.self="closeModal"` which immediately closes the modal
6. Result: Modal opens and closes in the same event tick
### Code Location
File: `packages/app/src/pages/admin/card-types.vue`
**Before (buggy):**
```vue
<!-- Line 67 -->
<view class="ct-action-btn edit-btn" @tap="openEdit(ct)">
<text class="ct-action-text">编辑</text>
</view>
<!-- Line 73 -->
<view class="ct-action-btn toggle-btn" @tap="toggleActive(ct)">
...
</view>
<!-- Line 77 -->
<view class="ct-action-btn delete-btn" @tap="confirmDelete(ct)">
...
</view>
<!-- Line 85 - Modal mask -->
<view v-if="showModal" class="modal-mask" @tap.self="closeModal">
...
</view>
```
## Solution Applied
Added the `.stop` modifier to all action button tap handlers to **prevent event propagation** to parent elements:
```vue
<!-- Line 67 - FIXED -->
<view class="ct-action-btn edit-btn" @tap.stop="openEdit(ct)">
<text class="ct-action-text">编辑</text>
</view>
<!-- Line 73 - FIXED -->
<view class="ct-action-btn toggle-btn" @tap.stop="toggleActive(ct)">
...
</view>
<!-- Line 77 - FIXED -->
<view class="ct-action-btn delete-btn" @tap.stop="confirmDelete(ct)">
...
</view>
```
## Why This Works
The `.stop` modifier is equivalent to calling `event.stopPropagation()`. It prevents the tap event from bubbling up the DOM tree, so:
1. User taps edit button → `@tap.stop="openEdit(ct)"` fires
2. Event propagation is **stopped** - event does NOT bubble to modal-mask
3. `openEdit()` sets `showModal.value = true`
4. Modal renders and stays open ✓
## Technical Details
### Vue Event Modifiers Used
- **`.stop`** - Calls `event.stopPropagation()` to prevent event bubbling
### Affected Operations
Three actions were fixed:
1. **Edit** (编辑) - Opens form to edit selected card type
2. **Toggle** (上架/下架) - Toggles active status (on/off shelf)
3. **Delete** (删除) - Opens confirmation dialog for deletion
## Testing Instructions
To verify the fix works:
1. Navigate to Admin → Card Types Management
2. Click the **[编辑]** button on any card
3. Verify the edit modal opens and **stays open**
4. Edit form fields and confirm the changes save correctly
5. Test the toggle button (上架/下架) - should toggle without closing modal
6. Test the delete button - should show confirmation dialog
## Code Changes Summary
| File | Line | Change | Type |
|------|------|--------|------|
| card-types.vue | 67 | `@tap="openEdit(ct)"``@tap.stop="openEdit(ct)"` | Fix |
| card-types.vue | 73 | `@tap="toggleActive(ct)"``@tap.stop="toggleActive(ct)"` | Fix |
| card-types.vue | 77 | `@tap="confirmDelete(ct)"``@tap.stop="confirmDelete(ct)"` | Fix |
Total changes: **3 lines modified**
## Impact Assessment
- **Severity**: High - Feature completely broken, users cannot edit card types
- **Risk**: Very Low - Simple modifier addition, no logic changes
- **Testing**: Quick manual test needed
- **Performance**: No impact
- **Breaking Changes**: None
- **Backward Compatibility**: Fully compatible
## Related Documentation
See the following files for comprehensive feature documentation:
- `CARD_TYPES_ANALYSIS.md` - Deep dive into the feature
- `CARD_TYPES_QUICK_REFERENCE.md` - Quick lookup guide
- `EXPLORATION_SUMMARY.md` - Full system overview
- `CARD_TYPES_INDEX.md` - Master index with all references
## Next Steps
1. ✅ Apply the fix (COMPLETED)
2. Test the feature manually
3. Verify all three action buttons work correctly
4. Consider adding automated E2E tests for card type management
5. Review other modals for similar event propagation issues

View File

@@ -64,17 +64,17 @@
<!-- Actions -->
<view class="ct-actions">
<view class="ct-action-btn edit-btn" @tap="openEdit(ct)">
<view class="ct-action-btn edit-btn" @tap.stop="openEdit(ct)">
<text class="ct-action-text">编辑</text>
</view>
<view
class="ct-action-btn toggle-btn"
:class="ct.isActive ? 'toggle-off' : 'toggle-on'"
@tap="toggleActive(ct)"
@tap.stop="toggleActive(ct)"
>
<text class="ct-action-text">{{ ct.isActive ? '下架' : '上架' }}</text>
</view>
<view class="ct-action-btn delete-btn" @tap="confirmDelete(ct)">
<view class="ct-action-btn delete-btn" @tap.stop="confirmDelete(ct)">
<text class="ct-action-text">删除</text>
</view>
</view>