long-waterflow-page.uvue 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. <template>
  2. <waterflow :id="id" class="grid" :bounces="false" :scroll-y="true" :custom-nested-scroll="true"
  3. main-axis-gap="8px" cross-axis-gap="8px" cross-axis-count=2
  4. @scrolltolower="loadData(null)" associative-container="nested-scroll-view">
  5. <flow-item class="flow-item" v-for="(item, _) in datagrid" :key="item.plugin_id" type=1>
  6. <view class="flow-item-icon">
  7. <image class="flow-item-icon-image" :src="item.plugin_img_link" mode="aspectFit"></image>
  8. </view>
  9. <view class="flow-item-fill">
  10. <view class="flex-row">
  11. <text class="title">{{item.plugin_name}}</text>
  12. </view>
  13. <view>
  14. <text class="description-text">{{item.plugin_intro}}</text>
  15. </view>
  16. <text class="icon-star">{{convertToStarUnicode(item.score)}}</text>
  17. <view class="tag-grid">
  18. <text class="tag-item" v-for="(item2, index2) in item.tags.slice(0,1)" :key="index2">{{item2}}</text>
  19. </view>
  20. <view class="flex-row update-date">
  21. <text class="author">{{item.author_name}}</text>
  22. </view>
  23. <view class="flex-row update-date">
  24. <text class="update-date-text">更新日期</text>
  25. <text class="update-date-value">{{item.update_date}}</text>
  26. </view>
  27. </view>
  28. </flow-item type="20">
  29. <flow-item slot="load-more" class="loading" type=6>
  30. <uni-loading :loading="loading" color="#999" :text="loadingText"></uni-loading>
  31. </flow-item>
  32. </waterflow>
  33. </template>
  34. <script>
  35. const SERVER_URL = "https://unidemo.dcloud.net.cn/plugin/uniappx-plugin-list"
  36. const PAGE_SIZE = 10; // 最大值 10
  37. type flowItem = {
  38. plugin_id : number,
  39. plugin_img_link : string,
  40. plugin_name : string,
  41. plugin_intro : string,
  42. score : number,
  43. tags : Array<string>,
  44. update_date : string,
  45. author_name : string,
  46. }
  47. type ResponseDataType = {
  48. code : number,
  49. data : flowItem[]
  50. }
  51. export default {
  52. props: {
  53. type: {
  54. type: String,
  55. default: ''
  56. },
  57. preload: {
  58. type: Boolean,
  59. default: false
  60. },
  61. id: {
  62. type: String,
  63. default: ''
  64. }
  65. },
  66. data() {
  67. return {
  68. loading: false,
  69. datagrid: [] as flowItem[],
  70. isEnded: false,
  71. loadingError: '',
  72. currentPage: 1
  73. }
  74. },
  75. computed: {
  76. loadingText() : string {
  77. if (this.loading) {
  78. return "加载中..."
  79. } else if (this.isEnded) {
  80. return "没有更多了"
  81. } else if (this.loadingError.length > 0) {
  82. return this.loadingError
  83. } else {
  84. return ""
  85. }
  86. }
  87. },
  88. created() {
  89. if (this.preload) {
  90. this.loadData(null)
  91. }
  92. },
  93. methods: {
  94. refreshData(loadComplete : (() => void) | null) {
  95. this.datagrid.length = 0
  96. this.currentPage = 1
  97. this.loadData(loadComplete)
  98. },
  99. loadData(loadComplete : (() => void) | null) {
  100. if (this.loading || this.isEnded) {
  101. return
  102. }
  103. this.loading = true
  104. uni.request<ResponseDataType>({
  105. url: SERVER_URL,
  106. data: {
  107. type: this.type,
  108. page: this.currentPage,
  109. page_size: PAGE_SIZE
  110. },
  111. success: (res) => {
  112. const responseData = res.data
  113. if (responseData == null) {
  114. return
  115. }
  116. this.datagrid.push(...responseData.data)
  117. if (responseData.data.length == 0) {
  118. this.isEnded = true
  119. } else {
  120. this.currentPage++
  121. }
  122. },
  123. fail: (err) => {
  124. this.loadingError = err.errMsg
  125. },
  126. complete: () => {
  127. this.loading = false
  128. if (loadComplete != null) {
  129. loadComplete()
  130. }
  131. }
  132. })
  133. },
  134. // score 0 ~ 50
  135. convertToStarUnicode(score : number) : string {
  136. const fill_code = '\ue879'
  137. const half_code = '\ue87a'
  138. const null_code = '\ue87b'
  139. const fillStarCount = parseInt(score / 10 % 10 + '')
  140. const halfStarCount = score % 10 >= 5 ? 1 : 0
  141. const nullStarCount = 5 - fillStarCount - halfStarCount
  142. let result = ''
  143. if (fillStarCount > 0) { result += fill_code.repeat(fillStarCount) }
  144. if (halfStarCount > 0) { result += half_code.repeat(halfStarCount) }
  145. if (nullStarCount > 0) { result += null_code.repeat(nullStarCount) }
  146. return result
  147. }
  148. }
  149. }
  150. </script>
  151. <style>
  152. @font-face {
  153. font-family: "UtsStarIcons";
  154. src: url('@/static/fonts/icon-star.ttf');
  155. }
  156. .grid {
  157. flex: 1;
  158. background-color: #f7f7f7;
  159. }
  160. .flow-item {
  161. flex-direction: column;
  162. border-radius: 5px;
  163. background-color: #ffffff;
  164. }
  165. .flow-item-icon {
  166. position: relative;
  167. }
  168. .flow-item-icon-image {
  169. width: 100%;
  170. }
  171. .flow-item-fill {
  172. flex: 1;
  173. padding: 5px;
  174. }
  175. .description-text {
  176. font-size: 13px;
  177. color: #666;
  178. line-height: 19px;
  179. }
  180. .icon-star {
  181. font-family: "UtsStarIcons";
  182. font-size: 16px;
  183. font-style: normal;
  184. color: #ffca3e;
  185. letter-spacing: 3px;
  186. }
  187. .tag-grid {
  188. flex-direction: row;
  189. margin-top: 5px;
  190. }
  191. .tag-item {
  192. font-size: 12px;
  193. background-color: #EFF9F0;
  194. color: #639069;
  195. border-radius: 20px;
  196. margin-right: 5px;
  197. padding: 2px 5px;
  198. }
  199. .update-date {
  200. margin-top: 10px;
  201. }
  202. .update-date-text {
  203. font-size: 12px;
  204. color: #888888;
  205. }
  206. .update-date-value {
  207. font-size: 12px;
  208. color: #777777;
  209. margin-left: 5px;
  210. }
  211. .author {
  212. font-size: 12px;
  213. color: #008000;
  214. }
  215. .loading {
  216. padding: 30px;
  217. align-items: center;
  218. height: 80px;
  219. }
  220. .flex-row {
  221. flex-direction: row;
  222. }
  223. </style>