xiaoxin пре 2 година
родитељ
комит
8bfb71d7f4

+ 1 - 1
components/listView.vue

@@ -22,7 +22,7 @@ onLoad(() => {})
 
 // 点击每一个学生回调
 const goPage = (item) => {
-	// console.log(item)
+	console.log(item)
 
 	if (props.appType == '学生轨迹') {
 		uni.navigateTo({

+ 5 - 0
node_modules/.package-lock.json

@@ -25,6 +25,11 @@
       "resolved": "https://registry.npmmirror.com/crypto-js/-/crypto-js-4.2.0.tgz",
       "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
     },
+    "node_modules/dayjs": {
+      "version": "1.11.11",
+      "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.11.tgz",
+      "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg=="
+    },
     "node_modules/mime": {
       "version": "2.6.0",
       "resolved": "https://registry.npmmirror.com/mime/-/mime-2.6.0.tgz",

+ 12 - 1
package-lock.json

@@ -6,7 +6,8 @@
     "": {
       "dependencies": {
         "cos-wx-sdk-v5": "^1.7.0",
-        "crypto-js": "^4.2.0"
+        "crypto-js": "^4.2.0",
+        "dayjs": "^1.11.11"
       }
     },
     "node_modules/@xmldom/xmldom": {
@@ -31,6 +32,11 @@
       "resolved": "https://registry.npmmirror.com/crypto-js/-/crypto-js-4.2.0.tgz",
       "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
     },
+    "node_modules/dayjs": {
+      "version": "1.11.11",
+      "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.11.tgz",
+      "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg=="
+    },
     "node_modules/mime": {
       "version": "2.6.0",
       "resolved": "https://registry.npmmirror.com/mime/-/mime-2.6.0.tgz",
@@ -63,6 +69,11 @@
       "resolved": "https://registry.npmmirror.com/crypto-js/-/crypto-js-4.2.0.tgz",
       "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
     },
+    "dayjs": {
+      "version": "1.11.11",
+      "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.11.tgz",
+      "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg=="
+    },
     "mime": {
       "version": "2.6.0",
       "resolved": "https://registry.npmmirror.com/mime/-/mime-2.6.0.tgz",

+ 2 - 1
package.json

@@ -1,6 +1,7 @@
 {
   "dependencies": {
     "cos-wx-sdk-v5": "^1.7.0",
-    "crypto-js": "^4.2.0"
+    "crypto-js": "^4.2.0",
+    "dayjs": "^1.11.11"
   }
 }

+ 11 - 5
pages.json

@@ -78,7 +78,7 @@
 		{
 			"path": "pages/student/student",
 			"style": {
-				"navigationBarTitleText": "学生名",
+				"navigationBarTitleText": "",
 				"enablePullDownRefresh": false
 			}
 		},
@@ -138,6 +138,13 @@
 				"navigationBarTitleText": "修改手机号",
 				"enablePullDownRefresh": false
 			}
+		},
+		{
+			"path": "pages/statistics/statistics",
+			"style": {
+				"navigationBarTitleText": "在校统计",
+				"enablePullDownRefresh": false
+			}
 		}
 	],
 	"subPackages": [{
@@ -178,10 +185,9 @@
 				}
 			},
 			{
-				"path" : "set/set",
-				"style" : 
-				{
-					"navigationBarTitleText" : "访客设置"
+				"path": "set/set",
+				"style": {
+					"navigationBarTitleText": "访客设置"
 				}
 			}
 		]

+ 1 - 2
pages/grade/grade.vue

@@ -59,8 +59,7 @@ const getData = async () => {
 		}
 	})
 	// console.log(res)
