newOne.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. <template>
  2. <view>
  3. <view class="imgs">
  4. <!-- images -->
  5. <view class="single" v-for="(item, index) in list" :key="index" >
  6. <image :src="item" :data-src="item" mode="aspectFit" @tap="previewImg" />
  7. <progress :percent="item.process" activeColor="#67C23A"
  8. :backgroundColor="item.process == 100 || item.process == undefined ? '#67C23A' : '#F56C6C'"
  9. stroke-width="3"
  10. v-if="mode == 'create' && showProcess" />
  11. <!-- 删除按钮 -->
  12. <view class="del" @tap="deleteItem(index)">×</view>
  13. </view>
  14. <!-- add button -->
  15. <view v-if="limit>list.length" class="single addNew" @tap="chooseFile">
  16. <text class="cuIcon-add">+</text>
  17. </view>
  18. </view>
  19. </view>
  20. </template>
  21. <script>
  22. /*
  23. 1.实现基础的上传预览
  24. 2. 实现精度条的显示
  25. 3. 实现可以移动的图片
  26. 4. 掌握基本的封装
  27. */
  28. import {toast}from '@/utils/common.js'
  29. export default {
  30. props: {
  31. attachmentList: {
  32. type: Array, //附件列表
  33. default () {
  34. return {}
  35. }
  36. },
  37. mode: {
  38. type: String //模式: create => 可新增或编辑附件 不填或其他 => 只能查看附件
  39. },
  40. uploadFileUrl: {
  41. type: String,
  42. dafault: '#' // 上传文件的服务器url
  43. },
  44. showProcess: {
  45. type: Boolean,
  46. default: false //是否显示进度,默认不显示
  47. },
  48. header: {
  49. type: Object, //上传图片到服务器时,HTTP 请求 Header
  50. default () {
  51. return {}
  52. }
  53. },
  54. limit: {
  55. type: Number, //限制可上传的图片数量
  56. default: 9 //这里有问题???
  57. },
  58. fileKeyName: {
  59. type: String,
  60. default: 'file' //用于在服务端通过自定义key值获取该文件数据
  61. },
  62. canUploadFile: { //是否更新
  63. type: Boolean,
  64. default: true
  65. }
  66. },
  67. computed: {
  68. list: {
  69. get(){return this.attachmentList},
  70. }
  71. },
  72. data() {
  73. return {
  74. imageList: [],
  75. urls:[]
  76. };
  77. },
  78. methods: {
  79. //预览
  80. previewImg(e) {
  81. console.log(...this.list);
  82. uni.previewImage({
  83. current: e.target.dataset.src,
  84. loop: true,
  85. longPressActions: {
  86. itemList: ['发送给朋友', '保存图片', '收藏'],
  87. success: function(data) {
  88. console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片');
  89. },
  90. fail: function(err) {
  91. console.log(err.errMsg);
  92. }
  93. },
  94. urls: this.list //this.imageList,保持删除了的不在
  95. });
  96. },
  97. //下载
  98. downLoad(url) {
  99. uni.showModal({
  100. title: '确定要下载此附件吗',
  101. content: ' ',
  102. success: res => {
  103. if (res.confirm) {
  104. uni.showLoading({
  105. title: '下载中,请稍后'
  106. });
  107. console.log(url);
  108. uni.downloadFile({
  109. url: url,
  110. success: res => {
  111. var tempFile = res.tempFilePath;
  112. uni.saveFile({
  113. tempFilePath: res.tempFilePath,
  114. success: res => {
  115. var savedFilePath = res.savedFilePath;
  116. uni.hideLoading();
  117. uni.showToast({
  118. title: '保存成功,路径为' + savedFilePath
  119. });
  120. uni.openDocument({
  121. filePath: savedFilePath,
  122. success: function(res) {
  123. console.log(res);
  124. }
  125. });
  126. }
  127. });
  128. },
  129. fail: res => {
  130. console.log(res);
  131. uni.hideLoading();
  132. uni.showToast({
  133. title: '下载失败',
  134. icon: 'none'
  135. });
  136. }
  137. });
  138. setTimeout(function() {
  139. uni.hideLoading();
  140. }, 2000);
  141. // downloadTask.onProgressUpdate((res) => {
  142. // console.log('下载中,进度' + res.progress)
  143. // });
  144. }
  145. }
  146. });
  147. },
  148. //删除
  149. deleteItem(index) {
  150. uni.showModal({
  151. title: '提示',
  152. content: '确定要删除此项吗?',
  153. success: res => {
  154. if (res.confirm) {
  155. // if (this.list[index].process != 100) {
  156. // typeof this.list[index].uploadTask != 'undefined' && this.list[index].uploadTask.abort();
  157. // }
  158. this.imageList.splice(index,1)
  159. this.list.splice(index, 1);
  160. this.$forceUpdate(); //强制更新
  161. this.$emit('update:attachmentList', this.list); //类似双向数据绑定
  162. }
  163. }
  164. });
  165. },
  166. chooseFile() {
  167. //双重保证
  168. // console.log(this.list);
  169. if (this.list.length >= this.limit) {
  170. toast('已达到最大上传数量')
  171. return;
  172. }
  173. let canUploadFile = this.canUploadFile;
  174. let tempFiles;
  175. if (canUploadFile) {
  176. uni.chooseImage({
  177. count: this.limit - this.list.length,
  178. sizeType: ['original', 'compressed'],
  179. sourceType: ['album', 'camera'],
  180. success: (res) => {
  181. // console.log(res.tempFilePaths);
  182. tempFiles = res.tempFilePaths;
  183. this.imageList = this.imageList.concat(tempFiles)
  184. console.log(this.imageList);
  185. this.list.push(...tempFiles)//如果图片一次性就超过这个值怎么使他赋的值回退
  186. // #ifdef H5
  187. if (this.list.length >= this.limit) {
  188. this.list.splice(this.limit)
  189. toast('已达到最大上传数量')
  190. return;
  191. }
  192. // #endif
  193. this.$emit('update:attachmentList', this.list); //类似双向数据绑定,更新数据, 使用.sync修饰
  194. this.$forceUpdate();
  195. console.log(this.list);
  196. },
  197. fail:err=>{
  198. console.log(err);
  199. }
  200. });
  201. }
  202. //设置文件名字
  203. /* for (let i in this.imageList) {
  204. let path = this.imageList[i];
  205. let index = this.list.length;
  206. console.log(this.list);
  207. //需要设置成多个上传,而非单个上传
  208. this.list.push({
  209. url: path,
  210. // fileName: fileName,
  211. type: 'image' ,
  212. index: index,
  213. process: 0,
  214. // uploadTask: uploadTask
  215. });
  216. /* //上传, 可能这里还需要调整一下,这里点击之后就直接上传了,让用户去操作
  217. var uploadTask = await uni.uploadFile({
  218. url: this.uploadFileUrl,
  219. filePath: path,// 使用files上传数组列表
  220. name: this.fileKeyName,
  221. headers: this.header,
  222. success: res => {
  223. // 上传完成后处理
  224. this.$emit('uploadSuccess', res);
  225. if (res.statusCode == 200) {
  226. this.$emit('update:attachmentList', this.list); //类似双向数据绑定,更新数据, 使用.sync修饰
  227. this.$forceUpdate();
  228. } else {
  229. }
  230. }
  231. });
  232. uploadTask.onProgressUpdate(res => {
  233. //此接口不显示真实进度, 所以需要特殊处理
  234. if (res.progress < 90) {
  235. this.$set(this.list[index], 'process', res.progress);
  236. this.$forceUpdate();
  237. }
  238. });
  239. */
  240. // }*/
  241. },
  242. upload(){
  243. uni.showLoading({
  244. title: '上传中...',
  245. mask: false
  246. });
  247. for(let i=0; i<this.list.length;i++){
  248. let path=this.list[i]
  249. let index=i.toString()
  250. console.log(path);
  251. uni.uploadFile({
  252. url: this.uploadFileUrl,
  253. name: this.fileKeyName,
  254. filePath: path, // 使用files上传数组列表,上面两者都会失效
  255. file:[
  256. {name:index,url:path}
  257. ],
  258. success:res=>{
  259. uni.hideLoading()
  260. console.log(res);
  261. this.$emit('uploadSuccess', res);
  262. if (res.statusCode == 200) {
  263. //上传成功将原信息,直接删除,
  264. this.list.splice(i,1)
  265. console.log(this.list);
  266. this.$forceUpdate();
  267. } else {
  268. }
  269. },
  270. fail:err=>{
  271. uni.hideLoading()
  272. toast(err.errMsg)
  273. console.log(err);
  274. }
  275. })
  276. }
  277. },
  278. /* async upload(){
  279. // 开始上传,先暂存文件
  280. this.list.push({
  281. fileName: fileName,
  282. url: path,
  283. type: this.isImg(path) ? 'image' : 'file',
  284. index: index,
  285. uploadTask: uploadTask,
  286. process: 0
  287. });
  288. this.$forceUpdate();
  289. //上传, 可能这里还需要调整一下,这里点击之后就直接上传了,让用户去操作
  290. var uploadTask = await uni.uploadFile({
  291. url: this.uploadFileUrl,
  292. filePath: path,// 使用files上传数组列表
  293. name: this.fileKeyName,
  294. headers: this.header,
  295. success: res => {
  296. // 上传完成后处理
  297. this.$emit('uploadSuccess', res);
  298. if (res.statusCode == 200) {
  299. this.$emit('update:attachmentList', this.list); //类似双向数据绑定,更新数据, 使用.sync修饰
  300. this.$forceUpdate();
  301. } else {
  302. }
  303. }
  304. });
  305. uploadTask.onProgressUpdate(res => {
  306. //此接口不显示真实进度, 所以需要特殊处理
  307. if (res.progress < 90) {
  308. this.$set(this.list[index], 'process', res.progress);
  309. this.$forceUpdate();
  310. }
  311. });
  312. },
  313. */
  314. //根据文件名,返回时是否是图片类型
  315. /* isImg(filePath) {
  316. let index = filePath.lastIndexOf('.');
  317. let ext = filePath.substr(index + 1);
  318. var temp = ['png', 'jpg', 'jpeg', 'bmp', 'gif', 'webp', 'svg', 'tiff'].indexOf(ext.toLowerCase()) !== -1;
  319. return temp;
  320. } */
  321. }
  322. };
  323. </script>
  324. <style lang="less" scoped>
  325. .imgs {
  326. display: flex;
  327. flex-wrap: wrap;
  328. justify-content: flex-start;
  329. align-items: center;
  330. // width: calc(100% + 15rpx);
  331. & .file {
  332. min-width: calc(100% - 15rpx);
  333. border: 1px solid #ccc;
  334. // border-radius: 10upx;
  335. box-sizing: border-box;
  336. margin-top: 20upx;
  337. position: relative;
  338. & .noImg {
  339. padding: 20rpx;
  340. display: flex;
  341. justify-content: center;
  342. text-align: left;
  343. width: 100%;
  344. font-size: 26upx;
  345. // flex-wrap: wrap;
  346. color: #999;
  347. word-break: break-all;
  348. box-sizing: border-box;
  349. }
  350. }
  351. progress {
  352. margin-top: -6rpx;
  353. border-radius: 20rpx;
  354. }
  355. .del {
  356. position: absolute;
  357. width: 35rpx;
  358. height: 35rpx;
  359. background: #f56c6c;
  360. color: #fff;
  361. top: 0;
  362. text-align: center;
  363. right: 0;
  364. line-height: 35rpx;
  365. font-size: 30rpx;
  366. z-index: 100;
  367. }
  368. & .single {
  369. width: 180rpx;
  370. height: 180rpx;
  371. border: 1px solid #ccc;
  372. // border-radius: 10upx;
  373. margin: 10rpx;
  374. position: relative;
  375. &.addNew {
  376. display: flex;
  377. justify-content: center;
  378. align-items: center;
  379. text {
  380. font-size: 50rpx;
  381. color: #999;
  382. }
  383. }
  384. & image {
  385. width: 100%;
  386. height: 100%;
  387. display: block;
  388. }
  389. }
  390. }
  391. </style>