jiangping
2023-12-21 83c7cfa4ecd5d59106b09efff26be43141e38386
Merge remote-tracking branch 'origin/master'
已修改25个文件
734 ■■■■ 文件已修改
admin/src/api/business/device.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/api/business/visitEvent.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/utils/util.js 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/carEvent.vue 123 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/device.vue 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/deviceEvent.vue 115 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/retention.vue 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/visitEvent.vue 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_admin/src/main/java/com/doumee/api/business/CarEventController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_admin/src/main/java/com/doumee/api/business/DeviceEventController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_admin/src/main/java/com/doumee/api/business/ERPSyncController.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_admin/src/main/java/com/doumee/api/business/VisitEventController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/core/erp/model/openapi/request/erp/UserListRequest.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/dao/admin/response/CarEventDTO.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/dao/admin/response/DeviceEventDTO.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/dao/admin/response/VisitEventDTO.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/dao/business/model/DeviceEvent.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/dao/business/model/Member.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/dao/business/model/Retention.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/service/business/impl/CarEventServiceImpl.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/service/business/impl/DeviceEventServiceImpl.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/service/business/impl/RetentionServiceImpl.java 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/service/business/impl/VisitEventServiceImpl.java 39 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/service/business/impl/erp/ErpSyncServiceImpl.java 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/openapi/src/main/java/com/doumee/api/BizResourceController.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/api/business/device.js
@@ -7,6 +7,11 @@
  })
}
// 同步
export function syncDevices (data) {
  return request.post('/business/erpsync/syncDevices', data)
}
// 修改
export function updateById (data) {
  return request.post('/business/device/updateById', data)
admin/src/api/business/visitEvent.js
@@ -6,3 +6,11 @@
    trim: true
  })
}
// 导出Excel
export function exportExcel (data) {
  return request.post('/business/visitEvent/exportExcel', data, {
    trim: true,
    download: true
  })
}
admin/src/utils/util.js
@@ -18,3 +18,26 @@
  }
  return data
}
export function timeForMat (count) {
  // 拼接时间
  const time1 = new Date()
  const time2 = new Date()
  if (count === 1) {
    time1.setTime(time1.getTime() - (24 * 60 * 60 * 1000))
  } else {
    time1.setTime(time1.getTime())
  }
  const Y1 = time1.getFullYear()
  const M1 = ((time1.getMonth() + 1) > 9 ? (time1.getMonth() + 1) : '0' + (time1.getMonth() + 1))
  const D1 = (time1.getDate() > 9 ? time1.getDate() : '0' + time1.getDate())
  const timer1 = Y1 + '-' + M1 + '-' + D1 + ' ' + '23:59:59' // 当前时间
  time2.setTime(time2.getTime() - (24 * 60 * 60 * 1000 * count))
  const Y2 = time2.getFullYear()
  const M2 = ((time2.getMonth() + 1) > 9 ? (time2.getMonth() + 1) : '0' + (time2.getMonth() + 1))
  const D2 = (time2.getDate() > 9 ? time2.getDate() : '0' + time2.getDate())
  const timer2 = Y2 + '-' + M2 + '-' + D2 + ' ' + '00:00:00' // 之前的7天或者30天
  return [timer2, timer1]
}
admin/src/views/business/carEvent.vue
@@ -1,49 +1,47 @@
<template>
    <TableLayout :permissions="['business:category:query']">
    <TableLayout :permissions="['business:carevent:query']">
        <!-- 搜索表单 -->
        <el-form ref="searchForm" slot="search-form" :model="searchForm" label-width="100px" inline>
            <el-form-item label="车牌号" prop="plateNos">
                <el-input v-model="searchForm.plateNos" placeholder="请输入车牌号" @keypress.enter.native="search"></el-input>
            </el-form-item>
            <el-form-item label="姓名/手机号" prop="plateNos">
                <el-input v-model="searchForm.plateNos" placeholder="请输入姓名/手机号" @keypress.enter.native="search"></el-input>
            <el-form-item label="姓名/手机号" prop="keyWords">
                <el-input v-model="searchForm.keyWords" placeholder="请输入姓名/手机号" @keypress.enter.native="search"></el-input>
            </el-form-item>
            <el-form-item label="公司/部门名称" prop="plateNos">
                <el-input v-model="searchForm.plateNos" placeholder="请输入公司/部门名称" @keypress.enter.native="search"></el-input>
            <el-form-item label="公司/部门名称" prop="companyName">
                <el-input v-model="searchForm.companyName" placeholder="请输入公司/部门名称" @keypress.enter.native="search"></el-input>
            </el-form-item>
            <el-form-item label="人员类型" prop="plateNos">
                <el-select v-model="searchForm.plateNos" placeholder="请选择">
                    <el-option
                        v-for="item in options"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value">
                    </el-option>
            <el-form-item label="人员类型" prop="memberType">
                <el-select v-model="searchForm.memberType" placeholder="请选择">
                    <el-option label="劳务访客" value="0"></el-option>
                    <el-option label="普通访客" value="1"></el-option>
                    <el-option label="内部人员" value="2"></el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="事件类型" prop="eventType">
                <el-select v-model="searchForm.eventType" placeholder="请选择">
                    <el-option
                        v-for="item in options"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value">
                    </el-option>
                    <el-option label="入场压线事件" value="771760130"></el-option>
                    <el-option label="入场放行事件" value="771760131"></el-option>
                    <el-option label="出场压线事件" value="771760133"></el-option>
                    <el-option label="出场放行事件" value="771760134"></el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="起始时间" prop="eventType">
                <el-date-picker
                    v-model="searchForm.eventType"
                    type="daterange"
                    @change="seleTime"
                    v-model="time"
                    type="datetimerange"
                    format="yyyy-MM-dd HH:mm:ss"
                    value-format="yyyy-MM-dd HH:mm:ss"
                    range-separator="至"
                    start-placeholder="开始日期"
                    end-placeholder="结束日期">
                </el-date-picker>
            </el-form-item>
            <el-radio-group v-model="searchForm.eventType" size="small">
                <el-radio-button label="当天"></el-radio-button>
                <el-radio-button label="近7天"></el-radio-button>
                <el-radio-button label="近30天"></el-radio-button>
            <el-radio-group v-model="searchForm.radio" size="small" @input="changeRadio">
                <el-radio-button label="0">当天</el-radio-button>
                <el-radio-button label="1">近7天</el-radio-button>
                <el-radio-button label="2">近30天</el-radio-button>
            </el-radio-group>
            <section>
                <el-button type="primary" @click="search">搜索</el-button>
@@ -52,8 +50,8 @@
        </el-form>
        <!-- 表格和分页 -->
        <template v-slot:table-wrap>
            <ul class="toolbar" v-permissions="['business:member:create', 'business:member:delete']">
                <li><el-button type="primary" v-permissions="['business:member:create']">导出</el-button></li>
            <ul class="toolbar" v-permissions="['business:carevent:exportExcel']">
                <li><el-button type="primary" v-permissions="['business:carevent:exportExcel']">导出</el-button></li>
            </ul>
            <el-table
                v-loading="isWorking.search"
