111
This commit is contained in:
parent
75494717df
commit
ef72a21402
|
|
@ -11,16 +11,370 @@
|
|||
<!-- 占位保持布局平衡 -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="ContentBox">
|
||||
<!-- 项目基本信息 -->
|
||||
<view class="PBasicBox">
|
||||
<u-row justify="space-between">
|
||||
<u-col span="4">
|
||||
<view class="LabelBox">项目编号:</view>
|
||||
<view class="LabelBoxTxt">{{ projectInfo.code }}</view>
|
||||
</u-col>
|
||||
<u-col span="3">
|
||||
<view class="LabelBox">作业负责人:</view>
|
||||
<view class="LabelBoxTxt">{{ projectInfo.leader }}</view>
|
||||
</u-col>
|
||||
<u-col span="5">
|
||||
<view class="LabelBox">作业周期:</view>
|
||||
<view class="LabelBoxTxt">{{ projectInfo.period }}</view>
|
||||
</u-col>
|
||||
</u-row>
|
||||
|
||||
<u-row>
|
||||
<u-col span="12">当前进度:
|
||||
<u-line-progress :percentage="projectInfo.percentage" activeColor="#55AAFF"></u-line-progress>
|
||||
</u-col>
|
||||
</u-row>
|
||||
</view>
|
||||
|
||||
<!-- 相机切换 -->
|
||||
<view class="CameraTabs">
|
||||
<view
|
||||
class="CameraTab"
|
||||
:class="{ active: currentCamera === 1 }"
|
||||
@click="currentCamera = 1"
|
||||
>
|
||||
相机 1
|
||||
</view>
|
||||
<view
|
||||
class="CameraTab"
|
||||
:class="{ active: currentCamera === 2 }"
|
||||
@click="currentCamera = 2"
|
||||
>
|
||||
相机 2
|
||||
</view>
|
||||
<view
|
||||
class="CameraTab"
|
||||
:class="{ active: currentCamera === 3 }"
|
||||
@click="currentCamera = 3"
|
||||
>
|
||||
相机 3
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 绘制按钮 -->
|
||||
<view class="DrawButtonBox">
|
||||
<u-button style="width: 150rpx;" type="primary" @click="startDraw" size="mini" >+ 绘制电子围栏</u-button>
|
||||
</view>
|
||||
|
||||
<!-- 监控画面 -->
|
||||
<view class="MonitorBox">
|
||||
<!-- 这里可以放真实的监控视频组件 -->
|
||||
<view class="MonitorPlaceholder">
|
||||
<text class="PlaceholderText">监控画面</text>
|
||||
</view>
|
||||
|
||||
<!-- 围栏图形 -->
|
||||
<view class="FenceOverlay">
|
||||
<view class="FenceShape" v-for="(fence, index) in fenceList" :key="index" :style="getFenceStyle(index)">
|
||||
<view class="FenceLabel">{{ fence.name }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 围栏列表 -->
|
||||
<view class="FenceList">
|
||||
<view class="FenceItem" v-for="(fence, index) in fenceList" :key="index">
|
||||
<view class="FenceItemHeader">
|
||||
<view class="FenceItemName">{{ fence.name }}</view>
|
||||
<view class="FenceItemAction">
|
||||
<u-button size="mini" type="primary" @click="editFence(index)">设置</u-button>
|
||||
</view>
|
||||
</view>
|
||||
<view class="FenceItemContent">
|
||||
<view class="FenceInfoRow">
|
||||
<text class="InfoLabel">位置:</text>
|
||||
<text class="InfoValue">{{ fence.position }}</text>
|
||||
</view>
|
||||
<view class="FenceInfoRow">
|
||||
<text class="InfoLabel">类型:</text>
|
||||
<text class="InfoValue">{{ fence.type }}</text>
|
||||
</view>
|
||||
<view class="FenceInfoRow">
|
||||
<text class="InfoLabel">级别:</text>
|
||||
<text class="InfoValue">{{ fence.level }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部弹窗 -->
|
||||
<u-popup v-model:show="showEditPopup" mode="bottom" :round="10" :safe-area-inset-bottom="30">
|
||||
<view class="EditPopup">
|
||||
<view class="PopupTitle">{{ currentEditFence.name }}</view>
|
||||
|
||||
<view class="PopupForm">
|
||||
<view class="FormItem">
|
||||
<text class="FormLabel">位置:</text>
|
||||
<text class="FormValue">{{ currentEditFence.position }}</text>
|
||||
</view>
|
||||
|
||||
<view class="FormItem">
|
||||
<text class="FormLabel">类型:</text>
|
||||
<u-select
|
||||
v-model="editForm.type"
|
||||
:list="fenceTypeList"
|
||||
@confirm="onTypeConfirm"
|
||||
></u-select>
|
||||
</view>
|
||||
|
||||
<view class="FormItem">
|
||||
<text class="FormLabel">时间:</text>
|
||||
<u-input
|
||||
v-model="editForm.time"
|
||||
type="number"
|
||||
:border="false"
|
||||
class="TimeInput"
|
||||
></u-input>
|
||||
<text class="TimeUnit">分钟</text>
|
||||
</view>
|
||||
|
||||
<view class="FormItem">
|
||||
<text class="FormLabel">级别:</text>
|
||||
<u-select
|
||||
v-model="editForm.level"
|
||||
:list="fenceLevelList"
|
||||
@confirm="onLevelConfirm"
|
||||
></u-select>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="PopupButtons">
|
||||
<u-button type="primary" @click="saveFenceConfig">保存配置</u-button>
|
||||
<u-button type="error" @click="deleteFence">删除围栏</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {ref, onMounted} from 'vue'
|
||||
|
||||
const projectId = ref('')
|
||||
const projectInfo = ref({
|
||||
code: '20230801001',
|
||||
leader: '张三',
|
||||
period: '2023.8.1-2023.12.31',
|
||||
percentage: 30
|
||||
})
|
||||
|
||||
// 当前相机
|
||||
const currentCamera = ref(1)
|
||||
|
||||
// 围栏列表
|
||||
const fenceList = ref([
|
||||
{
|
||||
name: '图形 1',
|
||||
position: '10,10',
|
||||
type: '入侵检测',
|
||||
level: '一级',
|
||||
top: '20%',
|
||||
left: '10%',
|
||||
width: '30%',
|
||||
height: '40%'
|
||||
},
|
||||
{
|
||||
name: '图形 2',
|
||||
position: '10,10',
|
||||
type: '滞留限制',
|
||||
level: '一级',
|
||||
top: '50%',
|
||||
left: '40%',
|
||||
width: '40%',
|
||||
height: '35%'
|
||||
},
|
||||
{
|
||||
name: '图形 2',
|
||||
position: '10,10',
|
||||
type: '滞留限制',
|
||||
level: '一级',
|
||||
top: '50%',
|
||||
left: '40%',
|
||||
width: '40%',
|
||||
height: '35%'
|
||||
},
|
||||
{
|
||||
name: '图形 2',
|
||||
position: '10,10',
|
||||
type: '滞留限制',
|
||||
level: '一级',
|
||||
top: '50%',
|
||||
left: '40%',
|
||||
width: '40%',
|
||||
height: '35%'
|
||||
},
|
||||
{
|
||||
name: '图形 2',
|
||||
position: '10,10',
|
||||
type: '滞留限制',
|
||||
level: '一级',
|
||||
top: '50%',
|
||||
left: '40%',
|
||||
width: '40%',
|
||||
height: '35%'
|
||||
},
|
||||
{
|
||||
name: '图形 2',
|
||||
position: '10,10',
|
||||
type: '滞留限制',
|
||||
level: '一级',
|
||||
top: '50%',
|
||||
left: '40%',
|
||||
width: '40%',
|
||||
height: '35%'
|
||||
},
|
||||
{
|
||||
name: '图形 2',
|
||||
position: '10,10',
|
||||
type: '滞留限制',
|
||||
level: '一级',
|
||||
top: '50%',
|
||||
left: '40%',
|
||||
width: '40%',
|
||||
height: '35%'
|
||||
}
|
||||
])
|
||||
|
||||
// 弹窗相关
|
||||
const showEditPopup = ref(false)
|
||||
const currentEditIndex = ref(-1)
|
||||
const currentEditFence = ref({
|
||||
name: '',
|
||||
position: '',
|
||||
type: '',
|
||||
level: '',
|
||||
time: ''
|
||||
})
|
||||
|
||||
// 围栏类型选项
|
||||
const fenceTypeList = ref([
|
||||
{label: '入侵检测', value: '入侵检测'},
|
||||
{label: '滞留限制', value: '滞留限制'},
|
||||
{label: '越界检测', value: '越界检测'},
|
||||
{label: '区域警戒', value: '区域警戒'}
|
||||
])
|
||||
|
||||
// 围栏级别选项
|
||||
const fenceLevelList = ref([
|
||||
{label: '一级', value: '一级'},
|
||||
{label: '二级', value: '二级'},
|
||||
{label: '三级', value: '三级'}
|
||||
])
|
||||
|
||||
// 编辑表单数据
|
||||
const editForm = ref({
|
||||
type: '',
|
||||
time: '',
|
||||
level: ''
|
||||
})
|
||||
|
||||
// 获取围栏样式
|
||||
const getFenceStyle = (index) => {
|
||||
const fence = fenceList.value[index]
|
||||
return {
|
||||
top: fence.top,
|
||||
left: fence.left,
|
||||
width: fence.width,
|
||||
height: fence.height
|
||||
}
|
||||
}
|
||||
|
||||
// 开始绘制
|
||||
const startDraw = () => {
|
||||
uni.showToast({
|
||||
title: '进入绘制模式',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
|
||||
// 编辑围栏
|
||||
const editFence = (index) => {
|
||||
currentEditIndex.value = index
|
||||
const fence = fenceList.value[index]
|
||||
currentEditFence.value = {...fence, time: '30'}
|
||||
editForm.value = {
|
||||
type: fence.type,
|
||||
time: '30',
|
||||
level: fence.level
|
||||
}
|
||||
showEditPopup.value = true
|
||||
}
|
||||
|
||||
// 类型确认
|
||||
const onTypeConfirm = (value) => {
|
||||
editForm.value.type = value
|
||||
}
|
||||
|
||||
// 级别确认
|
||||
const onLevelConfirm = (value) => {
|
||||
editForm.value.level = value
|
||||
}
|
||||
|
||||
// 保存配置
|
||||
const saveFenceConfig = () => {
|
||||
if (currentEditIndex.value >= 0) {
|
||||
fenceList.value[currentEditIndex.value] = {
|
||||
...fenceList.value[currentEditIndex.value],
|
||||
type: editForm.value.type,
|
||||
level: editForm.value.level
|
||||
}
|
||||
}
|
||||
|
||||
uni.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
showEditPopup.value = false
|
||||
}
|
||||
|
||||
// 删除围栏
|
||||
const deleteFence = () => {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要删除该围栏吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
if (currentEditIndex.value >= 0) {
|
||||
fenceList.value.splice(currentEditIndex.value, 1)
|
||||
}
|
||||
uni.showToast({
|
||||
title: '删除成功',
|
||||
icon: 'success'
|
||||
})
|
||||
showEditPopup.value = false
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 返回上一页
|
||||
const goBack = () => {
|
||||
uni.navigateBack({
|
||||
delta: 1
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const pages = getCurrentPages()
|
||||
const currentPage = pages[pages.length - 1]
|
||||
const options = currentPage.options || {}
|
||||
projectId.value = options.projectId || ''
|
||||
|
||||
// TODO: 根据 projectId 获取项目信息和围栏配置
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
@ -31,10 +385,26 @@ const goBack = () => {
|
|||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.PBasicBox {
|
||||
padding: 20rpx;
|
||||
background-color: #fff;
|
||||
|
||||
.LabelBox {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.LabelBoxTxt {
|
||||
font-size: 24rpx;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.PageBox {
|
||||
background-color: #f5f5f5;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
|
||||
.TopBox {
|
||||
height: 100rpx;
|
||||
|
|
@ -57,72 +427,213 @@ const goBack = () => {
|
|||
}
|
||||
|
||||
.ContentBox {
|
||||
width: 100%;
|
||||
height: calc(100% - 140rpx);
|
||||
background-color: #f5f5f5;
|
||||
height: calc(100vh - 210rpx);
|
||||
overflow-y: auto;
|
||||
padding: 20rpx;
|
||||
padding: 0 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
|
||||
.CardBox {
|
||||
.CameraTabs {
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
border-radius: 10rpx;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 0 10rpx rgba(0, 0, 0, 0.05);
|
||||
flex-shrink: 0;
|
||||
|
||||
.CardTitle {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 20rpx;
|
||||
padding-left: 10rpx;
|
||||
border-left: 4rpx solid #2979ff;
|
||||
.CameraTab {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 16rpx 0;
|
||||
font-size: 22rpx;
|
||||
color: #666;
|
||||
background-color: #fff;
|
||||
border: 1rpx solid #eaeaea;
|
||||
|
||||
&.active {
|
||||
background-color: #2979ff;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.FormItemBox {
|
||||
.DrawButtonBox {
|
||||
margin-bottom: 20rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.LabelBox {
|
||||
font-size: 24rpx;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
.small-button {
|
||||
width: auto !important;
|
||||
min-width: 300rpx !important;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.ValueBox {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
}
|
||||
.MonitorBox {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 400rpx;
|
||||
background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
|
||||
margin-bottom: 20rpx;
|
||||
border-radius: 10rpx;
|
||||
overflow: hidden;
|
||||
flex-shrink: 0;
|
||||
|
||||
.CoordBox {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 10rpx;
|
||||
}
|
||||
|
||||
.RangeBox {
|
||||
.MonitorPlaceholder {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
justify-content: center;
|
||||
|
||||
.RangeTxt {
|
||||
font-size: 24rpx;
|
||||
color: #2979ff;
|
||||
.PlaceholderText {
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
min-width: 80rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.FenceOverlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.FenceShape {
|
||||
position: absolute;
|
||||
border: 2rpx solid #ff9900;
|
||||
background-color: rgba(255, 153, 0, 0.2);
|
||||
pointer-events: none;
|
||||
|
||||
.FenceLabel {
|
||||
position: absolute;
|
||||
top: -40rpx;
|
||||
left: 0;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
color: #fff;
|
||||
padding: 8rpx 16rpx;
|
||||
border-radius: 4rpx;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.FenceList {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
min-height: 0;
|
||||
|
||||
.FenceItem {
|
||||
background-color: #fff;
|
||||
border-radius: 10rpx;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
|
||||
.FenceItemHeader {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.FenceItemName {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.FenceItemContent {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.FenceInfoRow {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
|
||||
.InfoLabel {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.InfoValue {
|
||||
font-size: 24rpx;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.FootBox {
|
||||
.EditPopup {
|
||||
padding: 30rpx;
|
||||
padding-bottom: calc(30rpx + env(safe-area-inset-bottom));
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx 20rpx 0 0;
|
||||
|
||||
.PopupTitle {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 30rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.PopupForm {
|
||||
.FormItem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 25rpx 0;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
|
||||
.FormLabel {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
min-width: 120rpx;
|
||||
}
|
||||
|
||||
.FormValue {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.TimeInput {
|
||||
width: 300rpx;
|
||||
border-bottom: 1rpx solid #eaeaea !important;
|
||||
}
|
||||
|
||||
.TimeUnit {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.PopupButtons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 20rpx;
|
||||
padding: 20rpx;
|
||||
background-color: #fff;
|
||||
border-top: 1rpx solid #eaeaea;
|
||||
margin-top: 50rpx;
|
||||
|
||||
button {
|
||||
flex: 1;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in New Issue