zhaohy
3 months ago
14 changed files with 2263 additions and 21 deletions
@ -0,0 +1,429 @@ |
|||
<template> |
|||
<table class="custom-table table1"> |
|||
<thead> |
|||
<tr :style="{ background: 'rgba(35,45,69)' }"> |
|||
<th>序号</th> |
|||
<th>执行时间</th> |
|||
<th>操作内容</th> |
|||
<th>操作人</th> |
|||
<th>状态</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<tr |
|||
:style="{ color: row.ctrlResult == 1 ? 'red' : 'white' }" |
|||
v-for="(row, index) in dataSource" |
|||
:key="index" |
|||
@click="handleRowClick(row.id, index)" |
|||
:class="index === trIndex ? 'isTrIndex' : ''"> |
|||
<td>{{ index + 1 }}</td> |
|||
<td>{{ row.startTime }}</td> |
|||
<td>{{ row.operationContent }}</td> |
|||
<td>{{ row.createUser }}</td> |
|||
<td>{{ row.ctrlResult ? '失败' : '成功' }}</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
<a-pagination |
|||
style="margin-top: 10px; text-align: right" |
|||
v-model:current="pagination.pageNum" |
|||
v-model:pageSize="pagination.pageSize" |
|||
show-size-changer |
|||
:total="pagination.total" |
|||
@change="getTable(true)" /> |
|||
<div style="width: 100%; height: 40px"></div> |
|||
|
|||
<div class="out-dialog" :class="{ showDialog: logModalVisible }" v-if="logModalVisible"> |
|||
<div class="content"> |
|||
<div> |
|||
<div class="div-operation"></div> |
|||
<span class="text-operation">变更内容 </span> |
|||
</div> |
|||
<div> |
|||
<button :class="{ btn: true, selected: activeButton == 1 }" @click="changeBtn(1)" |
|||
>阀门</button |
|||
> |
|||
<button :class="{ btn: true, selected: activeButton == 2 }" @click="changeBtn(2)" |
|||
>水泵</button |
|||
> |
|||
</div> |
|||
<div class="device-list" v-if="activeButton == 1"> |
|||
<div class="device-list-item" v-for="(item, index) in valveLogList" :key="index"> |
|||
<div class="list-item-title"> |
|||
<div class="item-title"> |
|||
<img src="../images/device1.png" alt="" /> |
|||
<span>{{ item.deviceGroupName }}</span> |
|||
</div> |
|||
</div> |
|||
<div class="list-item-main"> |
|||
<div> |
|||
<div class="info">开度</div> |
|||
<div class="text"> |
|||
<span>{{ item.openPercentBefore + '%' }}</span> |
|||
<img src="/asset/image/bulbLogo/22406.png" alt="" /> |
|||
<span>{{ item.openPercentAfter + '%' }}</span> |
|||
</div> |
|||
</div> |
|||
<div></div> |
|||
</div> |
|||
</div> |
|||
<a-empty style="margin-top: 100px" v-if="valveLogList.length == 0"> |
|||
<template #description> <span style="color: white">暂无数据</span></template> |
|||
</a-empty> |
|||
</div> |
|||
<div class="device-list" v-if="activeButton == 2"> |
|||
<div class="device-list-item" v-for="(item, index) in pumpLogList" :key="index"> |
|||
<div class="list-item-title"> |
|||
<div class="item-title"> |
|||
<img src="../images/device2.png" alt="" /> |
|||
<span>{{ item.deviceGroupName }}</span> |
|||
</div> |
|||
</div> |
|||
<div class="list-item-main"> |
|||
<div> |
|||
<div class="info">频率</div> |
|||
<div class="text"> |
|||
<span>{{ item.frequencyBefore + 'MHz' }}</span> |
|||
<img src="/asset/image/bulbLogo/22406.png" alt="" /> |
|||
<span>{{ item.frequencyAfter + 'MHz' }}</span> |
|||
</div> |
|||
</div> |
|||
<div> |
|||
<div class="info">开关</div> |
|||
<div class="text"> |
|||
<span>{{ item.switchStatusBefore.label }}</span> |
|||
<img src="/asset/image/bulbLogo/22406.png" alt="" /> |
|||
<span>{{ item.switchStatusAfter.label }}</span> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<a-empty style="margin-top: 100px" v-if="pumpLogList.length == 0"> |
|||
<template #description> <span style="color: white">暂无数据</span></template> |
|||
</a-empty> |
|||
</div> |
|||
</div> |
|||
<div style="width: 100%; height: 160px"></div> |
|||
<div class="button-box"> |
|||
<button class="cancel" @click="logModalVisible = false">关闭</button> |
|||
</div> |
|||
</div> |
|||
<div class="div-add"> |
|||
<button class="add" @click="reset">刷新</button> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, onMounted } from 'vue'; |
|||
import { message } from 'ant-design-vue'; |
|||
import { Pagination } from 'ant-design-vue'; |
|||
import { http } from '/nerv-lib/util/http'; |
|||
import { waterSys } from '/@/api/waterSystem'; |
|||
// 全局变量 |
|||
import { items } from '/@/store/item'; |
|||
|
|||
// 初始化 ======================================================= |
|||
|
|||
// 组件 |
|||
defineOptions({ |
|||
components: { |
|||
'a-pagination': Pagination, |
|||
}, |
|||
}); |
|||
// 初始化 |
|||
onMounted(() => { |
|||
getTable(); |
|||
}); |
|||
|
|||
// 全局变量 |
|||
const state = items(); |
|||
|
|||
// 日志业务 ====================================================== |
|||
|
|||
// 分页设置 |
|||
const pagination = ref({ |
|||
pageSize: 10, |
|||
pageNum: 1, |
|||
total: 0, |
|||
}); |
|||
// 表格数据 |
|||
const dataSource = ref([]); |
|||
// 当前选中表格行 |
|||
let trIndex = ref(-1); |
|||
// 获得表格数据 |
|||
const getTable = (changePage = false) => { |
|||
state.setLoading(true); |
|||
// 如果是切换页面,则清除当前序列、关闭弹窗 |
|||
if (changePage) { |
|||
trIndex.value = -1; |
|||
logModalVisible.value = false; |
|||
pumpLogList.value.length = 0; |
|||
valveLogList.value.length = 0; |
|||
} |
|||
http |
|||
.get(waterSys.getLog, { |
|||
pageSize: pagination.value.pageSize, |
|||
pageNum: pagination.value.pageNum, |
|||
}) |
|||
.then((res) => { |
|||
state.setLoading(false); |
|||
let data = res.data; |
|||
dataSource.value = data.records; |
|||
pagination.value.total = data.total; |
|||
}) |
|||
.catch(() => { |
|||
state.setLoading(false); |
|||
}); |
|||
}; |
|||
// 刷新功能(右下角) |
|||
const reset = () => { |
|||
trIndex.value = -1; |
|||
logModalVisible.value = false; |
|||
pagination.value = { |
|||
pageSize: 10, |
|||
pageNum: 1, |
|||
total: 0, |
|||
}; |
|||
getTable(); |
|||
}; |
|||
// 点击日志行事件 |
|||
const handleRowClick = (id: any, index: any) => { |
|||
trIndex.value = index; |
|||
getLogDetail(id); |
|||
}; |
|||
|
|||
// 日志详情业务 ================================================== |
|||
|
|||
// 日志详情显隐 |
|||
const logModalVisible = ref(false); |
|||
const getLogDetail = (id: any) => { |
|||
state.setLoading(true); |
|||
http |
|||
.get(waterSys.getLogDetail, { logId: id }) |
|||
.then((res) => { |
|||
state.setLoading(false); |
|||
const data = res.data; |
|||
if (data.pumpLogList.length || data.valveLogList.length) { |
|||
// 显示模态框 |
|||
logModalVisible.value = true; |
|||
pumpLogList.value = data.pumpLogList; |
|||
valveLogList.value = data.valveLogList; |
|||
} else { |
|||
return message.info('返回值无效'); |
|||
} |
|||
}) |
|||
.catch(() => { |
|||
state.setLoading(false); |
|||
}); |
|||
}; |
|||
// 当前选中的设备类型 阀门=1/水泵=2 |
|||
const activeButton = ref(1); |
|||
// 切换设备类型 |
|||
const changeBtn = (key: number) => { |
|||
activeButton.value = key; |
|||
}; |
|||
// 水泵数据 |
|||
const pumpLogList = ref<any>([]); |
|||
// 水阀数据 |
|||
const valveLogList = ref<any>([]); |
|||
|
|||
// 向外暴露方法 |
|||
defineExpose({ |
|||
reset, |
|||
}); |
|||
</script> |
|||
<style lang="less" scoped> |
|||
@import '../../style/dialogStyle.less'; |
|||
|
|||
// 右下角添加按钮 |
|||
.div-add { |
|||
height: 64px; |
|||
display: flex; |
|||
justify-content: flex-end; |
|||
align-items: center; |
|||
position: fixed; |
|||
bottom: 0; |
|||
right: 0; |
|||
margin-right: 20px; |
|||
.add { |
|||
width: 74px; |
|||
height: 40px; |
|||
opacity: 1; |
|||
border-radius: 4px; |
|||
background: rgba(67, 136, 251, 1); |
|||
border: rgba(67, 136, 251, 1); |
|||
font-size: 14px; |
|||
font-weight: 400; |
|||
color: rgba(255, 255, 255, 1); |
|||
cursor: pointer; |
|||
} |
|||
} |
|||
|
|||
// 表格 |
|||
.custom-table { |
|||
border-collapse: collapse; |
|||
width: 416px; |
|||
min-height: 60px; |
|||
max-height: 500px; |
|||
overflow-y: auto; |
|||
cursor: pointer; |
|||
color: rgba(255, 255, 255, 1); |
|||
} |
|||
|
|||
.custom-table th, |
|||
.custom-table td { |
|||
border: 1px solid rgba(163, 192, 243, 1); |
|||
text-align: left; |
|||
padding: 8px; |
|||
text-align: center; |
|||
} |
|||
|
|||
.table1 { |
|||
margin-top: 20px; |
|||
width: 100%; |
|||
border: 1px solid rgba(255, 255, 255); |
|||
border-radius: 5px; |
|||
background: rgba(255, 255, 255, 0.1); |
|||
|
|||
.tabReboot, |
|||
.tabDelete { |
|||
border: none; |
|||
background-color: rgba(0, 0, 0, 0); |
|||
font-size: 14px; |
|||
font-weight: 400; |
|||
letter-spacing: 0; |
|||
line-height: 20px; |
|||
color: rgba(67, 136, 251, 1); |
|||
} |
|||
|
|||
.tabReboot { |
|||
margin-right: 8px; |
|||
} |
|||
|
|||
.isTrIndex { |
|||
background: rgba(67, 136, 251, 1); |
|||
} |
|||
} |
|||
|
|||
::v-deep(.ant-transfer) { |
|||
// 屏蔽自带的hover效果 |
|||
.ant-transfer-list-content-item:hover { |
|||
background: black; |
|||
} |
|||
} |
|||
|
|||
.btn { |
|||
width: 92px; |
|||
height: 40px; |
|||
border-radius: 4px; |
|||
opacity: 1; |
|||
margin-top: 10px; |
|||
margin-left: 15px; |
|||
font-size: 14px; |
|||
font-weight: 400; |
|||
opacity: 1; |
|||
border: 1px solid rgba(207, 212, 219, 1); |
|||
line-height: 20.27px; |
|||
color: white; |
|||
text-align: center; |
|||
vertical-align: top; |
|||
background-color: rgba(255, 255, 255, 0.1); |
|||
} |
|||
|
|||
.selected { |
|||
background: linear-gradient(180deg, rgba(201, 245, 255, 1) 0%, rgba(138, 215, 255, 1) 100%); |
|||
color: rgba(0, 61, 90, 1); |
|||
border: 1px solid white; |
|||
} |
|||
|
|||
.btn:hover { |
|||
background-color: rgba(207, 212, 219, 1); |
|||
} |
|||
|
|||
.btn:active { |
|||
background-color: rgba(102, 102, 102, 1); |
|||
color: white; |
|||
} |
|||
.device-list { |
|||
margin-left: 15px; |
|||
margin-top: 15px; |
|||
width: calc(100% - 15px); |
|||
font-size: 13px; |
|||
height: auto; |
|||
display: flex; |
|||
gap: 15px; |
|||
flex-direction: column; |
|||
.device-list-item { |
|||
width: calc(100% - 15px); |
|||
box-sizing: border-box; |
|||
padding: 10px; |
|||
border: 2px solid #03407e; |
|||
border-radius: 4px; |
|||
background: rgba(0, 177, 255, 0.2); |
|||
display: flex; |
|||
gap: 10px; |
|||
flex-direction: column; |
|||
.list-item-title { |
|||
color: white; |
|||
display: flex; |
|||
justify-content: space-between; |
|||
.item-title { |
|||
img { |
|||
width: 25px; |
|||
} |
|||
span { |
|||
margin-left: 10px; |
|||
font-size: 16px; |
|||
} |
|||
} |
|||
.revoke { |
|||
text-align: center; |
|||
border: none; |
|||
border-radius: 4px; |
|||
padding: 5px 15px; |
|||
background: linear-gradient( |
|||
180deg, |
|||
rgba(255, 187, 0, 1) 0%, |
|||
rgba(255, 112, 3, 1) 91.21%, |
|||
rgba(255, 129, 3, 1) 100% |
|||
); |
|||
cursor: pointer; |
|||
} |
|||
} |
|||
.list-item-main { |
|||
display: flex; |
|||
> div { |
|||
flex: 1; |
|||
display: flex; |
|||
gap: 8px; |
|||
> .info { |
|||
text-align: center; |
|||
width: 6em; |
|||
height: 2.5em; |
|||
line-height: 2.5em; |
|||
border-radius: 4px; |
|||
color: white; |
|||
background: linear-gradient( |
|||
180deg, |
|||
rgba(86, 221, 253, 1) 0%, |
|||
rgba(25, 176, 255, 1) 100% |
|||
); |
|||
} |
|||
> .text { |
|||
:first-child { |
|||
color: white; |
|||
line-height: 2.5em; |
|||
} |
|||
img { |
|||
padding: 0 5px; |
|||
} |
|||
:last-child { |
|||
line-height: 2.5em; |
|||
color: red; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,381 @@ |
|||
<template> |
|||
<div class="div-add"> |
|||
<button class="add" @click="addModal">添加</button> |
|||
<a-popconfirm |
|||
title="是否提交以上修改?" |
|||
placement="bottomLeft" |
|||
ok-text="确定" |
|||
cancel-text="取消" |
|||
@confirm="sendTable"> |
|||
<button class="add" style="margin-left: 20px">执行</button> |
|||
</a-popconfirm> |
|||
</div> |
|||
<div class="buttons"> |
|||
<span style="color: red; padding-top: 20px">*以下修改需执行后生效</span> |
|||
<div class="plans"> |
|||
<button class="plan enabled" style="margin-right: 10px" @click="togglePlan(1)"> |
|||
计划启用 |
|||
</button> |
|||
<button class="plan disabled" @click="togglePlan(3)"> 计划禁用 </button> |
|||
</div> |
|||
</div> |
|||
<table class="custom-table table1"> |
|||
<thead> |
|||
<tr :style="{ background: 'rgba(35,45,69)' }"> |
|||
<th>序号</th> |
|||
<th>执行时间</th> |
|||
<th>计划名称</th> |
|||
<th>状态</th> |
|||
<th>操作</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<tr v-for="(row, index) in dataSource" v-show="row.executeStatus.value != 0" :key="index"> |
|||
<td>{{ index + 1 }}</td> |
|||
<td>{{ row.startTime }}</td> |
|||
<td>{{ row.planName }}</td> |
|||
<td> |
|||
<button |
|||
:style="{ |
|||
'font-size': '12px', |
|||
width: '5em', |
|||
background: 'rgb(47, 47, 47)', |
|||
color: setStateColor(row.executeStatus.value), |
|||
border: '1px solid', |
|||
}"> |
|||
{{ setStateText(row.executeStatus.value) }} |
|||
</button> |
|||
</td> |
|||
<td> |
|||
<div class="tabReboot" @click="startPlan(row)">启用</div> |
|||
<a-popconfirm |
|||
title="此操作将移除该数据" |
|||
ok-text="确定" |
|||
cancel-text="取消" |
|||
placement="topRight" |
|||
@confirm="deletePlan(row)"> |
|||
<div class="tabDelete">删除</div> |
|||
</a-popconfirm> |
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
<div class="out-dialog" v-if="addVisible"> |
|||
<div class="content"> |
|||
<div class="div-operation"></div> |
|||
<span class="text-operation">计划库</span> |
|||
</div> |
|||
<div style="margin-top: 20px"> |
|||
<a-transfer |
|||
v-model:target-keys="targetKeys" |
|||
:data-source="transferData" |
|||
show-search |
|||
:filter-option="filterOption" |
|||
:render="(item: any) => item.title" |
|||
@change="handleChange" |
|||
:style="{ color: 'rgba(255,255,255,1)' }" |
|||
@search="handleSearch" |
|||
:listStyle="{ border: '2px solid rgba(25,74,125,1)', height: 'calc(100vh - 200px)' }" /> |
|||
</div> |
|||
<div style="width: 100%; height: 60px"></div> |
|||
<div class="button-box"> |
|||
<button class="cancel" @click="addVisible = false">取消</button> |
|||
<button class="execute" @click="sendPlan">确定</button> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, onMounted } from 'vue'; |
|||
// 请求 |
|||
import { http } from '/nerv-lib/util/http'; |
|||
import { planManage } from '/@/api/planManage'; |
|||
import { waterSys } from '/@/api/waterSystem'; |
|||
import { message } from 'ant-design-vue'; |
|||
import { getEnum } from '/@/api'; |
|||
// 全局变量 |
|||
import { items } from '/@/store/item'; |
|||
|
|||
// 初始化 =========================================================== |
|||
|
|||
onMounted(() => { |
|||
// 获得枚举 |
|||
getStateEnum(); |
|||
// 获得穿梭框 与 表格数据 |
|||
reset(); |
|||
}); |
|||
// 全局变量 |
|||
const state = items(); |
|||
// 获得任务状态枚举 |
|||
const getStateEnum = async () => { |
|||
let enumData = await getEnum({ params: { enumType: 'PlanExecuteStatus' } }); |
|||
stateList.value = enumData.data; |
|||
}; |
|||
/** |
|||
* @method resetAll 刷新3个tab中的全部数据(修改计划,会影响tab1数据信息,生成tab3日志) |
|||
*/ |
|||
const emit = defineEmits(['resetAll']); |
|||
|
|||
// tab页部分 ======================================================== |
|||
|
|||
// 状态枚举 |
|||
const stateList = ref([]); |
|||
// 设置枚举的颜色 与 文本 |
|||
const setStateColor = (state: number) => { |
|||
if (state == 0) { |
|||
return '#ccc'; |
|||
} else if (state == 1) { |
|||
return 'orange'; |
|||
} else if (state == 2) { |
|||
return 'rgb(57, 215, 187)'; |
|||
} else if (state == 3) { |
|||
return 'rgb(255, 0, 0)'; |
|||
} |
|||
}; |
|||
// 设置枚举的文本 |
|||
const setStateText = (state: number) => { |
|||
const res = stateList.value.find((item) => { |
|||
return item.value == state; |
|||
}); |
|||
return res.label; |
|||
}; |
|||
// 计划启用/禁用事件 |
|||
const togglePlan = (state: number) => { |
|||
dataSource.value.forEach((item: any) => { |
|||
// 执行中 无法修改为待执行 |
|||
if (state == 1) { |
|||
if (item.executeStatus.value != 2) { |
|||
item.executeStatus.value = state; |
|||
} |
|||
// 任何状态都可以修改为 暂停 |
|||
} else { |
|||
item.executeStatus.value = state; |
|||
} |
|||
}); |
|||
}; |
|||
|
|||
// 表格数据 |
|||
const dataSource = ref([]); |
|||
// 获得表格数据 |
|||
const getTable = () => { |
|||
http |
|||
.get(planManage.getTableData, { |
|||
projectId: state.projectId, |
|||
siteId: state.siteId, |
|||
// 设备类型(1照明,2空调,3排风扇,4风幕机,5电动窗,6给排水) |
|||
ctrlType: 6, |
|||
}) |
|||
.then((res) => { |
|||
dataSource.value = res.data; |
|||
}); |
|||
}; |
|||
// 删除表格中的计划(将当前任意状态,修改为未启用 =0) |
|||
const deletePlan = (row: any) => { |
|||
row.executeStatus.value = 0; |
|||
}; |
|||
// 重启表格中的计划(将当前任意状态,修改为待执行 = 1) |
|||
const startPlan = (row: any) => { |
|||
if (row.executeStatus.value == 1) { |
|||
return message.info('该数据已是待执行状态,无需再次修改'); |
|||
} |
|||
if (row.executeStatus.value == 2) { |
|||
return message.info('执行中的状态已被启用,无需修改'); |
|||
} |
|||
row.executeStatus.value = 1; |
|||
}; |
|||
// 将对表格的修改统一发送 |
|||
const sendTable = () => { |
|||
if (!dataSource.value.length) { |
|||
return message.info('没有任何数据可以提交'); |
|||
} |
|||
state.setLoading(true); |
|||
http |
|||
.post( |
|||
waterSys.submitTableData + |
|||
`?projectId=${state.projectId}${state.siteId ? `&siteId=${state.siteId}` : ''}`, |
|||
dataSource.value, |
|||
) |
|||
.then((res) => { |
|||
state.setLoading(false); |
|||
if (res.retcode == 0) { |
|||
message.success('操作成功'); |
|||
// 刷新数据 |
|||
emit('resetAll'); |
|||
} else { |
|||
message.info(res.msg); |
|||
} |
|||
}) |
|||
.catch(() => { |
|||
state.setLoading(false); |
|||
}); |
|||
}; |
|||
|
|||
const reset = () => { |
|||
// 计划表格 |
|||
getTable(); |
|||
// 穿梭框原始数据 |
|||
getLeftPlan(); |
|||
}; |
|||
|
|||
// tab页弹窗部分 ==================================================== |
|||
|
|||
// 添加弹窗控制变量 |
|||
const addVisible = ref(false); |
|||
// 打开弹窗 |
|||
const addModal = () => { |
|||
addVisible.value = true; |
|||
}; |
|||
|
|||
// 穿梭框部分 ======================================================= |
|||
|
|||
// 穿梭框数据 |
|||
const transferData = ref([]) as any; |
|||
// 获得穿梭框原始数据 |
|||
const getLeftPlan = () => { |
|||
http |
|||
.get(planManage.getTransData, { |
|||
projectId: state.projectId, |
|||
siteId: state.siteId, |
|||
// 设备类型(1照明,2空调,3排风扇,4风幕机,5电动窗,6给排水) |
|||
ctrlType: 6, |
|||
}) |
|||
.then((res) => { |
|||
let arr: Array<Object> = []; |
|||
res.data.forEach((item: any) => { |
|||
arr.push({ |
|||
key: item.id, |
|||
title: item.planName, |
|||
}); |
|||
}); |
|||
transferData.value = arr; |
|||
}); |
|||
}; |
|||
|
|||
const handleChange = (keys: string[], direction: string, moveKeys: string[]) => { |
|||
console.log(keys, direction, moveKeys); |
|||
}; |
|||
const handleSearch = (dir: string, value: string) => { |
|||
console.log('search:', dir, value); |
|||
}; |
|||
// 穿梭框选中数据 |
|||
const targetKeys = ref<string[]>([]); |
|||
// 将穿梭框选中的计划提交 |
|||
const sendPlan = () => { |
|||
if (targetKeys.value.length < 1) { |
|||
return message.info('没有选择任何计划'); |
|||
} |
|||
http.post(planManage.submitTransData, targetKeys.value).then(() => { |
|||
message.success('添加成功'); |
|||
// 如果发送成功,则刷新表格 |
|||
reset(); |
|||
}); |
|||
}; |
|||
|
|||
const filterOption = (inputValue: string, option: any) => { |
|||
return option.description.indexOf(inputValue) > -1; |
|||
}; |
|||
|
|||
// 向外暴露方法 |
|||
defineExpose({ |
|||
reset, |
|||
}); |
|||
</script> |
|||
<style lang="less" scoped> |
|||
@import '../../style/dialogStyle.less'; |
|||
.buttons { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
.plan { |
|||
border: none; |
|||
font-size: 14px; |
|||
font-weight: 400; |
|||
border-radius: 5px; |
|||
width: 88px; |
|||
height: 32px; |
|||
color: white; |
|||
cursor: pointer; |
|||
margin: 15px 0; |
|||
vertical-align: middle; |
|||
} |
|||
.plan.enabled { |
|||
background: linear-gradient(180deg, rgba(103, 222, 0, 1) 0%, rgba(0, 181, 6, 1) 100%); |
|||
} |
|||
.plan.disabled { |
|||
background-color: red; |
|||
} |
|||
.plan:disabled { |
|||
cursor: not-allowed; |
|||
} |
|||
} |
|||
// 右下角添加按钮 |
|||
.div-add { |
|||
height: 64px; |
|||
display: flex; |
|||
justify-content: flex-end; |
|||
align-items: center; |
|||
position: fixed; |
|||
bottom: 0; |
|||
right: 0; |
|||
margin-right: 10px; |
|||
.add { |
|||
width: 74px; |
|||
height: 40px; |
|||
opacity: 1; |
|||
border-radius: 4px; |
|||
background: rgba(67, 136, 251, 1); |
|||
border: rgba(67, 136, 251, 1); |
|||
font-size: 14px; |
|||
font-weight: 400; |
|||
color: rgba(255, 255, 255, 1); |
|||
cursor: pointer; |
|||
} |
|||
} |
|||
// 表格 |
|||
.custom-table { |
|||
border-collapse: collapse; |
|||
width: 416px; |
|||
height: 40px; |
|||
color: rgba(255, 255, 255, 1); |
|||
} |
|||
.custom-table th, |
|||
.custom-table td { |
|||
border: 1px solid rgba(163, 192, 243, 1); |
|||
text-align: left; |
|||
padding: 8px; |
|||
text-align: center; |
|||
} |
|||
.table1 { |
|||
width: 100%; |
|||
border: 1px solid rgba(255, 255, 255); |
|||
border-radius: 5px; |
|||
background: rgba(255, 255, 255, 0.1); |
|||
// 表格中的操作按钮 |
|||
.tabReboot, |
|||
.tabDelete { |
|||
border: none; |
|||
display: inline-block; |
|||
background-color: rgba(0, 0, 0, 0); |
|||
font-size: 14px; |
|||
font-weight: 400; |
|||
letter-spacing: 0; |
|||
line-height: 20px; |
|||
color: rgba(67, 136, 251, 1); |
|||
cursor: pointer; |
|||
} |
|||
.tabReboot { |
|||
margin-right: 8px; |
|||
} |
|||
.tabReboot::active { |
|||
color: white !important; |
|||
} |
|||
.tabDelete::active { |
|||
color: white; |
|||
} |
|||
} |
|||
::v-deep(.ant-transfer) { |
|||
// 屏蔽自带的hover效果 |
|||
.ant-transfer-list-content-item:hover { |
|||
background: black; |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,282 @@ |
|||
import { ref } from 'vue'; |
|||
// 流动线条样式与定位
|
|||
export const linePosition = [ |
|||
// 雨水池 - 控制阀
|
|||
{ |
|||
left: '4%', |
|||
top: '44%', |
|||
transform: 'rotateZ(-30deg)', |
|||
transformOrigin: 'left', |
|||
zIndex: '6', |
|||
width: '6%', |
|||
}, |
|||
{ |
|||
left: '4%', |
|||
top: '84%', |
|||
transform: 'rotateZ(-30deg)', |
|||
transformOrigin: 'left', |
|||
zIndex: '6', |
|||
width: '6%', |
|||
}, |
|||
// 控制阀 - 进水阀
|
|||
{ left: '12%', top: '34%', width: '10%' }, |
|||
{ left: '12%', top: '74%', width: '10%' }, |
|||
// 进水阀 - 集水池
|
|||
{ left: '23%', top: '34%', width: '8%' }, |
|||
{ left: '23%', top: '74%', width: '8%' }, |
|||
// 集水池 - 排水泵 - 横线
|
|||
{ left: '35%', top: '34%', width: '4%' }, |
|||
{ left: '35%', top: '74%', width: '4%' }, |
|||
// 上半集水池右侧分线
|
|||
{ left: '39%', top: '34%', transform: 'rotateZ(90deg)', transformOrigin: 'left', width: '4%' }, |
|||
{ left: '39%', top: '34%', transform: 'rotateZ(-90deg)', transformOrigin: 'left', width: '4%' }, |
|||
// 下半集水池右侧分线
|
|||
{ left: '39%', top: '74%', transform: 'rotateZ(90deg)', transformOrigin: 'left', width: '4%' }, |
|||
{ left: '39%', top: '74%', transform: 'rotateZ(-90deg)', transformOrigin: 'left', width: '4%' }, |
|||
// 上半-左侧水泵分线
|
|||
{ left: '39%', top: '25%', width: '8%' }, |
|||
{ left: '39%', top: '43%', width: '8%' }, |
|||
// 下半-左侧水泵分线
|
|||
{ left: '39%', top: '65%', width: '8%' }, |
|||
{ left: '39%', top: '83%', width: '8%' }, |
|||
// 水泵右侧合线 下半
|
|||
{ left: '47%', top: '83%', transform: 'rotateZ(-90deg)', transformOrigin: 'left', width: '14%' }, |
|||
// 水泵右侧合线 上半
|
|||
{ left: '47%', top: '25%', transform: 'rotateZ(90deg)', transformOrigin: 'left', width: '12%' }, |
|||
// 汇入总闸连线
|
|||
{ left: '47%', top: '52%', width: '4%' }, |
|||
// 汇入总集水池
|
|||
{ left: '51%', top: '52%', transform: 'rotateZ(-25deg)', transformOrigin: 'left', width: '7%' }, |
|||
// 汇入总排水闸
|
|||
{ left: '58%', top: '45%', width: '9%' }, |
|||
// 汇入市政管道 - 途径水泵2
|
|||
{ left: '68%', top: '45%', width: '28%' }, |
|||
// 总排水闸 - 总排水泵1 上半
|
|||
{ left: '75%', top: '45%', transform: 'rotateZ(-90deg)', transformOrigin: 'left', width: '10%' }, |
|||
{ left: '75%', top: '23%', width: '11%' }, |
|||
{ left: '86%', top: '22.5%', transform: 'rotateZ(90deg)', transformOrigin: 'left', width: '10%' }, |
|||
// 总排水闸 - 总排水泵3 下半
|
|||
{ left: '75%', top: '45%', transform: 'rotateZ(90deg)', transformOrigin: 'left', width: '9%' }, |
|||
{ left: '75%', top: '65%', width: '11%' }, |
|||
{ |
|||
left: '86%', |
|||
top: '65%', |
|||
transform: 'rotateZ(-90deg)', |
|||
transformOrigin: 'left', |
|||
width: '9%', |
|||
}, |
|||
]; |
|||
|
|||
/** |
|||
* 1. 设备数量是固定的 |
|||
* 2. 设备顺序是固定的 |
|||
* 3. 此处数据用于渲染设备图标,后端返回数据后,将依次插入 |
|||
* @param icon 决定调用的设备图标:污水池=1/集水池=2/控制阀=3//进水阀=4//排水泵=5
|
|||
* @param type 设备类型:污水池=1/阀门=2/集水池=3/水泵=4 |
|||
* @param open 水泵的开关状态 开=true/关=false |
|||
* @param control 是否可以被操作(是否显示顶部按钮,水池为false) |
|||
* @param edited 是否已经被编辑(决定显示编辑 或 撤销) |
|||
*/ |
|||
// 污水池
|
|||
export const device1 = ref([ |
|||
{ |
|||
control: false, |
|||
type: 1, |
|||
icon: 1, |
|||
styleObject: { |
|||
left: '1%', |
|||
top: '40%', |
|||
zIndex: '9', |
|||
}, |
|||
}, |
|||
{ |
|||
control: false, |
|||
type: 1, |
|||
icon: 1, |
|||
styleObject: { |
|||
left: '1%', |
|||
top: '80%', |
|||
zIndex: '9', |
|||
}, |
|||
}, |
|||
]); |
|||
// 阀门
|
|||
export const device2 = ref([ |
|||
{ |
|||
control: true, |
|||
open: true, |
|||
type: 2, |
|||
icon: 3, |
|||
edited: false, |
|||
styleObject: { |
|||
left: '8%', |
|||
top: '28%', |
|||
}, |
|||
}, |
|||
{ |
|||
control: true, |
|||
open: false, |
|||
type: 2, |
|||
icon: 3, |
|||
edited: false, |
|||
styleObject: { |
|||
left: '8%', |
|||
top: '68%', |
|||
}, |
|||
}, |
|||
{ |
|||
control: true, |
|||
open: true, |
|||
type: 2, |
|||
icon: 4, |
|||
edited: false, |
|||
styleObject: { |
|||
left: '20%', |
|||
top: '28%', |
|||
}, |
|||
}, |
|||
{ |
|||
control: true, |
|||
open: true, |
|||
type: 2, |
|||
icon: 4, |
|||
edited: false, |
|||
styleObject: { |
|||
left: '20%', |
|||
top: '68%', |
|||
}, |
|||
}, |
|||
{ |
|||
control: true, |
|||
open: true, |
|||
type: 2, |
|||
icon: 3, |
|||
edited: false, |
|||
styleObject: { |
|||
left: '48%', |
|||
top: '46%', |
|||
}, |
|||
}, |
|||
{ |
|||
control: true, |
|||
open: true, |
|||
type: 2, |
|||
icon: 3, |
|||
edited: false, |
|||
styleObject: { |
|||
left: '65%', |
|||
top: '38%', |
|||
}, |
|||
}, |
|||
]); |
|||
// 集水池
|
|||
export const device3 = ref([ |
|||
{ |
|||
control: false, |
|||
type: 3, |
|||
icon: 2, |
|||
styleObject: { |
|||
left: '30%', |
|||
top: '68%', |
|||
}, |
|||
}, |
|||
{ |
|||
control: false, |
|||
type: 3, |
|||
icon: 2, |
|||
styleObject: { |
|||
left: '30%', |
|||
top: '28%', |
|||
}, |
|||
}, |
|||
{ |
|||
control: false, |
|||
type: 3, |
|||
icon: 2, |
|||
styleObject: { |
|||
left: '56%', |
|||
top: '40%', |
|||
}, |
|||
}, |
|||
]); |
|||
// 水泵
|
|||
export const device4 = ref([ |
|||
{ |
|||
control: true, |
|||
open: false, |
|||
type: 4, |
|||
icon: 5, |
|||
edited: false, |
|||
styleObject: { |
|||
left: '40%', |
|||
top: '20%', |
|||
}, |
|||
}, |
|||
{ |
|||
control: true, |
|||
open: true, |
|||
type: 4, |
|||
icon: 5, |
|||
edited: false, |
|||
styleObject: { |
|||
left: '40%', |
|||
top: '40%', |
|||
}, |
|||
}, |
|||
{ |
|||
control: true, |
|||
open: true, |
|||
type: 4, |
|||
icon: 5, |
|||
edited: false, |
|||
styleObject: { |
|||
left: '40%', |
|||
top: '60%', |
|||
}, |
|||
}, |
|||
{ |
|||
control: true, |
|||
open: true, |
|||
type: 4, |
|||
icon: 5, |
|||
edited: false, |
|||
styleObject: { |
|||
left: '40%', |
|||
top: '80%', |
|||
}, |
|||
}, |
|||
// 右上3水泵
|
|||
{ |
|||
control: true, |
|||
open: true, |
|||
type: 4, |
|||
icon: 5, |
|||
edited: false, |
|||
styleObject: { |
|||
left: '78%', |
|||
top: '20%', |
|||
}, |
|||
}, |
|||
{ |
|||
control: true, |
|||
open: true, |
|||
type: 4, |
|||
icon: 5, |
|||
edited: false, |
|||
styleObject: { |
|||
left: '78%', |
|||
top: '40%', |
|||
}, |
|||
}, |
|||
{ |
|||
control: true, |
|||
open: true, |
|||
type: 4, |
|||
icon: 5, |
|||
edited: false, |
|||
styleObject: { |
|||
left: '78%', |
|||
top: '60%', |
|||
}, |
|||
}, |
|||
]); |
@ -0,0 +1,150 @@ |
|||
<template> |
|||
<div class="left-top"> |
|||
<div class="info"> |
|||
<div class="title-item"> |
|||
<div class="title-back">设备状态</div> |
|||
</div> |
|||
<div class="info-item"> |
|||
<div v-for="(item, index) in deviceState" :key="index"> |
|||
<img v-if="item.type == props.state" :src="item.icon" alt="" /> |
|||
<img v-else :src="item.default" alt="" /> |
|||
<div class="mode-item-text">{{ item.name }}</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="mode"> |
|||
<div class="title-item"> |
|||
<div class="title-back">控制模式</div> |
|||
<div class="title-button">计划启用</div> |
|||
</div> |
|||
<div class="mode-item"></div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref, onMounted } from 'vue'; |
|||
// 全局变量 |
|||
import { items } from '/@/store/item'; |
|||
// 图像资源引入 |
|||
import type1 from './images/type1.png'; |
|||
import type2 from './images/type2.png'; |
|||
import type3 from './images/type3.png'; |
|||
import type1off from './images/type1off.png'; |
|||
import type2off from './images/type2off.png'; |
|||
import type3off from './images/type3off.png'; |
|||
// 传入的值 |
|||
const props = defineProps({ |
|||
// 设备状态 |
|||
state: { |
|||
type: Number, |
|||
}, |
|||
}); |
|||
const deviceState = [ |
|||
{ |
|||
icon: type1, |
|||
default: type1off, |
|||
name: '运行', |
|||
type: 1, |
|||
}, |
|||
{ |
|||
icon: type2, |
|||
default: type2off, |
|||
name: '故障', |
|||
type: 2, |
|||
}, |
|||
{ |
|||
icon: type3, |
|||
default: type3off, |
|||
name: '强排', |
|||
type: 3, |
|||
}, |
|||
]; |
|||
//页面 创建 |
|||
onMounted(() => {}); |
|||
</script> |
|||
<style lang="less" scoped> |
|||
.left-top { |
|||
--pad: 12px; |
|||
position: absolute; |
|||
left: var(--pad); |
|||
top: var(--pad); |
|||
width: auto; |
|||
height: 110px; |
|||
display: flex; |
|||
z-index: 99; |
|||
gap: var(--pad); |
|||
> div { |
|||
background: black; |
|||
display: flex; |
|||
flex-direction: column; |
|||
gap: 3px; |
|||
box-sizing: border-box; |
|||
padding: 10px; |
|||
border-radius: 4px; |
|||
.title-item { |
|||
padding: 5px; |
|||
position: relative; |
|||
.title-back { |
|||
margin-left: 10px; |
|||
padding-left: 5px; |
|||
background: linear-gradient(to right, #1aaefb, transparent); |
|||
width: 7em; |
|||
color: white; |
|||
position: relative; |
|||
font-size: 14px; |
|||
vertical-align: middle; |
|||
} |
|||
.title-back::before { |
|||
position: absolute; |
|||
content: ''; |
|||
display: block; |
|||
width: 5px; |
|||
height: 100%; |
|||
left: -12px; |
|||
background: #1aaefb; |
|||
} |
|||
.title-button { |
|||
position: absolute; |
|||
right: 2px; |
|||
top: 2px; |
|||
padding: 3px 8px; |
|||
color: white; |
|||
border-radius: 4px; |
|||
user-select: none; |
|||
cursor: pointer; |
|||
background: linear-gradient(180deg, rgba(103, 222, 0, 1) 0%, rgba(0, 181, 6, 1) 100%); |
|||
} |
|||
} |
|||
} |
|||
// 设备状态 |
|||
.info { |
|||
width: 230px; |
|||
.info-item { |
|||
display: flex; |
|||
padding-top: 3px; |
|||
div { |
|||
flex: 1; |
|||
display: flex; |
|||
flex-direction: column; |
|||
gap: 5px; |
|||
align-items: center; |
|||
.mode-item-text { |
|||
color: white; |
|||
user-select: none; |
|||
} |
|||
img { |
|||
width: 23px; |
|||
display: block; |
|||
user-select: none; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
// 控制模式 |
|||
.mode { |
|||
width: 200px; |
|||
.mode-item { |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,291 @@ |
|||
<template> |
|||
<div class="deviceItem" :style="info.styleObject"> |
|||
<!-- 点击编辑弹出框 --> |
|||
<a-popover |
|||
color="rgba(0, 0, 0, 0.8)" |
|||
placement="right" |
|||
v-model:visible="visible" |
|||
trigger="click"> |
|||
<template #content> |
|||
<div class="item-box"> |
|||
<div class="item-box-title"> |
|||
<img v-if="info.type == 2" src="./images/device1.png" alt="" /> |
|||
<img v-if="info.type == 4" src="./images/device2.png" alt="" /> |
|||
<span>{{ info.name }}</span> |
|||
</div> |
|||
<!-- 开关 --> |
|||
<div v-if="info.type == 4" class="item-box-switch"> |
|||
<div>开关</div> |
|||
<a-switch style="margin-top: 3px" size="small" v-model:checked="info.open" /> |
|||
</div> |
|||
<div v-if="info.type == 2" class="item-box-range"> |
|||
<div>开度</div> |
|||
<!-- <a-slider v-model:value="info.value" :tooltip-visible="true" :marks="range" :step="1"> --> |
|||
<a-slider v-model:value="info.value" :marks="range" :step="1"> |
|||
<template #mark="{ label, point }"> |
|||
<template v-if="point === 100"> |
|||
<strong>{{ label }}</strong> |
|||
</template> |
|||
<template v-else>{{ label }}</template> |
|||
</template> |
|||
</a-slider> |
|||
</div> |
|||
<div v-if="info.type == 4" class="item-box-range"> |
|||
<div>频率</div> |
|||
<a-slider v-model:value="info.value" :marks="range" :step="1"> |
|||
<template #mark="{ label, point }"> |
|||
<template v-if="point === 100"> |
|||
<strong>{{ label }}</strong> |
|||
</template> |
|||
<template v-else>{{ label }}</template> |
|||
</template> |
|||
</a-slider> |
|||
</div> |
|||
<div class="item-box-button"> |
|||
<a-button class="item-btn" @click="refresh">刷新</a-button> |
|||
<a-popconfirm |
|||
title="此操作只保存修改,需右下角按钮提交" |
|||
ok-text="确定" |
|||
cancel-text="取消" |
|||
@confirm="editDevice"> |
|||
<a-button class="item-btn" type="primary">执行</a-button> |
|||
</a-popconfirm> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
<div v-if="!info.edited && info.control" class="device-button-back"> |
|||
<img src="./images/edit.png" alt="" /> |
|||
编辑</div |
|||
> |
|||
</a-popover> |
|||
|
|||
<a-popconfirm |
|||
title="撤销将移除已保存的修改" |
|||
ok-text="确定" |
|||
cancel-text="取消" |
|||
@confirm="backConfirm"> |
|||
<div v-if="info.edited && info.control" class="device-button"> |
|||
<img src="./images/back.png" alt="" /> |
|||
撤销</div |
|||
> |
|||
</a-popconfirm> |
|||
<!-- 设备图标 - 当前共5种单位 --> |
|||
<img v-if="info.icon == 1" src="./images/pond1.png" alt="" /> |
|||
<img v-if="info.icon == 2" src="./images/pond2.png" alt="" /> |
|||
<img v-if="info.icon == 3" src="./images/valve1.png" alt="" /> |
|||
<img v-if="info.icon == 4" src="./images/valve2.png" alt="" /> |
|||
<img v-if="info.icon == 5" style="width: 70px; height: 70px" src="./images/pump.png" alt="" /> |
|||
<div class="info-name"> |
|||
<span>{{ info.name }}</span> |
|||
<div class="img-box"> |
|||
<img |
|||
v-if="(info.type == 2 || info.type == 4) && info.state == 0" |
|||
src="./images/alarm1.png" |
|||
alt="" /> |
|||
<img |
|||
v-if="(info.type == 2 || info.type == 4) && info.state > 0" |
|||
src="./images/alarm2.png" |
|||
alt="" /> |
|||
</div> |
|||
</div> |
|||
<!-- 只有水池会显示容量 --> |
|||
<div class="info-value" v-if="info.type == 1 || info.type == 3"> |
|||
容量 : {{ info.value + info.unit }}</div |
|||
> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref, onMounted, computed } from 'vue'; |
|||
import { message } from 'ant-design-vue'; |
|||
// 图像资源引入 |
|||
|
|||
// 初始化 =============================================================== |
|||
|
|||
//页面 创建 |
|||
onMounted(() => {}); |
|||
// 传入的值 |
|||
const props = defineProps({ |
|||
// 设备类型 |
|||
info: { |
|||
type: Object, |
|||
default: () => {}, |
|||
}, |
|||
}); |
|||
// 父组件传递的数据 |
|||
const info = computed(() => props.info); |
|||
|
|||
// 组件交互 ============================================================= |
|||
|
|||
// 用于控制弹窗的显示状态 |
|||
const visible = ref(false); |
|||
// 滑动条显示规则 |
|||
const range = ref({ |
|||
0: { |
|||
style: { |
|||
color: '#0DFFFF', |
|||
}, |
|||
label: 'min', |
|||
}, |
|||
100: { |
|||
style: { |
|||
color: '#0DFFFF', |
|||
}, |
|||
label: 'max', |
|||
}, |
|||
}); |
|||
// 刷新事件 |
|||
const refresh = () => { |
|||
info.value.value = info.value.oldVal; |
|||
}; |
|||
// 撤销事件 |
|||
const backConfirm = () => { |
|||
info.value.value = info.value.oldVal; |
|||
info.value.edited = false; |
|||
// 如果为水泵 |
|||
if (info.value.type == 4) { |
|||
console.log(info.value); |
|||
info.value.open = info.value.opened; |
|||
} |
|||
}; |
|||
// 编辑-执行事件 |
|||
const editDevice = () => { |
|||
// 未产生修改 |
|||
if (info.value.value == info.value.oldVal && info.value.open === info.value.opened) { |
|||
return message.info('未产生任何修改'); |
|||
} |
|||
// 产生修改 |
|||
visible.value = false; |
|||
info.value.edited = true; |
|||
message.success('保存成功'); |
|||
}; |
|||
</script> |
|||
<style lang="less" scoped> |
|||
// 设备的图像 |
|||
.deviceItem { |
|||
--size: 90px; |
|||
width: var(--size); |
|||
height: var(--size); |
|||
position: absolute; |
|||
top: 20%; |
|||
text-align: center; |
|||
// 默认使用3 |
|||
z-index: 3; |
|||
> img { |
|||
user-select: none; |
|||
} |
|||
// 设备名 |
|||
.info-name { |
|||
color: white; |
|||
font-size: 15px; |
|||
text-align: center; |
|||
position: relative; |
|||
> span { |
|||
vertical-align: middle; |
|||
} |
|||
.img-box { |
|||
display: inline-block; |
|||
position: absolute; |
|||
margin-left: 8px; |
|||
width: 22px; |
|||
> img { |
|||
width: 22px; |
|||
} |
|||
} |
|||
} |
|||
// 设备容量(仅水池) |
|||
.info-value { |
|||
text-align: center; |
|||
color: #23fdab; |
|||
font-size: 13px; |
|||
} |
|||
// 撤销按钮 |
|||
.device-button { |
|||
position: absolute; |
|||
top: -35px; |
|||
left: 0; |
|||
right: 0; |
|||
margin: auto; |
|||
width: 5em; |
|||
padding: 5px 0; |
|||
text-align: center; |
|||
border-radius: 4px; |
|||
font-weight: 700; |
|||
cursor: pointer; |
|||
background: linear-gradient(#ffd700, #ffa403); |
|||
color: #674330; |
|||
user-select: none; |
|||
> img { |
|||
width: 13px; |
|||
} |
|||
} |
|||
// 编辑按钮 |
|||
.device-button-back { |
|||
position: absolute; |
|||
top: -35px; |
|||
left: 0; |
|||
right: 0; |
|||
margin: auto; |
|||
width: 5em; |
|||
padding: 5px 0; |
|||
text-align: center; |
|||
border-radius: 4px; |
|||
font-weight: 700; |
|||
cursor: pointer; |
|||
background: linear-gradient(#00f92c, #00fe9f); |
|||
color: #003d5a; |
|||
user-select: none; |
|||
> img { |
|||
width: 13px; |
|||
} |
|||
} |
|||
> img { |
|||
width: 100%; |
|||
height: 100%; |
|||
} |
|||
} |
|||
// 弹出框样式 |
|||
.ant-popover-inner { |
|||
// 弹出框内部容器 |
|||
.item-box { |
|||
width: 250px; |
|||
display: flex; |
|||
flex-direction: column; |
|||
gap: 15px; |
|||
color: white; |
|||
img { |
|||
width: 20px; |
|||
margin-right: 10px; |
|||
vertical-align: middle; |
|||
} |
|||
} |
|||
// 开关控件 |
|||
.item-box-switch { |
|||
padding: 10px 15px; |
|||
display: flex; |
|||
justify-content: space-between; |
|||
border-radius: 4px; |
|||
background: rgba(67, 136, 251, 0.3); |
|||
.ant-switch-checked { |
|||
background: linear-gradient(180deg, rgba(1, 206, 255, 1) 0%, rgba(0, 150, 229, 1) 100%); |
|||
} |
|||
} |
|||
// 滑动条控件 |
|||
.item-box-range { |
|||
padding: 10px 15px 10px 15px; |
|||
box-sizing: border-box; |
|||
border-radius: 4px; |
|||
background: rgba(67, 136, 251, 0.3); |
|||
.ant-slider-handle { |
|||
border: 2px solid red !important; |
|||
} |
|||
} |
|||
// 底部按钮区 |
|||
.item-box-button { |
|||
text-align: right; |
|||
.item-btn { |
|||
text-align: center; |
|||
margin-left: 10px; |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,30 @@ |
|||
<template> |
|||
<div class="line-item" :style="position"></div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { computed } from 'vue'; |
|||
|
|||
// 传入的值 |
|||
const props = defineProps({ |
|||
// 线条 |
|||
position: { |
|||
type: Object, |
|||
default: () => {}, |
|||
}, |
|||
}); |
|||
const position = computed(() => { |
|||
return props.position; |
|||
}); |
|||
</script> |
|||
<style lang="less" scoped> |
|||
.line-item { |
|||
position: absolute; |
|||
height: 10px; |
|||
width: 250px; |
|||
z-index: 1; |
|||
background-image: url(./images/back.gif); |
|||
background-color: rgba(13, 255, 164, 0.3); |
|||
background-size: 200px 10px; |
|||
border-radius: 5px; |
|||
} |
|||
</style> |
After Width: | Height: | Size: 3.8 KiB |
@ -0,0 +1,663 @@ |
|||
<template> |
|||
<div class="main"> |
|||
<!-- 左上角设备信息面板 --> |
|||
<deviceInfo :state="deviceState" /> |
|||
<!-- 示意图 --> |
|||
<div class="map"> |
|||
<!-- 污水池图标 --> |
|||
<deviceItem v-for="(item, index) in device1" :key="index" :info="item" /> |
|||
<!-- 阀门图标 --> |
|||
<deviceItem v-for="(item, index) in device2" :key="index" :info="item" /> |
|||
<!-- 集水池图标 --> |
|||
<deviceItem v-for="(item, index) in device3" :key="index" :info="item" /> |
|||
<!-- 排水泵图标 --> |
|||
<deviceItem v-for="(item, index) in device4" :key="index" :info="item" /> |
|||
<!-- 市政管道图标 --> |
|||
<div class="pipe"> |
|||
<div>市政管道</div> |
|||
<img src="./images/pipe.png" alt="" /> |
|||
</div> |
|||
<!-- 设备图标底部连线 --> |
|||
<deviceLine v-for="(item, index) in linePosition" :key="index" :position="item" /> |
|||
</div> |
|||
<!-- 右下角按钮 --> |
|||
<div class="buttons"> |
|||
<a-button type="primary" @click="openDrawer1">执行</a-button> |
|||
<a-button type="primary" @click="resetAll">全部撤销</a-button> |
|||
</div> |
|||
<!-- 页面右侧抽屉开关 --> |
|||
<div class="right-button"> |
|||
<div>计划与日志</div> |
|||
<img @click="visible = true" src="./images/open.png" alt="" /> |
|||
</div> |
|||
<!-- 右侧 计划日志抽屉 --> |
|||
<a-drawer |
|||
v-model:visible="visible" |
|||
class="drawer-item" |
|||
width="496" |
|||
placement="right" |
|||
:body-style="{ background: 'rgba(0, 0, 0)', opacity: 0.8 }" |
|||
:closable="false" |
|||
id="drawer" |
|||
:maskStyle="{ 'background-color': 'rgba(0, 0, 0, 0)' }"> |
|||
<a-tabs v-model:activeKey="activeKey"> |
|||
<a-tab-pane key="1" tab="计划列表" force-render> |
|||
<planTab ref="tabs1Ref" @reset-all="resetDrawer" /> |
|||
</a-tab-pane> |
|||
<a-tab-pane key="2" tab="日志"> |
|||
<logTab ref="tabs2Ref" @reset-all="resetDrawer" /> |
|||
</a-tab-pane> |
|||
</a-tabs> |
|||
</a-drawer> |
|||
<!-- 右侧 操作队列 --> |
|||
<a-drawer |
|||
v-model:visible="visible1" |
|||
class="drawer-item" |
|||
width="496" |
|||
placement="right" |
|||
:body-style="{ background: 'rgba(0, 0, 0)', opacity: 0.8 }" |
|||
:closable="false" |
|||
id="drawer" |
|||
:maskStyle="{ 'background-color': 'rgba(0, 0, 0, 0)' }"> |
|||
<a-tabs v-model:activeKey="activeKey1"> |
|||
<a-tab-pane key="1" tab="操作队列" force-render> |
|||
<div> |
|||
<a-badge :offset="[-5, 12]" :count="valveList.length"> |
|||
<button :class="{ btn: true, selected: activeButton == 1 }" @click="changeBtn(1)" |
|||
>阀门</button |
|||
> |
|||
</a-badge> |
|||
<a-badge :offset="[-5, 12]" :count="pumpList.length"> |
|||
<button :class="{ btn: true, selected: activeButton == 2 }" @click="changeBtn(2)" |
|||
>水泵</button |
|||
> |
|||
</a-badge> |
|||
</div> |
|||
<div class="device-list" v-if="activeButton == 1"> |
|||
<div class="device-list-item" v-for="(item, index) in valveList" :key="index"> |
|||
<div class="list-item-title"> |
|||
<div class="item-title"> |
|||
<img src="./images/device1.png" alt="" /> |
|||
<span>{{ item.name }}</span> |
|||
</div> |
|||
<div class="revoke" @click="revoke(item.id, index, 1)">撤销</div> |
|||
</div> |
|||
<div class="list-item-main"> |
|||
<div> |
|||
<div class="info">开度</div> |
|||
<div class="text"> |
|||
<span>{{ item.oldVal + item.unit }}</span> |
|||
<img src="/asset/image/bulbLogo/22406.png" alt="" /> |
|||
<span>{{ item.value + item.unit }}</span> |
|||
</div> |
|||
</div> |
|||
<div></div> |
|||
</div> |
|||
</div> |
|||
<a-empty style="margin-top: 100px" v-if="valveList.length == 0"> |
|||
<template #description> <span style="color: white">暂无数据</span></template> |
|||
</a-empty> |
|||
</div> |
|||
<div class="device-list" v-if="activeButton == 2"> |
|||
<div class="device-list-item" v-for="(item, index) in pumpList" :key="index"> |
|||
<div class="list-item-title"> |
|||
<div class="item-title"> |
|||
<img src="./images/device2.png" alt="" /> |
|||
<span>{{ item.name }}</span> |
|||
</div> |
|||
<div class="revoke" @click="revoke(item.id, index, 2)">撤销</div> |
|||
</div> |
|||
<div class="list-item-main"> |
|||
<div> |
|||
<div class="info">频率</div> |
|||
<div class="text"> |
|||
<span>{{ item.oldVal + item.unit }}</span> |
|||
<img src="/asset/image/bulbLogo/22406.png" alt="" /> |
|||
<span>{{ item.value + item.unit }}</span> |
|||
</div> |
|||
</div> |
|||
<div> |
|||
<div class="info">开关</div> |
|||
<div class="text"> |
|||
<span>{{ item.opened ? '开' : '关' }}</span> |
|||
<img src="/asset/image/bulbLogo/22406.png" alt="" /> |
|||
<span>{{ item.open == 1 ? '开' : '关' }}</span> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<a-empty style="margin-top: 100px" v-if="pumpList.length == 0"> |
|||
<template #description> <span style="color: white">暂无数据</span></template> |
|||
</a-empty> |
|||
</div> |
|||
<div style="width: 100%; height: 100px"></div> |
|||
<div class="button-box"> |
|||
<button class="cancel" @click="visible1 = false">取消</button> |
|||
<a-popconfirm |
|||
title="此操作将提交以上修改内容" |
|||
ok-text="确定" |
|||
cancel-text="取消" |
|||
placement="bottomRight" |
|||
@confirm="submitChange"> |
|||
<button class="execute">执行</button> |
|||
</a-popconfirm> |
|||
</div> |
|||
</a-tab-pane> |
|||
</a-tabs> |
|||
</a-drawer> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref, onMounted } from 'vue'; |
|||
import { Modal, message } from 'ant-design-vue'; |
|||
|
|||
import deviceInfo from './deviceInfo.vue'; |
|||
import deviceLine from './deviceLine.vue'; |
|||
import deviceItem from './deviceItem.vue'; |
|||
import planTab from './component/planTab.vue'; |
|||
import logTab from './component/logTab.vue'; |
|||
import { linePosition, device1, device2, device3, device4 } from './device'; |
|||
// 网络请求 |
|||
import { http } from '/nerv-lib/util/http'; |
|||
import { waterSys } from '/@/api/waterSystem'; |
|||
// 全局变量 |
|||
import { items } from '/@/store/item'; |
|||
|
|||
// 初始化 =========================================================================================== |
|||
|
|||
const state = items(); |
|||
onMounted(() => { |
|||
// 获得所有设备状态 |
|||
getAllDevice(); |
|||
}); |
|||
const deviceState = 1; |
|||
|
|||
// 计划与日志 抽屉业务 ========================================================================================= |
|||
|
|||
// 计划与日志 |
|||
const visible = ref(false); |
|||
// 当前选中的tab |
|||
const activeKey = ref('1'); |
|||
|
|||
// 执行 抽屉业务 ========================================================================================= |
|||
|
|||
// 执行 |
|||
const visible1 = ref(false); |
|||
// 当前选中的tab |
|||
const activeKey1 = '1'; |
|||
// 当前选中的设备类型 阀门=1/水泵=2 |
|||
const activeButton = ref(1); |
|||
// 切换设备类型 |
|||
const changeBtn = (key: number) => { |
|||
activeButton.value = key; |
|||
}; |
|||
// 当前修改的水泵数据 |
|||
const pumpList = ref<any>([]); |
|||
// 当前修改的水阀数据 |
|||
const valveList = ref<any>([]); |
|||
|
|||
// 打开右侧抽屉 |
|||
const openDrawer1 = () => { |
|||
valveList.value = device2.value.filter((item: any) => { |
|||
return item.edited; |
|||
}); |
|||
pumpList.value = device4.value.filter((item: any) => { |
|||
return item.edited; |
|||
}); |
|||
if (valveList.value.length || pumpList.value.length) { |
|||
visible1.value = true; |
|||
} else { |
|||
message.info('未产生任何修改'); |
|||
} |
|||
}; |
|||
// 右侧抽屉 - 撤回 |
|||
const revoke = (id: any, index: number, type: number) => { |
|||
if (type == 1) { |
|||
valveList.value.splice(index, 1); |
|||
device2.value.forEach((item: any) => { |
|||
if (item.id == id) { |
|||
item.value = item.oldVal; |
|||
item.edited = false; |
|||
} |
|||
}); |
|||
} else if (type == 2) { |
|||
pumpList.value.splice(index, 1); |
|||
device4.value.forEach((item: any) => { |
|||
if (item.id == id) { |
|||
item.value = item.oldVal; |
|||
item.open = item.opened; |
|||
item.edited = false; |
|||
} |
|||
}); |
|||
} |
|||
}; |
|||
const submitChange = () => { |
|||
let valveList = []; |
|||
device2.value.forEach((item: any) => { |
|||
if (item.edited) { |
|||
valveList.push({ |
|||
deviceGroup: item.id, |
|||
openPercent: item.value, |
|||
}); |
|||
} |
|||
}); |
|||
let pumpList = []; |
|||
device4.value.forEach((item: any) => { |
|||
if (item.edited) { |
|||
pumpList.push({ |
|||
deviceGroup: item.id, |
|||
frequency: item.value, |
|||
switchStatus: +item.open, |
|||
}); |
|||
} |
|||
}); |
|||
state.setLoading(true); |
|||
http |
|||
.post(waterSys.submitList, { |
|||
projectId: state.projectId, |
|||
siteId: state.siteId, |
|||
valveList, |
|||
pumpList, |
|||
}) |
|||
.then((res) => { |
|||
let data = res.data; |
|||
state.setLoading(false); |
|||
// 修改请求发送了,但操作时产生了失败结果 |
|||
if (res.retcode != 0) { |
|||
// 直接提示并跳出 |
|||
return message.warning(res.msg); |
|||
} |
|||
// 所有修改均生效 |
|||
if (data.allSucceed) { |
|||
message.success('修改完成'); |
|||
// allSucceed不为true,则至少有一条数据修改失败 |
|||
} else { |
|||
message.info(`${data.successList.length}条修改成功,${data.failList.length}条修改失败`); |
|||
} |
|||
// 将所有已修改状态的数据还原 |
|||
resetEdit(); |
|||
visible1.value = false; |
|||
getAllDevice(); |
|||
}); |
|||
}; |
|||
|
|||
const resetEdit = () => { |
|||
device2.value.forEach((item) => { |
|||
item.edited = false; |
|||
}); |
|||
device4.value.forEach((item) => { |
|||
item.edited = false; |
|||
}); |
|||
}; |
|||
|
|||
// 设备数据业务 ========================================================================================== |
|||
|
|||
// 当其中一个tab产生了数据修改,可以调用该方法重置所有tab |
|||
const resetDrawer = () => { |
|||
try { |
|||
// tab1重置 |
|||
tabs1Ref.value.reset(); |
|||
} catch {} |
|||
try { |
|||
// tab2重置 |
|||
tabs2Ref.value.reset(); |
|||
} catch {} |
|||
}; |
|||
// 抽屉tab1组件的引用 |
|||
const tabs1Ref = ref(); |
|||
// 抽屉tab2组件的引用 |
|||
const tabs2Ref = ref(); |
|||
// 撤销所有修改 |
|||
const resetAll = () => { |
|||
Modal.confirm({ |
|||
title: '提示信息', |
|||
content: '该操作将还原已编辑内容', |
|||
onOk() { |
|||
// 水阀 |
|||
device2.value.forEach((item: any) => { |
|||
if (item.edited) { |
|||
item.value = item.oldVal; |
|||
item.edited = false; |
|||
} |
|||
}); |
|||
// 水泵 水泵包含 |
|||
device4.value.forEach((item: any) => { |
|||
if (item.edited) { |
|||
item.value = item.oldVal; |
|||
item.open = item.opened; |
|||
item.edited = false; |
|||
} |
|||
}); |
|||
}, |
|||
onCancel() {}, |
|||
}); |
|||
}; |
|||
// 获得所有设备状态 |
|||
const getAllDevice = () => { |
|||
getDevice(1); |
|||
getDevice(2); |
|||
getDevice(3); |
|||
getDevice(4); |
|||
}; |
|||
/** |
|||
* 获取一个设备类型的数据 |
|||
* @param type 污水池=1/阀门=2/集水池=3/水泵=4 |
|||
*/ |
|||
const getDevice = (type: number) => { |
|||
// 请求地址 |
|||
let url = ''; |
|||
if (type == 1) { |
|||
url = waterSys.getPool1; |
|||
} else if (type == 2) { |
|||
url = waterSys.getValve; |
|||
} else if (type == 3) { |
|||
url = waterSys.getPool2; |
|||
} else if (type == 4) { |
|||
url = waterSys.getPump; |
|||
} |
|||
http |
|||
.get(url, { |
|||
projectId: state.projectId, |
|||
siteId: state.siteId, |
|||
}) |
|||
.then((res) => { |
|||
let data = res.data; |
|||
// 污水池数据 |
|||
if (type == 1) { |
|||
device1.value.forEach((item: any, index: number) => { |
|||
let result = data[index]; |
|||
// 污水池名称 |
|||
item.name = result.deviceInfoName; |
|||
// 污水池容量 |
|||
item.value = result.record.capacity ? result.record.capacity : '--'; |
|||
// 单位 |
|||
item.unit = result.record.capacityUnit ? result.record.capacityUnit : ''; |
|||
}); |
|||
} |
|||
// 阀门数据 |
|||
if (type == 2) { |
|||
device2.value.forEach((item: any, index: number) => { |
|||
let result = data[index]; |
|||
// 阀门名称 |
|||
item.name = result.deviceGroupName; |
|||
// 阀门ID |
|||
item.id = result.deviceGroup; |
|||
// 编辑状态重置 |
|||
item.edited = false; |
|||
// 设备状态(是否正常) |
|||
item.state = result.record.runStatus.value != null ? result.record.runStatus.value : -1; |
|||
// 开度-新值 |
|||
item.value = result.record.openPercent ? result.record.openPercent : 0; |
|||
// 开度-旧值(用于判断旧值是否被修改) |
|||
item.oldVal = result.record.openPercent ? result.record.openPercent : null; |
|||
// 单位 |
|||
item.unit = result.record.openPercentUnit ? result.record.openPercentUnit : ''; |
|||
}); |
|||
} |
|||
// 集水池数据 |
|||
if (type == 3) { |
|||
device3.value.forEach((item: any, index: number) => { |
|||
let result = data[index]; |
|||
// 集水池名称 |
|||
item.name = result.deviceInfoName; |
|||
// 集水池容量 |
|||
item.value = result.record.capacity ? result.record.capacity : '--'; |
|||
// 单位 |
|||
item.unit = result.record.capacityUnit ? result.record.capacityUnit : ''; |
|||
}); |
|||
} |
|||
// 水泵数据 |
|||
if (type == 4) { |
|||
device4.value.forEach((item: any, index: number) => { |
|||
let result = data[index]; |
|||
// 水泵名称 |
|||
item.name = result.deviceGroupName; |
|||
// 水泵ID |
|||
item.id = result.deviceGroup; |
|||
// 编辑状态重置 |
|||
item.edited = false; |
|||
// 水泵的开启状态-新值 |
|||
item.open = result.record.switchStatus.value == 1 ? true : false; |
|||
// 水泵的开启状态-旧值(用于判断是否被修改) |
|||
item.opened = result.record.switchStatus.value == 1 ? true : false; |
|||
// 设备状态(是否正常) |
|||
item.state = result.record.runStatus.value != null ? result.record.runStatus.value : -1; |
|||
// 频率-新值 |
|||
item.value = result.record.frequency ? result.record.frequency : 0; |
|||
// 频率-旧值(用于判断是否被修改) |
|||
item.oldVal = result.record.frequency ? result.record.frequency : null; |
|||
// 单位 |
|||
item.unit = result.record.frequencyUnit ? result.record.frequencyUnit : ''; |
|||
}); |
|||
} |
|||
}); |
|||
}; |
|||
</script> |
|||
<style lang="less" scoped> |
|||
.main { |
|||
width: 100%; |
|||
height: 100%; |
|||
position: relative; |
|||
background: linear-gradient(to bottom, rgb(35, 102, 165), rgb(1, 19, 81)); |
|||
// 图例区域 |
|||
.map { |
|||
width: 85vw; |
|||
height: 38vw; |
|||
position: relative; |
|||
left: 0; |
|||
right: 0; |
|||
top: 0; |
|||
bottom: 0; |
|||
margin: auto; |
|||
// 右侧 市政管道 |
|||
.pipe { |
|||
width: 120px; |
|||
height: 120px; |
|||
position: absolute; |
|||
text-align: center; |
|||
left: 92%; |
|||
top: 40%; |
|||
z-index: 3; |
|||
transform: translateY(-60px); |
|||
img { |
|||
height: 100%; |
|||
} |
|||
div { |
|||
width: inherit; |
|||
color: white; |
|||
position: absolute; |
|||
top: -1.5em; |
|||
font-size: 16px; |
|||
} |
|||
} |
|||
} |
|||
// 右下角按钮 |
|||
.buttons { |
|||
position: absolute; |
|||
right: 15px; |
|||
bottom: 15px; |
|||
display: flex; |
|||
gap: 15px; |
|||
height: 40px; |
|||
> button { |
|||
height: 40px; |
|||
} |
|||
} |
|||
.right-button { |
|||
height: 25px; |
|||
position: absolute; |
|||
top: 0; |
|||
bottom: 0; |
|||
right: 10px; |
|||
margin: auto; |
|||
display: flex; |
|||
z-index: 99; |
|||
gap: 10px; |
|||
color: #0dffff; |
|||
> img { |
|||
width: 25px; |
|||
height: 25px; |
|||
border-radius: 2px; |
|||
vertical-align: middle; |
|||
cursor: pointer; |
|||
user-select: none; |
|||
} |
|||
} |
|||
.drawer-item { |
|||
width: 100px; |
|||
height: 100px; |
|||
border: 2px solid red; |
|||
} |
|||
} |
|||
// 抽屉顶部tab按钮样式 |
|||
:deep(.ant-tabs-tab-btn) { |
|||
color: white; |
|||
} |
|||
.btn { |
|||
width: 92px; |
|||
height: 40px; |
|||
border-radius: 4px; |
|||
opacity: 1; |
|||
margin-top: 10px; |
|||
margin-left: 15px; |
|||
font-size: 14px; |
|||
font-weight: 400; |
|||
opacity: 1; |
|||
border: 1px solid rgba(207, 212, 219, 1); |
|||
line-height: 20.27px; |
|||
color: white; |
|||
text-align: center; |
|||
vertical-align: top; |
|||
background-color: rgba(255, 255, 255, 0.1); |
|||
} |
|||
|
|||
.selected { |
|||
background: linear-gradient(180deg, rgba(201, 245, 255, 1) 0%, rgba(138, 215, 255, 1) 100%); |
|||
color: rgba(0, 61, 90, 1); |
|||
border: 1px solid white; |
|||
} |
|||
|
|||
.btn:hover { |
|||
background-color: rgba(207, 212, 219, 1); |
|||
} |
|||
|
|||
.btn:active { |
|||
background-color: rgba(102, 102, 102, 1); |
|||
color: white; |
|||
} |
|||
.device-list { |
|||
margin-left: 15px; |
|||
margin-top: 15px; |
|||
width: 100%; |
|||
height: auto; |
|||
display: flex; |
|||
gap: 15px; |
|||
flex-direction: column; |
|||
.device-list-item { |
|||
width: calc(100% - 15px); |
|||
box-sizing: border-box; |
|||
padding: 10px; |
|||
border: 2px solid #03407e; |
|||
border-radius: 4px; |
|||
background: rgba(0, 177, 255, 0.2); |
|||
display: flex; |
|||
gap: 10px; |
|||
flex-direction: column; |
|||
.list-item-title { |
|||
color: white; |
|||
display: flex; |
|||
justify-content: space-between; |
|||
.item-title { |
|||
img { |
|||
width: 25px; |
|||
} |
|||
span { |
|||
margin-left: 10px; |
|||
font-size: 16px; |
|||
} |
|||
} |
|||
.revoke { |
|||
text-align: center; |
|||
border: none; |
|||
border-radius: 4px; |
|||
padding: 5px 15px; |
|||
background: linear-gradient( |
|||
180deg, |
|||
rgba(255, 187, 0, 1) 0%, |
|||
rgba(255, 112, 3, 1) 91.21%, |
|||
rgba(255, 129, 3, 1) 100% |
|||
); |
|||
cursor: pointer; |
|||
} |
|||
} |
|||
.list-item-main { |
|||
display: flex; |
|||
font-size: 13px; |
|||
> div { |
|||
flex: 1; |
|||
display: flex; |
|||
gap: 8px; |
|||
> .info { |
|||
text-align: center; |
|||
width: 6em; |
|||
height: 2.5em; |
|||
line-height: 2.5em; |
|||
border-radius: 4px; |
|||
color: white; |
|||
background: linear-gradient( |
|||
180deg, |
|||
rgba(86, 221, 253, 1) 0%, |
|||
rgba(25, 176, 255, 1) 100% |
|||
); |
|||
} |
|||
> .text { |
|||
:first-child { |
|||
color: white; |
|||
line-height: 2.5em; |
|||
} |
|||
img { |
|||
padding: 0 5px; |
|||
} |
|||
:last-child { |
|||
line-height: 2.5em; |
|||
color: red; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
.button-box { |
|||
width: 100%; |
|||
box-sizing: border-box; |
|||
padding: 10px; |
|||
height: 60px; |
|||
position: absolute; |
|||
background-color: transparent; |
|||
text-align: right; |
|||
bottom: 0; |
|||
left: 0; |
|||
right: 0; |
|||
.execute, |
|||
.cancel { |
|||
margin-right: 10px; |
|||
width: 74px; |
|||
height: 40px; |
|||
opacity: 1; |
|||
cursor: pointer; |
|||
border-radius: 4px; |
|||
font-size: 14px; |
|||
font-weight: 400; |
|||
border: 0; |
|||
margin-left: 10px; |
|||
} |
|||
.execute { |
|||
background: rgb(67, 136, 251); |
|||
color: white; |
|||
} |
|||
.cancel { |
|||
background: white; |
|||
color: black; |
|||
} |
|||
} |
|||
</style> |
Loading…
Reference in new issue