siteServeH6.vue 12 KB

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