widget.vue 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143
  1. <template>
  2. <div class="testResultDiagram i-scrollbar" :data="'这个是data'">
  3. <!-- 检测成果专题图 -->
  4. <p class="title">查询设置</p>
  5. <el-form ref="form" :model="form" label-width="100px" :rules="rules">
  6. <el-form-item label="工程名称:" prop="name">
  7. <el-select @change="projectChange" v-model="form.project" clearable>
  8. <el-option
  9. v-for="(item, index) in projectOpt"
  10. :key="index"
  11. :label="item.label"
  12. :value="item.value"
  13. ></el-option>
  14. </el-select>
  15. </el-form-item>
  16. <el-form-item label="检测报告:" prop="rpt">
  17. <el-select :disabled="!form.project" v-model="form.report" placeholder="请选择检测报告" multiple clearable>
  18. <el-option
  19. v-for="(item, index) in reportOpt"
  20. :key="index"
  21. :label="item.label"
  22. :value="item.value"
  23. ></el-option>
  24. </el-select>
  25. </el-form-item>
  26. <el-form-item label="检测日期:">
  27. <el-row style="margin-bottom: 15px">
  28. <el-date-picker
  29. type="date"
  30. placeholder="开始日期"
  31. v-model="form.startDate"
  32. :picker-options="sOpition"
  33. style="width: 100%"
  34. @change="sDateChange"
  35. ></el-date-picker>
  36. </el-row>
  37. <el-row>
  38. <el-date-picker
  39. type="date"
  40. placeholder="结束日期"
  41. v-model="form.endDate"
  42. :picker-options="eOpition"
  43. style="width: 100%"
  44. @change="eDateChange"
  45. ></el-date-picker>
  46. </el-row>
  47. </el-form-item>
  48. </el-form>
  49. <div class="see-btn">
  50. <el-button type="primary" @click="showLayer">查看<i :class="loading ? 'el-icon-loading' : ''"></i></el-button>
  51. </div>
  52. <p class="title">专题图列表</p>
  53. <div v-for="(item, index) in defectLegend" :key="index" class="thematicMap-list">
  54. <div>
  55. <div class="thematicMap-title">
  56. <i
  57. style="cursor: pointer"
  58. @click="changeArrow(index)"
  59. :class="{ 'el-icon-caret-bottom': showThemBox[index], 'el-icon-caret-right': !showThemBox[index] }"
  60. ></i>
  61. <el-checkbox
  62. @change="setThemLayerVisible(index, item.open)"
  63. v-model="item.open"
  64. :label="item.title"
  65. ></el-checkbox>
  66. </div>
  67. <transition>
  68. <div v-if="item.type === 'gradient' && showThemBox[index]" class="transition-box">
  69. <div class="line-color"></div>
  70. <div class="text-mix-max">
  71. <span>{{ item.start }}</span>
  72. <span>{{ item.end }}</span>
  73. </div>
  74. </div>
  75. <div v-else-if="showThemBox[index]" class="transition-box">
  76. <ul>
  77. <li
  78. @click="openBox(item.layerName, i)"
  79. v-for="(level, i) in item.level"
  80. :key="i"
  81. :class="comStyle(item.type, level.color)"
  82. >
  83. {{ level.label + ' / ' + level.num + level.unit
  84. }}<i :class="level.num || hasLoad ? '' : 'el-icon-loading'"></i>
  85. </li>
  86. </ul>
  87. </div>
  88. </transition>
  89. </div>
  90. </div>
  91. </div>
  92. </template>
  93. <script>
  94. import {
  95. queryDefectdetails,
  96. histroyPipeData,
  97. getDefectData,
  98. getProject,
  99. getReportByProjecetId,
  100. getDefectDataByFilter
  101. } from '@/views/pipelineDefect/api/pipelineDefect'
  102. import { baseAddress } from '@/utils/request';
  103. import checkDetails from '../../components/checkDetails.vue'
  104. import { projUtil } from '@/views/pipelineDefect/common/proj'
  105. import { appconfig } from 'staticPub/config';
  106. import { Point, LineString, Polygon } from 'ol/geom'
  107. import Feature from 'ol/Feature'
  108. import { Style } from 'ol/style'
  109. import Icon from 'ol/style/Icon'
  110. import { comSymbol } from '@/utils/comSymbol'
  111. import defectImg1 from '@/assets/images/traingle1.png'
  112. import defectImg2 from '@/assets/images/traingle2.png'
  113. import defectImg3 from '@/assets/images/traingle3.png'
  114. import defectImg4 from '@/assets/images/traingle4.png'
  115. import defectImg0 from '@/assets/images/traingle0.png'
  116. import GraphicUtil from '@/views/pipelineDefect/common/graphic';
  117. import HandleManage from '@/views/pipelineDefect/common/cesiumEvent';
  118. import CesiumUtil from '@/views/pipelineDefect/common/cesiumUtil';
  119. export default {
  120. components: { checkDetails },
  121. props: { data: Object },
  122. data() {
  123. return {
  124. rules: {
  125. name: [
  126. { required: true, message: '不能为空', trigger: 'blur' },
  127. { max: 100, message: '内容不能超过100个字符串', trigger: 'change' }
  128. ],
  129. rpt: [
  130. { required: true, message: '不能为空', trigger: 'blur' },
  131. ]
  132. },
  133. form: {
  134. project: '',
  135. report: '',
  136. startDate: '',
  137. endDate: ''
  138. },
  139. // 报告数据
  140. reportOpt: [],
  141. // 工程数据
  142. projectOpt: [],
  143. defectLegend: [
  144. {
  145. title: '管道缺陷分布图',
  146. layerName: 'pipeDefectLayer',
  147. open: true,
  148. type: 'img',
  149. level: [
  150. { color: '1', label: '一级', num: 0, unit: '个' },
  151. { color: '2', label: '二级', num: 0, unit: '个' },
  152. { color: '3', label: '三级', num: 0, unit: '个' },
  153. { color: '4', label: '四级', num: 0, unit: '个' },
  154. // { color: '0', label: '正常', num: 0, unit: '个' }
  155. ]
  156. },
  157. {
  158. title: '管道结构性缺陷等级分布图',
  159. layerName: 'pipeStrucLayer',
  160. open: true,
  161. type: 'line',
  162. level: [
  163. { color: 'green', label: 'Ⅰ级', num: 0, unit: '条' },
  164. { color: 'blue', label: 'Ⅱ级', num: 0, unit: '条' },
  165. { color: 'pink', label: 'Ⅲ级', num: 0, unit: '条' },
  166. { color: 'red', label: 'Ⅳ级', num: 0, unit: '条' },
  167. { color: 'un', label: '正常', num: 0, unit: '条' }
  168. ]
  169. },
  170. {
  171. title: '管道功能性缺陷等级分布图',
  172. layerName: 'pipeFuncLayer',
  173. open: true,
  174. type: 'line',
  175. level: [
  176. { color: 'green', label: 'Ⅰ级', num: 0, unit: '条' },
  177. { color: 'blue', label: 'Ⅱ级', num: 0, unit: '条' },
  178. { color: 'pink', label: 'Ⅲ级', num: 0, unit: '条' },
  179. { color: 'red', label: 'Ⅳ级', num: 0, unit: '条' },
  180. { color: 'un', label: '正常', num: 0, unit: '条' }
  181. ]
  182. }
  183. ],
  184. showThemBox: [true, true, true, true],
  185. currentDataProjName: appconfig.currPRJ,
  186. //
  187. projUtil: null,
  188. loading: false,
  189. currentInfoCard: false,
  190. DetailsForm: {},
  191. popup: null,
  192. activeName: 'picnum',
  193. currentInfoCard2: false,
  194. // 时间过滤
  195. sOpition: {
  196. disabledDate: (time) => {
  197. time = time.getTime()
  198. if (this.form.endDate) {
  199. return time > new Date(this.form.endDate).getTime()
  200. }
  201. return time > new Date().getTime()
  202. }
  203. },
  204. eOpition: {
  205. disabledDate: (time) => {
  206. time = time.getTime()
  207. if (this.form.startDate) {
  208. return time < new Date(this.form.startDate).getTime() || time > new Date().getTime()
  209. }
  210. return time > new Date().getTime()
  211. }
  212. },
  213. //
  214. dialogFormVisible: false,
  215. pipeId: 0,
  216. hasLoad: false,
  217. //
  218. currentForm: [], // 缩略提示框
  219. currentIndex: 0,
  220. imgArrIndex: 0, // 缩略框照片索引
  221. themLayerName: 'pipeAndDefectLayer',
  222. //
  223. graphicUtil: null,
  224. propertyName: 'bsdata', // 添加到地图实体里的数据名
  225. geometryType: 'geometryType', // 类型区分
  226. dSName: 'pipeDefectLayer',
  227. fSName: 'pipeFuncLayer',
  228. sSName: 'pipeStrucLayer',
  229. clkHanderIndex: 0,
  230. }
  231. },
  232. mounted() {
  233. this.init()
  234. console.log('加载检测成果专题图')
  235. },
  236. destroyed() {
  237. this.clearAll()
  238. },
  239. computed: {
  240. // 获取照片数组路径
  241. getImgUrlArrEV() {
  242. let arr = this.getCurrentForm.pipeDefects.map((v) => {
  243. return baseAddress + '/psjc/file' + v.picPath
  244. })
  245. return arr
  246. },
  247. // 获取文件url
  248. getImgUrlEV() {
  249. let address = baseAddress + '/psjc/file' + this.getCurrentForm.pipeDefects[this.imgArrIndex].picPath
  250. console.log('address', address)
  251. return address
  252. },
  253. getVideoUrlEV() {
  254. console.log('照片', this.getCurrentForm.pipeDefects.length)
  255. let address = baseAddress + '/psjc/file' + this.getCurrentForm.videoPath
  256. console.log('address', address)
  257. return address
  258. },
  259. // 提示框当前信息
  260. getCurrentForm() {
  261. return this.currentForm ? this.currentForm[this.currentIndex] : {}
  262. },
  263. getVideoUrl() {
  264. let address = baseAddress + '/psjc/file' + this.DetailsForm.videopath
  265. console.log('address', address)
  266. return address
  267. },
  268. getImgUrl() {
  269. let address = baseAddress + '/psjc/file' + this.DetailsForm.picPath
  270. console.log('address', address)
  271. return address
  272. },
  273. // 获取文件url
  274. getImgUrlEV() {
  275. let address = baseAddress + '/psjc/file' + this.getCurrentForm.pipeDefects[this.imgArrIndex].picPath
  276. console.log('address', address)
  277. return address
  278. },
  279. getVideoUrlEV() {
  280. console.log('照片', this.getCurrentForm.pipeDefects.length)
  281. let address = baseAddress + '/psjc/file' + this.getCurrentForm.videoPath
  282. console.log('address', address)
  283. return address
  284. },
  285. },
  286. watch: {
  287. '$store.state.app.activeSideItem': function(n, o) {
  288. if (n === '检测成果专题图') this.init()
  289. else this.clearAll()
  290. },
  291. 'form.report': function (n, o) {
  292. if (n.length > 1) {
  293. if (n.some(i => isNaN(i))) {
  294. this.form.report = n.filter(i => !isNaN(i))
  295. }
  296. }
  297. },
  298. },
  299. methods: {
  300. sDateChange (t) {
  301. if (!this.form.endDate) {
  302. console.log('时间变化')
  303. this.$nextTick(() => {
  304. this.form.endDate = this.form.startDate
  305. })
  306. }
  307. },
  308. eDateChange (t) {
  309. if (!this.form.startDate) {
  310. this.$nextTick(() => {
  311. this.form.startDate = this.form.endDate
  312. })
  313. }
  314. },
  315. init () {
  316. this.viewer = window.viewer
  317. this.projUtil = new projUtil()
  318. this.projUtil.resgis(this.currentDataProjName)
  319. this.cesiumUitl = new CesiumUtil(this.viewer)
  320. this.graphicUtil = new GraphicUtil()
  321. this.handleManage = new HandleManage(this.viewer)
  322. this.setdefectVisible()
  323. this.setEvent()
  324. let dataSources = this.viewer.dataSources
  325. this.defectSource = new Cesium.CustomDataSource(this.dSName)
  326. dataSources.add(this.defectSource)
  327. this.fpipeSource = new Cesium.CustomDataSource(this.fSName)
  328. dataSources.add(this.fpipeSource)
  329. this.spipeSource = new Cesium.CustomDataSource(this.sSName)
  330. dataSources.add(this.spipeSource)
  331. this.lightPrimitiveCollection = new Cesium.PrimitiveCollection()
  332. this.lightPrimitiveCollection.destroyPrimitives = false
  333. this.viewer.scene.primitives.add(this.lightPrimitiveCollection)
  334. // 添加缺陷数据
  335. this.setProjectData()
  336. },
  337. clearAll() {
  338. this.viewer.dataSources.remove(this.defectSource)
  339. this.viewer.dataSources.remove(this.fpipeSource)
  340. this.viewer.dataSources.remove(this.spipeSource)
  341. this.handleManage.remove(this.clkHanderIndex)
  342. this.removeListener && this.removeListener()
  343. this.lightPrimitiveCollection.removeAll()
  344. },
  345. setEvent () {
  346. this.clkHanderIndex = this.handleManage.create('lclick', evt => {
  347. let { car3, position, pick, rayPoint } = evt
  348. let data = null, type = ''
  349. this.data.that.$refs.popupwindow.removePopupWindow()
  350. if (pick && pick.id) {
  351. data = pick.id[this.propertyName]
  352. type = data[this.geometryType]
  353. this.data.that.$refs.popupwindow.showPopupWindow(rayPoint, pick.id[this.propertyName], type)
  354. }
  355. this.removeLightFeas()
  356. // 高亮
  357. let fieldText = this.lightFeaText
  358. if (type === 'line') {
  359. this.lightGraphic = this.getPrimity('line', data.lineCar3, { color: this.lightStyle.line, width: 12 }, { [this.lightLayerName]: fieldText })
  360. this.lightPrimitiveCollection.add(this.lightGraphic)
  361. }
  362. })
  363. this.removeListener = this.viewer.camera.changed.addEventListener(evt => {
  364. this.data.that.$refs.popupwindow.movePosition()
  365. })
  366. },
  367. setdefectVisible () {
  368. let viewer = window.viewer
  369. let sources = viewer.dataSources
  370. let pS = this.getDataSource('pipeline')
  371. let dS = this.getDataSource('defect')
  372. if (pS && dS) {
  373. let entities = [...pS.entities.values, ...dS.entities.values]
  374. entities.forEach(e => { e.show = false })
  375. }
  376. },
  377. setProjectData() {
  378. getProject({ current: 1, size: 1e4 }).then((res) => {
  379. if (res.code === 1) {
  380. // label, value
  381. this.projectOpt = res.result.records.map((record) => {
  382. return { label: record.prjName, value: record.prjNo }
  383. })
  384. if (this.projectOpt.length > 0) {
  385. this.form.project = this.projectOpt[0].label
  386. let prjNo = this.projectOpt[0].value
  387. getReportByProjecetId({ prjNo, state: 1 }).then(res => {
  388. if (res.code === 1) {
  389. let data = res.result
  390. this.reportOpt = data.map(d => {
  391. return { label: d.wordInfoName, value: d.id }
  392. })
  393. if (this.reportOpt.length !== 0) {
  394. this.form.report = [this.reportOpt[0].label]
  395. this.showLayer(this.projectOpt[0].value, this.reportOpt[0].value)
  396. } else {
  397. this.loading = false
  398. this.hasLoad = true
  399. }
  400. } else this.$message.error('获取报告失败!')
  401. })
  402. }
  403. // 默认选择第一项
  404. // if (this.projectOpt.length !== 0) {
  405. // this.$set(this.form, 'project', this.projectOpt[0].label)
  406. // this.projectChange(this.projectOpt[0].value)
  407. // }
  408. } else this.$message.error('获取工程项目失败!')
  409. })
  410. },
  411. removeLightFeas () {
  412. let primitives = this.lightPrimitiveCollection
  413. let l = primitives.length
  414. for(let i = 0; i < l; i++) {
  415. let p = primitives.get(i)
  416. primitives.remove(p)
  417. }
  418. },
  419. // 项目变化
  420. projectChange(prjNo) {
  421. prjNo = prjNo || this.form.project
  422. getReportByProjecetId({ prjNo, state: 1 }).then((res) => {
  423. if (res.code === 1) {
  424. this.form.report = ''
  425. let data = res.result
  426. this.reportOpt = data.map((d) => {
  427. return { label: d.wordInfoName, value: d.id }
  428. })
  429. } else this.$message.error('获取报告失败!')
  430. })
  431. },
  432. openBox(layerName, level) {
  433. if (!this.hasLoad) return
  434. let typeIndex = ['pipeDefectLayer', 'pipeFuncLayer', 'pipeStrucLayer'].indexOf(layerName)
  435. let filter = [
  436. { key: 'defectLevel', value: [['一', '1'], ['二', '2'], ['三', '3'], ['四', '4'], null] },
  437. { key: 'funcClass', value: ['Ⅰ', 'Ⅱ', 'Ⅲ', 'Ⅳ', null] },
  438. { key: 'structClass', value: ['Ⅰ', 'Ⅱ', 'Ⅲ', 'Ⅳ', null] }
  439. ][typeIndex]
  440. let lv = filter.value[level] ? `${filter.value[level][0]}级` : '正常'
  441. this.openDefect(filter.key, lv, layerName)
  442. },
  443. initMap(data) {
  444. // 管网缺陷
  445. let { strucDefectFeatures, funcDefectFeatures, pipeDefectFeatures } = this.getReportFeatures(data)
  446. if ([...strucDefectFeatures, ...funcDefectFeatures, ...pipeDefectFeatures].length !== 0) {
  447. strucDefectFeatures.forEach(e => this.spipeSource.entities.add(e))
  448. funcDefectFeatures.forEach(e => this.fpipeSource.entities.add(e))
  449. pipeDefectFeatures.forEach(e => this.defectSource.entities.add(e))
  450. this.cesiumUitl.flyTo(strucDefectFeatures[0])
  451. }
  452. },
  453. lastImg() {
  454. if (this.imgArrIndex <= 0) {
  455. this.imgArrIndex = 0
  456. return
  457. }
  458. this.imgArrIndex--
  459. },
  460. // 下一张照片
  461. nextImg() {
  462. if (this.imgArrIndex + 1 >= this.getCurrentForm.pipeDefects.length) {
  463. this.imgArrIndex = this.getCurrentForm.pipeDefects.length - 1
  464. return
  465. }
  466. this.imgArrIndex++
  467. },
  468. // 上一页
  469. lastPage() {
  470. if (this.currentIndex <= 0) {
  471. this.currentIndex = 0
  472. return
  473. }
  474. this.currentIndex--
  475. },
  476. // 下一页
  477. nextPage() {
  478. if (this.currentIndex + 1 >= this.currentForm.length) {
  479. this.currentIndex = this.currentForm.length - 1
  480. return
  481. }
  482. this.currentIndex++
  483. },
  484. /**
  485. * 构造管道缺陷地图要素
  486. * @param reportInfos 报告数据
  487. * */
  488. getReportFeatures (defectInfos) {
  489. const colors = [
  490. { level: 'Ⅰ', color: 'green', index: 0 },
  491. { level: 'Ⅱ', color: 'blue', index: 1 },
  492. { level: 'Ⅲ', color: 'pink', index: 2 },
  493. { level: 'Ⅳ', color: 'red', index: 3 }
  494. ], defaultColor = '#070358'
  495. let style = null, features = { pipeDefectFeatures: [], funcDefectFeatures: [], strucDefectFeatures: [], normal: [] }
  496. if (defectInfos.length === 0) { return features }
  497. let funcNum = [0, 0, 0, 0, 0]
  498. let strucNum = [0, 0, 0, 0, 0]
  499. let defectNum = [0, 0, 0, 0, 0]
  500. defectInfos.forEach(defect => {
  501. let { startPointXLocation, startPointYLocation, endPointXLocation, endPointYLocation } = defect
  502. if (startPointXLocation && startPointYLocation && endPointXLocation && endPointYLocation) {
  503. let startPoint = this.projUtil.transform([Number(startPointXLocation), Number(startPointYLocation)], this.currentDataProjName, 'proj84')
  504. let endPoint = this.projUtil.transform([Number(endPointXLocation), Number(endPointYLocation)], this.currentDataProjName, 'proj84')
  505. let lineCar3 = CesiumUtil.degreesArray2Car3([startPoint, endPoint].flat())
  506. // 健康等级颜色
  507. let findFuncColor = colors.find(colorObj => defect['funcClass'] && defect['funcClass'].includes(colorObj.level))
  508. let findStrucColor = colors.find(colorObj => defect['structClass'] && defect['structClass'].includes(colorObj.level))
  509. // 功能性缺陷
  510. if (!isExit(defect.expNo, 'funcDefectFeatures')) {
  511. let fcolor = findFuncColor ? findFuncColor.color : defaultColor
  512. let fFea = this.getEntity('line', lineCar3, { color: fcolor }, { ...defect, lineCar3 })
  513. fFea && features.funcDefectFeatures.push(fFea)
  514. let findex = findFuncColor ? findFuncColor.index : 4
  515. funcNum[findex] += 1
  516. }
  517. // 结构性缺陷
  518. if (!isExit(defect.expNo, 'strucDefectFeatures')) {
  519. let scolor = findStrucColor ? findStrucColor.color : defaultColor
  520. let sFea = this.getEntity('line', lineCar3, { color: scolor }, { ...defect, lineCar3 })
  521. sFea && features.strucDefectFeatures.push(sFea)
  522. let sindex = findStrucColor ? findStrucColor.index : 4
  523. strucNum[sindex] += 1
  524. }
  525. // 缺陷点
  526. if (defect.geometry) {
  527. let { x, y } = JSON.parse(defect.geometry)
  528. let [lon, lat] = this.projUtil.transform([x, y], this.currentDataProjName, 'proj84')
  529. let pointCar3 = CesiumUtil.degrees2Car3(lon, lat, 0)
  530. let imgs = [
  531. { level: ['一级', '1'], img: defectImg1, index: 0 },
  532. { level: ['二级', '2'], img: defectImg2, index: 1 },
  533. { level: ['三级', '3'], img: defectImg3, index: 2 },
  534. { level: ['四级', '4'], img: defectImg4, index: 3 }
  535. ]
  536. let findimg = null
  537. if (defect.defectLevel) {
  538. findimg = imgs.find((colorObj) => colorObj.level.includes(defect['defectLevel']))
  539. }
  540. if (findimg) {
  541. defectNum[findimg.index] += 1
  542. let dFea = this.getEntity('img', pointCar3, { img: findimg.img }, { ...defect, pointCar3 })
  543. features.pipeDefectFeatures.push(dFea)
  544. }
  545. }
  546. }
  547. })
  548. // 把数量填充到图例
  549. this.defectLegend[1].level.forEach((l, index) => {
  550. l.num = strucNum[index]
  551. })
  552. this.defectLegend[2].level.forEach((l, index) => {
  553. l.num = funcNum[index]
  554. })
  555. this.defectLegend[0].level.forEach((l, index) => {
  556. l.num = defectNum[index]
  557. })
  558. return features
  559. function isExit(pipeId, feasType) {
  560. return features[feasType].some(fea => fea['bsdata'].expNo === pipeId)
  561. }
  562. },
  563. getEntity (type, positions, style, data) {
  564. data[this.geometryType] = type
  565. let entity = this.graphicUtil.getEntity(type, positions, style)
  566. entity[this.propertyName] = data
  567. return entity
  568. },
  569. getPrimity (type, positions, style, data = {}) {
  570. data[this.geometryType] = 'line'
  571. let primitive = this.graphicUtil.getPrimity(type, positions, style, {[this.propertyName]: data})
  572. return primitive
  573. },
  574. randomPoint(center, range, num) {
  575. return new Array(num).fill(center).map(([centerX, centerY]) => {
  576. let x = Math.random() * range
  577. let y = Math.random() * range
  578. return [centerX + x, centerY + y]
  579. })
  580. },
  581. showLayer(projectId, reportId) {
  582. if (!this.form.project) return this.$message.warning('请先填写工程名称')
  583. if (!reportId && this.form.report.length === 0) return this.$message.warning('请先选择报告')
  584. this.loading = true
  585. let ids = '', prjNo = ''
  586. if (reportId) {
  587. ids = reportId
  588. prjNo = projectId
  589. } else {
  590. if (this.form.report) {
  591. ids = this.reportOpt.filter(proj => this.form.report.some(rep => proj.value === rep || proj.label === rep)).map(proj => proj.value).join(',')
  592. }
  593. prjNo = this.projectOpt.find(proj => proj.value === this.form.project || proj.label === this.form.project).value
  594. }
  595. let params = {
  596. prjNo,
  597. ids,
  598. jcStartDate: this.form.startDate ? this.form.startDate.toLocaleDateString().replace(/\//g, '-') : '',
  599. jcEndDate: this.form.endDate ? this.form.endDate.toLocaleDateString().replace(/\//g, '-') : ''
  600. }
  601. getDefectDataByFilter(params).then(res => {
  602. this.loading = false
  603. this.hasLoad = true
  604. if (res.code === 1) {
  605. let data = res.result
  606. if (data.length !== 0) {
  607. this.initMap(data)
  608. } else this.$message.info('无管线缺陷数据')
  609. } else this.$message.error('请求缺陷数据出错')
  610. })
  611. },
  612. getDataSource (name) {
  613. return this.viewer.dataSources.getByName(name)[0]
  614. },
  615. setThemLayerVisible(index, visible) {
  616. let legendParams = this.defectLegend[index]
  617. let source = this.getDataSource(legendParams.layerName)
  618. let entities = source.entities.values
  619. entities.forEach(e => { e.show = visible })
  620. this.lightPrimitiveCollection.removeAll()
  621. },
  622. changeArrow(index) {
  623. this.$set(this.showThemBox, index, !this.showThemBox[index])
  624. },
  625. comStyle(type, color) {
  626. if (type === 'img') return `type-${type}-${color}`
  627. return `item-${color} type-${type}`
  628. },
  629. // 管道缺陷管理的信息
  630. openDefect(type, level, layerName, data = []) {
  631. let doc = {
  632. structClass: `管道结构性缺陷`,
  633. funcClass: '管道功能性缺陷',
  634. defectLevel: '管道缺陷'
  635. }
  636. let com = type === 'defectLevel' ? 'testPipelineDefect' : 'testPipelineEvaluation'
  637. this.$store.dispatch('map/handelClose', { box: 'HalfPanel', pathId: com })
  638. let info = {
  639. id: com,
  640. label: `${doc[type]} (${level})`,
  641. meta: {
  642. title: doc[type] + level
  643. },
  644. name: com,
  645. noShowingChildren: true,
  646. parentPathid: '/' + com,
  647. path: '',
  648. type: 'gis',
  649. widgetid: 'HalfPanel',
  650. param: { type, level, data, layerName, rootPage: this }
  651. }
  652. // 这是map里的跳转方法
  653. this.$nextTick(() => {
  654. this.$store.dispatch('map/changeMethod', info)
  655. })
  656. this.openPromptBox('109YS322~109YS327', '')
  657. },
  658. // 打开弹窗
  659. openPromptBox (id, type) {
  660. this.data.that.$refs.popupwindow.removePopupWindow()
  661. this.removeLightFeas()
  662. let idText = ['id', 'expNo'][type],
  663. height = [150, 500, 6000],
  664. center,
  665. findFeas = []
  666. if (type) {
  667. let pEntities = this.getDataSource(this.sSName).entities.values
  668. findFeas = pEntities.filter(e => e[this.propertyName][idText] === id).map(i => i[this.propertyName])
  669. let features = this.getLightFeatures(findFeas)
  670. center = this.cesiumUitl.getCenterFormFeas(features.map(f => f.geometryInstances.id[this.propertyName].coors))
  671. features.forEach(f => this.lightPrimitiveCollection.add(f))
  672. } else {
  673. let dEntities = this.getSource(this.dSName).entities.values
  674. findFeas = dEntities.filter(e => e[this.propertyName][idText] === id).map(i => i[this.propertyName])
  675. let { x, y } = JSON.parse(findFeas[0]['geometry'])
  676. let [lon, lat] = this.projUtil.transform([x, y], this.currentDataProjName, 'proj84')
  677. center = [lon, lat]
  678. }
  679. if (center) {
  680. this.cesiumUitl.setView(CesiumUtil.degrees2Car3(center[0], center[1], height[type]), () => {
  681. let car3 = CesiumUtil.degrees2Car3(center[0], center[1], 0)
  682. let winPos = this.cesiumUitl.car32WindowPosition(car3)
  683. let geotype = type ? 'line' : 'point'
  684. let rayPoint = this.viewer.scene.globe.pick(this.viewer.scene.camera.getPickRay(winPos), this.viewer.scene);
  685. this.data.that.$refs.popupwindow.showPopupWindow(rayPoint, findFeas[0], geotype)
  686. })
  687. } else {
  688. this.$message.error('该点无位置信息');
  689. }
  690. },
  691. // 获取高亮的要素
  692. getLightFeatures(data) {
  693. let that = this
  694. let features = [], lightColor = 'rgba(0, 255, 255, 0.6)'
  695. data.forEach(defect => {
  696. let { endPointXLocation, endPointYLocation, startPointXLocation, startPointYLocation } = defect
  697. if (startPointXLocation && startPointYLocation && endPointXLocation && endPointYLocation) {
  698. let startPoint = this.projUtil.transform([Number(startPointXLocation), Number(startPointYLocation)], this.currentDataProjName, 'proj84')
  699. let endPoint = this.projUtil.transform([Number(endPointXLocation), Number(endPointYLocation)], this.currentDataProjName, 'proj84')
  700. let lineCar3 = CesiumUtil.degreesArray2Car3([startPoint, endPoint].flat())
  701. let fea = this.getPrimity('line', lineCar3, { color: lightColor, width: 7 }, { ...defect, coors: [startPoint, endPoint]})
  702. if (!isExist(defect.expNo)) {
  703. features.push(fea)
  704. }
  705. }
  706. })
  707. return features
  708. function isExist (expNo) {
  709. return features.some(f => f.geometryInstances.id[that.propertyName].expNo === expNo)
  710. }
  711. },
  712. lightFea (feaid, layerName) {
  713. let field = layerName === "pipeDefectLayer" ? "id" : 'expNo'
  714. let feas = this[layerName].getSource().getFeatures()
  715. let fea = feas.find(fea => fea.get(field) === feaid)
  716. if (fea) {
  717. let geometry = fea.getGeometry().clone()
  718. this.lightLayer.getSource().clear()
  719. this.lightLayer.getSource().addFeature(new Feature({ geometry }))
  720. let center = mapUtil.getCenter(fea)
  721. return center
  722. } else {
  723. this.$message.warning('该点无位置信息')
  724. }
  725. },
  726. openDetails() {
  727. console.log('打开详情', this.DetailsForm)
  728. // 管道缺陷传stateId
  729. // 评估传id
  730. this.pipeId = this.DetailsForm.stateId
  731. this.dialogFormVisible = true
  732. },
  733. openDetailsDialog(id) {
  734. this.pipeId = id
  735. console.log('打开检测详情', this.DetailsId)
  736. this.dialogFormVisible = true
  737. },
  738. // 详情关闭
  739. dialogClose(bool) {
  740. this.dialogFormVisible = bool
  741. }
  742. }
  743. }
  744. </script>
  745. <style lang="scss" scoped>
  746. @import '~@/styles/mixin.scss';
  747. .i-scrollbar {
  748. overflow: auto;
  749. @include scrollBar;
  750. }
  751. .testResultDiagram {
  752. padding: 0 12px !important;
  753. overflow-y: scroll;
  754. font-size: 14px;
  755. font-family: Arial, Helvetica, sans-serif;
  756. .see-btn {
  757. display: flex;
  758. flex-direction: row-reverse;
  759. }
  760. ul,
  761. li {
  762. padding: 0;
  763. margin: 0;
  764. list-style: none;
  765. font-size: 14px;
  766. font-family: Arial, Helvetica, sans-serif;
  767. }
  768. }
  769. .title {
  770. padding-left: 16px;
  771. margin: 15px 0;
  772. }
  773. .title::before {
  774. position: relative;
  775. left: -10px;
  776. top: 2px;
  777. content: '';
  778. width: 5px;
  779. height: 18px;
  780. display: inline-block;
  781. background-color: #2d74e7;
  782. }
  783. .thematicMap-list {
  784. display: flex;
  785. flex-direction: column;
  786. .transition-box {
  787. padding: 6px 0 6px 44px;
  788. box-sizing: border-box;
  789. }
  790. }
  791. .line-color {
  792. width: 140px;
  793. height: 10px;
  794. border: 1px solid #666;
  795. background: linear-gradient(to right, #3ce10f, #ff0602); /* 标准的语法 */
  796. }
  797. .text-mix-max {
  798. width: 140px;
  799. display: flex;
  800. padding: 8px 0;
  801. box-sizing: border-box;
  802. justify-content: space-between;
  803. }
  804. .type-img-3 {
  805. cursor: pointer;
  806. margin: 10px 0 10px 20px !important;
  807. &::before {
  808. position: relative;
  809. left: -20px;
  810. top: -2px;
  811. content: '';
  812. width: 10px;
  813. height: 10px;
  814. background-image: url('../../../../assets/images/traingle3.png');
  815. background-size: 100% 100%;
  816. display: inline-block;
  817. }
  818. }
  819. .type-img-2 {
  820. cursor: pointer;
  821. margin: 10px 0 10px 20px !important;
  822. &::before {
  823. position: relative;
  824. left: -20px;
  825. top: -2px;
  826. content: '';
  827. width: 10px;
  828. height: 10px;
  829. background-image: url('../../../../assets/images/traingle2.png');
  830. background-size: 100% 100%;
  831. display: inline-block;
  832. }
  833. }
  834. .type-img-1 {
  835. cursor: pointer;
  836. margin: 10px 0 10px 20px !important;
  837. &::before {
  838. position: relative;
  839. left: -20px;
  840. top: -2px;
  841. content: '';
  842. width: 10px;
  843. height: 10px;
  844. background-image: url('../../../../assets/images/traingle1.png');
  845. background-size: 100% 100%;
  846. display: inline-block;
  847. }
  848. }
  849. .type-img-4 {
  850. cursor: pointer;
  851. margin: 10px 0 10px 20px !important;
  852. &::before {
  853. position: relative;
  854. left: -20px;
  855. top: -2px;
  856. content: '';
  857. width: 10px;
  858. height: 10px;
  859. background-image: url('../../../../assets/images/traingle4.png');
  860. background-size: 100% 100%;
  861. display: inline-block;
  862. }
  863. }
  864. .type-img-0 {
  865. cursor: pointer;
  866. margin: 10px 0 10px 20px !important;
  867. &::before {
  868. position: relative;
  869. left: -20px;
  870. top: -2px;
  871. content: '';
  872. width: 10px;
  873. height: 10px;
  874. background-image: url('../../../../assets/images/traingle0.png');
  875. background-size: 100% 100%;
  876. display: inline-block;
  877. }
  878. }
  879. .type-circle {
  880. cursor: pointer;
  881. margin: 10px 0 10px 20px !important;
  882. &::before {
  883. position: relative;
  884. left: -20px;
  885. top: -2px;
  886. content: '';
  887. width: 10px;
  888. height: 10px;
  889. border-radius: 50%;
  890. display: inline-block;
  891. }
  892. }
  893. .type-square {
  894. cursor: pointer;
  895. margin: 10px 0 10px 20px !important;
  896. &::before {
  897. position: relative;
  898. left: -20px;
  899. top: -2px;
  900. content: '';
  901. width: 10px;
  902. height: 10px;
  903. border-radius: 50%;
  904. background-color: transparent !important;
  905. display: inline-block;
  906. }
  907. }
  908. .type-line {
  909. cursor: pointer;
  910. margin: 10px 0 10px 18px !important;
  911. &::before {
  912. position: relative;
  913. top: -2px;
  914. left: -20px;
  915. content: '';
  916. width: 40px;
  917. height: 8px;
  918. display: inline-block;
  919. }
  920. }
  921. .item-un {
  922. &::before {
  923. background-color: #070358;
  924. border: 1px solid #070358;
  925. }
  926. }
  927. .item-blue {
  928. &::before {
  929. background-color: blue;
  930. border: 1px solid blue;
  931. }
  932. }
  933. .item-green {
  934. &::before {
  935. background-color: #0c9923;
  936. border: 1px solid #0c9923;
  937. }
  938. }
  939. .item-pink {
  940. &::before {
  941. background-color: #f405ff;
  942. border: 1px solid #f405ff;
  943. }
  944. }
  945. .item-red {
  946. &::before {
  947. background-color: #ff0000;
  948. border: 1px solid #ff0000;
  949. }
  950. }
  951. #popupCardDefRes {
  952. .histroyPipeData {
  953. // 详情卡片的样式
  954. .detailsCrad {
  955. position: fixed;
  956. top: 100px;
  957. right: 24px;
  958. z-index: 9;
  959. .clearfix:before,
  960. .clearfix:after {
  961. display: table;
  962. content: '';
  963. }
  964. .clearfix:after {
  965. clear: both;
  966. }
  967. /deep/ .box-card {
  968. width: 500px;
  969. max-height: 80vh;
  970. .el-card__header {
  971. height: 48px;
  972. color: #fff;
  973. background-color: #2d74e7;
  974. }
  975. .el-card__body {
  976. padding: 0;
  977. .el-menu-item {
  978. height: 45px;
  979. font-size: 16px;
  980. }
  981. }
  982. .content {
  983. height: 600px;
  984. /deep/ .content-info {
  985. overflow-y: scroll;
  986. // max-height: 545px;
  987. height: 100%;
  988. padding: 10px 20px;
  989. .el-textarea__inner,
  990. .el-input__inner {
  991. color: #666;
  992. }
  993. .detailsTitle {
  994. position: relative;
  995. font-size: 16px;
  996. padding: 5px 0;
  997. box-sizing: border-box;
  998. }
  999. .detailsTitle::after {
  1000. position: absolute;
  1001. top: 5px;
  1002. left: -10px;
  1003. content: '';
  1004. width: 4px;
  1005. height: 65%;
  1006. background-color: #2d74e7;
  1007. }
  1008. /deep/ .el-form {
  1009. .is-disabled {
  1010. .el-input__inner {
  1011. background-color: transparent;
  1012. }
  1013. .el-textarea__inner {
  1014. background-color: transparent;
  1015. }
  1016. }
  1017. .el-form-item {
  1018. margin-bottom: 10px;
  1019. }
  1020. }
  1021. }
  1022. }
  1023. .table-content {
  1024. padding: 15px;
  1025. .content-info {
  1026. font-size: 12px;
  1027. display: flex;
  1028. // justify-content: space-between;
  1029. flex-direction: column;
  1030. align-content: center;
  1031. .left {
  1032. font-family: 'Microsoft YaHei UI', sans-serif;
  1033. flex: 1;
  1034. }
  1035. /deep/ .right {
  1036. flex: 1;
  1037. .container {
  1038. height: 100%;
  1039. width: 100%;
  1040. padding: 5px;
  1041. box-sizing: border-box;
  1042. }
  1043. .is-top {
  1044. }
  1045. .el-tabs__item {
  1046. margin: 11px 0 0 0;
  1047. background: transparent;
  1048. }
  1049. .el-tabs__header {
  1050. border-top: 0;
  1051. background: #fff;
  1052. }
  1053. // .el-tabs__nav-wrap::after {
  1054. // z-index: 2;
  1055. // }
  1056. // .el-tabs__active-bar
  1057. }
  1058. .detailsTitle {
  1059. position: relative;
  1060. margin: 6px 0;
  1061. padding-left: 10px;
  1062. box-sizing: border-box;
  1063. margin-bottom: 10px;
  1064. }
  1065. .detailsTitle::after {
  1066. position: absolute;
  1067. left: 0;
  1068. content: '';
  1069. width: 4px;
  1070. height: 100%;
  1071. background-color: #2d74e7;
  1072. }
  1073. }
  1074. }
  1075. }
  1076. }
  1077. }
  1078. &::after {
  1079. content: '';
  1080. display: block;
  1081. width: 45px;
  1082. height: 27px;
  1083. background: url('../../components/testImg/corner.png');
  1084. position: absolute;
  1085. bottom: -26px;
  1086. left: 50%;
  1087. transform: translate(-50%, 0);
  1088. }
  1089. }
  1090. #popupCardRes {
  1091. &::after {
  1092. content: '';
  1093. display: block;
  1094. width: 45px;
  1095. height: 27px;
  1096. background: url('../../components/testImg/corner.png');
  1097. position: absolute;
  1098. bottom: -26px;
  1099. left: 50%;
  1100. transform: translate(-50%, 0);
  1101. }
  1102. }
  1103. </style>