Browse Source

Merge branch 'dev' into v1.2.0

tremble 2 năm trước cách đây
mục cha
commit
84cd8f0828
100 tập tin đã thay đổi với 3319 bổ sung1115 xóa
  1. 2 0
      packages/qjkankan-editor/.env
  2. 0 5
      packages/qjkankan-editor/.env.bendi
  3. 8 0
      packages/qjkankan-editor/.env.eurdev
  4. 10 0
      packages/qjkankan-editor/.env.eurprod
  5. 8 0
      packages/qjkankan-editor/.env.eurtestdev
  6. 10 0
      packages/qjkankan-editor/.env.eurtestprod
  7. 1 0
      packages/qjkankan-editor/.env.prod
  8. 7 0
      packages/qjkankan-editor/.env.testdev
  9. 1 0
      packages/qjkankan-editor/.env.testprod
  10. 5 1
      packages/qjkankan-editor/package.json
  11. 1 1
      packages/qjkankan-editor/public/edit.html
  12. 1 1
      packages/qjkankan-editor/public/material.html
  13. 12 2
      packages/qjkankan-editor/src/api/index.js
  14. 11 0
      packages/qjkankan-editor/src/assets/images/default/logo_white_en.svg
  15. 0 0
      packages/qjkankan-editor/src/assets/images/default/logo_white_zh.svg
  16. BIN
      packages/qjkankan-editor/src/assets/images/default/mask_bg_en.png
  17. 0 0
      packages/qjkankan-editor/src/assets/images/default/mask_bg_zh.png
  18. BIN
      packages/qjkankan-editor/src/assets/images/icons/USA.jpg
  19. BIN
      packages/qjkankan-editor/src/assets/images/icons/USA@2x.jpg
  20. BIN
      packages/qjkankan-editor/src/assets/images/icons/china.png
  21. BIN
      packages/qjkankan-editor/src/assets/images/icons/china@2x.png
  22. 11 0
      packages/qjkankan-editor/src/assets/images/icons/logo_black_en.svg
  23. 0 0
      packages/qjkankan-editor/src/assets/images/icons/logo_black_zh.svg
  24. BIN
      packages/qjkankan-editor/src/assets/images/select_pic_btn_en.png
  25. 0 0
      packages/qjkankan-editor/src/assets/images/select_pic_btn_zh.png
  26. 1 0
      packages/qjkankan-editor/src/assets/style/component.less
  27. 1 0
      packages/qjkankan-editor/src/assets/style/style.pc.editor.less
  28. 92 91
      packages/qjkankan-editor/src/components/materialSelectorForEditor.vue
  29. 220 203
      packages/qjkankan-editor/src/components/materialSelectorForManageCenter.vue
  30. 20 20
      packages/qjkankan-editor/src/components/materialSelectorFromWorkForEditor.vue
  31. 3 3
      packages/qjkankan-editor/src/components/preview/index.vue
  32. 3 2
      packages/qjkankan-editor/src/components/pulldownMenuInEditor.vue
  33. 6 3
      packages/qjkankan-editor/src/components/rangeItem/index.vue
  34. 25 13
      packages/qjkankan-editor/src/components/sceneGroupInEditor.vue
  35. 6 6
      packages/qjkankan-editor/src/components/sceneInGroupInEditor.vue
  36. 7 2
      packages/qjkankan-editor/src/components/shared/Editor.vue
  37. 9 2
      packages/qjkankan-editor/src/components/shared/loading/smallWaiting.vue
  38. 8 2
      packages/qjkankan-editor/src/components/shared/loading/smallWaiting1.vue
  39. 4 3
      packages/qjkankan-editor/src/components/shared/message/Alert.vue
  40. 2 2
      packages/qjkankan-editor/src/components/shared/message/Confirm.vue
  41. 1 37
      packages/qjkankan-editor/src/config/index.js
  42. 0 3
      packages/qjkankan-editor/src/core/utils.js
  43. 53 22
      packages/qjkankan-editor/src/framework/EditorHead.vue
  44. 3 3
      packages/qjkankan-editor/src/framework/MenuPC.vue
  45. 1 1
      packages/qjkankan-editor/src/framework/core/index.vue
  46. 170 22
      packages/qjkankan-editor/src/framework/material/header.vue
  47. 1 1
      packages/qjkankan-editor/src/framework/play/index.vue
  48. 18 8
      packages/qjkankan-editor/src/framework/play/pano/components/list.vue
  49. 6 6
      packages/qjkankan-editor/src/framework/play/pano/index.vue
  50. 140 62
      packages/qjkankan-editor/src/lang/_en.js
  51. 862 0
      packages/qjkankan-editor/src/lang/_en.json
  52. 73 13
      packages/qjkankan-editor/src/lang/_zh.js
  53. 873 0
      packages/qjkankan-editor/src/lang/_zh.json
  54. 2 2
      packages/qjkankan-editor/src/lang/index.js
  55. 8 25
      packages/qjkankan-editor/src/mixins/index.js
  56. 2 0
      packages/qjkankan-editor/src/pages/Edit.vue
  57. 1 0
      packages/qjkankan-editor/src/pages/Material.vue
  58. 2 0
      packages/qjkankan-editor/src/pages/material.js
  59. 3 0
      packages/qjkankan-editor/src/pages/show.js
  60. 2 0
      packages/qjkankan-editor/src/pages/vr.js
  61. 4 1
      packages/qjkankan-editor/src/router/editorRouter.js
  62. 1 1
      packages/qjkankan-editor/src/router/index.js
  63. 1 1
      packages/qjkankan-editor/src/router/material.js
  64. 3 1
      packages/qjkankan-editor/src/utils/other.js
  65. 32 39
      packages/qjkankan-editor/src/utils/request.js
  66. 11 12
      packages/qjkankan-editor/src/views/base/Toolbar.vue
  67. 154 118
      packages/qjkankan-editor/src/views/base/customButtonSettings.vue
  68. 6 8
      packages/qjkankan-editor/src/views/base/customLogoSettings.vue
  69. 11 11
      packages/qjkankan-editor/src/views/base/customMaskSettings.vue
  70. 3 3
      packages/qjkankan-editor/src/views/base/openingAnimationSettings.vue
  71. 14 13
      packages/qjkankan-editor/src/views/base/openingTipSettings.vue
  72. 2 2
      packages/qjkankan-editor/src/views/base/passwordSettings.vue
  73. 7 7
      packages/qjkankan-editor/src/views/explanation/explanationSettings.vue
  74. 66 64
      packages/qjkankan-editor/src/views/hotspot/EditPanel.vue
  75. 15 15
      packages/qjkankan-editor/src/views/hotspot/HotSpotList.vue
  76. 4 3
      packages/qjkankan-editor/src/views/hotspot/hotspotType/audio.vue
  77. 4 4
      packages/qjkankan-editor/src/views/hotspot/hotspotType/image.vue
  78. 2 2
      packages/qjkankan-editor/src/views/hotspot/hotspotType/link.vue
  79. 3 2
      packages/qjkankan-editor/src/views/hotspot/hotspotType/scene.vue
  80. 1 1
      packages/qjkankan-editor/src/views/hotspot/hotspotType/textarea.vue
  81. 3 3
      packages/qjkankan-editor/src/views/hotspot/hotspotType/video.vue
  82. 11 11
      packages/qjkankan-editor/src/views/material/audio/index.vue
  83. 11 11
      packages/qjkankan-editor/src/views/material/image/index.vue
  84. 62 107
      packages/qjkankan-editor/src/views/material/pano/index.vue
  85. 7 7
      packages/qjkankan-editor/src/views/material/popup/cover.vue
  86. 7 7
      packages/qjkankan-editor/src/views/material/popup/imagePreviewer.vue
  87. 6 6
      packages/qjkankan-editor/src/views/material/popup/panoImagePreviewer.vue
  88. 4 4
      packages/qjkankan-editor/src/views/material/popup/rename.vue
  89. 4 4
      packages/qjkankan-editor/src/views/material/popup/share.vue
  90. 2 1
      packages/qjkankan-editor/src/views/material/style.less
  91. 12 12
      packages/qjkankan-editor/src/views/material/video/index.vue
  92. 56 39
      packages/qjkankan-editor/src/views/material/works/index.vue
  93. 18 17
      packages/qjkankan-editor/src/views/navigation/groupSettings.vue
  94. 9 8
      packages/qjkankan-editor/src/views/navigation/initialSceneSettings.vue
  95. 2 2
      packages/qjkankan-editor/src/views/screen/Setting.vue
  96. 1 1
      packages/qjkankan-kankan-view/.env
  97. 21 0
      packages/qjkankan-kankan-view/.env.eurprod
  98. 21 0
      packages/qjkankan-kankan-view/.env.eurtestprod
  99. 2 0
      packages/qjkankan-kankan-view/package.json
  100. 0 0
      packages/qjkankan-kankan-view/public/smg.html

+ 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=

+ 0 - 5
packages/qjkankan-editor/.env.bendi

@@ -1,5 +0,0 @@
-VUE_APP_MAIN_COLOR=''
-VUE_APP_STATIC_DIR=static
-VUE_APP_CDN=https://ossxiaoan.4dage.com
-VUE_APP_PROXY_URL='http://192.168.0.135:8001/'
-VUE_APP_URL_FILL='/'

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

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

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

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

+ 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

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

@@ -0,0 +1,7 @@
+VUE_APP_MAIN_COLOR=''
+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

+ 5 - 1
packages/qjkankan-editor/package.json

@@ -6,10 +6,14 @@
     "serve": "vue-cli-service serve",
     "serve-prod": "vue-cli-service serve --mode prod",
     "serve-testprod": "vue-cli-service serve --mode testprod",
