Commit e0fedd15 by 李君

特征比对

1 parent b393711c
window._serverHost = ['localhost', '192.168.1.168'].includes(window.location.hostname) ? '36.112.68.214:9999/' : window.location.host
window._baseUrl = ['localhost', '192.168.1.168'].includes(window.location.hostname) ? 'http://36.112.68.214:9999/' : `http://${window._serverHost}`
// window._baseUrl = 'http://36.112.68.214:9999'
window._baseImgUrl = ['localhost', '192.168.1.168'].includes(window.location.hostname) ? 'http://36.112.68.214:33333/' : window.location.origin
const log = console.log.bind(console)
<template>
<div>
抓拍图片对比
<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.type" style="width: 280px">
<a-select-option :value="0">全场</a-select-option>
<a-select-option :value="1">广场出入口</a-select-option>
<a-select-option :value="2">楼层出入口</a-select-option>
<a-select-option :value="3">店铺出入口</a-select-option>
<a-select-option :value="4">其他</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="区域信息:" style="padding: 5px 0" v-if='queryForm.type==0 || queryForm.type==3'>
<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-select v-model:value="queryForm.direction" mode="multiple" :maxTagCount="1" style="width: 280px">
<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>
</a-form-item>
<a-form-item label="抓拍类型:" style="padding: 5px 0">
<a-select v-model:value="queryForm.picType" style="width: 280px">
<a-select-option :value="1">半身照</a-select-option>
<a-select-option :value="2">全身照</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="人员类型:" style="padding: 5px 0">
<a-select v-model:value="queryForm.personType" mode="multiple" :maxTagCount="1"
style="width: 280px">
<a-select-option :value="1">店员</a-select-option>
<a-select-option :value="2">顾客</a-select-option>
</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" />
<a-time-picker 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.minPic" :min="0" style="width: 100px"/>
<a-input-number v-model:value="queryForm.maxPic" :min="0" style="width: 100px"/>
</a-form-item>
<a-form-item style="padding: 5px 0">
<a-button type="primary" @click="confirmSearch" :loading="isLoading">查询</a-button>
</a-form-item>
</a-form>
<div v-loading="isLoading">
<a-row v-for="row in pagedTableDataList">
<a-col :span="3" v-for="(item,index) in row">
<div style="margin: 0 5px" draggable="true" @dragstart="dragStart(item,$event)" :class="item.id==currentItemId?'actived':''">
<el-image :src="item.picture_url" :fit="'fill'" class="single-image">
</el-image>
<div>时间:{{ item.counttime }}</div>
<div>类型:{{ formatPersonType(item.personType) }}</div>
<div>地点:{{ item.gate_name }}</div>
</div>
</a-col>
</a-row>
<a-pagination v-model:current="pageNum" v-model:pageSize="pageSize" :total="total"
:show-total="total => `共 ${total} 条`" :pageSizeOptions="['16', '32']"
@change="onPageNumChange" @showSizeChange="onPageSizeChange" show-size-changer show-quick-jumper
style="text-align:center" />
</div>
<div class="imgbox1">
<div class="btns">
<a-button type="primary" @click="featureComparison" >特征对比</a-button>
<a-button type="primary" @click="shoperFeatureComparison" >店员特征对比</a-button>
</div>
<a-row :gutter="[16,16]">
<a-col :span='12'>
<div class='comparsionBox' v-loading='isLoadingComparison'>
<p v-if='boxListLeft.length>0'>{{boxListLeft.length}}</p>
<a-row @dragenter="dragEnter($event)" @dragleave="dragLeave($event)" @drop="dropLeft($event)"
@dragover="allowDrop($event)" >
<a-col :span="8" v-for="item in boxListLeft">
<div style="margin: 0 5px" >
<el-image :src="item.picture_url" :fit="'fill'" class="single-image">
</el-image>
<div>时间:{{ item.counttime }}</div>
<div>方向:{{ formatDirection(item.direction) }}</div>
<div>地点:{{ item.gate_name }}</div>
</div>
</a-col>
<a-empty v-if='boxListLeft.length==0' description="拖拽图片到此处"></a-empty>
</a-row>
</div>
</a-col>
<a-col :span='12'>
<div class='comparsionBox' v-loading='isLoadingComparisonRight'>
<p v-if='boxListRight.length>0'>{{boxListRight.length}}</p>
<a-row @dragenter="dragEnter($event)" @dragleave="dragLeave($event)" @drop="dropRight($event)"
@dragover="allowDrop($event)">
<a-col :span="8" v-for="item in boxListRight">
<div style="margin: 0 5px" >
<el-image :src="item.picture_url" :fit="'fill'" class="single-image">
</el-image>
<div>时间:{{ item.counttime }}</div>
<div>方向:{{ formatDirection(item.direction) }}</div>
<div>地点:{{ item.gate_name }}</div>
</div>
</a-col>
<a-empty v-if='boxListRight.length==0' description="拖拽图片到此处"></a-empty>
</a-row>
</div>
</a-col>
</a-row>
<DetailDialog ref="DetailDialogRef" />
<DetailDialogComparison ref="DetailDialogComparisonRef" />
</div>
</template>
<script>
import {
computed,
reactive,
ref,
toRaw
} from 'vue'
import comparsionResultApi from '@/views/ComparisonCapturedPictures/api'
import snapshotRecordApi from '@/views/SnapshotCluster/SnapshotRecord/SnapshotRecordApi'
import {
isArray
} from '@/PublicUtil/Judgment'
import moment from 'moment'
import {
filterEmptyValueInObject,
formatDate,
formatTime,
getPagedList
} from '@/PublicUtil/PublicUtil'
import {ElMessage} from 'element-plus'
import DetailDialog from "./DetailDialog.vue";
import DetailDialogComparison from "./DetailDialogComparison.vue";
export default {
components: {
DetailDialog,
DetailDialogComparison
},
setup() {
// scalar
const pageNum = ref(1)
const pageSize = ref(16)
const total = ref()
const isLoading = ref(false)
const isLoadingComparison = ref(false)
const isLoadingComparisonRight = ref(false)
// sequence
const dataList = ref([])
const accountList = ref([])
const plazaList = ref([])
const zoneList = ref([])
const gateList = ref([])
// ref
const DetailDialogRef = ref();
const DetailDialogComparisonRef = ref();
const pagedTableDataList = computed(
() => {
return getPagedList(dataList.value, 8)
}
)
const queryForm = reactive({
account_id: [],
plaza_id: [],
zone_id: [],
gate_id: [],
type: 0,
direction: [1, -1, 0],
picType: 2,
personType: [1, 2],
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'),
minPic:'',
maxPic:'',
})
// function
const onPageNumChange = function(num) {
pageNum.value = num
confirmSearch()
}
const onPageSizeChange = function(current, size) {
pageNum.value = 1
pageSize.value = size
confirmSearch()
}
const onAccountChange = function() {
getPlazaList()
getZoneList()
getGateList()
}
const onPlazaChange = function() {
getZoneList()
getGateList()
}
const onZoneChange = function() {
getGateList()
}
const getPlazaList = function() {
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,
})
}
}
}
)
}
const getZoneList = function() {
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,
})
}
}
}
)
}
const getGateList = function() {
queryForm.gate_id = []
gateList.value = []
snapshotRecordApi.getGateList({
account_id: queryForm.account_id.toString(),
plaza_id: queryForm.plaza_id.toString(),
zone_id: queryForm.zone_id.toString(),
type: queryForm.type,
}).then(
(r) => {
if (isArray(r.data)) {
for (const item of r.data) {
gateList.value.push({
value: item.id,
label: item.name,
})
}
}
}
)
}
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,
})
}
}
}
)
}
const confirmSearch = function() {
const rawData = toRaw(queryForm)
if(rawData.minPic>rawData.maxPic){
ElMessage(
{
message: `请输入正确的图片数量范围`,
type: 'warning'
}
)
return
}
isLoading.value = true
const data = filterEmptyValueInObject({
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(),
picType: rawData.picType,
personType: rawData.personType.toString(),
startTime: formatDate(rawData.date) + ' ' + formatTime(rawData.startTime),
endTime: formatDate(rawData.date) + ' ' + formatTime(rawData.endTime),
minPic:rawData.minPic,
maxPic:rawData.maxPic,
page: pageNum.value - 1,
pageSize: pageSize.value,
})
comparsionResultApi.getPersonGroupList(data).then(
(r) => {
isLoading.value = false
r.data.persons.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
}
})
dataList.value = r.data.persons
total.value = r.data.pageNum
// boxListLeft.value = []
// boxListRight.value = []
// boxObj.value = {}
}
)
}
const formatDirection = function(number) {
switch (number) {
case 1: {
return '进'
}
case -1: {
return '出'
}
case 0: {
return '横穿'
}
default: {
break
}
}
}
const formatPersonType = function(number){
switch (number) {
case 1: {
return '店员'
}
case 0: {
return '顾客'
}
default: {
break
}
}
}
const __main = function() {
getAccountList()
}
let boxObjStart = ref({})
let boxObj = ref({})
let boxListLeft = ref([])
let boxListRight = ref([])
const currentItemId = ref()
const dragStart= function (item,event) {
boxObjStart.value = item
}
const dragEnter= function (event) {
console.log('进入')
}
const dragLeave= function (event) {
console.log('出去')
}
const allowDrop= function (event) {
event.preventDefault();
}
const dropLeft= function (event) {
event.preventDefault();
boxObj.value = boxObjStart.value
currentItemId.value = boxObj.value.id
isLoadingComparison.value = true;
boxListLeft.value = [];
const rawData = toRaw(queryForm)
let parmas = {
account_id: rawData.account_id.toString(),
plaza_id: rawData.plaza_id.toString(),
zone_id: rawData.zone_id.toString(),
gate_id: rawData.gate_id.toString(),
type: rawData.type,
direction: rawData.direction.toString(),
picType: rawData.picType,
personType: rawData.personType.toString(),
startTime: formatDate(rawData.date) + ' ' + formatTime(rawData.startTime),
endTime: formatDate(rawData.date) + ' ' + formatTime(rawData.endTime),
person_unid:boxObj.value.person_unid,
}
comparsionResultApi.getPersonsDetailList(parmas).then((r) => {
isLoadingComparison.value = false
if (r.msg_code==200 && isArray(r.data.personList)) {
if(r.data.personList.length>0){
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
}
})
boxListLeft.value = r.data.personList
}
}
}
)
}
const dropRight= function (event) {
event.preventDefault();
boxListRight.value = [];
boxObj.value = boxObjStart.value
currentItemId.value = boxObj.value.id
const rawData = toRaw(queryForm)
isLoadingComparisonRight.value = true
let parmas = {
account_id: rawData.account_id.toString(),
plaza_id: rawData.plaza_id.toString(),
zone_id: rawData.zone_id.toString(),
gate_id: rawData.gate_id.toString(),
type: rawData.type,
direction: rawData.direction.toString(),
picType: rawData.picType,
personType: rawData.personType.toString(),
startTime: formatDate(rawData.date) + ' ' + formatTime(rawData.startTime),
endTime: formatDate(rawData.date) + ' ' + formatTime(rawData.endTime),
person_unid:boxObj.value.person_unid,
}
comparsionResultApi.getPersonsDetailList(parmas).then((r) => {
isLoadingComparisonRight.value = false
if (r.msg_code==200 && isArray(r.data.personList)) {
if(r.data.personList.length>0){
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
}
})
boxListRight.value = r.data.personList
}
}
}
)
}
// 特征对比
const featureComparison = function(){
const rawData = toRaw(queryForm)
if(!boxObj.value.id){
ElMessage(
{
message: `请拖拽图片到下方`,
type: 'warning'
}
)
return
}
if(!boxObj.value.picture_url){
ElMessage(
{
message: `该图片没有特征,请选择有效的图片`,
type: 'warning'
}
)
return
}
let parmas = {
mall_id:boxObj.value.mall_id,
picType:rawData.picType,
pic_id:boxObj.value.id,
countdate:formatDate(rawData.date)
}
parmas.persionlistLeft = boxListLeft.value
parmas.persionlistRight = boxListRight.value
DetailDialogComparisonRef.value.initDialog(boxObj.value,parmas);
}
// 店员特征对比
const shoperFeatureComparison = function(){
const rawData = toRaw(queryForm)
if(!boxObj.value.id){
ElMessage(
{
message: `请拖拽图片到下方`,
type: 'warning'
}
)
return
}
if(!boxObj.value.picture_url){
ElMessage(
{
message: `该图片没有特征,请选择有效的图片`,
type: 'warning'
}
)
return
}
let parmas = {
plaza_id:boxObj.value.mall_id,
pic_type:rawData.picType,
pic_id:boxObj.value.id,
ip:window._baseImgUrl
}
DetailDialogRef.value.initDialog(boxObj.value,parmas);
}
__main()
return {
// scalar
isLoading,
pageNum,
pageSize,
total,
isLoadingComparison,
isLoadingComparisonRight,
currentItemId,
// sequence
accountList,
plazaList,
zoneList,
gateList,
pagedTableDataList,
boxListLeft,
boxListRight,
// mapping
queryForm,
// function
onPageNumChange,
onPageSizeChange,
onAccountChange,
onPlazaChange,
onZoneChange,
confirmSearch,
formatDirection,
formatPersonType,
dragStart,
dragEnter,
dragLeave,
allowDrop,
dropLeft,
dropRight,
featureComparison,
shoperFeatureComparison,
// ref
DetailDialogRef,
DetailDialogComparisonRef
}
}
}
</script>
<style scoped="scoped" lang="less">
.single-image {
height: 300px;
width: 100%;
}
.actived{
border: 1px solid #1890ff;
}
.imgbox1{
<style>
margin-top: 20px;
.btns{
margin-top: 10px;
margin-bottom: 10px;
}
button{
margin-right: 10px;
}
}
.comparsionBox{
padding-top: 5px;
border: 2px dashed #ccc;
height: 430px;
overflow-y: auto;
p{
text-align: right;
margin-right: 20px;
}
.ant-empty{
margin: 0 auto;
margin-top: 50px;
}
}
</style>
<template>
<a-modal
title="店员特征对比"
v-model:visible="isVisible"
width="1500px"
height='90%'
class="detail-modal"
>
<div v-loading='isLoading'>
<a-row :gutter="[16,16]">
<a-col :span='4'>
<div style="margin: 0 5px">
<el-image :src="detailData.picture_url" :fit="'fill'" class="single-image">
</el-image>
<div>时间:{{ detailData.counttime }}</div>
<div>方向:{{ formatDirection(detailData.direction) }}</div>
<div>地点:{{ detailData.gate_name }}</div>
</div>
</a-col>
<a-col :span='20'>
<a-row v-for="(row,index) in dataList" :key='index' class='rowBox'>
<p>{{row.name}} {{row.shopname}}</p>
<a-col :span="6" v-for="item in row.personList" class='itemBox' :key='item.id'>
<div style="margin: 0 5px">
<el-image :src="item.picture_url" :fit="'fill'" class="single-image">
</el-image>
<p class="featureNum">{{item.featureNum}}</p>
<div>时间:{{ item.counttime }}</div>
</div>
</a-col>
</a-row>
</a-col>
</a-row>
</div>
<template #footer>
<a-button @click="onCancel">返回</a-button>
</template>
</a-modal>
</template>
<script>
import { reactive, ref } from "vue";
import {isArray } from '@/PublicUtil/Judgment'
import comparsionResultApi from '@/views/ComparisonCapturedPictures/api'
export default {
setup() {
const isVisible = ref(false);
const isLoading = ref(false);
const detailData = ref({});
const dataList = ref([])
const initDialog = (record,parmas) => {
detailData.value = record;
isVisible.value = true;
dataList.value = []
isLoading.value = true
comparsionResultApi.getStaffContrastList(parmas).then((r) => {
isLoading.value = false
if (isArray(r.data)) {
if(r.data.length>0){
dataList.value = r.data
console.log(r.data)
}
}
}
)
};
const formatDirection = function(number) {
switch (number) {
case 1: {
return '进'
}
case -1: {
return '出'
}
case 0: {
return '横穿'
}
default: {
break
}
}
}
const onCancel = () => {
isVisible.value = false;
};
return {
isVisible,
detailData,
onCancel,
dataList,
initDialog,
isLoading,
formatDirection
};
},
};
</script>
<style lang="less" scoped>
.single-image {
height: 300px;
width: 100%;
}
.rowBox{
border : 2px dashed #ccc;
padding: 0 5px;
margin-bottom: 15px;
}
.itemBox{
position: relative;
}
.featureNum{
position: absolute;
top: 0;
left: 15px;
color: red;
font-weight: 900;
font-size: 16px;
}
</style>
<template>
<a-modal
title="特征对比"
v-model:visible="isVisible"
width="1500px"
class="detail-modal"
>
<div>
<a-row :gutter="[16,16]">
<a-col :span='4'>
<div style="margin: 0 5px">
<el-image :src="detailData.picture_url" :fit="'fill'" class="single-image">
</el-image>
<div>时间:{{ detailData.counttime }}</div>
<div>方向:{{ formatDirection(detailData.direction) }}</div>
<div>地点:{{ detailData.gate_name }}</div>
</div>
</a-col>
<a-col :span='20'>
<div v-loading='isLoadingTop' class='rowBox'>
<p v-if="dataListLeft">左侧</p>
<a-row >
<a-col :span="6" v-for="(item,index) in dataListLeft" :key='index'>
<div style="margin: 0 5px" class="itemBox">
<el-image :src="item.picture_url" :fit="'fill'" class="single-image">
</el-image>
<p class="featureNum">{{(item.featureNum).toFixed(2)}}</p>
<div>时间:{{ item.counttime }}</div>
<div>方向:{{ formatDirection(item.direction) }}</div>
<div>地点:{{ item.gate_name }}</div>
</div>
</a-col>
</a-row>
</div>
<div v-loading='isLoadingBottom' class='rowBox'>
<p v-if="dataListRight">右侧</p>
<a-row>
<a-col :span="6" v-for="(item,index) in dataListRight" :key='index'>
<div style="margin: 0 5px" class="itemBox">
<el-image :src="item.picture_url" :fit="'fill'" class="single-image">
</el-image>
<p class="featureNum">{{(item.featureNum).toFixed(2)}}</p>
<div>时间:{{ item.counttime }}</div>
<div>方向:{{ formatDirection(item.direction) }}</div>
<div>地点:{{ item.gate_name }}</div>
</div>
</a-col>
</a-row>
</div>
</a-col>
</a-row>
</div>
<template #footer>
<a-button @click="onCancel">返回</a-button>
</template>
</a-modal>
</template>
<script>
import { reactive, ref } from "vue";
import {isArray } from '@/PublicUtil/Judgment'
import comparsionResultApi from '@/views/ComparisonCapturedPictures/api'
export default {
setup() {
const isVisible = ref(false);
const isLoadingTop = ref(false);
const isLoadingBottom = ref(false);
const detailData = ref({});
const dataListLeft = ref([])
const dataListRight = ref([])
const initDialog = (record,parmas) => {
detailData.value = record;
isVisible.value = true;
dataListLeft.value = []
dataListRight.value = []
if(parmas.persionlistLeft.length>0){
isLoadingTop.value = true
// 左侧
let parmasObj = {
mall_id:parmas.mall_id,
picType:parmas.picType,
pic_id:parmas.pic_id,
countdate:parmas.countdate,
personList:parmas.persionlistLeft
}
comparsionResultApi.getPersonContrastList(parmasObj).then((r) => {
isLoadingTop.value = false
if (r.data&&isArray(r.data.personList)) {
if(r.data.personList.length>0){
// r.data.forEach((item) => {
// let str = item.features_url.indexOf("/images/feature")
// if (item.features_url) {
// item.features_url = window._baseImgUrl + item.features_url.substring(str)
// }
// let str1 = item.picture_url.indexOf("/images/picture")
// if (item.picture_url) {
// item.picture_url = window._baseImgUrl + item.picture_url.substring(str1)
// }
// })
dataListLeft.value = r.data.personList
console.log(r.data)
}
}
}
)
}
if(parmas.persionlistRight.length>0){
isLoadingBottom.value = true
let parmasObj = {
mall_id:parmas.mall_id,
picType:parmas.picType,
pic_id:parmas.pic_id,
countdate:parmas.countdate,
personList:parmas.persionlistRight
}
//右侧
comparsionResultApi.getPersonContrastList(parmasObj).then((r) => {
isLoadingBottom.value = false
if (r.data&&isArray(r.data.personList)) {
if(r.data.personList.length>0){
// r.data.forEach((item) => {
// let str = item.features_url.indexOf("/images/feature")
// if (item.features_url) {
// item.features_url = window._baseImgUrl + item.features_url.substring(str)
// }
// let str1 = item.picture_url.indexOf("/images/picture")
// if (item.picture_url) {
// item.picture_url = window._baseImgUrl + item.picture_url.substring(str1)
// }
// })
dataListRight.value = r.data.personList
console.log(r.data)
}
}
}
)
}
};
const formatDirection = function(number) {
switch (number) {
case 1: {
return '进'
}
case -1: {
return '出'
}
case 0: {
return '横穿'
}
default: {
break
}
}
}
const onCancel = () => {
isVisible.value = false;
};
return {
isVisible,
detailData,
onCancel,
dataListLeft,
dataListRight,
initDialog,
formatDirection,
isLoadingTop,
isLoadingBottom
};
},
};
</script>
<style lang="less" scoped>
.single-image {
height: 300px;
width: 100%;
}
.rowBox{
border : 2px dashed #ccc;
padding: 0 5px;
margin-bottom: 15px;
}
.itemBox{
position: relative;
}
.featureNum{
position: absolute;
top: 0;
left: 15px;
color: red;
font-weight: 900;
font-size: 16px;
}
</style>
import axiosInstance from "@/Request/PublicAxiosInstance"
import {filterEmptyValueInObject} from "@/PublicUtil/PublicUtil"
class ComparisonResultApi {
getPersonGroupList(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/feature/personGroup`,
params: filterEmptyValueInObject(
data
)
}
)
}
// 人员列表详情
getPersonsDetailList(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/feature/persons`,
params: filterEmptyValueInObject(
data
)
}
)
}
// 店员特征对比
getStaffContrastList(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/feature/staffContrast`,
params: filterEmptyValueInObject(
data
)
}
)
}
// 特征对比
getPersonContrastList(data) {
return axiosInstance.request(
{
method: 'POST',
url: `/feature/personContrast`,
data: filterEmptyValueInObject(
data
)
}
)
}
}
const comparsionResultApi = new ComparisonResultApi()
export default comparsionResultApi
\ No newline at end of file
<template>
<a-row>
<a-row style='height: 100%;' :gutter="10">
<a-col :span="14">
<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"
<a-select v-model:value="queryForm.account_id" style="width: 230px" 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"
<a-select v-model:value="queryForm.plaza_id" style="width: 230px" 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.type" style="width: 280px">
<a-select v-model:value="queryForm.type" style="width: 230px">
<a-select-option :value="0">全场</a-select-option>
<a-select-option :value="1">广场出入口</a-select-option>
<a-select-option :value="2">楼层出入口</a-select-option>
......@@ -21,42 +21,42 @@
<a-select-option :value="4">其他</a-select-option>
</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"
<a-form-item label="区域信息:" style="padding: 5px 0" v-if='queryForm.type==0 || queryForm.type==3'>
<a-select v-model:value="queryForm.zone_id" style="width: 230px" 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"
<a-select v-model:value="queryForm.gate_id" style="width: 230px" mode="multiple" :maxTagCount="1"
:options="gateList" optionFilterProp="label" show-search>
</a-select>
</a-form-item>
<a-form-item label="方向:" style="padding: 5px 0">
<a-select v-model:value="queryForm.direction" mode="multiple" :maxTagCount="1" style="width: 280px">
<a-select v-model:value="queryForm.direction" mode="multiple" :maxTagCount="1" style="width: 230px">
<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>
</a-form-item>
<a-form-item label="抓类型:" style="padding: 5px 0">
<a-select v-model:value="queryForm.picType" style="width: 280px">
<a-form-item label="抓类型:" style="padding: 5px 0">
<a-select v-model:value="queryForm.picType" style="width: 230px">
<a-select-option :value="1">半身照</a-select-option>
<a-select-option :value="2">全身照</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="人员类型:" style="padding: 5px 0">
<a-select v-model:value="queryForm.personType" mode="multiple" :maxTagCount="1"
style="width: 280px">
style="width: 230px">
<a-select-option :value="1">店员</a-select-option>
<a-select-option :value="2">顾客</a-select-option>
</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-date-picker v-model:value="queryForm.date" :format="'YYYY-MM-DD'" style="width: 230px" />
</a-form-item>
<a-form-item label="选择时间:" style="padding: 5px 0">
<a-time-picker v-model:value="queryForm.startTime" style="width: 140px" />
<a-time-picker v-model:value="queryForm.endTime" style="width: 140px" />
<a-time-picker v-model:value="queryForm.startTime" style="width: 100px" />
<a-time-picker v-model:value="queryForm.endTime" style="width: 100px" />
</a-form-item>
<a-form-item style="padding: 5px 0">
<a-button type="primary" @click="confirmSearch" :loading="isLoading">查询</a-button>
......@@ -64,8 +64,8 @@
</a-form>
<div v-loading="isLoading">
<el-row v-for="row in pagedTableDataList">
<el-col :span="6" v-for="item in row">
<div style="margin: 0 5px">
<el-col :span="6" v-for="(item,index) in row" :key="index">
<div style="margin: 0 5px" @click='chooseItem(item)' class="colItem" :class="currentItemId==item.id?'actived':''">
<el-image :src="item.picture_url" :fit="'fill'" class="single-image">
</el-image>
<div>时间:{{ item.counttime }}</div>
......@@ -74,15 +74,41 @@
</div>
</el-col>
</el-row>
<a-pagination v-model:current="pageNum" v-model:pageSize="pageSize" :total="total"
:show-total="total => `共 ${total} 条`" :pageSizeOptions="['12', '24', '48', '192']"
@change="onPageNumChange" @showSizeChange="onPageSizeChange" show-size-changer show-quick-jumper
style="text-align:center" />
</div>
</a-col>
<a-col :span="10">
col-12
<a-col :span="10" class='imgBox1'>
<el-row class="imgBox1_top" :gutter="10" v-loading="isLoadingFeature">
<el-col :span="8" class="itemBox" v-for="item in featureList">
<el-image :src="item.picture_url" :fit="'fill'" class="single-image">
</el-image>
<p class="featureNum">{{(item.featureNum).toFixed(2)}}</p>
<div>时间:{{ item.counttime }}</div>
<div>方向:{{ 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>
<div class="imgBox2_top" >
<div class="btns">
<a-button type="primary" @click="reComparison" >重新比对</a-button>
<a-button type="primary" @click="reComparisonFeature" >重提特征比对</a-button>
</div>
<el-row :gutter="10" v-loading="isLoadingComparison" class='imgBox2'>
<el-col :span="8" class="itemBox" v-for="item in comparisonList">
<el-image :src="item.picture_url" :fit="'fill'" class="single-image">
</el-image>
<p class="featureNum">{{(item.featureNum).toFixed(2)}}</p>
<div>时间:{{ item.counttime }}</div>
<div>方向:{{ 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>
</div>
</a-col>
</a-row>
......@@ -96,6 +122,7 @@
toRaw
} from 'vue'
import snapshotRecordApi from '@/views/SnapshotCluster/SnapshotRecord/SnapshotRecordApi'
import featureApi from '@/views/FeatureComparisonVerification/api.js'
import {
isArray
} from '@/PublicUtil/Judgment'
......@@ -106,7 +133,7 @@
formatTime,
getPagedList
} from '@/PublicUtil/PublicUtil'
import {ElMessage} from 'element-plus'
export default {
setup() {
// scalar
......@@ -120,7 +147,11 @@
const plazaList = ref([])
const zoneList = ref([])
const gateList = ref([])
const featureList = ref([])
const comparisonList = ref([])
const boxObj = ref({})
const currentItemId = ref()
const isLoadingFeature = ref(false)
const pagedTableDataList = computed(
() => {
return getPagedList(dataList.value, 8)
......@@ -154,8 +185,8 @@
const onAccountChange = function() {
getPlazaList()
getZoneList()
getGateList()
// getZoneList()
// getGateList()
}
const onPlazaChange = function() {
......@@ -268,15 +299,11 @@
(r) => {
isLoading.value = false
r.data.persons.forEach((item) => {
let str = item.features_url.indexOf("/images/feature")
if (item.features_url) {
item.features_url = window.location.origin + item.features_url
.substring(str)
item.features_url = window._baseImgUrl + item.features_url
}
let str1 = item.picture_url.indexOf("/images/picture")
if (item.picture_url) {
item.picture_url = window.location.origin + item.picture_url.substring(
str1)
item.picture_url = window._baseImgUrl + item.picture_url
}
})
dataList.value = r.data.persons
......@@ -302,11 +329,109 @@
}
}
}
const __main = function() {
getAccountList()
}
const chooseItem = function(data){
isLoadingFeature.value = true
currentItemId.value = data.id
const rawData = toRaw(queryForm)
let parmas = {
mall_id:data.mall_id,
picType:rawData.picType,
countdate:formatDate(rawData.date),
pic_id:data.id,
personList:[data]
}
boxObj.value = data;
featureList.value = []
featureApi.getPersonContrastList(parmas).then((r) => {
isLoadingFeature.value = false
console.log(r.data)
if (r.data&&isArray(r.data.personList)) {
featureList.value = r.data.personList
}
}
)
}
const isLoadingComparison = ref(false)
const reComparison = function(){
const rawData = toRaw(queryForm)
if(!boxObj.value.id){
ElMessage(
{
message: `请选择左侧列表`,
type: 'warning'
}
)
return
}
isLoadingComparison.value = true
let parmas = {
plaza_id:boxObj.value.mall_id,
pic_type:rawData.picType,
countdate:formatDate(rawData.date),
pic_id:boxObj.value.id,
ip:window._baseImgUrl
}
comparisonList.value = []
featureApi.getAllPersonContrastList(parmas).then((r) => {
isLoadingComparison.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
}
}
}
)
}
const reComparisonFeature = function(){
const rawData = toRaw(queryForm)
if(!boxObj.value.id){
ElMessage(
{
message: `请选择左侧列表`,
type: 'warning'
}
)
return
}
isLoadingComparison.value = true
let parmas = {
plaza_id:boxObj.value.mall_id,
pic_type:rawData.picType,
countdate:formatDate(rawData.date),
pic_id:boxObj.value.id,
ip:window._baseImgUrl
}
comparisonList.value = []
featureApi.getNewPersonContrastList(parmas).then((r) => {
isLoadingComparison.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
}
}
}
)
}
__main()
return {
......@@ -315,12 +440,17 @@
pageNum,
pageSize,
total,
isLoadingFeature,
isLoadingComparison,
currentItemId,
// sequence
accountList,
plazaList,
zoneList,
gateList,
pagedTableDataList,
featureList,
comparisonList,
// mapping
queryForm,
// function
......@@ -331,13 +461,63 @@
onZoneChange,
confirmSearch,
formatDirection,
chooseItem,
reComparison,
reComparisonFeature,
}
}
}
</script>
<style scoped="scoped">
<style scoped="scoped" lang="less">
.single-image {
height: 300px;
width: 100%;
}
.imgBox1{
border-left: 10px solid #efefef;
box-sizing: border-box;
min-height: 100%;
.itemBox{
position: relative;
}
.featureNum{
position: absolute;
top: 0;
left: 15px;
color: red;
font-weight: 900;
font-size: 16px;
}
}
.imgBox2{
min-height: 400px;
max-height: 600px;
overflow-y: auto;
}
.imgBox1_top{
min-height: 400px;
max-height: 600px;
overflow-y: auto;
border-bottom: 10px solid #efefef;
}
.imgBox2_top{
.btns{
text-align: right;
margin-top: 10px;
margin-bottom: 10px;
}
button{
margin-right: 10px;
}
}
.colItem{
cursor: pointer;
div{
padding-left: 5px;
}
}
.actived{
border: 1px solid #1890ff;
}
</style>
import axiosInstance from "@/Request/PublicAxiosInstance"
import {filterEmptyValueInObject} from "@/PublicUtil/PublicUtil"
class FeatureResultApi {
getPersonContrastList(data) {
return axiosInstance.request(
{
method: 'POST',
url: `/feature/personContrast`,
data: filterEmptyValueInObject(
data
)
}
)
}
// 重新比对
getAllPersonContrastList(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/feature/allPersonContrast`,
params: filterEmptyValueInObject(
data
)
}
)
}
// 特征重提
getNewPersonContrastList(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/feature/newPersonContrast`,
params: filterEmptyValueInObject(
data
)
}
)
}
}
const featureResultApi = new FeatureResultApi()
export default featureResultApi
\ No newline at end of file
......@@ -67,7 +67,7 @@
<a-select-option :value="0">横穿</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="抓类型:" style="padding: 5px 0">
<a-form-item label="抓类型:" style="padding: 5px 0">
<a-select v-model:value="queryForm.picType" style="width: 280px">
<a-select-option :value="1">半身照</a-select-option>
<a-select-option :value="2">全身照</a-select-option>
......@@ -337,13 +337,11 @@ export default {
sortDataList(r.data.persons)
r.data.persons.forEach((itemPerson)=>{
itemPerson.perrsonList.forEach((item)=>{
let str = item.features_url.indexOf("/images/feature")
if(item.features_url){
item.features_url = window.location.origin+item.features_url.substring(str)
if (item.features_url) {
item.features_url = window._baseImgUrl + item.features_url
}
let str1 = item.picture_url.indexOf("/images/picture")
if(item.picture_url){
item.picture_url = window.location.origin+item.picture_url.substring(str1)
if (item.picture_url) {
item.picture_url = window._baseImgUrl + item.picture_url
}
})
})
......
......@@ -66,7 +66,7 @@
<a-select-option :value="0">横穿</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="抓类型:" style="padding: 5px 0">
<a-form-item label="抓类型:" style="padding: 5px 0">
<a-select v-model:value="queryForm.picType" style="width: 280px">
<a-select-option :value="1">半身照</a-select-option>
<a-select-option :value="2">全身照</a-select-option>
......@@ -323,13 +323,11 @@ export default {
(r) => {
isLoading.value = false
r.data.persons.forEach((item)=>{
let str = item.features_url.indexOf("/images/feature")
if(item.features_url){
item.features_url = window.location.origin+item.features_url.substring(str)
if (item.features_url) {
item.features_url = window._baseImgUrl + item.features_url
}
let str1 = item.picture_url.indexOf("/images/picture")
if(item.picture_url){
item.picture_url = window.location.origin+item.picture_url.substring(str1)
if (item.picture_url) {
item.picture_url = window._baseImgUrl + item.picture_url
}
})
dataList.value = r.data.persons
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!