@@ -61,20 +59,34 @@
                stripe
            >
                <el-table-column prop="plateNos" label="车牌号" min-width="100px"></el-table-column>
                <el-table-column prop="plateNos" label="归属用户类型" min-width="100px"></el-table-column>
                <el-table-column prop="plateNos" label="姓名" min-width="100px"></el-table-column>
                <el-table-column prop="plateNos" label="手机号" min-width="100px"></el-table-column>
                <el-table-column prop="plateNos" label="公司/部门" min-width="100px"></el-table-column>
                <el-table-column label="归属用户类型" min-width="100px">
                    <template slot-scope="{row}">
                        <span v-if="row.personType === '0'">劳务访客</span>
                        <span v-if="row.personType === '1'">普通访客</span>
                        <span v-if="row.personType === '2'">内部人员</span>
                    </template>
                </el-table-column>
                <el-table-column prop="personName" label="姓名" min-width="100px"></el-table-column>
                <el-table-column prop="personPhone" label="手机号" min-width="100px"></el-table-column>
                <el-table-column prop="personCompanyName" label="公司/部门" min-width="100px"></el-table-column>
                <el-table-column prop="parkName" label="停车库名称" min-width="100px"></el-table-column>
                <el-table-column prop="gateName" label="出入口名称" min-width="100px"></el-table-column>
                <el-table-column prop="eventType" label="事件类型" min-width="100px"></el-table-column>
                <el-table-column prop="inoutType" label="出入类型" min-width="100px">
                <el-table-column prop="eventTypeName" label="事件类型" min-width="100px"></el-table-column>
                <el-table-column label="出入类型" min-width="100px">
                    <template slot-scope="{row}">
                        <span v-if="row.inoutType === 0">进场</span>
                        <span v-if="row.inoutType === 1">出场</span>
                    </template>
                </el-table-column>
                <el-table-column prop="vehiclePicUrl" label="抓拍图片" min-width="100px"></el-table-column>
                <el-table-column label="抓拍图片" min-width="100px">
                    <template slot-scope="{row}">
                        <el-image
                            style="width: 80px; height: 80px"
                            :src="row.vehiclePicUrl"
                            :preview-src-list="[row.vehiclePicUrl]">
                        </el-image>
                    </template>
                </el-table-column>
                <el-table-column prop="happenTime" label="事件时间" min-width="100px"></el-table-column>
            </el-table>
            <pagination
@@ -91,6 +103,7 @@
import BaseTable from '@/components/base/BaseTable'
import TableLayout from '@/layouts/TableLayout'
import Pagination from '@/components/common/Pagination'
import { timeForMat } from '@/utils/util'
export default {
  name: 'CarEvent',
  extends: BaseTable,
@@ -100,9 +113,15 @@
      // 搜索
      searchForm: {
        eventType: '',
        plateNos: ''
        keyWords: '',
        plateNos: '',
        memberType: '',
        companyName: '',
        startTime: '',
        endTime: '',
        radio: null
      },
      options: []
      time: []
    }
  },
  created () {
@@ -113,6 +132,38 @@
      'field.main': 'id'
    })
    this.search()
  },
  methods: {
    reset () {
      this.$refs.searchForm.resetFields()
      this.searchForm.startTime = ''
      this.searchForm.endTime = ''
      this.time = []
      this.searchForm.radio = null
      this.search()
    },
    changeRadio (e) {
      if (e === '0') {
        this.searchForm.startTime = timeForMat(1)[0]
        this.searchForm.endTime = timeForMat(1)[1]
        this.time = timeForMat(1)
      } else if (e === '1') {
        this.searchForm.startTime = timeForMat(7)[0]
        this.searchForm.endTime = timeForMat(7)[1]
        this.time = timeForMat(7)
      } else if (e === '2') {
        this.searchForm.startTime = timeForMat(30)[0]
        this.searchForm.endTime = timeForMat(30)[1]
        this.time = timeForMat(30)
      }
      this.search()
    },
    seleTime (e) {
      this.searchForm.startTime = e[0]
      this.searchForm.endTime = e[1]
      this.searchForm.radio = null
      this.search()
    }
  }
}
</script>
admin/src/views/business/device.vue
@@ -1,18 +1,15 @@
<template>
    <TableLayout :permissions="['business:company:query']">
    <TableLayout :permissions="['business:device:query']">
        <!-- 搜索表单 -->
        <el-form ref="searchForm" slot="search-form" :model="searchForm" label-width="100px" inline>
            <el-form-item label="门禁名称" prop="title">
                <el-input v-model="searchForm.title" placeholder="请输入门禁名称" @keypress.enter.native="search"></el-input>
            <el-form-item label="门禁名称" prop="name">
                <el-input v-model="searchForm.name" placeholder="请输入门禁名称" @keypress.enter.native="search"></el-input>
            </el-form-item>
            <el-form-item label="门禁等级" prop="level">
                <el-select v-model="searchForm.level" placeholder="请选择门禁等级" @keypress.enter.native="search">
                    <el-option
                        v-for="item in options"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value">
                    </el-option>
                    <el-option label="一级门禁" value="1"></el-option>
                    <el-option label="二级门禁" value="2"></el-option>
                    <el-option label="三级门禁" value="3"></el-option>
                </el-select>
            </el-form-item>
            <section>
@@ -23,7 +20,7 @@
        <!-- 表格和分页 -->
        <template v-slot:table-wrap>
            <ul class="toolbar">
                <li><el-button type="primary">同步</el-button></li>
                <li><el-button type="primary" @click="synchronousData">同步</el-button></li>
            </ul>
            <el-table
                v-loading="isWorking.search"
@@ -32,16 +29,16 @@
            >
                <el-table-column prop="manufature" label="厂商" min-width="100px"></el-table-column>
                <el-table-column prop="no" label="设备编号" min-width="100px"></el-table-column>
                <el-table-column prop="title" label="门禁名称" min-width="100px"></el-table-column>
                <el-table-column prop="name" label="门禁名称" min-width="100px"></el-table-column>
                <el-table-column prop="level" label="门禁等级" min-width="100px"></el-table-column>
                <el-table-column prop="status" label="设备状态 0禁用 1启用" min-width="100px">
                <el-table-column prop="status" label="设备状态" min-width="100px">
                    <template slot-scope="{row}">
                        <span v-if="row.status === 0">禁用</span>
                        <span v-if="row.status === 1">启用</span>
                    </template>
                </el-table-column>
                <el-table-column
                    v-if="containPermissions(['business:company:update'])"
                    v-if="containPermissions(['business:device:update'])"
                    label="操作"
                    min-width="120"
                    fixed="right"
