avatar.vue 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. <template>
  2. <a-upload
  3. v-model:file-list="avatarFile"
  4. name="file"
  5. accept=".png,.jpg,.jpeg"
  6. :show-upload-list="false"
  7. action="https://v4-test.4dkankan.com/takelook/upload/file"
  8. :max-count="1"
  9. class="uploader"
  10. :headers="{
  11. authorization: 'authorization-text'
  12. }"
  13. :disabled="avatarFile.length > 0"
  14. @change="handleAvatarChange"
  15. >
  16. <div
  17. class="add-item-icon scene-sign"
  18. v-if="avatarFile.length > 0 && avatarFile[0].response"
  19. >
  20. <a-image class="avatar" :src="avatarFile[0].response.data" alt="avatar" />
  21. <span class="delete-scene" @click="deleteAvatar(avatarFile[0])">
  22. <close-outlined class="delete-scene-icon" />
  23. </span>
  24. </div>
  25. <div class="add-item-icon" v-else>
  26. <a-button shape="circle" class="button" type="primary">
  27. <plus-outlined class="add-room-icon" />
  28. </a-button>
  29. </div>
  30. </a-upload>
  31. </template>
  32. <script lang="ts" setup>
  33. import { ref } from 'vue'
  34. import { message, type UploadChangeParam } from 'ant-design-vue'
  35. import type { FileItem } from './album-list.vue'
  36. import { watchEffect } from 'vue'
  37. const emit = defineEmits(['sync'])
  38. const avatarFile = ref<any[]>([])
  39. const props = defineProps<{ data: string | undefined }>()
  40. watchEffect(() => {
  41. if (props.data?.length) {
  42. const tempData = {} as FileItem
  43. tempData.uid = `data-0`
  44. tempData.response = {
  45. data: props.data,
  46. ok: 0
  47. }
  48. if (!avatarFile.value?.length) {
  49. console.log('mapper', tempData)
  50. avatarFile.value = [tempData]
  51. }
  52. } else {
  53. avatarFile.value = []
  54. }
  55. })
  56. const handleAvatarChange = (info: UploadChangeParam) => {
  57. if (info.file.status === 'done') {
  58. const { code, data } = info.file.response
  59. if (code === 0) {
  60. emit('sync', data || '')
  61. }
  62. } else if (info.file.status === 'error') {
  63. message.error(`${info.file.name} file upload failed.`)
  64. }
  65. }
  66. const deleteAvatar = (item: any) => {
  67. const index = avatarFile.value.findIndex(i => i.uid === item.uid)
  68. if (index > -1) {
  69. avatarFile.value.splice(index, 1)
  70. }
  71. emit('sync', '')
  72. }
  73. </script>
  74. <style lang="scss" scoped>
  75. .add-item-icon {
  76. width: 120px;
  77. height: 120px;
  78. display: flex;
  79. justify-content: center;
  80. align-items: center;
  81. border: 1px solid #ebedf0;
  82. overflow: hidden;
  83. .avatar {
  84. max-width: 100%;
  85. // border-radius: 50%;
  86. }
  87. .button {
  88. background: linear-gradient(144deg, #00aefb 0%, #0076f6 100%);
  89. width: 40px;
  90. height: 40px;
  91. }
  92. }
  93. .scene-sign {
  94. border-radius: 4px;
  95. overflow: hidden;
  96. position: relative;
  97. z-index: 10;
  98. img {
  99. width: 100%;
  100. height: 100%;
  101. display: block;
  102. object-fit: cover;
  103. }
  104. .title {
  105. position: absolute;
  106. bottom: 0;
  107. left: 0;
  108. right: 0;
  109. height: 24px;
  110. background: rgba(0, 0, 0, 0.5);
  111. padding: 5px;
  112. font-size: 12px;
  113. color: #fff;
  114. margin: 0;
  115. overflow: hidden;
  116. text-overflow: ellipsis;
  117. white-space: nowrap;
  118. }
  119. .delete-scene {
  120. z-index: 2;
  121. position: absolute;
  122. right: 0;
  123. top: 0;
  124. width: 52px;
  125. height: 52px;
  126. background-color: rgba(0, 0, 0, 0.5);
  127. color: #fa5555;
  128. font-size: 14px;
  129. border-radius: 50%;
  130. display: flex;
  131. align-items: flex-end;
  132. transform: translate(100%, -100%);
  133. transition: all 0.3s ease;
  134. opacity: 0;
  135. cursor: pointer;
  136. .delete-scene-icon {
  137. padding: 10px;
  138. }
  139. }
  140. &:hover .delete-scene {
  141. transform: translate(50%, -50%);
  142. opacity: 1;
  143. }
  144. .status-cover {
  145. z-index: 1;
  146. position: absolute;
  147. left: 0;
  148. top: 0;
  149. right: 0;
  150. bottom: 0;
  151. background-color: rgba(0, 0, 0, 0.5);
  152. display: flex;
  153. align-items: center;
  154. justify-content: center;
  155. p {
  156. color: #fff;
  157. }
  158. }
  159. }
  160. </style>