mk-upload.vue 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. <template>
  2. <view
  3. class="mk-upload"
  4. :class="{'reverse': reverse}"
  5. >
  6. <!--进行flex占位-->
  7. <block v-if="imgList.length >= column && reverse">
  8. <block v-if="imgItemAppendLength === 0">
  9. <view
  10. class="mk-upload_item"
  11. :class="uploadItemColumn"
  12. v-for="(item, index) in (imgItemAppendLength + (column -1))"
  13. />
  14. </block>
  15. <block v-if="imgItemAppendLength === 1">
  16. <block v-if="column == 3">
  17. <view
  18. class="mk-upload_item"
  19. :class="uploadItemColumn"
  20. v-for="(item, index) in imgItemAppendLength"
  21. />
  22. </block>
  23. <block v-if="column == 4">
  24. <view
  25. class="mk-upload_item"
  26. :class="uploadItemColumn"
  27. v-for="(item, index) in (imgItemAppendLength + 1)"
  28. />
  29. </block>
  30. <block v-if="column == 5">
  31. <view
  32. class="mk-upload_item"
  33. :class="uploadItemColumn"
  34. v-for="(item, index) in (imgItemAppendLength + 2)"
  35. />
  36. </block>
  37. </block>
  38. <block v-if="imgItemAppendLength === 2">
  39. <block v-if="column == 4">
  40. <view
  41. class="mk-upload_item"
  42. :class="uploadItemColumn"
  43. v-for="(item, index) in (imgItemAppendLength - 1)"
  44. />
  45. </block>
  46. <block v-if="column == 5">
  47. <view
  48. class="mk-upload_item"
  49. :class="uploadItemColumn"
  50. v-for="(item, index) in imgItemAppendLength"
  51. />
  52. </block>
  53. </block>
  54. <block v-if="imgItemAppendLength === 3">
  55. <block v-if="column == 5">
  56. <view class="mk-upload_item" :class="uploadItemColumn"/>
  57. </block>
  58. </block>
  59. </block>
  60. <!--进行flex占位-->
  61. <view
  62. class="mk-upload_item"
  63. :class="uploadItemColumn"
  64. v-for="(item, index) in imgList"
  65. :key="index"
  66. >
  67. <view
  68. class="mk-upload_remove"
  69. :class="deletePosition"
  70. @tap="onDeleteThis(index)"
  71. v-if="deleteShow"
  72. >
  73. <text>✕</text>
  74. </view>
  75. <image
  76. :src="item"
  77. class="mk-upload_item_img"
  78. @tap="onPreviewImage(index)"
  79. mode="aspectFill"
  80. />
  81. </view>
  82. <!-- 列表end -->
  83. <view
  84. class="mk-upload_item"
  85. :class="uploadItemColumn"
  86. v-if="controlShow && imgList.length < maxCount"
  87. >
  88. <view
  89. class="mk-upload_add"
  90. @tap="onChooseImage"
  91. >+</view>
  92. </view>
  93. <!-- 上传按钮 -->
  94. </view>
  95. </template>
  96. <script>
  97. export default {
  98. //组件传参
  99. props: {
  100. //图片数组
  101. imgList: {
  102. type: Array,
  103. default: function() {
  104. return []
  105. }
  106. },
  107. //行数量
  108. column: {
  109. type: [Number, String],
  110. default: 3
  111. },
  112. reverse: {
  113. type: Boolean,
  114. default: false
  115. },
  116. //是否显示上传按钮
  117. controlShow: {
  118. type: Boolean,
  119. default: true
  120. },
  121. //是否显示删除按钮
  122. deleteShow: {
  123. type: Boolean,
  124. default: true
  125. },
  126. //删除按钮位置
  127. deletePosition: {
  128. type: String,
  129. default: 'topRight'
  130. },
  131. //album 从相册选图,camera 使用相机
  132. sourceType: {
  133. type: Array,
  134. default: function() {
  135. return ['camera', 'album']
  136. }
  137. },
  138. //original 原图,compressed 压缩图
  139. sizeType: {
  140. type: Array,
  141. default: function() {
  142. return ['original', 'compressed']
  143. }
  144. },
  145. //最多可以选择的图片张
  146. maxChooseCount: {
  147. type: Number,
  148. default: 9
  149. },
  150. //最大条数
  151. maxCount: {
  152. type: Number,
  153. default: 100
  154. }
  155. },
  156. data() {
  157. return {
  158. }
  159. },
  160. //计算属性
  161. computed: {
  162. uploadItemColumn(){
  163. return `mk-upload_item_column${this.column}`
  164. },
  165. imgItemAppendLength(){
  166. return this.imgList.length % this.column;
  167. }
  168. },
  169. //检测属性
  170. watch: {
  171. },
  172. //组件加载后
  173. created() {
  174. },
  175. methods: {
  176. //删除指定图片
  177. onDeleteThis(index){
  178. if(this.$listeners.onDeleteTake){
  179. this.$emit('onDeleteTake', index);
  180. return;
  181. }
  182. uni.showModal({
  183. title: '提示',
  184. content: '您确定删除吗?',
  185. success: (res)=> {
  186. if(res.confirm) {
  187. this.$emit('onDelete', index);
  188. }
  189. }
  190. });
  191. },
  192. //预览图片
  193. onPreviewImage(index) {
  194. if(this.$listeners.onPreviewTake){
  195. this.$emit('onPreviewTake', index);
  196. return;
  197. }
  198. const imgList = this.imgList;
  199. const isReverse = this.reverse;
  200. const currentIndex = isReverse ? (imgList.length - index) - 1 : index
  201. const imgLists = isReverse ? imgList.reverse() : imgList;
  202. uni.previewImage({
  203. current: currentIndex,
  204. urls: imgLists
  205. });
  206. },
  207. //选择图片
  208. onChooseImage(){
  209. uni.chooseImage({
  210. sizeType: this.sizeType,
  211. sourceType: this.sourceType,
  212. count: this.maxChooseCount,
  213. success: (res) => {
  214. this.$emit('onChoose', res);
  215. }
  216. });
  217. }
  218. }
  219. }
  220. </script>
  221. <style lang="less" scoped>
  222. .mk-upload{
  223. display: flex;
  224. flex-wrap: wrap;
  225. box-sizing: border-box;
  226. padding-left: var(--mk-upload_item_margin, 15px);
  227. padding-bottom: var(--mk-upload_item_margin, 15px);
  228. flex-direction: row;
  229. &.reverse{
  230. flex-direction: row-reverse;
  231. flex-wrap: wrap-reverse;
  232. justify-content: flex-end;
  233. }
  234. .mk-upload_item{
  235. position: relative;
  236. margin-top: var(--mk-upload_item_margin, 15px);
  237. margin-right: var(--mk-upload_item_margin, 15px);
  238. flex: 0 calc(33.3% - var(--mk-upload_item_margin, 15px));
  239. .mk-upload_remove{
  240. background-color: var(--mk-upload_remove_color, #D1372C);
  241. color: #fff;
  242. width: var(--mk-upload_remove_size, 24px);
  243. height: var(--mk-upload_remove_size, 24px);
  244. display: flex;
  245. justify-content: center;
  246. align-items: flex-start;
  247. opacity: 0.8;
  248. position: absolute;
  249. z-index: 2;
  250. cursor: pointer;
  251. box-sizing: border-box;
  252. text{
  253. transform: scale(0.8);
  254. position: absolute;
  255. top: -2upx;
  256. line-height: var(--mk-upload_remove_size, 24px);
  257. }
  258. &:active{
  259. opacity: 0.6;
  260. }
  261. &.topLeft{
  262. top: 0;
  263. left: 0;
  264. border-radius: 0 0 100% 0;
  265. text{
  266. left: 8upx;
  267. }
  268. }
  269. &.topRight{
  270. top: 0;
  271. right: 0;
  272. border-radius: 0 0 0 100%;
  273. text{
  274. left: 18upx;
  275. }
  276. }
  277. &.bottomLeft{
  278. bottom: 0;
  279. left: 0;
  280. border-radius: 0 100% 0 0;
  281. text{
  282. left: 8upx;
  283. top: 6upx;
  284. }
  285. }
  286. &.bottomRight{
  287. bottom: 0;
  288. right: 0;
  289. border-radius: 100% 0 0 0;
  290. text{
  291. top: 6upx;
  292. left: 16upx;
  293. }
  294. }
  295. }
  296. .mk-upload_add{
  297. display: flex;
  298. justify-content: center;
  299. align-items: center;
  300. background-color: var(--mk-upload_add_bgcolor, #f1f1f1);
  301. font-size: var(--mk-upload_add_size, 30px);
  302. height: var(--mk-upload_img_height, 100px);
  303. width: 100%;
  304. }
  305. .mk-upload_item_img{
  306. display: block;
  307. width: 100%;
  308. height: var(--mk-upload_img_height, 100px);
  309. }
  310. &.mk-upload_item_column2{
  311. flex: 0 calc(50% - var(--mk-upload_item_margin, 15px));
  312. }
  313. &.mk-upload_item_column3{
  314. flex: 0 calc(33.3% - var(--mk-upload_item_margin, 15px));
  315. }
  316. &.mk-upload_item_column4{
  317. flex: 0 calc(25% - var(--mk-upload_item_margin, 15px));
  318. .mk-upload_item_img,
  319. .mk-upload_add{
  320. height: var(--mk-upload_img_height, 70px);
  321. font-size: var(--mk-upload_add_size, 25px);
  322. }
  323. }
  324. &.mk-upload_item_column5{
  325. flex: 0 calc(20% - var(--mk-upload_item_margin, 15px));
  326. .mk-upload_item_img,
  327. .mk-upload_add{
  328. height: var(--mk-upload_img_height, 55px);
  329. font-size: var(--mk-upload_add_size, 25px);
  330. }
  331. }
  332. &.mk-upload_item_column4,
  333. &.mk-upload_item_column5{
  334. .mk-upload_remove{
  335. width: var(--mk-upload_remove_size, 20px);
  336. height: var(--mk-upload_remove_size, 20px);
  337. text{
  338. transform: scale(0.6);
  339. }
  340. &.topLeft{
  341. text{
  342. left: 6upx;
  343. top: -6upx;
  344. }
  345. }
  346. &.topRight{
  347. text{
  348. left: 10upx;
  349. top: -6upx;
  350. }
  351. }
  352. &.bottomLeft{
  353. text{
  354. left: 4upx;
  355. top: 0;
  356. }
  357. }
  358. &.bottomRight{
  359. text{
  360. left: 10upx;
  361. top: 0;
  362. }
  363. }
  364. }
  365. }
  366. }
  367. }
  368. </style>