1
0

index.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. <template>
  2. <view class="facility">
  3. <wd-sticky :z-index="10">
  4. <view class="facility-top">
  5. <wd-search :placeholder-left="true" placeholder="请输入内容" v-model="state.text">
  6. <template #suffix>
  7. <view style="display: flex;align-items: center;margin: 0 20rpx;">
  8. <wd-button size="small" @click="onClickSearch">
  9. 搜索
  10. </wd-button>
  11. </view>
  12. </template>
  13. </wd-search>
  14. <wd-tabs slidable="always" v-model="state.tabValue" @change="onChangeTabs">
  15. <wd-tab v-for="(item, index) in state.tabList" :title="item.label" :name="item.value" :key="index" />
  16. </wd-tabs>
  17. </view>
  18. </wd-sticky>
  19. <view class="facility-list">
  20. <view class="facility-list-item" v-for="(item, index) in state.list" :key="index"
  21. @click="onClickNavigate(item.id)">
  22. <view class="facility-list-item-sign">
  23. {{ item.sign }}
  24. </view>
  25. <wd-img height="300rpx" mode="heightFix" :src="item.url" />
  26. <view style="padding: 0 10rpx;">
  27. <view class="facility-list-item-title">
  28. {{ item.title }}
  29. </view>
  30. <view class="facility-list-item-text">
  31. {{ item.description }}
  32. </view>
  33. </view>
  34. </view>
  35. </view>
  36. </view>
  37. </template>
  38. <script lang="ts" setup>
  39. import { reactive } from 'vue';
  40. import { onShow, onReachBottom } from '@dcloudio/uni-app';
  41. import { apis } from '@/apis';
  42. interface State {
  43. text?: string,
  44. tabList: {
  45. label: string,
  46. value: string,
  47. }[],
  48. tabValue?: string,
  49. list: {
  50. id: string,
  51. url: string,
  52. sign: string,
  53. title: string,
  54. description: string,
  55. }[],
  56. page: {
  57. pageNumber: number,
  58. pageSize: number,
  59. total: number,
  60. },
  61. };
  62. const state = reactive<State>({
  63. text: undefined,
  64. tabList: [],
  65. tabValue: undefined,
  66. list: [],
  67. page: {
  68. pageNumber: 1,
  69. pageSize: 20,
  70. total: 0,
  71. },
  72. });
  73. const api = {
  74. // 获取区域列表
  75. fetchRegionList: async () => {
  76. try {
  77. const data = {
  78. dictType: 'region_type',
  79. };
  80. const res = await apis.fetchRegionList(data);
  81. const list = res.rows.map((item: any) => {
  82. return {
  83. label: item.dictLabel,
  84. value: item.dictValue,
  85. }
  86. });
  87. state.tabList = list;
  88. state.tabValue = list.length ? list[0].value : undefined;
  89. } catch (error: any) {
  90. console.error(error);
  91. }
  92. },
  93. // 获取设施列表
  94. fetchFacilityList: async (concat?: boolean) => {
  95. uni.showLoading({
  96. title: '加载中',
  97. });
  98. try {
  99. const data = {
  100. facilitiesTitle: state.text,
  101. dictType: state.tabValue,
  102. pageNum: state.page.pageNumber,
  103. pageSize: state.page.pageSize,
  104. };
  105. const res = await apis.fetchFacilityList(data);
  106. const list = res.rows.map((item: any) => {
  107. return {
  108. id: item.facilitiesId,
  109. url: item.sysimg[0].url,
  110. sign: item.facilitiesName,
  111. title: item.facilitiesTitle,
  112. description: item.facilitiesDesc,
  113. };
  114. });
  115. state.list = concat ? state.list.concat(list) : list;
  116. state.page = {
  117. ...state.page,
  118. total: res.total,
  119. };
  120. } catch (error: any) {
  121. console.error(error);
  122. } finally {
  123. uni.hideLoading();
  124. }
  125. },
  126. }
  127. const init = async () => {
  128. // 获取区域列表
  129. await api.fetchRegionList();
  130. // 获取设施列表
  131. await api.fetchFacilityList();
  132. };
  133. onShow(() => {
  134. state.page = {
  135. ...state.page,
  136. pageNumber: 1,
  137. };
  138. init();
  139. });
  140. // 更改分页
  141. const onChangePagination = async () => {
  142. const { pageNumber, pageSize, total } = state.page;
  143. if (total > pageNumber * pageSize) {
  144. state.page = {
  145. ...state.page,
  146. pageNumber: pageNumber + 1,
  147. }
  148. // 获取设施列表
  149. await api.fetchFacilityList(true);
  150. }
  151. }
  152. onReachBottom(() => {
  153. onChangePagination();
  154. });
  155. // 点击搜索
  156. const onClickSearch = async () => {
  157. state.page = {
  158. ...state.page,
  159. pageNumber: 1,
  160. };
  161. // 获取设施列表
  162. await api.fetchFacilityList();
  163. }
  164. // 更改标签页
  165. const onChangeTabs = async ({ name }: { name: string }) => {
  166. state.tabValue = name;
  167. state.page = {
  168. ...state.page,
  169. pageNumber: 1,
  170. };
  171. // 获取设施列表
  172. await api.fetchFacilityList();
  173. }
  174. // 点击跳转
  175. const onClickNavigate = (id: string) => {
  176. uni.navigateTo({
  177. url: `/pages/facility/facilityDetail/index?id=${id}`,
  178. });
  179. }
  180. </script>
  181. <style lang="scss" scoped>
  182. .facility {
  183. &-top {
  184. width: 100vw;
  185. border-bottom: 2rpx solid $border-color;
  186. }
  187. &-list {
  188. padding: 0 20rpx;
  189. display: flex;
  190. flex-wrap: wrap;
  191. margin-top: 20rpx;
  192. &-item {
  193. width: calc(50% - 10rpx);
  194. background: #F4F4F4;
  195. border-radius: $border-radius-base;
  196. margin-bottom: 20rpx;
  197. position: relative;
  198. overflow: hidden;
  199. &-sign {
  200. width: 85%;
  201. height: 50rpx;
  202. padding: 0 10rpx;
  203. background: rgba(0, 0, 0, 0.4);
  204. border-top-right-radius: $border-radius-base;
  205. display: flex;
  206. align-items: center;
  207. font-size: $font-size-mini;
  208. color: #FFFFFF;
  209. overflow: hidden;
  210. white-space: nowrap;
  211. text-overflow: ellipsis;
  212. position: absolute;
  213. top: 250rpx;
  214. left: 0;
  215. z-index: 2;
  216. }
  217. &-title {
  218. font-weight: bold;
  219. display: -webkit-box;
  220. -webkit-box-orient: vertical;
  221. -webkit-line-clamp: 2;
  222. line-clamp: 2;
  223. overflow: hidden;
  224. text-overflow: ellipsis;
  225. margin-bottom: 10rpx;
  226. }
  227. &-text {
  228. width: 100%;
  229. max-height: 300rpx;
  230. color: $gray-color;
  231. overflow: hidden;
  232. margin-bottom: 10rpx;
  233. }
  234. }
  235. &-item:nth-child(odd) {
  236. margin-right: 10rpx;
  237. }
  238. &-item:nth-child(even) {
  239. margin-left: 10rpx;
  240. }
  241. }
  242. }
  243. </style>