tm-pagination.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. <template>
  2. <view class="tm-pagination flex-center">
  3. <view v-if="tal" class="flex-start flex-wrap flex-between fulled">
  4. <tm-button :fllowTheme="false" :shadow="4" :icon-size="24"
  5. :font-color="nowIndex==1||disabled?'grey':color_tmeme" :black="black_tmeme" @click="tv_pre"
  6. :disabled="nowIndex==1||disabled" theme="white" :item-class="round?'rounded':''" block height="64" width="64"
  7. icon="icon-angle-left"></tm-button>
  8. <block v-for="(item,index) in items " :key="index">
  9. <tm-button :fllowTheme="false" :shadow="4" :disabled="disabled" :black="black_tmeme"
  10. :theme="item==nowIndex?color_tmeme:'white'" @click="clicPages(item)" block
  11. :item-class="round?'rounded':''" height="64" width="64">
  12. {{item}}
  13. </tm-button>
  14. </block>
  15. <tm-button :fllowTheme="false" :shadow="4" :icon-size="24"
  16. :font-color="nowIndex==tal||disabled?'grey':color_tmeme" :black="black_tmeme" theme="white"
  17. @click="tv_next" :disabled="nowIndex==tal||disabled?true:false" :item-class="round?'rounded':''" block
  18. height="64" width="64" icon="icon-angle-right">
  19. </tm-button>
  20. </view>
  21. </view>
  22. </template>
  23. <script>
  24. /**
  25. * 分页
  26. * @property {Function} change 页面改变时触发。
  27. * @property {Number} page = [] 默认:1当前页码,必须使用page.sync
  28. * @property {Number} total-visible = [] 默认:5最大可见页数
  29. * @property {Number} total = [] 默认:0总条数。
  30. * @property {Number} size = [] 默认:8每页的数量。
  31. * @property {Boolean} round = [] 默认:false,是否圆形按钮。
  32. * @property {Boolean} black = [] 默认:false,是否暗黑模式
  33. * @property {Boolean} disabled = [] 默认:false,禁用
  34. * @property {String} color = [] 默认:primary,选中的主题色
  35. * @example <tm-pagination :page.sync="page" :total="100"></tm-pagination>
  36. */
  37. import tmButton from "@/tm-vuetify/components/tm-button/tm-button.vue"
  38. export default {
  39. components: {
  40. tmButton
  41. },
  42. name: "tm-pagination",
  43. props: {
  44. total: {
  45. type: Number,
  46. default: 0
  47. },
  48. // 最大可见按钮数量。
  49. totalVisible: {
  50. type: Number,
  51. default: 5
  52. },
  53. // 当前页码。需要page.sync同步。
  54. page: {
  55. type: Number,
  56. default: 1
  57. },
  58. // 每页的数量 。
  59. size: {
  60. type: Number,
  61. default: 10
  62. },
  63. // 是否圆形按钮。
  64. round: {
  65. type: Boolean,
  66. default: false
  67. },
  68. // 是否暗黑模式
  69. black: {
  70. type: Boolean | String,
  71. default: null
  72. },
  73. // 主题色
  74. color: {
  75. type: String,
  76. default: 'primary'
  77. },
  78. disabled: {
  79. type: Boolean,
  80. default: false
  81. },
  82. // 跟随主题色的改变而改变。
  83. fllowTheme: {
  84. type: Boolean | String,
  85. default: true
  86. }
  87. },
  88. watch: {
  89. page: function(val) {
  90. this.init()
  91. }
  92. },
  93. computed: {
  94. black_tmeme: function() {
  95. if (this.black !== null) return this.black;
  96. return this.$tm.vx.state().tmVuetify.black;
  97. },
  98. color_tmeme: function() {
  99. if (this.$tm.vx.state().tmVuetify.color !== null && this.$tm.vx.state().tmVuetify.color && this
  100. .fllowTheme) {
  101. return this.$tm.vx.state().tmVuetify.color;
  102. }
  103. return this.color;
  104. },
  105. //总共的页码。
  106. tal: function() {
  107. if (this.total <= this.size) return 1;
  108. let isInt = this.total % this.size;
  109. let ds = this.total / this.size;
  110. return isInt == 0 ? Math.floor(ds) : Math.floor(ds) + 1;
  111. },
  112. items: function() {
  113. const totalVisible = parseInt(this.totalVisible, 10)<=5?5:parseInt(this.totalVisible, 10);
  114. if(this.tal<=totalVisible){
  115. return this.range(1, this.tal)
  116. }
  117. if (totalVisible === 0) {
  118. return []
  119. }
  120. const maxLength = Math.min(
  121. Math.max(0, totalVisible) || this.tal,
  122. Math.max(0, this.maxButtons) || this.tal,
  123. this.tal
  124. )
  125. if (this.tal <= maxLength) {
  126. return this.range(1, this.tal)
  127. }
  128. const even = maxLength % 2 === 0 ? 1 : 0
  129. const left = Math.floor(maxLength / 2)
  130. const right = this.tal - left + 1 + even
  131. if (this.page > left && this.page < right) {
  132. const firstItem = 1
  133. const lastItem = this.tal
  134. const start = this.page - left + 2
  135. const end = this.page + left - 2 - even
  136. const secondItem = start - 1 === firstItem + 1 ? 2 : '...'
  137. const beforeLastItem = end + 1 === lastItem - 1 ? end + 1 : '...'
  138. return [1, secondItem, ...this.range(start, end), beforeLastItem, this.tal]
  139. } else if (this.page === left) {
  140. const end = this.page + left - 1 - even
  141. return [...this.range(1, end), '...', this.tal]
  142. } else if (this.page === right) {
  143. const start = this.page - left + 1
  144. return [1, '...', ...this.range(start, this.tal)]
  145. } else {
  146. return [
  147. ...this.range(1, left),
  148. '...',
  149. ...this.range(right, this.tal),
  150. ]
  151. }
  152. },
  153. },
  154. data() {
  155. return {
  156. nowIndex: 1,
  157. maxButtons: 0,
  158. };
  159. },
  160. mounted() {
  161. let t = this;
  162. this.$Querey('.tm-pagination').then(res => {
  163. let w = res[0].width;
  164. t.maxButtons = Math.floor((w - uni.upx2px(20)) / uni.upx2px(64))
  165. })
  166. },
  167. methods: {
  168. clicPages(index) {
  169. if (index == '...') return;
  170. this.$emit('input', index)
  171. this.$emit('update:page', index)
  172. this.$emit('prev')
  173. this.$emit('change',index)
  174. },
  175. tv_pre() {
  176. this.$emit('input', this.page - 1)
  177. this.$emit('update:page', this.page - 1)
  178. this.$emit('prev')
  179. this.$emit('change',this.page - 1)
  180. },
  181. tv_next() {
  182. this.$emit('input', this.page + 1)
  183. this.$emit('update:page', this.page + 1)
  184. this.$emit('next')
  185. this.$emit('change',this.page + 1)
  186. },
  187. range(from = 1, to) {
  188. const range = []
  189. from = from > 0 ? from : 1
  190. for (let i = from; i <= to; i++) {
  191. range.push(i)
  192. }
  193. return range
  194. },
  195. init() {
  196. this.nowIndex = null;
  197. uni.$tm.sleep(100).then(() => (this.nowIndex = this.page))
  198. },
  199. },
  200. }
  201. </script>
  202. <style lang="scss">
  203. </style>