463 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			463 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | |
|   <div class="layout-config__group--wrapper">
 | |
|     <template v-if="options.type=='map'">
 | |
|       <ai-fold>
 | |
|         <div slot="title" class="flex w100">
 | |
|           <span class="layoutTitle fill">标记点设置</span>
 | |
|           <el-button type="text" icon="iconfont iconAdd" @click="handleMapMarker()">添加</el-button>
 | |
|         </div>
 | |
|         <config-item v-for="(item,i) in markers" :key="i" :label="item.label">
 | |
|           <el-input :value="[item.lat,item.lng].join(',')" readonly size="small"/>
 | |
|           <el-button type="text" icon="el-icon-edit" @click="handleMapMarker(item,i)"/>
 | |
|           <el-button type="text" icon="el-icon-delete" @click="removeMapMarker(i)"/>
 | |
|         </config-item>
 | |
|       </ai-fold>
 | |
|       <ai-fold title="标记点连线">
 | |
|         <ai-dialog-btn :modal="false" dialog-title="设置标记点连线" :customFooter="false" @confirm="savePolylines"
 | |
|                        @open="handleMapPolylines">
 | |
|           <code-editor slot="btn" readonly :value="JSON.stringify(options.staticData.polylines, null, 2)" lang="json"
 | |
|                        theme="github" width="100%" height="250" placeholder="测试默认值"/>
 | |
|           <el-button class="m-center" type="text" @click="handleMapPolylineDoc" :closable="false">
 | |
|             点击查看连线设置参考文档
 | |
|           </el-button>
 | |
|           <code-editor v-model="json" lang="json" theme="github" width="100%" height="440"/>
 | |
|         </ai-dialog-btn>
 | |
|       </ai-fold>
 | |
|     </template>
 | |
|     <template v-else-if="isPlot">
 | |
|       <ai-fold v-for="(chart,i) in options.charts" :key="i">
 | |
|         <div slot="title" class="flex w100">
 | |
|           <span class="layoutTitle fill" v-text="chart.title"/>
 | |
|           <el-button type="text" icon="el-icon-delete" @click="options.charts.splice(i,1)"/>
 | |
|         </div>
 | |
|         <config-item label="图表名">
 | |
|           <el-input size="small" v-model="chart.title"/>
 | |
|         </config-item>
 | |
|         <config-item label="图表模板">
 | |
|           <chart-picker v-model="chart.chart"/>
 | |
|         </config-item>
 | |
|         <datasource-picker v-model="chart.ds" :instance="instance" class="mar-b10"
 | |
|                            @input="chart={...chart,...chart.ds},$emit('change',options)"/>
 | |
|         <config-item label="数据维度" v-if="chart.dataType !== 'staticData'">
 | |
|           <code-editor v-model="chart.djson" lang="json" theme="github" width="100%" height="100"
 | |
|                        placeholder="参照echarts配置数据维度,为一个数组,数组的第一个值为维度值"
 | |
|                        @change="v=>chart.dimensions=JSON.parse(v)"/>
 | |
|         </config-item>
 | |
|       </ai-fold>
 | |
|       <el-button type="text" icon="el-icon-plus" @click="options.charts.push({title:'新图表'})">添加图表</el-button>
 | |
|     </template>
 | |
|     <template v-else-if="options.type=='monitorCarousel'">
 | |
|       <config-item label="监控列表">
 | |
|         <el-button type="text" icon="el-icon-plus" @click="options.list.push({})"/>
 | |
|       </config-item>
 | |
|       <el-table size="mini" :data="options.list" border :row-style="{backgroundColor:'transparent'}">
 | |
|         <el-table-column label="监控类型">
 | |
|           <template v-slot="{row}">
 | |
|             <ai-select size="mini" v-model="row.monitorType" :select-list="monitorTypes"/>
 | |
|           </template>
 | |
|         </el-table-column>
 | |
|         <el-table-column label="监控地址">
 | |
|           <template v-slot="{row}">
 | |
|             <el-input v-if="['hik','dahua'].includes(row.monitorType)" size="mini" v-model="row.src" clearable/>
 | |
|             <div v-else-if="['cmcc','slw'].includes(row.monitorType)">
 | |
|               <el-input size="mini" v-model="row.api" clearable placeholder="请输入监控列表接口"/>
 | |
|               <ai-select v-model="row.did" :instance="instance" @change="handleMonitor(row)" size="mini"
 | |
|                          :prop="{label:'name'}" :condition="e=>!!e.name&&!!e.id" class="mar-t8" :action="row.api"/>
 | |
|             </div>
 | |
|           </template>
 | |
|         </el-table-column>
 | |
|         <el-table-column width="60px" label="操作">
 | |
|           <template v-slot="{row,i}">
 | |
