siteServe.vue 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. <template>
  2. <view class="serve-content" :style="{'height':height +'px' }">
  3. <view class="serve-title">可以办事项</view>
  4. <view class="serve-search">
  5. <input confirm-type="search" ref="searchInputRef" class="search-input" :auto-blur="true" type="text"
  6. placeholder="搜索服务事项" v-model="matterName" @confirm="getMatterList" />
  7. <view class="search-btn" @click.stop="getMatterList"> 搜 索 </view>
  8. </view>
  9. <view class="matter-loading" v-if="MatterListLoading">
  10. <u-loading-icon />
  11. </view>
  12. <view class="serve" :style="{'height':scrollH +'px' }" v-else-if="MatterList">
  13. <scroll-view class="scroll-lable" :style="{'height':scrollH +'px' }" scroll-y="true"
  14. :show-scrollbar="false">
  15. <template v-for="(value, key , index) in MatterList">
  16. <view :class="['lable one-row' , index === activeIndex ? 'active-lable' : '' ]"
  17. @click.stop="openTyle(index)">{{ key }}</view>
  18. </template>
  19. </scroll-view>
  20. <scroll-view class="scroll-val" :scroll-into-view="scrollIntoView" @scroll="scrollService"
  21. :style="{'height':scrollH +'px' }" scroll-y="true" :show-scrollbar="false">
  22. <template v-for="(value, key , index) in MatterList">
  23. <view class="val-content" :id="`service_${index}`">
  24. <view class="val-name">{{key}}</view>
  25. <template v-for="item in (value || [])">
  26. <!-- @click.stop="LookMatterDetails(item)" -->
  27. <view class="val" >
  28. <text class="val-text one-row">{{ item.name }}</text>
  29. <!-- <svg t="1734508422065" class="val-icon" viewBox="0 0 1024 1024" version="1.1"
  30. xmlns="http://www.w3.org/2000/svg" p-id="4279"
  31. xmlns:xlink="http://www.w3.org/1999/xlink">
  32. <path
  33. 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"
  34. p-id="4280"></path>
  35. </svg> -->
  36. </view>
  37. </template>
  38. </view>
  39. </template>
  40. </scroll-view>
  41. </view>
  42. <view v-else class="matter-loading">
  43. <u-empty mode="data" :iconSize="emptySize" text="暂无可办事项" />
  44. </view>
  45. </view>
  46. </template>
  47. <script>
  48. import { getMapMatterList_Api } from "@/api/map.js"
  49. export default {
  50. props: {
  51. height: {
  52. type: Number,
  53. default: 0
  54. },
  55. mapLocationId: {
  56. type: Number | String,
  57. default: null
  58. }
  59. },
  60. data() {
  61. return {
  62. scrollH: 0,
  63. matterName: '',
  64. MatterList: null,
  65. MatterListLoading: false,
  66. activeIndex: undefined,
  67. scrollIntoView: undefined,
  68. scrollStatus: true,
  69. oldScrollNum: 0,
  70. RightTopArr: [],
  71. emptySize: uni.upx2px(130)
  72. }
  73. },
  74. watch: {
  75. height: {
  76. handler(newH) {
  77. // 区域高度 - 标题高度 - 搜索区域高度
  78. this.scrollH = newH - uni.upx2px(60) - uni.upx2px(100);
  79. },
  80. immediate: true
  81. },
  82. mapLocationId: {
  83. handler(newId) {
  84. this.getMatterList(newId)
  85. },
  86. immediate: true
  87. },
  88. },
  89. created() {
  90. },
  91. methods: {
  92. getLabel(item) {
  93. console.log("getLabel = ", item)
  94. const label = Object.keys(item)[0];
  95. return label;
  96. },
  97. getMatterList() {
  98. this.MatterListLoading = true;
  99. const parmas = {
  100. mapLocationId: this.mapLocationId,
  101. matterName: this.matterName
  102. };
  103. getMapMatterList_Api(parmas).then(res => {
  104. const keys = Object.keys(res || {});
  105. if (keys && keys.length > 0) {
  106. this.MatterList = res;
  107. this.activeIndex = 0;
  108. this.getNodesInfo()
  109. } else {
  110. this.MatterList = null;
  111. this.activeIndex = undefined;
  112. }
  113. }).catch(err => {
  114. this.MatterList = null;
  115. this.activeIndex = undefined;
  116. }).finally(() => {
  117. setTimeout(() => {
  118. this.MatterListLoading = false;
  119. }, 300)
  120. })
  121. },
  122. openTyle(index) {
  123. this.scrollStatus = false;
  124. this.activeIndex = index
  125. this.scrollIntoView = `service_${index}`
  126. setTimeout(() => {
  127. this.scrollStatus = true;
  128. }, 200)
  129. },
  130. scrollService(event) {
  131. // console.log('stopPropagation ' , event)
  132. // event.stopPropagation();
  133. if (!this.scrollStatus) return
  134. const { scrollTop } = event.detail;
  135. let scrollNums = scrollTop;
  136. if (this.oldScrollNum > scrollTop) {
  137. scrollNums = scrollTop + 80;
  138. };
  139. try {
  140. this.RightTopArr.forEach((el, index) => {
  141. let data = this.RightTopArr[index];
  142. if (scrollNums >= data.height && index == this.RightTopArr.length - 1 ? true :
  143. scrollNums < this.RightTopArr[parseInt(index) + 1].height) {
  144. this.activeIndex = index;
  145. throw new Error()
  146. }
  147. })
  148. } catch (e) {
  149. //TODO handle the exception
  150. }
  151. this.oldScrollNum = scrollTop;
  152. },
  153. // 查看事项详情
  154. LookMatterDetails(item) {
  155. // pages/map/matterDetails
  156. // 在起始页面跳转到test.vue页面,并监听test.vue发送过来的事件数据
  157. uni.navigateTo({
  158. url: '/pages/map/matterDetails',
  159. success: function(res) {
  160. // 通过eventChannel向被打开页面传送数据
  161. res.eventChannel.emit('acceptDataFromOpenerPage', item)
  162. }
  163. })
  164. },
  165. getNodesInfo() {
  166. new Promise(resolve => {
  167. let selectorQuery = uni.createSelectorQuery();
  168. // 获取节点的位置信息
  169. selectorQuery.selectAll('.val-content').boundingClientRect((rects) => {
  170. // 如果节点尚未生成,rects值为[](因为用selectAll,所以返回的是数组),循环调用执行
  171. if (!rects.length) {
  172. setTimeout(() => {
  173. this.$nextTick(() => {
  174. this.getNodesInfo();
  175. })
  176. }, 10);
  177. return;
  178. }
  179. this.RightTopArr = [];
  180. // 生成之后开始添加进去数组
  181. rects.forEach((rect) => {
  182. // 这里减去rects[0].top,是因为第一项顶部不是贴到导航栏=>每一个商品距离顶部的高度,如果此页面顶部没有其他的view那就不用减去rects[0].top,自己视情况而定。
  183. let tops = rect.top - rects[0].top;
  184. this.RightTopArr.push({
  185. height: tops,
  186. id: rect.id
  187. });
  188. })
  189. resolve();
  190. }).exec()
  191. });
  192. },
  193. }
  194. }
  195. </script>
  196. <style lang="scss" scoped>
  197. .serve-content {
  198. border-top: 1rpx solid #F0F0F0;
  199. .serve-title {
  200. color: #7D7D7D;
  201. font-size: 32rpx;
  202. height: 60rpx;
  203. line-height: 60rpx;
  204. }
  205. .serve-search {
  206. width: 100%;
  207. padding: 20rpx 0;
  208. display: flex;
  209. justify-content: space-between;
  210. align-items: stretch;
  211. .search-input {
  212. flex: 1;
  213. height: 60rpx;
  214. border: 1rpx solid #F0F0F0;
  215. border-radius: 10rpx;
  216. padding: 0 15rpx;
  217. font-size: 28rpx;
  218. }
  219. .search-btn {
  220. width: 120rpx;
  221. background-color: #3291F8;
  222. margin-left: 20rpx;
  223. line-height: 60rpx;
  224. text-align: center;
  225. color: #fff;
  226. font-size: 28rpx;
  227. border-radius: 10rpx;
  228. }
  229. }
  230. .serve {
  231. width: 100%;
  232. overflow: hidden;
  233. display: flex;
  234. align-items: stretch;
  235. .scroll-lable {
  236. width: 200rpx;
  237. .lable {
  238. width: 100%;
  239. height: 80rpx;
  240. font-size: 30rpx;
  241. line-height: 80rpx;
  242. text-align: center;
  243. border-left: 6rpx solid transparent;
  244. padding: 0 10rpx;
  245. }
  246. .active-lable {
  247. color: #3291F8;
  248. font-weight: 600;
  249. border-left-color: #3291F8;
  250. }
  251. }
  252. .scroll-val {
  253. width: calc(100% - 200rpx);
  254. padding: 0 0 0 20rpx;
  255. .val-content {
  256. // height: 300px;
  257. }
  258. .val-name {
  259. font-size: 30rpx;
  260. padding: 15rpx 0;
  261. }
  262. .val {
  263. width: 100%;
  264. height: 100rpx;
  265. padding: 0 20rpx;
  266. border: 1rpx solid #F0F0F0;
  267. display: flex;
  268. justify-content: space-between;
  269. align-items: center;
  270. margin-bottom: 20rpx;
  271. .val-text {
  272. flex: 1;
  273. width: 1px;
  274. font-size: 30rpx;
  275. }
  276. .val-icon {
  277. width: 34rpx;
  278. height: 34rpx;
  279. }
  280. }
  281. }
  282. }
  283. .matter-loading {
  284. padding-top: 50rpx;
  285. text-align: center;
  286. }
  287. }
  288. </style>