index.tsx 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. import {
  2. closeToast,
  3. Icon,
  4. Image,
  5. showLoadingToast,
  6. showToast,
  7. Uploader,
  8. UploaderInstance
  9. } from 'vant'
  10. import { defineComponent, ref } from 'vue'
  11. import styles from './index.module.less'
  12. import ColCropper from '../o-cropper'
  13. import { useCustomFieldValue } from '@vant/use'
  14. import { postMessage } from '@/helpers/native-message'
  15. import umiRequest from 'umi-request'
  16. import iconUploader from '@common/images/icon_uploader.png'
  17. import request from '@/helpers/request'
  18. import { getOssUploadUrl, state } from '@/state'
  19. import { getUploadSign, onOnlyFileUpload } from '@/helpers/oss-file-upload'
  20. export default defineComponent({
  21. name: 'col-upload',
  22. props: {
  23. modelValue: String,
  24. tips: {
  25. type: String,
  26. default: '点击上传'
  27. },
  28. deletable: {
  29. type: Boolean,
  30. default: true
  31. },
  32. native: {
  33. // 是否原生上传
  34. type: Boolean,
  35. default: false
  36. },
  37. cropper: {
  38. // 是否进行裁切
  39. type: Boolean,
  40. default: false
  41. },
  42. options: {
  43. // 裁切需要参数
  44. type: Object,
  45. default: {}
  46. },
  47. uploadSize: {
  48. // 上传图片大小
  49. type: Number,
  50. default: 5
  51. },
  52. onUploadChange: {
  53. type: Function,
  54. default: (url: string) => {}
  55. },
  56. bucket: {
  57. type: String,
  58. default: 'gyt'
  59. },
  60. path: {
  61. // 创建的目录
  62. type: String,
  63. default: ''
  64. },
  65. disabled: {
  66. type: Boolean,
  67. default: false
  68. }
  69. },
  70. methods: {
  71. nativeUpload() {
  72. if (this.disabled) return
  73. postMessage(
  74. {
  75. api: 'chooseFile',
  76. content: { type: 'img', max: 1, bucket: this.bucket, path: this.path }
  77. },
  78. (res: any) => {
  79. console.log(res, 'fileUrl')
  80. this.$emit('update:modelValue', res.fileUrl)
  81. }
  82. )
  83. },
  84. beforeRead(file: any) {
  85. console.log(file, 'beforeRead')
  86. const isLt2M = file.size / 1024 / 1024 < this.uploadSize
  87. if (!isLt2M) {
  88. showToast(`上传文件大小不能超过 ${this.uploadSize}MB`)
  89. return false
  90. }
  91. return true
  92. },
  93. beforeDelete(file: any, detail: { index: any }) {
  94. // this.dataModel.splice(detail.index, 1)
  95. return true
  96. },
  97. async afterRead(file: any, detail: any) {
  98. try {
  99. file.status = 'uploading'
  100. file.message = '上传中...'
  101. await this.uploadFile(file.file)
  102. } catch (error) {
  103. //
  104. console.log(error, '2323')
  105. closeToast()
  106. }
  107. },
  108. onClose(e: any) {
  109. this.$emit('update:modelValue', null)
  110. this.onUploadChange()
  111. e.stopPropagation()
  112. },
  113. async getFile(file: any) {
  114. try {
  115. await this.uploadFile(file)
  116. } catch {
  117. //
  118. }
  119. },
  120. async uploadFile(file: any) {
  121. // 上传文件
  122. try {
  123. // 获取签名
  124. if (state.platformType === 'SCHOOL') {
  125. state.platformApi = '/api-school'
  126. } else if (state.platformType === 'TEACHER') {
  127. state.platformApi = '/api-teacher'
  128. } else if (state.platformType === 'STUDENT') {
  129. state.platformApi = '/api-student'
  130. }
  131. // const signUrl = state.platformApi + '/open/getUploadSign'
  132. // const tempName = file.name || ''
  133. // console.log(this.path)
  134. // const fileName = this.path + '/' + (tempName && tempName.replace(/ /gi, '_'))
  135. // const key = new Date().getTime() + fileName
  136. // console.log(file)
  137. const tempName = file.name || ''
  138. const fileName = this.path
  139. ? this.path + '/' + (tempName && tempName.replace(/ /gi, '_'))
  140. : tempName && tempName.replace(/ /gi, '_')
  141. const key = new Date().getTime() + fileName
  142. // const res = await request.post(signUrl, {
  143. // data: {
  144. // filename: fileName,
  145. // bucketName: this.bucket,
  146. // postData: {
  147. // filename: fileName,
  148. // acl: 'public-read',
  149. // key: key,
  150. // unknowValueField: []
  151. // }
  152. // }
  153. // })
  154. const { data } = await getUploadSign({
  155. filename: key,
  156. bucketName: this.bucket,
  157. postData: {
  158. filename: key,
  159. acl: 'public-read',
  160. key: key,
  161. unknowValueField: []
  162. }
  163. })
  164. showLoadingToast({
  165. message: '加载中...',
  166. forbidClick: true,
  167. loadingType: 'spinner',
  168. duration: 0
  169. })
  170. const obj = {
  171. policy: data.policy,
  172. signature: data.signature,
  173. key: key,
  174. KSSAccessKeyId: data.kssAccessKeyId,
  175. acl: 'public-read',
  176. name: key,
  177. file
  178. }
  179. const uploadUrl = await onOnlyFileUpload(getOssUploadUrl(this.bucket), obj)
  180. closeToast()
  181. this.$emit('update:modelValue', uploadUrl)
  182. this.onUploadChange(uploadUrl)
  183. } catch (error) {
  184. console.log(error, 'uploadFile')
  185. }
  186. },
  187. startUpload() {
  188. ;(this as any).$refs.uploaderRef?.startChiose()
  189. }
  190. },
  191. render() {
  192. useCustomFieldValue(() => this.modelValue)
  193. return (
  194. <div class={[styles['uploader-section'], 'oUpload']}>
  195. {this.modelValue && this.deletable ? (
  196. <Icon name="cross" onClick={this.onClose} class={styles['img-close']} />
  197. ) : null}
  198. {this.cropper && !this.native ? (
  199. <div class={styles['col-uploader']}>
  200. {this.modelValue ? (
  201. <Image fit="cover" position="center" class={styles.uploadImg} src={this.modelValue} />
  202. ) : (
  203. <div class={styles.uploader}>
  204. <Icon name={iconUploader} size="32" />
  205. {this.tips && <p class={styles.uploaderText}>{this.tips}</p>}
  206. </div>
  207. )}
  208. <ColCropper ref="uploaderRef" option={this.options} getFile={this.getFile} />
  209. </div>
  210. ) : this.native ? (
  211. <div
  212. style={{
  213. display: 'flex',
  214. alignItems: 'center',
  215. justifyContent: 'center',
  216. height: '100%'
  217. }}
  218. onClick={this.nativeUpload}
  219. >
  220. {this.modelValue ? (
  221. <Image fit="cover" position="center" class={styles.uploadImg} src={this.modelValue} />
  222. ) : (
  223. <div class={styles.uploader}>
  224. <Icon name={iconUploader} size="32" />
  225. {this.tips && <p class={styles.uploaderText}>{this.tips}</p>}
  226. </div>
  227. )}
  228. </div>
  229. ) : (
  230. <Uploader
  231. afterRead={this.afterRead}
  232. beforeRead={this.beforeRead}
  233. beforeDelete={this.beforeDelete}
  234. disabled={this.disabled}
  235. v-slots={{
  236. default: () =>
  237. this.modelValue ? (
  238. <Image
  239. fit="cover"
  240. position="center"
  241. class={styles.uploadImg}
  242. src={this.modelValue}
  243. />
  244. ) : (
  245. <div class={styles.uploader}>
  246. <Icon name={iconUploader} size="32" />
  247. {this.tips && <p class={styles.uploaderText}>{this.tips}</p>}
  248. </div>
  249. )
  250. }}
  251. />
  252. )}
  253. </div>
  254. )
  255. }
  256. })