index.tsx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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. onRemove: {
  64. type: Function,
  65. default: (data: string) => ({})
  66. },
  67. domSize: {
  68. type: Object,
  69. default: {
  70. width: '150px',
  71. height: '85px'
  72. }
  73. }
  74. },
  75. data() {
  76. return {
  77. isStopRun: false,
  78. loading: false
  79. }
  80. },
  81. methods: {
  82. onDelete() {
  83. // 删除图片
  84. this.$emit('update:modelValue', '')
  85. },
  86. //从本地选择文件
  87. async handleChange(info: any) {
  88. if (this.isStopRun) {
  89. return
  90. }
  91. this.loading = true
  92. const options = this.options
  93. this.getBase64(info.file, (imageUrl: any) => {
  94. const target = Object.assign({}, options, {
  95. img: imageUrl,
  96. name: info.file.name // 上传文件名
  97. })
  98. ;(this as any).$refs.CropperModal.edit(target)
  99. })
  100. },
  101. // 上传之前 格式与大小校验
  102. beforeUpload(file) {
  103. this.isStopRun = false
  104. const fileType = file.type
  105. if (fileType.indexOf('image') < 0) {
  106. ElMessage.warning('请上传图片')
  107. this.isStopRun = true
  108. return false
  109. }
  110. // const isJpgOrPng = this.acceptArray.includes(file.type)
  111. // if (!isJpgOrPng) {
  112. // ElMessage.error('你上传图片格式不正确!')
  113. // this.isStopRun = true
  114. // }
  115. // console.log(this.size)
  116. const size = this.size || 0
  117. const isLtSize = file.size < size * 1024 * 1024
  118. if (!isLtSize) {
  119. ElMessage.error('图片大小不能超过' + this.size + 'MB!')
  120. this.isStopRun = true
  121. }
  122. return isLtSize
  123. },
  124. error() {
  125. this.onDelete()
  126. this.loading = false
  127. },
  128. //获取服务器返回的地址
  129. handleCropperSuccess(data: any) {
  130. //将返回的数据回显
  131. this.loading = false
  132. // console.log(data, 'success')
  133. this.$emit('update:modelValue', data)
  134. this.cropUploadSuccess(data)
  135. // this.$emit('cropUploadSuccess', data)
  136. // console.log(this.modelValue, 'modelValue')
  137. },
  138. // 取消上传
  139. handleCropperClose() {
  140. this.loading = false
  141. this.onDelete()
  142. },
  143. getBase64(img, callback) {
  144. const reader = new FileReader()
  145. reader.addEventListener('load', () => callback(reader.result))
  146. reader.readAsDataURL(img)
  147. }
  148. },
  149. render() {
  150. return (
  151. <div class={[styles.colUpload, 'w-full']} style={{ lineHeight: 0 }}>
  152. <ElUpload
  153. disabled={this.disabled}
  154. showFileList={false}
  155. accept={this.accept}
  156. beforeUpload={this.beforeUpload}
  157. // @ts-ignore
  158. httpRequest={this.handleChange}
  159. // limit={1}
  160. ref="uploadRef"
  161. >
  162. <div
  163. ref="uploadDom"
  164. class={[styles.uploadClass, 'w-full']}
  165. style={{ height: this.domSize.height, width: this.domSize.width }}
  166. >
  167. {this.modelValue ? (
  168. <div class="relative">
  169. <ElImage
  170. src={this.modelValue}
  171. fit="cover"
  172. style={{
  173. height: this.domSize.height,
  174. width: this.domSize.width
  175. }}
  176. class={styles.uploadSection}
  177. />
  178. {this.delete && (
  179. <i
  180. class={styles.iconDelete}
  181. onClick={(e: any) => {
  182. e.stopPropagation()
  183. this.onRemove()
  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. })