@@ -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); | |||||
} | } | ||||
}; | }; | ||||
@@ -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); | |||||
} | } | ||||
}; | }; | ||||
@@ -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"> | ||||
@@ -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; //显示表单 | ||||
/* 监听系部、专业 */ | /* 监听系部、专业 */ | ||||
@@ -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; | ||||
@@ -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"> | ||||
@@ -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) { | ||||
@@ -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("请选择班级")] | ||||
}); | }); | ||||
@@ -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"> | ||||
@@ -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; | ||||
@@ -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 | |||||
}) | |||||
} |
@@ -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; |
@@ -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 | |||||
} | } | ||||
}, | }, | ||||
{ | { | ||||
@@ -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 | ||||
@@ -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') | ||||
}) | }) | ||||
} | } | ||||
@@ -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, | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
@@ -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; | ||||
@@ -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; | ||||
@@ -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: { | ||||