244 lines
7.5 KiB
JavaScript
244 lines
7.5 KiB
JavaScript
const { del, get, put, uploadFile } = require("../../utils/api");
|
|
const { hasManagePermission } = require("../../utils/permissions");
|
|
const { showError } = require("../../utils/page-helpers");
|
|
|
|
const FUND_INCOME_CATEGORIES = ["班费收取", "活动赞助", "其他收入"];
|
|
const FUND_EXPENSE_CATEGORIES = ["聚餐", "活动物资", "场地费", "交通费", "礼品", "其他支出"];
|
|
|
|
function formatAmount(value) {
|
|
return Number(value || 0).toFixed(2);
|
|
}
|
|
|
|
function formatDateTime(value) {
|
|
if (!value) return "";
|
|
return String(value).replace("T", " ").slice(0, 16);
|
|
}
|
|
|
|
function normalizeRecord(record) {
|
|
const isIncome = record.type === "income";
|
|
const imageUrls = Array.isArray(record.image_urls) ? record.image_urls : [];
|
|
return {
|
|
...record,
|
|
amount_text: formatAmount(record.amount),
|
|
signed_amount_text: `${isIncome ? "+" : "-"}¥${formatAmount(record.amount)}`,
|
|
type_text: isIncome ? "收入" : "支出",
|
|
type_class: isIncome ? "income" : "expense",
|
|
image_urls: imageUrls,
|
|
image_count_text: imageUrls.length ? `${imageUrls.length} 张凭证` : "未上传凭证",
|
|
created_at_text: formatDateTime(record.created_at),
|
|
updated_at_text: formatDateTime(record.updated_at)
|
|
};
|
|
}
|
|
|
|
Page({
|
|
data: {
|
|
id: null,
|
|
record: null,
|
|
canManage: false,
|
|
editOpen: false,
|
|
editForm: {},
|
|
editImageUrls: [],
|
|
editCategories: FUND_EXPENSE_CATEGORIES,
|
|
editIncomeClass: "",
|
|
editExpenseClass: "active expense",
|
|
loading: false,
|
|
saving: false,
|
|
deleting: false,
|
|
uploadingImages: false
|
|
},
|
|
|
|
onLoad(options) {
|
|
wx.setNavigationBarTitle({ title: "班费详情" });
|
|
this.setData({ id: options.id || null });
|
|
this.load(options.id);
|
|
},
|
|
|
|
async onPullDownRefresh() {
|
|
await this.load(this.data.id);
|
|
wx.stopPullDownRefresh();
|
|
},
|
|
|
|
async load(id) {
|
|
if (!id) return;
|
|
this.setData({ loading: true });
|
|
try {
|
|
const record = await get(`/api/fund/${id}`);
|
|
const user = getApp().globalData.user || wx.getStorageSync("auth_user");
|
|
const canManage = hasManagePermission(user, record.class_id, "fund");
|
|
this.setData({ record: normalizeRecord(record), canManage });
|
|
} catch (error) {
|
|
showError(error, "加载班费详情失败");
|
|
} finally {
|
|
this.setData({ loading: false });
|
|
}
|
|
},
|
|
|
|
previewImage(event) {
|
|
const current = event.currentTarget.dataset.src;
|
|
const urls = this.data.record && this.data.record.image_urls ? this.data.record.image_urls : [];
|
|
if (!current || !urls.length) return;
|
|
wx.previewImage({ current, urls });
|
|
},
|
|
|
|
noop() {},
|
|
|
|
openEdit() {
|
|
const record = this.data.record;
|
|
if (!record || !this.data.canManage) return;
|
|
const categories = record.type === "income" ? FUND_INCOME_CATEGORIES : FUND_EXPENSE_CATEGORIES;
|
|
this.setData({
|
|
editOpen: true,
|
|
editForm: {
|
|
type: record.type,
|
|
amount: String(record.amount || ""),
|
|
category: record.category || categories[0],
|
|
description: record.description || "",
|
|
record_date: record.record_date || ""
|
|
},
|
|
editImageUrls: [...record.image_urls],
|
|
editCategories: categories,
|
|
editIncomeClass: record.type === "income" ? "active income" : "",
|
|
editExpenseClass: record.type === "expense" ? "active expense" : ""
|
|
});
|
|
},
|
|
|
|
closeEdit() {
|
|
if (this.data.saving || this.data.uploadingImages) return;
|
|
this.setData({ editOpen: false });
|
|
},
|
|
|
|
onEditInput(event) {
|
|
const field = event.currentTarget.dataset.field;
|
|
this.setData({ [`editForm.${field}`]: event.detail.value });
|
|
},
|
|
|
|
setEditFundType(event) {
|
|
const type = event.currentTarget.dataset.type;
|
|
const categories = type === "income" ? FUND_INCOME_CATEGORIES : FUND_EXPENSE_CATEGORIES;
|
|
this.setData({
|
|
"editForm.type": type,
|
|
"editForm.category": categories[0],
|
|
editCategories: categories,
|
|
editIncomeClass: type === "income" ? "active income" : "",
|
|
editExpenseClass: type === "expense" ? "active expense" : ""
|
|
});
|
|
},
|
|
|
|
onEditCategoryChange(event) {
|
|
const index = Number(event.detail.value);
|
|
this.setData({ "editForm.category": this.data.editCategories[index] });
|
|
},
|
|
|
|
onEditDateChange(event) {
|
|
this.setData({ "editForm.record_date": event.detail.value });
|
|
},
|
|
|
|
chooseEditImages() {
|
|
if (this.data.uploadingImages) return;
|
|
if (this.data.editImageUrls.length >= 6) {
|
|
wx.showToast({ title: "最多 6 张图片", icon: "none" });
|
|
return;
|
|
}
|
|
wx.chooseMedia({
|
|
count: 6 - this.data.editImageUrls.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.editImageUrls];
|
|
for (const path of paths) {
|
|
const result = await uploadFile("/api/upload/image", path, {}, "file");
|
|
if (result && result.url) uploaded.push(result.url);
|
|
}
|
|
this.setData({ editImageUrls: uploaded.slice(0, 6) });
|
|
} catch (error) {
|
|
showError(error, "上传图片失败");
|
|
} finally {
|
|
this.setData({ uploadingImages: false });
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
removeEditImage(event) {
|
|
const index = Number(event.currentTarget.dataset.index);
|
|
this.setData({
|
|
editImageUrls: this.data.editImageUrls.filter((_, itemIndex) => itemIndex !== index)
|
|
});
|
|
},
|
|
|
|
async saveEdit() {
|
|
if (this.data.saving || this.data.uploadingImages) return;
|
|
const form = this.data.editForm;
|
|
const amount = Number(form.amount);
|
|
if (!amount || 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;
|
|
}
|
|
this.setData({ saving: true });
|
|
try {
|
|
const updated = await put(`/api/fund/${this.data.id}`, {
|
|
type: form.type,
|
|
amount,
|
|
category: form.category,
|
|
description: form.description || null,
|
|
image_urls: this.data.editImageUrls,
|
|
record_date: form.record_date
|
|
});
|
|
this.setData({
|
|
record: normalizeRecord(updated),
|
|
editOpen: false
|
|
});
|
|
this.refreshPreviousPage();
|
|
wx.showToast({ title: "已更新", icon: "success" });
|
|
} catch (error) {
|
|
showError(error, "保存失败");
|
|
} finally {
|
|
this.setData({ saving: false });
|
|
}
|
|
},
|
|
|
|
deleteRecord() {
|
|
if (this.data.deleting || !this.data.canManage || !this.data.record) return;
|
|
wx.showModal({
|
|
title: "删除班费记录",
|
|
content: "删除后无法恢复,确认删除这条班费记录?",
|
|
confirmText: "删除",
|
|
confirmColor: "#b42318",
|
|
success: async (res) => {
|
|
if (!res.confirm) return;
|
|
this.setData({ deleting: true });
|
|
try {
|
|
await del(`/api/fund/${this.data.id}`);
|
|
this.refreshPreviousPage();
|
|
wx.showToast({ title: "已删除", icon: "success" });
|
|
setTimeout(() => wx.navigateBack(), 500);
|
|
} catch (error) {
|
|
showError(error, "删除失败");
|
|
} finally {
|
|
this.setData({ deleting: false });
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
refreshPreviousPage() {
|
|
const pages = getCurrentPages();
|
|
const previousPage = pages[pages.length - 2];
|
|
if (previousPage && previousPage.load) {
|
|
previousPage.load();
|
|
}
|
|
}
|
|
});
|