wwp 6 месяцев назад
Родитель
Сommit
63cae06080
20 измененных файлов: 518 добавлений и 298 удалений
  1. +4
    -0
      SafeCampus.WEB/src/api/modules/attendance/roolcall.ts
  2. +16
    -0
      SafeCampus.WEB/src/api/modules/violation/portraitSummary.ts
  3. +2
    -0
      SafeCampus.WEB/src/views/attendance/behaviorTrace/index.vue
  4. +5
    -3
      SafeCampus.WEB/src/views/attendance/roolcall/components/form/index.vue
  5. +47
    -19
      SafeCampus.WEB/src/views/attendance/roolcall/detail.vue
  6. +3
    -1
      SafeCampus.WEB/src/views/attendance/roolcall/index.vue
  7. +2
    -0
      SafeCampus.WEB/src/views/userManage/personnel/components/form/form_basic.vue
  8. +2
    -2
      SafeCampus.WEB/src/views/userManage/personnel/components/form/index.vue
  9. +2
    -0
      SafeCampus.WEB/src/views/userManage/personnel/index.vue
  10. +188
    -145
      SafeCampus.WEB/src/views/violation/portrait/detail.vue
  11. +2
    -2
      monitorMobile/App.vue
  12. +38
    -0
      monitorMobile/api/work/rollCall.js
  13. +31
    -4
      monitorMobile/http/api.js
  14. +6
    -3
      monitorMobile/pages.json
  15. +1
    -0
      monitorMobile/pages/login.vue
  16. +1
    -1
      monitorMobile/pages/my/index.vue
  17. +2
    -3
      monitorMobile/pages/work/passengerFlow/index.vue
  18. +95
    -58
      monitorMobile/pages/work/rollCall/detail.vue
  19. +34
    -52
      monitorMobile/pages/work/rollCall/index.vue
  20. +37
    -5
      monitorMobile/store/index.js

+ 4
- 0
SafeCampus.WEB/src/api/modules/attendance/roolcall.ts Просмотреть файл

@@ -48,6 +48,10 @@ const attendanceRoolcallApi = {
/** 修改点名任务 */ /** 修改点名任务 */
update(params: any) { update(params: any) {
return http.put("update", params); return http.put("update", params);
},
/** 手动点名 */
manualRoll(params: any) {
return http.post("manualRoll", params);
} }
}; };




+ 16
- 0
SafeCampus.WEB/src/api/modules/violation/portraitSummary.ts Просмотреть файл

@@ -39,6 +39,22 @@ const portraitSummaryApi = {
/** 获取学生属性标签 */ /** 获取学生属性标签 */
getStudentDetail(params: any) { getStudentDetail(params: any) {
return http.get("getStudentDetail", params); return http.get("getStudentDetail", params);
},
/* 学生-出勤情况 */
getStudentAttendance(params: any) {
return http.post("attendance", params);
},
/* 学生-出校 */
getStudentOutSchool(params: any) {
return http.post("outsideSchool", params);
},
/* 学生-图书馆 */
getStudentLibrary(params: any) {
return http.post("library", params);
},
/* 学生-食堂 */
getStudentCanteen(params: any) {
return http.post("canteen", params);
} }
}; };




+ 2
- 0
SafeCampus.WEB/src/views/attendance/behaviorTrace/index.vue Просмотреть файл

@@ -187,6 +187,8 @@ const detialRef = ref<InstanceType<typeof TraceShow> | null>(null);
onMounted(async () => { onMounted(async () => {
// 获取系部下拉数据 // 获取系部下拉数据
departmentOptions.value = await getDepartmentList() departmentOptions.value = await getDepartmentList()
// 获取班级
classOptions.value = await getClassList('')
}); });
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">


+ 5
- 3
SafeCampus.WEB/src/views/attendance/roolcall/components/form/index.vue Просмотреть файл

@@ -101,9 +101,9 @@ const rules = reactive({
similarity: [required("请选择相似度")], similarity: [required("请选择相似度")],
cameraId: [required("请选择摄像头")], cameraId: [required("请选择摄像头")],
continueTime: [required("请选择持续时间")], continueTime: [required("请选择持续时间")],
personSetId: [required("请选择所属班级")],
depId: [required("请选择系部")],
majorId: [required("请选择专业")]
personSetId: [required("请选择所属班级")]
// depId: [required("请选择系部")],
// majorId: [required("请选择专业")]
}); });


