const { post, uploadFile } = require("../../utils/api"); const { getModule } = require("../../utils/modules"); const { hasManagePermission } = require("../../utils/permissions"); const { ensureModuleOpen, getActiveClassId, showError } = require("../../utils/page-helpers"); const FORM_DEFAULTS = { announcements: { title: "", content: "", is_pinned: false }, votes: { title: "", description: "", options_text: "", vote_type: "single", is_anonymous: false }, schedule: { title: "", type: "course", start_time: "", end_time: "", location: "", description: "" }, fund: { type: "expense", amount: "", category: "", description: "", record_date: "" } }; Page({ data: { moduleKey: "", title: "新增", form: {}, isAnnouncements: false, isVotes: false, isSchedule: false, isFund: false, isScheduleDeadline: false, scheduleTimeLabel: "开始时间", isFundIncome: false, isFundExpense: true, fundIncomeClass: "", fundExpenseClass: "active expense", scheduleTypes: ["课程", "截止日", "活动"], scheduleTypeValues: ["course", "deadline", "activity"], scheduleTypeLabel: "课程", fundTypes: ["income", "expense"], fundTypeLabels: ["入账", "出账"], fundIncomeCategories: ["班费收取", "活动赞助", "其他收入"], fundExpenseCategories: ["聚餐", "活动物资", "场地费", "交通费", "礼品", "其他支出"], fundCategories: ["聚餐", "活动物资", "场地费", "交通费", "礼品", "其他支出"], fundImageUrls: [], uploadingImages: false, loading: false }, onLoad(options) { const moduleKey = options.module || ""; const module = getModule(moduleKey); const classId = getActiveClassId(); const user = getApp().globalData.user; if (!module || !ensureModuleOpen(moduleKey) || !hasManagePermission(user, classId, moduleKey)) { const unavailableTitle = module ? module.title : "功能"; wx.redirectTo({ url: `/pages/module-unavailable/index?title=${encodeURIComponent(unavailableTitle)}` }); return; } const form = Object.assign({}, FORM_DEFAULTS[moduleKey] || {}); if (moduleKey === "fund" && !form.record_date) { form.record_date = new Date().toISOString().slice(0, 10); } if (moduleKey === "fund" && !form.category) { form.category = form.type === "income" ? "班费收取" : "聚餐"; } this.setData({ moduleKey, title: `新增${module.title}`, form, isAnnouncements: moduleKey === "announcements", isVotes: moduleKey === "votes", isSchedule: moduleKey === "schedule", isScheduleDeadline: moduleKey === "schedule" && form.type === "deadline", scheduleTimeLabel: form.type === "deadline" ? "截止时间" : "开始时间", scheduleTypeLabel: moduleKey === "schedule" ? this.scheduleTypeText(form.type) : "课程", isFund: moduleKey === "fund", isFundIncome: form.type === "income", isFundExpense: form.type === "expense", fundIncomeClass: form.type === "income" ? "active income" : "", fundExpenseClass: form.type === "expense" ? "active expense" : "", fundCategories: form.type === "income" ? this.data.fundIncomeCategories : this.data.fundExpenseCategories, fundImageUrls: [] }); wx.setNavigationBarTitle({ title: `新增${module.title}` }); }, onInput(event) { const field = event.currentTarget.dataset.field; this.setData({ [`form.${field}`]: event.detail.value }); }, onSwitch(event) { const field = event.currentTarget.dataset.field; this.setData({ [`form.${field}`]: event.detail.value }); }, onPicker(event) { const field = event.currentTarget.dataset.field; const value = event.currentTarget.dataset.values.split(",")[Number(event.detail.value)]; const nextData = { [`form.${field}`]: value }; if (this.data.moduleKey === "schedule" && field === "type") { nextData.isScheduleDeadline = value === "deadline"; if (value === "deadline") { nextData["form.end_time"] = ""; } } this.setData(nextData); }, scheduleTypeText(type) { return { course: "课程", deadline: "截止日", activity: "活动" }[type] || type || "课程"; }, onScheduleTypeChange(event) { const index = Number(event.detail.value); const value = this.data.scheduleTypeValues[index]; const nextData = { "form.type": value, scheduleTypeLabel: this.scheduleTypeText(value), isScheduleDeadline: value === "deadline", scheduleTimeLabel: value === "deadline" ? "截止时间" : "开始时间" }; if (value === "deadline") { nextData["form.end_time"] = ""; } this.setData(nextData); }, setFundType(event) { const type = event.currentTarget.dataset.type; const categories = type === "income" ? this.data.fundIncomeCategories : this.data.fundExpenseCategories; this.setData({ "form.type": type, "form.category": categories[0], isFundIncome: type === "income", isFundExpense: type === "expense", fundIncomeClass: type === "income" ? "active income" : "", fundExpenseClass: type === "expense" ? "active expense" : "", fundCategories: categories }); }, onDateChange(event) { this.setData({ "form.record_date": event.detail.value }); }, onFundCategoryChange(event) { const index = Number(event.detail.value); this.setData({ "form.category": this.data.fundCategories[index] }); }, chooseFundImages() { if (this.data.uploadingImages) return; if (this.data.fundImageUrls.length >= 6) { wx.showToast({ title: "最多 6 张图片", icon: "none" }); return; } wx.chooseMedia({ count: 6 - this.data.fundImageUrls.length, mediaType: ["image"], sourceType: ["album", "camera"], success: async (res) => { const paths = (res.tempFiles || []).map((item) => item.tempFilePath); if (!paths.length) return; this.setData({ uploadingImages: true }); try { const uploaded = [...this.data.fundImageUrls]; for (const path of paths) { const result = await uploadFile("/api/upload/image", path, {}, "file"); if (result && result.url) uploaded.push(result.url); } this.setData({ fundImageUrls: uploaded.slice(0, 6) }); } catch (error) { showError(error, "上传图片失败"); } finally { this.setData({ uploadingImages: false }); } } }); }, removeFundImage(event) { const index = Number(event.currentTarget.dataset.index); this.setData({ fundImageUrls: this.data.fundImageUrls.filter((_, itemIndex) => itemIndex !== index) }); }, async submit() { const classId = getActiveClassId(); const moduleKey = this.data.moduleKey; const form = this.data.form; this.setData({ loading: true }); try { if (moduleKey === "announcements") { await post(`/api/announcements/?class_id=${classId}`, { title: form.title, content: form.content || null, is_pinned: Boolean(form.is_pinned) }); } if (moduleKey === "votes") { const options = String(form.options_text || "") .split("\n") .map((item) => item.trim()) .filter(Boolean); await post(`/api/votes/?class_id=${classId}`, { title: form.title, description: form.description || null, vote_type: form.vote_type || "single", is_anonymous: Boolean(form.is_anonymous), max_choices: form.vote_type === "multiple" ? Math.max(2, options.length) : 1, options }); } if (moduleKey === "schedule") { if (!form.title || !form.start_time) { wx.showToast({ title: "请填写标题和开始时间", icon: "none" }); return; } if (form.type !== "deadline" && !form.end_time) { wx.showToast({ title: "请填写结束时间", icon: "none" }); return; } if (form.end_time && new Date(form.end_time).getTime() <= new Date(form.start_time).getTime()) { wx.showToast({ title: "结束时间应晚于开始时间", icon: "none" }); return; } await post(`/api/schedule/?class_id=${classId}`, { title: form.title, type: form.type, start_time: form.start_time, end_time: form.end_time || null, location: form.location || null, description: form.description || null }); } if (moduleKey === "fund") { if (!form.amount || Number(form.amount) <= 0) { wx.showToast({ title: "请输入有效金额", icon: "none" }); return; } if (!form.category) { wx.showToast({ title: "请输入分类", icon: "none" }); return; } if (!form.record_date) { wx.showToast({ title: "请选择日期", icon: "none" }); return; } await post(`/api/fund/?class_id=${classId}`, { type: form.type, amount: Number(form.amount), category: form.category, description: form.description || null, image_urls: this.data.fundImageUrls, record_date: form.record_date }); } wx.showToast({ title: "已保存", icon: "success" }); setTimeout(() => wx.navigateBack(), 500); } catch (error) { showError(error, "保存失败"); } finally { this.setData({ loading: false }); } } });