-    "serve-local": "vue-cli-service serve --mode bendi",
+    "serve-testdev": "vue-cli-service serve --mode testdev",
+    "serve-eurdev": "vue-cli-service serve --mode eurdev",
+    "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",
+    "build-eurprod": "vue-cli-service build --mode eurprod",
     "lint": "vue-cli-service lint"
   },
   "dependencies": {

+ 1 - 1
packages/qjkankan-editor/public/edit.html

@@ -16,7 +16,7 @@
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/scrollbar/perfect-scrollbar.css"/>
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/swiper/swiper.min.css" />
 
-    <title>四维全景编辑器</title>
+    <title>-</title>
   </head>
   <body>
     <div id="app"></div>

+ 1 - 1
packages/qjkankan-editor/public/material.html

@@ -15,7 +15,7 @@
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/tooltipster/tooltipster.bundle.min.css"/>
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/tooltipster/tooltipster-sideTip-borderless.min.css"/>
 
-    <title>四维全景</title>
+    <title>-</title>
   </head>
   <body>
     <div id="app"></div>

+ 12 - 2
packages/qjkankan-editor/src/api/index.js

@@ -1,5 +1,6 @@
 import { http,getToken } from '../utils/request'
 import config from '../config'
+import { $waiting } from "@/components/shared/loading";
 
 
 const number = function() {
@@ -123,7 +124,11 @@ export function getUserInfo(ok, no) {
  * @param {*} no 
  */
  export function getSceneList(data, ok, no) {
-    return http.postJson(`${URL_FILL}/manage/work/select/4dkk/${data.workId || number()}`, data, ok, no)
+    $waiting.show()
+    return http.postJson(`${URL_FILL}/manage/work/select/4dkk/${data.workId || number()}`, data, (result)=>{
+        $waiting.hide()
+        return ok(result)
+    }, no)
 }
 
 
@@ -466,11 +471,16 @@ export function setListSort(data, ok, no) {
  * @param {*} no 
  */
  export function getMaterialList(data, ok, no) {
+    
     let url = `${URL_FILL}/manage/fodder/list`
     // if (data.urlSelect) {
     //     url = `${URL_FILL}/manage/fodder/select/${data.type}/${number()}`
     // }
-    return http.postJson(url, data, ok, no)
+    $waiting.show()
+    return http.postJson(url, data, (result)=>{
+        $waiting.hide()
+        return ok(result)
+    }, no)
 }
 
 /**

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 11 - 0
packages/qjkankan-editor/src/assets/images/default/logo_white_en.svg


packages/qjkankan-editor/src/assets/images/default/logo_white.svg → packages/qjkankan-editor/src/assets/images/default/logo_white_zh.svg


BIN
packages/qjkankan-editor/src/assets/images/default/mask_bg_en.png


packages/qjkankan-editor/src/assets/images/default/mask_bg.png → packages/qjkankan-editor/src/assets/images/default/mask_bg_zh.png


BIN
packages/qjkankan-editor/src/assets/images/icons/USA.jpg


BIN
packages/qjkankan-editor/src/assets/images/icons/USA@2x.jpg


BIN
packages/qjkankan-editor/src/assets/images/icons/china.png


BIN
packages/qjkankan-editor/src/assets/images/icons/china@2x.png


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 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
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


+ 1 - 0
packages/qjkankan-editor/src/assets/style/component.less

@@ -93,6 +93,7 @@ textarea:-ms-input-placeholder {
     position: absolute;
     left: 50%;
     transform: translateX(-50%);
+    white-space: nowrap;
     top: -46px;
     color: #fff;
     pointer-events: none;

+ 1 - 0
packages/qjkankan-editor/src/assets/style/style.pc.editor.less

@@ -89,6 +89,7 @@ textarea:-ms-input-placeholder {
     transform: translateX(-50%);
     top: -46px;
     color: #fff;
+    white-space: nowrap;
     pointer-events: none;
     text-align: center;
     word-break: keep-all;

+ 92 - 91
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,14 +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"
-        :key="currentMaterialType"
+        <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
@@ -547,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>
@@ -683,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;
@@ -703,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;
@@ -1000,7 +999,8 @@ 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_0,h_0,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;
@@ -1114,7 +1114,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);
@@ -1124,7 +1124,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);
@@ -1139,7 +1139,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);
@@ -1148,7 +1148,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);
@@ -1160,7 +1160,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: '',
@@ -1175,7 +1175,7 @@ export default {
             uid: itemInUploadList.uid,
           },
           (response) => { // 上传成功
-            itemInUploadList.statusText = '正在切图处理'
+            itemInUploadList.statusText = this.$i18n.t(`gather.cutting`)
             itemInUploadList.ifKnowProgress = false
             itemInUploadList.backendId = response.data.id
           },
@@ -1189,7 +1189,7 @@ export default {
             } else {
               console.log('失败!');
               itemInUploadList.status = 'FAIL'
-              itemInUploadList.statusText = '素材上传失败'
+              itemInUploadList.statusText = this.$i18n.t(`gather.material_upload_fail`)
             }
           },
           (progress) => {
@@ -1211,7 +1211,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);
@@ -1221,7 +1221,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);
@@ -1233,7 +1233,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,
@@ -1268,7 +1268,7 @@ export default {
             } else {
               console.log('失败!');
               itemInUploadList.status = 'FAIL'
-              itemInUploadList.statusText = '素材上传失败'
+              itemInUploadList.statusText = this.$i18n.t(`gather.material_upload_fail`)
             }
           },
           (progress) => {
@@ -1285,7 +1285,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);
@@ -1295,7 +1295,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);
@@ -1307,7 +1307,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,
         };
@@ -1342,7 +1342,7 @@ export default {
             } else {
               console.log('上传失败');
               itemInUploadList.status = 'FAIL'
-              itemInUploadList.statusText = '素材上传失败'
+              itemInUploadList.statusText = this.$i18n.t(`gather.material_upload_fail`)
             }
           },
           (progress) => {
@@ -1359,7 +1359,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);
@@ -1369,7 +1369,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);
@@ -1381,7 +1381,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,
         };
@@ -1402,7 +1402,8 @@ export default {
             result.data.fileSize = changeByteUnit(Number(result.data.fileSize));
             result.data.createTime = result.data.createTime.substring(0, result.data.createTime.length - 3)
             result.data.updateTime = result.data.updateTime.substring(0, result.data.updateTime.length - 3)
-            result.data.icon = result.data.ossPath + '?x-oss-process=video/snapshot,t_0,f_jpg,w_0,h_0,m_fast,ar_auto';
+            result.data.icon = process.env.VUE_APP_ORIGIN=='aws'?result.data.icon:(result.data.ossPath + '?x-oss-process=video/snapshot,t_0,f_jpg,w_89,h_50,m_fast,ar_auto');
+
             this.uploadStatusListVideo[index].status = 'SUCCESS'
             this.uploadStatusListVideo[index].successInfo = result.data
           },
@@ -1414,7 +1415,7 @@ export default {
               this.uploadStatusListVideo.splice(index, 1)
             } else {
               itemInUploadList.status = 'FAIL'
-              itemInUploadList.statusText = '素材上传失败'
+              itemInUploadList.statusText = this.$i18n.t(`gather.material_upload_fail`)
             }
           },
           (progress) => {
@@ -1442,7 +1443,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) {
@@ -1524,7 +1525,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()
         }
@@ -1766,17 +1767,17 @@ 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) {
-    width: calc(416px - 316px);
+    width: calc(380px - 316px);
   }
   &:nth-of-type(5) {
-    width: calc(100% - 416px);
+    width: calc(100% - 380px);
   }
 }
 
@@ -1806,14 +1807,14 @@ export default {
     }
   }
   &:nth-of-type(2) {
-    width: calc(116px - 50px);
+    width: calc(146px - 50px);
   }
   &:nth-of-type(3) {
-    width: calc(416px - 116px);
+    width: calc(380px - 146px);
     padding-right: 30px;
   }
   &:nth-of-type(4) {
-    width: calc(100% - 416px);
+    width: calc(100% - 380px);
   }
 }
 
@@ -1843,14 +1844,14 @@ export default {
     }
   }
   &:nth-of-type(2) {
-    width: calc(116px - 50px);
+    width: calc(146px - 50px);
   }
   &:nth-of-type(3) {
-    width: calc(416px - 116px);
+    width: calc(380px - 146px);
     padding-right: 30px;
   }
   &:nth-of-type(4) {
-    width: calc(100% - 416px);
+    width: calc(100% - 380px);
   }
 }
 
@@ -1880,14 +1881,14 @@ export default {
     }
   }
   &:nth-of-type(2) {
-    width: calc(116px - 50px);
+    width: calc(146px - 50px);
   }
   &:nth-of-type(3) {
-    width: calc(416px - 116px);
+    width: calc(380px - 146px);
     padding-right: 30px;
   }
   &:nth-of-type(4) {
-    width: calc(100% - 416px);
+    width: calc(100% - 380px);
   }
 }
 
@@ -1917,14 +1918,14 @@ export default {
     }
   }
   &:nth-of-type(2) {
-    width: calc(116px - 50px);
+    width: calc(146px - 50px);
   }
   &:nth-of-type(3) {
-    width: calc(416px - 116px);
+    width: calc(380px - 146px);
     padding-right: 30px;
   }
   &:nth-of-type(4) {
-    width: calc(100% - 416px);
+    width: calc(100% - 380px);
   }
 }
 

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 220 - 203
packages/qjkankan-editor/src/components/materialSelectorForManageCenter.vue


+ 20 - 20
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,14 +401,14 @@ 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(380px - 146px);
     padding-right: 30px;
   }
   &:nth-of-type(4) {
-    width: calc(100% - 416px);
+    width: calc(100% - 380px);
   }
 }
 
@@ -419,14 +419,14 @@ 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(380px - 146px);
     padding-right: 30px;
   }
   &:nth-of-type(4) {
-    width: calc(100% - 416px);
+    width: calc(100% - 380px);
   }
 }
 

+ 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);

+ 3 - 2
packages/qjkankan-editor/src/components/pulldownMenuInEditor.vue

@@ -1,14 +1,14 @@
 <template>
   <div class="pull-down-menu-in-editor" v-clickoutside="onClickOutside">
     <button class="menu-cover" @click="isExpand = !isExpand">
-      {{placeholder ? placeholder : value}}
+      {{placeholder ? placeholder : $i18n.t(`zh_key.${value}`)}}
       <i class="iconfont icon-material_preview_upload_collect" :class="{flip: isExpand}"></i>
     </button>
     <div class="menu" v-show="isExpand">
       <button v-for="(item, index) of valueList" :key="index"
         @click="onSelect(item)"
       >
-        {{item}}
+        {{$i18n.t(`zh_key.${item}`)}}
       </button>
     </div>
   </div>
@@ -47,6 +47,7 @@ export default {
       }
     },
     onSelect(item) {
+      console.log(item,'ads')
       this.isExpand = false
       this.$emit('input', item)
     }

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

@@ -12,7 +12,7 @@
       <div class="minmax">
         <span>
           {{current.min}}{{current.unit}}
-          <span v-if="current.tip"> (不显示)</span>
+          <span v-if="current.tip"> {{$i18n.t('edit_settings.no_display')}}</span>
         </span>
         <span>{{current.max}}{{current.unit}}</span>
       </div>
@@ -39,9 +39,12 @@ export default {
       }
     },
     'current.value': function(n, o) {
-      if (!(this.value.value === this.current.value)) {
+      // console.log(this.current.value,'this.current.value');
+      // console.log(this.value.value,'this.value.value');
+
+      // if (!(this.value.value === this.current.value)) {
         this.$emit('input', this.current)
-      }
+      // }
     },
     value:{
       handler:function name(newVal) {

+ 25 - 13
packages/qjkankan-editor/src/components/sceneGroupInEditor.vue

@@ -22,16 +22,17 @@
       <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="'新增二级分组'"
+          v-tooltip="$i18n.t('navigation.add_two_group')"
           @click.stop="onRequestForAddGroup"
         >
         </i>
         <i
           class="iconfont icon-editor_list_image icon-image"
-          v-tooltip="'新增全景图或三维场景'" 
+          v-tooltip="$i18n.t('navigation.add_pano_or_scene')" 
           @click.stop="onRequestForAddScene"
           v-show="
             level === 2 ||
@@ -40,7 +41,8 @@
               (
                 groupNode.children.length === 0 ||
                 (
-                  groupNode.children.length === 1 && groupNode.children[0].name === '默认二级分组'
+                  groupNode.children.length === 1 && 
+                  (groupNode.children[0].name === '默认二级分组'||groupNode.children[0].name === $i18n.t('navigation.default_group_two'))
                 )
               )
             )
@@ -49,13 +51,13 @@
         </i>
         <i
           class="iconfont icon-editor_list_edit icon-edit"
-          v-tooltip="'重命名'"
+          v-tooltip="$i18n.t('navigation.rename')"
           @click.stop="onClickForRename"
         >
         </i>
         <i
           class="iconfont icon-editor_list_delete icon-delete"
-          v-tooltip="'删除'"
+          v-tooltip="$i18n.t('navigation.delete')"
           @click.stop="onRequestForDelete"
         >
         </i>
@@ -64,7 +66,7 @@
             v-clickoutside="onRequestForCancelDelete"
             @click.stop="onConfirmDelete"
           >
-            删除
+           {{$i18n.t('navigation.delete')}} 
           </div>
         </div>
       </template>
@@ -74,7 +76,7 @@
         v-model.trim="newName"
         ref="input-for-rename"
         maxlength="50"
-        placeholder="输入名字"
+        :placeholder="$i18n.t('navigation.enter_name')"
         @blur="onInputNewNameComplete"
         @keydown.enter="onInputEnter"
         @click.stop
@@ -82,7 +84,8 @@
     </div>
 
     <div class="group-content" v-if="isExpanded">
-      <template v-if="!(groupNode.children.length === 1 && groupNode.children[0].name === '默认二级分组')">
+      <template v-if="!(groupNode.children.length === 1 &&
+       (groupNode.children[0].name === '默认二级分组' || groupNode.children[0].name === $i18n.t('navigation.default_group_two')))">
         <InsertPositionTip
           position-debug="1"
           :indentLevel="level + 1"
@@ -157,7 +160,7 @@
 
     <div class="dialog" style="z-index: 2000" v-if="isShowSelectionWindow">
       <MaterialSelector
-        title="选择素材"
+        :title="$i18n.t('gather.select_material')"
         @cancle="isShowSelectionWindow = false"
         @submit="onSubmitFromMaterialSelector"
         :selectableType="['pano', '3D']"
@@ -250,7 +253,15 @@ export default {
     onClickForRename() {
       this.isRenaming = true
       console.log(this.groupNode.name);
-      this.newName = this.groupNode.name
+
+      if (this.groupNode.name=='默认二级分组') {
+        this.newName = this.$i18n.t('navigation.default_group_two')
+      } else if (this.groupNode.name=='一级分组') {
+        this.newName = this.$i18n.t('navigation.group_one')
+      } else{
+        this.newName = this.groupNode.name
+      }
+
       this.$nextTick(() => {
         // this.$refs['input-for-rename'].focus()
         this.$refs['input-for-rename'].select()
@@ -327,7 +338,8 @@ export default {
         })
         if (temp) {
           setTimeout(() => {
-            this.$msg.message(`${item.type == '4dkk' ? '场景' : '全景图'}${item.sceneTitle}已存在,不可重复添加`)
+            this.$msg.message(
+              `${item.type == '4dkk' ? this.$i18n.t('navigation.scene_name') : this.$i18n.t('navigation.pano')}${this.$i18n.t('navigation.already_exists',{msg:item.sceneTitle})}`)
           }, i * 100)
           allSuccess = false
           return
@@ -337,7 +349,7 @@ export default {
 
       this.isShowSelectionWindow = false
       if (allSuccess) {
-        this.$msg.success("操作成功")
+        this.$msg.success(this.$i18n.t('gather.success'))
       }
     },
     onDragStart(e) {

+ 6 - 6
packages/qjkankan-editor/src/components/sceneInGroupInEditor.vue

@@ -28,18 +28,18 @@
         v-model.trim="newName"
         ref="input-for-rename"
         maxlength="50"
-        placeholder="输入名字"
+        :placeholder="$i18n.t('navigation.enter_name')"
         @blur="onInputNewNameComplete"
         @keydown.enter="onInputEnter"
       />
       <div class="right-bottom">
         <span class="scene-type">{{translateSceneType(sceneInfo.type)}}</span>
         <div class="icons">
-          <i class="iconfont icon-editor_list_edit icon-edit" v-tooltip="'重命名'"
+          <i class="iconfont icon-editor_list_edit icon-edit" v-tooltip="$i18n.t('navigation.rename')"
             @click="onRequestForRename"
           >
           </i>
-          <i class="iconfont icon-editor_list_delete icon-delete" v-tooltip="'删除'"
+          <i class="iconfont icon-editor_list_delete icon-delete" v-tooltip="$i18n.t('navigation.delete')"
             @click="onRequestForDelete"
           >
           </i>
@@ -51,7 +51,7 @@
         v-clickoutside="onRequestForCancelDelete"
         @click="onConfirmDelete"
       >
-        删除
+        {{$i18n.t('navigation.delete')}}
       </div>
     </div>
   </div>
@@ -94,9 +94,9 @@ export default {
     ossImagePreviewUrlSuffix,
     translateSceneType(type) {
       if (type === 'pano') {
-        return '全景'
+        return this.$i18n.t('navigation.pano')
       } else {
-        return '三维'
+        return this.$i18n.t('navigation.scene')
       }
     },
     onRequestForRename() {

+ 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));

+ 4 - 3
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">
@@ -92,7 +92,8 @@ export default {
 
 <style lang="less" scoped>
 .ui-message {
-  width: 400px;
-  height: 230px;
+    width: 400px;
+    min-width: 400px;
+    height: 230px;
 }
 </style>

+ 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;

+ 0 - 3
packages/qjkankan-editor/src/core/utils.js

@@ -15,7 +15,6 @@ export default class Utils {
     var sceneName = krpano.get('xml.scene');
     var hlookat = krpano.get("view.hlookat");
     var vlookat = krpano.get("view.vlookat");
-    console.log(hlookat, vlookat);
     return {
       sceneName,
       hlookat,
@@ -86,8 +85,6 @@ export default class Utils {
     krpano.call("screentosphere(curscreen_x, curscreen_y, curscreen_ath, curscreen_atv);");
     let ath = krpano.get("curscreen_ath");
     let atv = krpano.get("curscreen_atv");
-    console.log(param.hotspotTitle,'param.hotspotTitle');
-    console.log(param.name,'param.name');
     krpano.call(`addImgTextHotSpot(
       ${param.img},
       ${param.name},

+ 53 - 22
packages/qjkankan-editor/src/framework/EditorHead.vue

@@ -1,20 +1,22 @@
 <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}}
+      {{ back_myworks }}
     </a>
     <span class="app-head-title">{{ info.name }}</span>
-    <div class="app-head-save ui-button deepcancel app-head-view" @click="onView" :class="{ disable: !canLoad || isEditing }">
+    <div class="app-head-save ui-button deepcancel app-head-view" @click="onView"
+      :class="{ disable: !canLoad || isEditing }">
       <i class="iconfont iconeditor_preview"></i>
-      {{preview}}
+      {{ preview }}
     </div>
 
     <div class="ui-button submit app-head-save" @click="onSave" :class="{ disable: !canLoad || isEditing }">
       <i class="iconfont iconeditor_save"></i>
-      {{savetips}}
+      {{ savetips }}
     </div>
-    <preview v-if="info" :key="Math.random()" :name="info.name" :show="showPreview" :ifr="`./show.html?id=${info.id}&rnd=${Math.random()}`" @close="showPreview = false" />
+    <preview v-if="info" :key="Math.random()" :name="info.name" :show="showPreview"
+      :ifr="`./show.html?id=${info.id}&lang=${$lang}&rnd=${Math.random()}`" @close="showPreview = false" />
   </header>
 </template>
 <script>
@@ -22,7 +24,8 @@ import { saveWorks, getPanoInfo, checkLogin } from "@/api";
 import { mapGetters } from "vuex";
 // import config from '@/config'
 import preview from "@/components/preview";
-import {i18n} from "@/lang"
+import { i18n } from "@/lang"
+import { $waiting } from "@/components/shared/loading";
 
 let hhhreg = /\\\\\\\\/g;
 
@@ -68,7 +71,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" });
           },
@@ -98,24 +101,33 @@ export default {
         }
         return item;
       });
+      $waiting.show()
+
       saveWorks(
         {
           password: this.info.password,
           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: "至少添加一个场景才可预览,请前往“场景导航”添加",
-              });
-            }
-            this.showPreview = true;
-          }, 500);
+          this.getInfo().then((res) => {
+            // getInfo里调用了后端接口,底层用了jquery的网络请求方法,为啥会导致promise嵌套没有展平,res拿到的不是promise 对象的resolve值而是promise对象本身????
+            res.then(() => {
+              this.$store.commit("UpdateIsShowState", true);
+              $waiting.hide()
+              setTimeout(() => {
+                if (this.info.scenes.length <= 0 && this.isShow) {
+                  return this.$alert({
+                    content: this.$i18n.t('gather.at_least_one_scene'),
+                  });
+                }
+                this.showPreview = true;
+              }, 500);
+            })
+          });
+
+
         }
       );
     },
@@ -143,6 +155,7 @@ export default {
         }
         return item;
       });
+      $waiting.show()
 
       saveWorks(
         {
@@ -150,28 +163,41 @@ 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);
           this.$store.commit("TakeInfoSnapShotAtSave")
         },
-        () => {}
+        () => { }
       );
     },
     getInfo() {
       return checkLogin().then((res) => {
         return new Promise((resolve, reject) => {
+          $waiting.hide()
+
           if (res.code == 0) {
+            $waiting.show()
             getPanoInfo("", (data) => {
               this.$store.commit("SetInfo", data);
               this.$store.commit("scene/setScenes", data.scenes);
+              $waiting.hide()
 
               let firstScene = "";
 
               if (data.firstScene) {
                 firstScene = data.scenes.find((item) => item.sceneCode == data.firstScene.sceneCode);
               }
+
+              //判断列表里是否有全景图
+              if (data.scenes.some(item => item.type == 'pano') && firstScene && firstScene.type == '4dkk') {
+                console.log(this.currentScene.sceneCode);
+                //如果当前有选中场景,则激活选中场景,无则显示第一个全景图
+                firstScene = this.currentScene.sceneCode ? this.currentScene : data.scenes.find(item => item.type == 'pano')
+              }
+
+              console.log(firstScene, 'firstScene');
               this.$store.commit("scene/setCurrentScene", firstScene || data.scenes[0]);
 
               // 查询初始场景的所在1级分组
@@ -203,6 +229,7 @@ export default {
   height: 60px;
   position: relative;
 }
+
 .app-head-back {
   color: white;
   display: flex;
@@ -212,10 +239,12 @@ export default {
   left: 24px;
   top: 50%;
   transform: translateY(-50%);
-  > i {
+
+  >i {
     margin-right: 15px;
   }
 }
+
 .app-head-title {
   position: absolute;
   left: 50%;
@@ -224,6 +253,7 @@ export default {
   font-size: 16px;
   color: white;
 }
+
 .app-head-save {
   cursor: pointer;
   display: flex;
@@ -233,6 +263,7 @@ export default {
   top: 50%;
   transform: translateY(-50%);
   right: 10px;
+
   i {
     font-size: 14px;
     margin-right: 4px;

+ 3 - 3
packages/qjkankan-editor/src/framework/MenuPC.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="pc-menu" app-border dir-right>
+  <div class="pc-menu" :style="`width:${$i18n.t('style_key.menu_width')}`" app-border dir-right>
     <ul class="pc-menu-container">
       <li v-for="(item, key) in menu" v-show="!item.hidden" :class="{disable:key!=0&&!isShow}" :key="key">
         <router-link :to="item.link" :exact="false">
@@ -10,8 +10,8 @@
       </li>
     </ul>
 
-    <a class="help" href="https://docs.4dkankan.com/#/product/4dpano/zh-cn/README" target="_blank">
-      <img v-tooltip="'帮助中心'"  :src="require(`@/assets/images/icons/help_tips.png`)" alt="">
+    <a class="help" :href="$lang=='en'?'https://docs.4dkankan.com/#/product/4dpano/en-us/README':'https://docs.4dkankan.com/#/product/4dpano/zh-cn/README'" target="_blank">
+      <img v-tooltip="$i18n.t('edit_settings.help_center')"  :src="require(`@/assets/images/icons/help_tips.png`)" alt="">
     </a>
 
   </div>

+ 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);
           }
         });

+ 170 - 22
packages/qjkankan-editor/src/framework/material/header.vue

@@ -1,14 +1,30 @@
 <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">
+        <li @click="handleItem(item)" :class="{ active: active.id == item.id }" v-for="(item, i) in tab" :key="i">
           {{ item.name }}
         </li>
       </ul>
+
+      <div class="language-w">
+        <div class="list">
+          <a class="header-item" :class="{ 'is-hover': showLangList }" @touchstart="showLangList = !showLangList">
+            <p class="guoqi" :style="{ 'background-image': `url(${languageObj.img})` }">
+              {{ languageObj.name }}
+            </p>
+            <ul class="child-list">
+              <li v-for="item in languageList" :key="item.name" :style="{ 'background-image': `url(${item.img})` }"
+                @click="changeLanguage(item.value)">{{ item.name }}</li>
+            </ul>
+          </a>
+        </div>
+        <!-- <span class="language en" :class="{'is-active': language === 'en'}" @click="changeLanguage('en')">EN</span>
+          <span class="language" :class="{'is-active': language !== 'en'}" @click="changeLanguage('zh')">中</span> -->
+      </div>
       <user-info class="user-info"></user-info>
     </div>
   </div>
@@ -16,7 +32,7 @@
 
 <script>
 import UserInfo from "@/components/userInfo.vue";
-import {i18n} from "@/lang"
+import { i18n } from "@/lang"
 
 export default {
   components: {
@@ -24,37 +40,63 @@ export default {
   },
   data() {
     return {
-      active:{},
+      homeLink: process.env.VUE_APP_PROXY_URL_ROOT,
+      langauge: localStorage.getItem('language'),
+      languageList: [
+        {
+          name: '简体中文',
+          img: require('@/assets/images/icons/china@2x.png'),
+          value: 'zh'
+        },
+        {
+          name: 'English',
+          img: require('@/assets/images/icons/USA@2x.jpg'),
+          value: 'en'
+        }
+      ],
+      showLangList: false,
+      active: {},
       tab: [
         {
           name: i18n.t("gather.my_works"),
           id: "works",
-          path:{
-            path:'/works'
+          path: {
+            path: '/works'
           }
         },
         {
           name: i18n.t("gather.my_material"),
           id: "material",
-          path:{
-            path:'/'
+          path: {
+            path: '/pano'
           }
         }
       ],
     };
   },
-  watch:{
-    '$route.meta':{
-      deep:true,
-      handler:function (newVal) {
-        this.active  = this.tab.find(item=>{
-          return item.id == newVal.belong 
+  computed: {
+    languageObj() {
+      console.log(i18n.locale);
+      return this.languageList.find(item => item.value === i18n.locale)
+    },
+  },
+  watch: {
+    '$route.meta': {
+      deep: true,
+      handler: function (newVal) {
+        this.active = this.tab.find(item => {
+          return item.id == newVal.belong
         })
       }
     }
   },
-  methods:{
-    handleItem(item){
+  methods: {
+    changeLanguage(lang) {
+      let arr = location.href.split('#/')
+      location.href = `material.html?lang=${lang}#/${arr[1]}`
+      localStorage.language = lang
+    },
+    handleItem(item) {
       this.$router.push(item.path)
     }
   }
@@ -69,6 +111,7 @@ export default {
   top: 0;
   left: 0;
   z-index: 999;
+
   .con {
     color: #000;
     max-width: 1280px;
@@ -78,31 +121,37 @@ export default {
     margin: 0 auto;
     position: relative;
     padding: 0;
+
     .logo {
       font-size: 24px;
       font-weight: bold;
       height: 100%;
-      >img{
+
+      >img {
         height: 100%;
         vertical-align: middle;
       }
     }
+
     .tab {
       display: flex;
       align-items: center;
       margin-left: 116px;
-      > li {
+
+      >li {
         cursor: pointer;
         margin-right: 50px;
         text-align: left;
         font-size: 16px;
         color: #909090;
-        &.active{
+
+        &.active {
           font-size: 16px;
           font-weight: bold;
           color: #0076F6;
           position: relative;
-          &::before{
+
+          &::before {
             content: '';
             width: 20px;
             height: 2px;
@@ -116,8 +165,107 @@ export default {
         }
       }
     }
-    .user-info {
+
+    .language-w {
       margin-left: auto;
+      .list{
+        height: 100%;
+        display: flex;
+      }
+
+      .header-item {
+        margin-right: 20px !important;
+
+        &:hover,
+        &.is-hover {
+          position: relative;
+          color: #202020;
+
+          .child-list {
+            display: block;
+          }
+        }
+
+        p {
+          color: #323233;
+          font-size: 14px;
+          font-weight: normal;
+          cursor: pointer;
+          background: url(~@/assets/images/icons/china.png) no-repeat left center;
+          background-size: 20px 14px;
+          padding: 10px 0 10px 28px;
+
+          .iconfont {
+            font-size: 10px;
+            color: rgb(144, 144, 144);
+          }
+
+        }
+
+        &:hover p .iconfont::before {
+          content: "\E744";
+        }
+      }
+
+      .child-list {
+        position: absolute;
+        // width: 112px;
+        box-shadow: 0px -2px 6px rgba(113, 113, 113, 0.16);
+        margin-top: 0;
+        left: 50%;
+        transform: translateX(-50%);
+        z-index: 0;
+        display: none;
+        transition: all linear 0.5s;
+        padding-top: 6px;
+        background: #fff;
+
+        &::before {
+          position: absolute;
+          display: block;
+          top: -5px;
+          left: 50%;
+          margin-left: -2px;
+          width: 0;
+          height: 0px;
+          content: '';
+          background: #fff;
+          border-style: solid;
+          border-width: 4px;
+          border-color: #fff #fff transparent transparent;
+          transform: rotate(-45deg);
+          box-shadow: 1px -1px 0px rgba(113, 113, 113, 0.16);
+          z-index: 1;
+        }
+
+        li {
+          height: 48px;
+          line-height: 48px;
+          font-size: 16px;
+          text-align: center;
+          position: relative;
+          background: #fff;
+          cursor: pointer;
+          z-index: 2;
+          padding: 0 25px;
+          white-space: nowrap;
+          color: #909090;
+          font-size: 14px;
+          font-weight: normal;
+          padding: 0 13px 0 40px;
+          background: url(~@/assets/images/icons/china.png) no-repeat 13px center;
+          background-size: 20px 14px;
+
+          &:hover {
+            background-color: #EBEBEB;
+            color: #202020;
+          }
+        }
+      }
+
+    }
+
+    .user-info {
       margin-right: 0;
     }
   }

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

@@ -4,7 +4,7 @@
     ref="layer"
     :class="{showPlayer:$route.meta.hasPreviewArea}"
     :style="{
-      left: $route.meta.previewAreaExtraLeft + 58 + 'px',
+      left: $route.meta.previewAreaExtraLeft + Number($i18n.t('style_key.play_width')||0) + 58 + 'px',
     }"
   >
     <pano />

+ 18 - 8
packages/qjkankan-editor/src/framework/play/pano/components/list.vue

@@ -8,7 +8,7 @@
        id="swScenes" ref="sw"
         v-swiper:mySwiper="swiperOptions" v-if="currentScenesList.length > 0">
         <ul class="swiper-wrapper">
-          <li v-tooltip="item.type === '4dkk' ? '请前往四维时代个人中心编辑场景' : ''" @click="tabCurrentScene(item)"
+          <li v-tooltip="item.type === '4dkk' ? $i18n.t('navigation.scene_edit_tips') : ''" @click="tabCurrentScene(item)"
             class="swiper-slide" :class="{
               active: currentScene.id == item.id,
               loopspan: item.sceneTitle.length > spanlength && currentScene.id == item.id,
@@ -26,14 +26,14 @@
       </div>
 
       <div class="swiper-container" :style="`width:${secondaryW}px`" id="swSecondary" ref="sw1"
-        v-swiper:mySwipera="swiperOptions" v-if="!(secondaryList.length === 1 && secondaryList[0].name === '默认二级分组')">
+        v-swiper:mySwipera="swiperOptions" v-if="!(secondaryList.length === 1 && (secondaryList[0].name === '默认二级分组'||secondaryList[0].name === $i18n.t('navigation.default_group_two')))">
         <ul class="swiper-wrapper">
           <li class="swiper-slide" @click="tabSecondary(item)" :class="{
             active: currentSecondary.id == item.id,
-            loopspan: item.name.length > spanlength && currentSecondary.id == item.id,
+            loopspan: fixTitle(item.name).length > spanlength && currentSecondary.id == item.id,
           }" v-for="(item, i) in secondaryList" :key="i">
-            <span v-if="currentSecondary.id == item.id">{{ item.name }}</span>
-            <span v-else>{{ item.name.length > spanlength ? item.name.slice(0, spanlength) : item.name }}</span>
+            <span v-if="currentSecondary.id == item.id">{{ fixTitle(item.name) }}</span>
+            <span v-else>{{ fixTitle(item.name).length > spanlength ? fixTitle(item.name).slice(0, spanlength) : fixTitle(item.name) }}</span>
           </li>
         </ul>
       </div>
@@ -45,10 +45,10 @@
       <ul class="swiper-wrapper" v-if="metadata.catalogRoot.length > 1">
         <li class="swiper-slide" :class="{
           active: currentCatalogRoot.id == item.id,
-          loopspan: item.name.length > spanlength && currentCatalogRoot.id == item.id,
+          loopspan: fixTitle(item.name).length > spanlength && currentCatalogRoot.id == item.id,
         }" @click="tabRoot(item)" v-for="(item, i) in metadata.catalogRoot" :key="i">
-          <span v-if="currentCatalogRoot.id == item.id">{{ item.name }}</span>
-          <span v-else>{{ item.name.length > spanlength ? item.name.slice(0, spanlength) : item.name }}</span>
+          <span v-if="currentCatalogRoot.id == item.id">{{ fixTitle(item.name) }}</span>
+          <span v-else>{{ fixTitle(item.name).length > spanlength ? fixTitle(item.name).slice(0, spanlength) : fixTitle(item.name) }}</span>
         </li>
       </ul>
     </div>
@@ -136,6 +136,16 @@ export default {
     },
   },
   methods: {
+    fixTitle(name){
+      if (name=='默认二级分组') {
+        name = this.$i18n.t('navigation.default_group_two')
+      } else if (name=='一级分组') {
+        name = this.$i18n.t('navigation.group_one')
+      } else{
+        name = name
+      }
+      return name
+    },
     loadList() {
       this.$nextTick(() => {
         // let t = setTimeout(() => {

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

@@ -7,15 +7,15 @@
     </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">将当前视角设为初始画面</button>
+      <button class="ui-button submit set-initial-view" :class="{disable: currentScene.type === '4dkk',}" @click="onClick">{{$i18n.t('screen.setting_screen')}}</button>
     </template>
 
     <div class="btn-4dkk-tip" v-if="currentScene.type ==='4dkk'">
       <img src="@/assets/images/default/empty-go-4dkk.png" alt="" draggable="false">
-      <div>请前往四维时代个人中心编辑场景~</div>
-      <button class="ui-button submit" @click="onClickGo4dkk">立即前往</button>
+      <div>{{$i18n.t('navigation.scene_edit_tips')}}~</div>
+      <button class="ui-button submit" @click="onClickGo4dkk">{{$i18n.t('navigation.go_scene_editor')}}</button>
     </div>
   </div>
 </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() {

+ 140 - 62
packages/qjkankan-editor/src/lang/_en.js

@@ -235,7 +235,7 @@ module.exports = {
             "save": "Save current settings",
             "hide": "Hide the spot",
             "show": "Show the spot",
-            "pano_tips":"Tip: You hide the initial point, so you can't roam in this scene."
+            "pano_tips": "Tip: You hide the initial point, so you can't roam in this scene."
         },
         "model": {
             "__name": "修整模型",
@@ -527,74 +527,152 @@ module.exports = {
     },
     "material": {
         "works": {
-            "my":"我的作品",
-            "create":"创建作品",
-            "search":"搜索作品",
-            "preview":"预览",
-            "edit":"编辑",
-            "share":"分享",
-            "delete":"删除",
-            "no_works":"您还没有作品,请先创建作品~",
-            "work_link":"作品链接",
-            "work_qrCode":"作品二维码",
-            "download_qrCode":"下载二维码",
-            "copy_link":"复制链接",
-            "work_preview":"全景作品预览",
-            "new_blank":"新窗口打开",
-            "cancel":"取消",
+            "my": "My Project",
+            "create": "Create the project",
+            "search": "Search",
+            "preview": "Preview",
+            "edit": "Edit",
+            "share": "Share",
+            "delete": "Delete",
+            "no_works": "No results found; you do not yet have a project; please create one first~",
+            "work_link": "Project link",
+            "work_qrCode": "Project QR Code",
+            "download_qrCode": "Download the QR code",
+            "copy_link": "Copy link",
+            "work_preview": "Project Preview",
+            "new_blank": "Open in a new window",
+            "cancel": "Cancel",
         },
     },
-    "gather":{
-        "select_material":"选择素材",
-        "no_title":"无标题",
-
-        "my_works":"我的作品",
-        "my_material":"我的素材",
+    "gather": {
+        "select_material": "Select the material",
+        "no_title": "No title",
+        "my_works": "My Project",
+        "my_material": "My Material",
+        "panorama": "Panorama",
+        "image": "Pictures",
+        "audio": "Audio",
+        "video": "Video",
+        "scene": "3D Scene",
+        "keywords": "Enter keywords",
+        "how_to_shoot": "How to shoot a 3D scene?",
+        "pano_size": "Support 2:1 jpg files ≤ 120MB",
+        "cancel": "Cancel",
+        "comfirm": "Confirm",
+        "pano_fail": "Format error. Support 2:1 jpg files ≤ 120MB",
+        "pano_limit": "The file is too large. Support 2:1 jpg files ≤ 120MB",
+        "edit_cover": "Thumbnail Settings",
+        "img_fail": "Format error.Support jpg/png files: ≤ 10MB",
+        "img_limit": "The file is too large.Support jpg/png files: ≤ 10MB",
+        "img_size": "Support jpg/png files: ≤ 10MB",
+        "audio_size": "Support MP3 files: ≤ 20MB",
+        "audio_limit": "The file is too large. Support MP3 files: ≤ 20MB",
+        "audio_fail": "Format error. Support MP3 files: ≤ 20MB",
+        "upload_material": "Upload material",
+        "video_size": "Support MP4 files: ≤ 200MB",
+        "video_limit": "The file is too large.Support MP4 files: ≤ 200MB",
+        "video_fail": "Format error. Support MP4 files: ≤ 200MB",
+        "serch_material": "Search",
+        "rename": "Rename",
+        "delete": "Delete",
+        "no_serch_result": "No resulrs found",
+        "no_material_result": "No materials found",
+        "had_load": "{msg} pieces of data have been loaded",
+        "uploading": "Uploading {msg}"
+    },
+    "personal_center": {
+        "personal_center": "Personal Center",
+        "logout": "Log out",
+        "login": "Login",
+        "register": "Sign up",
+    },
+    "edit_page": {
+        "back_myworks": "Back",
+        "preview": "Preview",
+        "settings": "Basic Settings",
+        "navigation": "Navigation",
+        "viewpoint": "Starting Screen",
+        "hotspot": "Hotspots",
+        "explanation": "Voice Guide",
+        "save": "Save",
+    },
+    "edit_settings": {
+        "auto_pano": "Walkthrough",
+        "enter_auto": "Enter the walkthrough panorama mode (takes 3 mins to complete per walkthrough)",
+        "set_bgm": "Set the BGM",
+        "add_audio": "Add the audio",
+        "change_audio": "Change the audio",
+        "custom_button": "Custom Button",
+        "custom_button_tips": "Custom buttons provide contact info, website URLs, etc. to a project, which can subsequently be made visible and displayed as well.",
+        "edit": "Edit",
+        "hide": "Hide",
+        "show": "Display",
+        "button_name": "Button name",
+        "button_placeholder": "Please enter the button name",
+        "please_input": "Please enter",
+        "phone": "Phone",
+        "link": "URL Address",
+        "phone_short": "Tel",
+        "link_short": "Link",
+        "custom_logo": "Custom Logo",
+        "show_logo": "Display Logo",
+        "logo_size": "300*300 pixels, within 600kb, <br>jpg/png format support",
+        "mask_setting": "Mask Settings",
+        "sky_mask": "Top mask",
+        "sky_tips": "The top mask is exhibited at the scene's top, while the bottom mask is presented at the scene's bottom.",
+        "mask_setting": "Mask Settings",
+        "mask_size": "500*500 pixels, <br>jpg/png format support",
+        "bottom_mask": "Bottom mask",
+        "opening_setting": "Set the animations",
+        "opening_tips_setting": "Notifications Settings",
+        "opening_tips": "The notifications only apply to panoramic images. The following notifications are inapplicable if the start screen is a 3D model.",
+        "pc": "PC",
+        "mobile": "Mobile",
+        "select_image": "Select pictures",
+        "opening_size": "Recommend 300*300 pixels, within 600kb, jpg/png format support",
+        "show_setting": "Display settings",
+        "first_notice": "Prompt only when the link is opened for the first time",
+        "password_setting": "Set an access code",
+        "password_placeholder": "Please enter the access password, limited to 20-character",
+        "base_setting": "Basic Settings",
+        "setting_cover": "Thumbnail Settings",
+        "cover_size": "512*512px, support jpg/png format",
+        "title": "Title",
+        "description": "Description",
+        "work_placeholder": "Please enter the project title",
+        "intro_placeholder": "Please input no more than 500 words of text content.",
 
 
- 
-        "panorama":"全景图",
-        "image":"图片",
-        "audio":"音频",
-        "video":"视频",
-        "scene":"三维场景",
-        "keywords":"输入关键词",
-        "how_to_shoot":"如何拍摄三维场景",
-        "pano_size":"请上传2:1、120MB以内、jpg格式的图片",
-        "cancel":"取消",
-        "comfirm":"确定",
+        "help_center":"帮助中心",
+        "display_time":"显示时间",
+        "no_display":"(不显示)",
+        "second":"秒",
 
-        "pano_fail":"格式错误,请上传2:1、120MB以内、jpg格式的全景图片",
-        "pano_limit":"过大,请上传2:1、120MB以内、jpg格式的全景图片",
-        "edit_cover":"编辑封面",
 
-        "img_fail":"格式错误,请上传10MB以内、jpg/png格式的图片",
-        "img_limit":"过大,请上传10MB以内、jpg/png格式的图片",
-        "img_size":"请上传10MB以内、jpg/png格式的图片",
-        
- 
-        "audio_size":"请上传20MB以内、mp3格式的音频",
-        "audio_limit":"过大,请上传20MB以内、mp3格式的音频",
-        "audio_fail":"格式错误,请上传20MB以内、mp3格式的音频",
-       
+    },
 
-        "upload_material":"上传素材",
-        "video_size":"请上传200MB以内、mp4格式的视频",
-        "video_limit":"过大,请上传200MB以内、mp4格式的视频",
-        "video_fail":"格式错误,请上传200MB以内、mp4格式的视频",
-        "serch_material":"搜索素材",
-        "rename":"重命名",
-        "delete":"删除",
-        "no_serch_result":"未搜索到结果",
-        "no_material_result":"暂无素材~",
-        "had_load":"已加载{msg}条",
-        "uploading":"正在上传 {msg}"
+    "zh_key": {
+        "电话": "Tel",
+        "链接": "Link",
+        '小行星开场': "Start with asteroid",
+        '小行星巡游开场': "Start with asteroid cruise",
+        '小行星缩放开场': "Start with asteroid zoom",
+        '水平巡游开场': "Start with horizontal cruise",
+        '水晶球开场': "Start with crystal ball",
+        '开场提示': "Notifications",
+        '开场动画': "Animations",
+        '访问密码': "Access code",
+        '自动巡游': "Walkthrough",
+        '背景音乐': "BGM",
+        '自定义LOGO': "Custom Logo",
+        '自定义遮罩': "Custom Mask",
+        '自定义按钮': "Custom Button",
     },
-    "personal_center":{
-        "personal_center":"个人中心",
-        "logout":"退出登录",
-        "login":"登录",
-        "register":"注册",
-        
+
+
+
+    "style_key":{
+        'menu_width':'88px',
+        'play_width':'31'
     }
 }

+ 862 - 0
packages/qjkankan-editor/src/lang/_en.json

@@ -0,0 +1,862 @@
+{
+  "menu": {
+    "__name": "菜单",
+    "music": "BGM",
+    "base": "Basic Setting",
+    "information": "Scene Info",
+    "screen": "Scene Cover",
+    "hotspot": "Add Hotspot",
+    "guide": "Tour Guide",
+    "sign": "Spot Logo",
+    "walk": "Roaming Possibility",
+    "model": "Model Edit",
+    "custom": "Upload Download",
+    "videos": "Add Videos",
+    "vrhouse": "VR house",
+    "business": "Business part",
+    "scene": "Scene transition",
+    "video": "Add video",
+    "decor": "Decor",
+    "link": "Scene associate"
+  },
+  "modules": {
+    "__name": "模块",
+    "base": {
+      "__name": "基础设置",
+      "qrcode": "QR Code",
+      "qrcode_download": "Download the QR code",
+      "qrcode_tips": "Customize your logo",
+      "scene_link": "Scene Link",
+      "scene_link_copy": "Copy the link",
+      "scene_link_copy_tips": "Copied",
+      "bgm": "BGM",
+      "pano_text": "Roaming",
+      "mode_2d_text": "Layout Plan",
+      "mode_3d_text": "3D Model",
+      "map_text": "Mini-map",
+      "vr_text": "VR Mode",
+      "vr_tips": "Please view the VR effect on the mobile display page",
+      "guide_text": "Tour Guide",
+      "rule_text": "Measurements",
+      "cad_text": "Floor Layout",
+      "measure_text": "Ruler",
+      "measure_tips": "The measuring function cannot be used in edit mode, please use it on display page",
+      "turned_vr": "VR turned {status}",
+      "turned_map": "Mini-map feature  {status}",
+      "turned_cad": "Layout plan {status}",
+      "turned_m2d": "Plane view {status}",
+      "turned_m3d": "3D view {status}",
+      "turned_pano": "Roaming view {status}",
+      "turned_rule": "Measuring function {status}",
+      "turned_guide": "Tour guide {status}",
+      "turned_measure": "Ruler {status}",
+      "shortcut_copy": "One-click copy",
+      "share_link": "Share links to friends",
+      "measure_show_tips": "Please use the measuring function on the display page",
+      "delete_measure_line": "Delete measurement line",
+      "please_click_tips": "'Please click“allow”'",
+      "vr_fail_app_tips": "The browser failed to detect the rotation. Please enable the settings such as motion and direction access in the phone or browser settings, and then refresh this page.",
+      "vr_fail_safari_tips": "The browser failed to detect the rotation. To fully experience the VR effect, please open the \"Motion and Direction Access\" switch under \"Settings\"> \"Safari\"> \"Privacy and Security\", and then refresh this page.",
+      "loading_bottom_text": "4Dage provides technical support",
+      "vr_fail_reopen_tips": "Can't access motion and orientation, please restart App and try again.",
+      "add_music_title": "Add BGM",
+      "add_music_tips": "Support MP3, WAV and other audio formats, no more than 5MB",
+      "re_add_music": "Re-add",
+      "re_add_title": "Re-add BGM",
+      "re_add_tips": "The latest music will replace the added music, <br>Are you sure to continue adding?",
+      "re_add_mobile_tips": "Re-adding will replace the added music",
+      "delete_tips": "Are you sure to delete the current BGM?",
+      "delete_title": "Delete BGM",
+      "bgm_empty_tips": "Please select BGM",
+      "wechat": "Wechat",
+      "friend_circle": "Moments"
+    },
+    "information": {
+      "__name": "场景信息",
+      "title": "Title",
+      "title_tips": "Please enter a title",
+      "title_require": "Please add a title (max {limit} characters).",
+      "description": "Description",
+      "description_tips": "Please enter a description.",
+      "link": "Add a link",
+      "link_text_tips": "Link title",
+      "link_href_tips": "Link",
+      "link_text_require": "Please fill in the text.",
+      "link_href_require": "Please fill in the link.",
+      "classify": "Choose a category",
+      "upload_time": "Upload date",
+      "record": "Not recorded",
+      "shoot_count": "Number of shots",
+      "password": "Set a password",
+      "password_tips": "4 characters",
+      "password_desc": "Set a password if you don't want it to be accessible for the public.",
+      "password_require": "Please enter a password with {limit} digits",
+      "logo_edit": "Edit the logo",
+      "logo_exit": "Finish editting logo",
+      "logo_show_bottom": "Show original logo",
+      "logo_style1": "Logo style 1",
+      "logo_style2": "Logo style 2",
+      "logo_delete": "Delete the uploaded logo?"
+    },
+    "screen": {
+      "__name": "初始画面",
+      "current": "Current cover",
+      "current_set": "Set as scene cover",
+      "tips": "Drag the screen, click and save your scene cover."
+    },
+    "hotspot": {
+      "__name": "添加热点",
+      "add": "Add hotspot",
+      "edit": "Edit hotspot",
+      "count": "Added hotspots",
+      "location": "Hotspot Location",
+      "location_tips": "Drag the hotspot to another position.",
+      "location_modify": "Modify hotspot location",
+      "location_confirm": "Confirm hotspot location",
+      "location_desc": "Please drag the hot spot in the two scene areas on the left and align it to the desired point.",
+      "style": "Choose hotspot style",
+      "style_desc": "Choose the default style, or manually upload the picture to customize the style, upload the picture in PNG/JPG format",
+      "style_name": "Style",
+      "style_dele": "Sure to delete this style?",
+      "style_manage": "Manage",
+      "style_exit": "Quit",
+      "media_photo": "Add pictures to enrich hot content",
+      "media_video": "Upload local videos for more display",
+      "media_voice": "Upload local audio content for hotspot explanation",
+      "media_link": "You can add a hyperlink to the video, and the video will be played in the hotspot",
+      "title": "Title",
+      "title_tips": "Please enter a title",
+      "title_require": "Please add a title (max {limit} characters).",
+      "description": "Description",
+      "description_tips": "Please enter a description.",
+      "text_link": "Add a link",
+      "text_link_text_tips": "Please fill in the link text",
+      "text_link_href_tips": "Please fill in the link address",
+      "text_link_text_require": "Link text cannot be empty",
+      "text_link_href_require": "Link address cannot be empty",
+      "link": "Add a link",
+      "link_require": "Please add an external link",
+      "photo": "Photo",
+      "voice": "Audio",
+      "video": "Video",
+      "photo_tips": "Support JPG, PNG and other image formats",
+      "voice_tips": "Support MP3, WAV and other audio formats",
+      "video_tips": "Support MP4 format. <20M",
+      "photo_require": "Please add photos",
+      "voice_require": "Please add audio",
+      "video_require": "Please add videos",
+      "m_location_tips1": "Point split-screen hotspots above and below to the marked target",
+      "m_location_tips2": "Determine the hotspot location, click next to edit content",
+      "m_location_up": "Above",
+      "m_location_left": "Left side",
+      "m_location_move_tips": "The auxiliary calibration position may be inaccurate,<br>please check and drag to {direction} the same location",
+      "set_visible_btn": "Hotspot Visiblity",
+      "save_visible_btn": "Save",
+      "save_hotspot_done": "Successfully saved hotspot",
+      "save_hotspot_fail": "Failed to save hotspot",
+      "delete_hotspot_tips": "Do you want to delete the current hotspot?",
+      "delete_hotspot_done": "Successfully deleted hotspot",
+      "delete_hotspot_fail": "Failed to delete hotspot",
+      "cant_add_hotspot_tips": "Unable to add hotspot",
+      "cant_add_hotspot_content": "The number of hotspots has reached the maximum: {limit}",
+      "link_text_tips": "Link title",
+      "link_href_tips": "Link",
+      "link_text_require": "Please fill in the text",
+      "link_href_require": "Please fill in the link",
+      "add_media": "Add Content"
+    },
+    "guide": {
+      "__name": "自动导览",
+      "route": "Tour Route",
+      "view": "Switch View",
+      "record": "Start recording",
+      "record_audio": "Record",
+      "pause": "Pause",
+      "stop": "Stop",
+      "end": "End",
+      "delete": "Delete",
+      "continue": "Continue recording",
+      "preview": "View",
+      "clear": "Clear",
+      "sync": "Audiovisual synchronization",
+      "sound": "Record audio",
+      "file": "Upload audio",
+      "file_add": "Add audio",
+      "tips": "Click \"Start\" to record the tour.",
+      "start": "Start",
+      "finish": "Finish",
+      "less": "Less",
+      "replace_tips": "Do you want to start over the tour recording?",
+      "replace_content": "Redo the recording will overwrite previous data.",
+      "sound_open_fail_tips": "Failed to turn on the microphone",
+      "sound_tips": "Failed to turn on the microphone, continue recording?",
+      "sound_content": "Please allow this site to use the microphone in your browser settings and refresh the page.",
+      "upload_sound_done": "Upload sound explanation successfully",
+      "upload_sound_fail": "Failed to upload sound explanation",
+      "delete_sound_done": "Delete sound explanation successfully",
+      "delete_sound_fail": "Failed to delete sound explanation",
+      "room_title": "Title",
+      "room_title_tips": "Please enter the room title",
+      "room_title_require": "Please enter a title",
+      "room_panel_title": "Guide information",
+      "room_sound_title": "Record audio",
+      "delete_video_content": "Your current recording will be deleted",
+      "delete_file_content": "Your currently uploaded sound explanation will be deleted",
+      "delete_sound_content": "Your recorded audio will be deleted",
+      "camera_save_success": "Successfully saved camera",
+      "clear_video_tip": "Your current recording will be cleared",
+      "saving_sound": "Saving recording",
+      "save_sound_done": "Successfully saved recording",
+      "save_sound_fail": "Failed to save recording",
+      "no_sound_tips": "Currently does not support recordig.<br>Please record on WeChat or computer",
+      "sound_success_tips": "Successfully opened the microphone",
+      "sound_fail_tips": "Currently does not support recording.<br>Official account information configuration error",
+      "wechat_sound_fail_tips": "Failed to open WeChat microphone",
+      "open_sound_guide_tips": "If you want to record, please enable it in the WeChat settings-privacy-authorization management. And ensure that the recording equipment is normal",
+      "sound_cant_open_tips": "This browser does not support recording. <br>It is recommended to replace other mainstream browsers for a better experience",
+      "replace_sound_tips": "Re-record?",
+      "replace_sound_content": "Current sound explanation will be replaced",
+      "merge_sound_fail": "Fail to merge sound explanation",
+      "sound_limit": "The recording duration cannot exceed {time} minutes",
+      "select_to_record": "Please select the corresponding point to record the guide in this area"
+    },
+    "sign": {
+      "title": "Logo style",
+      "size": "Size",
+      "style0": "Style one",
+      "style1": "Style two",
+      "style2": "Style three",
+      "style3": "Upload"
+    },
+    "walk": {
+      "title": "Roaming Possibility",
+      "tips1": "Further optimize the experience during roaming by setting roaming possibility, such as cases in which one may penetrate through the walls. ",
+      "tips2": "Set the roaming possibility by clicking and setting the connection of each roaming point.",
+      "save": "Save current settings",
+      "hide": "Hide the spot",
+      "show": "Show the spot",
+      "pano_tips": "Tip: You hide the initial point, so you can't roam in this scene."
+    },
+    "model": {
+      "__name": "修整模型",
+      "cad": "CAD View",
+      "cad_download": "FloorPlan Download",
+      "view": "Switch View",
+      "title": "Add structure",
+      "title_door": "Doors and windows",
+      "title_component": "Components",
+      "title_other": "Others",
+      "attribute": "Attributes",
+      "door": "Door",
+      "slideDoor": "Slidedoor",
+      "casement": "Window",
+      "bayCase": "Bay Window",
+      "groundCase": "French Sash",
+      "column": "Column",
+      "furnColumn": "Frame Column",
+      "furnFlue": "Flue",
+      "point": "Point",
+      "line": "Interior Wall",
+      "tagging": "Tag",
+      "tagging_name_tips": "Tag name",
+      "tagging_area_tips": "Enter area",
+      "direction": "Compass",
+      "wallLine": "Interior wall",
+      "widget_delete": "{widget} will be deleted",
+      "panel_btn_default": "Reset",
+      "panel_btn_delete": "Delete",
+      "attr_angle": "Rotation angle",
+      "attr_within": "Flip direction",
+      "attr_ewidth": "Width",
+      "attr_eheight": "Height",
+      "attr_tick": "Tickness",
+      "attr_showTitle": "Tag name",
+      "attr_showContent": "Tag area",
+      "attr_top": "Top",
+      "attr_bottom": "Bottom",
+      "success": "Add successfully {widget}",
+      "error_location": "Current location cannot be added {widget}",
+      "error_outdoor": "Outdoor cannot be added {widget}",
+      "error_something": "Building at the current location cannot be added {widget}",
+      "error_widget": "Current location cannot be added {widget}",
+      "enter_adjust_floor": "Ground adjustment",
+      "exit_adjust_floor": "Exit adjustment mode",
+      "color_title": "Protractor Color:"
+    },
+    "videos": {
+      "__name": "添加视频",
+      "tips": "Please click on the reference plane to set the video position.",
+      "panel_title": "Video attributes",
+      "panel_preview": "Preview",
+      "panel_upload": "Upload",
+      "panel_upload_tips": "Support MP4 format",
+      "panel_move": "Move",
+      "panel_zoom": "Zoom",
+      "panel_thickness": "Tickness",
+      "recoverRatio": "Restore original aspect ratio",
+      "recoverRatioTip": "Restore original aspect ratio of the video"
+    },
+    "custom": {
+      "model_title": "Download model",
+      "uploading": "Uploading…",
+      "download": "Original model download",
+      "download_panos": "Download panos",
+      "upload": "Modified model upload",
+      "title1": "Model download/upload tutorial",
+      "tips11": "1.After downloading the ZIP package of the scene model, open the decompressed file”mesh.obj” to edit it.",
+      "tips12": "2.After the edit is completed, it is recommended to render the model texture. The render texture should be controlled within 1.5M while the saved obj files should be controlled within 3M.",
+      "tips13": "3.After completing steps 1 and 2, package the obj, mtl, and texture into a zip package and upload it.",
+      "title2": "Notes:",
+      "tips21": "1.Please control the file size, in order not to freeze when you are browsing which will affect your experience.",
+      "tips22": "2.Please use the same name in both obj and ZIP package, otherwise the replacement will fail.",
+      "get_image_fail": "Failed to get image. Please check your network settings and try again.",
+      "download_model_fail": "Fail to download model",
+      "reupload_tips": "Upload {type}",
+      "panoramic_upload": "Pano Upload",
+      "panoramic_upload_tips": "Panorama upload",
+      "panoramic_upload_box_tips": "Please upload JPG image<br>with corresponding point name.",
+      "panoramic_download": "Pano Download",
+      "panoramic_download_tips": "Panorama download",
+      "panoramic": "Panorama",
+      "ball_video": "Video",
+      "ball_video_upload_tips": "Video Upload",
+      "ball_video_download_tips": "Video Download",
+      "ball_video_upload_box_tips": "The panoramic video supports MP4 format<br>which should not exceed 1024M.",
+      "upload_title": "Upload files",
+      "upload_format_error": "File format error, please upload again",
+      "upload_name_error": "File name error, please upload again",
+      "upload_success": "The upload is successful and will take effect<br>after saving and publishing",
+      "upload_code_5017": "Failed to upload the model, <br>please refer tothe tutorial on the right",
+      "upload_code_5018": "The zip file can only have<br>one level of directory or no directory",
+      "upload_code_5019": "There must be only one obj and mtl file",
+      "upload_code_5020": "The texture needs to be controlled within 1.5M, and the obj file needs to be controlled within 3M",
+      "upload_code_5012": "The data is abnormal",
+      "upload_code_5023": "The upload file format is incorrect, <br>only jpg or mp4 format.",
+      "download_tips": "Download {type}",
+      "download_fail": "Failed to download"
+    },
+    "vrhouse": {
+      "__name": "VR看房",
+      "linkto_management": "Go to the VR house management background"
+    },
+    "business": {
+      "__name": "商圈模块",
+      "list_title": "Scene hotspot list"
+    },
+    "link": {
+      "__name": "跳转关联",
+      "title1": "Save the link",
+      "title2": "Edit the link",
+      "list_text": "Added links",
+      "btn_new_text": "Add a link",
+      "btn_add_title": "关联点定位",
+      "btn_add_text": "确定关联点位置",
+      "btn_add_desc": "将关联点标记并拖动到合适的位置。",
+      "btn_edit_text": "Adjust the link position",
+      "style": "Link icon",
+      "style_name": "icon",
+      "style_desc": "upport customized icon with recommended size of 100*100 pixels. Support JPG/PNG format.",
+      "style_dele": "Delete this icon? <br /> The same icon used for other links will also be deleted.",
+      "desc_title": "Description",
+      "desc_tips": "Please enter a description.",
+      "desc_require": "Please enter a description.",
+      "type": "Choose the type of link",
+      "type_photo": "upport uploading panoramic pictures with an aspect ratio of 2:1, recommended pixel size should not be less than 6000 × 3000 pixels, and the file should not exceed 120M",
+      "type_photo_require": "Upload panoramic pictures.",
+      "type_link": "Please input the scene link.",
+      "type_link_tips": "http(s)://",
+      "type_link_require": "Please input the scene link.",
+      "enter_title": "Link cover",
+      "enter_require": "Please set a link cover",
+      "enter_btn_text": "Set a link cover",
+      "outer_title": "Exit spot position",
+      "outer_style": "Exit spot icon",
+      "outer_desc": "Support customized icon with recommended size of 100*100 pixels. Support JPG/PNG format.",
+      "outer_require": "Please set the position of exit spot.",
+      "outer_btn_text": "Set the position of exit spot."
+    }
+  },
+  "login": {
+    "__name": "登录",
+    "title": "Message",
+    "login": "Log in",
+    "logon": "Log in and continue",
+    "login_tips": "You are not logged in. Please log in to edit."
+  },
+  "common": {
+    "__name": "公用",
+    "on": "on",
+    "off": "off",
+    "add": "Add",
+    "set": "OK",
+    "ok": "OK",
+    "save": "Save",
+    "cancel": "Cancel",
+    "complete": "Complete",
+    "edit": "Modify",
+    "giveup": "Give up",
+    "commit": "Commit",
+    "photo": "Photo",
+    "voice": "Audio",
+    "video": "Video",
+    "bgm": "BGM",
+    "crop": "Crop",
+    "upload": "Upload",
+    "download": "Download",
+    "change": "Change",
+    "unnamed": "Unnamed",
+    "publish": "Save and publish",
+    "publish_text": "Save and publish successfully!",
+    "publish_tips": "Check your scene immediately?",
+    "publish_btn_ok": "Now",
+    "publish_btn_no": "Later",
+    "public": "Public",
+    "private": "Private",
+    "waiting": "Waiting...",
+    "audio": "Audio",
+    "second": "s",
+    "delete": "Delete",
+    "prev": "Go back",
+    "next": "Next",
+    "meter": "≈{meter}m",
+    "guide": "Tour Guide",
+    "rule": "Ruler",
+    "roaming": "Roaming",
+    "continue": "Continue",
+    "ensure_delete": "Delete",
+    "text_limit": "Limit within {limit} characters",
+    "default": "Default",
+    "custom": "Customize",
+    "back": "Back",
+    "will_delete": "Will be deleted",
+    "setup": "Set",
+    "exit": "Done",
+    "music": {
+      "__name": "背景音乐",
+      "none": "No music",
+      "cheerfu": "Cheerful",
+      "ethereal": "Ethereal",
+      "rhythmic": "Rhythmic",
+      "nostalgic": "Nostalgic",
+      "missing": "Missing",
+      "retro": "Retro",
+      "strings": "Strings",
+      "happy": "Happy"
+    },
+    "category": {
+      "__name": "分类",
+      "museum": "Museum",
+      "estate": "Real estate",
+      "eshop": "E-Commerce",
+      "catering": "Catering",
+      "home": "Home",
+      "other": "Other"
+    },
+    "uploads": {
+      "__name": "文件上传",
+      "uploading": "Uploading",
+      "uploaded": "Uploaded",
+      "wait": "Wait...",
+      "error": "Error",
+      "add": "Add",
+      "start": "Start",
+      "file_require": "Please add file",
+      "cant_upload": "Your browser does not support uploading files",
+      "not_support": "The file you selected is not {fileType} supported by the browser, please select again",
+      "too_large": "The file is too large and cannot be larger than {size} trillion",
+      "too_large_reupload_tips": "The uploaded video is too large, please upload again"
+    },
+    "tips": {
+      "__name": "提示",
+      "wait": "Please wait..."
+    }
+  },
+  "tips": {
+    "__name": "提示",
+    "title": "Tip",
+    "set_done": "Set up successfully",
+    "set_fail": "Set up failed",
+    "save_done": "Save successfully",
+    "save_fail": "Save failed",
+    "delete": "Delete or not?",
+    "delete_done": "Delete successfully",
+    "delete_fail": "Fail to delete",
+    "upload_done": "Upload successfully",
+    "upload_fail": "Failed to upload",
+    "exception": "Error",
+    "network_error": "The internet is disconnected, please try it again",
+    "file_notfound": "The file is not found",
+    "scene_notfound": "The scene is not found",
+    "params_notfound": "The parameter is not found",
+    "camera_notfound": "The matched camera is not found",
+    "password_error": "Incorrect password",
+    "data_error": "The data is not found",
+    "auth_deny": "Unathorized to operate the scene",
+    "clear": "Sure to clear?",
+    "upload_pic_fail": "Failed to upload pictures",
+    "wait": "Please waiting...",
+    "house_type_save_fail": "Failed to save house type"
+  },
+  "show": {
+    "__name": "展示页面",
+    "on": "On",
+    "off": "Off",
+    "measure": "Measuring tool",
+    "measure_start": "Start",
+    "measure_end": "End",
+    "measure_button": "Confirm {status}",
+    "location_up": "Above",
+    "location_left": "Left",
+    "location_start_tips": "Please click on {direction}",
+    "location_end_tips": "The starting point is determined, please locate the end point",
+    "vr": "VR mode",
+    "share": "Share it",
+    "music": "Turn {status} music",
+    "password_tips": "Password",
+    "password_require": "Please enter the password"
+  },
+  "components": {
+    "user_guid": {
+      "__name": "用户引导",
+      "title": "Operation Tips",
+      "pano": "Walk<br />Click to move.",
+      "rotate": "Roam<br />Swipe the screen to roam.",
+      "zoom": "Zoom<br />Zoom in or out.",
+      "set": "Got it"
+    }
+  },
+  "material": {
+    "works": {
+      "my": "My Project",
+      "create": "Create a project",
+      "search": "Search",
+      "preview": "View",
+      "edit": "Edit",
+      "share": "Share",
+      "delete": "Delete",
+      "no_works": "No results found, you do not yet have a project, please create one first~",
+      "work_link": "Project link",
+      "work_qrCode": "Project QR Code",
+      "download_qrCode": "Download the QR code",
+      "copy_link": "Copy link",
+      "work_preview": "View Project",
+      "new_blank": "Open in a new window",
+      "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": "View",
+      "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":"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":"View",
+      "rename_material":"Rename the material"
+    }
+  },
+  "gather": {
+    "select_material": "Select the materials",
+    "no_title": "No title",
+    "name": "4DPano",
+    "editpage_name": "Editing platform",
+    "my_works": "My Project",
+    "my_material": "My Material",
+    "panorama": "Panorama",
+    "image": "Pictures",
+    "audio": "Audio",
+    "video": "Video",
+    "scene": "3D Scene",
+    "keywords": "Enter keywords",
+    "how_to_shoot": "How to shoot a 3D scene?",
+    "pano_size": "Support 2:1 jpg files ≤ 120MB",
+    "cancel": "Cancel",
+    "comfirm": "Confirm",
+    "pano_fail": "Format error. Support 2:1 jpg files ≤ 120MB",
+    "pano_limit": "The file is too large. Support 2:1 jpg files ≤ 120MB",
+    "edit_cover": "Thumbnail Settings",
+    "img_fail": "Format error.Support jpg/png files: ≤ 10MB",
+    "img_limit": "The file is too large.Support jpg/png files: ≤ 10MB",
+    "img_size": "Support jpg/png files: ≤ 10MB",
+    "audio_size": "Support MP3 files: ≤ 20MB",
+    "audio_limit": "The file is too large. Support MP3 files: ≤ 20MB",
+    "audio_fail": "Format error. Support MP3 files: ≤ 20MB",
+    "upload_material": "Upload materials",
+    "video_size": "Support MP4 files: ≤ 200MB",
+    "video_limit": "The file is too large.Support MP4 files: ≤ 200MB",
+    "video_fail": "Format error. Support MP4 files: ≤ 200MB",
+    "serch_material": "Search",
+    "rename": "Rename",
+    "delete": "Delete",
+    "no_serch_result": "No resulrs found",
+    "no_material_result": "No materials found",
+    "had_load": "{msg} pieces of data have been loaded",
+    "uploading": "Uploading {msg}",
+    "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",
+    "logout": "Log out",
+    "login": "Login",
+    "register": "Sign up"
+  },
+  "edit_page": {
+    "back_myworks": "Back",
+    "preview": "View",
+    "settings": "Basic Settings",
+    "navigation": "Navigation",
+    "viewpoint": "Starting Screen",
+    "hotspot": "Hotspots",
+    "explanation": "Voice Guide",
+    "save": "Save"
+  },
+  "edit_settings": {
+    "auto_pano": "Rotation",
+    "enter_auto": "Enter the rotation mode (takes 3 mins to complete per rotation)",
+    "set_bgm": "Set the BGM",
+    "add_audio": "Add the audio",
+    "change_audio": "Change the audio",
+    "custom_button": "Custom Button",
+    "custom_button_tips": "Custom buttons provide contact info, website URLs, etc. to a project, which can subsequently be made visible and displayed as well.",
+    "edit": "Edit",
+    "hide": "Hide",
+    "show": "Display",
+    "button_name": "Button name",
+    "button_placeholder": "Please enter the button name",
+    "please_input": "Please enter",
+    "phone": "Phone",
+    "link": "URL Address",
+    "phone_short": "Tel",
+    "link_short": "Link",
+    "custom_logo": "Custom Logo",
+    "show_logo": "Display Logo",
+    "logo_size": "300*300 pixels, within 600kb, <br>jpg/png format support",
+    "sky_mask": "Top mask",
+    "sky_tips": "The top mask is exhibited at the scene's top, while the bottom mask is presented at the scene's bottom.",
+    "mask_setting": "Mask Settings",
+    "mask_size": "500*500 pixels, <br>jpg/png format support",
+    "bottom_mask": "Bottom mask",
+    "opening_setting": "Set the animations",
+    "opening_tips_setting": "Notifications Settings",
+    "opening_tips": "The notifications only apply to panoramic images. The following notifications are inapplicable if the start screen is a 3D model.",
+    "pc": "PC",
+    "mobile": "Mobile",
+    "select_image": "Select pictures",
+    "opening_size": "Recommend 300*300 pixels, within 600kb, jpg/png format support",
+    "show_setting": "Display settings",
+    "first_notice": "Prompt only when the link is opened for the first time",
+    "password_setting": "Set an access code",
+    "password_placeholder": "Please enter the access password, limited to 20-character",
+    "base_setting": "Basic Settings",
+    "setting_cover": "Thumbnail Settings",
+    "cover_size": "512*512px, support jpg/png format",
+    "title": "Title",
+    "description": "Description",
+    "work_placeholder": "Please enter the project title",
+    "intro_placeholder": "Please input no more than 500 words of text content",
+    "help_center": "Help Center",
+    "display_time": "Display duration",
+    "no_display": "(No display)",
+    "second": " Sec"
+  },
+  "zh_key": {
+    "电话": "Tel",
+    "链接": "Link",
+    "小行星开场": "Start with asteroid",
+    "小行星巡游开场": "Start with asteroid cruise",
+    "小行星缩放开场": "Start with asteroid zoom",
+    "水平巡游开场": "Start with horizontal cruise",
+    "水晶球开场": "Start with crystal ball",
+    "开场提示": "Notifications",
+    "开场动画": "Animations",
+    "访问密码": "Access code",
+    "自动巡游": "Rotation",
+    "背景音乐": "BGM",
+    "自定义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": "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",
+    "delete_init_scene": "Delete",
+    "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": "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": {
+    "img_size":"Upload up to 20 images",
+    "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": "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"
+  }
+}

+ 73 - 13
packages/qjkankan-editor/src/lang/_zh.js

@@ -547,12 +547,8 @@ module.exports = {
     "gather":{
         "select_material":"选择素材",
         "no_title":"无标题",
-
         "my_works":"我的作品",
         "my_material":"我的素材",
-
-
- 
         "panorama":"全景图",
         "image":"图片",
         "audio":"音频",
@@ -563,21 +559,15 @@ module.exports = {
         "pano_size":"请上传2:1、120MB以内、jpg格式的图片",
         "cancel":"取消",
         "comfirm":"确定",
-
         "pano_fail":"格式错误,请上传2:1、120MB以内、jpg格式的全景图片",
         "pano_limit":"过大,请上传2:1、120MB以内、jpg格式的全景图片",
         "edit_cover":"编辑封面",
-
         "img_fail":"格式错误,请上传10MB以内、jpg/png格式的图片",
         "img_limit":"过大,请上传10MB以内、jpg/png格式的图片",
         "img_size":"请上传10MB以内、jpg/png格式的图片",
-        
- 
         "audio_size":"请上传20MB以内、mp3格式的音频",
         "audio_limit":"过大,请上传20MB以内、mp3格式的音频",
         "audio_fail":"格式错误,请上传20MB以内、mp3格式的音频",
-       
-
         "upload_material":"上传素材",
         "video_size":"请上传200MB以内、mp4格式的视频",
         "video_limit":"过大,请上传200MB以内、mp4格式的视频",
@@ -609,12 +599,9 @@ module.exports = {
     "edit_settings":{
         "auto_pano":"自动巡游",
         "enter_auto":"进入全景图自动巡游(3分钟完整巡游一次)",
-
-
         "set_bgm":"设置背景音乐",
         "add_audio":"添加音频",
         "change_audio":"更换音频",
-
         "custom_button":"自定义按钮",
         "custom_button_tips":"自定义按钮可为作品添加联系方式或网站链接等,设置可见后即可在作品显示。",
         "edit":"编辑",
@@ -627,7 +614,80 @@ module.exports = {
         "link":"链接地址",
         "phone_short":"电话",
         "link_short":"链接",
+        "custom_logo":"自定义LOGO",
+        "show_logo":"显示LOGO",
+        "logo_size":"300*300px,600kb以内,支持<br>jpg/png格式",
+        "mask_setting":"遮罩设置",
+        "sky_mask":"天空遮罩",
+        "sky_tips":"天空遮罩显示在场景的顶部,地面遮罩显示在场景的底部。",
+        "mask_setting":"遮罩设置",
+        "mask_size":"建议500*500px,<br/>支持jpg/png格式",
+        "bottom_mask":"地面遮罩",
+        "opening_setting":"设置开场动画",
+        "opening_tips_setting":"提示设置",
+        "opening_tips":"开场提示仅适用于全景图。若初始场景为三维模\n型,以下开场提示不适用。",
+        "pc":"PC端",
+        "mobile":"移动端",
+        "select_image":"选择图片",
+        "opening_size":"建议300*300px,600kb以内,<br/>支持jpg/png格式",
+        "show_setting":"显示设置",
+        "first_notice":"仅首次打开链接时,提示",
+        "password_setting":"设置访问密码",
+        "password_placeholder":"请输入访问密码,限20位",
+        "base_setting":"基础设置",
+        "setting_cover":"设置封面",
+        "cover_size":"512*512px,支持jpg/png格式",
+        "title":"标题",
+        "description": "简介",
+        "work_placeholder":"请输入作品标题",
+        "intro_placeholder":"请输入文字内容,限500字",
+
+
+        "help_center":"帮助中心",
+        "display_time":"显示时间",
+        "no_display":"(不显示)",
+        "second":"秒",
+
+    },
+
+    "zh_key":{
+        "电话":"电话",
+        "链接":"链接",
+        '小行星开场':"小行星开场",
+        '小行星巡游开场':"小行星巡游开场",
+        '小行星缩放开场':"小行星缩放开场",
+        '水平巡游开场':"水平巡游开场",
+        '水晶球开场':"水晶球开场",
+        '开场提示':"开场提示",
+        '开场动画':"开场动画",
+        '访问密码':"访问密码",
+        '自动巡游':"自动巡游",
+        '背景音乐':"背景音乐",
+        '自定义LOGO':"自定义LOGO",
+        '自定义遮罩':"自定义遮罩",
+        '自定义按钮':"自定义按钮",
+    },
+
+
+
+    "navigation":{
+        "scene_navigation":"场景导航",
+        "add_group":"新建分组",
+        "scene_tips":"场景素材包括全景图和三维场景,您可自定义分组及场景的排列顺序。",
+        "add_two_group":"新建二级分组",
+        "group_one":"一级分组",
+        "group_two":"二级分组",
+        "default_group_two":"默认二级分组",
+        "init_scene":"初始场景",
+        "setting_init_scene":"设置初始场景",
 
         
+    },
+
+
+
+    "style_key":{
+        'menu_width':'58px',
+        'play_width':'0'
     }
 }

+ 873 - 0
packages/qjkankan-editor/src/lang/_zh.json

@@ -0,0 +1,873 @@
+{
+  "menu": {
+    "__name": "菜单",
+    "music": "背景音乐",
+    "base": "基础设置",
+    "information": "场景信息",
+    "screen": "初始画面",
+    "hotspot": "添加热点",
+    "guide": "自动导览",
+    "sign": "地面Logo",
+    "walk": "漫游可行",
+    "model": "修整模型",
+    "custom": "上传下载",
+    "videos": "添加视频",
+    "vrhouse": "VR看房",
+    "business": "商圈模块",
+    "scene": "场景跳转",
+    "video": "添加视频",
+    "decor": "一键换装",
+    "link": "场景关联"
+  },
+  "modules": {
+    "__name": "模块",
+    "base": {
+      "__name": "基础设置",
+      "qrcode": "场景二维码",
+      "qrcode_download": "下载二维码",
+      "qrcode_tips": "自定义logo",
+      "scene_link": "场景地址",
+      "scene_link_copy": "复制链接",
+      "scene_link_copy_tips": "复制成功",
+      "bgm": "背景音乐",
+      "pano_text": "漫游视角可视",
+      "mode_2d_text": "平面图可视",
+      "mode_3d_text": "三维模型可视",
+      "map_text": "小地图预览可视",
+      "vr_text": "VR模式可视",
+      "vr_tips": "请在手机展示页面观看VR效果",
+      "guide_text": "自动导览可视",
+      "rule_text": "标尺可视",
+      "cad_text": "俯视图户型可视",
+      "measure_text": "测量工具可视",
+      "measure_tips": "编辑模式下无法使用测距功能,请在展示页面操作",
+      "turned_vr": "VR功能已{status}",
+      "turned_map": "小地图功能已{status}",
+      "turned_cad": "俯视图户型功能已{status}",
+      "turned_m2d": "平面视角功能已{status}",
+      "turned_m3d": "三维视角功能已{status}",
+      "turned_pano": "漫游视角功能已{status}",
+      "turned_rule": "标尺功能已{status}",
+      "turned_guide": "自动导览功能已{status}",
+      "turned_measure": "测距功能已{status}",
+      "shortcut_copy": "一键复制",
+      "share_link": "分享链接给好友",
+      "measure_show_tips": "请在展示页面使用测距功能",
+      "delete_measure_line": "删除测量线",
+      "please_click_tips": "'请点击“允许”'",
+      "vr_fail_app_tips": "浏览器未能检测到转动。请在手机或浏览器设置中开启了运动和方向访问等设置,然后刷新此页面。",
+      "vr_fail_safari_tips": "浏览器未能检测到转动。为完整体验VR效果,请打开 “设置” > “Safari” > “隐私和安全” 下的 “运动和方向访问” 开关,然后刷新此页面。",
+      "loading_bottom_text": "四维时代提供技术支持",
+      "vr_fail_reopen_tips": "运动和方向访问失败。您需要完全关闭此应用,然后再次打开,并允许访问运动与方向",
+      "add_music_title": "添加背景音乐",
+      "add_music_tips": "支持MP3、WAV等音频格式,不超过5MB",
+      "re_add_music": "重新添加",
+      "re_add_title": "重新添加背景音乐",
+      "re_add_tips": "新添加的音乐会替换已添加的音乐,<br>确定继续添加吗?",
+      "re_add_mobile_tips": "重新添加将会覆盖已添加音乐",
+      "delete_tips": "您确定删除当前音乐吗?",
+      "delete_title": "删除背景音乐",
+      "bgm_empty_tips": "请选择背景音乐",
+      "wechat": "微信",
+      "friend_circle": "朋友圈"
+    },
+    "information": {
+      "__name": "场景信息",
+      "title": "标题",
+      "title_tips": "请填写标题",
+      "title_require": "请添加标题({limit}字以内)",
+      "description": "简介",
+      "description_tips": "请填写简介",
+      "link": "添加链接",
+      "link_text_tips": "请填写链接文本",
+      "link_href_tips": "请填写链接地址",
+      "link_text_require": "请填写链接文本",
+      "link_href_require": "请填写链接地址",
+      "classify": "分类",
+      "upload_time": "上传时间",
+      "record": "未记录",
+      "shoot_count": "拍摄数量",
+      "password": "访问密码",
+      "password_tips": "访问密码",
+      "password_desc": "设置完密码后,当其他人访问您的场景时,需要输入您设置的密码才能访问。如无需设置点击“公开”即可。",
+      "password_require": "请输入{limit}位数的密码",
+      "logo_edit": "编辑页面Logo",
+      "logo_exit": "退出页面Logo编辑",
+      "logo_show_bottom": "显示初始Logo",
+      "logo_style1": "顶部Logo-方",
+      "logo_style2": "顶部Logo-长",
+      "logo_delete": "是否删除已上传Logo?"
+    },
+    "screen": {
+      "__name": "初始画面",
+      "current": "当前初始视角",
+      "current_set": "设置为初始画面",
+      "tips": "移动屏幕,点击保存您的初始画面。"
+    },
+    "hotspot": {
+      "__name": "添加热点",
+      "add": "添加热点",
+      "edit": "编辑热点",
+      "count": "已添加热点",
+      "location": "热点定位",
+      "location_tips": "将热点标记并拖动到合适的位置。",
+      "location_modify": "修改热点位置",
+      "location_confirm": "确定热点位置",
+      "location_desc": "请于左方两个场景区域拖动热点并对准所需标记的位置。",
+      "style": "选择热点样式",
+      "style_desc": "选择默认样式,或者手动上传图片自定义样式,上传图片格式PNG/JPG",
+      "style_name": "样式",
+      "style_dele": "是否删除该样式?",
+      "style_manage": "管理",
+      "style_exit": "退出",
+      "media_photo": "可添加图片以丰富热点内容",
+      "media_video": "可上传本地视频,进行更多的展示",
+      "media_voice": "可上传本地音频内容进行热点讲解",
+      "media_link": "可添加视频的超链接,视频将在热点里播放",
+      "title": "标题",
+      "title_tips": "请填写标题",
+      "title_require": "请添加标题({limit}字以内)",
+      "description": "简介",
+      "description_tips": "请填写简介",
+      "text_link": "添加链接",
+      "text_link_text_tips": "请填写链接文本",
+      "text_link_href_tips": "请填写链接地址",
+      "text_link_text_require": "链接文本不能为空",
+      "text_link_href_require": "链接地址不能为空",
+      "link": "嵌入式链接",
+      "link_require": "请添加外链",
+      "photo": "图片",
+      "voice": "音频",
+      "video": "视频",
+      "photo_tips": "支持JPG、PNG等图片格式,不超过{size}MB",
+      "voice_tips": "支持MP3、WAV等音频格式,不超过{size}MB",
+      "video_tips": "支持MP4、MOV等视频格式,不超过{size}MB",
+      "photo_require": "请添加图片",
+      "voice_require": "请添加音频",
+      "video_require": "请添加视频",
+      "m_location_tips1": "将上下分屏热点对准同一个所标记目标",
+      "m_location_tips2": "确定热点位置,点击下一步编辑内容",
+      "m_location_up": "上方",
+      "m_location_left": "左侧",
+      "m_location_move_tips": "辅助校准位置可能不准确,<br>请检查并拖动到{direction}相同位置",
+      "set_visible_btn": "设置热点可视",
+      "save_visible_btn": "保存当前设置",
+      "save_hotspot_done": "保存热点成功",
+      "save_hotspot_fail": "保存热点失败",
+      "delete_hotspot_tips": "是否删除当前热点?",
+      "delete_hotspot_done": "热点删除成功",
+      "delete_hotspot_fail": "热点删除失败",
+      "cant_add_hotspot_tips": "无法添加热点",
+      "cant_add_hotspot_content": "热点数目已达最大:{limit}",
+      "link_text_tips": "链接标题",
+      "link_href_tips": "链接",
+      "link_text_require": "请填写链接文本",
+      "link_href_require": "请填写链接地址",
+      "add_media": "添加多媒体"
+    },
+    "guide": {
+      "__name": "自动导览",
+      "route": "导航路线",
+      "view": "切换视角",
+      "record": "开始录制",
+      "record_audio": "录音",
+      "pause": "暂停",
+      "stop": "停止",
+      "end": "结束",
+      "delete": "删除",
+      "continue": "继续录制",
+      "preview": "查看",
+      "clear": "清空",
+      "sync": "声画同步",
+      "sound": "录制音频",
+      "file": "上传音频",
+      "file_add": "添加音频",
+      "tips": "点击开始录制导览",
+      "start": "开始",
+      "finish": "完成录制",
+      "less": "小于",
+      "replace_tips": "是否重新录制导览?",
+      "replace_content": "重新录制将覆盖之前的数据",
+      "sound_open_fail_tips": "麦克风开启失败",
+      "sound_tips": "麦克风开启失败,是否继续录制?",
+      "sound_content": "您需要在浏览器的设置中允许此网站使用麦克风,并且添加麦克风设备,然后刷新该页面。",
+      "upload_sound_done": "上传语音讲解成功",
+      "upload_sound_fail": "上传语音讲解失败",
+      "delete_sound_done": "删除语音讲解成功",
+      "delete_sound_fail": "删除语音讲解失败",
+      "room_title": "标题",
+      "room_title_tips": "请输入导览标题",
+      "room_title_require": "请输入标题",
+      "room_panel_title": "导览信息",
+      "room_sound_title": "录制音频",
+      "delete_video_content": "您当前录制的画面将会被删除",
+      "delete_file_content": "您当前上传的语音讲解将会被删除",
+      "delete_sound_content": "已录制配音将会被删除",
+      "camera_save_success": "镜头保存成功",
+      "clear_video_tip": "您当前录制的内容将会被清空",
+      "saving_sound": "正在保存录音",
+      "save_sound_done": "录音保存成功",
+      "save_sound_fail": "录音保存失败",
+      "no_sound_tips": "当前不支持录音<br>可在微信或电脑端录音",
+      "sound_success_tips": "麦克风开启成功",
+      "sound_fail_tips": "当前不支持录音<br>公众号信息配置错误",
+      "wechat_sound_fail_tips": "微信麦克风开启失败",
+      "open_sound_guide_tips": "可能您若要开启录音,请于微信的设置—隐私—授权管理中开启。且保证录音设备正常",
+      "sound_cant_open_tips": "此浏览器不支持录音。<br>建议更换其他主流浏览器,体验更佳",
+      "replace_sound_tips": "是否重新录制?",
+      "replace_sound_content": "已有语音讲解将会被替换",
+      "merge_sound_fail": "合并语音讲解失败",
+      "sound_limit": "录制时长为{time}分钟,当前已经达到上限",
+      "select_to_record": "请选择对应点位进行本区域的导览录制"
+    },
+    "sign": {
+      "title": "Logo样式",
+      "size": "Logo大小",
+      "style0": "样式一",
+      "style1": "样式二",
+      "style2": "样式三",
+      "style3": "手动上传"
+    },
+    "walk": {
+      "title": "漫游可行",
+      "tips1": "通过设置漫游可行,进一步优化在漫游时出现的体验;例如,您在漫游时,出现穿透房间的情况。",
+      "tips2": "通过点选各个漫游点的连线即可设置漫游点的可行性。",
+      "save": "保存当前设置",
+      "hide": "隐藏该点位置",
+      "show": "显示该点位置",
+      "pano_tips": "提示:您隐藏了初始画面点位,此操作将使进入场景后无法漫游。"
+    },
+    "model": {
+      "__name": "修整模型",
+      "cad": "CAD视角",
+      "cad_download": "平面图下载",
+      "view": "切换视角",
+      "title": "增添结构",
+      "title_door": "门窗类",
+      "title_component": "构建类",
+      "title_other": "其他",
+      "attribute": "属性",
+      "door": "门",
+      "slideDoor": "移门",
+      "casement": "窗",
+      "bayCase": "飘窗",
+      "groundCase": "落地窗",
+      "column": "柱子",
+      "furnColumn": "框架柱",
+      "furnFlue": "烟道",
+      "point": "点",
+      "line": "墙",
+      "tagging": "标注",
+      "tagging_name_tips": "请输入名称",
+      "tagging_area_tips": "输入面积,支持小数点后面两位",
+      "direction": "指南针",
+      "wallLine": "墙关联房间",
+      "widget_delete": "{widget}将被删除",
+      "panel_btn_default": "恢复默认",
+      "panel_btn_delete": "删除部件",
+      "attr_angle": "旋转角度",
+      "attr_within": "翻转方向",
+      "attr_ewidth": "宽度",
+      "attr_eheight": "高度",
+      "attr_tick": "厚度",
+      "attr_showTitle": "标注名称",
+      "attr_showContent": "标注面积",
+      "attr_top": "顶部",
+      "attr_bottom": "底部",
+      "success": "成功添加{widget}",
+      "error_location": "当前位置无法添加{widget}",
+      "error_outdoor": "户外无法添加{widget}",
+      "error_something": "当前位置点有建筑,无法添加{widget}",
+      "error_widget": "当前位置不可添加{widget}",
+      "enter_adjust_floor": "进入地面高度调节模式",
+      "exit_adjust_floor": "退出地面高度调节模式",
+      "color_title": "量角器颜色:"
+    },
+    "videos": {
+      "__name": "添加视频",
+      "tips": "请先点击场景的基准面,确定视频位置",
+      "panel_title": "视频属性",
+      "panel_preview": "预览",
+      "panel_upload": "上传视频",
+      "panel_upload_tips": "支持MP4视频格式",
+      "panel_move": "位移",
+      "panel_zoom": "缩放",
+      "panel_thickness": "厚度",
+      "recoverRatio": "恢复原始比例",
+      "recoverRatioTip": "恢复视频文件原始长宽比"
+    },
+    "custom": {
+      "model_title": "模型下载",
+      "uploading": "文件上传中...",
+      "download": "原始模型下载",
+      "download_panos": "下载点位图",
+      "upload": "修改模型上传",
+      "title1": "模型下载/上传功能教程",
+      "tips11": "1.下载场景模型的压缩包后,使用三维软件打开解压后文件“mesh.obj”,即可开展编辑;",
+      "tips12": "2.编辑完成后,建议将模型贴图进行烘焙,烘焙贴图需控制在1.5M以内,同时,保存的obj文件需要控制在3M以内;",
+      "tips13": "3.完成1、2步骤后,将obj,mtl,贴图打包为zip压缩包上传即可。",
+      "title2": "注:",
+      "tips21": "1.请尽量控制文件大小,以免浏览的时候卡顿,影响体验。",
+      "tips22": "2.请将obj及压缩包的名称保持一致,否则会替换失败。",
+      "get_image_fail": "获取贴图失败,可能网络状态不佳,请检查您的网络设置并重新尝试。",
+      "download_model_fail": "模型下载失败",
+      "reupload_tips": "上传后点击保存并发布生效",
+      "panoramic_upload": "全景照片上传",
+      "panoramic_upload_tips": "上传后点击“保存并发布”即生效",
+      "panoramic_upload_box_tips": "请上传对应点位名称的JPG图片",
+      "panoramic_download": "全景照片下载",
+      "panoramic_download_tips": "请勿修改照片名称和格式",
+      "panoramic": "全景图片",
+      "ball_video": "球幕视频",
+      "ball_video_upload_tips": "上传后点击“保存并发布”即生效",
+      "ball_video_download_tips": "请勿修改视频名称和格式",
+      "ball_video_upload_box_tips": "球幕视频支持MP4格式,不超过1024M",
+      "upload_title": "上传文件",
+      "upload_format_error": "文件格式错误,请重新上传",
+      "upload_name_error": "文件名称错误,请重新上传",
+      "upload_success": "上传成功,保存并发布后才能生效",
+      "upload_code_5017": "上传模型失败,请参照右侧教程",
+      "upload_code_5018": "zip文件只能有一层目录或无目录",
+      "upload_code_5019": "必须有且仅有一个obj和mtl文件",
+      "upload_code_5020": "贴图需控制在1.5M以内,obj文件需要控制在3M以内。",
+      "upload_code_5012": "数据不正常",
+      "upload_code_5023": "上传文件格式不正确,只能是jpg或mp4格式",
+      "download_tips": "下载后名称与格式请勿修改",
+      "download_fail": "下载失败"
+    },
+    "vrhouse": {
+      "__name": "VR看房",
+      "linkto_management": "前往云看房管理后台"
+    },
+    "business": {
+      "__name": "商圈模块",
+      "list_title": "场景热点列表"
+    },
+    "link": {
+      "__name": "跳转关联",
+      "title1": "锁定关联点",
+      "title2": "编辑关联点",
+      "list_text": "已添加关联点",
+      "btn_new_text": "添加关联点",
+      "btn_add_title": "关联点定位",
+      "btn_add_text": "确定关联点位置",
+      "btn_add_desc": "将关联点标记并拖动到合适的位置。",
+      "btn_edit_text": "修改关联点位置",
+      "style": "关联点样式",
+      "style_name": "样式",
+      "style_desc": "支持自定义图标,建议尺寸为100x100 像素,格式为jpg/png。",
+      "style_dele": "是否删除该样式?<br />如该样式在其它关联点使用,也将被删除",
+      "desc_title": "描述",
+      "desc_tips": "请输入描述内容",
+      "desc_require": "请输入描述内容",
+      "type": "选择关联类型",
+      "type_photo": "支持上传宽高比为2:1的单张全景图片,建议像素不小于6000x3000像素,文件不超过120M。",
+      "type_photo_require": "请上传全景图",
+      "type_link": "请输入目标场景链接",
+      "type_link_tips": "http(s)://",
+      "type_link_require": "请输入场景链接",
+      "enter_title": "进入画面",
+      "enter_require": "请设置进入画面",
+      "enter_btn_text": "设置进入画面",
+      "outer_title": "跳出点位置",
+      "outer_style": "跳出点样式",
+      "outer_desc": "支持自定义图标,建议尺寸为100x100像素,格式为jpg/png。",
+      "outer_require": "请设置跳出点位置",
+      "outer_btn_text": "设置跳出点位置"
+    }
+  },
+  "login": {
+    "__name": "登录",
+    "title": "提示",
+    "login": "去登录",
+    "logon": "登录完毕,继续",
+    "login_tips": "您没有登录,请于主页登录后再编辑"
+  },
+  "common": {
+    "__name": "公用",
+    "on": "打开",
+    "off": "关闭",
+    "add": "添加",
+    "set": "确定",
+    "ok": "确定",
+    "save": "保存",
+    "cancel": "取消",
+    "complete": "完成",
+    "edit": "修改",
+    "giveup": "取消",
+    "commit": "提交",
+    "photo": "图片",
+    "voice": "音频",
+    "video": "视频",
+    "bgm": "音乐",
+    "crop": "裁剪",
+    "upload": "上传",
+    "download": "下载",
+    "change": "更改",
+    "unnamed": "未命名",
+    "publish": "保存并发布",
+    "publish_text": "保存并发布成功!",
+    "publish_tips": "是否立刻前往观看您的场景?",
+    "publish_btn_ok": "立刻前往",
+    "publish_btn_no": "暂时不去",
+    "public": "公开",
+    "private": "加密",
+    "waiting": "请稍等...",
+    "audio": "音频",
+    "second": "秒",
+    "delete": "删除",
+    "prev": "上一步",
+    "next": "下一步",
+    "meter": "约{meter}米",
+    "guide": "导览",
+    "rule": "测量工具",
+    "roaming": "漫游",
+    "continue": "继续",
+    "ensure_delete": "确定删除",
+    "text_limit": "限制{limit}字内",
+    "default": "默认",
+    "custom": "自定义",
+    "back": "返回",
+    "will_delete": "将被删除",
+    "setup": "设置",
+    "exit": "退出",
+    "music": {
+      "__name": "背景音乐",
+      "none": "无",
+      "cheerfu": "欢快",
+      "ethereal": "空灵",
+      "rhythmic": "节奏",
+      "nostalgic": "怀旧",
+      "missing": "想念",
+      "retro": "复古",
+      "strings": "琴弦",
+      "happy": "愉快"
+    },
+    "category": {
+      "__name": "分类",
+      "museum": "文博",
+      "estate": "地产",
+      "eshop": "电商",
+      "catering": "餐饮",
+      "home": "家居",
+      "other": "其他"
+    },
+    "uploads": {
+      "__name": "文件上传",
+      "uploading": "上传中",
+      "uploaded": "已上传",
+      "wait": "等待上传...",
+      "error": "上传出错",
+      "add": "添加文件",
+      "start": "开始上传",
+      "file_require": "请添加文件",
+      "cant_upload": "您的浏览器不支持上传文件",
+      "not_support": "您选择的不是浏览器支持的{fileType}文件,请重新选择",
+      "too_large": "文件过大,不能大于{size}MB",
+      "too_large_reupload_tips": "上传视频过大,请重新上传"
+    },
+    "tips": {
+      "__name": "提示",
+      "wait": "请等待..."
+    }
+  },
+  "tips": {
+    "__name": "弹窗、提示",
+    "title": "提示",
+    "set_done": "设置成功",
+    "set_fail": "设置失败",
+    "save_done": "保存成功",
+    "save_fail": "保存失败",
+    "delete": "是否删除?",
+    "delete_done": "删除成功",
+    "delete_fail": "删除失败",
+    "upload_done": "上传成功",
+    "upload_fail": "上传失败",
+    "exception": "异常错误",
+    "network_error": "网络连接失败,请稍后再试",
+    "file_notfound": "文件不存在",
+    "scene_notfound": "场景不存在",
+    "params_notfound": "缺少必要参数",
+    "camera_notfound": "找不到该场景对应的相机",
+    "password_error": "密码错误",
+    "data_error": "数据不正常",
+    "auth_deny": "无权操作该场景",
+    "clear": "是否清空?",
+    "upload_pic_fail": "上传图片失败",
+    "wait": "请稍后...",
+    "house_type_save_fail": "户型保存失败"
+  },
+  "show": {
+    "__name": "展示页面",
+    "on": "开启",
+    "off": "关闭",
+    "measure": "测距工具",
+    "measure_start": "起点",
+    "measure_end": "终点",
+    "measure_button": "确定{status}",
+    "location_up": "上方",
+    "location_left": "左侧",
+    "location_start_tips": "请先在{direction}点击",
+    "location_end_tips": "起点确定完毕,请定位终点",
+    "vr": "VR模式",
+    "share": "分享",
+    "music": "{status}音乐",
+    "password_tips": "密码",
+    "password_require": "请输入密码"
+  },
+  "components": {
+    "user_guid": {
+      "__name": "用户引导",
+      "title": "操作提示",
+      "pano": "行走<br />点击任意方向移动",
+      "rotate": "旋转视角<br />左右滑动屏幕,旋转视觉",
+      "zoom": "缩放<br />双指滑动放大或缩小视图",
+      "set": "我知道了"
+    }
+  },
+  "material": {
+    "works": {
+      "my": "我的作品",
+      "create": "创建作品",
+      "search": "搜索作品",
+      "preview": "查看",
+      "edit": "编辑",
+      "share": "分享",
+      "delete": "删除",
+      "no_works": "您还没有作品,请先创建作品~",
+      "work_link": "作品链接",
+      "work_qrCode": "作品二维码",
+      "download_qrCode": "下载二维码",
+      "copy_link": "复制链接",
+      "work_preview": "查看作品",
+      "new_blank": "新窗口打开",
+      "cancel": "取消",
+
+      "no_link": "链接未生成,请编辑作品添加素材",
+      "had_created": "您已成功创建作品!",
+      "goto_preview": "查看",
+      "continue_edit": "继续编辑",
+      "had_created_but_no_link": "已成功新建作品,但刷新作品列表失败,请稍后手动刷新。",
+      "delete_work": "删除作品",
+      "comfirm_delete": "确定要删除作品吗?"
+
+      
+      
+    },
+    
+    "components":{
+      "prev":"上一张",
+      "next":"下一张",
+      "zoom_in":"放大",
+      "zoom_out":"缩小",
+      "delete":"删除",
+      "fullscreen":"全屏",
+      "cancel_fullscreen":"取消全屏",
+      "pano_setting":"全景图封面设置",
+      "drag_to_cut":"拖动画面截取封面",
+      "cutting":"截图",
+      "preview_cover":"封面预览",
+      "rename_material":"重命名素材"
+    }
+  },
+  "gather": {
+    "select_material": "选择素材",
+    "no_title": "无标题",
+    "name": "四维全景",
+    "editpage_name": "四维全景编辑器",
+    "my_works": "我的作品",
+    "my_material": "我的素材",
+    "panorama": "全景图",
+    "image": "图片",
+    "audio": "音频",
+    "video": "视频",
+    "scene": "三维场景",
+    "keywords": "输入关键词",
+    "how_to_shoot": "如何拍摄三维场景",
+    "pano_size": "请上传2:1、120MB以内、jpg格式的图片",
+    "cancel": "取消",
+    "comfirm": "确定",
+    "pano_fail": "格式错误,请上传2:1、120MB以内、jpg格式的全景图片",
+    "pano_limit": "过大,请上传2:1、120MB以内、jpg格式的全景图片",
+    "edit_cover": "编辑封面",
+    "img_fail": "格式错误,请上传10MB以内、jpg/png格式的图片",
+    "img_limit": "过大,请上传10MB以内、jpg/png格式的图片",
+    "img_size": "请上传10MB以内、jpg/png格式的图片",
+    "audio_size": "请上传20MB以内、mp3格式的音频",
+    "audio_limit": "过大,请上传20MB以内、mp3格式的音频",
+    "audio_fail": "格式错误,请上传20MB以内、mp3格式的音频",
+    "upload_material": "上传素材",
+    "video_size": "请上传200MB以内、mp4格式的视频",
+    "video_limit": "过大,请上传200MB以内、mp4格式的视频",
+    "video_fail": "格式错误,请上传200MB以内、mp4格式的视频",
+    "serch_material": "搜索素材",
+    "rename": "重命名",
+    "delete": "删除",
+    "no_serch_result": "未搜索到结果",
+    "no_material_result": "暂无素材~",
+    "had_load": "已加载{msg}条",
+    "uploading": "正在上传 {msg}",
+    "success": "操作成功",
+    "delete_success": "删除成功",
+    "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": "个人中心",
+    "logout": "退出登录",
+    "login": "登录",
+    "register": "注册"
+  },
+  "edit_page": {
+    "back_myworks": "返回我的作品",
+    "preview": "查看",
+    "settings": "基础",
+    "navigation": "导航",
+    "viewpoint": "视角",
+    "hotspot": "热点",
+    "explanation": "讲解",
+    "save": "保存"
+  },
+  "edit_settings": {
+    "auto_pano": "自动巡游",
+    "enter_auto": "进入全景图自动巡游(3分钟完整巡游一次)",
+    "set_bgm": "设置背景音乐",
+    "add_audio": "添加音频",
+    "change_audio": "更换音频",
+    "custom_button": "自定义按钮",
+    "custom_button_tips": "自定义按钮可为作品添加联系方式或网站链接等,设置可见后即可在作品显示。",
+    "edit": "编辑",
+    "hide": "隐藏",
+    "show": "显示",
+    "button_name": "按钮名称",
+    "button_placeholder": "请输入按钮名称",
+    "please_input": "请输入",
+    "phone": "电话号码",
+    "link": "链接地址",
+    "phone_short": "电话",
+    "link_short": "链接",
+    "custom_logo": "自定义LOGO",
+    "show_logo": "显示LOGO",
+    "logo_size": "300*300px,600kb以内,支持<br>jpg/png格式",
+    "mask_setting": "遮罩设置",
+    "sky_mask": "天空遮罩",
+    "sky_tips": "天空遮罩显示在场景的顶部,地面遮罩显示在场景的底部。",
+    "mask_size": "建议500*500px,<br/>支持jpg/png格式",
+    "bottom_mask": "地面遮罩",
+    "opening_setting": "设置开场动画",
+    "opening_tips_setting": "提示设置",
+    "opening_tips": "开场提示仅适用于全景图。若初始场景为三维模\n型,以下开场提示不适用。",
+    "pc": "PC端",
+    "mobile": "移动端",
+    "select_image": "选择图片",
+    "opening_size": "建议300*300px,600kb以内,<br/>支持jpg/png格式",
+    "show_setting": "显示设置",
+    "first_notice": "仅首次打开链接时,提示",
+    "password_setting": "设置访问密码",
+    "password_placeholder": "请输入访问密码,限20位",
+    "base_setting": "基础设置",
+    "setting_cover": "设置封面",
+    "cover_size": "512*512px,支持jpg/png格式",
+    "title": "标题",
+    "description": "简介",
+    "work_placeholder": "请输入作品标题",
+    "intro_placeholder": "请输入文字内容,限500字",
+    "help_center": "帮助中心",
+    "display_time": "显示时间",
+    "no_display": "(不显示)",
+    "second": "秒"
+  },
+  "zh_key": {
+    "电话": "电话",
+    "链接": "链接",
+    "小行星开场": "小行星开场",
+    "小行星巡游开场": "小行星巡游开场",
+    "小行星缩放开场": "小行星缩放开场",
+    "水平巡游开场": "水平巡游开场",
+    "水晶球开场": "水晶球开场",
+    "开场提示": "开场提示",
+    "开场动画": "开场动画",
+    "访问密码": "访问密码",
+    "自动巡游": "自动巡游",
+    "背景音乐": "背景音乐",
+    "自定义LOGO": "自定义LOGO",
+    "自定义遮罩": "自定义遮罩",
+    "自定义按钮": "自定义按钮",
+
+    "素材": "素材",
+    "名称": "名称",
+    "大小": "大小",
+    "分辨率": "分辨率",
+    "创建时间": "创建时间",
+    "修改时间": "修改时间",
+
+    "封面": "封面",
+    "场景标题": "场景标题",
+    "拍摄时间": "拍摄时间",
+
+    "一级分组":"一级分组",
+    "二级分组":"二级分组",
+    "默认二级分组":"默认二级分组"
+
+
+
+  },
+  "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}已存在,不可重复添加"
+  },
+  "screen": {
+    "init_screen": "初始画面",
+    "screen_tips": "初始画面为进入场景时第一画面,请拖动全景图选择合适的画面设置。",
+    "setting_screen": "将当前视角设为初始画面"
+  },
+  "hotspot": {
+    "img_size":"最多添加20张图片",
+    "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": "更换视频"
+  },
+  "explanation": {
+    "explanation_settings": "语音讲解",
+    "explanation_tips": "您可以为当前全景图添加语音讲解音频。",
+    "add_audio": "添加音频",
+    "change_audio": "更换音频",
+    "default_open": "默认开启",
+    "loop": "循环播放"
+  },
+  "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": "加载失败"
+  }
+}

+ 2 - 2
packages/qjkankan-editor/src/lang/index.js

@@ -1,7 +1,7 @@
 import Vue from 'vue'
 import VueI18n from 'vue-i18n'
-import zh from './_zh'
-import en from './_en'
+import zh from './_zh.json'
+import en from './_en.json'
 import config from '@/config'
 import browser from '@/utils/browser'
 

+ 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 = [];
 

+ 2 - 0
packages/qjkankan-editor/src/pages/Edit.vue

@@ -17,6 +17,8 @@ export default {
     ]),
   },
   mounted() {
+    document.title = this.$i18n.t('gather.editpage_name')
+
     window.addEventListener('beforeunload', (e) => {
       if (this.isInfoChangedSinceSave) {
         e.preventDefault()

+ 1 - 0
packages/qjkankan-editor/src/pages/Material.vue

@@ -11,6 +11,7 @@ export default {
     AppLayout
   },
   mounted() {
+    document.title = this.$i18n.t('gather.name')
     window.addEventListener('keydown',  (event) =>{
       if (event.keyCode === 27) {
         this.$bus.emit('clickEsc')

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

@@ -9,6 +9,7 @@ import { showLoginTips } from '@/utils/request'
 import { Button } from 'element-ui';
 import '@/directives/vTitleInManageCenter.js'
 import '@/directives/vTooltipInManageCenter.js'
+import { i18n } from "@/lang"
 
 Vue.component(Button.name, Button);
 
@@ -35,5 +36,6 @@ window.addEventListener('storage', () => {
 new Vue({
   router,
   store,
+  i18n,
   render: h => h(App)
 }).$mount('#app')

+ 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')

+ 4 - 1
packages/qjkankan-editor/src/router/editorRouter.js

@@ -4,6 +4,9 @@ import { PCMenu } from "../config/menu.js";
 import { checkWork, checkLogin, getPanoInfo } from '@/api'
 import store from '../Store'
 
+import {i18n} from '@/lang'
+
+
 let vue = new Vue()
 
 import { LoginDetector,OnlineDetector } from "@/utils/starter";
@@ -79,7 +82,7 @@ router.beforeEach(async (to, from, next) => {
     if (from.name == 'hotspot') {
       if (store.getters.isEditing) {
         vue.$confirm({
-            content: "热点内容未编辑完,确定要关闭吗",
+            content: i18n.t('hotspot.close_dialog'),
             ok: () => {
               vue.$bus.emit('delhotspot') 
              return next()

+ 1 - 1
packages/qjkankan-editor/src/router/index.js

@@ -79,7 +79,7 @@ router.beforeEach(async (to, from, next) => {
     if (from.name == 'hotspot') {
       if (store.getters.isEditing) {
         vue.$confirm({
-            content: "热点内容未编辑完,确定要关闭吗",
+            content: vue.$i18n.t('hotspot.close_dialog'),
             ok: () => {
               vue.$bus.emit('delhotspot') 
              return next()

+ 1 - 1
packages/qjkankan-editor/src/router/material.js

@@ -28,7 +28,7 @@ const router = new Router({
 
 router.beforeEach(async (to, from, next) => {
   if (to.path == '/') {
-      return next({path: "/pano" })
+      return next({path: "/works" })
   }
   next()
 })

+ 3 - 1
packages/qjkankan-editor/src/utils/other.js

@@ -75,7 +75,9 @@ export function debounce(fn, delay, isImmediateCall = false) {
 ④12345678
  */
 export function isValidPhoneNumber(value) {
-  const reg = /^1\d{10}$|^(0\d{2,3}-?|\(0\d{2,3}\))?[1-9]\d{4,7}(-\d{1,8})?$/
+  const reg = /^1\d{10}$|^400[0-9]{7}|^(0\d{2,3}-?|\(0\d{2,3}\))?[1-9]\d{4,7}(-\d{1,8})?$/
+  // const reg = /^400[0-9]{7}|^1[34578]\d{9}$|^0[0-9]{2,3}-[0-9]{8}/
+
   return reg.test(value)
 }
 

+ 32 - 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,57 @@ 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.FAILURE_3011') });
+    return false
+  }
+  if (result.code == statusCode.FAILURE_CODE_3011) {
+    $alert({ content: i18n.t('tips_code.FAILURE_3011') });
     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_3101) {
+    $alert({ content: i18n.t('tips_code.FAILURE_3101') });
     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 +178,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 +211,7 @@ $.ajaxSetup({
     }
     __showNetworkError = true;
     $alert({
-      content: "网络异常,请稍后再试",
+      content: i18n.t('tips_code.FAILURE_error'),
       forceOK: true,
       ok: () => {
         __showNetworkError = false;
@@ -245,7 +238,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 +453,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() {

+ 11 - 12
packages/qjkankan-editor/src/views/base/Toolbar.vue

@@ -2,18 +2,18 @@
   <!-- 编辑器-基础-中间部分 -->
   <div class="app-view-toolbar app-view-full-toolbar">
     <div class="main">
-      <div class="ui-title-big">基础设置</div>
+      <div class="ui-title-big">{{$i18n.t(`edit_settings.base_setting`)}}</div>
       <div class="upload-con">
         <div class="uc-l">
           <div class="preview">
             <img :src="info.icon || require('@/assets/images/default/img_cover_default_2.png')" alt="" />
-            <button class="ui-button submit setting-cover-btn" @click="onClickSettingCover">设置封面</button>
+            <button class="ui-button submit setting-cover-btn" @click="onClickSettingCover">{{$i18n.t(`edit_settings.setting_cover`)}}</button>
           </div>
-          <div class="ui-remark">512*512px,支持jpg/png格式</div>
+          <div class="ui-remark" v-html="$i18n.t(`edit_settings.cover_size`)"></div>
         </div>
         <div class="uc-r">
           <div class="ui-title">
-            <span class="">标题</span>
+            <span class="">{{$i18n.t(`edit_settings.title`)}}</span>
           </div>
           <div class="title-input-wrapper">
             <input
@@ -23,11 +23,11 @@
               type="text"
               autocomplete="new-password"
               maxlength="50"
-              placeholder="请输入作品标题"
+              :placeholder="$i18n.t(`edit_settings.work_placeholder`)"
             />
             <span class="count">{{titleLength}}/50</span>
           </div>
-          <div class="ui-title jianjie"><span>简介</span></div>
+          <div class="ui-title jianjie"><span>{{$i18n.t(`edit_settings.description`)}}</span></div>
           <div class="jianjie-textarea-wrapper">
             <!-- <textarea
               v-model.trim="info.description"
@@ -36,7 +36,7 @@
               type="text"
             /> -->
 
-            <editor ref="editor" :html="info.description" :placeholder="'请输入文字内容,限500字'" :maxlength="500" @change="onEditorChange"></editor>
+            <editor ref="editor" :html="info.description" :placeholder="$i18n.t(`edit_settings.intro_placeholder`)" :maxlength="500" @change="onEditorChange"></editor>
 
             <span class="count">{{jianjieLength}}/500</span>
           </div>
@@ -49,7 +49,7 @@
           :class="{active: activeTab === item}"
           @click="activeTab = item"
         >
-          {{item}}
+        {{$i18n.t(`zh_key.${item}`)}}
         </li>
       </menu>
       <div class="settings-view-wrapper">
@@ -67,7 +67,7 @@
     <div class="dialog" style="z-index: 2000" v-if="isShowSettingCoverWindow">
       <MaterialSelectorForEditor
         :selectableType="['image', 'pano', '3D']"
-        title="选择素材"
+        :title="$i18n.t(`gather.select_material`)"
         @cancle="isShowSettingCoverWindow = false"
         @submit="onCoverSelected"
       />
@@ -141,7 +141,6 @@ export default {
       });
     },
     onEditorChange(content){
-      console.log(content);
       this.info.description = content.html
       this.jianjieLength = content.size
     },
@@ -267,7 +266,7 @@ export default {
 
 menu {
   display: inline-block;
-  width: 133px;
+  width: 168px;
   font-size: 14px;
   color: rgba(255, 255, 255, 0.5);
   padding-left: 0;
@@ -306,7 +305,7 @@ menu {
 .settings-view-wrapper {
   vertical-align: top;
   display: inline-block;
-  width: 797px;
+  width: 762px;
 
 }
 </style>

+ 154 - 118
packages/qjkankan-editor/src/views/base/customButtonSettings.vue

@@ -1,72 +1,51 @@
 <template>
   <div class="custom-button-settings">
-    <span class="title">自定义按钮</span>
+    <span class="title">{{ custom_button }}</span>
 
 
-    <i class="iconfont icon-material_prompt tool-tip-for-editor" v-tooltip="'自定义按钮可为作品添加联系方式或网站链接等,设置可见后即可在作品显示。'">
+    <i class="iconfont icon-material_prompt tool-tip-for-editor" v-tooltip="custom_button_tips">
     </i>
-    <br/>
-    
-    <div v-for="(item, index) of info.customButton" :key="index" class="button-setting-item" :class="{expand: expandStatus[index]}">
-      <div
-        class="title-bar"
-        :class="info.customButton[index].isShow ? 'bright' : 'dark'"
-        @click="onRequestForChangeExpandStatus(index)"
-      >
+    <br />
+
+    <div v-for="(item, index) of info.customButton" :key="index" class="button-setting-item"
+      :class="{ expand: expandStatus[index] }">
+      <div class="title-bar" :class="info.customButton[index].isShow ? 'bright' : 'dark'"
+        @click="onRequestForChangeExpandStatus(index)">
         <div class="left">
-          <i
-            class="iconfont icon-edit_input_arrow icon-expand"
-          ></i>
-          <img v-if="info.customButton[index].type === '电话' && info.customButton[index].isShow" :src="require('@/assets/images/icons/phone.svg')" class="button-icon" alt="">
-          <img v-if="info.customButton[index].type === '电话' && !info.customButton[index].isShow" :src="require('@/assets/images/icons/phone-dark.svg')" class="button-icon" alt="">
-          <img v-if="info.customButton[index].type === '链接' && info.customButton[index].isShow" :src="require('@/assets/images/icons/link.svg')" class="button-icon" alt="">
-          <img v-if="info.customButton[index].type === '链接' && !info.customButton[index].isShow" :src="require('@/assets/images/icons/link-dark.svg')" class="button-icon" alt="">
+          <i class="iconfont icon-edit_input_arrow icon-expand"></i>
+          <img v-if="info.customButton[index].type === '电话' && info.customButton[index].isShow"
+            :src="require('@/assets/images/icons/phone.svg')" class="button-icon" alt="">
+          <img v-if="info.customButton[index].type === '电话' && !info.customButton[index].isShow"
+            :src="require('@/assets/images/icons/phone-dark.svg')" class="button-icon" alt="">
+          <img v-if="info.customButton[index].type === '链接' && info.customButton[index].isShow"
+            :src="require('@/assets/images/icons/link.svg')" class="button-icon" alt="">
+          <img v-if="info.customButton[index].type === '链接' && !info.customButton[index].isShow"
+            :src="require('@/assets/images/icons/link-dark.svg')" class="button-icon" alt="">
           <span class="button-name">
-            {{info.customButton[index].name}}
+            {{ buttonName[index] }}
+            <!-- {{ info.customButton[index].name  }} -->
           </span>
         </div>
         <div class="right">
-          <i
-            class="iconfont icon-editor_list_edit btn-edit"
-            @click.stop="onRequestForEdit(index)"
-            v-tooltip="'编辑'"
-          >
+          <i class="iconfont icon-editor_list_edit btn-edit" @click.stop="onRequestForEdit(index)" v-tooltip="edittips">
           </i>
-          <i
-            v-show="info.customButton[index].isShow"
-            class="iconfont icon-editor_on btn-show"
-            v-tooltip="'隐藏'"
-            @click.stop="info.customButton[index].isShow = false"
-          ></i>
-          <i
-            v-show="!info.customButton[index].isShow"
-            class="iconfont icon-editor_off btn-hide"
-            v-tooltip="'显示'"
-            @click.stop="onRequestForShow(index)"
-          ></i>
+          <i v-show="info.customButton[index].isShow" class="iconfont icon-editor_on btn-show" v-tooltip="hidetips"
+            @click.stop="info.customButton[index].isShow = false"></i>
+          <i v-show="!info.customButton[index].isShow" class="iconfont icon-editor_off btn-hide" v-tooltip="showtips"
+            @click.stop="onRequestForShow(index)"></i>
         </div>
       </div>
       <div class="edit-content">
         <div class="edit-content-item">
-          <span class="item-name">按钮名称</span>
-          <PulldownMenuInEditor
-            class="selector"
-            :valueList="buttonTypeList"
-            v-model="info.customButton[index].type"
-          ></PulldownMenuInEditor>
-          <input
-            class="name-input"
-            placeholder="请输入按钮名称"
-            v-model="info.customButton[index].name"
-            maxlength="15"
-          >
+          <span class="item-name">{{ button_name }}</span>
+          <PulldownMenuInEditor class="selector" :valueList="buttonTypeList" v-model="info.customButton[index].type">
+          </PulldownMenuInEditor>
+          <input class="name-input" :placeholder="button_placeholder" v-model="info.customButton[index].name"
+            maxlength="15">
         </div>
         <div class="edit-content-item">
-          <span class="item-name">{{buttonValueTips[index]}}</span>
-          <input
-            class="value-input"
-            v-model="info.customButton[index].value"
-          >
+          <span class="item-name">{{ buttonValueTips[index] }}</span>
+          <input class="value-input" v-model="info.customButton[index].value">
         </div>
       </div>
     </div>
@@ -74,7 +53,7 @@
     <popup v-if="isEditing" :canClose="false">
       <div class="ui-message ui-message-confirm dark edit-window">
         <div class="ui-message-header">
-          <span>自定义按钮</span>
+          <span>{{ custom_button }}</span>
           <span @click="isEditing = false">
             <i class="iconfont icon_close"></i>
           </span>
@@ -82,38 +61,24 @@
 
         <div class="ui-message-main">
           <div class="edit-content-item">
-            <span class="item-name">按钮名称</span>
-            <PulldownMenuInEditor
-              class="selector"
-              :valueList="buttonTypeList"
-              v-model="editingInfo.type"
-            ></PulldownMenuInEditor>
-            <input
-              class="name-input"
-              placeholder="请输入按钮名称"
-              v-model="editingInfo.name"
-              maxlength="15"
-            >
+            <span class="item-name">{{ button_name }}</span>
+            <PulldownMenuInEditor class="selector" :valueList="buttonTypeList" v-model="editingInfo.type">
+            </PulldownMenuInEditor>
+            <input class="name-input" :placeholder="button_placeholder" v-model="editingInfo.name" maxlength="15">
           </div>
           <div class="edit-content-item">
-            <span class="item-name">{{editingButtonValueTip}}</span>
-            <input
-              class="value-input"
-              :placeholder="`请输入${editingButtonValueTip}`"
-              v-model="editingInfo.value"
-            >
+            <span class="item-name">{{ editingButtonValueTip }}</span>
+            <input class="value-input" :placeholder="`${please_input}${editingButtonValueTip}`"
+              v-model="editingInfo.value">
           </div>
         </div>
 
         <div class="ui-message-footer">
           <button class="ui-button deepcancel" @click="isEditing = false">
-            取消
+            {{ canceltips }}
           </button>
-          <button
-            class="ui-button submit"
-            @click="onConfirmEditing"
-          >
-            确定
+          <button class="ui-button submit" @click="onConfirmEditing">
+            {{ comfirmtips }}
           </button>
         </div>
       </div>
@@ -126,6 +91,8 @@ import { mapGetters } from "vuex";
 import PulldownMenuInEditor from "@/components/pulldownMenuInEditor.vue";
 import { isValidPhoneNumber } from "@/utils/other.js";
 import Popup from "@/components/shared/popup/index.vue";
+import { i18n } from "@/lang"
+
 
 export default {
   components: {
@@ -134,6 +101,18 @@ export default {
   },
   data() {
     return {
+      custom_button: i18n.t("edit_settings.custom_button"),
+      custom_button_tips: i18n.t("edit_settings.custom_button_tips"),
+      edittips: i18n.t("edit_settings.edit"),
+      hidetips: i18n.t("edit_settings.hide"),
+      showtips: i18n.t("edit_settings.show"),
+      button_name: i18n.t("edit_settings.button_name"),
+      button_placeholder: i18n.t("edit_settings.button_placeholder"),
+      please_input: i18n.t("edit_settings.please_input"),
+
+      canceltips: i18n.t("gather.cancel"),
+      comfirmtips: i18n.t("gather.comfirm"),
+
       expandStatus: [],
       buttonTypeList: [
         '电话',
@@ -151,15 +130,31 @@ export default {
   },
   computed: {
     ...mapGetters({
-      info:'info'
+      info: 'info'
     }),
     buttonValueTips() {
-      if (this?.info?.customButton) {
+      if (this.info.customButton) {
         return this.info.customButton.map((item) => {
           if (item.type === '电话') {
-            return '电话号码'
+            return i18n.t("edit_settings.phone")
           } else if (item.type === '链接') {
-            return '链接地址'
+            return i18n.t("edit_settings.link")
+          } else {
+            return ''
+          }
+        })
+      } else {
+        return null
+      }
+    },
+
+    buttonName() {
+      if (this.info.customButton) {
+        return this.info.customButton.map((item) => {
+          if (item.type === '电话') {
+            return i18n.t("edit_settings.phone_short")
+          } else if (item.type === '链接') {
+            return i18n.t("edit_settings.link_short")
           } else {
             return ''
           }
@@ -170,9 +165,9 @@ export default {
     },
     editingButtonValueTip() {
       if (this.editingInfo.type === '电话') {
-        return '电话号码'
+        return i18n.t("edit_settings.phone")
       } else if (this.editingInfo.type === '链接') {
-        return '链接地址'
+        return i18n.t("edit_settings.link")
       } else {
         return ''
       }
@@ -182,7 +177,8 @@ export default {
     'editingInfo.type': {
       handler(vNew) {
         if (!this.isIgnoreTypeChangeWhenEditing) {
-          this.editingInfo.name = vNew
+          console.log(vNew);
+          this.editingInfo.name = i18n.t(`zh_key.${vNew}`)
           this.editingInfo.value = ''
         }
         this.isIgnoreTypeChangeWhenEditing = false
@@ -222,7 +218,7 @@ export default {
     },
     checkButtonName(name) {
       if (!name) {
-        this.$msg.warning('请填写完整信息')
+        this.$msg.warning(i18n.t('gather.fill_complete'))
         return false
       }
       return true
@@ -230,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
         }
       }
@@ -248,10 +244,10 @@ export default {
       if (!this.checkButtonValue(this.editingInfo.value, this.editingInfo.type)) {
         return
       }
-      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.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(i18n.t('gather.success'))
       this.isEditing = false
     },
     onRequestForShow(index) {
@@ -263,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>
 
@@ -272,10 +273,12 @@ export default {
   padding: 24px 30px;
   background: #252526;
   height: 546px;
+
   .title {
     font-size: 18px;
     color: #FFFFFF;
   }
+
   .tool-tip-for-editor {
     margin-left: 4px;
     font-size: 12px;
@@ -283,11 +286,13 @@ export default {
     position: relative;
     top: -2px;
   }
-  > .button-setting-item {
+
+  >.button-setting-item {
     margin-top: 16px;
     position: relative;
     min-height: 50px;
-    > .title-bar {
+
+    >.title-bar {
       position: absolute;
       width: 100%;
       height: 50px;
@@ -299,77 +304,95 @@ export default {
       align-items: center;
       padding: 0 16px;
       cursor: pointer;
+
       &.bright {
         color: #fff;
       }
+
       &.dark {
         color: #808080;
       }
-      > .left {
+
+      >.left {
         display: flex;
         align-items: center;
-        > .icon-expand {
+
+        >.icon-expand {
           font-size: 10px;
           color: rgba(255, 255, 255, 0.6);
           transform: rotate(-90deg);
           cursor: pointer;
         }
-        > .button-icon {
+
+        >.button-icon {
           width: 18px;
           height: 18px;
           margin-left: 6px;
         }
-        > .button-name {
+
+        >.button-name {
           font-size: 16px;
           margin-left: 6px;
         }
       }
-      > .right {
+
+      >.right {
         display: flex;
         align-items: center;
+
         i.btn-edit {
           margin-left: 16px;
           cursor: pointer;
+
           &:hover {
             color: #0076F6;
           }
         }
-        > .btn-show {
+
+        >.btn-show {
           margin-left: 16px;
           cursor: pointer;
+
           &:hover {
             color: #0076F6;
           }
         }
-        > .btn-hide {
+
+        >.btn-hide {
           margin-left: 16px;
           cursor: pointer;
+
           &:hover {
             color: #0076F6;
           }
         }
       }
     }
-    > .edit-content {
+
+    >.edit-content {
       border-radius: 2px;
       border: 1px solid #404040;
       padding-top: 58px;
       padding-bottom: 26px;
       display: none;
       pointer-events: none;
-      > .edit-content-item {
+
+      >.edit-content-item {
         margin-top: 16px;
         display: flex;
         align-items: center;
-        > .item-name {
+
+        >.item-name {
           margin-left: 16px;
           font-size: 14px;
           color: rgba(255, 255, 255, 0.5)
         }
-        > .selector {
+
+        >.selector {
           margin-left: 16px;
         }
-        > .name-input {
+
+        >.name-input {
           height: 36px;
           background: transparent;
           border-radius: 2px;
@@ -379,11 +402,13 @@ export default {
           padding: 0 16px;
           letter-spacing: 1px;
           width: 470px;
+
           &:focus {
             border-color: #0076F6;
           }
         }
-        > .value-input {
+
+        >.value-input {
           margin-left: 16px;
           height: 36px;
           background: transparent;
@@ -394,6 +419,7 @@ export default {
           padding: 0 16px;
           letter-spacing: 1px;
           width: 610px;
+
           &:focus {
             border-color: #0076F6;
           }
@@ -401,36 +427,43 @@ export default {
       }
     }
   }
-  > .button-setting-item.expand {
-    > .title-bar {
-      > .left {
-        > .icon-expand {
+
+  >.button-setting-item.expand {
+    >.title-bar {
+      >.left {
+        >.icon-expand {
           transform: rotate(0deg);
         }
       }
     }
-    > .edit-content {
+
+    >.edit-content {
       display: block;
     }
   }
 
   .edit-window {
     width: 574px;
-    > .ui-message-main {
+
+    >.ui-message-main {
       margin-bottom: 40px;
-      > .edit-content-item {
+
+      >.edit-content-item {
         margin-top: 16px;
         display: flex;
         align-items: center;
-        > .item-name {
+
+        >.item-name {
           flex: 0 0 auto;
           font-size: 14px;
           color: rgba(255, 255, 255, 0.5)
         }
-        > .selector {
+
+        >.selector {
           margin-left: 16px;
         }
-        > .name-input {
+
+        >.name-input {
           height: 36px;
           background: #252526;
           border-radius: 2px;
@@ -440,11 +473,13 @@ export default {
           padding: 0 16px;
           letter-spacing: 1px;
           width: 470px;
+
           &:focus {
             border-color: #0076F6;
           }
         }
-        > .value-input {
+
+        >.value-input {
           margin-left: 16px;
           height: 36px;
           background: #252526;
@@ -455,6 +490,7 @@ export default {
           padding: 0 16px;
           letter-spacing: 1px;
           width: 610px;
+
           &:focus {
             border-color: #0076F6;
           }

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

@@ -1,21 +1,21 @@
 <template>
   <div class="custom-logo-settings">
-    <span class="title">自定义LOGO</span>
+    <span class="title">{{$i18n.t(`edit_settings.custom_logo`)}}</span>
     <br>
     <div class="switch-wrapper">
-      <span class="label">显示LOGO</span>
+      <span class="label">{{$i18n.t(`edit_settings.show_logo`)}}</span>
       <Switcher :value="info.isLogo" @change="onSwitcherChange"></Switcher>
     </div>
     <div class="bottom" :class="{disabled: !info.isLogo}">
         <SelectedImage
           :imgSrc="info.logo"
-          :defaultImgSrc="require('@/assets/images/default/logo_white.svg')"
+          :defaultImgSrc="require(`@/assets/images/default/logo_white_${$lang}.svg`)"
           @cancel="onClickCancelCustomLogo"
         ></SelectedImage>
       <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
@@ -24,16 +24,14 @@
         >
           选择图片
         </button> -->
-        <div class="remark">
-          300*300px,600kb以内,支持<br>
-          jpg/png格式
+        <div class="remark" v-html="$i18n.t(`edit_settings.logo_size`)">
         </div>
       </div>
     </div>
 
     <div class="dialog" style="z-index: 2000" v-if="isShowSelectionWindow">
       <MaterialSelectorForEditor
-        title="选择素材"
+        :title="$i18n.t(`gather.select_material`)"
         @cancle="isShowSelectionWindow = false"
         @submit="handleSubmitFromMaterialSelector"
         :selectableType="['image']"

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

@@ -1,24 +1,24 @@
 <template>
   <div class="custom-mask-settings">
-    <span class="title">遮罩设置</span>
-    <i class="iconfont icon-material_prompt tool-tip-for-editor" v-tooltip="'天空遮罩显示在场景的顶部,地面遮罩显示在场景的底部。'">
+    <span class="title">{{$i18n.t(`edit_settings.mask_setting`)}}</span>
+    <i class="iconfont icon-material_prompt tool-tip-for-editor" v-tooltip="$i18n.t(`edit_settings.sky_tips`)">
     </i>
     <br>
     <div class="image-selection">
       <div class="title">
-        <span class="label">天空遮罩</span>
+        <span class="label">{{$i18n.t(`edit_settings.sky_mask`)}}</span>
         <Switcher :value="info.customMask.sky.isShow" @change="(data)=>{info.customMask.sky.isShow=data}"></Switcher>
       </div>
       <div class="bottom">
         <SelectedImage
           :imgSrc="info && info.customMask && info.customMask.sky.icon"
-          :defaultImgSrc="require('@/assets/images/default/mask_bg.png')"
+          :defaultImgSrc="require(`@/assets/images/default/mask_bg_${$lang}.png`)"
           @cancel="onCancelSelection('sky')"
         ></SelectedImage>
         <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
@@ -27,25 +27,25 @@
           >
             选择图片
           </button> -->
-          <div class="ui-remark">建议500*500px,<br/>支持jpg/png格式</div>
+          <div class="ui-remark" v-html="$i18n.t(`edit_settings.mask_size`)"></div>
         </div>
       </div>
     </div>
     <div class="image-selection">
       <div class="title">
-        <span class="label">地面遮罩</span>
+        <span class="label">{{$i18n.t(`edit_settings.bottom_mask`)}}</span>
         <Switcher :value="info.customMask.earth.isShow"  @change="(data)=>{info.customMask.earth.isShow=data}"></Switcher>
       </div>
       <div class="bottom">
         <SelectedImage
           :imgSrc="info && info.customMask && info.customMask.earth.icon"
-          :defaultImgSrc="require('@/assets/images/default/mask_bg.png')"
+          :defaultImgSrc="require(`@/assets/images/default/mask_bg_${$lang}.png`)"
           @cancel="onCancelSelection('earth')"
         ></SelectedImage>
         <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
@@ -54,14 +54,14 @@
           >
             选择图片
           </button> -->
-          <div class="ui-remark">建议500*500px,<br/>支持jpg/png格式</div>
+          <div class="ui-remark" v-html="$i18n.t(`edit_settings.mask_size`)"></div>
         </div>
       </div>
     </div>
 
     <div class="dialog" style="z-index: 2000" v-if="isShowSelectionWindow">
       <MaterialSelectorForEditor
-        title="选择素材"
+        :title="$i18n.t(`gather.select_material`)"
         @cancle="isShowSelectionWindow = false"
         @submit="handleSubmitFromMaterialSelector"
         :selectableType="['image']"

+ 3 - 3
packages/qjkankan-editor/src/views/base/openingAnimationSettings.vue

@@ -1,13 +1,13 @@
 <template>
   <div class="opening-animation-settings">
-    <span class="title">设置开场动画</span>
+    <span class="title">{{$i18n.t(`edit_settings.opening_setting`)}}</span>
     <br>
     <div class="btns-and-video">
       <div class="btn-wrapper">
         <button v-for="item of openingTypeList" :key="item" class="opening-selection-btn"
           :class="{ 'active-opening-type': info.openingAnimationType === item }"
           @click="info.openingAnimationType = item">
-          {{ item }}
+          {{$i18n.t(`zh_key.${item}`)}}
         </button>
       </div>
       <div class="video-wrapper">
@@ -85,7 +85,7 @@ export default {
 
     .btn-wrapper {
       .opening-selection-btn {
-        width: 180px;
+        width: 210px;
         height: 40px;
         background: #1A1B1D;
         border-radius: 2px;

+ 14 - 13
packages/qjkankan-editor/src/views/base/openingTipSettings.vue

@@ -1,11 +1,11 @@
 <template>
   <div class="opening-tip-settings">
-    <span class="title">提示设置</span>
-    <i class="iconfont icon-material_prompt tool-tip-for-editor" v-tooltip="'开场提示仅适用于全景图。若初始场景为三维模\n型,以下开场提示不适用。'">
+    <span class="title">{{$i18n.t(`edit_settings.opening_tips_setting`)}}</span>
+    <i class="iconfont icon-material_prompt tool-tip-for-editor" v-tooltip="$i18n.t(`edit_settings.opening_tips`)">
     </i>
     <br>
     <div class="image-selection">
-      <div class="title">PC端</div>
+      <div class="title">{{$i18n.t(`edit_settings.pc`)}}</div>
       <div class="bottom">
         <SelectedImage
           :imgSrc="info.pcIcon"
@@ -13,13 +13,13 @@
           @cancel="onCancelPcTip"
         ></SelectedImage>
         <div class="bottom-right">
-          <button class="ui-button submit" @click="isShowSelectionWindow = true, selectingFor = 'pc'">选择图片</button>
-          <div class="ui-remark">建议300*300px,600kb以内,<br/>支持jpg/png格式</div>
+          <button class="ui-button submit" @click="isShowSelectionWindow = true, selectingFor = 'pc'">{{$i18n.t(`edit_settings.select_image`)}}</button>
+          <div class="ui-remark" v-html="$i18n.t(`edit_settings.opening_size`)"></div>
         </div>
       </div>
     </div>
     <div class="image-selection">
-      <div class="title">移动端</div>
+      <div class="title">{{$i18n.t(`edit_settings.mobile`)}}</div>
       <div class="bottom">
         <SelectedImage
           :imgSrc="info.appIcon"
@@ -27,15 +27,15 @@
           @cancel="onCancelAppTip"
         ></SelectedImage>
         <div class="bottom-right">
-          <button class="ui-button submit" @click="isShowSelectionWindow = true, selectingFor = 'mobile'">选择图片</button>
-          <div class="ui-remark">建议300*300px,600kb以内,<br/>支持jpg/png格式</div>
+          <button class="ui-button submit" @click="isShowSelectionWindow = true, selectingFor = 'mobile'">{{$i18n.t(`edit_settings.select_image`)}}</button>
+          <div class="ui-remark" v-html="$i18n.t(`edit_settings.opening_size`)"></div>
         </div>
       </div>
     </div>
 
-    <div class="title">显示设置</div>
+    <div class="title">{{$i18n.t(`edit_settings.show_setting`)}}</div>
     <div class="switch-wrapper">
-        <span class="label">仅首次打开链接时,提示</span>
+        <span class="label">{{$i18n.t(`edit_settings.first_notice`)}}</span>
         <switcher :value="info.isRemind" @change="onSwitcherChange"></switcher>
     </div>
     <div class="range-wrapper">
@@ -44,7 +44,7 @@
 
     <div class="dialog" style="z-index: 2000" v-if="isShowSelectionWindow">
       <MaterialSelectorForEditor
-        title="选择素材"
+        :title="$i18n.t(`gather.select_material`)"
         :isMultiSelection="false"
         @cancle="isShowSelectionWindow = false"
         @submit="handleSubmitFromMaterialSelector"
@@ -73,8 +73,8 @@ export default {
       isShowSelectionWindow: false,
       selectingFor: '', // 'pc', 'mobile'
       rang: {
-        label: '显示时间',
-        unit: "秒",
+        label: this.$i18n.t('edit_settings.display_time'),
+        unit: this.$i18n.t('edit_settings.second'),
         value: 1,
         min: 0,
         max: 3,
@@ -113,6 +113,7 @@ export default {
       this.info.isRemind = data
     },
     onRangeChange(data) {
+      console.log(data.value);
       this.info.remindTime = parseInt(data.value)
     },
   }

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

@@ -1,11 +1,11 @@
 <template>
   <div class="password-settings">
-    <span class="title">设置访问密码</span>
+    <span class="title">{{$i18n.t(`edit_settings.password_setting`)}}</span>
     <br>
     <div class="input-wrapper">
       <input
         :type="canSee ? 'text' : 'password'"
-        placeholder="请输入访问密码,限20位"
+        :placeholder="$i18n.t(`edit_settings.password_placeholder`)"
         :maxlength="20"
         v-model="info.password"
         autocomplete="new-password"

+ 7 - 7
packages/qjkankan-editor/src/views/explanation/explanationSettings.vue

@@ -1,8 +1,8 @@
 <template>
   <div class="explanation-settings"  app-border dir-left>
     <div class="title">
-      语音讲解
-      <i class="iconfont icon-material_prompt tool-tip-for-editor" v-tooltip="'您可以为当前全景图添加语音讲解音频。'"/>
+      {{$i18n.t("explanation.explanation_settings")}}
+      <i class="iconfont icon-material_prompt tool-tip-for-editor" v-tooltip="$i18n.t('explanation.explanation_tips')"/>
     </div>
     <button
       v-if="!currentScene.explanation.audioId"
@@ -13,7 +13,7 @@
       @click="isShowSelectionWindow = true"
     >
       <i class="iconfont icon-editor_add"></i>
-      添加音频
+      {{$i18n.t("explanation.add_audio")}}
     </button>
     <template v-else>
       <div class="music-display" @click.self="onClickCurrentMusic">
@@ -23,19 +23,19 @@
       </div>
       <button class="ui-button" @click="isShowSelectionWindow = true">
         <i class="iconfont icon-editor_update"></i>
-        更换音频
+        {{$i18n.t("explanation.change_audio")}}
       </button>
     </template>
 
     <div class="switch-wrapper">
-      <span class="label">默认开启</span>
+      <span class="label">{{$i18n.t("explanation.default_open")}}</span>
       <Switcher
         :disable="!currentScene || currentScene.type ==='4dkk'"
         :value="currentScene.explanation.openByDefault" @change="currentScene.explanation.openByDefault = !currentScene.explanation.openByDefault"
       />
     </div>
     <div class="switch-wrapper">
-      <span class="label">循环播放</span>
+      <span class="label">{{$i18n.t("explanation.loop")}}</span>
       <Switcher
         :disable="!currentScene || currentScene.type ==='4dkk'"
         :value="currentScene.explanation.repeat" @change="currentScene.explanation.repeat = !currentScene.explanation.repeat"
@@ -44,7 +44,7 @@
 
     <div class="dialog" style="z-index: 2000" v-if="isShowSelectionWindow">
       <MaterialSelectorForEditor
-        title="选择素材"
+        :title="$i18n.t('gather.select_material')"
         @cancle="isShowSelectionWindow = false"
         @submit="handleSubmitFromMaterialSelector"
         :selectableType="['audio']"

+ 66 - 64
packages/qjkankan-editor/src/views/hotspot/EditPanel.vue

@@ -3,13 +3,13 @@
     leave-active-class="animated slideOutRight speed">
     <div class="hots-panel" v-show="show">
       <div class="ui-between header">
-        <span>{{ editTitle }}热点</span>
+        <span>{{ editTitle }}{{ $i18n.t('hotspot.hotspot_name') }}</span>
         <i class="iconfont icon_close" @click="confirmCancel"></i>
       </div>
       <div class="content" ref="content">
         <div class="icon-setting">
-          <div class="icon-setting-title">热点图标</div>
-          <div class="remark">选择图标</div>
+          <div class="icon-setting-title">{{ $i18n.t('hotspot.hotspot_icon') }}</div>
+          <div class="remark">{{ $i18n.t('hotspot.select_icon') }}</div>
           <div class="icon-list">
             <div class="margin-handler-layer">
               <ul>
@@ -25,23 +25,23 @@
           </div>
         </div>
         <div class="title-setting">
-          <div class="title-setting-title">标题设置</div>
+          <div class="title-setting-title">{{ $i18n.t('hotspot.title_setting') }}</div>
           <div class="switch-wrapper">
-            <span class="label">是否显示标题</span>
+            <span class="label">{{ $i18n.t('hotspot.isshow_title') }}</span>
             <Switcher :value="hotspot.visible" @change="hotspot.visible = !hotspot.visible"></Switcher>
           </div>
           <div class="title-input-wrapper">
-            <input v-model.trim="hotspot.hotspotTitle" type="text" maxlength="50" placeholder="请输入标题,限50字" />
+            <input v-model.trim="hotspot.hotspotTitle" type="text" maxlength="50" :placeholder="$i18n.t('hotspot.title_placeholder')" />
             <span class="count">{{ hotspot.hotspotTitle.length }}/50</span>
           </div>
         </div>
         <div class="effect-setting">
-          <div class="effect-setting-title">效果设置</div>
+          <div class="effect-setting-title">{{$i18n.t('hotspot.effect_settings')}}</div>
           <combox class="combox" :data="hotSpotTypeList" :selected-id="hotspot.hotspotType"
             :bottomSpace="comboxBottomSpace" @change="onhotSpotTypeChange"></combox>
           <component class="effect-setting-component" @sceneSelect="handleSceneSelect" :scene="hotspot.secne"
             @imageChange="data => { hotspot.image = data }" :image="hotspot.image"
-            @linkChange="data => { hotspot.hyperlink = data }" :link="hotspot.hyperlink" 
+            @linkChange="data => { hotspot.hyperlink = data }" :link="hotspot.hyperlink"
             @linkOpenType="data => { hotspot.linkOpenType = data }" :linkOpenType="hotspot.linkOpenType"
             @textChange="data => { hotspot.textarea = data }" :textarea="hotspot.textarea"
             @audioChange="data => { hotspot.audio = data }" :audio="hotspot.audio"
@@ -49,8 +49,8 @@
         </div>
       </div>
       <div class="ui-between footer" app-border dir-top>
-        <button class="ui-button deepcancel" :class="{ disable: false }" @click="confirmCancel">取消</button>
-        <button class="ui-button submit" :class="{ disable: false }" @click="save">完成</button>
+        <button class="ui-button deepcancel" :class="{ disable: false }" @click="confirmCancel">{{$i18n.t('hotspot.cancel')}}</button>
+        <button class="ui-button submit" :class="{ disable: false }" @click="save">{{$i18n.t('hotspot.finish')}}</button>
       </div>
     </div>
   </transition>
@@ -78,38 +78,8 @@ let comparisonKey = [
   'video'
 ]
 
-let HTMap = {
-  scene: {
-    key: 'secne',
-    type: 'Object',
-    errortxt: '请选择场景'
-  },
-  audio: {
-    key: 'audio',
-    type: 'String',
-    errortxt: '请选择音频'
-  },
-  video: {
-    key: 'video',
-    type: 'String',
-    errortxt: '请选择视频'
-  },
-  image: {
-    key: 'image',
-    type: 'Array',
-    errortxt: '请选择图片'
-  },
-  link: {
-    key: 'hyperlink',
-    type: 'String',
-    errortxt: '请输入超链接'
-  },
-  textarea: {
-    key: 'textarea',
-    type: 'String',
-    errortxt: '请输入文本'
-  }
-}
+
+let HTMap = ''
 
 
 export default {
@@ -130,38 +100,70 @@ export default {
         thumb: cdn + `img_doticon_${String(i + 1).padStart(2, '0')}.svg`
       }
     }
+    HTMap = {
+      scene: {
+        key: 'secne',
+        type: 'Object',
+        errortxt: this.$i18n.t('hotspot.secne_errortxt')
+      },
+      audio: {
+        key: 'audio',
+        type: 'String',
+        errortxt: this.$i18n.t('hotspot.audio_errortxt')
+      },
+      video: {
+        key: 'video',
+        type: 'String',
+        errortxt: this.$i18n.t('hotspot.video_errortxt')
+      },
+      image: {
+        key: 'image',
+        type: 'Array',
+        errortxt: this.$i18n.t('hotspot.image_errortxt')
+      },
+      link: {
+        key: 'hyperlink',
+        type: 'String',
+        errortxt: this.$i18n.t('hotspot.link_errortxt')
+      },
+      textarea: {
+        key: 'textarea',
+        type: 'String',
+        errortxt: this.$i18n.t('hotspot.textarea_errortxt')
+      }
+    }
     return {
       canSave: false,
       hotSpotTypeList: [
         {
           id: 'scene',
-          name: '场景切换'
+          name: this.$i18n.t('hotspot.secne')
         },
         {
           id: 'link',
-          name: '超链接'
+          name: this.$i18n.t('hotspot.link')
         },
         {
           id: 'textarea',
-          name: '文本'
+          name: this.$i18n.t('hotspot.textarea')
         },
         {
           id: 'image',
-          name: '图片'
+          name: this.$i18n.t('hotspot.image')
         },
         {
           id: 'audio',
-          name: '音频'
+          name: this.$i18n.t('hotspot.audio')
         },
         {
           id: 'video',
-          name: '视频'
+          name: this.$i18n.t('hotspot.video')
         }
       ],
       hotStyle,
       rang: {
-        label: '图标大小',
-        unit: "倍",
+        label: this.$i18n.t('hotspot.icon_size'),
+        unit: this.$i18n.t('hotspot.unit'),
         gradient: 0.5,
         value: 1,
         min: 0.5,
@@ -247,7 +249,7 @@ export default {
 
 
     this.$nextTick(() => {
-      if (this.editTitle != '编辑') {
+      if (this.editTitle != '编辑'&&this.editTitle != this.$i18n.t('hotspot.edit')) {
         this.addhotspot(this.hotStyle[0])
         this.rang.value = window.g_hotspotCurrentScale
         this.onRangeChange({ value: window.g_hotspotCurrentScale })
@@ -288,12 +290,12 @@ export default {
           break;
       }
     },
-    listerFnReset(){
-      if (this.hotspot.hotspotTitle == '单击确定热点位置') {
+    listerFnReset() {
+      if (this.hotspot.hotspotTitle == '单击确定热点位置'||this.hotspot.hotspotTitle == this.$i18n.t('hotspot.click_to_comfirm')) {
         this.hotspot.hotspotTitle = ''
       }
     },
-    
+
     listerFn(data) {
       this.selectItem = {
         sceneCode: data.sceneCode
@@ -316,7 +318,7 @@ export default {
       let { hotspotTitle, hotspotType } = this.hotspot
       let item = HTMap[hotspotType]
       if (
-        (hotspotTitle.trim() && hotspotTitle.trim() != '单击确定热点位置')
+        (hotspotTitle.trim() && (hotspotTitle.trim() != '单击确定热点位置'&&hotspotTitle.trim() != this.$i18n.t('hotspot.click_to_comfirm')))
         || this.hotspot[item.key]
         || (item.type == 'Array' && this.hotspot[item.key].length > 0)
       ) {
@@ -326,10 +328,10 @@ export default {
     },
 
     confirmCancel() {
-      if (this.editTitle != '编辑') {
+      if (this.editTitle != '编辑'&&this.editTitle != this.$i18n.t('hotspot.edit')) {
         if (this.isAddChange()) {
           this.$confirm({
-            content: "热点内容未编辑完,确定要关闭吗",
+            content: this.$i18n.t('hotspot.close_dialog'),
             ok: () => {
               this.cancel()
             }
@@ -340,7 +342,7 @@ export default {
       } else {
         if (this.isDiffHotSpot() || this.isAddChange()) {
           this.$confirm({
-            content: "热点内容未编辑完,确定要关闭吗",
+            content: this.$i18n.t('hotspot.close_dialog'),
             ok: () => {
               this.cancel()
             }
@@ -353,7 +355,7 @@ export default {
     cancel() {
       this.$store.commit("SetHotspot", this.backupHotSpot);
       this.$emit("close", {
-        type: this.editTitle == '编辑' ? 'edit' : 'add',
+        type: this.editTitle == this.$i18n.t('hotspot.edit') ? 'edit' : 'add',
         data: this.backupHotSpot
       });
     },
@@ -368,13 +370,13 @@ export default {
 
       if (!img) {
         return this.$alert({
-          content: "请选择热点图标",
+          content: this.$i18n.t('hotspot.select_hotspot_icon'),
         });
       }
 
-      if (!(hotspotTitle.trim() && hotspotTitle.trim() != '单击确定热点位置')) {
+      if (!(hotspotTitle.trim() && (hotspotTitle.trim() != '单击确定热点位置'&&hotspotTitle.trim() != this.$i18n.t('hotspot.click_to_comfirm')))) {
         return this.$alert({
-          content: "请输入热点标题",
+          content: this.$i18n.t('hotspot.input_hotspot_title'),
         });
       }
 
@@ -389,9 +391,9 @@ export default {
     },
     addhotspot(data) {
 
-      console.log(this.isAdd,'this.isAdd');
+      console.log(this.isAdd, 'this.isAdd');
 
-      if (this.isAdd && this.editTitle != '编辑') {
+      if (this.isAdd && (this.editTitle != '编辑'&&this.editTitle != this.$i18n.t('hotspot.edit'))) {
         this.isAdd = false
         this.hotspot.img = data.img
         this.hotspot.icontype = data.id

+ 15 - 15
packages/qjkankan-editor/src/views/hotspot/HotSpotList.vue

@@ -1,14 +1,14 @@
 <template>
   <div class="hot-spot-list" app-border dir-left>
     <div class="title">
-      热点设置
-      <i class="iconfont icon-material_prompt tool-tip-for-editor" v-tooltip="'在全景图中添加图标热点,并设置热点的效果。'" />
+      {{$i18n.t('hotspot.hotspot_setting')}}
+      <i class="iconfont icon-material_prompt tool-tip-for-editor" v-tooltip="$i18n.t('hotspot.hotspot_tips')" />
     </div>
     <button class="ui-button submit" :class="{ disable: !currentScene || currentScene.type ==='4dkk' }" @click="open(null)">
-      添加热点
+      {{$i18n.t('hotspot.add_hotspot')}}
     </button>
 
-    <div class="total-count">当前全景图热点
+    <div class="total-count">{{$i18n.t('hotspot.current_hotspots')}}
       <span class="number">({{ someData.hotspots.length }})</span>
     </div>
     <div class="hots">
@@ -16,18 +16,18 @@
         <li v-for="(item, key) in someData.hotspots" :key="key" @click="open(item)">
           <img class="hot-spot-thumb" :src="item.img" alt="">
           <span class="hot-spot-title" v-title="item.hotspotTitle">{{ item.hotspotTitle }}</span>
-          <i class="iconfont icon-editor_list_delete icon-delete" v-tooltip="'删除'" @click.stop="deleIndex = key" />
+          <i class="iconfont icon-editor_list_delete icon-delete" v-tooltip="$i18n.t('hotspot.delete')" @click.stop="deleIndex = key" />
           <div class="deletion-confirm-wrap">
             <div class="deletion-confirm" :class="deleIndex == key ? 'show' : 'hide'" v-clickoutside="clickoutside"
               @click.stop="deleteHot(item)">
-              删除
+              {{$i18n.t('hotspot.delete')}}
             </div>
           </div>
         </li>
       </ul>
       <div v-else class="empty-tip">
         <img src="@/assets/images/default/empty_hotspot_list.png" alt="">
-        <div>暂无热点信息~</div>
+        <div>{{$i18n.t('hotspot.no_hotspot')}}</div>
       </div>
     </div>
     <EditPanel class="adding-hotspot-panel" v-if="showPanel" :editTitle="editTitle" @save="save" :show="showPanel"
@@ -66,7 +66,7 @@ export default {
       showPanel: false,
       someData: { hotspots: [] },
       deleIndex: -1,
-      editTitle: "编辑",
+      editTitle: this.$i18n.t('hotspot.edit'),
     }
   },
   watch: {
@@ -118,10 +118,10 @@ export default {
         }
         return
       }
-      if (this.editTitle == '新增') {
+      if (this.editTitle == '新增' || this.editTitle == this.$i18n.t('hotspot.add')) {
         if (this.showPanel) {
           return this.$confirm({
-            content: "热点内容未编辑完,确定要关闭吗",
+            content: this.$i18n.t('hotspot.close_dialog'),
             ok: () => {
               this.deleteKRHotspot(this.hotspot)
               this.open(this.someData.hotspots[idx])
@@ -177,7 +177,7 @@ export default {
       }
 
       this.currentScene.someData = this.someData
-      this.$msg.success(this.editTitle + "成功")
+      this.$msg.success(this.editTitle + this.$i18n.t('hotspot.success'))
 
       window.g_hotspotCurrentScale = mapFontSize[data.fontSize] || 1
 
@@ -200,13 +200,13 @@ export default {
       this.deleteKRHotspot(data)
       this.currentScene.someData = this.someData
       this.updateInfo()
-      this.$msg.success("删除成功")
+      this.$msg.success(this.$i18n.t('hotspot.delete')+this.$i18n.t('hotspot.success'))
     },
     open(data) {
-      this.editTitle = "新增"
+      this.editTitle = this.$i18n.t('hotspot.add')
       let temp = data ? browser.CloneObject(data)  : {
         name: "_" + this.$randomWord(true, 8, 8),
-        hotspotTitle: '单击确定热点位置',
+        hotspotTitle: this.$i18n.t('hotspot.click_to_comfirm'),
         fontSize: 12,
         type: '',
         img: '',
@@ -230,7 +230,7 @@ export default {
 
       if (data) {
         this.editLink = temp.link
-        this.editTitle = "编辑"
+        this.editTitle =  this.$i18n.t('hotspot.edit')
         window.__krfn.utils.looktohotspot(this.$getKrpano(), data.name)
       }
     },

+ 4 - 3
packages/qjkankan-editor/src/views/hotspot/hotspotType/audio.vue

@@ -2,7 +2,7 @@
   <div class="audio-hotspot-setting">
     <button class="add-btn" v-if="!tAudio.id" @click="selectHandle">
       <i class="iconfont icon-editor_add"></i>
-      添加音频
+      {{$i18n.t('hotspot.add_audio')}}
     </button>
     <template v-else>
       <div class="music-display" @click.self="onClickCurrentMusic">
@@ -12,13 +12,14 @@
       </div>
       <button class="change-btn" @click="selectHandle">
         <i class="iconfont icon-editor_update"></i>
-        更换音频
+      {{$i18n.t('hotspot.change_audio')}}
+        
       </button>
     </template>
 
     <div class="dialog" style="z-index: 2000" v-if="isShowSelect">
       <MaterialSelectorForEditor
-        title="选择音频"
+        :title="$i18n.t('hotspot.select_audio')"
         @cancle="isShowSelect = false"
         @submit="handleSelect"
         :selectableType="['audio']"

+ 4 - 4
packages/qjkankan-editor/src/views/hotspot/hotspotType/image.vue

@@ -4,13 +4,13 @@
     <div class="image-list-wrap">
       <button class="add-btn" v-if="images.length === 0" @click="selectHandle">
         <img src="@/assets/images/default/hotspot_scene_add.png" alt="">
-        <div>添加图片</div>
+        <div>{{$i18n.t('hotspot.add_image')}}</div>
       </button>
       <ul class="image-list" v-else>
         <button class="add-btn" @click="selectHandle">
           <div class="inner-wrap">
             <img src="@/assets/images/default/hotspot_scene_add.png" alt="">
-            <div>添加</div>
+            <div>{{$i18n.t('hotspot.add_tooltips')}}</div>
           </div>
         </button>
         <li v-for="(item,i) in images" :key="i">
@@ -25,7 +25,7 @@
 
     <div class="dialog" style="z-index: 2000" v-if="isShowSelect">
       <MaterialSelectorForEditor
-        title="选择图片"
+        :title="$i18n.t('hotspot.select_image')"
         @cancle="isShowSelect = false"
         @submit="handleSelect"
         :selectableType="['image']"
@@ -66,7 +66,7 @@ export default {
   watch: {
     images(newVal) {
       if (newVal.length > 20) {
-        return this.$alert({ content: "最多添加20张图片" });
+        return this.$alert({ content: this.$i18n.t('hotspot.img_size') });
       }
       this.$emit('imageChange',newVal)
     }

+ 2 - 2
packages/qjkankan-editor/src/views/hotspot/hotspotType/link.vue

@@ -20,11 +20,11 @@ export default {
       linkTypeList: [
         {
           id: 'popup',
-          name: '弹出层打开'
+          name: this.$i18n.t('hotspot.popup')
         },
         {
           id: 'newTab',
-          name: '新窗口打开'
+          name: this.$i18n.t('hotspot.newTab')
         },
 
       ],

+ 3 - 2
packages/qjkankan-editor/src/views/hotspot/hotspotType/scene.vue

@@ -3,7 +3,7 @@
     <div class="add-btn-wrap" v-if="!selected.icon">
       <button @click="showScene = true">
         <img src="@/assets/images/default/hotspot_scene_add.png" alt="">
-        <div>添加场景</div>
+        <div>{{$i18n.t('hotspot.add_scene')}}</div>
       </button>
     </div>
     <div v-else class="scene-info">
@@ -16,7 +16,7 @@
         </button>
       </div>
       <div class="right-wrap">
-        <button class="ui-button submit" @click="showScene = true">更换场景</button>
+        <button class="ui-button submit" @click="showScene = true">{{$i18n.t('hotspot.change_scene')}}</button>
         <div class="scene-title" v-title="selected.sceneTitle">{{selected.sceneTitle}}</div>
       </div>
     </div>
@@ -147,6 +147,7 @@ export default {
       button {
         width: 100%;
         padding: 0;
+        white-space: unset;
       }
       .scene-title {
         margin-top: 10px;

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

@@ -8,7 +8,7 @@
         type="text"
       /> -->
 
-      <editor ref="editor" :html="text" :placeholder="'请输入文字内容,限500字'" :maxlength="500" @change="onEditorChange"></editor>
+      <editor ref="editor" :html="text" :placeholder="$i18n.t('hotspot.text_placeholder')" :maxlength="500" @change="onEditorChange"></editor>
       <span class="count">{{size}}/500</span>
     </div>
   </div>

+ 3 - 3
packages/qjkankan-editor/src/views/hotspot/hotspotType/video.vue

@@ -4,7 +4,7 @@
     <div class="add-btn-wrap" v-if="!tVideo.id">
       <button @click="selectHandle">
         <img src="@/assets/images/default/hotspot_scene_add.png" alt="">
-        <div>添加视频</div>
+        <div>{{$i18n.t('hotspot.add_video')}}</div>
       </button>
     </div>
 
@@ -18,13 +18,13 @@
       </div>
       <button class="change-btn" @click="selectHandle">
         <i class="iconfont icon-editor_update"></i>
-        更换视频
+        {{$i18n.t('hotspot.change_video')}}
       </button>
     </div>
 
     <div class="dialog" style="z-index: 2000" v-if="isShowSelect">
       <MaterialSelectorForEditor
-        title="选择视频"
+        :title="$i18n.t('hotspot.change_video')"
         @cancle="isShowSelect = false"
         @submit="handleSelect"
         :selectableType="['video']"

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

@@ -56,7 +56,7 @@
         ref="table-list"
       >
         <div slot-scope="{ data }" slot="header">
-          {{ data.name }}
+          {{ data.name && $i18n.t(`zh_key.${data.name}`)  }}
         </div>
         <div slot-scope="{ data, item, sub }" slot="item" style="width: 100%">
           <div class="handle" v-if="sub.canclick">
@@ -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) => {

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

@@ -56,7 +56,7 @@
         ref="table-list"
       >
         <div slot-scope="{ data }" slot="header">
-          {{ data.name }}
+          {{ data.name && $i18n.t(`zh_key.${data.name}`)  }}
         </div>
         <div slot-scope="{ data, item, sub }" slot="item" style="width: 100%">
           <div v-if="sub.canclick" class="handle">
@@ -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) => {

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

@@ -5,97 +5,64 @@
     </div>
     <div class="second-line">
       <div class="btn">
-        <button
-          @mouseover.stop="showList = true"
-          @click="onUploadFile"
-          class="ui-button submit"
-        >
-          <span>{{upload_material}}</span>
+        <button @mouseover.stop="showList = true" @click="onUploadFile" class="ui-button submit">
+          <span>{{ upload_material }}</span>
           <i class="iconfont icon-material_prompt hover-tips hover-tips-upload-icon">
             <div>
-              <div class="remark">{{pano_size}}</div>
+              <div class="remark">{{ pano_size }}</div>
             </div>
           </i>
-          <upload
-            ref="uploadFile"
-            :failString="pano_fail"
-            :limitFailStr="pano_limit"
-            accept-type=".jpg"
-            media-type="image"
-            :limit="120"
-            @file-change="onFileChange"
-          ></upload>
+          <upload ref="uploadFile" :failString="pano_fail" :limitFailStr="pano_limit" accept-type=".jpg"
+            media-type="image" :limit="120" @file-change="onFileChange"></upload>
         </button>
       </div>
       <div class="filter">
-        <div :class="{active: isFilterFocus}" @focusin="onFilterFocus" @focusout="onFilterBlur">
+        <div :class="{ active: isFilterFocus }" @focusin="onFilterFocus" @focusout="onFilterBlur">
           <i class="iconfont icon-works_search search"></i>
-          <input
-            type="text"
-            v-model="searchKey"
-            :placeholder="serch_material"
-          />
-          <i v-if="searchKey" @click="searchKey=''" class="iconfont icontoast_red del"></i>
+          <input type="text" v-model="searchKey" :placeholder="serch_material" />
+          <i v-if="searchKey" @click="searchKey = ''" class="iconfont icontoast_red del"></i>
         </div>
       </div>
     </div>
     <div class="list">
-      <tableList
-        @selection-change="
-          (data) => {
-            selectedArr = data;
-          }
-        "
-        @request-more-data="getMoreMaterialItem"
-        :canRequestMoreData="hasMoreData && !isRequestingMoreData"
-        :header="tabHeader"
-        :showLine="true"
-        :selection="false"
-        :data="list"
-        class="table-list"
-        ref="table-list"
-      >
+      <tableList @selection-change="
+        (data) => {
+          selectedArr = data;
+        }
+      " @request-more-data="getMoreMaterialItem" :canRequestMoreData="hasMoreData && !isRequestingMoreData"
+        :header="tabHeader" :showLine="true" :selection="false" :data="list" class="table-list" ref="table-list">
         <!-- 表头 -->
         <div slot-scope="{ data }" slot="header">
-          {{ data.name }}
+          {{ data.name && $i18n.t(`zh_key.${data.name}`) }}
         </div>
         <!-- 内容各单元格 -->
         <!-- item:传给组件的data里各元素,对应单元格所在行(hasAuth都写成false);data:item里各元素,对应每个单元格;sub:表头数据各元素,即单元各所属列的表头数据 -->
         <div slot-scope="{ data, item, sub }" slot="item" style="width: 100%">
           <!-- 操作型单元格 -->
           <div class="handle" v-if="sub.canclick">
-            <i
-              class="iconfont icon-material_operation_image hover-tips"
-              @click="(showCover = true), (popupItem = item)"
-            >
+            <i class="iconfont icon-material_operation_image hover-tips"
+              @click="(showCover = true), (popupItem = item)">
               <div>
-                <div class="remark">{{edit_cover}}</div>
+                <div class="remark">{{ edit_cover }}</div>
               </div>
             </i>
 
-            <i
-              class="iconfont icon-material_operation_editor hover-tips"
-              @click="(showRename = true), (popupItem = item)"
-            >
+            <i class="iconfont icon-material_operation_editor hover-tips"
+              @click="(showRename = true), (popupItem = item)">
               <div>
-                <div class="remark">{{rename}}</div>
+                <div class="remark">{{ rename }}</div>
               </div>
             </i>
             <i class="iconfont icon-material_operation_delete hover-tips-warn" @click="del(item)">
               <div>
-                <div class="remark">{{deltips}}</div>
+                <div class="remark">{{ deltips }}</div>
               </div>
             </i>
           </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()}` : '') "
-            alt="" />
+          <div class="img" v-else-if="sub.type == 'image'" @click="previewImage(item)">
+            <img :src="data + (Number(item.fileSize) > 512 ? $imgsuffix : '')"
+              alt="" />
           </div>
           <span style="cursor: pointer;" @click="previewImage(item)" v-else-if="sub.key == 'name'">{{ data || "-" }}
           </span>
@@ -105,37 +72,24 @@
           </span>
         </div>
       </tableList>
-      <UploadTaskList class="upload-task-list" fileType="IMAGE" :taskList="uploadListForUI" @cancel-task="onCancelTask"></UploadTaskList>
-      <div class="total-number" v-if="list.length !== 0 || hasMoreData">{{had_load}}</div>
+      <UploadTaskList class="upload-task-list" fileType="IMAGE" :taskList="uploadListForUI" @cancel-task="onCancelTask">
+      </UploadTaskList>
+      <div class="total-number" v-if="list.length !== 0 || hasMoreData">{{ had_load }}</div>
       <div class="nodata" v-if="list.length == 0 && !hasMoreData && lastestUsedSearchKey">
         <img :src="$noresult" alt="" />
-        <span>{{no_serch_result}}</span>
+        <span>{{ no_serch_result }}</span>
       </div>
       <div class="nodata" v-if="list.length == 0 && !hasMoreData && !lastestUsedSearchKey">
         <img :src="config.empty" alt="" />
-        <span>{{no_material_result}}</span>
-        <button @click="$refs.uploadFile.click()" class="upload-btn-in-table">{{upload_material}}</button>
+        <span>{{ no_material_result }}</span>
+        <button @click="$refs.uploadFile.click()" class="upload-btn-in-table">{{ upload_material }}</button>
       </div>
     </div>
 
-    <rename
-      v-if="showRename"
-      :item="popupItem"
-      @rename="handleRename"
-      @close="showRename = false"
-    />
-    <preview
-      ref="image-previewer"
-      :sceneCodeList="list.map(item => item.sceneCode)"
-      :imageTitleList="list.map(item => item.name)"
-      @click-delete="onClickDeleteInPreview"
-    />
-    <cover
-      @panocover="handlePanoCover"
-      :item="popupItem"
-      v-if="showCover"
-      @close="showCover = false"
-    />
+    <rename v-if="showRename" :item="popupItem" @rename="handleRename" @close="showRename = false" />
+    <preview ref="image-previewer" :sceneCodeList="list.map(item => item.sceneCode)"
+      :imageTitleList="list.map(item => item.name)" @click-delete="onClickDeleteInPreview" />
+    <cover @panocover="handlePanoCover" :item="popupItem" v-if="showCover" @close="showCover = false" />
   </div>
 </template>
 
@@ -163,7 +117,7 @@ import {
   checkUserSize
 } from "@/api";
 
-import {i18n} from "@/lang"
+import { i18n } from "@/lang"
 
 
 const TYPE = "pano";
@@ -192,7 +146,7 @@ export default {
       edit_cover: i18n.t("gather.edit_cover"),
       rename: i18n.t("gather.rename"),
       deltips: i18n.t("gather.delete"),
-      
+
       config,
       showRename: false,
       showCover: false,
@@ -200,7 +154,7 @@ export default {
       popupItem: null,
       tabHeader: data,
       selectedArr: [],
-      
+
       searchKey: "",
       // 因为searchKey的变化经过debounce、异步请求的延时,才会反映到数据列表的变化上,所以是否显示、显示哪种无数据提示,也要等到数据列表变化后,根据数据列表是否为空,以及引发本次变化的那个searchKey瞬时值来决定。本变量就是用来保存那个瞬时值。
       lastestUsedSearchKey: '',
@@ -227,8 +181,8 @@ export default {
         return item.status === 'LOADING' && item.ifKnowProgress === false
       })
     },
-    had_load(){
-      return i18n.t("gather.had_load",{msg:this.list.length})
+    had_load() {
+      return i18n.t("gather.had_load", { msg: this.list.length })
     }
   },
   mounted() {
@@ -258,12 +212,12 @@ export default {
     },
   },
   methods: {
-    onUploadFile(){
-      checkUserSize({},(data)=>{
+    onUploadFile() {
+      checkUserSize({}, (data) => {
         //判断已用是否大于3G
         if ((data.data / 1024 / 1024) > 3) {
-          this.$alert({ content: "空间已满" });
-        }else{
+          this.$alert({ content: i18n.t("tips_code.FAILURE_3024") });
+        } else {
           this.$refs.uploadFile.click()
         }
       })
@@ -274,7 +228,7 @@ export default {
     onFilterBlur() {
       this.isFilterFocus = false
     },
-    refreshListDebounced: debounce(function() {
+    refreshListDebounced: debounce(function () {
       this.list = []
       this.isRequestingMoreData = false
       this.hasMoreData = true
@@ -291,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
           })
@@ -319,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
@@ -377,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))
@@ -390,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(
@@ -453,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);
@@ -463,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);
@@ -472,13 +426,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}”${i18n.t("gather.pano_fail")}`,
               type: "warning",
             });
           }, i * 100);
@@ -487,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);
@@ -499,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: '',
@@ -514,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
           },
@@ -526,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) => {
@@ -586,6 +540,7 @@ export default {
 </script>
 
 <style lang="less" scoped>
+
 </style>
 <style lang="less" scoped>
 @import "../style.less";

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

@@ -2,36 +2,36 @@
     <popup>
       <div class="ui-message ui-message-confirm message-material">
         <div class="ui-message-header header-material">
-          <div>全景图封面设置</div>
+          <div>{{$i18n.t(`material.components.pano_setting`)}}</div>
           <div @click="$emit('close')">
             <i class="iconfont icon_close"></i>
           </div>
         </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">拖动画面截取封面</span>
+              <span class="remark">{{$i18n.t(`material.components.drag_to_cut`)}}</span>
               <div @click="onClick" :class="canPrintScreen ? 'print-screen-btn' : 'print-screen-btn--disabled'" >
                 <i class="iconfont icon-pop-ups_crop"></i>
-                截图
+                {{$i18n.t(`material.components.cutting`)}}
               </div>
             </div>
           </div>
           <div>
             <img :src="img||$thumb" alt="" />
             <div>
-              <div class="remark">封面预览</div>
+              <div class="remark">{{$i18n.t(`material.components.preview_cover`)}}</div>
             </div>
           </div>
         </div>
         <div class="ui-message-footer">
           <div class="btn">
             <button @click="$emit('close')" class="ui-button ui-button-rect cancel" >
-              取消
+              {{$i18n.t(`gather.cancel`)}}
             </button>
             <button @click="save" class="ui-button ui-button-rect submit" >
-              确定
+              {{$i18n.t(`gather.comfirm`)}}
             </button>
           </div>
         </div>

+ 7 - 7
packages/qjkankan-editor/src/views/material/popup/imagePreviewer.vue

@@ -16,37 +16,37 @@
         <i
           class="iconfont icon-material_preview_previous hover-tips" :class="{disabled: currentIndex === 0}" @click="onClickPrevious()">
           <div>
-            <div class="remark">上一张</div>
+            <div class="remark">{{$i18n.t(`material.components.prev`)}}</div>
           </div>
         </i>
         <i class="iconfont icon-material_preview_next1 hover-tips append-splitter" :class="{disabled: currentIndex === imageList.length - 1}" @click="onClickNext()">
           <div>
-            <div class="remark">下一张</div>
+            <div class="remark">{{$i18n.t(`material.components.next`)}}</div>
           </div>
         </i>
         <i v-if="canScale" class="iconfont icon-material_preview_enlarge hover-tips" @click="onClickZoomIn()">
           <div>
-            <div class="remark">放大</div>
+            <div class="remark">{{$i18n.t(`material.components.zoom_in`)}}</div>
           </div>
         </i>
         <i v-if="canScale" class="iconfont icon-material_preview_narrow hover-tips" @click="onClickZoomOut()">
           <div>
-            <div class="remark">缩小</div>
+            <div class="remark">{{$i18n.t(`material.components.zoom_out`)}}</div>
           </div>
         </i>
         <i class="iconfont icon-material_preview_next hover-tips-warn" @click="onClickDelete()">
           <div>
-            <div class="remark">删除</div>
+            <div class="remark">{{$i18n.t(`material.components.delete`)}}</div>
           </div>
         </i>
         <i v-if="canFullScreen && objectFit === 'scale-down'" class="iconfont icon-material_preview_full_screen hover-tips" @click="onClickFullScreen()">
           <div>
-            <div class="remark">全屏</div>
+            <div class="remark">{{$i18n.t(`material.components.fullscreen`)}}</div>
           </div>
         </i>
         <i v-if="canFullScreen && objectFit === 'contain'" class="iconfont icon-material_preview_drop_out hover-tips" @click="onClickCancelFullScreen()">
           <div>
-            <div class="remark">取消全屏</div>
+            <div class="remark">{{$i18n.t(`material.components.cancel_fullscreen`)}}</div>
           </div>
         </i>
       </div>

+ 6 - 6
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}"
       />
@@ -21,27 +21,27 @@
         <i
           class="iconfont icon-material_preview_previous hover-tips" :class="{disabled: currentIndex === 0}" @click="onClickPrevious()">
           <div>
-            <div class="remark">上一张</div>
+            <div class="remark">{{$i18n.t(`material.components.prev`)}}</div>
           </div>
         </i>
         <i class="iconfont icon-material_preview_next1 hover-tips append-splitter" :class="{disabled: currentIndex === sceneCodeList.length - 1}" @click="onClickNext()">
           <div>
-            <div class="remark">下一张</div>
+            <div class="remark">{{$i18n.t(`material.components.next`)}}</div>
           </div>
         </i>
         <i class="iconfont icon-material_preview_next hover-tips-warn" @click="onClickDelete()">
           <div>
-            <div class="remark">删除</div>
+            <div class="remark">{{$i18n.t(`material.components.delete`)}}</div>
           </div>
         </i>
         <i v-if="!isFullscreen" class="iconfont icon-material_preview_full_screen hover-tips" @click="onClickFullScreen()">
           <div>
-            <div class="remark">全屏</div>
+            <div class="remark">{{$i18n.t(`material.components.fullscreen`)}}</div>
           </div>
         </i>
         <i v-if="isFullscreen" class="iconfont icon-material_preview_drop_out hover-tips" @click="onClickCancelFullScreen()">
           <div>
-            <div class="remark">退出全屏</div>
+            <div class="remark">{{$i18n.t(`material.components.cancel_fullscreen`)}}</div>
           </div>
         </i>
       </div>

+ 4 - 4
packages/qjkankan-editor/src/views/material/popup/rename.vue

@@ -2,19 +2,19 @@
   <popup>
     <div class="ui-message ui-message-confirm" style="width: 400px">
       <div class="ui-message-header">
-        <span>重命名素材</span>
+        <span>{{$i18n.t(`material.components.rename_material`)}}</span>
         <span @click="$emit('close')">
           <i class="iconfont icon_close"></i>
         </span>
       </div>
-      <input class="ui-input" type="text" maxlength="50" placeholder="请输入" @input="emojistr" v-model="key" />
+      <input class="ui-input" type="text" maxlength="50" :placeholder="$i18n.t(`edit_settings.please_input`)" @input="emojistr" v-model="key" />
       <div class="ui-message-footer">
         <div class="btn">
           <button @click="$emit('close')" class="ui-button ui-button-rect cancel">
-            取消
+            {{$i18n.t(`gather.cancel`)}}
           </button>
           <button @click="emitname" class="ui-button ui-button-rect submit" :class="{disable:!key}">
-            确定
+            {{$i18n.t(`gather.comfirm`)}}
           </button>
         </div>
       </div>

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

@@ -11,7 +11,7 @@
         <ul>
           <li>
             <span>{{work_link}}</span>
-            <input :title="item.share" class="ui-input" disabled type="text" maxlength="15"  v-model="item.share" />
+            <input :title="item.share+`&lang=${$lang}`" class="ui-input" disabled type="text" maxlength="15"  v-model="item.share" />
           </li>
           <li>
             <span>{{work_qrCode}}</span>
@@ -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

@@ -56,7 +56,7 @@
         ref="table-list"
       >
         <div slot-scope="{ data }" slot="header">
-          {{ data.name }}
+          {{ data.name && $i18n.t(`zh_key.${data.name}`)  }}
         </div>
         <div slot-scope="{ data, item, sub }" slot="item" style="width: 100%">
           <div class="handle" v-if="sub.canclick">
@@ -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;

+ 56 - 39
packages/qjkankan-editor/src/views/material/works/index.vue

@@ -4,13 +4,13 @@
       <i class="iconfont icon-top"></i>
     </div>
     <div class="tab">
-      <span>{{myWorks}} {{workTotalNum !== undefined ? `(${workTotalNum})`:''}}</span>
+      <span>{{ myWorks }} {{ workTotalNum !== undefined ? `(${workTotalNum})` : '' }}</span>
       <div class="tab-r">
         <div class="filter">
-          <div :class="{active: isFilterFocus}" @focusin="onFilterFocus" @focusout="onFilterBlur">
+          <div :class="{ active: isFilterFocus }" @focusin="onFilterFocus" @focusout="onFilterBlur">
             <i class="iconfont iconworks_search search"></i>
             <input type="text" :placeholder="search" v-model="searchKey">
-            <i v-if="searchKey" @click="searchKey=''" class="iconfont icontoast_red del"></i>
+            <i v-if="searchKey" @click="searchKey = ''" class="iconfont icontoast_red del"></i>
           </div>
         </div>
       </div>
@@ -26,7 +26,7 @@
             <div>
               <i class="iconfont icon_plus"></i>
             </div>
-            <span>{{create}}</span>
+            <span>{{ create }}</span>
           </div>
         </div>
       </li>
@@ -38,27 +38,27 @@
           </div>
         </li>
       </template>
-      <li v-for="(item,i) in list" :key="i" :class="{'has-more-data': hasMoreData}">
+      <li v-for="(item, i) in list" :key="i" :class="{ 'has-more-data': hasMoreData }">
         <div class="wrapper">
           <div class="li-hover">
-            <span class="lipreview" @click="handlePreview(item)">{{preview}}</span>
+            <span class="lipreview" @click="handlePreview(item)">{{ preview }}</span>
             <ul class="oper">
-              <li class="comfirmhover" @click="edit(item)"><i class="iconfont icon-works_editor"></i>{{edittips}}</li>
-              <li class="comfirmhover" @click="openShare(item)"><i class="iconfont icon-works_share"></i>{{share}}</li>
-              <li class="cancelhover" @click="del(item, i)"><i class="iconfont icon-works_delete"></i>{{deltips}}</li>
+              <li class="comfirmhover" @click="edit(item)"><i class="iconfont icon-works_editor"></i>{{ edittips }}</li>
+              <li class="comfirmhover" @click="openShare(item)"><i class="iconfont icon-works_share"></i>{{ share }}</li>
+              <li class="cancelhover" @click="del(item, i)"><i class="iconfont icon-works_delete"></i>{{ deltips }}</li>
             </ul>
           </div>
           <div class="img" @click="handlePreview(item)">
-            <img class="real" :src="item.icon||$thumb" alt="" />
+            <img class="real" :src="item.icon || $thumb" alt="" />
           </div>
           <div class="li-info">
             <div>
-              <span class="shenglve tttttt" :title="item.name||no_title">{{item.name||no_title}}</span>
+              <span class="shenglve tttttt" :title="item.name || no_title">{{ item.name || no_title }}</span>
             </div>
             <div>
-              <span>{{item.createTime.split(' ')[0]}}</span>
+              <span>{{ item.createTime.split(' ')[0] }}</span>
               <div :title="item.visit">
-                <i class="iconfont iconworks_look"></i>{{item.visit>10000?'1w+':item.visit}}
+                <i class="iconfont iconworks_look"></i>{{ item.visit > 10000 ? '1w+' : item.visit }}
               </div>
             </div>
           </div>
@@ -70,19 +70,20 @@
     </ul>
     <div class="nodata" v-if="list.length == 0 && !hasMoreData && lastestUsedSearchKey">
       <img :src="$noresult" alt="" />
-      <span>{{no_serch_result}}~</span>
+      <span>{{ no_serch_result }}~</span>
     </div>
     <div class="nodata" v-if="list.length == 0 && !hasMoreData && !lastestUsedSearchKey">
       <img :src="config.empty" alt="" />
-      <span>{{no_works}}</span>
-      <button @click="add" class="upload-btn-in-table">{{create}}</button>
+      <span>{{ no_works }}</span>
+      <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}`"
-      :dark="false" @close="showPreview = false" />
+    <share :show='showShare' :item="shareItem" @close="showShare = false"></share>
+    <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"
-        :selectableType="['pano', '3D']" :isMultiSelection="true" :workId="newWorkId" initialMaterialType="pano" />
+      <MaterialSelector :title="select_material" @cancle="isShowMaterialSelector = false"
+        @submit="handleSubmitFromMaterialSelector" :selectableType="['pano', '3D']" :isMultiSelection="true"
+        :workId="newWorkId" initialMaterialType="pano" />
     </div>
   </div>
 </template>
@@ -95,7 +96,8 @@ import config from "@/config";
 import { debounce } from "@/utils/other.js"
 import MaterialSelector from "@/components/materialSelectorForManageCenter.vue";
 import { mapGetters } from "vuex";
-import {i18n} from "@/lang"
+import { i18n } from "@/lang"
+import { $waiting } from "@/components/shared/loading";
 
 
 import {
@@ -183,9 +185,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 +198,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,
@@ -206,15 +209,18 @@ export default {
     },
     add() {
       // 新建作品,弹窗让用户给作品选择素材。
+      $waiting.show();
       addWorks(
         {},
         (res) => {
+          $waiting.hide();
           this.newWorkId = res.data.id
           this.isShowMaterialSelector = true
         },
       )
     },
     handleSubmitFromMaterialSelector(selected) {
+      $waiting.show();
       // 拿新作品的初始数据
       getPanoInfo(
         this.newWorkId,
@@ -249,12 +255,15 @@ export default {
             {
               id: this.newWorkId,
               password: '',
-              someData: { ...this.info,
-                 status: 1,
-                icon: this.info.scenes[0].icon },
+              someData: {
+                ...this.info,
+                status: 1,
+                icon: this.info.scenes[0].icon
+              },
             },
             // 保存成功
             () => {
+              $waiting.hide();
               // 隐藏素材选择弹窗
               this.isShowMaterialSelector = false
 
@@ -267,28 +276,29 @@ 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('已成功新建作品,但刷新作品列表失败。')
               })
             },
             // 保存失败,删除新建的作品。
             (error) => {
+              $waiting.hide();
               console.error('保存失败:', error);
               delWorks(this.newWorkId)
               this.newWorkId = ''
@@ -305,15 +315,18 @@ 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: () => {
+
+          $waiting.show();
+
           delWorks(item.id, () => {
-            this.$msg.success("删除成功");
+            this.$msg.success(this.$i18n.t("gather.delete_success"));
             this.isRequestingMoreData = true
             const lastestUsedSearchKey = this.searchKey
             getWorksList(
@@ -323,6 +336,7 @@ export default {
                 searchKey: this.searchKey
               },
               (data) => {
+                $waiting.hide();
                 this.list.splice(index, 1)
                 this.list = this.list.concat(data.data.list)
                 if (this.list.length === data.data.total) {
@@ -339,6 +353,7 @@ export default {
                 })
               },
               () => {
+                $waiting.hide();
                 this.lastestUsedSearchKey = lastestUsedSearchKey
                 this.isRequestingMoreData = false
               }
@@ -477,7 +492,7 @@ export default {
   .mask {
     position: absolute;
     width: 100%;
-    top: 210px;
+    top: 200px;
     height: 30px;
     background: linear-gradient(rgb(239, 242, 244), rgba(255, 255, 255, 0));
     z-index: 1;
@@ -487,7 +502,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;
@@ -676,6 +692,7 @@ export default {
             background: linear-gradient(144deg, #00AEFB 0%, #0076F6 100%);
             position: relative;
             cursor: pointer;
+            margin: 0 auto;
 
             >i {
               font-size: 32px;

+ 18 - 17
packages/qjkankan-editor/src/views/navigation/groupSettings.vue

@@ -1,14 +1,14 @@
 <template>
   <div class="group-settings" app-border dir-right>
-    <div class="ui-title-big">场景导航
-      <i class="iconfont icon-material_prompt tool-tip-for-editor" v-tooltip="'场景素材包括全景图和三维场景,您可自定义分组及场景的排列顺序。'">
+    <div class="ui-title-big">{{$i18n.t("navigation.scene_navigation")}}
+      <i class="iconfont icon-material_prompt tool-tip-for-editor" v-tooltip="$i18n.t('navigation.scene_tips')">
       </i>
     </div>
     <button class="ui-button create-group-btn"
       @click="onRequestForAddLevel1Group"
     >
       <i class="iconfont icon-editor_add"></i>
-      新增分组
+      {{$i18n.t('navigation.add_group')}}
     </button>
 
     <div class="scene-group-wrap">
@@ -63,13 +63,13 @@ export default {
 
       const newGroupLevel1 = {
         id: newGroupLevel1Id,
-        name: '一级分组',
+        name: this.$i18n.t('navigation.group_one'),
         children: [newGroupLevel2Id],
       }
       this.info.catalogRoot.push(newGroupLevel1)
       this.info.catalogs.push({
         id: newGroupLevel2Id,
-        name: '默认二级分组',
+        name: this.$i18n.t('navigation.default_group_two'),
       })
 
       this.$nextTick(() => {
@@ -87,7 +87,7 @@ export default {
       parent.children.push(id);
       const newGroupLevel2 = {
         id,
-        name: '二级分组',
+        name: this.$i18n.t('navigation.group_two'),
       }
       this.info.catalogs.push(newGroupLevel2);
 
@@ -113,8 +113,8 @@ export default {
     onDeleteScene(sceneId) {
       if (this.info.scenes.length === 1) {
         this.$alert({
-          title: '删除场景',
-          content: '请至少保留一个场景',
+          title: this.$i18n.t('navigation.delete_init_scene'),
+          content: this.$i18n.t('navigation.keep_one_scene'),
         })
         return
       }
@@ -123,7 +123,7 @@ export default {
       })
       this.info.scenes.splice(deleteTargetIdx, 1)
       this.delFirstScene()
-      this.$msg.success("删除成功")
+      this.$msg.success(this.$i18n.t('gather.delete_success'))
     },
     onRenameGroup(groupId, level, newName) {
       if (level === 1) {
@@ -131,13 +131,13 @@ export default {
           return item.id === groupId
         })
         target.name = newName
-        this.$msg.success('操作成功')
+        this.$msg.success(this.$i18n.t('gather.success'))
       } else if (level === 2) {
         const target = this.info.catalogs.find((item) => {
           return item.id === groupId
         })
         target.name = newName
-        this.$msg.success('操作成功')
+        this.$msg.success(this.$i18n.t('gather.success'))
       } else {
         console.error('invalid level!');
       }
@@ -149,7 +149,7 @@ export default {
           (groupLevel === 2 && this.info.catalogs.length === 1)
         ) {
           this.$alert({
-            content: "请至少保留一个分组",
+            content: this.$i18n.t('navigation.keep_one_group'),
           })
           return
         }
@@ -171,7 +171,7 @@ export default {
             })
           ) {
             this.$alert({
-              content: "请至少保留一个场景",
+              content: this.$i18n.t('navigation.keep_one_scene'),
             })
             return
           }
@@ -183,14 +183,14 @@ export default {
             return scene.category === groupId
           })) {
             this.$alert({
-              content: "请至少保留一个场景",
+              content: this.$i18n.t('navigation.keep_one_scene'),
             })
             return
           }
         }
       } catch(e) {
         console.error(e);
-        this.$msg.error('删除失败')
+        this.$msg.error(this.$i18n.t('gather.delete_fail'))
         return
       }
 
@@ -239,7 +239,7 @@ export default {
           this.info.catalogRoot[belongGroupIdxLevel1].children.push(newGroupLevel2Id)
           this.info.catalogs.push({
             id: newGroupLevel2Id,
-            name: '默认二级分组',
+            name: this.$i18n.t('navigation.default_group_two'),
           })
         }
 
@@ -268,10 +268,11 @@ export default {
         }
         // 酌情清空初始场景设置
         this.delFirstScene()
-        this.$msg.success("删除成功")
+        this.$msg.success(this.$i18n.t('gather.delete_success'))
       } catch(e) {
         console.error(e);
         this.$msg.error('删除失败')
+        this.$msg.error(this.$i18n.t('gather.delete_fail'))
         this.$store.commit("SetInfo", backup)
       }
     },

+ 9 - 8
packages/qjkankan-editor/src/views/navigation/initialSceneSettings.vue

@@ -1,22 +1,22 @@
 <template>
   <div class="initial-scene-settings" app-border dir-left>
     <div class="initial-scene-settings__title">
-      初始场景
-      <i class="iconfont icon-material_prompt tool-tip-for-editor" v-tooltip="'初始场景为查看链接时进入的第一个场景,未设\n置时,不固定从某一场景打开。'"/>
+      {{$i18n.t('navigation.init_scene')}}
+      <i class="iconfont icon-material_prompt tool-tip-for-editor" v-tooltip="$i18n.t('navigation.init_scene_tips')"/>
     </div>
     
     <img class="preview" v-if="info.firstScene" :src="info.firstScene.icon" alt="">
     <img class="placeholder" v-else src="@/assets/images/pano-image-placeholder.png" alt="">
 
     <div class="change-init" v-if="info.firstScene">
-      <button class="ui-button deepcancel" @click="deleteIndexInfo">删除场景</button>
+      <button class="ui-button deepcancel" @click="deleteIndexInfo">{{$i18n.t('navigation.delete_init_scene')}}</button>
       <button @click="showInitScene=true" class="ui-button submit">
-        修改场景
+        {{$i18n.t('navigation.edit_init_scene')}}
       </button>
     </div>
     <div class="set-init" v-else>
       <button @click="showInitScene=true" class="ui-button submit">
-        设置初始场景
+        {{$i18n.t('navigation.setting_init_scene')}}
       </button>
     </div>
 
@@ -55,11 +55,11 @@ export default {
   methods:{
     deleteIndexInfo(){
       this.$confirm({
-          content: "是否删除?",
+          content: this.$i18n.t('tips.delete'),
           ok: () => {
               this.info.firstScene = ''
               this.$store.commit("SetInfo", this.info);
-              this.$msg.success('删除成功')
+              this.$msg.success(this.$i18n.t('tips.delete_done'))
           }
       });
       
@@ -110,7 +110,8 @@ export default {
     display: flex;
     justify-content: space-between;
     .ui-button {
-      width: calc((100% - 14px) / 2)
+      width: calc((100% - 14px) / 2);
+      white-space: initial;
     }
   }
   .set-init {

+ 2 - 2
packages/qjkankan-editor/src/views/screen/Setting.vue

@@ -1,8 +1,8 @@
 <template>
   <div class="view-setting" app-border dir-left>
     <div class="title">
-      初始画面
-      <i class="iconfont icon-material_prompt tool-tip-for-editor" v-tooltip="'初始画面为进入场景时第一画面,请拖动全景图选择合适的画面设置。'"/>
+      {{$i18n.t('screen.init_screen')}}
+      <i class="iconfont icon-material_prompt tool-tip-for-editor" v-tooltip="$i18n.t('screen.screen_tips')"/>
     </div>
     <img class="preview" v-if="initImg" :src="`${initImg}?${Math.random()}`" alt="">
     <img class="placeholder" v-else src="@/assets/images/pano-image-placeholder.png" alt="">

+ 1 - 1
packages/qjkankan-kankan-view/.env

@@ -15,5 +15,5 @@ VUE_APP_REGION_URL=
 
 
 # 接口请求地址
-VUE_APP_APIS_URL=https://test.4dkankan.com/
+VUE_APP_APIS_URL=https://www.4dkankan.com/
 

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

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

+ 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/
+

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

@@ -6,6 +6,8 @@
     "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",
+    "build-eurprod": "vue-cli-service build --mode eurprod",
     "lint": "vue-cli-service lint"
   },
   "dependencies": {

+ 0 - 0
packages/qjkankan-kankan-view/public/smg.html


Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác