Commit 3ca4c554 by 李乾广

试乘接待开发,批次开发

1 parent d94b1f16
......@@ -34,6 +34,10 @@ const menuRoute = [
component: () => import("@/views/SnapshotCluster1/SnapshotCluster.vue"),
},
{
path: 'TestDriveHospitality',
component: () => import("@/views/TestDriveHospitality/SnapshotCluster.vue"),
},
{
path: 'SourceTrajectoryAnalysis',
component: () => import("@/views/SourceTrajectoryAnalysis/index.vue"),
},
......
......@@ -55,6 +55,12 @@
<span style="padding: 0 5px">抓拍聚类</span>
</div>
</a-menu-item>
<a-menu-item :key="'/Main/TestDriveHospitality'">
<div class="flex-vertical-center">
<img :src="require('./Icons/6.svg')" style="height: auto;width:20px"/>
<span style="padding: 0 5px">试乘接待</span>
</div>
</a-menu-item>
<a-menu-item :key="'/Main/EquipmentTimeErrorVerification'">
<div class="flex-vertical-center">
<img :src="require('./Icons/7.svg')" style="height: auto;width:20px"/>
......
......@@ -66,6 +66,7 @@
<a-select-option :value="1"></a-select-option>
<a-select-option :value="-1"></a-select-option>
<a-select-option :value="0">横穿</a-select-option>
<a-select-option :value="2">过店</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="抓拍类型:" style="padding: 5px 0">
......@@ -287,7 +288,7 @@ export default {
plazaList.value = []
clusterResultApi.getPlazaList(
{
account_id: queryForm.account_id.toString()
account_id: queryForm.account_id?queryForm.account_id.toString():''
}
).then(
(r) => {
......@@ -321,8 +322,8 @@ export default {
zoneList.value = []
clusterResultApi.getZoneList(
{
account_id: queryForm.account_id.toString(),
plaza_id: queryForm.plaza_id.toString(),
account_id: queryForm.account_id?queryForm.account_id.toString():'',
plaza_id: queryForm.plaza_id?queryForm.plaza_id.toString():'',
}
).then(
(r) => {
......@@ -355,9 +356,9 @@ export default {
gateList.value = []
clusterResultApi.getGateList(
{
account_id: queryForm.account_id.toString(),
plaza_id: queryForm.plaza_id.toString(),
zone_id: queryForm.zone_id.toString(),
account_id: queryForm.account_id?queryForm.account_id.toString():'',
plaza_id: queryForm.plaza_id?queryForm.plaza_id.toString():'',
zone_id: queryForm.zone_id?queryForm.zone_id.toString():'',
type: queryForm.type,
}
).then(
......@@ -424,21 +425,21 @@ export default {
const rawData = toRaw(queryForm)
const data = filterEmptyValueInObject(
{
account_id: rawData.account_id.toString(),
account_id: rawData.account_id?rawData.account_id.toString():'',
type: rawData.type,
plaza_id: rawData.plaza_id.toString(),
zone_id: rawData.zone_id.toString(),
gate_id: rawData.gate_id.toString(),
direction: rawData.direction.toString(),
plaza_id: rawData.plaza_id?rawData.plaza_id.toString():'',
zone_id: rawData.zone_id?rawData.zone_id.toString():'',
gate_id: rawData.gate_id?rawData.gate_id.toString():'',
direction: rawData.direction?rawData.direction.toString():'',
picType: rawData.picType,
personType: rawData.personType.toString(),
personType: rawData.personType?rawData.personType.toString():'',
startTime: formatDate(rawData.date) + ' ' + rawData.startTime,
endTime: formatDate(rawData.date) + ' ' + rawData.endTime,
minPic: rawData.minPic,
maxPic: rawData.maxPic,
page: pageNum.value - 1,
pageSize: pageSize.value,
childAdult: rawData.childAdult.toString(),
childAdult: rawData.childAdult?rawData.childAdult.toString():'',
}
)
const storageData = filterEmptyValueInObject(
......
......@@ -6,6 +6,9 @@
<a-menu-item :key="'聚类结果'">
聚类结果
</a-menu-item>
<a-menu-item :key="'批次'">
批次
</a-menu-item>
</a-menu>
<div v-if="currentMenu[0] === '抓拍记录'">
<SnapshotRecord></SnapshotRecord>
......@@ -13,17 +16,22 @@
<div v-if="currentMenu[0] === '聚类结果'">
<ClusterResult></ClusterResult>
</div>
<div v-if="currentMenu[0] === '批次'">
<batchesResult></batchesResult>
</div>
</template>
<script>
import {ref} from 'vue'
import SnapshotRecord from './SnapshotRecord/SnapshotRecord.vue'
import ClusterResult from './ClusterResult/ClusterResult.vue'
import batchesResult from './batchesResult/batchesResult.vue'
export default {
components: {
SnapshotRecord,
ClusterResult,
batchesResult,
},
setup() {
// scalar
......
......@@ -64,6 +64,7 @@
<a-select-option :value="1"></a-select-option>
<a-select-option :value="-1"></a-select-option>
<a-select-option :value="0">横穿</a-select-option>
<a-select-option :value="2">过店</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="抓拍类型:" style="padding: 5px 0">
......@@ -214,7 +215,7 @@ export default {
const searchCondition = ref({})
if(window.localStorage.getItem('searchCondition')){
searchCondition.value = JSON.parse(window.localStorage.getItem('searchCondition'));
queryForm.type = searchCondition.value.type;
// queryForm.type = searchCondition.value.type;
queryForm.zone_id = searchCondition.value.zone_id;
queryForm.gate_id = searchCondition.value.gate_id;
queryForm.direction = searchCondition.value.direction;
......@@ -255,7 +256,7 @@ export default {
plazaList.value = []
snapshotRecordApi.getPlazaList(
{
account_id: queryForm.account_id.toString()
account_id: queryForm.account_id?queryForm.account_id.toString():''
}
).then(
(r) => {
......@@ -288,8 +289,8 @@ export default {
zoneList.value = []
snapshotRecordApi.getZoneList(
{
account_id: queryForm.account_id.toString(),
plaza_id: queryForm.plaza_id.toString(),
account_id: queryForm.account_id?queryForm.account_id.toString():'',
plaza_id: queryForm.plaza_id?queryForm.plaza_id.toString():'',
}
).then(
(r) => {
......@@ -322,9 +323,9 @@ export default {
gateList.value = []
snapshotRecordApi.getGateList(
{
account_id: queryForm.account_id.toString(),
plaza_id: queryForm.plaza_id.toString(),
zone_id: queryForm.zone_id.toString(),
account_id: queryForm.account_id?queryForm.account_id.toString():'',
plaza_id: queryForm.plaza_id?queryForm.plaza_id.toString():'',
zone_id: queryForm.zone_id?queryForm.zone_id.toString():'',
type: queryForm.type,
}
).then(
......@@ -388,19 +389,19 @@ export default {
const rawData = toRaw(queryForm)
const data = filterEmptyValueInObject(
{
account_id: rawData.account_id.toString(),
account_id: rawData.account_id?rawData.account_id.toString():'',
type: rawData.type,
plaza_id: rawData.plaza_id.toString(),
zone_id: rawData.zone_id.toString(),
gate_id: rawData.gate_id.toString(),
direction: rawData.direction.toString(),
plaza_id: rawData.plaza_id?rawData.plaza_id.toString():'',
zone_id: rawData.zone_id?rawData.zone_id.toString():'',
gate_id: rawData.gate_id?rawData.gate_id.toString():'',
direction: rawData.direction?rawData.direction.toString():'',
picType: rawData.picType,
personType: rawData.personType.toString(),
personType: rawData.personType?rawData.personType.toString():'',
startTime: formatDate(rawData.date) + ' ' + rawData.startTime,
endTime: formatDate(rawData.date) + ' ' + rawData.endTime,
page: pageNum.value - 1,
pageSize: pageSize.value,
childAdult: rawData.childAdult.toString(),
childAdult: rawData.childAdult?rawData.childAdult.toString():'',
}
)
const storageData = filterEmptyValueInObject(
......
.single-image {
height: 300px;
width: 100%;
}
.direction{
font-weight: 900;
background-color: red;
color: white;
}
.direction1{
background-color: green;
}
.direction0{
background-color: orange;
}
<template>
<div class="containter">
<a-form :model="queryForm" layout="inline" :label-col="{ style: { width: '70px' } }">
<a-form-item label="集团:" style="padding: 5px 0">
<a-select v-model:value="queryForm.account_id" style="width: 240px" mode="multiple" :maxTagCount="1"
@change="onAccountChange" :options="accountList" optionFilterProp="label" show-search>
</a-select>
</a-form-item>
<a-form-item label="广场:" style="padding: 5px 0">
<a-select v-model:value="queryForm.plaza_id" style="width: 240px" mode="multiple" :maxTagCount="1" :options="plazaList" optionFilterProp="label" show-search>
</a-select>
</a-form-item>
<a-form-item label="选择日期:" style="padding: 5px 0">
<a-date-picker v-model:value="queryForm.date" :format="'YYYY-MM-DD'" style="width: 240px" />
</a-form-item>
<a-form-item label="选择时间:" style="padding: 5px 0">
<a-time-picker format="HH:mm:ss" valueFormat="HH:mm:ss" v-model:value="queryForm.startTime" style="width: 140px" />
<span style="padding: 0 4px"></span>
<a-time-picker format="HH:mm:ss" valueFormat="HH:mm:ss" v-model:value="queryForm.endTime" style="width: 140px" />
</a-form-item>
<a-form-item label="批次人数:" style="padding: 5px 0"> <a-input-number v-model:value="queryForm.minNum" :min="0" :max="100000000" style="width: 140px"/> <span style="padding: 0 4px"></span> <a-input-number v-model:value="queryForm.maxNum" :min="queryForm.maxNum||0" :max="100000000" style="width: 140px"/> </a-form-item>
<a-form-item style="padding: 5px 0">
<a-button type="primary" @click="clickSearch" :loading="isLoading">查询</a-button>
</a-form-item>
<a-form-item style="padding: 5px 0"> <a-button type="primary" @click="concatBatches">合并</a-button> </a-form-item> <a-form-item style="padding: 5px 0"> <a-button type="primary" @click="deleteBatches">删除</a-button> </a-form-item>
</a-form>
<div v-loading="isLoading">
<div class="resultContent" :style="{'height':contentHeight+'px'}">
<template v-for="person in dataList">
<div class="classBox" :class="person.expand?'expand':''">
<div :class="person.checked?'checked':''">
<div class="boxInfo">
<span class="iconExpand" v-show="!person.expand"></span>
<span class="iconExpand" v-show="person.expand"></span>
<span class="expandWord" @click='expandChange(person)'>{{person.expand?'收起':'展开'}}</span>
<el-checkbox class="checkBox" v-model="person.checked" @change='checkChange(person)'></el-checkbox>
批次id:{{ ' ' + person.groupUnid }}
<span style="margin-left: 20px;">图片数量:{{ person.personRecordList.length }}</span>
</div>
<el-row v-for="row in getPagedList(person.personRecordList, 8)">
<el-col :span="3" v-for="item in row">
<div style="margin: 0 2px;border: 3px solid transparent;" @click="handleClick(item)" :class="currentItemId==item.id?'actived':''">
<el-image :src="item.faceRecognitionVo.picture_url" :fit="'fill'" class="single-image">
</el-image>
<div style="padding-left: 5px;padding-right: 5px;">
<div style="width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">unid:{{ item.faceRecognitionVo.unid||'--' }}</div>
<div style="width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">personid:{{ item.faceRecognitionVo.person_unid||'--' }}</div>
<div>时间:{{ item.faceRecognitionVo.counttime }}</div>
<div>类型:{{ item.faceRecognitionVo.person_type==1?'店员':(item.faceRecognitionVo.person_type==0?'顾客':'未知') }}({{ item.faceRecognitionVo.childAdult==1?'成人':(item.faceRecognitionVo.childAdult==0?'儿童':'未知') }})</div>
<div>性别:{{ formatGender(item.faceRecognitionVo.gender) }}({{item.age}})</div>
<div>地点:{{ item.faceRecognitionVo.gate_name }}</div>
</div>
</div>
</el-col>
</el-row>
</div>
</div>
</template>
</div>
<a-pagination v-model:current="pageNum" v-model:pageSize="pageSize" :total="total"
:show-total="total => `共 ${total} 条`" :pageSizeOptions="['10', '20', '40', '80']" @change="onPageNumChange"
@showSizeChange="onPageSizeChange" show-size-changer show-quick-jumper style="text-align:center" />
</div>
</div>
</template>
<script>
import {
reactive,
ref,
toRaw
} from 'vue'
import batchesResultApi from '@/views/SnapshotCluster/batchesResult/batchesResultApi'
import {
isArray
} from '@/PublicUtil/Judgment'
import moment from 'moment'
import {
filterEmptyValueInObject,
formatDate,
getPagedList
} from '@/PublicUtil/PublicUtil'
import {ElMessage,ElMessageBox} from 'element-plus'
export default {
components: {
},
setup() {
// scalar
const pageNum = ref(1)
const pageSize = ref(10)
const total = ref()
const isLoading = ref(false)
const dataList = ref([])
const accountList = ref([])
const plazaList = ref([])
const currobj = ref({})
const currentItemId = ref()
const queryForm = reactive({
account_id: [],
plaza_id: [],
date: moment(moment().format('YYYY-MM-DD'), 'YYYY-MM-DD'),
startTime: '00:00:00',
endTime: '23:59:59',
minNum: 0,
maxNum: 100000,
})
const searchCondition = ref({})
if (window.localStorage.getItem('searchCondition')) {
searchCondition.value = JSON.parse(window.localStorage.getItem('searchCondition'));
// queryForm.startTime = searchCondition.value.startTime;
// queryForm.endTime = searchCondition.value.endTime;
queryForm.minNum = searchCondition.value.minNum || 0;
queryForm.maxNum = searchCondition.value.maxNum || 100000;
}
const onPageNumChange = function(num) {
pageNum.value = num
confirmSearch()
}
const onPageSizeChange = function(current, size) {
pageNum.value = 1
pageSize.value = size
confirmSearch()
}
const onAccountChange = function() {
getPlazaList(1)
}
const getPlazaList = function(val) {
queryForm.plaza_id = []
plazaList.value = []
batchesResultApi.getPlazaList({
account_id: queryForm.account_id.toString()
}).then(
(r) => {
if (isArray(r)) {
for (const item of r) {
plazaList.value.push({
value: item.id,
label: item.name,
})
}
if (plazaList.value.length > 0) {
if (!val && searchCondition.value.plaza_id && searchCondition.value.plaza_id.length > 0) {
queryForm.plaza_id = searchCondition.value.plaza_id
} else {
queryForm.plaza_id.push(plazaList.value[0].value)
}
confirmSearch()
}
}
}
)
}
const getAccountList = function() {
queryForm.account_id = []
accountList.value = []
batchesResultApi.getAccountList().then(
(r) => {
if (isArray(r)) {
for (const item of r) {
accountList.value.push({
value: item.id,
label: item.name,
})
}
if (accountList.value.length) {
if (searchCondition.value.account_id && searchCondition.value.account_id.length > 0) {
queryForm.account_id = searchCondition.value.account_id
} else {
queryForm.account_id.push(accountList.value[0].value)
}
getPlazaList()
}
}
}
)
}
const clickSearch = function() {
pageNum.value = 1
confirmSearch()
}
const confirmSearch = function() {
isLoading.value = true
const rawData = toRaw(queryForm)
const data = filterEmptyValueInObject({
mallId: rawData.plaza_id?rawData.plaza_id.toString():'',
countDate: formatDate(rawData.date),
startTime: formatDate(rawData.date) + ' ' + rawData.startTime,
endTime: formatDate(rawData.date) + ' ' + rawData.endTime,
minNum: rawData.minNum,
maxNum: rawData.maxNum,
pageNum: pageNum.value,
pageSize: pageSize.value,
})
const storageData = filterEmptyValueInObject({
account_id: rawData.account_id,
plaza_id: rawData.plaza_id,
date: rawData.date,
minNum: rawData.minNum,
maxNum: rawData.maxNum,
startTime: rawData.startTime,
endTime: rawData.endTime,
})
window.localStorage.setItem('searchCondition', JSON.stringify(storageData))
batchesResultApi.getBatchesResultList(data).then(
(r) => {
isLoading.value = false
sortDataList(r.data.pageData)
r.data.pageData.forEach((itemPerson) => {
itemPerson.checked = false
itemPerson.expand = false
itemPerson.personRecordList.forEach((item) => {
if (item.faceRecognitionVo&&item.faceRecognitionVo.picture_url) {
item.faceRecognitionVo.picture_url = window._baseImgUrl + item.faceRecognitionVo.picture_url
}
if (item.faceRecognitionVo&&item.faceRecognitionVo.features_url) {
item.faceRecognitionVo.features_url = window._baseImgUrl + item.faceRecognitionVo.features_url
}
})
})
dataList.value = r.data.pageData
console.log(dataList.value)
total.value = r.data.total
document.getElementsByClassName('resultContent')[0].scrollTop = 0
}
)
}
const formatGender = function(number) {
switch (number) {
case 1: {
return '男'
}
case -1: {
return '未知'
}
case 0: {
return '女'
}
default: {
break
}
}
}
const sortDataList = function(list) {
list.sort(
(a, b) => {
return (b.personRecordList.length - a.personRecordList.length)
}
)
}
const checkChange = function(data) {
console.log(data)
}
const expandChange = function(data) {
dataList.value.forEach(item => {
if (data.groupUnid == item.groupUnid) {
item.expand = !item.expand
}
})
}
// 批次合并
const concatBatches = function() {
const rawData = toRaw(queryForm)
let selectArr = []
dataList.value.forEach(item => {
if (item.checked && item.checked == true) {
selectArr.push(item)
}
})
if (selectArr.length != 2) {
ElMessage({
message: `请选择两个批次分组进行合并`,
type: 'warning'
})
return
}
console.log(selectArr)
let parmas = {
countDate: formatDate(rawData.date),
sourceGroupUnid:selectArr[0].groupUnid,
targetGroupUnid:selectArr[1].groupUnid,
mallId: rawData.plaza_id?rawData.plaza_id.toString():'',
}
ElMessageBox.confirm('是否合并选中的两个批次分组?', {
confirmButtonText: '确认',
cancelButtonText: '取消',
}).then(() => {
batchesResultApi.concatTwoBatches(parmas).then(
(res) => {
if(res.code == 200) {
ElMessage({
message: `合并成功`,
type: 'success'
})
confirmSearch()
} else {
ElMessage({
message: `删除失败`,
type: 'warning'
})
}
}
)
}).catch(() => {})
}
//删除批次记录
const deleteBatches = function(){
if(!currentItemId.value){
ElMessage(
{
message: `请选择图片`,
type: 'warning'
}
)
return
}
if(!currobj.value.picture_url){
ElMessage(
{
message: `请选择有效的图片`,
type: 'warning'
}
)
return
}
ElMessageBox.confirm('是否确认删除该批次记录?', {
confirmButtonText: '确认',
cancelButtonText: '取消',
}).then(() => {
batchesResultApi.deleteOneBatches({id:currentItemId.value}).then(
(res) => {
console.log(res)
if(res.code == 200) {
ElMessage({
message: `删除成功`,
type: 'success'
})
confirmSearch()
currentItemId.value = ''
currobj.value = {};
} else {
ElMessage({
message: `删除失败`,
type: 'warning'
})
}
}
)
}).catch(() => {})
}
const handleClick = function(data){
currentItemId.value = data.id
currobj.value = data;
}
const contentHeight = ref(0)
const __main = function() {
getAccountList()
contentHeight.value = window.innerHeight - 310
}
__main()
return {
isLoading,
pageNum,
pageSize,
total,
accountList,
plazaList,
dataList,
contentHeight,
currentItemId,
currobj,
handleClick,
queryForm,
onPageNumChange,
onPageSizeChange,
onAccountChange,
confirmSearch,
getPagedList,
checkChange,
expandChange,
formatGender,
clickSearch,
concatBatches,
deleteBatches,
}
}
}
</script>
<style lang="less" scoped>
@import "./batchesResult";
.actived {
border: 3px solid #1890ff!important;
}
.checkBox {
margin-left: 10px;
}
.boxInfo {
line-height: 28px;
margin-bottom: 10px;
}
.classBox {
margin: 10px 0;
border: solid 1px black;
height: 485px;
overflow-y: hidden;
}
.expand {
height: auto;
overflow: auto;
}
.expandWord {
color: #1890ff;
margin-right: 5px;
cursor: pointer;
float: right;
}
.iconExpand {
cursor: pointer;
float: right;
color: #1890ff;
margin-right: 20px;
}
.checked {
background-color: #bbb;
}
.resultContent {
overflow: auto;
min-height: 500px;
}
.downBtn {
color: #409EFF;
font-size: 15px;
cursor: pointer;
display: inline-block;
width: auto;
}
.downBtn1 {
float: right;
}
</style>
\ No newline at end of file
import axiosInstance from "@/Request/PublicAxiosInstance"
import {filterEmptyValueInObject} from "@/PublicUtil/PublicUtil"
class ClusterResultApi {
getBatchesResultList(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/car4s/group/page`,
params: filterEmptyValueInObject(data)
}
)
}
getAccountList() {
return axiosInstance.request(
{
method: 'GET',
url: `/accounts`,
}
)
}
getPlazaList(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/malls`,
params: filterEmptyValueInObject(
{
accountIds: data.account_id
},
)
}
)
}
// 合并批次分组
concatTwoBatches(data) {
return axiosInstance.request(
{
method: 'PUT',
url: `/car4s/group/merge`,
data: filterEmptyValueInObject(data)
}
)
}
// 删除批次记录
deleteOneBatches(data) {
return axiosInstance.request(
{
method: 'PUT',
url: `/car4s/group/remove`,
data: filterEmptyValueInObject(data)
}
)
}
}
const clusterResultApi = new ClusterResultApi()
export default clusterResultApi
.single-image {
height: 300px;
width: 100%;
}
.direction{
font-weight: 900;
background-color: red;
color: white;
}
.direction1{
background-color: green;
}
.direction0{
background-color: orange;
}
<template>
<div class="containter">
<a-form :model="queryForm" layout="inline" :label-col="{ style: { width: '70px' } }">
<a-form-item label="集团:" style="padding: 5px 0">
<a-select v-model:value="queryForm.account_id" style="width: 280px" mode="multiple" :maxTagCount="1"
@change="onAccountChange" :options="accountList" optionFilterProp="label" show-search>
</a-select>
</a-form-item>
<a-form-item label="广场:" style="padding: 5px 0">
<a-select v-model:value="queryForm.plaza_id" style="width: 280px" mode="multiple" :maxTagCount="1"
@change="onPlazaChange" :options="plazaList" optionFilterProp="label" show-search>
</a-select>
</a-form-item>
<a-form-item label="区域信息:" style="padding: 5px 0">
<a-select v-model:value="queryForm.zone_id" style="width: 280px" mode="multiple" :maxTagCount="1"
@change="onZoneChange" :options="zoneList" optionFilterProp="label" show-search>
</a-select>
</a-form-item>
<a-form-item label="监控点:" style="padding: 5px 0">
<a-select v-model:value="queryForm.gate_id" style="width: 280px" mode="multiple" :maxTagCount="1"
:options="gateList" optionFilterProp="label" show-search>
</a-select>
</a-form-item>
<a-form-item label="选择日期:" style="padding: 5px 0">
<a-date-picker v-model:value="queryForm.date" :format="'YYYY-MM-DD'" style="width: 280px" />
</a-form-item>
<a-form-item label="选择时间:" style="padding: 5px 0">
<a-time-picker v-model:value="queryForm.startTime" style="width: 140px" />
<span style="padding: 0 4px"></span>
<a-time-picker v-model:value="queryForm.endTime" style="width: 140px" />
</a-form-item>
<a-form-item style="padding: 5px 0">
<a-button type="primary" @click="clickSearch" :loading="isLoading">查询</a-button>
</a-form-item>
<a-form-item style="padding: 5px 0">
<a-upload :file-list="fileList" :before-upload="beforeUpload">
<a-button type="primary">
<upload-outlined></upload-outlined>
导入
</a-button>
</a-upload>
</a-form-item>
<!-- <a-form-item style="padding: 5px 0">
<a-button type="primary" @click="deleteBatches">删除</a-button>
</a-form-item> -->
</a-form>
<div v-loading="isLoading">
<div class="resultContent" :style="{'height':contentHeight+'px'}">
<template v-for="person in dataList">
<div class="classBox">
<div>
<div class="boxInfo">
<span>记录id:{{ person.personUnid }}</span>
<span style="margin-left: 20px;">开始接待时间:{{ person.startTime }}</span>
<span style="margin-left: 20px;">结束接待时间:{{ person.endTime }}</span>
<span style="margin-left: 20px;">接待时长:{{ person.duration }}</span>
</div>
<el-row v-for="row in getPagedList(person.customerList, 8)">
<el-col :span="3" v-for="item in row">
<div style="margin: 0 5px" @click="handleClick(item)" :class="currentItemId==item.id?'actived':''">
<el-image :src="item.picture_url" :fit="'fill'" class="single-image"></el-image>
<div>unid:{{ item.unid }}</div>
<div>时间:{{ item.counttime }}</div>
<div>性别:{{ formatGender(item.gender) }}({{item.age}})</div>
<div>地点:{{ item.gate_name }}</div>
</div>
</el-col>
</el-row>
</div>
</div>
</template>
</div>
<a-pagination v-model:current="pageNum" v-model:pageSize="pageSize" :total="total"
:show-total="total => `共 ${total} 条`" :pageSizeOptions="['10', '20', '40', '80']" @change="onPageNumChange"
@showSizeChange="onPageSizeChange" show-size-changer show-quick-jumper style="text-align:center" />
</div>
</div>
</template>
<script>
import {
reactive,
ref,
toRaw
} from 'vue'
import clusterResultApi from '@/views/TestDriveHospitality/ClusterResult/ClusterResultApi'
import {
isArray
} from '@/PublicUtil/Judgment'
import moment from 'moment'
import {
filterEmptyValueInObject,
formatDate,
formatTime,
getPagedList
} from '@/PublicUtil/PublicUtil'
import {
ElMessage,
ElMessageBox
} from 'element-plus'
export default {
components: {
},
setup() {
const pageNum = ref(1)
const pageSize = ref(10)
const total = ref()
const isLoading = ref(false)
const currobj = ref({})
const currentItemId = ref()
const dataList = ref([])
const accountList = ref([])
const plazaList = ref([])
const zoneList = ref([])
const gateList = ref([])
const queryForm = reactive({
account_id: [],
plaza_id: [],
zone_id: [],
gate_id: [],
date: moment(moment().format('YYYY-MM-DD'), 'YYYY-MM-DD'),
startTime: moment('00:00:00', 'HH:mm:ss'),
endTime: moment('23:59:59', 'HH:mm:ss'),
})
const searchCondition = ref({})
if (window.localStorage.getItem('searchCondition')) {
searchCondition.value = JSON.parse(window.localStorage.getItem('searchCondition'));
queryForm.date = searchCondition.value.date;
// queryForm.startTime = searchCondition.value.startTime;
// queryForm.endTime = searchCondition.value.endTime;
}
const onPageNumChange = function(num) {
pageNum.value = num
confirmSearch()
}
const onPageSizeChange = function(current, size) {
pageNum.value = 1
pageSize.value = size
confirmSearch()
}
const onAccountChange = function() {
getPlazaList(1)
}
const onPlazaChange = function() {
getZoneList()
getGateList()
}
const onZoneChange = function() {
getGateList()
}
const getPlazaList = function(val) {
queryForm.plaza_id = []
plazaList.value = []
clusterResultApi.getPlazaList({
account_id: queryForm.account_id.toString()
}).then(
(r) => {
if (isArray(r)) {
for (const item of r) {
plazaList.value.push({
value: item.id,
label: item.name,
})
}
if (plazaList.value.length > 0) {
if (!val && searchCondition.value.plaza_id && searchCondition.value.plaza_id.length > 0) {
queryForm.plaza_id = searchCondition.value.plaza_id
} else {
queryForm.plaza_id.push(plazaList.value[0].value)
}
getZoneList(1)
getGateList(1)
confirmSearch()
}
}
}
)
}
const getZoneList = function(val) {
zoneList.value = []
clusterResultApi.getZoneList({
account_id: queryForm.account_id.toString(),
plaza_id: queryForm.plaza_id.toString(),
}).then(
(r) => {
if (isArray(r)) {
for (const item of r) {
zoneList.value.push({
value: item.id,
label: item.name,
})
}
if (zoneList.value.length) {
if (val && searchCondition.value.zone_id && searchCondition.value.zone_id.length > 0) {
queryForm.zone_id = searchCondition.value.zone_id
} else {
queryForm.zone_id = []
}
} else {
queryForm.zone_id = []
}
}
}
)
}
const getGateList = function(val) {
gateList.value = []
clusterResultApi.getGateList({
account_id: queryForm.account_id.toString(),
plaza_id: queryForm.plaza_id.toString(),
zone_id: queryForm.zone_id.toString(),
type: 0,
}).then(
(r) => {
if (isArray(r.data)) {
for (const item of r.data) {
gateList.value.push({
value: item.id,
label: item.name,
})
}
if (gateList.value.length) {
if (val && searchCondition.value.gate_id && searchCondition.value.gate_id.length > 0) {
queryForm.gate_id = searchCondition.value.gate_id
} else {
queryForm.gate_id = []
}
} else {
queryForm.gate_id = []
}
}
}
)
}
const getAccountList = function() {
queryForm.account_id = []
accountList.value = []
clusterResultApi.getAccountList().then(
(r) => {
if (isArray(r)) {
for (const item of r) {
accountList.value.push({
value: item.id,
label: item.name,
})
}
if (accountList.value.length) {
if (searchCondition.value.account_id && searchCondition.value.account_id.length > 0) {
queryForm.account_id = searchCondition.value.account_id
} else {
queryForm.account_id.push(accountList.value[0].value)
}
getPlazaList()
}
}
}
)
}
const clickSearch = function() {
pageNum.value = 1
confirmSearch()
}
const confirmSearch = function() {
isLoading.value = true
const rawData = toRaw(queryForm)
const data = filterEmptyValueInObject({
// account_id: rawData.account_id?rawData.account_id.toString():'',
mallId: rawData.plaza_id?rawData.plaza_id.toString():'',
zoneIds: rawData.zone_id?rawData.zone_id.toString():'',
gateIds: rawData.gate_id?rawData.gate_id.toString():'',
countDate: formatDate(rawData.date),
startTime: formatDate(rawData.date) + ' ' + formatTime(rawData.startTime),
endTime: formatDate(rawData.date) + ' ' + formatTime(rawData.endTime),
pageNum: pageNum.value,
pageSize: pageSize.value,
})
const storageData = filterEmptyValueInObject({
account_id: rawData.account_id,
plaza_id: rawData.plaza_id,
zone_id: rawData.zone_id,
gate_id: rawData.gate_id,
date: rawData.date,
startTime: formatDate(rawData.date) + ' ' + formatTime(rawData.startTime),
endTime: formatDate(rawData.date) + ' ' + formatTime(rawData.endTime),
})
window.localStorage.setItem('searchCondition', JSON.stringify(storageData))
clusterResultApi.getClusterResultList(data).then(
(r) => {
isLoading.value = false
sortDataList(r.data.pageData)
r.data.pageData.forEach((itemPerson) => {
itemPerson.customerList.forEach((item) => {
if (item.features_url) {
item.features_url = window._baseImgUrl + item.features_url
}
if (item.picture_url) {
item.picture_url = window._baseImgUrl + item.picture_url
}
})
itemPerson.staffList.forEach((item1) => {
if (item1.features_url) {
item1.features_url = window._baseImgUrl + item1.features_url
}
if (item1.picture_url) {
item1.picture_url = window._baseImgUrl + item1.picture_url
}
})
})
dataList.value = r.data.pageData
total.value = r.data.total
document.getElementsByClassName('resultContent')[0].scrollTop = 0
}
)
}
const formatGender = function(number) {
switch (number) {
case 1: {
return '男'
}
case -1: {
return '未知'
}
case 0: {
return '女'
}
default: {
break
}
}
}
const sortDataList = function(list) {
list.sort(
(a, b) => {
return (b.customerList.length - a.customerList.length)
}
)
}
const handleClick = function(data) {
currentItemId.value = data.id
currobj.value = data;
}
// 导入接待记录
const importHospitality = function(data) {
}
// 删除试乘记录
const deleteBatches = function() {
if (!currentItemId.value) {
ElMessage({
message: `请选择图片`,
type: 'warning'
})
return
}
if (!currobj.value.picture_url) {
ElMessage({
message: `请选择有效的图片`,
type: 'warning'
})
return
}
ElMessageBox.confirm('是否确认删除该接待记录?', {
confirmButtonText: '确认',
cancelButtonText: '取消',
}).then(() => {
clusterResultApi.deleteOneDrive({
id: currentItemId.value
}).then(
(res) => {
console.log(res)
if (res.code == 200) {
ElMessage({
message: `删除成功`,
type: 'success'
})
confirmSearch()
currentItemId.value = ''
currobj.value = {};
} else {
ElMessage({
message: `删除失败`,
type: 'warning'
})
}
}
)
}).catch(() => {})
}
const contentHeight = ref(0)
const __main = function() {
getAccountList()
contentHeight.value = window.innerHeight - 310
}
const fileList = ([]);
const beforeUpload= function(file) {
const formData = new FormData();
formData.append('file', file);
clusterResultApi.uploadReception(formData).then((res) => {
if (res.code == 200) {
ElMessage({
message: `上传成功`,
type: 'success'
})
clickSearch()
} else {
ElMessage({
message: `上传失败`,
type: 'warning'
})
}
})
return false;
};
__main()
return {
beforeUpload,
fileList,
isLoading,
pageNum,
pageSize,
total,
currentItemId,
currobj,
accountList,
plazaList,
zoneList,
gateList,
dataList,
contentHeight,
queryForm,
onPageNumChange,
onPageSizeChange,
onAccountChange,
onPlazaChange,
onZoneChange,
confirmSearch,
getPagedList,
handleClick,
importHospitality,
formatGender,
clickSearch,
deleteBatches
}
}
}
</script>
<style lang="less" scoped>
@import "./ClusterResult";
.actived {
border: 3px solid #1890ff;
}
.checkBox {
margin-left: 10px;
}
.boxInfo {
line-height: 28px;
margin-bottom: 10px;
}
.classBox {
margin: 10px 0;
border: solid 1px black;
height: 485px;
overflow-y: hidden;
}
.expand {
height: auto;
overflow: auto;
}
.expandWord {
color: #1890ff;
margin-right: 5px;
cursor: pointer;
float: right;
}
.iconExpand {
cursor: pointer;
float: right;
color: #1890ff;
margin-right: 20px;
}
.checked {
background-color: #bbb;
}
.resultContent {
overflow: auto;
min-height: 500px;
}
.downBtn {
color: #409EFF;
font-size: 15px;
cursor: pointer;
display: inline-block;
width: auto;
}
.downBtn1 {
float: right;
}
</style>
\ No newline at end of file
import axiosInstance from "@/Request/PublicAxiosInstance"
import {filterEmptyValueInObject} from "@/PublicUtil/PublicUtil"
class ClusterResultApi {
getClusterResultList(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/car4s/reception/page`,
params: filterEmptyValueInObject(
data
)
}
)
}
getAccountList() {
return axiosInstance.request(
{
method: 'GET',
url: `/accounts`,
}
)
}
getPlazaList(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/malls`,
params: filterEmptyValueInObject(
{
accountIds: data.account_id
},
)
}
)
}
getZoneList(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/zones/zoneList`,
params: filterEmptyValueInObject(
{
account_id: data.account_id,
plaza_id: data.plaza_id,
},
)
}
)
}
getGateList(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/gates/gateByInfo`,
params: filterEmptyValueInObject(
{
account_id: data.account_id,
plaza_id: data.plaza_id,
zone_id: data.zone_id,
type: data.type,
},
)
}
)
}
getBodyPoint(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/feature/bodyPoint`,
params: filterEmptyValueInObject(
data
)
}
)
}
// 上传接待记录
uploadReception(data) {
return axiosInstance.request(
{
method: 'POST',
url: `/car4s/reception/upload`,
headers: {
'Content-Type': 'multipart/form-data'
},
data: data
}
)
}
}
const clusterResultApi = new ClusterResultApi()
export default clusterResultApi
<template>
<a-menu v-model:selectedKeys="currentMenu" mode="horizontal">
<a-menu-item :key="'试乘记录'">
试乘记录
</a-menu-item>
<a-menu-item :key="'接待记录'">
接待记录
</a-menu-item>
</a-menu>
<div v-if="currentMenu[0] === '试乘记录'">
<SnapshotRecord></SnapshotRecord>
</div>
<div v-if="currentMenu[0] === '接待记录'">
<ClusterResult></ClusterResult>
</div>
</template>
<script>
import {ref} from 'vue'
import SnapshotRecord from './SnapshotRecord/SnapshotRecord.vue'
import ClusterResult from './ClusterResult/ClusterResult.vue'
export default {
components: {
SnapshotRecord,
ClusterResult,
},
setup() {
// scalar
const currentMenu = ref(['试乘记录'])
// sequence
// mapping
// function
return {
// scalar
currentMenu,
// sequence
// mapping
// function
}
}
}
</script>
<style scoped>
</style>
.single-image {
height: 300px;
width: 100%;
}
.direction{
font-weight: 900;
background-color: red;
color: white;
}
.direction1{
background-color: green;
}
.direction0{
background-color: orange;
}
<template>
<a-form :model="queryForm" layout="inline" :label-col="{ style: { width: '70px' } }">
<a-form-item label="集团:" style="padding: 5px 0">
<a-select v-model:value="queryForm.account_id" style="width: 280px" mode="multiple" :maxTagCount="1"
@change="onAccountChange" :options="accountList" optionFilterProp="label" show-search>
</a-select>
</a-form-item>
<a-form-item label="广场:" style="padding: 5px 0">
<a-select v-model:value="queryForm.plaza_id" style="width: 280px" mode="multiple" :maxTagCount="1"
@change="onPlazaChange" :options="plazaList" optionFilterProp="label" show-search>
</a-select>
</a-form-item>
<a-form-item label="区域信息:" style="padding: 5px 0">
<a-select v-model:value="queryForm.zone_id" style="width: 280px" mode="multiple" :maxTagCount="1"
@change="onZoneChange" :options="zoneList" optionFilterProp="label" show-search>
</a-select>
</a-form-item>
<a-form-item label="监控点:" style="padding: 5px 0">
<a-select v-model:value="queryForm.gate_id" style="width: 280px" mode="multiple" :maxTagCount="1"
:options="gateList" optionFilterProp="label" show-search>
</a-select>
</a-form-item>
<a-form-item label="选择日期:" style="padding: 5px 0">
<a-date-picker v-model:value="queryForm.date" :format="'YYYY-MM-DD'" style="width: 280px" />
</a-form-item>
<a-form-item label="选择时间:" style="padding: 5px 0">
<a-time-picker v-model:value="queryForm.startTime" style="width: 140px" />
<span style="padding: 0 4px"></span>
<a-time-picker v-model:value="queryForm.endTime" style="width: 140px" />
</a-form-item>
<a-form-item style="padding: 5px 0">
<a-button type="primary" @click="clickSearch" :loading="isLoading">查询</a-button>
</a-form-item>
<a-form-item style="padding: 5px 0">
<a-upload :file-list="fileList" :before-upload="beforeUpload">
<a-button type="primary">
<upload-outlined></upload-outlined>
导入
</a-button>
</a-upload>
</a-form-item>
<a-form-item style="padding: 5px 0">
<a-button type="primary" @click="deleteBatches">删除</a-button>
</a-form-item>
</a-form>
<div v-loading="isLoading">
<div class="resultContent" :style="{'height':contentHeight+'px'}">
<el-row v-for="row in pagedTableDataList">
<el-col :span="3" v-for="item in row">
<div style="margin: 0 5px;cursor: pointer;" @click="handleClick(item)"
:class="currentItemId==item.id?'actived':''">
<el-image :src="item.picture_url" :fit="'fill'" class="single-image">
</el-image>
<div>unid:{{ item.unid }}</div>
<div>时间:{{ item.counttime }}</div>
<div>性别:{{ formatGender(item.gender) }}({{item.age}})</div>
<div>地点:{{ item.gate_name }}</div>
</div>
</el-col>
</el-row>
</div>
<a-pagination v-model:current="pageNum" v-model:pageSize="pageSize" :total="total"
:show-total="total => `共 ${total} 条`" :pageSizeOptions="['24', '48', '96', '192']" @change="onPageNumChange"
@showSizeChange="onPageSizeChange" show-size-changer show-quick-jumper style="text-align:center" />
</div>
<DetailDialog ref="DetailDialogRef" />
</template>
<script>
import {
computed,
reactive,
ref,
toRaw
} from 'vue'
import snapshotRecordApi from '@/views/TestDriveHospitality/SnapshotRecord/SnapshotRecordApi'
import {
isArray
} from '@/PublicUtil/Judgment'
import moment from 'moment'
import {
filterEmptyValueInObject,
formatDate,
formatTime,
getPagedList
} from '@/PublicUtil/PublicUtil'
// import imgDialog from '../imgDialog.vue'
import {
ElMessage,
ElMessageBox
} from 'element-plus'
import Cookies from "js-cookie"
import DetailDialog from "../../ComparisonCapturedPictures/DetailDialog.vue";
export default {
components: {
// imgDialog ,
DetailDialog
},
setup() {
// scalar
const pageNum = ref(1)
const pageSize = ref(24)
const total = ref()
const isLoading = ref(false)
// sequence
const dataList = ref([])
const accountList = ref([])
const plazaList = ref([])
const zoneList = ref([])
const gateList = ref([])
const currentItemId = ref()
const currobj = ref({})
const DetailDialogRef = ref();
const pagedTableDataList = computed(
() => {
return getPagedList(dataList.value, 8)
}
)
const queryForm = reactive({
account_id: [],
plaza_id: [],
zone_id: [],
gate_id: [],
date: moment(moment().format('YYYY-MM-DD'), 'YYYY-MM-DD'),
startTime: moment('00:00:00', 'HH:mm:ss'),
endTime: moment('23:59:59', 'HH:mm:ss'),
})
const searchCondition = ref({})
if (window.localStorage.getItem('searchCondition')) {
searchCondition.value = JSON.parse(window.localStorage.getItem('searchCondition'));
queryForm.date = searchCondition.value.date;
// queryForm.startTime = searchCondition.value.startTime;
// queryForm.endTime = searchCondition.value.endTime;
}
const onPageNumChange = function(num) {
pageNum.value = num
confirmSearch()
}
const onPageSizeChange = function(current, size) {
pageNum.value = 1
pageSize.value = size
confirmSearch()
}
const onAccountChange = function() {
getPlazaList(1)
}
const onPlazaChange = function() {
getZoneList()
getGateList()
}
const onZoneChange = function() {
getGateList()
}
const getPlazaList = function(val) {
queryForm.plaza_id = []
plazaList.value = []
snapshotRecordApi.getPlazaList({
account_id: queryForm.account_id.toString()
}).then(
(r) => {
if (isArray(r)) {
for (const item of r) {
plazaList.value.push({
value: item.id,
label: item.name,
})
}
if (plazaList.value.length) {
if (!val && searchCondition.value.plaza_id && searchCondition.value.plaza_id.length > 0) {
queryForm.plaza_id = searchCondition.value.plaza_id
} else {
queryForm.plaza_id.push(plazaList.value[0].value)
}
getZoneList(1)
getGateList(1)
confirmSearch()
}
}
}
)
}
const getZoneList = function(val) {
queryForm.zone_id = []
zoneList.value = []
snapshotRecordApi.getZoneList({
account_id: queryForm.account_id.toString(),
plaza_id: queryForm.plaza_id.toString(),
}).then(
(r) => {
if (isArray(r)) {
for (const item of r) {
zoneList.value.push({
value: item.id,
label: item.name,
})
}
if (zoneList.value.length) {
if (val && searchCondition.value.zone_id && searchCondition.value.zone_id.length > 0) {
queryForm.zone_id = searchCondition.value.zone_id
} else {
queryForm.zone_id = []
}
} else {
queryForm.zone_id = []
}
}
}
)
}
const getGateList = function(val) {
gateList.value = []
snapshotRecordApi.getGateList({
account_id: queryForm.account_id.toString(),
plaza_id: queryForm.plaza_id.toString(),
zone_id: queryForm.zone_id.toString(),
type:0,
}).then(
(r) => {
if (isArray(r.data)) {
for (const item of r.data) {
gateList.value.push({
value: item.id,
label: item.name,
})
}
if (gateList.value.length) {
if (val && searchCondition.value.gate_id && searchCondition.value.gate_id.length > 0) {
queryForm.gate_id = searchCondition.value.gate_id
} else {
queryForm.gate_id = []
}
} else {
queryForm.gate_id = []
}
}
}
)
}
const getAccountList = function() {
queryForm.account_id = []
accountList.value = []
snapshotRecordApi.getAccountList().then(
(r) => {
if (isArray(r)) {
for (const item of r) {
accountList.value.push({
value: item.id,
label: item.name,
})
}
if (accountList.value.length) {
if (searchCondition.value.account_id && searchCondition.value.account_id.length > 0) {
queryForm.account_id = searchCondition.value.account_id
} else {
queryForm.account_id.push(accountList.value[0].value)
}
getPlazaList()
}
}
}
)
}
const confirmSearch = function() {
isLoading.value = true
const rawData = toRaw(queryForm)
console.log(rawData)
const data = filterEmptyValueInObject({
mallId: rawData.plaza_id?rawData.plaza_id.toString():'',
zoneIds: rawData.zone_id?rawData.zone_id.toString():'',
gateIds: rawData.gate_id?rawData.gate_id.toString():'',
startTime: formatDate(rawData.date) + ' ' + formatTime(rawData.startTime),
endTime: formatDate(rawData.date) + ' ' + formatTime(rawData.endTime),
pageNum: pageNum.value - 1,
pageSize: pageSize.value,
})
const storageData = filterEmptyValueInObject({
account_id: rawData.account_id,
plaza_id: rawData.plaza_id,
zone_id: rawData.zone_id,
gate_id: rawData.gate_id,
date: rawData.date,
startTime: formatDate(rawData.date) + ' ' + formatTime(rawData.startTime),
endTime: formatDate(rawData.date) + ' ' + formatTime(rawData.endTime),
})
window.localStorage.setItem('searchCondition', JSON.stringify(storageData))
snapshotRecordApi.getSnapshotRecordList(data).then(
(r) => {
isLoading.value = false
r.data.pageData.forEach((item) => {
if (item.features_url) {
item.features_url = window._baseImgUrl + item.features_url
}
if (item.picture_url) {
item.picture_url = window._baseImgUrl + item.picture_url
}
if (item.track_url) {
item.track_url = window._baseImgUrl + item.track_url
}
})
dataList.value = r.data.pageData
total.value = r.data.total
document.getElementsByClassName('resultContent')[0].scrollTop = 0
}
)
}
const formatGender = function(number) {
switch (number) {
case 1: {
return '男'
}
case -1: {
return '未知'
}
case 0: {
return '女'
}
default: {
break
}
}
}
const handleClick = function(data) {
currentItemId.value = data.id
currobj.value = data;
}
const comparativeFun = function() {
if (currobj.value == {}) {
ElMessage({
message: `请选择图片进行对比验证`,
type: 'warning'
});
return false
}
if (!currobj.value.picture_url) {
ElMessage({
message: `该图片没有特征,请选择有效的图片`,
type: 'warning'
})
return
}
const rawData = toRaw(queryForm)
let parmas = {
plaza_id: currobj.value.mall_id,
pic_type: rawData.picType,
pic_id: currobj.value.id,
ip: window._baseImgUrl,
countdate: formatDate(rawData.date)
}
DetailDialogRef.value.initDialog(currobj.value, parmas);
}
const clickSearch = function() {
pageNum.value = 1
confirmSearch()
}
// 删除试乘记录
const deleteBatches = function() {
if (!currentItemId.value) {
ElMessage({
message: `请选择图片`,
type: 'warning'
})
return
}
if (!currobj.value.picture_url) {
ElMessage({
message: `请选择有效的图片`,
type: 'warning'
})
return
}
ElMessageBox.confirm('是否确认删除该试乘记录?', {
confirmButtonText: '确认',
cancelButtonText: '取消',
}).then(() => {
snapshotRecordApi.deleteOneDrive({
id: currentItemId.value
}).then(
(res) => {
console.log(res)
if (res.code == 200) {
ElMessage({
message: `删除成功`,
type: 'success'
})
confirmSearch()
currentItemId.value = ''
currobj.value = {};
} else {
ElMessage({
message: `删除失败`,
type: 'warning'
})
}
}
)
}).catch(() => {})
}
const contentHeight = ref(0)
const __main = function() {
getAccountList()
contentHeight.value = window.innerHeight - 310
}
const fileList = ([]);
const beforeUpload= function(file) {
const formData = new FormData();
formData.append('file', file);
snapshotRecordApi.uploadDrive(formData).then((res) => {
if (res.code == 200) {
ElMessage({
message: `上传成功`,
type: 'success'
})
clickSearch()
} else {
ElMessage({
message: `上传失败`,
type: 'warning'
})
}
})
return false;
};
__main()
return {
beforeUpload,
fileList,
isLoading,
pageNum,
pageSize,
total,
currobj,
accountList,
plazaList,
zoneList,
gateList,
pagedTableDataList,
currentItemId,
contentHeight,
queryForm,
onPageNumChange,
onPageSizeChange,
onAccountChange,
onPlazaChange,
onZoneChange,
confirmSearch,
handleClick,
comparativeFun,
formatGender,
clickSearch,
deleteBatches,
DetailDialogRef,
}
}
}
</script>
<style lang="less" scoped>
@import "./SnapshotRecord";
.actived {
border: 3px solid #1890ff;
}
.resultContent {
overflow: auto;
min-height: 500px;
}
.downBtn {
color: #409EFF;
font-size: 15px;
cursor: pointer;
display: inline-block;
width: auto;
}
.downBtn1 {
float: right;
}
</style>
\ No newline at end of file
import axiosInstance from "@/Request/PublicAxiosInstance"
import {filterEmptyValueInObject} from "@/PublicUtil/PublicUtil"
class SnapshotRecordApi {
getSnapshotRecordList(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/car4s/engage/page`,
params: filterEmptyValueInObject(
data
)
}
)
}
getAccountList() {
return axiosInstance.request(
{
method: 'GET',
url: `/accounts`,
}
)
}
getPlazaList(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/malls`,
params: filterEmptyValueInObject(
{
accountIds: data.account_id
},
)
}
)
}
getResidenceList(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/residence`,
params:data
}
)
}
getZoneList(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/zones/zoneList`,
params: filterEmptyValueInObject(
{
account_id: data.account_id,
plaza_id: data.plaza_id,
},
)
}
)
}
getGateList(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/gates/gateByInfo`,
params: filterEmptyValueInObject(
{
account_id: data.account_id,
plaza_id: data.plaza_id,
zone_id: data.zone_id,
type: data.type,
},
)
}
)
}
// 删除试乘记录
deleteOneDrive(data) {
return axiosInstance.request(
{
method: 'DELETE',
url: `/car4s/engage/${data.id}`,
}
)
}
// 上传试乘记录
uploadDrive(data) {
return axiosInstance.request(
{
method: 'POST',
url: `/car4s/engage/upload`,
headers: {
'Content-Type': 'multipart/form-data'
},
data: data
}
)
}
}
const snapshotRecordApi = new SnapshotRecordApi()
export default snapshotRecordApi
<template>
<a-modal
title="图片"
v-if='isVisible'
v-model:visible="isVisible"
width="1200px"
height='90%'
class="detail-modal"
>
<canvas id="myCanvas"></canvas>
<img :src="imgUrl" alt="" id="img">
<template #footer>
<a-button @click="onCancel">返回</a-button>
</template>
</a-modal>
</template>
<script>
import { reactive, ref } from "vue";
export default {
setup() {
const isVisible = ref(false);
const isLoading = ref(false);
const detailData = ref({});
const imgUrl = ref()
const canvas = ref()
const ctx = ref()
const initDialog = (url,data) => {
imgUrl.value = url
isVisible.value = true;
setTimeout(()=>{
var imgscream=document.getElementById("img");
let height = imgscream.offsetHeight;
let width = imgscream.offsetWidth;
canvas.value = document.getElementById("myCanvas");//初始化
canvas.value.height = height;
canvas.value.width = width;
ctx.value = canvas.value.getContext("2d")
ctx.value.drawImage(imgscream,0,0,width,height);
ctx.value.beginPath();
ctx.value.lineWidth = 3
ctx.value.strokeStyle = "red";
ctx.value.moveTo(data.head_x_inSmall, data.head_y_inSmall);//起始位置
ctx.value.lineTo(data.foot_x_inSmall, data.foot_y_inSmall);//停止位置
ctx.value.stroke();
},0)
};
const onCancel = () => {
canvas.value = ''
isVisible.value = false;
};
return {
isVisible,
onCancel,
initDialog,
isLoading,
imgUrl,
detailData
};
},
};
</script>
<style lang="less" scoped>
#myCanvas{
display: block;
margin: 0 auto;
}
#img{
position: relative;
top: -5000px;
float: left;
}
</style>
<template>
<a-modal
title="单张图片特征对比"
v-if='isVisible'
v-model:visible="isVisible"
width="1600px"
height='90%'
class="detail-modal"
>
<el-row :gutter="20">
<el-col :span="8" class='imgBox1' v-loading='isLoading'>
<p class="title">
<span class="name">现在聚类</span>
<span class="id">{{detailData.person_unid}}</span>
<span class="num">{{featureList.length}}</span>
</p>
<el-row :gutter="10" class="imgBox1_top">
<el-col :span="8" class="itemBox" v-for="item in featureList">
<el-image :src="item.picture_url" :fit="'fill'" class="single-image" @click='clickItem(item)'>
</el-image>
<span class="el-icon-document downloadFile" @click="downloadFile(item,$event)"></span>
<span class="el-icon-picture-outline openImage" @click="openImage(item,$event)"></span>
<p class="featureNum">{{(item.featureNum).toFixed(2)}}</p>
<div>时间:{{ item.counttime }}</div>
<div>人员类型:{{ item.person_type==1?'店员':'顾客' }}</div>
<div class="direction" :class="'direction'+item.direction">方向:{{ formatDirection(item.direction) }}</div>
<div>地点:{{ item.gate_name }}</div>
</el-col>
<a-empty v-if='featureList.length==0' style='margin: 0 auto;'></a-empty>
</el-row>
</el-col>
<el-col :span="8" class='imgBox1' v-loading='isLoading1'>
<p class="title">
<span class="name">特征比对</span>
<span class="num">{{comparisonList.length}}</span>
</p>
<el-row :gutter="10" class="imgBox1_top">
<el-col :span="8" class="itemBox" v-for="item in comparisonList">
<el-image :src="item.picture_url" :fit="'fill'" class="single-image" @click='clickItem(item)'>
</el-image>
<span class="el-icon-picture-outline openImage" @click="openImage(item,$event)"></span>
<span class="el-icon-document downloadFile" @click="downloadFile(item,$event)"></span>
<p class="featureNum">{{item.featureNum?(item.featureNum).toFixed(2):0}}</p>
<div>时间:{{ item.counttime }}</div>
<div>人员类型:{{ item.person_type==1?'店员':'顾客' }}</div>
<div class="direction" :class="'direction'+item.direction">方向:{{ formatDirection(item.direction) }}</div>
<div>地点:{{ item.gate_name }}</div>
</el-col>
<a-empty v-if='comparisonList.length==0' style='margin: 0 auto;'></a-empty>
</el-row>
</el-col>
<el-col :span="8" class='imgBox1' v-loading='isLoading2'>
<p class="title">
<span class="name">重提特征后比对</span>
<a-button class="id" type="primary" @click="reComparisonFeature" >重提特征比对</a-button>
<span class="num">{{reComparisonList.length}}</span>
</p>
<el-row :gutter="10" class="imgBox1_top">
<el-col :span="8" class="itemBox" v-for="item in reComparisonList">
<el-image :src="item.picture_url" :fit="'fill'" class="single-image" @click='clickItem(item)'>
</el-image>
<span class="el-icon-picture-outline openImage" @click="openImage(item,$event)"></span>
<span class="el-icon-document downloadFile" @click="downloadFile(item,$event)"></span>
<p class="featureNum">{{item.featureNum?(item.featureNum).toFixed(2):0}}</p>
<div>时间:{{ item.counttime }}</div>
<div>人员类型:{{ item.person_type==1?'店员':'顾客' }}</div>
<div class="direction" :class="'direction'+item.direction">方向:{{ formatDirection(item.direction) }}</div>
<div>地点:{{ item.gate_name }}</div>
</el-col>
<a-empty v-if='reComparisonList.length==0' style='margin: 0 auto;'></a-empty>
</el-row>
</el-col>
</el-row>
<template #footer>
<a-button @click="onCancel">返回</a-button>
</template>
</a-modal>
<imgDialog ref='imgModelRef'></imgDialog>
<imgOtherDialog ref="imgOtherDialogRef" ></imgOtherDialog>
</template>
<script>
import { reactive, ref, watch } from "vue";
import featureApi from '@/views/FeatureComparisonVerification/api.js'
import clusterResultApi from '@/views/SnapshotCluster/ClusterResult/ClusterResultApi'
import {isArray} from '@/PublicUtil/Judgment'
import imgDialog from './imgDialog.vue'
import imgOtherDialog from "../ComparisonCapturedPictures/imgOtherDialog.vue";
export default {
components:{
imgDialog,
imgOtherDialog
},
setup() {
const isVisible = ref(false);
const isLoading = ref(false);
const isLoading1 = ref(false);
const isLoading2= ref(false);
const detailData = ref({});
const featureList = ref([])
const imgModelRef = ref();
const imgOtherDialogRef = ref();
const comparisonList = ref([])
const reComparisonList = ref([])
const formatDirection = function(number) {
switch (number) {
case 1: {
return '进'
}
case -1: {
return '出'
}
case 0: {
return '横穿'
}
default: {
break
}
}
}
watch([featureList],(newVal,oldVal)=>{
},{deep:true})
const initDialog = (data) => {
isLoading.value = true;
isLoading1.value = true;
isLoading2.value = false;
detailData.value = data;
featureList.value = []
reComparisonList.value = []
featureApi.getPersonContrastList(data).then((r) => {
isLoading.value = false
if (r.data&&isArray(r.data.personList)) {
r.data.personList.forEach((item) => {
if (item.features_url) {
item.features_url = window._baseImgUrl + item.features_url
}
if (item.picture_url) {
item.picture_url = window._baseImgUrl + item.picture_url
}
})
featureList.value = r.data.personList
}
}
)
comparisonList.value = []
featureApi.getAllPersonContrastList(data).then((r) => {
isLoading1.value = false
if (isArray(r.data)) {
if(r.data.length>0){
r.data.forEach((item) => {
if (item.features_url) {
item.features_url = window._baseImgUrl + item.features_url
}
if (item.picture_url) {
item.picture_url = window._baseImgUrl + item.picture_url
}
})
comparisonList.value = r.data
}
}
}
)
isVisible.value = true;
};
const clickItem = function(data){
clusterResultApi.getBodyPoint({'feature_url':data.features_url}).then((r) => {
imgModelRef.value.initDialog(data.picture_url,r.data);
})
}
const reComparisonFeature = function(){
isLoading2.value = true
reComparisonList.value = []
featureApi.getNewPersonContrastList(detailData.value).then((r) => {
isLoading2.value = false
if (isArray(r.data)) {
if(r.data.length>0){
r.data.forEach((item) => {
if (item.features_url) {
item.features_url = window._baseImgUrl + item.features_url
}
if (item.picture_url) {
item.picture_url = window._baseImgUrl + item.picture_url
}
})
reComparisonList.value = r.data
}
}
}
)
}
const downloadFile = function(item,event){
event.stopPropagation()
if(item.features_url){
window.open(item.features_url)
}else{
ElMessage(
{
message: `该图片没有特征`,
type: 'warning'
}
)
return
}
}
const openImage = function(item,event){
event.stopPropagation()
if(item.features_url){
let url = item.picture_url
imgOtherDialogRef.value.initDialog(url.split('0.jpg')[0]+'1.jpg')
}else{
ElMessage(
{
message: `该图片没有特征`,
type: 'warning'
}
)
return
}
}
const onCancel = () => {
isVisible.value = false;
};
return {
isVisible,
onCancel,
initDialog,
isLoading,
isLoading1,
isLoading2,
detailData,
featureList,
formatDirection,
downloadFile,
clickItem,
imgModelRef,
comparisonList,
reComparisonList,
reComparisonFeature,
openImage,
imgOtherDialogRef
};
},
};
</script>
<style lang="less" scoped>
.single-image {
height: 200px;
width: 150px;
cursor: pointer;
}
.direction{
font-weight: 900;
background-color: red;
color: white;
}
.direction1{
background-color: green;
}
.direction0{
background-color: orange;
}
.title{
height: 32px;
line-height: 32px;
padding: 0;
.name{
font-weight: 900;
font-size: 18px;
}
.id{
margin-left: 20px;
}
.num{
float: right;
margin-right: 15px;
}
}
.imgBox1{
// border-left: 10px solid #efefef;
box-sizing: border-box;
min-height: 100%;
.itemBox{
position: relative;
}
.downloadFile{
position: absolute;
color: #1890ff;
font-size: 32px;
top: 0;
right: 10px;
cursor: pointer;
}
.openImage{
position: absolute;
color: #1890ff;
font-size: 32px;
top: 0;
left: 90px;
cursor: pointer;
}
.featureNum{
position: absolute;
top: 0;
left: 15px;
color: red;
font-weight: 900;
font-size: 16px;
}
}
.imgBox1_top{
min-height: 400px;
max-height: 600px;
overflow-y: auto;
}
</style>
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!