Ver código fonte

update 报警设置

GuoYuFu123 6 anos atrás
pai
commit
c83537b6b0
45 arquivos alterados com 8040 adições e 37 exclusões
  1. 178 0
      src/api/alarm/alarm.js
  2. 117 0
      src/components/alarm/common/AlarmClass.vue
  3. 237 0
      src/components/alarm/common/AlarmItem.vue
  4. 121 0
      src/components/alarm/common/CheckBox.vue
  5. 153 0
      src/components/alarm/common/ObjLocation.vue
  6. 313 0
      src/components/alarm/common/ObjType.vue
  7. 45 0
      src/components/alarm/common/utils.js
  8. 5 1
      src/components/config_point/step3_edit/index.vue
  9. 0 0
      src/components/sagacloud/BasePagination.vue
  10. 72 0
      src/components/sagacloud/SgSelector.vue
  11. 41 30
      src/plugins/components.js
  12. 8 3
      src/router/sagacloud.js
  13. 5 3
      src/store/index.js
  14. 28 0
      src/store/modules/alarm.js
  15. 0 0
      src/store/modules/proMess.js
  16. 0 0
      src/store/modules/project.js
  17. 139 0
      src/views/alarm/notice/ApplyDialog.vue
  18. 146 0
      src/views/alarm/notice/IndexCondition.vue
  19. 164 0
      src/views/alarm/notice/IndexContent.vue
  20. 396 0
      src/views/alarm/notice/IndexContentList.vue
  21. 204 0
      src/views/alarm/notice/IndexContentTable.vue
  22. 209 0
      src/views/alarm/notice/ManageNoticeUser.vue
  23. 141 0
      src/views/alarm/notice/SetNoticeUser.vue
  24. 295 0
      src/views/alarm/notice/UserAddNotice.vue
  25. 73 0
      src/views/alarm/notice/api.js
  26. 70 0
      src/views/alarm/notice/common/LvSelect.vue
  27. 74 0
      src/views/alarm/notice/common/UserSelect.vue
  28. 50 0
      src/views/alarm/notice/index.vue
  29. 29 0
      src/views/alarm/notice/remine.md
  30. 281 0
      src/views/alarm/notice/utils.js
  31. 239 0
      src/views/alarm/projalarm/addmodel.vue
  32. 182 0
      src/views/alarm/projalarm/alarmitem.vue
  33. 145 0
      src/views/alarm/projalarm/api.js
  34. 138 0
      src/views/alarm/projalarm/batchapply.vue
  35. 813 0
      src/views/alarm/projalarm/create.vue
  36. 573 0
      src/views/alarm/projalarm/edit/Base.vue
  37. 350 0
      src/views/alarm/projalarm/edit/index.vue
  38. 272 0
      src/views/alarm/projalarm/hasproblem.vue
  39. 503 0
      src/views/alarm/projalarm/index.vue
  40. 267 0
      src/views/alarm/projalarm/lookitem.vue
  41. 334 0
      src/views/alarm/projalarm/nospport.vue
  42. 241 0
      src/views/alarm/projalarm/selectratedinfo.vue
  43. 28 0
      src/views/alarm/projalarm/utils.js
  44. 208 0
      src/views/alarm/staff/ManageUser.vue
  45. 153 0
      src/views/alarm/staff/index.vue

+ 178 - 0
src/api/alarm/alarm.js

@@ -0,0 +1,178 @@
+/**
+@author:fugy
+@date:2019.1.10
+@info:alarm-api
+ */
+import httputils from '@/utils/httputils'
+const api = {
+    //获取对象类型
+    getObjectType() {
+        return new Promise((resolve, reject) => {
+            httputils.getJson(
+                '/server/dataplatform/dict/query/equipment_all',
+                null,
+                res => {
+                    if (res.result === 'success') {
+                        let dataArr = res.data
+                        objTypeArr = []
+                        let sysArr = []
+                        let devArr = []
+                        dataArr.forEach(item => {
+                            objTypeArr.push(item)
+                            let sysObj = {
+                                label: item.name,
+                                value: item.code,
+                                type: item.type
+                            }
+                            let devObj = {
+                                label: item.name,
+                                value: item.code,
+                                type: item.type
+                            }
+                            if (item.content) {
+                                sysObj.children = []
+                                devObj.children = []
+                                item.content.forEach(ele => {
+                                    objTypeArr.push(ele)
+                                    let sysObj1 = {
+                                        label: ele.name,
+                                        value: ele.code,
+                                        type: ele.type
+                                    }
+                                    let devObj1 = {
+                                        label: ele.name,
+                                        value: ele.code,
+                                        type: ele.type
+                                    }
+                                    if (ele.content) {
+                                        devObj1.children = []
+                                        ele.content.forEach(strip => {
+                                            objTypeArr.push(strip)
+                                            let devObj2 = {
+                                                label: strip.name,
+                                                value: strip.code,
+                                                type: strip.type
+                                            }
+                                            devObj1.children.push(devObj2)
+                                        })
+                                    } else {
+                                        devObj1 = {
+                                            label: ele.name,
+                                            value: ele.code,
+                                            type: ele.type,
+                                            disabled: true
+                                        }
+                                    }
+                                    sysObj.children.push(sysObj1)
+                                    devObj.children.push(devObj1)
+                                })
+                            }
+                            sysArr.push(sysObj)
+                            devArr.push(devObj)
+                        })
+                        let resObj = {
+                            sysArr,
+                            devArr
+                        }
+                        objTypeDevArr = devArr
+                        resolve(resObj)
+                    } else {
+                        reject('fail')
+                    }
+                },
+                fail => {
+                    reject(fail)
+                },
+                err => {
+                    reject(err)
+                }
+            )
+        })
+    },
+    // 获取对象类中的空间级联
+    getObjTypeSpace() {
+        return new Promise((resolve, reject) => {
+            httputils.getJson('/server/dataplatform/dict/query/space', {}, res => {
+                if (res.result == "success") {
+                    resolve(res.data)
+                } else {
+                    resolve([])
+                }
+            })
+        })
+    },
+    // 获取固定和项目报警的list数据
+    getListData(params) {
+        return new Promise((resolve, reject) => {
+            httputils.postJson(
+                '/server/alarm/config/queryConfig',
+                params,
+                res => {
+                    resolve(res)
+                },
+                fail => {
+                    reject(fail)
+                },
+                err => {
+                    reject(err)
+                }
+            )
+        })
+    },
+    // 通过根据Id批量获取各物理实体
+    getApplyObjInfo(projectId, data) {
+        return new Promise((resolve, reject) => {
+            httputils.postJson('/server/dataplatform/object/batchquery?projectId=' + projectId, data, res => {
+                if (res.Result === "success") {
+                    resolve(res.Content || []);
+                }
+            }, fail => {
+                reject(fail);
+            }, err => {
+                reject(err);
+            })
+        })
+    },
+  //查询报警分类
+  alarmClassList(params) {
+    return new Promise(resolve => {
+      httputils.postJson('/server/alarm/config/category/query', params, resp => {
+        if (resp.result == 'success' && resp.count) {
+          resolve(resp.content)
+        } else {
+          resolve([])
+        }
+      })
+    })
+  },
+  //创建报警分类
+  createAlarmClass(params) {
+    return new Promise(resolve => {
+      httputils.postJson('/server/alarm/config/category/create', params, resp => {
+        resolve(resp)
+      })
+    })
+  },
+  /***************断数报警*************************************************** */
+  //获取断数报警通知人员
+  getNumUserNotice(params) {
+    return new Promise(resolve => {
+        httputils.postJson('/server/alarm/notifyuser/queryBrokenAlarmNotifyUser', params, resp => {
+            if(resp.result == 'success' && resp.count) {
+                resolve(resp.content)
+            } else {
+                resolve([])
+            }
+        })
+    })
+  },
+  //更新断数报警的通知方式
+  updateNumUserNotice(params) {
+    return new Promise(resolve => {
+        httputils.postJson('/server/alarm/brokenalarmnotifyuser/update', params, resp => {
+            resolve(resp)
+        })
+    })
+  }
+}
+export default api

+ 117 - 0
src/components/alarm/common/AlarmClass.vue

@@ -0,0 +1,117 @@
+<template>
+    <div>
+        <el-select :style='"width:+"+width'  v-model='selectValue' :clearable='!isAll' :placeholder='placeholder' @change="selectHandler">
+            <el-option v-for='item in selectArr' :key='item.value' :label='item.category' :value='item.category'></el-option>
+        </el-select>
+        <el-popover v-if="isAddBtn" title='添加新分类' v-model='visible' placement='top-start' width='400' trigger='click'>
+            <div>
+                <el-input placeholder='手动添加一个新分类' v-model='inputValue' clearable style='width:300px'></el-input>
+                <el-button type='primary' size='mini' @click='addNew'>确定</el-button>
+            </div>
+            <el-button type='text' slot='reference'>添加新分类</el-button>
+        </el-popover>
+        
+    </div>
+</template>
+<script>
+export default {
+    name: 'alarm-class',
+    data() {
+        return {
+            selectValue: '', //下拉绑定value
+            selectArr:[], //下拉数据的数组
+            inputValue: '', //输入框中的value
+            visible: false,
+        }
+    },
+    props: {
+        //绑定的下拉value值
+        value: {
+            default: ''
+        },
+        //下拉数据Arr
+        options: {
+            type: Array,
+            default: function() {
+                return [
+                    {
+                        category: '测试',
+                        id: 'a'
+                    }
+                ]
+            }
+        },
+        //是否显示添加按钮
+        isAddBtn: {
+            type: Boolean,
+            dafault: true
+        },
+        //宽度
+        width: {
+            type: String,
+            dafault:'200px'
+        },
+        //占位符
+        placeholder: {
+            type: String,
+            default: '请选择报警分类'
+        },
+        //是否全部
+        isAll: {
+            type: Boolean,
+            default: false
+        }
+    },
+    methods: {
+        selectHandler() {
+            if(this.selectValue == '报警分类:全部') {
+                this.$emit('change', null)
+            } else {
+                this.$emit('change', this.selectValue)
+            }            
+        },
+        addNew() {
+            if(this.inputValue == '') {
+                this.$message({
+                    message: '请填写分类信息',
+                    type: 'warning'
+                });
+                return false
+            }
+            if(this.inputValue.length > 5 ) {
+                this.$message({
+                    message: '长度不大于5位',
+                    type: 'warning'
+                });
+                return false
+            }
+            this.$emit('add',this.inputValue)
+        },
+        addAll() {
+            return {category: '报警分类:全部', id: ''}
+        }
+    },
+    watch: {
+        value: {
+            immediate: true,
+            handler(val) {
+                this.selectValue = val
+            }
+        },
+        options: {
+            handler() {
+                let arr = []
+                if(this.isAll){
+                    arr = [this.addAll(),...this.options]
+                } else {
+                    arr = this.options
+            
+                }   
+                this.selectArr = arr;             
+            }
+        }
+    }
+}
+</script>
+<style>
+</style>

+ 237 - 0
src/components/alarm/common/AlarmItem.vue

@@ -0,0 +1,237 @@
+/** 
+*props: objTypeArr:[](对象类数组)
+**/
+<template>
+<span>
+    <span class="show-box">
+        <el-button style="width: 250px;" @click="btnClick">{{btnInfo}}</el-button>
+        <i class="el-icon-circle-close-outline clear-icon" @click="clear"></i> 
+    </span>    
+<el-dialog
+title="选择报警条目"
+:visible.sync="dialogVisible"
+width="40%"
+center
+append-to-body
+>
+    <div class="alarm-item-box">
+        <div class="radio-box">
+            <el-radio-group v-model="radioValue" @change="radioChange">
+                <el-radio-button label="fixed">固定条目</el-radio-button>
+                <el-radio-button label="customed">自定义条目</el-radio-button>                
+            </el-radio-group>
+        </div>
+        <div class="table-box">
+            <el-table
+            ref="multipleTable"
+            :loading="loading"
+            :data="tableData"
+            tooltip-effect="dark"
+            style="width: 100%"
+            border
+            @selection-change="handleSelectionChange">                
+                <el-table-column
+                header-align="center"
+                prop="code"
+                label="报警条目编码">                
+                </el-table-column>
+                <el-table-column
+                header-align="center"
+                prop="name"
+                label="报警条目名称">
+                </el-table-column>
+                <el-table-column
+                type="selection"
+                width="55">
+                </el-table-column>
+            </el-table>
+        </div>
+        <div class="btn-box">
+            <el-button type="primary" @click="save">保存</el-button>
+            <el-button class="cancel-btn" @click="cancel">取消</el-button>
+        </div>
+    </div>      
+</el-dialog> 
+</span>
+</template>
+
+<script>
+import fixedApi from "@/api/alarm/alarm"
+import fixedUtils from './utils'
+import { mapGetters } from 'vuex'
+export default {
+    name: 'alarm-item',
+    data() {
+        return {
+            btnInfo: "报警条目",
+            loading: false,
+            dialogVisible: false,
+            radioValue: 'fixed', //默认固定
+            tableData:[], 
+            multipleSelection:[],
+            alarmItemArr:[]
+        }
+    },
+    props: {
+        objTypeArr: {
+            type: Array,
+            default: []
+        }
+    },
+    computed: {
+        ...mapGetters("alarm",["spaceCodeObj"])
+    },
+    methods: {
+        btnClick() {
+            this.dialogVisible = true;
+            this.btnInfo = "报警条目";
+            this.getAlarmItem()
+        },
+         // radio改变事件
+        radioChange(val) {
+            this.multipleSelection = [];
+            this.alarmItemArr = [];
+            this.getAlarmItem();
+        },
+        // 多选事件
+        handleSelectionChange(val,index) {
+            this.multipleSelection = val;
+        },
+        // 获取报警条目数据
+        getAlarmItem() {
+            this.tableData = []
+            let category = null;
+            let objType = null;
+            if(this.objTypeArr.length) {
+                if(this.objTypeArr[0]) { //第一项全部
+                    objType = this.objTypeArr[0]
+                    if(this.objTypeArr[0] == "building" || this.objTypeArr[0] == "floor") {
+                        category = null;
+                    }else if(this.objTypeArr[0] == "space") {
+                        if(this.objTypeArr.length == 1) {
+                            category = null;
+                        } else {
+                            // category = this.objTypeArr[this.objTypeArr.length - 1];
+                            let p = fixedUtils.spaceSonCode(this.objTypeArr[this.objTypeArr.length - 1], this.spaceCodeObj);
+                            category = p;
+                        }
+                    } else {
+                        category = [this.objTypeArr[this.objTypeArr.length - 1]];
+                    }
+                }
+            }
+            let params = {
+                criteria: {
+                    type: this.radioValue,   //报警条目类别,fixed 固定,customed 自定义     **必须
+                    projectId: this.radioValue == "fixed" ? null : this.projectId,  //项目id,自定义类别时不为空
+                    objType: objType,   //对象类型,building,floor,space,system,facility,为null或没有此字段时不过滤此项
+                    category: category ? {"$in":category} : null, 
+                }              
+            };  
+            fixedApi.getListData(params).then(res => {
+                if(res.result == "success"){
+                    if(res.content && res.content.length) {
+                        this.tableData = res.content;    
+                        // 判断是否已经选中
+                        this.$nextTick(() => {
+                            if(this.alarmItemArr) {
+                                let indexArr = [];
+                                this.alarmItemArr.length ? this.alarmItemArr.forEach((item, idx) =>{
+                                    this.tableData.forEach((ele, index) =>{
+                                        if(ele.code === item.code){
+                                            indexArr.push(index);
+                                        }    
+                                    })
+                                }) : null;
+                                indexArr.length ? indexArr.forEach((item) => {
+                                    this.$refs.multipleTable.toggleRowSelection(this.tableData[item], true);
+                                }) : null
+                            } else {
+                                this.$refs.multipleTable.clearSelection();
+                            }
+                        })
+                    } else {
+                        this.tableData =[];
+                    }                   
+                }
+            });
+        },
+        save() {
+            this.alarmItemArr = this.multipleSelection;           
+            let codeArr = [];
+			let str = "";
+			this.multipleSelection.forEach((item, index, arr) => {
+				codeArr.push(item.code);
+				if(index == arr.length-1) {
+					str += item.name;
+				} else {
+					str += item.name + "、";
+				}
+				
+			})
+			if(str.length > 22) {				
+				 let strTem= str.substring(0, 13);
+				 if(strTem.charAt(strTem.length-1) == "、") {
+					 strTem = strTem.substr(0, strTem.length-1)
+				 }
+				this.btnInfo = strTem.charAt(strTem.length-1) == "、" ? strTem : (strTem + "...");
+			} else {
+				this.btnInfo = str
+            };
+            if( !this.multipleSelection.length ) {
+                this.btnInfo = "报警条目";
+            }
+            this.$emit("change", this.radioValue, codeArr);
+            this.dialogVisible = false;
+        },
+        cancel() {
+            this.dialogVisible = false;
+        },
+        clear() {
+            this.multipleSelection = [];
+            this.alarmItemArr = [];
+            this.btnInfo = "报警条目";
+            this.$emit("change", this.radioValue, []);
+        }
+
+    },
+    created() {
+        if(!this.spaceCodeObj) {
+            this.$store.commit("alarm/ADD_INDEX")
+        }
+    },
+    watch:{
+        objTypeArr: {
+            handler() {
+                this.clear();
+            }
+        }
+    }
+}
+</script>
+
+<style lang="less" scoped>
+.show-box {
+    font-size: 20px;
+    .clear-icon{
+        cursor: pointer;
+    }
+}
+.alarm-item-box{    
+    .radio-box{
+        text-align: center;
+    }
+    .table-box{
+        height: 500px;
+        overflow-y: auto;
+        margin-top: 10px;
+    }
+    .btn-box{
+        margin-top:10px;
+        text-align: center;
+        .cancel-btn{
+            margin-left: 50px;
+        }
+    }
+}
+</style>

+ 121 - 0
src/components/alarm/common/CheckBox.vue

@@ -0,0 +1,121 @@
+/**
+@author:fugy--update
+@date:2018.12.12
+@info:多选组件封装
+@prop:sendMessage, sendEmail, sendEmail
+@return: {sendMessage: 0|1, sendEmail: 0|1, sendEmail: 0|1}
+**/
+<template>
+    <div class='box'>
+        <p v-if='isAll'>
+            <el-checkbox v-model='checkAll' @change='handleCheckAllChange'>全选</el-checkbox>
+        </p>
+        <p class='check-item'>
+            <el-checkbox v-model='message' @change='messageHandle'>短信</el-checkbox>
+            <el-checkbox v-model='email' @change='emailHandle'>邮件</el-checkbox>
+            <el-checkbox v-model='wechat' @change='wechatHandle'>微信</el-checkbox>
+        </p>
+    </div>
+</template>
+<script>
+export default {
+    name: 'multiple-checkbox',
+    data() {
+        return {
+            checkAll: false,
+            message: false,
+            email: false,
+            wechat: false,
+            flag: false, //防止回传
+        }
+    },
+    props: {
+        sendMessage: {
+            require: true
+        },
+        sendEmail: {
+            require: true
+        },
+        sendWechat: {
+            require: true
+        },
+        define: {
+            default: null
+        },
+        isAll: {
+            type: Boolean,
+            default: true
+        }
+    },
+    methods: {
+        //全部
+        handleCheckAllChange(val) {
+            if (val) {
+                this.message = true
+                this.email = true
+                this.wechat = true
+            } else {
+                this.message = false
+                this.email = false
+                this.wechat = false
+            }
+            this.emit()
+        },
+        messageHandle() {
+            this.handleIsAll()
+        },
+        emailHandle() {
+            this.handleIsAll()
+        },
+        wechatHandle() {
+            this.handleIsAll()
+        },
+        //是否全部
+        handleIsAll() {
+            if (this.message && this.email && this.wechat) {
+                this.checkAll = true
+            } else {
+                this.checkAll = false
+            }
+            this.emit()
+        },
+        //回传
+        emit() {
+            let obj = {
+                sendMessage: this.message ? 1 : 0,
+                sendEmail: this.email ? 1 : 0,
+                sendWechat: this.wechat ? 1 : 0
+            }
+            if(this.flag) {
+                this.$emit('change', obj, this.define)
+            }
+            
+        },
+        DataHandle() {
+            this.message = this.sendMessage ? true : false;
+            this.email = this.sendEmail ? true : false;
+            this.wechat = this.sendWechat ? true: false;
+            this.handleIsAll();
+            this.flag = true
+        }
+    },
+    watch: {
+        sendMessage: {
+            immediate: true,
+            handler(val) {
+                this.DataHandle()
+            }
+            
+        }
+    }
+}
+</script>
+<style lang="less" scoped>
+.box {
+    display: flex;
+    .check-item {
+        margin-left: 20px;
+    }
+}
+</style>
+

+ 153 - 0
src/components/alarm/common/ObjLocation.vue

@@ -0,0 +1,153 @@
+/**
+@author:guoguo
+@date:2018.11.30
+@info: 对象位置
+**/
+<template>
+<el-cascader
+    style="width: 249px;"
+    placeholder="对象位置"
+    :options="options"
+    :value="value"
+    @active-item-change="handleItemChange"
+    @change="change"
+    :props="configObj"
+  ></el-cascader>
+</template>
+<script>
+export default {
+    name: "obj-location",
+    data() {
+        return {
+            options: [{
+                value: 'zhinan',
+                label: '指南',
+                children:[]
+            }],
+            configObj: {
+                label: "name",
+                value: "id",
+            },
+            value: []
+        }
+    },
+    props:{
+        projectId: {
+            type: String,
+            required: true
+        }
+    },
+    methods: {
+        //id=[建筑id|楼层Id]
+        getList(type, id, BdId) {
+            let params = {
+                criteria:{
+                    id: id || undefined,
+                    type: [type]
+                }
+            }
+            this.postJson(`/server/dataplatform/object/subquery?projectId=${this.projectId}`, params, resp => {
+                if (resp.Result === 'success'  && resp.Count) {
+                    if(type == "Bd") {
+                        this.handleBd(resp.Content);
+                    } else if ( type == "Fl") {
+                        this.handleFl(resp.Content, id)
+                    } else {
+                        this.handleSp(resp.Content, BdId, id)
+                    }                   
+                } else { //如果是室外
+                    if(type == "Sp") {
+                        let arr = [this.allItem()];
+                        this.options.forEach(item => {
+                            item.children?item.children.forEach(ele => {
+                                if(ele.id == id) {
+                                    ele.children = arr;
+                                }
+                            }):""
+                        })
+                    }
+
+                }
+            })            
+        },
+        handleBd(content) {
+            let arr = [];
+            content.forEach(item=> {
+                let obj = {
+                    id: item.id,
+                    name: item.infos.BuildLocalName,
+                    children: []
+                }
+                arr.push(obj);
+            })
+            this.options = arr;
+            this.options.unshift(this.allBdItem())
+        },
+        handleFl(content, id) {
+            let arr = [];
+            content.forEach(item=> {
+                let obj = {
+                    id: item.id,
+                    name: item.infos.FloorLocalName,
+                    children:[]
+                }
+                arr.push(obj);
+            })
+            this.options.forEach(item => {
+                if(item.id == id) {
+                    item.children = arr
+                }
+            })
+        },
+        handleSp(content, BdId, flId) {
+            let arr = []
+            content.forEach(item => {
+                let obj = {
+                    id: item.id,
+                    name: item.infos.RoomLocalName,
+                }
+                arr.push(obj);
+            });
+            arr.unshift(this.allItem())
+             this.options.forEach(item => {
+                if(item.id == BdId) {
+                    item.children.forEach(ele => {
+                        if(ele.id == flId) {
+                            ele.children = arr;
+                        }
+                    })
+                }
+            })
+        },
+        allBdItem() {
+            return {id: "", name: "对象位置:全部"}
+        },
+        allItem() {
+            return {id: "" , name: "全部"}
+        },
+        handleItemChange(val) {
+            if(val.length == 1 && val[0]) {
+                this.getList( "Fl", val[0]);
+            } else if(val.length == 2){
+                this.getList( "Sp", val[1], val[0]);
+            }
+        },
+        change(val) {
+            let id = val[val.length - 1];
+            if(val.length > 1 && !val[val.length-1]){
+                id = val[val.length-2];
+            }
+            this.$emit("change", id)
+        }
+    },
+    watch: {
+        projectId: {
+            immediate: true,
+            handler(val){
+                this.getList("Bd")
+            }
+        }
+    }
+
+}
+</script>

+ 313 - 0
src/components/alarm/common/ObjType.vue

@@ -0,0 +1,313 @@
+/**
+@author:guoguo
+@date:2018.11.30
+@info: 对象类型
+**/
+<template>
+    <el-form class='form' :model='ruleForm' ref='ruleForm'>
+        <el-form-item
+            class='select-left'
+            prop='selectValue'
+            :rules='hasVerify ? [{ required: true, message: "请选择对象类", trigger: "change" }] : null'
+        >
+            <!-- 下拉框 -->
+            <el-select
+                style='width:150px;'
+                v-model='ruleForm.selectValue'
+                placeholder='对象类'
+                @change='selectChange'
+                clearable
+                :disabled="disabled"
+            >
+                <el-option v-for='item in selectOpt' :key='item.value' :label='item.label' :value='item.value'></el-option>
+            </el-select>
+        </el-form-item>
+        <el-form-item
+            prop='spaceValue'
+            v-show='ruleForm.selectValue == "space"'
+        >
+            <!-- 空间级联 -->
+            <el-cascader
+                v-show="!isShowSpace"
+                clearable
+                ref='space'
+                change-on-select
+                :options='spaceOptions'
+                v-model='ruleForm.spaceValue'
+                :props='spaceProps'
+                @change='spaceChange'
+                placeholder="请选择空间类"
+                :disabled="disabled"
+                :style='"width:" + width'
+            ></el-cascader>
+        </el-form-item>
+        <!-- 系统 -->
+        <el-form-item
+            prop='sysValue'
+            v-show='ruleForm.selectValue == "system"'
+            :rules=' hasVerify ? [{ required: true, message: "请选择系统类",  trigger: ["blur","change" ] }] : null'
+        >
+            <el-cascader ref='sys' :options='sysOptions' v-model='ruleForm.sysValue' @change='sysChange' placeholder="请选择系统类" :disabled="disabled" clearable :style='"width:" + width'></el-cascader>
+        </el-form-item>
+        <!-- 设备 -->
+        <el-form-item
+            prop='devValue'
+            v-show='ruleForm.selectValue == "facility"'
+            :rules=' hasVerify ? [{ required: true, message: "请选择设备类",  trigger: ["blur","change" ] }] : null'
+        >
+            <el-cascader ref='dev' :options='devOptions' v-model='ruleForm.devValue' @change='devChange' placeholder="请选择设备类" :disabled="disabled" clearable :style='"width:" + width'></el-cascader>
+        </el-form-item>
+        <!-- <el-button @click='btn'></el-button> -->
+    </el-form>
+</template>
+<script>
+import fixApi from '@/api/alarm/alarm'
+import utils from './utils'
+import { mapGetters } from 'vuex'
+export default {
+    name: 'obj-type',
+    data() {
+        return {
+            isShowSpace: false,
+            ruleForm: {
+                selectValue: '',
+                spaceValue: [],
+                sysValue: [],
+                devValue: []
+            },
+            /****************左侧下拉***************** */
+            selectOpt: [
+                {
+                    value: 'building',
+                    label: '建筑'
+                },
+                {
+                    value: 'floor',
+                    label: '楼层'
+                },
+                {
+                    value: 'space',
+                    label: '空间'
+                },
+                {
+                    value: 'system',
+                    label: '系统类'
+                },
+                {
+                    value: 'facility',
+                    label: '设备类'
+                }
+            ],
+            selectValue: '',
+            /*****************右侧级联******************* */
+            // 空间
+            spaceOptions: [],
+            spaceValue: [],
+            spaceProps: {
+                value: 'code',
+                label: 'name',
+                children: 'content'
+            },
+            // 系统
+            sysOptions: [],
+            sysValue: [],
+            // 设备
+            devOptions: [],
+            devValue: [],
+            //Dict
+            spaceDict: {},
+            spaceNameDict: {}
+        }
+    },
+    props: {
+        objType: {},
+        hasVerify: {
+            default: false
+        },
+        disabled: {
+            default: false
+        },
+        width: {
+            default: "200px",
+            type: String
+        }
+    },
+    computed: {
+        ...mapGetters('alarm', ['index'])
+    },
+    methods: {
+        // 下拉框
+        selectChange(val) {
+            this.isShowSpace = false
+            this.ruleForm.spaceValue = []
+            this.ruleForm.sysValue = []
+            this.ruleForm.devValue = []
+            if (val == 'building' || val == 'floor') {
+            } else if (val == 'space') {
+                this.$refs.space.handleClick()
+            } else if (val == 'system') {
+                this.$refs.sys.handleClick()
+            } else if (val == 'facility') {
+                this.$refs.dev.handleClick()
+            } else {
+            }
+            if (val) {
+                this.$emit('change', [val])
+            } else {
+                this.$emit('change', [])
+            }
+        },
+        spaceChange(val) {
+            let arr = [this.ruleForm.selectValue, ...val]
+            this.$emit('change', arr)
+        },
+        sysChange(val) {
+            let arr = [this.ruleForm.selectValue, ...val]
+            this.$emit('change', arr)
+        },
+        devChange(val) {
+            let arr = [this.ruleForm.selectValue, ...val]
+            this.$emit('change', arr)
+        },
+        change(val) {},
+        async getSpace() {
+            // 获取空间的级联
+            let spaceRes = await fixApi.getObjTypeSpace()
+            this.spaceOptions = spaceRes
+            this.spaceDictHandle(spaceRes)
+            // 获取name的dict
+            this.spaceNameDictHandle(spaceRes)
+            // 获取code的子集
+            this.spaceCodeDictHandle(spaceRes)
+        },
+        spaceNameDictHandle(spaceRes) {
+            if (spaceRes.length) {
+                let obj = {}
+                spaceRes.forEach(item => {
+                    obj[item.code] = item.name
+                    if (item.content) {
+                        item.content.forEach(item1 => {
+                            obj[item1.code] = item1.name
+                            if (item1.content) {
+                                item1.content.forEach(item2 => {
+                                    obj[item2.code] = item2.name
+                                })
+                            }
+                        })
+                    }
+                })
+                this.$store.commit('alarm/SPACE_NAME_OBJ', obj)
+            }
+        },
+        spaceCodeDictHandle(spaceRes) {
+            let res = utils.getSpaceSonCode(spaceRes)
+            this.$store.commit('alarm/SPACE_CODE_OBJ', res)
+        },
+        spaceDictHandle(spaceRes) {
+            // 做dict   spaceDict
+            let obj = {}
+            if (spaceRes.length) {
+                // let cur = spaceRes
+                spaceRes.forEach(item => {
+                    obj[item.code] = [item.code]
+                    if (item.content) {
+                        item.content.forEach(item1 => {
+                            obj[item1.code] = [item.code, item1.code]
+                            if (item1.content) {
+                                item1.content.forEach(item2 => {
+                                    obj[item2.code] = [item.code, item1.code, item2.code]
+                                })
+                            }
+                        })
+                    }
+                })
+            }
+            this.spaceDict = obj
+        },
+        async getSysDev() {
+            // 获取系统和设备的级联
+            let sysDevRes = await fixApi.getObjectType()
+            this.sysOptions = sysDevRes.sysArr
+            this.devOptions = sysDevRes.devArr
+        },
+        async init() {
+            this.getSpace()
+            this.getSysDev()
+        },
+        // 校验,return 【true or false】
+        verify() {
+            let flag = false
+            this.$refs['ruleForm'].validate(valid => {})
+            if (this.ruleForm.selectValue) {
+                let selectValue = this.ruleForm.selectValue
+                if (selectValue == 'building' || selectValue == 'floor') {
+                    flag = true
+                } else if (selectValue == 'space') {
+                    flag = true
+                } else if (selectValue == 'system') {
+                    if (this.ruleForm.sysValue.length) {
+                        flag = true
+                    } else {
+                        flag = false
+                    }
+                } else if (selectValue == 'facility') {
+                    if (this.ruleForm.devValue.length) {
+                        flag = true
+                    } else {
+                        flag = false
+                    }
+                }
+            } else {
+                flag = false
+            }
+            return flag
+        },
+        btn() {
+            this.verify()
+        },
+        // 处理回填值
+        async handleObjType() {
+            await this.getSpace()
+            if (this.objType.length) {
+                this.ruleForm.selectValue = this.objType[0]
+                let arr = JSON.parse(JSON.stringify(this.objType))
+                if (this.objType[0] == 'space') {
+                    if(this.objType.length == 1) {
+                        this.isShowSpace = true
+                    }else {
+                        this.isShowSpace = false
+                        this.ruleForm.spaceValue = this.spaceDict[arr[1]]
+                    }                    
+                } else if (this.objType[0] == 'system') {
+                    this.ruleForm.sysValue = arr.splice(1)
+                } else if (this.objType[0] == 'facility') {
+                    this.ruleForm.devValue = arr.splice(1)
+                }
+            }
+        }
+    },
+    created() {
+        this.init()
+    },
+    watch: {
+        objType: {
+            handler() {
+                this.handleObjType()
+            }
+        },
+        index : {
+            handler() {
+                this.init()
+            }
+        }
+    }
+}
+</script>
+<style scoped lang="less">
+.form {
+    display: flex;
+    .select-left {
+        margin-right: 5px;
+    }
+}
+</style>

+ 45 - 0
src/components/alarm/common/utils.js

@@ -0,0 +1,45 @@
+var spaceObj = {}
+var spaceSonCode = []
+const api = {    
+    // 1、获取指定空间code下的所有子code,返回{code: code-obj}
+    getSpaceSonCode(arr) {
+        if(arr.length) {
+            spaceObj = {};
+            api.getSpaceData(arr);
+        }
+        return spaceObj
+    },
+    // 获取space的obj数据
+    getSpaceData(arr) {
+        if(arr.length) {
+            arr.forEach((item) => {
+                spaceObj[item.code] = item;
+                if (item.content) {
+                    api.getSpaceData(item.content);
+                }
+            })
+        }
+    },
+    // 2、空间对象类根据指定的code值返回该值下所有的子集code
+    spaceSonCode(code, data) {
+        let obj = data[code];
+        spaceSonCode = []
+        spaceSonCode.push(obj.code)
+        if (obj.content) {
+            api.getSonAllCode(obj)
+        }
+        return spaceSonCode
+    },
+    // 获取子集的所有code值
+    getSonAllCode(obj) {
+        if (obj.content) {
+            obj.content.forEach(item => {
+                api.getSonAllCode(item)
+            })
+        } else {
+            spaceSonCode.push(obj.code);
+        }
+    }
+
+};
+export default api;

+ 5 - 1
src/components/config_point/step3_edit/index.vue

@@ -474,7 +474,11 @@ export default {
                     this.unitObj = this.infoDict[data.InfomationPointCode]
                     this.InfomationPoint = this.unitObj.infoPointName || '--';
                     if(typeof this.unitObj.dataSource == "string") {
-                        this.ValueDescription = this.unitObj.dataSource
+                        if(this.unitObj.dataSource.length) {
+                            this.ValueDescription = this.unitObj.dataSource
+                        } else {
+                            this.ValueDescription = "无信息点单位及值说明"
+                        }                        
                     } else {
                         let str = ''
                         this.unitObj.dataSource.forEach(ele => {

src/components/BasePagination.vue → src/components/sagacloud/BasePagination.vue


+ 72 - 0
src/components/sagacloud/SgSelector.vue

@@ -0,0 +1,72 @@
+<template>
+	<el-select v-model="selected" :placeholder="placeholder" :filterable="canFilter">
+		<el-option v-for="item in ops" :key="item.value" :label="item.name" :value="item.value">
+		</el-option>
+	</el-select>
+</template>
+<script>
+export default {
+	name: "sg-selector",
+	props: ['default', 'type', 'placeholder', 'param', 'filterable', 'hasAll'],
+	data() {
+		let defaultV = "";
+		if (this.default) {
+			defaultV = this.default;
+		}
+		return {
+			loaded: false,
+			canFilter: this.filterable ? true : false,
+			selected: defaultV,
+			ops: []
+		}
+	},
+	methods: {
+		init() {
+			let vm = this;
+			vm.ops = [];
+			if (vm.hasAll) {
+				vm.ops.push({name: "全部", value: 'all'});
+			}
+			vm.postJson("/server/common/component/selector", { type: vm.type, param: vm.param }, (resp) => {
+				if (vm.selected === '' && resp.selectedValue) {
+					vm.selected = resp.selectedValue;
+				}
+				if(resp.options){
+					resp.options.forEach((item)=>{
+						vm.ops.push(item);
+					});
+				}
+				if(vm.selected === '' && vm.ops[0]){
+					vm.selected = vm.ops[0].value;
+				}
+			});
+		}
+	},
+	created: function() {
+		this.init();
+		if (this.defautl === undefined) {
+			return false;
+		}
+		this.$emit("changed", this.default);
+	},
+	watch: {
+		selected: function(n, o) {
+			if (!n || n === undefined) {
+				return false;
+			}
+			if (n && o && n === o) {
+				return false;
+			}
+			this.$emit("changed", n);
+		},
+		param: function(n, o) {
+			if (n && o && n === o) {
+				return false;
+			}
+			this.selected = "";
+			this.init();
+		}
+	}
+}
+
+</script>

+ 41 - 30
src/plugins/components.js

@@ -1,40 +1,51 @@
-import BasePagination from '@/components/BasePagination'
+import BasePagination from '@/components/sagacloud/BasePagination'
 import TableTemplate from '@/framework/template/TablePageTemplate'
+import SgSelector from '@/components/sagacloud/SgSelector'
 //tools
 import basicutils from '@/utils/basicutils'
+import httputils from '@/utils/httputils.js'
 
 export default {
-  install: function(Vue) {
-    Vue.prototype.initPagination = function() {
-      return {
-        pageSize: 10,
-        pageSizes: [10, 20, 50, 100, 200, 500],
-        layout: 'total, sizes, prev, pager, next, jumper',
-        total: 0,
-        currentPage: 1,
-        data: [],
-        params: {}
-      }
-    }
-    Vue.component('base-pagination', BasePagination)
-    Vue.component('table-page-template', TableTemplate)
+    install: function(Vue) {
+        Vue.prototype.initPagination = function() {
+            return {
+                pageSize: 10,
+                pageSizes: [10, 20, 50, 100, 200, 500],
+                layout: 'total, sizes, prev, pager, next, jumper',
+                total: 0,
+                currentPage: 1,
+                data: [],
+                params: {}
+            }
+        }
+        Vue.component('base-pagination', BasePagination)
+        Vue.component('table-page-template', TableTemplate)
+        Vue.component('sg-selector', SgSelector)
 
-    Vue.prototype.formatDate = function(date) {
-      return basicutils.formatDateByPattern(date, 'yyyy-MM-dd HH:mm:ss')
-    }
+        Vue.prototype.formatDate = function(date) {
+            return basicutils.formatDateByPattern(date, 'yyyy-MM-dd HH:mm:ss')
+        }
 
-    Vue.prototype.hasPermission = function(promise) {
-      return basicutils.hasPermission(promise)
-    }
+        Vue.prototype.hasPermission = function(promise) {
+            return basicutils.hasPermission(promise)
+        }
+
+        /**http plugins */
+        // 添加全局方法
+        Vue.prototype.getJson = httputils.getJson
 
-    Vue.filter('formatDateForMillisecond', function(value) {
-      if (!value) return ''
-      return basicutils.formatDateByPattern(new Date(value), 'yyyy-MM-dd')
-    })
+        Vue.prototype.postJson = httputils.postJson
 
-    Vue.filter('formatDateTimeForMillisecond', function(value) {
-      if (!value) return ''
-      return basicutils.formatDateByPattern(new Date(value), 'yyyy-MM-dd HH:mm:ss')
-    })
-  }
+        Vue.prototype.download = httputils.download
+
+        Vue.filter('formatDateForMillisecond', function(value) {
+            if (!value) return ''
+            return basicutils.formatDateByPattern(new Date(value), 'yyyy-MM-dd')
+        })
+
+        Vue.filter('formatDateTimeForMillisecond', function(value) {
+            if (!value) return ''
+            return basicutils.formatDateByPattern(new Date(value), 'yyyy-MM-dd HH:mm:ss')
+        })
+    }
 }

+ 8 - 3
src/router/sagacloud.js

@@ -4,6 +4,11 @@ import Auth from '@/views/system/auth'
 import Dasboard from '@/views/dasboard'
 import ChangePwd from '@/views/system/pwd/ChangePwd'
 
+/** 报警设置 */
+const ProjAlarm = () => import('@/views/alarm/projalarm/index');
+const ProjNotice = () => import('@/views/alarm/notice/index')
+const StaffSetting = () => import('@/views/alarm/staff/index')
+
 /**点位部分 */
 import pointConfig from '@/views/point/config_point'
 import editDataSouce from '@/views/point/config_point/edit_origin'
@@ -46,9 +51,9 @@ export default [
         component: LayoutMain,
         children: [
             { path: '', name: 'Dasboard', component: Dasboard },
-            { path: 'projsetting', name: 'Dasboard', component: Dasboard },
-            { path: 'projnotice', name: 'Dasboard', component: Dasboard },
-            { path: 'staffsetting', name: 'Dasboard', component: Dasboard }
+            { path: 'projsetting', name: 'Dasboard', component: ProjAlarm },
+            { path: 'projnotice', name: 'Dasboard', component: ProjNotice },
+            { path: 'staffsetting', name: 'Dasboard', component: StaffSetting }
         ]
     },
     // 与FM相关设置

+ 5 - 3
src/store/index.js

@@ -2,8 +2,9 @@ import Vue from 'vue'
 import Vuex from 'vuex'
 import storage from '@/utils/storage'
 import layout from '@/framework/layout/layout-store'
-import project from "./moudles/project"
-import peojMess from "./moudles/proMess"
+import project from "./modules/project"
+import peojMess from "./modules/proMess"
+import alarm from './modules/alarm'
 Vue.use(Vuex)
 console.log(project, 'project')
 const KEY_LAST_ROUTE = 'last_route'
@@ -38,6 +39,7 @@ export default new Vuex.Store({
     modules: {
         layout,
         project,
-        peojMess
+        peojMess,
+        alarm
     }
 })

+ 28 - 0
src/store/modules/alarm.js

@@ -0,0 +1,28 @@
+const alarm = {
+    namespaced: true,
+  state: {
+        index: 0, //刷新数据的index 递增刷新
+        spaceNameObj: null, //对象空间的名称字典
+        spaceCodeObj: null //对象类空间字典对象
+  },
+  getters: {
+      index: state => state.index,
+        spaceNameObj: state => state.spaceNameObj,
+        spaceCodeObj: state => state.spaceCodeObj
+  },
+  mutations: {
+    //   刷新index
+      ADD_INDEX(state) {
+        state.index = state.index + 1 ;
+      },
+    //   空间名称dict
+      SPACE_NAME_OBJ(state, spaceNameObj ){
+          state.spaceNameObj = spaceNameObj
+      },
+    //   空间code值dict
+        SPACE_CODE_OBJ(state, spaceCodeObj) {
+            state.spaceCodeObj = spaceCodeObj
+        }
+  }
+}
+export default alarm;

src/store/moudles/proMess.js → src/store/modules/proMess.js


src/store/moudles/project.js → src/store/modules/project.js


+ 139 - 0
src/views/alarm/notice/ApplyDialog.vue

@@ -0,0 +1,139 @@
+/**
+@author:fugy
+@date:2018.11.30
+@info: 批量适用于
+**/
+<template>
+    <el-dialog title='批量适用于' :visible.sync='dialogVisible' width='50%' append-to-body center :before-close="closeDialog">
+        <div class="box" v-if="userData.length">
+            <h6>您还可以勾选其他人员,以适用此次添加的报警通知</h6>
+            <ul class="ul-box">
+                <li class="tit">
+                <p>人员姓名及通知方式</p>
+                </li>
+                <li v-for="(item, index) in userData" :key="index">
+                    <p>
+                        <span class="name">{{item.name}}</span>
+                        <span class="name">{{item.phone}}</span>
+                        <span class="name">{{item.email}}</span>
+                    </p>         
+                <span>
+                    <v-check-box :define="index" @change="checkBoxChange"></v-check-box>
+                </span>
+                </li>
+            </ul>
+        </div>
+        <div v-else style="text-align:center;">暂无人员</div>
+        <span slot='footer' class='dialog-footer'>
+            <el-button type='primary' @click='save'>适用于</el-button>
+            <el-button @click='cancel'>取 消</el-button>
+        </span>
+    </el-dialog>
+</template>
+
+<script>
+import api from './api'
+import utils from "./utils"
+import vCheckBox from '@/components/alarm/common/CheckBox'
+export default {
+    name: 'apply-to',
+    data() {
+        return {
+            dialogVisible: false,
+            userData:[],
+        }
+    },
+    props: ['applyDialogVisible', "id", "alarmIdArr", 'projectId'],
+    components: { vCheckBox },
+    methods: {
+        async getUserData() {
+            this.userData = [];
+            let userParams = {
+                criteria: {
+                    projectId: this.projectId
+                }                
+            }
+            let res = await api.getUserList(userParams);
+            if(res.result == "success" && res.count) {
+                res.content.forEach((item,index, arr) => {
+                    item.notifyType = null;
+                    if (item.id == this.id) {
+                        arr.splice(index, 1);
+                    }
+                });
+                this.userData = res.content;
+            }
+        },
+        // 多选
+        checkBoxChange(obj, index) {
+            this.userData[index].sendMessage = obj.sendMessage;
+            this.userData[index].sendEmail = obj.sendEmail;
+            this.userData[index].sendWechat = obj.sendWechat;
+        },
+        closeDialog() {
+            this.$emit("close")
+        },
+        cancel() {
+            this.dialogVisible = false;
+            this.$emit("close")
+        },
+        // 保存
+        async save() {
+            let notifyUserList = utils.applyUserHandle(this.userData);
+            if(!notifyUserList.length) {
+                this.$message({
+                    message: '请选择',
+                    type: 'warning'
+                });
+                return;
+            }
+            let params = {
+                projectId: this.projectId,
+                alarmConfigResultIdList: this.alarmIdArr,
+                notifyUserList: notifyUserList
+            };
+            let res = await api.setNoticeUser(params);
+            if(res.result == "success") {
+                this.$emit("refresh")          
+                this.$message({
+                    type: 'success',
+                    message: '保存成功'
+                });
+                this.dialogVisible = false;
+            }
+        }
+    },
+    watch: {
+        applyDialogVisible() {
+            this.dialogVisible = true
+            this.getUserData()
+        }
+    }
+}
+</script>
+
+<style lang="less" scoped>
+.box {
+  font-size: 16px;
+  h6{ text-align: center; margin-bottom: 10px; font-size: 14px;}
+  .ul-box {
+    border: 1px solid #ebeef5;
+    border-bottom: none;
+    li {
+      padding: 10px;
+      display: flex;
+      justify-content: space-between;
+      border-bottom: 1px solid #ebeef5;
+      p {
+          display: flex;
+          .name {
+              width: 150px;
+          }
+      }
+    }
+    .tit {
+      justify-content: center;
+    }
+  }
+}
+</style>

+ 146 - 0
src/views/alarm/notice/IndexCondition.vue

@@ -0,0 +1,146 @@
+/**
+@author:fugy
+@date:2018.11.27
+@info:项目报警通知条件区
+**/
+<template>
+    <div class="condition">
+        <sg-selector class="item" type='project' @changed='projectedSelected'></sg-selector>
+        <v-obj-location class="item" v-if="params.projectId" :projectId="params.projectId" @change="objLocationChange"></v-obj-location>
+        <v-obj-type class="item" @change="objTypeChange" :hasVerify='false'></v-obj-type>
+        <v-lv-select class="item" @change='lvSelectChange'></v-lv-select>
+        <v-user-select v-if="params.projectId" class="item" @change='userSelectChange' :userIndex="userIndex" :projectId='params.projectId'></v-user-select>       
+        <v-alarm-class class="alarm-item" width='150px' style="margin-right: 5px;" placeholder='报警分类' :options='alarmClassArr' :isAll='true' @change='alarmClassChange'></v-alarm-class>
+        <v-alarm-item class="alarm-item" @change="alarmItemChange" :objTypeArr="objTypeArr"></v-alarm-item>
+    </div>
+</template>
+<script>
+import vLvSelect from './common/LvSelect'
+import vUserSelect from './common/UserSelect'
+import vObjLocation from '@/components/alarm/common/ObjLocation'
+import vObjType from '@/components/alarm/common/ObjType'
+import vAlarmItem from '@/components/alarm/common/AlarmItem'
+import vAlarmClass from '@/components/alarm/common/AlarmClass'
+//utils
+import fixedUtils from '@/components/alarm/common/utils'
+import { mapGetters } from 'vuex'
+//api
+import alarmApi from '@/api/alarm/alarm'
+export default {
+    name: 'index-condition',
+    data() {
+        return {
+            params: {
+                projectId: null,
+                objType: null,
+                category: null,
+                level: null,
+                instanceLocation: null,
+                code:[],
+                notifyUserId: null ,
+                alarmCategory: undefined
+            },
+            objTypeArr:[],
+            /**v1.1****************** */
+            alarmClassArr: [], //报警分类数组
+        }
+    },
+    computed: {
+        ...mapGetters("alarm",["spaceCodeObj"])
+    },
+    props: ["userIndex"],
+    components: {
+        vLvSelect,
+        vUserSelect,
+        vObjLocation,
+        vObjType,
+        vAlarmItem,
+        vAlarmClass
+    },
+    methods: {
+        // 项目
+        projectedSelected(projectId) {
+            this.params.projectId = projectId;
+            this.getAlarmClassList()            
+        },
+        //获取报警分类
+        async getAlarmClassList() {
+            let params = {                
+                criteria: {
+                    projectId: {$in:[this.params.projectId,"0"]}
+                }                
+            }
+            let res = await alarmApi.alarmClassList(params)
+            this.alarmClassArr = res
+            this.emit()
+        },
+        //报警分类改变
+        alarmClassChange(val) {
+            this.params.alarmCategory = val;
+            this.emit()
+        },
+        // 对象类型改变
+        objLocationChange(val) {
+            this.params.instanceLocation = val || null;
+            this.emit()
+        },
+        // 对象类型change
+        objTypeChange(val) {
+            this.objTypeArr = val; //报警条目
+            if(val[0]) {
+                this.params.objType = val[0];
+                if(val[0] == "building" || val[0] == "floor") {
+                    this.params.category = null
+                } else if(val[0] == 'space'){
+                    if(val.length == 1) {
+                        this.params.category = null;
+                    } else {
+                        this.params.category = val[val.length - 1];
+                        let p = fixedUtils.spaceSonCode(val[val.length - 1], this.spaceCodeObj)
+                        this.params.category = p;
+                    }
+                } else if (val[0] == 'system' || val[0] == 'facility'){                 
+                    this.params.category = [val[val.length - 1]];
+                };
+            } else {
+                this.params.objType = undefined;
+                this.params.category = undefined;
+            }
+        },
+        // 严重程度
+        lvSelectChange(val) {
+            this.params.level = val || null;
+            this.emit()
+        },
+        // 人员
+        userSelectChange(val) {
+            this.params.notifyUserId = val || null;
+            this.emit()
+        },        
+        // 报警条目
+        alarmItemChange(type, codeArr) {
+            this.params.code = codeArr;
+            this.emit()
+        },
+        emit() {
+            this.$emit('change', this.params)
+        }
+    },
+    created() {
+        if(!this.spaceCodeObj){
+            this.$store.commit("alarm/ADD_INDEX")
+        }
+    }
+}
+</script>
+<style lang="less" scoped>
+.condition{
+    display: flex;
+    flex-wrap: wrap;
+    .item {
+        margin-right: 5px;
+    }
+    .alarm-item {line-height: 0 }
+}
+
+</style>

+ 164 - 0
src/views/alarm/notice/IndexContent.vue

@@ -0,0 +1,164 @@
+/**
+@author:fugy
+@date:2018.11.27
+@info:项目报警通知内容区 的容器
+**/
+<template>
+    <div class='box'>
+        <!-- 条件 -->
+        <div class='condition'>
+            <div class='tab-switch'>
+                <p :class='tabIndex == 0 ? "tab-checked" : ""' @click='tabSwitch'>通过报警查看通知人员</p>
+                <p :class='tabIndex == 1 ? "tab-checked" : ""' @click='tabSwitch'>通过人员查看报警通知</p>
+            </div>
+            <div class='no-set' v-show='tabIndex == 0'>
+                <el-checkbox v-model='checked' @change='checkBoxHandle'>只看尚未设定人员通知的报警</el-checkbox>
+            </div>
+            <div class='btn'>
+                <el-button v-show='tabIndex == 0' size='medium' @click='setUser'>为所选报警统一设定通知人员</el-button>
+                <el-button v-show='tabIndex == 1' type='text' icon='el-icon-setting' @click='mangeUser'>管理通知人员</el-button>
+            </div>
+        </div>
+        <div class='container'>
+            <!-- 表格 -->
+            <v-index-content-table
+                ref='table'
+                v-show='tabIndex == 0'
+                :tableParams='tableParams'
+                @select-change='selectChange'
+                @userRefresh='userRefresh'
+            ></v-index-content-table>
+            <!-- 列表 -->
+            <v-index-content-list ref="list" v-show='tabIndex == 1' :tableParams='tableParams' :userIndex='userIndex'></v-index-content-list>
+            <!-- 管理通知人员 -->
+            <v-manage-user :manageDialogVisible='manageDialogVisible' @refresh="userRefresh" :params="tableParams"></v-manage-user>
+        </div>
+    </div>
+</template>
+<script>
+import vIndexContentTable from './IndexContentTable'
+import vIndexContentList from './IndexContentList'
+import vManageUser from './ManageNoticeUser'
+import api from './api'
+export default {
+    name: 'index-content',
+    data() {
+        return {
+            manageDialogVisible: false, //管理通知人员
+            tabIndex: 0,
+            checked: false, //多选尚未设定的人的通知报警
+            selectBoxIdArr: [], //表格多选的alarm的id数组
+            /****params */
+            tableParams: {
+                projectId: '',
+                objType: null,
+                category: undefined,
+                code: [],
+                level: null,
+                instanceLocation: null,
+                notifyUserId: null,
+                hasNotifyUser: undefined,
+                alarmCategory: undefined
+            } //表格的参数
+        }
+    },
+    props: ['conditionParams','userIndex'],
+    components: {
+        vIndexContentTable,
+        vIndexContentList,
+        vManageUser
+    },
+    methods: {
+        tabSwitch() {
+            this.tabIndex = this.tabIndex ? 0 : 1;
+            if(this.tabIndex == 0) {
+                this.$refs.table.getList()
+            } else {
+                this.$refs.list.init()
+            }
+        },
+        // 表格多选事件
+        selectChange(arr) {
+            this.selectBoxIdArr = arr
+        },
+        setUser() {
+            if (this.selectBoxIdArr.length) {
+                this.$refs.table.setUser(null, true)
+            } else {
+                this.$message({
+                    message: '请选择报警',
+                    type: 'warning'
+                })
+            }
+        },
+        mangeUser() {
+            this.manageDialogVisible = !this.manageDialogVisible
+        },
+        checkBoxHandle(val) {
+            this.tableParams.hasNotifyUser = val ? 0 : 999
+        },
+        // 拼参数
+        handleParams(conditionParams) {            
+            this.tableParams.projectId = conditionParams.projectId
+            this.tableParams.objType = conditionParams.objType
+            this.tableParams.category = conditionParams.category
+            this.tableParams.code = conditionParams.code
+            this.tableParams.level = conditionParams.level
+            this.tableParams.instanceLocation = conditionParams.instanceLocation
+            this.tableParams.notifyUserId = conditionParams.notifyUserId
+            this.tableParams.alarmCategory = conditionParams.alarmCategory
+        },
+        //人员刷新
+        userRefresh() {
+            this.$emit("userRefresh")
+        } 
+    },
+    watch: {
+        conditionParams: {
+            deep: true,
+            handler: function(val) {
+                this.handleParams(val)
+            }
+        }
+    }
+}
+</script>
+<style lang="less" scoped>
+.tab-checked {
+    background: #aeaeae;
+    color: #fff;
+}
+.box {
+    font-size: 14px;
+    color: #606266;
+    .condition {
+        overflow: hidden;
+        .tab-switch {
+            float: left;
+            border: 1px solid #dcdfe6;
+            overflow: hidden;
+            p {
+                padding: 6px 15px;
+                float: left;
+                cursor: pointer;
+            }
+            p:nth-of-type(1) {
+                border-right: 1px solid #dcdfe6;
+            }
+        }
+        .no-set {
+            float: left;
+            line-height: 30px;
+            margin-left: 20px;
+        }
+        .btn {
+            float: right;
+            margin-right: 10px;
+        }
+    }
+    .container {
+        margin-top: 10px;
+        margin-right: 10px;
+    }
+}
+</style>

+ 396 - 0
src/views/alarm/notice/IndexContentList.vue

@@ -0,0 +1,396 @@
+/**
+@author:fugy
+@date:2018.11.28
+@info:项目报警通知列表表格
+**/
+<template>
+    <div class='box'>
+        <table v-if="tableData && tableData.length" class='table' border='1' cellpadding='0' cellspacing='0'>
+            <tr v-for='(item,index) in tableData' :key='index'>
+                <td v-show='item.isShow'>
+                    <div class='td-box' :style='"margin-left:" + ( 30 * item.level ) + "px;"'>
+                        <!-- 图标 -->
+                        <div class='icon-box'>
+                            <span v-if='item.isLow' @click='switchIcon(item)'>
+                                <i v-show='!item.isExpend' class='el-icon-caret-right'></i>
+                                <i v-show='item.isExpend' class='el-icon-caret-bottom'></i>
+                            </span>
+                        </div>
+                        <div class='con-box'>
+                            <!-- 1级 -->
+                            <p v-if='item.level == 1' class='first-level'>
+                                <span class='first-span first-span-name'>{{item.name}}</span>
+                                <span class='first-span'>{{item.phone}}</span>
+                                <span class='first-span'>{{item.email}}</span>
+                                <el-button type='text' class='first-btn' @click="addNotice(item)">增加通知</el-button>
+                            </p>
+                            <!-- 2级 -->
+                            <p v-else-if='item.level == 2'>
+                                <span>{{item.objName}}</span>
+                            </p>
+                            <!-- 3级 -->
+                            <p v-else-if='item.level == 3' class='three-level'>
+                                <span>{{item.instanceInfo}}</span>
+                                <!-- <el-button type='text' class='three-btn gray' @click="noLookObj(item)">不再关注此对象</el-button> -->
+                            </p>
+                            <!-- 4级 -->                            
+                            <p v-else-if='item.level == 4' class='four-level'>
+                                <span class='four-span'>{{item.alarmLevel}} 级</span>
+                                <span class='four-span'>{{item.alarmName}}</span>
+                                <!-- <el-button type='text' class='four-btn gray' @click="noLook(item)">不再关注</el-button> -->
+                                <v-check-box
+                                    class='four-check'
+                                    :sendMessage='item.notifyUserList&&item.notifyUserList.length ? item.notifyUserList[0].sendMessage: 0'
+                                    :sendEmail='item.notifyUserList&&item.notifyUserList.length ? item.notifyUserList[0].sendEmail: 0'
+                                    :sendWechat='item.notifyUserList&&item.notifyUserList.length ? item.notifyUserList[0].sendWechat: 0'
+                                    :define='item'
+                                    :isAll="false"
+                                    @change='checkBoxChange'
+                                ></v-check-box>
+                            </p>
+                        </div>
+                    </div>
+                </td>
+            </tr>
+        </table>
+        <div v-else style="text-align:center; line-height: 500px;">
+            暂无数据
+        </div>
+        <!-- 组件 -->
+        <v-user-add-notice :addNoticeDialogVisible="addNoticeDialogVisible" :userData="userData" :projectId="projectId" @refresh="refreshList"></v-user-add-notice>
+    </div>
+</template>
+<script>
+import api from './api'
+import proApi from '@/api/alarm/alarm'
+import utils from './utils'
+import proUtils from './utils'
+// component
+import vCheckBox from '@/components/alarm/common/CheckBox'
+import vUserAddNotice from './UserAddNotice'
+export default {
+    name: 'index-content-list',
+    data() {
+        return {
+            addNoticeDialogVisible: false,
+            userData: null,
+            projectId: null,
+            /**
+             * level: 级别
+             * isExpend: 图标样式
+             * isLow: 是否有下一级
+             * isShow: 当前行是否显示
+             * index: 下标
+             */
+            tableData: [],
+            pidArr: [], //树形结构pid数组
+            treeObj: [],
+            /****Dict***** */
+            entityDictObj: {} //对象类的名称
+
+        }
+    },
+    props: ['tableParams','userIndex'],
+    components: { vCheckBox , vUserAddNotice },
+    methods: {
+        /********************************树形结构----up************************************************************************** */
+        async switchIcon(row) {
+            row.isExpend = !row.isExpend
+            if (row.isExpend) {
+                if (row.level == 1) {
+                    await this.getAlarmList(row.id)
+                    this.tableData.forEach(hh => {
+                        if (hh.id == row.id && hh.level == 1) { //展开第一行
+                            this.pidArr = []
+                            hh.isExpend = true
+                        }
+                    })
+                }
+                //展开
+                this.pidArr.push(row.index)
+                this.pidArr.sort((a, b) => a - b)
+                this.expend()
+            } else {
+                //折叠
+                for (let i = 0; i < this.pidArr.length; i++) {
+                    if (row.index == this.pidArr[i]) {
+                        this.pidArr.splice(i, 1)
+                    }
+                }
+                this.refresh()
+            }
+        },
+        /********pidArr中存在,并且父级的isShow为true**** */
+        // 展开
+        expend() {
+            this.pidArr.forEach(item => {
+                this.tableData.forEach(ele => {
+                    if (item == ele.pid) {
+                        ele.isShow = true
+                    }
+                })
+            })
+            this.refresh()
+        },
+        // 刷新
+        refresh() {
+            this.tableData.forEach(ele => {
+                let pidFlag = this.pidArr.includes(ele.pid)
+                if (pidFlag) {
+                    //pid存在
+                    this.tableData.forEach(item => {
+                        //父级是否show
+                        if (item.index == ele.pid) {
+                            if (item.level == 1) {
+                                ele.isShow = item.isExpend
+                            } else {
+                                ele.isShow = item.isShow
+                            }
+                        }
+                    })
+                } else {
+                    if (ele.level == 1) {
+                        ele.isShow = true
+                    } else {
+                        ele.isShow = false
+                    }
+                }
+            })
+        },
+        /********************************树形结构----down************************************************************************** */
+        // checkbox多选回填
+        async checkBoxChange(obj, define) {         
+            let params = {   
+                projectId: this.tableParams.projectId,             
+                notifyUserId:define.notifyUserList[0].id,   
+                alarmConfigResultIdList:[{    
+                    alarmConfigResultId:define.alarmId,
+                    sendMessage: obj.sendMessage,
+                    sendEmail: obj.sendEmail,
+                    sendWechat: obj.sendWechat 
+                }]
+            };
+            let res = await api.setUpAlarmConfigResult(params);
+            if (res.result == "success") {
+                this.$message({
+                    message: '设定成功',
+                    type: 'success'
+                });
+            }
+        },
+        // 不再关注对象
+        noLookObj(item) {
+            this.$confirm('取消后,不再收到该对象下的报警提醒?', '提示', {
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'warning'
+            }).then(async () => {
+                let arr = []
+                this.tableData.forEach(ele => {
+                    if(ele.pid == item.index){
+                        let obj = {
+                            alarmConfigResultId:ele.alarmId,
+                            notifyType:[]
+                        }
+                        arr.push(obj);
+                    }
+                })
+
+                let params = {                
+                    notifyUserId:item.id,      
+                    alarmConfigResultIdList: arr
+                };
+                let res = await api.setUpAlarmConfigResult(params);
+                if (res.result == "success") {
+                    this.$message({
+                        message: '设定成功',
+                        type: 'success'
+                    });
+                }
+            }).catch(() => {
+                this.$message({
+                    type: 'info',
+                    message: '已取消'
+                });          
+            });
+        },
+        // 不再关注
+        async noLook(item) {
+            let params = {                
+                notifyUserId:item.id,      
+                alarmConfigResultIdList:[{
+                    alarmConfigResultId:item.alarmId,
+                    notifyType:[]
+                }]
+            };
+            let res = await api.setUpAlarmConfigResult(params);
+            if (res.result == "success") {
+                this.$message({
+                    message: '设定成功',
+                    type: 'success'
+                });
+            }
+        },
+        addNotice(item) {
+            this.userData = item;
+            this.addNoticeDialogVisible = !this.addNoticeDialogVisible
+        },
+        async getAlarmList(id) {
+            let params = {
+                criteria: {
+                    projectId: this.tableParams.projectId,
+                    notifyUserId: id
+                },
+                page: 1,
+                size: 1000
+            }
+            let res = await api.queryNotifyUserByAlarmConfigResult(params)
+            if (res.result == 'success' && res.count) {
+                // 获取location本地名称
+                let applyArr = []
+                res.content.forEach((item, index) => {
+                    applyArr.push({ id: item.instanceId })
+                    item.objName = utils.getObjName(item.objType) //对象名称
+                    if(item.notifyUserList) {
+                        let arr = item.notifyUserList.filter((user)=> {
+                            return user.id == id
+                        })
+                        item.notifyUserList = arr
+                    }
+                })
+                let param = { criterias: applyArr ,valid: null}
+                let resp = await proApi.getApplyObjInfo(this.tableParams.projectId, param)
+                if (resp.length) {
+                    this.entityDictObj = proUtils.entityDict(resp)
+                    res.content.forEach((ele, idx) => {
+                        let preName = proUtils.objPreName(ele.objType)
+                        let name =
+                            this.entityDictObj[ele.instanceId].infos[preName + 'LocalName'] ||
+                            this.entityDictObj[ele.instanceId].infos[preName + 'Name']
+                        let id =
+                            this.entityDictObj[ele.instanceId].infos[preName + 'LocalID'] ||
+                            this.entityDictObj[ele.instanceId].infos[preName + 'ID']
+                        ele.instanceInfo = name
+                    })
+                }
+                this.treeObj = await utils.alarmToTree(this.treeObj, id, res.content)
+                this.tableData = await utils.treeToData(this.treeObj)
+            }
+        },
+        async init() {           
+            // 获取人员
+            this.tableData = []
+            let userParams = {
+                criteria:{
+                    projectId: this.tableParams.projectId,
+                    id: this.tableParams.notifyUserId || undefined
+                }                
+            };
+            let res = await api.getUserList(userParams)
+            if (res.result == 'success' && res.count) {
+                this.treeObj = await utils.userToTree(res.content)
+                this.tableData = await utils.treeToData(this.treeObj)
+            }
+        },
+        refreshList() {
+            this.init();
+        },
+    },    
+    created() {
+         if(this.tableParams.projectId){
+            this.init()
+        }        
+    },
+    watch: {
+        tableParams: {
+            deep: true,
+            handler(val) {
+                this.projectId = val.projectId
+                this.init()
+            }
+        },
+        userIndex() {
+            this.init()
+        }
+    }
+}
+</script>
+<style lang="less" scoped>
+.gray {
+    color: #AEAEAE;
+}
+.box {
+    .table {  
+        width: 100%; 
+        border-width: 1px;
+        border-color: #ebeef5;
+        border-collapse: collapse;     
+        tr {
+            line-height: 40px;
+            td {
+               
+                border-width: 1px;
+                padding: 8px;
+                border-style: solid;
+                border-color: #ebeef5;
+                .td-box {
+                    overflow: hidden;
+                    .icon-box {
+                        float:left;
+                        width: 15px;
+                        height: 40px;
+                        cursor: pointer;
+                    };
+                    .con-box {
+                        width: 97%;
+                        float: left;
+                        margin-left: 10px; 
+                        overflow: hidden;
+                        p {
+                            overflow: hidden;
+                            width: 99%;
+                            float: left;
+                            margin-left: 10px;
+                        }
+                        .first-level{
+                            .first-span {
+                                float: left;
+                                width: 150px;
+                            }
+                            .first-span-name{
+                                width: 100px;
+                            }
+                            .first-btn {
+                                float: right;
+                            }
+                        }
+                        .three-level {
+                            .three-btn {
+                                float: right;
+                            }
+                        }
+                        .four-level {
+                            .four-span {
+                                float: left;
+                            }
+                            .four-span:nth-of-type(1) {
+                                width: 80px;
+                            }
+                            .four-btn {
+                                float: right;
+                            }
+                            .four-check {
+                                float: right;
+                                line-height: 22px;
+                                margin-top:8px;
+                                margin-right: 50px;
+                            }
+                        }
+                    }
+                }
+            } 
+        }
+    }
+}
+</style>
+

+ 204 - 0
src/views/alarm/notice/IndexContentTable.vue

@@ -0,0 +1,204 @@
+/**
+@author:fugy
+@date:2018.11.27
+@info:项目报警通知内容区的table表格
+**/
+<template>
+    <!-- content -->
+    <div class='box'>
+        <span class='all-select'>全选</span>
+        <el-table :data='tableData' border @selection-change='handleSelectionChange' style='width: 100%' v-loading="loading">
+            <el-table-column type='selection' width='60'></el-table-column>
+            <el-table-column prop='alarmCategory' label='报警分类' width="100"></el-table-column>
+            <el-table-column prop='instanceInfo' label='适用对象实例'></el-table-column>
+            <el-table-column prop='name' label='报警条目名称'></el-table-column>
+            <el-table-column label='报警条目编码' header-align='center'>
+                <template slot-scope='scope'>
+                    <p style='display: flex; justify-content: space-between'>
+                        <span>{{scope.row.code}}</span>
+                        <el-tag style='margin-left: 10px;' v-if='scope.row.type=="customed"'>自定义</el-tag>
+                    </p>
+                </template>
+            </el-table-column>
+            <el-table-column prop='level' label='严重程度'></el-table-column>
+            <el-table-column label='通知人员'>
+                <template slot-scope='scope'>
+                    <p style='display: flex; justify-content: space-between; line-height: 40px;'>
+                        <span>{{scope.row.noticeUserName}}</span>
+                        <el-button v-if='scope.row.noticeUserName' type='text' @click='setUser(scope.row)'>更改</el-button>
+                        <el-button v-else type='text' @click='setUser(scope.row)'>设定</el-button>
+                    </p>
+                </template>
+            </el-table-column>
+        </el-table>
+        <base-pagination style='margin-top: 10px;' :total='count' :currentPages='page' @pageChanged='pageChange'></base-pagination>
+        <!-- component -->
+        <v-set-user
+            :setDialogVisible='setDialogVisible'
+            :setUserData='setUserData'
+            :alarmIdArr='alarmIdArr'
+            :params='tableParams'
+            @to-manage='toManageUser'
+            @refresh='refresh'
+        ></v-set-user>
+        <v-manage-user :manageDialogVisible='manageDialogVisible' @refresh='userRefresh' :params='tableParams'></v-manage-user>
+    </div>
+</template>
+<script>
+import vSetUser from './SetNoticeUser'
+import vManageUser from './ManageNoticeUser'
+import api from './api'
+import fixApi from '@/api/alarm/alarm'
+import fixUtils from './utils'
+export default {
+    name: 'index-content-table',
+    data() {
+        return {
+            loading: false,
+            setDialogVisible: false,
+            setUserData: null, //设定人员数组
+            alarmIdArr: null, //数组
+            manageDialogVisible: false, //管理通知人员
+
+            /*******/
+            tableData: [],
+            count: 0,
+            /***params*** */
+            page: 1,
+            size: 10,
+            // dict
+            entityDictObj: {}
+        }
+    },
+    components: {
+        vSetUser,
+        vManageUser
+    },
+    props: ['tableParams'],
+    methods: {
+        pageChange(page, size) {
+            this.page = page
+            this.size = size
+            this.getList()
+        },
+        // 设定or更改人员===flag是否是通过批量设定
+        setUser(row, flag) {
+            if (flag) {
+                this.setUserData = []
+            } else {
+                this.alarmIdArr = [row.id]
+                this.setUserData = row.notifyUserList || []
+            }
+            this.setDialogVisible = !this.setDialogVisible
+        },
+        // 管理通知人员
+        toManageUser() {
+            this.manageDialogVisible = !this.manageDialogVisible
+        },
+        // 多选事件
+        handleSelectionChange(val) {
+            let arr = []
+            val.forEach(item => {
+                arr.push(item.id)
+            })
+            this.alarmIdArr = arr
+            this.$emit('select-change', arr)
+        },
+        // 刷新
+        refresh() {
+            this.getList()
+        },
+        // 获取list数据
+        async getList() {
+            this.loading = true;
+            this.tableData = [];
+            let params = {
+                criteria: {
+                    projectId: this.tableParams.projectId, //项目ID
+                    level: this.tableParams.level || undefined,
+                    notifyUserId: this.tableParams.notifyUserId || undefined,
+                    code: this.tableParams.code.length ? this.tableParams.code : undefined,
+                    position: this.tableParams.instanceLocation || undefined,
+                    objType: this.tableParams.objType || undefined,
+                    category: this.tableParams.category ? {"$in":this.tableParams.category} : undefined,
+                    hasNotifyUser: this.tableParams.hasNotifyUser == 999 ? undefined : this.tableParams.hasNotifyUser,
+                    alarmCategory: this.tableParams.alarmCategory || undefined
+                },
+                page: this.page,
+                size: this.size
+            }
+            let res = await api.queryNotifyUserByAlarmConfigResult(params)
+            this.loading = false;
+            if (res.result == 'success' && res.count) {
+                let applyArr = []
+                res.content.forEach(item => {
+                    applyArr.push({ id: item.instanceId })
+                    let str = ''
+                    if (item.notifyUserList) {
+                        item.notifyUserList.forEach(ele => {
+                            str += ele.name + '、'
+                        })
+                        str = str.substring(0, str.length - 1)
+                    }
+                    item.noticeUserName = str
+                })
+                // 去获取适用对象类的本地信息 ---- 对象位置-位置-ID
+                let param = { criterias: applyArr ,valid: null}
+                fixApi.getApplyObjInfo(this.tableParams.projectId, param).then(resp => {
+                    if (resp.length) {
+                        this.entityDictObj = fixUtils.entityDict(resp)
+                        res.content.forEach((ele, idx) => {
+                            let preName = fixUtils.objPreName(ele.objType)        
+                            let name =
+                                this.entityDictObj[ele.instanceId].infos[preName + 'LocalName'] ||
+                                this.entityDictObj[ele.instanceId].infos[preName + 'Name']
+                            let id =
+                                this.entityDictObj[ele.instanceId].infos[preName + 'LocalID'] ||
+                                this.entityDictObj[ele.instanceId].infos[preName + 'ID']
+                            if (preName == 'facility') {
+                                ele.instanceInfo =
+                                    name + ' - ' + id + (ele.instanceLocation ? ' - ' + ele.instanceLocation : '')
+                            } else {
+                                ele.instanceInfo = name + ' - ' + id
+                            }
+                        })
+                        // 最后赋值
+                        this.count = res.count
+                        this.tableData = res.content
+                    }
+                })
+            } else {
+                this.count = 0
+                this.tableData = []
+            }
+        },
+        // 人员刷新
+        userRefresh() {
+            this.getList()
+            this.$emit("userRefresh")
+        }
+    },
+    watch: {
+        tableParams: {
+            deep: true,
+            handler(val) {
+                this.page = 1
+                this.getList()
+            }
+        }
+    }
+}
+</script>
+<style lang="less" scoped>
+.box {
+    position: relative;
+    .all-select {
+        position: absolute;
+        top: 15px;
+        left: 30px;
+        z-index: 9;
+        color: #909399
+    }
+}
+</style>
+

+ 209 - 0
src/views/alarm/notice/ManageNoticeUser.vue

@@ -0,0 +1,209 @@
+/**
+@author:fugy
+@date:2018.11.28
+@info:管理通知人员
+**/
+<template>
+  <el-dialog title="管理通知人员" :visible.sync="dialogVisible" width="50%" center>
+    <div class="box" v-if="isrefresh">
+      <el-table :data="tableData" style="width: 100%" border> 
+        <el-table-column label="姓名">
+          <template slot-scope="scope">
+            <el-input v-if="scope.row.edit" v-model.trim="scope.row.name" size="small" placeholder="请输入姓名"/>
+            <span v-else>{{scope.row.name}}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="手机号">
+          <template slot-scope="scope">
+            <el-input v-if="scope.row.edit" v-model.trim="scope.row.phone" size="small" placeholder="请输入手机号码"/>
+            <span v-else>{{scope.row.phone}}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="邮箱地址">
+          <template slot-scope="scope">
+            <el-input v-if="scope.row.edit" v-model.trim="scope.row.email" size="small" placeholder="请输入邮箱地址"/>
+            <span v-else>{{scope.row.email}}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作">
+          <template slot-scope="scope">
+            <p v-if="scope.row.edit">
+              <el-button type="text" size="small" @click="save(scope.row)">保存</el-button>
+              <el-button type="text" size="small" class="gray" @click="cancel(scope)">取消</el-button>
+            </p>
+            <p v-else>
+              <el-button type="text" size="small" class="red" @click="del(scope)">删除人员</el-button>
+              <el-button type="text" size="small" @click="edit(scope.row)">编辑个人信息</el-button>
+            </p>
+          </template>
+        </el-table-column>
+      </el-table>
+      <p>
+        <el-button type="text" icon="el-icon-setting" @click="addUser">添加人员</el-button>
+      </p>
+    </div>
+  </el-dialog>
+</template>
+<script>
+import api from "./api";
+import utils from './utils';
+export default {
+  name: "set-notice-user",
+  data() {
+    return {
+      dialogVisible: false,
+      tableData: [],
+      isrefresh: true,
+    }
+  },
+  props: ["manageDialogVisible","params"],
+  methods: {
+    async getUserData() {
+        this.tableData = []
+      let params = {
+          criteria: {
+              projectId: this.params.projectId
+          }           
+      }
+      let res = await api.getUserList(params);
+      if (res.result && res.count) {
+        res.content.forEach(ele => {
+          ele.edit = false;
+        });
+        this.tableData = res.content;
+      }
+    },
+    addUser() {
+        this.tableData.push(this.initUser());        
+    },
+    initUser() {
+        return {name: "", phone: "", email: "", edit: true};
+    },
+    // 保存
+    async save(row) {
+        // 正则校验==姓名必填---其余的填写就校验
+        if(row.name && row.phone) {
+            if(row.phone) {
+                if(/^1[3456789]\d{9}$/.test(row.phone)) {
+                    //判断手机号是否重复
+                    let flag = utils.repetePhone(this.tableData, row)
+                    if(!flag){
+                        this.message('手机号重复,请重新填写');
+                        return;
+                    }
+                } else {
+                    this.message('手机格式不正确');
+                    return;
+                }
+            }
+            if(row.email) {
+                if(/^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/.test(row.email)) {
+
+                } else {
+                    this.message('邮箱格式不正确');
+                    return;
+                }
+            }
+        } else {
+            this.message('请填写姓名和手机号码');
+            return;
+        }
+        let params = {
+            name: row.name,
+            phone: row.phone,
+            email: row.email
+        };
+        if(row.id) { //编辑保存
+            params.id = row.id;
+            params.projectId = this.params.projectId
+            let res = await api.userEditSave(params);
+            if(res.result == "success") {
+                row.edit = false;
+                this.successMsg();
+            }
+        } else { //新增保存            
+            params.projectId = this.params.projectId
+            let res = await api.userAddSave(params);
+            if(res.result == "success") {
+                row.edit = false;
+                this.getUserData()
+                this.successMsg();
+                this.isrefresh = this.isrefresh ? false : true;
+                this.$nextTick(() => {
+                    this.isrefresh = this.isrefresh ? false : true;
+                })
+            }  
+        };
+        this.$emit("refresh");     
+    },
+    // message
+    message(msg) {
+        this.$message({
+            message: msg,
+            type: 'warning'
+        });
+    },
+    // 删除
+    del(scope) {
+        this.$confirm('删除后,此人员将不再收到任何报警通知, 是否继续?', '删除人员', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }).then(() => {
+            let params = { id: scope.row.id , projectId: this.params.projectId}
+            api.delUser(params).then(res => {
+                if(res.result == "success") {
+                    this.tableData.splice(scope.$index, 1);
+                    this.$message({
+                        type: 'success',
+                        message: '删除成功!'
+                    });
+                    this.$emit("refresh");     
+                }                
+            })         
+        }).catch(() => {
+          this.$message({
+            type: 'info',
+            message: '已取消删除'
+          });          
+        });
+    },
+    successMsg() {
+        this.$message({
+          message: '保存成功',
+          type: 'success'
+        });
+    },
+    // 取消 编辑取消or新建取消
+    cancel(scope) {
+        if(scope.row.id) {
+            scope.row.edit = false;
+        } else {
+            this.tableData.splice(scope.$index, 1)
+        }
+    },
+    // 编辑
+    edit(row) {
+        row.edit = true;
+    }
+  },
+  watch: {
+    manageDialogVisible() {
+      this.dialogVisible = true;
+      this.getUserData();
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+.box {
+  font-size: 16px;
+}
+.red {
+    color: red;
+}
+.gray {
+    color: #AEAEAE;
+}
+</style>
+

+ 141 - 0
src/views/alarm/notice/SetNoticeUser.vue

@@ -0,0 +1,141 @@
+/**
+@author:fugy
+@date:2018.11.27
+@info:设定通知人员
+**/
+<template>
+  <el-dialog title="设定通知人员" :visible.sync="dialogVisible" width="50%" center>
+    <div class="box" v-if="userData.length">
+      <ul class="ul-box">
+        <li class="tit">
+          <p>人员姓名及通知方式</p>
+        </li>
+        <li v-for="(item, index) in userData" :key="index">
+            <p>
+                <span class="name">{{item.name}}</span>
+                <span class="name">{{item.phone}}</span>
+                <span class="name">{{item.email}}</span>
+            </p>         
+          <span>
+            <v-check-box :sendMessage='item.sendMessage' :sendEmail='item.sendEmail' :sendWechat='item.sendWechat' :define="index" @change="checkBoxChange"></v-check-box>
+          </span>
+        </li>
+      </ul>      
+    </div>
+    <div v-else style="text-align:center;">暂无人员</div>
+    <p>
+        <el-button type="text" icon="el-icon-setting" @click="manageUser">管理通知人员</el-button>
+      </p>
+    <span slot="footer" class="dialog-footer">
+        <el-button size="middle" type="primary" @click="save">保 存</el-button>
+        <el-button size="middle" @click="dialogVisible = false">取 消</el-button>      
+    </span>    
+  </el-dialog>
+</template>
+<script>
+import api from "./api";
+import vCheckBox from "@/components/alarm/common/CheckBox";
+import utils from "./utils";
+export default {
+  name: "set-notice-user",
+  data() {
+    return {
+      dialogVisible: false,
+      userData: []
+    }
+  },
+  props: ["setDialogVisible", "setUserData", "alarmIdArr", "params"],
+  components: {
+    vCheckBox,
+    // vCheckBox1
+  },
+  methods: {
+    async getUserData() {
+        this.userData = []
+      let params = {
+          criteria: {
+              projectId: this.params.projectId
+          }          
+      }
+      let res = await api.getUserList(params);
+      if (res.result && res.count) {
+          this.handleData(res.content)      
+      }
+    },
+    handleData(res) {
+      res.forEach(item => {
+          this.setUserData.forEach(ele => {
+              if(item.id == ele.id) {
+                  item.sendMessage = ele.sendMessage;
+                  item.sendEmail = ele.sendEmail;
+                  item.sendWechat = ele.sendWechat;
+              }
+          })
+      });
+      this.userData = res;
+    },
+    // 管理通知人员
+    manageUser() {
+        this.dialogVisible = false;
+        this.$emit("to-manage");
+    },
+    checkBoxChange(obj, index) {
+        this.userData[index].sendMessage = obj.sendMessage;
+        this.userData[index].sendEmail = obj.sendEmail;
+        this.userData[index].sendWechat = obj.sendWechat;
+    },
+    async save() {
+        let notifyUserList = await utils.setNoticeUserData(this.userData);
+        let alarmConfigResultIdList = this.alarmIdArr;;
+        let params = {
+            projectId: this.params.projectId,
+            alarmConfigResultIdList: alarmConfigResultIdList,
+            notifyUserList: notifyUserList
+        };
+        let res = await api.setNoticeUser(params);
+        if(res.result == "success") {
+            this.$emit("refresh")          
+            this.$message({
+                type: 'success',
+                message: '保存成功'
+            });
+            this.dialogVisible = false;
+        }
+    },
+    refresh() {
+        this.$emit("refresh")        
+    }   
+  },
+  watch: {
+    setDialogVisible() {
+      this.dialogVisible = true;
+      this.getUserData();
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+.box {
+  font-size: 16px;
+  .ul-box {
+    border: 1px solid #ebeef5;
+    border-bottom: none;
+    li {
+      padding: 10px;
+      display: flex;
+      justify-content: space-between;
+      border-bottom: 1px solid #ebeef5;
+      p {
+          display: flex;
+          .name {
+              width: 150px;
+          }
+      }
+    }
+    .tit {
+      justify-content: center;
+    }
+  }
+}
+</style>
+

+ 295 - 0
src/views/alarm/notice/UserAddNotice.vue

@@ -0,0 +1,295 @@
+/**
+@author:fugy
+@date:2018.11.29
+@info:为指定人员添加报警通知
+**/
+<template>
+<div v-if="dialogVisible">
+    <el-dialog :title='title' :visible.sync='dialogVisible' width='70%' center>
+    <div class='box'>
+        <div class='condition'>
+            <v-obj-location class="item" v-if="projectId" :projectId="projectId" @change="objLocationChange"></v-obj-location>
+            <v-obj-type class="item" @change="objTypeChange"></v-obj-type>
+            <v-lv-select class="item" @change='lvSelectChange'></v-lv-select> 
+            <v-alarm-item @change="alarmItemChange" :objTypeArr="objTypeArr"></v-alarm-item>
+        </div>
+        <div class='table'>
+            <el-table :data='tableData' style='width: 100%' border height='500' v-loading="loading" @sort-change="sortChange" :empty-text="emptyText">
+                <el-table-column prop='instanceInfo' label='适用对象实例' sortable></el-table-column>
+                <el-table-column prop='code' label='报警条目编码' sortable></el-table-column>
+                <el-table-column prop='name' label='报警条目名称'></el-table-column>
+                <el-table-column prop='level' label='严重程度' sortable width="120"></el-table-column>
+                <el-table-column label='通知方式' width='350'>
+                    <template slot-scope='scope'>
+                        <v-check-box
+                            :define='scope.$index'
+                            @change='checkBoxChange'
+                        ></v-check-box>
+                    </template>
+                </el-table-column>
+            </el-table>
+        </div>
+    </div>
+    <span slot='footer' class='dialog-footer'>
+        <el-button type='primary' @click='save'>保 存</el-button>
+        <el-button @click='dialogVisible = false'>取 消</el-button>
+    </span>
+    <!-- conponent -->
+    <v-apply :applyDialogVisible='applyDialogVisible' :id='userData ? userData.id : ""' :alarmIdArr="alarmIdArr" @refresh="refresh" @close="closeDialog" :projectId='projectId'></v-apply>
+    </el-dialog>
+</div>
+
+</template>
+
+<script>
+import api from './api'
+import utils from "./utils"
+import proApi from '@/api/alarm/alarm'
+import proUtils from './utils'
+// component
+import vCheckBox from '@/components/alarm/common/CheckBox'
+import vApply from './ApplyDialog'
+import vLvSelect from './common/LvSelect'
+import vObjLocation from '@/components/alarm/common/ObjLocation'
+import vObjType from '@/components/alarm/common/ObjType'
+import vAlarmItem from '@/components/alarm/common/AlarmItem'
+//utils
+import fixedUtils from '@/components/alarm/common/utils'
+// vuex
+import { mapGetters } from 'vuex';
+
+export default {
+    name: '',
+    data() {
+        return {
+            applyDialogVisible: false, //批量适用于的flag
+            loading: false,
+            alarmIdArr: [],
+            dialogVisible: false,
+            title: null,
+            tableData: [],
+            objTypeArr: [],
+            params: {
+                projectId: null,
+                level: null,
+                code: [],
+                instanceLocation: null,
+                objType: null,
+                category: null
+            },
+            emptyText: "请使用关键字搜索或调整筛选查找",
+        }
+    },
+    computed: {
+        ...mapGetters("alarm",["spaceCodeObj"])
+    },
+    props: ['addNoticeDialogVisible', 'userData', 'projectId'],
+    components: { vCheckBox, vApply , vLvSelect , vObjLocation , vObjType , vAlarmItem },
+    methods: {
+        getData() {            
+            this.getList()
+        },
+        // 获取list数据
+        async getList() {
+            this.tableData = []
+            this.loading = true;
+            let params = {
+                criteria: {
+                    projectId: this.projectId, //项目ID
+                    objType: this.params.objType || undefined,
+                    category: this.params.category ? {"$in":this.params.category} : undefined,
+                    level: this.params.level || undefined,
+                    code: this.params.code.length ? this.params.code : undefined,
+                    position: this.params.instanceLocation || undefined,
+                },
+                page: 1,
+                size: 10000,
+            };            
+            let res = await api.queryNotifyUserByAlarmConfigResult(params)
+            this.loading = false;
+            this.emptyText = "获取数据中..."
+            if (res.result == 'success' && res.count) {
+                let applyArr = []
+                res.content.forEach(item => {
+                    applyArr.push({ id: item.instanceId })
+                })
+                // 去获取适用对象类的本地信息 ---- 对象位置-位置-ID
+                let param = { criterias: applyArr,valid: null }
+                proApi.getApplyObjInfo(this.projectId, param).then(resp => {
+                    if (resp.length) {
+                        this.entityDictObj = proUtils.entityDict(resp)
+                        res.content.forEach((ele, idx) => {
+                            let preName = proUtils.objPreName(ele.objType)
+                            let name =
+                                this.entityDictObj[ele.instanceId].infos[preName + 'LocalName'] ||
+                                this.entityDictObj[ele.instanceId].infos[preName + 'Name']
+                            let id =
+                                this.entityDictObj[ele.instanceId].infos[preName + 'LocalID'] ||
+                                this.entityDictObj[ele.instanceId].infos[preName + 'ID']
+                            if (preName == 'facility') {
+                                ele.instanceInfo =
+                                    name + ' - ' + id + (ele.instanceLocation ? ' - ' + ele.instanceLocation : '')
+                            } else {
+                                ele.instanceInfo = name + ' - ' + id
+                            }
+                        })
+                        // 最后赋值
+                        this.tableData = res.content
+                    }
+                })
+            } else {
+                this.tableData = [];
+                this.emptyText = "暂无数据"
+            }
+        },
+        checkBoxChange(obj, index) {
+            this.tableData[index].sendMessage = obj.sendMessage;
+            this.tableData[index].sendEmail = obj.sendEmail;
+            this.tableData[index].sendWechat = obj.sendWechat;
+        },
+        // 保存
+        async save() {
+            let {alarmConfigResultIdList , alarmIdArr } = utils.getAlarmItemAndNotice(this.tableData);
+            if(!alarmConfigResultIdList.length) {
+                this.$message({
+                    message: '请选择',
+                    type: 'warning'
+                });
+                return;
+            };
+            let params = {
+                projectId: this.projectId,
+                notifyUserId: this.userData.id,
+                alarmConfigResultIdList: alarmConfigResultIdList
+            };
+            let res = await api.setUpAlarmConfigResult(params);
+            if(res.result == "success") {
+                this.$message({
+                    message: '保存成功',
+                    type: 'success'
+                });
+                // 开启批量适用于                
+                this.alarmIdArr = alarmIdArr;
+                setTimeout(()=> {
+                    this.applyDialogVisible = !this.applyDialogVisible;
+                },500);
+            }        
+        },
+        // 排序
+        sortChange(arg) {
+            if(arg.prop) {
+                if(arg.prop == "level") {
+                   let S = this.tableData.filter((item) => {
+                       return item.level == "S"
+                   });
+                   let A = this.tableData.filter((item) => {
+                       return item.level == "A"
+                   });
+                   let B = this.tableData.filter((item) => {
+                       return item.level == "B"
+                   });  
+                   let C = this.tableData.filter((item) => {
+                       return item.level == "C"
+                   });
+                   let D = this.tableData.filter((item) => {
+                       return item.level == "D"
+                   });
+                   if(arg.order == "descending") {
+                       this.tableData = [].concat(S,A,B,C,D)                       
+                   } else {
+                       this.tableData = [].concat(D,C,B,A,S)
+                   }
+                }
+            } else {
+                this.getData();
+            }
+        },
+        refresh() {
+            this.dialogVisible = false;
+            this.$emit("refresh")
+        },
+        /*************组件回传************************************/ 
+        objLocationChange(val) {
+            this.params.instanceLocation = val || null;
+            this.getData();
+
+        },
+        objTypeChange(val) {
+            this.objTypeArr = val; 
+            if(val[0]) {
+                this.params.objType = val[0];
+                if(val[0] == "building" || val[0] == "floor") {
+                    this.params.category = null
+                } else if(val[0] == 'space'){
+                     if(val.length == 1) {
+                        this.params.category = null;
+                    } else {
+                        this.params.category = val[val.length - 1];
+                        let p = fixedUtils.spaceSonCode(val[val.length - 1], this.spaceCodeObj)
+                        this.params.category = p;
+                    }
+                } else {
+                    this.params.category = [val[val.length - 1]];
+                };
+            } else {
+                this.params.objType = undefined;
+                this.params.category = undefined;
+            }
+
+
+//  if(val.length == 1) {
+//                         this.params.category = null;
+//                     } else {
+//                         this.params.category = val[val.length - 1];
+//                         let p = fixedUtils.spaceSonCode(val[val.length - 1], this.spaceCodeObj)
+//                         this.params.category = p;
+//                     }
+
+
+
+
+            this.getData();
+        },
+        lvSelectChange(val) {
+            this.params.level = val || null;
+            this.getData();          
+        },
+        alarmItemChange(type, codeArr) {
+            this.params.code = codeArr;
+            this.getData();
+        },
+        closeDialog() {
+            this.dialogVisible = false
+            this.$emit("refresh")
+        }
+    },
+    created() {
+        if(!this.spaceCodeObj){
+            this.$store.commit("alarm/ADD_INDEX")
+        }
+    },
+    watch: {
+        addNoticeDialogVisible() {
+            this.dialogVisible = true;
+            this.tableData = [];
+            this.emptyText = "请使用关键字搜索或调整筛选查找";
+            this.title = `为  ${this.userData.name} ( ${this.userData.phone || "---"}       ${this.userData.email || "---"} ) 添加通知`
+            // this.getData()
+        }
+    }
+}
+</script>
+
+<style lang="less" scoped>
+.box {
+    .condition {
+        display: flex;
+        .item {
+            margin-right: 5px;
+        }
+
+    }
+}
+</style>
+
+

+ 73 - 0
src/views/alarm/notice/api.js

@@ -0,0 +1,73 @@
+/**
+@author:fugy
+@date:2018.11.27
+@info:项目报警通知
+ */
+import httputils from '@/utils/httputils';
+const api = {
+  // 获取报警通知table表格数据
+  queryNotifyUserByAlarmConfigResult(params) {
+    return new Promise(resolve => {
+      httputils.postJson('/server/alarm/notifyuser/queryNotifyUserByAlarmConfigResult', params, res => {
+        resolve(res)
+      })
+    })
+  },
+  // 获取项目通知人员列表
+  getUserList(params) {
+    return new Promise(resolve => {
+        httputils.postJson('/server/alarm/notifyuser/query', params, res => {
+        resolve(res)
+      })
+    })
+  },
+  // 批量设定通知人员
+  setNoticeUser(params) {
+    return new Promise(resolve => {
+      httputils.postJson('/server/alarm/notifyuser/setUpNotifyUser', params, res => {
+        resolve(res)
+      })
+    })
+  },
+    //批量设置人员下的报警条目通知方式
+    setUpAlarmConfigResult(params) {
+        return new Promise(resolve => {
+            httputils.postJson('/server/alarm/notifyuser/setUpAlarmConfigResult', params, res => {
+              resolve(res)
+            })
+        })
+    },
+  //添加人员
+  userAddSave(params) {
+    return new Promise(resolve => {
+      httputils.postJson('/server/alarm/notifyuser/create', params, res => {
+        resolve(res)
+      })
+    })
+  },
+  //编辑人员
+  userEditSave(params) {
+    return new Promise(resolve => {
+      httputils.postJson('/server/alarm/notifyuser/update', params, res => {
+        resolve(res)
+      })
+    })
+  },
+  // 删除人员
+  delUser(params) {
+    return new Promise(resolve => {
+      httputils.postJson('/server/alarm/notifyuser/delete', params, res => {
+        resolve(res)
+      })
+    })
+  },
+  // 为人员批量设置报警条目
+  setUpAlarmConfigResult(params) {
+      return new Promise(resolve => {
+          httputils.postJson('/server/alarm/notifyuser/setUpAlarmConfigResult', params, res => {
+            resolve(res)
+          })
+      })
+  }
+}
+export default api;

+ 70 - 0
src/views/alarm/notice/common/LvSelect.vue

@@ -0,0 +1,70 @@
+/**
+@author:fugy
+@date:2018.11.30
+@info:严重程度封装
+@prop: hasAll(是否需要全部[value需改])
+**/
+<template>
+<el-select style="width: 150px;" v-model="lvValue" placeholder="严重程度" @change="change">
+    <el-option
+        v-for="item in options"
+        :key="item.value"
+        :label="item.label"
+        :value="item.value">
+    </el-option>
+</el-select>
+</template>
+<script>
+    export default {
+        name: "level-select",
+        data() {
+            return {
+                options: [{
+                    label: "严重程度:全部",
+                    value: ""
+                },{
+                    label: "S",
+                    value: "S"
+                },{
+                    label: "A",
+                    value: "A"
+                },{
+                    label: "B",
+                    value: "B"
+                },{
+                    label: "C",
+                    value: "C"
+                },{
+                    label: "D",
+                    value: "D"
+                }],
+                lvValue: null
+            }
+        },
+        props:{
+            hasAll: {
+                type: Boolean,
+                default: true
+            }
+        },
+        methods: {
+            handleData() {
+                if(!this.hasAll) {
+                    this.options.shift()
+                }
+            },
+            change() {
+                this.$emit("change", this.lvValue)
+            }
+        },
+        watch: {
+            hasAll: {
+                immediate : true,
+                handler(){
+                    this.handleData()
+                }
+            }
+        }
+
+    }
+</script>

+ 74 - 0
src/views/alarm/notice/common/UserSelect.vue

@@ -0,0 +1,74 @@
+/**
+@author:fugy
+@date:2018.11.30
+@info:人员组件封装
+@prop: hasAll(是否需要全部[value需改])
+**/
+<template>
+<el-select style="width: 150px;" v-model="userValue" placeholder="人员全部" @change="change">
+    <el-option
+        v-for="(item,index) in options"
+        :key="index"
+        :label="item.name"
+        :value="item.id">
+    </el-option>
+</el-select>
+</template>
+<script>
+import api from "../api"
+    export default {
+        name: "user-select",
+        data() {
+            return {
+                options: [{
+                    name: "人员全部:全部",
+                    id: ""
+                }],
+                userValue: null
+            }
+        },
+        props:{
+            userIndex: {
+
+            },
+            projectId: {
+
+            }
+        },
+        methods: {
+            async getList() {
+                this.options = [this.initOpt()]
+                let params = {
+                    criteria:{
+                        projectId: this.projectId
+                    }
+                    
+                }
+                let res = await api.getUserList(params);
+                if (res.result && res.count) {
+                    this.options = this.options.concat(res.content);
+                }
+            },
+            change() {
+                this.$emit("change", this.userValue)
+            },
+            initOpt() {
+                return { name: "人员全部:全部",id: ""}
+            }
+        },
+        created() {
+            this.getList()
+        },
+        watch: {
+            userIndex() {
+                this.getList()
+            },
+            projectId() {
+                this.options = [this.initOpt()]
+                this.userValue = ""
+                this.getList()
+                this.change()
+            }
+        }
+    }
+</script>

+ 50 - 0
src/views/alarm/notice/index.vue

@@ -0,0 +1,50 @@
+/**
+@author:fugy
+@date:2018.11.27
+@info:项目报警首页容器container
+**/
+<template>
+<div>
+    <v-index-condition @change="conditionChange" :userIndex='userIndex'></v-index-condition>
+    <hr class="line" />
+    <v-index-content :conditionParams="conditionParams" @userRefresh='userRefresh' :userIndex='userIndex'></v-index-content>
+</div>
+</template>
+<script>
+import vIndexCondition from "./IndexCondition";
+import vIndexContent from "./IndexContent";
+export default {
+    name: "project-index",
+    data() {
+        return {
+            conditionParams: null,
+            userIndex: 0,
+        }
+    },
+    components: {
+        vIndexCondition,
+        vIndexContent
+    },
+    methods: {
+        conditionChange(params) {
+            this.conditionParams = params;
+        },
+        userRefresh() {
+            this.userIndex ++;
+        }
+    },
+    created() {
+
+    }
+
+}    
+</script>
+<style lang="less" scoped>
+.line {
+    background-color: #ccc;
+    height: 1px;
+    border: none;
+}
+</style>
+
+

+ 29 - 0
src/views/alarm/notice/remine.md

@@ -0,0 +1,29 @@
+###报警通知列表说明 (树)
+####表格渲染数据格式
+tableData = [{userId: 0, name: "张三", object: "建筑", objectName: "建筑名称", alarm: "报警条目222", level: 1, isExpend: false, isLow: true, isShow: true,    index: 0, pid: null},
+{userId: 0, name: "张三", object: "楼层", objectName: "楼层名称", alarm: "报警条目222", level: 2, isExpend: false, isLow: true, isShow: false,   index: 1, pid: 0},
+{userId: 0, name: "张三", object: "楼层", objectName: "楼层名称", alarm: "报警条目222", level: 3, isExpend: false, isLow: true, isShow: false,   index: 2, pid: 1},
+{userId: 0, name: "张三", object: "楼层", objectName: "楼层名称", alarm: "报警条目222", level: 4, isExpend: false, isLow: false, isShow: false,  index: 3, pid: 2},
+{userId: 0, name: "张三", object: "楼层", objectName: "楼层名称", alarm: "报警条目222", level: 4, isExpend: false, isLow: false, isShow: false,  index: 4, pid: 2},
+{userId: 0, name: "张三", object: "楼层", objectName: "楼层名称", alarm: "报警条目222", level: 2, isExpend: false, isLow: true, isShow: false,   index: 5, pid: 1},
+{userId: 0, name: "张三", object: "楼层", objectName: "楼层名称", alarm: "报警条目222", level: 3, isExpend: false, isLow: true, isShow: false,   index: 6, pid: 5},
+{userId: 0, name: "张三", object: "楼层", objectName: "楼层名称", alarm: "报警条目222", level: 4, isExpend: false, isLow: false, isShow: false,  index: 7, pid: 6},
+{userId: 0, name: "张三", object: "楼层", objectName: "楼层名称", alarm: "报警条目222", level: 4, isExpend: false, isLow: false, isShow: false,  index: 8, pid: 6},
+{userId: 1, name: "李四", object: "楼层", objectName: "楼层名称", alarm: "报警条目222", level: 1, isExpend: false, isLow: false, isShow: true,   index: 9, pid: null}]
+#####字段解释
+/**
+* level: 级别
+* isExpend: 图标样式
+* isLow: 是否有下一级
+* isShow: 当前行是否显示
+* index: 下标
+*/
+####树形对象结构(以人Id为主键)
+treeObj = {
+    useId : {
+        userInfo:{},
+        alarmData:[{},{},{}]
+    }
+}
+####通过pidArr进行显示隐藏(当前的pid在pidArr中 && 当前的级别的上一级别是显示的[判断是否是第一级])
+pidArr: [ 0, 1, 2] or [0,2] 

+ 281 - 0
src/views/alarm/notice/utils.js

@@ -0,0 +1,281 @@
+const utils = {
+  // 设定通知人员的提交数据处理
+  setNoticeUserData: function(data) {
+    let arr = []
+    data.forEach(item => {
+      let obj = {
+        id: item.id,
+        sendMessage: item.sendMessage || 0,
+        sendEmail: item.sendEmail || 0,
+        sendWechat: item.sendWechat || 0
+      }
+      arr.push(obj)
+    })
+    return arr
+  },
+  //   获取objType名称
+  getObjName(code) {
+    let name = '---'
+    switch (code) {
+      case 'building':
+        name = '建筑'
+        break
+      case 'floor':
+        name = '楼层'
+        break
+      case 'space':
+        name = '空间'
+        break
+      case 'system':
+        name = '系统类'
+        break
+      case 'facility':
+        name = '设备类'
+        break
+    }
+    return name
+  },
+  // 通过查看报警通知的原始数据=》树形结构
+  userToTree(userData) {
+    let obj = {}
+    userData.forEach(ele => {
+      obj[ele.id] = {}
+      obj[ele.id].userInfo = ele
+    })
+    return obj
+  },
+  //报警条目 =》 树形结构
+  alarmToTree(treeObj, userId, alarmData) {
+    treeObj[userId].alarmData = alarmData
+    return treeObj
+  },
+  //树形结构转为正常数据
+  treeToData(treeObj) {
+    // console.log('utils---------------------------------------------')
+    // console.log(treeObj)
+
+    let arr = []
+    for (let key in treeObj) {
+      var index1 = null
+      var index2 = null
+      var index3 = null
+      //   console.log(treeObj[key])
+      let obj = {}
+      let userValue = treeObj[key]
+      Object.assign(obj, userValue.userInfo)
+      obj.level = 1
+      obj.isExpend = false
+      obj.isLow = true
+      obj.isShow = true
+      obj.index = arr.length
+      obj.pid = null
+      index1 = arr.length
+      arr.push(obj) //1级数据
+      if (userValue.alarmData) {
+        let alarmArr = userValue.alarmData
+        var objType = alarmArr[0].objType
+        var count = 0
+        let userInfoData = Object.assign({}, userValue.userInfo)
+        alarmArr.forEach(item => {
+          // console.log("_________________________________________")
+          // console.log(item)
+          if (item.objType == objType) {
+            if (count == 0) {
+              let obj2 = {}
+              Object.assign(obj2, userInfoData)
+              obj2.alarmId = item.id
+              obj2.notifyUserList = item.notifyUserList
+              // obj2.alarmLevel = item.level;
+              obj2.objName = item.objName
+              // obj2.instanceInfo = item.instanceInfo;
+              // obj2.alarmName = item.name;
+              obj2.level = 2
+              obj2.isExpend = false
+              obj2.isLow = true
+              obj2.isShow = false
+              obj2.index = arr.length
+              obj2.pid = index1
+              index2 = arr.length
+              arr.push(obj2) //2级
+              let obj3 = {}
+              Object.assign(obj3, userInfoData)
+              obj3.alarmId = item.id
+              obj3.notifyUserList = item.notifyUserList
+              // obj3.alarmLevel = item.level;
+              // obj3.objName = item.objName;
+              obj3.instanceInfo = item.instanceInfo
+              // obj3.alarmName = item.name;
+              obj3.level = 3
+              obj3.isExpend = false
+              obj3.isLow = true
+              obj3.isShow = false
+              obj3.index = arr.length
+              obj3.pid = index2
+              index3 = arr.length
+              arr.push(obj3) //3级
+              let obj4 = {}
+              Object.assign(obj4, userInfoData)
+              obj4.alarmId = item.id
+              obj4.notifyUserList = item.notifyUserList
+              obj4.alarmLevel = item.level
+              // obj4.objName = item.objName;
+              // obj4.instanceInfo = item.instanceInfo;
+              obj4.alarmName = item.name
+              obj4.level = 4
+              obj4.isExpend = false
+              obj4.isLow = false
+              obj4.isShow = false
+              obj4.index = arr.length
+              obj4.pid = index3
+              arr.push(obj4) //4级
+              count++
+            } else {
+              //同4
+              let obj4 = {}
+              Object.assign(obj4, userInfoData)
+              obj4.alarmId = item.id
+              obj4.notifyUserList = item.notifyUserList
+              obj4.alarmLevel = item.level
+              // obj4.objName = item.objName;
+              // obj4.instanceInfo = item.instanceInfo;
+              obj4.alarmName = item.name
+              obj4.level = 4
+              obj4.isExpend = false
+              obj4.isLow = false
+              obj4.isShow = false
+              obj4.index = arr.length
+              obj4.pid = index3
+              arr.push(obj4) //4级
+            }
+          } else {
+            count = 1
+            objType = item.objType
+            //同上2-4
+            let obj2 = {}
+            Object.assign(obj2, userInfoData)
+            obj2.alarmId = item.id
+            // obj2.notifyUserList = item.notifyUserList;
+            // obj2.alarmLevel = item.level;
+            obj2.objName = item.objName
+            // obj2.instanceInfo = item.instanceInfo;
+            // obj2.alarmName = item.name;
+            obj2.level = 2
+            obj2.isExpend = false
+            obj2.isLow = true
+            obj2.isShow = false
+            obj2.index = arr.length
+            obj2.pid = index1
+            index2 = arr.length
+            arr.push(obj2) //2级
+            let obj3 = {}
+            Object.assign(obj3, userInfoData)
+            obj3.alarmId = item.id
+            // obj3.notifyUserList = item.notifyUserList;
+            // obj3.alarmLevel = item.level;
+            // obj3.objName = item.objName;
+            obj3.instanceInfo = item.instanceInfo
+            // obj3.alarmName = item.name;
+            obj3.level = 3
+            obj3.isExpend = false
+            obj3.isLow = true
+            obj3.isShow = false
+            obj3.index = arr.length
+            obj3.pid = index2
+            index3 = arr.length
+            arr.push(obj3) //3级
+            let obj4 = {}
+            Object.assign(obj4, userInfoData)
+            obj4.alarmId = item.id
+            obj4.notifyUserList = item.notifyUserList
+            obj4.alarmLevel = item.level
+            // obj4.objName = item.objName;
+            // obj4.instanceInfo = item.instanceInfo;
+            obj4.alarmName = item.name
+            obj4.level = 4
+            obj4.isExpend = false
+            obj4.isLow = false
+            obj4.isShow = false
+            obj4.index = arr.length
+            obj4.pid = index3
+            arr.push(obj4) //4级
+          }
+        })
+      }
+    }
+    return arr
+  },
+  //   增加通知获取报警通知人员的多条报警条目
+  getAlarmItemAndNotice(tableData) {
+    let alarmConfigResultIdList = []
+    let alarmIdArr = []
+    tableData.forEach(item => {
+      if (item.sendEmail || item.sendMessage || item.sendWechat) {
+        let obj = {
+          alarmConfigResultId: item.id,
+          sendEmail: item.sendEmail,
+          sendMessage: item.sendMessage,
+          sendWechat: item.sendWechat
+        }
+        alarmConfigResultIdList.push(obj)
+        alarmIdArr.push(item.id)
+      }
+    })
+    return { alarmConfigResultIdList, alarmIdArr }
+  },
+  // 批量适用于人员处理
+    applyUserHandle(data) {
+      let arr = []
+      data.forEach(item => {
+          if (item.sendMessage || item.sendEmail || item.sendWechat) {
+              let obj = {
+                  id: item.id,
+                  sendMessage: item.sendMessage,
+                  sendEmail: item.sendEmail,
+                  sendWechat: item.sendWechat
+              }
+              arr.push(obj)
+          }        
+          
+      })
+      return arr
+  },
+//   判断手机号是否重复
+    repetePhone(arr, row) {
+        let flag = true;
+        let farr = arr.filter(item => {
+          return item.phone == row.phone
+        })
+        if (farr.length > 1) {
+            flag = false
+        }        
+        return flag;
+    },
+    // 整合物理实体字典
+    entityDict(oldArr) {
+        let obj = {};
+        oldArr.forEach((ele, index) => {
+            obj[ele.id] = ele
+        })
+        return obj;
+    },
+    // 获取根据objtype获取名字前缀
+    objPreName: function (objType) {
+        let pre = null;
+        switch (objType) {
+            case "building":
+                pre = "Build"; break;
+            case "floor":
+                pre = "Floor"; break;
+            case "space":
+                pre = "Room"; break;
+            case "system":
+                pre = "Sys"; break;
+            case "facility":
+                pre = "Equip"; break;
+        }
+        return pre;
+    }
+}
+
+
+export default utils

+ 239 - 0
src/views/alarm/projalarm/addmodel.vue

@@ -0,0 +1,239 @@
+/**
+@author:fugy
+@date:2018.09.19
+@info:添加固定报警条目的model
+ */
+<template>
+<div v-if="dialogVisible">
+<el-dialog
+title="为项目添加报警条目"
+:visible.sync="dialogVisible"
+width="50%"
+center
+>
+    <div class="add-box">
+        <div class="top">
+            <span>对象类型 : </span>
+            <!-- <el-cascader
+            style="width: 300px;"
+            :options="objTypeOptions"
+            v-model="selectedOptions"
+            clearable
+            @change="objTypeHandle"
+            ></el-cascader> -->
+            <v-obj-type @change="objTypeChange" ref="objType" :objType="objTypeComValue" :hasVerify="false" width='400px'></v-obj-type>
+            <span v-if="!infoCode" class="hint"> * 请选择对象类型</span>
+        </div>
+        <hr class="line" />
+        <div class="content">
+            <p class="tooltip">
+                <el-input style="width: 400px;" placeholder="可输入关键字搜索自定义信息点" v-model.trim="searchValue" clearable>
+                    <el-button slot="append" icon="el-icon-search" @click="search()"></el-button>
+                </el-input>                
+            </p>
+            <div class="table-box">
+                <el-table
+                :data="tableData"
+                border
+                style="width: 100%">
+                    <el-table-column
+                        prop="infoPointName"
+                        label="信息点名称"
+                        header-align="center">
+                    </el-table-column>
+                    <el-table-column
+                        prop="infoPointCode"
+                        label="信息点"
+                        header-align="center">
+                    </el-table-column>
+                    <el-table-column
+                        label="操作"
+                        header-align="center">
+                        <template slot-scope="scope">
+                            <el-button type="text" @click="addItem(scope.row)">为此自定义点添加报警条目</el-button>
+                        </template>
+                    </el-table-column>
+                </el-table>
+            </div>
+        </div>
+    </div>
+    
+</el-dialog> 
+</div>
+</template>
+<script>
+import vObjType from '@/components/alarm/common/ObjType' //对象类型
+import api from "./api"
+    export default {
+        name: 'add-model',
+        data() {
+            return {
+                /********* */
+                objTypeComValue: [],
+                objTypeArr:[],
+                /********** */
+                dialogVisible: false,
+                searchValue: '',
+                // objTypeOptions: [ //对象类型级联框
+                // { 
+                //     value: 'building',
+                //     label: '建筑',
+                // },{
+                //     value: 'floor',
+                //     label: '楼层',
+                // },{
+                //     value: 'space',
+                //     label: '空间',
+                // },{
+                //     value: 'system',
+                //     label: '系统类',
+                //     children: []
+                // },{
+                //     value: 'facility',
+                //     label: '设备类',
+                //     children: []
+                // }],            
+                // selectedOptions: [], //级联款绑定的value
+                tableData: [], //表格数据
+                infoCode: null, //级联截取的后2位或者后4位编码
+                startCascadeValue: '', //是给create使用的值
+                endCascadeValue: '', //是给create使用的值
+            }
+        },
+        props:["addVisibleFlag","projectId"],
+        components: {
+            vObjType
+        },
+        methods: {
+            //自定义添加
+            addItem (row) {
+                this.dialogVisible = false;
+                this.$router.push({
+                    path: "/project/projectalarmcreate",
+                    query: {
+                        infoPointName: row.infoPointName,
+                        infoPointCode: row.infoPointCode,
+                        unit: row.unit,
+                        projectId:this.projectId,
+                        endCascadeValue: this.endCascadeValue,
+                        startCascadeValue: this.startCascadeValue,
+                        objTypeArr: this.objTypeArr,
+                    }
+                })
+                // this.$router.push("/project/projectalarmcreate?params=" + JSON.stringify(params));
+            },
+            // 对象类型的失焦时间
+            objTypeHandle(value) {
+                if(value.length){
+                    let firstCode = value[0];
+                    this.infoCode = value[value.length - 1];
+                    this.startCascadeValue = value[0];
+                    this.endCascadeValue = value[value.length - 1];
+                    if(firstCode == "system") {
+                        this.infoCode = this.infoCode.substring(2, 4);
+                    }
+                    if(firstCode == "facility") {
+                        this.infoCode = this.infoCode.substring(2, 6);
+                    }
+                } else {
+                    this.infoCode = null; 
+                } 
+                this.getListData();
+            },
+            //对象类回填事件
+            objTypeChange(val) {
+                this.objTypeArr = val
+                this.infoCode = null
+                if(val.length){
+                    this.infoCode = val[val.length - 1];
+                    this.startCascadeValue = val[0];
+                    this.endCascadeValue = val[val.length-1];
+                    if(val.length == 1 && this.startCascadeValue == "space") {
+                        this.endCascadeValue = null;
+                    }
+                    if(this.startCascadeValue == "space") {
+                        this.infoCode = "space"
+                        if(val.length == 1) {
+                            this.endCascadeValue = null;
+                        }
+                    }
+                    if(val[0] == "system" && val.length > 1) {
+                        this.infoCode = this.infoCode.substring(2, 4);
+                    }
+                    if(val[0] == "facility" && val.length > 1) {
+                        this.infoCode = this.infoCode.substring(2, 6);
+                    }
+                } else {
+                    this.startCascadeValue = null;
+                    this.endCascadeValue = null;
+                }
+                this.getListData();
+            },
+            // 搜索
+            search() {
+                if(this.tableData && this.tableData.length && this.searchValue) {
+                    let arr = this.tableData.filter((item, index) => {
+                        return (item.infoPointName == this.searchValue || item.infoPointCode == this.searchValue)
+                    })
+                    this.tableData = arr;
+                } else {
+                    this.getListData();
+                }
+            },
+            // 获取列表数据
+            getListData() {
+                if(!this.infoCode){
+                    this.tableData = [];
+                    return false;
+                }
+                let params = {
+                    type: this.infoCode,
+                    projectId: this.projectId
+                }
+                api.getCustomInfoListData(params).then((res) => {
+                    this.tableData = res;
+                }).catch(err => {
+                    throw err;
+                })
+            }
+        },
+        watch: {
+            addVisibleFlag () {
+                this.dialogVisible = true;
+                this.infoCode = null;
+                this.selectedOptions = [];
+                this.tableData = [];
+                // 获取列表数据
+                this.getListData();
+            }
+        }
+
+    }
+</script>
+<style lang='less' scoped>
+.add-box {
+    .top {
+        display: flex;
+        line-height: 40px;
+        .hint{
+            color: red;
+        }        
+    }
+    .line{
+        background-color: #ccc;
+        height: 1px;
+        border: none;
+    }
+    .content{
+        .tooltip {
+            text-align: right;
+        }
+        .table-box {
+            margin-top: 10px;
+            height: 500px;
+            overflow-y: auto; 
+        }
+    }
+}
+</style>
+

+ 182 - 0
src/views/alarm/projalarm/alarmitem.vue

@@ -0,0 +1,182 @@
+/**
+@author:fugy
+@date:2018.09.27
+@info:选择报警条目
+ */
+<template>
+<el-dialog
+title="选择报警条目"
+:visible.sync="dialogVisible"
+width="40%"
+center
+>
+    <div class="alarm-item-box">
+        <div class="radio-box">
+            <el-radio-group v-model="radioValue" @change="radioChange">
+                <el-radio-button label="fixed">固定条目</el-radio-button>
+                <el-radio-button label="customed">自定义条目</el-radio-button>                
+            </el-radio-group>
+        </div>
+        <div class="table-box">
+            <el-table
+            ref="multipleTable"
+            :loading="loading"
+            :data="tableData"
+            tooltip-effect="dark"
+            style="width: 100%"
+            border
+            @selection-change="handleSelectionChange">                
+                <el-table-column
+                header-align="center"
+                prop="code"
+                label="报警条目编码">                
+                </el-table-column>
+                <el-table-column
+                header-align="center"
+                prop="name"
+                label="报警条目名称">
+                </el-table-column>
+                <el-table-column
+                type="selection"
+                width="55">
+                </el-table-column>
+            </el-table>
+        </div>
+        <div class="btn-box">
+            <el-button type="primary" @click="save">保存</el-button>
+            <el-button class="cancel-btn" @click="cancel">取消</el-button>
+        </div>
+    </div>  
+</el-dialog> 
+</template>
+<script>
+import fixedApi from "../fixedalarmitem/api"
+export default {
+    name: 'alarm-item',
+    props: ["selectAlarmItemFlag", "projectId", "startCascadeValue", "endCascadeValue","selectAlarmItemArr","selectAlarmItemRadio"],
+    data() {
+        return {
+            dialogVisible: false,
+            loading: false,
+            radioValue: 'fixed', //默认固定
+            tableData: [], //表格数据
+            multipleSelection: [],
+            alarmItemArr:[], //传过来的报警条目数组 == selectAlarmItemArr
+        }
+    },
+    methods: {
+        // 多选事件
+        handleSelectionChange(val,index) {
+            this.multipleSelection = val;
+        },
+        // radio改变事件
+        radioChange(val) {
+            this.multipleSelection = [];
+            this.alarmItemArr = [];
+            this.getAlarmItem();
+        },
+        // 获取报警条目数据
+        getAlarmItem() {
+            this.loading = true;
+            let category = null;
+            if(this.startCascadeValue == "building" || this.startCascadeValue == "floor" || this.startCascadeValue == "space") {
+                category = null;
+            } else {
+                category = this.endCascadeValue;
+            }
+            let params = {
+                criteria: {
+                    type: this.radioValue,   //报警条目类别,fixed 固定,customed 自定义     **必须
+                    projectId: this.radioValue == "fixed" ? null : this.projectId,  //项目id,自定义类别时不为空
+                    keyword : null,  //对象类型,报警条目编码、报警条目编码名称、信息点名称、信息点id关键字,为null或没有此字段时不过滤此项
+                    objType: this.startCascadeValue,   //对象类型,building,floor,space,system,facility,为null或没有此字段时不过滤此项
+                    category: category, 
+                },                
+                page: null,   //页数   不传的时候取全部
+                size: null   //个数   
+            }  
+            fixedApi.getListData(params).then(res => {
+                if(res.result == "success"){
+                    this.loading = false;
+                    if(res.content && res.content.length) {
+                        this.tableData = res.content;    
+                        // 判断是否已经选中
+                        this.$nextTick(() => {
+                            // this.$refs.multipleTable.toggleRowSelection(this.tableData[0], true);  
+                            if(this.alarmItemArr) {
+                                let indexArr = [];
+                                this.alarmItemArr.length ? this.alarmItemArr.forEach((item, idx) =>{
+                                    this.tableData.forEach((ele, index) =>{
+                                        if(ele.code === item.code){
+                                            indexArr.push(index);
+                                        }    
+                                    })
+                                }) : null;
+                                indexArr.length ? indexArr.forEach((item) => {
+                                    this.$refs.multipleTable.toggleRowSelection(this.tableData[item], true);
+                                }) : null
+                            } else {
+                                this.$refs.multipleTable.clearSelection();
+                            }
+                        })
+                    } else {
+                        this.tableData =[];
+                    }                   
+                    }
+            });
+        },
+        // 保存
+        save() {
+            if(this.multipleSelection.length) {
+                this.$emit("select-alarm-item", this.multipleSelection, this.radioValue);
+                this.dialogVisible = false;
+            } else {
+                this.$message({
+					message: '请选择报警条目',
+					type: 'warning'
+				});
+            }
+        },
+        // 取消
+        cancel() {
+            this.dialogVisible = false;
+        }
+    },
+    watch: {
+        selectAlarmItemFlag() {
+            this.dialogVisible = true;
+            this.alarmItemArr = this.selectAlarmItemArr;
+            // 是否默认固定条目
+            if(this.selectAlarmItemRadio) {
+                this.radioValue = this.selectAlarmItemRadio
+            } else {
+                this.radioValue = "fixed";
+            }
+            
+            this.getAlarmItem();            
+        },   
+        selectAlarmItemArr(val) {
+            this.alarmItemArr = val
+        }  
+    }
+}
+</script>
+<style lang="less" scoped>
+.alarm-item-box{    
+    .radio-box{
+        text-align: center;
+    }
+    .table-box{
+        height: 500px;
+        overflow-y: auto;
+        margin-top: 10px;
+    }
+    .btn-box{
+        margin-top:10px;
+        text-align: center;
+        .cancel-btn{
+            margin-left: 50px;
+        }
+    }
+}
+</style>

+ 145 - 0
src/views/alarm/projalarm/api.js

@@ -0,0 +1,145 @@
+/**
+@author:fugy
+@date:2018.09.27
+@info:项目报警条目api
+ */
+import httputils from '@/utils/httputils'
+const api = {
+    //选择问题接口
+    getProblemList(params) {
+        return new Promise((resolve, reject) => {
+            httputils.postJson(
+                '/server/workorder/generalProblem/problem/query',
+                params,
+                res => {
+                    resolve(res)
+                },
+                fail => {
+                    reject(fail)
+                },
+                err => {
+                    reject(err)
+                }
+            )
+        })
+    },
+    // 获取对象实例的数目
+    getProjectExampleNum(params) {
+        return new Promise((resolve, reject) => {
+            httputils.getJson(
+                '/server/alarm/config/result/listProjectConfigsResultNums',
+                params,
+                res => {
+                    if (res.result == 'success') {
+                        resolve(res)
+                    }
+                },
+                fail => {
+                    reject(fail)
+                },
+                err => {
+                    reject(err)
+                }
+            )
+        })
+    },
+    // 获取项目的列表数据
+    getListData(params) {
+        return new Promise((resolve, reject) => {
+            httputils.postJson(
+                '/server/alarm/config/result/query',
+                params,
+                res => {
+                    if (res.result == 'success') {
+                        resolve(res)
+                    }
+                },
+                fail => {
+                    reject(fail)
+                },
+                err => {
+                    reject(err)
+                }
+            )
+        })
+    },
+    //修改开关状态
+    switchStatus(params) {
+        return new Promise((resolve, reject) => {
+            httputils.postJson(
+                '/server/alarm/config/result/updateProjectConfigResultOpenStatus',
+                params,
+                res => {
+                    if (res.result == 'success') {
+                        resolve(res)
+                    }
+                },
+                fail => {
+                    reject(fail)
+                },
+                err => {
+                    reject(err)
+                }
+            )
+        })
+    },
+    // 更新或者批量适用于
+    updateBatch(params) {
+        return new Promise((resolve, reject) => {
+            httputils.postJson(
+                '/server/alarm/config/result/update',
+                params,
+                res => {
+                    resolve(res)
+                },
+                fail => {
+                    reject(fail)
+                },
+                err => {
+                    reject(err)
+                }
+            )
+        })
+    },
+    // 获取自定义信息点的数据列表
+    getCustomInfoListData(params) {
+        return new Promise((resolve, reject) => {
+            httputils.getJson(
+                '/server/dataplatform/custom_infocode/query_property',
+                params,
+                res => {
+                    if (res.result === 'success') {
+                        resolve(res.data || [])
+                    }
+                },
+                fail => {
+                    reject(fail)
+                },
+                err => {
+                    reject(err)
+                }
+            )
+        })
+    },
+    // 通过根据Id批量获取各物理实体
+    getApplyObjInfo(projectId, data) {
+        return new Promise((resolve, reject) => {
+            httputils.postJson(
+                '/server/dataplatform/object/batchquery?projectId=' + projectId,
+                data,
+                res => {
+                    if (res.Result === 'success') {
+                        resolve(res.Content || [])
+                    }
+                },
+                fail => {
+                    reject(fail)
+                },
+                err => {
+                    reject(err)
+                }
+            )
+        })
+    }
+}
+export default api

+ 138 - 0
src/views/alarm/projalarm/batchapply.vue

@@ -0,0 +1,138 @@
+/**
+@author:fugy
+@date:2018.09.29
+@info:批量适用于
+ */
+ <template>
+<el-dialog
+title="批量适用于"
+:visible.sync="dialogVisible"
+width="40%"
+:close-on-click-modal="false"
+:show-close="false"
+center
+>
+    <div class="batch-box">
+        <div class="top">
+            <p>您可以勾选适用此报警条目的其他实例,以适用此次编辑</p>
+        </div>
+        <div class="table-box">
+            <el-table                
+                :data="tableData"
+                tooltip-effect="dark"
+                style="width: 100%"
+                border
+                @selection-change="handleSelectionChange">                
+                <el-table-column
+                prop="instanceInfo"
+                label="对象实例"
+                header-align="center">
+                </el-table-column>
+                <el-table-column
+                    type="selection"
+                    width="55">
+                </el-table-column>
+            </el-table>
+        </div>
+        <div class="btn-box">
+            <el-button type="primary" @click="save">确定</el-button>
+            <el-button class="cancel" @click="cancel">取消</el-button>   
+        </div>
+    </div>
+</el-dialog>
+ </template>
+ 
+ <script>
+ import api from "./api"; //api;
+ import utils from "./utils"; //api
+
+export default {
+    name: "batch-apply",
+    data() {
+        return {            
+            dialogVisible: false,
+            multipleSelection: [], //多选框
+            tableData: [],
+            entityDictObj:[], //对象实例的本地字典
+        }
+    },
+    props:["batchApplyFlag", "batchApplyArr", "id", "projectId"],
+    methods: {
+        // checkbox选择事件
+        handleSelectionChange(val) {
+            this.multipleSelection = val;
+        },
+        // 批量数据处理
+        btachListHandle() {
+            let applyArr = [];            
+            this.batchApplyArr.forEach((item, index, arr) => {   
+                if(item.id == this.id) {
+                    arr.splice(index, 1);
+                };              
+            });
+            // 中转适用对象类实例
+            this.batchApplyArr.forEach((item, index, arr) => {  
+                applyArr.push({id: item.instanceId})            
+			});
+            let params = {criterias: applyArr, valid: null}
+            api.getApplyObjInfo(this.projectId, params).then(resp => {	
+                if(resp.length) {
+                    this.entityDictObj = utils.entityDict(resp);
+                    this.batchApplyArr.forEach((ele, idx) => {
+                        let preName = utils.objPreName(ele.objType);
+                        let name = this.entityDictObj[ele.instanceId].infos[preName + "LocalName"] || this.entityDictObj[ele.instanceId].infos[preName + "Name"];
+                        let id = this.entityDictObj[ele.instanceId].infos[preName + "LocalID"] || this.entityDictObj[ele.instanceId].infos[preName + "ID"];
+                        if(preName == "facility") {
+                            ele.instanceInfo = name + " - " + id + (ele.instanceLocation ? " - "+ele.instanceLocation : "");
+                        } else {
+                            ele.instanceInfo = name + " - " + id;
+                        }
+                    })
+                    // 最后赋值
+                    this.tableData = this.batchApplyArr;				
+                }
+            })
+        },
+        // 保存
+        save() {
+            let arr = this.multipleSelection.length ? this.multipleSelection: [];
+            this.$emit("batch-apply-handle", arr);
+            this.dialogVisible = false;
+        },
+        // 取消
+        cancel() {
+            let arr = []
+            this.$emit("batch-apply-handle", arr);
+            this.dialogVisible = false;
+        }
+    },
+    watch: {
+        batchApplyFlag() {
+            this.dialogVisible = true;
+            this.btachListHandle();
+        }
+    }
+}
+ </script>
+ <style lang="less" scoped>
+.batch-box {
+    .top {
+        text-align: center;
+    }
+    .table-box{
+        height: 500px;
+        overflow-y: auto; 
+        margin-top: 10px;
+    }
+    .btn-box {
+        margin-top: 10px;
+        text-align: center;
+        .cancel {
+            margin-left: 50px;
+        }
+    }
+}
+ 
+ </style>
+ 
+ 

+ 813 - 0
src/views/alarm/projalarm/create.vue

@@ -0,0 +1,813 @@
+/**
+@author:fugy
+@date:2018.09.18
+@info:项目报警条目添加与编辑
+ */
+<template>
+<div class="edit-box">
+    <h5 class="title">添加报警条目</h5>
+    <div class="form-box">
+        <el-form 
+        label-width="150px"
+        :model="formValue"
+        :rules="rules" 
+        ref="ruleForm">
+            <el-form-item label="适用对象类" prop="objTypeRules">
+                <span class="infoStar">*</span>
+                <v-obj-type ref="objType" :objType="objTypeComValue" :disabled='true' width='400px'></v-obj-type>
+            </el-form-item>
+            <el-form-item label="报警条目编码" prop="code">
+                <el-input
+                placeholder="请输入不超过10位的数字"
+                v-model="formValue.code"
+                clearable>
+                </el-input>
+            </el-form-item>
+            <el-form-item label="报警条目名称" prop="name">
+                <el-input
+                placeholder="名称不超过30个字"
+                v-model="formValue.name"
+                clearable>
+                </el-input>
+            </el-form-item>            
+            <el-form-item label="报警分类">
+                <v-alarm-class 
+                ref="alarm-class"
+                :isAddBtn='true' 
+                :options='alarmClassArr'  
+                :value='alarmClassValue'
+                @change="alarmClassChange"
+                @add='alarmClassAdd' 
+                ></v-alarm-class>
+            </el-form-item>
+            <el-form-item label="严重程度" prop="level">
+                <el-select v-model="formValue.level" clearable placeholder="请选择">
+                    <el-option
+                    v-for="item in levelSelectArr"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value">
+                    </el-option>
+                </el-select>
+            </el-form-item>
+            <el-form-item>
+                <div class="level_describe">
+                    <p>S 严重故障:会导致停机、设备损坏等问题的严重故障;计入设备、系统故障时间统计;</p>
+                    <p>A 故障 :会导致运行故障,但不会引起严重的系统问题,影响范围有限。例如单个污水坑报警;计入设备、系统故障时间统计;</p>
+                    <p>B 一般问题: 不会导致停机, 但对安全运行会造成风险的一般报警, 例如房间温度过高, 传感器不正常等; 不计入故障时间统计;</p>
+                    <p>C 预警: 提前预判故障或问题, 发出警告, 例如算范判断的管道脏堵、 换热器效率下降等; 不计入故障时间统计;</p>
+                    <p>D 数据问题: 断数、 云服务故障等我们的系统产生的问题; 不计入故障时间统计;</p>
+                </div>
+            </el-form-item>
+            <el-form-item label="备注">
+                <el-input
+                type="textarea"
+                :rows="3"
+                placeholder="不超过100字"
+                v-model="formValue.remark">
+                </el-input>
+            </el-form-item>
+            <el-form-item label="报警触发时所转问题">
+                <el-select 
+                v-model="formValue.hasProblem" 
+                clearable 
+                placeholder="请选择"  
+                :disabled="formValue.objTypeRules.length==0"
+                @change="hasProblemHandle">
+                    <el-option
+                    v-for="item in hasProblemArr"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value"                   
+                    >
+                    </el-option>
+                </el-select>
+                <span v-show="hasProblemInfo">问题为:&nbsp;&nbsp;&nbsp;{{hasProblemInfo}}</span>
+            </el-form-item>
+            <el-form-item label="报警所用算法" prop="aligothmType">
+                <el-select 
+                :disabled="formValue.objTypeRules.length==0"
+                style="width: 300px;"
+                v-model="formValue.aligothmType" 
+                clearable 
+                placeholder="请选择">
+                    <el-option
+                    v-for="item in aligothmTypeArr"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value"                   
+                    >
+                    </el-option>
+                </el-select>                
+            </el-form-item>
+            <el-form-item label="取值信息点" prop="funcid">
+                <span class="infoStar">*</span>
+                <span>{{selectInfoBtn}}</span>
+            </el-form-item>
+            <!-- 阈值算法 -->
+            <div v-if="formValue.aligothmType == 'threshold'" class="threshold-box">
+                <el-form-item label="报警诊断启动前提" prop="aligothmTypeInfo.precondition" :rules="rules.precondition">
+                    <el-radio-group class="precondition" v-model="formValue.aligothmTypeInfo.precondition">
+                        <p><el-radio label="running" :disabled="!isRunStatus">只有当设备处于运行状态才启动报警诊断</el-radio></p>
+                        <p><el-radio label="runningEnergy" :disabled="!isElecConsumP">只有当设备的运行能耗大于
+                            <el-input
+                            style="width: 200px; margin: 0 10px;"
+                            placeholder="请输入"
+                            v-model="formValue.aligothmTypeInfo.energyupper"
+                            :disabled="formValue.aligothmTypeInfo.precondition!='runningEnergy'">
+                            <template slot="append">kwh</template>
+                            </el-input>时才启动报警诊断</el-radio></p>
+                        <p><el-radio label="any">设备在任何状态下都启动报警诊断</el-radio></p>
+                    </el-radio-group>
+                </el-form-item>
+                <el-form-item label="报警诊断日期及时间" prop="aligothmTypeInfo.dateSet" :rules="rules.dateSet">
+                    <p>
+                        <span style="margin: 0 10px;">日期设定</span>
+                        <el-radio-group v-model="formValue.aligothmTypeInfo.dateSet">
+                            <el-radio label="all">全部日期</el-radio>
+                            <el-radio label="workday">仅工作日</el-radio>
+                            <el-radio label="weekday">仅周末</el-radio>
+                        </el-radio-group>
+                    </p>
+                    <p>
+                        <span style="margin: 0 10px;">时间设定</span>
+                        <el-radio-group v-model="formValue.aligothmTypeInfo.timeSet" @change="timeRadioHandle">
+                            <el-radio label="all">全部时间</el-radio>
+                            <el-radio label="customed">自定义时间段</el-radio>
+                        </el-radio-group>                        
+                        <el-time-picker
+                            v-if="formValue.aligothmTypeInfo.timeSet=='customed'"
+                            style="margin-left: 10px;"
+                            is-range
+                            v-model="customTimeRange"
+                            range-separator="至"
+                            start-placeholder="开始时间"
+                            end-placeholder="结束时间"
+                            placeholder="选择时间范围"
+                            format="HH:mm"
+                            size="small"
+                            value-format="HHmm"
+                            @change="timeRangeHandle">
+                        </el-time-picker>
+                    </p>
+                </el-form-item>
+                <el-form-item label="报警值持续时间要求" prop="aligothmTypeInfo.errorlastperiod" :rules="rules.errorlastperiod">
+                    <p>异常数据持续超过
+                        <el-input
+                        style="width: 200px; margin: 0 10px;"
+                        placeholder="请输入"
+                        v-model="formValue.aligothmTypeInfo.errorlastperiod">
+                            <template slot="append">秒</template>
+                        </el-input>时产生报警
+                    </p>
+                </el-form-item>
+                <el-form-item label="报警门限值设定方法" prop="aligothmTypeInfo.thresholdSetType" :rules="rules.thresholdSetType">
+                    <p>
+                        <el-select v-model="formValue.aligothmTypeInfo.thresholdSetTypeInfo.type" clearable placeholder="请选择">
+                            <el-option
+                            v-for="item in thresholdSetTypeInfoArr"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value"
+                            >
+                            </el-option>
+                        </el-select>
+                    </p>     
+                </el-form-item>               
+                   <el-radio-group class="precondition precondition-left" v-model="formValue.aligothmTypeInfo.thresholdSetType" @change="thresholdSetTypeChange">
+                    <p><el-radio label="customed">手动设定报警门限值
+                        <el-form-item prop="aligothmTypeInfo.thresholdSetType" :rules="rules.verifyUpperLower">       
+                            <p style="margin-left: 10px;">                                    
+                                <el-input
+                                v-if="formValue.aligothmTypeInfo.thresholdSetTypeInfo.type != 'upper'"
+                                style="width: 200px; margin: 0 10px;"
+                                placeholder="请输入"
+                                v-model="formValue.aligothmTypeInfo.thresholdSetTypeInfo.lower">
+                                    <template slot="append">{{unit || "单位"}}</template>
+                                </el-input>
+                                <span v-if="formValue.aligothmTypeInfo.thresholdSetTypeInfo.type == 'upperLower'">至</span>
+                                <el-input
+                                v-if="formValue.aligothmTypeInfo.thresholdSetTypeInfo.type != 'lower'"
+                                style="width: 200px; margin: 0 10px;"
+                                placeholder="请输入"
+                                v-model="formValue.aligothmTypeInfo.thresholdSetTypeInfo.upper">
+                                    <template slot="append">{{unit || "单位"}}</template>
+                                </el-input>
+                                <!-- 浮动范围
+                                <el-input
+                                style="width: 150px; margin: 0 10px;"
+                                placeholder="请输入"
+                                v-model="formValue.aligothmTypeInfo.thresholdSetTypeInfo.rangefrom">
+                                    <template slot="append">%</template>
+                                </el-input> -->
+                            </p>
+                            </el-form-item>
+                        </el-radio>
+                    </p>
+                    <p>                        
+                        <el-radio label="compareInfoCode">指定数据字典中信息点进行比对
+                            <el-form-item prop="aligothmTypeInfo.thresholdSetType" :rules="rules.verifyCompareInfo">  
+                                <el-button @click="selectRatedInfoHandle('lower')" 
+                                    v-if="formValue.aligothmTypeInfo.thresholdSetTypeInfo.type != 'upper'"
+                                    :disabled="formValue.aligothmTypeInfo.thresholdSetType != 'compareInfoCode'">{{selectRatedInfoLowerBtn}}</el-button>  
+                                <el-button @click="selectRatedInfoHandle('upper')" 
+                                v-if="formValue.aligothmTypeInfo.thresholdSetTypeInfo.type != 'lower'"
+                                :disabled="formValue.aligothmTypeInfo.thresholdSetType != 'compareInfoCode'">{{selectRatedInfoUpperBtn}}</el-button>    
+                            </el-form-item>                              
+                        </el-radio>
+                        
+                        </p>
+                    <p><el-radio label="compareHistory">使用历史值进行对比</el-radio></p>
+                </el-radio-group>  
+
+            </div>
+        </el-form>
+    </div>
+    <div class="btn-box"> 
+        <el-button class="edit-btn" type="primary" :loading="btnLoading" @click="saveHandle('ruleForm')">保存</el-button>
+        <el-button @click="cancelHandle()">取消</el-button>
+    </div>
+    <!-- 所转问题弹窗 -->
+    <v-has-problem 
+    :hasProblemVisibleFlag="hasProblemVisibleFlag" 
+    :objTypeValue="startCascadeValue"
+    :startCascadeValue="startCascadeValue"
+    :endCascadeValue="endCascadeValue"
+    @has-problem-handle="hasProblemEmitHandle"
+    @has-problem-close="hasProblemCloseHandle">
+    </v-has-problem>
+    <!-- 选择额定信息点 -->
+    <v-select-rated-info
+    :selectRatedInfoFlag="selectRatedInfoFlag"
+    :objTypeValue="startCascadeValue"
+    :infoPointArr="infoPointArr"
+    :selectRatedInfoCheckedCode="selectRatedInfoCheckedCode"
+    @select-info-handle="selectRatedInfoEmitHandle">
+    </v-select-rated-info>
+</div>    
+</template>
+<script>
+import fixedApi from '../fixedalarmitem/api';
+import alarmApi from '@/api/alarm'
+//components
+import vHasProblem from './hasproblem'; //所转问题弹窗
+// import vSelectInfo from './selectinfo'; //选择信息点
+import vSelectRatedInfo from './selectratedinfo'; //选择技术信息点
+import vObjType from '@/components/alarm/ObjType'
+import vAlarmClass from '@/components/alarm/AlarmClass'
+export default {
+    name: 'edit',
+    data () {
+        /******校验规则部分****** */
+        // 报警编码值code校验
+        let validatorCode = (rules, value, callback) => {
+            let num = Number(value);
+            if(isNaN(num)){
+                callback(new Error('请输入数字'));
+            } else {
+                let reg = /^\d{1,10}$/
+                if(reg.test(num)){
+                    callback()
+                }else{
+                    callback(new Error('请输入不超过10位的数字'));
+                }
+            }
+        };
+        // 报警诊断启动前提
+        let validatorPrecondition = (rules, value, callback) => {
+            if(value === 'runningEnergy') {
+                let reg = /^[1-9]\d*$/;
+                if(reg.test(this.formValue.aligothmTypeInfo.energyupper)) {
+                    callback()
+                } else {
+                    callback(new Error('请输入正整数'));
+                }
+            } else {
+                callback();
+            }            
+        };
+        // 报警持续要求时间
+        let validatorErrorLastPeriod = (rules, value, callback) => {       
+            if(value == 0) {
+                callback()
+            } else {
+                let reg = /^[1-9]\d{0,3}$/;
+                if(reg.test(value)) {
+                    callback()
+                } else {
+                    callback(new Error('请输入不超4位正整数'));
+                }               
+            }                 
+        };
+        let validatorupperLower = (rules, value, callback) => {
+            if(this.formValue.aligothmTypeInfo.thresholdSetTypeInfo.type == 'upperLower' && this.formValue.aligothmTypeInfo.thresholdSetType == "customed" ) { // 上下限
+                if(/^-?\d{1,8}(?:\.\d{1,3})?$/.test(this.formValue.aligothmTypeInfo.thresholdSetTypeInfo.lower)
+                && /^-?\d{1,8}(?:\.\d{1,3})?$/.test(this.formValue.aligothmTypeInfo.thresholdSetTypeInfo.upper)){
+                    let lower = Number(this.formValue.aligothmTypeInfo.thresholdSetTypeInfo.lower)
+                    let upper = Number(this.formValue.aligothmTypeInfo.thresholdSetTypeInfo.upper)
+                    if(lower > upper) {
+                        callback(new Error('下限大于上限'));
+                    } else {
+                        callback()
+                    }
+                } else {
+                    callback(new Error('整数最多8位,小数最多3位'));
+                }
+            } else if (this.formValue.aligothmTypeInfo.thresholdSetTypeInfo.type == 'upper' && this.formValue.aligothmTypeInfo.thresholdSetType == "customed"){ //上限
+                if(/^-?\d{1,8}(?:\.\d{1,3})?$/.test(this.formValue.aligothmTypeInfo.thresholdSetTypeInfo.upper)){
+                    callback()
+                } else {
+                    callback(new Error('整数最多8位,小数最多3位'));
+                }
+            } else if (this.formValue.aligothmTypeInfo.thresholdSetTypeInfo.type == 'lower' && this.formValue.aligothmTypeInfo.thresholdSetType == "customed"){ //下限
+                if(/^-?\d{1,8}(?:\.\d{1,3})?$/.test(this.formValue.aligothmTypeInfo.thresholdSetTypeInfo.lower)){
+                    callback()
+                } else {
+                    callback(new Error('整数最多8位,小数最多3位'));
+                }
+            } else {
+                callback();
+            }
+        };
+        let validatorcompareInfo = (rules, value, callback) => {
+            if( this.formValue.aligothmTypeInfo.thresholdSetTypeInfo.type == 'upperLower' && this.formValue.aligothmTypeInfo.thresholdSetType == "compareInfoCode") { // 上下限
+                if(this.formValue.aligothmTypeInfo.thresholdSetTypeInfo.lowerCompareInfocode && this.formValue.aligothmTypeInfo.thresholdSetTypeInfo.upperCompareInfocode){
+                    callback()
+                } else {
+                    callback(new Error('请选择信息点'));
+                }
+            } else if (this.formValue.aligothmTypeInfo.thresholdSetTypeInfo.type == 'upper' && this.formValue.aligothmTypeInfo.thresholdSetType == "compareInfoCode"){ //上限
+                if(this.formValue.aligothmTypeInfo.thresholdSetTypeInfo.upperCompareInfocode){
+                    callback()
+                } else {
+                    callback(new Error('请选择信息点'));
+                }
+            } else if (this.formValue.aligothmTypeInfo.thresholdSetTypeInfo.type == 'lower' && this.formValue.aligothmTypeInfo.thresholdSetType == "compareInfoCode"){ //下限
+                if(this.formValue.aligothmTypeInfo.thresholdSetTypeInfo.lowerCompareInfocode){
+                    callback()
+                } else {
+                    callback(new Error('请选择信息点'));
+                }
+            } else {
+                callback();
+            }
+        };
+        return {
+            /********************* */
+            objTypeComValue: [],
+            /********************* */
+            projectId: null, //项目id
+            hasProblemVisibleFlag: false, //所转问题的弹窗的flag
+            slectInfoFlag: false, //选择信息点的flag
+            selectRatedInfoFlag: false, //选择额定信息点的flag
+            btnLoading: false, //按钮loading
+            formValue: {
+                objType: null,   //对象类型,project,floor,space,system,facility,  **必须
+                objTypeRules:[],
+                category: null,   //系统或者设备的category  例如:选系统或者设备时加上前面加上专业编号 其他对象类型为空
+                code: null,             //报警条目编码    **必须
+                name: null,     //报警条目名称   **必须
+                alarmCategory: undefined, //报警分类
+                level: null,            //严重程度 S A B C D 五级
+                funcid:[{                   //信息点信息,污水坑算法时不用传
+                    funcidId: null,        //对应信息点id
+                    funcidName: null        //对应信息点名称
+                }],
+                hasProblem: null,           //'1转问题,0不转问题',int类型
+                problemId: null,      //问题id,hasProblem为1时此项不为空' ,
+                remark: null,          //备注
+                aligothmType: "none",     //算法类型,不需要算法,none 阈值threshold,污水坑sump
+                aligothmTypeInfo: {
+                    precondition: null,//前提,running(只有当设备处于运行状态时才启动报警诊断),runningEnergy(只有当设备运行能耗大于时启动),any(任何情况都启动)
+                    energyupper: 40,     // precondition为runningEnergy时不为空,int类型
+                    dateSet: "all",     //日期设定,all,workday,weekday
+                    timeSet: "all",     //时间设定,all,customed
+                    startTime: null,     //自定义时间设定开始时间hhss,timeSet为customed时不为空
+                    endTime: null,      //自定义时间设定结束时间hhss,timeSet为customed时不为空
+                    errorlastperiod: 0,      //异常持续时间,单位秒,
+                    thresholdSetType: "customed",      //门限设置方式,customed,compareInfoCode,compareHistory
+                    compareInfocode: null,      //比对信息点thresholdSetType为compareInfoCode时必须
+                    thresholdSetTypeInfo:{
+                        type: "upperLower",      //aligothmType为threshold时必须 upperLower,upper,lower
+                        lower: 0,      //下限
+                        upper: 0,       //上限
+                        rangefrom: 0,      //浮动范围,不是必须
+                        lowerCompareInfocode: null,
+                        upperCompareInfocode: null,
+                    }
+                }
+            }, 
+            rules: { //表单的规则
+                objTypeRules: [{ required:true, message: '请选择对象类', trigger: 'change'}],
+                code: [{ required:true, message: '请填写条目编码', trigger: 'blur'},
+                    {validator: validatorCode, trigger: 'blur'}],
+                name: [{ required:true, message: '请填写条目名称', trigger: 'blur'},
+                    { min: 1, max: 30, message: '不超过30个字', trigger: 'blur'}],
+                level: [{ required:true, message: '请选择严重程度', trigger: 'change'}],
+                aligothmType: [{ required:true, message: '请选择报警所用算法', trigger: 'change'}],
+                precondition: [{ required:true, message: '请选择报警诊断前提', trigger: 'change'},
+                    {validator: validatorPrecondition, trigger: 'blur'}],
+                dateSet: [{ required:true, message: '请选择日期和时间', trigger: 'blur'}],
+                errorlastperiod: [{ required:true, message: '请选择报警持续时间', trigger: 'blur'},
+                    {validator: validatorErrorLastPeriod, trigger: 'blur'}],
+                verifyUpperLower: [
+                    {validator: validatorupperLower, trigger: 'blur'}],
+                verifyCompareInfo: [
+                    {validator: validatorcompareInfo, trigger: 'blur'}
+                ]
+
+            },            
+            levelSelectArr: [ //严重级别的下拉数据
+                {
+                    label: "S",
+                    value: "S",
+                },{
+                    label: "A",
+                    value: "A",
+                },{
+                    label: "B",
+                    value: "B",
+                },{
+                    label: "C",
+                    value: "C",
+                },{
+                    label: "D",
+                    value: "D",
+                }
+            ],            
+            hasProblemArr: [ //报警触发时所转问题的下拉数据
+                {
+                    label: "不转问题",
+                    value: "0",
+                },{
+                    label: "选择问题",
+                    value: "1",
+                }
+            ],
+            aligothmTypeArr: [
+                {
+                    label: "直接从点位值判断,不需要算法",
+                    value: "none"
+                }, {
+                    label: "使用阈值算法",
+                    value: "threshold",
+                }
+            ],
+            thresholdSetTypeInfoArr: [ //阈值算法的报警们限值设定方式的上下限的数组
+                {
+                    label: '上下限',
+                    value: 'upperLower'
+                },{
+                    label: '上限',
+                    value: 'upper'
+                },{
+                    label: '下限',
+                    value: 'lower'
+                }        
+            ],
+            // objTypeOptions: [{ //选择适用对象类的级联框                
+            //     value: 'building',
+            //     label: '建筑',
+            // },{
+            //     value: 'floor',
+            //     label: '楼层',
+            // },{
+            //     value: 'space',
+            //     label: '空间',
+            // },{
+            //     value: 'system',
+            //     label: '系统类',
+            //     children: []
+            // },{
+            //     value: 'facility',
+            //     label: '设备类',
+            //     children: []
+            // }],
+            startCascadeValue: null, //级联第一级
+            endCascadeValue: null, //级联最后一级
+            infoPointArr:[], //信息点总数组
+            hasProblemInfo: null, //所转问题详情
+            selectInfoBtn: null,
+            customTimeRange: [new Date(), new Date()], //自定义时间段
+            selectRatedInfoUpperBtn: '请选择上限信息点', //选择固定的信息点
+            selectRatedInfoLowerBtn: '请选择下限信息点', 
+            selectRatedInfoCodeFlag: null, //选择信息点的flag
+            selectRatedInfoCheckedCode: null, //被选中的信息点
+            unit: null, //阈值算法的单位
+            isRunStatus: false, //是否有RunStatus的信息点
+            isElecConsumP: false, //是否有ElecConsumP的信息点
+            createStatus: false, //创建状态
+            //业务管理v1.1升级
+            alarmClassArr:[], //报警分类的下拉数据
+            alarmClassValue: '', //绑定的value
+        }
+    },
+    components: {
+        vHasProblem,
+        vSelectRatedInfo,
+        vObjType,
+        vAlarmClass
+    },
+    methods: {
+        //保存
+        saveHandle(formName) {
+            this.$refs[formName].validate((valid) => {
+                this.btnLoading = true;
+                if (valid) {                                         
+                    let params = {
+                        type: "customed",   //报警条目类别,fixed 固定,customed 自定义     **必须
+                        projectId: this.projectId,  //项目id,自定义类别时不为空
+                        code: this.formValue.code,    //报警条目编码    code和name可以只传一个
+                        name: this.formValue.name    //报警条目名称
+                    }
+                    fixedApi.isExisted(params).then(res => {
+                        if(res.result == 'success') {                            
+                            if(res.name || res.code){
+                                this.$message({
+                                    message: '报警编码或报警条目重复',
+                                    type: 'warning'
+                                });
+                                let name = this.formValue.name;
+                                let code = this.formValue.code;
+                                if(res.name) {
+                                    this.formValue.name = null;                                
+                                }
+                                if(res.code){
+                                    this.formValue.code = null;                              
+                                }
+                                this.$refs[formName].validate((valid) => {
+                                    this.formValue.name = name;
+                                    this.formValue.code = code;
+                                })
+                                this.btnLoading = false;
+                                return false;
+                            }
+                            //调保存接口           
+                            this.formValue.type = "customed";
+                            this.formValue.projectId = this.projectId;               
+                            let param = this.formValue;
+                            fixedApi.save(param).then(res => {
+                                if(res.result === "success"){
+                                    this.$message({
+                                        message: '保存成功',
+                                        type: 'success'
+                                    });
+                                    this.btnLoading = false;
+                                    this.$router.push("/projectinit/projectalarmitem?projectId=" +this.projectId)
+                                } else {
+                                    this.btnLoading = false;
+                                    this.$message({
+                                        message: '网络连接超时,请重新提交',
+                                        type: 'error'
+                                    });
+                                }
+                            })
+                        }
+                    });                  
+                } else {
+                    this.$message({
+                        message: '页面有必填项,请填写后提交!',
+                        type: 'warning'
+                    });
+                    this.btnLoading = false;
+                    console.log('error submit!!');
+                    return false;
+                }
+            });
+        },
+        // 取消
+        cancelHandle () {
+            this.$router.push("/projectinit/projectalarmitem?projectId=" +this.projectId)
+        },
+        // 获取对象类
+        // getObjTypeData() {
+        //     fixedApi.getObjectType().then(res => {
+        //         let {sysArr, devArr} = res;
+        //         this.objTypeOptions[3].children = sysArr;
+        //         this.objTypeOptions[4].children = devArr;
+        //     });
+        // },
+        // 获取信息的数组接口
+        getInfoPointArr(type) {  
+            if(this.startCascadeValue == "system") {
+                type = type.substring(2, 4);
+            } 
+            if(this.startCascadeValue == "facility") {
+                type = type.substring(2, 6);
+            }
+            let params = {
+                type: type,
+            }
+            fixedApi.getInfoListData(params).then((res) => {
+                let data = res;
+                this.infoPointArr = data;
+                let RunStatusArr = data.filter((ele, index) => {
+                    return ele.infoPointCode == "RunStatus"
+                });
+                let ElecConsumPArr = data.filter((ele, index) => {
+                    return ele.infoPointCode == "ElecConsumP"
+                });
+                this.isRunStatus = RunStatusArr[0] ? true : false;
+                this.isElecConsumP = ElecConsumPArr[0] ? true : false;
+            }).catch(err => {
+                throw err;
+            })
+        },    
+        // 时间日期radiochange事件
+        timeRadioHandle(val) {
+            if(val == "customed") {
+                let startTime = this.customTimeRange[0];
+                let endTime = this.customTimeRange[1];
+                this.formValue.aligothmTypeInfo.startTime = "" + startTime.getHours() + startTime.getMinutes();;
+                this.formValue.aligothmTypeInfo.endTime = "" + endTime.getHours() + endTime.getMinutes();
+            } else {
+                this.formValue.aligothmTypeInfo.startTime = null;
+                this.formValue.aligothmTypeInfo.endTime = null;
+            }
+        }, 
+        // 时间日期区间change事件
+        timeRangeHandle(timeArr) {
+            if(timeArr) {
+                this.formValue.aligothmTypeInfo.startTime = timeArr[0];
+                this.formValue.aligothmTypeInfo.endTime = timeArr[1];
+            } else {
+                this.formValue.aligothmTypeInfo.startTime = null;
+                this.formValue.aligothmTypeInfo.endTime = null;
+            }
+        },   
+        //报警门限值change事件
+        thresholdSetTypeChange(val) {
+            this.formValue.aligothmTypeInfo.compareInfocode = null;
+        },        
+        // 填写默认值
+        getDefaultValue(){
+            let creatParams = this.$route.query;
+            if(creatParams){              
+                
+                // 处理对象类
+                let objArr = [];
+                objArr[0] = creatParams.startCascadeValue;    
+                this.startCascadeValue = creatParams.startCascadeValue;
+                this.endCascadeValue = creatParams.startCascadeValue;        
+                if(creatParams.startCascadeValue == 'system') {
+                    this.endCascadeValue = creatParams.endCascadeValue;    
+                    objArr[1] = creatParams.endCascadeValue.substring(0, 2);
+                    objArr[2] = creatParams.endCascadeValue.substring(0, 4);
+                } 
+                if (creatParams.startCascadeValue == 'facility') {
+                    this.endCascadeValue = creatParams.endCascadeValue;    
+                    objArr[1] = creatParams.endCascadeValue.substring(0, 2);
+                    objArr[2] = creatParams.endCascadeValue.substring(0, 4);
+                    objArr[3] = creatParams.endCascadeValue.substring(0, 6);
+                }
+                if(creatParams.startCascadeValue == 'space') {
+                    this.endCascadeValue = creatParams.endCascadeValue;  
+                    objArr = ['space', creatParams.endCascadeValue];
+                }
+                this.createStatus = true;
+                this.formValue.objTypeRules = objArr;
+                this.objTypeComValue = objArr;
+                this.formValue.objType = creatParams.startCascadeValue;
+                this.formValue.category = creatParams.endCascadeValue;
+                this.formValue.name = creatParams.infoPointName;
+                // 信息点
+                this.selectInfoBtn = creatParams.infoPointName;
+                this.formValue.funcid[0].funcidId = creatParams.infoPointCode;
+                this.formValue.funcid[0].funcidName = creatParams.infoPointName
+                // 单位
+                this.unit = creatParams.unit || "单位"
+                // 获取信息点
+                let infoParam = creatParams.startCascadeValue == 'space' ? 'space' : this.endCascadeValue;
+                this.getInfoPointArr(infoParam);
+            } else {
+                window.history.go(-1);
+            }
+        },
+        /***************************组件回调时间************************************** */
+        //触发问题下拉事件
+        hasProblemHandle(value) {
+            if(value == 1){
+                this.hasProblemVisibleFlag = !this.hasProblemVisibleFlag;
+            } else {
+                this.hasProblemInfo = null;
+            }
+        },
+        //触发所转问题的回调事件
+        hasProblemEmitHandle(name, id) {
+            this.hasProblemInfo = name + '---' + id;
+            this.formValue.problemId = id;
+        },
+        //触发所转问题的关闭事件
+        hasProblemCloseHandle(radioValue) {
+            if(!radioValue){
+                this.formValue.hasProblem = null;
+            }
+        },
+        //选择技术信息点的点击事件
+        selectRatedInfoHandle(flag) {  
+            this.selectRatedInfoCodeFlag = flag; //标记是上限 or 下限
+            if (flag == "lower") {
+                this.selectRatedInfoCheckedCode = this.formValue.aligothmTypeInfo.thresholdSetTypeInfo.lowerCompareInfocode;
+            } else {
+                this.selectRatedInfoCheckedCode = this.formValue.aligothmTypeInfo.thresholdSetTypeInfo.upperCompareInfocode;
+            }           
+            this.selectRatedInfoFlag = !this.selectRatedInfoFlag;
+        },
+        //选择技术信息点的回填事件
+        selectRatedInfoEmitHandle(name, code) {
+           if (this.selectRatedInfoCodeFlag == "lower") {
+                this.selectRatedInfoLowerBtn = name + '---' + code;
+                this.formValue.aligothmTypeInfo.thresholdSetTypeInfo.lowerCompareInfocode = code;
+            } else {
+                this.selectRatedInfoUpperBtn = name + '---' + code;
+                this.formValue.aligothmTypeInfo.thresholdSetTypeInfo.upperCompareInfocode = code;
+            }
+        },
+        init() {
+            this.projectId = this.$route.query.projectId;
+            // 填写默认值
+            this.getDefaultValue();
+            //获取报警分类的列表
+            this.getAlarmClassList()
+        },
+        /**v1.1********************************* */
+        //获取报警分类
+        async getAlarmClassList() {
+            let params = {                
+                criteria: {
+                    projectId: {$in:[this.projectId,"0"]}
+                }                
+            }
+            let res = await alarmApi.alarmClassList(params)
+            this.alarmClassArr = res
+        },
+        //报警分类的change
+        alarmClassChange(val) {         
+            this.formValue.alarmCategory = val || undefined
+        },
+        //报警分类添加
+        async alarmClassAdd(val) {
+            let params = {
+                projectId: this.projectId,
+                category: val
+            }
+            let res = await alarmApi.createAlarmClass(params)
+            if(res.result == 'success') {
+                this.$message({
+                    message: '添加成功',
+                    type: 'success'
+                });
+                this.$refs['alarm-class'].visible = false
+                await this.getAlarmClassList()
+                this.alarmClassValue = val       
+                this.formValue.alarmCategory = val       
+            }
+        }
+    },
+    mounted() {
+        this.init()        
+    }
+    
+} 
+</script>
+<style lang='less' scoped>
+.edit-box{
+    .title {text-align: center;}
+    .form-box {
+        margin-top:20px;
+        margin-left:20%;
+        width: 50%;
+        .infoStar{
+            color: #f56c6c;
+            position: absolute;
+            left: -93px;
+        }
+        .threshold-box{
+            .precondition-left{
+                padding-left:150px;                
+            }
+            .precondition{
+                p{
+                    margin:10px 0;
+                }
+            }
+        };
+        .level_describe {
+            color: #b2b2b2;
+            p {
+            line-height: 24px;
+            }
+        }
+    }
+    .btn-box{
+        margin-top: 10px;
+        text-align: center;
+        .edit-btn{
+            margin-right: 50px;
+        }
+    }
+}
+</style>
+<style>
+.edit-box .form-box .threshold-box .precondition-left .el-form-item__content{margin-left: 0px!important} 
+</style>

+ 573 - 0
src/views/alarm/projalarm/edit/Base.vue

@@ -0,0 +1,573 @@
+<template>
+    <div class='edit-base'>
+        <el-form label-width='150px' :model='formValue' ref='ruleForm' :rules='rules'>
+            <el-form-item label='适用对象实例'>
+                <span class='infoStar'>*</span>
+                <span v-if='editStatus'>{{formValue.instanceInfo}}</span>
+                <v-obj-type v-else ref='objType' :objType='objTypeComValue' :disabled='true' width='400px'></v-obj-type>
+            </el-form-item>
+            <el-form-item
+                label='报警条目编码'
+                prop='code'
+                :rules='[{ required:true, message: "请填写条目编码", trigger: "blur"},
+                {validator: validatorCode, trigger: ["blur","submmit"]}
+                    ]'
+            >
+                <el-input placeholder='请输入不超过10位的数字' v-model='formValue.code' :readonly='editStatus' clearable></el-input>
+            </el-form-item>
+            <el-form-item
+                label='报警条目名称'
+                prop='name'
+                :rules='[
+                    { required: true, message: "请填写条目编码", trigger: "blur" },
+                    { min: 1, max: 30, message: "不超过30个字", trigger: "blur" },
+                    {validator: validatorName, trigger: ["blur","submmit"]}
+                ]'
+            >
+                <el-input placeholder='名称不超过30个字' v-model='formValue.name' clearable :readonly='editStatus'></el-input>
+            </el-form-item>
+            <el-form-item label='要求响应时限' prop='respondTime'>
+                <p class='level_describe resp-desc'>响应时间范围是“业务触发->传感器感知->产生报警->发出工单”整体流程的时限</p>
+                <el-radio-group v-model='formValue.respondTime' :disabled='respTimeOnly'>
+                    <p class='resp-time' v-for='(item,index) in respTimeArr' :key='index'>
+                        <el-radio :label='item.value'>{{item.name}}</el-radio>
+                    </p>
+                </el-radio-group>
+            </el-form-item>
+            <el-form-item label='报警分类'>
+                <v-alarm-class
+                    ref='alarm-class'
+                    :isAddBtn='true'
+                    :options='alarmClassArr'
+                    :value='alarmClassValue'
+                    @change='alarmClassChange'
+                    @add='alarmClassAdd'
+                ></v-alarm-class>
+            </el-form-item>
+            <el-form-item label='严重程度' prop='level'>
+                <el-select v-model='formValue.level' clearable placeholder='请选择'>
+                    <el-option v-for='item in levelSelectArr' :key='item.value' :label='item.label' :value='item.value'></el-option>
+                </el-select>
+            </el-form-item>
+            <el-form-item>
+                <div class='level_describe'>
+                    <p>S 严重故障:会导致停机、设备损坏等问题的严重故障;计入设备、系统故障时间统计;</p>
+                    <p>A 故障 :会导致运行故障,但不会引起严重的系统问题,影响范围有限。例如单个污水坑报警;计入设备、系统故障时间统计;</p>
+                    <p>B 一般问题: 不会导致停机, 但对安全运行会造成风险的一般报警, 例如房间温度过高, 传感器不正常等; 不计入故障时间统计;</p>
+                    <p>C 预警: 提前预判故障或问题, 发出警告, 例如算范判断的管道脏堵、 换热器效率下降等; 不计入故障时间统计;</p>
+                    <p>D 数据问题: 断数、 云服务故障等我们的系统产生的问题; 不计入故障时间统计;</p>
+                </div>
+            </el-form-item>
+            <el-form-item label='备注'>
+                <el-input type='textarea' :rows='3' placeholder='不超过100字' v-model='formValue.remark'></el-input>
+            </el-form-item>
+            <el-form-item label='报警触发时所转问题'>
+                <el-select v-model='formValue.hasProblem' clearable placeholder='请选择' @change='hasProblemHandle'>
+                    <el-option v-for='item in hasProblemArr' :key='item.value' :label='item.label' :value='item.value'></el-option>
+                </el-select>
+                <span v-show='hasProblemInfo'>问题为:&nbsp;&nbsp;&nbsp;{{hasProblemInfo}}</span>
+            </el-form-item>
+            <el-form-item label='报警所用算法' prop='aligothmType'>
+                <span v-if='editStatus'>{{alarmAlgorithm}}</span>
+                <el-select
+                    v-else
+                    style='width: 300px;'
+                    v-model='formValue.aligothmType'
+                    clearable
+                    placeholder='请选择'
+                    @change='changeAligothmTypeHandle'
+                >
+                    <el-option
+                        v-for='item in aligothmTypeArr'
+                        :disabled='item.disabled'
+                        :key='item.value'
+                        :label='item.label'
+                        :value='item.value'
+                    ></el-option>
+                </el-select>
+            </el-form-item>
+            <el-form-item label='取值信息点' prop='funcid'>
+                <span class='infoStar'>*</span>
+                <span>{{selectInfoBtn}}</span>
+            </el-form-item>
+        </el-form>
+        <!-- 组件 -->
+        <v-has-problem
+            :hasProblemVisibleFlag='hasProblemVisibleFlag'
+            :objTypeValue='startCascadeValue'
+            :startCascadeValue='startCascadeValue'
+            :endCascadeValue='endCascadeValue'
+            @has-problem-handle='hasProblemEmitHandle'
+            @has-problem-close='hasProblemCloseHandle'
+        ></v-has-problem>
+    </div>
+</template>
+
+<script>
+//com
+import vObjType from '@/components/alarm/ObjType' //对象类型
+import vAlarmClass from '@/components/alarm/AlarmClass' //报警分类
+import vHasProblem from '../../fixedalarmitem/hasproblem' //所转问题弹窗
+
+//api
+import api from '../../fixedalarmitem/api'
+import alarmApi from '@/api/alarm'
+
+export default {
+    name: 'alarm-base',
+    data() {
+        return {
+            //弹窗标志
+            hasProblemVisibleFlag: false, //所转问题的弹窗
+            slectInfoFlag: false, //选择信息点的flag
+            formValue: {
+                code: null, //报警条目编码    **必须
+                name: null, //报警条目名称   **必须
+                respondTime: 600,
+                alarmCategory: undefined, //报警分类
+                level: null, //严重程度 S A B C D 五级
+                remark: null, //备注
+                problemId: null, //问题id,hasProblem为1时此项不为空' ,
+                hasProblem: null, //'1转问题,0不转问题',int类型
+                aligothmType: 'none', //算法类型,不需要算法,none 阈值threshold,污水坑sump
+                funcid: [{ funcidId: null, funcidName: null }] //信息点
+            },
+            //表单的规则
+            rules: {
+                respondTime: [{ required: true, message: '请选择要求响应时间', trigger: 'change' }],
+                level: [{ required: true, message: '请选择严重程度', trigger: 'change' }],
+                aligothmType: [{ required: true, message: '请选择报警所用算法', trigger: 'change' }]
+            },
+            //要求响应时限
+            respTimeArr: [
+                {
+                    name: '5~30秒内',
+                    value: 5
+                },
+                {
+                    name: '1~3分钟内',
+                    value: 60
+                },
+                {
+                    name: '10~30分钟内',
+                    value: 600
+                }
+            ],
+            levelSelectArr: [
+                //严重级别的下拉数据
+                {
+                    label: 'S',
+                    value: 'S'
+                },
+                {
+                    label: 'A',
+                    value: 'A'
+                },
+                {
+                    label: 'B',
+                    value: 'B'
+                },
+                {
+                    label: 'C',
+                    value: 'C'
+                },
+                {
+                    label: 'D',
+                    value: 'D'
+                }
+            ],
+            hasProblemArr: [
+                //报警触发时所转问题的下拉数据
+                {
+                    label: '不转问题',
+                    value: 0
+                },
+                {
+                    label: '选择问题',
+                    value: 1
+                }
+            ],
+            aligothmTypeArr: [
+                {
+                    label: '直接从点位值判断,不需要算法',
+                    value: 'none',
+                    disabled: false
+                },
+                {
+                    label: '使用阈值算法',
+                    value: 'threshold',
+                    disabled: false
+                }
+            ],
+            aligothmTypeArr1: [
+                {
+                    label: '直接从点位值判断,不需要算法',
+                    value: 'none'
+                },
+                {
+                    label: '使用阈值算法',
+                    value: 'threshold'
+                },
+                {
+                    label: '使用污水坑算法',
+                    value: 'sump'
+                }
+            ],
+            // objTypeArr: [], //适用对象类数组
+            startCascadeValue: null, //级联第一级
+            endCascadeValue: null, //级联最后一级
+            hasProblemInfo: null,
+            selectInfoBtn: '请选择一个信息点',
+            infoPointArr: [], //信息点总数组
+
+            objTypeComValue: [], //对象类型组件
+            alarmClassArr: [], //报警分类的下拉数据
+            alarmClassValue: '', //绑定的value
+            alarmAlgorithm: '' ,//报警算法
+            /*******添加响应时间******************* */
+            respTimeOnly: false,
+        }
+    },
+    props: ['baseValue', 'editStatus', 'params', 'projectId'],
+    components: {
+        vObjType,
+        vAlarmClass,
+        vHasProblem
+    },
+    methods: {
+        async validateForm(cb) {
+            this.$refs['ruleForm'].validate(valid => {
+                if (valid) {
+                    cb(this.formValue)
+                } else {
+                    cb(false)
+                }
+            })
+        },
+        //校验
+        async validatorCode(rules, value, callback) {
+            let num = Number(value)
+            if (isNaN(num)) {
+                callback(new Error('请输入数字'))
+            } else {
+                let reg = /^\d{1,10}$/
+                if (reg.test(num)) {
+                    if (this.editStatus) {
+                        callback()
+                    } else {
+                        let res = await this.isCodeAndNameExisted()
+                        if (res.code) {
+                            callback(new Error('报警条目编码重复'))
+                        } else {
+                            callback()
+                        }
+                    }
+                } else {
+                    callback(new Error('请输入不超过10位的数字'))
+                }
+            }
+        },
+        async validatorName(rules, value, callback) {
+            if (this.editStatus) {
+                callback()
+            } else {
+                let res = await this.isCodeAndNameExisted()
+                if (res.name) {
+                    callback(new Error('报警条目名称重复'))
+                } else {
+                    callback()
+                }
+            }
+        },
+        //判断报警条目编码和报警条目名称是否重复
+        async isCodeAndNameExisted() {
+            let params = {
+                type: 'customed', //报警条目类别,fixed 固定,customed 自定义     **必须
+                projectId: this.projectId, //项目id,自定义类别时不为空
+                code: this.formValue.code, //报警条目编码    code和name可以只传一个
+                name: this.formValue.name //报警条目名称
+            }
+            let res = await api.isExisted(params)
+            return res
+        },
+        //触发问题下拉事件
+        hasProblemHandle(value) {
+            if (value == 1) {
+                this.hasProblemVisibleFlag = !this.hasProblemVisibleFlag
+            } else {
+                this.hasProblemInfo = null
+            }
+        },
+        //触发所转问题的回调事件
+        hasProblemEmitHandle(name, id) {
+            this.hasProblemInfo = name + '---' + id
+            this.formValue.problemId = id
+        },
+        //触发所转问题的关闭事件
+        hasProblemCloseHandle(radioValue) {
+            if (!radioValue) {
+                this.formValue.hasProblem = null
+            }
+        },
+        //获取信息点
+        getInfoPointArr(type) {
+            if (this.startCascadeValue == 'system') {
+                type = type.substring(2, 4)
+            }
+            if (this.startCascadeValue == 'facility') {
+                type = type.substring(2, 6)
+            }
+            let params = {
+                type: type
+            }
+            api.getInfoListData(params)
+                .then(res => {
+                    this.infoPointArr = res
+                    let RunStatusArr = res.filter((ele, index) => {
+                        return ele.infoPointCode == 'RunStatus'
+                    })
+                    let ElecConsumPArr = res.filter((ele, index) => {
+                        return ele.infoPointCode == 'ElecConsumP'
+                    })
+                    let isRunStatus = RunStatusArr[0] ? true : false
+                    let isElecConsumP = ElecConsumPArr[0] ? true : false
+                    let obj = {
+                        isRunStatus,
+                        isElecConsumP,
+                        startCascadeValue: this.startCascadeValue,
+                        infoPointArr: this.infoPointArr
+                    }
+                    this.$emit('obj-type-change', obj)
+                })
+                .catch(err => {
+                    throw err
+                })
+        },
+        //选择信息点的回填事件
+        selectInfoEmitHandle(name, code, unit) {
+            this.unit = unit
+            this.formValue.funcid[0].funcidId = code
+            this.formValue.funcid[0].funcidName = name
+            this.selectInfoBtn = name + '---' + code
+        },
+        // 选择信息点关闭事件
+        selectInfoCloseHandle(val) {
+            if (!val) {
+                this.selectInfoBtn = '请选择一个信息点'
+            }
+        },
+        changeAligothmTypeHandle(val) {
+            this.$emit('alarm-algor', val)
+        },
+
+        //报警分类的change
+        alarmClassChange(val) {
+            this.formValue.alarmCategory = val || undefined
+        },
+        //报警分类添加
+        async alarmClassAdd(val) {
+            let params = {
+                projectId: this.projectId,
+                category: val
+            }
+            let res = await alarmApi.createAlarmClass(params)
+            if (res.result == 'success') {
+                this.$message({
+                    message: '添加成功',
+                    type: 'success'
+                })
+                this.$refs['alarm-class'].visible = false
+                await this.getAlarmClassList()
+                this.alarmClassValue = val
+                this.formValue.alarmCategory = val
+            }
+        },
+        //获取报警分类
+        async getAlarmClassList() {
+            let params = {
+                criteria: {
+                    projectId: { $in: [this.projectId, '0'] }
+                }
+            }
+            let res = await alarmApi.alarmClassList(params)
+            this.alarmClassArr = res
+        },
+        // 获取问题数据list
+        getProblemList(problemId) {
+            let objType = null
+            if (
+                this.startCascadeValue == 'building' ||
+                this.startCascadeValue == 'floor' ||
+                this.startCascadeValue == 'space'
+            ) {
+                objType = this.startCascadeValue
+            } else {
+                objType = this.endCascadeValue
+            }
+            let params = {
+                criteria: {
+                    objType: objType
+                }
+            }
+            api.getProblemList(params).then(res => {
+                if (res.result == 'success' && res.content) {
+                    if (problemId) {
+                        let arr = res.content.filter((item, index) => {
+                            return item.id == problemId
+                        })
+                        this.hasProblemInfo = arr[0].name + '---' + arr[0].id
+                    }
+                }
+            })
+        },
+        //创建处理
+        createHandle(creatParams) {
+            // console.log(creatParams)
+            // 处理对象类
+            let objArr = []
+            objArr[0] = creatParams.startCascadeValue
+            this.startCascadeValue = creatParams.startCascadeValue
+            this.endCascadeValue = creatParams.startCascadeValue
+            if (creatParams.startCascadeValue == 'system') {
+                this.endCascadeValue = creatParams.endCascadeValue
+                objArr[1] = creatParams.endCascadeValue.substring(0, 2)
+                objArr[2] = creatParams.endCascadeValue.substring(0, 4)
+            }
+            if (creatParams.startCascadeValue == 'facility') {
+                this.endCascadeValue = creatParams.endCascadeValue
+                objArr[1] = creatParams.endCascadeValue.substring(0, 2)
+                objArr[2] = creatParams.endCascadeValue.substring(0, 4)
+                objArr[3] = creatParams.endCascadeValue.substring(0, 6)
+            }
+            if (creatParams.startCascadeValue == 'space') {
+                this.endCascadeValue = creatParams.endCascadeValue
+                objArr = ['space', creatParams.endCascadeValue]
+            }
+            this.objTypeComValue = objArr
+            this.formValue.objType = creatParams.startCascadeValue
+            this.formValue.category = creatParams.endCascadeValue
+            this.formValue.name = creatParams.infoPointName
+            // 信息点
+            this.selectInfoBtn = creatParams.infoPointName
+            this.formValue.funcid[0].funcidId = creatParams.infoPointCode
+            this.formValue.funcid[0].funcidName = creatParams.infoPointName
+            // 单位
+            // this.unit = creatParams.unit || "单位"
+            // 获取信息点
+            let infoParam = creatParams.startCascadeValue == 'space' ? 'space' : this.endCascadeValue
+            this.getInfoPointArr(infoParam)
+        },
+        //编辑处理
+        editHandle(res) {
+            // 处理对象类
+            let objArr = []
+            objArr[0] = res.objType
+            this.startCascadeValue = res.objType
+            this.endCascadeValue = res.objType
+            if (res.objType == 'space') {
+                if (res.category) {
+                    this.endCascadeValue = res.category
+                    objArr[1] = res.category
+                } else {
+                    this.endCascadeValue = 'space'
+                }
+            }
+            if (res.objType == 'system') {
+                this.endCascadeValue = res.category
+                objArr[1] = res.category.substring(0, 2)
+                objArr[2] = res.category.substring(0, 4)
+            }
+            if (res.objType == 'facility') {
+                this.endCascadeValue = res.category
+                objArr[1] = res.category.substring(0, 2)
+                objArr[2] = res.category.substring(0, 4)
+                objArr[3] = res.category.substring(0, 6)
+            }
+            this.objTypeComValue = objArr
+            //处理要求响应时限
+            if(res.configType == 'fixed') {
+                this.respTimeOnly = false
+            } else {
+                this.respTimeOnly = true
+            }
+            //处理报警分类
+            if (res.alarmCategory) {
+                this.alarmClassValue = res.alarmCategory
+            }
+            // 赋值适用对象类名称
+            res.instanceInfo = this.params.instanceInfo
+            // 处理报警所用算法
+            let algorithmArr = this.aligothmTypeArr1.filter((item, index) => {
+                return item.value == res.aligothmType
+            })
+            this.alarmAlgorithm = algorithmArr[0].label
+            // 处理信息点
+            let infoPointStr = ''
+            res.funcid && res.funcid.length
+                ? res.funcid.forEach((infoPoint, ind, arr) => {
+                      infoPointStr +=
+                          infoPoint.funcidId + ',' + infoPoint.funcidName + (ind == arr.length - 1 ? '' : ';')
+                  })
+                : ''
+            this.selectInfoBtn = infoPointStr
+
+            // 处理转问题toString
+            if (res.hasProblem == '1') {
+                this.getProblemList(res.problemId)
+            }
+            //赋值操作
+            this.formValue = res
+        }
+    },
+    watch: {
+        params: {
+            deep: true,
+            // immediate: true,
+            handler(val) {
+                if (!this.editStatus) {
+                    this.createHandle(val)
+                }
+            }
+        },
+        baseValue: {
+            deep: true,
+            immediate: true,
+            handler(val) {
+                if (this.editStatus) {
+                    this.editHandle(val)
+                }
+            }
+        },
+        projectId: {
+            immediate: true,
+            handler(val) {
+                this.getAlarmClassList()
+            }
+        }
+    }
+}
+</script>
+
+<style lang='less' scoped>
+.edit-base {
+    margin-top: 20px;
+    .infoStar {
+        color: #f56c6c;
+        position: absolute;
+        left: -105px;
+    }
+    .level_describe {
+        color: #b2b2b2;
+        p {
+            line-height: 24px;
+        }
+    }
+    .resp-desc {
+        margin-top: 7px;
+        line-height: 24px;
+    }
+    .resp-time {
+        margin: 10px 0;
+    }
+}
+</style>

+ 350 - 0
src/views/alarm/projalarm/edit/index.vue

@@ -0,0 +1,350 @@
+<template>
+    <div class='edit-box'>
+        <h5 class='title'>{{editStatus? '编辑' : '添加'}}报警条目</h5>
+        <!-- 基本 -->
+        <v-base 
+        ref='alarm-base' 
+        :params='params'
+        :projectId="projectId"
+        :baseValue='baseValue'
+        :editStatus='editStatus'
+        @obj-type-change='objTypeChange' 
+        @alarm-algor='alarmAlgor'></v-base>
+        <!-- 阈值 -->
+        <v-threshold
+            v-if='alarmAlgorType == "threshold"'
+            ref='alarm-threshold'
+            :editStatus='editStatus'
+            :isRunStatus='baseToThreshold.isRunStatus'
+            :isElecConsumP='baseToThreshold.isElecConsumP'
+            :startCascadeValue='baseToThreshold.startCascadeValue'
+            :infoPointArr='baseToThreshold.infoPointArr'
+            :thresholdValue='thresholdValue'
+        ></v-threshold>
+        <!-- 污水坑 -->
+        <v-sump 
+        v-if='alarmAlgorType == "sump"' 
+        ref='alarm-sump'
+        :sumpValue='sumpValue'
+        :editStatus='editStatus'></v-sump>
+        <div class='btn-box'>
+            <el-button class='edit-btn' v-loading="btnLoading" type='primary' @click='saveHandle()'>保存</el-button>
+            <el-button @click='cancelHandle()'>取消</el-button>
+        </div>
+        <!-- 批量适用于 -->
+    <v-batch-apply
+    :batchApplyFlag="batchApplyFlag"
+    :batchApplyArr="batchApplyArr"
+    :id="formValue.id" 
+    :projectId="projectId"   
+    @batch-apply-handle="batchApplyHandle"
+    ></v-batch-apply>
+    </div>
+</template>
+
+<script>
+//api
+import fixedApi from '../../fixedalarmitem/api';
+import proApi from '../api'
+//components
+import vBase from './Base'
+import vThreshold from '../../fixedalarmitem/edit/Threshold'
+import vSump from '../../fixedalarmitem/edit/Sump'
+import vBatchApply from '../batchapply'; //批量适用于
+export default {
+    name: 'alarm-index',
+    data() {
+        return {
+            batchApplyFlag: false,
+            formValue: {},
+            projectId: null, 
+            params: null, //传递的参数
+            editStatus: false, //是否为编辑状态
+            isEditfirst: false, //是不是编辑状态第一步 
+            btnLoading: false, //按钮loading状态
+            alarmAlgorType: 'none', //报警算法类型[none | threshold | sump],
+            baseToThreshold: {
+                isRunStatus: false,
+                isElecConsumP: false,
+                startCascadeValue: null,
+                infoPointArr: []
+            },
+            baseValue: {}, //基本框架
+            thresholdValue: {}, //阈值算法
+            sumpValue: {}, //污水坑
+
+            batchApplyArr: [], //
+        }
+    },
+    components: {
+        vBase,
+        vThreshold,
+        vSump,
+        vBatchApply
+    },
+    methods: {
+        saveHandle() {
+            let formValue = {}
+            this.$refs['alarm-base'].validateForm(baseData => {
+                //1、判断基本组件
+                if (baseData) {
+                    //判断信息点
+                    formValue = { ...baseData }
+                    /******************判断是哪一个算法******************************* */
+                    if (this.alarmAlgorType == 'threshold') {
+                        if (baseData.funcid[0].funcidId) {
+                            //2、阈值算范模块alarm-threshold
+                            this.$refs['alarm-threshold'].validateForm(thresholdData => {
+                                if (thresholdData) {
+                                    formValue.aligothmTypeInfo = thresholdData
+                                    this.save(formValue)
+                                } else {
+                                    this.notice()
+                                }
+                            })
+                        } else {
+                            this.$message({
+                                message: '请选择信息点',
+                                type: 'warning'
+                            })
+                        }
+                    } else if (this.alarmAlgorType == 'sump') {
+                        //3、污水坑算法
+                        this.$refs['alarm-sump'].validateForm(sumpData => {
+                            if (sumpData) {
+                                formValue.aligothmTypeInfo = sumpData
+                                this.save(formValue)
+                            } else {
+                                this.notice()
+                            }
+                        })
+                    } else {
+                        if (baseData.funcid[0].funcidId) {
+                            this.save(baseData)
+                        } else {
+                            this.$message({
+                                message: '请选择信息点',
+                                type: 'warning'
+                            })
+                        }
+                    }
+                } else {
+                    this.notice()
+                }
+            })
+        },
+        //save
+        async save(formValue) {
+            this.btnLoading = true;
+            formValue.type = "customed";
+            formValue.projectId = this.projectId;               
+            let param = formValue;
+            if ( this.editStatus ) { //编辑
+                // console.log(formValue)
+                this.formValue = formValue
+                this.editBatchSave(formValue)
+            } else { //新建                
+                let res = await fixedApi.save(param);
+                if(res.result === "success"){
+                    this.$message({
+                        message: '保存成功',
+                        type: 'success'
+                    });
+                    this.btnLoading = false;
+                    this.$router.push("/projectinit/projectalarmitem?projectId=" +this.projectId)
+                } else {
+                    this.$message({
+                        message: '网络连接超时,请重新提交',
+                        type: 'error'
+                    });
+                }
+            }
+            
+        },
+        //批量保存
+        async editBatchSave(formValue) {
+            let category = null;
+            if(formValue.objType == "building" || formValue.objType == "floor" || formValue.objType == "space") {
+                category = null;
+            } else {
+                category = formValue.category;
+            }
+             // 查询批量数据
+            let params = {
+                criteria: {
+                    objType: this.formValue.objType,
+                    category: category,
+                    // configType: this.type,
+                    issupport: 1,
+                    code: {$in:[this.formValue.code]},
+                    projectId: this.projectId
+                },                         
+                page: null,
+                size: null
+            }
+            let res = await proApi.getListData(params, this.projectId)
+            if(res.result == "success") {
+                if (res.content.length > 1) {
+                    this.batchApplyFlag = !this.batchApplyFlag //开启批量弹窗
+                    this.batchApplyArr = res.content
+                } else {
+                    this.batchApplyHandle([]);
+                }
+                    
+            } 
+        
+        },
+        // 批量适用于
+        async batchApplyHandle(arr) {  
+            this.formValue.funcid = null; //后端要求
+            let { result } = await  proApi.updateBatch(this.formValue);
+            if(result === "success") {
+                this.btnLoading = false;
+                if(arr.length) {
+                    let isSuccess = true;
+                    let copyObj = JSON.parse(JSON.stringify(this.formValue));
+                    for(let i = 0; i < arr.length; i++) {
+                        copyObj.id = arr[i].id;
+                        copyObj.instanceId = arr[i].instanceId;
+                        copyObj.instanceName = arr[i].instanceName;
+                        copyObj.instanceInfo = arr[i].instanceInfo;
+                        copyObj.isedit = arr[i].isedit;
+                        copyObj.isopen = arr[i].isopen;
+                        copyObj.issupport = arr[i].issupport;
+                        copyObj.reason = arr[i].reason;
+                        let res = await  proApi.updateBatch(copyObj);
+                        if(res.result != "success") {
+                            isSuccess = false;        
+                            break;                    
+                        }                        
+                    }
+                    if(isSuccess) {
+                            this.$message({
+                                message: '批量更新成功',
+                                type: 'success'
+                            });
+                            this.$router.push("/projectinit/projectalarmitem?projectId=" +this.projectId)
+                        } else {
+                            this.$message({
+                                message: '批量更新失败',
+                                type: 'error'
+                            });                            
+                        }
+                } else {
+                    this.$message({
+                        message: '保存成功',
+                        type: 'success'
+                    });
+                    this.$router.push("/projectinit/projectalarmitem?projectId=" +this.projectId)
+                }
+            } else {
+                this.$message({
+                    message: '保存失败',
+                    type: 'error'
+                });
+            }
+        },
+        //取消
+        cancelHandle() {
+            window.history.go(-1)
+        },
+        //对象类型改变
+        objTypeChange(obj) {
+            this.baseToThreshold.isRunStatus = obj.isRunStatus
+            this.baseToThreshold.isElecConsumP = obj.isElecConsumP
+            this.baseToThreshold.startCascadeValue = obj.startCascadeValue
+            this.baseToThreshold.infoPointArr = obj.infoPointArr
+            // 重置报警诊断前提
+            if (this.$refs['alarm-threshold']) {
+                if(this.editStatus) {
+                    if (this.isEditfirst) {
+                        this.$refs['alarm-threshold'].formValue.precondition = null
+                        this.isEditfirst = true;
+                    }                    
+                } else {
+                    this.$refs['alarm-threshold'].formValue.precondition = null
+                }   
+                
+            }
+        },
+        //选择算法
+        alarmAlgor(val) {
+            this.alarmAlgorType = val
+            if (val == 'sump') {
+                // this.$refs['alarm-threshold'].formValue.precondition =  'any';
+            } else {
+                this.$nextTick(() => {
+                    if (this.$refs['alarm-threshold'])  {
+                        // this.$refs['alarm-threshold'].formValue.precondition = null
+                    }                    
+                })
+            }
+        },
+        notice() {
+            this.$message({
+                message: '页面有必填项,请填写后提交!',
+                type: 'warning'
+            })
+        },
+        //编辑请求数据
+        async editItem(query) {
+            let params = {
+                criteria: {
+                    id: query.id
+                }   
+            }
+            let res =await proApi.getListData(params)
+            if(res.result === 'success' && res.content) {
+                // 处理数据格式
+                this.editItemHandle(res.content[0]);                    
+            }            
+        },
+        //处理数据格式
+        editItemHandle(res) {
+            // console.log('res')
+            // console.log(res)
+            this.baseValue = res;
+            // 报警所用算法
+            this.alarmAlgorType = res.aligothmType;
+            if (this.alarmAlgorType == 'threshold') {
+                this.thresholdValue = res;
+            } else if (this.alarmAlgorType == 'sump') {
+                this.sumpValue = res
+            }
+        },
+        init() {
+            let params = this.$route.query;
+            this.projectId = params.projectId;
+            this.params  = params
+            // console.log(params)
+            if (params.objTypeArr) {
+                this.editStatus = false
+            } else {
+                this.editStatus = true
+                this.editItem(params)
+            }
+        }
+    },
+    mounted() {
+        this.init()
+    }
+
+}
+</script>
+
+<style lang='less' scoped>
+.edit-box {
+    margin-left: 20%;
+    width: 50%;
+    .title {
+        text-align: center;
+    }
+    .btn-box {
+        margin-top: 10px;
+        text-align: center;
+        .edit-btn {
+            margin-right: 50px;
+        }
+    }
+}
+</style>

+ 272 - 0
src/views/alarm/projalarm/hasproblem.vue

@@ -0,0 +1,272 @@
+/**
+@author:fugy
+@date:2018.09.20
+@info:固定报警条目的所转问题弹窗
+ */
+ <template>
+<el-dialog
+title="选择报警触发时所转问题"
+:visible.sync="dialogVisible"
+width="50%"
+center
+@close="hasProblemCloseHandle"
+>
+    <div class="problem-box">
+        <div class="top">   
+            <!-- <el-radio-group v-model="radioValue">
+                
+                <el-radio-button v-for="(item, index) in radioArr" :key="index" :label="item.value" :disabled="objTypeValue != item.value">{{item.label}}</el-radio-button>
+            </el-radio-group> -->
+            <el-input placeholder="请使用问题名称进行搜索" v-model.trim="searchValue">
+                <el-button slot="append" icon="el-icon-search"  @click="search"></el-button>
+            </el-input>
+        </div>
+        <!-- <hr class="line" /> -->
+        <div class="content">
+            <!-- <div class="contion" v-if="radioValue == 'system' || radioValue == 'facility'">
+                <el-select v-model="majorSelectValue" clearable placeholder="请选择专业" @change="changeMajorHandle">
+                    <el-option
+                    v-for="item in majorSelectArr"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value">
+                    </el-option>
+                </el-select>
+                <el-select v-if="majorSelectValue" v-model="sysSelectValue" clearable placeholder="请选择系统" @change="changeSysHandle">
+                    <el-option
+                    v-for="item in sysSelectArr"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value">
+                    </el-option>
+                </el-select>
+                <el-select v-if="sysSelectValue && this.radioValue=='facility'" v-model="devSelectValue" clearable placeholder="请选择设备" @change="changeDevHandle">
+                    <el-option
+                    v-for="item in devSelectArr"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value">
+                    </el-option>
+                </el-select>
+            </div> -->
+            <div class="table-box">
+                <el-table
+                    :loading = "loading"
+                    :data="tableData"
+                    border
+                    style="width: 100%">
+                    <el-table-column
+                    prop="name"
+                    label="问题名称"
+                    header-align="center">
+                    </el-table-column>
+                    <el-table-column
+                    prop="id"
+                    label="问题编号"
+                    header-align="center">
+                    </el-table-column>                   
+                    <el-table-column
+                    label="选择"
+                    header-align="center"
+                    align="center"
+                    >
+                    <template slot-scope="scope">
+                        <el-radio v-model="radioTableValue" :label="scope.row.id" @change="radioHandle(scope.row)">{{null}}</el-radio>
+                    </template>
+                    </el-table-column>
+                </el-table>
+            </div>
+        </div>
+    </div>
+</el-dialog>
+ </template>
+ 
+ <script>
+import api from '../fixedalarmitem/api';
+import utils from '@/components/alarm/utils';
+import { mapGetters } from 'vuex';
+export default {
+    name: "has-problem",
+    data() {
+        return {            
+            dialogVisible: false,
+            loading: false,
+            searchValue: "", //搜索问题的value
+            radioArr:[{ //单选按钮的数据Arr             
+                value: 'building',
+                label: '建筑',
+            },{
+                value: 'floor',
+                label: '楼层',
+            },{
+                value: 'space',
+                label: '空间',
+            },{
+                value: 'system',
+                label: '系统类',
+            },{
+                value: 'facility',
+                label: '设备类',
+            }], 
+            radioValue:'space', //单选按钮的value值
+            majorSelectValue: null, //专业下拉value
+            majorSelectArr: [], //专业下拉的数组
+            sysSelectValue: null, //系统下拉value
+            sysSelectArr: [], //系统下拉的数组
+            devSelectValue: null, //设备下拉value
+            devSelectArr: [], //设备下拉的属猪
+            tableData:[],
+            radioTableValue: null, // 表格单选按钮的value值
+            paramObjType: null, //参数
+            paramCategory: null,
+        }
+    },
+    props:["hasProblemVisibleFlag", "objTypeValue", "startCascadeValue", "endCascadeValue"],
+    computed: {
+        ...mapGetters("alarm", ['spaceCodeObj'])
+    },
+    methods: {
+        //表格单选按钮
+        radioHandle(row){
+            this.$emit("has-problem-handle", row.name, row.id);
+            this.dialogVisible = false;
+        },
+        //弹窗关闭
+        hasProblemCloseHandle() {
+            this.majorSelectValue = null;
+            this.sysSelectValue = null;
+            this.devSelectValue = null;
+            this.loading = false;
+            this.$emit("has-problem-close", this.radioTableValue)
+        },
+        //获取专业的接口
+        getmajorSelectData() {
+            this.majorSelectArr = api.getMajorSelectData();
+        },
+        // 改变专业下拉,获取系统的下拉列表
+        changeMajorHandle(val) {
+            if(!val){
+                return;
+            }
+            this.sysSelectValue = null;
+            let arr = api.getSysSelectData(val);
+            if(arr){
+                this.sysSelectArr = arr;
+            } else {
+                this.sysSelectArr = [];
+            }
+        },
+        // 改变系统下拉,获取设备的下拉列表
+        changeSysHandle(val) {
+            // console.log(val);
+            if(!val){
+                return;
+            }
+            if (this.radioValue == "system") { //系统
+
+            } else { //设备
+                this.devSelectValue = null;
+                let arr = api.getDevSelectData(val);
+                if(arr){
+                    this.devSelectArr = arr;
+                }else {
+                    this.devSelectArr = [];
+                }  
+            }
+                       
+        },
+        // 改变设备的下拉
+        changeDevHandle (val) {
+            console.log(val)
+        },
+        // 获取问题数据list
+        getProblemList(){
+            this.loading = true;
+            let params= {
+                criteria:{
+                    objType: this.paramObjType,
+                    category: this.paramCategory ?{"$in":this.paramCategory} : undefined,
+                    name: this.searchValue ? {$like: `%${this.searchValue}%`} : undefined
+                }
+            }
+            api.getProblemList(params).then(res => {
+                if(res.result == "success" && res.content) {
+                    this.loading = false;
+                    this.tableData = res.content;
+                }
+            });
+        },
+        search() {
+            this.getProblemList();
+        },
+        handleParams() {
+            this.paramObjType = this.startCascadeValue;
+            if(this.startCascadeValue == 'building' || this.startCascadeValue == 'floor') {
+                this.paramCategory = null;
+            }else if(this.startCascadeValue == "space") {
+                if(this.endCascadeValue) {
+                    if(this.endCascadeValue == 'space') {
+                        this.paramCategory = null;
+                    } else {
+                        this.paramCategory = utils.spaceSonCode(this.endCascadeValue, this.spaceCodeObj);
+                    }
+                } else {
+                    this.paramCategory = null;
+                }
+                
+            } else if(this.startCascadeValue == "system" || this.startCascadeValue == 'facility') {
+                this.paramCategory = [this.endCascadeValue];
+            }
+            this.getProblemList();
+        }
+    },
+    created() {
+        if(!this.spaceCodeObj){
+            this.$store.commit("alarm/ADD_INDEX")
+        }
+    },
+    watch: {
+        //弹窗显示
+        hasProblemVisibleFlag() {
+            this.dialogVisible = true;
+            this.radioTableValue = null;
+            this.handleParams();
+            // 获取问题接口
+            // this.getProblemList();
+            // if (this.objTypeValue == "system" || this.objTypeValue == "facility") {
+            //     this.getmajorSelectData();
+            // }
+        },
+        //获取专业的下拉列表
+        objTypeValue() {
+            this.radioValue = this.objTypeValue;            
+        },
+        //对象类型最后位数
+        // endCascadeValue: {
+        //     immediate: true,
+        //     handler() {
+        //         this.param = this.endCascadeValue;
+        //     }            
+        // }
+    }
+}
+ </script>
+ <style lang="less" scoped>
+ .problem-box{
+     .top{
+         text-align: center;
+     }
+     .line{
+        background-color: #ccc;
+        height: 1px;
+        border: none;
+     }
+     .content{
+         .table-box{
+             margin-top: 10px;
+         }
+     }
+ }
+ </style>
+ 
+ 

+ 503 - 0
src/views/alarm/projalarm/index.vue

@@ -0,0 +1,503 @@
+/**
+@author:fugy
+@date:2018.09.19
+@info:查看项目报警条目的详情
+ */
+<template>
+    <div class='project-alarm-box'>
+        <div class='top'>
+            <sg-selector type='project' @changed='projectedSelected' :default='projectSelectValue'></sg-selector>
+            <el-input style='width: 500px;' placeholder='支持报警条目名称、条目编码进行搜索' v-model.trim='searchValue' clearable>
+                <el-button slot='append' icon='el-icon-search' @click='search'></el-button>
+            </el-input>
+            <el-button style='float: right' type='primary' @click='addAlarmHandle()'>+为项目添加报警条目</el-button>
+        </div>
+        <hr class='line'>
+        <div class='content'>
+            <p class='tooltip'>
+                当前此项目涉及报警的对象实例共
+                <span class='num'>&nbsp;&nbsp;{{alarmExampleNumObj.total}}&nbsp;</span>
+                个,共适用
+                <span class='num'>&nbsp;&nbsp;{{alarmExampleNumObj.fixed}}&nbsp;</span>
+                类通用报警条目,另有
+                <span class='num'>&nbsp;&nbsp;{{alarmExampleNumObj.customed}}&nbsp;</span>
+                类自定义报警条目;
+                <el-button class='noSupportBtn' type='text' @click='noSpportHandle()'>查看项目内对象实例不支持的报警条目 ></el-button>
+            </p>
+            <div class='condition'>
+                <p class='block'>
+                    <span>报警条目 :</span>
+                    <v-alarm-item @change='alarmChange' :objTypeArr='objTypeArr'></v-alarm-item>
+                </p>
+                <p class='block obj-type'>
+                    <span>对象类型 :</span>
+                    <v-obj-type @change='objTypeChange' ref='objType' :objType='objTypeComValue' :hasVerify='false'></v-obj-type>
+                </p>
+                <p class='block'>
+                    <span>报警分类 :</span>
+                    <v-alarm-class
+                        width='150px'
+                        style='display:inline-block'
+                        @change='alarmClassChange'
+                        :options='alarmClassArr'
+                    ></v-alarm-class>
+                </p>
+            </div>
+            <div class='table-box'>
+                <el-table v-loading='loading' :data='tableData' border style='width: 100%'>
+                    <el-table-column prop='alarmCategory' label='报警分类' header-align='center' width='100'></el-table-column>
+                    <el-table-column prop='instanceInfo' label='适用对象实例' header-align='center'></el-table-column>
+                    <el-table-column prop='name' label='报警条目名称' header-align='center'></el-table-column>
+                    <el-table-column label='报警条目编码' header-align='center'>
+                        <template slot-scope='scope'>
+                            <p style='display: flex; justify-content: space-between'>
+                                <span>{{scope.row.code}}</span>
+                                <el-tag style='margin-left: 10px;' v-if='scope.row.type=="customed"'>自定义</el-tag>
+                            </p>
+                        </template>
+                    </el-table-column>
+                    <el-table-column prop='level' label='严重程度' header-align='center' width='100'></el-table-column>
+                    <el-table-column label='是否开启' header-align='center' width='100'>
+                        <template slot-scope='scope'>
+                            <el-switch
+                                v-model='scope.row.isOpenDetail'
+                                active-color='#13ce66'
+                                inactive-color='#C2C2C2'
+                                @change='switchChangeHandle(scope.row)'
+                            ></el-switch>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label='操作' header-align='center' width='150'>
+                        <template slot-scope='scope'>
+                            <el-button type='text' size='small' @click='getLook(scope.row)'>查看</el-button>
+                            <el-button type='text' size='small' @click='edit(scope.row)'>编辑</el-button>
+                        </template>
+                    </el-table-column>
+                </el-table>
+            </div>
+        </div>
+        <el-row class='page-box' v-if='count'>
+            <el-pagination
+                @size-change='handleSizeChange'
+                @current-change='handleCurrentChange'
+                :current-page='currentPage'
+                :page-sizes='[10, 20, 30, 50]'
+                :page-size='currentSize'
+                layout='total, sizes, prev, pager, next, jumper'
+                :total='count'
+            ></el-pagination>
+        </el-row>
+        <!-- 为项目添加自定义报警条目 -->
+        <v-add-model :addVisibleFlag='addVisibleFlag' :projectId='projectSelectValue'></v-add-model>
+        <!-- 查看单条报警状态 -->
+        <v-look-item :rowInfoData='rowInfoData' :lookVisibleFlag='lookVisibleFlag'></v-look-item>
+    </div>
+</template>
+<script>
+import { mapGetters } from 'vuex'
+// component
+import vAddModel from './addmodel' //添加报警条目的弹框
+import vLookItem from './lookitem' //查看的报警条目弹窗
+import vObjType from '@/components/alarm/common/ObjType' //对象类型
+import vAlarmItem from '@/components/alarm/common/AlarmItem' //报警条目
+import vAlarmClass from '@/components/alarm/common/AlarmClass'
+// utils
+import alarmApi from '@/api/alarm/alarm'
+import fixedUtils from '@/components/alarm/common/utils'
+import utils from './utils' //utils
+import api from './api'
+export default {
+    name: 'projectalarmitem',
+    data() {
+        return {
+            /****************** */
+            objTypeComValue: [],
+            objTypeArr: [],
+            /****************** */
+            loading: true,
+            addVisibleFlag: false, //为项目添加报警条目状态的flag
+            noSpportVisibleFlag: false, //项目不支持的报警条目
+            lookVisibleFlag: false, //查看单条项目报警状态的flag
+            // selectAlarmItemFlag: false, //筛选报警条目的状态flag
+            projectSelectArr: [], //项目的数据下拉列表
+            projectSelectValue: '', //项目绑定值
+            searchValue: '', //搜索框中的value值
+            likeSearchValue: null, //模糊查询
+            alarmExampleNumObj: {
+                //报警实例的对应的数量
+                customed: 0,
+                fixed: 0,
+                total: 0,
+                unSupport: 0
+            },
+            tableData: [],
+            currentPage: 1, //分页当前页
+            currentSize: 10, //分页当前的size
+            count: 0, //总条数
+            startCascadeValue: null, //级联第一项
+            endCascadeValue: null, //级联最后一级
+            // selectAlarmItemArr: null, //筛选报警条目的回显数组
+            selectAlarmItemRadio: null, //筛选的报警条目的通用or自定义
+            selectAlarmCodeArr: null, //筛选报警条目的回显数组code值为了请求列表
+            // selectBtnInfo: '全部', //报警条目的按钮内部内容
+            generalProblemArr: null, //通用问题的缓存数据
+            rowInfoData: null, //每一行的信息数据(下传查看)
+            // infoPointArr:null, //信息点的系统和设备的
+            entityDictObj: [], //适用对象类实体的数据字典
+            /**业务v1.1**************************************** */
+            alarmClassArr: [], //报警分类的下拉数组
+            alarmClassValue: undefined //报警分类的value
+        }
+    },
+    computed: {
+        ...mapGetters('alarm', ['spaceCodeObj'])
+    },
+    components: {
+        vLookItem,
+        vAddModel,
+        vAlarmItem,
+        vObjType,
+        vAlarmClass
+    },
+    methods: {
+        // 项目change事件
+        changeProjectHandle() {
+            this.getProjectExampleNum()
+            this.clearAlarmItem()
+        },
+        projectedSelected(projectId) {
+            this.projectSelectValue = projectId
+            if (projectId) {
+                this.changeProjectHandle()
+                //获取报警分类下拉列表数据
+                this.getAlarmClassList()
+            }
+        },
+        // keyword查询事件
+        search() {
+            if (this.searchValue) {
+                this.likeSearchValue = {
+                    $like: `%${this.searchValue}%`
+                }
+            } else {
+                this.likeSearchValue = null
+            }
+            this.currentPage = 1
+            this.getListData()
+        },
+        //分页
+        handleSizeChange(size) {
+            this.currentPage = 1
+            this.currentSize = size
+            this.getListData()
+        },
+        handleCurrentChange(page) {
+            this.currentPage = page
+            this.getListData()
+        },
+        // 清空报警条目
+        clearAlarmItem() {
+            this.currentPage = 1
+            // this.selectAlarmItemArr = null;
+            // this.selectAlarmCodeArr = null;
+            // this.selectAlarmItemRadio = null;
+            this.selectBtnInfo = '全部'
+            this.getListData()
+        },
+        // 获取list数据
+        getListData() {
+            this.loading = true
+            // 判断category
+            let category = null
+            if (this.startCascadeValue == 'building' || this.startCascadeValue == 'floor') {
+                category = null
+            } else if (this.startCascadeValue == 'space') {
+                if (this.endCascadeValue) {
+                    let p = fixedUtils.spaceSonCode(this.endCascadeValue, this.spaceCodeObj)
+                    category = p
+                } else {
+                    category = null
+                }
+            } else if (this.startCascadeValue == 'system' || this.startCascadeValue == 'facility') {
+                category = [this.endCascadeValue]
+            }
+            let params = {
+                criteria: {
+                    keyword: this.likeSearchValue,
+                    objType: this.startCascadeValue || null,
+                    category: category ? { $in: category } : null,
+                    configType: this.selectAlarmItemRadio,
+                    issupport: 1,
+                    code: this.selectAlarmCodeArr ? { $in: this.selectAlarmCodeArr } : null,
+                    projectId: this.projectSelectValue,
+                    alarmCategory: this.alarmClassValue || undefined
+                },
+                page: this.currentPage,
+                size: this.currentSize
+            }
+            api.getListData(params).then(res => {
+                if (res.result === 'success' && res.content) {
+                    let applyArr = []
+                    res.content.forEach((item, index) => {
+                        // 中转适用对象类实例
+                        applyArr.push({ id: item.instanceId })
+                        // 中转是否开启
+                        if (item.isopen === 0) {
+                            item.isOpenDetail = false
+                        } else {
+                            item.isOpenDetail = true
+                        }
+
+                        // 中转通用问题
+                        if (item.hasProblem) {
+                            let arrTem = this.generalProblemArr
+                                ? this.generalProblemArr.filter((ele, index) => {
+                                      return ele.id == item.problemId
+                                  })
+                                : []
+                            item.generalProblemDetail = arrTem.length ? arrTem[0].name : '---'
+                        } else {
+                            item.generalProblemDetail = '---'
+                        }
+                        // 中转信息点
+                        let infoStr = ''
+                        item.funcid.forEach((ele, index, arr) => {
+                            infoStr += ele.funcidId + ',' + ele.funcidName + (index == arr.length - 1 ? '' : ';')
+                        })
+                        item.infoPointDetail = infoStr
+                    })
+                    // 去获取适用对象类的本地信息
+                    let params = { criterias: applyArr, valid: null }
+                    api.getApplyObjInfo(this.projectSelectValue, params).then(resp => {
+                        if (resp.length) {
+                            this.entityDictObj = utils.entityDict(resp)
+                            res.content.forEach((ele, idx) => {
+                                let preName = utils.objPreName(ele.objType)
+                                let name =
+                                    this.entityDictObj[ele.instanceId].infos[preName + 'LocalName'] ||
+                                    this.entityDictObj[ele.instanceId].infos[preName + 'Name']
+                                let id =
+                                    this.entityDictObj[ele.instanceId].infos[preName + 'LocalID'] ||
+                                    this.entityDictObj[ele.instanceId].infos[preName + 'ID']
+                                if (preName == 'facility') {
+                                    ele.instanceInfo =
+                                        name + ' - ' + id + (ele.instanceLocation ? ' - ' + ele.instanceLocation : '')
+                                } else {
+                                    ele.instanceInfo = name + ' - ' + id
+                                }
+                            })
+                            // 最后赋值
+                            this.loading = false
+                            this.count = res.count
+                            this.tableData = res.content
+                        }
+                    })
+                } else {
+                    this.loading = false
+                    this.count = 0
+                    this.tableData = []
+                }
+            })
+        },
+        // 开关事件
+        switchChangeHandle(row) {
+            let status = row.isopen == 0 ? 1 : 0
+            let params = {
+                id: row.id,
+                isopen: status
+            }
+            api.switchStatus(params).then(res => {
+                let arr = this.tableData.filter((item, index) => {
+                    return item.code == row.code
+                })
+                if (res.result == 'success') {
+                    arr[0].isopen = status
+                    this.$message({
+                        message: '修改成功',
+                        type: 'success'
+                    })
+                } else {
+                    arr[0].isopen = status == 0 ? 1 : 0
+                }
+            })
+        },
+        // 对象类型的change
+        objTypeChange(val) {
+            this.objTypeArr = val
+            if (val.length) {
+                this.startCascadeValue = val[0]
+                this.endCascadeValue = val[val.length - 1]
+                if (val.length == 1 && this.startCascadeValue == 'space') {
+                    this.endCascadeValue = null
+                }
+            } else {
+                this.startCascadeValue = null
+                this.endCascadeValue = null
+            }
+            this.clearAlarmItem()
+        },
+        // 对象类型的change
+        objTypeHandle(val) {
+            if (val.length) {
+                this.startCascadeValue = val[0]
+                this.endCascadeValue = val[val.length - 1]
+            } else {
+                this.startCascadeValue = null
+                this.endCascadeValue = null
+            }
+            this.clearAlarmItem()
+        },
+        //为项目添加报警条目
+        addAlarmHandle() {
+            this.addVisibleFlag = !this.addVisibleFlag
+        },
+        //项目不支持的报警条目
+        noSpportHandle() {
+            this.$router.push('/project/projectalarmnospport?proId=' + this.projectSelectValue)
+        },
+        //查看单条报警状态
+        getLook(row) {
+            this.rowInfoData = row
+            this.lookVisibleFlag = !this.lookVisibleFlag
+        },
+        // 编辑
+        edit(row) {
+            this.$router.push({
+                path: '/project/projectalarmedit',
+                query: {
+                    id: row.id,
+                    projectId: this.projectSelectValue,
+                    type: row.type,
+                    instanceInfo: row.instanceInfo
+                }
+            })
+        },
+        // 获取项目列表
+        getProjectList() {
+            let projectId = this.$route.query.projectId
+            this.projectSelectArr = api.getProjectList()
+            if (projectId) {
+                this.projectSelectValue = projectId
+            } else {
+                this.projectSelectValue = this.projectSelectArr[0].projId //默认第一项
+            }
+            // 获取对象实例的数量
+            this.getProjectExampleNum()
+            this.getGeneralProblem()
+        },
+        // 获取通用问题接口
+        getGeneralProblem() {
+            let params = {}
+            api.getProblemList(params).then(res => {
+                if (res.result === 'success') {
+                    this.generalProblemArr = res.content
+                    // 获取list数据
+                    this.getListData()
+                }
+            })
+        },
+        // 获取对象实例数目
+        getProjectExampleNum() {
+            let params = {
+                projectId: this.projectSelectValue
+            }
+            api.getProjectExampleNum(params).then(res => {
+                this.alarmExampleNumObj = res
+            })
+        },
+        /********************组件回传事件******************************* */
+        // 筛选报警对象
+        alarmChange(radio, arr) {
+            if (arr.length) {
+                this.selectAlarmCodeArr = arr
+            } else {
+                this.selectAlarmCodeArr = null
+            }
+            this.currentPage = 1
+            this.selectAlarmItemRadio = radio
+            this.getListData()
+        },
+        init() {            
+            this.getGeneralProblem()
+        },
+        /**********v1.1******************************************************************************** */
+        //获取报警分类
+        async getAlarmClassList() {
+            let params = {
+                criteria: {
+                    projectId: { $in: [this.projectSelectValue, '0'] }
+                }
+            }
+            let res = await alarmApi.alarmClassList(params)
+            this.alarmClassArr = res
+        },
+        alarmClassChange(val) {
+            this.currentPage = 1
+            this.alarmClassValue = val
+            this.getListData()
+        }
+    },
+    created() {
+        if (!this.spaceCodeObj) {
+            this.$store.commit('alarm/ADD_INDEX')
+        }
+        if (this.$route.query.projectId) {
+            this.projectSelectValue = this.$route.query.projectId
+            //获取报警分类下拉列表数据
+            this.getAlarmClassList()
+            // 获取对象实例的数量
+            this.getProjectExampleNum()
+        }
+        // console.log(this.$route.query.projectId)
+    },
+    mounted() {
+        this.init()
+    }
+}
+</script>
+<style lang='less' scoped>
+.project-alarm-box {
+    .top {
+        overflow: hidden;
+    }
+    .line {
+        background-color: #ccc;
+        height: 1px;
+        border: none;
+    }
+    .content {
+        .tooltip {
+            font-weight: 100;
+            font-size: 18px;
+            .num {
+                color: #66cc00;
+            }
+            .noSupportBtn {
+                font-size: 16px;
+            }
+        }
+        .condition {
+            font-size: 16px;
+            overflow: hidden;
+            .block {
+                float: right;
+                margin-left: 30px;
+                .clear-icon {
+                    cursor: pointer;
+                }
+            }
+            .obj-type {
+                display: flex;
+                line-height: 40px;
+            }
+        }
+        .table-box {
+            margin-top: 10px;
+        }
+    }
+    .page-box {
+        margin-top: 10px;
+        text-align: center;
+    }
+}
+</style>

+ 267 - 0
src/views/alarm/projalarm/lookitem.vue

@@ -0,0 +1,267 @@
+/**
+@author:fugy
+@date:2018.09.18
+@info:查看固定报警条目的详情
+ */
+<template>
+    <el-dialog title='报警条目详情' :visible.sync='dialogVisible' width='50%' center>
+        <div class='item-info-box' v-if='itemData'>
+            <div class='item-info'>
+                <p>
+                    <span>适用对象实例 :</span>
+                    <span>{{itemData.instanceInfo}}</span>
+                </p>
+                <p>
+                    <span>报警条目编码 :</span>
+                    <span>{{itemData.code}}</span>
+                </p>
+                <p>
+                    <span>报警条目名称 :</span>
+                    <span>{{itemData.name}}</span>
+                </p>
+                <p>
+                    <span>要求响应时限 :</span>
+                    <span>{{itemData.respTime}}</span>
+                </p>
+                <p>
+                    <span>报警分类 :</span>
+                    <span>{{itemData.alarmCategory || '暂无分类'}}</span>
+                </p>
+                <p>
+                    <span>严重程度 :</span>
+                    <span>{{itemData.level}}</span>
+                </p>
+                <p class='level-dec'>{{levelDec}}</p>
+                <p>
+                    <span>备注 :</span>
+                    <span>{{itemData.remark || '---'}}</span>
+                </p>
+                <p>
+                    <span>报警触发时所转问题 :</span>
+                    <span>{{itemData.generalProblemDetail}}</span>
+                </p>
+                <div>
+                    <p>
+                        <span>报警所用算法 :</span>
+                        <span>{{itemData.aligothmTypeDetail}}</span>
+                    </p>
+                    <p>
+                        <span>对应信息点 :</span>
+                        <span>{{itemData.infoPointDetail}}</span>
+                    </p>
+                </div>
+                <div v-if='itemData.aligothmType == "threshold"'>
+                    <p>
+                        <span>报警诊断启动前提 :</span>
+                        <span>{{itemData.preconditionDetail}}</span>
+                    </p>
+                    <p>
+                        <span>报警诊断日期及时间 :</span>
+                        <span>{{itemData.dateSetDetail}}&nbsp;&nbsp;&nbsp;{{itemData.timeSetDetail}}</span>
+                    </p>
+                    <p>
+                        <span>警值持续时间要求 :</span>
+                        <span>异常数据持续超过{{itemData.aligothmTypeInfo.errorlastperiod}}秒时产生报警</span>
+                    </p>
+                    <p>
+                        <span>报警门限值设定方式 :</span>
+                        <span>
+                            {{itemData.thresholdMethod}}
+                            <br>
+                            {{itemData.thresholdCustomed}}
+                        </span>
+                    </p>
+                </div>
+                <div v-if='itemData.aligothmType == "sump"'>
+                    <p>
+                        <span>报警诊断启动前提 :</span>
+                        <span>{{itemData.preconditionDetail}}</span>
+                    </p>
+                    <p>
+                        <span>报警诊断日期及时间 :</span>
+                        <span>{{itemData.dateSetDetail}}&nbsp;&nbsp;&nbsp;{{itemData.timeSetDetail}}</span>
+                    </p>
+                    <p>
+                        <span>警值持续时间要求 :</span>
+                        <span>异常数据持续超过{{itemData.aligothmTypeInfo.errorlastperiod}}秒时产生报警</span>
+                    </p>
+                </div>
+            </div>
+            <div class='btn-box'>
+                <el-button class='edit-btn' type='primary' @click='editHandle'>编辑</el-button>
+            </div>
+        </div>
+    </el-dialog>
+</template>
+<script>
+import api from './api'
+export default {
+    name: 'look-item',
+    data() {
+        return {
+            dialogVisible: false,
+            itemData: null,
+            aligothmTypeArr: [
+                {
+                    label: '直接从点位值判断,不需要算法',
+                    value: 'none'
+                },
+                {
+                    label: '使用阈值算法',
+                    value: 'threshold'
+                },
+                {
+                    label: '使用污水坑算法',
+                    value: 'sump'
+                }
+            ],
+            //要求响应时限
+            respTimeObj: {
+                '5': '5~30秒内',
+                '60': '1~3分钟内',
+                '600': '10~30分钟内'
+            },
+            levelDec: '---',
+            levelDecObj: {
+                S: '严重故障:会导致停机、设备损坏等问题的严重故障;计入设备、系统故障时间统计',
+                A:
+                    '故障 :会导致运行故障,但不会引起严重的系统问题,影响范围有限。例如单个污水坑报警;计入设备、系统故障时间统计',
+                B:
+                    '一般问题:不会导致停机,但对安全运行会造成风险的一般报警,例如房间温度过高,传感器不正常等;不计入故障时间统计',
+                C: '预警:提前预判故障或问题,发出警告,例如算范判断的管道脏堵、换热器效率下降等;不计入故障时间统计',
+                D: '数据问题:断数、云服务故障等我们的系统产生的问题;不计入故障时间统计'
+            }
+        }
+    },
+    props: ['lookVisibleFlag', 'rowInfoData'],
+    methods: {
+        //  编辑跳页
+        editHandle() {
+            this.dialogVisible = false
+            this.$router.push({
+                path: '/project/projectalarmedit',
+                query: {
+                    id: this.itemData.id,
+                    projectId: this.itemData.projectId,
+                    type: this.itemData.type,
+                    instanceInfo: this.itemData.instanceInfo
+                }
+            })
+        },
+        // 处理数据
+        itemDataHandle(val) {
+            let params = val
+            this.levelDec = this.levelDecObj[val.level]
+            // 算法
+            let aligothm = this.aligothmTypeArr.filter(ele => {
+                return ele.value == params.aligothmType
+            })
+            params.aligothmTypeDetail = aligothm[0].label
+            if (aligothm[0].value != 'none') {
+                // 报警诊断启动前提
+                if (params.aligothmTypeInfo.precondition == 'running') {
+                    params.preconditionDetail = '只有当设备处于运行状态才启动报警诊断'
+                } else if (params.aligothmTypeInfo.precondition == 'runningEnergy') {
+                    params.preconditionDetail =
+                        '只有当设备的运行能耗大于' + params.aligothmTypeInfo.energyupper + 'kwh时才启动诊断'
+                } else {
+                    params.preconditionDetail = '设备在任何状态下都启动报警诊断'
+                }
+                // 报警诊断日期及时间
+                if (params.aligothmTypeInfo.dateSet == 'all') {
+                    params.dateSetDetail = '全部时间'
+                } else if (params.aligothmTypeInfo.dateSet == 'workday') {
+                    params.dateSetDetail = '仅工作日'
+                } else {
+                    params.dateSetDetail = '仅周末'
+                }
+                if (params.aligothmTypeInfo.timeSet == 'all') {
+                    params.timeSetDetail = '全部时间'
+                } else {
+                    let start1 = params.aligothmTypeInfo.startTime.substring(0, 2)
+                    let start2 = params.aligothmTypeInfo.startTime.substring(2, 4)
+                    let end1 = params.aligothmTypeInfo.endTime.substring(0, 2)
+                    let end2 = params.aligothmTypeInfo.endTime.substring(2, 4)
+                    params.timeSetDetail = start1 + ':' + start2 + '---' + end1 + ':' + end2
+                }
+            }
+            // 阈值算法
+            if (aligothm[0].value == 'threshold') {
+                // 报警门限值设定方法
+                if (params.aligothmTypeInfo.thresholdSetType == 'customed') {
+                    params.thresholdMethod = '手动设定报警门限值'
+                    if (params.aligothmTypeInfo.thresholdSetTypeInfo.type == 'upperLower') {
+                        params.thresholdCustomed =
+                            '上下限:' +
+                            params.aligothmTypeInfo.thresholdSetTypeInfo.lower +
+                            '---' +
+                            params.aligothmTypeInfo.thresholdSetTypeInfo.upper
+                    } else if (params.aligothmTypeInfo.thresholdSetTypeInfo.type == 'lower') {
+                        params.thresholdCustomed = '下限:' + params.aligothmTypeInfo.thresholdSetTypeInfo.lower
+                    } else {
+                        params.thresholdCustomed = '上限:' + params.aligothmTypeInfo.thresholdSetTypeInfo.upper
+                    }
+                } else if (params.aligothmTypeInfo.thresholdSetType == 'compareInfoCode') {
+                    params.thresholdMethod = '指定数据字典中信息点进行比对'
+                    if (params.aligothmTypeInfo.thresholdSetTypeInfo.type == 'upperLower') {
+                        params.thresholdCustomed =
+                            '上下限:' +
+                            params.aligothmTypeInfo.thresholdSetTypeInfo.lowerCompareInfocode +
+                            '---' +
+                            params.aligothmTypeInfo.thresholdSetTypeInfo.upperCompareInfocode
+                    } else if (params.aligothmTypeInfo.thresholdSetTypeInfo.type == 'lower') {
+                        params.thresholdCustomed =
+                            '下限:' + params.aligothmTypeInfo.thresholdSetTypeInfo.lowerCompareInfocode
+                    } else {
+                        params.thresholdCustomed =
+                            '上限:' + params.aligothmTypeInfo.thresholdSetTypeInfo.upperCompareInfocode
+                    }
+                } else {
+                    params.thresholdMethod = '使用历史值进行比对'
+                    params.thresholdCustomed = null
+                }
+            }
+            //要求响应时间
+            params.respTime = this.respTimeObj[params.respondTime] || '--'
+            this.itemData = params
+        }
+    },
+    watch: {
+        lookVisibleFlag: function() {
+            this.dialogVisible = true
+        },
+        rowInfoData(val) {
+            if (val) {
+                this.itemDataHandle(val)
+            }
+        }
+    }
+}
+</script>
+<style lang='less' scoped>
+.item-info-box {
+    .item-info {
+        padding-left: 20%;
+        p {
+            padding: 10px 0;
+            display: flex;
+            span:nth-of-type(1) {
+                margin-right: 20px;
+            }
+        }
+        .level-dec {
+            color: #b2b2b2;
+        }
+    }
+    .btn-box {
+        margin-top: 20px;
+        text-align: center;
+        .edit-btn {
+            margin-right: 50px;
+        }
+    }
+}
+</style>
+
+
+

+ 334 - 0
src/views/alarm/projalarm/nospport.vue

@@ -0,0 +1,334 @@
+/**
+@author:fugy
+@date:2018.09.19
+@info:查看不支持的项目报警条目
+ */
+ <template>
+    <div class="item-box">
+        <div class="tit">
+            <el-button class="btn" type="primary" size="small" @click="confirmHandle()">返回</el-button>
+            <h6 class="name">查看项目内对象实例不支持的报警条目</h6>
+        </div>
+        <div class="top">
+            <el-input
+            style="width: 500px;"
+            placeholder="支持报警条目名称、条目编码进行搜索"
+            v-model.trim="searchValue"
+            clearable>
+                <el-button slot="append" icon="el-icon-search" @click="search"></el-button>
+            </el-input>
+        </div>
+        <hr class="line" />
+        <div class="content">
+            <div class="condition">
+                <p class="block">
+                    <span>报警条目 : </span>
+                    <v-alarm-item @change="alarmChange" :objTypeArr="objTypeArr"></v-alarm-item>
+                </p>
+                <p class="block obj-type">
+                    <span>对象类型 : </span>
+                    <v-obj-type @change="objTypeChange" ref="objType" :objType="objTypeComValue" :hasVerify="false"></v-obj-type>
+                </p>			
+            </div>
+            <div class="table-box">
+                <el-table
+                v-loading='loading'
+                :data="tableData"
+                border
+                style="width: 100%">
+                    <el-table-column
+                    prop="instanceInfo"
+                    label="适用对象实例"
+                    header-align="center"
+                    >
+                    </el-table-column>
+                    <el-table-column
+                    prop="name"
+                    label="报警条目名称"
+                    header-align="center"
+                    >
+                    </el-table-column>
+                    <el-table-column
+                    label="报警条目编码"
+                    header-align="center">
+                        <template slot-scope="scope">
+                            <p style="display: flex; justify-content: space-between">
+                                <span>{{scope.row.code}}</span>
+                                <el-tag style="margin-left: 10px;" v-if="scope.row.type=='customed'">自定义</el-tag>
+                            </p>
+                        </template>
+                    </el-table-column>
+                    <el-table-column
+                    prop="level"
+                    label="严重程度"
+                    header-align="center"
+                    >
+                    </el-table-column>
+                    <el-table-column
+                    prop="reason"
+                    label="不适用原因"
+                    header-align="center"
+                    >
+                    </el-table-column>                   
+                </el-table>
+            </div>
+        </div>
+        <el-row class="page-box" v-if="count">
+            <el-pagination
+            @size-change="handleSizeChange"
+            @current-change="handleCurrentChange"
+            :current-page="currentPage"
+            :page-sizes="[10, 20, 30, 50]"
+            :page-size="currentSize"
+            layout="total, sizes, prev, pager, next, jumper"
+            :total="count">
+            </el-pagination>
+        </el-row>
+    </div>
+ </template>
+
+ <script>
+ import api from './api';
+ import fixedApi from '@/api/alarm/alarm';
+ import fixedUtils from '@/components/alarm/utils'
+ import utils from "./utils"; //utils
+ //components
+ import vObjType from '@/components/alarm/ObjType' //对象类型
+import vAlarmItem from '@/components/alarm/AlarmItem' //报警条目
+// vuex
+import { mapGetters } from 'vuex';
+ export default {
+     name: 'no-spport',
+     data() {
+         return {
+             /************** */
+             objTypeComValue: [],
+             objTypeArr:[],
+             /**************** */
+             loading: false,
+            // selectAlarmItemFlag: false, //报警条目筛选的状态
+            projectId: '', //项目id
+            searchValue: '', //关键字查询
+            likeSearchValue: null, //模糊查询
+            tableData: [], //表格数据
+            startCascadeValue: null, //级联第一项
+            endCascadeValue: null, //级联最后一项
+            selectAlarmItemArr: null, //筛选报警条目的回显数组
+            selectAlarmItemRadio: null, //筛选的报警条目的固定or自定义
+            currentPage: 1,
+            currentSize: 10,
+            count: 0,      
+            entityDictObj:[], //适用对象类实体的数据字典	   
+        }
+     },
+     props: ["noSpportVisibleFlag", "vAlarmItem"],
+     computed: {
+         ...mapGetters("alarm", ["spaceCodeObj"])
+     },
+     components: {
+         vObjType,
+         vAlarmItem,
+     },
+     methods: {
+        // 返回事件
+        confirmHandle () {
+            this.$router.push("/projectinit/projectalarmitem?projectId=" +this.projectId)   
+        },
+        //分页
+		handleSizeChange (size) {
+			this.currentPage = 1;
+			this.currentSize = size;
+			this.getListData();
+		},
+		handleCurrentChange (page) {
+			this.currentPage = page;
+			this.getListData();
+		},
+        // 查询事件
+        search() {
+            if(this.searchValue) {
+                this.likeSearchValue = {
+                    $like: `%${this.searchValue}%`
+                }
+            }else {
+                this.likeSearchValue = null;
+            }
+            this.currentPage = 1;
+            this.getListData();
+        },
+        // 清空报警条目
+		clearAlarmItem() {
+            this.currentPage = 1;
+			// this.selectAlarmItemArr = null;
+			this.selectAlarmCodeArr = null;
+			this.selectAlarmItemRadio = null;
+			// this.selectBtnInfo = "全部"
+			this.getListData();
+		},
+        // 报警条目
+		alarmItemHandle() {
+			this.selectAlarmItemFlag = !this.selectAlarmItemFlag;			
+		},
+        // 获取list数据
+		getListData() {
+            this.loading = true;
+            this.tableData = [];
+            // 判断category
+            let category = null;
+            if(this.startCascadeValue == "building" || this.startCascadeValue == "floor") {
+                category = null
+            } else if(this.startCascadeValue == "space"){
+                if(this.endCascadeValue){
+                    let p = fixedUtils.spaceSonCode(this.endCascadeValue, this.spaceCodeObj);
+                    category = p;
+                } else {
+                    category = null
+                }                
+            } else if (this.startCascadeValue == "system" || this.startCascadeValue == "facility"){
+                category = [this.endCascadeValue]
+            }
+			let params = {
+                criteria: {
+                    keyword: this.likeSearchValue|| null, 
+                    objType: this.startCascadeValue || null,  
+                    category: category ? {"$in":category} : null,
+                    configType: this.selectAlarmItemRadio,  
+                    issupport: 0, 
+                    code: this.selectAlarmCodeArr ? ({$in: this.selectAlarmCodeArr}) : null,  
+                    projectId: this.projectId
+                },				 
+				page: this.currentPage, 
+				size: this.currentSize  
+            }
+			api.getListData(params).then(res => {
+                this.loading = false;
+				if(res.result === "success" && res.content) {
+                    let applyArr = [];
+					res.content.forEach((item, index) => {
+                        // 中转适用对象类实例
+						applyArr.push({id: item.instanceId})	
+						// 中转设备类
+						if(item.objType == "facility") {
+							item.instanceInfo = item.instanceName + " - " + item.instanceId + (item.instanceLocation ? " - "+item.instanceLocation : null)
+						} else {
+							item.instanceInfo = item.instanceName + " - " + item.instanceId
+						}
+                    })
+                    // 去获取适用对象类的本地信息
+					let params = {criterias: applyArr, valid: null}
+					api.getApplyObjInfo(this.projectId, params).then(resp => {	
+						if(resp.length) {
+							this.entityDictObj = utils.entityDict(resp);
+							res.content.forEach((ele, idx) => {
+								let preName = utils.objPreName(ele.objType);
+								let name = this.entityDictObj[ele.instanceId].infos[preName + "LocalName"] || this.entityDictObj[ele.instanceId].infos[preName + "Name"];
+								let id = this.entityDictObj[ele.instanceId].infos[preName + "LocalID"] || this.entityDictObj[ele.instanceId].infos[preName + "ID"];
+								if(preName == "facility") {
+									ele.instanceInfo = name + " - " + id + (ele.instanceLocation ? " - "+ele.instanceLocation : "");
+								} else {
+									ele.instanceInfo = name + " - " + id;
+								}
+							})
+							// 最后赋值
+							this.count = res.count;
+							this.tableData = res.content;						
+						}
+					})
+				} else {
+                    this.count = 0;
+					this.tableData = [];
+                }
+			}) 
+        },
+        // 获取对象类型的Arr
+		getObjectType() {
+			fixedApi.getObjectType().then(res => {
+                let {sysArr, devArr} = res;
+                this.objTypeOptions[3].children = sysArr;
+                this.objTypeOptions[4].children = devArr;
+            });
+		},
+        /******************组件回传事件********************************************** */
+        objTypeChange(val) {
+            this.objTypeArr = val;
+            if(val.length){
+				this.startCascadeValue = val[0];
+                this.endCascadeValue = val[val.length-1];
+                if(val.length == 1 && this.startCascadeValue == "space") {
+                    this.endCascadeValue = null;
+                }
+			} else {
+				this.startCascadeValue = null;
+				this.endCascadeValue = null;
+			}
+			this.clearAlarmItem();
+        },
+        alarmChange(radio, arr) {
+            if(arr.length) {
+                this.selectAlarmCodeArr = arr;
+            } else {
+                this.selectAlarmCodeArr = null;
+            }
+            this.currentPage = 1;								
+			this.selectAlarmItemRadio = radio;
+			this.getListData();
+        }
+     },
+     created() {
+         if(!this.spaceCodeObj) {
+             this.$store.commit("alarm/ADD_INDEX")
+         }
+     },
+     mounted() {
+        this.projectId = this.$route.query.proId;
+        if(this.projectId) {
+            // 获取对象类型的数据
+            // this.getObjectType();
+            // 获取列表数据
+            this.getListData();
+        } else {
+            window.history.go(-1);
+        }
+        
+     }
+ }
+ </script>
+ <style lang="less" scoped>
+ .item-box {
+    .tit{
+        text-align: center;
+        height: 35px;
+        .btn{
+            float: left;
+        }
+    }
+    .line {
+        background-color: #ccc;
+        height: 1px;
+        border: none;
+        }
+        .content {
+            .condition {
+            font-size: 16px;
+            overflow: hidden;
+            .block {
+                float: right;
+                margin-left: 30px;
+            }
+            .obj-type {
+                display: flex;
+                line-height: 40px;
+            }
+        }
+        .table-box {
+            margin-top: 10px;
+        } 
+    }
+    .page-box {
+        margin-top: 10px;
+        text-align: center;
+    }
+ }
+ </style>
+ 
+ 

+ 241 - 0
src/views/alarm/projalarm/selectratedinfo.vue

@@ -0,0 +1,241 @@
+/**
+@author:fugy
+@date:2018.09.21
+@info:固定报警条目选择技术报警点的弹窗
+ */
+ <template>
+ <!-- @close="selectInfoCloseHandle" -->
+<el-dialog
+title="选择报警触发时所转问题"
+:visible.sync="dialogVisible"
+width="50%"
+center
+>
+    <div class="problem-box">
+        <!-- <div class="top">   
+            <el-radio-group v-model="radioValue">
+                <el-radio-button v-for="(item, index) in radioArr" :key="index" :label="item.value" :disabled="objTypeValue != item.value">{{item.label}}</el-radio-button>
+            </el-radio-group>
+        </div>
+        <hr class="line" /> -->
+        <div class="content">
+            <!-- <div class="contion" v-if="radioValue == 'system' || radioValue == 'facility'">
+                <el-select v-model="majorSelectValue" clearable placeholder="请选择专业" @change="changeMajorHandle">
+                    <el-option
+                    v-for="item in majorSelectArr"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value">
+                    </el-option>
+                </el-select>
+                <el-select v-if="majorSelectValue" v-model="sysSelectValue" clearable placeholder="请选择系统" @change="changeSysHandle">
+                    <el-option
+                    v-for="item in sysSelectArr"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value">
+                    </el-option>
+                </el-select>
+                <el-select v-if="sysSelectValue && this.radioValue=='facility'" v-model="devSelectValue" clearable placeholder="请选择设备" @change="changeDevHandle">
+                    <el-option
+                    v-for="item in devSelectArr"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value">
+                    </el-option>
+                </el-select>
+            </div> -->
+            <div class="table-box">
+                <el-table
+                    v-if="infoPointArr"
+                    v-loading="loading"
+                    :data="infoPointArr"
+                    border
+                    style="width: 100%">
+                    <el-table-column
+                    prop="infoPointName"
+                    label="信息点名称"
+                    header-align="center">
+                    </el-table-column>
+                    <el-table-column
+                    prop="infoPointCode"
+                    label="信息点infoid"
+                    header-align="center">
+                    </el-table-column>                   
+                    <el-table-column
+                    label="选择"
+                    header-align="center"
+                    align="center"
+                    >
+                    <template slot-scope="scope">
+                        <el-radio v-model="selectInfoValue" :label="scope.row.infoPointCode" @change="radioHandle(scope.row)">{{null}}</el-radio>
+                    </template>
+                    </el-table-column>
+                </el-table>
+            </div>
+        </div>
+    </div>
+</el-dialog>
+ </template>
+ 
+ <script>
+import api from './api';
+export default {
+    name: "has-problem",
+    data() {
+        return {            
+            dialogVisible: false,
+            loading: false,
+            radioArr:[{ //单选按钮的数据Arr             
+                value: 'building',
+                label: '建筑',
+            },{
+                value: 'floor',
+                label: '楼层',
+            },{
+                value: 'system',
+                label: '系统类',
+            },{
+                value: 'facility',
+                label: '设备类',
+            }], 
+            radioValue:'space', //单选按钮的value值
+            majorSelectValue: null, //专业下拉value
+            majorSelectArr: [], //专业下拉的数组
+            sysSelectValue: null, //系统下拉value
+            sysSelectArr: [], //系统下拉的数组
+            devSelectValue: null, //设备下拉value
+            devSelectArr: [], //设备下拉的属猪
+            tableData:[
+                {
+                    infoPointName: '信息点1',
+                    infoPointCode: '001',
+                },{
+                    infoPointName: '信息点2',
+                    infoPointCode: '002',
+                }
+            ],
+            selectInfoValue: null, // 表格单选按钮的value值
+            param: null, //请求参数
+        }
+    },
+    props:["selectRatedInfoFlag", "objTypeValue", "infoPointArr","selectRatedInfoCheckedCode"],
+    methods: {
+        //表格单选按钮
+        radioHandle(row){
+            this.$emit("select-info-handle", row.infoPointName, row.infoPointCode);
+            this.dialogVisible = false;
+        },
+        //弹窗关闭
+        // selectInfoCloseHandle() {
+        //     this.majorSelectValue = null;
+        //     this.sysSelectValue = null;
+        //     this.devSelectValue = null;
+        //     this.loading = false;
+        // },
+        //获取专业的接口
+        getmajorSelectData() {
+            this.majorSelectArr = api.getMajorSelectData();
+        },
+        // 改变专业下拉,获取系统的下拉列表
+        changeMajorHandle(val) {
+            if(!val){
+                return;
+            }
+            this.sysSelectValue = null;
+            let arr = api.getSysSelectData(val);
+            if(arr){
+                this.sysSelectArr = arr;
+            } else {
+                this.sysSelectArr = [];
+            }
+        },
+        // 改变系统下拉,获取设备的下拉列表
+        changeSysHandle(val) {
+            // console.log(val);
+            if(!val){
+                return;
+            }
+            if (this.radioValue == "system") { //系统
+
+            } else { //设备
+                this.devSelectValue = null;
+                let arr = api.getDevSelectData(val);
+                if(arr){
+                    this.devSelectArr = arr;
+                }else {
+                    this.devSelectArr = [];
+                }  
+            }
+                       
+        },
+        // 改变设备的下拉
+        changeDevHandle (val) {
+            console.log(val)
+        },
+        //获取技术信息点
+        getInfoListData() {
+            this.loading = true;
+            this.param = this.endCascadeValue;
+            if (this.startCascadeValue == 'system') {
+                this.param = this.param.substring(2,4);
+            }
+            if (this.startCascadeValue == 'facility') {
+                this.param = this.param.substring(2,6);
+            } 
+            let params = {
+                type: this.param,
+            }
+            api.getInfoListData(params).then((res) => {
+                this.loading = false;
+                // console.log(res);
+                // let data = res;
+                // let arr = data.filter((ele, index) => {
+                //     return ele.firstTag ? ele.firstTag == '技术参数': null
+                // })
+                this.tableData = res;
+            }).catch(err => {
+                throw err;
+            })
+        }
+    },
+    watch: {
+        //弹窗显示
+        selectRatedInfoFlag() {
+            this.dialogVisible = true;
+            this.selectInfoValue = this.selectRatedInfoCheckedCode;
+            //获取技术信息点
+            // this.getInfoListData(); 
+            // this.selectInfoValue = null;
+            // if (this.objTypeValue == "system" || this.objTypeValue == "facility") {
+            //     this.getmajorSelectData();
+            // }
+        },
+        //获取专业的下拉列表
+        objTypeValue() {
+            this.radioValue = this.objTypeValue;            
+        }
+    }
+}
+ </script>
+ <style lang="less" scoped>
+ .problem-box{
+     height: 600px;
+     overflow-y: auto;
+     .top{
+         text-align: center;
+     }
+     .line{
+        background-color: #ccc;
+        height: 1px;
+        border: none;
+     }
+     .content{
+         .table-box{
+             margin-top: 10px;
+         }
+     }
+ }
+ </style>
+ 
+ 

+ 28 - 0
src/views/alarm/projalarm/utils.js

@@ -0,0 +1,28 @@
+const utils = {
+    // 整合物理实体字典
+    entityDict(oldArr) {
+        let obj = {};
+        oldArr.forEach((ele, index) => {
+            obj[ele.id] = ele
+        }) 
+        return obj;
+    },
+    // 获取根据objtype获取名字前缀
+    objPreName: function (objType) {
+        let pre = null;
+        switch (objType) {
+            case "building": 
+                pre = "Build"; break;
+            case "floor": 
+                pre = "Floor"; break;
+            case "space":
+                pre = "Room"; break;
+            case "system":
+                pre = "Sys"; break;
+            case "facility":
+                pre = "Equip"; break;
+        }
+        return pre;
+    },
+}
+export default utils;

+ 208 - 0
src/views/alarm/staff/ManageUser.vue

@@ -0,0 +1,208 @@
+<template>
+    <el-dialog title='管理通知人员' :visible.sync='dialogVisible' width='60%' center top='10vh'>
+        <div class='box'>
+            <el-table :data='tableData' style='width: 100%' border height='500'>
+                <el-table-column prop='name' label='姓名' header-align='center' width='150'></el-table-column>
+                <el-table-column prop='phone' label='手机号' header-align='center'></el-table-column>
+                <el-table-column prop='email' label='邮箱地址' header-align='center'></el-table-column>
+                <el-table-column prop='address' label='操作' width='150' header-align='center'>
+                    <template slot-scope='scope'>
+                        <el-button style='color: red' @click='handleClick(scope.row)' type='text' size='small'>不再接收断数报警</el-button>
+                    </template>
+                </el-table-column>
+            </el-table>
+        </div>
+        <p class="select" v-clickoutside='handleClose'>
+            <el-button type='text' icon='el-icon-setting' @click='manageUser'>从项目通知人员表中选择人员</el-button>
+            <ul v-if="userData.length" class="select-box" v-show="selectFlag">
+                <li v-for="(item,index) in userData" :key="index" :class='userSelected == index ? "userSelected" : ""' @click="addNotice(item,index)">
+                    {{item.name}}
+                </li>
+            </ul>
+            <ul v-else class="select-box" v-show="selectFlag">
+                <li>暂无数据</li>
+            </ul>
+        </p>
+    </el-dialog>
+</template>
+
+<script>
+//api
+import api from '@/api/alarm/alarm'
+import noticeApi from '../notice/api'
+export default {
+    name: 'notice-user',
+    data() {
+        return {
+            dialogVisible: false,
+            selectFlag: false,
+            userSelected: null,
+            tableData: [], //表格数据
+            userData: [] //所有通用人员的数据
+        }
+    },
+    props: ['manageDialogVisible','projectId'],
+    directives:{
+        clickoutside:{
+            bind:function(el,binding,vnode){
+                function documentHandler(e){
+                    if(el.contains(e.target)){
+                        return false;
+                    }
+                    if(binding.expression){
+                        binding.value(e)
+                    }
+                }
+                el._vueClickOutside_ = documentHandler;
+                document.addEventListener('click',documentHandler);
+            },
+            unbind:function(el,binding){
+                document.removeEventListener('click',el._vueClickOutside_);
+                delete el._vueClickOutside_;
+            }
+        }
+    },
+    methods: {
+        async handleClick(row) {
+            let params = {
+                id: row.id,
+                projectId: this.projectId,
+                isReceiveBrokenAlarm: 0
+            };
+            let res = await noticeApi.userEditSave(params)
+            if(res.result == 'success') {
+                this.$message({
+                    message: '保存成功',
+                    type: 'success'
+                });
+                this.getNumUser()
+                this.$emit('refresh')
+            }
+        },
+        manageUser() {
+            this.userSelected = null;
+            this.selectFlag = true;
+        },
+        handleClose(){
+            this.selectFlag = false
+        },
+        async addNotice(obj, index) {
+            this.userSelected = index;
+            //添加断数报警
+            let arr = this.tableData.filter((item) => {
+                return item.id == obj.id
+            });
+            if(arr.length) {
+                this.$message({
+                    message: '当前人员已在断数通知人员中',
+                    type: 'warning'
+                });
+            } else {
+                let params = {
+                    id: obj.id,
+                    projectId: this.projectId,
+                    isReceiveBrokenAlarm: 1
+                };
+                let res =await noticeApi.userEditSave(params)
+                if(res.result == 'success') {
+                    this.$message({
+                        message: '添加成功',
+                        type: 'success'
+                    });
+                    this.getNumUser()
+                    this.$emit('refresh')
+                }
+            }
+
+        },
+        //获取通知人员
+        async getUser() {
+            let params = {
+                criteria: {
+                    projectId: this.projectId
+                }
+            };
+            let res = await noticeApi.getUserList(params)
+            if(res.result == 'success' && res.count) {
+                this.userData = res.content
+            }else {
+                this.userData = []
+            }
+        },
+        // 获取断数报警人员
+        async getNumUser() {            
+            let params = {
+                criteria: {
+                    projectId: this.projectId,
+                    isReceiveBrokenAlarm: 1
+                }
+            };
+            let res = await noticeApi.getUserList(params)
+            if(res.result == 'success' && res.count) {
+                this.tableData = res.content
+            } else {
+                this.tableData = []
+            }
+        },
+        init(){
+            // 获取通知人员
+            this.getUser()
+            //获取断数报警人员
+            this.getNumUser()
+        }  
+    },
+    mounted() {
+        this.init()
+    },
+    watch: {
+        manageDialogVisible() {
+            this.selectFlag = false;
+            this.userSelected = null;
+            this.dialogVisible = true;
+            this.init()
+        }
+    }
+}
+</script>
+
+<style lang='less' scoped>
+.select{
+    position: relative;
+    width: 300px;
+    .select-box {
+        top: 35px;
+        left: 5px;
+        position: absolute;
+        width: 250px;
+        padding: 6px 0;
+        border: 1px solid #e4e7ed;
+        border-radius: 4px;
+        background-color: #fff;
+        box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
+        box-sizing: border-box;
+        margin: 5px 0;
+        max-height: 150px;
+        overflow: auto;
+        li{
+            border-bottom: 1px solid #e4e7ed;
+            font-size: 14px;
+            padding: 0 20px;
+            white-space: nowrap;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            color: #606266;
+            height: 34px;
+            line-height: 34px;
+            box-sizing: border-box;
+            cursor: pointer;
+        }
+        li:last-child{
+            border: none
+        }       
+        .userSelected{
+            color: #409eff;
+            font-weight: 600
+        }    
+    }
+}
+</style>

+ 153 - 0
src/views/alarm/staff/index.vue

@@ -0,0 +1,153 @@
+<template>
+    <div>
+        <!-- contion -->
+        <div class='cont'>
+            <sg-selector type='project' @changed='projectedSelected'></sg-selector>
+            <el-button class='btn' type='primary' @click='manageBtn'>管理断数报警通知人员</el-button>
+        </div>
+        <!-- list -->
+        <div class='content'>
+            <div class='box'>
+                <ul class='ul-box' v-if='userData.length'>
+                    <li class='tit'>
+                        <p>人员姓名及通知方式</p>
+                    </li>
+                    <li v-for='(item, index) in userData' :key='item.id'>
+                        <p>
+                            <span class='name'>{{item.name}}</span>
+                            <span class='name'>{{item.phone}}</span>
+                            <span class='name'>{{item.email}}</span>
+                        </p>
+                        <span>
+                            <v-check-box
+                                :sendMessage='item.sendMessage'
+                                :sendEmail='item.sendEmail'
+                                :sendWechat='item.sendWechat'
+                                :define='index'
+                                @change='checkBoxChange'
+                            ></v-check-box>
+                        </span>
+                    </li>
+                </ul>
+                <!-- 没有数据的时候 -->
+                <ul class='ul-box' v-else>
+                     <li class='tit'>
+                        <p>人员姓名及通知方式</p>
+                    </li>
+                    <li>暂无数据</li>
+                </ul>                
+            </div>
+        </div>
+        <!-- components -->
+        <v-manage-user :manageDialogVisible='manageDialogVisible' :projectId='projectId' @refresh='refreshPage'></v-manage-user>
+    </div>
+</template>
+
+<script>
+//api
+import api from '@/api/alarm/alarm'
+//components
+import vCheckBox from '@/components/alarm/common/CheckBox'
+import vManageUser from './ManageUser'
+export default {
+    name: 'numnotice',
+    data() {
+        return {
+            manageDialogVisible: false,
+            projectId: null,
+            userData: []
+        }
+    },
+    components: {
+        vCheckBox,
+        vManageUser
+    },
+    methods: {
+        //项目change
+        projectedSelected(val) {
+            this.projectId = val
+            //获取人员通知方式
+            this.getUserNotice()
+        },
+        //管理断数报警通知人员
+        manageBtn() {
+            this.manageDialogVisible = !this.manageDialogVisible
+        },
+        //多选修改
+        checkBoxChange(obj, index) {
+            this.updateUserNotice(obj, index)
+        },
+        //获取通知人员的通知方式
+        async getUserNotice() {
+            let params = {
+                criteria: {
+                    projectId: this.projectId,
+                    isReceiveBrokenAlarm: 1
+                }
+            }
+            let res = await api.getNumUserNotice(params)
+            this.userData = res
+        },
+        //更新报警通知方式
+        async updateUserNotice(obj, index) {
+            let id = this.userData[index].id
+            let params = {
+                id: id,
+                projectId: this.projectId,
+                sendMessage: obj.sendMessage,
+                sendEmail: obj.sendEmail,
+                sendWechat: obj.sendWechat
+            }
+            let res = await api.updateNumUserNotice(params)
+            if (res.result == 'success') {
+                this.$message({
+                    message: '保存成功',
+                    type: 'success'
+                })
+            }
+        },
+        //refresh
+        refreshPage() {
+            this.getUserNotice()
+        }
+    }
+}
+</script>
+
+<style lang='less' scoped>
+.cont {
+    overflow: hidden;
+    margin-bottom: 10px;
+    .btn {
+        float: right;
+    }
+}
+.content {
+    .box {
+        font-size: 16px;
+        color: #606266;
+        .ul-box {
+            border: 1px solid #ebeef5;
+            border-bottom: none;
+            li {
+                padding: 10px;
+                display: flex;
+                justify-content: space-between;
+                border-bottom: 1px solid #ebeef5;
+                p {
+                    display: flex;
+                    .name {
+                        width: 150px;
+                    }
+                }
+            }
+            .tit {
+                justify-content: center;
+            }
+        }
+    }
+}
+</style>
+ 
+
+