const app = getApp(); const svc = require('../../services/exercise'); const DIM_MAP = { bodyPart: 'body-parts', equipment: 'equipment', target: 'targets', muscleGroup: 'muscle-groups', type: 'types' }; const SECONDARY_LABEL = { bodyPart: '部位', equipment: '器械' }; function labelForDim(d) { return ({ bodyPart: '按部位', equipment: '按器械', target: '按目标', muscleGroup: '按肌群', type: '按类型' })[d] || '分类'; } Page({ data: { statusBarHeight: 20, dimension: 'bodyPart', title: '分类', value: '', values: [], activeValue: '', // 二级维度(多维度筛选):进入器械维度时交叉按部位,其余维度交叉按器械 secondaryDim: 'equipment', secondaryKey: 'equipment', secondaryLabel: '器械', secondaryList: [], secondarySelected: [], exercises: [], loading: true, loadingMore: false, hasMore: true, page: 1, pageSize: 20, total: 0 }, onLoad(query) { const dimension = query.dimension || 'bodyPart'; const value = query.value || ''; const secondaryDim = dimension === 'equipment' ? 'bodyPart' : 'equipment'; const title = query.title || labelForDim(dimension); this.setData({ statusBarHeight: app.globalData.statusBarHeight || 20, dimension, value, secondaryDim, secondaryKey: DIM_MAP[secondaryDim] || 'equipment', secondaryLabel: SECONDARY_LABEL[secondaryDim] || '器械', title }); this.loadValues(); }, loadValues() { this.setData({ loading: true }); const key = DIM_MAP[this.data.dimension] || 'body-parts'; const secKey = this.data.secondaryKey; Promise.all([ svc.getCategories(key), svc.getCategories(secKey).catch(() => []) ]).then(([items, secItems]) => { const list = (items || []).slice(); // 头部插入「全部」项:明确当前为「全部」 list.unshift({ value: '', label: '全部' }); const activeValue = this.data.value || ''; // 用分类枚举里的干净中文标签回写标题,避免外部传入的标题出现乱码 let title = this.data.title; if (activeValue) { const hit = list.find((it) => it.value === activeValue); if (hit && hit.label) title = hit.label; } const secList = (secItems || []).slice().map((it) => ({ ...it, active: this.data.secondarySelected.includes(it.value) })); this.setData({ values: list, activeValue: activeValue, secondaryList: secList, title, loading: false }); this.loadExercises(); }).catch(() => { this.setData({ loading: false }); }); }, syncSecondaryActive() { const sel = this.data.secondarySelected; const list = this.data.secondaryList.map((it) => ({ ...it, active: sel.includes(it.value) })); this.setData({ secondaryList: list }); }, loadExercises() { this.setData({ loading: true, page: 1 }); const params = { page: 1, pageSize: this.data.pageSize }; params[this.data.dimension] = this.data.activeValue; if (this.data.secondarySelected.length) { params[this.data.secondaryDim] = this.data.secondarySelected.join(','); } svc.listExercises(params).then((res) => { const items = (res && res.items) || []; const total = (res && res.total) || 0; this.setData({ exercises: items, total, loading: false, hasMore: items.length < total }); }).catch(() => { this.setData({ loading: false }); }); }, onReachBottom() { if (this.data.loading || this.data.loadingMore || !this.data.hasMore) return; this.loadMore(); }, loadMore() { const next = this.data.page + 1; this.setData({ loadingMore: true }); const params = { page: next, pageSize: this.data.pageSize }; params[this.data.dimension] = this.data.activeValue; if (this.data.secondarySelected.length) { params[this.data.secondaryDim] = this.data.secondarySelected.join(','); } svc.listExercises(params).then((res) => { const items = (res && res.items) || []; const total = (res && res.total) || 0; const merged = this.data.exercises.concat(items); this.setData({ exercises: merged, total, page: next, loadingMore: false, hasMore: merged.length < total }); }).catch(() => { this.setData({ loadingMore: false }); }); }, onValue(e) { const value = e.detail.value; if (value === this.data.activeValue) return; this.setData({ activeValue: value, page: 1 }, () => this.loadExercises()); }, onSecondary(e) { const value = e.detail.value; if (!value) return; const cur = this.data.secondarySelected; const next = cur.includes(value) ? cur.filter((v) => v !== value) : cur.concat(value); this.setData({ secondarySelected: next, page: 1 }, () => { this.syncSecondaryActive(); this.loadExercises(); }); }, onSecondaryClear() { this.setData({ secondarySelected: [], page: 1 }, () => { this.syncSecondaryActive(); this.loadExercises(); }); }, onExercise(e) { if (!e || !e.detail || !e.detail.id) return; wx.navigateTo({ url: '/pages/detail/detail?id=' + encodeURIComponent(e.detail.id) }); } });