Переглянути джерело

教室点名接口对接

master
yxq 2 місяці тому
джерело
коміт
5503ff036b
10 змінених файлів з 247 додано та 128 видалено
  1. +2
    -2
      monitorMobile/App.vue
  2. +38
    -0
      monitorMobile/api/work/rollCall.js
  3. +31
    -4
      monitorMobile/http/api.js
  4. +6
    -3
      monitorMobile/pages.json
  5. +1
    -0
      monitorMobile/pages/login.vue
  6. +1
    -1
      monitorMobile/pages/my/index.vue
  7. +2
    -3
      monitorMobile/pages/work/passengerFlow/index.vue
  8. +95
    -58
      monitorMobile/pages/work/rollCall/detail.vue
  9. +34
    -52
      monitorMobile/pages/work/rollCall/index.vue
  10. +37
    -5
      monitorMobile/store/index.js

+ 2
- 2
monitorMobile/App.vue Переглянути файл

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

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

@font-face {
font-family: 'Alimama ShuHeiTi';//字体别名
font-family: 'Alimama ShuHeiTi'; //字体别名
src: url('/static/fonts/alimamashuheiti.ttf') format('truetype');
font-weight: 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';
import Request from '@/utils/luch-request/index.js';
const http = new Request(options);
import store from "@/store"
http.interceptors.request.use((config) => { // 可使用async await 做异步操作
// 假设有token值需要在头部需要携带
let token = uni.getStorageSync('token');
if (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
@@ -22,10 +34,7 @@ http.interceptors.request.use((config) => { // 可使用async await 做异步操
return Promise.reject(config)
})
http.interceptors.response.use((response) => {
// 若有数据返回则通过
if (response.data.access_token || response.data.key) {
return response.data
}
checkAndStoreAuthentication(response)
// 服务端返回的状态码不等于200,则reject()
if (response.data.code && response.data.code !== 200) {
setTimeout(() => {
@@ -49,6 +58,7 @@ http.interceptors.response.use((response) => {
if (response.statusCode == 401) {
const pages = getCurrentPages()
const currentPage = pages[pages.length - 1]
this.$store.dispatch('clearToken')
uni.redirectTo({
url: `/pages/login?redirect=/${currentPage.route}`
})
@@ -74,4 +84,21 @@ function decryptJWT(token) {
function getJWTDate(timestamp) {
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;

+ 6
- 3
monitorMobile/pages.json Переглянути файл

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


+ 1
- 0
monitorMobile/pages/login.vue Переглянути файл

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


+ 1
- 1
monitorMobile/pages/my/index.vue Переглянути файл

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


+ 2
- 3
monitorMobile/pages/work/passengerFlow/index.vue Переглянути файл

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

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


+ 95
- 58
monitorMobile/pages/work/rollCall/detail.vue Переглянути файл

@@ -1,63 +1,66 @@
<template>
<view style="height: 100%;">
<view class="title">
应到:8
应到:{{list.length}}
</view>
<view style="padding: 26rpx;overflow: hidden;">
<view class="cate">
<view class="cateList">
<view v-for="item in cateList" :class="{active:item.value == cate}" :key="item.value" class="item"
@click="cateItemClick(item)">
{{item.label}}({{item.value}})
{{item.label}}({{item.num}})
</view>
</view>
</view>
</view>
<view style="height:calc(100% - 200rpx);overflow: auto;">
<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 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 class="depart">
系部:安环部
</view>
<view class="bottom">
<view class="major">专业:环艺</view>
<view class="class">班级:第二班</view>
</view>
</view>
</view>
</view>
</template>
</view>
</view>
<u-popup :show="show" mode="center" :round="10">
<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="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 class="name">
杨云
{{popupInfo.name}}
</view>
</view>
<view class="depart">
系部:安环部
系部:{{popupInfo.majorName}}
</view>
<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 class="closeBox">
<image @click="show = false" src="/static/image/close.png" class="close"></image>
@@ -68,44 +71,77 @@
</template>

<script>
import {
detail,
page
} from '@/api/work/rollCall.js'
export default {
data() {
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: [],

show: false,
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: {
cateItemClick(item) {
this.cate = item.value
@@ -166,8 +202,9 @@
width: 100%;
position: absolute;
left: 0;
bottom:-98rpx;
bottom: -98rpx;
text-align: center;

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


+ 34
- 52
monitorMobile/pages/work/rollCall/index.vue Переглянути файл

@@ -1,7 +1,8 @@
<template>
<view style="height: 100%;">
<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>
<u-empty marginTop="100rpx" :show="false" mode="list" text="暂无数据"></u-empty>
<u-list @scrolltolower="scrolltolower" style="height: calc(100% - 150rpx);">
@@ -10,19 +11,19 @@
<view :class="{whiteCard:true,active:checkboxValue.includes(item.name)}">
<view class="left">
<view class="row1">
教室(海康)
{{item.cameraName}}
</view>
<view class="row2">
<view class="">
持续时间:20
持续时间:{{item.continueTime}}
</view>
<view class="">
相似度:0.5
相似度:{{item.similarity}}
</view>
</view>
</view>
<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>
<image src="@/static/image/seeBlue.png" mode="aspectFill"></image>
</view>
@@ -38,39 +39,24 @@

<script>
import SelectRadio from "@/components/selectRadio.vue"
import {
taskPage
} from '@/api/work/rollCall.js'
export default {
components: {
SelectRadio
},
data() {
return {
list: [{
name: 1
}, {
name: 2
}, {
name: 3
}, {
name: 4
}, {
name: 5
}, {
name: 6
}, {
name: 7
}, {
name: 8
}, {
name: 9
}],
list: [],
isLoading: false,
status: 'loadmore', //loading正在加载 loadmore加载更多 nomore没有更多了
search: {
class: '',
CameraId: '',
},
page: {
size: 8,
page: 8,
pageNum: 1,
pageSize: 10,
},
checkboxValue: [],
isManage: false,
@@ -83,48 +69,41 @@
loadmore() {
if (this.status != 'loadmore') return
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'
} else {
this.status = 'loadmore'
}
}, 2000)
})
},
refresh() {
this.status = 'loadmore'
this.list = []
this.page.page = 1
this.page.pageNum = 1
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() {
console.log(this.allOptions)
this.loadmore()
},
onPullDownRefresh(){
uni.stopPullDownRefresh()
this.refresh()
}
}
</script>

<style lang="scss" scoped>

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

.left {
width: 76%;
}

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

.btn {
text-align: center;



+ 37
- 5
monitorMobile/store/index.js Переглянути файл

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

let lifeData = {};

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

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

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


Завантаження…
Відмінити
Зберегти