index.vue 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. <template>
  2. <div class="singleImageUpload2 upload-container">
  3. <el-upload
  4. v-show="uploaderShow"
  5. v-loading="uploaderLoading"
  6. class="image-uploader"
  7. :action="uploaderRequestUrl"
  8. name="file"
  9. :headers="uploaderHeaders"
  10. :data="uploaderFormData"
  11. :show-file-list="false"
  12. :before-upload="uploaderHandleBefore"
  13. :on-success="uploaderHandleSuccess"
  14. :disabled="uploaderDisabled"
  15. :style="isImgUpload ? `width:${width};min-height:${height};` : ''"
  16. >
  17. <template v-if="isImgUpload">
  18. <el-image
  19. v-if="uploaderImageUrl"
  20. :src="uploaderImageUrl"
  21. class="image-preview"
  22. fit="contain"
  23. :style="`width:${width};min-height:${height};display: block;`"
  24. ></el-image>
  25. <i
  26. v-else
  27. class="el-icon-plus uploader-icon"
  28. :style="`width:${width};height:${height};line-height:${height};`"
  29. />
  30. </template>
  31. <template v-else>
  32. <el-button type="primary">{{ uploadBtnTitle }}</el-button>
  33. </template>
  34. </el-upload>
  35. <template v-if="isImgUpload">
  36. <div v-show="!uploaderShow" class="image-show">
  37. <el-image :src="uploaderImageUrl" alt="" :width="width" :height="height"></el-image>
  38. </div>
  39. </template>
  40. <div class="previewImg">
  41. <el-button v-show="uploaderImageUrl" type="info" class="previewImgButton" @click="previewImg">{{ $t('shop.imagePreview') }}</el-button>
  42. </div>
  43. <el-dialog append-to-body top="5vh" :visible.sync="dialogVisible" custom-class="custom-dialog">
  44. <div class="previewImage">
  45. <el-image width="60%" :src="uploaderImageUrl" alt=""></el-image>
  46. </div>
  47. </el-dialog>
  48. </div>
  49. </template>
  50. <script>
  51. import { getToken } from '@/api/upload'
  52. export default {
  53. name: 'Uploader',
  54. props: {
  55. isImgUpload: {
  56. type: Boolean,
  57. default: true
  58. },
  59. uploadBtnTitle: {
  60. type: String,
  61. default: '上传'
  62. },
  63. requestRoute: {
  64. type: String,
  65. required: true
  66. },
  67. defaultImageUrl: {
  68. type: String,
  69. default: null
  70. },
  71. uploaderSuccessCanChange: {
  72. type: Boolean,
  73. default: true
  74. },
  75. width: {
  76. type: String,
  77. default: '100px'
  78. },
  79. height: {
  80. type: String,
  81. default: '100%'
  82. }
  83. },
  84. data() {
  85. return {
  86. uploaderShow: true,
  87. uploaderLoading: false,
  88. uploaderFormData: {
  89. 'uploadToken': ''
  90. },
  91. uploaderRequestUrl: process.env.VUE_APP_BASE_API + `/${this.requestRoute}`,
  92. uploaderHeaders: {
  93. 'Device-Type': 'pc',
  94. 'Suppress-Response-Code': '1',
  95. 'Authorization': ''
  96. },
  97. uploaderDisabled: false,
  98. successImageUrl: null,
  99. uploaderImage: null,
  100. dialogVisible: false,
  101. uploadedImages: []
  102. }
  103. },
  104. computed: {
  105. uploaderImageUrl() {
  106. if (this.uploaderImage != null) {
  107. return this.uploaderImage
  108. }
  109. if (this.successImageUrl !== null) {
  110. return this.successImageUrl
  111. } else if (this.defaultImageUrl !== null) {
  112. // this.uploaderShow = false
  113. // this.uploaderDisabled = true
  114. // this.uploaderLoading = false
  115. return this.defaultImageUrl
  116. } else {
  117. return ''
  118. }
  119. }
  120. },
  121. watch: {
  122. defaultImageUrl(newVal, oldVal) {
  123. this.uploaderImage = newVal
  124. // console.log(oldVal)
  125. }
  126. },
  127. created() {
  128. console.log(this.uploaderImage)
  129. },
  130. methods: {
  131. previewImg(){
  132. this.dialogVisible = true;
  133. },
  134. uploaderHandleBefore() {
  135. const auth_token = localStorage.accessToken
  136. this.uploaderHeaders.Authorization = 'Bearer ' + auth_token
  137. return new Promise((resolve, reject) => {
  138. getToken().then(response => {
  139. console.log(response)
  140. this.uploaderFormData.uploadToken = response.data
  141. resolve(true)
  142. }).catch(() => {
  143. reject(false)
  144. })
  145. })
  146. },
  147. uploaderHandleSuccess(response, file) {
  148. // console.log(response)
  149. if (response.success) {
  150. this.$message({
  151. message: 'Successful',
  152. type: 'success'
  153. })
  154. this.successImageUrl = URL.createObjectURL(file.raw)
  155. if (!this.uploaderSuccessCanChange) {
  156. this.uploaderShow = false
  157. this.uploaderDisabled = true
  158. this.uploaderLoading = false
  159. }
  160. this.$emit('on-success', response.data)
  161. } else {
  162. this.$message({
  163. message: response.data.message,
  164. type: 'warning'
  165. })
  166. this.uploaderLoading = false
  167. }
  168. }
  169. }
  170. }
  171. </script>
  172. <style lang="scss" scoped>
  173. .upload-container {
  174. width: 100%;
  175. height: 100%;
  176. position: relative;
  177. margin-bottom: 50px;
  178. .image-uploader {
  179. height: 100%;
  180. }
  181. .image-preview {
  182. width: 100%;
  183. height: 100%;
  184. position: absolute;
  185. left: 0px;
  186. top: 0px;
  187. border: 1px dashed #d9d9d9;
  188. .image-preview-wrapper {
  189. position: relative;
  190. width: 100%;
  191. height: 100%;
  192. img {
  193. width: 100%;
  194. height: 100%;
  195. }
  196. }
  197. .image-preview-action {
  198. position: absolute;
  199. width: 100%;
  200. height: 100%;
  201. left: 0;
  202. top: 0;
  203. cursor: default;
  204. text-align: center;
  205. color: #fff;
  206. opacity: 0;
  207. font-size: 20px;
  208. background-color: rgba(0, 0, 0, .5);
  209. transition: opacity .3s;
  210. cursor: pointer;
  211. text-align: center;
  212. line-height: 200px;
  213. .el-icon-delete {
  214. font-size: 36px;
  215. }
  216. }
  217. &:hover {
  218. .image-preview-action {
  219. opacity: 1;
  220. }
  221. }
  222. }
  223. }
  224. .previewImage{
  225. display: flex;
  226. justify-content: center;
  227. align-items: center;
  228. }
  229. .previewImg{
  230. display: flex;
  231. justify-content: center;
  232. .previewImgButton{
  233. position: absolute;
  234. bottom: -50px;
  235. }
  236. }
  237. .custom-dialog {
  238. //background: rgba(0, 0, 0, 0); /* 半透明的背景 */
  239. background-color: transparent!important;
  240. }
  241. .custom-dialog {
  242. background-color: transparent; /* 使对话框的背景透明 */
  243. box-shadow: none; /* 移除阴影 */
  244. }
  245. .custom-dialog .el-dialog__header,
  246. .custom-dialog .el-dialog__body,
  247. .custom-dialog .el-dialog__footer {
  248. background-color: transparent; /* 透明的头部、内容和底部 */
  249. }
  250. .custom-dialog .el-dialog__header {
  251. border-bottom: none; /* 移除对话框头部的边框 */
  252. }
  253. .custom-dialog .el-dialog__footer {
  254. border-top: none; /* 移除底部的边框 */
  255. }
  256. </style>