JavaProjectRepo/business-css/frontend/src/views/component/scenario/condition.vue

728 lines
22 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script lang="ts">
export default {
name: "condition-条件",
};
</script>
<script setup lang="ts">
import { onMounted, ref, nextTick } from "vue";
import { ElForm, ElMessage, ElMessageBox } from "element-plus";
import Page from '@/components/Pagination/page.vue'
import { getDictItemById } from '@/api/dict';
import { topologyDevicesLsit } from '@/api/business/project';
import { getToken } from '@/utils/auth';
import { searchEventsByScenarioId } from '@/api/business/event';
const url = import.meta.env.VITE_APP_BASE_API;
const conditionData:any = ref([{ // 套件数据
}])
defineExpose({
submitClick
});
const props = defineProps({ // 接收父组件传递的项目信息
projectInfo: {
required: true,
type: Object,
default: {}
},
scenarioId: {
required: true,
type: String,
default: ''
},
isEdit: {
required: true,
type: Boolean,
default: false
},
});
const isEdit = ref(props.isEdit)
function submitClick() {
return menuList.value
}
function initDeviceData(){
topologyDevicesLsit({
id: props.projectInfo.projectId
}).then((res:any) => {
if (res.code == 0) {
deviceData.value = res.data;
}
})
}
function initConditionData(){
searchEventsByScenarioId({
scenarioId: props.scenarioId
}).then((res:any) => {
if(res.length > 0){
menuList.value = []
}
for(let i = 0; i < res.length; i++){
if(res[i].attrChanges != null && res[i].attrChanges != ''){
let attrChanges = JSON.parse(res[i].attrChanges)
menuList.value.push({
...attrChanges,
eventId: res[i].eventId,
})
getTimelineList()
}
}
if(res.length > 0){
getDeviceInfo(menuList.value[0].device)
}
})
}
onMounted(() => {
DicInit()
initDeviceData()
initConditionData()
});
const deviceData:any = ref([]) // 始发设备数据
const attributeData:any = ref([]) // 设备属性数据
const materialData:any = ref([]) // 变化物料数据
const menuList:any = ref([
{
label: '条件1',
target:{
entityType: '',
entityId: '',
property: '',
},
unit: 'cm',
segments: [{
segmentId: '分段-1',
start:null,
end:null,
timeline:[]
}]
}
])
const menuIndex = ref(0) // 当前菜单索引
const segmentationIndex:any = ref(0) // 当前分段索引
function addSegmentation() { // 添加分段
menuList.value[menuIndex.value].segments.push({
segmentId: '分段-' + (menuList.value[menuIndex.value].segments.length + 1),
start:null,
end:null,
timeline:[]
})
}
function removeSegmentation(index:any){ // 删除分段
menuList.value[menuIndex.value].segments.splice(index, 1);
segmentationIndex.value = 0
getTimelineList()
}
function removeAttr(index:any){ // 删除自定义属性
menuList.value[menuIndex.value].segments[segmentationIndex.value].timeline.splice(index, 1);
getTimelineList()
}
function addAttr(){ // 添加自定义属性
menuList.value[menuIndex.value].segments[segmentationIndex.value].timeline.push({
t: null,
value: null
});
getTimelineList()
}
function menuClick(index:any){ // 点击菜单切换
menuIndex.value = index;
segmentationIndex.value = 0;
getTimelineList()
}
function addMenu(){ //添加导菜单
menuList.value.push({
label: '条件' + (menuList.value.length + 1),
target:{
entityType: '',
entityId: '',
property: '',
},
unit: 'cm',
segments: [{
segmentId: '分段-1',
start:null,
end:null,
timeline:[]
}]
})
menuClick(menuList.value.length - 1)
}
function delMenu(){ // 删除导菜单
menuList.value.splice(menuIndex.value, 1);
menuIndex.value = 0
menuClick(menuList.value.length - 1)
}
// 查询字典项
function DicInit() {
let params = {
dictId: 'dc7419e5f8a655966e6bb90b0cb5c0c2',
size:99,
current:1
}
getDictItemById(params).then((result: any) => {
attributeData.value = result.data.records;
}).catch((err: any) => {
if(menuList.value[menuIndex.value].target.entityType == 'device'){
getDeviceInfo(menuList.value[menuIndex.value].device)
}
});
let paramss = {
dictId: '9d87f873bc80e79c6d399131cbe01016',
size:99,
current:1
}
getDictItemById(paramss).then((result: any) => {
materialData.value = result.data.records;
if(menuList.value[menuIndex.value].target.entityType == 'device'){
getDeviceInfo(menuList.value[menuIndex.value].device)
}
}).catch((err: any) => {
});
}
const attribute = ref('') // 选中设备属性
const material = ref('') // 选中变化物料
function changeAttribute(e:any){ // 设备属性改变时,清空变化物料
menuList.value[menuIndex.value].target.entityType = ''
if(e!='' && e!=null){
material.value = ''
menuList.value[menuIndex.value].target.entityType = 'device'
menuList.value[menuIndex.value].target.property = e
deviceData.value.forEach((item:any) => {
if(item.deviceName == menuList.value[menuIndex.value].device){
menuList.value[menuIndex.value].target.entityId = item.deviceId
}
})
}
getDeviceInfo(e)
}
function changeMaterial(e:any){ // 设备属性改变时,清空变化物料
menuList.value[menuIndex.value].target.entityType = ''
if(e!='' && e!=null){
material.value = ''
menuList.value[menuIndex.value].target.entityType = 'material'
menuList.value[menuIndex.value].target.entityId = ''
deviceData.value.forEach((item:any) => {
if(item.deviceName == menuList.value[menuIndex.value].device){
menuList.value[menuIndex.value].target.entityId = item.materialId
}
})
menuList.value[menuIndex.value].target.property = e
}
getDeviceInfo(e)
}
const devicename = ref('') // 选中始发设备
const deviceMaterial = ref('') // 选中始发设备的变化物料
const timelineList:any = ref([]) // 时间线数据
function getTimelineList(){
timelineList.value = []
let item = menuList.value[menuIndex.value]
item.segments.forEach((segment:any) => {
segment.timeline.forEach((timeline:any) => {
console.log(timeline)
timelineList.value.push(timeline)
})
})
}
function getDeviceInfo(e:any){ // 获取设备信息
devicename.value = ""
deviceMaterial.value = ""
deviceData.value.forEach((item:any) => {
if(item.deviceName == menuList.value[menuIndex.value].device){
devicename.value = item.deviceName
}
})
if(menuList.value[menuIndex.value].target.entityType == 'device'){
attributeData.value.forEach((item:any) => {
if(item.itemCode == menuList.value[menuIndex.value].attribute){
deviceMaterial.value = item.dictName
}
})
}
if(menuList.value[menuIndex.value].target.entityType == 'material'){
materialData.value.forEach((item:any) => {
if(item.itemCode == menuList.value[menuIndex.value].material){
deviceMaterial.value = item.dictName
}
})
}
}
const upload:any = ref(null)
function handleSuccess(file: any) {
if(file.code =="0"){
file.data.forEach((item:any) => {
menuList.value[menuIndex.value].segments[segmentationIndex.value].timeline.push(item)
})
ElMessage({
message: "导入成功!",
type: "success",
});
upload.value.clearFiles()
}
}
</script>
<template>
<div class="condition-box">
<div class="condition-left">
<div class="condition-menu">
<div v-for="(item, index) in menuList" :key="index" class="condition-item"
:class="{'condition-item-active': index == menuIndex}" @click="menuClick(index)">
{{ item.label }}
</div>
<img src="@/assets/add.png" v-if="isEdit == true" alt="" class="condition-img" style="cursor: pointer;" @click="addMenu">
<img src="@/assets/del.png" v-if="isEdit == true && menuList.length > 1" alt="" class="condition-img" style="cursor: pointer;" @click="delMenu">
</div>
<el-form ref="infoForm" label-width="120px">
<el-form-item label="始发设备(物料)" prop="code">
<el-select v-model="menuList[menuIndex].device" placeholder="请选择" style="width:100%;" clearable @change="getDeviceInfo"
:disabled="isEdit == false">
<el-option v-for="item in deviceData" :key="item.deviceName" :label="item.deviceName +'('+item.materialName+')'" :value="item.deviceName" />
</el-select>
</el-form-item>
<div style="display: flex; width: 100%;justify-content: space-between;">
<el-form-item label="设备属性" prop="name" style="width: 49%;">
<el-select v-model="menuList[menuIndex].attribute" placeholder="请选择" style="width:100%;" clearable
:disabled="(menuList[menuIndex].material!='' && menuList[menuIndex].material!=null) || isEdit == false" @change="changeAttribute">
<el-option v-for="item in attributeData" :key="item.itemCode" :label="item.dictName" :value="item.itemCode" />
</el-select>
</el-form-item>
<el-form-item label="变化物料" style="width: 49%;">
<el-select v-model="menuList[menuIndex].material" placeholder="请选择" style="width:100%;" clearable
:disabled="(menuList[menuIndex].attribute!='' && menuList[menuIndex].attribute!=null)|| isEdit == false" @change="changeMaterial">
<el-option v-for="item in materialData" :key="item.itemCode" :label="item.dictName" :value="item.itemCode" />
</el-select>
</el-form-item>
</div>
<div class="segmentation-menu">
<div v-for="(item, index) in menuList[menuIndex].segments" :key="index" class="segmentation-item"
:class="{'segmentation-item-active': index == segmentationIndex}" @click="segmentationIndex = index">
<span>{{ item.segmentId }}</span>
<svg v-if="isEdit == true && menuList[menuIndex].segments.length >1 && menuList[menuIndex].segments.length - 1 == index"
@click.top="removeSegmentation(index)"
t="1766969938271" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4998" width="14" height="14"><path d="M571.01312 523.776l311.3472-311.35232c15.7184-15.71328 15.7184-41.6256 0-57.344l-1.69472-1.69984c-15.7184-15.71328-41.6256-15.71328-57.34912 0l-311.3472 311.77728-311.35232-311.77728c-15.7184-15.71328-41.63072-15.71328-57.344 0l-1.69984 1.69984a40.0128 40.0128 0 0 0 0 57.344L452.92544 523.776l-311.35232 311.35744c-15.71328 15.71328-15.71328 41.63072 0 57.33888l1.69984 1.69984c15.71328 15.7184 41.6256 15.7184 57.344 0l311.35232-311.35232 311.3472 311.35232c15.72352 15.7184 41.63072 15.7184 57.34912 0l1.69472-1.69984c15.7184-15.70816 15.7184-41.6256 0-57.33888l-311.3472-311.35744z" p-id="4999" fill="currentColor"></path></svg>
</div>
<div class="segmentation-item-add" @click="addSegmentation" v-if="isEdit == true">
+ 新增分段
</div>
</div>
<div class="segmentation-content">
<div style="display: flex; align-items: center;">
<span>时间段 </span>
<el-input v-model="menuList[menuIndex].segments[segmentationIndex].start" style="width: 160px;margin-left: 20px;" placeholder="">
<template #append>s</template>
</el-input>
<span style="padding: 0 10px;">-</span>
<el-input v-model="menuList[menuIndex].segments[segmentationIndex].end" style="width: 160px" placeholder="">
<template #append>s</template>
</el-input>
<el-upload
ref="upload"
class="upload-demo"
accept=".xlsx"
:action=" url + '/events/upload-excel'"
:show-file-list="false"
:on-success="handleSuccess">
<el-button type="primary" style="margin: 0 10px;" v-if="isEdit == true">
导入数据</el-button>
</el-upload>
</div>
<div class="segmentation_custom_attrs_box">
<div class="segmentation_custom_attrs_header">
<div class="segmentation_custom_attrs_header1">序号</div>
<div class="segmentation_custom_attrs_header2">时间s</div>
<div class="segmentation_custom_attrs_header3">数值</div>
<div class="segmentation_custom_attrs_header4">操作</div>
</div>
<div class="segmentation_custom_attrs_header" v-for="(item, indexs) in menuList[menuIndex].segments[segmentationIndex].timeline" :key="indexs">
<div class="segmentation_custom_attrs_content1">
{{ Number(indexs) + 1 }}
</div>
<div class="segmentation_custom_attrs_content2">
<el-input v-model="item.t" style="width: 100%" placeholder="" ></el-input>
</div>
<div class="segmentation_custom_attrs_content3">
<el-input v-model="item.value" style="width: 100%" placeholder=""></el-input>
</div>
<div class="segmentation_custom_attrs_content4" >
<span @click="removeAttr(indexs)" style="cursor: pointer;" v-if="isEdit == true">删除</span>
</div>
</div>
</div>
<div class="addAttrBox" @click="addAttr" v-if="isEdit == true">
<svg t="1766543724217" style="margin-right: 5px;" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6518" width="16" height="16"><path d="M105 480a8 8 0 0 1 8-8h799a8 8 0 0 1 8 8v64a8 8 0 0 1-8 8H113a8 8 0 0 1-8-8v-64z" fill="#266FFF" p-id="6519"></path><path d="M480 920a8 8 0 0 1-8-8V112a8 8 0 0 1 8-8h64a8 8 0 0 1 8 8v800a8 8 0 0 1-8 8h-64z" fill="#266FFF" p-id="6520"></path></svg>
添加一行
</div>
</div>
</el-form>
</div>
<div class="condition-right">
<div class="condition-right-titlebox">
<div class="condition-right-titleline"></div>
<div>配置结果</div>
</div>
<div class="condition-right-devicename">
<span style="padding-right: 20px;">{{ devicename }}</span>
<span>{{ deviceMaterial }}</span>
</div>
<div class="condition-right-content">
<div class="condition-right-tableheader">
<div>时间s</div>
<div>数值</div>
</div>
<div class="condition-right-tablecontent" v-for="(item, index) in timelineList" :key="index">
<div>{{ item.t }}</div>
<div>{{ item.value }}</div>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.condition-box {
box-sizing: border-box;
width: 100%;
height: 100%;
display: flex;
}
.condition-left {
width: calc(100% - 270px) ;
height: 100%;
border-right: 1px solid #e4e7ed;
box-sizing: border-box;
padding: 20px;
}
.condition-right {
width: 270px;
height: 100%;
box-sizing: border-box;
padding: 20px;
}
.condition-menu{
display: flex;
justify-content: flex-start;
align-items: center;
padding-bottom: 10px;
border-bottom: 1px solid #e4e7ed;
margin-bottom: 10px;
}
.condition-item{
width: 110px;
height: 32px;
background: rgba(242, 242, 242, 1);
font-size: 14px;
color: #363636;
font-family: 'Arial Normal', 'Arial';
font-weight: 400;
font-style: normal;
display: flex;
justify-content: center;
align-items: center;
border-radius: 4px;
margin-right: 10px;
cursor: pointer;
}
.condition-item:hover{
color: rgba(38, 111, 255, 1);
}
.condition-item-active{
background: rgba(38, 111, 255, 1);
color: #ffffff !important;
}
.segmentation-menu{
display: flex;
}
.segmentation-item{
width: 90px;
height: 30px;
background: rgba(255, 255, 255, 1);
box-sizing: border-box;
border: 1px solid rgba(242, 242, 242, 1);
border-radius: 5px 5px 0px 0px;
box-shadow: none;
font-family: '微软雅黑';
font-weight: 400;
font-style: normal;
color: #949494;
text-align: left;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 8px;
cursor: pointer;
margin-right: 10px;
}
.segmentation-item-active{
background: rgba(250, 250, 250, 1);
color: #266FFF;
}
.condition-left .el-form {
height: 100%;
}
.segmentation-content{
width: 590px;
height: calc(100vh - 530px);
background: rgba(250, 250, 250, 1);
box-sizing: border-box;
border: 1px solid rgba(242, 242, 242, 1);
border-radius: 5px;
padding: 15px;
overflow: auto;
}
.segmentation-item-add{
line-height: 30px;
font-family: '微软雅黑';
font-weight: 400;
font-style: normal;
font-size: 14px;
color: #266FFF;
cursor: pointer;
}
</style>
<style>
.segmentation_custom_attrs_box{
width: 100%;
height: calc(100% - 98px);
border: 1px solid #f0f1f2;
border-bottom: 0px solid #f0f1f2;
overflow: auto;
margin-top: 10px;
}
.segmentation_custom_attrs_header{
display: flex;
}
.segmentation_custom_attrs_header1{
width: 10%;
height: 40px;
line-height: 40px;
text-align: center;
font-family: 'Arial Negreta', 'Arial Normal', 'Arial', sans-serif;
font-weight: 700;
font-style: normal;
font-size: 14px;
color: #282828;
background-color: #fafafa;
border-right: 1px solid #f0f1f2;
border-bottom: 1px solid #f0f1f2;
}
.segmentation_custom_attrs_header2{
width: 40%;
height: 40px;
line-height: 40px;
text-align: center;
font-family: 'Arial Negreta', 'Arial Normal', 'Arial', sans-serif;
font-weight: 700;
font-style: normal;
font-size: 14px;
color: #282828;
background-color: #fafafa;
border-right: 1px solid #f0f1f2;
border-bottom: 1px solid #f0f1f2;
}
.segmentation_custom_attrs_header3{
width: 40%;
height: 40px;
line-height: 40px;
text-align: center;
font-family: 'Arial Negreta', 'Arial Normal', 'Arial', sans-serif;
font-weight: 700;
font-style: normal;
font-size: 14px;
color: #282828;
background-color: #fafafa;
border-right: 1px solid #f0f1f2;
border-bottom: 1px solid #f0f1f2;
}
.segmentation_custom_attrs_header4{
width: 10%;
height: 40px;
line-height: 40px;
text-align: center;
font-family: 'Arial Negreta', 'Arial Normal', 'Arial', sans-serif;
font-weight: 700;
font-style: normal;
font-size: 14px;
color: #282828;
background-color: #fafafa;
border-bottom: 1px solid #f0f1f2;
}
.segmentation_custom_attrs_content1{
width: 10%;
height: 42px;
line-height: 40px;
text-align: center;
font-family: 'Arial Negreta', 'Arial Normal', 'Arial', sans-serif;
font-weight: 700;
font-style: normal;
font-size: 14px;
color: #282828;
border-right: 1px solid #f0f1f2;
border-bottom: 1px solid #f0f1f2;
}
.segmentation_custom_attrs_content2{
width: 40%;
height: 42px;
line-height: 40px;
text-align: center;
font-family: 'Arial Negreta', 'Arial Normal', 'Arial', sans-serif;
font-weight: 700;
font-style: normal;
font-size: 14px;
color: #282828;
border-right: 1px solid #f0f1f2;
border-bottom: 1px solid #f0f1f2;
}
.segmentation_custom_attrs_content3{
width: 40%;
height: 42px;
line-height: 40px;
text-align: center;
font-family: 'Arial Negreta', 'Arial Normal', 'Arial', sans-serif;
font-weight: 700;
font-style: normal;
font-size: 14px;
color: #282828;
border-right: 1px solid #f0f1f2;
border-bottom: 1px solid #f0f1f2;
}
.segmentation_custom_attrs_content4{
width: 10%;
height: 42px;
line-height: 40px;
text-align: center;
font-family: '微软雅黑', sans-serif;
font-weight: 400;
font-style: normal;
font-size: 14px;
color: #266FFF;
border-bottom: 1px solid #f0f1f2;
}
.segmentation_custom_attrs_content1 .el-input__wrapper{
box-shadow: 0 0 0 transparent;
}
.segmentation_custom_attrs_content1 .el-input__wrapper.is-focus{
box-shadow:inset 0 0 0 1px #266FFF !important;
}
.segmentation_custom_attrs_content2 .el-input__wrapper{
box-shadow: 0 0 0 transparent;
}
.segmentation_custom_attrs_content2 .el-input__wrapper.is-focus{
box-shadow:inset 0 0 0 1px #266FFF !important;
}
.segmentation_custom_attrs_content3 .el-input__wrapper{
box-shadow: 0 0 0 transparent;
}
.segmentation_custom_attrs_content3 .el-input__wrapper.is-focus{
box-shadow:inset 0 0 0 1px #266FFF !important;
}
.addAttrBox{
width: 100%;
height: 38px;
background-color: #f5f8ff;
line-height: 38px;
text-align: center;
font-family: '微软雅黑', sans-serif;
font-weight: 400;
font-style: normal;
font-size: 14px;
color: #266FFF;
border: 1px dashed #266FFF;
margin-top: 10px;
cursor: pointer;
}
.condition-right-titlebox{
display: flex;
align-items: center;
font-family: 'Arial Negreta', 'Arial Normal', 'Arial';
font-weight: 700;
font-style: normal;
font-size: 16px;
color: #363636;
}
.condition-right-titleline{
width: 5px;
height: 14px;
background-color: rgba(38, 111, 255, 1);
margin-right: 8px;
}
.condition-right-devicename{
font-family: 'Arial Normal', 'Arial';
font-weight: 400;
font-style: normal;
font-size: 14px;
padding: 10px 0;
}
.condition-right-content{
border-left: 1px solid #f0f1f2;
border-top: 1px solid #f0f1f2;
}
.condition-right-tableheader{
display: flex;
}
.condition-right-tablecontent{
display: flex;
}
.condition-right-tableheader div{
width: 115px;
height: 36px;
line-height: 36px;
text-align: center;
font-family: 'Arial Negreta', 'Arial Normal', 'Arial';
font-weight: 700;
font-style: normal;
color: #383838;
background: #fafafa;
border-right: 1px solid #f0f1f2;
border-bottom: 1px solid #f0f1f2;
}
.condition-right-tablecontent div{
width: 115px;
height: 36px;
line-height: 36px;
text-align: center;
font-family: 'Arial Normal', 'Arial';
font-weight: 400;
font-style: normal;
font-size: 13px;
color: #505050;
text-align: center;
border-right: 1px solid #f0f1f2;
border-bottom: 1px solid #f0f1f2;
}
</style>