index.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. <template>
  2. <com-head :options="headList" v-model="search.state.type" showCtrl>
  3. <el-form label-width="90px" inline="true">
  4. <el-form-item label="楼栋-单元:">
  5. <el-input v-model="search.state.buildingUnit" placeholder="请输入"></el-input>
  6. </el-form-item>
  7. <el-form-item label="房号:">
  8. <el-input v-model="search.state.roomNumber" placeholder="请输入"></el-input>
  9. </el-form-item>
  10. <el-form-item label="建筑面积:" >
  11. <div class="range-number">
  12. <el-input v-model="search.state.constructionAreaStar" placeholder="请输入"></el-input>
  13. <span>至</span>
  14. <el-input v-model="search.state.constructionAreaEnd" placeholder="请输入"></el-input>
  15. </div>
  16. </el-form-item>
  17. <el-form-item label="套内面积:">
  18. <div class="range-number">
  19. <el-input v-model="search.state.insideAreaStar" placeholder="请输入"></el-input>
  20. <span>至</span>
  21. <el-input v-model="search.state.insideAreaSnd" placeholder="请输入"></el-input>
  22. </div>
  23. </el-form-item>
  24. <el-form-item label="更新时间:">
  25. <el-date-picker
  26. v-model="updateTime"
  27. type="daterange"
  28. range-separator="至"
  29. start-placeholder="开始时间"
  30. end-placeholder="结束时间">
  31. </el-date-picker>
  32. </el-form-item>
  33. <el-form-item label="维护人:">
  34. <el-input v-model="search.state.maintenanceman" placeholder="请输入"></el-input>
  35. </el-form-item>
  36. <el-form-item label="状态:">
  37. <el-select v-model="search.state.auditStatus" placeholder="全部">
  38. <el-option v-for="(item) in status" :key="item.value" :label="item.name" :value="item.value"></el-option>
  39. </el-select>
  40. </el-form-item>
  41. <el-form-item label="审核人:">
  42. <el-input v-model="search.state.reviewer" placeholder="请输入"></el-input>
  43. </el-form-item>
  44. <el-form-item label="创建时间:">
  45. <el-date-picker
  46. v-model="createTime"
  47. type="daterange"
  48. range-separator="至"
  49. start-placeholder="开始日期"
  50. end-placeholder="结束日期">
  51. </el-date-picker>
  52. </el-form-item>
  53. <el-form-item label="审核时间:">
  54. <el-date-picker
  55. v-model="reviewTime"
  56. type="daterange"
  57. range-separator="至"
  58. start-placeholder="开始日期"
  59. end-placeholder="结束日期">
  60. </el-date-picker>
  61. </el-form-item>
  62. <el-form-item class="searh-btns">
  63. <el-button @click="resetSearch">重置</el-button>
  64. <el-button type="primary" @click="search.submit">查询</el-button>
  65. </el-form-item>
  66. </el-form>
  67. </com-head>
  68. <div class="body-layer">
  69. <div class="body-head">
  70. <h3>
  71. <span>全部房源VR</span>
  72. </h3>
  73. <!-- <div>
  74. <el-button type="primary" @click="dataList.deleteSelect" v-if="auth.delete" :disabled="!dataList.state.length">删除</el-button>
  75. </div> -->
  76. </div>
  77. <el-table ref="multipleTable" :data="dataList.state" style="width: 100%" @selection-change="dataList.changeSelectRows">
  78. <el-table-column type="selection" width="55" @click.stop v-if="auth.deleteProject"></el-table-column>
  79. <el-table-column label="楼栋-单元" v-slot:default="{ row }">
  80. {{row.buildingUnit}}
  81. </el-table-column>
  82. <el-table-column label="房号" v-slot:default="{ row }">
  83. {{row.roomNumber}}
  84. </el-table-column>
  85. <el-table-column label="建筑面积" prop="buildArea"></el-table-column>
  86. <el-table-column label="套内面积" prop="roomArea"></el-table-column>
  87. <el-table-column label="状态" v-slot:default="{row}" width="90">
  88. <div class="status" :class="{interactive:row.auditStatus !== draftStatus || row.reviewer || row.reviewTime}" @click="(row.auditStatus !== draftStatus || row.reviewer || row.reviewTime) && selectRow(row)">
  89. <span>{{getStatusName(row.auditStatus)}}</span>
  90. <template v-if="row.auditStatus !== draftStatus || row.reviewer || row.reviewTime">
  91. <i class="el-icon-document" v-if="row.auditStatus !== noAdoptStatus && row.auditStatus !== noComAdoptStatus"></i>
  92. <i class="el-icon-warning-outline error" v-else></i>
  93. </template>
  94. </div>
  95. </el-table-column>
  96. <el-table-column label="维护人" prop="maintenanceman"></el-table-column>
  97. <el-table-column label="更新时间" prop="lastupdateTime"></el-table-column>
  98. <el-table-column label="审核人" prop="reviewer"></el-table-column>
  99. <el-table-column label="审核时间" prop="reviewTime"></el-table-column>
  100. <el-table-column label="操作" width="180" v-slot:default="{row}">
  101. <span
  102. class="oper-span"
  103. @click="(~[draftStatus, noAdoptStatus, noComAdoptStatus].indexOf(row.auditStatus)) && editHouse(row)"
  104. :class="{disable: !~[draftStatus, noAdoptStatus, noComAdoptStatus].indexOf(row.auditStatus)}"
  105. v-if="auth.update"
  106. >
  107. 编辑VR
  108. </span>
  109. <span
  110. class="oper-span"
  111. @click="() => {~[adoptStatus, uplineStatus].indexOf(row.auditStatus) && (queryVR.show = true ,queryVR.data = row)}"
  112. :class="{disable: (!~[adoptStatus, uplineStatus].indexOf(row.auditStatus))}" >
  113. 查看
  114. </span>
  115. <!-- <span
  116. class="oper-span"
  117. @click="~[draftStatus, noAdoptStatus, noComAdoptStatus].indexOf(row.status) && editHouse(row)"
  118. :class="{disable: !~[draftStatus, noAdoptStatus, noComAdoptStatus].indexOf(row.status)}"
  119. v-if="auth.deleteProject">
  120. 删除
  121. </span>
  122. -->
  123. <span
  124. class="oper-span"
  125. v-if="user.role !== 'group'"
  126. :class="{disable: user.role === 'group' || adoptStatus === row.auditStatus || uplineStatus === row.auditStatus}"
  127. @click.stop="(user.role !== 'group' && row.auditStatus !== adoptStatus && row.auditStatus !== uplineStatus) && examine(row)">
  128. {{ ~[draftStatus, noAdoptStatus, adoptStatus, noComAdoptStatus].indexOf(row.auditStatus) ? '提审' : '撤回'}}
  129. </span>
  130. <span
  131. class="oper-span"
  132. @click="(~[draftStatus, noAdoptStatus, noComAdoptStatus].indexOf(row.auditStatus)) && delModel(row)"
  133. :class="{disable: !~[draftStatus, noAdoptStatus, noComAdoptStatus].indexOf(row.auditStatus)}"
  134. v-if="auth.update"
  135. >
  136. 删除VR
  137. </span>
  138. <span class="oper-span" @click.stop="shareRow(row)" v-if="false">预览</span>
  139. <span class="oper-span" @click.stop="offlineItem(row)" v-if="row.auditStatus === uplineStatus" :class="{disable: !~[adoptStatus, uplineStatus].indexOf(row.auditStatus)}">
  140. {{row.auditStatus === uplineStatus ? '下线' : '上线' }}
  141. </span>
  142. </el-table-column>
  143. </el-table>
  144. <com-pagination
  145. @size-change="pag.sizeChange"
  146. @current-change="pag.currentChange"
  147. :current-page="pag.state.currPage"
  148. :page-size="pag.state.size"
  149. layout="total, sizes, prev, pager, next, jumper"
  150. :total="pag.state.total"/>
  151. </div>
  152. <com-query-vr v-model:show="queryVR.show" :data="queryVR.data" v-if="queryVR.show" />
  153. <com-record v-model:show="recordData.show" :data="recordData.id" v-if="recordData.show" />
  154. <com-share
  155. :setLogo="auth.update"
  156. v-if="shareData.show"
  157. v-model:show="shareData.show"
  158. :items="shareData.data" />
  159. <com-vrlist v-model:show="selectVR.show" v-if="selectVR.show" @enter="item => updateModel(item)" v-model="selectVR.value" />
  160. </template>
  161. <script>
  162. import axios from 'axios'
  163. import {ref, watch} from 'vue'
  164. import getTableState from '@/state/tableRef'
  165. import comHead from "@/components/head";
  166. import comShare from "../share";
  167. import comRecord from "./record";
  168. import comVrlist from "./vrlist";
  169. import comQueryVr from "./queryvr";
  170. import qrcode from 'qrcode'
  171. import auth from "@/state/viewAuth";
  172. import comPagination from "@/components/pagination";
  173. import router from '@/router'
  174. import { dateFormat, strToParams } from '@/util'
  175. import user from '@/state/user'
  176. import {
  177. EXAMINE_SHOW_SELECT_STATUS_2 as EXAMINE_SHOW_SELECT_STATUS,
  178. EXAMINE_SHOW_SELECT_STATUS_3 as EXAMINE_SHOW_SELECT_STATUS_TEXT,
  179. EXAMINE_DRAFT_STATUS,
  180. UN_REQ_NUM,
  181. EXAMINE_NO_ADOPT_STATUS,
  182. EXAMINE_NO_AUDIT_STATUS,
  183. EXAMINE_NO_COM_ADOPT_STATUS,
  184. EXAMINE_ADOPT_STATUS,
  185. EXAMINE_UP_ONLINE_STATUS,
  186. EXAMINE_NO_COM_AUDIT_STATUS,
  187. getName,
  188. getRedirectRoomAuditBody
  189. } from '@/constant'
  190. import {
  191. getCommunityByHouseId,
  192. getSecondHouseList,
  193. deleteSecondHouse,
  194. auditSecondHouse,
  195. dismissSecondHouse,
  196. secondHouseOnline
  197. } from '@/request/config'
  198. const getTimeMapSearch = (searchKey, search) => {
  199. const time = ref(null)
  200. const start = `${searchKey}Start`
  201. const end = `${searchKey}End`
  202. watch(time, () => {
  203. if (time.value) {
  204. search.value.state[start] = dateFormat(new Date(time.value[0]), 'yyyy-MM-dd hh:mm:ss').toString()
  205. search.value.state[end] = dateFormat(new Date(time.value[1]), 'yyyy-MM-dd 23:59:59').toString()
  206. } else {
  207. search.value.state[start] = search.value.state[end] = ''
  208. }
  209. })
  210. watch(
  211. () => search.value.state[start],
  212. () => {
  213. if (!search.value.state[start]) {
  214. time.value = null
  215. }
  216. }
  217. )
  218. watch(
  219. () => search.value.state[end],
  220. () => {
  221. if (!search.value.state[end]) {
  222. time.value = null
  223. }
  224. }
  225. )
  226. return time
  227. }
  228. export default {
  229. name: 'housing',
  230. setup() {
  231. const headList = ref([{ name: "二手房", value: 1 }])
  232. const state = getTableState({
  233. getUrl: getSecondHouseList,
  234. delUrl: deleteSecondHouse,
  235. pagAttr: {listMap: {roomid: 'id'}},
  236. searchAttr: {
  237. gardenId: router.currentRoute.value.params.id,
  238. cityId: router.currentRoute.value.params.cityId,
  239. buildingUnit: "",
  240. roomNumber: '',
  241. maintenanceman: '',
  242. auditStatus: UN_REQ_NUM,
  243. reviewer: '',
  244. updateTimeStart: '',
  245. updateTimeEnd: '',
  246. createTimeStart: '',
  247. createTimeEnd: '',
  248. reviewTimeStart: '',
  249. reviewTimeEnd: '',
  250. insideAreaSnd: '',
  251. insideAreaStar: '',
  252. constructionAreaStar: '',
  253. constructionAreaEnd: '',
  254. }
  255. })
  256. state.dataList.value._delete = async (data) => {
  257. await axios.post(deleteSecondHouse, {}, {params: {roomid: data.roomid} })
  258. }
  259. const names = ref([])
  260. const initNames = ref([])
  261. return {
  262. ...state,
  263. headList,
  264. auth,
  265. user,
  266. initNames,
  267. names,
  268. updateTime: getTimeMapSearch('updateTime', state.search),
  269. auditTime: getTimeMapSearch('auditTime', state.search),
  270. createTime: getTimeMapSearch('createTime', state.search),
  271. reviewTime: getTimeMapSearch('reviewTime', state.search)
  272. };
  273. },
  274. data() {
  275. return {
  276. gardenName: '',
  277. status: EXAMINE_SHOW_SELECT_STATUS,
  278. uplineStatus: EXAMINE_UP_ONLINE_STATUS,
  279. draftStatus: EXAMINE_DRAFT_STATUS,
  280. noAdoptStatus: EXAMINE_NO_ADOPT_STATUS,
  281. noComAdoptStatus: EXAMINE_NO_COM_ADOPT_STATUS,
  282. noAuditStatus: EXAMINE_NO_AUDIT_STATUS,
  283. adoptStatus: EXAMINE_ADOPT_STATUS,
  284. recordData: { show: false, id: 0 },
  285. selectVR: { show: false, data: null, value: null },
  286. queryVR: { show: false, data: null },
  287. shareData: { show: false, data: 0 }
  288. }
  289. },
  290. methods: {
  291. clickEstateItem(ev, item) {
  292. if (item.disable) {
  293. ev.stopPropagation()
  294. }
  295. },
  296. getStatusName: getName(EXAMINE_SHOW_SELECT_STATUS_TEXT),
  297. selectRow(data) {
  298. this.recordData.show = true
  299. this.recordData.id = data.vrId
  300. },
  301. async shareRow(raw, type = 1) {
  302. if (!raw.vRUrl) {
  303. return this.$confirm('暂无有效链接', '提示')
  304. }
  305. const vrLink = process.env.VUE_APP_DOMAIN + raw.vRUrl
  306. const QrCode = await qrcode.toDataURL(vrLink)
  307. let shareItems = [{
  308. QrCode: QrCode,
  309. type: 'building',
  310. noRandow: true,
  311. houseTitle: raw.buildingUnit + raw.roomNumber,
  312. epcVrLink: vrLink.replace('hengda.html', 'epc.html'),
  313. vrLink: vrLink,
  314. innerVrLink: process.env.VUE_APP_INTRANET_DOMAIN + raw.vRUrl,
  315. status: raw.auditStatus,
  316. }]
  317. if (type === 1) {
  318. this.shareData.show = true
  319. this.shareData.data = shareItems
  320. } else {
  321. window.open(type === 1 ? shareItems[0].vrLink : shareItems[0].epcVrLink)
  322. }
  323. },
  324. openHouse(data) {
  325. return this.shareRow(data)
  326. // if (data.status === this.adoptStatus) {
  327. // window.open(data.vrLink)
  328. // } else {
  329. // window.open(data.innerVrLink)
  330. // }
  331. },
  332. async offlineItem(data) {
  333. data.cityId = this.$route.params.cityId
  334. data.gardenName = this.gardenName
  335. if (data.auditStatus !== EXAMINE_ADOPT_STATUS && data.auditStatus !== EXAMINE_UP_ONLINE_STATUS) return;
  336. if (data.auditStatus === EXAMINE_UP_ONLINE_STATUS) {
  337. if (!(await this.$msgbox({
  338. message: '下线后VR链接将无法继续访问,确定要下线吗?',
  339. title: '下线',
  340. showCancelButton: true,
  341. confirmButtonText: '下线',
  342. cancelButtonText: '取消',
  343. }))) {
  344. return;
  345. }
  346. }
  347. const status = data.auditStatus === EXAMINE_UP_ONLINE_STATUS ? EXAMINE_DRAFT_STATUS : EXAMINE_UP_ONLINE_STATUS
  348. await axios.post(
  349. secondHouseOnline,
  350. getRedirectRoomAuditBody(data, status)
  351. )
  352. this.$alert((status === EXAMINE_UP_ONLINE_STATUS ? '上' : '下') + '线成功', '提示')
  353. this.dataList.refer()
  354. },
  355. async examine(data) {
  356. data.cityId = this.$route.params.cityId
  357. data.gardenName = this.gardenName
  358. console.log(data)
  359. if (~[this.draftStatus, this.noAdoptStatus, this.adoptStatus, this.noComAdoptStatus].indexOf(data.auditStatus)) {
  360. await this.shareRow(data)
  361. if (!this.shareData.show) {
  362. return;
  363. }
  364. this.shareData.show = false
  365. // await axios.post(auditSecondHouse, getRedirectRoomAuditBody(data, EXAMINE_NO_COM_AUDIT_STATUS))
  366. const status = user.value.role === 'group' || user.value.role === 'admin' || user.value.role === 'region'
  367. ? EXAMINE_NO_AUDIT_STATUS
  368. : EXAMINE_NO_COM_AUDIT_STATUS
  369. await axios.post(auditSecondHouse, getRedirectRoomAuditBody(data, status))
  370. // data.auditId = res.data.auditId
  371. this.$alert('提审成功', '提示')
  372. } else {
  373. await axios.post(dismissSecondHouse, getRedirectRoomAuditBody(data, EXAMINE_DRAFT_STATUS))
  374. this.$alert('撤销成功', '提示')
  375. }
  376. this.dataList.refer()
  377. },
  378. resetSearch() {
  379. let type = this.search.state.type
  380. this.search.reset()
  381. this.search.state.type = type
  382. },
  383. async updateModel(raw) {
  384. const upload = {
  385. vrModelName: raw.sceneName,
  386. num: raw.num,
  387. vrCover: raw.thumb,
  388. vRUrl: `/hengda.html?m=${raw.num}&prodId=${this.search.state.gardenId}&houseId=${this.selectVR.data.roomlistingId}&businessType=2`
  389. }
  390. await axios.post(dismissSecondHouse, getRedirectRoomAuditBody({
  391. ...this.selectVR.data,
  392. ...upload
  393. }, EXAMINE_DRAFT_STATUS, '', this.selectVR.data.roomlistingId))
  394. this.selectVR.show = false
  395. this.dataList.refer()
  396. },
  397. async delModel(row) {
  398. if (!row.vRUrl) {
  399. return this.$alert('暂无有效链接', '提示')
  400. }
  401. await axios.post(dismissSecondHouse, getRedirectRoomAuditBody({
  402. ...row,
  403. vrCover: '',
  404. vRUrl: '',
  405. }, EXAMINE_DRAFT_STATUS, '', this.selectVR.data.roomlistingId))
  406. this.selectVR.show = false
  407. this.dataList.refer()
  408. },
  409. editHouse(item, isView = 0) {
  410. if (isView) {
  411. const params = strToParams(item.vRUrl.substr(item.vRUrl.indexOf('?')))
  412. const link = '/epc.html?m=' + params.m + '&token=' + user.value.token
  413. return window.open(link)
  414. } else {
  415. if (item.vRUrl) {
  416. const params = strToParams(item.vRUrl.substr(item.vRUrl.indexOf('?')))
  417. this.selectVR.value = params.m
  418. } else {
  419. this.selectVR.value = null
  420. }
  421. this.selectVR.show = true
  422. this.selectVR.data = item
  423. }
  424. // let link = process.env.VUE_APP_PREFIX + '/sh_house/edit.html?m=' + item.id + '&h=' + item.gardenId + '&canView=' + isView
  425. // window.open(link)
  426. }
  427. },
  428. watch: {
  429. '$route': {
  430. immediate: true,
  431. async handler(newVal, oldVal) {
  432. if (newVal.name !== "secondHouse" || (this.search.state.gardenId === newVal.params.id && oldVal)) return;
  433. try {
  434. this.search.state.gardenId = newVal.params.id
  435. let res = await axios.get(getCommunityByHouseId, { params: { gardenId: newVal.params.id } })
  436. this.gardenName = res.data.gardenName
  437. document.querySelector('.player').querySelector('.active span').textContent = this.gardenName
  438. this.gardenId = res.data.gardenId
  439. } catch (e) {
  440. this.$router.back()
  441. }
  442. }
  443. }
  444. },
  445. components: {
  446. comVrlist,
  447. comQueryVr,
  448. "com-head": comHead,
  449. "com-record": comRecord,
  450. "com-share": comShare,
  451. "com-pagination": comPagination
  452. },
  453. };
  454. </script>
  455. <style lang="less">
  456. .my-autocomplete {
  457. li {
  458. line-height: normal;
  459. padding: 0 !important;
  460. .item-layout {
  461. padding: 7px !important;
  462. display: flex;
  463. justify-content: space-between;
  464. span {
  465. flex: none;
  466. }
  467. }
  468. .item-layout.disable {
  469. cursor: not-allowed;
  470. *{
  471. color: #c0c4cc;
  472. }
  473. }
  474. .name {
  475. text-overflow: ellipsis;
  476. overflow: hidden;
  477. line-height: 16px;
  478. }
  479. .addr {
  480. text-overflow: ellipsis;
  481. overflow: hidden;
  482. line-height: 16px;
  483. }
  484. .highlighted .addr {
  485. color: #ddd;
  486. }
  487. }
  488. }
  489. .info-from .el-form-item__content{
  490. width: calc(100% - 100px);
  491. }
  492. .info-from .el-form-item__content .inline-input {
  493. width: 100%;
  494. }
  495. </style>
  496. <style lang="scss" scoped>
  497. .add-input {
  498. width: 250px;
  499. margin: 40px auto;
  500. padding-left: 80px;
  501. position: relative;
  502. label {
  503. position: absolute;
  504. left: 0;
  505. top: 50%;
  506. transform: translateY(-50%);
  507. span {
  508. color: var(--primaryColor);
  509. }
  510. }
  511. }
  512. .cover-img {
  513. width: 32px;
  514. height: 32px;
  515. }
  516. .status {
  517. &.interactive {
  518. cursor: pointer;
  519. }
  520. i {
  521. vertical-align: text-bottom;
  522. margin-left: 5px;
  523. font-size: 1.2rem;
  524. color: rgb(144,144,150);
  525. &.error {
  526. color: var(--primaryColor);
  527. }
  528. }
  529. }
  530. </style>