update:student-vol

This commit is contained in:
dichgrem
2025-12-25 17:02:20 +08:00
parent 57679a4d0b
commit d076ee1d3a
38 changed files with 2361 additions and 971 deletions

BIN
student-vol/11.pdf Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -17,6 +17,8 @@
}, },
"devDependencies": { "devDependencies": {
"@vitejs/plugin-vue": "^6.0.1", "@vitejs/plugin-vue": "^6.0.1",
"vite": "^7.2.4" "vite": "^7.2.4",
"vite-plugin-vue-devtools": "^8.0.5",
"vite-plugin-vue-inspector": "^5.3.2"
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -20,7 +20,7 @@ body {
background-color: #f5f5f5; background-color: #f5f5f5;
} }
.container { #app > .container {
min-height: 100vh; min-height: 100vh;
padding-bottom: 20px; padding-bottom: 20px;
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 785 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 889 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 711 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 649 B

View File

@@ -1,90 +1,94 @@
<template> <template>
<div class="actItem" @click="detailsClick(data.id)"> <div class="actItem" @click="detailsClick(data.id)">
<div class="actItem-pic"> <div class="actItem-pic">
<img :src="data.actPic"/> <img :src="data.actPic" />
<span class="actItemStatus" :style="getTagStyle(data)"> <span class="actItemStatus" :style="getTagStyle(data)">
{{ getTagTxt(data) }} {{ getTagTxt(data) }}
</span> </span>
</div>
<div class="actItem-body">
<p class="actItem-title">{{ data.title }}</p>
<p>
{{ formatDate(data.startTime) }}
{{ formatDate(data.endTime) }}
</p>
<p class="actItem-tag">
{{ data.isYourSchool ? "本人所在学校活动" : data.palce }}
</p>
</div>
</div> </div>
<div class="actItem-body">
<p class="actItem-title">{{ data.title }}</p>
<p>{{ formatDate(data.startTime) }} {{ formatDate(data.endTime) }}</p>
<p class="actItem-tag">
{{ data.isYourSchool ? "本人所在学校活动" : data.palce }}
</p>
</div>
</div>
</template> </template>
<script> <script>
import moment from "moment"; import moment from "moment";
export default { export default {
props: ["data"], props: ["data"],
methods: { methods: {
getTagStyle(data) { getTagStyle(data) {
return { backgroundColor: data.canApply ? "#07c160" : "#999" }; return { backgroundColor: data.canApply ? "#07c160" : "#999" };
},
formatDate(value) {
return value ? moment(value).format("YYYY-MM-DD HH:mm") : "";
},
detailsClick(id) {
this.$emit("goDetails", id);
},
getTagTxt(data) {
return data.canApply ? "进行中" : "已结束";
},
}, },
formatDate(value) {
return value ? moment(value).format("YYYY-MM-DD HH:mm") : "";
},
detailsClick(id) {
this.$emit("goDetails", id);
},
getTagTxt(data) {
return data.canApply ? "进行中" : "已结束";
},
},
}; };
</script> </script>
<style scoped> <style scoped>
.actItem { .actItem {
display: flex; display: flex;
gap: 15px; gap: 15px;
padding: 15px; padding: 15px;
background: white; background: white;
margin-bottom: 10px; margin-bottom: 10px;
cursor: pointer; cursor: pointer;
} }
.actItem-pic { .actItem-pic {
position: relative; position: relative;
width: 100px; width: 100px;
height: 100px; height: 100px;
} }
.actItem-pic img { .actItem-pic img {
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: cover; object-fit: cover;
border-radius: 8px; border-radius: 8px;
} }
.actItemStatus { .actItemStatus {
position: absolute; position: absolute;
top: 5px; top: 5px;
right: 5px; right: 5px;
padding: 2px 8px; padding: 2px 8px;
color: white; color: white;
font-size: 12px; font-size: 12px;
border-radius: 4px; border-radius: 4px;
} }
.actItem-body { .actItem-body {
flex: 1; flex: 1;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between; justify-content: space-between;
color: #333;
} }
.actItem-title { .actItem-title {
font-weight: bold; font-weight: bold;
font-size: 16px; font-size: 16px;
} }
.actItem-tag { .actItem-tag {
color: #666; color: #666;
font-size: 14px; font-size: 14px;
} }
</style> </style>

View File

@@ -1,15 +1,14 @@
<template> <template>
<div class="header-inner"> <router-link to="/userCenter" class="header-inner">
<div class="userInfo"> <div class="title">大学生志愿者活动</div>
<span class="avatar"> <div class="user-info-container">
<img :src="user.avatar" /> <div class="userInfo">
</span> <img class="avatar" :src="user.avatar" />
<span>{{ user.name }}</span> <span class="user-name">{{ user.name }}</span>
</div>
<span class="arrow">></span>
</div> </div>
<router-link to="/userCenter"> </router-link>
<button class="rArrow"></button>
</router-link>
</div>
</template> </template>
<script> <script>
@@ -20,11 +19,25 @@ export default {
<style scoped> <style scoped>
.header-inner { .header-inner {
display: flex;
flex-direction: column;
padding: 15px;
color: white;
text-decoration: none;
}
.title {
font-size: 18px;
font-weight: bold;
text-align: center;
margin-bottom: 15px;
}
.user-info-container {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 15px; width: 100%;
background: white;
} }
.userInfo { .userInfo {
@@ -33,18 +46,19 @@ export default {
gap: 10px; gap: 10px;
} }
.avatar img { .avatar {
width: 50px; width: 50px;
height: 50px; height: 50px;
border-radius: 50%; border-radius: 50%;
border: 2px solid white;
} }
.rArrow { .user-name {
width: 20px; font-weight: bold;
height: 20px; }
border: none;
background: url('../assets/rArrow.png') no-repeat center; .arrow {
background-size: contain; font-size: 24px;
cursor: pointer; font-weight: bold;
} }
</style> </style>

View File

@@ -59,28 +59,50 @@ export default {
.overview { .overview {
display: flex; display: flex;
justify-content: space-around; justify-content: space-around;
padding: 20px; padding: 20px 15px;
background: white; background: white;
list-style: none; list-style: none;
margin: 10px 0; border-radius: 16px;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08);
margin: -20px 12px 15px;
position: relative;
z-index: 10;
} }
.overview li { .overview li {
text-align: center; text-align: center;
flex: 1;
position: relative;
}
.overview li:not(:last-child)::after {
content: '';
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
width: 1px;
height: 40px;
background: linear-gradient(to bottom, transparent, #eee, transparent);
} }
.num { .num {
font-size: 20px; font-size: 14px;
margin-bottom: 8px; margin-bottom: 8px;
color: #666;
} }
.highColor { .highColor {
color: #ff5d23; color: #ff6b35;
font-weight: bold; font-weight: 700;
font-size: 26px;
display: block;
margin-bottom: 2px;
} }
.label { .label {
color: #666; color: #999;
font-size: 12px; font-size: 12px;
font-weight: 500;
} }
</style> </style>

View File

@@ -42,52 +42,76 @@ export default {
</script> </script>
<style scoped> <style scoped>
.container {
margin-bottom: 6px;
}
.details { .details {
display: flex; display: flex;
gap: 15px; gap: 10px;
padding: 15px; padding: 12px;
background: white; background: white;
margin-bottom: 10px;
cursor: pointer; cursor: pointer;
border-radius: 12px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06);
transition: all 0.3s ease;
}
.details:active {
transform: scale(0.99);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
} }
.imgBox { .imgBox {
position: relative; position: relative;
width: 100px; width: 76px;
height: 100px; height: 76px;
flex-shrink: 0;
} }
.imgBox img { .imgBox img {
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: cover; object-fit: cover;
border-radius: 8px; border-radius: 10px;
} }
.status { .status {
position: absolute; position: absolute;
top: 5px; top: 0;
right: 5px; left: 0;
padding: 2px 8px; padding: 3px 10px;
color: white; color: white;
font-size: 12px; font-size: 11px;
border-radius: 4px; border-radius: 10px 0 8px 0;
font-weight: 500;
} }
.main { .main {
flex: 1; flex: 1;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between; justify-content: flex-start;
gap: 8px;
min-width: 0;
} }
.content { .content {
font-size: 15px; font-size: 15px;
line-height: 1.5; line-height: 1.5;
color: #333;
font-weight: 500;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
} }
.bottomTxt { .bottomTxt {
color: #999; color: #aaa;
font-size: 12px; font-size: 12px;
display: flex;
align-items: center;
gap: 8px;
} }
</style> </style>

View File

@@ -70,29 +70,41 @@ export default {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 15px; padding: 0;
margin: 0;
background: transparent;
} }
.user { .user {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 15px; gap: 10px;
} }
.user-avatar { .user-avatar {
width: 60px; width: 65px;
height: 60px; height: 65px;
border-radius: 50%; border-radius: 50%;
border: 3px solid rgba(255, 255, 255, 0.8);
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15);
object-fit: cover;
} }
.user-name { .user-name {
font-size: 18px; font-size: 20px;
font-weight: bold; font-weight: 600;
margin-bottom: 5px; margin-bottom: 6px;
color: #fff;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
} }
.user-score { .user-score {
color: #ff5d23; background: rgba(255, 255, 255, 0.25);
font-size: 14px; padding: 4px 12px;
border-radius: 20px;
font-size: 13px;
color: #fff;
font-weight: 500;
backdrop-filter: blur(5px);
} }
</style> </style>

View File

@@ -1,55 +1,62 @@
<template> <template>
<div class="container"> <div class="container">
<div class="head"> <div class="head">
<p class="title">{{ data.title }}</p> <p class="title">{{ data.title }}</p>
<div class="status"> <div class="status">
<van-tag :color="getActStatusColor(data)" round style="margin-right: 10px"> <van-tag
{{ data.canApply ? '进行中' : '已结束' }} :color="getActStatusColor(data)"
</van-tag> round
<van-tag :color="getActApplyColor(data)" round> style="margin-right: 10px"
{{ applyStatusMap[data.applyStatus] }} >
</van-tag> {{ data.canApply ? "进行中" : "已结束" }}
</div> </van-tag>
</div> <van-tag :color="getActApplyColor(data)" round>
{{ applyStatusMap[data.applyStatus] }}
</van-tag>
</div>
</div>
<div class="dataItem"> <div class="dataItem">
<span class="label">活动时间</span> <span class="label">活动时间</span>
<p>{{ formatDate(data.startTime) }} - {{ formatDate(data.endTime) }}</p> <p>
</div> {{ formatDate(data.startTime) }} -
{{ formatDate(data.endTime) }}
</p>
</div>
<div class="dataItem"> <div class="dataItem">
<span class="label">活动地点</span> <span class="label">活动地点</span>
<p>{{ data.palce }}</p> <p>{{ data.palce }}</p>
</div> </div>
<div class="dataItem"> <div class="dataItem">
<span class="label">活动简介</span> <span class="label">活动简介</span>
<p>{{ data.content }}</p> <p>{{ data.content }}</p>
</div> </div>
<div class="dataItem"> <div class="dataItem">
<span class="label">活动来源</span> <span class="label">活动来源</span>
<p>{{ data.publisher }}</p> <p>{{ data.publisher }}</p>
</div> </div>
<div class="dataItem"> <div class="dataItem">
<span class="label">服务时长</span> <span class="label">服务时长</span>
<p>{{ data.hour }}小时</p> <p>{{ data.hour }}小时</p>
</div> </div>
<div class="dataItem"> <div class="dataItem">
<span class="label">招募人数</span> <span class="label">招募人数</span>
<p>{{ data.total }}</p> <p>{{ data.total }}</p>
</div> </div>
<button <button
class="fBtn" class="fBtn"
v-if="[2, 3].indexOf(data.applyStatus) === -1" v-if="[2, 3].indexOf(data.applyStatus) === -1"
@click="applyClick" @click="applyClick"
> >
{{ data.applyStatus === 1 ? '撤销申请' : '立即报名' }} {{ data.applyStatus === 1 ? "撤销申请" : "立即报名" }}
</button> </button>
</div> </div>
</template> </template>
<script> <script>
@@ -58,108 +65,112 @@ import moment from "moment";
import { showSuccessToast, showFailToast } from "vant"; import { showSuccessToast, showFailToast } from "vant";
export default { export default {
data() { data() {
return { return {
data: {}, data: {},
applyStatusMap: ["", "审核中", "审核通过", "审核拒绝"], applyStatusMap: ["", "审核中", "审核通过", "审核拒绝"],
}; };
},
methods: {
formatDate(value) {
return value ? moment(value).format("YYYY-MM-DD HH:mm") : "--";
}, },
getActStatusColor(data) { methods: {
return data.canApply ? "#07C160" : "#ff976a"; formatDate(value) {
}, return value ? moment(value).format("YYYY-MM-DD HH:mm") : "--";
getActApplyColor(data) { },
const list = ["", "#1989fa", "#07c160", "#f6352c"]; getActStatusColor(data) {
return list[data.applyStatus]; return data.canApply ? "#07C160" : "#ff976a";
}, },
fetchDetails() { getActApplyColor(data) {
const that = this; const list = ["", "#1989fa", "#07c160", "#f6352c"];
const payload = { id: this.$route.query.id }; return list[data.applyStatus];
axios },
.get("/api/actDetails/details", { fetchDetails() {
params: payload, const that = this;
}) const payload = { id: this.$route.query.id };
.then(function (response) { axios
const { error, data = {} } = response.data; .get("/api/actDetails/details", {
if (error === 0) { params: payload,
that.data = data.details || {}; })
} .then(function (response) {
}); const { error, data = {} } = response.data;
}, if (error === 0) {
applyClick() { that.data = data.details || {};
const that = this; }
const payload = { });
isApplay: this.data.applyStatus !== 1, },
id: this.$route.query.id, applyClick() {
}; const that = this;
const payload = {
isApplay: this.data.applyStatus !== 1,
id: this.$route.query.id,
};
axios.post("/api/actDetails/apply", payload).then(function (response) { axios
const { error, msg } = response.data; .post("/api/actDetails/apply", payload)
if (error === 0) { .then(function (response) {
showSuccessToast("操作成功"); const { error, msg } = response.data;
that.fetchDetails(); if (error === 0) {
} else { showSuccessToast("操作成功");
showFailToast(msg || "网络错误,请稍后重试"); that.fetchDetails();
} } else {
}); showFailToast(msg || "网络错误,请稍后重试");
}
});
},
},
mounted() {
this.fetchDetails();
}, },
},
mounted() {
this.fetchDetails();
},
}; };
</script> </script>
<style scoped> <style scoped>
.head { .head {
background: white; background: white;
padding: 20px; padding: 20px;
margin-bottom: 10px; margin-bottom: 10px;
color: #333; /* ✅ 让 head 区域默认文字深色 */
} }
.title { .title {
font-size: 20px; font-size: 20px;
font-weight: bold; font-weight: bold;
margin-bottom: 10px; margin-bottom: 10px;
color: #333; /* ✅ 标题深色(关键) */
} }
.status { .status {
display: flex; display: flex;
gap: 10px; gap: 10px;
} }
.dataItem { .dataItem {
background: white; background: white;
padding: 15px 20px; padding: 15px 20px;
margin-bottom: 1px; margin-bottom: 1px;
} }
.label { .label {
display: block; display: block;
color: #666; color: #666;
font-size: 14px; font-size: 14px;
margin-bottom: 8px; margin-bottom: 8px;
} }
.dataItem p { .dataItem p {
color: #333; color: #333;
line-height: 1.6; line-height: 1.6;
} }
.fBtn { .fBtn {
position: fixed; position: fixed;
bottom: 20px; bottom: 20px;
left: 20px; left: 20px;
right: 20px; right: 20px;
padding: 15px; padding: 15px;
background: #ff5d23; background: #ff5d23;
color: white; color: white;
border: none; border: none;
border-radius: 8px; border-radius: 8px;
font-size: 16px; font-size: 16px;
cursor: pointer; cursor: pointer;
} }
</style> </style>

View File

@@ -1,28 +1,27 @@
<template> <template>
<div class="home"> <div class="home">
<div class="header"> <div class="header">
<h1>大学生志愿者活动</h1> <User :user="userInfo" />
<User :user="userInfo" /> </div>
</div> <Navs />
<Navs /> <div class="list">
<div class="list"> <div class="list-header">
<div class="list-header"> <span>志愿活动</span>
<span>志愿活动</span> <div class="list-more" @click="goMoreActs">
<div class="list-more" @click="goMoreActs"> 查看更多
查看更多 <img src="../assets/rArrow.png" />
<img src="../assets/rArrow.png" /> </div>
</div>
<div class="actList">
<ActItem
v-for="item in list"
:key="item.id"
:data="item"
@goDetails="goDetails"
/>
</div>
</div> </div>
</div>
<div class="actList">
<ActItem
v-for="item in list"
:key="item.id"
:data="item"
@goDetails="goDetails"
/>
</div>
</div> </div>
</div>
</template> </template>
<script> <script>
@@ -32,96 +31,96 @@ import Navs from "../components/Home/Navs.vue";
import ActItem from "../components/Home/ActItem.vue"; import ActItem from "../components/Home/ActItem.vue";
export default { export default {
components: { components: {
User, User,
Navs, Navs,
ActItem, ActItem,
},
data() {
return {
userInfo: {
avatar: "",
name: "",
},
list: [],
};
},
methods: {
fetchUserInfo() {
const that = this;
axios.get("/api/userInfo").then(function (response) {
const { error, data = {} } = response.data;
if (error === 0) {
that.userInfo = {
avatar: data.avatar,
name: data.name,
};
}
});
}, },
fetchActList() { data() {
const that = this; return {
axios.get("/api/actList").then(function (response) { userInfo: {
const { error, data = {} } = response.data; avatar: "",
if (error === 0) { name: "",
that.list = data.list; },
} list: [],
}); };
}, },
goDetails(id) { methods: {
this.$router.push("/actDetails?id=" + id); fetchUserInfo() {
const that = this;
axios.get("/api/userInfo").then(function (response) {
const { error, data = {} } = response.data;
if (error === 0) {
that.userInfo = {
avatar: data.avatar,
name: data.name,
};
}
});
},
fetchActList() {
const that = this;
axios.get("/api/actList").then(function (response) {
const { error, data = {} } = response.data;
if (error === 0) {
that.list = data.list;
}
});
},
goDetails(id) {
this.$router.push("/actDetails?id=" + id);
},
goMoreActs() {
this.$router.push("/loveActs");
},
}, },
goMoreActs() { mounted() {
this.$router.push("/loveActs"); this.fetchUserInfo();
this.fetchActList();
}, },
},
mounted() {
this.fetchUserInfo();
this.fetchActList();
},
}; };
</script> </script>
<style scoped> <style scoped>
.home { .home {
min-height: 100vh; min-height: 100vh;
background: #f5f5f5; background: #f5f5f5;
} }
.header { .header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white; color: white;
padding: 20px 0; padding: 20px 0;
} }
.header h1 { .header h1 {
text-align: center; text-align: center;
margin-bottom: 15px; margin-bottom: 15px;
}
.list {
padding: 15px;
} }
.list-header { .list-header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
margin-bottom: 15px; margin-bottom: 15px;
font-weight: bold; font-weight: bold;
}
.list-header span {
color: #333;
} }
.list-more { .list-more {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 5px; gap: 5px;
color: #666; color: #666;
font-size: 14px; font-size: 14px;
cursor: pointer; cursor: pointer;
} }
.list-more img { .list-more img {
width: 16px; width: 16px;
height: 16px; height: 16px;
} }
</style> </style>

View File

@@ -1,30 +1,33 @@
<template> <template>
<div class="container"> <div class="container">
<div class="searchBox"> <div class="searchBox">
<div class="search"> <div class="search">
<span class="search-icon"></span> <span class="search-icon"></span>
<input placeholder="请输入地点、活动名称等关键字" v-model="keyword" /> <input
</div> placeholder="请输入地点、活动名称等关键字"
</div> v-model="keyword"
/>
</div>
</div>
<div class="body"> <div class="body">
<van-list <van-list
v-model:loading="loading" v-model:loading="loading"
:finished="finished" :finished="finished"
finished-text="没有更多了" finished-text="没有更多了"
@load="onLoad" @load="onLoad"
> >
<ActItem <ActItem
v-for="item in actList" v-for="item in actList"
:key="item.id" :key="item.id"
:data="item" :data="item"
@goDetails="goDetails" @goDetails="goDetails"
/> />
</van-list> </van-list>
</div> </div>
<button class="fBtn" @click="goMyApply">我的报名</button> <button class="fBtn" @click="goMyApply">我的报名</button>
</div> </div>
</template> </template>
<script> <script>
@@ -32,108 +35,106 @@ import axios from "axios";
import ActItem from "../components/Home/ActItem.vue"; import ActItem from "../components/Home/ActItem.vue";
export default { export default {
components: { components: {
ActItem, ActItem,
}, },
data() { data() {
return { return {
actList: [], actList: [],
loading: false, loading: false,
finished: false, finished: false,
currentPage: 1, currentPage: 1,
keyword: "", keyword: "",
}; };
}, },
methods: { methods: {
fetchActList(currentPage = 1) { fetchActList(currentPage = 1) {
const that = this; const that = this;
const payload = { const payload = {
currentPage, currentPage,
pageSize: 10, pageSize: 10,
keyword: this.keyword, keyword: this.keyword,
}; };
this.loading = true; this.loading = true;
axios axios
.get("/api/actList", { params: payload }) .get("/api/actList", { params: payload })
.then(function (response) { .then(function (response) {
const { error, data = {} } = response.data; const { error, data = {} } = response.data;
if (error === 0) { if (error === 0) {
const currentPage = data.current; const currentPage = data.current;
const list = data.list; const list = data.list;
if (currentPage === 1) { if (currentPage === 1) {
that.actList = list; that.actList = list;
} else { } else {
that.actList.push(...list); that.actList.push(...list);
} }
that.currentPage = currentPage; that.currentPage = currentPage;
that.finished = data.pageCount === currentPage; that.finished = data.pageCount === currentPage;
} }
}) })
.finally(function () { .finally(function () {
that.loading = false; that.loading = false;
}); });
},
onLoad() {
this.fetchActList(this.currentPage + 1);
},
goMyApply() {
this.$router.push("/myApply");
},
goDetails(id) {
this.$router.push("/actDetails?id=" + id);
},
}, },
onLoad() { watch: {
this.fetchActList(this.currentPage + 1); keyword() {
this.currentPage = 1;
this.fetchActList(1);
},
}, },
goMyApply() { mounted() {
this.$router.push("/myApply"); this.fetchActList(1);
}, },
goDetails(id) {
this.$router.push("/actDetails?id=" + id);
},
},
watch: {
keyword() {
this.currentPage = 1;
this.fetchActList(1);
},
},
mounted() {
this.fetchActList(1);
},
}; };
</script> </script>
<style scoped> <style scoped>
.searchBox { .searchBox {
padding: 15px; padding: 15px;
background: white; background: white;
}
.search {
display: flex;
align-items: center;
padding: 10px;
background: #f5f5f5;
border-radius: 20px;
} }
.search input { .search input {
flex: 1; flex: 1;
border: none; border: none;
background: transparent; background: transparent;
outline: none; outline: none;
margin-left: 10px; margin-left: 10px;
color: #333;
font-size: 14px;
}
.search input::placeholder {
color: #999;
} }
.body { .body {
padding: 10px; padding: 10px;
} }
.fBtn { .fBtn {
position: fixed; position: fixed;
bottom: 20px; bottom: 20px;
right: 20px; right: 20px;
padding: 12px 24px; padding: 12px 24px;
background: #ff5d23; background: #ff5d23;
color: white; color: white;
border: none; border: none;
border-radius: 25px; border-radius: 25px;
box-shadow: 0 2px 8px rgba(0,0,0,0.2); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
cursor: pointer; cursor: pointer;
} }
</style> </style>

View File

@@ -1,203 +1,199 @@
<template> <template>
<div class="container"> <div class="container">
<div class="tabs"> <div class="tabs">
<div :class="{ tabItem: true, active: curTab === 0 }" @click="tabClick(0)"> <div
总积分 :class="{ tabItem: true, active: curTab === 0 }"
</div> @click="tabClick(0)"
<div :class="{ tabItem: true, active: curTab === 1 }" @click="tabClick(1)"> >
年度积分 积分
</div> </div>
</div> <div
:class="{ tabItem: true, active: curTab === 1 }"
@click="tabClick(1)"
>
年度积分
</div>
</div>
<div class="dataList"> <div class="dataList">
<div class="dataItem"> <div class="dataItem">
<p class="dataItem-score">{{ provinceRank }}</p> <p class="dataItem-score">{{ provinceRank }}</p>
<p class="dataItem-label">全省的排名</p> <p class="dataItem-label">全省的排名</p>
</div> </div>
<div class="dataItem"> <div class="dataItem">
<p class="dataItem-score">{{ totalScore }}</p> <p class="dataItem-score">{{ totalScore }}</p>
<p class="dataItem-label">服务总积分</p> <p class="dataItem-label">服务总积分</p>
</div> </div>
<div class="dataItem"> <div class="dataItem">
<p class="dataItem-score">{{ grandeRank }}</p> <p class="dataItem-score">{{ grandeRank }}</p>
<p class="dataItem-label">本校本年级排名</p> <p class="dataItem-label">本校本年级排名</p>
</div> </div>
</div> </div>
<div class="rank"> <div class="rank">
<div class="rank-hd"> <div class="rank-hd">
<p class="rank-title">本校本年级服务标兵</p> <p class="rank-title">本校本年级服务标兵</p>
<p class="rank-range">1200人参与排名</p> <p class="rank-range">1200人参与排名</p>
</div> </div>
<ul class="rank-list"> <ul class="rank-list">
<li v-for="(item, idx) in dataList" :key="item.id"> <li v-for="(item, idx) in dataList" :key="item.id">
<div class="rank-student"> <div class="rank-student">
<span class="rank-idx">{{ idx + 1 }}</span> <span class="rank-idx">{{ idx + 1 }}</span>
<span class="rank-avatar"> <span class="rank-avatar">
<img :src='item.avatar' /> <img :src="item.avatar" />
</span> </span>
<span class="rank-name">{{ item.name }}</span> <span class="rank-name">{{ item.name }}</span>
</div> </div>
<div class="rank-score">{{ item.score }}</div> <div class="rank-score">{{ item.score }}</div>
</li> </li>
</ul> </ul>
</div>
</div> </div>
</div>
</template> </template>
<script> <script>
import axios from "axios"; import axios from "axios";
export default { export default {
data() { data() {
return { return {
curTab: 0, curTab: 0,
dataList: [], dataList: [],
provinceRank: "", provinceRank: "",
totalScore: "", totalScore: "",
grandeRank: "", grandeRank: "",
}; };
},
methods: {
tabClick(value) {
this.curTab = Number(value);
this.fetchOverview(this.curTab);
this.fetchRankList(this.curTab);
}, },
fetchOverview(type) { methods: {
const that = this; tabClick(value) {
axios this.curTab = Number(value);
.get("/api/report/myOverview", { this.fetchOverview(this.curTab);
params: { type }, this.fetchRankList(this.curTab);
}) },
.then(function (response) { fetchOverview(type) {
const { error, data = {} } = response.data; const that = this;
if (error === 0) { axios
that.provinceRank = data.provinceRank; .get("/api/report/myOverview", {
that.totalScore = data.totalScore; params: { type },
that.grandeRank = data.grandeRank; })
} .then(function (response) {
}); const { error, data = {} } = response.data;
if (error === 0) {
that.provinceRank = data.provinceRank;
that.totalScore = data.totalScore;
that.grandeRank = data.grandeRank;
}
});
},
fetchRankList(type) {
const that = this;
const payload = {
currentPage: 1,
pageSize: 10,
type,
};
axios
.get("/api/report/rankList", { params: payload })
.then(function (response) {
const { error, data = {} } = response.data;
if (error === 0) {
that.dataList = data.list || [];
}
});
},
}, },
fetchRankList(type) { mounted() {
const that = this; this.fetchOverview(this.curTab);
const payload = { this.fetchRankList(this.curTab);
currentPage: 1,
pageSize: 10,
type,
};
axios
.get("/api/report/rankList", { params: payload })
.then(function (response) {
const { error, data = {} } = response.data;
if (error === 0) {
that.dataList = data.list || [];
}
});
}, },
},
mounted() {
this.fetchOverview(this.curTab);
this.fetchRankList(this.curTab);
},
}; };
</script> </script>
<style scoped> <style scoped>
.container {
background-color: #f7f8fa;
padding: 10px;
min-height: 100vh;
}
.tabs,
.dataList,
.rank {
background: white;
border-radius: 8px;
margin-bottom: 10px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}
.tabs { .tabs {
display: flex; display: flex;
background: white; padding: 10px;
padding: 10px;
} }
.tabItem { .tabItem {
flex: 1; flex: 1;
text-align: center; text-align: center;
padding: 10px; padding: 10px;
cursor: pointer; cursor: pointer;
color: #666;
} }
.tabItem.active { .tabItem.active {
color: #ff5d23; color: #ff5d23;
border-bottom: 2px solid #ff5d23; border-bottom: 2px solid #ff5d23;
font-weight: bold;
} }
.dataList { .dataList {
display: flex; display: flex;
justify-content: space-around; justify-content: space-around;
padding: 20px; padding: 20px;
background: white;
margin: 10px 0;
} }
.dataItem { .dataItem {
text-align: center; text-align: center;
} }
.dataItem-score { .dataItem-score {
font-size: 24px; font-size: 24px;
font-weight: bold; font-weight: bold;
color: #ff5d23; color: #ff5d23;
margin-bottom: 5px; margin-bottom: 5px;
} }
.dataItem-label { .dataItem-label {
font-size: 12px; font-size: 12px;
color: #666; color: #333;
} }
.rank { .rank {
background: white; padding: 15px;
padding: 15px; color: #333; /* ⭐ 内容区统一深色 */
}
.rank-hd {
margin-bottom: 15px;
} }
.rank-title { .rank-title {
font-weight: bold; font-weight: bold;
font-size: 16px; font-size: 16px;
} }
.rank-range { .rank-range {
font-size: 12px; font-size: 12px;
color: #666; color: #666;
margin-top: 5px; margin-top: 5px;
}
.rank-list {
list-style: none;
}
.rank-list li {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 0;
border-bottom: 1px solid #eee;
}
.rank-student {
display: flex;
align-items: center;
gap: 10px;
} }
.rank-idx { .rank-idx {
width: 20px; width: 20px;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
} }
.rank-avatar img { .rank-name {
width: 40px; font-size: 14px;
height: 40px;
border-radius: 50%;
} }
.rank-score { .rank-score {
color: #ff5d23; color: #ff5d23;
font-weight: bold; font-weight: bold;
} }
</style> </style>

View File

@@ -1,36 +1,36 @@
<template> <template>
<div class="container"> <div class="container">
<ul class="tabList"> <ul class="tabList">
<li @click="tabClick(0)"> <li @click="tabClick(0)">
<span :class="curTab === 0 ? 'active' : ''">全部</span> <span :class="curTab === 0 ? 'active' : ''">全部</span>
</li> </li>
<li @click="tabClick(1)"> <li @click="tabClick(1)">
<span :class="curTab === 1 ? 'active' : ''">审核中</span> <span :class="curTab === 1 ? 'active' : ''">审核中</span>
</li> </li>
<li @click="tabClick(2)"> <li @click="tabClick(2)">
<span :class="curTab === 2 ? 'active' : ''">审核通过</span> <span :class="curTab === 2 ? 'active' : ''">审核通过</span>
</li> </li>
<li @click="tabClick(3)"> <li @click="tabClick(3)">
<span :class="curTab === 3 ? 'active' : ''">审核拒绝</span> <span :class="curTab === 3 ? 'active' : ''">审核拒绝</span>
</li> </li>
</ul> </ul>
<div class="list"> <div class="list">
<van-list <van-list
v-model:loading="loading" v-model:loading="loading"
:finished="finished" :finished="finished"
finished-text="没有更多了" finished-text="没有更多了"
@load="onLoad" @load="onLoad"
> >
<ActItem <ActItem
v-for="item in actList" v-for="item in actList"
:key="item.id" :key="item.id"
:data="item" :data="item"
@goDetails="goDetails" @goDetails="goDetails"
/> />
</van-list> </van-list>
</div>
</div> </div>
</div>
</template> </template>
<script> <script>
@@ -38,93 +38,95 @@ import axios from "axios";
import ActItem from "../components/Home/ActItem.vue"; import ActItem from "../components/Home/ActItem.vue";
export default { export default {
components: { components: {
ActItem, ActItem,
},
data() {
return {
curTab: 0,
actList: [],
loading: false,
finished: false,
currentPage: 1,
};
},
methods: {
tabClick(value) {
this.curTab = value;
this.currentPage = 1;
this.fetchApplyList(1);
}, },
fetchApplyList(currentPage = 1) { data() {
const that = this; return {
const payload = { curTab: 0,
currentPage, actList: [],
pageSize: 10, loading: false,
type: this.curTab, finished: false,
}; currentPage: 1,
};
},
methods: {
tabClick(value) {
this.curTab = value;
this.currentPage = 1;
this.fetchApplyList(1);
},
fetchApplyList(currentPage = 1) {
const that = this;
const payload = {
currentPage,
pageSize: 10,
type: this.curTab,
};
this.loading = true; this.loading = true;
axios axios
.get("/api/myApplyList", { params: payload }) .get("/api/myApplyList", { params: payload })
.then(function (response) { .then(function (response) {
const { error, data = {} } = response.data; const { error, data = {} } = response.data;
if (error === 0) { if (error === 0) {
const currentPage = data.current; const currentPage = data.current;
const list = data.list; const list = data.list;
if (currentPage === 1) { if (currentPage === 1) {
that.actList = list; that.actList = list;
} else { } else {
that.actList.push(...list); that.actList.push(...list);
} }
that.currentPage = currentPage; that.currentPage = currentPage;
that.finished = data.pageCount === currentPage; that.finished = data.pageCount === currentPage;
} }
}) })
.finally(function () { .finally(function () {
that.loading = false; that.loading = false;
}); });
},
onLoad() {
this.fetchApplyList(this.currentPage + 1);
},
goDetails(id) {
this.$router.push("/actDetails?id=" + id);
},
}, },
onLoad() { mounted() {
this.fetchApplyList(this.currentPage + 1); this.fetchApplyList(1);
}, },
goDetails(id) {
this.$router.push("/actDetails?id=" + id);
},
},
mounted() {
this.fetchApplyList(1);
},
}; };
</script> </script>
<style scoped> <style scoped>
.tabList { .tabList {
display: flex; display: flex;
background: white; background: white;
list-style: none; list-style: none;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
color: #333; /* ✅ tab 区域默认文字深色 */
} }
.tabList li { .tabList li {
flex: 1; flex: 1;
text-align: center; text-align: center;
padding: 15px 0; padding: 15px 0;
cursor: pointer; cursor: pointer;
} }
.tabList span { .tabList span {
padding: 5px 10px; padding: 5px 10px;
color: #333; /* ✅ 兜底span 明确深色 */
} }
.tabList span.active { .tabList span.active {
color: #ff5d23; color: #ff5d23;
border-bottom: 2px solid #ff5d23; border-bottom: 2px solid #ff5d23;
} }
.list { .list {
padding: 10px; padding: 10px;
} }
</style> </style>

View File

@@ -1,59 +1,59 @@
<template> <template>
<div class="container"> <div class="container">
<div class="dataItem"> <div class="dataItem">
<span class="label">服务时间</span> <span class="label">服务时间</span>
<span>{{ formatDay(data.actTime) }}</span> <span>{{ formatDay(data.actTime) }}</span>
</div> </div>
<div class="dataItem"> <div class="dataItem">
<span class="label">服务地点</span> <span class="label">服务地点</span>
<span>{{ data.place }}</span> <span>{{ data.place }}</span>
</div> </div>
<div class="dataItem"> <div class="dataItem">
<span class="label">服务内容</span> <span class="label">服务内容</span>
<span>{{ data.content }}</span> <span>{{ data.content }}</span>
</div> </div>
<div class="dataItem"> <div class="dataItem">
<span class="label">服务照片</span> <span class="label">服务照片</span>
<div> <div>
<img <img
class="serviceImg" class="serviceImg"
v-for="(url) in data.imgList" v-for="url in data.imgList"
:src="url" :src="url"
:key="url" :key="url"
/> />
</div> </div>
</div> </div>
<div class="dataItem"> <div class="dataItem">
<span class="label">服务时长</span> <span class="label">服务时长</span>
<span>{{ data.hour }}小时</span> <span>{{ data.hour }}小时</span>
</div> </div>
<div class="dataItem"> <div class="dataItem">
<span class="label">纪实时间</span> <span class="label">纪实时间</span>
<span>{{ formatDate(data.uploadTime) }}</span> <span>{{ formatDate(data.uploadTime) }}</span>
</div> </div>
<div class="dataItem"> <div class="dataItem">
<span class="label">审核状态</span> <span class="label">审核状态</span>
<span> <span>
<span <span
class="status" class="status"
:style="{ backgroundColor: bgColorMap[data.status] }" :style="{ backgroundColor: bgColorMap[data.status] }"
> >
{{ statusMap[data.status] }} {{ statusMap[data.status] }}
</span> </span>
</span> </span>
</div> </div>
<div class="footer"> <div class="footer">
<p class="title">{{ titleMap[data.status] }}</p> <p class="title">{{ titleMap[data.status] }}</p>
<p class="score" v-if="data.status === 1">4分</p> <p class="score" v-if="data.status === 1">4分</p>
</div>
</div> </div>
</div>
</template> </template>
<script> <script>
@@ -61,92 +61,93 @@ import axios from "axios";
import moment from "moment"; import moment from "moment";
export default { export default {
data() { data() {
return { return {
data: {}, data: {},
statusMap: ["审核中", "审核通过", "审核驳回"], statusMap: ["审核中", "审核通过", "审核驳回"],
bgColorMap: ["#1989fa", "#07c160", "#f6352c"], bgColorMap: ["#1989fa", "#07c160", "#f6352c"],
titleMap: [ titleMap: [
"正在审核中,请耐心等待", "正在审核中,请耐心等待",
"感谢您的服务,请收下服务积分", "感谢您的服务,请收下服务积分",
"审核被驳回了哟", "审核被驳回了哟",
], ],
}; };
},
methods: {
formatDate(value) {
return value ? moment(value).format("YYYY-MM-DD HH:mm") : "--";
}, },
formatDay(value) { methods: {
return value ? moment(value).format("YYYY-MM-DD") : "--"; formatDate(value) {
return value ? moment(value).format("YYYY-MM-DD HH:mm") : "--";
},
formatDay(value) {
return value ? moment(value).format("YYYY-MM-DD") : "--";
},
fetchDetails() {
const that = this;
const payload = { id: this.$route.query.id };
axios
.get("/api/service/details", {
params: payload,
})
.then(function (response) {
const { error, data = {} } = response.data;
if (error === 0) {
that.data = data.details || {};
}
});
},
}, },
fetchDetails() { mounted() {
const that = this; this.fetchDetails();
const payload = { id: this.$route.query.id };
axios
.get("/api/service/details", {
params: payload,
})
.then(function (response) {
const { error, data = {} } = response.data;
if (error === 0) {
that.data = data.details || {};
}
});
}, },
},
mounted() {
this.fetchDetails();
},
}; };
</script> </script>
<style scoped> <style scoped>
.dataItem { .dataItem {
background: white; background: white;
padding: 15px 20px; padding: 15px 20px;
margin-bottom: 1px; margin-bottom: 1px;
color: #333; /* ✅ 关键:让值的文字变深色 */
} }
.label { .label {
display: block; display: block;
color: #666; color: #666;
font-size: 14px; font-size: 14px;
margin-bottom: 8px; margin-bottom: 8px;
} }
.serviceImg { .serviceImg {
width: 100px; width: 100px;
height: 100px; height: 100px;
object-fit: cover; object-fit: cover;
border-radius: 8px; border-radius: 8px;
margin-right: 10px; margin-right: 10px;
margin-top: 10px; margin-top: 10px;
} }
.status { .status {
padding: 4px 12px; padding: 4px 12px;
color: white; color: white;
font-size: 12px; font-size: 12px;
border-radius: 12px; border-radius: 12px;
} }
.footer { .footer {
background: white; background: white;
padding: 20px; padding: 20px;
text-align: center; text-align: center;
margin-top: 10px; margin-top: 10px;
} }
.title { .title {
font-size: 16px; font-size: 16px;
color: #666; color: #666;
margin-bottom: 10px; margin-bottom: 10px;
} }
.score { .score {
font-size: 32px; font-size: 32px;
color: #ff5d23; color: #ff5d23;
font-weight: bold; font-weight: bold;
} }
</style> </style>

View File

@@ -1,31 +1,25 @@
<template> <template>
<div> <div class="container">
<div class="header"> <div class="header">
<User <User @updateYear="updateYear" :date="year" :dateList="dateList" />
@updateYear="updateYear" </div>
:date="year"
:dateList="dateList"
/>
</div>
<div class="overview"> <Overview :year="year.value" />
<Overview :year="year.value" />
</div>
<van-list <van-list
v-model:loading="loading" v-model:loading="loading"
:finished="finished" :finished="finished"
finished-text="没有更多了" finished-text="没有更多了"
@load="onLoad" @load="onLoad"
> >
<RecordItem <RecordItem
v-for="item in dataList" v-for="item in dataList"
:key="item.id" :key="item.id"
:data="item" :data="item"
@goDetails="goDetails" @goDetails="goDetails"
/> />
</van-list> </van-list>
</div> </div>
</template> </template>
<script> <script>
@@ -119,8 +113,25 @@ export default {
</script> </script>
<style scoped> <style scoped>
.container {
background-color: #f5f6f8;
min-height: auto;
padding-bottom: 20px;
}
.header { .header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); background: linear-gradient(135deg, #ff6b35 0%, #f7931e 50%, #ffb347 100%);
color: white; color: white;
padding: 10px 12px 12px;
border-radius: 0 0 30px 30px;
box-shadow: 0 4px 20px rgba(255, 107, 53, 0.3);
margin-bottom: 10px;
}
.header :deep(.container) {
min-height: 0 !important;
height: auto !important;
padding: 0 !important;
margin: 0 !important;
} }
</style> </style>

View File

@@ -1,45 +1,60 @@
<template> <template>
<div class="container"> <div class="container">
<div class="inner"> <div class="inner">
<h1>个人信息</h1> <h1>个人信息</h1>
<ul> <ul>
<li> <li>
<p class="label"><span>*</span>姓名</p> <p class="label"><span>*</span>姓名</p>
<span class="txt">{{ name }}</span> <span class="txt">{{ name }}</span>
</li> </li>
<li> <li>
<p class="label"><span>*</span>编号</p> <p class="label"><span>*</span>编号</p>
<span class="txt">{{ code }}</span> <span class="txt">{{ code }}</span>
</li> </li>
<li> <li>
<p class="label"><span>*</span>性别</p> <p class="label"><span>*</span>性别</p>
<input type="radio" value="0" v-model="gender" /> <input type="radio" value="0" v-model="gender" />
<input type="radio" value="1" v-model="gender" /> <input type="radio" value="1" v-model="gender" />
</li> </li>
<li> <li>
<p class="label"><span>*</span>手机号</p> <p class="label"><span>*</span>手机号</p>
<input placeholder="请输入手机号" v-model.trim="phoneNum" /> <input placeholder="请输入手机号" v-model.trim="phoneNum" />
</li> </li>
<li> <li>
<p class="label"><span>*</span>学校</p> <p class="label"><span>*</span>学校</p>
<input placeholder="请输入学校名称" v-model.trim="school" /> <input placeholder="请输入学校名称" v-model.trim="school" />
</li> </li>
<li> <li>
<p class="label"><span>*</span>专业</p> <p class="label"><span>*</span>专业</p>
<input placeholder="请输入专业名称" v-model.trim="profession" /> <input
</li> placeholder="请输入专业名称"
<li> v-model.trim="profession"
<p class="label"><span>*</span>人员属性</p> />
<div class="userTypeList"> </li>
<span :class="{ active: userType === 0 }" @click="changeUserType(0)">群众</span> <li>
<span :class="{ active: userType === 1 }" @click="changeUserType(1)">团员</span> <p class="label"><span>*</span>人员属性</p>
<span :class="{ active: userType === 2 }" @click="changeUserType(2)">党员</span> <div class="userTypeList">
</div> <span
</li> :class="{ active: userType === 0 }"
</ul> @click="changeUserType(0)"
<button class="subBtn" @click="submitClick">提交</button> >群众</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> </div>
</div>
</template> </template>
<script> <script>
@@ -47,156 +62,181 @@ import axios from "axios";
import { showToast, showSuccessToast, showFailToast } from "vant"; import { showToast, showSuccessToast, showFailToast } from "vant";
export default { export default {
data() { data() {
return { return {
name: "", name: "",
code: null, code: null,
gender: 0, gender: 0,
phoneNum: "", phoneNum: "",
school: "", school: "",
profession: "", profession: "",
userType: 0, userType: 0,
}; };
},
methods: {
changeUserType(value) {
this.userType = value;
}, },
fetchUsrInfo() { methods: {
const that = this; changeUserType(value) {
axios.get("/api/userInfo").then(function (response) { this.userType = value;
const { error, data = {} } = response.data; },
if (error === 0) { fetchUsrInfo() {
that.name = data.name; const that = this;
that.code = data.code; axios.get("/api/userInfo").then(function (response) {
that.gender = data.gender; const { error, data = {} } = response.data;
that.phoneNum = data.phoneNum; if (error === 0) {
that.school = data.school; that.name = data.name;
that.profession = data.profession; that.code = data.code;
that.userType = data.userType; that.gender = data.gender;
} that.phoneNum = data.phoneNum;
}); that.school = data.school;
}, that.profession = data.profession;
check() { that.userType = data.userType;
var phoneNum = this.phoneNum; }
var school = this.school; });
var profession = this.profession; },
check() {
var phoneNum = this.phoneNum;
var school = this.school;
var profession = this.profession;
if (phoneNum === "") { if (phoneNum === "") {
showToast("手机号不可为空"); showToast("手机号不可为空");
return; return;
} }
if (school === "") { if (school === "") {
showToast("学校不可为空"); showToast("学校不可为空");
return; return;
} }
if (profession === "") { if (profession === "") {
showToast("专业不可为空"); showToast("专业不可为空");
return; return;
} }
const payload = { const payload = {
name: this.name, name: this.name,
code: this.code, code: this.code,
gender: this.gender, gender: this.gender,
phoneNum, phoneNum,
school, school,
profession, profession,
userType: this.userType, userType: this.userType,
}; };
return payload; return payload;
}, },
submitClick() { submitClick() {
var payload = this.check(); var payload = this.check();
if (!payload) { if (!payload) {
return; return;
} }
axios.post("/api/userInfo/submit", payload).then(function (response) { axios
const { error, msg } = response.data; .post("/api/userInfo/submit", payload)
if (error === 0) { .then(function (response) {
showSuccessToast("操作成功"); const { error, msg } = response.data;
} else { if (error === 0) {
showFailToast(msg || "网络错误,请稍后重试"); showSuccessToast("操作成功");
} } else {
}); showFailToast(msg || "网络错误,请稍后重试");
}
});
},
},
mounted() {
this.fetchUsrInfo();
}, },
},
mounted() {
this.fetchUsrInfo();
},
}; };
</script> </script>
<style scoped> <style scoped>
.inner { .inner {
padding: 20px; padding: 20px;
background: white; background: white;
color: #333;
} }
h1 { h1 {
text-align: center; text-align: center;
margin-bottom: 20px; margin-bottom: 20px;
color: #333;
} }
ul { ul {
list-style: none; list-style: none;
padding: 0;
margin: 0;
} }
li { li {
padding: 15px 0; padding: 15px 0;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
color: #333;
} }
.label { .label {
font-weight: bold; font-weight: bold;
margin-bottom: 10px; margin-bottom: 10px;
color: #333;
} }
.label span { .label span {
color: red; color: red;
} }
.txt { .txt {
color: #666; color: #666;
} }
input[type="text"], input { li input:not([type="radio"]) {
width: 100%; width: 100%;
padding: 10px; padding: 10px;
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: 4px; border-radius: 4px;
margin-top: 5px; margin-top: 5px;
box-sizing: border-box;
color: #333;
background-color: #fff;
}
li input:not([type="radio"])::placeholder {
color: #999;
}
input[type="radio"] {
margin-right: 6px;
margin-left: 10px;
}
input[type="radio"]:first-of-type {
margin-left: 0;
} }
.userTypeList { .userTypeList {
display: flex; display: flex;
gap: 10px; gap: 10px;
margin-top: 10px; margin-top: 10px;
} }
.userTypeList span { .userTypeList span {
padding: 8px 20px; padding: 8px 20px;
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: 4px; border-radius: 4px;
cursor: pointer; cursor: pointer;
color: #333;
} }
.userTypeList span.active { .userTypeList span.active {
background: #ff5d23; background: #ff5d23;
color: white; color: white;
border-color: #ff5d23; border-color: #ff5d23;
} }
.subBtn { .subBtn {
width: 100%; width: 100%;
padding: 15px; padding: 15px;
background: #ff5d23; background: #ff5d23;
color: white; color: white;
border: none; border: none;
border-radius: 4px; border-radius: 4px;
font-size: 16px; font-size: 16px;
margin-top: 20px; margin-top: 20px;
cursor: pointer; cursor: pointer;
} }
</style> </style>

View File

@@ -1,5 +1,6 @@
import { defineConfig } from "vite"; import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue"; import vue from "@vitejs/plugin-vue";
import VueDevTools from "vite-plugin-vue-devtools";
import fs from "fs"; import fs from "fs";
import path from "path"; import path from "path";
@@ -144,5 +145,10 @@ function mockPlugin() {
} }
export default defineConfig({ export default defineConfig({
plugins: [vue(), mockPlugin()], base: './',
}); plugins: [
vue(),
mockPlugin(),
VueDevTools(),
],
})