191 lines
5.9 KiB
JavaScript
191 lines
5.9 KiB
JavaScript
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: '分类',
|
||
dimTitle: '分类',
|
||
// 主维度支持多选:activeValues 为已选 value 数组(空数组 = 全部)
|
||
activeValues: [],
|
||
values: [],
|
||
// 二级维度(多维度筛选):进入器械维度时交叉按部位,其余维度交叉按器械
|
||
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 activeValues = value ? [value] : [];
|
||
const secondaryDim = dimension === 'equipment' ? 'bodyPart' : 'equipment';
|
||
const title = query.title || labelForDim(dimension);
|
||
this.setData({
|
||
statusBarHeight: app.globalData.statusBarHeight || 20,
|
||
dimension,
|
||
activeValues,
|
||
dimTitle: labelForDim(dimension),
|
||
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: '全部' });
|
||
// 用分类枚举里的干净中文标签回写标题,避免外部传入的标题出现乱码
|
||
let title = this.data.title;
|
||
const { activeValues } = this.data;
|
||
if (activeValues.length === 1) {
|
||
const hit = list.find((it) => it.value === activeValues[0]);
|
||
if (hit && hit.label) title = hit.label;
|
||
} else if (activeValues.length > 1) {
|
||
title = `已选 ${activeValues.length} 个`;
|
||
}
|
||
// 主维度 items 带 active 标志(供 filter-bar 置顶/内联展示)
|
||
const primaryItems = list.map((it) => ({ ...it, active: activeValues.includes(it.value) }));
|
||
const secList = (secItems || []).slice().map((it) => ({
|
||
...it,
|
||
active: this.data.secondarySelected.includes(it.value)
|
||
}));
|
||
this.setData({
|
||
values: primaryItems,
|
||
secondaryList: secList,
|
||
title,
|
||
loading: false
|
||
});
|
||
this.loadExercises();
|
||
}).catch(() => {
|
||
this.setData({ loading: false });
|
||
});
|
||
},
|
||
|
||
buildParams(page) {
|
||
const params = { page, pageSize: this.data.pageSize };
|
||
const av = this.data.activeValues;
|
||
if (av.length) params[this.data.dimension] = av.join(',');
|
||
if (this.data.secondarySelected.length) {
|
||
params[this.data.secondaryDim] = this.data.secondarySelected.join(',');
|
||
}
|
||
return params;
|
||
},
|
||
|
||
loadExercises() {
|
||
this.setData({ loading: true, page: 1 });
|
||
svc.listExercises(this.buildParams(1)).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 });
|
||
svc.listExercises(this.buildParams(next)).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 });
|
||
});
|
||
},
|
||
|
||
// 主维度(按器械/按部位)多选
|
||
onPrimaryChange(e) {
|
||
const vals = e.detail.values || [];
|
||
const values = this.data.values.map((it) => ({ ...it, active: vals.includes(it.value) }));
|
||
let title = this.data.title;
|
||
if (vals.length === 1) {
|
||
const hit = values.find((it) => it.value === vals[0]);
|
||
title = (hit && hit.label) || labelForDim(this.data.dimension);
|
||
} else if (vals.length > 1) {
|
||
title = `已选 ${vals.length} 个`;
|
||
} else {
|
||
title = labelForDim(this.data.dimension);
|
||
}
|
||
this.setData({ activeValues: vals, values, title, page: 1 }, () => this.loadExercises());
|
||
},
|
||
|
||
// 二级维度(部位/器械)多选
|
||
onSecondaryChange(e) {
|
||
const values = e.detail.values || [];
|
||
const secondaryList = this.data.secondaryList.map((it) => ({ ...it, active: values.includes(it.value) }));
|
||
this.setData({ secondarySelected: values, secondaryList, page: 1 }, () => this.loadExercises());
|
||
},
|
||
|
||
onSecondaryClear() {
|
||
const secondaryList = this.data.secondaryList.map((it) => ({ ...it, active: false }));
|
||
this.setData({ secondarySelected: [], secondaryList, page: 1 }, () => this.loadExercises());
|
||
},
|
||
|
||
onExercise(e) {
|
||
if (!e || !e.detail || !e.detail.id) return;
|
||
wx.navigateTo({ url: '/pages/detail/detail?id=' + encodeURIComponent(e.detail.id) });
|
||
}
|
||
});
|