index.tsx 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. import { closeToast, Icon, Image, showLoadingToast, showToast, Uploader } from 'vant'
  2. import { defineComponent, ref } from 'vue'
  3. import styles from './index.module.less'
  4. import { useCustomFieldValue } from '@vant/use'
  5. import { postMessage } from '@/helpers/native-message'
  6. import umiRequest from 'umi-request'
  7. import iconUploader from '@common/images/icon-upload.png'
  8. import iconUploadClose from '@common/images/icon-upload-close.png'
  9. import request from '@/helpers/request'
  10. import { getOssUploadUrl, state } from '@/state'
  11. export default defineComponent({
  12. name: 'col-upload',
  13. props: {
  14. modelValue: {
  15. type: Array,
  16. default: () => []
  17. },
  18. deletable: {
  19. type: Boolean,
  20. default: true
  21. },
  22. maxCount: {
  23. type: Number,
  24. default: 1
  25. },
  26. native: {
  27. // 是否原生上传
  28. type: Boolean,
  29. default: false
  30. },
  31. uploadSize: {
  32. // 上传图片大小
  33. type: Number,
  34. default: 5
  35. },
  36. accept: {
  37. type: String,
  38. default: 'image/*'
  39. },
  40. onUploadChange: {
  41. type: Function,
  42. default: (url: string) => {}
  43. },
  44. bucket: {
  45. type: String,
  46. default: 'daya'
  47. },
  48. uploadIcon: {
  49. type: String,
  50. default: iconUploader
  51. },
  52. size: {
  53. type: String,
  54. default: 'default'
  55. }
  56. },
  57. methods: {
  58. nativeUpload() {
  59. postMessage(
  60. {
  61. api: 'chooseFile',
  62. content: { type: 'img', max: 1, bucket: this.bucket }
  63. },
  64. (res: any) => {
  65. console.log(res, 'fileUrl')
  66. this.$emit('update:modelValue', [...this.modelValue, res.fileUrl])
  67. }
  68. )
  69. },
  70. beforeRead(file: any) {
  71. console.log(file, 'beforeRead')
  72. const isLt2M = file.size / 1024 / 1024 < this.uploadSize
  73. if (!isLt2M) {
  74. showToast(`上传文件大小不能超过 ${this.uploadSize}MB`)
  75. return false
  76. }
  77. return true
  78. },
  79. beforeDelete(file: any, detail: { index: any }) {
  80. // this.dataModel.splice(detail.index, 1)
  81. return true
  82. },
  83. async afterRead(file: any, detail: any) {
  84. try {
  85. file.status = 'uploading'
  86. file.message = '上传中...'
  87. await this.uploadFile(file.file)
  88. } catch (error) {
  89. closeToast()
  90. }
  91. },
  92. onClose(e: any) {
  93. this.$emit('update:modelValue', null)
  94. this.onUploadChange()
  95. e.stopPropagation()
  96. },
  97. async getFile(file: any) {
  98. try {
  99. await this.uploadFile(file)
  100. } catch {
  101. //
  102. }
  103. },
  104. async uploadFile(file: any) {
  105. // 上传文件
  106. try {
  107. // 获取签名
  108. if (state.platformType === 'SCHOOL') {
  109. state.platformApi = '/api-school'
  110. } else if (state.platformType === 'TEACHER') {
  111. state.platformApi = '/api-teacher'
  112. } else if (state.platformType === 'STUDENT') {
  113. state.platformApi = '/api-student'
  114. }
  115. const signUrl = state.platformApi + '/open/getUploadSign'
  116. const tempName = file.name || ''
  117. const fileName = tempName && tempName.replace(/ /gi, '_')
  118. const key = new Date().getTime() + fileName
  119. console.log(file)
  120. const res = await request.post(signUrl, {
  121. data: {
  122. filename: fileName,
  123. bucketName: this.bucket,
  124. postData: {
  125. filename: fileName,
  126. acl: 'public-read',
  127. key: key,
  128. unknowValueField: []
  129. }
  130. }
  131. })
  132. showLoadingToast({
  133. message: '加载中...',
  134. forbidClick: true,
  135. loadingType: 'spinner',
  136. duration: 0
  137. })
  138. const obj = {
  139. policy: res.data.policy,
  140. signature: res.data.signature,
  141. key: key,
  142. KSSAccessKeyId: res.data.kssAccessKeyId,
  143. acl: 'public-read',
  144. name: fileName
  145. }
  146. const formData = new FormData()
  147. for (const key in obj) {
  148. formData.append(key, obj[key])
  149. }
  150. formData.append('file', file, fileName)
  151. await umiRequest(getOssUploadUrl(this.bucket), {
  152. method: 'POST',
  153. data: formData
  154. })
  155. console.log(getOssUploadUrl(this.bucket) + key)
  156. const uploadUrl = getOssUploadUrl(this.bucket) + key
  157. closeToast()
  158. // 判断是否是多选
  159. this.$emit('update:modelValue', [...this.modelValue, uploadUrl])
  160. this.onUploadChange([...this.modelValue, uploadUrl])
  161. } catch (error) {
  162. console.log(error, 'uploadFile')
  163. }
  164. }
  165. },
  166. render() {
  167. useCustomFieldValue(() => this.modelValue)
  168. return (
  169. <div class={styles['uploader-section']}>
  170. {this.modelValue.length > 0 &&
  171. this.modelValue.map((item: any) => (
  172. <div class={[styles.uploader, styles[this.size]]}>
  173. {/* 删除按钮 */}
  174. {this.deletable && (
  175. <Icon name="cross" onClick={this.onClose} class={styles['img-close']} />
  176. )}
  177. <div class={['van-uploader__upload']}>
  178. <Image src={item} class={styles.previewImg} fit="cover" />
  179. </div>
  180. </div>
  181. ))}
  182. {this.native ? (
  183. this.maxCount > 1 ? (
  184. <div class={[styles.uploader, styles[this.size]]} onClick={this.nativeUpload}>
  185. {this.modelValue ? (
  186. <Image
  187. fit="cover"
  188. position="center"
  189. class={styles.uploadImg}
  190. src={this.modelValue as any}
  191. />
  192. ) : (
  193. <Icon name={this.uploadIcon} size="32" />
  194. )}
  195. </div>
  196. ) : (
  197. ''
  198. )
  199. ) : this.maxCount > 1 ? (
  200. <Uploader
  201. class={[styles.uploader, styles[this.size]]}
  202. afterRead={this.afterRead}
  203. beforeRead={this.beforeRead}
  204. beforeDelete={this.beforeDelete}
  205. uploadIcon={this.uploadIcon}
  206. disabled={this.modelValue.length === this.maxCount}
  207. accept={this.accept}
  208. />
  209. ) : (
  210. <Uploader
  211. class={[styles.uploader, styles[this.size]]}
  212. afterRead={this.afterRead}
  213. beforeRead={this.beforeRead}
  214. beforeDelete={this.beforeDelete}
  215. uploadIcon={this.uploadIcon}
  216. accept={this.accept}
  217. >
  218. <Icon name={this.uploadIcon} class={['van-uploader__upload']} size="32" />
  219. </Uploader>
  220. )}
  221. </div>
  222. )
  223. }
  224. })