Skip to content
Toggle navigation
Projects
Groups
Snippets
Help
Toggle navigation
This project
Loading...
Sign in
罗鑫霖
/
vion-tools
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit b4bfa343
authored
May 24, 2023
by
李君
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
匹配精度
1 parent
ef981a17
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
1856 additions
and
9 deletions
public/config.js
src/Request/PublicAxiosInstance.js
src/router/index.js
src/views/FeatureMatchingAccuracy/FeatureMatchingAccuracy.vue
src/views/FeatureMatchingAccuracy/FeatureMatchingAccuracyApi.js
src/views/FeatureMatchingAccuracy/addPerson.vue
src/views/FeatureMatchingAccuracy/editPerson.vue
src/views/FeatureMatchingAccuracy/hitDetailDialog.vue
src/views/Main/Main.vue
vue.config.js
public/config.js
View file @
b4bfa34
window
.
_serverHost
=
[
'localhost'
,
'192.168.1.
165'
].
includes
(
window
.
location
.
hostname
)
?
'36.112.68.214:33333
'
:
window
.
location
.
host
window
.
_baseUrl
=
[
'localhost'
,
'192.168.1.
165'
].
includes
(
window
.
location
.
hostname
)
?
'http://36.112.68.214:33333
/btool/'
:
`https://
${
window
.
_serverHost
}
/btool/`
window
.
_baseImgUrl
=
[
'localhost'
,
'192.168.1.
39'
].
includes
(
window
.
location
.
hostname
)
?
'https://store
.keliuyun.com/images/'
:
`
${
window
.
location
.
origin
}
/images/`
window
.
_socketUrl
=
[
'localhost'
,
'192.168.1.
165
'
].
includes
(
window
.
location
.
hostname
)
?
`wss://
${
window
.
_serverHost
}
/`
:
`wss://
${
window
.
_serverHost
}
/`
window
.
_serverHost
=
[
'localhost'
,
'192.168.1.
28'
].
includes
(
window
.
location
.
hostname
)
?
'https://mall.keliuyun.com
'
:
window
.
location
.
host
window
.
_baseUrl
=
[
'localhost'
,
'192.168.1.
28'
].
includes
(
window
.
location
.
hostname
)
?
'https://mall.keliuyun.com
/btool/'
:
`https://
${
window
.
_serverHost
}
/btool/`
window
.
_baseImgUrl
=
[
'localhost'
,
'192.168.1.
28'
].
includes
(
window
.
location
.
hostname
)
?
'https://mall
.keliuyun.com/images/'
:
`
${
window
.
location
.
origin
}
/images/`
window
.
_socketUrl
=
[
'localhost'
,
'192.168.1.
28
'
].
includes
(
window
.
location
.
hostname
)
?
`wss://
${
window
.
_serverHost
}
/`
:
`wss://
${
window
.
_serverHost
}
/`
const
log
=
console
.
log
.
bind
(
console
)
src/Request/PublicAxiosInstance.js
View file @
b4bfa34
...
...
@@ -14,14 +14,14 @@ const axiosInstance = axios.create(
// 请求拦截器
axiosInstance
.
interceptors
.
request
.
use
(
config
=>
{
// Cookies.set('atoken','
d697b325-3a0d-4364-b851-a27d8b6e2a1e
')
// Cookies.set('atoken','
57ac28e0-c2d9-4287-8d20-bc0332372dad
')
if
(
!
Cookies
.
get
(
'atoken'
)){
ElMessage
({
message
:
`登录过期,请重新登录`
,
type
:
'warning'
})
setTimeout
(()
=>
{
let
url
=
[
'localhost'
,
'192.168.1.28'
].
includes
(
window
.
location
.
hostname
)
?
'https://
store
.keliuyun.com/'
:
window
.
location
.
origin
let
url
=
[
'localhost'
,
'192.168.1.28'
].
includes
(
window
.
location
.
hostname
)
?
'https://
mall
.keliuyun.com/'
:
window
.
location
.
origin
// if(url.includes('36.112.68.214')){
// url = 'http://36.112.68.214:33333/'
// }
...
...
@@ -45,7 +45,7 @@ axiosInstance.interceptors.response.use(
type
:
'warning'
})
setTimeout
(()
=>
{
let
url
=
[
'localhost'
,
'192.168.1.28'
].
includes
(
window
.
location
.
hostname
)
?
'https://
store
.keliuyun.com/'
:
window
.
location
.
origin
let
url
=
[
'localhost'
,
'192.168.1.28'
].
includes
(
window
.
location
.
hostname
)
?
'https://
mall
.keliuyun.com/'
:
window
.
location
.
origin
// if(url.includes('36.112.68.214')){
// url = 'http://36.112.68.214:33333/'
// }
...
...
src/router/index.js
View file @
b4bfa34
...
...
@@ -61,6 +61,10 @@ const menuRoute = [
path
:
'equipmentDataRetransmission'
,
component
:
()
=>
import
(
"@/views/equipmentDataRetransmission/equipmentDataRetransmission.vue"
),
},
{
path
:
'FeatureMatchingAccuracy'
,
component
:
()
=>
import
(
"@/views/FeatureMatchingAccuracy/FeatureMatchingAccuracy.vue"
)
},
]
},
]
...
...
src/views/FeatureMatchingAccuracy/FeatureMatchingAccuracy.vue
0 → 100644
View file @
b4bfa34
<
template
>
<div
class=
"containter"
>
<el-row
class=
"contentBox"
v-loading=
"isLoading"
>
<el-col
:span=
"7"
class=
"box boxLeft"
>
<a-form
:model=
"queryForm"
layout=
"inline"
:label-col=
"
{ style: { width: '70px' } }">
<a-form-item
label=
"集团:"
>
<a-select
v-model:value=
"queryForm.account_id"
style=
"width: 150px"
:options=
"accountList"
@
change=
"onAccountChange"
optionFilterProp=
"label"
show-search
>
</a-select>
</a-form-item>
<a-form-item
label=
"广场:"
>
<a-select
v-model:value=
"queryForm.plaza_id"
style=
"width: 150px"
:options=
"plazaList"
@
change=
"onMallChange"
optionFilterProp=
"label"
show-search
>
</a-select>
</a-form-item>
</a-form>
<div
class=
"btns"
>
<a-button
type=
"primary"
@
click=
"confirmSearch"
class=
"btn"
>
搜索
</a-button>
<a-button
type=
"primary"
@
click=
"addPersonFun"
class=
"btn"
>
新增注册人员
</a-button>
<!--
<a-button
type=
"primary"
@
click=
"confirmSearch"
class=
"btn"
>
预览报告
</a-button>
-->
</div>
<el-table
:data=
"resultList"
@
row-click=
'clickRow'
:highlight-current-row=
'true'
:rowKey=
"id"
:height=
"contentHeight"
style=
"width: 100%"
>
<el-table-column
type=
"index"
align=
"center"
label=
"序号"
width=
"80"
>
<template
#
default=
"scope"
>
<span
v-text=
"getIndex(scope.$index)"
>
</span>
</
template
>
</el-table-column>
<el-table-column
prop=
"name"
align=
"center"
label=
"姓名"
>
</el-table-column>
<el-table-column
prop=
"regCount"
align=
"center"
label=
"注册图片数量"
>
</el-table-column>
<el-table-column
prop=
"hitCount"
align=
"center"
label=
"命中目标数量"
>
</el-table-column>
<el-table-column
prop=
"content"
align=
"center"
label=
"操作"
width=
"150"
>
<
template
#
default=
"scope"
>
<el-button
@
click
.
stop
@
click=
"editRow(scope.row)"
type=
"text"
size=
"small"
class=
"tab-btn"
>
编辑
</el-button>
<el-button
@
click
.
stop
@
click=
"deleteRow(scope.row)"
type=
"text"
size=
"small"
class=
"tab-btn"
>
删除
</el-button>
<el-button
@
click
.
stop
@
click=
"hitDetail(scope.row)"
type=
"text"
size=
"small"
class=
"tab-btn"
>
命中详情
</el-button>
</
template
>
</el-table-column>
</el-table>
<a-pagination
v-model:current=
"pageNum"
v-model:pageSize=
"pageSize"
:total=
"total"
:show-total=
"total => `共 ${total} 条`"
:pageSizeOptions=
"['10', '20', '50']"
@
change=
"onPageNumChange"
@
showSizeChange=
"onPageSizeChange"
show-size-changer
show-quick-jumper
style=
"text-align:center"
/>
</el-col>
<el-col
:span=
"17"
class=
"box boxRight"
>
<div
style=
"margin-bottom: 10px;min-height:350px"
>
<a-tabs
type=
"card"
v-model:activeKey=
"activeKey"
>
<a-tab-pane
key=
"1"
tab=
"注册样本"
class=
"regBox"
>
<div>
注册样本图:{{regPictureList.length}}
</div>
<el-row
:gutter=
"10"
>
<el-col
:span=
"3"
v-for=
"item in regPictureList"
>
<div
style=
"cursor: pointer;"
class=
'hitBox'
@
click=
"clickPicture(item)"
:class=
"currentId==item.id?'active':''"
>
<el-image
:src=
"item.picture_url"
:fit=
"'fill'"
class=
"single-image"
>
</el-image>
<span
class=
"el-icon-delete delHitPic"
@
click
.
stop
@
click=
"delSamplePic(item)"
></span>
</div>
</el-col>
</el-row>
</a-tab-pane>
<a-tab-pane
key=
"2"
tab=
"命中目标"
class=
"regBox"
>
<p>
命中目标图:{{hitPictureList.length}}
</p>
<el-row
:gutter=
"10"
>
<el-col
:span=
"3"
v-for=
"item in hitPictureList"
>
<div
style=
"cursor: pointer;"
class=
'hitBox'
@
click=
"clickPicture(item)"
:class=
"currentId==item.id?'active':''"
>
<el-image
:src=
"item.picture_url"
:fit=
"'fill'"
class=
"single-image"
>
</el-image>
<span
class=
"el-icon-delete delHitPic"
@
click
.
stop
@
click=
"delHitPic(item)"
></span>
</div>
</el-col>
</el-row>
</a-tab-pane>
</a-tabs>
</div>
<a-form
:model=
"hitSearchObj"
layout=
"inline"
:label-col=
"{ style: { width: 'auto' } }"
>
<a-form-item
label=
"监控点:"
class=
"secondCondition"
>
<a-select
v-model:value=
"hitSearchObj.gate_id"
style=
"width: 250px"
mode=
"multiple"
:maxTagCount=
"1"
:options=
"gateList"
optionFilterProp=
"label"
show-search
>
</a-select>
</a-form-item>
<a-form-item
label=
"方向:"
class=
"secondCondition"
>
<a-select
v-model:value=
"hitSearchObj.direction"
mode=
"multiple"
:maxTagCount=
"1"
style=
"width: 125px"
>
<a-select-option
:value=
"1"
>
进
</a-select-option>
<a-select-option
:value=
"-1"
>
出
</a-select-option>
</a-select>
</a-form-item>
<a-form-item
label=
"分数:"
class=
"secondCondition"
>
<a-input
v-model:value=
"hitSearchObj.score"
style=
"width: 50px;"
></a-input>
</a-form-item>
<a-form-item
label=
"选择日期:"
class=
"secondCondition"
>
<a-date-picker
v-model:value=
"hitSearchObj.date"
:format=
"'YYYY-MM-DD'"
style=
"width: 110px"
/>
</a-form-item>
<a-form-item
label=
"选择时间:"
class=
"secondCondition"
>
<a-time-picker
v-model:value=
"hitSearchObj.startTime"
style=
"width: 90px"
/>
<a-time-picker
v-model:value=
"hitSearchObj.endTime"
style=
"width: 90px"
/>
</a-form-item>
<a-form-item
class=
"secondCondition"
>
<a-button
type=
"primary"
style=
"margin-right: 5px;"
@
click=
"searchPicture"
>
查询
</a-button>
<a-button
type=
"primary"
@
click=
"checkPicture"
>
选中
</a-button>
</a-form-item>
</a-form>
<div
class=
"identifyResult"
>
<div>
识别结果:{{identifyResultList.length}}
</div>
<el-row
:gutter=
"10"
class=
"identifyResultTable"
:style=
"{height:contentHeight-340+'px'}"
>
<el-col
:span=
"3"
v-for=
"item in identifyResultList"
>
<div
class=
"pictureBox"
>
<el-image
:src=
"item.picture_url"
:fit=
"'fill'"
class=
"single-image"
>
</el-image>
<el-checkbox
class=
"checkBox"
v-model=
"item.checked"
></el-checkbox>
<span
class=
"score"
>
{{item.featureNum}}
</span>
<span
class=
"text"
@
click=
"clickPicture(item)"
>
<span
class=
"el-icon-picture-outline iconPic"
></span>
</span>
</div>
</el-col>
</el-row>
<a-pagination
v-model:current=
"pageNum_identify"
v-model:pageSize=
"pageSize_identify"
:total=
"total_identify"
:show-total=
"total => `共 ${total_identify} 条`"
:pageSizeOptions=
"['16', '32', '64']"
@
change=
"onPageNumChange_identify"
@
showSizeChange=
"onPageSizeChange_identify"
show-size-changer
show-quick-jumper
style=
"text-align:center"
/>
</div>
</el-col>
</el-row>
<addPersonConfig
ref=
"addPersonConfigRef"
@
refreshParentTable =
'confirmSearch'
></addPersonConfig>
<editPersonConfig
ref=
"editPersonConfigRef"
@
refreshParentTable =
'confirmSearch'
></editPersonConfig>
<hitDetailDialog
ref=
"hitDetailDialogRef"
@
refreshParentTable =
'confirmSearch'
></hitDetailDialog>
</div>
</template>
<
script
>
import
{
reactive
,
ref
,
toRaw
}
from
'vue'
import
moment
from
'moment'
import
snapshotRecordApi
from
'@/views/SnapshotCluster/SnapshotRecord/SnapshotRecordApi'
import
{
isArray
}
from
'@/PublicUtil/Judgment'
import
{
filterEmptyValueInObject
,
formatDate
,
formatTime
}
from
'@/PublicUtil/PublicUtil'
import
FeatureMatchingAccuracyApi
from
'@/views/FeatureMatchingAccuracy/FeatureMatchingAccuracyApi'
import
{
PlusOutlined
}
from
'@ant-design/icons-vue'
import
addPersonConfig
from
'./addPerson.vue'
import
editPersonConfig
from
'./editPerson.vue'
import
hitDetailDialog
from
'./hitDetailDialog.vue'
import
{
ElMessage
,
ElMessageBox
}
from
'element-plus'
export
default
{
components
:{
addPersonConfig
,
editPersonConfig
,
hitDetailDialog
},
setup
()
{
const
accountList
=
ref
([])
const
plazaList
=
ref
([])
const
queryForm
=
reactive
({
account_id
:
''
,
plaza_id
:
''
,
})
const
hitSearchObj
=
reactive
({
gate_id
:
[],
score
:
75
,
direction
:
[
1
,
-
1
],
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
onAccountChange
=
function
()
{
getPlazaList
()
}
const
getPlazaList
=
function
()
{
queryForm
.
plaza_id
=
''
plazaList
.
value
=
[]
snapshotRecordApi
.
getPlazaList
({
account_id
:
queryForm
.
account_id
}).
then
(
(
r
)
=>
{
if
(
isArray
(
r
))
{
for
(
const
item
of
r
)
{
plazaList
.
value
.
push
({
value
:
item
.
id
,
label
:
item
.
name
,
})
}
queryForm
.
plaza_id
=
r
[
0
].
id
getGateList
()
confirmSearch
()
}
}
)
}
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
,
})
}
queryForm
.
account_id
=
r
[
0
].
id
getPlazaList
()
}
}
)
}
const
onMallChange
=
function
(){
getGateList
()
}
const
gateList
=
ref
([])
const
getGateList
=
function
()
{
hitSearchObj
.
gate_id
=
[]
gateList
.
value
=
[]
snapshotRecordApi
.
getGateList
(
{
account_id
:
queryForm
.
account_id
,
plaza_id
:
queryForm
.
plaza_id
,
type
:
0
,
}
).
then
(
(
r
)
=>
{
if
(
isArray
(
r
.
data
))
{
for
(
const
item
of
r
.
data
)
{
gateList
.
value
.
push
(
{
value
:
item
.
id
,
label
:
item
.
name
,
}
)
}
}
}
)
}
const
resultList
=
ref
([])
const
confirmSearch
=
function
()
{
pageNum
.
value
=
1
;
getTableData
()
}
const
getTableData
=
function
(){
resultList
.
value
=
[]
const
data
=
filterEmptyValueInObject
(
{
pageNum
:
pageNum
.
value
-
1
,
pageSize
:
pageSize
.
value
,
accountId
:
queryForm
.
account_id
,
mallId
:
queryForm
.
plaza_id
}
)
FeatureMatchingAccuracyApi
.
getMatch
(
data
).
then
(
(
r
)
=>
{
if
(
r
.
msg_code
==
200
){
resultList
.
value
=
r
.
data
.
records
;
total
.
value
=
r
.
data
.
total
;
}
}
)
}
const
onPageNumChange
=
function
(
num
)
{
pageNum
.
value
=
num
confirmSearch
()
}
const
onPageSizeChange
=
function
(
current
,
size
)
{
pageNum
.
value
=
1
pageSize
.
value
=
size
confirmSearch
()
}
const
isLoading
=
ref
(
false
)
const
pageNum
=
ref
(
1
)
const
pageSize
=
ref
(
10
)
const
total
=
ref
()
const
contentHeight
=
ref
(
0
)
const
addPersonConfigRef
=
ref
();
const
addPersonFun
=
function
(){
addPersonConfigRef
.
value
.
initDialog
({
account_id
:
queryForm
.
account_id
,
plaza_id
:
queryForm
.
plaza_id
,
});
}
const
editPersonConfigRef
=
ref
();
const
editRow
=
function
(
row
){
FeatureMatchingAccuracyApi
.
getMatchOne
(
row
).
then
(
(
r
)
=>
{
if
(
r
.
msg_code
==
200
){
editPersonConfigRef
.
value
.
initDialog
(
r
.
data
);
}
else
{
ElMessage
({
message
:
r
.
msg_info
,
type
:
'error'
})
return
false
;
}
}
)
}
const
deleteRow
=
function
(
row
){
ElMessageBox
.
confirm
(
'此操作将永久删除该文件, 是否继续?'
,
'提示'
,
{
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
,
}).
then
(()
=>
{
isLoading
.
value
=
true
;
FeatureMatchingAccuracyApi
.
delMatch
(
row
).
then
(
(
r
)
=>
{
isLoading
.
value
=
false
;
if
(
r
.
msg_code
==
200
){
ElMessage
({
message
:
r
.
msg_info
,
type
:
'success'
})
confirmSearch
()
}
else
{
ElMessage
({
message
:
r
.
msg_info
,
type
:
'error'
})
return
false
;
}
}
)
})
}
const
hitDetailDialogRef
=
ref
()
const
hitDetail
=
function
(
row
){
const
data
=
filterEmptyValueInObject
(
{
accountId
:
row
.
accountId
,
mallId
:
row
.
mallId
,
id
:
row
.
id
}
)
FeatureMatchingAccuracyApi
.
getMatchHitDetail
(
data
).
then
(
(
r
)
=>
{
if
(
r
.
msg_code
==
200
){
let
checkPersonId
=
''
r
.
data
.
forEach
(
item
=>
{
if
(
item
.
personId
==
row
.
personUnid
){
checkPersonId
=
item
.
personId
;
}
item
.
expand
=
false
;
item
.
records
.
forEach
(
record
=>
{
record
.
picture_url
=
window
.
_baseImgUrl
+
'picture/'
+
record
.
bodyPath
+
record
.
bodyPic
})
})
hitDetailDialogRef
.
value
.
initDialog
({
regId
:
row
.
id
,
data
:
r
.
data
,
checkPersonId
:
checkPersonId
})
}
}
)
}
// 注册样本图
const
regPictureList
=
ref
([])
const
hitPictureList
=
ref
([])
const
regPersonId
=
ref
()
const
redPersonObj
=
ref
({})
const
clickRow
=
function
(
row
){
isLoading
.
value
=
true
;
redPersonObj
.
value
=
row
;
regPersonId
.
value
=
row
.
id
;
regPictureList
.
value
=
[]
hitPictureList
.
value
=
[]
FeatureMatchingAccuracyApi
.
getMatchOne
(
row
).
then
(
(
r
)
=>
{
isLoading
.
value
=
false
;
if
(
r
.
msg_code
==
200
){
r
.
data
.
faceList
.
forEach
(
item
=>
{
item
.
picture_url
=
window
.
_baseImgUrl
+
'picture/'
+
item
.
bodyPath
+
item
.
bodyPic
})
regPictureList
.
value
=
r
.
data
.
faceList
r
.
data
.
hitList
.
forEach
(
item
=>
{
item
.
picture_url
=
window
.
_baseImgUrl
+
'picture/'
+
item
.
bodyPath
+
item
.
bodyPic
})
hitPictureList
.
value
=
r
.
data
.
hitList
}
}
)
}
// 识别结果
const
identifyResultList
=
ref
([])
const
pageNum_identify
=
ref
(
1
)
const
pageSize_identify
=
ref
(
10
)
const
total_identify
=
ref
(
0
)
const
onPageNumChange_identify
=
function
(
num
)
{
pageNum_identify
.
value
=
num
clickPicture
()
}
const
onPageSizeChange_identify
=
function
(
current
,
size
)
{
pageNum_identify
.
value
=
1
pageSize_identify
.
value
=
size
clickPicture
()
}
const
currentId
=
ref
()
const
clickPicture
=
function
(
row
){
const
rawData
=
toRaw
(
hitSearchObj
)
// if(rawData.gate_id.length<1){
// ElMessage({
// message: '请选择监控点',
// type: 'warning'
// })
// return false;
// }
currentId
.
value
=
row
.
id
isLoading
.
value
=
true
;
let
data
=
filterEmptyValueInObject
({
accountId
:
queryForm
.
account_id
,
mallId
:
queryForm
.
plaza_id
,
gateId
:
rawData
.
gate_id
.
toString
(),
score
:
rawData
.
score
,
direction
:
rawData
.
direction
.
toString
(),
startTime
:
formatDate
(
rawData
.
date
)
+
' '
+
formatTime
(
rawData
.
startTime
),
endTime
:
formatDate
(
rawData
.
date
)
+
' '
+
formatTime
(
rawData
.
endTime
),
faceId
:
currentId
.
value
,
page
:
pageNum_identify
.
value
-
1
,
pageSize
:
pageSize_identify
.
value
,
regId
:
regPersonId
.
value
})
FeatureMatchingAccuracyApi
.
getSearchByPic
(
data
).
then
(
(
r
)
=>
{
isLoading
.
value
=
false
;
if
(
r
.
msg_code
==
200
){
console
.
log
(
r
.
data
.
records
)
r
.
data
.
records
.
forEach
(
item
=>
{
item
.
checked
=
false
;
item
.
featureNum
=
item
.
featureNum
.
toFixed
(
2
)
item
.
picture_url
=
window
.
_baseImgUrl
+
'picture/'
+
item
.
picture_path
+
item
.
picture_url
})
identifyResultList
.
value
=
r
.
data
.
records
total_identify
.
value
=
r
.
data
.
total
}
}
)
}
const
searchPicture
=
function
(){
if
(
!
currentId
.
value
){
ElMessage
({
message
:
'请选择样本图'
,
type
:
'warning'
})
return
false
;
}
clickPicture
({
id
:
currentId
.
value
})
}
// 选中命中目标
const
checkPicture
=
function
(){
let
checkList
=
[]
identifyResultList
.
value
.
forEach
(
item
=>
{
if
(
item
.
checked
==
true
){
checkList
.
push
(
item
.
id
)
}
})
if
(
checkList
.
length
<
1
){
ElMessage
({
message
:
'请选择识别结果图片'
,
type
:
'warning'
})
return
false
;
}
if
(
!
regPersonId
.
value
){
ElMessage
({
message
:
'请选择注册人员'
,
type
:
'warning'
})
return
false
;
}
isLoading
.
value
=
true
;
FeatureMatchingAccuracyApi
.
addMatchHit
({
id
:
regPersonId
.
value
,
faceIds
:
checkList
}).
then
(
(
r
)
=>
{
isLoading
.
value
=
false
;
if
(
r
.
msg_code
==
200
){
ElMessage
({
message
:
r
.
msg_info
,
type
:
'success'
})
getTableData
()
clickRow
(
redPersonObj
.
value
)
searchPicture
()
}
}
)
}
// 删除命中目标图片
const
delHitPic
=
function
(
row
){
FeatureMatchingAccuracyApi
.
delMatchHit
({
regId
:
regPersonId
.
value
,
faceId
:
row
.
id
}).
then
(
(
r
)
=>
{
isLoading
.
value
=
false
;
if
(
r
.
msg_code
==
200
){
ElMessage
({
message
:
r
.
msg_info
,
type
:
'success'
})
getTableData
()
clickRow
(
redPersonObj
.
value
)
searchPicture
()
}
}
)
}
// 删除样本图片
const
delSamplePic
=
function
(
row
){
FeatureMatchingAccuracyApi
.
delMatchSample
({
regId
:
regPersonId
.
value
,
faceId
:
row
.
id
}).
then
(
(
r
)
=>
{
isLoading
.
value
=
false
;
if
(
r
.
msg_code
==
200
){
ElMessage
({
message
:
r
.
msg_info
,
type
:
'success'
})
getTableData
()
clickRow
(
redPersonObj
.
value
)
}
}
)
}
const
getIndex
=
function
(
val
)
{
return
(
pageNum
.
value
-
1
)
*
pageSize
.
value
+
val
+
1
}
const
__main
=
function
()
{
contentHeight
.
value
=
window
.
innerHeight
-
200
getAccountList
()
}
__main
()
return
{
// sequence
isLoading
,
pageNum
,
pageSize
,
total
,
contentHeight
,
accountList
,
plazaList
,
resultList
,
addPersonConfigRef
,
editPersonConfigRef
,
hitSearchObj
,
gateList
,
activeKey
:
ref
(
'1'
),
regPictureList
,
pageNum_identify
,
pageSize_identify
,
total_identify
,
identifyResultList
,
currentId
,
hitPictureList
,
hitDetailDialogRef
,
// mapping
queryForm
,
onAccountChange
,
confirmSearch
,
onPageNumChange
,
onPageSizeChange
,
addPersonFun
,
getIndex
,
editRow
,
deleteRow
,
onMallChange
,
clickRow
,
searchPicture
,
clickPicture
,
onPageNumChange_identify
,
onPageSizeChange_identify
,
checkPicture
,
delHitPic
,
hitDetail
,
delSamplePic
}
}
}
</
script
>
<
style
lang=
"less"
scoped
>
.active
{
border
:
2px
solid
#40a9ff
}
.regBox
{
height
:
300px
;
overflow-y
:
auto
;
overflow-x
:
hidden
;
}
.hitBox
{
position
:
relative
;
}
.delHitPic
{
position
:
absolute
;
right
:
0
;
top
:
0
;
color
:
#1890ff
;
font-size
:
28px
;
}
.secondCondition
{
margin-right
:
5px
!important
;
}
.identifyResultTable
{
overflow-y
:
auto
;
}
.pictureBox
{
position
:
relative
;
cursor
:
pointer
;
}
.checkBox
{
position
:
absolute
;
left
:
1px
;
top
:
0
;
}
.score
{
position
:
absolute
;
left
:
50px
;
top
:
0
;
color
:
red
;
font-weight
:
900
;
}
.iconPic
{
position
:
absolute
;
right
:
0px
;
top
:
0px
;
color
:
#1890ff
;
font-size
:
28px
;
}
.single-image
{
width
:
100%
;
height
:
200px
;
}
.containter
{
height
:
100%
;
}
.contentBox
{
height
:
100%
;
}
.box
{
height
:
100%
;
}
.boxRight
{
border-left
:
5px
solid
#ccc
;
padding-left
:
5px
;
}
.btns
{
text-align
:
right
;
margin-top
:
10px
;
margin-right
:
15px
;
}
.btn
{
margin-left
:
10px
;
}
</
style
>
src/views/FeatureMatchingAccuracy/FeatureMatchingAccuracyApi.js
0 → 100644
View file @
b4bfa34
import
axiosInstance
from
"@/Request/PublicAxiosInstance"
import
{
filterEmptyValueInObject
}
from
"@/PublicUtil/PublicUtil"
class
FeatureMatchingAccuracy
{
addMatch
(
data
)
{
return
axiosInstance
.
request
(
{
method
:
'POST'
,
url
:
`/feature/match`
,
data
:
data
}
)
}
getMatchOne
(
data
)
{
return
axiosInstance
.
request
(
{
method
:
'GET'
,
url
:
`/feature/match/
${
data
.
id
}
`
,
}
)
}
editMatch
(
data
)
{
return
axiosInstance
.
request
(
{
method
:
'PUT'
,
url
:
`/feature/match`
,
data
:
data
}
)
}
delMatch
(
data
){
return
axiosInstance
.
request
(
{
method
:
'DELETE'
,
url
:
`/feature/match/
${
data
.
id
}
`
,
}
)
}
getMatch
(
data
)
{
return
axiosInstance
.
request
(
{
method
:
'GET'
,
url
:
`/feature/match`
,
params
:
data
}
)
}
getSearchByPic
(
data
){
return
axiosInstance
.
request
(
{
method
:
'GET'
,
url
:
`/feature/match/searchByPic`
,
params
:
data
}
)
}
addMatchHit
(
data
)
{
return
axiosInstance
.
request
(
{
method
:
'POST'
,
url
:
`/feature/match/hit`
,
data
:
data
}
)
}
delMatchHit
(
data
){
return
axiosInstance
.
request
(
{
method
:
'DELETE'
,
url
:
`/feature/match/hit/
${
data
.
regId
}
/
${
data
.
faceId
}
`
,
}
)
}
getMatchHitDetail
(
data
){
return
axiosInstance
.
request
(
{
method
:
'GET'
,
url
:
`/feature/match/hitDetail/
${
data
.
id
}
`
,
params
:
data
}
)
}
getMatchHit
(
data
){
return
axiosInstance
.
request
(
{
method
:
'GET'
,
url
:
`/feature/match/
${
data
.
id
}
/
${
data
.
personUnid
}
`
,
}
)
}
delMatchSample
(
data
){
return
axiosInstance
.
request
(
{
method
:
'DELETE'
,
url
:
`/feature/match/
${
data
.
regId
}
/
${
data
.
faceId
}
`
,
}
)
}
}
const
FeatureMatchingAccuracyApi
=
new
FeatureMatchingAccuracy
()
export
default
FeatureMatchingAccuracyApi
src/views/FeatureMatchingAccuracy/addPerson.vue
0 → 100644
View file @
b4bfa34
<
template
>
<a-modal
title=
"新增注册人员"
v-if=
"isVisible"
v-model:visible=
"isVisible"
width=
"1500px"
:dialog-style=
"
{ top: '20px',height:'90%' }"
class="detail-modal"
>
<div
style=
"height: 700px;"
>
<a-form
:model=
"formObj"
layout=
"inline"
:label-col=
"
{ style: { width: '100px' } }">
<a-form-item
label=
"姓名:"
>
<a-input
v-model:value=
"formObj.name"
style=
"width: 500px"
>
</a-input>
</a-form-item>
<a-form-item
label=
"描述:"
>
<a-input
v-model:value=
"formObj.dec"
style=
"width: 500px"
>
</a-input>
</a-form-item>
<a-form-item
label=
"选择样本图:"
class=
"pictures"
>
<a-tabs
type=
"card"
v-model:activeKey=
"activeKey"
>
<a-tab-pane
key=
"1"
tab=
"本地上传"
>
<a-upload
:file-list=
"fileList"
:remove=
"handleRemove"
:before-upload=
"beforeUpload"
:multiple=
"false"
>
<a-button>
<upload-outlined></upload-outlined>
上传文件
</a-button>
</a-upload>
<a-button
type=
"primary"
:disabled=
"fileList.length === 0"
:loading=
"loading"
style=
"margin-top: 16px"
@
click=
"handleUpload"
>
{{
loading
?
'上传中'
:
'开始上传'
}}
</a-button>
</a-tab-pane>
<a-tab-pane
key=
"2"
tab=
"抓拍记录图"
class=
"resultPic"
>
<a-form-item
label=
"监控点:"
style=
"padding: 5px 0"
class=
"secondCondition"
>
<a-select
v-model:value=
"formObj.gate_id"
style=
"width: 270px"
mode=
"multiple"
:maxTagCount=
"1"
:options=
"gateList"
optionFilterProp=
"label"
show-search
>
</a-select>
</a-form-item>
<a-form-item
label=
"方向:"
style=
"padding: 5px 0"
class=
"secondCondition"
>
<a-select
v-model:value=
"formObj.direction"
mode=
"multiple"
:maxTagCount=
"1"
style=
"width: 200px"
>
<a-select-option
:value=
"1"
>
进
</a-select-option>
<a-select-option
:value=
"-1"
>
出
</a-select-option>
</a-select>
</a-form-item>
<a-form-item
label=
"选择日期:"
style=
"padding: 5px 0"
class=
"secondCondition"
>
<a-date-picker
v-model:value=
"formObj.date"
:format=
"'YYYY-MM-DD'"
style=
"width: 150px"
/>
</a-form-item>
<a-form-item
label=
"选择时间:"
style=
"padding: 5px 0"
class=
"secondCondition"
>
<a-time-picker
v-model:value=
"formObj.startTime"
style=
"width: 100px"
/>
<a-time-picker
v-model:value=
"formObj.endTime"
style=
"width: 100px"
/>
</a-form-item>
<a-form-item
style=
"padding: 5px 0"
class=
"secondCondition"
>
<a-button
type=
"primary"
@
click=
"picSearch"
:loading=
"isLoading"
style=
"margin-right: 10px;"
>
查询
</a-button>
<!--
<a-button
type=
"primary"
@
click=
"clickCheck"
>
选中
</a-button>
-->
</a-form-item>
<div
class=
"resultContent"
:style=
"
{'height':contentHeight+'px'}">
<template
v-for=
"person in dataList"
>
<div
class=
"classBox"
:class=
"person.expand?'expand':''"
>
<div>
<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>
<span
style=
"padding-left: 10px;"
>
人id:
{{
' '
+
person
.
person_unid
}}
图片数量:
{{
person
.
perrsonList
.
length
}}
</span>
</div>
<el-row
v-for=
"row in getPagedList(person.perrsonList, 8)"
>
<el-col
:span=
"3"
v-for=
"item in row"
>
<div
style=
"margin: 0 5px"
class=
"picBox"
>
<el-checkbox
class=
"checkBox"
v-model=
"item.checked"
></el-checkbox>
<el-image
:src=
"item.picture_url"
:fit=
"'fill'"
class=
"single-image"
>
</el-image>
</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"
/>
</a-tab-pane>
</a-tabs>
</a-form-item>
</a-form>
</div>
<
template
#
footer
>
<a-button
@
click=
"onCancel"
>
返回
</a-button>
<a-button
@
click=
"onConfirm"
type=
"primary"
>
确定
</a-button>
</
template
>
</a-modal>
</template>
<
script
>
import
moment
from
'moment'
import
{
reactive
,
ref
,
toRaw
}
from
"vue"
;
import
{
PlusOutlined
,
LoadingOutlined
}
from
'@ant-design/icons-vue'
;
import
{
isArray
}
from
'@/PublicUtil/Judgment'
import
snapshotRecordApi
from
'@/views/SnapshotCluster/SnapshotRecord/SnapshotRecordApi'
import
clusterResultApi
from
'@/views/SnapshotCluster/ClusterResult/ClusterResultApi'
import
FeatureMatchingAccuracyApi
from
'@/views/FeatureMatchingAccuracy/FeatureMatchingAccuracyApi'
import
{
filterEmptyValueInObject
,
formatDate
,
formatTime
,
getPagedList
}
from
'@/PublicUtil/PublicUtil'
import
{
ElMessage
}
from
'element-plus'
export
default
{
components
:
{
LoadingOutlined
,
PlusOutlined
,
},
setup
(
props
,
context
)
{
const
isVisible
=
ref
(
false
);
const
pageNum
=
ref
(
1
)
const
pageSize
=
ref
(
10
)
const
total
=
ref
()
const
dataList
=
ref
([])
// 暂时选中目标,但没提交
const
checkList
=
ref
([])
const
formObj
=
reactive
({
name
:
''
,
dec
:
''
,
gate_id
:
[],
direction
:
[
1
,
-
1
],
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
isLoading
=
ref
(
false
)
const
accountId
=
ref
(
''
);
const
mallId
=
ref
(
''
);
const
gateList
=
ref
([])
const
getGateList
=
function
()
{
formObj
.
gate_id
=
[]
gateList
.
value
=
[]
snapshotRecordApi
.
getGateList
(
{
account_id
:
accountId
.
value
,
plaza_id
:
mallId
.
value
,
type
:
0
,
}
).
then
(
(
r
)
=>
{
if
(
isArray
(
r
.
data
))
{
for
(
const
item
of
r
.
data
)
{
gateList
.
value
.
push
(
{
value
:
item
.
id
,
label
:
item
.
name
,
}
)
}
picSearch
()
}
}
)
}
const
initDialog
=
function
(
parmas
)
{
accountId
.
value
=
parmas
.
account_id
;
mallId
.
value
=
parmas
.
plaza_id
;
formObj
.
name
=
''
;
formObj
.
dec
=
''
;
getGateList
()
isVisible
.
value
=
true
;
};
const
onCancel
=
()
=>
{
dataList
.
value
=
[]
total
.
value
=
0
isVisible
.
value
=
false
;
};
const
refreshParentTable
=
function
(){
context
.
emit
(
'refreshParentTable'
)
}
const
onConfirm
=
function
(){
let
faceIds
=
[]
dataList
.
value
.
forEach
((
itemPerson
)
=>
{
itemPerson
.
perrsonList
.
forEach
((
item
)
=>
{
if
(
item
.
checked
)
{
faceIds
.
push
(
item
.
id
)
}
})
})
if
(
faceIds
.
length
<
1
){
ElMessage
({
message
:
`请选择图片`
,
type
:
'warning'
})
return
false
;
}
const
data
=
filterEmptyValueInObject
(
{
accountId
:
accountId
.
value
,
mallId
:
mallId
.
value
,
name
:
formObj
.
name
,
description
:
formObj
.
dec
,
faceIds
:
faceIds
}
)
FeatureMatchingAccuracyApi
.
addMatch
(
data
).
then
(
(
r
)
=>
{
if
(
r
.
msg_code
==
200
){
ElMessage
({
message
:
r
.
msg_info
,
type
:
'success'
})
refreshParentTable
()
isVisible
.
value
=
false
}
else
{
ElMessage
({
message
:
r
.
msg_info
,
type
:
'error'
})
return
false
;
}
}
)
}
const
loading
=
ref
(
false
);
const
imageUrl
=
ref
(
''
);
const
fileList
=
ref
([]);
const
beforeUpload
=
(
file
)
=>
{
fileList
.
value
=
[
file
];
return
false
;
};
const
handleRemove
=
(
file
)
=>
{
const
index
=
fileList
.
value
.
indexOf
(
file
);
const
newFileList
=
fileList
.
value
.
slice
();
newFileList
.
splice
(
index
,
1
);
fileList
.
value
=
newFileList
;
};
const
handleUpload
=
function
(){
const
formData
=
new
FormData
();
fileList
.
value
.
forEach
((
file
)
=>
{
formData
.
append
(
'files[]'
,
file
);
});
loading
.
value
=
true
;
}
const
sortDataList
=
function
(
list
)
{
list
.
sort
(
(
a
,
b
)
=>
{
return
(
b
.
perrsonList
.
length
-
a
.
perrsonList
.
length
)
}
)
}
const
picSearch
=
function
(){
pageNum
.
value
=
1
clickSearch
()
}
const
clickSearch
=
function
(){
const
rawData
=
toRaw
(
formObj
)
const
data
=
filterEmptyValueInObject
(
{
account_id
:
accountId
.
value
,
type
:
0
,
plaza_id
:
mallId
.
value
,
gate_id
:
rawData
.
gate_id
.
toString
(),
direction
:
rawData
.
direction
.
toString
(),
picType
:
2
,
personType
:
'1, 0,'
,
startTime
:
formatDate
(
rawData
.
date
)
+
' '
+
formatTime
(
rawData
.
startTime
),
endTime
:
formatDate
(
rawData
.
date
)
+
' '
+
formatTime
(
rawData
.
endTime
),
page
:
pageNum
.
value
-
1
,
pageSize
:
pageSize
.
value
,
}
)
clusterResultApi
.
getClusterResultList
(
data
).
then
(
(
r
)
=>
{
isLoading
.
value
=
false
sortDataList
(
r
.
data
.
persons
)
r
.
data
.
persons
.
forEach
((
itemPerson
)
=>
{
itemPerson
.
expand
=
false
itemPerson
.
perrsonList
.
forEach
((
item
)
=>
{
item
.
checked
=
false
;
if
(
item
.
picture_url
)
{
item
.
picture_url
=
window
.
_baseImgUrl
+
item
.
picture_url
}
})
})
dataList
.
value
=
r
.
data
.
persons
total
.
value
=
r
.
data
.
pageNum
document
.
getElementsByClassName
(
'resultContent'
)[
0
].
scrollTop
=
0
}
)
}
const
onPageNumChange
=
function
(
num
)
{
pageNum
.
value
=
num
clickSearch
()
}
const
onPageSizeChange
=
function
(
current
,
size
)
{
pageNum
.
value
=
1
pageSize
.
value
=
size
clickSearch
()
}
const
expandChange
=
function
(
data
){
dataList
.
value
.
forEach
(
item
=>
{
if
(
data
.
person_unid
==
item
.
person_unid
)
{
item
.
expand
=
!
item
.
expand
}
})
}
const
clickCheck
=
function
(){
dataList
.
value
.
forEach
((
itemPerson
)
=>
{
itemPerson
.
perrsonList
.
forEach
((
item
)
=>
{
if
(
item
.
checked
){
checkList
}
})
})
}
return
{
isVisible
,
formObj
,
onCancel
,
onConfirm
,
initDialog
,
activeKey
:
ref
(
'2'
),
beforeUpload
,
loading
,
imageUrl
,
fileList
,
handleUpload
,
handleRemove
,
gateList
,
isLoading
,
clickSearch
,
onPageNumChange
,
onPageSizeChange
,
total
,
dataList
,
pageNum
,
pageSize
,
getPagedList
,
expandChange
,
clickCheck
,
refreshParentTable
,
picSearch
};
},
};
</
script
>
<
style
lang=
"less"
scoped
>
.resultPic
{
border
:
1px
solid
#ddd
;
padding
:
0px
10px
;
}
.pictures
{
width
:
100%
;
margin-top
:
10px
;
}
.secondCondition
{
//
max-width
:
300px
;
display
:
inline-block
;
}
.resultContent
{
overflow
:
auto
;
max-height
:
540px
;
min-height
:
300px
;
margin-bottom
:
10px
;
}
.boxInfo
{
line-height
:
28px
;
margin-bottom
:
5px
;
}
.classBox
{
margin
:
7px
0
;
border
:
solid
1px
black
;
height
:
260px
;
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
;
}
.single-image
{
width
:
100%
;
height
:
220px
;
}
.picBox
{
position
:
relative
;
}
.checkBox
{
position
:
absolute
;
left
:
5px
;
top
:
0
;
}
</
style
>
src/views/FeatureMatchingAccuracy/editPerson.vue
0 → 100644
View file @
b4bfa34
<
template
>
<a-modal
title=
"编辑注册人员"
v-model:visible=
"isVisible"
width=
"1500px"
:dialog-style=
"
{ top: '20px',height:'90%' }"
class="detail-modal"
>
<div
style=
"height: 700px;"
>
<a-form
:model=
"formObj"
layout=
"inline"
:label-col=
"
{ style: { width: '100px' } }">
<a-form-item
label=
"姓名:"
>
<a-input
v-model:value=
"formObj.name"
style=
"width: 500px"
>
</a-input>
</a-form-item>
<a-form-item
label=
"描述:"
>
<a-input
v-model:value=
"formObj.dec"
style=
"width: 500px"
>
</a-input>
</a-form-item>
<a-form-item
label=
"选择样本图:"
class=
"pictures"
>
<a-tabs
type=
"card"
v-model:activeKey=
"activeKey"
>
<a-tab-pane
key=
"1"
tab=
"本地上传"
>
<a-upload
:file-list=
"fileList"
:remove=
"handleRemove"
:before-upload=
"beforeUpload"
:multiple=
"false"
>
<a-button>
<upload-outlined></upload-outlined>
上传文件
</a-button>
</a-upload>
<a-button
type=
"primary"
:disabled=
"fileList.length === 0"
:loading=
"loading"
style=
"margin-top: 16px"
@
click=
"handleUpload"
>
{{
loading
?
'上传中'
:
'开始上传'
}}
</a-button>
</a-tab-pane>
<a-tab-pane
key=
"2"
tab=
"抓拍记录图"
class=
"resultPic"
>
<a-form-item
label=
"监控点:"
style=
"padding: 5px 0"
class=
"secondCondition"
>
<a-select
v-model:value=
"formObj.gate_id"
style=
"width: 270px"
mode=
"multiple"
:maxTagCount=
"1"
:options=
"gateList"
optionFilterProp=
"label"
show-search
>
</a-select>
</a-form-item>
<a-form-item
label=
"方向:"
style=
"padding: 5px 0"
class=
"secondCondition"
>
<a-select
v-model:value=
"formObj.direction"
mode=
"multiple"
:maxTagCount=
"1"
style=
"width: 200px"
>
<a-select-option
:value=
"1"
>
进
</a-select-option>
<a-select-option
:value=
"-1"
>
出
</a-select-option>
</a-select>
</a-form-item>
<a-form-item
label=
"选择日期:"
style=
"padding: 5px 0"
class=
"secondCondition"
>
<a-date-picker
v-model:value=
"formObj.date"
:format=
"'YYYY-MM-DD'"
style=
"width: 150px"
/>
</a-form-item>
<a-form-item
label=
"选择时间:"
style=
"padding: 5px 0"
class=
"secondCondition"
>
<a-time-picker
v-model:value=
"formObj.startTime"
style=
"width: 100px"
/>
<a-time-picker
v-model:value=
"formObj.endTime"
style=
"width: 100px"
/>
</a-form-item>
<a-form-item
style=
"padding: 5px 0"
class=
"secondCondition"
>
<a-button
type=
"primary"
@
click=
"picSearch"
:loading=
"isLoading"
style=
"margin-right: 10px;"
>
查询
</a-button>
<!--
<a-button
type=
"primary"
@
click=
"clickCheck"
>
选中
</a-button>
-->
</a-form-item>
<div
class=
"resultContent"
:style=
"
{'height':contentHeight+'px'}">
<template
v-for=
"person in dataList"
>
<div
class=
"classBox"
:class=
"person.expand?'expand':''"
>
<div>
<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>
<span
style=
"padding-left: 10px;"
>
人id:
{{
' '
+
person
.
person_unid
}}
图片数量:
{{
person
.
perrsonList
.
length
}}
</span>
</div>
<el-row
v-for=
"row in getPagedList(person.perrsonList, 8)"
>
<el-col
:span=
"3"
v-for=
"item in row"
>
<div
style=
"margin: 0 5px"
class=
"picBox"
>
<el-checkbox
class=
"checkBox"
v-model=
"item.checked"
></el-checkbox>
<el-image
:src=
"item.picture_url"
:fit=
"'fill'"
class=
"single-image"
>
</el-image>
</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"
/>
</a-tab-pane>
</a-tabs>
</a-form-item>
</a-form>
</div>
<
template
#
footer
>
<a-button
@
click=
"onCancel"
>
返回
</a-button>
<a-button
@
click=
"onConfirm"
type=
"primary"
>
确定
</a-button>
</
template
>
</a-modal>
</template>
<
script
>
import
moment
from
'moment'
import
{
reactive
,
ref
,
toRaw
}
from
"vue"
;
import
{
PlusOutlined
,
LoadingOutlined
}
from
'@ant-design/icons-vue'
;
import
{
isArray
}
from
'@/PublicUtil/Judgment'
import
snapshotRecordApi
from
'@/views/SnapshotCluster/SnapshotRecord/SnapshotRecordApi'
import
clusterResultApi
from
'@/views/SnapshotCluster/ClusterResult/ClusterResultApi'
import
FeatureMatchingAccuracyApi
from
'@/views/FeatureMatchingAccuracy/FeatureMatchingAccuracyApi'
import
{
filterEmptyValueInObject
,
formatDate
,
formatTime
,
getPagedList
}
from
'@/PublicUtil/PublicUtil'
import
{
ElMessage
}
from
'element-plus'
export
default
{
components
:
{
LoadingOutlined
,
PlusOutlined
,
},
setup
(
props
,
context
)
{
const
isVisible
=
ref
(
false
);
const
pageNum
=
ref
(
1
)
const
pageSize
=
ref
(
10
)
const
total
=
ref
()
const
dataList
=
ref
([])
const
formObj
=
reactive
({
name
:
''
,
dec
:
''
,
gate_id
:
[],
direction
:
[
1
,
-
1
],
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'
),
id
:
''
})
const
isLoading
=
ref
(
false
)
const
accountId
=
ref
(
''
);
const
mallId
=
ref
(
''
);
const
gateList
=
ref
([])
const
checkGateList
=
ref
([])
const
getGateList
=
function
()
{
formObj
.
gate_id
=
[]
gateList
.
value
=
[]
snapshotRecordApi
.
getGateList
(
{
account_id
:
accountId
.
value
,
plaza_id
:
mallId
.
value
,
type
:
0
,
}
).
then
(
(
r
)
=>
{
if
(
isArray
(
r
.
data
))
{
for
(
const
item
of
r
.
data
)
{
gateList
.
value
.
push
(
{
value
:
item
.
id
,
label
:
item
.
name
,
}
)
}
picSearch
()
}
}
)
}
const
initDialog
=
function
(
parmas
)
{
accountId
.
value
=
parmas
.
accountId
;
mallId
.
value
=
parmas
.
mallId
;
formObj
.
name
=
parmas
.
name
;
formObj
.
dec
=
parmas
.
description
;
formObj
.
id
=
parmas
.
id
;
// checkGateList.value = parmas.faceIds
getGateList
()
isVisible
.
value
=
true
;
};
const
onCancel
=
()
=>
{
isVisible
.
value
=
false
;
};
const
refreshParentTable
=
function
(){
context
.
emit
(
'refreshParentTable'
)
}
const
onConfirm
=
function
(){
let
faceIds
=
[]
dataList
.
value
.
forEach
((
itemPerson
)
=>
{
itemPerson
.
perrsonList
.
forEach
((
item
)
=>
{
if
(
item
.
checked
)
{
faceIds
.
push
(
item
.
id
)
}
})
})
if
(
faceIds
.
length
<
1
&&
checkGateList
.
length
<
1
){
ElMessage
({
message
:
`请选择图片`
,
type
:
'warning'
})
return
false
;
}
const
data
=
filterEmptyValueInObject
(
{
// accountId: accountId.value,
// mallId: mallId.value,
name
:
formObj
.
name
,
description
:
formObj
.
dec
,
faceIds
:
faceIds
.
length
<
1
?
checkGateList
.
value
:
faceIds
,
id
:
formObj
.
id
}
)
FeatureMatchingAccuracyApi
.
editMatch
(
data
).
then
(
(
r
)
=>
{
if
(
r
.
msg_code
==
200
){
ElMessage
({
message
:
r
.
msg_info
,
type
:
'success'
})
refreshParentTable
()
isVisible
.
value
=
false
}
else
{
ElMessage
({
message
:
r
.
msg_info
,
type
:
'error'
})
return
false
;
}
}
)
}
const
loading
=
ref
(
false
);
const
imageUrl
=
ref
(
''
);
const
fileList
=
ref
([]);
const
beforeUpload
=
(
file
)
=>
{
fileList
.
value
=
[
file
];
return
false
;
};
const
handleRemove
=
(
file
)
=>
{
const
index
=
fileList
.
value
.
indexOf
(
file
);
const
newFileList
=
fileList
.
value
.
slice
();
newFileList
.
splice
(
index
,
1
);
fileList
.
value
=
newFileList
;
};
const
handleUpload
=
function
(){
const
formData
=
new
FormData
();
fileList
.
value
.
forEach
((
file
)
=>
{
formData
.
append
(
'files[]'
,
file
);
});
loading
.
value
=
true
;
}
const
sortDataList
=
function
(
list
)
{
list
.
sort
(
(
a
,
b
)
=>
{
return
(
b
.
perrsonList
.
length
-
a
.
perrsonList
.
length
)
}
)
}
const
picSearch
=
function
(){
pageNum
.
value
=
1
clickSearch
()
}
const
clickSearch
=
function
(){
const
rawData
=
toRaw
(
formObj
)
const
data
=
filterEmptyValueInObject
(
{
account_id
:
accountId
.
value
,
type
:
0
,
plaza_id
:
mallId
.
value
,
gate_id
:
rawData
.
gate_id
.
toString
(),
direction
:
rawData
.
direction
.
toString
(),
picType
:
2
,
personType
:
'1, 0,'
,
startTime
:
formatDate
(
rawData
.
date
)
+
' '
+
formatTime
(
rawData
.
startTime
),
endTime
:
formatDate
(
rawData
.
date
)
+
' '
+
formatTime
(
rawData
.
endTime
),
page
:
pageNum
.
value
-
1
,
pageSize
:
pageSize
.
value
,
}
)
clusterResultApi
.
getClusterResultList
(
data
).
then
(
(
r
)
=>
{
isLoading
.
value
=
false
sortDataList
(
r
.
data
.
persons
)
r
.
data
.
persons
.
forEach
((
itemPerson
)
=>
{
itemPerson
.
expand
=
false
itemPerson
.
perrsonList
.
forEach
((
item
)
=>
{
if
(
checkGateList
.
value
.
includes
(
item
.
id
)){
item
.
checked
=
true
;
}
else
{
item
.
checked
=
false
;
}
if
(
item
.
picture_url
)
{
item
.
picture_url
=
window
.
_baseImgUrl
+
item
.
picture_url
}
})
})
dataList
.
value
=
r
.
data
.
persons
total
.
value
=
r
.
data
.
pageNum
document
.
getElementsByClassName
(
'resultContent'
)[
0
].
scrollTop
=
0
}
)
}
const
onPageNumChange
=
function
(
num
)
{
pageNum
.
value
=
num
clickSearch
()
}
const
onPageSizeChange
=
function
(
current
,
size
)
{
pageNum
.
value
=
1
pageSize
.
value
=
size
clickSearch
()
}
const
expandChange
=
function
(
data
){
dataList
.
value
.
forEach
(
item
=>
{
if
(
data
.
person_unid
==
item
.
person_unid
)
{
item
.
expand
=
!
item
.
expand
}
})
}
const
clickCheck
=
function
(){
console
.
log
(
dataList
.
value
)
}
return
{
isVisible
,
formObj
,
onCancel
,
onConfirm
,
initDialog
,
activeKey
:
ref
(
'2'
),
beforeUpload
,
loading
,
imageUrl
,
fileList
,
handleUpload
,
handleRemove
,
gateList
,
isLoading
,
clickSearch
,
onPageNumChange
,
onPageSizeChange
,
total
,
dataList
,
pageNum
,
pageSize
,
getPagedList
,
expandChange
,
clickCheck
,
refreshParentTable
,
picSearch
};
},
};
</
script
>
<
style
lang=
"less"
scoped
>
.resultPic
{
border
:
1px
solid
#ddd
;
padding
:
0px
10px
;
}
.pictures
{
width
:
100%
;
margin-top
:
10px
;
}
.secondCondition
{
//
max-width
:
300px
;
display
:
inline-block
;
}
.resultContent
{
overflow
:
auto
;
max-height
:
540px
;
min-height
:
300px
;
margin-bottom
:
10px
;
}
.boxInfo
{
line-height
:
28px
;
margin-bottom
:
5px
;
}
.classBox
{
margin
:
7px
0
;
border
:
solid
1px
black
;
height
:
260px
;
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
;
}
.single-image
{
width
:
100%
;
height
:
220px
;
}
.picBox
{
position
:
relative
;
}
.checkBox
{
position
:
absolute
;
left
:
5px
;
top
:
0
;
}
</
style
>
src/views/FeatureMatchingAccuracy/hitDetailDialog.vue
0 → 100644
View file @
b4bfa34
<
template
>
<a-modal
title=
"命中详情"
v-if=
"isVisible"
v-model:visible=
"isVisible"
width=
"1500px"
:dialog-style=
"
{ top: '20px',height:'90%' }"
class="detail-modal"
>
<div
style=
"height: 700px;overflow-y: auto;"
>
<template
v-for=
"person in hitPersonList"
>
<div
class=
"classBox"
:class=
"person.expand?'expand':''"
>
<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>
人id:
{{
' '
+
person
.
personId
}}
图片数量:
{{
person
.
count
}}
<el-radio
class=
"checkBox"
v-model=
"checked"
:label=
"person.personId"
>
以此为对比项
</el-radio>
</div>
<el-row
:gutter=
"10"
>
<el-col
:span=
"3"
v-for=
"item in person.records"
>
<div>
<el-image
:src=
"item.picture_url"
:fit=
"'fill'"
class=
"single-image"
>
</el-image>
</div>
</el-col>
</el-row>
</div>
</
template
>
</div>
<
template
#
footer
>
<a-button
@
click=
"onCancel"
>
返回
</a-button>
<a-button
@
click=
"onConfirm"
type=
"primary"
>
确定
</a-button>
</
template
>
</a-modal>
</template>
<
script
>
import
moment
from
'moment'
import
{
reactive
,
ref
,
toRaw
}
from
"vue"
;
import
{
isArray
}
from
'@/PublicUtil/Judgment'
import
{
ElMessage
}
from
'element-plus'
import
FeatureMatchingAccuracyApi
from
'@/views/FeatureMatchingAccuracy/FeatureMatchingAccuracyApi'
export
default
{
setup
(
props
,
context
)
{
const
isVisible
=
ref
(
false
);
const
isLoading
=
ref
(
false
)
const
accountId
=
ref
(
''
);
const
mallId
=
ref
(
''
);
const
checked
=
ref
(
''
);
const
hitPersonList
=
ref
([])
const
regId
=
ref
()
const
initDialog
=
function
(
parmas
)
{
regId
.
value
=
parmas
.
regId
hitPersonList
.
value
=
parmas
.
data
checked
.
value
=
parmas
.
checkPersonId
isVisible
.
value
=
true
;
};
const
expandChange
=
function
(
data
){
hitPersonList
.
value
.
forEach
(
item
=>
{
if
(
data
.
personId
==
item
.
personId
)
{
item
.
expand
=
!
item
.
expand
}
})
}
const
refreshParentTable
=
function
(){
context
.
emit
(
'refreshParentTable'
)
}
const
onCancel
=
()
=>
{
isVisible
.
value
=
false
;
};
const
onConfirm
=
function
(){
if
(
!
checked
.
value
){
ElMessage
({
message
:
`请选择对比项`
,
type
:
'warning'
})
return
false
;
}
FeatureMatchingAccuracyApi
.
getMatchHit
({
id
:
regId
.
value
,
personUnid
:
checked
.
value
}).
then
(
(
r
)
=>
{
if
(
r
.
msg_code
==
200
){
ElMessage
({
message
:
`
${
r
.
msg_info
}
`
,
type
:
'success'
})
refreshParentTable
()
isVisible
.
value
=
false
;
}
else
{
ElMessage
({
message
:
`
${
r
.
msg_info
}
`
,
type
:
'error'
})
}
}
)
}
return
{
isVisible
,
onCancel
,
onConfirm
,
initDialog
,
hitPersonList
,
expandChange
,
checked
,
refreshParentTable
};
},
};
</
script
>
<
style
lang=
"less"
scoped
>
.single-image
{
width
:
100%
;
height
:
220px
;
}
.boxInfo
{
line-height
:
28px
;
margin-bottom
:
10px
;
}
.checkBox
{
margin-left
:
15px
;
}
.classBox
{
margin-bottom
:
10px
;
border
:
solid
1px
black
;
height
:
265px
;
overflow
:
hidden
;
padding
:
5px
;
}
.expand
{
height
:
auto
;
overflow-y
:
auto
;
}
.expandWord
{
color
:
#1890ff
;
margin-right
:
5px
;
cursor
:
pointer
;
float
:
right
;
}
.iconExpand
{
cursor
:
pointer
;
float
:
right
;
color
:
#1890ff
;
margin-right
:
20px
;
}
</
style
>
src/views/Main/Main.vue
View file @
b4bfa34
...
...
@@ -103,7 +103,12 @@
<span
style=
"padding: 0 5px"
>
特征匹配
</span>
</div>
</a-menu-item>
<a-menu-item
:key=
"'/Main/FeatureMatchingAccuracy'"
>
<div
class=
"flex-vertical-center"
>
<img
:src=
"require('./Icons/2.svg')"
style=
"height: auto;width:20px"
/>
<span
style=
"padding: 0 5px"
>
特征匹配精度
</span>
</div>
</a-menu-item>
</a-menu>
</el-aside>
<el-main>
...
...
vue.config.js
View file @
b4bfa34
...
...
@@ -58,7 +58,7 @@ module.exports = {
devServer
:
{
proxy
:
{
'/'
:
{
target
:
'http
://36.112.68.214:33333
/btool/'
,
target
:
'http
s://mall.keliuyun.com
/btool/'
,
changeOrigin
:
true
}
}
...
...
Write
Preview
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment