497 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			497 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | |
|   <div class="layout-config__group--wrapper">
 | |
|     <div class="layout-config__group" v-if="options.type=='map'">
 | |
|       <div flex>
 | |
|         <span class="layoutTitle fill">标记点设置</span>
 | |
|         <el-button type="text" icon="iconfont iconAdd" @click="handleMapMarker()">添加</el-button>
 | |
|       </div>
 | |
|       <div class="layout-config__item" v-for="(item,i) in options.staticData" :key="i">
 | |
|         <label v-text="item.label"/>
 | |
|         <div class="layout-config__item--right">
 | |
|           <el-input :value="[item.lat,item.lng].join(',')" readonly size="small"/>
 | |
|           <el-button type="text" icon="el-icon-edit" @click="handleMapMarker(item,i)"/>
 | |
|         </div>
 | |
|       </div>
 | |
|     </div>
 | |
|     <div class="layout-config__group" v-else-if="options.monitorType !== 'hik' && options.monitorType !== 'dahua'">
 | |
|       <h2>基础设置</h2>
 | |
|       <div class="layout-config__item">
 | |
|         <label>数据类型</label>
 | |
|         <div class="layout-config__item--right">
 | |
|           <el-select size="mini" v-model="options.dataType" placeholder="请选择数据类型">
 | |
|             <el-option
 | |
|                 v-for="item in dataTypes"
 | |
|                 :key="item.value"
 | |
|                 :label="item.label"
 | |
|                 :value="item.value">
 | |
|             </el-option>
 | |
|           </el-select>
 | |
|         </div>
 | |
|       </div>
 | |
|       <div class="layout-config__code" v-if="options.dataType === 'staticData'">
 | |
|         <el-button @click="showEditor" class="layout-config__code--btn" title="编辑" type="text" icon="iconfont iconjdq_led_edit"></el-button>
 | |
|         <code-editor readonly :value="JSON.stringify(options.staticData, null, 2)" lang="json" theme="github" width="100%" height="250"></code-editor>
 | |
|       </div>
 | |
|       <template v-else-if="options.dataType === 'dynamicData'">
 | |
|         <div class="layout-config__item">
 | |
|           <label>数据源</label>
 | |
|           <div class="layout-config__item--right">
 | |
|             <el-select size="mini" v-model="options.sourceDataId" placeholder="请选择数据源" @change="onDataChange">
 | |
|               <el-option
 | |
|                   v-for="item in sourceData"
 | |
|                   :key="item.id"
 | |
|                   :label="item.description"
 | |
|                   :value="item.id">
 | |
|               </el-option>
 | |
|             </el-select>
 | |
|           </div>
 | |
|         </div>
 | |
|       </template>
 | |
|       <template v-else>
 | |
|         <div class="layout-config__item">
 | |
|           <label>接口地址</label>
 | |
|           <div class="layout-config__item--right">
 | |
|             <el-input size="mini" v-model="options.api" @blur="onApiChange"></el-input>
 | |
|           </div>
 | |
|         </div>
 | |
|       </template>
 | |
|     </div>
 | |
|     <div class="layout-config__group" v-if="options.monitorType === 'hik' || options.monitorType === 'dahua'">
 | |
|       <h2>基础设置</h2>
 | |
|       <div class="layout-config__item">
 | |
|         <label>视频地址</label>
 | |
|         <div class="layout-config__item--right">
 | |
|           <el-input size="mini" v-model="options.src"></el-input>
 | |
|         </div>
 | |
|       </div>
 | |
|     </div>
 | |
|     <div class="layout-config__group" v-if="options.dataType !== 'staticData' && options.type === 'monitor' &&['cmcc','slw'].includes(options.monitorType)">
 | |
|       <h2>字段设置</h2>
 | |
|       <div class="layout-config__item">
 | |
|         <label>监控视频</label>
 | |
|         <div class="layout-config__item--right">
 | |
|           <el-select size="mini" v-model="options.moniterId" placeholder="请选择监控视频" @change="onMoniterId">
 | |
|             <el-option
 | |
|                 v-for="(item, index) in monitorList"
 | |
|                 :key="index"
 | |
|                 :label="item.name"
 | |
|                 :value="item.id">
 | |
|             </el-option>
 | |
|           </el-select>
 | |
|         </div>
 | |
|       </div>
 | |
|     </div>
 | |
|     <div class="layout-config__group" v-if="options.dataType !== 'staticData' && options.type !== 'monitor' && keys.length && options.type !== 'table'">
 | |
|       <h2>字段设置</h2>
 | |
|       <div class="layout-config__item">
 | |
|         <label>X轴设置</label>
 | |
|         <div class="layout-config__item--right">
 | |
|           <el-select size="mini" v-model="options.dataX" placeholder="请选择X轴" @change="onChooseChange">
 | |
|             <el-option
 | |
|                 v-for="(item, index) in keys"
 | |
|                 :key="index"
 | |
|                 :label="item"
 | |
|                 :value="item">
 | |
|             </el-option>
 | |
|           </el-select>
 | |
|         </div>
 | |
|       </div>
 | |
|       <div class="layout-config__item">
 | |
|         <label>Y轴设置</label>
 | |
|         <div class="layout-config__item--right">
 | |
|           <el-select size="mini" multiple :multiple-limit="options.type.indexOf('pie') > -1 ? 1 : 100" v-model="options.dataY" collapse-tags placeholder="请选择Y轴"
 | |
|                      @change="onChooseChange">
 | |
|             <el-option
 | |
|                 v-for="(item, index) in keys"
 | |
|                 :key="index"
 | |
|                 :label="item"
 | |
|                 :value="item">
 | |
|             </el-option>
 | |
|           </el-select>
 | |
|         </div>
 | |
|       </div>
 | |
|     </div>
 | |
|     <ai-dialog
 | |
|         append-to-body
 | |
|         :visible.sync="isShowEditor"
 | |
|         width="1000px"
 | |
|         class="layout-config__edit"
 | |
|         title="编辑器"
 | |
|         @onConfirm="onConfirm">
 | |
|       <div>
 | |
|         <code-editor v-model="json" lang="json" theme="github" width="100%" height="440"></code-editor>
 | |
|       </div>
 | |
|     </ai-dialog>
 | |
|     <ai-dialog class="layout-config__edit" v-model="showMapEditor" title="设置地图标记点" append-to-body @close="form={}" @confirm="saveMarker">
 | |
|       <el-form :model="form" size="small" ref="mapMarker" label-width="120px">
 | |
|         <el-form-item label="标记点名称" :rules="{required:true,message:'请填写标记点名称'}">
 | |
|           <el-input placeholder="用于地图上展示对标记点的文字标签" v-model="form.label" clearable/>
 | |
|         </el-form-item>
 | |
|         <div flex>
 | |
|           <el-form-item class="fill" label="经度" :rules="{required:true,message:'请填写标记点经度'}">
 | |
|             <el-input v-model="form.lng" clearable placeholder="小数点位保留至少6位数"/>
 | |
|           </el-form-item>
 | |
|           <el-form-item class="fill" label="纬度" :rules="{required:true,message:'请填写标记点纬度'}">
 | |
|             <el-input v-model="form.lat" clearable placeholder="小数点位保留至少6位数"/>
 | |
|           </el-form-item>
 | |
|         </div>
 | |
|         <el-form-item label="弹窗内容">
 | |
|           <ai-editor v-model="form.infoWindowHtml" :instance="instance"/>
 | |
|         </el-form-item>
 | |
|       </el-form>
 | |
|     </ai-dialog>
 | |
|   </div>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
| import CodeEditor from 'bin-ace-editor'
 | |
| import 'brace/mode/json'
 | |
| import 'brace/snippets/json';
 | |
| import 'brace/theme/github';
 | |
| import 'brace/theme/monokai';
 | |
| 
 | |
| export default {
 | |
|   name: 'dataConfig',
 | |
| 
 | |
|   props: {
 | |
|     options: Object,
 | |
|     instance: Function,
 | |
|     dict: Object,
 | |
|     params: Object,
 | |
|   },
 | |
| 
 | |
|   data() {
 | |
|     return {
 | |
|       dataTypes: [
 | |
|         {
 | |
|           value: 'staticData',
 | |
|           label: '静态数据'
 | |
|         },
 | |
|         {
 | |
|           value: 'dynamicData',
 | |
|           label: '动态数据'
 | |
|         },
 | |
|         {
 | |
|           value: 'apiData',
 | |
|           label: '接口'
 | |
|         }
 | |
|       ],
 | |
|       isShowEditor: false,
 | |
|       json: {},
 | |
|       sourceDataId: '',
 | |
|       sourceData: [],
 | |
|       keys: [],
 | |
|       monitorList: [],
 | |
|       list: [],
 | |
|       jsonData: `{"title":"测试json数据","children":[{"name":"子项名称", "desc":"子项说明" },{"name":"子项名称1", "desc":"子项说明1" }]}`,
 | |
|       showMapEditor: false,
 | |
|       form: {}
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   components: {
 | |
|     CodeEditor
 | |
|   },
 | |
| 
 | |
|   mounted() {
 | |
|     this.getDataList()
 | |
| 
 | |
|     if ((this.options.dataY && this.options.dataY.length && this.options.dataX) || this.options.type === 'monitor') {
 | |
|       const api = this.options.dataType === 'apiData' ? this.options.api : `/app/appdiylargescreen/statisticsByLsid?id=${this.options.sourceDataId}`
 | |
|       this.instance.post(api).then(res => {
 | |
|         if (res.code == 0) {
 | |
|           if (res.data.length && this.options.type !== 'monitor') {
 | |
|             this.list = res.data
 | |
|             this.keys = Object.keys(res.data[0])
 | |
| 
 | |
|             this.$nextTick(() => {
 | |
|               this.onChooseChange()
 | |
|             })
 | |
|           } else if (this.options.type === 'monitor') {
 | |
|             this.monitorList = res.data
 | |
| 
 | |
|             if (this.options.src) {
 | |
|               const obj = res.data.filter(v => this.options.title === v.name)
 | |
| 
 | |
|               if (obj.length) {
 | |
|                 this.options.src = obj[0].url
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       })
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   methods: {
 | |
|     showEditor() {
 | |
|       this.json = JSON.stringify(this.options.staticData, null, 2)
 | |
|       this.isShowEditor = true
 | |
|     },
 | |
| 
 | |
|     onMoniterId(e) {
 | |
|       this.instance.post(`/app/appzyvideoequipment/getWebSdkUrl?deviceId=${e}`).then(res => {
 | |
|         if (res.code == 0) {
 | |
|           this.options.src = JSON.parse(res.data).url
 | |
|         }
 | |
|       })
 | |
|     },
 | |
| 
 | |
|     getDataList() {
 | |
|       this.instance.post(`/app/appdiylargescreen/allDatasourceByPage`, null, {
 | |
|         params: {
 | |
|           current: 1,
 | |
|           size: 10000
 | |
|         }
 | |
|       }).then(res => {
 | |
|         if (res.code == 0) {
 | |
|           this.sourceData = res.data.records
 | |
|         }
 | |
|       })
 | |
|     },
 | |
| 
 | |
|     onApiChange() {
 | |
|       this.options.dataX = ''
 | |
|       this.options.dataY = []
 | |
|       this.instance.post(this.options.api).then(res => {
 | |
|         if (res.code == 0) {
 | |
|           if (res.data.length) {
 | |
|             if (this.options.type === 'table' || this.options.type === 'AiDvTable') {
 | |
|               const keys = Object.keys(res.data[0])
 | |
|               const list = res.data
 | |
|               this.options.apiData = keys.map(v => {
 | |
|                 let obj = {}
 | |
|                 list.forEach((item, index) => {
 | |
|                   obj[`v${index}`] = item[v]
 | |
|                 })
 | |
| 
 | |
|                 return {
 | |
|                   row: v,
 | |
|                   ...obj
 | |
|                 }
 | |
|               })
 | |
|             } else if (this.options.type === 'summary') {
 | |
|               if (this.options.display === 'summary9') {
 | |
|                 this.options.apiData = res.data
 | |
|               } else {
 | |
|                 this.options.apiData = Object.keys(res.data[0]).map(item => {
 | |
|                   return {
 | |
|                     key: item,
 | |
|                     value: res.data[0][item]
 | |
|                   }
 | |
|                 })
 | |
|               }
 | |
|             } else if (this.options.type === 'monitor') {
 | |
|               this.monitorList = res.data
 | |
|             } else {
 | |
|               this.list = res.data
 | |
|               this.keys = Object.keys(res.data[0])
 | |
|             }
 | |
|           }
 | |
|         } else {
 | |
|           this.options.dynamicData = []
 | |
|         }
 | |
|       })
 | |
|     },
 | |
| 
 | |
|     onChooseChange() {
 | |
|       let arr = []
 | |
|       if (this.options.dataX && this.options.dataY.length) {
 | |
|         this.list.forEach(item => {
 | |
|           let obj = {}
 | |
|           this.options.dataY.forEach(v => {
 | |
|             obj[v] = item[v]
 | |
|           })
 | |
|           arr.push({
 | |
|             [this.options.dataX]: item[this.options.dataX],
 | |
|             ...obj
 | |
|           })
 | |
|         })
 | |
| 
 | |
|         this.options[this.options.dataType] = arr
 | |
|       }
 | |
|     },
 | |
| 
 | |
|     onDataChange(e) {
 | |
|       this.options.dataX = ''
 | |
|       this.options.dataY = []
 | |
|       this.instance.post(`/app/appdiylargescreen/statisticsByLsid?id=${e}`).then(res => {
 | |
|         if (res.code == 0) {
 | |
|           if (res.data.length) {
 | |
|             if (this.options.type === 'table' || this.options.type === 'AiDvTable') {
 | |
|               const keys = Object.keys(res.data[0])
 | |
|               const list = res.data
 | |
|               this.options.dynamicData = keys.map(v => {
 | |
|                 let obj = {}
 | |
|                 list.forEach((item, index) => {
 | |
|                   obj[`v${index}`] = item[v]
 | |
|                 })
 | |
| 
 | |
|                 return {
 | |
|                   row: v,
 | |
|                   ...obj
 | |
|                 }
 | |
|               })
 | |
|             } else if (this.options.type === 'summary') {
 | |
|               this.options.dynamicData = Object.keys(res.data[0]).map(item => {
 | |
|                 return {
 | |
|                   key: item,
 | |
|                   value: res.data[0][item]
 | |
|                 }
 | |
|               })
 | |
|             } else {
 | |
|               this.list = res.data
 | |
|               this.keys = Object.keys(res.data[0])
 | |
|             }
 | |
|           } else {
 | |
|             this.options.dynamicData = []
 | |
|           }
 | |
|         }
 | |
|       })
 | |
|     },
 | |
| 
 | |
|     onConfirm() {
 | |
|       this.$set(this.options, 'staticData', JSON.parse(this.json))
 | |
|       this.isShowEditor = false
 | |
|       this.$emit('change')
 | |
|     },
 | |
|     handleMapMarker(v = {}, index) {
 | |
|       this.form = this.$copy({...v, index})
 | |
|       this.showMapEditor = true
 | |
|     },
 | |
|     saveMarker() {
 | |
|       this.$refs.mapMarker.validate().then(() => {
 | |
|         const i = this.$copy(this.form.index)
 | |
|         delete this.form.index
 | |
|         if (i > -1) {
 | |
|           this.options.staticData.splice(i, 1, this.form)
 | |
|         } else this.options.staticData.push(this.form)
 | |
|         this.showMapEditor = false
 | |
|       })
 | |
|     }
 | |
|   }
 | |
| }
 | |
| </script>
 | |
| 
 | |
| <style lang="scss">
 | |
| .el-dialog__body {
 | |
|   .jsoneditor-vue {
 | |
|     height: 480px;
 | |
| 
 | |
|     .jsoneditor-poweredBy {
 | |
|       display: none;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| .layout-config__group--wrapper {
 | |
|   .layout-config__code .bin-ace-editor {
 | |
|   }
 | |
| 
 | |
|   .layout-config__group {
 | |
|     padding: 10px 10px 20px;
 | |
|     border-bottom: 1px solid #000000;
 | |
| 
 | |
|     &:last-child {
 | |
|       border: none;
 | |
|     }
 | |
| 
 | |
|     .layout-config__code {
 | |
|       position: relative;
 | |
|       padding-left: 10px;
 | |
| 
 | |
|       .layout-config__code--btn {
 | |
|         position: absolute;
 | |
|         right: 0;
 | |
|         top: 0;
 | |
|         color: gray;
 | |
|         z-index: 111;
 | |
| 
 | |
|         &:hover {
 | |
|           opacity: 0.8;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     & > h2 {
 | |
|       margin-bottom: 20px;
 | |
|       color: #FFFFFF;
 | |
|       font-size: 15px;
 | |
|       font-weight: 700;
 | |
|     }
 | |
| 
 | |
|     .layoutTitle {
 | |
|       color: #FFFFFF;
 | |
|       font-size: 15px;
 | |
|       font-weight: 700;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   .layout-config__item {
 | |
|     display: flex;
 | |
|     align-items: center;
 | |
|     justify-content: space-between;
 | |
|     margin-bottom: 10px;
 | |
| 
 | |
|     &:last-child {
 | |
|       margin-bottom: 0;
 | |
|     }
 | |
| 
 | |
|     label {
 | |
|       flex-shrink: 0;
 | |
|       width: 60px;
 | |
|       color: #FFFFFF;
 | |
|       font-size: 12px;
 | |
|       text-align: right;
 | |
|     }
 | |
| 
 | |
|     .layout-config__item--right {
 | |
|       display: flex;
 | |
|       align-items: center;
 | |
|       justify-content: flex-end;
 | |
|       width: 200px;
 | |
|       text-align: right;
 | |
|     }
 | |
| 
 | |
|     .el-select .el-tag {
 | |
|       color: #fff;
 | |
|       background: transparent;
 | |
|     }
 | |
| 
 | |
|     input {
 | |
|       background: #262C33;
 | |
|       font-size: 12px;
 | |
|       color: #fff;
 | |
|       border: 1px solid #030411;
 | |
|     }
 | |
| 
 | |
|     .el-input__icon {
 | |
|       color: #fff;
 | |
|     }
 | |
| 
 | |
|     .el-switch__label {
 | |
|       color: #fff;
 | |
|     }
 | |
| 
 | |
|     .el-select {
 | |
|       width: 100%;
 | |
| 
 | |
|       &:last-child {
 | |
|         margin-right: 0;
 | |
|       }
 | |
| 
 | |
|       input {
 | |
|         background: #262C33;
 | |
|         font-size: 12px;
 | |
|         color: #fff;
 | |
|         border: 1px solid #030411;
 | |
|       }
 | |
| 
 | |
|       .el-input__icon {
 | |
|         color: #fff;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| </style>
 |