gallery.vue 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. <template>
  2. <view class="app-page">
  3. <!-- 顶部切换 -->
  4. <view class="e-fixed" v-if="category.list.length > 2">
  5. <tm-tabs color="light-blue" v-model="category.activeIndex" range-key="displayName" :list="category.list"
  6. align="left" @change="fnOnCategoryChange"></tm-tabs>
  7. </view>
  8. <!-- 占位区域 -->
  9. <view style="width: 100vw;height: 90rpx;"></view>
  10. <!-- 加载区域 -->
  11. <view v-if="loading != 'success'" class="loading-wrap">
  12. <tm-skeleton model="card"></tm-skeleton>
  13. <tm-skeleton model="card"></tm-skeleton>
  14. <tm-skeleton model="card"></tm-skeleton>
  15. <tm-skeleton model="card"></tm-skeleton>
  16. </view>
  17. <!-- 内容区域 -->
  18. <view class="content" v-else>
  19. <view v-if="dataList.length == 0" class="content-empty">
  20. <!-- 空布局 -->
  21. <tm-empty icon="icon-shiliangzhinengduixiang-" label="博主还没有分享图片~"></tm-empty>
  22. </view>
  23. <block v-else>
  24. <tm-flowLayout v-if="globalAppSettings.gallery.useWaterfull" @click="fnOnClick" ref="wafll">
  25. <template v-slot:left="{ hdata }">
  26. <tm-translate animation-name="fadeUp">
  27. <view class="card round-3 overflow white">
  28. <tm-images :previmage="false" :src="hdata.item.spec.cover"
  29. @click="fnPreview(hdata.item)"></tm-images>
  30. </view>
  31. </tm-translate>
  32. </template>
  33. <template v-slot:right="{ hdata }">
  34. <tm-translate animation-name="fadeUp">
  35. <view class="card round-3 overflow white">
  36. <tm-images :previmage="false" :src="hdata.item.spec.cover"
  37. @click="fnPreview(hdata.item)"></tm-images>
  38. </view>
  39. </tm-translate>
  40. </template>
  41. </tm-flowLayout>
  42. <block v-else>
  43. <block v-for="(item, index) in dataList" :key="index">
  44. <tm-translate animation-name="fadeUp" :wait="calcAniWait(index)">
  45. <view class="round-3 shadow-2 overflow white mb-24">
  46. <tm-images :previmage="false" :src="item.spec.cover"
  47. @click="fnPreview(item)"></tm-images>
  48. </view>
  49. </tm-translate>
  50. </block>
  51. </block>
  52. <tm-flotbutton @click="fnToTopPage" color="light-blue" size="m" icon="icon-angle-up"></tm-flotbutton>
  53. <view class="load-text">{{ loadMoreText }}</view>
  54. </block>
  55. </view>
  56. </view>
  57. </template>
  58. <script>
  59. import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
  60. import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
  61. import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
  62. import tmTags from '@/tm-vuetify/components/tm-tags/tm-tags.vue';
  63. import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
  64. import tmIcons from '@/tm-vuetify/components/tm-icons/tm-icons.vue';
  65. import tmImages from '@/tm-vuetify/components/tm-images/tm-images.vue';
  66. import tmFlowLayout from '@/tm-vuetify/components/tm-flowLayout/tm-flowLayout.vue';
  67. import tmTabs from '@/tm-vuetify/components/tm-tabs/tm-tabs.vue';
  68. export default {
  69. components: {
  70. tmSkeleton,
  71. tmTranslate,
  72. tmFlotbutton,
  73. tmTags,
  74. tmEmpty,
  75. tmIcons,
  76. tmImages,
  77. tmFlowLayout,
  78. tmTabs
  79. },
  80. data() {
  81. return {
  82. isBlackTheme: false,
  83. loading: 'loading',
  84. category: {
  85. activeIndex: 0,
  86. activeValue: '',
  87. list: []
  88. },
  89. queryParams: {
  90. size: 10,
  91. page: 1,
  92. group: ""
  93. },
  94. cache: {
  95. dataList: [],
  96. total: 0
  97. },
  98. isLoadMore: false,
  99. loadMoreText: '',
  100. result: {},
  101. dataList: []
  102. };
  103. },
  104. filters: {
  105. filterTakeTime(val) {
  106. return uni.$tm.dayjs(val).format('DD/MM/YYYY');
  107. }
  108. },
  109. onLoad() {
  110. this.fnSetPageTitle('个人图库');
  111. this.fnGetCategory();
  112. },
  113. onPullDownRefresh() {
  114. this.dataList = []
  115. this.isLoadMore = false;
  116. this.queryParams.page = 1;
  117. this.fnGetData();
  118. },
  119. onReachBottom(e) {
  120. if (this.result.hasNext) {
  121. this.queryParams.page += 1;
  122. this.isLoadMore = true;
  123. this.fnGetData();
  124. } else {
  125. uni.showToast({
  126. icon: 'none',
  127. title: '没有更多数据了'
  128. });
  129. }
  130. },
  131. methods: {
  132. fnOnCategoryChange(index) {
  133. this.fnResetSetAniWaitIndex();
  134. this.dataList = [];
  135. this.queryParams.group = this.category.list[index].name;
  136. this.queryParams.page = 1;
  137. this.fnToTopPage();
  138. this.fnGetData();
  139. },
  140. fnGetCategory() {
  141. this.$httpApi.v2.getPhotoGroupList({
  142. page: 1,
  143. size: 9999
  144. }).then(res => {
  145. this.category.list = res.items.map(item => {
  146. return {
  147. name: item.metadata.name,
  148. displayName: item.spec.displayName
  149. }
  150. });
  151. if (this.category.list.length !== 0) {
  152. this.queryParams.group = this.category.list[0].name;
  153. this.fnGetData();
  154. }
  155. });
  156. },
  157. fnGetData() {
  158. // 设置状态为加载中
  159. if (!this.isLoadMore) {
  160. this.loading = 'loading';
  161. }
  162. this.loadMoreText = '';
  163. this.$httpApi.v2
  164. .getPhotoListByGroupName(this.queryParams)
  165. .then(res => {
  166. console.log("相册 res", res)
  167. this.result = res;
  168. this.loading = 'success';
  169. if (res.items.length != 0) {
  170. const _list = res.items.map((item, index) => {
  171. item.spec.cover = this.$utils.checkImageUrl(item.spec.cover);
  172. return item;
  173. });
  174. this.fnCacheDataList(_list);
  175. if (this.globalAppSettings.gallery.useWaterfull) {
  176. this.dataList = _list;
  177. this.$nextTick(() => {
  178. this.$refs.wafll.pushData(_list);
  179. });
  180. } else {
  181. this.dataList = this.dataList.concat(_list);
  182. }
  183. }
  184. this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
  185. })
  186. .catch(err => {
  187. console.error(err);
  188. this.loading = 'error';
  189. this.waterfall.loading = 'finish';
  190. this.loadMoreText = '加载失败,请下拉刷新!';
  191. })
  192. .finally(() => {
  193. setTimeout(() => {
  194. uni.hideLoading();
  195. uni.stopPullDownRefresh();
  196. }, 500);
  197. });
  198. },
  199. // 缓存数据
  200. fnCacheDataList(dataList) {
  201. if (this.queryParams.page == 1) {
  202. this.cache.dataList = dataList;
  203. } else {
  204. this.cache.dataList = [...this.cache.dataList, ...dataList];
  205. }
  206. },
  207. // 瀑布流组件点击事件
  208. fnOnClick(data) {
  209. console.log('点击数据', data);
  210. },
  211. // 预览
  212. fnPreview(item) {
  213. const index = this.cache.dataList.findIndex(x => x.spec.cover == x.spec.cover);
  214. uni.previewImage({
  215. current: index,
  216. urls: this.cache.dataList.map(x => x.spec.cover),
  217. indicator: 'number',
  218. loop: true
  219. });
  220. }
  221. }
  222. };
  223. </script>
  224. <style lang="scss" scoped>
  225. .app-page {
  226. width: 100vw;
  227. min-height: 100vh;
  228. display: flex;
  229. flex-direction: column;
  230. padding-bottom: 24rpx;
  231. background-color: #fafafa;
  232. &.is-balck {
  233. background-color: #212121;
  234. }
  235. }
  236. .content {
  237. box-sizing: border-box;
  238. padding: 0 24rpx;
  239. padding-top: 24rpx;
  240. .content-empty {
  241. height: 60vh;
  242. display: flex;
  243. align-items: center;
  244. justify-content: center;
  245. }
  246. }
  247. .loading-wrap {
  248. box-sizing: border-box;
  249. padding: 24rpx;
  250. }
  251. .card {
  252. box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.03);
  253. }
  254. </style>