-	// const result = JSON.parse(decryptDes(res.data))
-	// console.log(result)
+
 	res.data.forEach((ele) => {
 		let temlist
 		ele.classBookList.forEach((item, index, arr) => {

+ 7 - 2
pages/home/home.vue

@@ -303,7 +303,8 @@ const updateObj = (data) => {
 	display: flex;
 	flex-direction: column;
 	padding: 0 20rpx;
-	min-height: 100vh;
+	height: 100vh;
+	overflow: hidden;
 	background-color: #f1f6fe;
 
 	// 自定义导航栏区域样式
@@ -394,6 +395,7 @@ const updateObj = (data) => {
 
 	// 详细信息区域样式
 	.body {
+		height: calc(100vh - 550rpx);
 		margin-top: 20rpx;
 
 		.body_header {
@@ -484,6 +486,9 @@ const updateObj = (data) => {
 		}
 
 		.body_list {
+			max-height: calc(100vh - 790rpx);
+			overflow-y: auto;
+			box-sizing: border-box;
 			padding: 30rpx 30rpx;
 			display: grid;
 			grid-template-columns: repeat(3, 1fr);
@@ -516,4 +521,4 @@ const updateObj = (data) => {
 		}
 	}
 }
-</style>
+</style>

+ 337 - 0
pages/statistics/statistics.vue

@@ -0,0 +1,337 @@
+<template>
+	<view class="statistics">
+		<!-- 背景图片区域 -->
+		<img class="img" src="../../static/images/center-bg.png" />
+
+		<!-- 时间选择区域 -->
+		<div class="picker">
+			<uni-datetime-picker type="date" :clear-icon="false" v-model="time" @change="changeTime"></uni-datetime-picker>
+		</div>
+
+		<!-- 状态选择区域 -->
+		<div class="type">
+			<div class="type_box" :class="{ active: currentType === 1 }" @click="changeType(1)">异常({{ info?.abnormal?.count }})</div>
+			<div class="type_box" :class="{ active: currentType === 2 }" @click="changeType(2)">正常({{ info?.normal?.count }})</div>
+			<div class="type_box" :class="{ active: currentType === 3 }" @click="changeType(3)">请假({{ info?.ack?.count }})</div>
+		</div>
+
+		<!-- 列表数据 -->
+		<div class="list" v-if="listData.length">
+			<div class="list_header">
+				<div class="header_box">姓名</div>
+				<div class="header_box">学号</div>
+				<div v-if="currentType != 1" class="header_box">操作</div>
+			</div>
+
+			<div class="list_content">
+				<div class="list_box" v-for="item in listData" :key="item.userId">
+					<div class="box" @click="clickName(item)">{{ item.name }}</div>
+					<div class="box">{{ item.cardNo }}</div>
+					<div v-if="currentType != 1" class="box color" @click="clickDetail(item)">详情</div>
+				</div>
+			</div>
+		</div>
+		<!-- 没有数据时展示的页面 -->
+		<NoData v-else />
+
+		<!-- 详情弹窗区域 -->
+		<uni-popup ref="popup" type="center" :is-mask-click="false">
+			<view class="popup_box">
+				<!-- 弹窗标题区域 -->
+				<view class="pop_header">
+					请假详情
+					<view class="header_icon" @click="popup.close()">×</view>
+				</view>
+
+				<!-- 弹窗详细信息区域 -->
+				<view class="pop_info">
+					<view class="info_key">请假人姓名:</view>
+					<view class="info_value">{{ askInfo.name }}</view>
+				</view>
+
+				<view class="pop_info">
+					<view class="info_key">学号:</view>
+					<view class="info_value">{{ askInfo.cardNo }}</view>
+				</view>
+
+				<view class="pop_info">
+					<view class="info_key">请假时间:</view>
+					<view class="info_value">{{ dayjs(askInfo.startTime).format('YYYY-MM-DD hh:mm:ss') }} - {{ dayjs(askInfo.endTime).format('YYYY-MM-DD hh:mm:ss') }}</view>
+				</view>
+
+				<view class="pop_info">
+					<view class="info_key">请假说明:</view>
+					<view class="info_value">{{ askInfo.reason }}</view>
+				</view>
+
+				<view class="pop_info">
+					<view class="info_key">创建时间:</view>
+					<view class="info_value">{{ dayjs(askInfo.initiateTime).format('YYYY-MM-DD hh:mm:ss') }}</view>
+				</view>
+			</view>
+		</uni-popup>
+	</view>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+import { onLoad } from '@dcloudio/uni-app'
+import { myRequest } from '@/utils/api.js'
+import dayjs from 'dayjs'
+import { decryptDes } from '@/utils/des.js'
+import NoData from '@/components/noData.vue'
+
+// 时间选择框绑定数据
+const time = ref('')
+
+// 当前状态
+const currentType = ref(1)
+
+// 展示的列表数据
+const listData = ref([])
+// 全部数据
+const info = ref({})
+
+// 弹窗元素标记
+const popup = ref(null)
+
+// 弹窗请假信息
+const askInfo = ref({})
+
+onLoad(() => {
+	// 获取当前时间
+	time.value = dayjs(Date.now()).format('YYYY-MM-DD') + ' 00:00:00'
+
+	getData()
+})
+
+// 获取列表数据
+const getData = async () => {
+	const res = await myRequest({
+		url: '/wanzai/api/smartUser/statisticsCampus',
+		data: {
+			classId: uni.getStorageSync('userInfo').schoolClass,
+			dateTime: time.value
+		}
+	})
+	// console.log(res)
+	if (res.code == 200) {
+		const result = JSON.parse(decryptDes(res.data))
+		// console.log(result)
+
+		info.value = result
+		if (currentType.value === 1) {
+			listData.value = result.abnormal.date
+		} else if (currentType.value === 2) {
+			listData.value = result.normal.date
+		} else if (currentType.value === 3) {
+			listData.value = result.ack.date
+		}
+	}
+}
+
+// 切换时间时的回调
+const changeTime = (v) => {
+	time.value = v + ' 00:00:00'
+	getData()
+}
+
+// 切换状态时的回调
+const changeType = (v) => {
+	if (currentType.value != v) {
+		currentType.value = v
+		getData()
+	}
+}
+
+// 点击姓名时触发的回调
+const clickName = async (item) => {
+	// 获取学生相关的信息
+	const res = await myRequest({
+		url: '/wanzai/api/smartUser/addressBook',
+		data: {
+			userId: item.userId
+		}
+	})
+	// console.log(res)
+	if (res.code == 200) {
+		const result = JSON.parse(decryptDes(res.data))
+		// console.log(result)
+
+		uni.navigateTo({
+			url: `/pages/student/student?msg=${JSON.stringify(result)}`
+		})
+	}
+}
+
+// 点击详情时触发的回调
+const clickDetail = (item) => {
+	// console.log(item)
+	if (currentType.value === 2) {
+		// 跳转 轨迹
+		uni.navigateTo({
+			url: `/pages/track/track?id=${item.userId}`
+		})
+	} else if (currentType.value === 3) {
+		// 弹窗
+		askInfo.value = {}
+		// 获取请假信息
+		getAskInfo(item.userId)
+		popup.value.open()
+	}
+}
+
+const getAskInfo = async (userId) => {
+	const res = await myRequest({
+		url: '/wanzai/api/smartAttendance/ackDetail',
+		data: {
+			userId,
+			dateTime: time.value
+		}
+	})
+	// console.log(res)
+	if (res.code == 200) {
+		const result = JSON.parse(decryptDes(res.data))
+		// console.log(result)
+		askInfo.value = result[0]
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+.statistics {
+	position: relative;
+	box-sizing: border-box;
+	padding: 130rpx 20rpx 0;
+	height: 100vh;
+	overflow: hidden;
+	background-color: #f1f6fe;
+
+	.img {
+		position: absolute;
+		top: -50rpx;
+		right: -50rpx;
+		width: 589rpx;
+		height: 320rpx;
+	}
+
+	.picker {
+		position: absolute;
+		top: 30rpx;
+		right: 20rpx;
+		width: 273rpx;
+		height: 80rpx;
+	}
+
+	.type {
+		position: relative;
+		display: flex;
+		justify-content: space-evenly;
+		align-items: center;
+		width: 710rpx;
+		height: 122rpx;
+		background-color: #fff;
+
+		.type_box {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			width: 210rpx;
+			height: 90rpx;
+			font-size: 28rpx;
+			border-radius: 10rpx;
+			background-color: #f2f6fc;
+		}
+
+		.active {
+			background-color: #3464ff;
+			color: #fff;
+		}
+	}
+
+	.list {
+		padding: 30rpx 20rpx;
+		margin-top: 20rpx;
+		max-height: calc(100vh - 402rpx);
+		font-size: 28rpx;
+		background-color: #fff;
+
+		.list_header {
+			display: flex;
+			justify-content: space-evenly;
+			align-items: center;
+			height: 73rpx;
+			background-color: #f2f6fc;
+
+			.header_box {
+				width: 33%;
+				text-align: center;
+			}
+		}
+
+		.list_content {
+			max-height: calc(100vh - 475rpx);
+			overflow-y: auto;
+
+			.list_box {
+				display: flex;
+				justify-content: space-evenly;
+				align-items: center;
+				height: 85rpx;
+				border-bottom: 2rpx solid #e5e5e5;
+
+				.box {
+					width: 33%;
+					text-align: center;
+				}
+
+				.color {
+					color: #0061ff;
+				}
+			}
+		}
+	}
+
+	.popup_box {
+		padding-bottom: 50rpx;
+		width: 710rpx;
+		border-radius: 22rpx;
+		background-color: #fff;
+
+		.pop_header {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			position: relative;
+			height: 94rpx;
+			font-size: 28rpx;
+			border-bottom: 1rpx solid #e6e6e6;
+
+			.header_icon {
+				position: absolute;
+				top: 18rpx;
+				right: 25rpx;
+				font-size: 40rpx;
+			}
+		}
+
+		.pop_info {
+			display: flex;
+			box-sizing: border-box;
+			margin-top: 22rpx;
+			padding: 0 35rpx;
+			width: 100%;
+			line-height: 42rpx;
+			font-size: 28rpx;
+
+			.info_key {
+				color: #999999;
+			}
+
+			.info_value {
+				flex: 1;
+			}
+		}
+	}
+}
+</style>

+ 10 - 6
pages/student/student.vue

@@ -9,18 +9,18 @@
 			<img
 				class="box_img"
 				mode="aspectFill"
-				:src="msg.headImage || '../../static/images/user-photo.png'"
-				@click="previewImage(msg.headImage || '../../static/images/user-photo.png')"
+				:src="msg.headImage || msg.student?.headImage || '../../static/images/user-photo.png'"
+				@click="previewImage(msg.headImage || msg.student?.headImage || '../../static/images/user-photo.png')"
 			/>
 			<view class="box_info">
-				<view class="info_name">{{ msg.name }}</view>
-				<view class="info_phone">{{ msg.cardNo }}</view>
+				<view class="info_name">{{ msg.name || msg.student?.name }}</view>
+				<view class="info_phone">{{ msg.cardNo || msg.student?.cardNo }}</view>
 			</view>
 		</view>
 
 		<!-- 家长信息区域 -->
 		<view class="identity">家长</view>
-		<view class="box mb-50" v-for="item in msg.userParents" :key="item.id">
+		<view class="box mb-50" v-for="item in msg.userParents || msg.patriarch" :key="item.id">
 			<img
 				class="box_img"
 				mode="aspectFill"
@@ -38,7 +38,7 @@
 			<view class="box_btn" @click="callPhone(item.phone)">呼叫</view>
 		</view>
 
-		<NoData v-if="!msg.userParents?.length" />
+		<NoData v-if="!msg.userParents?.length && !msg.patriarch?.length" />
 	</view>
 </template>
 
@@ -50,6 +50,10 @@ import NoData from '@/components/noData.vue'
 
 onLoad((options) => {
 	msg.value = JSON.parse(options.msg)
+
+	uni.setNavigationBarTitle({
+		title: msg.value.name || msg.value.student?.name
+	})
 })
 
 const msg = ref({})

+ 1 - 0
unpackage/dist/dev/mp-weixin/app.js

@@ -22,6 +22,7 @@ if (!Math) {
   "./pages/login2/login2.js";
   "./pages/switch/switch.js";
   "./pages/editPhone/editPhone.js";
+  "./pages/statistics/statistics.js";
   "./pagesReservation/reservation/reservation.js";
   "./pagesReservation/register/register.js";
   "./pagesReservation/record/record.js";

+ 2 - 1
unpackage/dist/dev/mp-weixin/app.json

@@ -19,7 +19,8 @@
     "pages/timeGroup/timeGroup",
     "pages/login2/login2",
     "pages/switch/switch",
-    "pages/editPhone/editPhone"
+    "pages/editPhone/editPhone",
+    "pages/statistics/statistics"
   ],
   "subPackages": [
     {

Разлика између датотеке није приказан због своје велике величине
+ 293 - 0
unpackage/dist/dev/mp-weixin/common/vendor.js


+ 1 - 0
unpackage/dist/dev/mp-weixin/components/listView.js

@@ -15,6 +15,7 @@ const _sfc_main = {
     common_vendor.onLoad(() => {
     });
     const goPage = (item) => {
+      console.log(item);
       if (props.appType == "学生轨迹") {
         common_vendor.index.navigateTo({
           url: `/pages/track/track?id=${item.id}`

+ 6 - 1
unpackage/dist/dev/mp-weixin/pages/home/home.wxss

@@ -4,7 +4,8 @@
   display: flex;
   flex-direction: column;
   padding: 0 20rpx;
-  min-height: 100vh;
+  height: 100vh;
+  overflow: hidden;
   background-color: #f1f6fe;
 }
 .container .tab.data-v-07e72d3c {
@@ -82,6 +83,7 @@
   background-color: #fff;
 }
 .container .body.data-v-07e72d3c {
+  height: calc(100vh - 550rpx);
   margin-top: 20rpx;
 }
 .container .body .body_header.data-v-07e72d3c {
@@ -163,6 +165,9 @@
   height: 42rpx;
 }
 .container .body .body_list.data-v-07e72d3c {
+  max-height: calc(100vh - 790rpx);
+  overflow-y: auto;
+  box-sizing: border-box;
   padding: 30rpx 30rpx;
   display: grid;
   grid-template-columns: repeat(3, 1fr);

+ 15 - 8
unpackage/dist/dev/mp-weixin/pages/student/student.js

@@ -9,7 +9,11 @@ const _sfc_main = {
   __name: "student",
   setup(__props) {
     common_vendor.onLoad((options) => {
+      var _a;
       msg.value = JSON.parse(options.msg);
+      common_vendor.index.setNavigationBarTitle({
+        title: msg.value.name || ((_a = msg.value.student) == null ? void 0 : _a.name)
+      });
     });
     const msg = common_vendor.ref({});
     const callPhone = (phoneNumber) => {
@@ -18,13 +22,16 @@ const _sfc_main = {
       });
     };
     return (_ctx, _cache) => {
-      var _a, _b;
+      var _a, _b, _c, _d, _e, _f, _g;
       return common_vendor.e({
-        a: msg.value.headImage || "../../static/images/user-photo.png",
-        b: common_vendor.o(($event) => common_vendor.unref(utils_previewImage.previewImage)(msg.value.headImage || "../../static/images/user-photo.png")),
-        c: common_vendor.t(msg.value.name),
-        d: common_vendor.t(msg.value.cardNo),
-        e: common_vendor.f(msg.value.userParents, (item, k0, i0) => {
+        a: msg.value.headImage || ((_a = msg.value.student) == null ? void 0 : _a.headImage) || "../../static/images/user-photo.png",
+        b: common_vendor.o(($event) => {
+          var _a2;
+          return common_vendor.unref(utils_previewImage.previewImage)(msg.value.headImage || ((_a2 = msg.value.student) == null ? void 0 : _a2.headImage) || "../../static/images/user-photo.png");
+        }),
+        c: common_vendor.t(msg.value.name || ((_b = msg.value.student) == null ? void 0 : _b.name)),
+        d: common_vendor.t(msg.value.cardNo || ((_c = msg.value.student) == null ? void 0 : _c.cardNo)),
+        e: common_vendor.f(msg.value.userParents || msg.value.patriarch, (item, k0, i0) => {
           return {
             a: item.headImage || "../../static/images/user-photo.png",
             b: common_vendor.o(($event) => common_vendor.unref(utils_previewImage.previewImage)(item.headImage || "../../static/images/user-photo.png"), item.id),
@@ -34,8 +41,8 @@ const _sfc_main = {
             f: item.id
           };
         }),
-        f: !((_a = msg.value.userParents) == null ? void 0 : _a.length)
-      }, !((_b = msg.value.userParents) == null ? void 0 : _b.length) ? {} : {});
+        f: !((_d = msg.value.userParents) == null ? void 0 : _d.length) && !((_e = msg.value.patriarch) == null ? void 0 : _e.length)
+      }, !((_f = msg.value.userParents) == null ? void 0 : _f.length) && !((_g = msg.value.patriarch) == null ? void 0 : _g.length) ? {} : {});
     };
   }
 };

+ 1 - 1
unpackage/dist/dev/mp-weixin/pages/student/student.json

@@ -1,5 +1,5 @@
 {
-  "navigationBarTitleText": "学生名",
+  "navigationBarTitleText": "",
   "enablePullDownRefresh": false,
   "usingComponents": {
     "no-data": "../../components/noData"

+ 2 - 9
unpackage/dist/dev/mp-weixin/project.private.config.json

@@ -8,15 +8,8 @@
     "miniprogram": {
       "list": [
         {
-          "name": "pagesReservation/register/register",
-          "pathName": "pagesReservation/register/register",
-          "query": "type=2",
-          "launchMode": "default",
-          "scene": null
-        },
-        {
-          "name": "pagesReservation/backlog/backlog",
-          "pathName": "pagesReservation/backlog/backlog",
+          "name": "pages/statistics/statistics",
+          "pathName": "pages/statistics/statistics",
           "query": "",
           "launchMode": "default",
           "scene": null