|             <el-button type="text" @click="$confirm('是否删除该监控?').then(()=>options.list.splice(i,1))">删除
 | |
|             </el-button>
 | |
|           </template>
 | |
|         </el-table-column>
 | |
|       </el-table>
 | |
|     </template>
 | |
|     <div class="layout-config__group" v-else-if="['hik','dahua'].includes(options.monitorType)">
 | |
|       <h2>基础设置</h2>
 | |
|       <config-item label="视频地址">
 | |
|         <el-input size="mini" v-model="options.src"/>
 | |
|       </config-item>
 | |
|     </div>
 | |
|     <div class="layout-config__group" v-else>
 | |
|       <h2>基础设置</h2>
 | |
|       <datasource-picker :options="options" :instance="instance" @input="$emit('change',options)"/>
 | |
|     </div>
 | |
|     <div class="layout-config__group" v-if="isTable">
 | |
|       <h2>表格设置</h2>
 | |
|       <code-editor v-model="json" theme="github" width="100%" height="440"
 | |
|                    placeholder="参照dvScrollBoard设置表格"
 | |
|                    @change="v=>options.tableConfig=JSON.parse(v)"/>
 | |
|     </div>
 | |
|     <div v-if="options.dataType!='staticData'&&options.type=='monitor'&&['cmcc','slw'].includes(options.monitorType)"
 | |
|          class="layout-config__group">
 | |
|       <h2>字段设置</h2>
 | |
|       <config-item label="监控视频">
 | |
|         <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>
 | |
|       </config-item>
 | |
|     </div>
 | |
|     <div v-if="options.dataType!='staticData'&& keys.length &&!['table','monitor','map','plot'].includes(options.type)"
 | |
|          class="layout-config__group">
 | |
|       <h2>字段设置</h2>
 | |
|       <config-item label="X轴设置">
 | |
|         <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>
 | |
|       </config-item>
 | |
|       <config-item label="Y轴设置">
 | |
|         <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>
 | |
|       </config-item>
 | |
|     </div>
 | |
|     <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>
 | |
|         <el-form-item label="标记点图标">
 | |
|           <el-input placeholder="用于地图上展示对标记点的显示图标" v-model="form.icon" 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';
 | |
| import AiDialogBtn from "dui/packages/layout/AiDialogBtn.vue";
 | |
| import AiFold from "dui/packages/layout/AiFold.vue";
 | |
| import ChartPicker from "./chartPicker.vue";
 | |
| import {DvCompData, monitorTypes} from "../config";
 | |
| import ConfigItem from "./configItem.vue";
 | |
| import DatasourcePicker from "./datasourcePicker.vue";
 | |
| import Template from "../../../../project/sass/apps/AppAskForm/components/Template.vue";
 | |
| import TableInputColumn from "../../../xbot/AppWorkOrderXbot/components/TableInputColumn.vue";
 | |
| import AiSelect from "dui/packages/basic/AiSelect.vue";
 | |
| 
 | |
| export default {
 | |
|   name: 'dataConfig',
 | |
|   model: {
 | |
|     prop: "options",
 | |
|     event: "change"
 | |
|   },
 | |
|   props: {
 | |
|     options: Object,
 | |
|     instance: Function,
 | |
|     dict: Object,
 | |
|   },
 | |
|   data() {
 | |
|     return {
 | |
|       dataTypes: Object.entries(DvCompData.types).map(e => ({id: e[0], label: e[1]})),
 | |
|       json: "",
 | |
|       keys: [],
 | |
|       monitorList: [],
 | |
|       list: [],
 | |
|       showMapEditor: false,
 | |
|       form: {},
 | |
|       datasource: {},
 | |
|       monitorTypes
 | |
|     }
 | |
|   },
 | |
|   computed: {
 | |
|     markers: v => v.options.staticData?.markers || [],
 | |
|     isTable: v => v.options.type == 'table',
 | |
|     isPlot: v => v.options.type == 'plot'
 | |
|   },
 | |
|   components: {
 | |
|     AiSelect,
 | |
|     TableInputColumn,
 | |
|     Template,
 | |
|     DatasourcePicker,
 | |
|     ConfigItem,
 | |
|     ChartPicker,
 | |
|     AiFold,
 | |
|     AiDialogBtn,
 | |
|     CodeEditor,
 | |
|   },
 | |
|   created() {
 | |
|     if (this.options.type == "map" && Array.isArray(this.options.staticData)) {//处理历史数据,并更新最新数据结构
 | |
|       const values = this.$copy(this.options)
 | |
|       values.staticData = {markers: this.$copy(this.options.staticData)}
 | |
|       this.$emit("change", values)
 | |
|     } else if (this.isTable) {
 | |
|       this.json = JSON.stringify(this.options.tableConfig)
 | |
|     } else if (this.options.type == "monitorCarousel") {
 | |
|       const {list = []} = this.options
 | |
|       this.$set(this.options, 'list', list)
 | |
|     } else if (this.isPlot) {
 | |
|       this.options.charts = this.options.charts.map(e => ({...e, ds: e}))
 | |
|     }
 | |
|   },
 | |
|   mounted() {
 | |
|     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: {
 | |
|     onMoniterId(e) {
 | |
|       this.instance.post(`/app/appzyvideoequipment/getWebSdkUrl?deviceId=${e}`).then(res => {
 | |
|         if (res.code == 0) {
 | |
|           this.options.src = JSON.parse(res.data).url
 | |
|         }
 | |
|       })
 | |
|     },
 | |
|     handleMonitor(row) {
 | |
|       this.instance.post(`/app/appzyvideoequipment/getWebSdkUrl?deviceId=${row.did}`).then(res => {
 | |
|         if (res.code == 0) {
 | |
|           this.$set(row, 'src', JSON.parse(res.data).url)
 | |
|         }
 | |
|       })
 | |
|     },
 | |
|     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
 | |
|       }
 | |
|     },
 | |
|     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.markers.splice(i, 1, this.form)
 | |
|         } else this.options.staticData.markers.push(this.form)
 | |
