tm-album.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. <template>
  2. <view class="tm-album">
  3. <view class="tm-album-body flex flex-wrap" :class="[`ml--${gutter}`]" :style="{width:alb_wk_body_size+'rpx'}">
  4. <block v-for="(item,index) in listData" :key="index">
  5. <view v-if="index<max-1" :style="{width:alb_body_size+'rpx'}" class="tm-album-item">
  6. <view @click="clickAlbum(item,index)" :class="[`py-${item[textKey]?0:gutter}`,`px-${gutter}`]">
  7. <view :style="{width:alb_size+'rpx',height:height||alb_size+'rpx'}" class="relative flex-center">
  8. <tm-images :round="round" :width="alb_size1" :height="alb_size1" mode="widthFix" :src="item[rangKey]"></tm-images>
  9. <view class="tm-album-action absolute fulled fulled-height t-0 l-0" :class="[
  10. actionsPos=='top'?'flex-top-end':'',
  11. actionsPos=='bottom'?'flex-end-right':'',
  12. ]">
  13. <slot name="actions" :item="{data:item,index:index}"></slot>
  14. </view>
  15. </view>
  16. <view v-if="item[textKey]" class="py-24 text-align-center text-overflow">
  17. <slot name="default" :text="{text:item[textKey]}">
  18. <text class="text-size-s ">{{item[textKey]}}</text>
  19. </slot>
  20. </view>
  21. </view>
  22. </view>
  23. </block>
  24. <view v-if="listData.length>max-1" :style="{width:alb_body_size+'rpx'}" class="tm-album-item " :class="[`round-${round}`,black_tmeme?'bk':'']">
  25. <view @click="more" :class="[`px-${gutter}`]">
  26. <view :style="{width:alb_size+'rpx',height:height||alb_size+'rpx'}" class="relative flex-center flex-col" :class="[`round-${round}`,color_tmeme]">
  27. <view><text class="iconfont icon-angle-right text-size-xl"></text></view>
  28. <view class="text-size-s mt-12">更多</view>
  29. </view>
  30. </view>
  31. </view>
  32. </view>
  33. </view>
  34. </template>
  35. <script>
  36. /**
  37. * 相册集
  38. * @property {Array} list = [] 数据列表,可以是对象数组,也可以是字符串数组,也可对象和字符串数组混合型。
  39. * @property {Number} grid = [] 默认:4,默认一行几个。
  40. * @property {Number} height = [] 默认:0,默认宽度和高度是相同的。指定相册集的高度。如果指定了高度将不使用计算的高度。
  41. * @property {Number} gutter = [] 默认:4,图片之间的间隙。
  42. * @property {Number} round = [] 默认:3,项目的圆角
  43. * @property {Number} max = [] 默认:999,最大可展示数量,超过不显示,以更多项目代替。
  44. * @property {String} rang-key = [] 默认:'src',如果list的项目是对象,则需要提供图片字段名称
  45. * @property {String} text-key = [] 默认:'text',如果list的项目是对象,则需要提供图片标题字段名称
  46. * @property {Boolean|String} preview = [] 默认:true,点击图片是否可以预览。
  47. * @property {Boolean|String} actions-pos = [bottom|top] 默认:bottom,可选bottom,top,内部压在图片上方的元素位置。内容可在插槽actions中布局。
  48. * @property {String} color = [] 默认:primary,主题色名称,显示更多项目的背景主题色。
  49. */
  50. import tmImages from '@/tm-vuetify/components/tm-images/tm-images.vue';
  51. export default {
  52. name:"tm-album",
  53. components: {
  54. tmImages
  55. },
  56. props: {
  57. list: {
  58. type: Array,
  59. default: ()=>[]
  60. },
  61. //指定相册集的高度。如果指定了高度将不使用计算的高度。
  62. height:{
  63. type:Number,
  64. default:0
  65. },
  66. grid:{
  67. type:Number,
  68. default:4
  69. },
  70. gutter:{
  71. type:Number,
  72. default:4
  73. },
  74. round:{
  75. type:Number,
  76. default:3
  77. },
  78. max:{
  79. type:Number,
  80. default:999
  81. },
  82. rangKey: {
  83. type: String,
  84. default: 'src'
  85. },
  86. textKey: {
  87. type: String,
  88. default: 'text'
  89. },
  90. preview:{
  91. type:Boolean,
  92. default:true
  93. },
  94. actionsPos:{
  95. type:String,
  96. default:'bottom',//bottom,top
  97. },
  98. black:{
  99. type:Boolean,
  100. default:null
  101. },
  102. // 跟随主题色的改变而改变。
  103. fllowTheme:{
  104. type:Boolean|String,
  105. default:true
  106. },
  107. color:{
  108. type:String,
  109. default:"primary"
  110. },
  111. },
  112. data() {
  113. return {
  114. alb_size:0,
  115. alb_body_size:0,
  116. alb_wk_body_size:0,
  117. listAlbum:[],
  118. alb_size1:180
  119. };
  120. },
  121. watch:{
  122. list:{
  123. deep:true,
  124. handler(){
  125. this.listData = this.chuliList(this.list)
  126. }
  127. }
  128. },
  129. created(){
  130. this.listData = this.chuliList(this.list)
  131. },
  132. computed: {
  133. black_tmeme: function() {
  134. if (this.black !== null) return this.black;
  135. return this.$tm.vx.state().tmVuetify.black;
  136. },
  137. color_tmeme:function(){
  138. if(this.$tm.vx.state().tmVuetify.color!==null&&this.$tm.vx.state().tmVuetify.color && this.fllowTheme){
  139. return this.$tm.vx.state().tmVuetify.color;
  140. }
  141. return this.color;
  142. },
  143. listData:{
  144. get:function () {
  145. return this.listAlbum;
  146. },
  147. set:function (val) {
  148. this.listAlbum = val;
  149. }
  150. }
  151. },
  152. async mounted() {
  153. await this.setInits();
  154. },
  155. methods: {
  156. //处理数据,以标准化。
  157. chuliList(){
  158. let list = [...this.list];
  159. let p = [];
  160. for (var i = 0; i < list.length; i++) {
  161. if(typeof list[i] == 'string'){
  162. let ls = {}
  163. ls[this.rangKey] = list[i];
  164. ls[this.textKey] = null;
  165. p.push(ls)
  166. }else if(typeof list[i] == 'object'){
  167. let ls = {}
  168. ls[this.rangKey] = '';
  169. ls[this.textKey] = null;
  170. ls={...ls,...list[i]}
  171. p.push(ls)
  172. }
  173. }
  174. return p;
  175. },
  176. async setInits(){
  177. this.$nextTick(async function() {
  178. let t = this;
  179. this.$tm.sleep(150).then(async function(){
  180. let p = await t.$Querey('.tm-album',t).catch(e =>{});
  181. if (!p[0]) return;
  182. let grid = t.grid || 1;
  183. let size = (p[0].width+t.gutter)/grid;
  184. let gutter = t.gutter*2
  185. let ratio = 750/uni.upx2px(750);
  186. let blv = size * ratio - gutter;
  187. t.alb_body_size = size * ratio;
  188. t.alb_wk_body_size = p[0].width*ratio+t.gutter*2+(grid*2);
  189. t.alb_size = blv;
  190. })
  191. });
  192. },
  193. clickAlbum(item,index){
  194. console.log(item)
  195. console.log(index)
  196. if(item.type=="tiao"){
  197. this.$emit('click',{item,index})
  198. }else{
  199. if(this.preview){
  200. uni.$tm.preview.previewImg(item[this.rangKey],this.listData,this.rangKey);
  201. }
  202. this.$emit('click',{item,index})
  203. }
  204. },
  205. more(){
  206. this.$emit('more')
  207. }
  208. },
  209. }
  210. </script>
  211. <style lang="scss" scoped>
  212. .tm-album{
  213. .tm-album-action{
  214. }
  215. }
  216. </style>