const api = require('../../utils/api'); const auth = require('../../utils/auth'); // 计划类型常量 const TYPES = ['weekly', 'monthly', 'yearly']; const TYPE_LABELS = ['周计划', '月计划', '年计划']; Page({ data: { // 类型切换相关 types: TYPE_LABELS, typeIndex: 0, // 视图模式:overview 总览 / detail 小组详情(仅老师) view: 'overview', // 加载状态 loading: false, refreshing: false, // 当前周期 periodKey: '', // 提交相关 canSubmit: false, message: '', // 我的计划状态 myChecked: false, myStatus: '', myRecord: null, myThumbs: [], // 未分组人数(仅老师可见) unassignedCount: 0, // 小组列表 groups: [], // 当前选中的小组 selectedGroupName: '', // 小组成员列表(老师详情 & 学员小组 tab) members: [], // 用户角色 isTeacher: false, myGroup: '', // 学员视图 tab:group / personal studentTab: 'group', // 个人历史列表 history: [], // 周期切换相关 periodList: [], // 可用周期列表 showPeriodPicker: false, }, onShow() { auth.ensureLogin().then((token) => { if (!token) { wx.showToast({ title: '请先登录', icon: 'none' }); setTimeout(() => wx.switchTab({ url: '/pages/profile/profile' }), 500); return; } wx.removeStorageSync('plan_overview_dirty'); this.setData({ view: 'overview' }); // 先加载周期列表,再加载总览(总览接口会返回 is_teacher) this.loadPeriods().then(() => { this.loadOverview(); }); }).catch((err) => { console.error('plan page init error:', err); }); }, /** 切换计划类型(周/月/年) */ onTypeChange(e) { const typeIndex = Number(e.currentTarget.dataset.index); if (typeIndex === this.data.typeIndex) { return; } this.setData({ typeIndex, view: 'overview', selectedGroupName: '', members: [], history: [], studentTab: 'group' }); // 切换类型后重新加载周期列表和总览 this.loadPeriods().then(() => { this.loadOverview(); }); }, /** 下拉刷新 */ onRefresh() { this.setData({ refreshing: true }); this.loadPeriods().then(() => { return this.loadOverview(); }).then(() => { // 学员个人 tab 也刷一下历史 if (!this.data.isTeacher && this.data.studentTab === 'personal') { return this.loadHistory(); } }).then(() => { this.setData({ refreshing: false }); }); }, /** 加载可用周期列表 */ loadPeriods() { const type = TYPES[this.data.typeIndex]; return api.request({ url: '/api/v1/plan/periods', data: { type } }) .then((res) => { const periods = res.periods || []; // 默认选第一个(最新)周期,或者后端返回的当前周期 let periodKey = periods[0] || res.current_period || ''; this.setData({ periodList: periods, periodKey: periodKey || this.data.periodKey, }); }) .catch(() => { // 获取失败不影响主流程 console.warn('获取周期列表失败'); }); }, /** 打开周期选择器 */ openPeriodPicker() { if (!this.data.periodList.length) { return; } this.setData({ showPeriodPicker: true }); }, /** 关闭周期选择器 */ closePeriodPicker() { this.setData({ showPeriodPicker: false }); }, /** 选择某个周期 */ onPeriodSelect(e) { const period = e.currentTarget.dataset.period; if (!period || period === this.data.periodKey) { this.setData({ showPeriodPicker: false }); return; } this.setData({ periodKey: period, showPeriodPicker: false, }); if (this.data.view === 'detail') { // 详情页:重新加载当前小组的该周期数据 this.loadDetail(); } else if (!this.data.isTeacher && this.data.studentTab === 'group' && this.data.myGroup) { // 学员总览 + 小组 tab:刷新本组成员 this.loadOverview(); } else { // 老师总览 / 学员个人 tab:重新加载总览 this.loadOverview(); } }, /** 加载总览数据 */ loadOverview() { const type = TYPES[this.data.typeIndex]; const periodKey = this.data.periodKey; this.setData({ loading: true }); return api.request({ url: '/api/v1/plan/groups', data: { type, period_key: periodKey } }) .then((res) => { const groups = (res.groups || []).map((g) => { const percent = g.total ? Math.round(((g.checked_count || 0) / g.total) * 100) : 0; return { ...g, percent, progressStyle: 'width:' + percent + '%;' }; }); const isTeacher = !!res.is_teacher; this.setData({ loading: false, refreshing: false, periodKey: res.period_key || periodKey, canSubmit: !!res.can_submit, message: res.message || '', myChecked: !!res.my_checked, myStatus: res.my_status || '', myRecord: res.my_record || null, myThumbs: ((res.my_record && res.my_record.attachments) || []).map((p) => api.planFileUrl(p)), unassignedCount: res.unassigned_count || 0, isTeacher, myGroup: res.my_group || '', groups, }); // 学员:如果在总览 + 小组 tab,加载本组成员 if (!isTeacher && this.data.view === 'overview' && this.data.studentTab === 'group' && res.my_group) { return this.loadDetailForGroup(res.my_group); } }) .catch(() => { this.setData({ loading: false, refreshing: false }); wx.showToast({ title: '加载失败', icon: 'none' }); }); }, /** 打开小组详情 */ openGroup(e) { const groupName = e.currentTarget.dataset.group; if (!groupName) { return; } this.setData({ selectedGroupName: groupName, view: 'detail', members: [] }); this.loadDetail(); }, /** 学员直接查看自己小组(只有一个小组时点击卡片直接进) */ openMyGroup() { const groupName = this.data.myGroup; if (!groupName) { return; } this.setData({ selectedGroupName: groupName, view: 'detail', members: [] }); this.loadDetail(); }, /** 加载小组详情 */ loadDetail() { const type = TYPES[this.data.typeIndex]; return this.loadDetailForGroup(this.data.selectedGroupName, type); }, /** 加载指定小组的成员数据(不改变视图状态) */ loadDetailForGroup(groupName, type) { type = type || TYPES[this.data.typeIndex]; this.setData({ loading: true }); return api.request({ url: '/api/v1/plan/group', data: { type, group_name: groupName, period_key: this.data.periodKey } }).then((res) => { this.setData({ loading: false, periodKey: res.period_key || this.data.periodKey, canSubmit: !!res.can_submit, message: res.message || '', members: res.members || [] }); }).catch(() => { this.setData({ loading: false }); wx.showToast({ title: '加载成员失败', icon: 'none' }); }); }, /** 学员切换 tab */ switchStudentTab(e) { const tab = e.currentTarget.dataset.tab; if (tab !== 'group' && tab !== 'personal') return; this.setData({ studentTab: tab }); if (tab === 'personal') { // 每次切到个人 tab 都刷新历史数据 this.loadHistory(); } else if (tab === 'group' && this.data.myGroup) { // 每次切回小组 tab 都刷新小组成员数据 this.loadDetailForGroup(this.data.myGroup); } }, /** 加载个人计划历史 */ loadHistory() { const type = TYPES[this.data.typeIndex]; return api.request({ url: '/api/v1/plan/history', data: { type, page: 1, size: 20 } }).then((res) => { const history = (res.list || []).map((item) => ({ ...item, thumbs: (item.attachments || []).map((p) => api.planFileUrl(p)).slice(0, 3), statusColor: item.status === '未完成' ? '#C67B30' : '#2E7D32', statusBg: item.status === '未完成' ? '#FFF3E6' : '#E8F4EB', })); this.setData({ history }); }).catch(() => {}); }, /** 返回总览 */ backToOverview() { this.setData({ view: 'overview', selectedGroupName: '', members: [] }); this.loadOverview(); }, /** 预览我的图片 */ previewMyImage(e) { const index = Number(e.currentTarget.dataset.index); const urls = this.data.myThumbs; const src = urls[index]; if (!src) return; wx.previewImage({ current: src, urls }); }, /** 去提交计划 */ goSubmit() { const type = TYPES[this.data.typeIndex]; if (!this.data.canSubmit) { wx.showToast({ title: this.data.message || '当前不可提交', icon: 'none' }); return; } const params = [ 'plan_type=' + type, 'period_key=' + encodeURIComponent(this.data.periodKey), 'group_name=' ].join('&'); wx.navigateTo({ url: '/pages/plan-submit/plan-submit?' + params }); }, // ---- 分享 ---- onShareAppMessage() { const type = this.data.types[this.data.typeIndex]; const checked = this.data.myChecked; const title = checked ? '我的' + type + '已提交,来明缘云道场一起成长吧' : '明缘云道场 · ' + type + '管理工具'; return { title, path: '/pages/plan/plan' }; }, onShareTimeline() { return { title: '明缘云道场 · 周/月/年计划,让成长有迹可循', query: 'from=timeline' }; } });