|         this.showMapEditor = false
 | |
|       })
 | |
|     },
 | |
|     removeMapMarker(i) {
 | |
|       this.$confirm("是否要删除该标记点").then(() => {
 | |
|         this.options.staticData.markers.splice(i, 1)
 | |
|       })
 | |
|     },
 | |
|     savePolylines() {
 | |
|       this.$set(this.options.staticData, 'polylines', JSON.parse(this.json))
 | |
|     },
 | |
|     handleMapPolylines() {
 | |
|       this.json = JSON.stringify(this.options.staticData.polylines || [{path: [[31.547706, 107.224325], [31.552456, 107.201185]]}])
 | |
|     },
 | |
|     handleMapPolylineDoc() {
 | |
|       window.open('https://lbs.amap.com/api/javascript-api-v2/documentation#polyline')
 | |
|     }
 | |
|   }
 | |
| }
 | |
| </script>
 | |
| 
 | |
| <style lang="scss">
 | |
| .el-dialog__body {
 | |
|   .jsoneditor-vue {
 | |
|     height: 480px;
 | |
| 
 | |
|     .jsoneditor-poweredBy {
 | |
|       display: none;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| .ai-dialog__wrapper {
 | |
|   color: #333;
 | |
| }
 | |
| 
 | |
| .layout-config__group--wrapper {
 | |
| 
 | |
|   :deep(.layout-config__group) {
 | |
|     padding: 10px 10px 20px;
 | |
|     border-bottom: 1px solid #000000;
 | |
| 
 | |
|     &:last-child {
 | |
|       border: none;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     & > h2 {
 | |
|       margin-bottom: 20px;
 | |
|       color: #FFFFFF;
 | |
|       font-size: 15px;
 | |
|       font-weight: 700;
 | |
|     }
 | |
| 
 | |
|     .layoutTitle {
 | |
|       color: #FFFFFF;
 | |
|       font-size: 15px;
 | |
|       font-weight: 700;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   :deep(.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;
 | |
|     }
 | |
| 
 | |
|     .el-select .el-tag {
 | |
|       color: #fff;
 | |
|       background: transparent;
 | |
|     }
 | |
| 
 | |
|     .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;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     :deep(.el-collapse) {
 | |
|       height: 18px;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   .el-icon-delete {
 | |
|     color: #f46;
 | |
|   }
 | |
| 
 | |
|   .el-button--text + .el-button--text {
 | |
|     margin-left: 0;
 | |
|   }
 | |
| 
 | |
|   input {
 | |
|     background: #262C33;
 | |
|     font-size: 12px;
 | |
|     color: #fff;
 | |
|     border: 1px solid #030411;
 | |
|   }
 | |
| 
 | |
|   .layout-config__item--right {
 | |
|     display: flex;
 | |
|     align-items: center;
 | |
|     justify-content: flex-end;
 | |
|     text-align: right;
 | |
|     margin-left: 30px;
 | |
|   }
 | |
| 
 | |
|   .el-table {
 | |
|     background-color: transparent;
 | |
| 
 | |
|     tr {
 | |
|       background-color: transparent;
 | |
|     }
 | |
| 
 | |
|     .el-table__cell {
 | |
|       color: white;
 | |
|       background-color: #1D2127 !important;
 | |
| 
 | |
|       input:disabled {
 | |
|         background-color: transparent;
 | |
|         border-color: transparent;
 | |
|         color: white;
 | |
|         padding: 0;
 | |
|       }
 | |
| 
 | |
|       &:last-of-type {
 | |
|         border-left: 1px solid #fff;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| </style>
 |