@@ -68,6 +65,7 @@
import TableLayout from '@/layouts/TableLayout'
import Pagination from '@/components/common/Pagination'
import OperaDeviceWindow from '@/components/business/OperaDeviceWindow'
import { syncDevices } from '@/api/business/device'
export default {
  name: 'Device',
  extends: BaseTable,
@@ -76,7 +74,7 @@
    return {
      // 搜索
      searchForm: {
        title: '',
        name: '',
        level: ''
      },
      options: []
@@ -90,6 +88,26 @@
      'field.main': 'id'
    })
    this.search()
  },
  methods: {
    synchronousData () {
      this.$confirm('确认同步吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        syncDevices({})
          .then(res => {
            this.$message({
              type: 'success',
              message: '同步成功'
            })
            this.search()
          })
      }).catch(() => {
      })
    }
  }
}
</script>
admin/src/views/business/deviceEvent.vue
@@ -1,53 +1,53 @@
<template>
    <TableLayout :permissions="['business:member:query']">
    <TableLayout :permissions="['business:deviceevent:query']">
        <!-- 搜索表单 -->
        <el-form ref="searchForm" slot="search-form" :model="searchForm" label-width="100px" inline>
            <el-form-item label="姓名/手机号" prop="eventType">
                <el-input v-model="searchForm.eventType" placeholder="请输入姓名/手机号" @keypress.enter.native="search"></el-input>
            <el-form-item label="姓名/手机号" prop="keyWords">
                <el-input v-model="searchForm.keyWords" placeholder="请输入姓名/手机号" @keypress.enter.native="search"></el-input>
            </el-form-item>
            <el-form-item label="公司/组织名称" prop="eventType">
                <el-input v-model="searchForm.eventType" placeholder="请输入公司/组织名称" @keypress.enter.native="search"></el-input>
            <el-form-item label="公司/组织名称" prop="personCompanyName">
                <el-input v-model="searchForm.personCompanyName" placeholder="请输入公司/组织名称" @keypress.enter.native="search"></el-input>
            </el-form-item>
            <el-form-item label="人员类型" prop="userType">
                <el-select v-model="searchForm.userType" placeholder="请选择">
                    <el-option label="未知" value="0"></el-option>
                    <el-option label="普通" value="1"></el-option>
                    <el-option label="来宾" value="2"></el-option>
                    <el-option label="黑名单" value="3"></el-option>
                    <el-option label="管理员" value="4"></el-option>
            <el-form-item label="人员类型" prop="personType">
                <el-select v-model="searchForm.personType" placeholder="请选择">
                    <el-option label="劳务访客" value="0"></el-option>
                    <el-option label="普通访客" value="1"></el-option>
                    <el-option label="内部人员" value="2"></el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="事件类型" prop="eventType">
                <el-select v-model="searchForm.eventType" placeholder="请选择">
                    <el-option label="未知" value="0"></el-option>
                    <el-option label="普通" value="1"></el-option>
                    <el-option label="来宾" value="2"></el-option>
                    <el-option label="黑名单" value="3"></el-option>
                    <el-option label="管理员" value="4"></el-option>
                    <el-option label="人脸认证失败" value="197163"></el-option>
                    <el-option label="人脸认证通过" value="196893"></el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="起始时间" prop="eventType">
                <el-date-picker
                    v-model="searchForm.eventType"
                    type="daterange"
                    @change="seleTime"
                    v-model="time"
                    type="datetimerange"
                    format="yyyy-MM-dd HH:mm:ss"
                    value-format="yyyy-MM-dd HH:mm:ss"
                    range-separator="至"
                    start-placeholder="开始日期"
                    end-placeholder="结束日期">
                </el-date-picker>
            </el-form-item>
            <el-radio-group v-model="searchForm.eventType" size="small">
                <el-radio-button label="当天"></el-radio-button>
                <el-radio-button label="近7天"></el-radio-button>
                <el-radio-button label="近30天"></el-radio-button>
            <el-radio-group v-model="searchForm.radio" size="small" @input="changeRadio">
                <el-radio-button label="0">当天</el-radio-button>
                <el-radio-button label="1">近7天</el-radio-button>
                <el-radio-button label="2">近30天</el-radio-button>
            </el-radio-group>
            <section>
                <el-button type="primary" @click="search">搜索</el-button>
                <el-button type="primary" :loading="isWorking.export" v-permissions="['business:member:exportExcel']" @click="exportExcel">导出</el-button>
                <el-button @click="reset">重置</el-button>
            </section>
        </el-form>
        <!-- 表格和分页 -->
        <template v-slot:table-wrap>
            <ul class="toolbar" v-permissions="['business:deviceevent:exportExcel']">
                <li><el-button type="primary" :loading="isWorking.export" v-permissions="['business:deviceevent:exportExcel']" @click="exportExcel">导出</el-button></li>
            </ul>
            <el-table
                v-loading="isWorking.search"
                :data="tableData.list"
@@ -63,12 +63,26 @@
                <el-table-column prop="name" label="姓名" min-width="100px"></el-table-column>
                <el-table-column prop="phone" label="手机号" min-width="100px"></el-table-column>
                <el-table-column prop="idcard" label="身份证号码" min-width="100px"></el-table-column>
                <el-table-column prop="company" label="公司/组织" min-width="100px"></el-table-column>
                <el-table-column prop="srcName" label="门禁名称" min-width="100px"></el-table-column>
                <el-table-column prop="personCompanyName" label="公司/组织" min-width="100px"></el-table-column>
                <el-table-column prop="devName" label="门禁名称" min-width="100px"></el-table-column>
                <el-table-column prop="srcName" label="门禁点" min-width="100px"></el-table-column>
                <el-table-column prop="eventType" label="事件类型" min-width="100px"></el-table-column>
                <el-table-column prop="eventType" label="出入类型" min-width="100px"></el-table-column>
                <el-table-column prop="extEventPictureURL" label="抓拍照片" min-width="100px"></el-table-column>
                <el-table-column prop="eventTypeName" label="事件类型" min-width="100px"></el-table-column>
                <el-table-column label="出入类型" min-width="100px">
                    <template slot-scope="{row}">
                        <span v-if="row.extEventInOut === 1">进</span>
                        <span v-if="row.extEventInOut === 0">出</span>
                        <span v-if="row.extEventInOut === -1">未知</span>
                    </template>
                </el-table-column>
                <el-table-column label="抓拍照片" min-width="100px">
                    <template slot-scope="{row}">
                        <el-image
                            style="width: 80px; height: 80px"
                            :src="row.extEventPictureURL"
                            :preview-src-list="[row.extEventPictureURL]">
                        </el-image>
                    </template>
                </el-table-column>
                <el-table-column prop="happenTime" label="事件时间" min-width="100px"></el-table-column>
            </el-table>
            <pagination
@@ -85,6 +99,7 @@
import BaseTable from '@/components/base/BaseTable'
import TableLayout from '@/layouts/TableLayout'
import Pagination from '@/components/common/Pagination'
import { timeForMat } from '@/utils/util'
export default {
  name: 'DeviceEvent',
  extends: BaseTable,
@@ -93,9 +108,15 @@
    return {
      // 搜索
      searchForm: {
        keyWords: '',
        personCompanyName: '',
        personType: '',
        eventType: '',
        userType: ''
      }
        startTime: '',
        endTime: '',
        radio: null
      },
      time: []
    }
  },
  created () {
@@ -106,6 +127,38 @@
      'field.main': 'id'
    })
    this.search()
  },
  methods: {
    changeRadio (e) {
      if (e === '0') {
        this.searchForm.startTime = timeForMat(1)[0]
        this.searchForm.endTime = timeForMat(1)[1]
        this.time = timeForMat(1)
      } else if (e === '1') {
        this.searchForm.startTime = timeForMat(7)[0]
        this.searchForm.endTime = timeForMat(7)[1]
        this.time = timeForMat(7)
      } else if (e === '2') {
        this.searchForm.startTime = timeForMat(30)[0]
        this.searchForm.endTime = timeForMat(30)[1]
        this.time = timeForMat(30)
      }
      this.search()
    },
    seleTime (e) {
      this.searchForm.startTime = e[0]
      this.searchForm.endTime = e[1]
      this.searchForm.radio = null
      this.search()
    },
    reset () {
      this.$refs.searchForm.resetFields()
      this.searchForm.startTime = ''
      this.searchForm.endTime = ''
      this.time = []
      this.searchForm.radio = null
      this.search()
    }
  }
}
</script>
admin/src/views/business/retention.vue
@@ -1,15 +1,12 @@
<template>
    <TableLayout :permissions="['business:member:query']">
    <TableLayout :permissions="['business:retention:query']">
        <!-- 搜索表单 -->
        <el-form ref="searchForm" slot="search-form" :model="searchForm" label-width="100px" inline>
            <el-form-item label="姓名" prop="name">
                <el-input v-model="searchForm.name" placeholder="请输入姓名" @keypress.enter.native="search"></el-input>
            <el-form-item label="姓名/手机号" prop="keyWords">
                <el-input v-model="searchForm.keyWords" placeholder="请输入姓名/手机号" @keypress.enter.native="search"></el-input>
            </el-form-item>
            <el-form-item label="手机号" prop="phone">
                <el-input v-model="searchForm.phone" placeholder="请输入手机号" @keypress.enter.native="search"></el-input>
            </el-form-item>
            <el-form-item label="公司/部门名称" prop="companyId">
                <el-input v-model="searchForm.companyId" placeholder="请输入公司/部门名称" @keypress.enter.native="search"></el-input>
            <el-form-item label="公司/部门名称" prop="companyName">
                <el-input v-model="searchForm.companyName" placeholder="请输入公司/部门名称" @keypress.enter.native="search"></el-input>
            </el-form-item>
            <el-form-item label="人员类型" prop="type">
                <el-select v-model="searchForm.type" placeholder="请选择">
