index.tsx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. import { ElImage, ElMessage, ElUpload } from 'element-plus'
  2. import { defineComponent } from 'vue'
  3. import styles from './index.module.less'
  4. import iconUpload from '../col-upload/images/icon_upload.png'
  5. import Cropper from './cropper'
  6. export default defineComponent({
  7. name: 'col-cropper',
  8. props: {
  9. modelValue: {
  10. type: String,
  11. default: ''
  12. },
  13. options: {
  14. // 裁切需要参数
  15. type: Object,
  16. default: {
  17. autoCrop: true, //是否默认生成截图框
  18. enlarge: 1, // 图片放大倍数
  19. autoCropWidth: 200, //默认生成截图框宽度
  20. autoCropHeight: 200, //默认生成截图框高度
  21. fixedBox: true, //是否固定截图框大小 不允许改变
  22. previewsCircle: true, //预览图是否是原圆形
  23. title: '上传图片'
  24. }
  25. },
  26. // 显示图片原始图片
  27. showSize: {
  28. type: Boolean,
  29. default: false
  30. },
  31. disabled: {
  32. type: Boolean,
  33. default: false
  34. },
  35. delete: {
  36. type: Boolean,
  37. default: false
  38. },
  39. bucket: {
  40. type: String,
  41. default: 'daya'
  42. },
  43. size: {
  44. type: Number,
  45. default: 5 // 默认5M
  46. },
  47. accept: {
  48. type: String,
  49. default: '.png,.jpg,.jpeg'
  50. },
  51. tips: {
  52. type: String,
  53. default: '请上传图片'
  54. },
  55. extraTips: {
  56. type: String,
  57. default: '图片最大不能超过5MB'
  58. },
  59. cropUploadSuccess: {
  60. type: Function,
  61. default: (data: string) => ({})
  62. },
  63. domSize: {
  64. type: Object,
  65. default: {
  66. width: '150px',
  67. height: '85px'
  68. }
  69. }
  70. },
  71. data() {
  72. return {
  73. isStopRun: false,
  74. loading: false
  75. }
  76. },
  77. methods: {
  78. onDelete() {
  79. // 删除图片
  80. this.$emit('update:modelValue', '')
  81. },
  82. //从本地选择文件
  83. async handleChange(info: any) {
  84. if (this.isStopRun) {
  85. return
  86. }
  87. this.loading = true
  88. const options = this.options
  89. this.getBase64(info.file, (imageUrl: any) => {
  90. const target = Object.assign({}, options, {
  91. img: imageUrl,
  92. name: info.file.name // 上传文件名
  93. })
  94. ;(this as any).$refs.CropperModal.edit(target)
  95. })
  96. },
  97. // 上传之前 格式与大小校验
  98. beforeUpload(file) {
  99. this.isStopRun = false
  100. const fileType = file.type
  101. if (fileType.indexOf('image') < 0) {
  102. ElMessage.warning('请上传图片')
  103. this.isStopRun = true
  104. return false
  105. }
  106. // const isJpgOrPng = this.acceptArray.includes(file.type)
  107. // if (!isJpgOrPng) {
  108. // ElMessage.error('你上传图片格式不正确!')
  109. // this.isStopRun = true
  110. // }
  111. // console.log(this.size)
  112. const size = this.size || 0
  113. const isLtSize = file.size < size * 1024 * 1024
  114. if (!isLtSize) {
  115. ElMessage.error('图片大小不能超过' + this.size + 'MB!')
  116. this.isStopRun = true
  117. }
  118. return isLtSize
  119. },
  120. error() {
  121. this.remove()
  122. this.loading = false
  123. },
  124. remove() {
  125. this.onDelete()
  126. },
  127. //获取服务器返回的地址
  128. handleCropperSuccess(data: any) {
  129. //将返回的数据回显
  130. this.loading = false
  131. // console.log(data, 'success')
  132. this.$emit('update:modelValue', data)
  133. this.cropUploadSuccess(data)
  134. // this.$emit('cropUploadSuccess', data)
  135. // console.log(this.modelValue, 'modelValue')
  136. },
  137. // 取消上传
  138. handleCropperClose() {
  139. this.loading = false
  140. this.remove()
  141. },
  142. getBase64(img, callback) {
  143. const reader = new FileReader()
  144. reader.addEventListener('load', () => callback(reader.result))
  145. reader.readAsDataURL(img)
  146. }
  147. },
  148. render() {
  149. return (
  150. <div class={[styles.colUpload, 'w-full']} style={{ lineHeight: 0 }}>
  151. <ElUpload
  152. disabled={this.disabled}
  153. showFileList={false}
  154. accept={this.accept}
  155. beforeUpload={this.beforeUpload}
  156. // @ts-ignore
  157. httpRequest={this.handleChange}
  158. // limit={1}
  159. ref="uploadRef"
  160. >
  161. <div
  162. ref="uploadDom"
  163. class={[styles.uploadClass, 'w-full']}
  164. style={{ height: this.domSize.height, width: this.domSize.width }}
  165. >
  166. {this.modelValue ? (
  167. <div class="relative">
  168. <ElImage
  169. src={this.modelValue}
  170. fit="cover"
  171. style={{
  172. height: this.domSize.height,
  173. width: this.domSize.width
  174. }}
  175. class={styles.uploadSection}
  176. />
  177. {this.delete && (
  178. <i
  179. class={styles.iconDelete}
  180. onClick={(e: any) => {
  181. console.log('11111')
  182. e.stopPropagation()
  183. this.onDelete()
  184. }}
  185. ></i>
  186. )}
  187. </div>
  188. ) : (
  189. <div
  190. class={[
  191. styles.uploadSection,
  192. 'flex items-center flex-col justify-center'
  193. ]}
  194. style={{
  195. height: this.domSize.height,
  196. width: this.domSize.width
  197. }}
  198. >
  199. <img src={iconUpload} class="w-8 h-7 mb-3" />
  200. <p>{this.tips}</p>
  201. </div>
  202. )}
  203. </div>
  204. </ElUpload>
  205. <p class="text-3 text-[#999999] leading-6 pt-1">{this.extraTips}</p>
  206. <Cropper
  207. ref="CropperModal"
  208. bucket={this.bucket}
  209. cropperNo={this.handleCropperClose}
  210. cropperOk={this.handleCropperSuccess}
  211. />
  212. </div>
  213. )
  214. }
  215. })