fix: 滑动卡片指示器联动 — _cardIdx从computed迁移到data独立管理

根因: _cardIdx存在computed lane对象中, computed重新计算时重置为0
修复: cardIndices{}独立data管理, keyed by lane._key
      新增watch product重置 + getCardIdx/setCardIdx方法
This commit is contained in:
2026-08-12 16:11:22 +08:00
parent a5e256330a
commit 8303c8b93f

View File

@ -6,7 +6,7 @@
<view class="ss-title-group"> <view class="ss-title-group">
<text class="ss-title">{{ lanes[currentLane].label }}</text> <text class="ss-title">{{ lanes[currentLane].label }}</text>
<text class="ss-step-hint"> <text class="ss-step-hint">
步骤 {{ lanes[currentLane]._cardIdx + 1 }}/{{ lanes[currentLane].cards.length }} 步骤 {{ getCardIdx(lanes[currentLane]._key) + 1 }}/{{ lanes[currentLane].cards.length }}
<text v-if="lanes.length > 1"> · ← 左右滑切换分支 →</text> <text v-if="lanes.length > 1"> · ← 左右滑切换分支 →</text>
</text> </text>
</view> </view>
@ -20,7 +20,7 @@
:style="{ height: swiperHeight + 'px' }" duration="250"> :style="{ height: swiperHeight + 'px' }" duration="250">
<swiper-item v-for="(lane, li) in lanes" :key="lane._key"> <swiper-item v-for="(lane, li) in lanes" :key="lane._key">
<!-- 🚀 垂直滑动:当前分支的时间线 --> <!-- 🚀 垂直滑动:当前分支的时间线 -->
<swiper class="ss-swiper-v" :current="lane._cardIdx" @change="onCardSwipe($event, li)" <swiper class="ss-swiper-v" :current="getCardIdx(lane._key)" @change="onCardSwipe($event, li)"
duration="200" vertical :style="{ height: swiperHeight + 'px' }"> duration="200" vertical :style="{ height: swiperHeight + 'px' }">
<swiper-item v-for="(card, ci) in lane.cards" :key="card._key"> <swiper-item v-for="(card, ci) in lane.cards" :key="card._key">
<view class="ss-card-wrapper"> <view class="ss-card-wrapper">
@ -85,7 +85,7 @@
</view> </view>
<view class="ss-dots"> <view class="ss-dots">
<view v-for="(c, i) in lanes[currentLane].cards" :key="'d'+i" <view v-for="(c, i) in lanes[currentLane].cards" :key="'d'+i"
:class="['ss-dot', i === lanes[currentLane]._cardIdx ? 'ss-dot-active' : '', c._isMain ? 'ss-dot-main' : '']"> :class="['ss-dot', i === getCardIdx(lanes[currentLane]._key) ? 'ss-dot-active' : '', c._isMain ? 'ss-dot-main' : '']">
<text class="ss-dot-label">{{ i + 1 }}</text> <text class="ss-dot-label">{{ i + 1 }}</text>
</view> </view>
</view> </view>
@ -104,9 +104,17 @@ export default {
data() { data() {
return { return {
currentLane: 0, currentLane: 0,
cardIndices: {}, // { laneKey: currentCardIndex } — 独立管理避免computed重置
swiperHeight: 600, swiperHeight: 600,
}; };
}, },
watch: {
// product 变化时重置所有滑动位置
product: {
immediate: true,
handler() { this.cardIndices = {}; },
},
},
computed: { computed: {
branchLabelMap() { branchLabelMap() {
const map = {}; const map = {};
@ -133,7 +141,7 @@ export default {
const result = []; const result = [];
if (!this.product || !this.product.task_tree) return result; if (!this.product || !this.product.task_tree) return result;
const mainLane = { _key: 'main', label: '主分支', cards: [], _cardIdx: 0 }; const mainLane = { _key: 'main', label: '主分支', cards: [] };
const sortTasks = (tasks) => { const sortTasks = (tasks) => {
if (!tasks) return []; if (!tasks) return [];
@ -160,7 +168,7 @@ export default {
const spawns = t.child_tasks.filter(c => c.task_type === 'SPAWN'); const spawns = t.child_tasks.filter(c => c.task_type === 'SPAWN');
for (const sc of spawns) { for (const sc of spawns) {
const blabel = (this.branchLabelMap && this.branchLabelMap[sc.id]) || '协助分支'; const blabel = (this.branchLabelMap && this.branchLabelMap[sc.id]) || '协助分支';
const branchLane = { _key: 'branch_' + sc.id, label: blabel, cards: [], _cardIdx: 0 }; const branchLane = { _key: 'branch_' + sc.id, label: blabel, cards: [] };
result.push(branchLane); // 先占坑:父分支排在前面 result.push(branchLane); // 先占坑:父分支排在前面
followMain([sc], branchLane); // 再递归:孙子分支自然排在后面 followMain([sc], branchLane); // 再递归:孙子分支自然排在后面
} }
@ -181,10 +189,13 @@ export default {
}, },
methods: { methods: {
formatUserName, formatUserName,
getCardIdx(laneKey) { return this.cardIndices[laneKey] || 0; },
setCardIdx(laneKey, idx) { this.$set(this.cardIndices, laneKey, idx); },
onLaneSwipe(e) { this.currentLane = e.detail.current; }, onLaneSwipe(e) { this.currentLane = e.detail.current; },
onCardSwipe(e, laneIdx) { onCardSwipe(e, laneIdx) {
if (this.lanes[laneIdx]) { const lane = this.lanes[laneIdx];
this.$set(this.lanes[laneIdx], '_cardIdx', e.detail.current); if (lane) {
this.setCardIdx(lane._key, e.detail.current);
} }
}, },
taskCardClass(t) { taskCardClass(t) {