app-upload-image.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. <template>
  2. <view class="app-upload-image">
  3. <view class='upload-box' :style="{'background':backgroundColor}">
  4. <view class='flex-wrap'>
  5. <view v-for='(item, index) in imageList' :key='item.id' class='img-box'>
  6. <view mode="aspectFill" @click='remove(index)' class='remove cross-center main-center'>x</view>
  7. <image @click='previewImage(index)' :src='item' mode="aspectFill" class='img'></image>
  8. </view>
  9. <view @click='chooseImage'>
  10. <view v-if='isAddImg' :style="{'margin':margin + 'rpx'}" :class="{'other-border': diy ? true : false}" class="add-img dir-top-nowrap cross-center main-center">
  11. <image mode="aspectFill" class='add-img-icon' :src='defaultImg'></image>
  12. <text class='text'>{{text}}</text>
  13. <text class='text' v-if="showNumber">(最多{{maxNum}}张)</text>
  14. </view>
  15. </view>
  16. </view>
  17. </view>
  18. </view>
  19. </template>
  20. <script>
  21. import uploadFile from '@/core/upload.js';
  22. export default {
  23. name: 'app-upload-image',
  24. props: {
  25. value: {
  26. default: null,
  27. },
  28. defaultImg: {
  29. // 添加图片的默认背景图片
  30. type: String,
  31. default: '/static/image/icon/icon-image.png'
  32. },
  33. maxNum: {
  34. // 可添加最大图片数量
  35. type: [Number, String],
  36. default: 3
  37. },
  38. // 标记
  39. // 当组件用于循环时使用
  40. sign: {
  41. type: String,
  42. default: ''
  43. },
  44. backgroundColor: {
  45. type: String,
  46. default: '#f7f7f7',
  47. },
  48. margin: {
  49. type: String,
  50. default: '10'
  51. },
  52. diy: {
  53. type: Boolean,
  54. default: false
  55. },
  56. showNumber: {
  57. type: Boolean,
  58. default: true,
  59. },
  60. text: {
  61. type: String,
  62. default: '上传图片',
  63. },
  64. count: {
  65. type: Number,
  66. default: 9
  67. }
  68. },
  69. data() {
  70. return {
  71. imageList: this.value ? this.value : [],
  72. isAddImg: true
  73. }
  74. },
  75. methods: {
  76. // 上传最大图片数量
  77. checkMaxNum() {
  78. let status = this.imageList.length >= this.maxNum ? false : true;
  79. this.isAddImg = status;
  80. },
  81. // 移除图片
  82. remove(index) {
  83. let imageList = this.imageList;
  84. let data = imageList.splice(index, 1);
  85. this.imageList = imageList;
  86. this.checkMaxNum();
  87. // 触发事件 tabEvent
  88. this.$emit('imageEvent', {
  89. imageList: imageList,
  90. sign: this.sign
  91. })
  92. },
  93. // 选择图片
  94. chooseImage() {
  95. let self = this;
  96. let imageList = self.imageList;
  97. // #ifdef MP
  98. uni.chooseImage({
  99. count: self.maxNum,
  100. success: function(e) {
  101. for (let i in e.tempFilePaths) {
  102. if (i >= (self.maxNum - imageList.length)) {
  103. break;
  104. }
  105. let fileName = '';
  106. // #ifdef MP-BAIDU
  107. fileName = e.tempFilePaths[i].substr(e.tempFilePaths[i].lastIndexOf('/') + 1);
  108. // #endif
  109. uni.uploadFile({
  110. url: self.$api.upload.file,
  111. filePath: e.tempFilePaths[i],
  112. name: 'file',
  113. fileType: 'image',
  114. formData: {
  115. file: e.tempFilePaths[i],
  116. file_name: fileName,
  117. },
  118. success(res) {
  119. const data = res.data;
  120. let result = null;
  121. if (typeof data === 'string') {
  122. result = JSON.parse(data);
  123. } else {
  124. result = data;
  125. }
  126. if (result.code == 0) {
  127. imageList.push(result.data.url)
  128. self.imageList = imageList;
  129. self.checkMaxNum();
  130. self.$emit('imageEvent', {
  131. imageList: imageList,
  132. sign: self.sign
  133. });
  134. } else {
  135. uni.showModal({
  136. title: '',
  137. content: result.msg,
  138. showCancel: false,
  139. });
  140. }
  141. },
  142. fail(e) {
  143. if (e && e.errMsg) {
  144. uni.showModal({
  145. title: '错误',
  146. content: e.errMsg,
  147. showCancel: false,
  148. });
  149. }
  150. },
  151. });
  152. }
  153. },
  154. complete: function(e) {
  155. // 触发事件 tabEvent
  156. self.$emit('imageEvent', {
  157. imageList: imageList,
  158. sign: self.sign
  159. })
  160. }
  161. })
  162. // #endif
  163. // #ifdef H5
  164. uni.chooseImage({
  165. count: Number(self.maxNum),
  166. success: function(e) {
  167. for (let i in e.tempFilePaths) {
  168. if (i >= (self.maxNum - imageList.length)) {
  169. break;
  170. }
  171. let image = new Image();
  172. image.src = e.tempFilePaths[i];
  173. image.onload = () => {
  174. let canvas = document.createElement("canvas");
  175. canvas.width = image.width;
  176. canvas.height = image.height;
  177. let ctx = canvas.getContext("2d");
  178. ctx.drawImage(image, 0, 0, image.width, image.height);
  179. let ext = image.src.substring(image.src.lastIndexOf(".") + 1).toLowerCase();
  180. let dataURL = canvas.toDataURL("image/" + ext);
  181. uploadFile({
  182. url: self.$api.upload.file,
  183. maxNum: self.maxNum,
  184. success: function({res, header}) {
  185. self.$request({
  186. url: self.$api.upload.file + '&name=base64',
  187. header: header,
  188. method: 'post',
  189. data: {
  190. database: dataURL
  191. }
  192. }).then(res => {
  193. if (res.code === 0) {
  194. self.imageList.push(res.data.url);
  195. self.checkMaxNum();
  196. self.$emit('imageEvent', {
  197. imageList: self.imageList,
  198. sign: self.sign
  199. });
  200. } else {
  201. uni.showModal({
  202. title: '',
  203. content: res.msg,
  204. showCancel: false,
  205. });
  206. }
  207. })
  208. }
  209. });
  210. };
  211. }
  212. },
  213. complete: function(e) {
  214. // 触发事件 tabEvent
  215. self.$emit('imageEvent', {
  216. imageList: imageList,
  217. sign: self.sign
  218. })
  219. }
  220. });
  221. // #endif
  222. },
  223. // 图片预览
  224. previewImage(index) {
  225. let imageList = this.imageList;
  226. uni.previewImage({
  227. current: imageList[index],
  228. urls: imageList
  229. })
  230. },
  231. createObjectURL(blob) {
  232. return (window.URL) ? window.URL.createObjectURL(blob) : window.webkitURL.createObjectURL(blob);
  233. }
  234. },
  235. created() {
  236. this.checkMaxNum();
  237. }
  238. }
  239. </script>
  240. <style lang="scss" scoped>
  241. .upload-box {
  242. background-color: #fff;
  243. }
  244. .upload-box .title {
  245. padding: 15#{rpx} 0 15#{rpx} 20#{rpx};
  246. }
  247. .upload-box .img {
  248. width: 188#{rpx};
  249. height: 188#{rpx};
  250. margin: 10#{rpx};
  251. display: block;
  252. }
  253. .upload-box .add-img {
  254. width: 188#{rpx};
  255. height: 188#{rpx};
  256. border: 1#{rpx} dotted $uni-weak-color-one;
  257. background-color: #fff;
  258. }
  259. .upload-box .add-img .text {
  260. color: $uni-general-color-two;
  261. font-size: $uni-font-size-weak-two;
  262. }
  263. .upload-box .add-img-icon {
  264. width: 56#{rpx};
  265. height: 56#{rpx};
  266. margin-bottom: 10#{rpx};
  267. }
  268. .upload-box .img-box {
  269. position: relative;
  270. }
  271. .upload-box .remove {
  272. width: 40#{rpx};
  273. height: 40#{rpx};
  274. position: absolute;
  275. right: -5rpx;
  276. top: -10rpx;
  277. background: $uni-important-color-red;
  278. color: #fff;
  279. border-radius: 50%;
  280. padding-bottom: 8#{rpx};
  281. font-size: 24#{rpx};
  282. z-index: 968;
  283. }
  284. .upload-box .add-img.other-border {
  285. border: 1#{rpx} solid $uni-weak-color-one
  286. }
  287. </style>