SearchBox.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. <template>
  2. <transition
  3. appear
  4. name="animate__animated animate__move"
  5. enter-active-class="animate__flipInX"
  6. leave-active-class="animate__flipOutX"
  7. >
  8. <div class="widget-SearchBox" ref="widget-SearchBox">
  9. <div class="search">
  10. <el-input placeholder="" v-model="searchInput" class="input-with-select" size="small" clearable>
  11. <el-select v-model="selectType" slot="prepend" placeholder="请选择" :popper-append-to-body="false">
  12. <el-option label="工程" value="4"></el-option>
  13. </el-select>
  14. <el-button slot="append" icon="el-icon-search" @click="searching()"></el-button>
  15. </el-input>
  16. <ComTreeList
  17. :prjId="prjId"
  18. style="position: absolute; top: 0; left: 0.46875rem; /* 90/192 */"
  19. @changeProjectName="changeProjectName($event)"
  20. />
  21. </div>
  22. <div class="lifting">
  23. <span>抬升:</span>
  24. <el-input-number v-model="layerdown" size="small" controls-position="right"></el-input-number>
  25. <span class="unit">米</span>
  26. </div>
  27. <div class="setOpacity">
  28. <span>透明度:</span>
  29. <el-input-number v-model="opacity" size="small" controls-position="right" :min="0" :max="100" :step="10">
  30. </el-input-number>
  31. <span class="unit">%</span>
  32. </div>
  33. </div>
  34. </transition>
  35. </template>
  36. <script lang="ts">
  37. import { Vue, Component, Prop, Watch } from 'vue-property-decorator'
  38. import { mapSearch_api } from '@/api/APIs'
  39. import { queryMapByAttribute } from '@/views/groupPage/util'
  40. import ComTreeList from '@/views/groupPage/components/ComTreeList.vue'
  41. import Config from '@/views/groupPage/districtPageModules/commonModules/config.json'
  42. import _ from 'lodash'
  43. const Cesium = (window as any).Cesium
  44. const SuperMap = (window as any).SuperMap
  45. let _customDataSource = null
  46. const gLayerList = [
  47. 'NETWORK_SJ_PSWS@sxgk#1',
  48. 'NETWORK_SJ_PSYS@sxgk#1',
  49. 'NETWORK_SJ_PSWS_Node@sxgk#1',
  50. 'NETWORK_SJ_PSYS_Node@sxgk#1',
  51. 'TF_SJ_PSYS_JG_B_3D@sxgk#1',
  52. 'TF_SJ_PSYS_JG_B_3D@sxgk#2',
  53. 'TF_SJ_PSWS_JG_B_3D@sxgk#2',
  54. 'TF_SJ_PSWS_JG_B_3D@sxgk#1'
  55. ]
  56. //搜索栏
  57. @Component({ name: 'SearchBox', components: { ComTreeList } })
  58. export default class SearchBox extends Vue {
  59. searchInput = ''
  60. selectType = '4'
  61. loading = null
  62. apiurl = {
  63. sjfw: '',
  64. dtfw: '',
  65. smiddtfw: ''
  66. }
  67. backImg = require('@/views/groupPage/images/searchBoxBack.png')
  68. layerdown = 0
  69. //地表透明度配置
  70. opacity = 0
  71. disVisibleLayers = ['Config']
  72. g_modelTransparent = false
  73. mounted() {
  74. let target = this.$refs['widget-SearchBox'] as any
  75. target.style.setProperty('--left', '2.34375rem')
  76. }
  77. viewer
  78. get prjId() {
  79. return 45
  80. }
  81. get config() {
  82. return Config
  83. }
  84. get mapConfig() {
  85. return this.$store.state.bigScreen.mapConfig
  86. }
  87. get isInitViewer() {
  88. return this.$store.state.bigScreen.isInitViewer
  89. }
  90. @Watch('isInitViewer')
  91. onChangeMethod() {
  92. this.viewer = (window as any).viewer
  93. this.init()
  94. }
  95. //透明度变化
  96. @Watch('opacity')
  97. changeOpacity(newVal) {
  98. const val = parseFloat(newVal)
  99. const alpha = parseFloat((1 - val / 100).toString())
  100. const layers = this.disVisibleLayers
  101. if (this.g_modelTransparent && layers.length > 0) {
  102. this.viewer.scene.layers.layerQueue.forEach((layer) => {
  103. if (_.indexOf(layers, layer.name) !== -1) {
  104. layer.style3D.fillForeColor.alpha = alpha
  105. }
  106. })
  107. }
  108. this.viewer.scene.globe.globeAlpha = 1 - val / 100
  109. for (var i = 0; i < this.viewer.scene.imageryLayers.length; i++) {
  110. var ly = this.viewer.scene.imageryLayers.get(i)
  111. ly.alpha = alpha
  112. }
  113. }
  114. //管线抬升
  115. @Watch('layerdown')
  116. changeDepth(value) {
  117. let height = parseFloat(value)
  118. if (isNaN(height)) {
  119. return
  120. }
  121. this.mapConfig.upDepth = height
  122. const style3D = new Cesium.Style3D()
  123. style3D.altitudeMode = 0
  124. style3D.bottomAltitude = height
  125. gLayerList.forEach((item) => {
  126. var layer = this.viewer.scene.layers.find(item)
  127. if (layer) {
  128. layer.style3D = style3D
  129. layer.refresh()
  130. }
  131. })
  132. }
  133. //工程搜索模块
  134. init() {
  135. this.apiurl.sjfw = this.mapConfig.gisResource.tiplayers.config['sjfw'].url
  136. this.apiurl.dtfw = this.mapConfig.gisResource.maps.config['sjdt'].url
  137. this.apiurl.smiddtfw = this.mapConfig.gisResource.tiplayers.config['bjsmidfw'].url
  138. _customDataSource = new Cesium.CustomDataSource('SearchBox')
  139. this.viewer.dataSources.add(_customDataSource)
  140. }
  141. changeProjectName(data) {
  142. if (data != '') {
  143. const { name, code } = data
  144. this.searchInput = name
  145. this.searching()
  146. } else {
  147. this.clearInput()
  148. }
  149. }
  150. clearInput() {
  151. this.searchInput = ''
  152. this.removeLabels()
  153. }
  154. searching() {
  155. const searchType = this.selectType
  156. const inputObj = this.searchInput
  157. // if (xss.isXSS(inputObj)) {
  158. if (!inputObj) {
  159. this.$message.warning('请选择工程!')
  160. return
  161. }
  162. switch (searchType) {
  163. case '4':
  164. this.searchPrjSpeedInfo(inputObj)
  165. break
  166. }
  167. }
  168. /**
  169. * 该方法用于查询工程进度
  170. * @param prjName 工程(包括工程项目、单项工程、单位工程、子单位工程)
  171. * @returns
  172. */
  173. searchPrjSpeedInfo(prjName) {
  174. if (!prjName) {
  175. this.removeLabels()
  176. // this.clearSelection()
  177. return
  178. }
  179. this.loading = this.$loading({
  180. lock: true,
  181. text: '正在搜索中,请耐心等待...',
  182. spinner: 'el-icon-loading',
  183. background: 'rgba(0, 0, 0, 0.3)',
  184. customClass: 'loadingclass'
  185. })
  186. const data = { queryText: prjName } //查询条件
  187. const pipe = (this.config as any).pipe
  188. const that = this
  189. const fieldName = 'CODE'
  190. const geourl = this.apiurl.smiddtfw
  191. mapSearch_api(data).then((res) => {
  192. const result = res
  193. if (result.code !== 1) return
  194. if (result.result.length === 0) {
  195. this.$message('未搜索到相关工程')
  196. this.loading.close()
  197. return
  198. }
  199. const filters = []
  200. const cwpInfos = []
  201. const len = result.result.length
  202. for (let i = 0; i < len; i++) {
  203. const item = result.result[i]
  204. const pipename = item.firstLayerName.split(',')[0]
  205. const layer = _.find(pipe, function (pipeItem) {
  206. return pipeItem.origindataset === pipename
  207. })
  208. if (!layer) {
  209. continue
  210. }
  211. //组装
  212. let cwpInfo = {
  213. name: '',
  214. roadName: '',
  215. code: '',
  216. percent: '',
  217. design: {
  218. name: '',
  219. total: 0,
  220. pipe: 0,
  221. node: 0
  222. },
  223. spv: {
  224. name: '',
  225. pipeLen: 0,
  226. times: 0,
  227. part: 0,
  228. pictures: 0
  229. },
  230. con: {
  231. name: '',
  232. pipeLen: 0,
  233. times: 0,
  234. part: 0,
  235. pictures: 0
  236. }
  237. }
  238. cwpInfo.percent = !item.percent ? 0 : item.percent
  239. cwpInfo.code = item.firstPbs
  240. cwpInfo.name = item.zdwName
  241. cwpInfo.roadName = item.roadName
  242. //设计
  243. const design = _.find(item.tjData, (djData) => {
  244. return djData.dataType === 'DESIGN'
  245. })
  246. if (design) {
  247. cwpInfo.design.name = design.designUnit
  248. cwpInfo.design.total = design.tfPipeLength
  249. cwpInfo.design.pipe = design.tfPipeCount
  250. cwpInfo.design.node = design.tfNodeCount
  251. }
  252. //施工
  253. const con = _.find(item.tjData, (djData) => {
  254. return djData.dataType === 'CON'
  255. })
  256. if (con) {
  257. cwpInfo.con.name = con.buildUnit
  258. cwpInfo.con.pipeLen = con.smLength
  259. cwpInfo.con.times = con.scanTimes
  260. cwpInfo.con.part = con.partsTotal
  261. cwpInfo.con.pictures = con.pictures
  262. }
  263. //监理
  264. const spv = _.find(item.tjData, (djData) => {
  265. return djData.dataType === 'SPV'
  266. })
  267. if (spv) {
  268. cwpInfo.spv.name = spv.supervisionUnit
  269. cwpInfo.spv.pipeLen = spv.smLength
  270. cwpInfo.spv.times = spv.scanTimes
  271. cwpInfo.spv.part = spv.partsTotal
  272. cwpInfo.spv.pictures = spv.pictures
  273. }
  274. cwpInfos.push(cwpInfo)
  275. //多图层搜索
  276. const queryname = layer.smidmapnameNT ? layer.smidmapnameNT : layer.smidmapname
  277. const JGFilter = new SuperMap.REST.FilterParameter({
  278. name: queryname,
  279. attributeFilter: fieldName + " = '" + item['firstPbs'] + "'",
  280. fields: [fieldName]
  281. })
  282. filters.push(JGFilter)
  283. }
  284. const onComplete = function (geoResult) {
  285. that.loading.close()
  286. //交互事件
  287. // that.getCurrentInfo()
  288. // that.clickHightLight()
  289. geoResult.originResult.recordsets.forEach((record) => {
  290. const features = record.features
  291. if (features.length > 1) {
  292. console.log('pbs重复')
  293. return true
  294. }
  295. if (features.length == 0) {
  296. return true
  297. }
  298. const scanProj = _.find(cwpInfos, function (scanItem) {
  299. return scanItem.code === features[0]['fieldValues'][0]
  300. })
  301. let labelText = ''
  302. let imgSrc = that.backImg
  303. let position = features[0].geometry.points[0]
  304. position = Cesium.Cartesian3.fromDegrees(position.x, position.y, position.z)
  305. //缩放定位,默认第一个
  306. const camera = that.viewer.camera
  307. const location = Cesium.Cartographic.fromDegrees(
  308. features[0].geometry.points[0].x,
  309. features[0].geometry.points[0].y,
  310. features[0].geometry.points[0].z + 5000
  311. )
  312. const cartesian3 = Cesium.Cartographic.toCartesian(location)
  313. camera.flyTo({
  314. destination: cartesian3,
  315. orientation: {
  316. heading: camera.heading,
  317. pitch: Cesium.Math.toRadians(-90),
  318. roll: 0
  319. }
  320. })
  321. scanProj.displayType = 'gcss'
  322. that.addUnitBillboard({
  323. id: scanProj.code,
  324. name: scanProj.code,
  325. text: labelText,
  326. position: position,
  327. scanProj: scanProj,
  328. imgSrc: imgSrc
  329. })
  330. })
  331. }
  332. queryMapByAttribute({
  333. url: geourl,
  334. filterParameters: filters,
  335. completed: onComplete.bind(this),
  336. failed: function (err) {
  337. that.loading.close()
  338. that.$message.error('查询失败')
  339. console.log(err)
  340. }
  341. })
  342. })
  343. }
  344. /**
  345. * 该方法用于生成部件定位指示牌
  346. * @param options entity信息
  347. * @param options.id entity ID
  348. * @param options.text 站点信息
  349. * @param options.name 站点信息
  350. * @param options.position 位置
  351. */
  352. addUnitBillboard(options) {
  353. var that = this
  354. var bottomPosition = Cesium.Cartographic.fromCartesian(options.position)
  355. var topPosition = Cesium.Cartographic.fromRadians(
  356. bottomPosition.longitude,
  357. bottomPosition.latitude,
  358. bottomPosition.height + 40
  359. )
  360. var bPosition = Cesium.Cartographic.toCartesian(bottomPosition)
  361. var tPosition = Cesium.Cartographic.toCartesian(topPosition)
  362. const percent = isNaN(options.scanProj.percent) ? 0 : parseFloat(options.scanProj.percent)
  363. options.text = options.scanProj.roadName + '(' + percent + '%)'
  364. var color = 'rgb(56, 136, 205)'
  365. var canvas = document.createElement('canvas')
  366. const ratio = 2.0
  367. let height = 50
  368. const realHeight = 48
  369. //临时数值
  370. let width = 100
  371. canvas.width = width * ratio
  372. canvas.height = height * ratio
  373. const fonttxt = '50px Arial'
  374. var ctx = canvas.getContext('2d')
  375. //ctx.scale(ratio, ratio)
  376. var img = new Image()
  377. img.src = options.imgSrc
  378. img.onload = function () {
  379. ctx.lineWidth = 10
  380. ctx.strokeStyle = color
  381. ctx.font = '24px Arial'
  382. const realWidth = ctx.measureText(options.text).width
  383. ctx.font = fonttxt
  384. width = ctx.measureText(options.text).width + 100
  385. canvas.width = width
  386. ctx.fillStyle = 'rgba(0,0,0,0.7)'
  387. ctx.fillRect(0, 0, canvas.width, canvas.height)
  388. if (percent !== 0) {
  389. ctx.drawImage(img, 0, 0, canvas.width * (percent / 100), canvas.height)
  390. }
  391. ctx.font = fonttxt
  392. ctx.fillStyle = 'rgb(255,255,255)'
  393. ctx.textBaseline = 'middle'
  394. ctx.fillText(options.text, 50, height)
  395. //ctx.fillText(options.text, (canvas.width - width) / 2, (canvas.height + 15) / 2);
  396. var entity = new Cesium.Entity({
  397. id: options.id,
  398. name: options.name,
  399. show: true,
  400. position: Cesium.Cartographic.toCartesian(topPosition),
  401. polyline: {
  402. positions: [bPosition, tPosition],
  403. material: Cesium.Color.fromBytes(56, 136, 205, 255),
  404. width: 3
  405. },
  406. billboard: {
  407. sizeInMeters: false,
  408. image: canvas.toDataURL(),
  409. //scale:0.2,
  410. width: realWidth,
  411. height: realHeight,
  412. scaleByDistance: new Cesium.NearFarScalar(10000, 1.0, 10100, 0.5),
  413. verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
  414. horizontalOrigin: Cesium.HorizontalOrigin.CENTER
  415. }
  416. })
  417. entity.displayType = options.scanProj.displayType
  418. entity.displayData = options.scanProj
  419. _customDataSource.entities.add(entity)
  420. }
  421. }
  422. //该方法用于清除entity label
  423. removeLabels() {
  424. if (Cesium.defined(_customDataSource)) {
  425. _customDataSource.entities.removeAll()
  426. }
  427. }
  428. }
  429. </script>
  430. <style lang="scss" scoped>
  431. .animate__flipInX,
  432. .animate__flipOutX {
  433. animation-duration: 3s; //动画持续时间
  434. animation-delay: 0s; //动画延迟时间
  435. }
  436. .widget-SearchBox {
  437. $size10: 0.052083rem /* 10/192 */;
  438. $size20: 0.104167rem /* 20/192 */;
  439. z-index: 2;
  440. //position
  441. top: 0.505208rem /* 97/192 */;
  442. margin-left: var(--left); //2.34375rem /* 450/192 */;
  443. position: absolute;
  444. left: 0;
  445. //font
  446. font-family: Source Han Sans CN;
  447. .search {
  448. float: left;
  449. margin-right: 0.052083rem /* 10/192 */;
  450. & ::placeholder {
  451. color: rgba(43, 167, 255, 1);
  452. }
  453. /deep/ .el-input {
  454. $backgroundColor: rgba(7, 48, 80, 0.9);
  455. .el-select .el-input {
  456. width: 0.46875rem /* 90/192 */;
  457. }
  458. .el-input__inner {
  459. color: #eee;
  460. background-color: $backgroundColor;
  461. border: none;
  462. width: 0.78125rem /* 150/192 */;
  463. }
  464. .el-input-group__append,
  465. .el-input-group__prepend {
  466. background-color: $backgroundColor;
  467. border: none;
  468. color: #2ba7ff;
  469. }
  470. .el-input-group__prepend {
  471. .el-select {
  472. margin: -0.015625rem /* 3/192 */ -0.109375rem /* 21/192 */;
  473. position: relative;
  474. }
  475. .el-input__inner {
  476. font-size: 0.072917rem /* 14/192 */;
  477. font-family: Source Han Sans CN;
  478. font-weight: 500;
  479. color: #2ba7ff;
  480. position: relative;
  481. }
  482. .el-input::after {
  483. content: '';
  484. position: absolute;
  485. top: 0;
  486. bottom: 0;
  487. right: 0;
  488. margin: auto 0;
  489. width: 1px;
  490. height: 80%;
  491. background-color: rgba(41, 177, 255, 0.3);
  492. }
  493. .el-icon-arrow-up:before {
  494. content: '';
  495. display: block;
  496. // 定义元素宽高
  497. margin-top: 0.041667rem /* 8/192 */;
  498. width: 0.130208rem /* 25/192 */;
  499. height: 0.078125rem /* 15/192 */;
  500. background: url('~@/views/groupPage/images/三角下.png') no-repeat center center;
  501. background-size: 100% 100%;
  502. transform: rotate(180deg);
  503. }
  504. }
  505. }
  506. }
  507. .lifting,
  508. .setOpacity {
  509. float: left;
  510. $background: rgba(7, 48, 80, 0.9);
  511. background: $background;
  512. border-radius: 0.010417rem /* 2/192 */;
  513. margin-right: 0.052083rem /* 10/192 */;
  514. span {
  515. padding: 0.052083rem /* 10/192 */ 0 0.052083rem /* 10/192 */ 0.052083rem /* 10/192 */;
  516. font-size: 0.072917rem /* 14/192 */;
  517. font-family: Source Han Sans CN;
  518. font-weight: 500;
  519. color: #82bae2;
  520. }
  521. .unit {
  522. padding: 0.052083rem /* 10/192 */ 0.052083rem /* 10/192 */ 0 0 !important;
  523. }
  524. /deep/ .el-input-number {
  525. width: 0.3125rem /* 60/192 */;
  526. .el-input-group__append,
  527. .el-input-group__prepend {
  528. padding: 0 0.026042rem /* 5/192 */;
  529. }
  530. .el-input__inner {
  531. color: rgba(43, 167, 255, 1);
  532. border: none;
  533. background-color: $background;
  534. position: relative;
  535. padding-right: 0.15625rem /* 30/192 */;
  536. padding-left: 0;
  537. }
  538. .el-input-number__decrease,
  539. .el-input-number__increase {
  540. background: transparent;
  541. border: none;
  542. height: 50%;
  543. }
  544. .el-input-number__increase .el-icon-arrow-up:before {
  545. content: '';
  546. display: block;
  547. // 定义元素宽高
  548. margin-top: 0.010417rem /* 2/192 */;
  549. width: 0.130208rem /* 25/192 */;
  550. height: 0.078125rem /* 15/192 */;
  551. background: url('~@/views/groupPage/images/三角上.png') no-repeat center center;
  552. background-size: 100% 100%;
  553. object-fit: contain;
  554. }
  555. .el-input-number__decrease .el-icon-arrow-down:before {
  556. content: '';
  557. display: block;
  558. // 定义元素宽高
  559. // margin-top: 0.010417rem /* 2/192 */;
  560. width: 0.130208rem /* 25/192 */;
  561. height: 0.078125rem /* 15/192 */;
  562. background: url('~@/views/groupPage/images/三角下.png') no-repeat center center;
  563. background-size: 100% 100%;
  564. object-fit: contain;
  565. }
  566. }
  567. }
  568. }
  569. </style>