@@ -18,10 +15,13 @@
                    <el-option label="内部员工" value="2"></el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="起始时间" prop="companyId">
            <el-form-item label="起始时间" prop="startTime">
                <el-date-picker
                    v-model="searchForm.companyId"
                    type="daterange"
                    @change="seleTime"
                    v-model="time"
                    type="datetimerange"
                    format="yyyy-MM-dd HH:mm:ss"
                    value-format="yyyy-MM-dd HH:mm:ss"
                    range-separator="至"
                    start-placeholder="开始日期"
                    end-placeholder="结束日期">
@@ -34,8 +34,8 @@
        </el-form>
        <!-- 表格和分页 -->
        <template v-slot:table-wrap>
            <ul class="toolbar" v-permissions="['business:member:create', 'business:member:delete']">
                <li><el-button type="primary" :loading="isWorking.export" v-permissions="['business:member:exportExcel']" @click="exportExcel">导出</el-button></li>
            <ul class="toolbar" v-permissions="['business:retention:exportExcel']">
                <li><el-button type="primary" :loading="isWorking.export" v-permissions="['business:retention:exportExcel']" @click="exportExcel">导出</el-button></li>
            </ul>
            <el-table
                v-loading="isWorking.search"
@@ -44,7 +44,7 @@
                @selection-change="handleSelectionChange"
            >
                <el-table-column type="selection" width="55"></el-table-column>
                <el-table-column prop="companyId" label="公司/组织" min-width="100px"></el-table-column>
                <el-table-column prop="companyName" label="公司/组织" min-width="100px"></el-table-column>
                <el-table-column prop="type" label="人员类型" min-width="100px">
                    <template slot-scope="{row}">
                        <span v-if="row.type === 0">劳务访客</span>
@@ -54,10 +54,14 @@
                </el-table-column>
                <el-table-column prop="name" label="姓名" min-width="100px"></el-table-column>
                <el-table-column prop="phone" label="手机号" min-width="100px"></el-table-column>
                <el-table-column prop="idcardNo" label="身份证号" min-width="100px"></el-table-column>
                <el-table-column prop="eventDate" label="进场门禁" min-width="100px"></el-table-column>
                <el-table-column prop="idcardNo" label="身份证号" min-width="130px"></el-table-column>
                <el-table-column prop="deviceName" label="进场门禁" min-width="100px"></el-table-column>
                <el-table-column prop="eventDate" label="进场时间" min-width="100px"></el-table-column>
                <el-table-column prop="faceImg" label="进场抓拍照片" min-width="100px"></el-table-column>
                <el-table-column label="进场抓拍照片" min-width="100px">
                    <template slot-scope="{row}">
                        <el-image style="width: 80px; height: 80px;" :src="row.faceImg"></el-image>
                    </template>
                </el-table-column>
            </el-table>
            <pagination
                @size-change="handleSizeChange"
@@ -81,11 +85,13 @@
    return {
      // 搜索
      searchForm: {
        companyId: '',
        companyName: '',
        type: '',
        name: '',
        phone: ''
      }
        keyWords: '',
        startTime: '',
        endTime: ''
      },
      time: []
    }
  },
  created () {
@@ -96,6 +102,19 @@
      'field.main': 'id'
    })
    this.search()
  },
  methods: {
    reset () {
      this.$refs.searchForm.resetFields()
      this.searchForm.startTime = ''
      this.searchForm.endTime = ''
      this.time = []
      this.search()
    },
    seleTime (e) {
      this.searchForm.startTime = e[0]
      this.searchForm.endTime = e[1]
    }
  }
}
</script>
admin/src/views/business/visitEvent.vue
@@ -1,52 +1,38 @@
<template>
    <TableLayout :permissions="['business:member:query']">
    <TableLayout :permissions="['business:visitevent:query']">
        <!-- 搜索表单 -->
        <el-form ref="searchForm" slot="search-form" :model="searchForm" label-width="100px" inline>
            <el-form-item label="姓名" prop="personName">
                <el-input v-model="searchForm.personName" placeholder="请输入姓名" @keypress.enter.native="search"></el-input>
            </el-form-item>
            <el-form-item label="手机号码" prop="endTime">
                <el-input v-model="searchForm.endTime" placeholder="请输入手机号码" @keypress.enter.native="search"></el-input>
            <el-form-item label="姓名/手机号" prop="keyWords">
                <el-input v-model="searchForm.keyWords" placeholder="请输入姓名/手机号" @keypress.enter.native="search"></el-input>
            </el-form-item>
            <el-form-item label="车牌号" prop="carNo">
                <el-input v-model="searchForm.carNo" placeholder="请输入车牌号" @keypress.enter.native="search"></el-input>
            </el-form-item>
            <el-form-item label="公司名称" prop="endTime">
                <el-input v-model="searchForm.endTime" placeholder="请输入公司名称" @keypress.enter.native="search"></el-input>
            <el-form-item label="公司名称" prop="companyName">
                <el-input v-model="searchForm.companyName" placeholder="请输入公司名称" @keypress.enter.native="search"></el-input>
            </el-form-item>
            <el-form-item label="设备类型" prop="carNo">
                <el-select v-model="searchForm.carNo" placeholder="请选择">
                    <el-option
                        v-for="item in options"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value">
                    </el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="出入类型" prop="carNo">
                <el-select v-model="searchForm.carNo" placeholder="请选择">
                    <el-option
                        v-for="item in options"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value">
                    </el-option>
            <el-form-item label="事件类型" prop="eventType">
                <el-select v-model="searchForm.eventType" placeholder="请选择">
                    <el-option label="访客登记" value="1392513025"></el-option>
                    <el-option label="访客签离" value="1392513026"></el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="起始时间" prop="carNo">
                <el-date-picker
                    v-model="searchForm.carNo"
                    type="daterange"
                    @change="seleTime"
                    v-model="time"
                    type="datetimerange"
                    format="yyyy-MM-dd HH:mm:ss"
                    value-format="yyyy-MM-dd HH:mm:ss"
                    range-separator="至"
                    start-placeholder="开始日期"
                    end-placeholder="结束日期">
                </el-date-picker>
            </el-form-item>
            <el-radio-group v-model="searchForm.eventType" size="small">
                <el-radio-button label="当天"></el-radio-button>
                <el-radio-button label="近7天"></el-radio-button>
                <el-radio-button label="近30天"></el-radio-button>
            <el-radio-group v-model="searchForm.radio" size="small" @input="changeRadio">
                <el-radio-button label="0">当天</el-radio-button>
                <el-radio-button label="1">近7天</el-radio-button>
                <el-radio-button label="2">近30天</el-radio-button>
            </el-radio-group>
            <section>
                <el-button type="primary" @click="search">搜索</el-button>
