gemercheung %!s(int64=2) %!d(string=hai) anos
pai
achega
0055a68490

+ 5 - 1
src/api/room.ts

@@ -34,6 +34,7 @@ export type SRoom = {
   image?: string[]
   head?: string
   gps?: string
+  video?: string
 }
 
 export interface RoomScene {
@@ -65,6 +66,7 @@ export interface Room {
   userObjList?: AuthUser[],
   scenesAvatar?: string
   scenesAlbum?: string[]
+  scenesVideo?: string
   gps?: string
 
 }
@@ -87,6 +89,7 @@ const serverToLocal = (sroom: SRoom): Room => ({
   userObjList: sroom.userObjList,
   scenesAlbum: sroom.image,
   scenesAvatar: sroom.head,
+  scenesVideo: sroom.video,
 })
 const localToServer = (room: Room): SRoom => ({
   roomId: room.id,
@@ -105,7 +108,8 @@ const localToServer = (room: Room): SRoom => ({
   freeRoamLock: room.freeRoamLock || 0,
   userObjList: room.userObjList,
   image: room.scenesAlbum,
-  head: room.scenesAvatar
+  head: room.scenesAvatar,
+  video: room.scenesVideo,
 })
 
 export const fetchRomms = async (status: number = 1): Promise<Rooms> => {

+ 21 - 4
src/views/room/edit-room/album-list.vue

@@ -6,6 +6,7 @@
           <a-upload
             v-model:file-list="albumFile"
             name="file"
+            accept=".png,.jpg,.jpeg"
             :show-upload-list="false"
             action="https://v4-test.4dkankan.com/takelook/upload/file"
             :multiple="true"
@@ -20,7 +21,7 @@
           </a-upload>
         </div>
 
-        <div v-else class="scene-sign">
+        <div v-else class="scene-sign" v-if="item.status === 'done'">
           <img v-if="item.response" :src="item.response?.data" />
           <span class="delete-scene" @click="deleteAblum(item)">
             <close-outlined class="delete-scene-icon" />
@@ -62,8 +63,17 @@ const props = defineProps<{ data: string[] }>()
 
 const addMarked = Symbol('add-album')
 const albumFile = ref<any[]>([])
+const albumFileExist = ref<any[]>([])
+const totalist = computed(() =>
+  uniqBy([albumFile.value, albumFileExist.value], 'response.data')
+)
 
-const current = computed(() => [addMarked, ...albumFile.value])
+const current = computed(() => [
+  addMarked
+  // ...totalist.value
+  // ...albumFileExist.value,
+  // ...albumFile.value
+])
 const albumList = computed(() =>
   Array.from(albumFile.value).reduce((prev, cur) => {
     if (prev && cur.response?.data) {
@@ -84,6 +94,7 @@ const deleteAblum = (item: FileItem) => {
 }
 const emit = defineEmits(['syncList'])
 watchEffect(() => {
+  console.log('totalist', totalist)
   if (props.data?.length) {
     const mapper = Array.from(props.data).map((i, index) => {
       const tempData = {} as FileItem
@@ -92,10 +103,13 @@ watchEffect(() => {
         data: i,
         ok: 0
       }
+      tempData.status = 'done'
       return tempData
     })
-
-    albumFile.value = uniqBy(albumFile.value.concat(mapper), 'response.data')
+    albumFileExist.value = uniqBy(
+      albumFileExist.value.concat(mapper),
+      'response.data'
+    )
   }
 })
 
@@ -107,7 +121,9 @@ const handleABlumChange = (info: UploadChangeParam) => {
   } else if (info.file.status === 'error') {
     message.error(`${info.file.name} file upload failed.`)
   }
+  console.log('check', albumFile)
 }
+
 const handleBeforeUpload = (file: any) => {
   const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png'
   if (!isJpgOrPng) {
@@ -126,6 +142,7 @@ const handleBeforeUpload = (file: any) => {
   border: 1px solid #ebedf0;
   border-radius: 4px;
   height: 100%;
+  width: 100%;
   cursor: pointer;
   display: flex;
   align-items: center;

+ 1 - 0
src/views/room/edit-room/avatar.vue

@@ -2,6 +2,7 @@
   <a-upload
     v-model:file-list="avatarFile"
     name="file"
+    accept=".png,.jpg,.jpeg"
     :show-upload-list="false"
     action="https://v4-test.4dkankan.com/takelook/upload/file"
     :max-count="1"

+ 12 - 9
src/views/room/edit-room/index.vue

@@ -74,7 +74,7 @@
             />
           </a-form-item>
 
-          <a-form-item label="位置" name="map">
+          <!-- <a-form-item label="位置" name="map">
             <a-input
               v-model:value.trim="current.location"
               placeholder=""
@@ -85,7 +85,7 @@
             />
             <div style="margin: 10px 0"></div>
             <div ref="mapRef" style="width: 100%; height: 194px"></div>
-          </a-form-item>
+          </a-form-item> -->
 
           <a-form-item :label="t('room.form.desc')" name="desc">
             <a-textarea
@@ -115,11 +115,7 @@
             />
           </a-form-item>
 
-          <a-form-item
-            label="头像"
-            name="title"
-            :rules="[{ required: true, message: '' }]"
-          >
+          <a-form-item label="头像" name="title">
             <EditAvatar :data="current.scenesAvatar" @sync="handleAvatarSync" />
           </a-form-item>
           <!-- 相册 -->
@@ -129,6 +125,12 @@
               @sync-list="handleAlbumSync"
             />
           </a-form-item>
+          <a-form-item label="视频" name="title">
+            <EditVideo
+              :data="current.scenesVideo"
+              @sync-list="handleAlbumSync"
+            />
+          </a-form-item>
 
           <a-form-item
             :label="t('room.form.addScene')"
@@ -306,6 +308,7 @@ import { mainURL } from '@/env'
 import EditScenes from './scene-list.vue'
 import EditAlbum from './album-list.vue'
 import EditAvatar from './avatar.vue'
+import EditVideo from './video.vue'
 import unScenePng from '@/assets/images/un-scene.png'
 import VOtpInput from 'vue3-otp-input'
 import type { Scene } from '@/store/modules/scene'
@@ -336,7 +339,7 @@ interface AuthUserFormState {
 
 export default defineComponent({
   name: 'EditRoom',
-  components: { EditScenes, VOtpInput, EditAlbum, EditAvatar },
+  components: { EditScenes, VOtpInput, EditAlbum, EditAvatar, EditVideo },
   props,
   setup(props) {
     const visible = ref(true)
@@ -601,7 +604,7 @@ export default defineComponent({
     }
 
     onMounted(() => {
-      initMap()
+      // initMap()
     })
 
     const handleAvatarChange = (info: UploadChangeParam) => {

+ 168 - 0
src/views/room/edit-room/video.vue

@@ -0,0 +1,168 @@
+<template>
+  <a-upload
+    v-model:file-list="avatarFile"
+    name="file"
+    :show-upload-list="false"
+    accept=".mp4"
+    action="https://v4-test.4dkankan.com/takelook/upload/file"
+    :max-count="1"
+    class="uploader"
+    :headers="{
+      authorization: 'authorization-text'
+    }"
+    :disabled="avatarFile.length > 0"
+    @change="handleAvatarChange"
+  >
+    <div
+      class="add-item-icon scene-sign"
+      v-if="avatarFile.length > 0 && avatarFile[0].response"
+    >
+      <img class="avatar" :src="avatarFile[0].response.data" alt="avatar" />
+      <span class="delete-scene" @click="deleteAvatar(avatarFile[0])">
+        <close-outlined class="delete-scene-icon" />
+      </span>
+    </div>
+    <div class="add-item-icon" v-else>
+      <a-button shape="circle" class="button" type="primary">
+        <plus-outlined class="add-room-icon" />
+      </a-button>
+    </div>
+  </a-upload>
+</template>
+<script lang="ts" setup>
+import { ref } from 'vue'
+import { message, type UploadChangeParam } from 'ant-design-vue'
+import type { FileItem } from './album-list.vue'
+
+import { watchEffect } from 'vue'
+const emit = defineEmits(['sync'])
+const avatarFile = ref<any[]>([])
+const props = defineProps<{ data: string | undefined }>()
+
+watchEffect(() => {
+  if (props.data?.length) {
+    const tempData = {} as FileItem
+    tempData.uid = `data-0`
+    tempData.response = {
+      data: props.data,
+      ok: 0
+    }
+    if (!avatarFile.value?.length) {
+      console.log('mapper', tempData)
+      avatarFile.value = [tempData]
+    }
+  } else {
+    avatarFile.value = []
+  }
+})
+
+const handleAvatarChange = (info: UploadChangeParam) => {
+  if (info.file.status === 'done') {
+    const { code, data } = info.file.response
+    if (code === 0) {
+      emit('sync', data || '')
+    }
+  } else if (info.file.status === 'error') {
+    message.error(`${info.file.name} file upload failed.`)
+  }
+}
+const deleteAvatar = (item: any) => {
+  const index = avatarFile.value.findIndex(i => i.uid === item.uid)
+  if (index > -1) {
+    avatarFile.value.splice(index, 1)
+  }
+  emit('sync', '')
+}
+</script>
+
+<style lang="scss" scoped>
+.add-item-icon {
+  width: 120px;
+  height: 120px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  border: 1px solid #ebedf0;
+  overflow: hidden;
+  .avatar {
+    max-width: 100%;
+    // border-radius: 50%;
+  }
+  .button {
+    background: linear-gradient(144deg, #00aefb 0%, #0076f6 100%);
+    width: 40px;
+    height: 40px;
+  }
+}
+.scene-sign {
+  border-radius: 4px;
+  overflow: hidden;
+  position: relative;
+  z-index: 10;
+  img {
+    width: 100%;
+    height: 100%;
+    display: block;
+    object-fit: cover;
+  }
+  .title {
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    height: 24px;
+    background: rgba(0, 0, 0, 0.5);
+    padding: 5px;
+    font-size: 12px;
+    color: #fff;
+    margin: 0;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+
+  .delete-scene {
+    z-index: 2;
+    position: absolute;
+    right: 0;
+    top: 0;
+    width: 52px;
+    height: 52px;
+    background-color: rgba(0, 0, 0, 0.5);
+    color: #fa5555;
+    font-size: 14px;
+    border-radius: 50%;
+    display: flex;
+    align-items: flex-end;
+    transform: translate(100%, -100%);
+    transition: all 0.3s ease;
+    opacity: 0;
+    cursor: pointer;
+
+    .delete-scene-icon {
+      padding: 10px;
+    }
+  }
+
+  &:hover .delete-scene {
+    transform: translate(50%, -50%);
+    opacity: 1;
+  }
+  .status-cover {
+    z-index: 1;
+    position: absolute;
+    left: 0;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0, 0, 0, 0.5);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+
+    p {
+      color: #fff;
+    }
+  }
+}
+</style>