tremble %!s(int64=2) %!d(string=hai) anos
pai
achega
40075a2941
Modificáronse 64 ficheiros con 917 adicións e 691 borrados
  1. 2 0
      packages/qjkankan-editor/.env
  2. 8 0
      packages/qjkankan-editor/.env.eurtestdev
  3. 10 0
      packages/qjkankan-editor/.env.eurtestprod
  4. 1 0
      packages/qjkankan-editor/.env.prod
  5. 1 0
      packages/qjkankan-editor/.env.testdev
  6. 1 0
      packages/qjkankan-editor/.env.testprod
  7. 2 0
      packages/qjkankan-editor/package.json
  8. 11 0
      packages/qjkankan-editor/src/assets/images/icons/logo_black_en.svg
  9. 0 0
      packages/qjkankan-editor/src/assets/images/icons/logo_black_zh.svg
  10. BIN=BIN
      packages/qjkankan-editor/src/assets/images/select_pic_btn_en.png
  11. 0 0
      packages/qjkankan-editor/src/assets/images/select_pic_btn_zh.png
  12. 82 82
      packages/qjkankan-editor/src/components/materialSelectorForEditor.vue
  13. 218 201
      packages/qjkankan-editor/src/components/materialSelectorForManageCenter.vue
  14. 18 18
      packages/qjkankan-editor/src/components/materialSelectorFromWorkForEditor.vue
  15. 3 3
      packages/qjkankan-editor/src/components/preview/index.vue
  16. 2 1
      packages/qjkankan-editor/src/components/sceneGroupInEditor.vue
  17. 7 2
      packages/qjkankan-editor/src/components/shared/Editor.vue
  18. 9 2
      packages/qjkankan-editor/src/components/shared/loading/smallWaiting.vue
  19. 8 2
      packages/qjkankan-editor/src/components/shared/loading/smallWaiting1.vue
  20. 1 1
      packages/qjkankan-editor/src/components/shared/message/Alert.vue
  21. 2 2
      packages/qjkankan-editor/src/components/shared/message/Confirm.vue
  22. 1 37
      packages/qjkankan-editor/src/config/index.js
  23. 5 5
      packages/qjkankan-editor/src/framework/EditorHead.vue
  24. 1 1
      packages/qjkankan-editor/src/framework/core/index.vue
  25. 3 2
      packages/qjkankan-editor/src/framework/material/header.vue
  26. 3 3
      packages/qjkankan-editor/src/framework/play/pano/index.vue
  27. 185 109
      packages/qjkankan-editor/src/lang/_en.json
  28. 88 4
      packages/qjkankan-editor/src/lang/_zh.json
  29. 8 25
      packages/qjkankan-editor/src/mixins/index.js
  30. 3 0
      packages/qjkankan-editor/src/pages/show.js
  31. 2 0
      packages/qjkankan-editor/src/pages/vr.js
  32. 21 39
      packages/qjkankan-editor/src/utils/request.js
  33. 0 1
      packages/qjkankan-editor/src/views/base/Toolbar.vue
  34. 10 5
      packages/qjkankan-editor/src/views/base/customButtonSettings.vue
  35. 1 1
      packages/qjkankan-editor/src/views/base/customLogoSettings.vue
  36. 2 2
      packages/qjkankan-editor/src/views/base/customMaskSettings.vue
  37. 1 0
      packages/qjkankan-editor/src/views/hotspot/hotspotType/scene.vue
  38. 11 11
      packages/qjkankan-editor/src/views/material/audio/index.vue
  39. 10 10
      packages/qjkankan-editor/src/views/material/image/index.vue
  40. 16 16
      packages/qjkankan-editor/src/views/material/pano/index.vue
  41. 1 1
      packages/qjkankan-editor/src/views/material/popup/cover.vue
  42. 1 1
      packages/qjkankan-editor/src/views/material/popup/panoImagePreviewer.vue
  43. 3 3
      packages/qjkankan-editor/src/views/material/popup/share.vue
  44. 2 1
      packages/qjkankan-editor/src/views/material/style.less
  45. 12 12
      packages/qjkankan-editor/src/views/material/video/index.vue
  46. 16 14
      packages/qjkankan-editor/src/views/material/works/index.vue
  47. 21 0
      packages/qjkankan-kankan-view/.env.eurtestprod
  48. 1 0
      packages/qjkankan-kankan-view/package.json
  49. 2 12
      packages/qjkankan-kankan-view/src/i18n/index.js
  50. 9 0
      packages/qjkankan-view/.env.eurtestdev
  51. 6 0
      packages/qjkankan-view/.env.eurtestprod
  52. 2 0
      packages/qjkankan-view/package.json
  53. 7 3
      packages/qjkankan-view/src/components/Fdkk/index.vue
  54. 2 4
      packages/qjkankan-view/src/components/Fdkk/v3fdkkmobile/iframe.vue
  55. 5 1
      packages/qjkankan-view/src/components/Pano/index.vue
  56. 2 2
      packages/qjkankan-view/src/components/assembly/Share.vue
  57. 2 13
      packages/qjkankan-view/src/i18n/index.js
  58. 35 34
      packages/qjkankan-view/src/locales/en.json
  59. 15 1
      packages/qjkankan-view/src/locales/zh.json
  60. 1 0
      packages/qjkankan-view/src/pages/show.js
  61. 5 0
      packages/qjkankan-view/src/pages/show.vue
  62. 7 0
      packages/qjkankan-view/src/pages/showMobile.vue
  63. 1 3
      packages/qjkankan-view/src/store/modules/fdkk.js
  64. 2 1
      packages/qjkankan-view/src/utils/config.js

+ 2 - 0
packages/qjkankan-editor/.env

@@ -3,4 +3,6 @@ VUE_APP_STATIC_DIR=static
 VUE_APP_CDN=https://4dkk.4dage.com
 VUE_APP_PROXY_URL_ROOT='https://www.4dkankan.com'
 VUE_APP_PROXY_URL='https://www.4dkankan.com/qjkankan/'
+VUE_APP_ORIGIN=
+
 VUE_APP_URL_FILL=

+ 8 - 0
packages/qjkankan-editor/.env.eurtestdev

@@ -0,0 +1,8 @@
+VUE_APP_MAIN_COLOR=''
+VUE_APP_STATIC_DIR=static
+VUE_APP_CDN=https://testeurs3.4dkankan.com
+VUE_APP_PROXY_URL_ROOT='https://testeur.4dkankan.com'
+VUE_APP_PROXY_URL='https://testeur.4dkankan.com/qjkankan/'
+VUE_APP_ORIGIN=aws
+
+VUE_APP_URL_FILL=

+ 10 - 0
packages/qjkankan-editor/.env.eurtestprod

@@ -0,0 +1,10 @@
+
+NODE_ENV=production
+VUE_APP_MAIN_COLOR=''
+VUE_APP_STATIC_DIR=static
+VUE_APP_CDN=https://testeurs3.4dkankan.com
+VUE_APP_PROXY_URL_ROOT='https://testeur.4dkankan.com'
+VUE_APP_PROXY_URL='https://testeur.4dkankan.com/qjkankan/'
+VUE_APP_ORIGIN=aws
+
+VUE_APP_URL_FILL=/qjkankan

+ 1 - 0
packages/qjkankan-editor/.env.prod

@@ -5,4 +5,5 @@ VUE_APP_STATIC_DIR=static
 VUE_APP_CDN=https://4dkk.4dage.com
 VUE_APP_PROXY_URL_ROOT='https://www.4dkankan.com'
 VUE_APP_PROXY_URL='https://www.4dkankan.com/qjkankan/'
+VUE_APP_ORIGIN=
 VUE_APP_URL_FILL=/qjkankan

+ 1 - 0
packages/qjkankan-editor/.env.testdev

@@ -3,4 +3,5 @@ VUE_APP_STATIC_DIR=static
 VUE_APP_CDN=https://ossxiaoan.4dage.com
 VUE_APP_PROXY_URL_ROOT='https://test.4dkankan.com'
 VUE_APP_PROXY_URL='https://test.4dkankan.com/qjkankan/'
+VUE_APP_ORIGIN=
 VUE_APP_URL_FILL=

+ 1 - 0
packages/qjkankan-editor/.env.testprod

@@ -5,4 +5,5 @@ VUE_APP_STATIC_DIR=static
 VUE_APP_CDN=https://ossxiaoan.4dage.com
 VUE_APP_PROXY_URL_ROOT='https://test.4dkankan.com'
 VUE_APP_PROXY_URL='https://test.4dkankan.com/qjkankan/'
+VUE_APP_ORIGIN=
 VUE_APP_URL_FILL=/qjkankan

+ 2 - 0
packages/qjkankan-editor/package.json

@@ -7,9 +7,11 @@
     "serve-prod": "vue-cli-service serve --mode prod",
     "serve-testprod": "vue-cli-service serve --mode testprod",
     "serve-testdev": "vue-cli-service serve --mode testdev",
+    "serve-eurtestdev": "vue-cli-service serve --mode eurtestdev",
     "build": "vue-cli-service build",
     "build-prod": "vue-cli-service build --mode prod",
     "build-testprod": "vue-cli-service build --mode testprod",