/** /**
@@ -112,6 +112,8 @@ const rules = reactive({
*/ */
async function onOpen(props: FormProps.Base<any>) { async function onOpen(props: FormProps.Base<any>) {
departmentOptions.value = await getDepartmentList(); departmentOptions.value = await getDepartmentList();
// 获取班级
classOptions.value = await getClassList("");
Object.assign(sysUserProps, props); //合并参数 Object.assign(sysUserProps, props); //合并参数
visible.value = true; //显示表单 visible.value = true; //显示表单
/* 监听系部、专业 */ /* 监听系部、专业 */


+ 47
- 19
SafeCampus.WEB/src/views/attendance/roolcall/detail.vue Просмотреть файл

@@ -8,7 +8,7 @@
><el-text class="mx-1" type="primary" size="large">应到:{{ listData.length }}人</el-text></el-col ><el-text class="mx-1" type="primary" size="large">应到:{{ listData.length }}人</el-text></el-col
> >
<el-col :span="6" <el-col :span="6"
><el-text class="mx-1" type="success" size="large">实到:{{ HighlightData.length }}人</el-text>
><el-text class="mx-1" type="success" size="large">实到:{{ listData.length - UnRollCallData.length }}人</el-text>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<el-text class="mx-1" type="warning" size="large">趴桌子:{{ LieOnTable.length }}人</el-text></el-col <el-text class="mx-1" type="warning" size="large">趴桌子:{{ LieOnTable.length }}人</el-text></el-col
@@ -20,9 +20,9 @@
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="24" <el-col :span="24"
><el-row class="rowbg"> ><el-row class="rowbg">
<el-col :xl="4" :lg="4" :md="6" :sm="8" :xs="12" v-for="(item, index) in listData" :key="index"
<el-col :xl="3" :lg="4" :md="6" :sm="8" :xs="12" v-for="(item, index) in listData" :key="index"
><div class="grid-content"> ><div class="grid-content">
<div class="imgBox" :class="{ active: item.status === 1 ? true : false }">
<div class="imgBox" :class="{ active: item.alarmTypes?.includes('class_room_call') }">
<el-image <el-image
v-if="item.faces && item.faces.length > 0" v-if="item.faces && item.faces.length > 0"
style="width: 100px; height: 100px" style="width: 100px; height: 100px"
@@ -42,6 +42,9 @@
{{ item.personSetName }} {{ item.personSetName }}
</div> </div>
</div> </div>
<div v-if="!item.alarmTypes?.includes('class_room_call')" class="btn btns" style="justify-content: center; border-top: none">
<el-button size="small" type="primary" @click="checkOut(item, index)">签到</el-button>
</div>
</div></el-col </div></el-col
> >
</el-row></el-col </el-row></el-col
@@ -122,24 +125,21 @@ const Highlight = () => {
}) })
.then((res: any) => { .then((res: any) => {
HighlightData.value = res.data.list; HighlightData.value = res.data.list;
listData.value
.map((item: any) => {
item.status = 0;
return item;
})
.forEach((item: any) => {
HighlightData.value.forEach((item1: any) => {
if (item.personId === item1.personId) {
item.status = 1;
}
});
listData.value = listData.value.map((e: any) => {
e.alarmTypes = [];
// alarmType:lie_on_table 趴桌子 class_room_call 点名(实到)
let arr = HighlightData.value.filter((e1: any) => {
return e1.personId == e.personId;
}); });
e.alarmTypes = arr.map((e: any) => e.alarmType);
return e;
});
// 未点名人员摘取 // 未点名人员摘取
UnRollCallData.value = JSON.parse(JSON.stringify(listData.value)).filter((item: any) => item.status == 0);
UnRollCallData.value = JSON.parse(JSON.stringify(listData.value)).filter((item: any) => !item.alarmTypes.includes("class_room_call"));
// 未识别人员摘取 // 未识别人员摘取
UnrecognizedD.value = JSON.parse(JSON.stringify(HighlightData.value)).filter((item: any) => !item.personId); UnrecognizedD.value = JSON.parse(JSON.stringify(HighlightData.value)).filter((item: any) => !item.personId);
// 趴桌子人员摘取 // 趴桌子人员摘取
LieOnTable.value = JSON.parse(JSON.stringify(HighlightData.value)).filter((item: any) => item.alarmType == "lie_on_table");
LieOnTable.value = JSON.parse(JSON.stringify(listData.value)).filter((item: any) => item.alarmTypes.includes("lie_on_table"));


console.log("未识别人员摘取:", UnrecognizedD.value, ",趴桌子人员摘取:", LieOnTable.value, ",未点名人员摘取:", UnRollCallData.value); console.log("未识别人员摘取:", UnrecognizedD.value, ",趴桌子人员摘取:", LieOnTable.value, ",未点名人员摘取:", UnRollCallData.value);
}); });
@@ -151,6 +151,20 @@ const assignFn = (item: any) => {
const checkOut = (item: any, index: number) => { const checkOut = (item: any, index: number) => {
checkIndex.value = index; checkIndex.value = index;
checkData.value = JSON.parse(JSON.stringify(item)); checkData.value = JSON.parse(JSON.stringify(item));

attendanceRoolcallApi.manualRoll([{ personId: item.personId, personSetId: item.personSetId, taskId: route.query.taskId }]).then(() => {
ElMessage({
message: "点名成功",
type: "success"
});
UnrecognizedD.value = UnrecognizedD.value.filter((item1: any) => item1.id !== item.id);
listData.value.map((item2: any) => {
if (item2.personId === item.personId) {
item2.alarmTypes.push("class_room_call");
UnRollCallData.value = JSON.parse(JSON.stringify(listData.value)).filter((item: any) => !item.alarmTypes.includes("class_room_call"));
}
});
});
}; };
const submitFn = () => { const submitFn = () => {
if (!checkIndex.value && checkIndex.value !== 0) { if (!checkIndex.value && checkIndex.value !== 0) {
@@ -162,7 +176,7 @@ const submitFn = () => {
} }
visible.value = false; visible.value = false;


attendanceRoolcallApi.update({ id: assignId.value, personId: checkData.value.personId, personSetId: checkData.value.personSetId }).then(() => {
attendanceRoolcallApi.update({ taskId: assignId.value, personId: checkData.value.personId, personSetId: checkData.value.personSetId }).then(() => {
ElMessage({ ElMessage({
message: "指派成功", message: "指派成功",
type: "success" type: "success"
@@ -209,11 +223,26 @@ onMounted(() => {
height: 190px; height: 190px;
margin-bottom: 20px; margin-bottom: 20px;
.grid-content { .grid-content {
position: relative;
box-sizing: border-box; box-sizing: border-box;
height: 100%;

// height: 100%;
padding: 15px; padding: 15px;
margin: 10px; margin: 10px;
background: #ffffff; background: #ffffff;
.btns {
position: absolute;
top: 0;
left: 0;
width: 100%;
background: rgb(0 0 0 / 80%);
opacity: 0;
}
&:hover {
.btns {
opacity: 1;
}
}
.imgBox { .imgBox {
display: flex; display: flex;
align-items: center; align-items: center;
@@ -233,7 +262,6 @@ onMounted(() => {
} }
} }
.info { .info {
height: 80px;
.label { .label {
margin-right: 8px; margin-right: 8px;
font-size: 14px; font-size: 14px;


+ 3
- 1
SafeCampus.WEB/src/views/attendance/roolcall/index.vue Просмотреть файл

@@ -181,7 +181,9 @@ const RefreshTable = () => {
} }
onMounted(async () => { onMounted(async () => {
// 获取系部下拉数据 // 获取系部下拉数据
departmentOptions.value = await getDepartmentList()
departmentOptions.value = await getDepartmentList();
// 获取班级
classOptions.value = await getClassList('')
}); });
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">


+ 2
- 0
SafeCampus.WEB/src/views/userManage/personnel/components/form/form_basic.vue Просмотреть файл

@@ -156,6 +156,8 @@ const genderOptions = ref([
]); ]);
onMounted(async () => { onMounted(async () => {
departmentOptions.value = await getDepartmentList(); departmentOptions.value = await getDepartmentList();
// 获取班级
classOptions.value = await getClassList("");
// 初始化 // 初始化
userInfo.value.gender = userInfo.value.gender ? userInfo.value.gender : genderOptions.value[0].value; userInfo.value.gender = userInfo.value.gender ? userInfo.value.gender : genderOptions.value[0].value;
if (userInfo.value.personId) { if (userInfo.value.personId) {


+ 2
- 2
SafeCampus.WEB/src/views/userManage/personnel/components/form/index.vue Просмотреть файл

@@ -49,8 +49,8 @@ const rules = reactive({
gender: [required("请选择性别")], gender: [required("请选择性别")],
faces: [required("请上传人脸图片")], faces: [required("请上传人脸图片")],
phone: [required("请输入手机号")], phone: [required("请输入手机号")],
depId: [required("请选择系部")],
majorId: [required("请选择专业")],
// depId: [required("请选择系部")],
// majorId: [required("请选择专业")],
personSetId: [required("请选择班级")] personSetId: [required("请选择班级")]
}); });




+ 2
- 0
SafeCampus.WEB/src/views/userManage/personnel/index.vue Просмотреть файл

@@ -281,6 +281,8 @@ const handleAvatarSuccess: UploadProps["onSuccess"] = (response) => {
onMounted(async () => { onMounted(async () => {
// 获取系部下拉数据 // 获取系部下拉数据
departmentOptions.value = await getDepartmentList() departmentOptions.value = await getDepartmentList()
// 获取班级
classOptions.value = await getClassList("");
}); });
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">


+ 188
- 145
SafeCampus.WEB/src/views/violation/portrait/detail.vue
Разница между файлами не показана из-за своего большого размера
Просмотреть файл


+ 2
- 2
monitorMobile/App.vue Просмотреть файл

@@ -2,7 +2,7 @@
export default { export default {
onLaunch: function() {}, onLaunch: function() {},
onShow: function() {}, onShow: function() {},
onHide: function() {}
onHide: function() {},
} }
</script> </script>


@@ -11,7 +11,7 @@
@import "uview-ui/index.scss"; @import "uview-ui/index.scss";


@font-face { @font-face {
font-family: 'Alimama ShuHeiTi';//字体别名
font-family: 'Alimama ShuHeiTi'; //字体别名
src: url('/static/fonts/alimamashuheiti.ttf') format('truetype'); src: url('/static/fonts/alimamashuheiti.ttf') format('truetype');
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;


+ 38
- 0
monitorMobile/api/work/rollCall.js Просмотреть файл

@@ -0,0 +1,38 @@
import http from '@/http/api.js'
const url = '/api/business/classRoomCallApi'

// 获取列表
export const page = (params) => {
return http.request({
url: url + '/getPageList',
method: 'get',
params
})
}

// 获取不分页列表
export const list = (params) => {
return http.request({
url: url + '/getNoPageList',
method: 'get',
params
})
}

// 获取点名列表某一项所有人员
export const detail = (data) => {
return http.request({
url: '/api/business/personApi/pageQuery',
method: 'post',
data
})
}

// 获取点名任务列表
export const taskPage = (params) => {
return http.request({
url: url + '/getTaskPageList',
method: 'get',
params
})
}

+ 31
- 4
monitorMobile/http/api.js Просмотреть файл

@@ -3,11 +3,23 @@ import {
} from '@/http/config.js'; } from '@/http/config.js';
import Request from '@/utils/luch-request/index.js'; import Request from '@/utils/luch-request/index.js';
const http = new Request(options); const http = new Request(options);
import store from "@/store"
http.interceptors.request.use((config) => { // 可使用async await 做异步操作 http.interceptors.request.use((config) => { // 可使用async await 做异步操作
// 假设有token值需要在头部需要携带 // 假设有token值需要在头部需要携带
let token = uni.getStorageSync('token'); let token = uni.getStorageSync('token');
if (token) { if (token) {
config.header['Authorization'] = 'Bearer ' + token; config.header['Authorization'] = 'Bearer ' + token;
const jwt = decryptJWT(token);
const exp = getJWTDate(jwt.exp);
// token 已经过期
if (new Date() <= exp) {
let refreshToken = store.state.refreshToken;
// 携带刷新 token
if (refreshToken) {
config.header["X-" + 'Authorization'] = 'Bearer ' + refreshToken;
}
}
} }


// #ifndef H5 // #ifndef H5
@@ -22,10 +34,7 @@ http.interceptors.request.use((config) => { // 可使用async await 做异步操
return Promise.reject(config) return Promise.reject(config)
}) })
http.interceptors.response.use((response) => { http.interceptors.response.use((response) => {
// 若有数据返回则通过
if (response.data.access_token || response.data.key) {
return response.data
}
checkAndStoreAuthentication(response)
// 服务端返回的状态码不等于200,则reject() // 服务端返回的状态码不等于200,则reject()
if (response.data.code && response.data.code !== 200) { if (response.data.code && response.data.code !== 200) {
setTimeout(() => { setTimeout(() => {
@@ -49,6 +58,7 @@ http.interceptors.response.use((response) => {
if (response.statusCode == 401) { if (response.statusCode == 401) {
const pages = getCurrentPages() const pages = getCurrentPages()
const currentPage = pages[pages.length - 1] const currentPage = pages[pages.length - 1]
this.$store.dispatch('clearToken')
uni.redirectTo({ uni.redirectTo({
url: `/pages/login?redirect=/${currentPage.route}` url: `/pages/login?redirect=/${currentPage.route}`
}) })
@@ -74,4 +84,21 @@ function decryptJWT(token) {
function getJWTDate(timestamp) { function getJWTDate(timestamp) {
return new Date(timestamp * 1000); return new Date(timestamp * 1000);
} }
/**
* 检查并存储授权信息
* @param res 响应对象
*/
const checkAndStoreAuthentication = (res) => {
// 读取响应报文头 token 信息
let token = res.header['access-token'];
let refreshToken = res.header['x-access-token'];
// 判断是否是无效 token
if (token === "invalid_token") {
stroe.dispatch('clearToken')
}
// 判断是否存在刷新 token,如果存在则存储在本地
else if (refreshToken && token && token !== "invalid_token") {
stroe.dispatch('setToken',{token,refreshToken})
}
}
export default http; export default http;

+ 6
- 3
monitorMobile/pages.json Просмотреть файл

@@ -57,7 +57,8 @@
{ {
"path": "pages/work/returnBed/index", "path": "pages/work/returnBed/index",
"style": { "style": {
"navigationBarTitleText": "归寝"
"navigationBarTitleText": "归寝",
"enablePullDownRefresh": true
} }
}, },
{ {
@@ -71,7 +72,8 @@
{ {
"path": "pages/work/passengerFlow/index", "path": "pages/work/passengerFlow/index",
"style": { "style": {
"navigationBarTitleText": "客流"
"navigationBarTitleText": "客流",
"enablePullDownRefresh": true
} }
}, },
{ {
@@ -85,7 +87,8 @@
{ {
"path": "pages/work/rollCall/index", "path": "pages/work/rollCall/index",
"style": { "style": {
"navigationBarTitleText": "点名"
"navigationBarTitleText": "点名",
"enablePullDownRefresh": true
} }
}, },
{ {


+ 1
- 0
monitorMobile/pages/login.vue Просмотреть файл

@@ -89,6 +89,7 @@
let data = res.data let data = res.data
this.$store.dispatch('setToken',{token:data.token}) this.$store.dispatch('setToken',{token:data.token})
this.$store.dispatch('getUserInfo') this.$store.dispatch('getUserInfo')
this.$store.dispatch('getAllOptions')
this.NAV_TO('/') this.NAV_TO('/')
}).finally(() => { }).finally(() => {
this.isLoading = false this.isLoading = false


+ 1
- 1
monitorMobile/pages/my/index.vue Просмотреть файл

@@ -125,7 +125,7 @@
}, },
loginOut() { loginOut() {
this.CONFIRM('您是否确认退出登录?').then(()=>{ this.CONFIRM('您是否确认退出登录?').then(()=>{
this.$store.dispatch('clearToken')
this.CLEAR_STORAGE()
this.JUMP_TO('/pages/login') this.JUMP_TO('/pages/login')
}) })
} }


+ 2
- 3
monitorMobile/pages/work/passengerFlow/index.vue Просмотреть файл

@@ -37,7 +37,6 @@
</u-list> </u-list>
</view> </view>
</template> </template>

<script> <script>
export default { export default {
data() { data() {
@@ -46,8 +45,8 @@
isLoading: false, isLoading: false,
status: 'loadmore', //loading正在加载 loadmore加载更多 nomore没有更多了 status: 'loadmore', //loading正在加载 loadmore加载更多 nomore没有更多了
page: { page: {
size: 8,
page: 8,
pageNum: 1,
pageSize: 10,
} }
} }
}, },


+ 95
- 58
monitorMobile/pages/work/rollCall/detail.vue Просмотреть файл

@@ -1,63 +1,66 @@
<template> <template>
<view style="height: 100%;"> <view style="height: 100%;">
<view class="title"> <view class="title">
应到:8
应到:{{list.length}}
</view> </view>
<view style="padding: 26rpx;overflow: hidden;"> <view style="padding: 26rpx;overflow: hidden;">
<view class="cate"> <view class="cate">
<view class="cateList"> <view class="cateList">
<view v-for="item in cateList" :class="{active:item.value == cate}" :key="item.value" class="item" <view v-for="item in cateList" :class="{active:item.value == cate}" :key="item.value" class="item"
@click="cateItemClick(item)"> @click="cateItemClick(item)">
{{item.label}}({{item.value}})
{{item.label}}({{item.num}})
</view> </view>
</view> </view>
</view> </view>
</view> </view>
<view style="height:calc(100% - 200rpx);overflow: auto;"> <view style="height:calc(100% - 200rpx);overflow: auto;">
<view class="list"> <view class="list">
<view v-for="(item, index) in list" :key="index" class="item" @click="popupShow(item)">
<view class="right">
<image src="@/static/image/test/image2.png" mode="aspectFill"
style="width: 160rpx;height: 160rpx;border-radius:10rpx"></image>
<view class="des">
<view class="top">
<view class="status"
:style="{backgroundColor:cate == 1?'#0FAF76':cate == 2?'#EF2D2D':'#F49D19' }">
{{cateList.find(e=>e.value == cate).label}}
<template v-for="(item, index) in list">
<view class="item" @click="popupShow(item)" :key="index" v-show="cateList.length&&cateList[cate].show(item)">
<view class="right">
<image src="@/static/image/test/image2.png" mode="aspectFill"
style="width: 160rpx;height: 160rpx;border-radius:10rpx"></image>
<view class="des">
<view class="top">
<view class="status"
:style="{backgroundColor:cate == 0?'#0FAF76':cate == 1?'#EF2D2D':'#F49D19' }">
{{cateList.find(e=>e.value == cate)?cateList.find(e=>e.value == cate).label:''}}
</view>
<view class="name">
{{item.name}}
</view>
</view> </view>
<view class="name">
杨云
<view class="depart">
系部:{{item.majorName}}
</view>
<view class="bottom">
<view class="major">专业:{{item.depName}}</view>
<view class="class">班级:{{item.personSetName}}</view>
</view> </view>
</view>
<view class="depart">
系部:安环部
</view>
<view class="bottom">
<view class="major">专业:环艺</view>
<view class="class">班级:第二班</view>
</view> </view>
</view> </view>
</view> </view>
</view>
</template>
</view> </view>
</view> </view>
<u-popup :show="show" mode="center" :round="10"> <u-popup :show="show" mode="center" :round="10">
<view class="popupInfo"> <view class="popupInfo">
<image src="/static/image/test/image.png" mode="widthFix" style="width: 480rpx;border-radius:10rpx"></image>
<image src="/static/image/test/image.png" mode="widthFix" style="width: 480rpx;border-radius:10rpx">
</image>
<view class="top"> <view class="top">
<view class="status" :style="{backgroundColor:cate == 1?'#0FAF76':cate == 2?'#EF2D2D':'#F49D19' }">
{{cateList.find(e=>e.value == cate).label}}
<view class="status" :style="{backgroundColor:cate == 0?'#0FAF76':cate == 1?'#EF2D2D':'#F49D19' }">
{{cateList.find(e=>e.value == cate)?cateList.find(e=>e.value == cate).label:''}}
</view> </view>
<view class="name"> <view class="name">
杨云
{{popupInfo.name}}
</view> </view>
</view> </view>
<view class="depart"> <view class="depart">
系部:安环部
系部:{{popupInfo.majorName}}
</view> </view>
<view class="bottom"> <view class="bottom">
<view class="major">专业:环艺</view>
<view class="class">班级:第二班</view>
<view class="major">专业:{{popupInfo.depName}}</view>
<view class="class">班级:{{popupInfo.personSetName}}</view>
</view> </view>
<view class="closeBox"> <view class="closeBox">
<image @click="show = false" src="/static/image/close.png" class="close"></image> <image @click="show = false" src="/static/image/close.png" class="close"></image>
@@ -68,44 +71,77 @@
</template> </template>


<script> <script>
import {
detail,
page
} from '@/api/work/rollCall.js'
export default { export default {
data() { data() {
return { return {
list: [{
name: 1
}, {
name: 2
}, {
name: 3
}],
cateList: [{
value: 1,
label: '实到'
},
{
value: 2,
label: '未到'
},
{
value: 3,
label: '趴桌子'
},
{
value: 4,
label: '玩手机'
},
{
value: 5,
label: '睡觉'
},
],
cate: 1,
list: [],
alarmList: [],
cateList: [],
cate: 0,
checkboxValue: [], checkboxValue: [],


show: false, show: false,
popupInfo: {}, popupInfo: {},
} }
}, },
async mounted() {
const {
personSetId,
taskId
} = this.options
// 班级人员
if (personSetId) {
await detail({
personSetId,
pageSize: 1000,
pageNum: 1
}).then(res => {
if (res.code != 200) return
this.list = res.data.list
})
}
// 监控行为列表
if (taskId) {
page({
taskId,
pageSize: 1000,
pageNum: 1
}).then(res => {
if (res.code != 200) return
this.alarmList = res.data.list
this.list = this.list.map(e => {
e.alarmTypes = []
// alarmType:lie_on_table 趴桌子 class_room_call 点名(实到)
let arr = this.alarmList.filter(e1 => e1.personId == e.personId)
e.alarmTypes = arr.map(e=>e.alarmType)
return e
})
this.cateList = [{
value: 0,
label: '实到',
show:(item)=>item.alarmTypes.includes('class_room_call'),
num: this.list.filter(e=>e.alarmTypes.includes('class_room_call')).length,
},
{
value: 1,
label: '未到',
show:(item)=>!item.alarmTypes.includes('class_room_call'),
num: this.list.filter(e=>!e.alarmTypes.includes('class_room_call')).length
},
{
value: 2,
label: '趴桌子',
show:(item)=>item.alarmTypes.includes('lie_on_table'),
num: this.list.filter(e=>e.alarmTypes.includes('lie_on_table')).length,
},
]
})
}
},
methods: { methods: {
cateItemClick(item) { cateItemClick(item) {
this.cate = item.value this.cate = item.value
@@ -166,8 +202,9 @@
width: 100%; width: 100%;
position: absolute; position: absolute;
left: 0; left: 0;
bottom:-98rpx;
bottom: -98rpx;
text-align: center; text-align: center;

.close { .close {
width: 60rpx; width: 60rpx;
height: 60rpx; height: 60rpx;


+ 34
- 52
monitorMobile/pages/work/rollCall/index.vue Просмотреть файл

@@ -1,7 +1,8 @@
<template> <template>
<view style="height: 100%;"> <view style="height: 100%;">
<view class="topBox"> <view class="topBox">
<SelectRadio v-model="search.departCalss" align="center" placeholder="请选择摄像头" :options="[{value:1,label:'走廊尽头(海康)'},{value:2,label:'厨房(海康)'},{value:3,label:'走廊尽头(海康)'},{value:4,label:'厨房(海康)'}]" />
<SelectRadio v-model="search.CameraId" align="center" placeholder="请选择摄像头" @change="refresh"
:options="allOptions.monitorList" />
</view> </view>
<u-empty marginTop="100rpx" :show="false" mode="list" text="暂无数据"></u-empty> <u-empty marginTop="100rpx" :show="false" mode="list" text="暂无数据"></u-empty>
<u-list @scrolltolower="scrolltolower" style="height: calc(100% - 150rpx);"> <u-list @scrolltolower="scrolltolower" style="height: calc(100% - 150rpx);">
@@ -10,19 +11,19 @@
<view :class="{whiteCard:true,active:checkboxValue.includes(item.name)}"> <view :class="{whiteCard:true,active:checkboxValue.includes(item.name)}">
<view class="left"> <view class="left">
<view class="row1"> <view class="row1">
教室(海康)
{{item.cameraName}}
</view> </view>
<view class="row2"> <view class="row2">
<view class=""> <view class="">
持续时间:20
持续时间:{{item.continueTime}}
</view> </view>
<view class=""> <view class="">
相似度:0.5
相似度:{{item.similarity}}
</view> </view>
</view> </view>
</view> </view>
<view class="right" v-show="!isManage"> <view class="right" v-show="!isManage">
<view class="btn" @click="NAV_TO('./detail')">
<view class="btn" @click="NAV_TO('./detail',{personSetId:item.personSetId,taskId:item.taskId})">
<view> <view>
<image src="@/static/image/seeBlue.png" mode="aspectFill"></image> <image src="@/static/image/seeBlue.png" mode="aspectFill"></image>
</view> </view>
@@ -38,39 +39,24 @@


<script> <script>
import SelectRadio from "@/components/selectRadio.vue" import SelectRadio from "@/components/selectRadio.vue"
import {
taskPage
} from '@/api/work/rollCall.js'
export default { export default {
components: { components: {
SelectRadio SelectRadio
}, },
data() { data() {
return { return {
list: [{
name: 1
}, {
name: 2
}, {
name: 3
}, {
name: 4
}, {
name: 5
}, {
name: 6
}, {
name: 7
}, {
name: 8
}, {
name: 9
}],
list: [],
isLoading: false, isLoading: false,
status: 'loadmore', //loading正在加载 loadmore加载更多 nomore没有更多了 status: 'loadmore', //loading正在加载 loadmore加载更多 nomore没有更多了
search: { search: {
class: '',
CameraId: '',
}, },
page: { page: {
size: 8,
page: 8,
pageNum: 1,
pageSize: 10,
}, },
checkboxValue: [], checkboxValue: [],
isManage: false, isManage: false,
@@ -83,48 +69,41 @@
loadmore() { loadmore() {
if (this.status != 'loadmore') return if (this.status != 'loadmore') return
this.status = 'loading' this.status = 'loading'
setTimeout(() => {
for (let i = 0; i < 1; i++) {
this.list.push({}, {}, {}, {}, {}, {})
}
// 获取到的总条数>=接口总条数 || 接口总条数为0
if (this.list.length >= 14) {
taskPage({
...this.page,
...this.search
}).then(res => {
if(res.code != 200)return
res.data.list.forEach(e=>{
this.list.push(e)
})
// 获取到的总条数>=接口总条数
if (this.list.length >= res.data.total) {
this.status = 'nomore' this.status = 'nomore'
} else { } else {
this.status = 'loadmore' this.status = 'loadmore'
} }
}, 2000)
})
}, },
refresh() { refresh() {
this.status = 'loadmore' this.status = 'loadmore'
this.list = [] this.list = []
this.page.page = 1
this.page.pageNum = 1
this.loadmore() this.loadmore()
}, },
manageClick() {
this.checkboxValue = []
this.isManage = this.isManage ? false : true
},
radioChange(e) {
if (e) {
let ids = this.list.map(e => e.name)
this.checkboxValue = ids
} else {
this.checkboxValue = []
}
},
pullDownRefresh() {
this.refresh()
}
}, },
onLoad() { onLoad() {
console.log(this.allOptions)
this.loadmore() this.loadmore()
}, },
onPullDownRefresh(){
uni.stopPullDownRefresh()
this.refresh()
}
} }
</script> </script>


<style lang="scss" scoped> <style lang="scss" scoped>

.topBox { .topBox {
padding: 26rpx 30rpx; padding: 26rpx 30rpx;
} }
@@ -159,9 +138,11 @@
padding: 30rpx; padding: 30rpx;
color: #333333; color: #333333;
display: flex; display: flex;
.left{

.left {
width: 76%; width: 76%;
} }

.row1 { .row1 {
font-size: 32rpx; font-size: 32rpx;
font-weight: 700; font-weight: 700;
@@ -179,6 +160,7 @@
justify-content: right; justify-content: right;
flex: 1; flex: 1;
padding-top: 19rpx; padding-top: 19rpx;

.btn { .btn {
text-align: center; text-align: center;




+ 37
- 5
monitorMobile/store/index.js Просмотреть файл

@@ -4,6 +4,9 @@ Vue.use(Vuex)
import { import {
getLoginUser getLoginUser
} from '@/api/user.js' } from '@/api/user.js'
import {
list as monitorList
} from '@/api/monitor/index.js'


let lifeData = {}; let lifeData = {};


@@ -15,7 +18,7 @@ try {
} }


// 需要永久存储,且下次APP启动需要取出的,在state中的变量名 // 需要永久存储,且下次APP启动需要取出的,在state中的变量名
let saveStateKeys = ['token', 'userInfo'];
let saveStateKeys = ['token', 'userInfo', 'allOptions', 'refreshToken'];


// 保存变量到本地存储中 // 保存变量到本地存储中
const saveLifeData = function(key, value) { const saveLifeData = function(key, value) {
@@ -42,14 +45,17 @@ const store = new Vuex.Store({
// 如果上面从本地获取的lifeData对象下有对应的属性,就赋值给state中对应的变量 // 如果上面从本地获取的lifeData对象下有对应的属性,就赋值给state中对应的变量
userInfo: lifeData.userInfo || null, userInfo: lifeData.userInfo || null,
token: lifeData.accessToken || '', token: lifeData.accessToken || '',
refreshToken: '',
refreshToken: lifeData.refreshToken || '',
allOptions: lifeData.allOptions || {
monitorList: [], //摄像头列表
},
}, },
actions: { actions: {
async getUserInfo(context) { async getUserInfo(context) {
const { const {
data data
} = await getLoginUser(); } = await getLoginUser();
if(data){
if (data) {
context.commit('$uStore', { context.commit('$uStore', {
name: 'userInfo', name: 'userInfo',
value: data value: data
@@ -57,17 +63,43 @@ const store = new Vuex.Store({
} }
return data; return data;
}, },
setToken(context,payload){
setToken(context, payload) {
context.commit('$uStore', { context.commit('$uStore', {
name: 'token', name: 'token',
value: payload.token value: payload.token
}) })
context.commit('$uStore', {
name: 'token',
value: payload.refreshToken || ''
})
}, },
clearToken(context){
clearToken(context) {
context.commit('$uStore', { context.commit('$uStore', {
name: 'token', name: 'token',
value: '' value: ''
}) })
context.commit('refreshToken', {
name: 'token',
value: ''
})
},
async getAllOptions(context) {
let allOptions = {}
// 摄像头列表
await monitorList({
pageSize: 1000
}).then(res => {
if (res.code != 200) return
allOptions.monitorList = res.data.list.map(e => {
e.value = e.sensorId
e.label = e.sensorName
return e
})
})
context.commit('$uStore', {
name: 'allOptions',
value: allOptions
})
} }
}, },
mutations: { mutations: {


Загрузка…
Отмена
Сохранить