Commit 57a5e9d7 by 李乾广

增加店铺客流来源轨迹分析页面

1 parent 39163ce7
...@@ -34,6 +34,10 @@ const menuRoute = [ ...@@ -34,6 +34,10 @@ const menuRoute = [
component: () => import("@/views/SnapshotCluster1/SnapshotCluster.vue"), component: () => import("@/views/SnapshotCluster1/SnapshotCluster.vue"),
}, },
{ {
path: 'SourceTrajectoryAnalysis',
component: () => import("@/views/SourceTrajectoryAnalysis/index.vue"),
},
{
path: 'EquipmentTimeErrorVerification', path: 'EquipmentTimeErrorVerification',
component: () => import("@/views/EquipmentTimeErrorVerification/EquipmentTimeErrorVerification.vue"), component: () => import("@/views/EquipmentTimeErrorVerification/EquipmentTimeErrorVerification.vue"),
}, },
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
</el-header> </el-header>
<el-main style="padding: 0"> <el-main style="padding: 0">
<el-container> <el-container>
<el-aside style="background: #001529" width="190px"> <el-aside style="background: #001529" width="200px">
<a-menu mode="inline" theme="dark" v-model:selectedKeys="selectedKeys" @click="onClick"> <a-menu mode="inline" theme="dark" v-model:selectedKeys="selectedKeys" @click="onClick">
<a-menu-item :key="'/Main/DataRerun'"> <a-menu-item :key="'/Main/DataRerun'">
<div class="flex-vertical-center"> <div class="flex-vertical-center">
...@@ -121,6 +121,12 @@ ...@@ -121,6 +121,12 @@
<span style="padding: 0 5px">抓拍聚类删除</span> <span style="padding: 0 5px">抓拍聚类删除</span>
</div> </div>
</a-menu-item> </a-menu-item>
<a-menu-item :key="'/Main/SourceTrajectoryAnalysis'">
<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> </a-menu>
</el-aside> </el-aside>
<el-main> <el-main>
......
.single-image {
height: 300px;
width: 100%;
}
.direction{
font-weight: 900;
background-color: red;
color: white;
}
.direction1{
background-color: green;
}
.direction0{
background-color: orange;
}
import axiosInstance from "@/Request/PublicAxiosInstance"
import {filterEmptyValueInObject} from "@/PublicUtil/PublicUtil"
class ClusterResultApi {
getClusterResultList(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/faceRecognitions/faceRecordGroup`,
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
)
}
)
}
}
const clusterResultApi = new ClusterResultApi()
export default clusterResultApi
import axiosInstance from "@/Request/PublicAxiosInstance"
import {filterEmptyValueInObject} from "@/PublicUtil/PublicUtil"
class SourceTrajectoryAnalysisApi {
getList(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/track/list`,
params: filterEmptyValueInObject(
data
)
}
)
}
}
const sourceTrajectoryAnalysisApi = new SourceTrajectoryAnalysisApi()
export default sourceTrajectoryAnalysisApi
<template>
<a-form :model="queryForm" layout="inline">
<a-form-item label="集团:" style="padding: 5px 0;margin-bottom: 24px;">
<a-select v-model:value="queryForm.account_id" style="width: 280px" @change="onAccountChange"
:options="accountList" optionFilterProp="label" show-search>
</a-select>
</a-form-item>
<a-form-item label="广场:" style="padding: 5px 0;margin-bottom: 24px;">
<a-select v-model:value="queryForm.plaza_id" style="width: 280px" @change="onPlazaChange" :options="plazaList"
optionFilterProp="label" show-search>
</a-select>
</a-form-item>
<a-form-item label="区域信息:" style="padding: 5px 0;margin-bottom: 24px;">
<a-select v-model:value="queryForm.zone_id" style="width: 240px" @change="onZoneChange" :options="zoneList"
optionFilterProp="label" show-search>
</a-select>
</a-form-item>
<a-form-item label="日期:" style="padding: 5px 0;margin-bottom: 24px;">
<a-date-picker v-model:value="queryForm.countDate" style="width: 280px" />
</a-form-item>
<a-form-item style="padding: 5px 0;margin-bottom: 24px;">
<a-button type="primary" @click="search">查询</a-button>
</a-form-item>
</a-form>
<a-table :dataSource="dataList" v-loading="isLoading" :columns="[
{
title: 'person_unid',
dataIndex: 'personUnid',
align:'center',
slots: {
customRender: 'accountname',
},
},
{
title: '第一次出现的地点',
dataIndex: 'firstGateName',
align:'center',
},
{
title: '第一次出现的时间',
dataIndex: 'fistCountTime',
align:'center',
},
{
title: '进入时间',
dataIndex: 'inTime',
align:'center',
},
{
title: '离开时间',
dataIndex: 'outTime',
align:'center',
},
{
title: '停留时间(毫秒)',
dataIndex: 'residenceTime',
align:'center',
},
{
title: '最后一次出现的地点',
dataIndex: 'lastGateName',
align:'center',
},
{
title: '最后一次出现的时间',
dataIndex: 'lastCountTime',
align:'center',
},
{
title: '到过的店铺数量',
dataIndex: 'inZoneNum',
align:'center',
},
{
title: '是否多次进出',
dataIndex: 'manyTimes',
align:'center',
},
{
title: '操作',
dataIndex: 'operation',
align: 'center',
width:100,
slots: {
customRender: 'operation',
},
}
]" :pagination="false">
<template #operation="{ record }">
<div>
<a-button @click="showDetail(record)" type="primary">查看详情</a-button>
</div>
</template>
</a-table>
<a-pagination v-model:current="pageNum" v-model:pageSize="pageSize" :total="total"
:show-total="total => `共 ${total} 条`" :pageSizeOptions="['10', '20']" @change="onPageNumChange"
@showSizeChange="onPageSizeChange" show-size-changer show-quick-jumper style="text-align:center;margin-top: 10px;" />
<ClusterResult ref="ClusterResultRef" />
</template>
<script>
import moment from 'moment'
import {
isArray
} from '@/PublicUtil/Judgment'
import {
defineComponent,
ref,
toRaw,
reactive
} from 'vue'
import {
filterEmptyValueInObject,
formatDate
} from '@/PublicUtil/PublicUtil'
import clusterResultApi from '@/views/SnapshotCluster/ClusterResult/ClusterResultApi'
import SourceTrajectoryAnalysisApi from '@/views/SourceTrajectoryAnalysis/SourceTrajectoryAnalysisApi'
import ClusterResult from '@/views/SourceTrajectoryAnalysis/ClusterResult/ClusterResult.vue'
export default defineComponent({
components: {
ClusterResult,
},
setup() {
const ClusterResultRef = ref();
const pageNum = ref(1)
const pageSize = ref(10)
const total = ref()
const dataList = ref([])
const isLoading = ref(false)
const accountList = ref([])
const plazaList = ref([])
const zoneList = ref([])
const queryForm = reactive({
account_id: '',
plaza_id: '',
zone_id: '',
countDate: moment(moment().format('YYYY-MM-DD'), 'YYYY-MM-DD')
})
const searchCondition = ref({})
// if (window.localStorage.getItem('searchCondition')) {
// searchCondition.value = JSON.parse(window.localStorage.getItem('searchCondition'));
// queryForm.account_id = searchCondition.value.zone_id;
// queryForm.plaza_id = searchCondition.value.plaza_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 = accountList.value[0].value
}
getPlazaList()
}
}
}
)
}
const onAccountChange = function() {
getPlazaList(1)
}
const getPlazaList = function(val) {
queryForm.plaza_id = ''
plazaList.value = []
if (!queryForm.account_id.toString()) {
return
}
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 = plazaList.value[0].value
}
getZoneList(1)
}
}
}
)
}
const onPlazaChange = function() {
getZoneList(1)
}
const getZoneList = function(val) {
queryForm.zone_id = ''
zoneList.value = []
clusterResultApi.getZoneList({
account_id: queryForm.account_id,
plaza_id: queryForm.plaza_id,
}).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 = zoneList.value[0].value
}
}
confirmSearch()
}
}
)
}
const onZoneChange = function() {
// confirmSearch()
}
const onPageNumChange = function(num) {
pageNum.value = num
confirmSearch()
}
const onPageSizeChange = function(current, size) {
pageNum.value = 1
pageSize.value = size
confirmSearch()
}
const confirmSearch = function() {
isLoading.value = true
const rawData = toRaw(queryForm)
const data = filterEmptyValueInObject({
page: pageNum.value - 1,
pageSize: pageSize.value,
countDate: formatDate(rawData.countDate),
zoneId: rawData.zone_id,
mallId: rawData.plaza_id,
})
dataList.value = [], total.value = 0
SourceTrajectoryAnalysisApi.getList(data).then(
(r) => {
isLoading.value = false
if (r.msg_code == 200) {
dataList.value = r.data.persons
total.value = r.data.pageNum
}
}
)
}
const search = function() {
pageNum.value = 1
pageSize.value = 10
confirmSearch()
}
const __main = function() {
getAccountList()
}
const showDetail = function(row) {
const rawData = toRaw(queryForm)
const data = filterEmptyValueInObject({
page: 0,
pageSize: 10,
account_id: rawData.account_id,
plaza_id: rawData.plaza_id,
type: 0,
picType: 2,
startTime:formatDate(rawData.countDate) + ' 00:00:00',
endTime:formatDate(rawData.countDate) + ' 23:59:59',
personUnid: row.personUnid,
direction: '-1,1',
})
// console.log(data)
ClusterResultRef.value.initDialog(data);
}
__main()
return {
ClusterResultRef,
accountList,
onAccountChange,
plazaList,
zoneList,
onPlazaChange,
onZoneChange,
queryForm,
pageNum,
pageSize,
total,
isLoading,
dataList,
onPageNumChange,
onPageSizeChange,
confirmSearch,
search,
showDetail
}
},
})
</script>
\ No newline at end of file \ No newline at end of file
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!