siteServeH6.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. <template>
  2. <view class="serve-content" :style="{'height':height +'px' }">
  3. <view class="serve-title">可办事项</view>
  4. <view class="serve-search">
  5. <view class="search-input">
  6. <svg t="1733904658291" class="search-icon" viewBox="0 0 1024 1024" version="1.1"
  7. xmlns="http://www.w3.org/2000/svg" p-id="5981" xmlns:xlink="http://www.w3.org/1999/xlink">
  8. <path
  9. d="M174.545 465.455c0-18.619 16.291-34.91 34.91-34.91s34.909 16.291 34.909 34.91c0 121.018 100.072 221.09 221.09 221.09 18.619 0 34.91 16.291 34.91 34.91s-16.291 34.909-34.91 34.909c-160.581 0-290.909-130.328-290.909-290.91z m290.91 360.727c200.145 0 360.727-160.582 360.727-360.727S665.6 104.727 465.455 104.727 104.727 265.31 104.727 465.455 265.31 826.182 465.455 826.182z m323.49-76.8L961.164 921.6c13.963 13.964 13.963 34.91 0 48.873-13.964 13.963-34.91 13.963-48.873 0L737.745 795.927c-74.472 60.51-169.89 97.746-272.29 97.746C228.073 896 34.909 702.836 34.909 465.455S228.073 34.909 465.455 34.909 896 228.073 896 465.455c0 109.381-39.564 209.454-107.055 283.927z"
  10. p-id="5982">
  11. </path>
  12. </svg>
  13. <input confirm-type="search" class="input" placeholder-class="placeholder" ref="searchInputRef"
  14. :auto-blur="true" type="text" placeholder="搜索服务事项" v-model="matterName" @confirm="getMatterList" />
  15. </view>
  16. <view class="search-btn" @click.stop="getMatterList"> 搜 索 </view>
  17. </view>
  18. <view class="matter-loading" v-if="MatterListLoading">
  19. <u-loading-icon />
  20. </view>
  21. <view class="serve" :style="{'height':scrollH +'px' , paddingTop:servePT + 'px' }" v-else-if="MatterList">
  22. <scroll-view class="scroll-lable" :style="{'height':scrollH +'px' }" scroll-y="true"
  23. :show-scrollbar="false">
  24. <template v-for="(value, key , index) in MatterList">
  25. <view :class="['lable one-row' , index === activeIndex ? 'active-lable' : '' ]"
  26. @click.stop="openTyle(index)">{{ key }}</view>
  27. </template>
  28. </scroll-view>
  29. <scroll-view class="scroll-val" :scroll-into-view="scrollIntoView" @scroll="scrollService"
  30. :style="{'height':scrollH +'px' }" scroll-y="true" :show-scrollbar="false">
  31. <template v-for="(value, key , index) in MatterList">
  32. <view class="val-content" :id="`service_${index}`">
  33. <view class="val-name">{{key}}</view>
  34. <template v-for="(t_v, t_k , t_i) in (value || [])">
  35. <view class="val">
  36. <view
  37. :class="['val-label' , showKey === getShowKey(index , t_i ) ? 'avtive-val-label' : '']"
  38. @click.stop="setShowKey(index , t_i)">
  39. <text class="val-text one-row">{{ t_k }}</text>
  40. <template v-if="t_v && t_v.length">
  41. <svg t="1734508422065" class="val-icon" viewBox="0 0 1024 1024" version="1.1"
  42. xmlns="http://www.w3.org/2000/svg" p-id="4279"
  43. xmlns:xlink="http://www.w3.org/1999/xlink">
  44. <path
  45. d="M492.675886 904.817574L885.696074 511.797385 492.675886 118.777197c-12.258185-12.258185-12.432147-32.892131 0.187265-45.51052 12.707416-12.707416 32.995485-12.703323 45.511543-0.187265l411.660734 411.660734c7.120165 7.120165 10.163477 17.065677 8.990768 26.624381 1.500167 9.755178-1.5104 20.010753-8.990768 27.491121L538.374694 950.515359c-12.258185 12.258185-32.892131 12.432147-45.511543-0.187265-12.707416-12.707416-12.703323-32.995485-0.187265-45.51052z"
  46. p-id="4280"></path>
  47. </svg>
  48. </template>
  49. </view>
  50. <!-- showKey -->
  51. <template v-if="showKey === getShowKey(index , t_i )">
  52. <view class="project-box">
  53. <view class="val-item" v-for="item in (t_v || [])"
  54. @click.stop="LookMatterDetails(item)">
  55. {{item.name}}
  56. </view>
  57. </view>
  58. </template>
  59. </view>
  60. </template>
  61. </view>
  62. </template>
  63. </scroll-view>
  64. </view>
  65. <view v-else class="matter-loading">
  66. <u-empty mode="data" :iconSize="emptySize" text="暂无可办事项" />
  67. </view>
  68. </view>
  69. </template>
  70. <script>
  71. import { getMapMatterListH6_Api } from "@/api/map.js"
  72. export default {
  73. props: {
  74. height: {
  75. type: Number,
  76. default: 0
  77. },
  78. mapLocationId: {
  79. type: Number | String,
  80. default: null
  81. }
  82. },
  83. data() {
  84. return {
  85. showKey: '',
  86. scrollH: 0,
  87. matterName: '',
  88. MatterList: null,
  89. MatterListLoading: false,
  90. activeIndex: undefined,
  91. scrollIntoView: undefined,
  92. scrollStatus: true,
  93. oldScrollNum: 0,
  94. RightTopArr: [],
  95. servePT: uni.upx2px(20),
  96. emptySize: uni.upx2px(130)
  97. }
  98. },
  99. watch: {
  100. height: {
  101. handler(newH) {
  102. // 区域高度 - 标题高度 - 搜索区域高度
  103. this.scrollH = newH - uni.upx2px(80) - uni.upx2px(100) - this.servePT;
  104. },
  105. immediate: true
  106. },
  107. mapLocationId: {
  108. handler(newId) {
  109. this.getMatterList(newId)
  110. },
  111. immediate: true
  112. },
  113. },
  114. created() {
  115. },
  116. methods: {
  117. getShowKey(k_1, k_2) {
  118. return `${k_1}${k_2}`
  119. },
  120. setShowKey(index, t_i) {
  121. const k = this.getShowKey(index, t_i);
  122. if (!this.showKey || this.showKey !== k) {
  123. this.showKey = k;
  124. } else {
  125. this.showKey = ''
  126. };
  127. },
  128. getLabel(item) {
  129. console.log("getLabel = ", item)
  130. const label = Object.keys(item)[0];
  131. return label;
  132. },
  133. getMatterList() {
  134. this.MatterListLoading = true;
  135. const parmas = {
  136. mapLocationId: this.mapLocationId,
  137. matterName: this.matterName
  138. };
  139. getMapMatterListH6_Api(parmas).then(res => {
  140. const keys = Object.keys(res || {});
  141. if (keys && keys.length > 0) {
  142. this.MatterList = res;
  143. this.activeIndex = 0;
  144. this.getNodesInfo()
  145. } else {
  146. this.MatterList = null;
  147. this.activeIndex = undefined;
  148. }
  149. }).catch(err => {
  150. this.MatterList = null;
  151. this.activeIndex = undefined;
  152. }).finally(() => {
  153. setTimeout(() => {
  154. this.MatterListLoading = false;
  155. }, 300)
  156. })
  157. },
  158. openTyle(index) {
  159. this.scrollStatus = false;
  160. this.activeIndex = index
  161. this.scrollIntoView = `service_${index}`
  162. setTimeout(() => {
  163. this.scrollStatus = true;
  164. }, 200)
  165. },
  166. scrollService(event) {
  167. // console.log('stopPropagation ' , event)
  168. // event.stopPropagation();
  169. if (!this.scrollStatus) return
  170. const { scrollTop } = event.detail;
  171. let scrollNums = scrollTop;
  172. if (this.oldScrollNum > scrollTop) {
  173. scrollNums = scrollTop + 80;
  174. };
  175. try {
  176. this.RightTopArr.forEach((el, index) => {
  177. let data = this.RightTopArr[index];
  178. if (scrollNums >= data.height && index == this.RightTopArr.length - 1 ? true :
  179. scrollNums < this.RightTopArr[parseInt(index) + 1].height) {
  180. this.activeIndex = index;
  181. throw new Error()
  182. }
  183. })
  184. } catch (e) {
  185. //TODO handle the exception
  186. }
  187. this.oldScrollNum = scrollTop;
  188. },
  189. // 查看事项详情
  190. LookMatterDetails(item) {
  191. const { handleMethod, serviceObject, processingConditions, processingMaterial, processingDays } = item ||
  192. {};
  193. if (handleMethod || serviceObject || processingConditions || processingMaterial || processingDays > 0) {
  194. uni.navigateTo({
  195. url: '/pages/map/matterDetails',
  196. success: function(res) {
  197. // 通过eventChannel向被打开页面传送数据
  198. res.eventChannel.emit('acceptDataFromOpenerPage', item)
  199. }
  200. })
  201. }
  202. // pages/map/matterDetails
  203. // 在起始页面跳转到test.vue页面,并监听test.vue发送过来的事件数据
  204. },
  205. getNodesInfo() {
  206. new Promise(resolve => {
  207. let selectorQuery = uni.createSelectorQuery();
  208. // 获取节点的位置信息
  209. selectorQuery.selectAll('.val-content').boundingClientRect((rects) => {
  210. // 如果节点尚未生成,rects值为[](因为用selectAll,所以返回的是数组),循环调用执行
  211. if (!rects.length) {
  212. setTimeout(() => {
  213. this.$nextTick(() => {
  214. this.getNodesInfo();
  215. })
  216. }, 10);
  217. return;
  218. }
  219. this.RightTopArr = [];
  220. // 生成之后开始添加进去数组
  221. rects.forEach((rect) => {
  222. // 这里减去rects[0].top,是因为第一项顶部不是贴到导航栏=>每一个商品距离顶部的高度,如果此页面顶部没有其他的view那就不用减去rects[0].top,自己视情况而定。
  223. let tops = rect.top - rects[0].top;
  224. this.RightTopArr.push({
  225. height: tops,
  226. id: rect.id
  227. });
  228. })
  229. resolve();
  230. }).exec()
  231. });
  232. },
  233. }
  234. }
  235. </script>
  236. <style lang="scss" scoped>
  237. $pad_: 30rpx;
  238. .serve-content {
  239. border-top: 1rpx solid #F0F0F0;
  240. .serve-title {
  241. height: 90rpx;
  242. line-height: 40rpx;
  243. padding: 30rpx $pad_ 0;
  244. font-size: 28rpx;
  245. font-family: PingFang SC, PingFang SC-Bold;
  246. font-weight: 700;
  247. color: #1a1a1a;
  248. }
  249. .serve-search {
  250. width: 100%;
  251. padding: 0 $pad_;
  252. display: flex;
  253. justify-content: space-between;
  254. align-items: stretch;
  255. .search-input {
  256. flex: 1;
  257. height: 80rpx;
  258. border: 1rpx solid #F0F0F0;
  259. border-radius: 10rpx 0 0 10rpx;
  260. padding: 0 15rpx 0 30rpx;
  261. font-size: 28rpx;
  262. display: flex;
  263. align-items: center;
  264. background-color: #F5F5F5;
  265. .search-icon {
  266. width: 33rpx;
  267. height: 33rpx;
  268. path {
  269. fill: #333333;
  270. }
  271. }
  272. .input {
  273. height: 100%;
  274. padding-left: 11rpx;
  275. }
  276. .placeholder {
  277. color: #B3B3B3;
  278. }
  279. }
  280. .search-btn {
  281. width: 134rpx;
  282. background-color: #61A8FF;
  283. line-height: 80rpx;
  284. text-align: center;
  285. color: #fff;
  286. font-size: 28rpx;
  287. border-radius: 0px 10rpx 10rpx 0px;
  288. font-family: PingFang SC, PingFang SC-Regular;
  289. font-weight: 400;
  290. }
  291. }
  292. .serve {
  293. width: 100%;
  294. overflow: hidden;
  295. display: flex;
  296. align-items: stretch;
  297. .scroll-lable {
  298. width: 183rpx;
  299. background-color: #f7f9fb;
  300. padding: 13rpx 7rpx 13rpx 0;
  301. .lable {
  302. width: 100%;
  303. height: 90rpx;
  304. font-size: 26rpx;
  305. line-height: 90rpx;
  306. text-align: center;
  307. padding: 0 10rpx;
  308. border-radius: 0px 20rpx 20rpx 0px;
  309. color: #808080;
  310. }
  311. .active-lable {
  312. background: #ffffff;
  313. font-family: PingFang SC, PingFang SC-Bold;
  314. font-weight: 700;
  315. color: #3b86f7;
  316. position: relative;
  317. &:before {
  318. content: '';
  319. position: absolute;
  320. left: 0;
  321. top: 50%;
  322. width: 16rpx;
  323. height: 40rpx;
  324. transform: translate(-50%, -50%);
  325. background: #3b86f7;
  326. border-radius: 8rpx;
  327. }
  328. }
  329. }
  330. .scroll-val {
  331. width: calc(100% - 160rpx);
  332. padding: 13rpx 30rpx 30rpx 26rpx;
  333. .val-content {
  334. // height: 300px;
  335. }
  336. .val-name {
  337. height: 90rpx;
  338. font-size: 28rpx;
  339. font-weight: 600;
  340. color: #1a1a1a;
  341. line-height: 90rpx;
  342. color: #1A1A1A;
  343. }
  344. .val {
  345. width: 100%;
  346. // border: 1rpx solid #F0F0F0;
  347. // margin-bottom: 20rpx;
  348. transition: height 1s;
  349. path {
  350. fill: #666666;
  351. }
  352. .val-label {
  353. width: 100%;
  354. height: 110rpx;
  355. display: flex;
  356. justify-content: space-between;
  357. align-items: center;
  358. border-bottom: 1rpx solid #F2F2F2;
  359. font-size: 26rpx;
  360. font-family: PingFang SC, PingFang SC-Regular;
  361. font-weight: 400;
  362. color: #1a1a1a;
  363. .val-icon {
  364. width: 34rpx;
  365. height: 34rpx;
  366. transition: transform 0.3s;
  367. }
  368. }
  369. .avtive-val-label {
  370. .val-text {
  371. font-size: 26rpx;
  372. font-family: PingFang SC, PingFang SC-Bold;
  373. font-weight: 700;
  374. color: #61a8ff;
  375. }
  376. .val-icon {
  377. transform: rotate(90deg);
  378. path {
  379. fill: #61a8ff;
  380. }
  381. }
  382. }
  383. .project-box {
  384. background-color: #f5f5f5;
  385. padding: 7rpx 20rpx;
  386. .val-item {
  387. padding: 20rpx 0;
  388. width: 100%;
  389. min-height: 83rpx;
  390. font-size: 24rpx;
  391. line-height: 34rpx;
  392. font-family: PingFang SC, PingFang SC-Regular;
  393. font-weight: 400;
  394. color: #666666;
  395. display: flex;
  396. align-items: center;
  397. flex-wrap: wrap;
  398. border-bottom: 1rpx solid #E6E6E6;
  399. &:last-child {
  400. border-bottom: none;
  401. }
  402. }
  403. }
  404. // .val-item {
  405. // width: 100%;
  406. // min-height: 100rpx;
  407. // padding: 10rpx 20rpx;
  408. // display: flex;
  409. // justify-content: space-between;
  410. // align-items: center;
  411. // border-top: 1rpx solid #F0F0F0;
  412. // &:first-child {
  413. // border-top: none;
  414. // }
  415. // }
  416. // .val-label {
  417. // font-weight: 600;
  418. // .val-text {
  419. // flex: 1;
  420. // width: 1px;
  421. // font-size: 30rpx;
  422. // }
  423. // .val-icon {
  424. // width: 34rpx;
  425. // height: 34rpx;
  426. // transition: transform 0.3s;
  427. // }
  428. // .avtive-icon {
  429. // transform: rotate(90deg);
  430. // }
  431. // }
  432. }
  433. }
  434. }
  435. .matter-loading {
  436. padding-top: 50rpx;
  437. text-align: center;
  438. }
  439. }
  440. </style>