Ver Código Fonte

[FE]:合并冲突

xiayu3 4 anos atrás
pai
commit
01bf6c60e0

+ 25 - 3
security-protection-platform/.aid/mock/aialarm.js

@ -11,7 +11,7 @@ const { data } = Mock.mock({
11 11
      equipment_number: 's00001',
12 12
      equipment_location: '1#风场SVG室',
13 13
      alarm_time: '@date("yyyy-MM-dd HH:mm:ss")',
14
      Handler: '@cname',
14
      'Handler|1': ['张三', '李四', '王五', '何六'],
15 15
      processing_time: '@date("yyyy-MM-dd HH:mm:ss")',
16 16
      picture_url: 'http://img95.699pic.com/photo/50028/0321.jpg_wh300.jpg',
17 17
      video_url: 'https://video.pearvideo.com/mp4/adshort/20201113/cont-1706887-15482034_adpkg-ad_hd.mp4'
@ -27,6 +27,7 @@ module.exports = [
27 27
    type: 'func',
28 28
    response: (option) => {
29 29
      const TypeName = ['身份异常', '穿戴异常', '潜在危险', '违规违章', '仪表异常']
30
      const handlername = ['张三', '李四', '王五', '何六']
30 31
      //获取page
31 32
      var page = getQuery(option.url, 'page')
32 33
      //获取limit
@ -39,22 +40,30 @@ module.exports = [
39 40
      //获取报警类型
40 41
      var typeid = getQuery(option.url, 'typeid')
41 42

43
      //获取报警人
44
      var handler = getQuery(option.url, 'handler')
45
      // console.log('报警人:', handler)
46

42 47
      var start = (page - 1) * limit
43 48
      var end = page * limit
44 49
      // console.log(option)
45 50

46 51
      var result = data
52
      // console.log(result)
47 53

48 54
      if (typeid) {
49 55
        result = result.filter((item) => { return item.type == TypeName[parseInt(typeid)] })
50 56
      }
51 57

52 58
      if (starttime) {
53
        result = result.filter((item) => { return +new Date(item.time) >= starttime })
59
        result = result.filter((item) => { return +new Date(item.alarm_time) >= starttime })
54 60
      }
55 61

56 62
      if (endtime) {
57
        result = result.filter((item) => { return +new Date(item.time) <= endtime })
63
        result = result.filter((item) => { return +new Date(item.alarm_time) <= endtime })
64
      }
65
      if (handler) {
66
        result = result.filter((item) => { return item.Handler == handlername[parseInt(handler)] })
58 67
      }
59 68

60 69

@ -79,6 +88,19 @@ module.exports = [
79 88
    }
80 89
  },
81 90
  {
91
    url: '/aialarm/getaialarmhandler',
92
    method: 'get',
93
    type: 'func',
94
    response: () => {
95
      return Mock.mock({
96
        'data|4': [{
97
          'id|+1': 0,
98
          'alarmhandler|+1': ['张三', '李四', '王五', '何六'],
99
        }]
100
      })
101
    }
102
  },
103
  {
82 104
    url: /\/aialarm\/dispose/,
83 105
    method: 'put',
84 106
    type: 'func',

+ 4 - 2
security-protection-platform/package.json

@ -79,6 +79,8 @@
79 79
    "video.js": "7.10.2",
80 80
    "videojs-playlist": "4.3.1",
81 81
    "videojs-flash": "2.2.1",
82
    "echarts": "^4.9.0"
82
    "vue-video-player": "5.0.2",
83
    "echarts": "^4.9.0",
84
    "videojs-contrib-hls": "5.15.0"
83 85
  }
84
}
86
}

+ 3 - 4
security-protection-platform/src/api/access/index.js

@ -1,10 +1,9 @@
1 1
import http from '@/http'
2
const { $http } = http
3

2
const { $http, $default } = http
4 3

5 4
const api = {
6 5
  getaccesslist (params) {
7
    return $http.get('/access/getaccesslist', params)
6
    return $default.get('/sp/inAndOutRecord/queryPageInAndOutRecord', params)
8 7
  },
9 8

10 9
  getaccesstype () {
@ -13,4 +12,4 @@ const api = {
13 12

14 13
}
15 14

16
export default api
15
export default api

+ 11 - 9
security-protection-platform/src/api/aialarm/index.js

@ -1,21 +1,23 @@
1 1
import http from '@/http'
2
const { $http } = http
3

2
const { $default, $http } = http
4 3

5 4
const api = {
5
  // 获取报警记录列表
6 6
  getaialarmlist (params) {
7
    return $http.get('/aialarm/getaialarmlist/', params)
7
    return $default.get('/sp/aiAlarmManage/queryPageAiAlarm', params)
8 8
  },
9

10
  // 获取报警类型查询下拉框
9 11
  getaialarmtype () {
10
    return $http.get('/aialarm/getaialarmtype')
12
    return $default.get('/sp/charSpec/getCharSpecList?charSpecCode=AI_ALARM_TYPE')
13
  },
14
  getaialarmhandler () {
15
    return $http.get('/aialarm/getaialarmhandler')
11 16
  },
12 17
  dispose (params) {
13
    return $http.put('/aialarm/dispose/', params)
18
    return $default.post('/sp/aiAlarmManage/changeTaskStatus', params)
14 19
  }
15 20

16

17

18

19 21
}
20 22

21
export default api
23
export default api

+ 7 - 7
security-protection-platform/src/api/attendance/index.js

@ -6,7 +6,7 @@ const { $default } = http
6 6
const mapping = {
7 7
  userid: 'id',
8 8
  current: 'pageNumber',
9
  orgId: 'orgCode',
9
  // orgId: 'orgCode',
10 10
  duty: 'mainJobPositionId',
11 11
  daysAttendance: 'clockingDays', // 出勤天数
12 12
  timesLate: 'lateDays', // 迟到次数
@ -21,31 +21,31 @@ const mapping = {
21 21
const api = {
22 22
  // 获取考勤日报表格数据
23 23
  // 新接口合并了 depId和orgId
24
  getDayAttendance({params}) {
24
  getDayAttendance ({ params }) {
25 25
    params.orgId = params.depId || params.orgId
26 26
    delete params.depId
27 27
    params = keysMapping(params, mapping)
28
    return $default.get('/sp/attendanceReport/queryDailyAttendanceReport', {params}).then(resp => {
28
    return $default.get('/sp/attendanceReport/queryDailyAttendanceReport', { params }).then(resp => {
29 29
      console.log('queryDailyAttendanceReport', resp)
30 30
      resp.data = keysMappingReverse(resp.data.data, mapping)
31 31
      return resp
32 32
    })
33 33
  },
34 34
  // 获取考勤月报表格数据
35
  getMonthAttendance({params}) {
35
  getMonthAttendance ({ params }) {
36 36
    params.orgId = params.depId || params.orgId
37 37
    delete params.depId
38 38
    params = keysMapping(params, mapping)
39
    return $default.get('/sp/attendanceReport/queryMonthlyAttendanceReport', {params}).then(resp => {
39
    return $default.get('/sp/attendanceReport/queryMonthlyAttendanceReport', { params }).then(resp => {
40 40
      console.log('queryMonthlyAttendanceReport', resp)
41 41
      resp.data = keysMappingReverse(resp.data.data, mapping)
42 42
      return resp
43 43
    })
44 44
  },
45 45
  // 获取考勤月报详情数据
46
  getAttendanceDetail({params}) {
46
  getAttendanceDetail ({ params }) {
47 47
    params = keysMapping(params, mapping)
48
    return $default.get('/sp/attendanceReport/queryAttendanceDetailReport', {params}).then(resp => {
48
    return $default.get('/sp/attendanceReport/queryAttendanceDetailReport', { params }).then(resp => {
49 49
      resp.data = resp.data.data
50 50
      return resp
51 51
    })

+ 45 - 30
security-protection-platform/src/api/common/index.js

@ -1,5 +1,8 @@
1 1
import http from '@/http'
2
2
import { keysMappingReverse } from '@/utils/keysMapping'
3
// const mapping = {
4
//   id: 'code'
5
// }
3 6
const $default = http.$default
4 7
const api = {
5 8
  /**
@ -11,44 +14,56 @@ const api = {
11 14
        'name':'发电部'
12 15
      }]
13 16
   */
14
  getDepartments() {
15
    return $default.get('/sp/workEmployee/queryAllOrganize').then(resp => {
17
  getDepartments () {
18
    return $default.get('/sp/workEmployee/queryAllOrganize').then((resp) => {
16 19
      const data = resp.data.data
17 20
      if (!Array.isArray(data)) return resp
21
      console.log(data)
18 22
      // eslint-disable-next-line one-var
19
      const newData = [], map = {}, queue = []
20
      data.forEach(item => {
21
        if (item.parentCode === '-1') {
22
          const dep = { id: item.code, name: item.name, departments: [] }
23
          map[item.code] = newData.length
24
          newData.push(dep)
25
        } else {
26
          queue.push(item)
27
        }
28
      })
29
      queue.forEach(item => {
30
        if (!(item.parentCode in map)) return
31
        const dep = { id: item.code, name: item.name }
32
        newData[map[item.parentCode]].departments.push(dep)
33
      })
34
      resp.data = newData
35
      console.log('queryAllOrganize', resp)
23
      // const newData = [],
24
      //   map = {},
25
      //   queue = []
26
      // console.log(data)
27
      // data.forEach((item) => {
28
      //   if (item.parentCode === '-1') {
29
      //     const dep = { id: item.code, name: item.name, departments: [] }
30
      //     map[item.code] = newData.length
31
      //     newData.push(dep)
32
      //   } else {
33
      //     queue.push(item)
34
      //   }
35
      // })
36
      // queue.forEach((item) => {
37
      //   if (!(item.parentCode in map)) return
38
      //   const dep = { id: item.code, name: item.name }
39
      //   newData[map[item.parentCode]].departments.push(dep)
40
      // })
41
      // resp.data = newData
42
      // console.log(newData)
43
      // console.log('queryAllOrganize', resp)
44
      resp.data = nest(data)
45
      // resp.data = keysMappingReverse(nest(data), mapping)
36 46
      return resp
37 47
    })
38 48
  },
39 49
40
  getEmployeeByOrgid(orgCode) {
41
    return $default.get(`/sp/workEmployee/queryEmployeeByOrg?orgCode=${orgCode}`).then(resp => {
42
      const data = resp.data.data || []
43
      resp.data = data.map(row => {
44
        return {
45
          name: row.name,
46
          userid: row.id
47
        }
50
  getEmployeeByOrgid (orgId) {
51
    return $default
52
      .get(`/sp/workEmployee/queryEmployeeByOrg?orgId=${orgId}`)
53
      .then((resp) => {
54
        const data = resp.data.data || []
55
        resp.data = data.map((row) => {
56
          return {
57
            name: row.name,
58
            userid: row.id
59
          }
60
        })
61
        return resp
48 62
      })
49
      return resp
50
    })
51 63
  }
52 64
}
65
function nest (items, code = '-1', link = 'parentCode') {
66
  return items.filter(item => item[link] === code).map(item => ({ ...item, departments: nest(items, item.code) }))
67
}
53 68
54 69
export default api

+ 10 - 2
security-protection-platform/src/api/videoSurveillance/index.js

@ -1,5 +1,10 @@
1 1
import http from '@/http'
2 2
const { $http, $default } = http
3
import { keysMapping, keysMappingReverse } from '@/utils/keysMapping'
4
const videoMapping = {
5
  fileName: 'beginTime',
6
  fileId: 'videoUrl'
7
}
3 8
4 9
const api = {
5 10
  // 获取风场大门表格数据
@ -15,8 +20,11 @@ const api = {
15 20
    return $default.get('/sp/monitorSceneManagement/queryPageMonitorScene', 0)
16 21
  },
17 22
  // 视频回放
18
  getVideoPlayBack (id) {
19
    return $default.get(`/sp/uploadFile/getFileUrl?fileName=${id}`).catch((err) => { return err })
23
  queryMonitorVideoLog (data) {
24
    return $default.get(`/sp/monitorVideoLog/queryMonitorVideoLog`, data).then(resp => {
25
      resp.data = keysMappingReverse(resp.data, videoMapping)
26
      return resp
27
    }).catch((err) => { return err })
20 28
  }
21 29
}
22 30
export default api

+ 47 - 48
security-protection-platform/src/modules/access/index.vue

@ -12,59 +12,56 @@
12 12
        <t-date-picker :confirm="false" v-model="searchdata.endtime" placeholder="请选择结束时间" style="width:200px;height:32px"></t-date-picker>
13 13
      </div>
14 14

15
      <div>
15
      <!-- <div>
16 16
        <span class="title">进出类型 : </span>
17 17
        <t-select v-model="searchdata.typeid" style="width:200px;height:32px">
18 18
          <t-option v-for="item in accesstype" :value="item.id" :key="item.id">{{ item.name }}</t-option>
19 19

20 20
        </t-select>
21
      </div> -->
22
      <div class="alarm_people">
23
        <span class="title">员工 : </span>
24
        <t-input v-model="searchdata.relateEmployeeNameAsLike" placeholder="员工姓名、编号关键字" style="width: 200px"></t-input>
21 25
      </div>
22 26

23 27
    </div>
24 28

25 29
    <div class="access_header">
26
      <div class="alarm_people">
27
        <span class="title">员工 : </span>
28
        <t-input v-model="searchdata.username" placeholder="员工姓名、编号关键字" style="width: 200px"></t-input>
30

31
      <!-- 导出excel -->
32
      <div>
33
        <t-button color="primary" icon="upload" style="width:128px;height:32px" class="upload">导出至Excel</t-button>
29 34
      </div>
30 35

31 36
      <div>
32 37
        <t-button color="primary" @click="btnsearch">查询</t-button>
33 38
        <t-button @click="reset">重置</t-button>
34 39
      </div>
35
    </div>
36
    <!-- 导出excel -->
37
    <div>
38
      <t-button color="primary" icon="upload" style="width:128px;height:32px" class="upload">导出至Excel</t-button>
40

39 41
    </div>
40 42

41 43
    <t-table :data="data" line @selection-change="handleSelectionChange">
42 44
      <t-table-column type="selection" width="34px"></t-table-column>
43
      <t-table-column label="进出类型" width="80px">
44
        <template slot-scope="scope">
45
          <t-tag v-if="scope.row.type=== '离开'" state="info">{{ scope.row.type }}</t-tag>
46
          <t-tag v-if="scope.row.type=== '进入'" state="success">{{ scope.row.type }}</t-tag>
47
        </template>
48
      </t-table-column>
49
      <t-table-column label="姓名" prop="employee_name" width="66px">
45

46
      <t-table-column label="姓名" prop="relateEmployeeRoleName" width="60px">
50 47
      </t-table-column>
51
      <t-table-column label="员工编号" prop="employee_number" width="80px">
48
      <t-table-column label="员工编号" prop="code" width="80px">
52 49
      </t-table-column>
53
      <t-table-column label="公司" prop="company" width="69px">
50
      <t-table-column label="公司" prop="orgName" width="94px">
54 51
      </t-table-column>
55
      <t-table-column label="部门" prop="department" width="94px">
52
      <t-table-column label="部门" prop="orgName" width="94px">
56 53
      </t-table-column>
57
      <t-table-column label="职务" prop="job" width="80px">
54
      <t-table-column label="职务" prop="mainJobPosition" width="80px">
58 55
      </t-table-column>
59 56
      <t-table-column label="相似度" prop="similarity" width="75px">
60 57
      </t-table-column>
61
      <t-table-column label="进出时间" prop="time" width="169px">
58
      <t-table-column label="进出时间" prop="taskExecuteTime" width="160px">
62 59
      </t-table-column>
63
      <t-table-column label="位置" prop="location" width="122px">
60
      <t-table-column label="位置" prop="terminalPosition" width="122px">
64 61
      </t-table-column>
65
      <t-table-column label="终端名称" prop="terminal_name" width="97px">
62
      <t-table-column label="终端名称" prop="resourceToolName" width="97px">
66 63
      </t-table-column>
67
      <t-table-column label="终端编号" prop="terminal_number" width="72px">
64
      <t-table-column label="终端编号" prop="resourceToolCode" width="72px">
68 65
      </t-table-column>
69 66
      <t-table-column label="操作" width="80px">
70 67
        <template slot-scope="scope">
@ -85,33 +82,33 @@
85 82
          <div class="detail_item1">
86 83
            <div>抓拍图片</div>
87 84
            <div>
88
              <img :src="rowdata.arrest_main_url" alt="" srcset="" style="width:100%;height:100%">
85
              <img :src="rowdata.idenVideoUrl" alt="" srcset="" style="width:100%;height:100%">
89 86
            </div>
90 87
          </div>
91 88
          <div class="detail_item2">
92 89
            <div>识别结果</div>
93 90
            <div>
94 91
              <div>
95
                <img :src="rowdata.arrest_part_url" alt="" srcset="" style="width:120px;height:160px;border-radius: 5px; ">
92
                <img :src="rowdata.idenPictureUrl" alt="" srcset="" style="width:120px;height:160px;border-radius: 5px; ">
96 93
                <div class="bottomimg">抓拍图片</div>
97 94
              </div>
98 95
              <div>
99 96
                <img src="http://img95.699pic.com/photo/50028/0321.jpg_wh300.jpg" alt="" srcset="">
100 97
              </div>
101 98
              <div>
102
                <img :src="rowdata.face_url" alt="" srcset="" style="width:100%;height:160px; border-radius: 5px;">
99
                <img :src="rowdata.headerUrl" alt="" srcset="" style="width:100%;height:160px; border-radius: 5px;">
103 100
                <div class="bottomimg">人脸底库</div>
104 101
              </div>
105 102
            </div>
106 103
            <div class="describe">
107 104
              <div>
108
                <t-icon icon="user-outline"></t-icon> {{ rowdata.employee_name }}({{ rowdata.employee_number }})
105
                <t-icon icon="user-outline"></t-icon> {{ rowdata.relateEmployeeRoleName }}({{ rowdata.code }})
109 106
              </div>
110 107
              <div>
111
                <t-icon icon="map-marker"></t-icon> {{ rowdata.location }}
108
                <t-icon icon="map-marker"></t-icon> {{ rowdata.terminalPosition }}
112 109
              </div>
113 110
              <div>
114
                <t-icon icon="clock-outline"></t-icon> {{ rowdata.time }}
111
                <t-icon icon="clock-outline"></t-icon> {{ rowdata.taskExecuteTime }}
115 112
              </div>
116 113
              <div>
117 114
                <t-icon icon="team-outline"></t-icon> 相似度:{{ rowdata.similarity }}
@ -130,6 +127,7 @@
130 127

131 128
<script>
132 129
import accessapi from '@/api/access'
130
import formatDateTime from '@/utils/formatDateTime.js'
133 131

134 132
export default {
135 133
  data () {
@ -147,10 +145,10 @@ export default {
147 145

148 146
      // 查询的参数
149 147
      searchdata: {
150
        typeid: '',
151
        username: '',
152
        starttime: '',
153
        endtime: ''
148

149
        relateEmployeeNameAsLike: '',
150
        beginTime: '',
151
        endTime: ''
154 152
      },
155 153
      // 一页的数据
156 154
      data: [
@ -164,7 +162,7 @@ export default {
164 162
  },
165 163

166 164
  mounted () {
167
    this.gettype()
165
    // this.gettype()
168 166
    this.search()
169 167
  },
170 168
  methods: {
@ -193,31 +191,32 @@ export default {
193 191
      }
194 192
    },
195 193
    // 获取进出类型
196
    gettype () {
197
      accessapi.getaccesstype().then((res) => {
198
        this.accesstype = res.data.data
199
        console.log(this.accesstype)
200
      })
201
    },
194
    // gettype () {
195
    //   accessapi.getaccesstype().then((res) => {
196
    //     this.accesstype = res.data.data
197
    //     console.log(this.accesstype)
198
    //   })
199
    // },
202 200
    // 查询数据
203 201
    async search () {
204 202
      // 检验数据
205
      var flag = this.startreend(this.searchdata.starttime, this.searchdata.endtime)
203
      var flag = this.startreend(this.searchdata.beginTime, this.searchdata.endTime)
206 204
      if (flag) {
207 205
        // console.log(this.page)
208 206
        // console.log(this.searchdata)
209 207

210 208
        var params = this.searchdata
211
        params.page = this.page
212
        params.limit = this.limit
213
        console.log(params)
209
        params.pageNumber = this.page
210
        params.pageSize = this.limit
211
        // console.log(params)
214 212
        var res = await accessapi.getaccesslist({ params: params })
215 213
        // console.log(res)
216 214
        if (res.status === 200) {
217 215
          console.log(res)
218
          this.data = res.data.data
219
          // console.log(this.data)
220
          this.total = Math.ceil(res.data.total / this.limit) * 5
216
          this.data = res.data.data.data
217
          this.data = this.data.map((item) => { item.taskExecuteTime = formatDateTime(item.taskExecuteTime); return item })
218
          console.log(this.data)
219
          this.total = Math.ceil(res.data.data.total / res.data.data.size) * 5
221 220
        }
222 221
      } else {
223 222
        this.$Message.danger('开始时间不能在结束时间的后面')
@ -262,7 +261,6 @@ export default {
262 261
  .upload {
263 262
    font-size: 14px;
264 263
    line-height: 22px;
265
    margin: 29px 0 25px 0;
266 264
  }
267 265
  .table th,
268 266
  .table td {
@ -273,6 +271,7 @@ export default {
273 271
    display: flex;
274 272
    justify-content: space-between;
275 273
    margin-top: 24px;
274
    margin-bottom: 24px;
276 275
    .title {
277 276
      display: inline-block;
278 277
      width: 70px;

+ 102 - 98
security-protection-platform/src/modules/aialarm/index.vue

@ -5,30 +5,36 @@
5 5
    <div class="alarm_header">
6 6
      <div>
7 7
        <span class="title">报警类型 : </span>
8
        <t-select v-model="searchdata.typeid" style="width:200px;height:32px">
9
          <t-option v-for="(item,index) in alarmtypelist" :key="index" :value="item.id">{{ item.name }}</t-option>
8
        <t-select v-model="searchdata.alarmTypeCode" style="width:200px;height:32px">
9
          <t-option v-for="item in alarmtypelist" :key="item.code" :value="item.code">{{ item.value }}</t-option>
10 10
        </t-select>
11 11
      </div>
12 12

13 13
      <div>
14 14
        <span class="title">开始时间 : </span>
15
        <t-date-picker :confirm="false" v-model="searchdata.starttime" placeholder="请选择开始时间" style="width:200px;height:32px"></t-date-picker>
15
        <t-date-picker :confirm="false" v-model="searchdata.beginTime" placeholder="请选择开始时间" style="width:200px;height:32px"></t-date-picker>
16 16
      </div>
17 17

18 18
      <div>
19 19
        <span class="title">结束时间 : </span>
20
        <t-date-picker :confirm="false" v-model="searchdata.endtime" placeholder="请选择结束时间" style="width:200px;height:32px"></t-date-picker>
20
        <t-date-picker :confirm="false" v-model="searchdata.endTime" placeholder="请选择结束时间" style="width:200px;height:32px"></t-date-picker>
21 21
      </div>
22 22

23 23
    </div>
24 24

25 25
    <div class="alarm_header">
26
      <div class="alarm_people">
26
      <!-- <div class="alarm_people">
27 27
        <span class="title">报警人 : </span>
28
        <t-select v-model="searchdata.Police" style="width:200px;height:32px">
29
          <t-option value="你好">选项1</t-option>
28
        <t-select v-model="searchdata.handler" style="width:200px;height:32px">
29
           <t-option value="你好">选项1</t-option>
30 30
          <t-option value="世界">选项2</t-option>
31
          <t-option v-for="item in aialarmhandlerlist" :value="item.id" :key="item.id">{{ item.alarmhandler }}</t-option>
31 32
        </t-select>
33
      </div> -->
34

35
      <!-- 导出excel组件 -->
36
      <div>
37
        <t-button color="primary" icon="upload" style="width:128px;height:32px" class="upload">导出至Excel</t-button>
32 38
      </div>
33 39

34 40
      <div>
@ -37,44 +43,40 @@
37 43
      </div>
38 44
    </div>
39 45

40
    <!-- 导出excel组件 -->
41
    <div>
42
      <t-button color="primary" icon="upload" style="width:128px;height:32px" class="upload">导出至Excel</t-button>
43
    </div>
44

45 46
    <!-- 表格 -->
46 47
    <t-table :data="data" line @selection-change="handleSelectionChange">
47 48
      <t-table-column type="selection" width="50"></t-table-column>
48
      <t-table-column label="状态" width="110">
49
      <t-table-column label="状态" width="100">
49 50
        <template slot-scope="scope">
50 51

51
          <t-tag v-if="scope.row.state=== '处理中'" state="info">{{ scope.row.state }}</t-tag>
52
          <t-tag v-if="scope.row.state=== '未确认'" state="warning">{{ scope.row.state }}</t-tag>
53
          <t-tag v-if="scope.row.state=== '已处理'" state="success">{{ scope.row.state }}</t-tag>
52
          <t-tag v-if="scope.row.status=== 'RUN'" state="info">处理中</t-tag>
53
          <t-tag v-if="scope.row.status=== 'INI'" state="warning">未确认</t-tag>
54
          <t-tag v-if="scope.row.status=== 'END'" state="success">已处理</t-tag>
55
          <t-tag v-if="scope.row.status=== 'FAL'" state="danger">误报</t-tag>
54 56
        </template>
55 57
      </t-table-column>
56
      <t-table-column label="报警类型" prop="type">
58
      <t-table-column label="报警类型" prop="alarmTypeName">
57 59
      </t-table-column>
58
      <t-table-column label="报警描述" prop="describe" width="110">
60
      <t-table-column label="报警描述" prop="alarmMemo" width="110">
59 61
      </t-table-column>
60
      <t-table-column label="设备名称" prop="equipment_name" width="110">
62
      <t-table-column label="设备名称" prop="resourceToolName" width="110">
61 63
      </t-table-column>
62
      <t-table-column label="设备编号" prop="equipment_number" width="90">
64
      <t-table-column label="设备编号" prop="resourceToolCode" width="90">
63 65
      </t-table-column>
64
      <t-table-column label="设备位置" prop="equipment_location" width="120">
66
      <t-table-column label="设备位置" prop="monitorSceneName" width="120">
65 67
      </t-table-column>
66
      <t-table-column label="报警时间" prop="alarm_time" width="148px">
68
      <t-table-column label="报警时间" prop="aiIdenTime" width="148px">
67 69
      </t-table-column>
68
      <t-table-column label="处理人" prop="Handler" width="70">
70
      <t-table-column label="处理人" prop="workEmployeeRoleName" width="70">
69 71
      </t-table-column>
70
      <t-table-column label="处理时间" prop="processing_time" width="148px">
72
      <t-table-column label="处理时间" prop="processTime" width="148px">
71 73
      </t-table-column>
72 74
      <t-table-column label="操作">
73 75
        <template slot-scope="scope">
74 76

75 77
          <a href="javascript:void(0)" size="sm" style="color:#0089D4" @click="handleClick(scope,0)">详情</a>
76
          <a v-if="scope.row.state=='处理中'" style="color:#0089D4" @click="handleClick(scope,1)">关闭</a>
77
          <a v-if="scope.row.state=='未确认'" style="color:#0089D4" @click="handleClick(scope,1)">处理</a>
78
          <a v-if="scope.row.status=='RUN'||scope.row.status=='FAL'" style="color:#0089D4" @click="handleClick(scope,1)">关闭</a>
79
          <a v-if="scope.row.status=='INI'" style="color:#0089D4" @click="handleClick(scope,1)">处理</a>
78 80
        </template>
79 81
      </t-table-column>
80 82
    </t-table>
@ -90,67 +92,68 @@
90 92
          <div class="detail">
91 93
            <label class="detail_title">状态:</label>
92 94
            <div class="detail_content">
93
              <t-tag v-if="currentdata.data.state==='未确认'" state="warning">{{ currentdata.data.state }}</t-tag>
94
              <t-tag v-if="currentdata.data.state==='已处理'" state="success">{{ currentdata.data.state }}</t-tag>
95
              <t-tag v-if="currentdata.data.state==='处理中'" state="info">{{ currentdata.data.state }}</t-tag>
95
              <t-tag v-if="currentdata.data.status==='INI'" state="warning">未确认</t-tag>
96
              <t-tag v-if="currentdata.data.status==='END'" state="success">已处理</t-tag>
97
              <t-tag v-if="currentdata.data.status==='RUN'" state="info">处理中</t-tag>
98
              <t-tag v-if="currentdata.data.status==='FAL'" state="danger">误报</t-tag>
96 99
            </div>
97 100

98 101
          </div>
99 102
          <div class="detail">
100 103
            <label class="detail_title">报警类型:</label>
101
            <div class="detail_content">{{ currentdata.data.type }}</div>
104
            <div class="detail_content">{{ currentdata.data.alarmTypeName }}</div>
102 105
          </div>
103 106
          <div class="detail">
104 107
            <label class="detail_title">报警描述:</label>
105
            <div class="detail_content">{{ currentdata.data.describe }}</div>
108
            <div class="detail_content">{{ currentdata.data.alarmMemo }}</div>
106 109
          </div>
107 110
          <div class="detail">
108 111
            <label class="detail_title">报警时间:</label>
109
            <div class="detail_content">{{ currentdata.data.alarm_time }}</div>
112
            <div class="detail_content">{{ currentdata.data.aiIdenTime }}</div>
110 113
          </div>
111 114

112 115
          <div class="detail">
113 116
            <label class="detail_title">设备编号:</label>
114
            <div class="detail_content">{{ currentdata.data.equipment_name }}</div>
117
            <div class="detail_content">{{ currentdata.data.resourceToolCode }}</div>
115 118
          </div>
116 119
          <div class="detail">
117 120
            <label class="detail_title">设备位置:</label>
118
            <div class="detail_content">{{ currentdata.data.equipment_location }}</div>
121
            <div class="detail_content">{{ currentdata.data.monitorSceneName }}</div>
119 122
          </div>
120 123

121 124
          <div class="detail">
122 125
            <label class="detail_title">处理人:</label>
123
            <div class="detail_content">{{ currentdata.data.Handler }}</div>
126
            <div class="detail_content">{{ currentdata.data.workEmployeeRoleName }}</div>
124 127
          </div>
125 128

126 129
          <div class="detail">
127 130
            <label class="detail_title">处理时间:</label>
128
            <div>{{ currentdata.data.processing_time }}</div>
131
            <div>{{ currentdata.data.processTime }}</div>
129 132
          </div>
130 133
        </div>
131 134

132 135
        <div class="details_item2">
133 136
          <div>
134 137
            <div>识别图片</div>
135
            <div><img :src="currentdata.data.picture_url" alt="" srcset="" style="width:100%;height:100%"></div>
138
            <div><img :src="currentdata.data.idenPictureUrl" alt="" srcset="" style="width:100%;height:100%"></div>
136 139
          </div>
137 140
          <div>
138 141
            <div>识别视频</div>
139 142
            <div>
140
              <video :src="currentdata.data.video_url" class="video" controls></video>
143
              <video :src="currentdata.data.idenVideoUrl" class="video" controls></video>
141 144
            </div>
142 145
          </div>
143 146
        </div>
144 147
        <div v-if="clickdetail==1">
145
          <div v-if="currentdata.data.state!='已处理'" class="radio">
148
          <div v-if="currentdata.data.status!='END'" class="radio">
146 149
            <div>报警处理 : </div>
147
            <div v-if="currentdata.data.state=='未确认'">
148
              <t-radio-group v-model="msg">
149
                <t-radio label="确认">
150
            <div v-if="currentdata.data.status=='INI'">
151
              <t-radio-group v-model="status">
152
                <t-radio label="RUN">
150 153

151 154
                  <span>确认</span>
152 155
                </t-radio>
153
                <t-radio label="误判">
156
                <t-radio label="FAL">
154 157

155 158
                  <span>误判</span>
156 159
                </t-radio>
@ -158,9 +161,9 @@
158 161
              </t-radio-group>
159 162
            </div>
160 163

161
            <div v-if="currentdata.data.state=='处理中'">
162
              <t-radio-group v-model="msg">
163
                <t-radio label="关闭">关闭</t-radio>
164
            <div v-if="currentdata.data.status=='RUN'||currentdata.data.status=='FAL'">
165
              <t-radio-group v-model="status">
166
                <t-radio label="END">关闭</t-radio>
164 167
              </t-radio-group>
165 168

166 169
            </div>
@ -188,21 +191,22 @@
188 191
<script>
189 192

190 193
import aialarmapi from '@/api/aialarm'
194
import formatDateTime from '@/utils/formatDateTime.js'
191 195
export default {
192 196

193 197
  data () {
194 198
    return {
195 199
      searchdata: {
196
        typeid: '', // 报警类型
197
        Police: '', // 报警人
198
        starttime: '', // 开始时间
199
        endtime: '' // 结束时间
200
        alarmTypeCode: '', // 报警类型
201
        beginTime: '', // 开始时间
202
        endTime: '' // 结束时间
200 203
      },
201 204
      // 报警类型
202 205
      alarmtypelist: [],
203 206
      // 报警人
207
      aialarmhandlerlist: [],
204 208
      // 模态框中的单选按钮
205
      msg: '',
209
      status: '',
206 210
      // 模态框
207 211
      details_modal: false,
208 212
      // 当前行的数据
@ -215,20 +219,23 @@ export default {
215 219
      // 判断是详情还是处理
216 220
      clickdetail: 0,
217 221
      // 一页的数据
218
      data: [
219
        orkTaskId': '202012031206570506796', // {
220
        //   state: '处理中',
221
        //   type: '身份异常',
222
        //   describe: '未授权车辆',
223
        //   equipment_name: '1#人脸终端',
224
        //   equipment_number: 's00001',
225
        //   equipment_location: '1#风场SVG室',
226
        //   alarm_time: '2020-09-21 16:07:09',
227
        //   Handler: '张三',
228
        //   processing_time: '2020-09-21 16:07:09',
229

230
        // },
231

222
      data: [{
223
        'workTaskId': '202012031206570506796', orkTaskId': '202012031206570506796', //
224
        'status': 'INI', // 状态
225
        'statusTime': '2020-12-03T04:06:58.000+0000', // 状态时间
226
        'processMemo': null, // 处理详情
227
        'alarmTypeCode': 'HAT', // 报警类型
228
        'alarmMemo': '没戴安全帽', // 报警描述
229
        'resourceToolName': null, // 设备名称
230
        'resourceToolCode': null, // 设备编号
231
        'monitorSceneName': '一号工地', // 设备位置
232
        'aiIdenTime': '2020-12-03T04:06:58.000+0000', // 报警时间l
233
        'targetEmployeeRoleId': '1001',
234
        'workEmployeeRoleId': '90001', // 处理人
235
        'processTime': '', // 处理时间
236
        'idenPictureUrl': 'http://pic/2970', // 图片url
237
        'idenVideoUrl': 'http://video/8989' // 视频url
238
      }
232 239
      ],
233 240
      // 页数
234 241
      page: 1,
@ -254,12 +261,12 @@ export default {
254 261
      this.clickdetail = val
255 262
      // 去除模态框中的单选项
256 263

257
      this.msg = ''
264
      this.status = ''
258 265

259 266
      this.details_modal = true // 打开模态框
260 267
      this.currentdata.data = scope.row // 获取当前行的数据
261 268
      this.currentdata.index = scope.$index // 获取当前行的索引
262
      console.log(this.currentdata.data)
269
      // console.log(this.currentdata.data)
263 270
    },
264 271

265 272
    // 未确认状态的模态框的确认按钮 || 处理中状态的模态框的确认按钮
@ -267,9 +274,11 @@ export default {
267 274
      // 获取单选框中的值
268 275
      // console.log(this.msg)
269 276
      // 判断是否选择了单选框
270
      if (this.msg) {
277
      if (this.status) {
271 278
        // 向后端发送数据
272
        this.alarmdispose(this.currentdata.data.id, this.msg)
279
        this.alarmdispose(this.currentdata.data.workTaskId, this.status)
280
        // console.log(this.status)
281
        // console.log(this.currentdata.data.workTaskId)
273 282
        // 关闭模态框
274 283
        this.details_modal = false
275 284
      } else {
@ -277,32 +286,21 @@ export default {
277 286
      }
278 287
    },
279 288

280
    async alarmdispose (id, msg) {
281
      var res = await aialarmapi.dispose({ 'id': id, 'msg': msg })
282
      console.log(res)
289
    async alarmdispose (id, status, processMemo) {
290
      const dict = { 'END': '已解决', 'RUN': '处理中', 'FAL': '误报' }
291

292
      var res = await aialarmapi.dispose({ 'workTaskId': id, 'status': status, 'processMemo': dict.status })
293
      // console.log(res)
283 294
      if (res.status === 200) {
295
        this.$Message.success('操作成功')
284 296
        // console.log(res.data.data)
285
        this.judgeradio(msg)
297
        this.data[this.currentdata.index].status = res.data.data.status
298
        this.data[this.currentdata.index].processTime = res.data.data.doneDate
286 299
      } else {
287 300
        this.$Message.danger('处理失败')
288 301
      }
289 302
    },
290 303

291
    // 判断选择了哪个单选按钮
292
    judgeradio (msg) {
293
      // 未确认的模态框选择了确认
294
      if (msg === '确认') {
295
        this.data[this.currentdata.index].state = '处理中'
296
      }
297
      // 未确认的模态框选择了误判
298
      if (msg === '误判') {
299
        this.$Message.info('未确认的模态框选择了误判')
300
      }
301
      // 处理中的模态框选择了关闭按钮
302
      if (msg === '关闭') {
303
        this.data[this.currentdata.index].state = '已处理'
304
      }
305
    },
306 304
    onChange (val) {
307 305
      // console.log(val)
308 306
      this.page = val
@ -318,25 +316,27 @@ export default {
318 316
      }
319 317
    },
320 318

321
    // 获取报警类型 以及报警人
319
    // 获取报警类型
322 320
    async gettype () {
323 321
      var res = await aialarmapi.getaialarmtype()
324 322
      // console.log(res)
325 323
      if (res.status === 200) {
326
        this.alarmtypelist = res.data.data
327
        console.log(this.alarmtypelist)
324
        // this.alarmtypelist = res.data.data
325
        // console.log(this.alarmtypelist)
326
        // console.log(res.data)
327
        this.alarmtypelist = res.data
328 328
      }
329 329
    },
330 330

331 331
    // 查询数据时
332 332
    async search () {
333
      var flag = this.startreend(this.searchdata.starttime, this.searchdata.endtime)
334
      console.log(flag)
333
      var flag = this.startreend(this.searchdata.beginTime, this.searchdata.endTime)
334
      // console.log(flag)
335 335
      if (flag) {
336 336
        // 查询
337 337
        var params = this.searchdata
338
        params.page = this.page
339
        params.limit = this.limit
338
        params.pageNumber = this.page
339
        params.pageSize = this.limit
340 340

341 341
        var res = await aialarmapi.getaialarmlist({
342 342
          params: params
@ -344,8 +344,12 @@ export default {
344 344

345 345
        // console.log(res)
346 346
        if (res.status === 200) {
347
          this.data = res.data.data
348
          this.total = Math.ceil(res.data.total / this.limit) * 5
347
          this.data = res.data.data.data
348
          // console.log('数据是:', this.data)
349
          this.data = this.data.map((item) => { item.aiIdenTime = formatDateTime(item.aiIdenTime); return item })
350
          // console.log(this.data)
351

352
          this.total = Math.ceil(res.data.data.total / res.data.data.size) * 5
349 353
        } else {
350 354
          this.$Message.danger('数据获取失败')
351 355
        }
@ -393,7 +397,6 @@ export default {
393 397
  .upload {
394 398
    font-size: 14px;
395 399
    line-height: 22px;
396
    margin: 29px 0 25px 0;
397 400
  }
398 401
  .table th,
399 402
  .table td {
@ -403,6 +406,7 @@ export default {
403 406
    display: flex;
404 407
    justify-content: space-between;
405 408
    margin-top: 24px;
409
    margin-bottom: 24px;
406 410
    .title {
407 411
      display: inline-block;
408 412
      width: 70px;

+ 60 - 21
security-protection-platform/src/modules/dashboard/index.vue

@ -5,7 +5,7 @@
5 5
    </div>
6 6
    <div>
7 7
      <div class="time"><span style="color: #00d8f3;font-size: 21px;">{{ nowDate | dateFormat }}</span></div>
8
      <div class="goto"><t-icon icon="arrow-right-outline"></t-icon>进入系统</div>
8
      <div class="goto" @click="gotoSystem"><t-icon icon="arrow-right-outline"></t-icon>进入系统</div>
9 9
    </div>
10 10
    <div class="body">
11 11
      <div class="body-left">
@ -57,7 +57,9 @@
57 57
        <div :style="`background-image: url(${titleImgBg})`" class="title" style="width: 370px;">
58 58
          <span class="title-span">重点区域监控</span>
59 59
        </div>
60
        <img src="@/assets/images/indexT1.png" style="width: 730px;height: 730px;padding-left: 20px;padding-top: 10px;">
60
        <video-player ref="videoPlayer" :options="videoOptions" class="vjs-custom-skin videoPlayer" :playsinline="true"></video-player>
61
62
<!--        <img src="@/assets/images/indexT1.png" style="width: 730px;height: 730px;padding-left: 20px;padding-top: 10px;">-->
61 63
      </div>
62 64
      <div class="body-right">
63 65
        <div :style="`background-image: url(${titleImgBg})`" class="title" style="width: 330px;">
@ -75,6 +77,10 @@ import titleImgBg from '@/assets/images/indexTitle.png'
75 77
import polygon from '@/assets/images/polygon.png'
76 78
import echarts from 'echarts'
77 79
import dasapi from '@/api/dashboard'
80
import 'video.js/dist/video-js.css'
81
import 'vue-video-player/src/custom-theme.css'
82
import { videoPlayer } from 'vue-video-player'
83
import 'videojs-flash'
78 84
79 85
export default {
80 86
  filters: {
@ -108,10 +114,13 @@ export default {
108 114
      )
109 115
    }
110 116
  },
111
  components: {},
117
  components: {
118
    videoPlayer
119
  },
112 120
  data() {
113 121
    return {
114 122
      nowDate: new Date(),
123
      videoOptions: {},
115 124
      imgBg: imgBg,
116 125
      titleImgBg: titleImgBg,
117 126
      polygon: polygon,
@ -120,15 +129,42 @@ export default {
120 129
      alarmDataX: [],
121 130
      alarmDataY: [],
122 131
      topData: [
123
        {name: '未戴安全帽', value: 0},
124
        {name: '人员聚集', value: 0},
125
        {name: '吸烟', value: 0},
126
        {name: '摔倒', value: 0}]
132
        {name: '未戴安全帽', value: ''},
133
        {name: '人员聚集', value: ''},
134
        {name: '吸烟', value: ''},
135
        {name: '摔倒', value: ''}],
136
      topData1: []
127 137
    }
128 138
  },
129 139
  computed: {
130 140
  },
131 141
  mounted () {
142
143
    this.videoOptions = {
144
      live: true,
145
      autoplay: true,
146
      fluid: true,
147
      notSupportedMessage: '暂时无法播放',
148
      controlBar: {
149
        timeDivider: true,
150
        durationDisplay: true,
151
        remainingTimeDisplay: false,
152
        fullscreenToggle: true // 全屏按钮
153
      },
154
      techOrder: ['flash'],
155
      flash: {
156
        hls: { withCredentials: false },
157
        swf: 'static/video-js.swf' // 引入静态文件swf
158
      },
159
      sources: [{ // 流配置,数组形式,会根据兼容顺序自动切换
160
        type: 'rtmp/mp4',
161
        src: 'rtmp://58.200.131.2:1935/livetv/hunantv' 
162
      }]
163
    }
164
165
166
167
132 168
    setInterval(() => { // 当前时间
133 169
      this.nowDate = new Date()
134 170
    }, 1000)
@ -137,10 +173,12 @@ export default {
137 173
    this.init24Top()
138 174
  },
139 175
  methods: {
176
177
    gotoSystem() {
178
      this.$router.push({name:'videoSurveillance'})
179
    },
140 180
    initAttendance() {
141
      debugger
142 181
      this.attendanceData = dasapi.queryAttendanceChart().then(res => {
143
        debugger
144 182
        this.population = res.data.totalSize
145 183
        res.data.dataList.forEach(e => {
146 184
          if (e.name === '在岗') {
@ -158,9 +196,7 @@ export default {
158 196
      })
159 197
    },
160 198
    initAlarm() {
161
      debugger
162 199
      this.population = dasapi.queryAlarmAnalysisChart().then(res => {
163
        debugger
164 200
        res.data.forEach(e => {
165 201
          this.alarmDataX.push(e.name)
166 202
          this.alarmDataY.push(e.value)
@ -169,10 +205,11 @@ export default {
169 205
      })
170 206
    },
171 207
    init24Top() {
172
      debugger
173
      this.topData = dasapi.queryAlarmAnalysisTopList().then(res => {
174
        debugger
175
        this.topData = res.data
208
      this.topData1 = dasapi.queryAlarmAnalysisTopList().then(res => {
209
        this.topData1 = res.data
210
        if (res.data.length>3){
211
          this.topData = this.topData1
212
        }
176 213
      })
177 214
    },
178 215
    initAttendanceData() {
@ -251,12 +288,14 @@ export default {
251 288
      var wordNum = parseInt((gridWidth / this.alarmDataX.length) / fontsize);
252 289
      var flag = 0
253 290
      this.alarmDataX.forEach(value => {
254
        var strs = value.split('')
255
        var str = ''
256
        for (var i = 0, s; s = strs[i++];) {
257
          str += s
258
          if (!(i % wordNum)) {
259
            flag = -20
291
        if (value){
292
          var strs = value.split('')
293
          var str = ''
294
          for (var i = 0, s; s = strs[i++];) {
295
            str += s
296
            if (!(i % wordNum)) {
297
              flag = -20
298
            }
260 299
          }
261 300
        }
262 301
      })

+ 75 - 48
security-protection-platform/src/modules/system/attendance/components/AttendancePanel/index.vue

@ -108,12 +108,7 @@
108 108
                <t-option :value="0">本月</t-option>
109 109
              </t-select>
110 110
              <t-select v-model="form.monthStart.day" style="margin-bottom:18px;width:84px">
111
                <t-option
112
                  v-for="item in dayOptions"
113
                  :key="item.value"
114
                  :value="item.value"
115
                  :disabled="item.value===1&&form.monthStart.type===-1"
116
                >
111
                <t-option v-for="item in dayOptions" :key="item.value" :value="item.value" :disabled="item.value===1&&form.monthStart.type===-1">
117 112
                  {{ item.label }}
118 113
                </t-option>
119 114
              </t-select>
@ -125,12 +120,7 @@
125 120
                <t-option :value="1" :disabled="form.monthEnd.day===31">下月</t-option>
126 121
              </t-select>
127 122
              <t-select v-model="form.monthEnd.day" style="margin-bottom:18px;width:84px">
128
                <t-option
129
                  v-for="item in dayOptions"
130
                  :key="item.value"
131
                  :value="item.value"
132
                  :disabled="item.value===31&&form.monthEnd.type===1"
133
                >
123
                <t-option v-for="item in dayOptions" :key="item.value" :value="item.value" :disabled="item.value===31&&form.monthEnd.type===1">
134 124
                  {{ item.label }}
135 125
                </t-option>
136 126
              </t-select>
@ -157,7 +147,7 @@ import commonapi from '@/api/common'
157 147
158 148
export default {
159 149
  components: { ShiftsItem, IntegerOnlyInput },
160
  data() {
150
  data () {
161 151
    return {
162 152
      filterValue: '',
163 153
      loadSubmit: false,
@ -176,10 +166,10 @@ export default {
176 166
  },
177 167
178 168
  computed: {
179
    currentSchedule() {
169
    currentSchedule () {
180 170
      return this.schedules.find(item => item.scheduleId === this.form.scheduleId) || {}
181 171
    },
182
    dayOptions() {
172
    dayOptions () {
183 173
      const options = []
184 174
      for (let i = 1; i <= 31; i++) {
185 175
        options.push({
@ -190,13 +180,13 @@ export default {
190 180
      return options
191 181
    },
192 182
    startDayValue: {
193
      get() {
183
      get () {
194 184
        const monthStart = this.form.monthStart || this.getDefaultForm().monthStart
195 185
        const type = parseInt(monthStart.type)
196 186
        const day = parseInt(monthStart.day)
197 187
        return type * 31 + day
198 188
      },
199
      set(val) {
189
      set (val) {
200 190
        if (this.form.monthStart == null) this.form.monthStart = {}
201 191
        const type = val < 1 ? -1 : 0
202 192
        this.form.monthStart.day = val - type * 31
@ -204,13 +194,13 @@ export default {
204 194
      }
205 195
    },
206 196
    endDayValue: {
207
      get() {
197
      get () {
208 198
        const monthEnd = this.form.monthEnd || this.getDefaultForm().monthEnd
209 199
        const type = parseInt(monthEnd.type)
210 200
        const day = parseInt(monthEnd.day)
211 201
        return type * 31 + day
212 202
      },
213
      set(val) {
203
      set (val) {
214 204
        if (this.form.monthEnd == null) this.form.monthEnd = {}
215 205
        const type = val > 31 ? 1 : 0
216 206
        this.form.monthEnd.day = val - type * 31
@ -220,54 +210,90 @@ export default {
220 210
  },
221 211
  watch: {
222 212
    // 处理开始日期和结束日期的联动
223
    startDayValue(val) {
213
    startDayValue (val) {
224 214
      this.endDayValue = val + 31 - 1
225 215
    },
226
    endDayValue(val) {
216
    endDayValue (val) {
227 217
      this.startDayValue = val - 31 + 1
228 218
    }
229 219
  },
230 220
231
  created() {
221
  created () {
232 222
    this.getDepartments()
233 223
    this.getSchedules()
234 224
  },
235 225
236 226
  methods: {
237
    getDepartments() {
227
    // 如果部门还有下级 递归
228
    nextDepartment (data, arr) {
229
      if (data.length > 0) {
230
        data.forEach(item => {
231
          arr.push({
232
            id: item.id + '',
233
            label: item.name,
234
            pid: item.parentCode
235
          })
236
          // 如果没有中值 默认选中一个值 这里是一般是公司的考勤
237
          if (this.treeValue.length === 0) this.handleDeptChange([item.id + ''])
238
          this.nextDepartment(item.departments, arr)
239
        })
240
      }
241
    },
242
    // 获取部门的考勤规则
243
    getDepartments () {
238 244
      this.loadDepts = true
239 245
      commonapi.getDepartments().then(resp => {
240 246
        const data = []
241
        console.log(resp)
242
        resp.data.forEach(item => {
243
          const orgId = item.id + ''
244
          data.push({
245
            id: orgId,
246
            label: item.name,
247
            disabled: true
248
          })
249
          item.departments.forEach(dept => {
250
            const deptId = dept.id + ''
251
            data.push({
252
              id: deptId,
253
              label: dept.name,
254
              pid: orgId
255
            })
256
            if (this.treeValue.length === 0) this.handleDeptChange([deptId])
257
          })
247
        // console.log(resp.data)
248
249
        // resp.data.forEach(item => {
250
        //   const orgId = item.id + ''
251
        //   data.push({
252
        //     id: orgId,
253
        //     label: item.name
254
        //     // disabled: true
255
        //   })
256
        //   item.departments.forEach(dept => {
257
        //     const deptId = dept.id + ''
258
        //     data.push({
259
        //       id: deptId,
260
        //       label: dept.name,
261
        //       pid: orgId
262
        //     })
263
        //     if (this.treeValue.length === 0) this.handleDeptChange([deptId])
264
        //     if (dept.departments.length > 0) {
265
        //       dept.departments.forEach(child => {
266
        //         const childId = child.id + ''
267
        //         data.push({
268
        //           id: childId,
269
        //           label: child.name,
270
        //           pid: deptId
271
        //         })
272
        //         this.handleDeptChange([childId])
273
        //       })
274
        //     }
275
        //   })
276
        // })
277
        // 递归
278
        this.nextDepartment(resp.data, data)
279
        // 删除pid为"-1"的的pid属性,否则tree渲染的时候没有根节点渲染不出来
280
        data.forEach(item => {
281
          if (item.pid === '-1') {
282
            delete item.pid
283
          }
258 284
        })
259 285
        this.treeData = data
260 286
      }).finally(() => {
261 287
        this.loadDepts = false
262 288
      })
263 289
    },
264
    getSchedules() {
290
    getSchedules () {
265 291
      sysapi.getSchedules().then(resp => {
266 292
        this.schedules = resp.data || []
267 293
        // this.scheduleId = this.schedules.length ? this.schedules[0].scheduleId : ''
268 294
      })
269 295
    },
270
    getDefaultForm() {
296
    getDefaultForm () {
271 297
      return {
272 298
        scheduleId: '',
273 299
        attendanceMonth: this.ENUM_NAT,
@ -281,7 +307,7 @@ export default {
281 307
        }
282 308
      }
283 309
    },
284
    getDepAttendanceRules(id) {
310
    getDepAttendanceRules (id) {
285 311
      this.loadForm = true
286 312
      sysapi.getDepAttendanceRules(id).then(resp => {
287 313
        this.form = resp.data.scheduleId === null ? this.getDefaultForm() : resp.data
@ -289,9 +315,9 @@ export default {
289 315
        this.loadForm = false
290 316
      })
291 317
    },
292
    submitAttendance() {
318
    submitAttendance () {
293 319
      this.loadSubmit = true
294
      sysapi.submitAttendanceRule({depId: this.treeValue[0], ...this.form }).then(resp => {
320
      sysapi.submitAttendanceRule({ depId: this.treeValue[0], ...this.form }).then(resp => {
295 321
        this.form = Object.assign(resp.data)
296 322
        this.$Message.success('修改成功')
297 323
      }, err => {
@ -301,15 +327,15 @@ export default {
301 327
        this.loadSubmit = false
302 328
      })
303 329
    },
304
    handleDeptChange(target) {
330
    handleDeptChange (target) {
305 331
      const deptId = target[0]
306 332
      this.treeValue[0] = deptId
307 333
      this.getDepAttendanceRules(deptId)
308 334
    },
309
    handleReset() {
335
    handleReset () {
310 336
      this.form = this.getDefaultForm()
311 337
    },
312
    handleSubmit() {
338
    handleSubmit () {
313 339
      this.$refs.form.validate(valid => {
314 340
        if (valid) {
315 341
          this.submitAttendance()
@ -318,6 +344,7 @@ export default {
318 344
    }
319 345
  }
320 346
}
347
321 348
</script>
322 349
323 350
<style lang="scss">

+ 95 - 29
security-protection-platform/src/modules/videoSurveillance/components/ReplayDialog/index.vue

@ -2,8 +2,20 @@
2 2
  <t-modal :visibled.sync="visible" :header-visibled="false" :footer-visibled="false" :no-padding="true" width="100%">
3 3
    <div class="replayer">
4 4
      <div class="replayer-list">
5
        <t-tabs v-model="currentTab" mode="scrollY" orientation="vertical" width="150px" @change="handleTabChange">
6
          <t-tab-panel v-for="item in list" :key="item.fileId" :label="item.fileName" :panel-id="item.fileId" />
5
        <div class="date-select-box row-12">
6
          <div class="col-12">
7
            <t-date-picker v-model="beginDay" type="dateTime" style="width:200px" placeholder="请选择开始时间"></t-date-picker>
8
          </div>
9
          <div class="col-12">
10
            <t-date-picker v-model="endDay" type="dateTime" style="width:200px" placeholder="请选择结束时间"></t-date-picker>
11
          </div>
12
          <div class="col-12 button-box" align="end">
13
            <t-button color="primary" @click="getData">查询</t-button>
14
            <t-button @click="resetData">重置</t-button>
15
          </div>
16
        </div>
17
        <t-tabs v-model="currentTab" mode="scrollY" orientation="vertical" width="100%" @change="handleTabChange">
18
          <t-tab-panel v-for="item in list" :key="item.monitorVideoLogId" :label="item.fileName|formatDateTime" :panel-id="item.fileId" />
7 19
        </t-tabs>
8 20
      </div>
9 21
@ -11,13 +23,7 @@
11 23
        <t-loading v-model="loadVideo">
12 24
          <span class="text-md text-info">获取视频资源...</span>
13 25
        </t-loading>
14
        <video-player
15
          :sources="videoList"
16
          :autoadvance="0"
17
          :style="{opacity: loadVideo ? 0: 1}"
18
          @player-inited="handlePlayerInited"
19
          @playlistitem="handlePlayerCurrentChange"
20
        />
26
        <video-player :sources="videoList" :autoadvance="0" :style="{opacity: loadVideo ? 0: 1}" @player-inited="handlePlayerInited" @playlistitem="handlePlayerCurrentChange" />
21 27
      </div>
22 28
    </div>
23 29
  </t-modal>
@ -25,39 +31,53 @@
25 31
26 32
<script>
27 33
import VideoPlayer from '@/components/VideoPlayer'
34
import formatDateTime from '@/utils/formatDateTime.js'
35
import sysapi from '@/api/videoSurveillance'
28 36
29 37
export default {
38
  filters: {
39
    formatDateTime
40
  },
30 41
  components: { VideoPlayer },
31 42
  props: {
32
    list: {
33
      type: Array,
34
      default: () => []
43
    replayId: {
44
      type: String
35 45
    },
36 46
    visibled: {
37 47
      type: Boolean,
38 48
      default: false
39 49
    }
40 50
  },
41
  data() {
51
  data () {
42 52
    return {
43 53
      currentTab: null,
44 54
      loadVideo: false,
55
      list: [],
45 56
      videoList: [],
46
      $player: null
57
      $player: null,
58
      // beginDay: formatDateTime(new Date(+new Date() - 10 * 60 * 1000), 'yyyy-MM-dd hh:mm:ss'),
59
      // endDay: formatDateTime(new Date(), 'yyyy-MM-dd hh:mm:ss')
60
      beginDay: '2020-12-18 17:19:00',
61
      endDay: '2020-12-18 17:19:59'
47 62
    }
48 63
  },
49 64
  computed: {
50 65
    visible: {
51
      get() { return this.visibled },
52
      set(val) {
66
      get () { return this.visibled },
67
      set (val) {
53 68
        if (!val) this.$player.pause()
54 69
        this.$emit('update:visibled', val)
55 70
      }
56 71
    }
57 72
  },
58 73
  watch: {
74
    replayId (val) {
75
      this.replayId = val
76
      this.getData()
77
    },
59 78
    list: {
60
      handler(val) {
79
      handler (val) {
80
        this.list = val
61 81
        console.warn(`list Change`)
62 82
        this.resetVideoList()
63 83
        if (val.length > 0) {
@ -69,22 +89,49 @@ export default {
69 89
      immediate: true
70 90
    }
71 91
  },
92
  mounted () {
93
    // this.list = [{
94
    //   fileName: '12月14日 16:55',
95
    //   fileId: 'ai-video_5A02296PAKA885B-video20201214165526.mp4',
96
    //   fileType: 'video/mp4'
97
    // }, {
98
    //   fileName: '12月14日 16:56',
99
    //   fileId: 'ai-video_5A02296PAKA885B-video20201214165527.mp4',
100
    //   fileType: 'video/mp4'
101
    // }, {
102
    //   fileName: '12月14日 16:57',
103
    //   fileId: 'ai-video_5A02296PAKA885B-video20201214165528.mp4',
104
    //   fileType: 'video/mp4'
105
    // }, {
106
    //   fileName: '12月14日 16:58',
107
    //   fileId: 'ai-video_5A02296PAKA885B-video20201214165529.mp4',
108
    //   fileType: 'video/mp4'
109
    // }, {
110
    //   fileName: '12月14日 16:59',
111
    //   fileId: 'ai-video_5A02296PAKA885B-video20201214165530.mp4',
112
    //   fileType: 'video/mp4'
113
    // }, {
114
    //   fileName: '12月14日 17:00',
115
    //   fileId: 'ai-video_5A02296PAKA885B-video20201214165531.mp4',
116
    //   fileType: 'video/mp4'
117
    // }]
118
  },
72 119
  methods: {
73
    handlePlayerInited(player) {
120
    handlePlayerInited (player) {
74 121
      this.$player = player
75 122
      window.player = this
76 123
    },
77
    async handleTabChange(name, index) {
124
    async handleTabChange (name, index) {
78 125
      this.$player.pause()
79 126
      await this.preloadOriVideoUrl(index)
80 127
      this.play(index)
81 128
    },
82
    handlePlayerCurrentChange(e, item) {
129
    handlePlayerCurrentChange (e, item) {
83 130
      const { index, fileId } = item
84 131
      this.currentTab = fileId
85 132
      this.preloadOriVideoUrl(index)
86 133
    },
87
    resetVideoList() {
134
    resetVideoList () {
88 135
      const videoList = this.list.map((item, index) => {
89 136
        const { fileId, fileType } = item
90 137
        return {
@ -97,7 +144,7 @@ export default {
97 144
98 145
      this.videoList = videoList
99 146
    },
100
    play(index) {
147
    play (index) {
101 148
      console.log(`播放:index=${index}`)
102 149
      // 调用额外的currentItem方法以避免currentItem在首次不生效
103 150
      // https://github.com/brightcove/videojs-playlist/blob/master/docs/api.md
@ -106,10 +153,10 @@ export default {
106 153
      this.$player.play()
107 154
    },
108 155
    /**
109
     *  从index开始预载videoList的视频地址
110
     *  此方法将在获取index对应的地址后就立即返回
111
     */
112
    preloadOriVideoUrl(index = 0, maxLength = 5) {
156
   *  从index开始预载videoList的视频地址
157
   *  此方法将在获取index对应的地址后就立即返回
158
   */
159
    preloadOriVideoUrl (index = 0, maxLength = 5) {
113 160
      return new Promise((resolve, reject) => {
114 161
        for (let i = index; i in this.videoList && i - index < maxLength; i++) {
115 162
          console.log(`预载地址:index=${i}`)
@ -136,9 +183,9 @@ export default {
136 183
      })
137 184
    },
138 185
    /*
139
     * 获取真实视频地址
140
     */
141
    getOriVideoUrl(fileId) {
186
   * 获取真实视频地址
187
   */
188
    getOriVideoUrl (fileId) {
142 189
      console.log(`请求地址:${fileId}`)
143 190
      // fake
144 191
      return new Promise((resolve, reject) => {
@ -152,6 +199,18 @@ export default {
152 199
          })
153 200
        }, 1000)
154 201
      })
202
    },
203
    async getData () {
204
      const res = await sysapi.queryMonitorVideoLog({ params: { id: this.replayId, beginDay: this.beginDay, endDay: this.endDay } })
205
      if (res.status === 200) {
206
        this.list = res.data.data
207
      } else {
208
        this.$Message.danger('视频列表数据获取失败!')
209
      }
210
    },
211
    resetData () {
212
      this.beginDay = formatDateTime(new Date(+new Date() - 10 * 60 * 1000), 'yyyy-MM-dd hh:mm:ss')
213
      this.endDay = formatDateTime(new Date(), 'yyyy-MM-dd hh:mm:ss')
155 214
    }
156 215
  }
157 216
}
@ -160,9 +219,16 @@ export default {
160 219
<style lang="scss">
161 220
.replayer {
162 221
  display: flex;
222
163 223
  &-list {
164 224
    margin-right: 20px;
165 225
    // width: 200px;
226
    .date-select-box {
227
      margin-top: 15px;
228
      > div {
229
        margin-bottom: 15px;
230
      }
231
    }
166 232
  }
167 233
168 234
  &-video {

+ 4 - 10
security-protection-platform/src/routes.js

@ -18,14 +18,14 @@ export const constantRoutes = [
18 18
    hidden: true
19 19
  },
20 20
  {
21
    name: 'dashboard',
21 22
    path: '/dashboard',
22
    component: Layout,
23
    meta: { icon: 'home' },
23
    component: () => import(/* webpackChunkName: "dashboard" */ './modules/dashboard'),
24
    meta: { title: '首页', icon: 'home' },
24 25
    children: [
25 26
      {
26
        name: 'dashboard',
27
        name: 'dashboardch',
27 28
        path: '',
28
        component: () => import(/* webpackChunkName: "dashboard" */ './modules/dashboard'),
29 29
        meta: { title: '首页', icon: 'home' }
30 30
      }
31 31
    ]
@ -40,12 +40,6 @@ export const constantRoutes = [
40 40
        path: '',
41 41
        component: () => import(/* webpackChunkName: "videoSurveillance" */ './modules/videoSurveillance'),
42 42
        meta: { title: '视频监控', icon: 'home' }
43
      },
44
      {
45
        name: 'videoSurveillance/distinguishRecord',
46
        path: '/videoSurveillance/distinguishRecord',
47
        component: () => import(/* webpackChunkName: "distinguishRecord" */ './modules/videoSurveillance/distinguishRecord'),
48
        hidden: true
49 43
      }
50 44
    ]
51 45
  },

BIN
security-protection-platform/static/video-js.swf