+    "build-eurtestprod": "vue-cli-service build --mode eurtestprod",
     "lint": "vue-cli-service lint"
   },
   "dependencies": {

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 11 - 0
packages/qjkankan-editor/src/assets/images/icons/logo_black_en.svg


packages/qjkankan-editor/src/assets/images/icons/logo_black.svg → packages/qjkankan-editor/src/assets/images/icons/logo_black_zh.svg


BIN=BIN
packages/qjkankan-editor/src/assets/images/select_pic_btn_en.png


packages/qjkankan-editor/src/assets/images/select_pic_btn.png → packages/qjkankan-editor/src/assets/images/select_pic_btn_zh.png


+ 82 - 82
packages/qjkankan-editor/src/components/materialSelectorForEditor.vue

@@ -5,29 +5,29 @@
 
     <div class="material-tab">
       <a v-if="selectableType.includes('image')" class="material-tab-item" @click.prevent="currentMaterialType = 'image'">
-        <span class="text">图片</span>
+        <span class="text">{{$i18n.t(`gather.image`)}}</span>
         <div v-if="currentMaterialType === 'image'" class="bottom-line"></div>
       </a>
       <a v-if="selectableType.includes('pano')" class="material-tab-item" @click.prevent="currentMaterialType = 'pano'">
-        <span class="text">全景图</span>
+        <span class="text">{{$i18n.t(`gather.panorama`)}}</span>
         <div v-if="currentMaterialType === 'pano'" class="bottom-line"></div>
       </a>
       <a v-if="selectableType.includes('audio')" class="material-tab-item" @click.prevent="currentMaterialType = 'audio'">
-        <span class="text">音频</span>
+        <span class="text">{{$i18n.t(`gather.audio`)}}</span>
         <div v-if="currentMaterialType === 'audio'" class="bottom-line"></div>
       </a>
       <a v-if="selectableType.includes('video')" class="material-tab-item" @click.prevent="currentMaterialType = 'video'">
-        <span class="text">视频</span>
+        <span class="text">{{$i18n.t(`gather.video`)}}</span>
         <div v-if="currentMaterialType === 'video'" class="bottom-line"></div>
       </a>
       <a v-if="selectableType.includes('3D')" class="material-tab-item" @click.prevent="currentMaterialType = '3D'">
-        <span class="text">三维场景</span>
+        <span class="text">{{$i18n.t(`gather.scene`)}}</span>
         <div v-if="currentMaterialType === '3D'" class="bottom-line"></div>
       </a>
     </div>
     
     <div class="filter">
-      <input type="text" placeholder="输入关键词" v-model="searchKey"/>
+      <input type="text" :placeholder="$i18n.t(`gather.keywords`)" v-model="searchKey"/>
       <i v-if="!searchKey" class="iconfont icon-editor_search search-icon"/>
       <i v-if="searchKey" @click="searchKey=''" class="iconfont icontoast_red clear-icon"></i>
     </div>
@@ -39,7 +39,7 @@
           <div v-show="!isAllSelected" class="unchecked" @click="onSelectAll"></div>
           <img v-show="isAllSelected" class="checked" @click="onUnselectAll" src="@/assets/images/icons/checkbox.png" />
         </span>
-        <span class="table-head" v-for="(item,i) in tableHeadersForImage" :key="i">{{item.name}}</span>
+        <span class="table-head" v-for="(item,i) in tableHeadersForImage" :key="i">{{ item.name && $i18n.t(`zh_key.${item.name}`) }}</span>
       </div>
       <div
         v-if="imageListLocalLength !== 0 || hasMoreImageData"
@@ -61,7 +61,7 @@
             </span>
             <span class="table-data" v-for="(tableItemStructure, idx) in tableHeadersForImage" :key="idx">
               <div v-if="tableItemStructure.type=='image'" class="list-img">
-                <img :src="item.successInfo[tableItemStructure.key] + (Number(item.fileSize)>512 ? `?x-oss-process=image/resize,p_20&${Math.random()}` : ``)" alt="">
+                <img :src="item.successInfo[tableItemStructure.key] + (Number(item.fileSize)>512 ? $imgsuffix : ``)" alt="">
               </div>
               <span  v-else class="ellipsis" v-title="tableItemStructure.key === 'name' ? item.successInfo[tableItemStructure.key] : ''">{{ item.successInfo[tableItemStructure.key] }}</span>
             </span>
@@ -79,7 +79,7 @@
                 <img src="@/assets/images/icons/upload-file-type-icon-image@2x.png" alt="">
               </div>
               <span  v-if="tableItemStructure.key !== 'name' && tableItemStructure.key !== 'dpi'"></span>
-              <span  v-if="tableItemStructure.key === 'dpi'">上传素材 {{Math.round(item.progress * 100)}}%</span>
+              <span  v-if="tableItemStructure.key === 'dpi'">{{$i18n.t(`gather.upload_material`)}} {{Math.round(item.progress * 100)}}%</span>
               <span  v-if="tableItemStructure.key === 'name'" class="ellipsis" v-title="tableItemStructure.key === 'name' ? item.title : ''">{{ item.title }}</span>
             </span>
           </template>
@@ -96,7 +96,7 @@
                 <img src="@/assets/images/icons/upload-file-type-icon-image@2x.png" alt="">
               </div>
               <span  v-if="tableItemStructure.key !== 'name' && tableItemStructure.key !== 'dpi'"></span>
-              <span  v-if="tableItemStructure.key === 'dpi'">上传失败</span>
+              <span  v-if="tableItemStructure.key === 'dpi'">{{$i18n.t(`tips_code.FAILURE_3025`)}}</span>
               <span  v-if="tableItemStructure.key === 'name'" class="ellipsis" v-title="tableItemStructure.key === 'name' ? item.title : ''">{{ item.title }}</span>
             </span>
           </template>
@@ -113,7 +113,7 @@
           </span>
           <span class="table-data" v-for="(sub,idx) in tableHeadersForImage" :key="idx">
             <div v-if="sub.type=='image'" class="list-img">
-              <img :src="item[sub.key] + (Number(item.fileSize)>512 ? `?x-oss-process=image/resize,p_20&${Math.random()}` : ``)" alt="">
+              <img :src="item[sub.key] + (Number(item.fileSize)>512 ? $imgsuffix : ``)" alt="">
             </div>
             <span class="ellipsis" v-else v-title="sub.key === 'name' ? item[sub.key] : ''">{{ item[sub.key] }}</span>
           </span>
@@ -123,11 +123,11 @@
       <div v-else class="no-data">
         <div v-if="latestUsedSearchKey">
           <img :src="require('@/assets/images/default/empty_04_search.png')" alt="">
-          <span>{{'未搜索到结果~'}}</span>
+          <span>{{$i18n.t(`gather.no_serch_result`)}}</span>
         </div>
         <div v-if="!latestUsedSearchKey">
           <img :src="require('@/assets/images/default/empty_04.png')" alt="">
-          <span>{{'暂无素材~'}}</span>
+          <span>{{$i18n.t(`gather.no_material_result`)}}</span>
         </div>
       </div>
     </div>
@@ -139,7 +139,7 @@
           <div v-show="!isAllSelected" class="unchecked" @click="onSelectAll"></div>
           <div v-show="isAllSelected" class="checked" @click="onUnselectAll"></div>
         </span>
-        <span class="table-head" v-for="(item,i) in tableHeadersForPano" :key="i">{{item.name}}</span>
+        <span class="table-head" v-for="(item,i) in tableHeadersForPano" :key="i">{{ item.name && $i18n.t(`zh_key.${item.name}`) }}</span>
       </div>
       <div
         v-if="panoListLocalLength !== 0 || hasMorePanoData"
@@ -161,7 +161,7 @@
             </span>
             <span class="table-data" v-for="(tableItemStructure, idx) in tableHeadersForPano" :key="idx">
               <div v-if="tableItemStructure.type=='image'" class="list-img">
-                <img :src="item.successInfo[tableItemStructure.key] + (Number(item.fileSize)>512 ? `?x-oss-process=image/resize,p_20&${Math.random()}` : ``)" alt="">
+                <img :src="item.successInfo[tableItemStructure.key] + (Number(item.fileSize)>512 ? $imgsuffix : ``)" alt="">
               </div>
               <span  v-else class="ellipsis" v-title="tableItemStructure.key === 'name' ? item.successInfo[tableItemStructure.key] : ''">{{ item.successInfo[tableItemStructure.key] }}</span>
             </span>
@@ -179,7 +179,7 @@
                 <img src="@/assets/images/icons/upload-file-type-icon-image@2x.png" alt="">
               </div>
               <span  v-if="tableItemStructure.key !== 'name' && tableItemStructure.key !== 'fileSize'"></span>
-              <span  v-if="tableItemStructure.key === 'fileSize' && item.ifKnowProgress">上传素材 {{Math.round(item.progress * 100)}}%</span>
+              <span  v-if="tableItemStructure.key === 'fileSize' && item.ifKnowProgress">{{$i18n.t(`gather.upload_material`)}} {{Math.round(item.progress * 100)}}%</span>
               <span  v-if="tableItemStructure.key === 'fileSize' && !item.ifKnowProgress">{{item.statusText}}</span>
               <span  v-if="tableItemStructure.key === 'name'" class="ellipsis" v-title="tableItemStructure.key === 'name' ? item.title : ''">{{ item.title }}</span>
             </span>
@@ -197,7 +197,7 @@
                 <img src="@/assets/images/icons/upload-file-type-icon-image@2x.png" alt="">
               </div>
               <span  v-if="tableItemStructure.key !== 'name' && tableItemStructure.key !== 'fileSize'"></span>
-              <span  v-if="tableItemStructure.key === 'fileSize'">上传失败</span>
+              <span  v-if="tableItemStructure.key === 'fileSize'">{{$i18n.t(`tips_code.FAILURE_3025`)}}</span>
               <span  v-if="tableItemStructure.key === 'name'" class="ellipsis" v-title="tableItemStructure.key === 'name' ? item.title : ''">{{ item.title }}</span>
             </span>
           </template>
@@ -214,7 +214,7 @@
           </span>
           <span class="table-data" v-for="(sub,idx) in tableHeadersForPano" :key="idx">
             <div v-if="sub.type=='image'" class="list-img">
-              <img :src="item[sub.key] + (Number(item.fileSize)>512 ? `?x-oss-process=image/resize,p_20&${Math.random()}` : '')" alt="">
+              <img :src="item[sub.key] + (Number(item.fileSize)>512 ? $imgsuffix : '')" alt="">
             </div>
             <span class="ellipsis" v-else v-title="sub.key === 'name' ? item[sub.key] : ''">{{item[sub.key]}}</span>
           </span>
@@ -224,11 +224,11 @@
       <div v-else class="no-data">
         <div v-if="latestUsedSearchKey">
           <img :src="require('@/assets/images/default/empty_04_search.png')" alt="">
-          <span>{{'未搜索到结果~'}}</span>
+          <span>{{$i18n.t(`gather.no_serch_result`)}}</span>
         </div>
         <div v-if="!latestUsedSearchKey">
           <img :src="require('@/assets/images/default/empty_04.png')" alt="">
-          <span>{{'暂无素材~'}}</span>
+          <span>{{$i18n.t(`gather.no_material_result`)}}</span>
         </div>
       </div>
     </div>
@@ -240,7 +240,7 @@
           <div v-show="!isAllSelected" class="unchecked" @click="onSelectAll"></div>
           <div v-show="isAllSelected" class="checked" @click="onUnselectAll"></div>
         </span>
-        <span class="table-head" v-for="(item,i) in tableHeadersForAudio" :key="i">{{item.name}}</span>
+        <span class="table-head" v-for="(item,i) in tableHeadersForAudio" :key="i">{{ item.name && $i18n.t(`zh_key.${item.name}`) }}</span>
       </div>
       <div
         v-if="audioListLocalLength !== 0 || hasMoreAudioData"
@@ -295,7 +295,7 @@
                 >
               </div>
               <span  v-if="tableItemStructure.key !== 'name' && tableItemStructure.key !== 'fileSize'"></span>
-              <span  v-if="tableItemStructure.key === 'fileSize'">上传素材 {{Math.round(item.progress * 100)}}%</span>
+              <span  v-if="tableItemStructure.key === 'fileSize'">{{$i18n.t(`gather.upload_material`)}} {{Math.round(item.progress * 100)}}%</span>
               <span  v-if="tableItemStructure.key === 'name'" class="ellipsis" v-title="tableItemStructure.key === 'name' ? item.title : ''">{{ item.title }}</span>
             </span>
           </template>
@@ -316,7 +316,7 @@
                 >
               </div>
               <span  v-if="tableItemStructure.key !== 'name' && tableItemStructure.key !== 'fileSize'"></span>
-              <span  v-if="tableItemStructure.key === 'fileSize'">上传失败</span>
+              <span  v-if="tableItemStructure.key === 'fileSize'">{{$i18n.t(`tips_code.FAILURE_3025`)}}</span>
               <span  v-if="tableItemStructure.key === 'name'" class="ellipsis" v-title="tableItemStructure.key === 'name' ? item.title : ''">{{ item.title }}</span>
             </span>
           </template>
@@ -354,11 +354,11 @@
       <div v-else class="no-data">
         <div v-if="latestUsedSearchKey">
           <img :src="require('@/assets/images/default/empty_04_search.png')" alt="">
-          <span>{{'未搜索到结果~'}}</span>
+          <span>{{$i18n.t(`gather.no_serch_result`)}}</span>
         </div>
         <div v-if="!latestUsedSearchKey">
           <img :src="require('@/assets/images/default/empty_04.png')" alt="">
-          <span>{{'暂无素材~'}}</span>
+          <span>{{$i18n.t(`gather.no_material_result`)}}</span>
         </div>
       </div>
     </div>
@@ -370,7 +370,7 @@
           <div v-show="!isAllSelected" class="unchecked" @click="onSelectAll"></div>
           <div v-show="isAllSelected" class="checked" @click="onUnselectAll"></div>
         </span>
-        <span class="table-head" v-for="(item,i) in tableHeadersForVideo" :key="i">{{item.name}}</span>
+        <span class="table-head" v-for="(item,i) in tableHeadersForVideo" :key="i">{{ item.name && $i18n.t(`zh_key.${item.name}`) }}</span>
       </div>
       <div
         v-if="videoListLocalLength !== 0 || hasMoreVideoData"
@@ -417,7 +417,7 @@
                 >
               </div>
               <span  v-if="tableItemStructure.key !== 'name' && tableItemStructure.key !== 'fileSize'"></span>
-              <span  v-if="tableItemStructure.key === 'fileSize'">上传素材 {{Math.round(item.progress * 100)}}%</span>
+              <span  v-if="tableItemStructure.key === 'fileSize'">{{$i18n.t(`gather.upload_material`)}} {{Math.round(item.progress * 100)}}%</span>
               <span  v-if="tableItemStructure.key === 'name'" class="ellipsis" v-title="tableItemStructure.key === 'name' ? item.title : ''">{{ item.title }}</span>
             </span>
           </template>
@@ -438,7 +438,7 @@
                 >
               </div>
               <span  v-if="tableItemStructure.key !== 'name' && tableItemStructure.key !== 'fileSize'"></span>
-              <span  v-if="tableItemStructure.key === 'fileSize'">上传失败</span>
+              <span  v-if="tableItemStructure.key === 'fileSize'">{{$i18n.t(`tips_code.FAILURE_3025`)}}</span>
               <span  v-if="tableItemStructure.key === 'name'" class="ellipsis" v-title="tableItemStructure.key === 'name' ? item.title : ''">{{ item.title }}</span>
             </span>
           </template>
@@ -466,11 +466,11 @@
       <div v-else class="no-data">
         <div v-if="latestUsedSearchKey">
           <img :src="require('@/assets/images/default/empty_04_search.png')" alt="">
-          <span>{{'未搜索到结果~'}}</span>
+          <span>{{$i18n.t(`gather.no_serch_result`)}}</span>
         </div>
         <div v-if="!latestUsedSearchKey">
           <img :src="require('@/assets/images/default/empty_04.png')" alt="">
-          <span>{{'暂无素材~'}}</span>
+          <span>{{$i18n.t(`gather.no_material_result`)}}</span>
         </div>
       </div>
     </div>
@@ -482,7 +482,7 @@
           <div v-show="!isAllSelected" class="unchecked" @click="onSelectAll"></div>
           <div v-show="isAllSelected" class="checked" @click="onUnselectAll"></div>
         </span>
-        <span class="table-head" v-for="(item,i) in tableHeadersFor3D" :key="i">{{item.name}}</span>
+        <span class="table-head" v-for="(item,i) in tableHeadersFor3D" :key="i">{{ item.name && $i18n.t(`zh_key.${item.name}`) }}</span>
       </div>
       <div
         v-if="scene3DList.length !== 0 || hasMore3DData"
@@ -501,7 +501,7 @@
           </span>
           <span class="table-data" v-for="(sub,idx) in tableHeadersFor3D" :key="idx">
             <div v-if="sub.type=='image'" class="list-img">
-              <img :src="item[sub.key] + (Number(item.fileSize)>512 ? `?x-oss-process=image/resize,p_20&${Math.random()}` : ``)" alt="">
+              <img :src="item[sub.key] + (Number(item.fileSize)>512 ? $imgsuffix : ``)" alt="">
             </div>
             <span class="ellipsis" v-else v-title="sub.key === 'name' ? item[sub.key] : ''">{{item[sub.key]}}</span>
           </span>
@@ -511,13 +511,13 @@
       <div v-else class="no-data">
         <div v-if="latestUsedSearchKey">
           <img :src="require('@/assets/images/default/empty_04_search.png')" alt="">
-          <span>{{'未搜索到结果~'}}</span>
+          <span>{{$i18n.t(`gather.no_serch_result`)}}</span>
         </div>
         <div v-if="!latestUsedSearchKey">
           <img :src="require('@/assets/images/default/empty_04.png')" alt="">
-          <span>{{'暂无素材~'}}</span>
+          <span>{{$i18n.t(`gather.no_material_result`)}}</span>
           <a href="/#/">
-            <button class="ui-button">如何拍摄三维场景</button>
+            <button class="ui-button">{{$i18n.t(`gather.how_to_shoot`)}}</button>
           </a>
         </div>
       </div>
@@ -525,13 +525,13 @@
 
     <div class="btns">
       <button v-if="currentMaterialType !== '3D'" class="ui-button upload-btn" @click="onClickUpload">
-        <span>上传素材</span>
-        <i class="iconfont icon-material_prompt tool-tip-for-editor"
+        <span>{{$i18n.t(`gather.upload_material`)}}</span>
+        <i :key="currentMaterialType" class="iconfont icon-material_prompt tool-tip-for-editor"
           v-tooltip="
-            currentMaterialType === 'image' ? '请上传10MB以内、jpg/png格式的图片' :
-            currentMaterialType === 'pano' ? '请上传2:1、120MB以内、jpg格式的图片' :
-            currentMaterialType === 'audio' ? '请上传20MB以内、mp3格式的音频' :
-            currentMaterialType === 'video' ? '请上传200MB以内、mp4格式的视频' : ''
+            currentMaterialType === 'image' ? $i18n.t(`gather.img_size`) :
+            currentMaterialType === 'pano' ? $i18n.t(`gather.pano_size`) :
+            currentMaterialType === 'audio' ? $i18n.t(`gather.audio_size`) :
+            currentMaterialType === 'video' ? $i18n.t(`gather.video_size`) : ''
           ">
         </i>
         <FileInput
@@ -546,9 +546,9 @@
       </button>
       <div v-else class="button-placeholder"></div>
       <div>
-        <button class="ui-button deepcancel" @click="$emit('cancle')">取消</button>
+        <button class="ui-button deepcancel" @click="$emit('cancle')">{{$i18n.t(`gather.cancel`)}}</button>
         <button class="ui-button submit" :class="{disable: !select.length}" @click="onClickComfirm">
-          确定
+          {{$i18n.t(`gather.comfirm`)}}
         </button>
       </div>
     </div>
@@ -682,16 +682,16 @@ export default {
       let ret = ''
       switch (this.currentMaterialType) {
         case 'pano':
-          ret = '格式错误,请上传2:1、120MB以内、jpg格式的全景图片'
+          ret = this.$i18n.t(`gather.pano_fail`)
           break;
         case 'image':
-          ret = '格式错误,请上传10MB以内、jpg/png格式的图片'
+          ret = this.$i18n.t(`gather.img_fail`)
           break;
         case 'audio':
-          ret = '格式错误,请上传20MB以内、mp3格式的音频'
+          ret = this.$i18n.t(`gather.audio_fail`)
           break;
         case 'video':
-          ret = '格式错误,请上传200MB以内、mp4格式的视频'
+          ret = this.$i18n.t(`gather.video_fail`)
           break;
         default:
           break;
@@ -702,16 +702,16 @@ export default {
       let ret = ''
       switch (this.currentMaterialType) {
         case 'pano':
-          ret = '过大,请上传2:1、120MB以内、jpg格式的全景图片'
+          ret = this.$i18n.t(`gather.pano_limit`)
           break;
         case 'image':
-          ret = '过大,请上传10MB以内、jpg/png格式的图片'
+          ret = this.$i18n.t(`gather.img_limit`)
           break;
         case 'audio':
-          ret = '过大,请上传20MB以内、mp3格式的音频'
+          ret = this.$i18n.t(`gather.audio_limit`)
           break;
         case 'video':
-          ret = '过大,请上传200MB以内、mp4格式的视频'
+          ret = this.$i18n.t(`gather.video_limit`)
           break;
         default:
           break;
@@ -1113,7 +1113,7 @@ export default {
           console.log('格式不对!');
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”格式错误,请上传2:1、120MB以内、jpg格式的全景图片`,
+              message: `“${eachFile.name}”${this.$i18n.t(`gather.pano_fail`)}`,
               type: "warning",
             });
           }, i * 100);
@@ -1123,7 +1123,7 @@ export default {
         if (eachFile.name.substring(0, eachFile.name.lastIndexOf(".")).length > 50) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”名称过长,请上传标题在50字以内的全景图片`,
+              message: `“${eachFile.name}”${this.$i18n.t(`gather.too_long_word`)}`,
               type: "warning",
             });
           }, i * 100);
@@ -1138,7 +1138,7 @@ export default {
           console.error('获取图像宽高失败:', e)
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”格式错误,请上传2:1、120MB以内、jpg格式的全景图片`,
+              message: `“${eachFile.name}”${this.$i18n.t(`gather.pano_fail`)}`,
               type: "warning",
             });
           }, i * 100);
@@ -1147,7 +1147,7 @@ export default {
         if (WHRate !== 2) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”格式错误,请上传2:1、120MB以内、jpg格式的全景图片`,
+              message: `“${eachFile.name}”${this.$i18n.t(`gather.pano_fail`)}`,
               type: "warning",
             });
           }, i * 100);
@@ -1159,7 +1159,7 @@ export default {
           ifKnowProgress: true,
           progress: 0,
           status: 'LOADING',
-          statusText: "正在上传素材",
+          statusText: this.$i18n.t(`gather.uploading_material`),
           uid: `u_${this.$randomWord(true, 8, 8)}`,
           abortHandler: null,
           backendId: '',
@@ -1174,7 +1174,7 @@ export default {
             uid: itemInUploadList.uid,
           },
           (response) => { // 上传成功
-            itemInUploadList.statusText = '正在切图处理'
+            itemInUploadList.statusText = this.$i18n.t(`gather.cutting`)
             itemInUploadList.ifKnowProgress = false
             itemInUploadList.backendId = response.data.id
           },
@@ -1188,7 +1188,7 @@ export default {
             } else {
               console.log('失败!');
               itemInUploadList.status = 'FAIL'
-              itemInUploadList.statusText = '素材上传失败'
+              itemInUploadList.statusText = this.$i18n.t(`gather.material_upload_fail`)
             }
           },
           (progress) => {
@@ -1210,7 +1210,7 @@ export default {
         ) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”格式错误,请上传10MB以内、jpg/png格式的图片`,
+              message: `“${eachFile.name}”${this.$i18n.t(`gather.img_fail`)}`,
               type: "warning",
             });
           }, i * 100);
@@ -1220,7 +1220,7 @@ export default {
         if (eachFile.name.substring(0, eachFile.name.lastIndexOf(".")).length > 50) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”名称过长,请上传标题在50字以内的图片`,
+              message: `“${eachFile.name}”${this.$i18n.t(`gather.too_long_word`)}`,
               type: "warning",
             });
           }, i * 100);
@@ -1232,7 +1232,7 @@ export default {
           ifKnowProgress: true,
           progress: 0,
           status: 'LOADING',
-          statusText: "正在上传素材",
+          statusText: this.$i18n.t(`gather.uploading_material`),
           uid: `u_${this.$randomWord(true, 8, 8)}`,
           abortHandler: null,
           successInfo: null,
@@ -1267,7 +1267,7 @@ export default {
             } else {
               console.log('失败!');
               itemInUploadList.status = 'FAIL'
-              itemInUploadList.statusText = '素材上传失败'
+              itemInUploadList.statusText = this.$i18n.t(`gather.material_upload_fail`)
             }
           },
           (progress) => {
@@ -1284,7 +1284,7 @@ export default {
         if (eachFile.name.toLowerCase().indexOf("mp3") <= -1) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”格式错误,请上传20MB以内、mp3格式的音频`,
+              message: `“${eachFile.name}”${this.$i18n.t(`gather.audio_fail`)}`,
               type: "warning",
             });
           }, i * 100);
@@ -1294,7 +1294,7 @@ export default {
         if (eachFile.name.substring(0, eachFile.name.lastIndexOf(".")).length > 50) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”名称过长,请上传标题在50字以内的音频`,
+              message: `“${eachFile.name}”${this.$i18n.t(`gather.too_long_word_audio`)}`,
               type: "warning",
             });
           }, i * 100);
@@ -1306,7 +1306,7 @@ export default {
           ifKnowProgress: true,
           progress: 0,
           status: 'LOADING',
-          statusText: "正在上传素材",
+          statusText: this.$i18n.t(`gather.uploading_material`),
           uid: `u_${this.$randomWord(true, 8, 8)}`,
           abortHandler: null,
         };
@@ -1341,7 +1341,7 @@ export default {
             } else {
               console.log('上传失败');
               itemInUploadList.status = 'FAIL'
-              itemInUploadList.statusText = '素材上传失败'
+              itemInUploadList.statusText = this.$i18n.t(`gather.material_upload_fail`)
             }
           },
           (progress) => {
@@ -1358,7 +1358,7 @@ export default {
         if (eachFile.name.toLowerCase().indexOf("mp4") <= -1) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”格式错误,请上传200MB以内、mp4格式的视频`,
+              message: `“${eachFile.name}”${this.$i18n.t(`gather.video_fail`)}`,
               type: "warning",
             });
           }, i * 100);
@@ -1368,7 +1368,7 @@ export default {
         if (eachFile.name.substring(0, eachFile.name.lastIndexOf(".")).length > 50) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”名称过长,请上传标题在50字以内的视频`,
+              message: `“${eachFile.name}”${this.$i18n.t(`gather.too_long_word_video`)}`,
               type: "warning",
             });
           }, i * 100);
@@ -1380,7 +1380,7 @@ export default {
           ifKnowProgress: true,
           progress: 0,
           status: 'LOADING',
-          statusText: "正在上传素材",
+          statusText: this.$i18n.t(`gather.uploading_material`),
           uid: `u_${this.$randomWord(true, 8, 8)}`,
           abortHandler: null,
         };
