Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
ai-yunshou-vue
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
AI云守
ai-yunshou-vue
Commits
7c50bfac
Commit
7c50bfac
authored
Aug 14, 2024
by
wp song
Browse files
Options
Browse Files
Download
Plain Diff
完成点位管理
parents
cb95ecb1
89befeef
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
214 additions
and
38 deletions
+214
-38
.env.development
.env.development
+3
-0
.env.production
.env.production
+4
-1
.env.staging
.env.staging
+4
-1
src/components/ImagePreview/index.vue
src/components/ImagePreview/index.vue
+2
-2
src/components/ImageUpload/index.vue
src/components/ImageUpload/index.vue
+11
-1
src/utils/webscoket.js
src/utils/webscoket.js
+57
-0
src/views/algorithmControl/components/form.vue
src/views/algorithmControl/components/form.vue
+26
-9
src/views/algorithmList/components/details.vue
src/views/algorithmList/components/details.vue
+44
-21
src/views/algorithmList/components/websockt.js
src/views/algorithmList/components/websockt.js
+53
-0
src/views/algorithmList/index.vue
src/views/algorithmList/index.vue
+4
-3
vite.config.js
vite.config.js
+6
-0
No files found.
.env.development
View file @
7c50bfac
...
...
@@ -6,3 +6,6 @@ VITE_APP_ENV = 'development'
# AI视频分析平台/开发环境
VITE_APP_BASE_API = '/dev-api'
# 图片服务器地址
VITE_IMG_BASE_PATH = 'http://192.168.4.206'
.env.production
View file @
7c50bfac
...
...
@@ -8,4 +8,7 @@ w
VITE_APP_BASE_API = '/ai'
# 是否在打包时开启压缩,支持 gzip 和 brotli
VITE_BUILD_COMPRESS = gzip
\ No newline at end of file
VITE_BUILD_COMPRESS = gzip
# 图片服务器地址
VITE_IMG_BASE_PATH = 'http://192.168.4.206'
\ No newline at end of file
.env.staging
View file @
7c50bfac
...
...
@@ -8,4 +8,7 @@ VITE_APP_ENV = 'staging'
VITE_APP_BASE_API = '/stage-api'
# 是否在打包时开启压缩,支持 gzip 和 brotli
VITE_BUILD_COMPRESS = gzip
\ No newline at end of file
VITE_BUILD_COMPRESS = gzip
# 图片服务器地址
VITE_IMG_BASE_PATH = 'http://192.168.4.206'
\ No newline at end of file
src/components/ImagePreview/index.vue
View file @
7c50bfac
...
...
@@ -40,7 +40,7 @@ const realSrc = computed(() => {
if
(
isExternal
(
real_src
))
{
return
real_src
;
}
return
import
.
meta
.
env
.
VITE_
APP_BASE_API
+
real_src
;
return
import
.
meta
.
env
.
VITE_
IMG_BASE_PATH
+
real_src
;
});
const
realSrcList
=
computed
(()
=>
{
...
...
@@ -53,7 +53,7 @@ const realSrcList = computed(() => {
if
(
isExternal
(
item
))
{
return
srcList
.
push
(
item
);
}
return
srcList
.
push
(
import
.
meta
.
env
.
VITE_
APP_BASE_API
+
item
);
return
srcList
.
push
(
import
.
meta
.
env
.
VITE_
IMG_BASE_PATH
+
item
);
});
return
srcList
;
});
...
...
src/components/ImageUpload/index.vue
View file @
7c50bfac
...
...
@@ -70,6 +70,11 @@ const props = defineProps({
type
:
Boolean
,
default
:
true
},
// 是否显示提示
defaultUrl
:
{
type
:
String
,
default
:
import
.
meta
.
env
.
VITE_APP_BASE_API
},
});
const
{
proxy
}
=
getCurrentInstance
();
...
...
@@ -79,7 +84,10 @@ const uploadList = ref([]);
const
dialogImageUrl
=
ref
(
""
);
const
dialogVisible
=
ref
(
false
);
const
baseUrl
=
'
http://192.168.4.206
'
const
uploadImgUrl
=
ref
(
import
.
meta
.
env
.
VITE_APP_BASE_API
+
"
/common/upload
"
);
// 上传的图片服务器地址
const
uploadImgUrl
=
computed
(
()
=>
props
.
defaultUrl
+
"
/common/upload
"
);
// const uploadImgUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload"); // 上传的图片服务器地址
const
headers
=
ref
({
Authorization
:
"
Bearer
"
+
getToken
()
});
const
fileList
=
ref
([]);
const
showTip
=
computed
(
...
...
@@ -151,6 +159,7 @@ function handleUploadSuccess(res, file) {
if
(
res
.
code
===
200
)
{
uploadList
.
value
.
push
({
name
:
res
.
fileName
,
url
:
res
.
fileName
});
uploadedSuccessfully
();
emit
(
"
update:modelObj
"
,
res
);
}
else
{
number
.
value
--
;
proxy
.
$modal
.
closeLoading
();
...
...
@@ -177,6 +186,7 @@ function uploadedSuccessfully() {
uploadList
.
value
=
[];
number
.
value
=
0
;
emit
(
"
update:modelValue
"
,
listToString
(
fileList
.
value
));
proxy
.
$modal
.
closeLoading
();
}
}
...
...
src/utils/webscoket.js
0 → 100644
View file @
7c50bfac
export
class
WebSocketManager
{
constructor
(
url
,
callback
)
{
this
.
url
=
url
this
.
callback
=
callback
this
.
socket
=
null
this
.
connected
=
false
this
.
error
=
null
}
connect
()
{
if
(
this
.
socket
&&
this
.
socket
.
readyState
===
WebSocket
.
OPEN
)
{
return
}
this
.
socket
=
new
WebSocket
(
this
.
url
);
console
.
log
(
"
🚀 ~ WebSocketClient ~ connect ~ this.url:
"
,
this
.
url
)
// 连接成功
this
.
socket
.
onopen
=
()
=>
{
console
.
log
(
'
WebSocket connected
'
)
this
.
connected
=
true
}
this
.
socket
.
onmessage
=
(
event
)
=>
{
console
.
log
(
'
message
'
,
event
)
this
.
callback
(
event
.
data
)
}
this
.
socket
.
onerror
=
(
event
)
=>
{
console
.
error
(
'
WebSocket error:
'
,
event
)
this
.
error
=
event
}
this
.
socket
.
onclose
=
()
=>
{
console
.
log
(
'
WebSocket closed
'
)
this
.
connected
=
false
}
}
disconnect
()
{
if
(
this
.
socket
)
{
this
.
socket
.
close
()
}
}
sendMessage
(
message
)
{
if
(
this
.
socket
.
readyState
!==
WebSocket
.
OPEN
)
{
return
}
this
.
socket
.
send
(
JSON
.
stringify
(
message
))
}
// sendApiRequest() {
// axios.get(this.apiEndpoint).then(response => {
// // 处理 API 返回数据并发送给服务端
// const data = response.data
// this.sendMessage(data)
// }).catch(error => {
// console.error('API request error:', error)
// })
// }
}
\ No newline at end of file
src/views/algorithmControl/components/form.vue
View file @
7c50bfac
...
...
@@ -109,7 +109,7 @@
</div>
<el-form
ref=
"algRef"
:model=
"form"
:rules=
"rules"
label-width=
"80px"
v-else
>
<el-tabs
v-model=
"activeName"
class=
"demo-tabs"
@
tab-click=
"handleClick"
>
<el-tabs
v-model=
"activeName"
class=
"demo-tabs"
>
<el-tab-pane
label=
"基础信息"
name=
"基础信息"
>
<el-row
:gutter=
"10"
class=
"mb8"
>
<div
class=
"form-title"
style=
"display: flex;justify-content: flex-start;align-items: center;"
>
...
...
@@ -287,9 +287,17 @@
</el-row>
<el-card
class=
"left-list"
>
<el-table
:data=
"boundaryList"
>
<el-table-column
label=
"边界类型"
align=
"center"
prop=
"caseType"
/>
<el-table-column
label=
"边界类型"
align=
"center"
prop=
"caseType"
>
<
template
#default
="
scope
"
>
<dict-tag
:options=
"algorithm_case"
:value=
"scope.row.caseType"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"边界内容"
align=
"center"
prop=
"remark"
/>
<el-table-column
label=
"边界案例图"
align=
"center"
prop=
"caseFile"
/>
<el-table-column
label=
"边界案例图"
align=
"center"
prop=
"caseFile"
>
<
template
#default
="
scope
"
>
<ImagePreview
:src=
"scope.row.caseFile"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"操作"
width=
"180"
align=
"center"
class-name=
"small-padding fixed-width"
>
<
template
#default
="
scope
"
>
<el-button
link
type=
"primary"
icon=
"Edit"
@
click=
"handleBoundaryUpdate(scope.row)"
>
修改
</el-button>
...
...
@@ -359,7 +367,7 @@
<el-row>
<el-col
:span=
"24"
>
<el-form-item
label=
"场景详情"
prop=
"sceneDetail"
>
<el-input
v-model=
"formScene.sceneDetail"
placeholder=
"请输入场景详情"
/>
<el-input
v-model=
"formScene.sceneDetail"
type=
"textarea"
:rows=
"4"
placeholder=
"请输入场景详情"
/>
</el-form-item>
</el-col>
</el-row>
...
...
@@ -382,24 +390,31 @@
<img
src=
"@/assets/images/logo_video.png"
width=
"25px"
alt=
""
>
<span>
{{
titleBoundary
}}
</span>
</div>
</
template
>
<el-form
ref=
"BoundaryRef"
:model=
"formBoundary"
:rules=
"rules"
label-width=
"
8
0px"
>
<el-form
ref=
"BoundaryRef"
:model=
"formBoundary"
:rules=
"rules"
label-width=
"
9
0px"
>
<el-row>
<el-col
:span=
"24"
>
<el-form-item
label=
"边界类型"
prop=
"caseType"
>
<el-input
v-model=
"formBoundary.caseType"
placeholder=
"请输入场景名称"
/>
<el-select
v-model=
"formBoundary.caseType"
placeholder=
"请选择边界类型"
clearable
>
<el-option
v-for=
"disc in algorithm_case"
:key=
"disc.value"
:label=
"disc.label"
:value=
"disc.value"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"24"
>
<el-form-item
label=
"边界内容"
prop=
"remark"
>
<el-input
v-model=
"formBoundary.remark"
placeholder=
"请输入场景详情
"
/>
<el-input
v-model=
"formBoundary.remark"
type=
"textarea"
:rows=
"4"
placeholder=
"请输入边界内容
"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"24"
>
<el-form-item
label=
"
场景图片
"
prop=
"caseFile"
>
<el-form-item
label=
"
边界案例图
"
prop=
"caseFile"
>
<ImageUpload
:modelValue=
"formBoundary.caseFile"
:limit=
'1'
:fileSize=
"5"
@
update:modelValue=
"getBoundaryImageUrl"
/>
</el-form-item>
</el-col>
...
...
@@ -419,7 +434,8 @@ import { addAlg, updateAlg , detailAlg} from "@/api/algorithmList/index.js";
import
{
listScene
,
detailScene
,
addScene
,
updateScene
,
deleteScene
}
from
"
@/api/algorithmList/scene.js
"
;
import
{
listBoundary
,
detailBoundary
,
addBoundary
,
updateBoundary
,
deleteBoundary
}
from
"
@/api/algorithmList/boundary.js
"
;
const
{
proxy
}
=
getCurrentInstance
();
const
{
algorithm_scen
,
sys_job_status
}
=
proxy
.
useDict
(
"
algorithm_scen
"
,
"
sys_job_status
"
);
const
{
algorithm_scen
,
algorithm_case
}
=
proxy
.
useDict
(
"
algorithm_scen
"
,
"
algorithm_case
"
);
console
.
log
(
"
🚀 ~ algorithm_case:
"
,
algorithm_case
)
const
emit
=
defineEmits
();
const
open
=
ref
(
false
);
const
openScene
=
ref
(
false
);
...
...
@@ -429,6 +445,7 @@ const title = ref("");
const
titleScene
=
ref
(
""
);
const
titleBoundary
=
ref
(
""
);
const
activeName
=
ref
(
"
基础信息
"
);
const
postList
=
ref
([]);
const
sceneList
=
ref
([]);
const
boundaryList
=
ref
([]);
const
ids
=
ref
([]);
...
...
src/views/algorithmList/components/details.vue
View file @
7c50bfac
...
...
@@ -11,18 +11,20 @@
<el-card
class=
"right-list"
>
<div
class=
"backcolor"
style=
"height: 350px;width: 100%; padding: 10px;"
>
<div
style=
"width: 500px;"
>
<h2
style=
"font-weight: 700;font-style: normal;font-size: 28px;color: #FFFFFF;"
>
反光衣识算法别
</h2>
<h2
style=
"font-weight: 700;font-style: normal;font-size: 28px;color: #FFFFFF;"
>
{{
form
.
algorithmName
}}
</h2>
<p
style=
"font-weight: 700;font-style: normal;font-size: 17px;color: rgba(255, 255, 255, 0.6);line-height: 21px;"
>
反光衣识别算法基于大规模反光衣服数据识别训练,配合现场摄像头,自动监控如工地矿井、公路环卫、
路政交警等特殊环境下人员是是否穿着反光衣,有效防范因未着反光衣造成的意外伤害事故,高效率监督监管
{{
form
.
cardCopywriting
}}
</p>
</div>
<ImagePreview
:src=
"'http://192.168.4.206/profile/upload/2024/08/05/picStream~1_20240805112450A012.png'
"
/>
<ImagePreview
style=
"width: 400px;height: 225px;"
:src=
"form.cardImg
"
/>
</div>
<div
class=
"form-title"
style=
"display: flex;justify-content: flex-start;align-items: center;"
>
<span>
应用场景
</span>
</div>
<div
class=
"alg-list"
>
<div
v-if=
"applicationList.length==0"
>
暂无数据
</div>
<el-card
v-for=
"item in applicationList"
:key=
"item.name"
class=
"alg-item"
shadow=
"hover"
>
<template
v-slot:default
>
<h2>
{{
item
.
sceneName
}}
</h2>
...
...
@@ -40,20 +42,26 @@
<el-col
:xs=
"4"
:sm=
"4"
:md=
"4"
:lg=
"4"
>
图片上传
<div
class=
"upload-box"
>
<ImageUpload
:
limit=
'1'
:fileSize=
"5"
:isShowTip=
"false
"
/>
<ImageUpload
:
defaultUrl=
"'/upload-api'"
:limit=
'1'
:fileSize=
"5"
:isShowTip=
"false"
@
update:modelObj=
"getImgObj
"
/>
</div>
</el-col>
<el-col
:xs=
"10"
:sm=
"10"
:md=
"10"
:lg=
"10"
>
原始数据
<div
class=
"img-box"
>
<div
class=
"img-box"
v-if=
"nowImg.length==0"
>
<img
src=
"@/assets/images/default.png"
height=
"100%"
/>
</div>
<div
class=
"img-box"
v-else
>
<img
:src=
"nowImg"
height=
"100%"
/>
</div>
</el-col>
<el-col
:xs=
"10"
:sm=
"10"
:md=
"10"
:lg=
"10"
>
算法识别结果
<div
class=
"img-box"
>
<div
class=
"img-box"
v-if=
"outFilePath.length==0"
>
<img
src=
"@/assets/images/default.png"
height=
"100%"
/>
</div>
<div
class=
"img-box"
v-else
>
<img
:src=
"outFilePath"
height=
"100%"
/>
</div>
</el-col>
</el-row>
</div>
...
...
@@ -85,23 +93,18 @@
<
script
setup
name=
"Index"
>
import
{
ArrowDown
}
from
'
@element-plus/icons-vue
'
import
{
Search
}
from
'
@element-plus/icons-vue
'
import
{
detailAlg
}
from
"
@/api/algorithmList/index.js
"
;
import
{
listScene
,
detailScene
}
from
"
@/api/algorithmList/scene.js
"
;
import
{
listBoundary
,
detailBoundary
}
from
"
@/api/algorithmList/boundary.js
"
;
import
{
useWebSockets
}
from
'
./websockt.js
'
;
// 注意文件路径可能需要调整
const
{
handeUpload
,
outFilePath
}
=
useWebSockets
();
const
router
=
useRouter
();
const
route
=
useRoute
()
const
nowImg
=
ref
(
''
)
const
{
roleId
}
=
route
.
params
const
{
proxy
}
=
getCurrentInstance
();
const
algFormRef
=
ref
(
null
)
const
applicationList
=
ref
([
{
sceneName
:
'
智慧校园
'
,
sceneDetail
:
'
将 Sketch 智能化解析输出到我们的平台。如果检测出同一个图片,那么这张图片会被认定为同一张图片。新版本会覆盖之前的版本,可以去图片历史中查看以往历史记录
'
,
},
{
sceneName
:
'
智慧校园
'
,
sceneDetail
:
'
将 Sketch 智能化解析输出到我们的平台。如果检测出同一个图片,那么这张图片会被认定为同一张图片。新版本会覆盖之前的版本,可以去图片历史中查看以往历史记录
'
,
},
{
sceneName
:
'
智慧校园
'
,
sceneDetail
:
'
将 Sketch 智能化解析输出到我们的平台。如果检测出同一个图片,那么这张图片会被认定为同一张图片。新版本会覆盖之前的版本,可以去图片历史中查看以往历史记录
'
,
},
])
const
applicationList
=
ref
([])
const
nowText
=
ref
(
'
算法详情
'
)
const
data
=
reactive
({
form
:
{},
...
...
@@ -118,6 +121,26 @@ const data = reactive({
});
const
{
queryParams
,
form
,
rules
}
=
toRefs
(
data
);
function
getDetials
(){
detailAlg
(
roleId
).
then
(
res
=>
{
console
.
log
(
res
)
form
.
value
=
res
.
data
})
listScene
({
algorithmId
:
roleId
}).
then
(
res
=>
{
console
.
log
(
"
🚀 ~ listScene ~ res:
"
,
res
)
applicationList
.
value
=
res
.
rows
})
listBoundary
({
algorithmId
:
roleId
}).
then
(
res
=>
{
console
.
log
(
"
🚀 ~ listBoundary ~ res:
"
,
res
)
})
}
function
getImgObj
(
obj
){
console
.
log
(
"
🚀 ~ getImgObj ~ obj:
"
,
obj
)
nowImg
.
value
=
obj
.
url
handeUpload
(
obj
)
}
getDetials
()
</
script
>
...
...
src/views/algorithmList/components/websockt.js
0 → 100644
View file @
7c50bfac
// mixins.js
import
{
ref
}
from
'
vue
'
;
import
{
WebSocketManager
}
from
'
@/utils/webscoket
'
export
function
useWebSockets
()
{
//定义初始值为0的变量,要使用ref方法赋值,直接赋值的话变量改变不会更新 UI
let
count
=
ref
(
0
);
const
uploadData
=
ref
({})
//上传成功后返回的数据
const
id
=
ref
(
null
)
const
client
=
ref
(
null
)
const
outFilePath
=
ref
(
''
)
//算法处理后的图片
const
route
=
useRoute
()
const
{
roleId
}
=
route
.
params
// 定义点击事件 myFn
function
handeUpload
(
e
){
uploadData
.
value
=
e
console
.
log
(
"
🚀 ~ handeUpload ~ uploadData.value:
"
,
uploadData
.
value
)
client
.
value
=
new
WebSocketManager
(
'
ws://192.168.3.71:8080/sf
'
,
websocketMessage
)
client
.
value
.
connect
();
}
function
websocketMessage
(
e
)
{
const
result
=
e
&&
JSON
.
parse
(
e
)
if
(
result
.
type
==
0
)
{
//获取sessionId
client
.
value
.
sendMessage
({
sessionId
:
e
,
algorithmType
:
roleId
,
fileType
:
uploadData
.
value
.
fileType
,
type
:
0
,
//0 图片 1视频
filePath
:
uploadData
.
value
.
url
,
fileName
:
uploadData
.
value
.
fileName
})
}
else
if
(
result
.
type
==
2
)
{
console
.
log
(
'
123
'
,
123
)
const
queue
=
result
.
data
.
queue
.
indexOf
(
'
[
'
)
==
-
1
?
result
.
data
.
queue
:
JSON
.
parse
(
result
.
data
.
queue
);
// this.result = queue;
if
(
!
queue
.
length
)
{
console
.
log
(
'
err
'
,
err
)
}
outFilePath
.
value
=
'
http://192.168.3.71:9081
'
+
'
/prod-api
'
+
'
/profile/endfile
'
+
result
.
data
.
outFilePath
;
// this.uploading = false;
client
.
value
.
disconnect
();
}
}
// 组件被挂载时,我们用 onMounted 钩子记录一些消息
onMounted
(()
=>
{
console
.
log
(
'
component mounted!
'
)
});
// 外部使用组合API中定义的变量或方法,在模板中可用。
return
{
handeUpload
,
outFilePath
}
// 返回的函数与方法的行为相同
}
\ No newline at end of file
src/views/algorithmList/index.vue
View file @
7c50bfac
...
...
@@ -77,7 +77,7 @@
</el-col>
</el-row>
<div
class=
"alg-list"
>
<el-card
v-for=
"item in algList"
:key=
"item.name"
class=
"alg-item"
shadow=
"hover"
@
click=
"handDetails"
>
<el-card
v-for=
"item in algList"
:key=
"item.name"
class=
"alg-item"
shadow=
"hover"
@
click=
"handDetails
(item)
"
>
<
template
v-slot:header
>
<div
class=
"cleartitle"
>
<span>
{{
item
.
algorithmName
}}
</span>
...
...
@@ -217,8 +217,9 @@
function
handeAdd
(
row
){
algorithmDownRef
.
value
.
handleAdd
()
}
function
handDetails
(
id
){
router
.
push
(
"
/algorithmList/details/info/
"
+
'
123
'
);
function
handDetails
(
row
){
// console.log("🚀 ~ handDetails ~ row:", row)
router
.
push
(
"
/algorithmList/details/info/
"
+
row
.
id
);
}
function
handleSetSize
(
row
)
{
console
.
log
(
'
%c [ row ]-170
'
,
'
font-size:13px; background:pink; color:#bf2c9f;
'
,
row
)
...
...
vite.config.js
View file @
7c50bfac
...
...
@@ -35,6 +35,12 @@ export default defineConfig(({ mode, command }) => {
target
:
'
http://192.168.14.43:8111/ai
'
,
changeOrigin
:
true
,
rewrite
:
(
p
)
=>
p
.
replace
(
/^
\/
dev-api/
,
''
)
},
'
/upload-api
'
:
{
// target: 'http://192.168.14.43:8111/ai',
target
:
'
http://192.168.3.71:8080
'
,
changeOrigin
:
true
,
rewrite
:
(
p
)
=>
p
.
replace
(
/^
\/
upload-api/
,
''
)
}
}
},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
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 comment