@@ -55,22 +41,31 @@
        </el-form>
        <!-- 表格和分页 -->
        <template v-slot:table-wrap>
            <ul class="toolbar" v-permissions="['business:visitevent:exportExcel']">
                <li><el-button type="primary" :loading="isWorking.export" v-permissions="['business:visitevent:exportExcel']" @click="exportExcel">导出</el-button></li>
            </ul>
            <el-table
                v-loading="isWorking.search"
                :data="tableData.list"
                stripe
            >
                <el-table-column prop="personName" label="姓名" min-width="100px"></el-table-column>
                <el-table-column prop="endTime" label="手机号码" min-width="100px"></el-table-column>
                <el-table-column prop="personPhone" label="手机号码" min-width="100px"></el-table-column>
                <el-table-column prop="idNo" label="身份证号码" min-width="100px"></el-table-column>
                <el-table-column prop="idNo" label="公司" min-width="100px"></el-table-column>
                <el-table-column prop="personCompanyName" label="公司" min-width="100px"></el-table-column>
                <el-table-column prop="carNo" label="车牌号" min-width="100px"></el-table-column>
                <el-table-column prop="carNo" label="设备类型" min-width="100px"></el-table-column>
                <el-table-column prop="carNo" label="设备名称" min-width="100px"></el-table-column>
                <el-table-column prop="carNo" label="出入类型" min-width="100px"></el-table-column>
                <el-table-column prop="captureUrl" label="抓拍图uri" min-width="100px"></el-table-column>
                <el-table-column prop="happenTime" label="抓拍照片" min-width="100px"></el-table-column>
                <el-table-column prop="captureUrl" label="事件时间" min-width="100px"></el-table-column>
                <el-table-column prop="beVisitedPersonName" label="被访人" min-width="100px"></el-table-column>
                <el-table-column prop="eventTypeName" label="事件类型" min-width="100px"></el-table-column>
                <el-table-column label="抓拍图uri" min-width="100px">
                    <template slot-scope="{row}">
                        <el-image
                            style="width: 80px; height: 80px"
                            :src="row.captureUrl"
                            :preview-src-list="[row.captureUrl]">
                        </el-image>
                    </template>
                </el-table-column>
                <el-table-column prop="happenTime" label="事件时间" min-width="100px"></el-table-column>
            </el-table>
            <pagination
                @size-change="handleSizeChange"
@@ -86,6 +81,7 @@
import BaseTable from '@/components/base/BaseTable'
import TableLayout from '@/layouts/TableLayout'
import Pagination from '@/components/common/Pagination'
import { timeForMat } from '@/utils/util'
export default {
  name: 'VisitEvent',
  extends: BaseTable,
@@ -95,10 +91,15 @@
      // 搜索
      searchForm: {
        personName: '',
        carNo: '',
        keyWords: '',
        startTime: '',
        endTime: '',
        carNo: ''
        eventType: '',
        companyName: '',
        radio: null
      },
      options: []
      time: []
    }
  },
  created () {
@@ -109,6 +110,38 @@
      'field.main': 'id'
    })
    this.search()
  },
  methods: {
    seleTime (e) {
      this.searchForm.startTime = e[0]
      this.searchForm.endTime = e[1]
      this.searchForm.radio = null
      this.search()
    },
    changeRadio (e) {
      if (e === '0') {
        this.searchForm.startTime = timeForMat(1)[0]
        this.searchForm.endTime = timeForMat(1)[1]
        this.time = timeForMat(1)
      } else if (e === '1') {
        this.searchForm.startTime = timeForMat(7)[0]
        this.searchForm.endTime = timeForMat(7)[1]
        this.time = timeForMat(7)
      } else if (e === '2') {
        this.searchForm.startTime = timeForMat(30)[0]
        this.searchForm.endTime = timeForMat(30)[1]
        this.time = timeForMat(30)
      }
      this.search()
    },
    reset () {
      this.$refs.searchForm.resetFields()
      this.searchForm.startTime = ''
      this.searchForm.endTime = ''
      this.time = []
      this.searchForm.radio = null
      this.search()
    }
  }
}
</script>
server/dmvisit_admin/src/main/java/com/doumee/api/business/CarEventController.java
@@ -77,7 +77,7 @@
    @ApiOperation("导出Excel")
    @PostMapping("/exportExcel")
    @RequiresPermissions("business:carevent:exportExcel")
    //@RequiresPermissions("business:carevent:exportExcel")
    public void exportExcel (@RequestBody PageWrap<CarEvent> pageWrap, HttpServletResponse response) {
        ExcelExporter.build(CarEvent.class).exportWithFirstAndEnd (carEventService.findPage(pageWrap).getRecords(),"停车场事件推送记录表", null, "停车场事件推送记录导出报表",null , response);
//        ExcelExporter.build(CarEvent.class).export(carEventService.findPage(pageWrap).getRecords(), "停车场事件推送记录表", response);
server/dmvisit_admin/src/main/java/com/doumee/api/business/DeviceEventController.java
@@ -77,7 +77,7 @@
    @ApiOperation("导出Excel")
    @PostMapping("/exportExcel")
    @RequiresPermissions("business:deviceevent:exportExcel")
    //@RequiresPermissions("business:deviceevent:exportExcel")
    public void exportExcel (@RequestBody PageWrap<DeviceEvent> pageWrap, HttpServletResponse response) {
        ExcelExporter.build(DeviceEvent.class).export(deviceEventService.findPage(pageWrap).getRecords(), "门禁事件推送记录表", response);
    }
server/dmvisit_admin/src/main/java/com/doumee/api/business/ERPSyncController.java
@@ -34,9 +34,9 @@
    private HkSyncPrivilegeServiceImpl hkSyncPrivilegeService;
    @PreventRepeat
    @ApiOperation("【ERP】全量同步组织信息接口")
    @PostMapping("/syncCompanies")
    @RequiresPermissions("business:erpsync:company")
    @ApiOperation("【ERP】全量同步门禁设备接口")
    @PostMapping("/syncDevices")
    //@RequiresPermissions("business:erpsync:device")
    public ApiResponse getDevices(@RequestBody AcsDeviceListRequest param) {
        String result = hkSyncDeviceService.syncHkDevices(param);
        return ApiResponse.success(result);
server/dmvisit_admin/src/main/java/com/doumee/api/business/VisitEventController.java
@@ -77,7 +77,7 @@
    @ApiOperation("导出Excel")
    @PostMapping("/exportExcel")
    @RequiresPermissions("business:visitevent:exportExcel")
    //@RequiresPermissions("business:visitevent:exportExcel")
    public void exportExcel (@RequestBody PageWrap<VisitEvent> pageWrap, HttpServletResponse response) {
        ExcelExporter.build(VisitEvent.class).export(visitEventService.findPage(pageWrap).getRecords(), "访客事件推送记录表", response);
    }
server/dmvisit_service/src/main/java/com/doumee/core/erp/model/openapi/request/erp/UserListRequest.java
@@ -4,6 +4,8 @@
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
 * 分类信息表
 * @author 江蹄蹄
@@ -21,7 +23,7 @@
    @ApiModelProperty(value = "身份证号" )
    private String idNo;
    @ApiModelProperty(value = "时间范围-开始,格式yyyy-MM-dd HH:mm:ss,如2023-11-24 09:17:11" )
    private String startTime ;
    private Date startTime ;
    @ApiModelProperty(value = "时间范围-截止,格式yyyy-MM-dd HH:mm:ss,如2023-11-24 09:17:11" )
    private String endTime ;
    private Date endTime ;
}
server/dmvisit_service/src/main/java/com/doumee/dao/admin/response/CarEventDTO.java
@@ -49,7 +49,9 @@
    private String srcName;
    @ApiModelProperty(value = "事件类型")
    private String eventType;
    private Integer eventType;
    @ApiModelProperty(value = "事件类型名称")
    private String eventTypeName;
    @ApiModelProperty(value = "事件状态,0-瞬时 1-开始2-停止4-事件联动结果更新5-事件图片异步上传")
    private Integer status;
server/dmvisit_service/src/main/java/com/doumee/dao/admin/response/DeviceEventDTO.java
@@ -36,8 +36,10 @@
    @ApiModelProperty(value = "事件唯一标识,同一事件若上报多次,则上报事件的eventId相同")
    private String eventId;
    @ApiModelProperty(value = "事件类型")
    private String eventType;
    @ApiModelProperty(value = "事件类型 -- 197163,人脸认证失败 ; 196893,人脸认证通过")
    private Integer eventType;
    @ApiModelProperty(value = "事件类型名称")
    private String eventTypeName;
    @ApiModelProperty(value = "事件源类型,如“acsDevice”")
    private String srcType;
@@ -48,9 +50,11 @@
    @ApiModelProperty(value = "门禁点唯一接入编码")
    private String srcIndex;
    @ApiModelProperty(value = "门禁名称")
    @ExcelColumn(name="门禁名称")
    @ApiModelProperty(value = "门禁点名称")
    private String srcName;
    @ApiModelProperty(value = "门禁名称")
    private String devName;
    @ApiModelProperty(value = "事件状态,0-瞬时1-开始2-停止4-事件联动结果更新5-事件图片异步上传")
    private Integer status;
@@ -191,4 +195,6 @@
    @ApiModelProperty(value = "通道总通行人数")
    private Integer totalTimes;
    @ApiModelProperty(value = "控制器设备唯一接入编码")
    private String srcParentIndex;
}
server/dmvisit_service/src/main/java/com/doumee/dao/admin/response/VisitEventDTO.java
@@ -46,7 +46,10 @@
    private String srcName;
    @ApiModelProperty(value = "事件类型")
    private String eventType;
    private Integer eventType;
    @ApiModelProperty(value = "事件类型名称")
    private String eventTypeName;
    @ApiModelProperty(value = "事件状态,0-瞬时1-开始2-停止4-事件联动结果更新5-事件图片异步上传")
    private Integer status;
