lion 7 months ago
commit 3acd345b5c

@ -0,0 +1,30 @@
import request from '@/utils/request'
// 获取仓库类型列表
export function getStorehouseTypeList(data) {
return request({
url: '/api/admin/storehouse/index',
method: 'post',
data,
headers: {
'Content-Type': 'multipart/form-data'
}
})
}
// 删除仓库类型
export function destroyStorehouseType(id) {
return request({
url: '/api/admin/storehouse/destroy?id=' + id,
method: 'get'
})
}
// 新增或更新仓库类型
export function saveStorehouseType(data) {
return request({
url: '/api/admin/storehouse/save',
method: 'post',
data
})
}

@ -1,34 +1,33 @@
<template>
<div>
<xy-dialog ref="dialog" :width='70' :is-show.sync="isShow" type="form" :title="type==='add'?'新增':'编辑'"
:form="form" :rules="rules" @submit="submit">
<template v-slot:cangkumingcheng>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;">*</span>仓库名称
</div>
<div class="xy-table-item-content">
<el-input style="width:300px" v-model="form.cangkumingcheng"></el-input>
</div>
</div>
</template>
<template v-slot:cangkubianma>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>仓库编码
</div>
<div class="xy-table-item-content">
<el-input style="width:300px" v-model="form.cangkubianma"></el-input>
</div>
</div>
</template>
<template v-slot:suozaiquyu>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>所在区域
</div>
<div class="xy-table-item-content">
<template>
<div>
<xy-dialog ref="dialog" :width='70' :is-show.sync="isShow" type="form" :title="type==='add'?'新增':'编辑'"
:form="form" :rules="rules" @submit="submit">
<template v-slot:cangkumingcheng>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;">*</span>仓库名称
</div>
<div class="xy-table-item-content">
<el-input style="width:300px" v-model="form.cangkumingcheng"></el-input>
</div>
</div>
</template>
<template v-slot:cangkubianma>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>仓库编码
</div>
<div class="xy-table-item-content">
<el-input style="width:300px" v-model="form.cangkubianma"></el-input>
</div>
</div>
</template>
<template v-slot:suozaiquyu>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>所在区域
</div>
<div class="xy-table-item-content">
<el-select v-model="form.suozaiquyu" @change="changeQuyu" style="width:300px" placeholder="请选择">
<el-option
v-for="item in areaList"
@ -36,150 +35,150 @@
:label="item.value"
:value="item.value">
</el-option>
</el-select>
</div>
</div>
</template>
<template v-slot:jiansheniandai>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>建设年代
</div>
<div class="xy-table-item-content">
<el-date-picker style="width:300px" value-format="yyyy" format="yyyy" v-model="form.jiansheniandai" type="year" placeholder="选择年">
</el-date-picker>
</div>
</div>
</template>
<template v-slot:cangkumianji>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>仓库面积
</div>
<div class="xy-table-item-content">
<el-input style="width:300px" v-model="form.cangkumianji"></el-input>
</div>
</div>
</template>
<template v-slot:fuzeren>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>负责人
</div>
<div class="xy-table-item-content">
<el-input style="width:300px" v-model="form.fuzeren"></el-input>
</div>
</div>
</template>
<template v-slot:lianxidianhua>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>联系电话
</div>
<div class="xy-table-item-content">
<el-input style="width: 300px;" v-model="form.lianxidianhua"></el-input>
</div>
</div>
</template>
<template v-slot:cangkudizhi>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>仓库地址
</div>
<div class="xy-table-item-content">
<avue-input-map v-model="mapform" :params="mapparams" style="width:300px"
placeholder="请选择地图"></avue-input-map>
</div>
</div>
</template>
<template v-slot:jingdu>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>经度
</div>
<div class="xy-table-item-content">
<el-input style="width: 300px;" v-model="form.jingdu"></el-input>
</div>
</div>
</template>
<template v-slot:weidu>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>纬度
</div>
<div class="xy-table-item-content">
<el-input style="width: 300px;" v-model="form.weidu"></el-input>
</div>
</div>
</template>
<template v-slot:cangkujianjie>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>仓库简介
</div>
<div class="xy-table-item-content">
<el-input style="width: 300px;" type="textarea" v-model="form.cangkujianjie"></el-input>
</div>
</div>
</template>
</xy-dialog>
</div>
</template>
<script>
import {
save,
show
</el-select>
</div>
</div>
</template>
<template v-slot:jiansheniandai>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>建设年代
</div>
<div class="xy-table-item-content">
<el-date-picker style="width:300px" value-format="yyyy" format="yyyy" v-model="form.jiansheniandai" type="year" placeholder="选择年">
</el-date-picker>
</div>
</div>
</template>
<template v-slot:cangkumianji>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>仓库面积
</div>
<div class="xy-table-item-content">
<el-input style="width:300px" v-model="form.cangkumianji"></el-input>
</div>
</div>
</template>
<template v-slot:fuzeren>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>负责人
</div>
<div class="xy-table-item-content">
<el-input style="width:300px" v-model="form.fuzeren"></el-input>
</div>
</div>
</template>
<template v-slot:lianxidianhua>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>联系电话
</div>
<div class="xy-table-item-content">
<el-input style="width: 300px;" v-model="form.lianxidianhua"></el-input>
</div>
</div>
</template>
<template v-slot:cangkudizhi>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>仓库地址
</div>
<div class="xy-table-item-content">
<avue-input-map v-model="mapform" :params="mapparams" style="width:300px"
placeholder="请选择地图"></avue-input-map>
</div>
</div>
</template>
<template v-slot:jingdu>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>经度
</div>
<div class="xy-table-item-content">
<el-input style="width: 300px;" v-model="form.jingdu"></el-input>
</div>
</div>
</template>
<template v-slot:weidu>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>纬度
</div>
<div class="xy-table-item-content">
<el-input style="width: 300px;" v-model="form.weidu"></el-input>
</div>
</div>
</template>
<template v-slot:cangkujianjie>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>仓库简介
</div>
<div class="xy-table-item-content">
<el-input style="width: 300px;" type="textarea" v-model="form.cangkujianjie"></el-input>
</div>
</div>
</template>
</xy-dialog>
</div>
</template>
<script>
import {
save,
show
} from "@/api/system/baseForm.js"
import {
getparameteritem
} from "@/api/system/dictionary.js"
import {
Message
} from 'element-ui'
export default {
data() {
return {
isShow: false,
type: 'add',
id: '',
import {
getparameteritem
} from "@/api/system/dictionary.js"
import {
Message
} from 'element-ui'
import { saveStorehouseType } from '@/api/system/storehouseType'
export default {
data() {
return {
isShow: false,
type: 'add',
id: '',
tableName: 'materialstorages',
// flood_storages
areaList:[],
mapparams: {
zoom: 11,
},
mapform: [],
form: {
cangkumingcheng: '',
cangkubianma: '',
suozaiquyu: '',
jiansheniandai: '',
cangkumianji: '',
fuzeren: '',
lianxidianhua: '',
cangkudizhi: '',
jingdu: '',
weidu: '',
areaList:[],
mapparams: {
zoom: 11,
},
mapform: [],
form: {
cangkumingcheng: '',
cangkubianma: '',
suozaiquyu: '',
jiansheniandai: '',
cangkumianji: '',
fuzeren: '',
lianxidianhua: '',
cangkudizhi: '',
jingdu: '',
weidu: '',
cangkujianjie: '',
quyu_id:''
},
rules: {
cangkumingcheng: [{
required: true,
message: '请填写仓库名称'
}]
},
}
},
created() {
this.getArea()
},
methods: {
quyu_id:''
},
rules: {
cangkumingcheng: [{
required: true,
message: '请填写仓库名称'
}]
},
}
},
created() {
this.getArea()
},
methods: {
getArea(){
getparameteritem("area").then(res=>{
this.areaList = res.detail
@ -200,75 +199,61 @@
},
setTableName(e){
this.tableName = e?e:'materialstorages'
},
async getDetail() {
const res = await show({
id: this.id,
table_name: this.tableName
})
this.$integrateData(this.form, res)
this.mapform = [res.jingdu, res.weidu, res.cangkudizhi]
},
submit() {
if (this.type === 'add') {
save({
table_name: this.tableName,
...this.form
}).then(res => {
Message({
type: 'success',
message: '新增成功'
})
this.$emit('refresh')
this.isShow = false
})
return
}
if (this.type === 'editor') {
save({
id: this.id,
table_name: this.tableName,
...this.form
}).then(res => {
Message({
type: 'success',
message: '编辑成功'
})
this.$emit('refresh')
this.isShow = false
})
}
},
},
watch: {
isShow(newVal) {
if (newVal) {
if (this.type === 'editor') {
this.getDetail()
}
} else {
this.id = ''
this.type = ''
this.mapform = []
this.$refs['dialog'].reset()
}
},
mapform(newVal, oldVal) {
console.log(newVal)
this.form.jingdu = newVal[0];
this.form.weidu = newVal[1];
this.form.cangkudizhi = newVal[2];
},
}
}
</script>
<style scoped lang="scss">
::v-deep .xy-table-item-label {
min-width: 160px !important
}
},
async getDetail() {
const res = await show({
id: this.id,
table_name: this.tableName
})
this.$integrateData(this.form, res)
this.mapform = [res.jingdu, res.weidu, res.cangkudizhi]
},
submit() {
const params = {
name: this.form.cangkumingcheng,
remark: this.form.cangkujianjie,
};
if (this.type === 'editor') {
params.id = this.id;
}
saveStorehouseType(params).then(res => {
Message({
type: 'success',
message: this.type === 'add' ? '新增成功' : '编辑成功'
})
this.$emit('refresh')
this.isShow = false
})
},
},
watch: {
isShow(newVal) {
if (newVal) {
if (this.type === 'editor') {
this.getDetail()
}
} else {
this.id = ''
this.type = ''
this.mapform = []
this.$refs['dialog'].reset()
}
},
mapform(newVal, oldVal) {
console.log(newVal)
this.form.jingdu = newVal[0];
this.form.weidu = newVal[1];
this.form.cangkudizhi = newVal[2];
},
}
}
</script>
<style scoped lang="scss">
::v-deep .xy-table-item-label {
min-width: 160px !important
}
</style>

@ -0,0 +1,129 @@
<template>
<div>
<xy-dialog ref="dialog" :width='700' :is-show.sync="isShow" type="form" :title="type==='add'?'新增仓库类型':'编辑仓库类型'"
:form="form" :rules="rules" @submit="submit">
<template v-slot:cangkumingcheng>
<div class="xy-table-item type-dialog-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;">*</span>仓库类型
</div>
<div class="xy-table-item-content">
<el-input style="width:500px; font-size:18px;" v-model="form.cangkumingcheng" placeholder="请输入仓库类型"></el-input>
</div>
</div>
</template>
<template v-slot:beizhu>
<div class="xy-table-item type-dialog-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>备注
</div>
<div class="xy-table-item-content">
<el-input style="width:500px; font-size:18px;" v-model="form.beizhu" placeholder="请输入备注"></el-input>
</div>
</div>
</template>
<template v-slot:sort>
<div class="xy-table-item type-dialog-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>排序编号
</div>
<div class="xy-table-item-content">
<el-input-number style="width: 200px; font-size:18px;" v-model="form.sort" :min="1" :max="9999" :step="1" placeholder="请输入排序编号"></el-input-number>
</div>
</div>
</template>
</xy-dialog>
</div>
</template>
<script>
import { saveStorehouseType } from '@/api/system/storehouseType'
import { Message } from 'element-ui'
export default {
data() {
return {
isShow: false,
type: 'add',
id: '',
form: {
cangkumingcheng: '',
beizhu: '',
sort: 1
},
rules: {
cangkumingcheng: [{ required: true, message: '请填写仓库类型' }]
}
}
},
methods: {
open(type = 'add', row = null) {
this.type = type;
this.isShow = true;
this.$nextTick(() => {
if (this.$refs.dialog && this.$refs.dialog.$refs.form) {
this.$refs.dialog.$refs.form.resetFields();
}
});
if (type === 'editor' && row) {
this.id = row.id;
Object.assign(this.form, {
cangkumingcheng: row.name || '',
beizhu: row.remark || '',
sort: row.sort || 1
});
} else {
this.id = '';
Object.assign(this.form, {
cangkumingcheng: '',
beizhu: '',
sort: 1
});
}
},
submit() {
const params = {
name: this.form.cangkumingcheng,
remark: this.form.beizhu,
sort: this.form.sort,
};
if (this.type === 'editor') {
params.id = this.id;
}
saveStorehouseType(params).then(res => {
Message({
type: 'success',
message: this.type === 'add' ? '新增成功' : '编辑成功'
})
this.$emit('refresh')
this.isShow = false
})
}
}
}
</script>
<style scoped lang="scss">
::v-deep .xy-table-item-label {
min-width: 120px !important;
font-size: 16px;
text-align: right;
}
.type-dialog-item {
margin-bottom: 28px;
display: flex;
align-items: center;
justify-content: center;
}
.xy-table-item-content {
display: flex;
align-items: center;
}
::v-deep .el-dialog {
border-radius: 12px;
}
::v-deep .el-button--primary {
border-radius: 6px;
font-size: 15px;
padding: 8px 24px;
}
</style>

@ -0,0 +1,190 @@
<template>
<div class="table-page-container">
<div ref="lxHeader">
<lx-header icon="md-apps" text="仓库类型" style="margin-bottom: 10px; border: 0px; margin-top: 15px">
<slot>
<div style="display: flex;justify-content: flex-start;flex-wrap: wrap;">
<Input v-model="select.keyword" style="width: 200px;margin-right: 10px;" placeholder="仓库类型" />
<Button type="primary" @click="getTypeList"></Button>
<Button type="primary" style="margin-left: 10px;" @click="$refs.addType.open('add')"></Button>
<!-- <Button icon="ios-add" type="primary" style="margin-left: 10px;"
@click="$refs['imports'].show()">导入</Button> -->
</div>
</slot>
</lx-header>
</div>
<div class="table-flex-content">
<xy-table :list="list" :total="total" @pageSizeChange="pageSizeChange" @pageIndexChange="pageChange"
:table-item="table" size="medium" :height="tableHeight" style="border-radius: 10px; overflow: hidden; box-shadow: 0 2px 12px 0 rgba(0,0,0,0.08); width: 100%;">
<template v-slot:btns>
<el-table-column label="操作" align="center" min-width="140" header-align="center" class-name="table-col-action">
<template slot-scope="scope">
<div style="display: flex; gap: 8px; justify-content: center;">
<Button type="primary" size="small" style="border-radius: 6px;" @click="$refs.addType.open('editor', scope.row)">编辑</Button>
<Button type="primary" style="margin-left: 0; border-radius: 6px;" size="small" ghost @click="delRow(scope.row.id)"></Button>
</div>
</template>
</el-table-column>
</template>
</xy-table>
<addType ref="addType" @refresh="getTypeList"></addType>
</div>
</div>
</template>
<script>
import {
destroy
} from "@/api/system/baseForm.js"
import { getStorehouseTypeList } from '@/api/system/storehouseType'
import addType from './components/addType.vue'
import {
getparameteritem
} from "@/api/system/dictionary.js"
import { destroyStorehouseType } from '@/api/system/storehouseType'
export default {
components: {
addType,
},
data() {
return {
select: {
page: 1,
page_size: 10,
keyword: '',
table_name: 'materialstorages',
area:''
},
areaList:[],
total: 0,
list: [],
table: [{
label: '序号',
type: 'index',
width: 60,
}, {
label: '仓库类型',
prop: 'name',
minWidth: 180
}, {
label: '排序编号',
prop: 'sort',
minWidth: 120,
}, {
label: '备注',
prop: 'remark',
minWidth: 200,
}, {
label: '创建日期',
prop: 'created_at',
minWidth: 120,
formatter: (cell, data, value) => {
return value ? value.substring(0, 10) : ''
}
}],
tableHeight: 550 //
}
},
created() {
this.getTypeList()
},
mounted() {
this.calcTableHeight();
window.addEventListener('resize', this.calcTableHeight);
},
beforeDestroy() {
window.removeEventListener('resize', this.calcTableHeight);
},
methods: {
async getTypeList() {
try {
const formData = new FormData();
formData.append('page', this.select.page);
formData.append('page_size', this.select.page_size);
//
if (this.select.keyword) {
formData.append('filter[0][key]', 'name');
formData.append('filter[0][op]', 'like');
formData.append('filter[0][value]', this.select.keyword);
}
const res = await getStorehouseTypeList(formData);
this.list = res.data;
this.total = res.total;
} catch (e) {
this.$message.error('获取仓库类型列表失败');
}
},
pageChange(e) {
this.select.page = e
this.getTypeList()
},
pageSizeChange(e){
this.select.page_size = e
this.getTypeList()
},
delRow(id) {
if (id) {
this.$confirm('确认要删除该仓库类型吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
try {
await destroyStorehouseType(id);
this.$message.success('删除成功');
this.getTypeList();
} catch (e) {
this.$message.error('删除失败');
}
});
}
},
calcTableHeight() {
const header = this.$refs.lxHeader ? this.$refs.lxHeader.offsetHeight : 0;
const windowHeight = window.innerHeight;
const minTableHeight = 600; //
this.tableHeight = Math.max(windowHeight - header - 100, minTableHeight);
},
}
}
</script>
<style>
.table-page-container {
display: flex;
flex-direction: column;
height: 100vh;
box-sizing: border-box;
background: #f5f7fa;
}
.table-flex-content {
flex: 1 1 0;
display: flex;
flex-direction: column;
min-height: 0;
}
.el-table th {
background: #f5f7fa !important;
color: #333;
font-weight: bold;
font-size: 15px;
}
.el-table td {
font-size: 14px;
height: 48px;
}
.el-table {
border-radius: 10px;
overflow: hidden;
width: 100%;
height: 100%;
}
/* 让操作列自动填充剩余空间 */
.table-col-action {
flex: 1 !important;
}
</style>

@ -1,24 +1,257 @@
<template>
<div class="container">
<div style="padding: 0px 20px">
<el-image
style="width: 100%"
:src="require('/src/assets/monitor.png')"
fit="fill"></el-image>
<!-- <div ref="lxHeader">
<lx-header icon="md-apps" text="环境监控" style="margin-bottom: 10px; border: 0px; margin-top: 15px">
<div slot="content"></div>
<slot>
</slot>
</lx-header>
</div> -->
<div class="monitor-container">
<!-- Camera Section -->
<el-row :gutter="20" class="camera-section">
<el-col :span="8" v-for="camera in cameras" :key="camera.id">
<el-card shadow="never">
<div slot="header" class="clearfix">
<span>{{ camera.name }}</span>
<el-button style="float: right; padding: 3px 0" type="text" :class="camera.status === '离线' ? 'offline' : ''">{{ camera.status }}</el-button>
</div>
<div class="camera-body">
<el-image
style="width: 100%; height: 180px; background-color: #000; display: flex; align-items: center; justify-content: center;"
:src="camera.image"
fit="cover">
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline" style="font-size: 40px; color: #ccc;"></i>
<div style="color: #ccc;">EZVIZ</div>
</div>
<div slot="placeholder" class="image-slot">
<i class="el-icon-loading" style="font-size: 40px; color: #ccc;"></i>
</div>
</el-image>
<div class="camera-info">视频通道: {{ camera.channel }}</div>
</div>
</el-card>
</el-col>
</el-row>
<!-- Environment Section -->
<div class="environment-section">
<h3 class="section-title">环境信息</h3>
<el-row :gutter="20">
<el-col :span="8" v-for="point in environmentPoints" :key="point.id">
<el-card shadow="never" :body-style="{ padding: '0px' }">
<div class="environment-card" :class="getCardClass(point.status)">
<div class="env-header">
<span>{{ point.name }}</span>
<el-tag size="small" :type="getTagType(point.status)" effect="dark" class="status-tag">
<i v-if="point.status === '正常'" class="el-icon-success" style="margin-right: 4px;"></i>
{{ point.status }}
</el-tag>
</div>
<el-row class="env-data">
<el-col :span="12">
<div class="data-item">
<div class="label">CO浓度</div>
<div class="value" :class="point.status === '预警' ? 'warning-value' : ''">{{ point.coConcentration }}</div>
</div>
</el-col>
<el-col :span="12">
<div class="data-item">
<div class="label">温度</div>
<div class="value">{{ point.temperature }}</div>
</div>
</el-col>
</el-row>
<el-row class="env-data">
<el-col :span="12">
<div class="data-item">
<div class="label">湿度</div>
<div class="value">{{ point.humidity }}</div>
</div>
</el-col>
<el-col :span="12">
<div class="data-item">
<div class="label">更新时间</div>
<div class="value date">{{ point.updateTime }}</div>
</div>
</el-col>
</el-row>
</div>
</el-card>
</el-col>
</el-row>
</div>
</div>
</template>
<script>
export default {
name: 'MonitorPage',
data() {
return {
cameras: [
{
id: 1,
name: '摄像头1',
status: '离线',
image: 'https://img.freepik.com/free-vector/cctv-surveillance-system-concept_23-2148529272.jpg',
channel: '[DS-2CD2225XM-LGLSE(AE1005192)- AE1005192]'
},
{
id: 2,
name: '摄像头2',
status: '离线',
image: 'https://img.freepik.com/premium-photo/security-camera-perspective-hallway-corridor-monitoring-space-3d-rendering_172660-215.jpg',
channel: '[DS-2CD2225XM-LGLSE(AE1005068)- AE1005068]'
},
{
id: 3,
name: '摄像头3',
status: '离线',
image: 'https://img.freepik.com/premium-photo/video-surveillance-camera-record-street-cctv-camera-work-building_169016-21553.jpg',
channel: '[DS-2CD2225XM-LGLSE(AE1005197)- AE1005197]'
}
],
environmentPoints: [
{ id: 'A', name: '监控点 A', status: '正常', coConcentration: '2.5 ppm', temperature: '24.5 ℃', humidity: '45 %', updateTime: '2024-01-05' },
{ id: 'B', name: '监控点 B', status: '预警', coConcentration: '8.2 ppm', temperature: '26.8 ℃', humidity: '52 %', updateTime: '2024-01-05' },
{ id: 'C', name: '监控点 C', status: '正常', coConcentration: '1.8 ppm', temperature: '23.9 ℃', humidity: '48 %', updateTime: '2024-01-05' }
]
};
},
methods: {
getCardClass(status) {
if (status === '正常') {
// Assuming the green normal status is also '' based on context,
// We check the ID for C to apply green, otherwise blue
// Or better, add a specific status like 'Normal-Green' if data allows
return 'status-normal-blue'; // Default blue for ''
// For point C, if we assume its status implies green:
// return pointId === 'C' ? 'status-normal-green' : 'status-normal-blue';
} else if (status === '预警') {
return 'status-warning';
}
return '';
},
getTagType(status) {
if (status === '正常') return 'success'; // Element UI tag type for green/blue normal
if (status === '预警') return 'warning'; // Element UI tag type for yellow warning
return 'info'; // Default
}
}
};
</script>
<style>
<style lang="scss" scoped>
.monitor-container {
padding: 20px;
background-color: #f5f7fa; // Light background for the whole page
}
.camera-section {
margin-bottom: 30px;
}
.el-card {
border: none; // Remove default card border if desired
}
.clearfix:before,
.clearfix:after {
display: table;
content: "";
}
.clearfix:after {
clear: both
}
.camera-body {
text-align: center;
.el-image {
margin-bottom: 10px;
border-radius: 4px;
overflow: hidden;
box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
.image-slot {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
}
}
.camera-info {
font-size: 12px;
color: #999;
margin-top: 5px;
word-break: break-all;
text-align: left;
padding: 0 5px;
}
}
.offline {
color: #F56C6C; // Style for offline button
}
.environment-section {
.section-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 15px;
color: #303133;
}
}
.environment-card {
padding: 15px;
color: #fff; // Default text color for cards
&.status-normal-blue {
background-color: #409EFF; // Blue for normal status
}
&.status-warning {
background-color: #E6A23C; // Yellow for warning status
}
&.status-normal-green { // Assuming point C has a distinct 'green normal' status
background-color: #67C23A; // Green for normal status
}
.env-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
font-size: 16px;
font-weight: bold;
.status-tag {
border-radius: 10px; // Make tag more pill-shaped
border: none;
// Match background to card, or use Element UI types
&.el-tag--success { background-color: rgba(255, 255, 255, 0.2); color: #fff;}
&.el-tag--warning { background-color: rgba(255, 255, 255, 0.2); color: #fff;}
}
}
.env-data {
margin-bottom: 10px; // Space between data rows
&:last-child {
margin-bottom: 0;
}
.data-item {
.label {
font-size: 13px;
color: rgba(255, 255, 255, 0.8); // Lighter label color
margin-bottom: 5px;
}
.value {
font-size: 20px;
font-weight: bold;
&.warning-value {
color: #fdf6ec; // Slightly different color for warning value if needed
}
&.date {
font-size: 14px; // Smaller font for date
font-weight: normal;
}
}
}
}
}
</style>

@ -0,0 +1,253 @@
<template>
<div class="warning-setting-container">
<el-card class="setting-card">
<div slot="header" class="clearfix">
<span>监控设置</span>
</div>
<!-- 监控点配置 -->
<el-form ref="monitorForm" :model="monitorPoints" label-width="120px">
<div v-for="(point, index) in monitorPoints" :key="`point-${index}`" class="monitor-point-config">
<div class="point-header">监控点 {{ point.name }}</div>
<!-- 视频配置 -->
<el-form-item :label="`摄像头地址`">
<el-input v-model="point.videoUrl" placeholder="请输入摄像头视频流地址"></el-input>
</el-form-item>
<el-form-item label="摄像头名称">
<el-input v-model="point.videoName" placeholder="请输入摄像头名称"></el-input>
</el-form-item>
<!-- 环境监测阈值 -->
<el-divider content-position="left">环境监测阈值</el-divider>
<el-form-item label="CO浓度阈值(ppm)">
<el-input-number
v-model="point.coThreshold"
:min="0"
:max="50"
:step="0.1"
:precision="1"
controls-position="right">
</el-input-number>
<span class="description">超过此值将触发预警</span>
</el-form-item>
<el-form-item label="温度阈值(℃)">
<el-row>
<el-col :span="11">
<el-input-number
v-model="point.tempMinThreshold"
:min="-20"
:max="50"
controls-position="right">
</el-input-number>
<span class="threshold-label">最低温度</span>
</el-col>
<el-col :span="11" :offset="2">
<el-input-number
v-model="point.tempMaxThreshold"
:min="0"
:max="100"
controls-position="right">
</el-input-number>
<span class="threshold-label">最高温度</span>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="湿度阈值(%)">
<el-row>
<el-col :span="11">
<el-input-number
v-model="point.humidityMinThreshold"
:min="0"
:max="100"
controls-position="right">
</el-input-number>
<span class="threshold-label">最低湿度</span>
</el-col>
<el-col :span="11" :offset="2">
<el-input-number
v-model="point.humidityMaxThreshold"
:min="0"
:max="100"
controls-position="right">
</el-input-number>
<span class="threshold-label">最高湿度</span>
</el-col>
</el-row>
</el-form-item>
</div>
</el-form>
<!-- 预警接收设置 -->
<div class="section-title">预警接收设置</div>
<el-form ref="warningForm" :model="warningForm" label-width="120px">
<el-form-item label="预警手机号">
<el-input v-model="warningForm.phoneNumber" placeholder="请输入接收预警信息的手机号">
<template slot="append">
<el-button @click="addReceiver"></el-button>
</template>
</el-input>
</el-form-item>
<el-table
v-if="warningForm.receivers.length > 0"
:data="warningForm.receivers"
style="width: 100%; margin-top: 10px;">
<el-table-column label="序号" type="index" width="50"></el-table-column>
<el-table-column prop="phone" label="手机号"></el-table-column>
<el-table-column prop="name" label="联系人"></el-table-column>
<el-table-column label="操作" width="120">
<template slot-scope="scope">
<el-button
type="text"
size="small"
@click="removeReceiver(scope.$index)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-form>
<el-form-item>
<el-button type="primary" @click="saveSettings"></el-button>
<el-button @click="resetForm"></el-button>
</el-form-item>
</el-card>
</div>
</template>
<script>
export default {
name: 'WarningSetting',
data() {
return {
monitorPoints: [
{
name: 'A',
videoName: '摄像头1',
videoUrl: 'ezopen://open.ys7.com/203751922/1.cga',
coThreshold: 5.0,
tempMinThreshold: 15,
tempMaxThreshold: 30,
humidityMinThreshold: 30,
humidityMaxThreshold: 70
},
{
name: 'B',
videoName: '摄像头2',
videoUrl: 'ezopen://open.ys7.com/F59651352/1.cga',
coThreshold: 5.0,
tempMinThreshold: 15,
tempMaxThreshold: 30,
humidityMinThreshold: 30,
humidityMaxThreshold: 70
},
{
name: 'C',
videoName: '摄像头3',
videoUrl: 'ezopen://open.ys7.com/G39410642/1.cga',
coThreshold: 5.0,
tempMinThreshold: 15,
tempMaxThreshold: 30,
humidityMinThreshold: 30,
humidityMaxThreshold: 70
}
],
warningForm: {
phoneNumber: '',
receivers: [
{ phone: '13800138000', name: '张三' },
{ phone: '13900139000', name: '李四' }
]
}
};
},
methods: {
addReceiver() {
if (!this.warningForm.phoneNumber) {
this.$message.warning('请输入手机号');
return;
}
//
const phoneReg = /^1[3-9]\d{9}$/;
if (!phoneReg.test(this.warningForm.phoneNumber)) {
this.$message.error('请输入正确的手机号格式');
return;
}
this.warningForm.receivers.push({
phone: this.warningForm.phoneNumber,
name: '联系人' + (this.warningForm.receivers.length + 1)
});
this.warningForm.phoneNumber = '';
},
removeReceiver(index) {
this.warningForm.receivers.splice(index, 1);
},
saveSettings() {
// API
console.log('Monitor point settings:', this.monitorPoints);
console.log('Warning receivers:', this.warningForm.receivers);
this.$message({
message: '设置保存成功',
type: 'success'
});
},
resetForm() {
//
this.$refs.monitorForm && this.$refs.monitorForm.resetFields();
this.$refs.warningForm && this.$refs.warningForm.resetFields();
}
}
};
</script>
<style lang="scss" scoped>
.warning-setting-container {
padding: 20px;
.setting-card {
margin-bottom: 20px;
}
.section-title {
font-size: 16px;
font-weight: bold;
padding: 10px 0;
margin: 15px 0 5px 0;
border-bottom: 1px solid #ebeef5;
}
.monitor-point-config {
background-color: #f9f9f9;
border-radius: 4px;
padding: 15px;
margin-bottom: 20px;
.point-header {
font-size: 16px;
font-weight: bold;
margin-bottom: 15px;
color: #409EFF;
}
}
.description {
margin-left: 10px;
color: #909399;
font-size: 12px;
}
.threshold-label {
margin-left: 5px;
color: #909399;
font-size: 12px;
}
}
</style>
Loading…
Cancel
Save