index.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. <!--
  2. *@description: 可视化进度
  3. *@author: yh Fu
  4. *@date: 2023-12-25 13:27:19
  5. *@version: V1.0.5
  6. -->
  7. <template>
  8. <div class="progresVisualContainer">
  9. <el-radio-group v-model="currentMenu" style="margin-bottom: 20px;" @input="toModule">
  10. <el-radio-button label="0">用料统计</el-radio-button>
  11. <el-radio-button label="1">进度统计</el-radio-button>
  12. <el-radio-button label="2">可视化统计</el-radio-button>
  13. <el-radio-button label="3">可视化进度</el-radio-button>
  14. </el-radio-group>
  15. <div class="topContain">
  16. <el-form :model="searchParam" ref="searchForm" class="searchForm" :rules="searchRules">
  17. <el-form-item label="行政区" prop="district">
  18. <el-select v-model="searchParam.district" placeholder="请选择行政区" clearable
  19. @change="searchParam.areaId = undefined;getAreaList(searchParam.district)"
  20. @clear="searchParam.areaId = undefined;areaList=[];
  21. searchParam.buildingId = undefined;buildingList=[];
  22. searchParam.unitId = undefined;unitList=[]">
  23. <el-option
  24. v-for="dict in dict.type.district"
  25. :key="dict.value"
  26. :label="dict.label"
  27. :value="dict.value"
  28. />
  29. </el-select>
  30. </el-form-item>
  31. <el-form-item label="小区名称" prop="areaId" style="width: 218px;">
  32. <el-select v-model="searchParam.areaId" filterable clearable placeholder="请选择小区"
  33. @change="searchParam.buildingId = undefined;getBuildingList1(searchParam.areaId)"
  34. @clear="searchParam.buildingId = undefined;buildingList=[];
  35. searchParam.unitId = undefined;unitList=[]">
  36. <el-option
  37. v-for="item in areaList"
  38. :key="item.id"
  39. :label="item.name"
  40. :value="item.id">
  41. </el-option>
  42. </el-select>
  43. </el-form-item>
  44. <el-form-item label="楼宇名称" prop="buildingId">
  45. <el-select v-model="searchParam.buildingId" filterable clearable placeholder="请选择楼宇"
  46. @change="searchParam.unitId = undefined;getUnitList1(searchParam.buildingId)"
  47. @clear="searchParam.unitId = undefined;unitList=[]"
  48. >
  49. <el-option
  50. v-for="item in buildingList"
  51. :key="item.id"
  52. :label="item.name"
  53. :value="item.id">
  54. </el-option>
  55. </el-select>
  56. </el-form-item>
  57. <el-form-item label="单元" prop="unitId">
  58. <el-select v-model="searchParam.unitId" placeholder="请选择单元" filterable clearable>
  59. <el-option
  60. v-for="obj in unitList"
  61. :key="obj.id"
  62. :label="obj.name"
  63. :value="obj.id"
  64. ></el-option>
  65. </el-select>
  66. </el-form-item>
  67. <el-form-item label="工程类型" prop="enginType">
  68. <el-select v-model="searchParam.enginType" placeholder="请选择工程类型" filterable clearable
  69. @change="enginTypeHasChangeds"
  70. >
  71. <el-option
  72. v-for="dict in enginTypeOption"
  73. :key="dict.value"
  74. :label="dict.label"
  75. :value="dict.value"
  76. />
  77. </el-select>
  78. </el-form-item>
  79. <!-- <el-form-item label="工程分类" prop="enginClassification">-->
  80. <!-- <el-select v-model="searchParam.enginClassification" placeholder="请选择工程分类" clearable-->
  81. <!-- @clear="currentEnginTypeChangeOptions1=[];searchParam.enginClassification=undefined;searchParam.enginType=undefined">-->
  82. <!-- <el-option-->
  83. <!-- v-for="dict in currentEnginTypeChangeOptions1"-->
  84. <!-- :key="dict.dictValue"-->
  85. <!-- :label="dict.dictLabel"-->
  86. <!-- :value="dict.dictValue"-->
  87. <!-- />-->
  88. <!-- </el-select>-->
  89. <!-- </el-form-item>-->
  90. <!-- <el-form-item label="工程周期" prop="enginCycle" style="width: 218px;">-->
  91. <!-- <el-select-->
  92. <!-- :disabled="title == '添加用料' "-->
  93. <!-- v-model="searchParam.enginCycle"-->
  94. <!-- placeholder="请填写工程周期"-->
  95. <!-- >-->
  96. <!-- <el-option-->
  97. <!-- v-for="e in dict.type.engin_cycle"-->
  98. <!-- :key="e.value"-->
  99. <!-- :label="e.label"-->
  100. <!-- :value="e.value"-->
  101. <!-- ></el-option>-->
  102. <!-- </el-select>-->
  103. <!-- </el-form-item>-->
  104. </el-form>
  105. <!-- <div style="width: 100%;height: 100%;">
  106. <el-select
  107. v-model="currentCommunity"
  108. placeholder="请选择行政区"
  109. class="projectSelect"
  110. popper-class="projectDropDown"
  111. :popper-append-to-body="false"
  112. >
  113. <el-option
  114. v-for="e in communityOptions"
  115. :key="e.value"
  116. :label="e.label"
  117. :value="e.value">
  118. </el-option>
  119. </el-select>
  120. <el-select
  121. v-model="currentCommunity"
  122. placeholder="请选择小区"
  123. class="projectSelect"
  124. popper-class="projectDropDown"
  125. :popper-append-to-body="false"
  126. >
  127. <el-option
  128. v-for="e in communityOptions"
  129. :key="e.value"
  130. :label="e.label"
  131. :value="e.value">
  132. </el-option>
  133. </el-select>
  134. <el-select
  135. v-model="currentType"
  136. placeholder="请选择工程类型"
  137. class="projectSelect"
  138. popper-class="projectDropDown"
  139. :popper-append-to-body="false"
  140. >
  141. <el-option
  142. v-for="e in typeOptions"
  143. :key="e.value"
  144. :label="e.label"
  145. :value="e.value">
  146. </el-option>
  147. </el-select>
  148. <el-date-picker
  149. v-model="currentDate"
  150. class="projectSelect"
  151. popper-class="projectDropDown"
  152. :popper-append-to-body="false"
  153. type="date"
  154. placeholder="选择日期">
  155. </el-date-picker>
  156. </div> -->
  157. <el-button class="searchBtn" @click="searchCompletionInfo">查询</el-button>
  158. <!-- <el-button class="searchBtn">导出</el-button>-->
  159. <div class="unitStatus" >
  160. <div
  161. v-for="(e,idx) in unitStatusOption"
  162. :key="idx"
  163. :style="`background-color:${e.color};width: 22%;height: 35px;position: absolute;right:${idx*130}px;box-shadow:0 5px 5px 0 #CDCDCD`"
  164. >
  165. <div
  166. style="position: relative;left: 107%;width: 116%;top: 20%;"
  167. >
  168. {{ e.label }}
  169. </div>
  170. </div>
  171. </div>
  172. </div>
  173. <!-- 房间集合 -->
  174. <!-- 楼栋 or 单元 -->
  175. <div style="min-width: 1618px;display: flex;overflow: hidden;overflow-x: scroll;align-items: end;">
  176. <div
  177. v-for="(e,idx) in roomsInfo"
  178. :key="idx"
  179. class="buildingContain"
  180. >
  181. <!-- 楼层 -->
  182. <div
  183. v-for="(v,vdx) in e.roomStatusVoList"
  184. :key="vdx"
  185. class="unitFloor"
  186. >
  187. {{ v.notstart || '' }}
  188. <!-- 房间 -->
  189. <div
  190. v-for="(k,kdx) in v"
  191. :key="kdx"
  192. class="room"
  193. @click="toDetail(k)"
  194. :style="`background-color:${k.roomStatus == '未施工' ? '#fec880' : k.roomStatus == '施工中' ? '#5ad3fe' : '#81d9af'};
  195. border: solid 1px ${k.roomStatus == '未施工' ? '#ffa938' : k.roomStatus == '施工中' ? '#30b3e1' : '#62b98f'}`"
  196. >
  197. {{ k.roomName || '' }}
  198. </div>
  199. </div>
  200. <h2 style="text-align: center; font-size: 1.1em;">{{ e.unitName }}</h2>
  201. </div>
  202. </div>
  203. <ConstructionDetails
  204. ref="ConstructionDetails"
  205. :currentCollapses="currentCollapses"
  206. :type="nodeDetailType"
  207. :status="status"
  208. enginType="民用工程"
  209. />
  210. </div>
  211. </template>
  212. <script>
  213. import ConstructionDetails from '@/components/ConstructionDetails'
  214. import {getAreaList} from "@/api/zdsz/area";
  215. import {getBuildingList} from "@/api/zdsz/building";
  216. import {getUnits} from "@/api/zdsz/unit";
  217. import {getDicts} from "@/api/system/dict/data";
  218. import {getObtainRoomcCompletionInformationList, viewQueryProcessSource} from "@/api/zdsz/enginee"
  219. import {getAreaCompletionInformationList} from "@/api/zdsz/overhead";
  220. export default {
  221. name: 'ProgreVisual',
  222. components: {
  223. ConstructionDetails
  224. },
  225. dicts: ['district', 'engin_cycle', 'new_built', 'old_renovation'],
  226. data() {
  227. return {
  228. currentMenu: 3, // 0:用料管理 1:进度统计 2:可视化进度
  229. currentCollapses: [],
  230. status: '',
  231. enginTypeOption: [
  232. {
  233. value: 'old_renovation',
  234. label: '旧改'
  235. }, {
  236. value: 'new_built',
  237. label: '新建'
  238. },
  239. ],
  240. typeOptions: [
  241. {
  242. value: '0',
  243. label: '市政工程'
  244. },
  245. {
  246. value: '1',
  247. label: '工业工程'
  248. },
  249. {
  250. value: '2',
  251. label: '民用工程'
  252. },
  253. {
  254. value: '3',
  255. label: '危险作业'
  256. },
  257. {
  258. value: '4',
  259. label: '顶管工程'
  260. },
  261. {
  262. value: '5',
  263. label: '基建工程'
  264. }
  265. ],
  266. communityOptions: [
  267. {
  268. value: '0',
  269. label: '领秀世家'
  270. },
  271. {
  272. value: '1',
  273. label: '上东府里'
  274. },
  275. {
  276. value: '2',
  277. label: '清华园'
  278. },
  279. {
  280. value: '3',
  281. label: '万科蓝山'
  282. },
  283. {
  284. value: '4',
  285. label: '龙腾香格里'
  286. },
  287. ],
  288. unitStatusOption: [
  289. {
  290. label: '竣工',
  291. color: '#81d9af'
  292. },
  293. {
  294. label: '施工中',
  295. color: '#5ad3fe'
  296. },
  297. {
  298. label: '未施工',
  299. color: '#fec880'
  300. },
  301. ],
  302. areaName:'',
  303. currentType: null,
  304. currentCommunity: null,
  305. areaList: [],
  306. buildingList: [],
  307. unitList: [],
  308. info: {
  309. district: undefined,
  310. },
  311. currentCheckList:[],
  312. currentEnginTypeChangeOptions1: [],
  313. searchParam: {
  314. district: null,
  315. enginCycle: 0,
  316. areaId: null,
  317. buildingId: null,
  318. unitId: null,
  319. enginClassification:null,
  320. },
  321. roomsInfo: [],
  322. AreaCompletionInformationList:[],
  323. updateParams: {},
  324. currentRoomId: null,
  325. currentEnginType: null,
  326. currentEnginClassification: 'indoor_engin',
  327. zEngineeringNodeBo:null,
  328. searchRules: {
  329. district: [
  330. {required: true, message: "行政区不能为空", trigger: ['change']}
  331. ],
  332. areaId: [
  333. {required: true, message: "小区不能为空", trigger: ['change']}
  334. ],
  335. // enginCycle: [
  336. // {required: true, message: "工程周期不能为空", trigger: ['change']}
  337. // ],
  338. }
  339. }
  340. },
  341. methods: {
  342. enginTypeHasChangeds(enginType = null) {
  343. if (this.searchParam.enginType == undefined || this.searchParam.enginType == null || this.searchParam.enginType == '')
  344. return
  345. this.currentCheckList = []
  346. this.searchParam.enginClassification = ''
  347. this.currentEnginTypeChangeOptions1 = []
  348. getDicts(enginType || this.searchParam.enginType).then(res => {
  349. this.currentEnginTypeChangeOptions1 = res.data
  350. })
  351. },
  352. toDetail(e) {
  353. this.currentRoomId = e.roomId
  354. let dictValue
  355. // 拼接字典
  356. console.log('e', this.dict)
  357. console.log(e.enginCycle)
  358. console.log(this.dict.type[e.enginCycle])
  359. this.dict.type[e.enginCycle].forEach(v => {
  360. if (v.label.includes('室内')) {
  361. this.currentEnginType = e.enginCycle
  362. dictValue = e.enginCycle + '_' + v.value
  363. }
  364. })
  365. // 加工字典
  366. getDicts(dictValue).then(res => {
  367. let dict = []
  368. for (let i = 0; i < res.data.length; i++) {
  369. dict.push({
  370. "label": res.data[i].dictLabel,
  371. "value": res.data[i].dictValue,
  372. })
  373. }
  374. let title = '施工记录 '+this.areaName + "-" + e.unitName + "-" +e.roomName;
  375. setTimeout(() => {
  376. this.$refs.ConstructionDetails.open(dict,this.currentEnginType,null,'民用',title,this.currentEnginClassification)
  377. })
  378. })
  379. this.status = 'read-only'
  380. },
  381. viewNodeSource(e) {
  382. let params = {
  383. type: e,
  384. houseId: this.currentRoomId,
  385. enginClassification: this.currentEnginClassification,
  386. enginType: this.currentEnginType
  387. }
  388. viewQueryProcessSource(params).then(res => {
  389. console.log('______', res)
  390. try {
  391. this.updateParams = res.data
  392. this.currentCollapses = res.data.zEngineeringNodeBo.zEngineeringInfoBoList
  393. this.zEngineeringNodeBo=res.data.zEngineeringNodeBo
  394. } catch (error) {
  395. this.currentCollapses = [];
  396. }
  397. console.log('折叠面板info', this.currentCollapses)
  398. })
  399. this.$forceUpdate()
  400. },
  401. // 查询进度
  402. searchCompletionInfo() {
  403. this.$refs.searchForm.validate(valid => {
  404. if (valid) {
  405. // 校验 pass
  406. let params = {
  407. enginCycle: this.searchParam.enginCycle,
  408. areaId: this.searchParam.areaId,
  409. buildingId: this.searchParam.buildingId,
  410. unitId: this.searchParam.unitId,
  411. enginType:this.searchParam.enginType,
  412. }
  413. getObtainRoomcCompletionInformationList(params).then(res => {
  414. let info = []
  415. info = res.data
  416. info.forEach(e => {
  417. e.roomStatusVoList = e.roomStatusVoList.reverse()
  418. })
  419. this.roomsInfo = info
  420. })
  421. } else {
  422. this.$message.error('请填写必填项!')
  423. }
  424. })
  425. },
  426. getAreaList(district) {
  427. if (district === undefined || district == null || district === '')
  428. return
  429. console.log(getAreaList)
  430. getAreaList({district: district}).then(res => this.areaList = res.data)
  431. },
  432. getBuildingList1(areaId) {
  433. if (areaId === undefined || areaId == null || areaId === '')
  434. return
  435. getBuildingList({areaId: areaId}).then(res => this.buildingList = res.data)
  436. this.areaName = this.areaList.find(item => item.id === areaId).name;
  437. },
  438. getUnitList1(buildingId) {
  439. if (buildingId === undefined || buildingId == null || buildingId === '')
  440. return
  441. getUnits(buildingId).then(res => this.unitList = res.data)
  442. },
  443. toModule() {
  444. console.log(this.$router)
  445. const currentPage = this.currentMenu == 0 ? 'material_statistics' : this.currentMenu == 1 ? 'progres_statistics' : this.currentMenu == 2 ? 'echarts_statistics' : 'progres_visual'
  446. this.$router.push({
  447. path: `/${currentPage}`
  448. })
  449. }
  450. }
  451. }
  452. </script>
  453. <style lang="scss" scoped>
  454. .progresVisualContainer {
  455. width: 100%;
  456. height: 100%;
  457. padding: 1%;
  458. .topContain {
  459. display: flex;
  460. justify-content: space-between;
  461. width: 60%;
  462. .searchBtn {
  463. height: 100%;
  464. width: 11%;
  465. background-color: #1890FF;
  466. color: #fff;
  467. }
  468. ::v-deep .projectSelect {
  469. width: 20% !important;
  470. .el-input__inner {
  471. background-color: #1890FF;
  472. color: #fff;
  473. }
  474. }
  475. .projectDropDown {
  476. background-color: #1890FF;
  477. .el-select-dropdown__item {
  478. background-color: #1890FF;
  479. color: #fff;
  480. }
  481. ::v-deep .el-select-dropdown__list {
  482. padding-top: 0 !important;
  483. padding-bottom: 0;
  484. }
  485. }
  486. .projectDropDown > ul {
  487. padding-top: 0;
  488. padding-bottom: 0;
  489. }
  490. .unitStatus {
  491. width: 13%;
  492. display: flex;
  493. position: absolute;
  494. right: 3%;
  495. height: 5%;
  496. }
  497. }
  498. }
  499. .buildingContain {
  500. height: 100%;
  501. border: solid 5px #c7eafe;
  502. padding: 10px;
  503. background: #e2f4ff;
  504. .unitFloor {
  505. display: flex;
  506. justify-content: space-around;
  507. //border: 1px solid #000;
  508. .room {
  509. flex: 1;
  510. width: 60px;
  511. height: 25px;
  512. text-align: center;
  513. line-height: 25px;
  514. cursor: pointer;
  515. font-size: 1em;
  516. //box-shadow: inset 0px 0px 10px rgba(0, 0, 0, .6);
  517. }
  518. }
  519. .unitFloor > div:not(:nth-child(1)) {
  520. margin-left: 2%;
  521. }
  522. }
  523. .buildingContain:not(:nth-child(1)) {
  524. margin-left: 5%;
  525. }
  526. .buildingContain .unitFloor:not(:nth-child(1)) {
  527. margin-top: 2%;
  528. }
  529. ::v-deep .searchForm {
  530. display: flex;
  531. .el-form-item {
  532. width: 205px;
  533. }
  534. .el-select {
  535. width: 135px;
  536. }
  537. }
  538. </style>