server/dmvisit_service/src/main/java/com/doumee/dao/business/model/DeviceEvent.java
@@ -261,6 +261,10 @@
    @ExcelColumn(name="通道总通行人数")
    private Integer totalTimes;
    @ApiModelProperty(value = "控制器设备唯一接入编码")
    @ExcelColumn(name = "控制器设备唯一接入编码")
    private String srcParentIndex;
    // 条件查询参数
    @ApiModelProperty(value = "关键字,姓名/手机号")
server/dmvisit_service/src/main/java/com/doumee/dao/business/model/Member.java
@@ -211,6 +211,10 @@
    @TableField(exist = false)
    private String roleIdParam;
    @ApiModelProperty(value = "授权门禁组编码集合,【访客端】唯一标识",hidden = true )
    @TableField(exist = false)
    private Integer[] roleIds;
    //暂无使用
    @ApiModelProperty(value = "姓名/手机号/工号")
    @TableField(exist = false)
server/dmvisit_service/src/main/java/com/doumee/dao/business/model/Retention.java
@@ -123,12 +123,15 @@
    // 条件查询参数
    @ApiModelProperty(value = "姓名/手机号")
    @TableField(exist = false)
    private String keyWords;
    @ApiModelProperty(value = "开始时间")
    @TableField(exist = false)
    private Date startTime;
    @ApiModelProperty(value = "结束时间")
    @TableField(exist = false)
    private Date endTime;
}
server/dmvisit_service/src/main/java/com/doumee/service/business/impl/CarEventServiceImpl.java
@@ -3,14 +3,20 @@
import cn.hutool.core.lang.PatternPool;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ReUtil;
import com.doumee.core.haikang.model.HKConstants;
import com.doumee.core.model.PageData;
import com.doumee.core.model.PageWrap;
import com.doumee.core.utils.Constants;
import com.doumee.core.utils.Utils;
import com.doumee.dao.admin.request.VisitEventQuery;
import com.doumee.dao.admin.response.CarEventDTO;
import com.doumee.dao.admin.response.DeviceEventDTO;
import com.doumee.dao.admin.response.VisitEventDTO;
import com.doumee.dao.business.CarEventMapper;
import com.doumee.dao.business.join.CarEventJoinMapper;
import com.doumee.dao.business.model.*;
import com.doumee.dao.system.SystemDictDataMapper;
import com.doumee.dao.system.model.SystemDictData;
import com.doumee.service.business.CarEventService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
@@ -22,8 +28,9 @@
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Objects;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
 * 停车场事件推送记录表Service实现
@@ -38,6 +45,9 @@
    @Autowired
    private CarEventJoinMapper carEventJoinMapper;
    @Autowired
    private SystemDictDataMapper systemDictDataMapper;
    @Override
    public Integer create(CarEvent carEvent) {
@@ -308,7 +318,32 @@
                    .le(Objects.nonNull(pageWrap.getModel().getEndTime()),
                            CarEvent::getCreateDate, pageWrap.getModel().getEndTime());
        IPage<CarEventDTO> carEventDTOIPage = carEventJoinMapper.selectJoinPage(page, CarEventDTO.class, queryWrapper);
        if(null != carEventDTOIPage && carEventDTOIPage.getRecords().size() > 0) {
            carEventDTOIPage.setRecords(newCarEventDTO(carEventDTOIPage.getRecords()));
        }
        return PageData.from(carEventDTOIPage);
    }
    private List<CarEventDTO> newCarEventDTO(List<CarEventDTO> newCarEventDTOList) {
        List<String> codes = Arrays.asList(Constants.FTP_RESOURCE_PATH,Constants.CAR_EVENT_IMG);
        List<SystemDictData> list = systemDictDataMapper.list(codes);
        Map<String,SystemDictData> dataMap = list.stream().collect(Collectors.toMap(SystemDictData::getLabel, Function.identity()));
        List<CarEventDTO> newDataList = new ArrayList<>();
        newCarEventDTOList.stream().forEach(obj->{
            obj.setVehiclePicUrl(dataMap.get(Constants.FTP_RESOURCE_PATH).getCode()
                    +dataMap.get(Constants.CAR_EVENT_IMG).getCode()
                    +obj.getVehiclePicUrl());
            if(Constants.formatIntegerNum(obj.getEventType()) == HKConstants.EventTypes.PARK_LINE_IN.getKey()){
                obj.setEventTypeName(HKConstants.EventTypes.PARK_LINE_IN.getName());
            }else if(Constants.formatIntegerNum(obj.getEventType()) == HKConstants.EventTypes.PARK_PASS_IN.getKey()){
                obj.setEventTypeName(HKConstants.EventTypes.PARK_PASS_IN.getName());
            }else if(Constants.formatIntegerNum(obj.getEventType()) == HKConstants.EventTypes.PARK_LINE_OUT.getKey()){
                obj.setEventTypeName(HKConstants.EventTypes.PARK_LINE_OUT.getName());
            }else{
                obj.setEventTypeName(HKConstants.EventTypes.PARK_PASS_OUT.getName());
            }
            newDataList.add(obj);
        });
        return newDataList;
    }
}
server/dmvisit_service/src/main/java/com/doumee/service/business/impl/DeviceEventServiceImpl.java
@@ -4,6 +4,7 @@
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.ReUtil;
import com.doumee.core.haikang.model.HKConstants;
import com.doumee.core.model.PageData;
import com.doumee.core.model.PageWrap;
import com.doumee.core.utils.Constants;
@@ -13,6 +14,7 @@
import com.doumee.dao.business.DeviceEventMapper;
import com.doumee.dao.business.join.DeviceEventJoinMapper;
import com.doumee.dao.business.model.Company;
import com.doumee.dao.business.model.Device;
import com.doumee.dao.business.model.DeviceEvent;
import com.doumee.dao.business.model.Member;
import com.doumee.dao.system.SystemDictDataMapper;
@@ -309,18 +311,20 @@
        boolean hasWord = ReUtil.contains(PatternPool.WORD, pageWrap.getModel().getKeyWords());
        queryWrapper.leftJoin(Member.class,Member::getHkId,DeviceEvent::getExtEventPersonNo)
                    .leftJoin(Company.class,Company::getId,Member::getCompanyId)
                    .leftJoin(Device.class,Device::getHkId,DeviceEvent::getSrcParentIndex)
                    .selectAll(DeviceEvent.class)
                    .selectAs(Member::getName,DeviceEventDTO::getPersonName)
                    .selectAs(Member::getType,DeviceEventDTO::getPersonType)
                    .selectAs(Member::getPhone,DeviceEventDTO::getPersonPhone)
                    .selectAs(Member::getIdcardDecode,DeviceEventDTO::getPersonIdcardDecode)
                    .selectAs(Device::getName,DeviceEventDTO::getDevName)
                    .selectAs(Company::getName,DeviceEventDTO::getPersonCompanyName);
        queryWrapper.like(number, Member::getPhone, pageWrap.getModel().getKeyWords())
                    .like((b||hasWord),Member::getName, pageWrap.getModel().getKeyWords())
                    .eq(StringUtils.isNotBlank(pageWrap.getModel().getPersonType()),
                                                Member::getType,
                                                pageWrap.getModel().getPersonType())
                    .eq( pageWrap.getModel().getEventType()!=null,
                    .eq(Objects.nonNull(pageWrap.getModel().getEventType()),
                                                DeviceEvent::getEventType,
                                                pageWrap.getModel().getEventType())
                    .ge(Objects.nonNull(pageWrap.getModel().getStartTime()),
@@ -360,6 +364,11 @@
                   dto.setExtEventPictureURL(null);
               }
           }
            if(Constants.formatIntegerNum(dto.getEventType()) == HKConstants.EventTypes.DOOR_FACE_AUTH_SUCCESS.getKey()){
                dto.setEventTypeName(HKConstants.EventTypes.DOOR_FACE_AUTH_SUCCESS.getName());
            }else if(Constants.formatIntegerNum(dto.getEventType()) == HKConstants.EventTypes.DOOR_FACE_AUTH_FAIL.getKey()){
                dto.setEventTypeName(HKConstants.EventTypes.DOOR_FACE_AUTH_FAIL.getName());
            }
            newDeviceEventDTOS.add(dto);
        }
        return newDeviceEventDTOS;
server/dmvisit_service/src/main/java/com/doumee/service/business/impl/RetentionServiceImpl.java
@@ -5,11 +5,14 @@
import cn.hutool.core.util.ReUtil;
import com.doumee.core.model.PageData;
import com.doumee.core.model.PageWrap;
import com.doumee.core.utils.Constants;
import com.doumee.core.utils.Utils;
import com.doumee.dao.admin.request.RetentionQuery;
import com.doumee.dao.business.RetentionMapper;
import com.doumee.dao.business.join.RetentionJoinMapper;
import com.doumee.dao.business.model.*;
import com.doumee.dao.system.SystemDictDataMapper;
import com.doumee.dao.system.model.SystemDictData;
import com.doumee.service.business.RetentionService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
@@ -21,9 +24,9 @@
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
 * 在厂人员信息 表(滞留)Service实现
@@ -38,6 +41,9 @@
    @Autowired
    private RetentionJoinMapper retentionJoinMapper;
    @Autowired
    private SystemDictDataMapper systemDictDataMapper;
    @Override
@@ -215,6 +221,16 @@
                            Retention::getEventDate,pageWrap.getModel().getStartTime());
        queryWrapper.orderByDesc(Retention::getCreateDate);
        IPage<Retention> retentionIPage = retentionJoinMapper.selectJoinPage(page, Retention.class, queryWrapper);
        if(null != retentionIPage && retentionIPage.getRecords().size() > 0) {
            List<String> codes = Arrays.asList(Constants.FTP_RESOURCE_PATH,Constants.MEMBER_IMG);
            List<SystemDictData> list = systemDictDataMapper.list(codes);
            Map<String,SystemDictData> dataMap = list.stream().collect(Collectors.toMap(SystemDictData::getLabel, Function.identity()));
            retentionIPage.getRecords().stream().forEach(obj->{
                obj.setFaceImg(dataMap.get(Constants.FTP_RESOURCE_PATH).getCode()
                        +dataMap.get(Constants.MEMBER_IMG).getCode()
                        +obj.getFaceImg());
            });
        }
        return PageData.from(retentionIPage);
    }
}
server/dmvisit_service/src/main/java/com/doumee/service/business/impl/VisitEventServiceImpl.java
@@ -3,14 +3,19 @@
import cn.hutool.core.lang.PatternPool;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ReUtil;
import com.doumee.core.haikang.model.HKConstants;
import com.doumee.core.model.PageData;
import com.doumee.core.model.PageWrap;
import com.doumee.core.utils.Constants;
import com.doumee.core.utils.Utils;
import com.doumee.dao.admin.request.VisitEventQuery;
import com.doumee.dao.admin.response.DeviceEventDTO;
import com.doumee.dao.admin.response.VisitEventDTO;
import com.doumee.dao.business.VisitEventMapper;
import com.doumee.dao.business.join.VisitEventJoinMapper;
import com.doumee.dao.business.model.*;
import com.doumee.dao.system.SystemDictDataMapper;
import com.doumee.dao.system.model.SystemDictData;
import com.doumee.service.business.VisitEventService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
@@ -22,8 +27,9 @@
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Objects;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
 * 访客事件推送记录表Service实现
