dt_upload.vue 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. <template>
  2. <view class="dt-upload-wrap">
  3. <block v-for="(item, idx) in imgList" :key="idx">
  4. <view v-if="idx<max" class="upload-item">
  5. <image
  6. class="file-image"
  7. mode="aspectFit"
  8. :src="item.path"
  9. @tap.stop="previewImgs(item,imgList)"
  10. ></image>
  11. <image
  12. class="remove-img"
  13. @tap.stop="remove(item,idx)"
  14. src="http://139.9.103.171:1888/img/image/del.png"
  15. mode="widthFix"
  16. ></image>
  17. <view v-if="status[idx]" class="loading-wrap" :class="status">
  18. <image
  19. v-if="status[idx] == 'loading'"
  20. class="loading"
  21. src="http://139.9.103.171:1888/img/image/loading.gif"
  22. mode="widthFix"
  23. ></image>
  24. <text v-if="status[idx] == 'success'">上传成功</text>
  25. <text v-else-if="status[idx] == 'failed'">上传失败</text>
  26. <text v-else-if="status[idx] == 'loading'">上传中...</text>
  27. </view>
  28. </view>
  29. </block>
  30. <view v-if="imgList.length < max" class="upload-item" @tap="chooseImgs">
  31. <image
  32. class="camera"
  33. src="http://139.9.103.171:1888/img/image/camera.png"
  34. mode="widthFix"
  35. ></image>
  36. <view class="title">{{ title }}</view>
  37. </view>
  38. </view>
  39. </template>
  40. <script>
  41. export default {
  42. props: {
  43. title: {
  44. type: String,
  45. default: ""
  46. },
  47. max: {
  48. type: Number,
  49. default: 3
  50. },
  51. files: {
  52. type: Array,
  53. default:()=>{
  54. return []
  55. }
  56. }
  57. },
  58. data(){
  59. return {
  60. status: [], // loading, success, failed
  61. successList:[],
  62. failedList:[],
  63. imgList:[], // {id,name,path}
  64. }
  65. },
  66. methods: {
  67. previewImgs(item, list) {
  68. let imgList = [item.path]
  69. let type = Object.prototype.toString.call(list)
  70. if (type == '[object Array]' && list.length > 0) {
  71. list.forEach((li)=>{
  72. imgList.push(li.path)
  73. })
  74. }
  75. uni.previewImage({
  76. current: url,
  77. urls: imgList
  78. })
  79. },
  80. clear(){
  81. this.$set(this, 'status', [])
  82. this.$set(this, 'successList', [])
  83. this.$set(this, 'failedList', [])
  84. this.$set(this, 'imgList', [])
  85. this.$emit('update:files',[])
  86. },
  87. isHost(path){
  88. let host = this.$global.server.apiUrl;
  89. return path && path != '' && path.indexOf(host) > -1;
  90. },
  91. remove(item,idx) {
  92. if(this.isHost(item.path)){
  93. // this.$api.deletePic(this.file);
  94. }
  95. this.imgList.splice(idx,1)
  96. this.$forceUpdate()
  97. },
  98. chooseImgs() {
  99. uni.chooseImage({
  100. count: this.max-this.imgList.length, //默认9
  101. sizeType: ["original", "compressed"], //可以指定是原图还是压缩图,默认二者都有
  102. sourceType: ["album", "camera"], //从相册选择
  103. success: res => {
  104. let tempPaths = res.tempFilePaths;
  105. let imgList = this.imgList.slice(0)
  106. tempPaths.forEach((itemPath)=>{
  107. imgList.push({
  108. path:itemPath
  109. })
  110. })
  111. this.imgList = imgList
  112. this.status = this.status || []
  113. for(let o of tempPaths){
  114. this.status.push('')
  115. }
  116. this.$forceUpdate()
  117. },
  118. fail: res => {
  119. console.warn(res.errormsg || "取消选择");
  120. },
  121. complete: () => {
  122. this.isLoading = false;
  123. }
  124. });
  125. },
  126. upload(){
  127. let promiseList = []
  128. let imgList = this.imgList || []
  129. imgList.forEach((file, idx)=>{
  130. if(this.isHost(file.path)){
  131. this.$set(this.status,idx,'success')
  132. return
  133. }
  134. this.$set(this.status,idx,'loading')
  135. let promiseObj = this.$api.uploadImg({
  136. _isReject:true,
  137. uri:file.path,
  138. name:'img_'+ this.$global.server.miniappCode +'_'+Date.now()
  139. })
  140. promiseList.push(promiseObj)
  141. })
  142. return new Promise((resolve,reject)=>{
  143. Promise.all(promiseList).then(resList=>{
  144. console.log(144,resList)
  145. let flagFail = false
  146. resList.forEach((res,idx)=>{
  147. if(res && res[0]){
  148. this.successList.push(res[0])
  149. this.imgList[idx] = res[0]
  150. this.$set(this.status,idx,'success')
  151. }else{
  152. this.$set(this.status,idx,'failed')
  153. flagFail = true
  154. }
  155. })
  156. if(flagFail){
  157. throw new Error("res is null")
  158. }
  159. this.$emit('complete',this.successList)
  160. console.log(160,this.successList)
  161. resolve(this.successList)
  162. }).catch(err=>{
  163. console.error('error',err)
  164. this.$emit('error',err)
  165. imgList.forEach((file,idx)=>{
  166. this.$set(this.status,idx,'failed')
  167. this.failedList.push(file)
  168. })
  169. reject(err)
  170. })
  171. })
  172. },
  173. },
  174. onReady(){
  175. this.$nextTick(()=>{
  176. let files = this.files || []
  177. this.imgList = [].concat(files)
  178. this.$forceUpdate()
  179. console.log(this.imgList)
  180. })
  181. },
  182. };
  183. </script>
  184. <style lang="scss">
  185. .dt-upload-wrap {
  186. display:flex;
  187. flex-wrap:wrap;
  188. .upload-item {
  189. position: relative;
  190. display: flex;
  191. flex-direction: column;
  192. justify-content: center;
  193. align-items: center;
  194. flex-wrap: wrap;
  195. text-align: center;
  196. margin:20upx 15upx;
  197. width: 150upx;
  198. height: 150upx;
  199. border: 2upx dashed $dt-border-color;
  200. box-sizing: border-box;
  201. .camera {
  202. width: 60upx;
  203. height: 60upx;
  204. }
  205. .title {
  206. font-size: 22upx;
  207. margin-top: 10upx;
  208. color: #999;
  209. }
  210. .loading-wrap {
  211. position: absolute;
  212. bottom: 0;
  213. display: flex;
  214. align-items: center;
  215. justify-content: center;
  216. height: 30upx;
  217. width: 100%;
  218. background-color: rgba(0, 0, 0, 0.3);
  219. color: #fff;
  220. font-size: 16upx;
  221. .loading {
  222. width: 20upx;
  223. height: 20upx;
  224. margin-right: 10upx;
  225. }
  226. }
  227. .success {
  228. color: #019808;
  229. }
  230. .failed {
  231. color: #dc0024;
  232. }
  233. // @keyframes loadingRotate{
  234. // 0% {transform: rotate(0deg);}
  235. // 50% {transform: rotate(180deg);}
  236. // 100% {transform: rotate(360deg);}
  237. // }
  238. // .ani-rotate{
  239. // animation: loadingRotate 1s linear infinite
  240. // }
  241. .remove-img {
  242. position: absolute;
  243. top: 0;
  244. right: 0;
  245. transform: translate(45%, -45%);
  246. width: 30upx;
  247. height: 30upx;
  248. padding:10upx;
  249. }
  250. .file-image {
  251. max-width: 100%;
  252. max-height: 100%;
  253. }
  254. }
  255. .upload-item:first-child{
  256. margin-left:0;
  257. }
  258. .upload-item:last-child{
  259. margin-right:0;
  260. }
  261. }
  262. </style>