Files
Vue/student-vol/vite.config.js
dichgrem c5ff55c726 fix:ID
2026-01-09 10:28:07 +08:00

381 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import VueDevTools from "vite-plugin-vue-devtools";
import fs from "fs";
import path from "path";
function mockPlugin() {
const mockDir = path.resolve(process.cwd(), "mock");
const filePath = (file) => path.resolve(mockDir, file);
const send = (res, obj, code = 200) => {
res.statusCode = code;
res.setHeader("Content-Type", "application/json; charset=utf-8");
res.end(JSON.stringify(obj));
};
const readJson = (file, fallback) => {
const p = filePath(file);
if (!fs.existsSync(p)) return fallback;
try {
return JSON.parse(fs.readFileSync(p, "utf-8") || "null") ?? fallback;
} catch {
return fallback;
}
};
const writeJson = (file, data) => {
const p = filePath(file);
fs.writeFileSync(p, JSON.stringify(data, null, 2), "utf-8");
};
const readBodyJson = (req) =>
new Promise((resolve, reject) => {
let body = "";
req.on("data", (c) => (body += c));
req.on("end", () => {
try {
resolve(JSON.parse(body || "{}"));
} catch (e) {
reject(e);
}
});
});
const getPathname = (req) => {
try {
return new URL(req.url, "http://localhost").pathname;
} catch {
return req.url;
}
};
// 统一 success
const ok = (res) => send(res, { error: 0, msg: "success" });
// ===== 业务联动:积分更新规则 =====
// yearScore: score=duration*2看起来是 1小时=2分
const POINTS_PER_HOUR = 2;
const addScore = (deltaHour) => {
const deltaScore = (Number(deltaHour) || 0) * POINTS_PER_HOUR;
// userInfo.json
const ui = readJson("userInfo.json", { error: 0, data: {} });
ui.data = ui.data || {};
ui.data.totalScore = (Number(ui.data.totalScore) || 0) + deltaScore;
writeJson("userInfo.json", ui);
// userScore.json
const us = readJson("userScore.json", { error: 0, data: {} });
us.data = us.data || {};
us.data.totalScore = (Number(us.data.totalScore) || 0) + deltaScore;
writeJson("userScore.json", us);
// scoreOverview.json
const ov = readJson("scoreOverview.json", { error: 0, data: {} });
ov.data = ov.data || {};
ov.data.totalScore = (Number(ov.data.totalScore) || 0) + deltaScore;
writeJson("scoreOverview.json", ov);
// yearScore.json
const ys = readJson("yearScore.json", { error: 0, data: {} });
ys.data = ys.data || {};
ys.data.times = (Number(ys.data.times) || 0) + 1;
ys.data.duration =
(Number(ys.data.duration) || 0) + (Number(deltaHour) || 0);
ys.data.score = (Number(ys.data.score) || 0) + deltaScore;
writeJson("yearScore.json", ys);
};
return {
name: "simple-mock-plugin",
configureServer(server) {
server.middlewares.use(async (req, res, next) => {
const pathname = getPathname(req);
// ========== GET仍然走你原来的静态文件 ==========
const sendJSON = (file) => {
const p = filePath(file);
if (!fs.existsSync(p)) {
return send(res, { error: `Mock file not found: ${file}` }, 404);
}
res.setHeader("Content-Type", "application/json; charset=utf-8");
res.end(fs.readFileSync(p, "utf-8"));
};
if (pathname === "/api/userInfo" && req.method === "GET")
return sendJSON("userInfo.json");
if (pathname.startsWith("/api/actList") && req.method === "GET")
return sendJSON("actList.json");
if (
pathname.startsWith("/api/report/myOverview") &&
req.method === "GET"
)
return sendJSON("scoreOverview.json");
if (pathname.startsWith("/api/report/rankList") && req.method === "GET")
return sendJSON("rank.json");
if (
pathname.startsWith("/api/actDetails/details") &&
req.method === "GET"
) {
const url = new URL(req.url, `http://${req.headers.host}`);
const id = Number(url.searchParams.get("id"));
if (!id) {
return send(res, { error: 1, msg: "missing id parameter" }, 400);
}
const actList = readJson("actList.json", {
error: 0,
data: { list: [] },
});
const act = (actList.data?.list || []).find((x) => Number(x.id) === id);
if (!act) {
return send(res, { error: 1, msg: "activity not found" }, 404);
}
const actDetails = readJson("actDetails.json", {
error: 0,
data: { details: {} },
});
const detailsTemplate = actDetails.data?.details || {};
const result = {
error: 0,
data: {
details: {
id: act.id,
title: act.title,
startTime: act.startTime,
endTime: act.endTime,
palce: act.palce,
content: detailsTemplate.content || "活动详情待补充",
publisher: detailsTemplate.publisher || "福州大学至诚学院团委",
hour: detailsTemplate.hour || 4,
total: detailsTemplate.total || 50,
canApply: act.canApply,
applyStatus: act.applyStatus || 0,
actPic: act.actPic
}
}
};
return send(res, result);
}
if (pathname.startsWith("/api/myApplyList") && req.method === "GET")
return sendJSON("myApplyList.json");
if (
pathname.startsWith("/api/act/publisherList") &&
req.method === "GET"
)
return sendJSON("publishers.json");
if (
pathname.startsWith("/api/act/durationsList") &&
req.method === "GET"
)
return sendJSON("durationList.json");
if (
pathname.startsWith("/api/service/userScore") &&
req.method === "GET"
)
return sendJSON("userScore.json");
if (
pathname.startsWith("/api/service/yearList") &&
req.method === "GET"
)
return sendJSON("yearList.json");
if (
pathname.startsWith("/api/service/yearScore") &&
req.method === "GET"
)
return sendJSON("yearScore.json");
if (pathname.startsWith("/api/service/list") && req.method === "GET") {
const sl = readJson("serviceList.json", {
error: 0,
data: { current: 1, pageSize: 10, pageCount: 1, list: [] },
});
const url = new URL(req.url, `http://${req.headers.host}`);
const year = url.searchParams.get("year");
let list = sl.data?.list || [];
if (year && year !== "all") {
const yearNum = Number(year);
list = list.filter((item) => {
const date = new Date(item.time);
return date.getFullYear() === yearNum;
});
}
const result = {
error: 0,
data: {
...sl.data,
list,
current: 1,
pageCount: 1,
},
};
return send(res, result);
}
if (pathname.startsWith("/api/service/details") && req.method === "GET")
return sendJSON("recordDetails.json");
// ========== POST全部改成“落盘” ==========
// 1) 用户信息保存
if (pathname === "/api/userInfo/submit" && req.method === "POST") {
try {
const incoming = await readBodyJson(req); // {name,code,gender,phoneNum,school,profession,userType...}
const old = readJson("userInfo.json", { error: 0, data: {} });
const next = {
error: 0,
data: { ...(old.data || {}), ...incoming },
};
writeJson("userInfo.json", next);
return ok(res);
} catch {
return send(res, { error: 1, msg: "Invalid JSON body" }, 400);
}
}
// 2) 申请/撤销活动:更新 myApplyList + actDetails(可选 actList)
if (
pathname.startsWith("/api/actDetails/apply") &&
req.method === "POST"
) {
try {
const incoming = await readBodyJson(req);
// 约定:至少要有 id可选传 action: "apply" | "cancel"
const id = Number(incoming.id ?? incoming.actId);
const action = incoming.action || "apply";
if (!id) return send(res, { error: 1, msg: "missing id" }, 400);
// 读活动列表,用来补齐标题/时间/地点等字段
const actList = readJson("actList.json", {
error: 0,
data: { list: [] },
});
const act = (actList.data?.list || []).find(
(x) => Number(x.id) === id,
);
// myApplyList.json
const applyJson = readJson("myApplyList.json", {
error: 0,
data: { current: 1, pageSize: 10, pageCount: 1, list: [] },
});
const list = applyJson.data?.list || [];
const existsIdx = list.findIndex((x) => Number(x.id) === id);
if (action === "cancel") {
if (existsIdx >= 0) list.splice(existsIdx, 1);
} else {
// apply
if (existsIdx < 0) {
// 申请状态:你的 mock 里 1/2 出现过。这里用 1 表示已申请
list.unshift({ ...(act || { id }), applyStatus: 1 });
} else {
list[existsIdx].applyStatus = 1;
}
}
applyJson.data = applyJson.data || {};
applyJson.data.list = list;
applyJson.data.pageCount = 1;
writeJson("myApplyList.json", applyJson);
// actDetails.json让详情页刷新后看到申请状态变化
const detailsJson = readJson("actDetails.json", {
error: 0,
data: { details: {} },
});
if (
detailsJson.data?.details &&
Number(detailsJson.data.details.id) === id
) {
if (action === "cancel") {
detailsJson.data.details.applyStatus = 0;
detailsJson.data.details.canApply = true;
} else {
detailsJson.data.details.applyStatus = 1;
detailsJson.data.details.canApply = false;
}
writeJson("actDetails.json", detailsJson);
}
// actList.json可选列表 canApply 同步变化
if (act) {
const idx = (actList.data?.list || []).findIndex(
(x) => Number(x.id) === id,
);
if (idx >= 0) {
actList.data.list[idx].canApply = action === "cancel";
writeJson("actList.json", actList);
}
}
return ok(res);
} catch {
return send(res, { error: 1, msg: "Invalid JSON body" }, 400);
}
}
// 3) 上传服务记录:写 serviceList + 联动积分文件
if (
pathname.startsWith("/api/act/uploadService") &&
req.method === "POST"
) {
try {
const incoming = await readBodyJson(req);
// 约定:时长字段可能叫 hour / duration / value
const hour =
Number(
incoming.hour ?? incoming.duration ?? incoming.value ?? 0,
) || 0;
// serviceList.json 结构:{data:{list:[{id,pic,content,publisher,time,status}]}}
const sl = readJson("serviceList.json", {
error: 0,
data: { current: 1, pageSize: 10, pageCount: 1, list: [] },
});
const list = sl.data?.list || [];
const nextId =
list.reduce((m, x) => Math.max(m, Number(x.id) || 0), 0) + 1;
list.unshift({
id: nextId,
pic: incoming.pic || "./imgs/actImg.jpeg",
content: incoming.content || "新增服务记录",
publisher: incoming.publisher || "未知来源",
time: incoming.time || Date.now(),
status: 1, // 1=通过?你 recordDetails.status=1看起来是已审核/有效
// 额外字段可保留(不影响页面)
hour,
});
sl.data = sl.data || {};
sl.data.list = list;
sl.data.pageCount = 1;
writeJson("serviceList.json", sl);
// 同步更新积分(按 1小时=2分
if (hour > 0) addScore(hour);
return ok(res);
} catch {
return send(res, { error: 1, msg: "Invalid JSON body" }, 400);
}
}
next();
});
},
};
}
export default defineConfig({
base: "./",
plugins: [vue(), mockPlugin(), VueDevTools()],
});