mirror of
https://github.com/Dichgrem/Vue.git
synced 2026-02-05 03:01:57 -05:00
fix:save_to_json
This commit is contained in:
@@ -32,7 +32,7 @@
|
||||
"endTime": 1672099200000,
|
||||
"palce": "福州市养老院",
|
||||
"isYourSchool": false,
|
||||
"canApply": true,
|
||||
"canApply": false,
|
||||
"actPic": "./imgs/actImg.jpeg"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -5,6 +5,17 @@
|
||||
"pageSize": 10,
|
||||
"pageCount": 1,
|
||||
"list": [
|
||||
{
|
||||
"id": 3,
|
||||
"title": "社区敬老院服务",
|
||||
"startTime": 1672012800000,
|
||||
"endTime": 1672099200000,
|
||||
"palce": "福州市养老院",
|
||||
"isYourSchool": false,
|
||||
"canApply": true,
|
||||
"actPic": "./imgs/actImg.jpeg",
|
||||
"applyStatus": 1
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"title": "运动会志愿者招募",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"error": 0,
|
||||
"data": {
|
||||
"provinceRank": 156,
|
||||
"totalScore": 128,
|
||||
"totalScore": 132,
|
||||
"grandeRank": 8
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,15 @@
|
||||
"pageSize": 10,
|
||||
"pageCount": 1,
|
||||
"list": [
|
||||
{
|
||||
"id": 4,
|
||||
"pic": "./imgs/actImg.jpeg",
|
||||
"content": "666",
|
||||
"publisher": "未知来源",
|
||||
"time": 1766717931972,
|
||||
"status": 1,
|
||||
"hour": 2
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"pic": "./imgs/actImg.jpeg",
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
"error": 0,
|
||||
"data": {
|
||||
"avatar": "./imgs/avatar.png",
|
||||
"name": "李华",
|
||||
"code": 12343434,
|
||||
"name": "666",
|
||||
"code": 114514,
|
||||
"gender": 0,
|
||||
"phoneNum": "18787698789",
|
||||
"phoneNum": "1919810",
|
||||
"school": "福州大学至诚学院",
|
||||
"profession": "软件工程",
|
||||
"userType": 0,
|
||||
"totalScore": 128
|
||||
"profession": "计算机",
|
||||
"userType": 2,
|
||||
"totalScore": 132
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,6 @@
|
||||
"data": {
|
||||
"avatar": "./imgs/avatar.png",
|
||||
"name": "李华",
|
||||
"totalScore": 128
|
||||
"totalScore": 132
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"error": 0,
|
||||
"data": {
|
||||
"times": 12,
|
||||
"duration": 48,
|
||||
"score": 96
|
||||
"times": 13,
|
||||
"duration": 50,
|
||||
"score": 100
|
||||
}
|
||||
}
|
||||
@@ -1,60 +1,58 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<div class="inner">
|
||||
<h1>个人信息</h1>
|
||||
<ul>
|
||||
<li>
|
||||
<p class="label"><span>*</span>姓名</p>
|
||||
<span class="txt">{{ name }}</span>
|
||||
</li>
|
||||
<li>
|
||||
<p class="label"><span>*</span>编号</p>
|
||||
<span class="txt">{{ code }}</span>
|
||||
</li>
|
||||
<li>
|
||||
<p class="label"><span>*</span>性别</p>
|
||||
<input type="radio" value="0" v-model="gender" />男
|
||||
<input type="radio" value="1" v-model="gender" />女
|
||||
</li>
|
||||
<li>
|
||||
<p class="label"><span>*</span>手机号</p>
|
||||
<input placeholder="请输入手机号" v-model.trim="phoneNum" />
|
||||
</li>
|
||||
<li>
|
||||
<p class="label"><span>*</span>学校</p>
|
||||
<input placeholder="请输入学校名称" v-model.trim="school" />
|
||||
</li>
|
||||
<li>
|
||||
<p class="label"><span>*</span>专业</p>
|
||||
<input
|
||||
placeholder="请输入专业名称"
|
||||
v-model.trim="profession"
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<p class="label"><span>*</span>人员属性</p>
|
||||
<div class="userTypeList">
|
||||
<span
|
||||
:class="{ active: userType === 0 }"
|
||||
@click="changeUserType(0)"
|
||||
>群众</span
|
||||
>
|
||||
<span
|
||||
:class="{ active: userType === 1 }"
|
||||
@click="changeUserType(1)"
|
||||
>团员</span
|
||||
>
|
||||
<span
|
||||
:class="{ active: userType === 2 }"
|
||||
@click="changeUserType(2)"
|
||||
>党员</span
|
||||
>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<button class="subBtn" @click="submitClick">提交</button>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="inner">
|
||||
<h1>个人信息</h1>
|
||||
<ul>
|
||||
<li>
|
||||
<p class="label"><span>*</span>姓名</p>
|
||||
<input placeholder="请输入姓名" v-model.trim="name" />
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<p class="label"><span>*</span>编号</p>
|
||||
<input placeholder="请输入编号" v-model.trim="codeStr" />
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<p class="label"><span>*</span>性别</p>
|
||||
<input type="radio" value="0" v-model="gender" />男
|
||||
<input type="radio" value="1" v-model="gender" />女
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<p class="label"><span>*</span>手机号</p>
|
||||
<input placeholder="请输入手机号" v-model.trim="phoneNum" />
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<p class="label"><span>*</span>学校</p>
|
||||
<input placeholder="请输入学校名称" v-model.trim="school" />
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<p class="label"><span>*</span>专业</p>
|
||||
<input placeholder="请输入专业名称" v-model.trim="profession" />
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<p class="label"><span>*</span>人员属性</p>
|
||||
<div class="userTypeList">
|
||||
<span :class="{ active: userType === 0 }" @click="changeUserType(0)">群众</span>
|
||||
<span :class="{ active: userType === 1 }" @click="changeUserType(1)">团员</span>
|
||||
<span :class="{ active: userType === 2 }" @click="changeUserType(2)">党员</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<button class="subBtn" :disabled="saving" @click="submitClick">
|
||||
{{ saving ? "保存中..." : "保存" }}
|
||||
</button>
|
||||
|
||||
<button class="subBtn subBtn-ghost" :disabled="saving" @click="resetClick">
|
||||
取消修改
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -62,181 +60,252 @@ import axios from "axios";
|
||||
import { showToast, showSuccessToast, showFailToast } from "vant";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
name: "",
|
||||
code: null,
|
||||
gender: 0,
|
||||
phoneNum: "",
|
||||
school: "",
|
||||
profession: "",
|
||||
userType: 0,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
changeUserType(value) {
|
||||
this.userType = value;
|
||||
},
|
||||
fetchUsrInfo() {
|
||||
const that = this;
|
||||
axios.get("/api/userInfo").then(function (response) {
|
||||
const { error, data = {} } = response.data;
|
||||
if (error === 0) {
|
||||
that.name = data.name;
|
||||
that.code = data.code;
|
||||
that.gender = data.gender;
|
||||
that.phoneNum = data.phoneNum;
|
||||
that.school = data.school;
|
||||
that.profession = data.profession;
|
||||
that.userType = data.userType;
|
||||
}
|
||||
});
|
||||
},
|
||||
check() {
|
||||
var phoneNum = this.phoneNum;
|
||||
var school = this.school;
|
||||
var profession = this.profession;
|
||||
data() {
|
||||
return {
|
||||
name: "",
|
||||
code: null,
|
||||
codeStr: "",
|
||||
|
||||
if (phoneNum === "") {
|
||||
showToast("手机号不可为空");
|
||||
return;
|
||||
}
|
||||
if (school === "") {
|
||||
showToast("学校不可为空");
|
||||
return;
|
||||
}
|
||||
if (profession === "") {
|
||||
showToast("专业不可为空");
|
||||
return;
|
||||
}
|
||||
gender: "0",
|
||||
phoneNum: "",
|
||||
school: "",
|
||||
profession: "",
|
||||
userType: 0,
|
||||
|
||||
const payload = {
|
||||
name: this.name,
|
||||
code: this.code,
|
||||
gender: this.gender,
|
||||
phoneNum,
|
||||
school,
|
||||
profession,
|
||||
userType: this.userType,
|
||||
};
|
||||
return payload;
|
||||
},
|
||||
submitClick() {
|
||||
var payload = this.check();
|
||||
if (!payload) {
|
||||
return;
|
||||
}
|
||||
saving: false,
|
||||
original: null,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
changeUserType(value) {
|
||||
this.userType = value;
|
||||
},
|
||||
|
||||
axios
|
||||
.post("/api/userInfo/submit", payload)
|
||||
.then(function (response) {
|
||||
const { error, msg } = response.data;
|
||||
if (error === 0) {
|
||||
showSuccessToast("操作成功");
|
||||
} else {
|
||||
showFailToast(msg || "网络错误,请稍后重试");
|
||||
}
|
||||
});
|
||||
},
|
||||
snapshot() {
|
||||
return {
|
||||
name: this.name,
|
||||
code: this.code,
|
||||
codeStr: this.codeStr,
|
||||
gender: this.gender,
|
||||
phoneNum: this.phoneNum,
|
||||
school: this.school,
|
||||
profession: this.profession,
|
||||
userType: this.userType,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.fetchUsrInfo();
|
||||
|
||||
applyData(data = {}) {
|
||||
this.name = data.name ?? "";
|
||||
this.code = data.code ?? null;
|
||||
this.codeStr = data.code != null ? String(data.code) : "";
|
||||
|
||||
this.gender = data.gender != null ? String(data.gender) : "0";
|
||||
|
||||
this.phoneNum = data.phoneNum ?? "";
|
||||
this.school = data.school ?? "";
|
||||
this.profession = data.profession ?? "";
|
||||
this.userType = data.userType ?? 0;
|
||||
},
|
||||
|
||||
fetchUsrInfo() {
|
||||
axios
|
||||
.get("/api/userInfo")
|
||||
.then((response) => {
|
||||
const { error, data = {}, msg } = response.data || {};
|
||||
if (error === 0) {
|
||||
this.applyData(data);
|
||||
this.original = this.snapshot();
|
||||
} else {
|
||||
showFailToast(msg || "获取用户信息失败");
|
||||
}
|
||||
})
|
||||
.catch(() => showFailToast("网络错误,请稍后重试"));
|
||||
},
|
||||
|
||||
check() {
|
||||
const name = this.name.trim();
|
||||
const codeStr = this.codeStr.trim();
|
||||
const phoneNum = this.phoneNum.trim();
|
||||
const school = this.school.trim();
|
||||
const profession = this.profession.trim();
|
||||
|
||||
if (!name) {
|
||||
showToast("姓名不可为空");
|
||||
return;
|
||||
}
|
||||
if (!codeStr) {
|
||||
showToast("编号不可为空");
|
||||
return;
|
||||
}
|
||||
if (!phoneNum) {
|
||||
showToast("手机号不可为空");
|
||||
return;
|
||||
}
|
||||
if (!school) {
|
||||
showToast("学校不可为空");
|
||||
return;
|
||||
}
|
||||
if (!profession) {
|
||||
showToast("专业不可为空");
|
||||
return;
|
||||
}
|
||||
|
||||
const codeNum = Number(codeStr);
|
||||
const code = Number.isFinite(codeNum) ? codeNum : codeStr;
|
||||
|
||||
const payload = {
|
||||
name,
|
||||
code,
|
||||
gender: Number(this.gender),
|
||||
phoneNum,
|
||||
school,
|
||||
profession,
|
||||
userType: this.userType,
|
||||
};
|
||||
return payload;
|
||||
},
|
||||
|
||||
submitClick() {
|
||||
const payload = this.check();
|
||||
if (!payload) return;
|
||||
if (this.saving) return;
|
||||
|
||||
this.saving = true;
|
||||
axios
|
||||
.post("/api/userInfo/submit", payload)
|
||||
.then((response) => {
|
||||
const { error, msg } = response.data || {};
|
||||
if (error === 0) {
|
||||
showSuccessToast("保存成功");
|
||||
this.original = this.snapshot();
|
||||
} else {
|
||||
showFailToast(msg || "网络错误,请稍后重试");
|
||||
}
|
||||
})
|
||||
.catch(() => showFailToast("网络错误,请稍后重试"))
|
||||
.finally(() => {
|
||||
this.saving = false;
|
||||
});
|
||||
},
|
||||
|
||||
resetClick() {
|
||||
if (!this.original) return;
|
||||
this.name = this.original.name;
|
||||
this.code = this.original.code;
|
||||
this.codeStr = this.original.codeStr;
|
||||
this.gender = this.original.gender;
|
||||
this.phoneNum = this.original.phoneNum;
|
||||
this.school = this.original.school;
|
||||
this.profession = this.original.profession;
|
||||
this.userType = this.original.userType;
|
||||
showToast("已还原");
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.fetchUsrInfo();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.inner {
|
||||
padding: 20px;
|
||||
background: white;
|
||||
color: #333;
|
||||
padding: 20px;
|
||||
background: white;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
padding: 15px 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
color: #333;
|
||||
padding: 15px 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.label span {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt {
|
||||
color: #666;
|
||||
color: red;
|
||||
}
|
||||
|
||||
li input:not([type="radio"]) {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
margin-top: 5px;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
margin-top: 5px;
|
||||
box-sizing: border-box;
|
||||
|
||||
color: #333;
|
||||
background-color: #fff;
|
||||
color: #333;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
li input:not([type="radio"])::placeholder {
|
||||
color: #999;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
input[type="radio"] {
|
||||
margin-right: 6px;
|
||||
margin-left: 10px;
|
||||
margin-right: 6px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
input[type="radio"]:first-of-type {
|
||||
margin-left: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.userTypeList {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.userTypeList span {
|
||||
padding: 8px 20px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
color: #333;
|
||||
padding: 8px 20px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.userTypeList span.active {
|
||||
background: #ff5d23;
|
||||
color: white;
|
||||
border-color: #ff5d23;
|
||||
background: #ff5d23;
|
||||
color: white;
|
||||
border-color: #ff5d23;
|
||||
}
|
||||
|
||||
.subBtn {
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
background: #ff5d23;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
font-size: 16px;
|
||||
margin-top: 20px;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
background: #ff5d23;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
font-size: 16px;
|
||||
margin-top: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.subBtn:disabled {
|
||||
opacity: 0.7;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.subBtn-ghost {
|
||||
background: transparent;
|
||||
color: #333;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -5,137 +5,299 @@ 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((req, res, next) => {
|
||||
server.middlewares.use(async (req, res, next) => {
|
||||
const pathname = getPathname(req);
|
||||
|
||||
// ========== GET:仍然走你原来的静态文件 ==========
|
||||
const sendJSON = (file) => {
|
||||
const filePath = path.resolve(process.cwd(), `mock/${file}`);
|
||||
if (!fs.existsSync(filePath)) {
|
||||
res.statusCode = 404;
|
||||
res.setHeader("Content-Type", "application/json");
|
||||
return res.end(
|
||||
JSON.stringify({
|
||||
error: `Mock file not found: ${file}`,
|
||||
}),
|
||||
);
|
||||
const p = filePath(file);
|
||||
if (!fs.existsSync(p)) {
|
||||
return send(res, { error: `Mock file not found: ${file}` }, 404);
|
||||
}
|
||||
const json = fs.readFileSync(filePath, "utf-8");
|
||||
res.setHeader("Content-Type", "application/json");
|
||||
res.end(json);
|
||||
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
||||
res.end(fs.readFileSync(p, "utf-8"));
|
||||
};
|
||||
|
||||
// 用户信息
|
||||
if (req.url === "/api/userInfo" && req.method === "GET") {
|
||||
if (pathname === "/api/userInfo" && req.method === "GET")
|
||||
return sendJSON("userInfo.json");
|
||||
}
|
||||
|
||||
// 提交用户信息
|
||||
if (req.url === "/api/userInfo/submit" && req.method === "POST") {
|
||||
return sendJSON("success.json");
|
||||
}
|
||||
|
||||
// 活动列表
|
||||
if (req.url.startsWith("/api/actList") && req.method === "GET") {
|
||||
if (pathname.startsWith("/api/actList") && req.method === "GET")
|
||||
return sendJSON("actList.json");
|
||||
}
|
||||
|
||||
// 积分概览
|
||||
if (
|
||||
req.url.startsWith("/api/report/myOverview") &&
|
||||
pathname.startsWith("/api/report/myOverview") &&
|
||||
req.method === "GET"
|
||||
) {
|
||||
)
|
||||
return sendJSON("scoreOverview.json");
|
||||
}
|
||||
|
||||
// 排名列表
|
||||
if (
|
||||
req.url.startsWith("/api/report/rankList") &&
|
||||
req.method === "GET"
|
||||
) {
|
||||
if (pathname.startsWith("/api/report/rankList") && req.method === "GET")
|
||||
return sendJSON("rank.json");
|
||||
}
|
||||
|
||||
// 活动详情
|
||||
if (
|
||||
req.url.startsWith("/api/actDetails/details") &&
|
||||
pathname.startsWith("/api/actDetails/details") &&
|
||||
req.method === "GET"
|
||||
) {
|
||||
)
|
||||
return sendJSON("actDetails.json");
|
||||
}
|
||||
|
||||
// 申请/撤销活动
|
||||
if (
|
||||
req.url.startsWith("/api/actDetails/apply") &&
|
||||
req.method === "POST"
|
||||
) {
|
||||
return sendJSON("success.json");
|
||||
}
|
||||
|
||||
// 我的报名列表
|
||||
if (req.url.startsWith("/api/myApplyList") && req.method === "GET") {
|
||||
if (pathname.startsWith("/api/myApplyList") && req.method === "GET")
|
||||
return sendJSON("myApplyList.json");
|
||||
}
|
||||
|
||||
// 活动来源列表
|
||||
if (
|
||||
req.url.startsWith("/api/act/publisherList") &&
|
||||
pathname.startsWith("/api/act/publisherList") &&
|
||||
req.method === "GET"
|
||||
) {
|
||||
)
|
||||
return sendJSON("publishers.json");
|
||||
}
|
||||
|
||||
// 服务时长列表
|
||||
if (
|
||||
req.url.startsWith("/api/act/durationsList") &&
|
||||
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")
|
||||
return sendJSON("serviceList.json");
|
||||
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 (
|
||||
req.url.startsWith("/api/act/uploadService") &&
|
||||
pathname.startsWith("/api/actDetails/apply") &&
|
||||
req.method === "POST"
|
||||
) {
|
||||
return sendJSON("success.json");
|
||||
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 (
|
||||
req.url.startsWith("/api/service/userScore") &&
|
||||
req.method === "GET"
|
||||
pathname.startsWith("/api/act/uploadService") &&
|
||||
req.method === "POST"
|
||||
) {
|
||||
return sendJSON("userScore.json");
|
||||
}
|
||||
try {
|
||||
const incoming = await readBodyJson(req);
|
||||
// 约定:时长字段可能叫 hour / duration / value
|
||||
const hour =
|
||||
Number(
|
||||
incoming.hour ?? incoming.duration ?? incoming.value ?? 0,
|
||||
) || 0;
|
||||
|
||||
// 年份列表
|
||||
if (
|
||||
req.url.startsWith("/api/service/yearList") &&
|
||||
req.method === "GET"
|
||||
) {
|
||||
return sendJSON("yearList.json");
|
||||
}
|
||||
// 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 || [];
|
||||
|
||||
// 年度积分
|
||||
if (
|
||||
req.url.startsWith("/api/service/yearScore") &&
|
||||
req.method === "GET"
|
||||
) {
|
||||
return sendJSON("yearScore.json");
|
||||
}
|
||||
const nextId =
|
||||
list.reduce((m, x) => Math.max(m, Number(x.id) || 0), 0) + 1;
|
||||
|
||||
// 服务记录列表
|
||||
if (req.url.startsWith("/api/service/list") && req.method === "GET") {
|
||||
return sendJSON("serviceList.json");
|
||||
}
|
||||
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,
|
||||
});
|
||||
|
||||
// 服务详情
|
||||
if (
|
||||
req.url.startsWith("/api/service/details") &&
|
||||
req.method === "GET"
|
||||
) {
|
||||
return sendJSON("recordDetails.json");
|
||||
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();
|
||||
@@ -145,10 +307,6 @@ function mockPlugin() {
|
||||
}
|
||||
|
||||
export default defineConfig({
|
||||
base: './',
|
||||
plugins: [
|
||||
vue(),
|
||||
mockPlugin(),
|
||||
VueDevTools(),
|
||||
],
|
||||
})
|
||||
base: "./",
|
||||
plugins: [vue(), mockPlugin(), VueDevTools()],
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user