@@ -38,6 +44,9 @@
    @Autowired
    private VisitEventJoinMapper visitEventJoinMapper;
    @Autowired
    private SystemDictDataMapper systemDictDataMapper;
    @Override
    public Integer create(VisitEvent visitEvent) {
@@ -236,9 +245,9 @@
        IPage<VisitEvent> page = new Page<>(pageWrap.getPage(), pageWrap.getCapacity());
        MPJLambdaWrapper<VisitEvent> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper .leftJoin(Company.class,Company::getId,Member::getCompanyId);
        queryWrapper .leftJoin(Visits.class,Visits::getHkId,VisitEvent::getVisitorId);
        queryWrapper.selectAll(VisitEvent.class)
                    .selectAs(Company::getName,VisitEventDTO::getPersonCompanyName);
                    .selectAs(Visits::getCompanyName,VisitEventDTO::getPersonCompanyName);
        queryWrapper.like(number,
                            VisitEvent::getPhone,
                            pageWrap.getModel().getKeyWords())
@@ -262,8 +271,28 @@
                            pageWrap.getModel().getEndTime());
        queryWrapper.orderByDesc(VisitEvent::getHappenTime);
        IPage<VisitEventDTO> visitEventDTOIPage = visitEventJoinMapper.selectJoinPage(page, VisitEventDTO.class, queryWrapper);
        if(null != visitEventDTOIPage && visitEventDTOIPage.getRecords().size() > 0) {
            visitEventDTOIPage.setRecords(newVisitEvent(visitEventDTOIPage.getRecords()));
        }
        return PageData.from(visitEventDTOIPage);
    }
    private List<VisitEventDTO> newVisitEvent(List<VisitEventDTO> VisitEventDTOList) {
        List<String> codes = Arrays.asList(Constants.FTP_RESOURCE_PATH,Constants.MEMBER_IMG);
        List<SystemDictData> list = systemDictDataMapper.list(codes);
        Map<String,SystemDictData> dataMap = list.stream().collect(Collectors.toMap(SystemDictData::getLabel, Function.identity()));
        List<VisitEventDTO> newDataList = new ArrayList<>();
        VisitEventDTOList.stream().forEach(obj->{
            obj.setCaptureUrl(dataMap.get(Constants.FTP_RESOURCE_PATH).getCode()
                    +dataMap.get(Constants.MEMBER_IMG).getCode()
                    +obj.getCaptureUrl());
            if(Constants.formatIntegerNum(obj.getEventType()) == HKConstants.EventTypes.VISIT_SIGN_IN.getKey()){
                obj.setEventTypeName(HKConstants.EventTypes.VISIT_SIGN_IN.getName());
            }else if(Constants.formatIntegerNum(obj.getEventType()) == HKConstants.EventTypes.VISIT_SIGN_OUT.getKey()){
                obj.setEventTypeName(HKConstants.EventTypes.VISIT_SIGN_OUT.getName());
            }
            newDataList.add(obj);
        });
        return newDataList;
    }
}
server/dmvisit_service/src/main/java/com/doumee/service/business/impl/erp/ErpSyncServiceImpl.java
@@ -271,31 +271,46 @@
            List<Member> addList = new ArrayList<>();
            List<Member> updateList = new ArrayList<>();
            List<Integer> delIds = new ArrayList<>(); 
            List<Member> delList = new ArrayList<>();
            List<Member> allList = memberMapper.selectList(new QueryWrapper<Member>().lambda()
                    .eq(Member::getIsdeleted,Constants.ZERO)
                    .eq(Member::getType, Constants.memberType.internal));
            dealUserChangeList(list,addList,updateList,delIds,allList);
            dealUserChangeList(list,addList,updateList,delList,allList);
            if(addList.size()>0){
                for (Member member:addList) {
                    dealRoleEmpower(member,param.getStartTime(), param.getEndTime());
                }
                memberMapper.insertBatchSomeColumn(addList);
            }
            if(updateList.size()>0){
                for(Member c : updateList){
                    dealRoleEmpower(c,param.getStartTime(), param.getEndTime());
                    memberMapper.updateById(c);
                }
            }
            if(delIds.size()>0){
                //删除所有需要删除的组织信息(逻辑删除)
            if(delList.size()>0){
                for (Member member:delList) {
                    dealRoleEmpower(member,param.getStartTime(), param.getEndTime());
                }
                delIds = delList.stream().map(m->m.getId()).collect(Collectors.toList());
                memberMapper.update(null,new UpdateWrapper<Member>().lambda().set(Member::getHkStatus,Constants.ZERO)
                        .set(Member::getIsdeleted, Constants.ONE).in(Member::getId,delIds));
            }
        }else{
            throw  new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "同步ERP数据为空!");
        }
        return  null;
    }
    private void dealUserChangeList(List<UserListRespone> list, List<Member> addList, List<Member> updateList, List<Integer> delIds, List<Member> allList) {
    public void dealRoleEmpower(Member member,Date startTime , Date endTime){
        List<Integer> doorIds = null;
        doorIds = getRoleIdByParam(member.getRoleIds(),member);
        //如果有授权门禁数据,进行用户授权数据下发任务创建
        dealMemberRoleEmpower(member,doorIds,startTime,endTime);
    }
    private void dealUserChangeList(List<UserListRespone> list, List<Member> addList, List<Member> updateList,List<Member> delList, List<Member> allList) {
        Date date = new Date();
        for(UserListRespone response : list){
            //根据 erpId 查询用户信息,判断是新增还是更新
@@ -311,7 +326,10 @@
                //如果是更新
                if(Constants.formatIntegerNum(response.getIsdeleted()) == Constants.ONE){
                    //如果已删除,加入删除集合中
                    delIds.add(member.getId());
                    member.setRoleIds(response.getRoleIds());
                    delList.add(member);
//                    delIds.add(member.getId());
                    continue;
                }
                updateList.add(addUpdateMemberModel(response,member,date));
@@ -320,7 +338,8 @@
        if(allList!=null && allList.size()>0){
            for(Member  c : allList){
                if(isUserDeleted(c,list)){
                    delIds.add(c.getId());
                    delList.add(c);
//                    delIds.add(c.getId());
                }
            }
        }
@@ -341,6 +360,7 @@
        member.setIdcardDecode(Constants.getTuominStr(param.getIdNo()));
        member.setCompanyId(param.getOrgId());
        member.setHkStatus(Constants.ZERO);
        member.setRoleIds(param.getRoleIds());
        return  member;
    }
@@ -353,12 +373,14 @@
        member.setEditDate(new Date());
        member.setErpDate(new Date());
        member.setHkStatus(Constants.ZERO);
        member.setRoleIds(param.getRoleIds());
        return  member;
    }
    private boolean isUserDeleted(Member c, List<UserListRespone> list) {
        for(UserListRespone m : list){
            if(StringUtils.equals(c.getErpId(),m.getId().toString())){
                c.setRoleIds(m.getRoleIds());
                return  true;
            }
        }
server/openapi/src/main/java/com/doumee/api/BizResourceController.java
@@ -1,11 +1,13 @@
package com.doumee.api;
import com.doumee.biz.system.SystemDictDataBiz;
import com.doumee.config.annotation.ErpLoginRequired;
import com.doumee.core.model.ApiResponse;
import com.doumee.core.model.PageData;
import com.doumee.core.model.PageWrap;
import com.doumee.core.erp.model.openapi.request.*;
import com.doumee.core.erp.model.openapi.response.*;
import com.doumee.core.utils.Constants;
import com.doumee.service.business.ERPSyncService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
@@ -15,7 +17,9 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * Created by IntelliJ IDEA.
@@ -32,6 +36,9 @@
    @Autowired
    private ERPSyncService erpSyncService;
    @Autowired
    private SystemDictDataBiz systemDictDataBiz;
    @ApiOperation(value = "调用凭据获取接口", notes = "访客端提供,供ERP端调用,向ERP提供统接口调用凭证")
@@ -147,6 +154,34 @@
        erpSyncService.approveApply(param);
        return  ApiResponse.success(null);
    }
    @ApiOperation(value = "FTP账户信息", notes = "访客端提供,供ERP端调用,FTP账户信息")
    @GetMapping("/resource/ftpAccount")
    public ApiResponse<Map<String,Object>> ftpAccount() {
        Map<String,Object> map = new HashMap<>();
        map.put("FTP主机地址IP",
        systemDictDataBiz.queryByCode(Constants.FTP,Constants.FTP_HOST).getCode());
        map.put("FTP访问端口",
        systemDictDataBiz.queryByCode(Constants.FTP,Constants.FTP_PORT).getCode());
        map.put("FTP访问登录名",
        systemDictDataBiz.queryByCode(Constants.FTP,Constants.FTP_USERNAME).getCode());
        map.put("FTP访问登陆密码",
        systemDictDataBiz.queryByCode(Constants.FTP,Constants.FTP_PWD).getCode());
        map.put("FTP访客事件图片存储目录",
        systemDictDataBiz.queryByCode(Constants.FTP,Constants.VISIT_EVENT_IMG).getCode());
        map.put("FTP车辆事件图片存储目录",
        systemDictDataBiz.queryByCode(Constants.FTP,Constants.CAR_EVENT_IMG).getCode());
        map.put("FTP门禁事件图片存储目录",
        systemDictDataBiz.queryByCode(Constants.FTP,Constants.DEVICE_EVENT_IMG).getCode());
        map.put("FTP用户图片存储目录",
        systemDictDataBiz.queryByCode(Constants.FTP,Constants.MEMBER_IMG).getCode());
        return  ApiResponse.success(map);
    }
}