@@ -1413,7 +1413,7 @@ export default {
               this.uploadStatusListVideo.splice(index, 1)
             } else {
               itemInUploadList.status = 'FAIL'
-              itemInUploadList.statusText = '素材上传失败'
+              itemInUploadList.statusText = this.$i18n.t(`gather.material_upload_fail`)
             }
           },
           (progress) => {
@@ -1441,7 +1441,7 @@ export default {
                 if (index >= 0) {
                   const targetItem = this.uploadStatusListPano[index]
                   targetItem.status = 'FAIL'
-                  targetItem.statusText = '素材切图失败'
+                  targetItem.statusText = this.$i18n.t(`gather.material_cutting_fail`)
                   targetItem.ifKnowProgress = true
                 }
               } else if (eachRes.status === 3) {
@@ -1523,7 +1523,7 @@ export default {
       checkUserSize({}, (data) => {
         //判断已用是否大于3G
         if ((data.data / 1024 / 1024) > 3) {
-          this.$alert({ content: "空间已满" });
+          this.$alert({ content: this.$i18n.t(`tips_code.FAILURE_3024`) });
         } else {
           this.$refs['file-input'].click()
         }
@@ -1765,10 +1765,10 @@ export default {
     }
   }
   &:nth-of-type(2) {
-    width: calc(116px - 50px);
+    width: calc(146px - 50px);
   }
   &:nth-of-type(3) {
-    width: calc(316px - 116px);
+    width: calc(316px - 146px);
     padding-right: 30px;
   }
   &:nth-of-type(4) {
@@ -1805,10 +1805,10 @@ export default {
     }
   }
   &:nth-of-type(2) {
-    width: calc(116px - 50px);
+    width: calc(146px - 50px);
   }
   &:nth-of-type(3) {
-    width: calc(416px - 116px);
+    width: calc(416px - 146px);
     padding-right: 30px;
   }
   &:nth-of-type(4) {
@@ -1842,10 +1842,10 @@ export default {
     }
   }
   &:nth-of-type(2) {
-    width: calc(116px - 50px);
+    width: calc(146px - 50px);
   }
   &:nth-of-type(3) {
-    width: calc(416px - 116px);
+    width: calc(416px - 146px);
     padding-right: 30px;
   }
   &:nth-of-type(4) {
@@ -1879,10 +1879,10 @@ export default {
     }
   }
   &:nth-of-type(2) {
-    width: calc(116px - 50px);
+    width: calc(146px - 50px);
   }
   &:nth-of-type(3) {
-    width: calc(416px - 116px);
+    width: calc(416px - 146px);
     padding-right: 30px;
   }
   &:nth-of-type(4) {
@@ -1916,10 +1916,10 @@ export default {
     }
   }
   &:nth-of-type(2) {
-    width: calc(116px - 50px);
+    width: calc(146px - 50px);
   }
   &:nth-of-type(3) {
-    width: calc(416px - 116px);
+    width: calc(416px - 146px);
     padding-right: 30px;
   }
   &:nth-of-type(4) {

+ 218 - 201
packages/qjkankan-editor/src/components/materialSelectorForManageCenter.vue

@@ -1,91 +1,78 @@
 <template>
   <div class="table-select">
-    <span class="title">{{title}}</span>
+    <span class="title">{{ title }}</span>
     <div class="close-btn"><i class="iconfont icon-pop-ups_shut-down" @click="$emit('cancle')"></i></div>
 
     <div class="material-tab">
-      <a v-if="selectableType.includes('image')" class="material-tab-item" @click.prevent="currentMaterialType = 'image'">
-        <span 
-        :class="{active: currentMaterialType === 'image'}"
-        class="text"
-        >
-          {{image}}
+      <a v-if="selectableType.includes('image')" class="material-tab-item"
+        @click.prevent="currentMaterialType = 'image'">
+        <span :class="{ active: currentMaterialType === 'image' }" class="text">
+          {{ image }}
         </span>
         <div v-if="currentMaterialType === 'image'" class="bottom-line"></div>
       </a>
       <a v-if="selectableType.includes('pano')" class="material-tab-item" @click.prevent="currentMaterialType = 'pano'">
-        <span 
-        :class="{active: currentMaterialType === 'pano'}"
-        class="text"
-        >
-          {{panorama}}
+        <span :class="{ active: currentMaterialType === 'pano' }" class="text">
+          {{ panorama }}
         </span>
         <div v-if="currentMaterialType === 'pano'" class="bottom-line"></div>
       </a>
-      <a v-if="selectableType.includes('audio')" class="material-tab-item" @click.prevent="currentMaterialType = 'audio'">
-        <span 
-        :class="{active: currentMaterialType === 'audio'}"
-        class="text"
-        >
-          {{audio}}
+      <a v-if="selectableType.includes('audio')" class="material-tab-item"
+        @click.prevent="currentMaterialType = 'audio'">
+        <span :class="{ active: currentMaterialType === 'audio' }" class="text">
+          {{ audio }}
         </span>
         <div v-if="currentMaterialType === 'audio'" class="bottom-line"></div>
       </a>
-      <a v-if="selectableType.includes('video')" class="material-tab-item" @click.prevent="currentMaterialType = 'video'">
-        <span 
-        :class="{active: currentMaterialType === 'video'}"
-        class="text"
-        >
-          {{video}}
+      <a v-if="selectableType.includes('video')" class="material-tab-item"
+        @click.prevent="currentMaterialType = 'video'">
+        <span :class="{ active: currentMaterialType === 'video' }" class="text">
+          {{ video }}
         </span>
         <div v-if="currentMaterialType === 'video'" class="bottom-line"></div>
       </a>
       <a v-if="selectableType.includes('3D')" class="material-tab-item" @click.prevent="currentMaterialType = '3D'">
-        <span 
-        :class="{active: currentMaterialType === '3D'}"
-        class="text"
-        >
-          {{scene}}
+        <span :class="{ active: currentMaterialType === '3D' }" class="text">
+          {{ scene }}
         </span>
         <div v-if="currentMaterialType === '3D'" class="bottom-line"></div>
       </a>
     </div>
-    
+
     <div class="filter">
-      <input type="text" :placeholder="keywords" v-model="searchKey"/>
-      <i v-if="!searchKey" class="iconfont icon-editor_search search-icon"/>
-      <i v-if="searchKey" @click="searchKey=''" class="iconfont icontoast_red clear-icon"></i>
+      <input type="text" :placeholder="keywords" v-model="searchKey" />
+      <i v-if="!searchKey" class="iconfont icon-editor_search search-icon" />
+      <i v-if="searchKey" @click="searchKey = ''" class="iconfont icontoast_red clear-icon"></i>
     </div>
 
     <div class="table table-pano" v-show="currentMaterialType === 'pano'">
       <div class="table-head-row">
         <span class="table-head">1</span>
-        <span class="table-head" v-for="(item,i) in tableHeadersForPano" :key="i">{{item.name}}</span>
+        <span class="table-head" v-for="(item, i) in tableHeadersForPano" :key="i">
+          {{ item.name && $i18n.t(`zh_key.${item.name}`) }}</span>
       </div>
-      <div
-        v-if="panoListLocalLength !== 0 || hasMorePanoData"
-        class="table-body"
+      <div v-if="panoListLocalLength !== 0 || hasMorePanoData" class="table-body"
         v-infinite-scroll="requestMorePanoData"
-        :infinite-scroll-disabled="!hasMorePanoData || isRequestingMorePanoData"
-      >
+        :infinite-scroll-disabled="!hasMorePanoData || isRequestingMorePanoData">
         <!-- vuex中的上传中数据 -->
         <div class="table-body-row" v-for="(item, i) in uploadStatusListPano" :key="item.uid" @click="onClickRow">
           <!-- 如果已经上传成功 -->
           <template v-if="item.status === 'SUCCESS'">
             <span class="table-data">
-              <RadioOrCheckbox
-                class="checkbox"
-                :isLightTheme="true"
-                :isMultiSelection="isMultiSelection"
+              <RadioOrCheckbox class="checkbox" :isLightTheme="true" :isMultiSelection="isMultiSelection"
                 :isCheckedInitial="select.some(i => i[primaryKey] === item.successInfo[primaryKey])"
-                @change="v => selectItem(item.successInfo, v)"
-              />
+                @change="v => selectItem(item.successInfo, v)" />
             </span>
             <span class="table-data" v-for="(tableItemStructure, idx) in tableHeadersForPano" :key="idx">
-              <div v-if="tableItemStructure.type=='image'" class="list-img">
-                <img :src="item.successInfo[tableItemStructure.key] + (Number(item.fileSize)>512 ? `?x-oss-process=image/resize,p_20&${Math.random()}` : ``)" alt="">
+              <div v-if="tableItemStructure.type == 'image'" class="list-img">
+                <img
+                  :src="item.successInfo[tableItemStructure.key] + (Number(item.fileSize) > 512 ? $imgsuffix : ``)"
+                  alt="">
               </div>
-              <span  v-else class="ellipsis" v-title="tableItemStructure.key === 'name' ? item.successInfo[tableItemStructure.key] : ''">{{ item.successInfo[tableItemStructure.key] }}</span>
+              <span v-else class="ellipsis"
+                v-title="tableItemStructure.key === 'name' ? item.successInfo[tableItemStructure.key] : ''">{{
+                    item.successInfo[tableItemStructure.key]
+                }}</span>
             </span>
           </template>
           <!-- 如果还在上传或切图处理中 -->
@@ -97,13 +84,16 @@
               </div>
             </span>
             <span class="table-data" v-for="(tableItemStructure, idx) in tableHeadersForPano" :key="idx">
-              <div v-if="tableItemStructure.type=='image'" class="list-img">
+              <div v-if="tableItemStructure.type == 'image'" class="list-img">
                 <img src="@/assets/images/icons/upload-file-type-icon-image@2x.png" alt="">
               </div>
-              <span  v-if="tableItemStructure.key !== 'name' && tableItemStructure.key !== 'fileSize'"></span>
-              <span  v-if="tableItemStructure.key === 'fileSize' && item.ifKnowProgress">上传素材 {{Math.round(item.progress * 100)}}%</span>
-              <span  v-if="tableItemStructure.key === 'fileSize' && !item.ifKnowProgress">{{item.statusText}}</span>
-              <span  v-if="tableItemStructure.key === 'name'" class="ellipsis" v-title="tableItemStructure.key === 'name' ? item.title : ''">{{ item.title }}</span>
+              <span v-if="tableItemStructure.key !== 'name' && tableItemStructure.key !== 'fileSize'"></span>
+              <span v-if="tableItemStructure.key === 'fileSize' && item.ifKnowProgress">{{$i18n.t(`gather.upload_material`)}} {{ Math.round(item.progress
+                  * 100)
+              }}%</span>
+              <span v-if="tableItemStructure.key === 'fileSize' && !item.ifKnowProgress">{{ item.statusText }}</span>
+              <span v-if="tableItemStructure.key === 'name'" class="ellipsis"
+                v-title="tableItemStructure.key === 'name' ? item.title : ''">{{ item.title }}</span>
             </span>
           </template>
           <!-- 如果上传失败了 -->
@@ -115,31 +105,30 @@
               </div>
             </span>
             <span class="table-data" v-for="(tableItemStructure, idx) in tableHeadersForPano" :key="idx">
-              <div v-if="tableItemStructure.type=='image'" class="list-img">
+              <div v-if="tableItemStructure.type == 'image'" class="list-img">
                 <img src="@/assets/images/icons/upload-file-type-icon-image@2x.png" alt="">
               </div>
-              <span  v-if="tableItemStructure.key !== 'name' && tableItemStructure.key !== 'fileSize'"></span>
-              <span  v-if="tableItemStructure.key === 'fileSize'">上传失败</span>
-              <span  v-if="tableItemStructure.key === 'name'" class="ellipsis" v-title="tableItemStructure.key === 'name' ? item.title : ''">{{ item.title }}</span>
+              <span v-if="tableItemStructure.key !== 'name' && tableItemStructure.key !== 'fileSize'"></span>
+              <span v-if="tableItemStructure.key === 'fileSize'">{{ $i18n.t(`tips_code.FAILURE_3025`) }}</span>
+              <span v-if="tableItemStructure.key === 'name'" class="ellipsis"
+                v-title="tableItemStructure.key === 'name' ? item.title : ''">{{ item.title }}</span>
             </span>
           </template>
         </div>
         <!-- 本组件内的列表数据 -->
-        <div class="table-body-row" v-for="(item,i) in panoList" :key="i" @click="onClickRow">
+        <div class="table-body-row" v-for="(item, i) in panoList" :key="i" @click="onClickRow">
           <span class="table-data">
-            <RadioOrCheckbox
-              class="checkbox"
-              :isLightTheme="true"
-              :isMultiSelection="isMultiSelection"
+            <RadioOrCheckbox class="checkbox" :isLightTheme="true" :isMultiSelection="isMultiSelection"
               :isCheckedInitial="select.some(i => i[primaryKey] === item[primaryKey])"
-              @change="v => selectItem(item, v)"
-            />
+              @change="v => selectItem(item, v)" />
           </span>
-          <span class="table-data" v-for="(sub,idx) in tableHeadersForPano" :key="idx">
-            <div v-if="sub.type=='image'" class="list-img">
-              <img :src="item[sub.key] + (Number(item.fileSize)>512 ? `?x-oss-process=image/resize,p_20&${Math.random()}` : ``)" alt="">
+          <span class="table-data" v-for="(sub, idx) in tableHeadersForPano" :key="idx">
+            <div v-if="sub.type == 'image'" class="list-img">
+              <img
+                :src="item[sub.key] + (Number(item.fileSize) > 512 ? $imgsuffix : ``)"
+                alt="">
             </div>
-            <span class="ellipsis" v-else v-title="sub.key === 'name' ? item[sub.key] : ''">{{item[sub.key]}}</span>
+            <span class="ellipsis" v-else v-title="sub.key === 'name' ? item[sub.key] : ''">{{ item[sub.key] }}</span>
           </span>
         </div>
       </div>
@@ -147,11 +136,11 @@
       <div v-else class="no-data">
         <div v-if="latestUsedSearchKey">
           <img :src="require('@/assets/images/default/empty_04_search.png')" alt="">
-          <span>{{no_serch_result}}</span>
+          <span>{{ no_serch_result }}</span>
         </div>
         <div v-if="!latestUsedSearchKey">
           <img :src="require('@/assets/images/default/empty_04.png')" alt="">
-          <span>{{no_material_result}}</span>
+          <span>{{ no_material_result }}</span>
         </div>
       </div>
     </div>
@@ -159,29 +148,24 @@
     <div class="table table-3D" v-show="currentMaterialType === '3D'">
       <div class="table-head-row">
         <span class="table-head">1</span>
-        <span class="table-head" v-for="(item,i) in tableHeadersFor3D" :key="i">{{item.name}}</span>
+        <span class="table-head" v-for="(item, i) in tableHeadersFor3D" :key="i">
+          {{ item.name && $i18n.t(`zh_key.${item.name}`) }}</span>
       </div>
-      <div
-        v-if="scene3DList.length !== 0 || hasMore3DData"
-        class="table-body"
-        v-infinite-scroll="requestMore3DData"
-        :infinite-scroll-disabled="!hasMore3DData || isRequestingMore3DData"
-      >
-        <div class="table-body-row" v-for="(item,i) in scene3DList" :key="i">
+      <div v-if="scene3DList.length !== 0 || hasMore3DData" class="table-body" v-infinite-scroll="requestMore3DData"
+        :infinite-scroll-disabled="!hasMore3DData || isRequestingMore3DData">
+        <div class="table-body-row" v-for="(item, i) in scene3DList" :key="i">
           <span class="table-data">
-            <RadioOrCheckbox
-              class="checkbox"
-              :isLightTheme="true"
-              :isMultiSelection="isMultiSelection"
+            <RadioOrCheckbox class="checkbox" :isLightTheme="true" :isMultiSelection="isMultiSelection"
               :isCheckedInitial="select.some(i => i[primaryKey] === item[primaryKey])"
-              @change="v => selectItem(item, v)"
-            />
+              @change="v => selectItem(item, v)" />
           </span>
-          <span class="table-data" v-for="(sub,idx) in tableHeadersFor3D" :key="idx">
-            <div v-if="sub.type=='image'" class="list-img">
-              <img :src="item[sub.key] + (Number(item.fileSize)>512 ? `?x-oss-process=image/resize,p_20&${Math.random()}` : ``)" alt="">
+          <span class="table-data" v-for="(sub, idx) in tableHeadersFor3D" :key="idx">
+            <div v-if="sub.type == 'image'" class="list-img">
+              <img
+                :src="item[sub.key] + (Number(item.fileSize) > 512 ? $imgsuffix : ``)"
+                alt="">
             </div>
-            <span class="ellipsis" v-else v-title="sub.key === 'name' ? item[sub.key] : ''">{{item[sub.key]}}</span>
+            <span class="ellipsis" v-else v-title="sub.key === 'name' ? item[sub.key] : ''">{{ item[sub.key] }}</span>
           </span>
         </div>
       </div>
@@ -189,13 +173,13 @@
       <div v-else class="no-data">
         <div v-if="latestUsedSearchKey">
           <img :src="require('@/assets/images/default/empty_04_search.png')" alt="">
-          <span>{{no_serch_result}}</span>
+          <span>{{ no_serch_result }}</span>
         </div>
         <div v-if="!latestUsedSearchKey">
           <img :src="require('@/assets/images/default/empty_04.png')" alt="">
-          <span>{{no_material_result}}</span>
+          <span>{{ no_material_result }}</span>
           <a href="/#/">
-            <button class="ui-button">{{how_to_shoot}}</button>
+            <button class="ui-button">{{ how_to_shoot }}</button>
           </a>
         </div>
       </div>
@@ -203,30 +187,23 @@
 
     <div class="btns">
       <button v-if="currentMaterialType !== '3D'" class="ui-button upload-btn" @click="onClickUpload">
-        <span>{{upload_material}}</span>
-        <i class="iconfont icon-material_prompt tool-tip-for-editor"
-          v-tooltip="
-            currentMaterialType === 'image' ? img_size :
+        <span>{{ upload_material }}</span>
+        <i :key="currentMaterialType" class="iconfont icon-material_prompt tool-tip-for-editor" v-tooltip="
+          currentMaterialType === 'image' ? img_size :
             currentMaterialType === 'pano' ? pano_size :
-            currentMaterialType === 'audio' ? audio_size :
-            currentMaterialType === 'video' ? video_size : ''
-          ">
+              currentMaterialType === 'audio' ? audio_size :
+                currentMaterialType === 'video' ? video_size : ''
+        ">
         </i>
-        <FileInput
-          ref="file-input"
-          :failString="fileInputFailString"
-          :limitFailStr="fileInputLimitFailStr"
-          :acceptType="fileInputAcceptType"
-          :mediaType="fileInputMediaType"
-          :limit="fileInputLimit"
-          @file-change="onFileInputChange"
-        ></FileInput>
+        <FileInput ref="file-input" :failString="fileInputFailString" :limitFailStr="fileInputLimitFailStr"
+          :acceptType="fileInputAcceptType" :mediaType="fileInputMediaType" :limit="fileInputLimit"
+          @file-change="onFileInputChange"></FileInput>
       </button>
       <div v-else class="button-placeholder"></div>
       <div>
-        <button class="ui-button cancel" @click="$emit('cancle')">{{cancel}}</button>
-        <button class="ui-button submit" :class="{disable: !select.length}" @click="onClickComfirm">
-          {{comfirm}}
+        <button class="ui-button cancel" @click="$emit('cancle')">{{ cancel }}</button>
+        <button class="ui-button submit" :class="{ disable: !select.length }" @click="onClickComfirm">
+          {{ comfirm }}
         </button>
       </div>
     </div>
@@ -249,20 +226,20 @@ import FileInput from "@/components/shared/uploads/UploadMultiple.vue";
 import { mapState } from "vuex";
 // import AudioIconCanPlay from "@/components/audio/indexForEditor.vue";
 import RadioOrCheckbox from "@/components/shared/RadioOrCheckbox.vue";
-import {i18n} from "@/lang"
+import { i18n } from "@/lang"
 
 export default {
-  props:{
-    title:{
-      default:'',
-      type:String
+  props: {
+    title: {
+      default: '',
+      type: String
     },
     primaryKey: {
-      default:'id'
+      default: 'id'
     },
     selectableType: {
       type: Array,
-      default: function() {
+      default: function () {
         return [
           'image',
           'pano',
@@ -285,12 +262,12 @@ export default {
       default: '',
     },
   },
-  components:{
+  components: {
     FileInput,
     // AudioIconCanPlay,
     RadioOrCheckbox,
   },
-  watch:{
+  watch: {
     searchKey: {
       handler: function () {
         this.refreshMaterialList(this.currentMaterialType)
@@ -329,7 +306,7 @@ export default {
       immediate: true,
     },
   },
-  computed:{
+  computed: {
     ...mapState({
       uploadStatusListAudio: 'uploadStatusListAudio',
       uploadStatusListImage: 'uploadStatusListImage',
@@ -365,16 +342,16 @@ export default {
       let ret = ''
       switch (this.currentMaterialType) {
         case 'pano':
-          ret = '格式错误,请上传2:1、120MB以内、jpg格式的全景图片'
+          ret = this.$i18n.t(`gather.pano_fail`)
           break;
         case 'image':
-          ret = '格式错误,请上传10MB以内、jpg/png格式的图片'
+          ret = this.$i18n.t(`gather.img_fail`)
           break;
         case 'audio':
-          ret = '格式错误,请上传20MB以内、mp3格式的音频'
+          ret = this.$i18n.t(`gather.audio_fail`)
           break;
         case 'video':
-          ret = '格式错误,请上传200MB以内、mp4格式的视频'
+          ret = this.$i18n.t(`gather.video_fail`)
           break;
         default:
           break;
@@ -385,16 +362,16 @@ export default {
       let ret = ''
       switch (this.currentMaterialType) {
         case 'pano':
-          ret = '过大,请上传2:1、120MB以内、jpg格式的全景图片'
+          ret = this.$i18n.t(`gather.pano_limit`)
           break;
         case 'image':
-          ret = '过大,请上传10MB以内、jpg/png格式的图片'
+          ret = this.$i18n.t(`gather.img_limit`)
           break;
         case 'audio':
-          ret = '过大,请上传20MB以内、mp3格式的音频'
+          ret = this.$i18n.t(`gather.audio_limit`)
           break;
         case 'video':
-          ret = '过大,请上传200MB以内、mp4格式的视频'
+          ret = this.$i18n.t(`gather.video_limit`)
           break;
         default:
           break;
@@ -499,7 +476,7 @@ export default {
       })
     },
   },
-  data () {
+  data() {
     return {
       no_serch_result: i18n.t("gather.no_serch_result"),
       no_material_result: i18n.t("gather.no_material_result"),
@@ -517,19 +494,19 @@ export default {
       video_size: i18n.t("gather.video_size"),
       cancel: i18n.t("gather.cancel"),
       comfirm: i18n.t("gather.comfirm"),
-      
+
       imageList: [],
       panoList: [],
       audioList: [],
       videoList: [],
       scene3DList: [],
-      
+
       select: [],
-      searchKey:'', // 搜索关键词
+      searchKey: '', // 搜索关键词
       latestUsedSearchKey: '',
 
       currentMaterialType: this.initialMaterialType,
-      
+
       isRequestingMoreImageData: false,
       isRequestingMorePanoData: false,
       isRequestingMoreAudioData: false,
@@ -721,7 +698,7 @@ export default {
         }
       )
     },
-    refreshMaterialList: debounce(function(type) {
+    refreshMaterialList: debounce(function (type) {
       if (type === 'image') {
         this.isRequestingMoreImageData = false
         this.hasMoreImageData = true
@@ -791,7 +768,7 @@ export default {
           console.log('格式不对!');
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”格式错误,请上传2:1、120MB以内、jpg格式的全景图片`,
+              message: `“${eachFile.name}”${this.$i18n.t(`gather.pano_fail`)}`,
               type: "warning",
             });
           }, i * 100);
@@ -801,7 +778,7 @@ export default {
         if (eachFile.name.substring(0, eachFile.name.lastIndexOf(".")).length > 50) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”名称过长,请上传标题在50字以内的全景图片`,
+              message: `“${eachFile.name}”${this.$i18n.t(`gather.too_long_word`)}`,
               type: "warning",
             });
           }, i * 100);
@@ -810,13 +787,13 @@ export default {
 
         let WHRate = null
         try {
-          const {width, height} = await getImgWH(eachFile)
+          const { width, height } = await getImgWH(eachFile)
           WHRate = width / height
-        } catch(e) {
+        } catch (e) {
           console.error('获取图像宽高失败:', e)
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”格式错误,请上传2:1、120MB以内、jpg格式的全景图片`,
+              message: `“${eachFile.name}”${this.$i18n.t(`gather.pano_fail`)}`,
               type: "warning",
             });
           }, i * 100);
@@ -825,7 +802,7 @@ export default {
         if (WHRate !== 2) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”格式错误,请上传2:1、120MB以内、jpg格式的全景图片`,
+              message: `“${eachFile.name}”${this.$i18n.t(`gather.pano_fail`)}`,
               type: "warning",
             });
           }, i * 100);
@@ -837,7 +814,7 @@ export default {
           ifKnowProgress: true,
           progress: 0,
           status: 'LOADING',
-          statusText: "正在上传素材",
+          statusText: this.$i18n.t(`gather.uploading_material`),
           uid: `u_${this.$randomWord(true, 8, 8)}`,
           abortHandler: null,
           backendId: '',
@@ -852,7 +829,7 @@ export default {
             uid: itemInUploadList.uid,
           },
           (response) => { // 上传成功
-            itemInUploadList.statusText = '正在切图处理'
+            itemInUploadList.statusText = this.$i18n.t(`gather.cutting`)
             itemInUploadList.ifKnowProgress = false
             itemInUploadList.backendId = response.data.id
           },
@@ -866,7 +843,7 @@ export default {
             } else {
               console.log('失败!');
               itemInUploadList.status = 'FAIL'
-              itemInUploadList.statusText = '素材上传失败'
+              itemInUploadList.statusText = this.$i18n.t(`gather.material_upload_fail`)
             }
           },
           (progress) => {
@@ -880,7 +857,7 @@ export default {
     },
     onImageFileInputChange(e) {
       console.log('tableHeadersForImage: ', this.tableHeadersForImage);
-      
+
       e.files.forEach((eachFile, i) => {
         if (
           eachFile.type.indexOf("jpeg") <= -1 &&
@@ -888,7 +865,7 @@ export default {
         ) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”格式错误,请上传10MB以内、jpg/png格式的图片`,
+              message: `“${eachFile.name}”${this.$i18n.t(`gather.img_fail`)}`,
               type: "warning",
             });
           }, i * 100);
@@ -898,7 +875,7 @@ export default {
         if (eachFile.name.substring(0, eachFile.name.lastIndexOf(".")).length > 50) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”名称过长,请上传标题在50字以内的图片`,
+              message: `“${eachFile.name}”${this.$i18n.t(`gather.too_long_word`)}`,
               type: "warning",
             });
           }, i * 100);
@@ -910,12 +887,12 @@ export default {
           ifKnowProgress: true,
           progress: 0,
           status: 'LOADING',
-          statusText: "正在上传素材",
+          statusText: this.$i18n.t(`gather.uploading_material`),
           uid: `u_${this.$randomWord(true, 8, 8)}`,
           abortHandler: null,
           successInfo: null,
         };
-        
+
         itemInUploadList.abortHandler = uploadMaterial(
           {
             file: eachFile
@@ -945,7 +922,7 @@ export default {
             } else {
               console.log('失败!');
               itemInUploadList.status = 'FAIL'
-              itemInUploadList.statusText = '素材上传失败'
+              itemInUploadList.statusText = this.$i18n.t(`gather.material_upload_fail`)
             }
           },
           (progress) => {
@@ -962,7 +939,7 @@ export default {
         if (eachFile.name.toLowerCase().indexOf("mp3") <= -1) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”格式错误,请上传20MB以内、mp3格式的音频`,
+              message: `“${eachFile.name}”${this.$i18n.t(`gather.audio_fail`)}`,
               type: "warning",
             });
           }, i * 100);
@@ -972,7 +949,7 @@ export default {
         if (eachFile.name.substring(0, eachFile.name.lastIndexOf(".")).length > 50) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”名称过长,请上传标题在50字以内的音频`,
+              message: `“${eachFile.name}”${this.$i18n.t(`gather.too_long_word_audio`)}`,
               type: "warning",
             });
           }, i * 100);
@@ -984,11 +961,11 @@ export default {
           ifKnowProgress: true,
           progress: 0,
           status: 'LOADING',
-          statusText: "正在上传素材",
+          statusText: this.$i18n.t(`gather.uploading_material`),
           uid: `u_${this.$randomWord(true, 8, 8)}`,
           abortHandler: null,
         };
-        
+
         itemInUploadList.abortHandler = uploadMaterial(
           {
             file: eachFile
@@ -1019,7 +996,7 @@ export default {
             } else {
               console.log('上传失败');
               itemInUploadList.status = 'FAIL'
-              itemInUploadList.statusText = '素材上传失败'
+              itemInUploadList.statusText = this.$i18n.t(`gather.material_upload_fail`)
             }
           },
           (progress) => {
@@ -1036,7 +1013,7 @@ export default {
         if (eachFile.name.toLowerCase().indexOf("mp4") <= -1) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”格式错误,请上传200MB以内、mp4格式的视频`,
+              message: `“${eachFile.name}”${this.$i18n.t(`gather.video_fail`)}`,
               type: "warning",
             });
           }, i * 100);
@@ -1046,7 +1023,7 @@ export default {
         if (eachFile.name.substring(0, eachFile.name.lastIndexOf(".")).length > 50) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”名称过长,请上传标题在50字以内的视频`,
+              message: `“${eachFile.name}”${this.$i18n.t(`gather.too_long_word_video`)}`,
               type: "warning",
             });
           }, i * 100);
@@ -1058,11 +1035,11 @@ export default {
           ifKnowProgress: true,
           progress: 0,
           status: 'LOADING',
-          statusText: "正在上传素材",
+          statusText: this.$i18n.t(`gather.uploading_material`),
           uid: `u_${this.$randomWord(true, 8, 8)}`,
           abortHandler: null,
         };
-        
+
         itemInUploadList.abortHandler = uploadMaterial(
           {
             file: eachFile
@@ -1091,7 +1068,7 @@ export default {
               this.uploadStatusListVideo.splice(index, 1)
             } else {
               itemInUploadList.status = 'FAIL'
-              itemInUploadList.statusText = '素材上传失败'
+              itemInUploadList.statusText = this.$i18n.t(`gather.material_upload_fail`)
             }
           },
           (progress) => {
@@ -1119,7 +1096,7 @@ export default {
                 if (index >= 0) {
                   const targetItem = this.uploadStatusListPano[index]
                   targetItem.status = 'FAIL'
-                  targetItem.statusText = '素材切图失败'
+                  targetItem.statusText = this.$i18n.t(`gather.material_cutting_fail`)
                   targetItem.ifKnowProgress = true
                 }
               } else if (eachRes.status === 3) {
@@ -1146,13 +1123,13 @@ export default {
       checkUserSize({}, (data) => {
         //判断已用是否大于3G
         if ((data.data / 1024 / 1024) > 3) {
-          this.$alert({ content: "空间已满" });
+          this.$alert({ content: this.$i18n.t('tips_code.FAILURE_3024')});
         } else {
           this.$refs['file-input'].click()
         }
       })
     },
-    onClickComfirm: debounce(function() {
+    onClickComfirm: debounce(function () {
       this.$emit('submit', this.select)
     }, 250),
   },
@@ -1179,7 +1156,7 @@ export default {
 </script>
 
 <style lang="less" scoped>
-.ellipsis{
+.ellipsis {
   text-overflow: ellipsis;
   overflow: hidden;
   white-space: nowrap;
@@ -1219,20 +1196,24 @@ export default {
 
 .material-tab {
   margin-top: 35px;
-  > .material-tab-item {
+
+  >.material-tab-item {
     display: inline-block;
     margin-right: 20px;
     position: relative;
     cursor: pointer;
-    > .text {
+
+    >.text {
       font-size: 14px;
       font-family: MicrosoftYaHei;
       color: #969799;
+
       &.active {
         color: #323233;
       }
     }
-    > .bottom-line {
+
+    >.bottom-line {
       position: absolute;
       left: 50%;
       transform: translateX(-50%);
@@ -1253,7 +1234,8 @@ export default {
   border-radius: 2px;
   border: 1px solid #EBEDF0;
   position: relative;
-  > input {
+
+  >input {
     box-sizing: border-box;
     width: calc(100% - 42px);
     height: 100%;
@@ -1263,7 +1245,8 @@ export default {
     color: #323233;
     outline: none;
   }
-  > .search-icon {
+
+  >.search-icon {
     position: absolute;
     top: 50%;
     transform: translateY(-50%);
@@ -1271,7 +1254,8 @@ export default {
     color: #C8C9CC;
     font-size: 20px;
   }
-  > .clear-icon {
+
+  >.clear-icon {
     position: absolute;
     top: 50%;
     transform: translateY(-50%);
@@ -1292,11 +1276,13 @@ export default {
   background: #ffffff;
   width: 100%;
   height: @table-height;
-  > .table-head-row {
+
+  >.table-head-row {
     width: 100%;
     height: @table-head-row-height;
     background: #F5F7FA;
     color: #646566;
+
     .table-head {
       font-size: 16px;
       line-height: @table-head-row-height;
@@ -1304,28 +1290,34 @@ export default {
       display: inline-block;
     }
   }
-  > .table-body {
+
+  >.table-body {
     height: calc(@table-height - @table-head-row-height - @table-border-size - @table-border-size);
     overflow: auto;
     display: inline-block;
     width: 100%;
-    > .table-body-row {
+
+    >.table-body-row {
       height: 50px;
       border-bottom: 1px solid #EBEDF0;
       display: flex;
       align-items: center;
       cursor: pointer;
-      > .table-data {
-        font-size:14px;
-        line-height:50px;
+
+      >.table-data {
+        font-size: 14px;
+        line-height: 50px;
         height: 100%;
         color: #323233;
-        > .list-img {
+
+        >.list-img {
           position: relative;
           height: 100%;
           display: inline-block;
           width: 100%;
-          > img, .audio-player {
+
+          >img,
+          .audio-player {
             position: absolute;
             top: 50%;
             transform: translateY(-50%);
@@ -1337,27 +1329,32 @@ export default {
       }
     }
   }
-  > .no-data {
+
+  >.no-data {
     height: calc(@table-height - @table-head-row-height - @table-border-size - @table-border-size);
     width: 100%;
     position: relative;
-    > div {
+
+    >div {
       position: absolute;
       top: 50%;
       left: 50%;
       transform: translate(-50%, -50%);
       text-align: center;
-      > img {
+
+      >img {
         width: 116px;
       }
-      > span {
+
+      >span {
         margin-top: 20px;
         display: block;
         font-size: 14px;
         color: rgba(255, 255, 255, 0.6);
       }
-      > a {
-        > button {
+
+      >a {
+        >button {
           margin-top: 20px;
         }
       }
@@ -1371,18 +1368,22 @@ export default {
     width: 50px;
     color: transparent;
   }
+
   &:nth-of-type(2) {
-    width: calc(116px - 50px);
+    width: calc(146px - 50px);
   }
+
   &:nth-of-type(3) {
-    width: calc(316px - 116px);
+    width: calc(316px - 146px);
     padding-right: 30px;
   }
+
   &:nth-of-type(4) {
-    width: calc(416px - 316px);
+    width: calc(400px - 316px);
   }
+
   &:nth-of-type(5) {
-    width: calc(100% - 416px);
+    width: calc(100% - 400px);
   }
 }
 
@@ -1392,15 +1393,18 @@ export default {
     width: 50px;
     color: transparent;
   }
+
   &:nth-of-type(2) {
-    width: calc(116px - 50px);
+    width: calc(146px - 50px);
   }
+
   &:nth-of-type(3) {
-    width: calc(416px - 116px);
+    width: calc(400px - 146px);
     padding-right: 30px;
   }
+
   &:nth-of-type(4) {
-    width: calc(100% - 416px);
+    width: calc(100% - 400px);
   }
 }
 
@@ -1410,15 +1414,18 @@ export default {
     width: 50px;
     color: transparent;
   }
+
   &:nth-of-type(2) {
-    width: calc(116px - 50px);
+    width: calc(146px - 50px);
   }
+
   &:nth-of-type(3) {
-    width: calc(416px - 116px);
+    width: calc(400px - 146px);
     padding-right: 30px;
   }
+
   &:nth-of-type(4) {
-    width: calc(100% - 416px);
+    width: calc(100% - 400px);
   }
 }
 
@@ -1428,15 +1435,18 @@ export default {
     width: 50px;
     color: transparent;
   }
+
   &:nth-of-type(2) {
-    width: calc(116px - 50px);
+    width: calc(146px - 50px);
   }
+
   &:nth-of-type(3) {
-    width: calc(416px - 116px);
+    width: calc(400px - 146px);
     padding-right: 30px;
   }
+
   &:nth-of-type(4) {
-    width: calc(100% - 416px);
+    width: calc(100% - 400px);
   }
 }
 
@@ -1446,15 +1456,18 @@ export default {
     width: 50px;
     color: transparent;
   }
+
   &:nth-of-type(2) {
-    width: calc(116px - 50px);
+    width: calc(146px - 50px);
   }
+
   &:nth-of-type(3) {
-    width: calc(416px - 116px);
+    width: calc(400px - 146px);
     padding-right: 30px;
   }
+
   &:nth-of-type(4) {
-    width: calc(100% - 416px);
+    width: calc(100% - 400px);
   }
 }
 
@@ -1467,20 +1480,24 @@ export default {
   display: flex;
   justify-content: space-between;
   margin-top: 40px;
+
   .upload-btn {
     display: flex;
     align-items: center;
-    > span {
+
+    >span {
       display: inline-block;
       margin-right: 4px;
     }
+
     i.tool-tip-for-editor {
       font-size: 12px;
       transform: scale(0.923) translateY(1px);
       cursor: default;
     }
   }
-  > div {
+
+  >div {
     .cancel {
       margin-right: 16px;
     }

+ 18 - 18
packages/qjkankan-editor/src/components/materialSelectorFromWorkForEditor.vue

@@ -1,21 +1,21 @@
 <template>
   <div class="table-select">
-    <span class="title">选择素材</span>
+    <span class="title">{{$i18n.t(`gather.select_material`)}}</span>
     <div class="close-btn"><i class="iconfont icon-pop-ups_shut-down" @click="$emit('cancle')"></i></div>
 
     <div class="material-tab">
       <a class="material-tab-item" @click.prevent="currentMaterialType = 'pano'">
-        <span class="text">全景图</span>
+        <span class="text">{{$i18n.t(`gather.panorama`)}}</span>
         <div v-if="currentMaterialType === 'pano'" class="bottom-line"></div>
       </a>
       <a class="material-tab-item" @click.prevent="currentMaterialType = '3D'">
-        <span class="text">三维场景</span>
+        <span class="text">{{$i18n.t(`gather.scene`)}}</span>
         <div v-if="currentMaterialType === '3D'" class="bottom-line"></div>
       </a>
     </div>
     
     <div class="filter">
-      <input type="text" placeholder="输入关键词" v-model="searchKey"/>
+      <input type="text" :placeholder="$i18n.t(`gather.keywords`)" v-model="searchKey"/>
       <i v-if="!searchKey" class="iconfont icon-editor_search search-icon"/>
       <i v-if="searchKey" @click="searchKey=''" class="iconfont icontoast_red clear-icon"></i>
     </div>
@@ -23,7 +23,7 @@
     <div class="table table-pano" v-show="currentMaterialType === 'pano'">
       <div class="table-head-row">
         <span class="table-head">1</span>
-        <span class="table-head" v-for="(item,i) in tableHeadersForPano" :key="i">{{item.name}}</span>
+        <span class="table-head" v-for="(item,i) in tableHeadersForPano" :key="i">{{ item.name && $i18n.t(`zh_key.${item.name}`) }}</span>
       </div>
       <div
         v-if="panoList.length !== 0"
@@ -45,7 +45,7 @@
           </span>
           <span class="table-data" v-for="(sub,idx) in tableHeadersForPano" :key="idx">
             <div v-if="sub.type=='image'" class="list-img">
-              <img :src="item.icon + (Number(item.fileSize)>512 ? `?x-oss-process=image/resize,p_20&${Math.random()}` : ``)" alt="">
+              <img :src="item.icon + (Number(item.fileSize)>512 ? $imgsuffix : ``)" alt="">
             </div>
             <span class="ellipsis" v-else v-title="item.sceneTitle">{{item.sceneTitle}}</span>
           </span>
@@ -55,11 +55,11 @@
       <div v-if="panoList.length === 0" class="no-data">
         <div v-if="latestUsedSearchKey">
           <img :src="require('@/assets/images/default/empty_04_search.png')" alt="">
-          <span>{{'未搜索到结果~'}}</span>
+          <span>{{$i18n.t(`gather.no_serch_result`)}}</span>
         </div>
         <div v-if="!latestUsedSearchKey">
           <img :src="require('@/assets/images/default/empty_04.png')" alt="">
-          <span>{{'暂无素材~'}}</span>
+          <span>{{$i18n.t(`gather.no_material_result`)}}</span>
         </div>
       </div>
     </div>
@@ -67,7 +67,7 @@
     <div class="table table-3D" v-show="currentMaterialType === '3D'">
       <div class="table-head-row">
         <span class="table-head">1</span>
-        <span class="table-head" v-for="(item,i) in tableHeadersFor3D" :key="i">{{item.name}}</span>
+        <span class="table-head" v-for="(item,i) in tableHeadersFor3D" :key="i">{{ item.name && $i18n.t(`zh_key.${item.name}`) }}</span>
       </div>
       <div
         v-if="scene3DList.length !== 0"
@@ -89,7 +89,7 @@
           </span>
           <span class="table-data" v-for="(sub,idx) in tableHeadersFor3D" :key="idx">
             <div v-if="sub.type=='image'" class="list-img">
-              <img :src="item.icon + (Number(item.fileSize)>512 ? `?x-oss-process=image/resize,p_20&${Math.random()}` : ``)" alt="">
+              <img :src="item.icon + (Number(item.fileSize)>512 ? $imgsuffix : ``)" alt="">
             </div>
             <span class="ellipsis" v-else v-title="item.sceneTitle">{{item.sceneTitle}}</span>
           </span>
@@ -99,20 +99,20 @@
       <div v-if="scene3DList.length === 0" class="no-data">
         <div v-if="latestUsedSearchKey">
           <img :src="require('@/assets/images/default/empty_04_search.png')" alt="">
-          <span>{{'未搜索到结果~'}}</span>
+          <span>{{$i18n.t(`gather.no_serch_result`)}}</span>
         </div>
         <div v-if="!latestUsedSearchKey">
           <img :src="require('@/assets/images/default/empty_04.png')" alt="">
-          <span>{{'暂无素材~'}}</span>
+          <span>{{$i18n.t(`gather.no_material_result`)}}</span>
         </div>
       </div>
     </div>
 
     <div class="btns">
       <div>
-        <button class="ui-button deepcancel" @click="$emit('cancle')">取消</button>
+        <button class="ui-button deepcancel" @click="$emit('cancle')">{{$i18n.t(`gather.cancel`)}}</button>
         <button class="ui-button submit" :class="{disable: !select.length}" @click="onClickComfirm">
-          确定
+          {{$i18n.t(`gather.comfirm`)}}
         </button>
       </div>
     </div>
@@ -401,10 +401,10 @@ export default {
     color: transparent;
   }
   &:nth-of-type(2) {
-    width: calc(116px - 50px);
+    width: calc(146px - 50px);
   }
   &:nth-of-type(3) {
-    width: calc(416px - 116px);
+    width: calc(416px - 146px);
     padding-right: 30px;
   }
   &:nth-of-type(4) {
@@ -419,10 +419,10 @@ export default {
     color: transparent;
   }
   &:nth-of-type(2) {
-    width: calc(116px - 50px);
+    width: calc(146px - 50px);
   }
   &:nth-of-type(3) {
-    width: calc(416px - 116px);
+    width: calc(416px - 146px);
     padding-right: 30px;
   }
   &:nth-of-type(4) {

+ 3 - 3
packages/qjkankan-editor/src/components/preview/index.vue

@@ -82,10 +82,10 @@ export default {
 
       try {
         document.execCommand("copy")
-          ? this.$msg.success("复制成功")
-          : this.$msg.error("复制失败")
+          ? this.$msg.success(this.$i18n.t('gather.scene_link_copy_tips'))
+          : this.$msg.error(this.$i18n.t('gather.scene_link_copy_failed'))
       } catch (err) {
-        this.$msg.error("复制失败")
+        this.$msg.error(this.$i18n.t('gather.scene_link_copy_failed'))
       }
 
       document.body.removeChild(textArea);

+ 2 - 1
packages/qjkankan-editor/src/components/sceneGroupInEditor.vue

@@ -22,7 +22,8 @@
       <i v-show="isExpanded" class="iconfont icon-editor_folder_on folder_expanded"></i>
       <i v-show="!isExpanded" class="iconfont icon-editor_folder_off folder_collapsed"></i>
       <template v-if="!isRenaming">
-        <span class="group-name" v-title="groupNode.name">{{groupNode.name}}</span>
+        <span class="group-name" v-title="$i18n.t(`zh_key.${groupNode.name}`).indexOf('zh_key')>-1?groupNode.name:$i18n.t(`zh_key.${groupNode.name}`)">{{
+          $i18n.t(`zh_key.${groupNode.name}`).indexOf('zh_key')>-1?groupNode.name:$i18n.t(`zh_key.${groupNode.name}`)}}</span>
         <i v-show="level === 1"
           class="iconfont icon-editor_list_add icon-add"
           v-tooltip="$i18n.t('navigation.add_two_group')"

+ 7 - 2
packages/qjkankan-editor/src/components/shared/Editor.vue

@@ -38,11 +38,17 @@ export default {
 
             if (text) {
                 //this.quill.root.innerHTML = this.quill.root.innerHTML+text;
-                let index = (this.quill.getSelection() || {}).index;
+                let index = this.quill.selection.savedRange.index
                 if (typeof index == "undefined") {
                     index = this.quill.getLength() - 1;
                 }
+
                 this.quill.insertText(index, text);
+
+                setTimeout(() => {
+                    this.quill.setSelection(index + text.length); 
+                }, 10);
+
             }
         });
         $editable.on("mousewheel touchstart touchmove", e => {
@@ -72,7 +78,6 @@ export default {
 
         this.quill.on("text-change", (delta, old, source) => {
             let html = this.quill.root.innerHTML == '<p><br></p>' ? '' : this.quill.root.innerHTML;
-            console.dir(this.quill.root, 'wdwdwd');
             // 过滤emoji表情
             html = html.replace(/(\ud83c[\udf00-\udfff])|(\ud83d[\udc00-\ude4f])|(\ud83d[\ude80-\udeff])/g, function (char) {
                 var H, L, code;

+ 9 - 2
packages/qjkankan-editor/src/components/shared/loading/smallWaiting.vue

@@ -4,7 +4,7 @@
             <div class="icon">
                 <img :src="require('@/assets/images/loading.png')" alt="">
             </div>
-            <div class="txt">加载中</div>
+            <div class="txt">{{lodingtxt}}</div>
             <!-- <div class="spinner">
                 <div class="bounce1"></div>
                 <div class="bounce2"></div>
@@ -16,17 +16,24 @@
 </template>
 <script>
 import Popup from "../popup";
+import { i18n } from "@/lang"
 export default {
     name: "ui-waiting",
     components: {
         Popup
     },
     data() {
+        console.log(i18n);
         return {
             display: false,
-            duration: 0
+            duration: 0,
         };
     },
+    computed:{
+        lodingtxt(){
+            return i18n.t(`gather.loading`)
+        }
+    },
     methods: {
         show() {
             this.$nextTick(() => (this.display = true));

+ 8 - 2
packages/qjkankan-editor/src/components/shared/loading/smallWaiting1.vue

@@ -1,7 +1,7 @@
 <template>
     <popup ref="Message" v-if="display">
         <div class="ui-waiting">
-            <div class="txt">加载中</div>
+            <div class="txt">{{lodingtxt}}</div>
             <div class="spinner">
                 <div class="bounce1"></div>
                 <div class="bounce2"></div>
@@ -13,6 +13,7 @@
 </template>
 <script>
 import Popup from "../popup";
+import { i18n } from "@/lang"
 export default {
     name: "ui-waiting",
     components: {
@@ -21,9 +22,14 @@ export default {
     data() {
         return {
             display: false,
-            duration: 0
+            duration: 0,
         };
     },
+    computed:{
+        lodingtxt(){
+            return i18n.t(`gather.loading`)
+        }
+    },
     methods: {
         show() {
             this.$nextTick(() => (this.display = true));

+ 1 - 1
packages/qjkankan-editor/src/components/shared/message/Alert.vue

@@ -1,6 +1,6 @@
 <template>
     <popup ref="Message" :show="show">
-        <div class="ui-message ui-message-confirm" :class="[isMaterial?'message-material':'dark']">
+        <div class="ui-message ui-message-confirm" :style="{width:$lang=='zh'?'400px':'auto'}" :class="[isMaterial?'message-material':'dark']">
             <div class="ui-message-header" :class="{'header-material':isMaterial}">
                 <span>{{title}}</span>
                 <span @click="onNo" v-if="showCloseIcon">

+ 2 - 2
packages/qjkankan-editor/src/components/shared/message/Confirm.vue

@@ -1,6 +1,6 @@
 <template>
     <popup ref="Message" :show="show">
-        <div class="ui-message ui-message-confirm" :class="[isMaterial?'message-material':'dark']">
+        <div class="ui-message ui-message-confirm" :style="{width:$lang=='zh'?'400px':'auto'}" :class="[isMaterial?'message-material':'dark']">
             <div class="ui-message-header" :class="{'header-material':isMaterial}">
                 <span>{{title}}</span>
                 <span @click="onNo" v-if="showCloseIcon">
@@ -92,7 +92,7 @@ export default {
 
 <style lang="less" scoped>
 .ui-message {
-  width: 400px;
+    min-width: 400px;
   height: 230px;
 }
 </style>

+ 1 - 37
packages/qjkankan-editor/src/config/index.js

@@ -12,46 +12,10 @@ const config = {
     noresult:require('@/assets/images/icons/img_noresults@2x.png'),
     empty: require('@/assets/images/icons/img_empty@2x.png'),
     projectNum: browser.urlQueryValue('id'),
+    lang: browser.urlQueryValue('lang') || 'zh',
     sceneNum: browser.urlQueryValue('vr'),
     hengdaNum: browser.urlQueryValue('h') || '6017118343179540233',
     CDN: process.env.VUE_APP_CDN,
-    panoSetting:{
-      angle_of_view:{
-        viewSettings:[
-                {
-                  sceneName:"",
-                  hlookat:"",
-                  vlookat:"",
-                  fov:"",
-                  fovmin:"",
-                  fovmax:"",
-                  vlookatmin:"",
-                  vlookatmax:"",
-                  keepView:""
-                }
-            ]
-        },
-      
-        hotspot:{
-            "scene_2714214b9d86af1c":{
-              link:[
-                    {
-                      ath: "29.67632725773",
-                      atv: "14.842309070323",
-                      hotspotTitle: "erer",
-                      iconType: "system",
-                      imgPath: "https://chuanvr.cn/vrimages/def_material/1609325861896b0h.png",
-                      isDynamic: "0",
-                      isNewWindow: "1",
-                      isShowSpotName: "",
-                      link: "http://tetet",
-                      name: "schp_z35sqjjbmy",
-                      thumbPath: "https://chuanvr.cn/vrimages/def_material/1609325861896b0h.png",
-                    }
-                ],
-            }
-        }
-    },
 
     isMobile: function() {
       var e = navigator.userAgent || navigator.vendor || window.opera;

+ 5 - 5
packages/qjkankan-editor/src/framework/EditorHead.vue

@@ -1,6 +1,6 @@
 <template>
   <header class="app-head" app-border dir-bottom>
-    <a class="app-head-back" href="./material.html#/works">
+    <a class="app-head-back" :href="`./material.html?lang=${$lang}#/works`">
       <i class="iconfont icon-editor_return"></i>
       {{back_myworks}}
     </a>
@@ -68,7 +68,7 @@ export default {
     checkParams() {
       if (!this.info.name && !this.info.icon && !this.info.description && this.info.scenes.length <= 0) {
         this.$alert({
-          content: "您还未创建任何内容哦",
+          content: this.$i18n.t('gather.nothing_edit'),
           ok: () => {
             this.$router.push({ path: "/base" });
           },
@@ -104,14 +104,14 @@ export default {
           someData: { ...this.info, status: 1 },
         },
         () => {
-          this.$msg.success("保存成功");
+          this.$msg.success(this.$i18n.t('gather.save_done'));
           document.title = this.info.name;
           this.getInfo();
           this.$store.commit("UpdateIsShowState", true);
           setTimeout(() => {
             if (this.info.scenes.length <= 0 && this.isShow) {
               return this.$alert({
-                content: "至少添加一个场景才可预览,请前往“场景导航”添加",
+                content: this.$i18n.t('gather.at_least_one_scene'),
               });
             }
             this.showPreview = true;
@@ -150,7 +150,7 @@ export default {
           someData: { ...this.info, status: 1 },
         },
         () => {
-          this.$msg.success("保存成功");
+          this.$msg.success(this.$i18n.t('gather.save_done'));
           document.title = this.info.name;
           this.getInfo();
           this.$store.commit("UpdateIsShowState", true);

+ 1 - 1
packages/qjkankan-editor/src/framework/core/index.vue

@@ -70,7 +70,7 @@ export default {
             this.$bus.emit('toggleFlash',false)
             this.$bus.emit("initView", res.data);
             this.updateInfo()
-            this.$msg.success("设置成功")
+            this.$msg.success(this.$i18n.t("gather.setting_success"))
             this.$store.commit("SetInfo", this.info);
           }
         });

+ 3 - 2
packages/qjkankan-editor/src/framework/material/header.vue

@@ -1,8 +1,8 @@
 <template>
   <div class="header">
     <div class="con">
-      <a href="https://www.4dkankan.com/" class="logo">
-        <img :src="require('@/assets/images/icons/logo_black.svg')" alt="" />
+      <a :href="homeLink" class="logo">
+        <img :src="require(`@/assets/images/icons/logo_black_${$lang}.svg`)" alt="" />
       </a>
       <ul class="tab">
         <li @click="handleItem(item)" :class="{active:active.id==item.id}" v-for="(item, i) in tab" :key="i">
@@ -24,6 +24,7 @@ export default {
   },
   data() {
     return {
+      homeLink:process.env.VUE_APP_PROXY_URL_ROOT,
       active:{},
       tab: [
         {

+ 3 - 3
packages/qjkankan-editor/src/framework/play/pano/index.vue

@@ -7,7 +7,7 @@
     </div>
     <list></list>
 
-    <template v-if="showSnapshot && currentScene">
+    <template v-if="showSnapshot && currentScene&&currentScene.type !=='4dkk'">
       <snapshot :showFlash="showFlash"></snapshot>
       <button class="ui-button submit set-initial-view" :class="{disable: currentScene.type === '4dkk',}" @click="onClick">{{$i18n.t('screen.setting_screen')}}</button>
     </template>
@@ -169,7 +169,7 @@ export default {
             this.$bus.emit('toggleFlash', false)
             this.$bus.emit("initView", res.data);
             this.updateInfo()
-            this.$msg.success("设置成功")
+            this.$msg.success(this.$i18n.t("gather.setting_success"))
             this.$store.commit("SetInfo", this.info);
           }
         });
@@ -179,7 +179,7 @@ export default {
       this.$store.commit("tags/setIsConfirmingPosi", param.name);
     },
     onClickGo4dkk() {
-      window.open('/#/')
+      window.open('/#/scene')
     }
   },
   mounted() {

+ 185 - 109
packages/qjkankan-editor/src/lang/_en.json

@@ -541,21 +541,31 @@
       "copy_link": "Copy link",
       "work_preview": "Project Preview",
       "new_blank": "Open in a new window",
-      "cancel": "Cancel"
+      "cancel": "Cancel",
+
+
+      "no_link": "Link not generated, please edit your project to include material",
+      "had_created": "You have created your project with success!",
+      "goto_preview": "Preview",
+      "continue_edit": "Continue to edit",
+      "had_created_but_no_link": "New project has been created successfully, but refreshing the project list failed; please try again later.",
+      "delete_work": "Delete project",
+      "comfirm_delete": "Confirm to delete the project?"
+
     },
     "components":{
-      "prev":"上一张",
-      "next":"下一张",
-      "zoom_in":"放大",
-      "zoom_out":"缩小",
-      "delete":"删除",
-      "fullscreen":"全屏",
-      "cancel_fullscreen":"取消全屏",
-      "pano_setting":"全景图封面设置",
-      "drag_to_cut":"拖动画面截取封面",
-      "cutting":"截图",
-      "preview_cover":"封面预览",
-      "rename_material":"重命名素材"
+      "prev":"Previous",
+      "next":"Next",
+      "zoom_in":"Zoom in",
+      "zoom_out":"Zoom out",
+      "delete":"Delete",
+      "fullscreen":"Full screen",
+      "cancel_fullscreen":"Exit full screen",
+      "pano_setting":"Thumbnail Settings",
+      "drag_to_cut":"Drag the screen to have a screenshot",
+      "cutting":"Screenshot",
+      "preview_cover":"Preview",
+      "rename_material":"Rename the material"
     }
   },
   "gather": {
@@ -593,9 +603,36 @@
     "no_material_result": "No materials found",
     "had_load": "{msg} pieces of data have been loaded",
     "uploading": "Uploading {msg}",
-    "success": "操作成功",
-    "delete_success": "删除成功",
-    "delete_fail": "删除失败"
+    "success": "Operation succeeded",
+    "delete_success": "Deletion succeeded",
+    "delete_fail": "Delete failed",
+    "loading": "Loading",
+
+    "too_long_word": "Title is too long; please upload an image with a 50-word or shorter title.",
+    "too_long_word_audio": "Title is too long; please upload an audio with a 50-word or shorter title",
+    "too_long_word_video": "Title is too long; please upload a video with a 50-word or shorter title",
+    "uploading_material": "Uploading material",
+    "cutting": "Cropping",
+    "material_upload_fail": "Failed to upload material",
+    "material_cutting_fail": "Failed to crop image",
+
+    "fill_complete": "Please fill in the complete information.",
+    "fill_phone": "Please fill in the phone number correctly",
+    "edit_success": "Modification succeeded",
+    "setting_success": "Setting succeeded",
+    "scene_link_copy_tips": "Copied",
+    "scene_link_copy_failed": "Copy failed",
+    
+    "delete_material": "Delete material",
+    "comfirm_delete_material": "Confirm to delete the material?",
+
+    "save_done": "Save successfully",
+
+    "nothing_edit": "You haven't created any content yet",
+    "at_least_one_scene": "At least one scene can be previewed. Please go to \"Scene Navigation\" to add",
+    "exitVr": "Exit VR"
+
+
   },
   "personal_center": {
     "personal_center": "Personal Center",
@@ -657,10 +694,10 @@
     "description": "Description",
     "work_placeholder": "Please enter the project title",
     "intro_placeholder": "Please input no more than 500 words of text content.",
-    "help_center": "帮助中心",
-    "display_time": "显示时间",
-    "no_display": "(不显示)",
-    "second": ""
+    "help_center": "Help Center",
+    "display_time": "Display duration",
+    "no_display": "(No display)",
+    "second": " Sec"
   },
   "zh_key": {
     "电话": "Tel",
@@ -678,106 +715,145 @@
     "自定义LOGO": "Custom Logo",
     "自定义遮罩": "Custom Mask",
     "自定义按钮": "Custom Button",
-    "素材": "素材",
-    "名称": "名称",
-    "大小": "大小",
-    "分辨率": "分辨率",
-    "创建时间": "创建时间",
-    "修改时间": "修改时间"
+    "素材": "Material",
+    "名称": "Title",
+    "大小": "Size",
+    "分辨率": "Resolution",
+    "创建时间": "Created",
+    "修改时间": "Modified",
+
+    "封面": "cover",
+    "场景标题": "Scene Title",
+    "拍摄时间": "Shooting Time",
+    "一级分组":"1st Grouping",
+    "二级分组":"2nd Grouping",
+    "默认二级分组":"Default as 2nd grouping"
   },
   "navigation": {
-    "scene_edit_tips": "请前往四维时代个人中心编辑场景",
-    "go_scene_editor": "立即前往",
-    "scene_navigation": "场景导航",
-    "add_group": "新建分组",
-    "scene_tips": "场景素材包括全景图和三维场景,您可自定义分组及场景的排列顺序。",
-    "add_two_group": "新建二级分组",
-    "add_pano_or_scene": "新增全景图或三维场景",
-    "group_one": "一级分组",
-    "group_two": "二级分组",
-    "default_group_two": "默认二级分组",
-    "init_scene": "初始场景",
-    "setting_init_scene": "设置初始场景",
-    "init_scene_tips": "初始场景为查看链接时进入的第一个场景,未设\n置时,不固定从某一场景打开。",
-    "edit_init_scene": "修改场景",
-    "delete_init_scene": "删除场景",
-    "keep_one_scene": "请至少保留一个场景",
-    "keep_one_group": "请至少保留一个分组",
-    "enter_name": "输入名字",
-    "rename": "重命名",
-    "delete": "删除",
-    "pano": "全景",
-    "scene": "三维",
-    "scene_name": "场景",
-    "already_exists": "{msg}已存在,不可重复添加"
+    "scene_edit_tips": "Please direct to the 4Dage Personal Center scene editing platform.",
+    "go_scene_editor": "Get started now",
+    "scene_navigation": "Navigation",
+    "add_group": "Add a grouping",
+    "scene_tips": "You can customize the grouping and ordering of scene material, which includes panorama and 3D scenes",
+    "add_two_group": "Add 2nd Grouping",
+    "add_pano_or_scene": "Add panorama or 3D scene",
+    "group_one": "1st Grouping",
+    "group_two": "2nd Grouping",
+    "default_group_two": "Default as 2nd grouping",
+    "init_scene": "Start screen",
+    "setting_init_scene": "Start screen settings",
+    "init_scene_tips": "The start screen is the initial scene entered when a link is viewed, and it is not fixed to a specific scene when \n is not set.",
+    "edit_init_scene": "Edit the scene",
+    "delete_init_scene": "Delete the scene",
+    "keep_one_scene": "Please retain at least one scene",
+    "keep_one_group": "Please retain at least one grouping",
+    "enter_name": "Please enter the project title",
+    "rename": "Rename",
+    "delete": "Delete",
+    "pano": "Panorama",
+    "scene": "3D Scene",
+    "scene_name": "Scene",
+    "already_exists": "{msg} already exists, can not be repeatedly added"
   },
   "screen": {
-    "init_screen": "初始画面",
-    "screen_tips": "初始画面为进入场景时第一画面,请拖动全景图选择合适的画面设置。",
-    "setting_screen": "将当前视角设为初始画面"
+    "init_screen": "Start screen",
+    "screen_tips": "The start screen is the initial screen that appears when entering a scene; please drag the panorama to select the appropriate screen setting.",
+    "setting_screen": "Set the current view to the start screen"
   },
   "hotspot": {
-    "hotspot_setting": "热点设置",
-    "hotspot_tips": "在全景图中添加图标热点,并设置热点的效果。",
-    "add_hotspot": "添加热点",
-    "current_hotspots": "当前全景图热点",
-    "delete": "删除",
-    "add": "新增",
-    "edit": "编辑",
-    "success": "成功",
-    "click_to_comfirm": "单击确定热点位置",
-    "no_hotspot": "暂无热点信息~",
-    "close_dialog": "热点内容未编辑完,确定要关闭吗",
-    "hotspot_name": "热点",
-    "hotspot_icon": "热点图标",
-    "select_hotspot_icon": "请选择热点图标",
-    "input_hotspot_title": "请选择热点图标",
-    "select_icon": "选择图标",
-    "title_setting": "标题设置",
-    "isshow_title": "是否显示标题",
-    "title_placeholder": "请输入标题,限50字",
-    "effect_settings": "效果设置",
-    "cancel": "取消",
-    "finish": "完成",
-    "secne": "场景",
-    "audio": "音频",
-    "video": "视频",
-    "image": "图片",
-    "link": "超链接",
-    "textarea": "文本",
-    "secne_errortxt": "请选择场景",
-    "audio_errortxt": "请选择音频",
-    "video_errortxt": "请选择视频",
-    "image_errortxt": "请选择图片",
-    "link_errortxt": "请输入超链接",
-    "textarea_errortxt": "请输入文本",
-    "icon_size": "图标大小",
-    "unit": "",
-    "add_audio": "添加音频",
-    "change_audio": "更换音频",
-    "select_audio": "选择音频",
-    "add_image": "添加图片",
-    "add_tooltips": "添加",
-    "select_image": "选择图片",
-    "popup": "弹出层打开",
-    "newTab": "新窗口打开",
-    "add_scene": "添加场景",
-    "change_scene": "更换场景",
-    "text_placeholder": "请输入文字内容,限500字",
-    "add_video": "添加视频",
-    "select_video": "添加视频",
-    "change_video": "更换视频"
+    "hotspot_setting": "Hotspot settings",
+    "hotspot_tips": "Add icon hotspots to the panorama and configure their effect",
+    "add_hotspot": "Add hotspot",
+    "current_hotspots": "Current panorama hotspots",
+    "delete": "Delete",
+    "add": "Add",
+    "edit": "Edit",
+    "success": "Success",
+    "click_to_comfirm": "Click to determine the location of hotspots",
+    "no_hotspot": "No hotspot information at this time~",
+    "close_dialog": "Hotspot content is not fully edited, confirm to close it",
+    "hotspot_name": "Hotspots",
+    "hotspot_icon": "Hotspot icon",
+    "select_hotspot_icon": "Select the hotspot icon",
+    "input_hotspot_title": "Enter the hotspot title",
+    "select_icon": "Select Icon",
+    "title_setting": "Title Settings",
+    "isshow_title": "Display the title or not",
+    "title_placeholder": "Enter a title with a maximum of 50 characters",
+    "effect_settings": "Effect settings",
+    "cancel": "Cancel",
+    "finish": "Finish",
+    "secne": "Scene",
+    "audio": "Audio",
+    "video": "Video",
+    "image": "Image",
+    "link": "Hyperlink",
+    "textarea": "Text",
+    "secne_errortxt": "Please select a scene",
+    "audio_errortxt": "Please select audio",
+    "video_errortxt": "Please choose a video",
+    "image_errortxt": "Please select pictures",
+    "link_errortxt": "Please enter the hyperlink",
+    "textarea_errortxt": "Please enter the text",
+    "icon_size": "Icon Size",
+    "unit": "times",
+    "add_audio": "Add audio",
+    "change_audio": "Change the audio",
+    "select_audio": "Select audio",
+    "add_image": "Add images",
+    "add_tooltips": "Add",
+    "select_image": "Select images",
+    "popup": "Pop-up Notification",
+    "newTab": "New Tab",
+    "add_scene": "Add a scene",
+    "change_scene": "Change a scene",
+    "text_placeholder": "Please enter no more than 500 words of text.",
+    "add_video": "Add a video",
+    "select_video": "Add a video",
+    "change_video": "Change a video"
   },
   "explanation": {
-    "explanation_settings": "语音讲解",
-    "explanation_tips": "您可以为当前全景图添加语音讲解音频。",
-    "add_audio": "添加音频",
-    "change_audio": "更换音频",
-    "default_open": "默认开启",
-    "loop": "循环播放"
+    "explanation_settings": "Voice Guide",
+    "explanation_tips": "You can add voice guide for the current panorama.",
+    "add_audio": "Add audio",
+    "change_audio": "Change audio",
+    "default_open": "Enable",
+    "loop": "Loop"
   },
   "style_key": {
     "menu_width": "88px",
     "play_width": "31"
+  },
+  "tips_code":{
+    "FAILURE_2020": "appId is absent",
+    "FAILURE_2021": "The appId was wrongly parsed",
+    "FAILURE_5001": "token is empty",
+    "FAILURE_5002": "redis token does not exist",
+    "FAILURE_5003": "token invalid(invalid)",
+    "FAILURE_3001": "Object does not exist",
+    "FAILURE_3011": "No operation authorization",
+    "FAILURE_3020": "Empty file",
+    "FAILURE_3021": "Illegal file",
+    "FAILURE_3022": "Upload file exceeds maximum",
+    "FAILURE_3023": "Illegal format",
+    "FAILURE_3025": "Upload error",
+    "FAILURE_3101": "The referenced material cannot be erased",
+    "FAILURE_3102": "The computation scene cannot be erased",
+    "FAILURE_3103": "Server someData.json file does not exist",
+    "FAILURE_3200": "Failed to request for third-party API",
+    "FAILURE_3201": "Failed to request the interface",
+    "FAILURE_error": "Network exception, please try again later",
+    "tips":"Tips",
+    "relogin":"Invalid login status; please log in again",
+    "goto_login":"Go to login",
+    "login_success":"Login completed, please continue",
+    "need_one":"Please keep at least one scene",
+    "not_less_than":"File title may not exceed 50 characters in length",
+    "work_had_delete":"The project has been deleted and cannot be edited",
+    "material_can_not_delete":"The material cannot be removed because it has been cited.",
+    "illegality_image":"This image is not supported",
+    "password_error":"Password error",
+    "FAILURE_3024": "Storage is at capacity",
+    "loading_fail": "Failed to load"
   }
 }

+ 88 - 4
packages/qjkankan-editor/src/lang/_zh.json

@@ -541,7 +541,18 @@
       "copy_link": "复制链接",
       "work_preview": "全景作品预览",
       "new_blank": "新窗口打开",
-      "cancel": "取消"
+      "cancel": "取消",
+
+      "no_link": "链接未生成,请编辑作品添加素材",
+      "had_created": "您已成功创建作品!",
+      "goto_preview": "预览一下",
+      "continue_edit": "继续编辑",
+      "had_created_but_no_link": "已成功新建作品,但刷新作品列表失败,请稍后手动刷新。",
+      "delete_work": "删除作品",
+      "comfirm_delete": "确定要删除作品吗?"
+
+      
+      
     },
     
     "components":{
@@ -596,7 +607,38 @@
     "uploading": "正在上传 {msg}",
     "success": "操作成功",
     "delete_success": "删除成功",
-    "delete_fail": "删除失败"
+    "delete_fail": "删除失败",
+    "loading": "加载中",
+
+    "too_long_word": "名称过长,请上传标题在50字以内的图片",
+    "too_long_word_audio": "名称过长,请上传标题在50字以内的音频",
+    "too_long_word_video": "名称过长,请上传标题在50字以内的视频",
+    "uploading_material": "正在上传素材",
+    "cutting": "正在切图处理",
+    "material_upload_fail": "素材上传失败",
+    "material_cutting_fail": "素材切图失败",
+
+
+    "fill_complete": "请填写完整信息",
+    "fill_phone": "请正确填写电话号码",
+    "edit_success": "修改成功",
+    "setting_success": "设置成功",
+    "scene_link_copy_tips": "复制成功",
+    "scene_link_copy_failed": "复制失败",
+
+
+    "delete_material": "删除素材",
+    "comfirm_delete_material": "确定要删除素材吗?",
+    
+    "save_done": "保存成功",
+
+    "nothing_edit": "您还未创建任何内容哦",
+    "at_least_one_scene": "至少添加一个场景才可预览,请前往“场景导航”添加",
+    "exitVr": "退出VR模式"
+
+    
+
+
   },
   "personal_center": {
     "personal_center": "个人中心",
@@ -685,7 +727,17 @@
     "大小": "大小",
     "分辨率": "分辨率",
     "创建时间": "创建时间",
-    "修改时间": "修改时间"
+    "修改时间": "修改时间",
+
+    "封面": "封面",
+    "场景标题": "场景标题",
+    "拍摄时间": "拍摄时间",
+
+    "一级分组":"一级分组",
+    "二级分组":"二级分组",
+    "默认二级分组":"默认二级分组"
+
+
 
   },
   "navigation": {
@@ -734,7 +786,7 @@
     "hotspot_name": "热点",
     "hotspot_icon": "热点图标",
     "select_hotspot_icon": "请选择热点图标",
-    "input_hotspot_title": "请选择热点图标",
+    "input_hotspot_title": "请输入热点标题",
     "select_icon": "选择图标",
     "title_setting": "标题设置",
     "isshow_title": "是否显示标题",
@@ -782,5 +834,37 @@
   "style_key": {
     "menu_width": "58px",
     "play_width": "0"
+  },
+  "tips_code":{
+    "FAILURE_2020": "appId为空",
+    "FAILURE_2021": "appId解析有误",
+    "FAILURE_5001": "token为空",
+    "FAILURE_5002": "redis token不存在",
+    "FAILURE_5003": "token invalid(无效)",
+    "FAILURE_3001": "对象不存在",
+    "FAILURE_3011": "没有操作权限",
+    "FAILURE_3020": "空文件",
+    "FAILURE_3021": "非法文件",
+    "FAILURE_3022": "上传文件超过最大值",
+    "FAILURE_3023": "非法格式",
+    "FAILURE_3025": "上传失败",
+    "FAILURE_3101": "素材已经被引用, 不能删除",
+    "FAILURE_3102": "计算中的场景不能删除",
+    "FAILURE_3103": "服务器someData.json文件不存在",
+    "FAILURE_3200": "请求第三方API失败",
+    "FAILURE_3201": "请求第三方API返回失败",
+    "FAILURE_error": "网络异常,请稍后再试",
+    "tips":"提示",
+    "relogin":"登录状态失效,请重新登录",
+    "goto_login":"去登录",
+    "login_success":"登录完毕,继续",
+    "need_one":"请至少保留一个场景。",
+    "not_less_than":"文件名称不允许超过50个字符",
+    "work_had_delete":"作品已被删除,无法编辑",
+    "material_can_not_delete":"素材已被引用,无法删除。",
+    "illegality_image":"不支持此图片",
+    "password_error":"密码错误",
+    "FAILURE_3024": "存储空间已满",
+    "loading_fail": "加载失败"
   }
 }

+ 8 - 25
packages/qjkankan-editor/src/mixins/index.js

@@ -38,6 +38,9 @@ let STRSTATUS = {
 
 Vue.use(InfiniteScroll)
 
+
+
+Vue.prototype.$lang = config.lang;
 Vue.prototype.$bus = bus;
 Vue.prototype.$api = api;
 Vue.prototype.$cdn = config.CDN;
@@ -86,32 +89,12 @@ Vue.prototype.$msg.error = (string)=>{
 Vue.prototype.$videoImg =
   "?x-oss-process=video/snapshot,t_0,f_jpg,w_0,h_0,m_fast,ar_auto";
 
-Vue.prototype.$panoType = [
-  {
-    id: "building",
-    name: "楼盘全景",
-  },
-  {
-    id: "garden",
-    name: "园林全景",
-  },
-  {
-    id: "house",
-    name: "户型",
-  },
-];
-
-Vue.prototype.$nameStr = {
-  building: "楼盘全景",
-  garden: "园林全景",
-  house: "户型",
-};
+  
+Vue.prototype.$imgsuffix =
+process.env.VUE_APP_ORIGIN=='aws'?encodeURIComponent('?x-oss-process=image@resize,m_lfit,w_200@crop,w_200,h_200'.replaceAll('/','@'))
+:`?x-oss-process=image/resize,p_20&${Math.random()}`;
 
-Vue.prototype.$nameSort = {
-  building: 1,
-  garden: 2,
-  house: 3,
-};
+console.log(process.env.VUE_APP_ORIGIN);
 
 Vue.prototype.$scrollbars = [];
 

+ 3 - 0
packages/qjkankan-editor/src/pages/show.js

@@ -4,6 +4,8 @@ import App from './show.vue'
 import store from '../Store'
 import 'viewerjs/dist/viewer.css'
 import Viewer from 'v-viewer'
+import { i18n } from "@/lang"
+
 Vue.use(Viewer,{
   defaultOptions: {
     toolbar: 0,
@@ -15,5 +17,6 @@ Vue.use(Viewer,{
 Vue.config.productionTip = false
 new Vue({
   store,
+  i18n,
   render: h => h(App)
 }).$mount('#app')

+ 2 - 0
packages/qjkankan-editor/src/pages/vr.js

@@ -1,8 +1,10 @@
 import Vue from 'vue'
 import '../mixins'
 import App from './vr.vue'
+import { i18n } from "@/lang"
 
 Vue.config.productionTip = false
 new Vue({
+  i18n,
   render: h => h(App)
 }).$mount('#app')

+ 21 - 39
packages/qjkankan-editor/src/utils/request.js

@@ -13,9 +13,11 @@ import { base64ToBlob } from "./file";
 import { checkLogin } from "@/api";
 import { LoginDetector } from "@/utils/starter";
 import { $alert, $confirm } from "@/components/shared/message";
+import {i18n} from '@/lang'
 
 let vue = new Vue();
 
+
 // 空函数
 const noop = function() {};
 // 请求回调队列
@@ -58,6 +60,7 @@ const statusCode = {
   FAILURE_CODE_3201: 3201, // "请求第三方API返回失败"
 
   FAILURE_CODE_5001: 5001, //token失效
+  FAILURE_CODE_5002: 5002, //token失效
   FAILURE_CODE_5003: 5003, //不支持此图片
   FAILURE_CODE_5004: 5004, // 密码错误
 
@@ -76,10 +79,10 @@ export const showLoginTips = () => {
   showLoginTips.__is_show = true;
 
   return $confirm({
-    title: "提示",
-    content: "登录状态失效,请重新登录",
-    okText: "去登录",
-    noText: "登录完毕,继续",
+    title: i18n.t('tips_code.tips'),
+    content: i18n.t('tips_code.relogin'),
+    okText: i18n.t('tips_code.goto_login'),
+    noText: i18n.t('tips_code.login_success'),
     okLink: "/",
     ok: function() {
       showLoginTips.__is_show = false;
@@ -92,7 +95,7 @@ export const showLoginTips = () => {
           postQueue = [];
           LoginDetector.valid();
           location.reload()
-        } else if (response.code === statusCode.FAILURE_CODE_5001) {
+        } else if (response.code === statusCode.FAILURE_CODE_5001||response.code === statusCode.FAILURE_CODE_5002) {
           showLoginTips();
         }
       })
@@ -117,67 +120,46 @@ export function getToken() {
 }
 
 export function statusCodesHandler(result, callback) {
-  if (result.code == statusCode.FAILURE_CODE_7005) {
-    $alert({
-      content: "该VR作品待审核,不可编辑。",
-      forceOK: true,
-      ok: () => {
-        let url = window.location.href
-        window.location.href = url
-      },
-    });
-    return false
-  }
-
-  if (result.code == statusCode.FAILURE_CODE_7006) {
-    $alert({
-      content: "该VR作品已审核,不可编辑。",
-      forceOK: true,
-      ok: () => {
-        window.location.reload();
-      },
-    });
-    return false
-  }
+  
 
   if (result.code == statusCode.FAILURE_CODE_3002) {
-    $alert({ content: "请至少保留一个场景。" });
+    $alert({ content: i18n.t('tips_code.need_one') });
     return false
   }
 
   if (result.code == statusCode.FAILURE_CODE_3003) {
-    $alert({ content: '文件名称不允许超过50个字符' })
+    $alert({ content: i18n.t('tips_code.not_less_than') })
     return false
   }
 
   if (result.code == statusCode.FAILURE_CODE_3005) {
-    $alert({ content: "作品已被删除,无法编辑" });
+    $alert({ content: i18n.t('tips_code.work_had_delete') });
     return false
   }
   
   if (result.code == statusCode.FAILURE_CODE_3006) {
-    $alert({ content: "作品已被删除,无法编辑" });
+    $alert({ content: i18n.t('tips_code.work_had_delete') });
     return
   }
 
   if (result.code == statusCode.FAILURE_CODE_3007) {
-    $alert({ content: "素材已被引用,无法删除。" });
+    $alert({ content: i18n.t('tips_code.material_can_not_delete') });
     return
   }
 
-  if (result.code == statusCode.FAILURE_CODE_5001) {
+  if (result.code == statusCode.FAILURE_CODE_5001||result.code === statusCode.FAILURE_CODE_5002) {
     callback(result.code);
     showLoginTips();
     return false
   }
 
   if (result.code == statusCode.FAILURE_CODE_5003) {
-    $alert({ content: '不支持此图片' })
+    $alert({ content: i18n.t('tips_code.illegality_image') })
     return false
   }
 
   if (result.code == statusCode.FAILURE_CODE_5004) {
-    vue.$msg.error("密码错误");
+    vue.$msg.error(i18n.t('tips_code.password_error'));
     return false
   }
 
@@ -185,7 +167,7 @@ export function statusCodesHandler(result, callback) {
     if (!isDiglog) {
       isDiglog = true
       $alert({
-        content: "存储空间已满",
+        content: i18n.t('tips_code.FAILURE_3024'),
         forceOK: true,
         ok: () => {
           isDiglog = false
@@ -218,7 +200,7 @@ $.ajaxSetup({
     }
     __showNetworkError = true;
     $alert({
-      content: "网络异常,请稍后再试",
+      content: i18n.t('tips_code.FAILURE_error'),
       forceOK: true,
       ok: () => {
         __showNetworkError = false;
@@ -245,7 +227,7 @@ export const http = {
       if (typeof result.code !== "undefined") { 
         const flag = statusCodesHandler(result, function(code) {
           // 需要登录的状态
-          if (code == statusCode.FAILURE_CODE_5001) {
+          if (code == statusCode.FAILURE_CODE_5001||code === statusCode.FAILURE_CODE_5002) {
             postQueue.push(function() {
               http[method](url, data, done, fail);
             });
@@ -460,7 +442,7 @@ export const http = {
     img.onerror = function() {
       retry > 0
         ? setTimeout(() => load(), 1e3)
-        : def.reject(`[${url}]加载失败`);
+        : def.reject(`[${url}]${i18n.t('tips_code.loading_fail')}`);
     };
 
     img.onload = function() {

+ 0 - 1
packages/qjkankan-editor/src/views/base/Toolbar.vue

@@ -141,7 +141,6 @@ export default {
       });
     },
     onEditorChange(content){
-      console.log(content);
       this.info.description = content.html
       this.jianjieLength = content.size
     },

+ 10 - 5
packages/qjkankan-editor/src/views/base/customButtonSettings.vue

@@ -218,7 +218,7 @@ export default {
     },
     checkButtonName(name) {
       if (!name) {
-        this.$msg.warning('请填写完整信息')
+        this.$msg.warning(i18n.t('gather.fill_complete'))
         return false
       }
       return true
@@ -226,12 +226,12 @@ export default {
     checkButtonValue(value, type) {
       if (type === '电话') {
         if (!isValidPhoneNumber(value)) {
-          this.$msg.warning('请正确填写电话号码')
+          this.$msg.warning(i18n.t('gather.fill_phone'))
           return false
         }
       } else if (type === '链接') {
         if (!value) {
-          this.$msg.warning('请填写完整信息')
+          this.$msg.warning(i18n.t('gather.fill_complete'))
           return false
         }
       }
@@ -247,7 +247,7 @@ export default {
       this.info.customButton[this.editingButtonIdx].type = this.editingInfo.type
       this.info.customButton[this.editingButtonIdx].name = this.editingInfo.name
       this.info.customButton[this.editingButtonIdx].value = this.editingInfo.value
-      this.$msg.success('操作成功')
+      this.$msg.success(i18n.t('gather.success'))
       this.isEditing = false
     },
     onRequestForShow(index) {
@@ -259,7 +259,12 @@ export default {
       }
       this.info.customButton[index].isShow = true
     }
-  }
+  },
+  mounted() {
+    this.info.customButton.forEach(item=>{
+      item.name = i18n.t(`zh_key.${item.name}`).indexOf('zh_key')>-1?item.name:i18n.t(`zh_key.${item.name}`)
+    })
+  },
 }
 </script>
 

+ 1 - 1
packages/qjkankan-editor/src/views/base/customLogoSettings.vue

@@ -15,7 +15,7 @@
       <div class="bottom-right">
         <img 
           class="select-pic-btn"
-          :src="require('@/assets/images/select_pic_btn.png')" alt=""
+          :src="require(`@/assets/images/select_pic_btn_${$lang}.png`)" alt=""
           @click="onClickSelectingPicBtn"
         >
         <!-- <button

+ 2 - 2
packages/qjkankan-editor/src/views/base/customMaskSettings.vue

@@ -18,7 +18,7 @@
         <div class="bottom-right">
           <img 
             class="select-pic-btn"
-            :src="require('@/assets/images/select_pic_btn.png')" alt=""
+            :src="require(`@/assets/images/select_pic_btn_${$lang}.png`)" alt=""
             @click="onSelectPic('sky')"
           >
           <!-- <button
@@ -45,7 +45,7 @@
         <div class="bottom-right">
           <img 
             class="select-pic-btn"
-            :src="require('@/assets/images/select_pic_btn.png')" alt=""
+            :src="require(`@/assets/images/select_pic_btn_${$lang}.png`)" alt=""
             @click="onSelectPic('earth')"
           >
           <!-- <button

+ 1 - 0
packages/qjkankan-editor/src/views/hotspot/hotspotType/scene.vue

@@ -147,6 +147,7 @@ export default {
       button {
         width: 100%;
         padding: 0;
+        white-space: unset;
       }
       .scene-title {
         margin-top: 10px;

+ 11 - 11
packages/qjkankan-editor/src/views/material/audio/index.vue

@@ -70,7 +70,7 @@
             </i>
             <i class="iconfont icon-material_operation_delete hover-tips-warn" @click="del(item)">
               <div>
-                <div class="remark">{{del}}</div>
+                <div class="remark">{{deltips}}</div>
               </div>
             </i>
           </div>
@@ -199,7 +199,7 @@ export default {
       checkUserSize({},(data)=>{
         //判断已用是否大于3G
         if ((data.data / 1024 / 1024) > 3) {
-          this.$alert({ content: "空间已满" });
+          this.$alert({ content: i18n.t("tips_code.FAILURE_3024") });
         }else{
           this.$refs.uploadFile.click()
         }
@@ -231,7 +231,7 @@ export default {
           name: newName,
         },
         () => {
-          this.$msg.success("修改成功");
+          this.$msg.success(i18n.t("gather.edit_success"));
           const index = this.list.findIndex((eachItem) => {
             return eachItem.id === this.popupItem.id
           })
@@ -247,12 +247,12 @@ export default {
     },
     del(item) {
       this.$confirm({
-        title: '删除素材',
-        content: "确定要删除素材吗?",
-        okText: '删除',
+        title: i18n.t("gather.delete_material"),
+        content: i18n.t("gather.comfirm_delete_material"),
+        okText: i18n.t("gather.delete"),
         ok: () => {
           delMaterial(item.id, () => {
-            this.$msg.success("删除成功");
+            this.$msg.success(i18n.t("gather.delete_success"));
             this.isRequestingMoreData = true
             const lastestUsedSearchKey = this.searchKey
             getMaterialList(
@@ -300,7 +300,7 @@ export default {
         if (eachFile.name.toLowerCase().indexOf("mp3") <= -1) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”格式错误,请上传20MB以内、mp3格式的音频`,
+              message: `“${eachFile.name}”${i18n.t("gather.audio_fail")}`,
               type: "warning",
             });
           }, i * 100);
@@ -310,7 +310,7 @@ export default {
         if (eachFile.name.substring(0, eachFile.name.lastIndexOf(".")).length > 50) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”名称过长,请上传标题在50字以内的音频`,
+              message: `“${eachFile.name}”${i18n.t("gather.too_long_word_audio")}`,
               type: "warning",
             });
           }, i * 100);
@@ -322,7 +322,7 @@ export default {
           ifKnowProgress: true,
           progress: 0,
           status: 'LOADING',
-          statusText: "正在上传素材",
+          statusText: i18n.t("gather.uploading_material"),
           uid: `u_${this.$randomWord(true, 8, 8)}`,
           abortHandler: null,
         };
@@ -350,7 +350,7 @@ export default {
               this.uploadListForUI.splice(index, 1)
             } else {
               itemInUploadList.status = 'FAIL'
-              itemInUploadList.statusText = '素材上传失败'
+              itemInUploadList.statusText = i18n.t("gather.material_upload_fail")
             }
           },
           (progress) => {

+ 10 - 10
packages/qjkankan-editor/src/views/material/image/index.vue

@@ -77,7 +77,7 @@
           <div v-else-if="sub.type == 'image'" class="img">
             <img
               :id="'img' + item.id"
-              :src="data + (Number(item.fileSize)>512 ? `?x-oss-process=image/resize,p_20&${Math.random()}` : '') "
+              :src="data + (Number(item.fileSize)>512 ? $imgsuffix : '') "
               alt=""
               @click="previewImage(item)"
             />
@@ -234,7 +234,7 @@ export default {
           name: newName,
         },
         () => {
-          this.$msg.success("修改成功");
+          this.$msg.success(i18n.t("gather.edit_success"));
           const index = this.list.findIndex((eachItem) => {
             return eachItem.id === this.popupItem.id
           })
@@ -250,12 +250,12 @@ export default {
     },
     del(item) {
       this.$confirm({
-        title: '删除素材',
-        content: "确定要删除素材吗?",
-        okText: '删除',
+        title: i18n.t("gather.delete_material"),
+        content: i18n.t("gather.comfirm_delete_material"),
+        okText: i18n.t("gather.delete"),
         ok: () => {
           delMaterial(item.id, () => {
-            this.$msg.success("删除成功");
+            this.$msg.success(i18n.t("gather.delete_success"));
             this.isRequestingMoreData = true
             const lastestUsedSearchKey = this.searchKey
             getMaterialList(
@@ -314,7 +314,7 @@ export default {
         ) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”格式错误,请上传10MB以内、jpg/png格式的图片`,
+              message: `“${eachFile.name}”${i18n.t("gather.img_fail")}`,
               type: "warning",
             });
           }, i * 100);
@@ -324,7 +324,7 @@ export default {
         if (eachFile.name.substring(0, eachFile.name.lastIndexOf(".")).length > 50) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”名称过长,请上传标题在50字以内的图片`,
+              message: `“${eachFile.name}”${i18n.t("gather.too_long_word")}`,
               type: "warning",
             });
           }, i * 100);
@@ -336,7 +336,7 @@ export default {
           ifKnowProgress: true,
           progress: 0,
           status: 'LOADING',
-          statusText: "正在上传素材",
+          statusText: i18n.t("gather.uploading_material"),
           uid: `u_${this.$randomWord(true, 8, 8)}`,
           abortHandler: null,
         };
@@ -364,7 +364,7 @@ export default {
               this.uploadListForUI.splice(index, 1)
             } else {
               itemInUploadList.status = 'FAIL'
-              itemInUploadList.statusText = '素材上传失败'
+              itemInUploadList.statusText = i18n.t("gather.material_upload_fail")
             }
           },
           (progress) => {

+ 16 - 16
packages/qjkankan-editor/src/views/material/pano/index.vue

@@ -61,7 +61,7 @@
           </div>
           <!-- 图片型单元格 -->
           <div class="img" v-else-if="sub.type == 'image'" @click="previewImage(item)">
-            <img :src="data + (Number(item.fileSize) > 512 ? `?x-oss-process=image/resize,p_20&${Math.random()}` : '')"
+            <img :src="data + (Number(item.fileSize) > 512 ? $imgsuffix : '')"
               alt="" />
           </div>
           <span style="cursor: pointer;" @click="previewImage(item)" v-else-if="sub.key == 'name'">{{ data || "-" }}
@@ -216,7 +216,7 @@ export default {
       checkUserSize({}, (data) => {
         //判断已用是否大于3G
         if ((data.data / 1024 / 1024) > 3) {
-          this.$alert({ content: "空间已满" });
+          this.$alert({ content: i18n.t("tips_code.FAILURE_3024") });
         } else {
           this.$refs.uploadFile.click()
         }
@@ -245,7 +245,7 @@ export default {
           name: newName,
         },
         () => {
-          this.$msg.success("修改成功");
+          this.$msg.success(i18n.t("gather.edit_success"));
           const index = this.list.findIndex((eachItem) => {
             return eachItem.id === this.popupItem.id
           })
@@ -273,7 +273,7 @@ export default {
               icon: res.data,
             },
             () => {
-              this.$msg.success("设置成功");
+              this.$msg.success(i18n.t("gather.setting_success"));
 
               const index = this.list.findIndex((eachItem) => {
                 return eachItem.id === this.popupItem.id
@@ -331,7 +331,7 @@ export default {
               if (eachRes.status === 2) {
                 const index = this.uploadListForUI.findIndex(eachTask => eachTask.backendId === eachRes.id)
                 index >= 0 && (this.uploadListForUI[index].status = 'FAIL')
-                index >= 0 && (this.uploadListForUI[index].statusText = '素材切图失败')
+                index >= 0 && (this.uploadListForUI[index].statusText = this.$msg.success(i18n.t("gather.material_cutting_fail")))
               } else if (eachRes.status === 3) {
                 const index = this.uploadListForUI.findIndex(eachTask => eachTask.backendId === eachRes.id)
                 index >= 0 && (this.uploadListForUI.splice(index, 1))
@@ -344,12 +344,12 @@ export default {
     },
     del(item) {
       this.$confirm({
-        title: '删除素材',
-        content: "确定要删除素材吗?",
-        okText: '删除',
+        title: i18n.t("gather.delete_material"),
+        content: i18n.t("gather.comfirm_delete_material"),
+        okText: i18n.t("gather.delete"),
         ok: () => {
           delMaterial(item.id, () => {
-            this.$msg.success("删除成功");
+            this.$msg.success(i18n.t("gather.delete_success"));
             this.isRequestingMoreData = true
             const lastestUsedSearchKey = this.searchKey
             getMaterialList(
@@ -407,7 +407,7 @@ export default {
         ) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”格式错误,请上传2:1、120MB以内、jpg格式的全景图片`,
+              message: `“${eachFile.name}”${i18n.t("gather.pano_fail")}`,
               type: "warning",
             });
           }, i * 100);
@@ -417,7 +417,7 @@ export default {
         if (eachFile.name.substring(0, eachFile.name.lastIndexOf(".")).length > 50) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”名称过长,请上传标题在50字以内的全景图片`,
+              message: `“${eachFile.name}”${i18n.t("gather.too_long_word")}`,
               type: "warning",
             });
           }, i * 100);
@@ -432,7 +432,7 @@ export default {
           console.error('获取图像宽高失败:', e)
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”格式错误,请上传2:1、120MB以内、jpg格式的全景图片`,
+              message: `“${eachFile.name}”${i18n.t("gather.pano_fail")}`,
               type: "warning",
             });
           }, i * 100);
@@ -441,7 +441,7 @@ export default {
         if (WHRate !== 2) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”格式错误,请上传2:1、120MB以内、jpg格式的全景图片`,
+              message: `“${eachFile.name}”${i18n.t("gather.pano_fail")}`,
               type: "warning",
             });
           }, i * 100);
@@ -453,7 +453,7 @@ export default {
           ifKnowProgress: true,
           progress: 0,
           status: 'LOADING',
-          statusText: "正在上传素材",
+          statusText: i18n.t("gather.uploading_material"),
           uid: `u_${this.$randomWord(true, 8, 8)}`,
           abortHandler: null,
           backendId: '',
@@ -468,7 +468,7 @@ export default {
             uid: itemInUploadList.uid,
           },
           (response) => { // 上传成功
-            itemInUploadList.statusText = '正在切图处理'
+            itemInUploadList.statusText = i18n.t("gather.cutting")
             itemInUploadList.ifKnowProgress = false
             itemInUploadList.backendId = response.data.id
           },
@@ -480,7 +480,7 @@ export default {
               this.uploadListForUI.splice(index, 1)
             } else {
               itemInUploadList.status = 'FAIL'
-              itemInUploadList.statusText = '素材上传失败'
+              itemInUploadList.statusText = i18n.t("gather.material_upload_fail")
             }
           },
           (progress) => {

+ 1 - 1
packages/qjkankan-editor/src/views/material/popup/cover.vue

@@ -9,7 +9,7 @@
         </div>
         <div class="ui-message-main re-name">
           <div>
-            <iframe id="ifrcover" :src="'./vr.html?hideScale=1&vr='+item.sceneCode" frameborder="0"></iframe>
+            <iframe id="ifrcover" :src="'./vr.html?hideScale=1&vr='+item.sceneCode+'&lang='+$lang" frameborder="0"></iframe>
             <div>
               <span class="remark">{{$i18n.t(`material.components.drag_to_cut`)}}</span>
               <div @click="onClick" :class="canPrintScreen ? 'print-screen-btn' : 'print-screen-btn--disabled'" >

+ 1 - 1
packages/qjkankan-editor/src/views/material/popup/panoImagePreviewer.vue

@@ -13,7 +13,7 @@
         ref="iframe"
         class="iframe"
         allowfullscreen="true"
-        :src="'./vr.html?hideScale=true&vr='+ sceneCodeList[currentIndex]"
+        :src="'./vr.html?hideScale=true&vr='+ sceneCodeList[currentIndex] +'&lang='+$lang"
         frameborder="0"
         :style="{width: imageWidth, height: imageHeight}"
       />

+ 3 - 3
packages/qjkankan-editor/src/views/material/popup/share.vue

@@ -24,7 +24,7 @@
         <button @click="downloadImg(item)" class="ui-button">
           {{download_qrCode}}
         </button>
-        <button @click="copy(item.share)" class="ui-button submit">
+        <button @click="copy(item.share+`&lang=${$lang}`)" class="ui-button submit">
           {{copy_link}}
         </button>
       </div>
@@ -116,9 +116,9 @@ export default {
       textArea.select();
 
       try {
-        document.execCommand("copy") ? this.$msg.success("复制成功") : this.$msg.error("复制失败");
+        document.execCommand("copy") ? this.$msg.success(this.$i18n.t('gather.scene_link_copy_tips')) : this.$msg.error(this.$i18n.t('gather.scene_link_copy_failed'));
       } catch (err) {
-        this.$msg.error("复制失败");
+        this.$msg.error(this.$i18n.t('gather.scene_link_copy_failed'));
       }
 
       document.body.removeChild(textArea);

+ 2 - 1
packages/qjkankan-editor/src/views/material/style.less

@@ -255,7 +255,7 @@
 // 列表为空时,上传按钮的样式。因为在“我的作品”和“我的素材”里位置不一样,所以只能写在这里。
 .upload-btn-in-table {
   cursor: pointer;
-  width: 100px;
+  // width: 100px;
   height: 36px;
   background: linear-gradient(144deg, #00AEFB 0%, #0076F6 100%);
   border-radius: 22px;
@@ -263,6 +263,7 @@
   font-size: 14px;
   color: #FFFFFF;
   margin-top: 20px;
+  padding: 0 16px;
 }
 
 // 左上角上传素材按钮的提示icon,hover时的样式和一般的有tooltip的元素不一样

+ 12 - 12
packages/qjkankan-editor/src/views/material/video/index.vue

@@ -70,7 +70,7 @@
             </i>
             <i class="iconfont icon-material_operation_delete hover-tips-warn" @click="del(item)">
               <div>
-                <div class="remark">{{del}}</div>
+                <div class="remark">{{deltips}}</div>
               </div>
             </i>
           </div>
@@ -208,7 +208,7 @@ export default {
       checkUserSize({},(data)=>{
         //判断已用是否大于3G
         if ((data.data / 1024 / 1024) > 3) {
-          this.$alert({ content: "空间已满" });
+          this.$alert({ content: i18n.t("tips_code.FAILURE_3024") });
         }else{
           this.$refs.uploadFile.click()
         }
@@ -239,7 +239,7 @@ export default {
           name: newName,
         },
         () => {
-          this.$msg.success("修改成功");
+          this.$msg.success(i18n.t("gather.edit_success"));
           const index = this.list.findIndex((eachItem) => {
             return eachItem.id === this.popupItem.id
           })
@@ -255,12 +255,12 @@ export default {
     },
     del(item) {
       this.$confirm({
-        title: '删除素材',
-        content: "确定要删除素材吗?",
-        okText: '删除',
+        title: i18n.t("gather.delete_material"),
+        content: i18n.t("gather.comfirm_delete_material"),
+        okText: i18n.t("gather.delete"),
         ok: () => {
           delMaterial(item.id, () => {
-            this.$msg.success("删除成功");
+            this.$msg.success(i18n.t("gather.delete_success"));
             this.isRequestingMoreData = true
             const lastestUsedSearchKey = this.searchKey
             getMaterialList(
@@ -308,7 +308,7 @@ export default {
         if (eachFile.name.toLowerCase().indexOf("mp4") <= -1) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”格式错误,请上传200MB以内、mp4格式的视频`,
+              message: `“${eachFile.name}”${i18n.t("gather.video_fail")}`,
               type: "warning",
             });
           }, i * 100);
@@ -318,7 +318,7 @@ export default {
         if (eachFile.name.substring(0, eachFile.name.lastIndexOf(".")).length > 50) {
           setTimeout(() => {
             this.$msg({
-              message: `“${eachFile.name}”名称过长,请上传标题在50字以内的视频`,
+              message: `“${eachFile.name}”${i18n.t("gather.too_long_word_video")}`,
               type: "warning",
             });
           }, i * 100);
@@ -330,7 +330,7 @@ export default {
           ifKnowProgress: true,
           progress: 0,
           status: 'LOADING',
-          statusText: "正在上传素材",
+          statusText: i18n.t("gather.uploading_material"),
           uid: `u_${this.$randomWord(true, 8, 8)}`,
           abortHandler: null,
         };
@@ -358,7 +358,7 @@ export default {
               this.uploadListForUI.splice(index, 1)
             } else {
               itemInUploadList.status = 'FAIL'
-              itemInUploadList.statusText = '素材上传失败'
+              itemInUploadList.statusText = i18n.t("gather.material_upload_fail")
             }
           },
           (progress) => {
@@ -392,7 +392,7 @@ export default {
         (data) => {
           const newData = data.data.list.map((i) => {
             i.fileSize = changeByteUnit(Number(i.fileSize));
-            i.icon = i.ossPath + '?x-oss-process=video/snapshot,t_0,f_jpg,w_89,h_50,m_fast,ar_auto';
+            i.icon = process.env.VUE_APP_ORIGIN=='aws'?i.icon:(i.ossPath + '?x-oss-process=video/snapshot,t_0,f_jpg,w_89,h_50,m_fast,ar_auto');
             i.createTime = i.createTime.substring(0, i.createTime.length - 3)
             i.updateTime = i.updateTime.substring(0, i.updateTime.length - 3)
             return i;

+ 16 - 14
packages/qjkankan-editor/src/views/material/works/index.vue

@@ -78,7 +78,7 @@
       <button @click="add" class="upload-btn-in-table">{{create}}</button>
     </div>
     <share :show='showShare' :item="shareItem" @close="showShare=false"></share>
-    <preview v-if="showItem" :name="showItem.name" :show="showPreview" :ifr="`./show.html?id=${showItem.id}`"
+    <preview v-if="showItem" :name="showItem.name" :show="showPreview" :ifr="`./show.html?id=${showItem.id}&lang=${$lang}`"
       :dark="false" @close="showPreview = false" />
     <div class="dialog" style="z-index: 10" v-if="isShowMaterialSelector">
       <MaterialSelector :title="select_material" @cancle="isShowMaterialSelector = false" @submit="handleSubmitFromMaterialSelector"
@@ -183,9 +183,10 @@ export default {
       this.requestMoreData()
     }, 700, false),
     openShare(data) {
+      console.log(data);
       getPanoInfo(data.id, (data) => {
         if (data.scenes.length <= 0) {
-          return this.$msg.warning("链接未生成,请编辑作品添加素材");
+          return this.$msg.warning(this.$i18n.t("material.works.no_link"));
         }
         this.showShare = true
         this.shareItem = data
@@ -195,7 +196,7 @@ export default {
     handlePreview(item) {
       getPanoInfo(item.id, (data) => {
         if (data.scenes.length <= 0) {
-          return this.$msg.warning("链接未生成,请编辑作品添加素材");
+          return this.$msg.warning(this.$i18n.t("material.works.no_link"));
         }
         this.showItem = {
           ...item,
@@ -267,23 +268,23 @@ export default {
 
                 // 弹出提示窗口
                 this.$confirm({
-                  title: '提示',
-                  content: "您已成功创建作品!",
-                  okText: '预览一下',
+                  title: this.$i18n.t('tips_code.tips'),
+                  content: this.$i18n.t("material.works.had_created"),
+                  okText: this.$i18n.t("material.works.goto_preview"),
                   ok: () => {
                     this.handlePreview(this.list[0])
                     this.newWorkId = ''
                     this.$store.commit("SetInfo", {});
                   },
-                  ok2Text: '继续编辑',
+                  ok2Text: this.$i18n.t("material.works.continue_edit"),
                   ok2: () => {
-                    window.open(`./edit.html?id=${this.newWorkId}`)
+                    window.open(`./edit.html?id=${this.newWorkId}&lang=${this.$lang}`)
                     this.newWorkId = ''
                     this.$store.commit("SetInfo", {});
                   },
                 });
               }).catch(() => {
-                this.$msg.message('已成功新建作品,但刷新作品列表失败,请稍后手动刷新。')
+                this.$msg.message(this.$i18n.t("material.works.had_created_but_no_link"))
                 console.error('已成功新建作品,但刷新作品列表失败。')
               })
             },
@@ -305,15 +306,15 @@ export default {
       )
     },
     edit(item) {
-      window.open(`./edit.html?id=${item.id}`)
+      window.open(`./edit.html?id=${item.id}&lang=${this.$lang}`)
     },
     del(item, index) {
       this.$confirm({
-        title: '删除作品',
-        content: "确定要删除作品吗?",
+        title: this.$i18n.t("material.works.delete_work"),
+        content: this.$i18n.t("material.works.comfirm_delete"),
         ok: () => {
           delWorks(item.id, () => {
-            this.$msg.success("删除成功");
+            this.$msg.success(this.$i18n.t("gather.delete_success"));
             this.isRequestingMoreData = true
             const lastestUsedSearchKey = this.searchKey
             getWorksList(
@@ -487,7 +488,8 @@ export default {
   .w-list {
     flex: 1 1 auto;
     overflow: auto;
-    margin-top: 30px;
+    margin-top: 22px;
+    padding-top: 8px;
     @gap: 20px;
     display: flex;
     flex-wrap: wrap;

+ 21 - 0
packages/qjkankan-kankan-view/.env.eurtestprod

@@ -0,0 +1,21 @@
+NODE_ENV=production
+
+# 场景资源地址
+VUE_APP_RESOURCE_URL=https://testeurs3.4dkankan.com/
+# 静态资源地址
+VUE_APP_CDN_URL=https://testeurs3.4dkankan.com/v4/www/
+# sdk文件地址
+VUE_APP_SDK_DIR=https://testeurs3.4dkankan.com/v4/www/sdk/
+
+
+
+# 静态资源目录
+VUE_APP_STATIC_DIR=viewer
+
+
+# 云存储环境
+VUE_APP_REGION_URL=
+
+# 接口请求地址
+VUE_APP_APIS_URL=https://testeur.4dkankan.com/
+

+ 1 - 0
packages/qjkankan-kankan-view/package.json

@@ -6,6 +6,7 @@
     "serve": "vue-cli-service serve",
     "serve-prod": "vue-cli-service serve --mode prod",
     "build": "vue-cli-service build --mode prod",
+    "build-eurtestprod": "vue-cli-service build --mode eurtestprod",
     "lint": "vue-cli-service lint"
   },
   "dependencies": {

+ 2 - 12
packages/qjkankan-kankan-view/src/i18n/index.js

@@ -44,18 +44,8 @@ export function setI18nLanguage(i18n, locale) {
 export async function loadLocaleMessages(i18n, locale) {
     // load locale messages with dynamic import
     // set locale and locale message
-    if (window.location.search.includes('i18n')) {
-        try {
-            const messages = await (await fetch(`https://4dkk.4dage.com/v4/www/locales/${locale}.json?_=${Date.now()}`)).json()
-            i18n.global.setLocaleMessage(locale, messages)
-        } catch (error) {
-            const messages = await import(/* webpackChunkName: "locale-[request]" */ `../locales/zh.json`)
-            i18n.global.setLocaleMessage(locale, messages.default)
-        }
-    } else {
-        const messages = await import(/* webpackChunkName: "locale-[request]" */ `../locales/${locale}.json`)
-        i18n.global.setLocaleMessage(locale, messages.default)
-    }
+    const messages = await import(/* webpackChunkName: "locale-[request]" */ `../locales/${locale}.json`)
+    i18n.global.setLocaleMessage(locale, messages.default)
 
     return nextTick()
 }

+ 9 - 0
packages/qjkankan-view/.env.eurtestdev

@@ -0,0 +1,9 @@
+VUE_APP_STATIC_DIR=showviewer
+VUE_APP_CDN=https://testeurs3.4dkankan.com
+VUE_APP_PROXY_URL_ROOT='https://testeur.4dkankan.com'
+VUE_APP_PROXY_URL='https://testeur.4dkankan.com/qjkankan/'
+VUE_APP_URL_FILL=
+
+# 接口请求地址
+VUE_APP_APIS_URL=https://testeur.4dkankan.com/
+

+ 6 - 0
packages/qjkankan-view/.env.eurtestprod

@@ -0,0 +1,6 @@
+NODE_ENV=production
+VUE_APP_STATIC_DIR=showviewer
+VUE_APP_CDN=https://testeurs3.4dkankan.com
+VUE_APP_PROXY_URL_ROOT='https://testeur.4dkankan.com'
+VUE_APP_PROXY_URL='https://testeur.4dkankan.com/qjkankan/'
+VUE_APP_URL_FILL=/qjkankan

+ 2 - 0
packages/qjkankan-view/package.json

@@ -4,8 +4,10 @@
   "private": true,
   "scripts": {
     "serve": "vue-cli-service serve",
+    "serve-eurtestdev": "vue-cli-service serve --mode eurtestdev",
     "build": "vue-cli-service build",
     "build-testprod": "vue-cli-service build --mode testprod",
+    "build-eurtestprod": "vue-cli-service build --mode eurtestprod",
     "build-prod": "vue-cli-service build --mode prod",
     "lint": "vue-cli-service lint"
   },

+ 7 - 3
packages/qjkankan-view/src/components/Fdkk/index.vue

@@ -2,19 +2,19 @@
   <div class="fdkkcon">
     <template v-if="fdkkCurrentVersion == 'v3'">
       <iframe allowfullscreen="true" allow="autoplay" :key="currentScene.sceneCode" v-if="!isMobile" id="fdkkifr"
-        :src="`/spc.html?m=${currentScene.sceneCode}`" frameborder="0"></iframe>
+        :src="`/spc.html?m=${currentScene.sceneCode}&lang=${lang}`" frameborder="0"></iframe>
       <!-- <iframe :key="currentScene.sceneCode" v-if="!isMobile" id="fdkkifr" :src="`https://test.4dkankan.com/spc.html?m=${currentScene.sceneCode}`" -->
 
       <!-- v3场景移动端,用embed.html定制开发 -->
       <v3mobile v-else @changeUrl="handleChange" @otherUrl="handleOther" :somedatainfo="somedatainfo"
         :key="embeM || currentScene.sceneCode"
-        :url="otherLink ? otherLink : `/embed.html?from=mingyuan&m=${embeM || currentScene.sceneCode}&lang=zh&scene-link=1&rnd=${rnd}`" />
+        :url="otherLink ? otherLink : `/embed.html?from=mingyuan&m=${embeM || currentScene.sceneCode}&lang=${lang}&scene-link=1&rnd=${rnd}`" />
     </template>
     <!-- :url="otherLink ? otherLink : `https://test.4dkankan.com/embed.html?from=mingyuan&m=${embeM || currentScene.sceneCode}&lang=zh&scene-link=1&rnd=${rnd}`" /> -->
 
 
     <iframe allowfullscreen="true" allow="autoplay" :key="currentScene.sceneCode" v-else id="fdkkifr"
-      :src="`${isMobile ? 'smg' : 'spg'}.html?m=${currentScene.sceneCode}`" frameborder="0"></iframe>
+      :src="`${isMobile ? 'smg' : 'spg'}.html?m=${currentScene.sceneCode}&lang=${lang}`" frameborder="0"></iframe>
     <!-- :src="`http://192.168.20.66:8080/${isMobile ? 'smg' : 'spg'}.html?m=${currentScene.sceneCode}`" -->
 
 
@@ -29,12 +29,16 @@ import browser from "@/utils/browser";
 import { useMusicPlayer } from '@/utils/sound'
 import v3mobile from "./v3fdkkmobile/iframe.vue";
 import { getApp } from '@/app'
+import config from "@/utils/config";
+
 
 const musicPlayer = useMusicPlayer()
 
 const store = useStore();
 const isMobile = computed(() => browser.isMobile());
 
+const lang = computed(() => config.lang);
+
 const currentScene = computed(() => store.getters["scene/currentScene"]);
 const fdkkCurrentVersion = computed(() => store.getters["scene/fdkkCurrentVersion"]);
 

+ 2 - 4
packages/qjkankan-view/src/components/Fdkk/v3fdkkmobile/iframe.vue

@@ -49,10 +49,8 @@ export default {
 
         if (e.data.event == "link-click") {
           if (
-            e.data.params.url.indexOf("https://www.4dkankan.com/spc.html?") > -1 ||
-            e.data.params.url.indexOf("https://www.4dkankan.com/smobile.html?") > -1 ||
-            e.data.params.url.indexOf("https://test.4dkankan.com/spc.html?") > -1 ||
-            e.data.params.url.indexOf("https://test.4dkankan.com/smobile.html?") > -1
+            e.data.params.url.indexOf(`https://${window.location.hostname}/spc.html?`) > -1 ||
+            e.data.params.url.indexOf(`https://${window.location.hostname}/smobile.html?`) > -1 
           ) {
             let m = browser.urlHasValueFromUrl("m", e.data.params.url);
             this.$emit("changeUrl", m);

+ 5 - 1
packages/qjkankan-view/src/components/Pano/index.vue

@@ -11,6 +11,7 @@ import Fdkk from "../Fdkk";
 import { getFdkkInfo } from "@/apis";
 import { useMusicPlayer, useSoundPlayer } from '@/utils/sound'
 import browser from "@/utils/browser";
+import config from "@/utils/config";
 
 
 //背景音乐
@@ -21,6 +22,7 @@ const soundPlayer = useSoundPlayer()
 
 const store = useStore();
 const isMobile = computed(() => browser.isMobile());
+const lang = computed(() => config.lang);
 
 const currentScene = computed(() => store.getters["scene/currentScene"]);
 const metadata = computed(() => store.getters["scene/metadata"]);
@@ -42,7 +44,9 @@ const loadScene = async (currentScene) => {
 };
 
 watch(currentScene, (newVal, oldVal) => {
-  history.replaceState(null, null, "".concat(window.location.pathname, "?").concat(`id=${metadata.value.id}&vr=${newVal.sceneCode}`));
+  console.log(lang.value);
+
+  history.replaceState(null, null, "".concat(window.location.pathname, "?").concat(`id=${metadata.value.id}&vr=${newVal.sceneCode}&lang=${lang.value}`));
 
   //默认版本是v4
   store.commit("scene/setFdkkCurrentVersion", 'v4');

+ 2 - 2
packages/qjkankan-view/src/components/assembly/Share.vue

@@ -2,13 +2,13 @@
   <div class="url-share" v-show="show">
     <div>
       <div class="tips">
-        <h4>{{ $t("share.shareLinkTips") }}</h4>
+        <h4>{{ $t("share.shareLink") }}</h4>
         <i class="iconfont icon-bs_close" @click="onNo"></i>
       </div>
       <div class="url">{{ copyLink }}</div>
       <div class="btns">
         <ui-button class="ccc" @click="onNo">{{ $t("common.cancel") }}</ui-button>
-        <ui-button class="primary" :data-clipboard-text="copyLink" ref="copy$">{{ $t("share.fastCopy") }}</ui-button>
+        <ui-button class="primary" :data-clipboard-text="copyLink" ref="copy$">{{ $t("share.copyLink") }}</ui-button>
       </div>
     </div>
   </div>

+ 2 - 13
packages/qjkankan-view/src/i18n/index.js

@@ -44,19 +44,8 @@ export function setI18nLanguage(i18n, locale) {
 export async function loadLocaleMessages(i18n, locale) {
     // load locale messages with dynamic import
     // set locale and locale message
-    if (window.location.search.includes('i18n')) {
-        try {
-            const messages = await (await fetch(`https://4dkk.4dage.com/v4/www/locales/${locale}.json?_=${Date.now()}`)).json()
-            i18n.global.setLocaleMessage(locale, messages)
-        } catch (error) {
-            const messages = await import(/* webpackChunkName: "locale-[request]" */ `../locales/zh.json`)
-            i18n.global.setLocaleMessage(locale, messages.default)
-        }
-    } else {
-        const messages = await import(/* webpackChunkName: "locale-[request]" */ `../locales/${locale}.json`)
-        i18n.global.setLocaleMessage(locale, messages.default)
-    }
-
+    const messages = await import(/* webpackChunkName: "locale-[request]" */ `../locales/${locale}.json`)
+    i18n.global.setLocaleMessage(locale, messages.default)
     return nextTick()
 }
 

+ 35 - 34
packages/qjkankan-view/src/locales/en.json

@@ -5,21 +5,43 @@
     "cancel": "Cancel",
     "tips": "Tips",
     "hide": "Hide",
-    "show": "Show",
+    "show": "Display",
     "review": "Preview",
     "open": "Open",
     "close": "Close",
     "pauseTour": "Pause",
     "playTour": "Play",
-    "passwordTips": "Please enter the password",
-    "passwordError": "Incorrect Password",
-    "tour": "Tour Planner",
-    "support": "4Dage provides technical support",
+    "passwordTips": "Please enter the access code",
+    "passwordError": "Password incorrect",
+    "support": "4Dage Offers Digital Solutions",
     "all": "All",
-    "model": "Dollhouse"
+    "model": "3D Model",
+    "phone":"Tel",
+    "workDelete":"The project has been deleted!",
+    "loading":"Loading",
+    "prev":"Previous",
+    "next":"Next",
+    "zoomIn":"Zoom in",
+    "zoomOut":"Zoom out",
+    "fullScene": "Full screen",
+    "exitFullScene": "Exit full screen",
+    "image_fail": "Failed to load image",
+    "exit_vr": "Exit VR"
+
   },
-  "limit": {
-    "viewInVr": "Please use your phone to view the VR effect on the Web Interface."
+  "menu":{
+    "introduce": "Introduction ",
+    "music": "BGM",
+    "commentary": "Voice Guide",
+    "autoRotate": "Auto-play",
+    "share": "Share",
+    "fullScreen": "Full screen",
+    "guide": "Navigation",
+    "panorama": "Walkthrough",
+    "floorplan": "Floor Plan",
+    "dollhouse": "Dollhouse",
+    "dollhouseModel": "3D Model",
+    "tour":"Virtual Tour"
   },
   "share": {
     "wechat": "WeChat",
@@ -28,36 +50,15 @@
     "facebook": "Facebook",
     "whatsApp": "WhatsApp",
     "copyLink": "Copy Link",
-    "shareLink": "Share Link",
+    "shareLink": "Share Works",
     "shareLinkTips": "Share with your friends",
     "vrMode": "VR Mode",
     "fastCopy": "One-click Copy"
   },
   "toast": {
     "copySuccess": "Successfully copied",
-    "inputPassword": "Please enter the passward",
-    "checkBrowser": "Please update or change your browser and try to open the page again.",
-    "changeBrowser": "It is recommended to use the following Web Browser "
-  },
-  "mode": {
-    "panorama": "Panorama",
-    "floorplan": "Floorplan",
-    "dollhouse": "Dollhouse",
-    "dollhouseModel": "Dollhouse",
-    "vr": "Features",
-    "music": "Music",
-    "fullScene": "Full Screen",
-    "exitFullScene": "Full Screen"
-  },
-  "model": {
-    "enter": "Main Door"
-  },
-  "guide": {
-    "title": "Operation Tips",
-    "pano": "Walk<br />Click to move",
-    "rotate": "Roam<br />Swipe the screen to roam the screen to roam",
-    "zoom": "Zoom<br />Zoom in or out",
-    "set": "Got it"
-  },
-  "code": "System is busy, please try again later."
+    "inputPassword": "Please enter the password",
+    "checkBrowser": "Please upgrade or change your browser, then reopen the page.",
+    "changeBrowser": "The following web browsers are recommended:"
+  }
 }

+ 15 - 1
packages/qjkankan-view/src/locales/zh.json

@@ -25,7 +25,9 @@
     "zoomOut":"缩小",
     "fullScene": "全屏",
     "exitFullScene": "取消全屏",
-    "image_fail": "图片加载失败"
+    "image_fail": "图片加载失败",
+    "exit_vr": "退出VR模式"
+
   },
   "menu":{
     "introduce": "简介",
@@ -41,6 +43,18 @@
     "dollhouseModel": "三维模型",
     "tour":"导览"
   },
+  "share": {
+    "wechat": "微信",
+    "friends": "朋友圈",
+    "qq": "QQ",
+    "facebook": "Facebook",
+    "whatsApp": "WhatsApp",
+    "copyLink": "复制链接",
+    "shareLink": "分享作品",
+    "shareLinkTips": "分享链接给好友",
+    "vrMode": "VR模式",
+    "fastCopy": "一键复制"
+  },
   "toast": {
     "copySuccess": "复制成功",
     "inputPassword": "请输入密码",

+ 1 - 0
packages/qjkankan-view/src/pages/show.js

@@ -30,6 +30,7 @@ if (
 
 const local = getLocale();
 
+
 loadLocaleMessages(i18n, local).then(() => {
   setI18nLanguage(i18n, local);
 

+ 5 - 0
packages/qjkankan-view/src/pages/show.vue

@@ -33,6 +33,8 @@ import { useStore } from "vuex";
 import config from "@/utils/config";
 import browser from "@/utils/browser";
 import { useApp } from '@/app'
+import { useI18n, getLocale } from '@/i18n'
+const { t } = useI18n({ useScope: 'global' })
 
 const fixOpening = {
   '小行星开场': 1,
@@ -163,6 +165,9 @@ onMounted(async () => {
               app.krpanoDom.set(`hotspot[peaklogo].url`, skyMask.value.icon);
             }
           }
+
+          app.krpanoDom.set(`layer[webvr_exitbutton].html`, t('common.exit_vr'));
+
         }
         app.Tags.initHotspot(currentScene.value.someData.hotspots, false);
       });

+ 7 - 0
packages/qjkankan-view/src/pages/showMobile.vue

@@ -32,6 +32,10 @@ import { useStore } from "vuex";
 import config from "@/utils/config";
 import browser from "@/utils/browser";
 import { useApp } from '@/app'
+import { useI18n, getLocale } from '@/i18n'
+const { t } = useI18n({ useScope: 'global' })
+
+
 
 const fixOpening = {
   '小行星开场': 1,
@@ -162,6 +166,9 @@ onMounted(async () => {
               app.krpanoDom.set(`hotspot[peaklogo].url`, skyMask.value.icon);
             }
           }
+
+          app.krpanoDom.set(`layer[webvr_exitbutton].html`, t('common.exit_vr'));
+
         }
         app.Tags.initHotspot(currentScene.value.someData ? currentScene.value.someData.hotspots : [], false);
       });

+ 1 - 3
packages/qjkankan-view/src/store/modules/fdkk.js

@@ -110,9 +110,7 @@ export default {
         if (payload.indexOf('http') > -1) {
           bgm = payload
         } else {
-          bgm = window.location.href.indexOf("www.4dkankan.com") > -1
-            ? ('https://www.4dkankan.com/panorama/' + payload)
-            : ('https://test.4dkankan.com/panorama/' + payload)
+          bgm = `https://${window.location.hostname}/panorama/${payload}`
         }
 
         state.fdkkBGM = bgm

+ 2 - 1
packages/qjkankan-view/src/utils/config.js

@@ -12,8 +12,9 @@ const config = {
     empty: require('@/assets/images/default/img_empty@2x.png'),
     projectNum: browser.urlQueryValue('id'),
     sceneNum: browser.urlQueryValue('vr'),
+    lang: browser.urlQueryValue('lang')||'zh',
     CDN: process.env.VUE_APP_CDN,
-    fdkkURL: process.env.VUE_APP_APIS_URL,
+    fdkkURL: process.env.VUE_APP_PROXY_URL_ROOT+'/',
 
     getKrpano(obj){
         if(typeof(obj)=="undefined"||obj==null) obj="krpanoSWFObject";