index.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. <template>
  2. <div class="ant-upload-preview">
  3. <div style="width: 100%">
  4. <el-upload class="avatar-uploader" :class="[disabled ? 'uploadDisabled' : null]" :disabled="disabled" :accept="accept" :show-file-list="false" action :before-upload="beforeUpload" :http-request="handleChange">
  5. <i v-if="isDelete && imageUrl" class="el-icon-error" @click.stop="onDelete" style="position: absolute;right: -14px;font-size: 24px;top: -14px;color: #787878;background: #fff;"></i>
  6. <img v-if="imageUrl" :src="imageUrl" class="avatar" :style="showBox" />
  7. <span v-else>
  8. <i v-if="loading" class="el-icon-loading avatar-uploader-icon" :style="showBox"></i>
  9. <i v-else class="el-icon-plus avatar-uploader-icon" :style="showBox"></i>
  10. <span class="upload-desc">添加上传图片</span>
  11. </span>
  12. </el-upload>
  13. </div>
  14. <!-- modal -->
  15. <cropper-modal ref="CropperModal" @cropper-no="handleCropperClose" @cropper-ok="handleCropperSuccess"></cropper-modal>
  16. </div>
  17. </template>
  18. <script>
  19. import CropperModal from './CropperModal'
  20. export default {
  21. name: 'ImageCropper',
  22. components: {
  23. CropperModal
  24. },
  25. props: {
  26. //图片裁切配置
  27. options: {
  28. type: Object,
  29. default: function() {
  30. return {
  31. autoCrop: true, //是否默认生成截图框
  32. enlarge: 1, // 图片放大倍数
  33. autoCropWidth: 200, //默认生成截图框宽度
  34. autoCropHeight: 200, //默认生成截图框高度
  35. fixedBox: false, //是否固定截图框大小 不允许改变
  36. previewsCircle: true, //预览图是否是原圆形
  37. title: '上传图片'
  38. }
  39. }
  40. },
  41. // 显示图片原始图片
  42. showSize: {
  43. type: Boolean,
  44. default: false,
  45. },
  46. // 上传图片的大小,单位M
  47. imgSize: {
  48. type: Number,
  49. default: 2
  50. },
  51. isDelete: {
  52. type: Boolean,
  53. default: false
  54. },
  55. // 图片地址
  56. imageUrl: {
  57. type: String,
  58. default: ''
  59. },
  60. // 默认图片格式
  61. accept: {
  62. type: String,
  63. default: '.png,.jpg,.jpeg,.gif'
  64. },
  65. acceptArray: {
  66. type: [Array, Object],
  67. default() {
  68. return ['image/jpeg', 'image/png', 'image/jpg', 'image/gif']
  69. }
  70. },
  71. bucket_name: {
  72. type: String,
  73. default: "daya",
  74. },
  75. disabled:{
  76. type: Boolean,
  77. default: false,
  78. }
  79. },
  80. data() {
  81. return {
  82. loading: false,
  83. isStopRun: false
  84. }
  85. },
  86. computed: {
  87. showBox() {
  88. let styleList = {}
  89. if(this.showSize) {
  90. styleList = {
  91. width: this.options.autoCropWidth + 'px',
  92. height: this.options.autoCropHeight + 'px',
  93. lineHeight: this.options.autoCropHeight + 'px',
  94. }
  95. }
  96. console.log(styleList)
  97. return styleList
  98. }
  99. },
  100. methods: {
  101. onDelete() { // 删除图片
  102. this.$emit('update:imageUrl', '')
  103. },
  104. //从本地选择文件
  105. handleChange(info) {
  106. if (this.isStopRun) {
  107. return
  108. }
  109. this.loading = true
  110. const { options } = this
  111. console.log(info)
  112. this.getBase64(info.file, imageUrl => {
  113. const target = Object.assign({}, options, {
  114. img: imageUrl,
  115. name: info.file.name // 上传文件名
  116. })
  117. this.$refs.CropperModal.edit(target)
  118. })
  119. },
  120. // 上传之前 格式与大小校验
  121. beforeUpload(file) {
  122. this.isStopRun = false
  123. var fileType = file.type
  124. if (fileType.indexOf('image') < 0) {
  125. this.$message.warning('请上传图片')
  126. this.isStopRun = true
  127. return false
  128. }
  129. const isJpgOrPng = this.acceptArray.includes(file.type)
  130. // file.type === 'image/jpeg' ||
  131. // file.type === 'image/png' ||
  132. // file.type === 'image/jpg'
  133. if (!isJpgOrPng) {
  134. this.$message.error('你上传图片格式不正确!')
  135. this.isStopRun = true
  136. }
  137. const isLtSize = file.size < this.imgSize * 1024 * 1024
  138. if (!isLtSize) {
  139. this.$message.error('图片大小不能超过' + this.imgSize + 'MB!')
  140. this.isStopRun = true
  141. }
  142. return isJpgOrPng && isLtSize
  143. },
  144. //获取服务器返回的地址
  145. handleCropperSuccess(data) {
  146. //将返回的数据回显
  147. this.loading = false
  148. this.$emit('crop-upload-success', data)
  149. },
  150. // 取消上传
  151. handleCropperClose() {
  152. this.loading = false
  153. this.$emit('crop-upload-close')
  154. },
  155. getBase64(img, callback) {
  156. const reader = new FileReader()
  157. reader.addEventListener('load', () => callback(reader.result))
  158. reader.readAsDataURL(img)
  159. }
  160. }
  161. }
  162. </script>
  163. <style lang="scss" scoped>
  164. .ant-upload-preview {
  165. background-color: #fff;
  166. .avatar-uploader {
  167. .upload-desc {
  168. position: absolute;
  169. bottom: 0;
  170. left: 0;
  171. color: #ccc;
  172. font-size: 8px;
  173. right: 0;
  174. }
  175. }
  176. }
  177. ::v-deep .avatar-uploader .el-upload--text {
  178. border: 1px dashed #d9d9d9;
  179. border-radius: 6px;
  180. margin-right: 20px;
  181. cursor: pointer;
  182. position: relative;
  183. // overflow: hidden;
  184. }
  185. ::v-deep .avatar-uploader.uploadDisabled {
  186. .el-upload--text {
  187. cursor: not-allowed;
  188. background-color: #f7f7f7;
  189. }
  190. .el-upload:hover {
  191. border-color: #d9d9d9;
  192. }
  193. }
  194. ::v-deep .avatar-uploader .el-upload:hover {
  195. border-color: #409eff;
  196. }
  197. ::v-deep .avatar-uploader-icon {
  198. font-size: 22px;
  199. color: #ccc;
  200. width: 108px;
  201. height: 108px;
  202. line-height: 108px;
  203. text-align: center;
  204. }
  205. ::v-deep.avatar {
  206. width: 108px;
  207. height: 108px;
  208. display: block;
  209. }
  210. </style>