tremble 4 年之前
父节点
当前提交
1d3423bcb2
共有 100 个文件被更改,包括 90985 次插入2110 次删除
  1. 17 0
      backstage/src/assets/styles/public.less
  2. 2 12
      backstage/src/components/editcomponent/editcon.vue
  3. 11 11
      backstage/src/components/editcomponent/usereditdialog.vue
  4. 13 15
      backstage/src/components/table/index.vue
  5. 1 1
      backstage/src/components/uploadFile/index.vue
  6. 13 0
      backstage/src/configue/api.js
  7. 1 1
      backstage/src/configue/http.js
  8. 68 62
      backstage/src/configue/menu.js
  9. 40 9
      backstage/src/mixins/index.js
  10. 48 4
      backstage/src/pages/content/collection/componets/img.vue
  11. 6 1
      backstage/src/pages/content/collection/componets/model.vue
  12. 1 1
      backstage/src/pages/content/collection/componets/plugin/uploadimg.vue
  13. 7 2
      backstage/src/pages/content/collection/componets/video.vue
  14. 21 51
      backstage/src/pages/content/collection/data.js
  15. 2 4
      backstage/src/pages/content/collection/edit.vue
  16. 22 10
      backstage/src/pages/content/collection/index.vue
  17. 187 0
      backstage/src/pages/content/expert/componets/expert.vue
  18. 0 0
      backstage/src/pages/content/expert/componets/mourn.vue
  19. 67 0
      backstage/src/pages/content/expert/componets/status/index.vue
  20. 75 0
      backstage/src/pages/content/expert/data.js
  21. 3 20
      backstage/src/pages/content/sweep/edit.vue
  22. 19 28
      backstage/src/pages/content/sweep/index.vue
  23. 0 0
      backstage/src/pages/content/interaction/componets/donate.vue
  24. 2 2
      backstage/src/pages/content/interaction/componets/questionGroup.vue
  25. 24 55
      backstage/src/pages/content/interaction/data.js
  26. 3 5
      backstage/src/pages/content/interaction/edit.vue
  27. 12 50
      backstage/src/pages/content/interaction/index.vue
  28. 34 0
      backstage/src/pages/content/sand/componets/mourn.vue
  29. 108 0
      backstage/src/pages/content/sand/componets/sand.vue
  30. 63 0
      backstage/src/pages/content/sand/componets/status/index.vue
  31. 52 0
      backstage/src/pages/content/sand/data.js
  32. 110 0
      backstage/src/pages/content/sand/edit.vue
  33. 123 0
      backstage/src/pages/content/sand/index.vue
  34. 3 4
      backstage/src/pages/content/scene/index.vue
  35. 0 130
      backstage/src/pages/content/sweep/componets/martyr.vue
  36. 0 132
      backstage/src/pages/content/sweep/data.js
  37. 15 11
      backstage/src/pages/layout/aside.vue
  38. 127 111
      backstage/src/pages/layout/head.vue
  39. 5 3
      backstage/src/pages/system/role/componets/manage.vue
  40. 2 1
      backstage/src/pages/system/role/edit.vue
  41. 1 1
      backstage/src/pages/system/role/edit/dialog.vue
  42. 1 1
      backstage/src/pages/system/user/edit.vue
  43. 4 4
      backstage/src/pages/system/user/index.vue
  44. 1 1
      backstage/src/pages/system/worklog/index.vue
  45. 27056 1
      backstage/theme/index.css
  46. 11 0
      web/package-lock.json
  47. 1 0
      web/package.json
  48. 二进制
      web/public/model/Build/WebGl-3DMapPage.data
  49. 7 0
      web/public/model/Build/WebGl-3DMapPage.framework.js
  50. 1 0
      web/public/model/Build/WebGl-3DMapPage.loader.js
  51. 二进制
      web/public/model/Build/WebGl-3DMapPage.wasm
  52. 二进制
      web/public/model/TemplateData/favicon.ico
  53. 二进制
      web/public/model/TemplateData/fullscreen-button.png
  54. 二进制
      web/public/model/TemplateData/progress-bar-empty-dark.png
  55. 二进制
      web/public/model/TemplateData/progress-bar-empty-light.png
  56. 二进制
      web/public/model/TemplateData/progress-bar-full-dark.png
  57. 二进制
      web/public/model/TemplateData/progress-bar-full-light.png
  58. 16 0
      web/public/model/TemplateData/style.css
  59. 二进制
      web/public/model/TemplateData/unity-logo-dark.png
  60. 二进制
      web/public/model/TemplateData/unity-logo-light.png
  61. 二进制
      web/public/model/TemplateData/webgl-logo.png
  62. 39 0
      web/public/model/index.html
  63. 1 1
      web/public/scene.html
  64. 3 3
      web/public/static/css/main.css
  65. 2 2
      web/public/static/css/oldVer/main0.css
  66. 1653 0
      web/public/static/js/Hot copy.js
  67. 75 60
      web/public/static/js/Hot.js
  68. 59051 0
      web/public/static/js/main_2020_show copy.js
  69. 410 1111
      web/public/static/js/main_2020_show.js
  70. 705 0
      web/public/static/js/manage copy.js
  71. 640 102
      web/public/static/js/manage.js
  72. 0 87
      web/public/static/js/myShow.js
  73. 二进制
      web/public/xuliezhen/female_1/Bye.png
  74. 二进制
      web/public/xuliezhen/female_1/Greeting.png
  75. 二进制
      web/public/xuliezhen/female_1/Right.png
  76. 二进制
      web/public/xuliezhen/female_1/Speaking1.png
  77. 二进制
      web/public/xuliezhen/female_1/Speaking2.png
  78. 二进制
      web/public/xuliezhen/female_1/Speaking3.png
  79. 二进制
      web/public/xuliezhen/female_1/Speaking4.png
  80. 二进制
      web/public/xuliezhen/female_1/Speaking5.png
  81. 二进制
      web/public/xuliezhen/female_1/Stand.png
  82. 二进制
      web/public/xuliezhen/female_1/Stand2.png
  83. 二进制
      web/public/xuliezhen/female_1/StandLook.png
  84. 二进制
      web/public/xuliezhen/female_1/Thanks.png
  85. 二进制
      web/public/xuliezhen/female_1/Wrong.png
  86. 二进制
      web/public/xuliezhen/female_2/Bye.png
  87. 二进制
      web/public/xuliezhen/female_2/Greeting.png
  88. 二进制
      web/public/xuliezhen/female_2/Right.png
  89. 二进制
      web/public/xuliezhen/female_2/Speaking1.png
  90. 二进制
      web/public/xuliezhen/female_2/Speaking2.png
  91. 二进制
      web/public/xuliezhen/female_2/Speaking3.png
  92. 二进制
      web/public/xuliezhen/female_2/Speaking4.png
  93. 二进制
      web/public/xuliezhen/female_2/Speaking5.png
  94. 二进制
      web/public/xuliezhen/female_2/Stand.png
  95. 二进制
      web/public/xuliezhen/female_2/Stand2.png
  96. 二进制
      web/public/xuliezhen/female_2/StandLook.png
  97. 二进制
      web/public/xuliezhen/female_2/Thanks.png
  98. 二进制
      web/public/xuliezhen/female_2/Wrong.png
  99. 二进制
      web/public/xuliezhen/male/Bye.png
  100. 0 0
      web/public/xuliezhen/male/Greeting.png

+ 17 - 0
backstage/src/assets/styles/public.less

@@ -277,6 +277,17 @@ input::-webkit-inner-spin-button{
   display: none!important;
 }
 
+
+.fadeVisable{
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+  opacity: 0;
+  position: absolute;
+  top: 0;
+  left: 0;
+}
+
 .disable {
   opacity: 0.8;
   pointer-events: none !important;
@@ -302,7 +313,13 @@ input::-webkit-inner-spin-button{
     margin-right: 4px;
   }
 }
+.el-input__inner{
+  padding: 0 50px 0 15px!important;
+}
 
+.el-input-number .el-input__inner{
+  padding: 15px!important;
+}
 @media screen and (max-width: 1700px) {
   html,body{
     font-size: 15px;

+ 2 - 12
backstage/src/components/editcomponent/editcon.vue

@@ -9,21 +9,11 @@
       </el-form>
     </el-main>
     <el-footer class="footer">
-      <template v-if="staStr=='草稿中'||staStr=='审核不通过'">
+      <template>
         <el-button @click="$emit('cancel')">取消</el-button>
-        <el-button :type="($route.params.id&&$route.params.id=='none')?'primary':''" @click="$emit('save')">保存</el-button>
-        <el-button v-if="$route.params.id&&$route.params.id!='none'" @click="$emit('submit')" type="primary">提交</el-button>
+        <el-button type="primary" @click="$emit('save')">保存</el-button>
       </template>
     
-      <template v-else-if="staStr=='待审核非查看'">
-        <el-button @click="$emit('cancel')">返回</el-button>
-        <el-button type="primary" @click="$emit('determine')">审核</el-button>
-      </template>
-
-       <template v-else>
-        <el-button @click="$emit('cancel')">返回</el-button>
-        <el-button v-if="$route.name=='edit-role'||$route.name=='edit-user'" type="primary" @click="$emit('determine')">确定</el-button>
-      </template>
     </el-footer>
   </el-container>
 </template>

+ 11 - 11
backstage/src/components/editcomponent/usereditdialog.vue

@@ -10,32 +10,32 @@
         <div class="formtop">
           <div class="left">
             <el-form-item label="身份码:" prop="userName">
-              <el-input :disabled="true" v-model="form.userName"></el-input>
+              <el-input :disabled="true" :maxlength="INPUTLENGTH" v-model="form.userName"></el-input>
             </el-form-item>
 
             <el-form-item label="用户昵称:" prop="nickName">
-              <el-input v-model="form.nickName"></el-input>
+              <el-input :maxlength="INPUTLENGTH" v-model="form.nickName"></el-input>
             </el-form-item>
 
             <el-form-item label="单位名称:" prop="unit">
-              <el-input :disabled="true" v-model="form.unit"></el-input>
+              <el-input :disabled="true" :maxlength="INPUTLENGTH*5" v-model="form.unit"></el-input>
             </el-form-item>
 
             <el-form-item label="联系电话:" prop="phone">
-              <el-input v-model="form.phone"></el-input>
+              <el-input :maxlength="INPUTLENGTH" v-model="form.phone"></el-input>
             </el-form-item>
           </div>
           <div class="right">
             <el-form-item label="用户角色:" prop="roleName">
-              <el-input :disabled="true" v-model="form.roleName"></el-input>
+              <el-input :disabled="true" :maxlength="INPUTLENGTH" v-model="form.roleName"></el-input>
             </el-form-item>
 
             <el-form-item label="真实姓名:" prop="realName">
-              <el-input :disabled="true" v-model="form.realName"></el-input>
+              <el-input :disabled="true" :maxlength="INPUTLENGTH" v-model="form.realName"></el-input>
             </el-form-item>
 
             <el-form-item label="通讯地址:" prop="address">
-              <el-input v-model="form.address"></el-input>
+              <el-input v-model="form.address" :maxlength="INPUTLENGTH*5"></el-input>
             </el-form-item>
 
             <el-form-item label="性别:" prop="sex">
@@ -50,16 +50,16 @@
         <div class="formbom">
           <div class="left">
             <el-form-item label="旧密码:" prop="oldPassword">
-              <el-input v-model="form.oldPassword"></el-input>
+              <el-input :maxlength="INPUTLENGTH" v-model="form.oldPassword"></el-input>
             </el-form-item>
             <el-form-item label="新密码:" prop="newPassword">
-              <el-input v-model="form.newPassword"></el-input>
+              <el-input :maxlength="INPUTLENGTH" v-model="form.newPassword"></el-input>
             </el-form-item>
           </div>
 
           <div class="right">
             <el-form-item label="确认密码:" prop="confirmPassword">
-              <el-input v-model="form.confirmPassword"></el-input>
+              <el-input :maxlength="INPUTLENGTH" v-model="form.confirmPassword"></el-input>
             </el-form-item>
           </div>
         </div>
@@ -126,7 +126,7 @@ export default {
           this.$alert('编辑成功', '提示', {
               confirmButtonText: '确定',
               callback: () => {
-                this.$$emit('logout')
+                this.$emit('logout')
               }
             })
         })

+ 13 - 15
backstage/src/components/table/index.vue

@@ -39,7 +39,7 @@
         </template>
 
         <template v-else-if="item.prop === 'isEnabled'">
-          <span v-if="scope.row.roleKey&&$route.name=='role'">-</span>
+          <span v-if="scope.row.roleKey&&($route.name=='role'||$route.name=='user')">-</span>
             <el-switch
             @change="(e)=>{handleDisableSwitch(e,scope.row)}"
             v-else
@@ -58,36 +58,31 @@
               <slot :name="item.prop" :data="scope.row"></slot>
           </template>
           
-          <span v-else>{{ scope.row[item.prop] }}</span>
+          <span v-else>{{ scope.row[item.prop] || item.default || '-' }}</span>
         </template>
       </el-table-column>
 
 
       <el-table-column label="操作" width="200" v-if="$route.meta.type=='content'&&$route.name!='scene'">
         <template slot-scope="scope">
-          <template v-if="isNull(scope.row.status)">
-            <span v-if="activeSub['查看']" class="o-span" @click="goto(scope.row)">查看</span>
-            <span v-if="activeSub['删除']" :class="{disabletxt:scope.row.display}" class="o-span" @click="$emit('del',{item:scope.row,type})">删除</span>
-          </template>
-
-          <template v-else>
+          <template>
              <!-- 草稿中 -->  
-            <span v-if="scope.row.status===0 && activeSub['提交']" class="o-span" @click="$emit('submit',{item:scope.row,type})">提交</span>
+            <span v-if="activeSub['提交']" class="o-span" @click="$emit('submit',{item:scope.row,type})">提交</span>
 
             <!-- 待审核 -->
-            <span v-if="(scope.row.status==1||scope.row.status==3) && activeSub['查看']" class="o-span" @click="goto(scope.row)">查看</span>
+            <!-- <span v-if="activeSub['查看']" class="o-span" @click="goto(scope.row)">查看</span> -->
 
             <!-- 有审核权限 -->
-            <span v-if="scope.row.status==1 && activeSub['审核']" class="o-span" @click="audit(scope.row)">审核</span>
+            <span v-if="activeSub['审核']" class="o-span" @click="audit(scope.row)">审核</span>
 
             <!-- 审核不通过||草稿中 -->
-            <span v-if="(scope.row.status==2||scope.row.status==0) && activeSub['编辑']" class="o-span" @click="goto(scope.row)">编辑</span> 
+            <span v-if="activeSub['编辑']" class="o-span" @click="goto(scope.row)">编辑</span> 
 
              <!-- 草稿中且有删除权限 -->  
             <span v-if="activeSub['删除']" :class="{disabletxt:scope.row.display}" class="o-span" @click="$emit('del',{item:scope.row,type})">删除</span>
           </template>
 
-          <span v-if="!activeSub['查看']&&!activeSub['提交']&&!activeSub['审核']&&!activeSub['编辑']&&!activeSub['删除']">-</span>
+          <span v-if="!activeSub['编辑']&&!activeSub['删除']">-</span>
         </template>
       </el-table-column>
       
@@ -159,10 +154,13 @@ export default {
       handleDisplay(this.type,{
         id:item.id,
         display:Number(val),
-      },()=>{})
+      },()=>{
+         if (this.type=='questionGroup') {
+            this.$emit('refresh')
+          }
+      })
     },
     handleDisableSwitch(val,item){
-      console.log(item);
       handleDisable(this.$route.name,{
         id:item.id,
         isEnabled:Number(val),

+ 1 - 1
backstage/src/components/uploadFile/index.vue

@@ -35,7 +35,7 @@ export default {
       this.loading = this.$loading(this.loadOption)
     },
     beforeMultipleUpload(file){
-      let typeArr = this.desc.indexOf('4dage')>-1 ? ['.4dage'] : ['avi','mov','rmvb','rm','flv','mp4','3gp']
+      let typeArr = this.desc.indexOf('4dage')>-1 ? ['.4dage'] : ['avi','mov','rmvb','rm','mp4']
       let type = this.isTypeBySend(file.name,typeArr);
       if (!type) {
         this.$message.error('只允许指定文件格式的文件');

+ 13 - 0
backstage/src/configue/api.js

@@ -134,6 +134,19 @@ export function delImg(data, cb) {
   });
 }
 
+
+//更新图库图片
+export function refreshImg(data, cb) {
+  axios({
+    method: "get",
+    url: `cms/goods/afresh/uploadImg/${data.fileId}/${data.code}`,
+  }).then((res) => {
+    cb(res);
+  });
+}
+
+
+
 //提审
 export function apply(type,data, cb) {
   axios({

+ 1 - 1
backstage/src/configue/http.js

@@ -8,7 +8,7 @@ const vue = new Vue();
 var isProduction = process.env.NODE_ENV === "production";
 let loading = "";
 
-const serverName = isProduction ? "/" : "http://192.168.0.245:8003/";
+const serverName = isProduction ? "/" : "http://192.168.0.135:8013/";
 
 const serverLocation = window.location.hostname;
 

+ 68 - 62
backstage/src/configue/menu.js

@@ -24,69 +24,79 @@ let routes = [
       {
         key: "id",
         default: "none",
+      }
+    ],
+    type:'content'
+  },
+  {
+    name: "专家风采管理",
+    id: "3",
+    key: "expert",
+    param: [
+      {
+        key: "type",
+        default: "expert", //信息:info,致敬:salute
       },
+    ],
+    editParam: [
       {
-        key: "status",
-        default: "0",
+        key: "type",
+        default: "expert",
+      },
+      {
+        key: "id",
+        default: "none",
       }
     ],
     type:'content'
   },
-  // {
-  //   name: "纪念祭扫管理",
-  //   id: "3",
-  //   key: "sweep",
-  //   param: [
-  //     {
-  //       key: "type",
-  //       default: "martyr", //信息:info,致敬:salute
-  //     },
-  //   ],
-  //   editParam: [
-  //     {
-  //       key: "type",
-  //       default: "martyr",
-  //     },
-  //     {
-  //       key: "id",
-  //       default: "none",
-  //     },
-  //     {
-  //       key: "status",
-  //       default: "0",
-  //     }
-  //   ],
-  //   type:'content'
-  // },
-  // {
-  //   name: "学习园地管理",
-  //   id: "4",
-  //   key: "study",
-  //   param: [
-  //     {
-  //       key: "type",
-  //       default: "info", //阅历:info,共享:share
-  //     },
-  //   ],
-  //   editParam: [
-  //     {
-  //       key: "type",
-  //       default: "info",
-  //     },
-  //     {
-  //       key: "id",
-  //       default: "none",
-  //     },
-  //     {
-  //       key: "status",
-  //       default: "0",
-  //     }
-  //   ],
-  //   type:'content'
-  // },
   {
-    name: "互动模块管理",
+    name: "数字沙盘管理",
+    id: "4",
+    key: "sand",
+    param: [
+      {
+        key: "type",
+        default: "sand", //信息:info,致敬:salute
+      },
+    ],
+    editParam: [
+      {
+        key: "type",
+        default: "sand",
+      },
+      {
+        key: "id",
+        default: "none",
+      }
+    ],
+    type:'content'
+  },
+  {
+    name: "学习园地管理",
     id: "5",
+    key: "study",
+    param: [
+      {
+        key: "type",
+        default: "info", //阅历:info,共享:share
+      },
+    ],
+    editParam: [
+      {
+        key: "type",
+        default: "info",
+      },
+      {
+        key: "id",
+        default: "none",
+      }
+    ],
+    type:'content'
+  },
+  {
+    name: "互动模块管理",
+    id: "6",
     key: "interaction",
     param: [
       {
@@ -102,17 +112,13 @@ let routes = [
       {
         key: "id",
         default: "none",
-      },
-      {
-        key: "status",
-        default: "0",
       }
     ],
     type:'content'
   },
   {
     name: "用户管理",
-    id: "6",
+    id: "7",
     key: "user",
     param: [
       {
@@ -134,7 +140,7 @@ let routes = [
   },
   {
     name: "角色权限管理",
-    id: "7",
+    id: "8",
     key: "role",
     param: [
       {
@@ -156,7 +162,7 @@ let routes = [
   },
   {
     name: "操作日志",
-    id: "8",
+    id: "9",
     key: "worklog",
     type:'system',
     noEdit:true

+ 40 - 9
backstage/src/mixins/index.js

@@ -11,8 +11,16 @@ Vue.prototype.$http = axios;
 Vue.prototype.isImage = isImage;
 Vue.prototype.isTypeBySend = isTypeBySend;
 
-Vue.prototype.INPUTLENGTH = 25;
+Vue.prototype.INPUTLENGTH = 20;
 Vue.prototype.PAGESIZES = [25, 50, 75, 100];
+Vue.prototype.UNITS = [{
+  name:'第一层',
+  id:'1'
+},{
+  name:'第二层',
+  id:'2'
+}]
+
 Vue.prototype.loading = {
   close() {},
 };
@@ -105,6 +113,23 @@ let g_political = [{
   val:'预备党员'
 }]
 
+let g_expert = [{
+  val:'一级',
+  id:1
+},{
+  val:'二级',
+  id:2
+},{
+  val:'三级',
+  id:3
+},{
+  val:'院士',
+  id:4
+},{
+  val:'其他',
+  id:5
+}]
+
 import MainTop from "@/components/main-top";
 import search from "@/components/search";
 import accordion from "@/components/accordion";
@@ -127,7 +152,8 @@ Vue.mixin({
   },
   data(){
     return {
-      g_political
+      g_political,
+      g_expert
     }
   },
   methods: {
@@ -181,12 +207,12 @@ Vue.mixin({
     },
     goto(item) {
       let { type } = this.$route.params;
+      console.log(type);
       this.$router.push({
         name: "edit-" + this.$route.name,
         params: {
           id: item.id,
           type: type,
-          status: item.status,
         },
       });
     },
@@ -214,7 +240,7 @@ Vue.mixin({
       let { type } = this.$route.params;
       this.$router.push({
         name: "edit-" + this.$route.name,
-        params: { id: item.id, type: type, status: item.status },
+        params: { id: item.id, type: type },
         query: { isAudit: true },
       });
     },
@@ -272,10 +298,13 @@ Vue.mixin({
       this.backList();
     },
     getAuth(menu, key) {
+
       if (!menu) return;
+
       let auth = {};
 
-      if (key == "场景") {
+      if (key == "场景" || key == '专家' || key=='沙盘') {
+
         menu.children && menu.children.forEach((item) => {
           auth[item.name] = item.authority;
         });
@@ -284,11 +313,16 @@ Vue.mixin({
         let temp =
           menu.children &&
           menu.children.find((item) => item.name.indexOf(key) > -1);
+      console.log(menu, key);
+
         if (!temp) return;
         temp.children.forEach((item) => {
           auth[item.name] = item.authority;
         });
+
         this.$store.commit("SetActiveSub", auth);
+      console.log(auth);
+
       }
     },
   },
@@ -298,9 +332,6 @@ Vue.mixin({
       handler: function() {
         this.getList && this.getList();
       },
-    },
-    status() {
-      this.getList && this.getList();
-    },
+    }
   },
 });

+ 48 - 4
backstage/src/pages/content/collection/componets/img.vue

@@ -1,13 +1,18 @@
 <template>
   <div>
     <el-form-item label="标题:" prop="name">
-      <el-input v-model="form.name" :maxlength="INPUTLENGTH" show-word-limit></el-input>
+      <el-input v-model="form.name" :maxlength="INPUTLENGTH*5" show-word-limit></el-input>
     </el-form-item>
 
     <el-form-item label="精品类型:">
       <el-radio disabled v-model="radio" label="选中且禁用">专题图库</el-radio>
     </el-form-item>
 
+    <el-form-item label="所属楼层:">
+      <el-radio v-model="form.zone" :label="1">第一层</el-radio>
+      <el-radio v-model="form.zone" :label="2">第二层</el-radio>
+    </el-form-item>
+
     <el-form-item label="图片:" prop="thumb">
       <el-input v-model="form.thumb" class="fadeDom"></el-input>
       <ul class="tuku">
@@ -36,11 +41,16 @@
               type="primary"
               >设为封面</el-button
             >
-            <el-button size="mini" @click="reupload">重新上传</el-button>
+            <el-button size="mini"  style="position:relative;">
+              <span>
+                重新上传{{item.code}}
+                <uploadImg class="fadeVisable" :url="`${$serverName}cms/goods/afresh/uploadImg/${item.id}/${form.code}`" @update="(e)=>{reupload(e,item)}" />
+              </span>
+            </el-button>
           </div>
         </li>
         <li>
-          <uploadImg :url="thumbUrl" @update="updateImg" :thumb="form.thumb" />
+          <uploadImg id="uli" :url="thumbUrl" @update="updateImg" :thumb="form.thumb" />
         </li>
       </ul>
     </el-form-item>
@@ -101,9 +111,43 @@ export default {
       });
     },
 
-    reupload() {},
+    reupload(data,item) {
+      try {
+        this.filelist = this.filelist.map((sub) => {
+        //匹配置为0
+        if (item.id == sub.id) {
+          sub = {
+            ...sub,
+            ...data
+          }
+          console.log(sub);
+        } 
+        return sub
+      });
+
+      } catch (e) {
+        !e
+      }
+      console.log(this.filelist);
+
+      // refreshImg(
+      //     {
+      //       fileId: data.id,
+      //       code:data.code
+      //     },
+      //     () => {
+            
+      //     }
+      //   );
+      
+      // console.log(this.filelist);
+
+      // this.$refs.uli.$el.$refs.chidleimg.click()
+    },
 
     updateImg(data) {
+
+      console.log(data);
       
       this.filelist.push({
         ...data,

+ 6 - 1
backstage/src/pages/content/collection/componets/model.vue

@@ -1,12 +1,17 @@
 <template>
   <div>
     <el-form-item label="标题:" prop="name">
-      <el-input v-model="form.name" :maxlength="INPUTLENGTH" show-word-limit></el-input>
+      <el-input v-model="form.name" :maxlength="INPUTLENGTH*5" show-word-limit></el-input>
     </el-form-item>
 
     <el-form-item label="精品类型:">
       <el-radio disabled v-model="radio" label="选中且禁用">实物模型</el-radio>
     </el-form-item>
+    
+    <el-form-item label="所属楼层:">
+      <el-radio v-model="form.zone" :label="1">第一层</el-radio>
+      <el-radio v-model="form.zone" :label="2">第二层</el-radio>
+    </el-form-item>
 
     <el-form-item label="封面图片:" prop="thumb">
       <uploadThumb :url="thumbUrl" @update="data=>{form.thumb = data}" :thumb="form.thumb" />

+ 1 - 1
backstage/src/pages/content/collection/componets/plugin/uploadimg.vue

@@ -37,7 +37,7 @@ export default {
       }
       const isLt2M = file.size / 1024 / 1024 < 20;
       if (!isLt2M) {
-        this.$message.error("上传头像图片大小不能超过 20MB!");
+        this.$message.error("上传图片大小不能超过 20MB!");
         return isLt2M;
       }
       this.showLoading()

+ 7 - 2
backstage/src/pages/content/collection/componets/video.vue

@@ -1,19 +1,24 @@
 <template>
   <div>
     <el-form-item label="标题:" prop="name">
-      <el-input v-model="form.name" :maxlength="INPUTLENGTH" show-word-limit></el-input>
+      <el-input v-model="form.name" :maxlength="INPUTLENGTH*5" show-word-limit></el-input>
     </el-form-item>
 
     <el-form-item label="精品类型:">
       <el-radio disabled v-model="radio" label="选中且禁用">视频档案</el-radio>
     </el-form-item>
 
+    <el-form-item label="所属楼层:">
+      <el-radio v-model="form.zone" :label="1">第一层</el-radio>
+      <el-radio v-model="form.zone" :label="2">第二层</el-radio>
+    </el-form-item>
+
     <el-form-item label="封面图片:" prop="thumb">
       <uploadThumb :url="thumbUrl" @update="data=>{form.thumb = data}" :thumb="form.thumb" />
     </el-form-item>
 
     <el-form-item label="视频文件:" prop="filePath">
-      <uploadFile :url="fileUrl"  @update="data=>{form.fileName = data.fileName,form.filePath = data.filePath}" :filePath="form.filePath" :desc="'支持AVI、mov、rmvb、rm、FLV、mp4、3GP等格式的视频文件,大小不超过2GB'" />
+      <uploadFile :url="fileUrl"  @update="data=>{form.fileName = data.fileName,form.filePath = data.filePath}" :filePath="form.filePath" :desc="'支持AVI、mov、rmvb、rm、mp4等格式的视频文件,大小不超过2GB'" />
       <video class="svideo" v-if="form.filePath" controls :src="form.filePath">
       </video>
     </el-form-item>

+ 21 - 51
backstage/src/pages/content/collection/data.js

@@ -13,25 +13,14 @@ let raw = {
       label: "封面图片",
     },
     {
-      prop: "visit",
-      label: "阅读量",
-    },
-    {
-      prop: "userName",
-      label: "提交人",
+      prop: "zone",
+      label: "楼层",
     },
     {
       prop: "createTime",
       label: "提交时间",
     },
-    {
-      prop: "status",
-      label: "状态",
-    },
-    {
-      prop: "record",
-      label: "审核记录",
-    },
+  
     {
       prop: "display",
       label: "是否显示"
@@ -51,25 +40,14 @@ let raw = {
       label: "封面图片",
     },
     {
-      prop: "visit",
-      label: "阅读量",
-    },
-    {
-      prop: "userName",
-      label: "提交人",
+      prop: "zone",
+      label: "单元",
     },
     {
       prop: "createTime",
       label: "提交时间",
     },
-    {
-      prop: "status",
-      label: "状态",
-    },
-    {
-      prop: "record",
-      label: "审核记录",
-    },
+
     {
       prop: "display",
       label: "是否显示"
@@ -89,25 +67,14 @@ let raw = {
       label: "封面图片",
     },
     {
-      prop: "visit",
-      label: "阅读量",
-    },
-    {
-      prop: "userName",
-      label: "提交人",
+      prop: "zone",
+      label: "单元",
     },
     {
       prop: "createTime",
       label: "提交时间",
     },
-    {
-      prop: "status",
-      label: "状态",
-    },
-    {
-      prop: "record",
-      label: "审核记录",
-    },
+    
     {
       prop: "display",
       label: "是否显示"
@@ -118,15 +85,15 @@ let raw = {
 let menu = [
   {
     id: 'model',
-    name: "实物模型",
+    name: "模型管理",
   },
   {
     id: 'img',
-    name: "专题图库",
+    name: "图片管理",
   },
   {
     id: 'video',
-    name: "视频档案",
+    name: "视频管理",
   },
 ];
 
@@ -135,20 +102,23 @@ let formKey = {
     name:'',
     thumb:'',
     filePath:'',
-    display: false
+    display: false,
+    zone: 1
   },
   img:{ 
     name:'',
     thumb:'',
     filePath:'',
     display: false,
-    indexId:''
+    indexId:'',
+    zone: 1
   },
   video:{ 
     name:'',
     thumb:'',
     filePath:'',
-    display: false
+    display: false,
+    zone: 1
   }
 }
 
@@ -161,12 +131,12 @@ let rules = {
   img:{ 
     name: [{ required: true, message: "请输入标题", trigger: "blur" }],
     thumb: [{ required: true, message: "请上传图片", trigger: "change" }],
-    filePath: [{ required: true, message: "请上传封面图片", trigger: "blur" }]
+    filePath: [{ required: true, message: "请上传封面图片", trigger: "change" }]
   },
   video:{ 
     name: [{ required: true, message: "请输入标题", trigger: "blur" }],
-    thumb: [{ required: true, message: "请上传封面图片", trigger: "blur" }],
-    filePath: [{ required: true, message: "请上传封面图片", trigger: "blur" }]
+    thumb: [{ required: true, message: "请上传封面图片", trigger: "change" }],
+    filePath: [{ required: true, message: "请上传封面图片", trigger: "change" }]
   }
 }
 

+ 2 - 4
backstage/src/pages/content/collection/edit.vue

@@ -7,14 +7,13 @@
       :type="type"
       :rule="rule"
       :form="form"
-      :status="status"
       @cancel="backList"
       @save="save"
       @submit="submit({id},val)"
       @determine="determine"
     >
       <template slot-scope="{ form }" slot="content" >
-        <component :data="form" :is="cp" :filelist="filelist" :class="{disable:status!==0&&status!==2}" />
+        <component :data="form" :is="cp" :filelist="filelist" />
       </template>
     </editcon>
 
@@ -44,12 +43,11 @@ export default {
     vvideo
   },
   data() {
-    let { type, id, status } = this.$route.params;
+    let { type, id } = this.$route.params;
     return {
       val:'goods',
       type,
       id:String(id),
-      status:Number(status),
       form: "",
       filelist: [],
       showAudit:false

+ 22 - 10
backstage/src/pages/content/collection/index.vue

@@ -15,7 +15,6 @@
         title="精品典藏"
       />
       <div class="tablebody">
-        <status :status="status" @select="selectStatus"></status>
         <search>
           <div slot="content" class="searchslot">
             <span>提交时间:</span>
@@ -37,8 +36,18 @@
               @keydown.enter.native="getList"
               placeholder="请输入关键字"
             ></el-input>
+            <span>楼层:</span>
+            <el-select v-model="search.zone" placeholder="请选择">
+              <el-option label="全部"  value="" key=""></el-option>
+              <el-option
+                v-for="item in UNITS"
+                :key="item.id"
+                :label="item.name"
+                :value="item.id">
+              </el-option>
+            </el-select>
             <el-button @click="getList" type="primary">查询</el-button>
-            <el-button @click="search.date='',search.inputKey='',getList()" >重置</el-button>
+            <el-button @click="search.date='',search.zone='',search.inputKey='',getList()" >重置</el-button>
           </div>
         </search>
         <div class="table">
@@ -61,10 +70,6 @@
             @submit="submit"
             :tableData="list"
           >
-          
-            <template slot-scope="{data}" slot="record">
-              <el-button @click="applyDetail(data,type)" type="text">审核详情</el-button>
-            </template>
           </vtable>
         </div>
       </div>
@@ -90,7 +95,8 @@ export default {
       search: {
         inputKey: "",
         date: "",
-        state: "",
+        unit: "",
+        zone:''
       },
       status: "all",
       menu,
@@ -107,20 +113,27 @@ export default {
       this.status = item.id;
     },
     handleMenu(data) {
+      this.search={
+        inputKey: "",
+        date: "",
+        unit: "",
+        zone:''
+      }
       this.$router.push({
         params: { ...this.$route.params, type: data },
       });
     },
    
     getList() {
-      let { inputKey, date } = this.search;
+      let { inputKey, date,zone } = this.search;
       getList(
         this.type,
         {
-          date: date,
+          date,
           pageNum: this.page.pageNum,
           pageSize: this.page.size,
           searchKey: inputKey,
+          zone,
           status: this.status == "all" ? "" : this.status,
           type: this.subMenu
         },
@@ -160,7 +173,6 @@ export default {
     }
   },
   mounted() {
-    this.getList();
   },
 };
 </script>

+ 187 - 0
backstage/src/pages/content/expert/componets/expert.vue

@@ -0,0 +1,187 @@
+<template>
+  <div class="formcon">
+    <div class="formtop">
+      <div class="left">
+        <el-form-item label="类型:" prop="level">
+          <el-select v-model="form.level" placeholder="请选择">
+            <el-option
+              v-for="(item, i) in g_expert"
+              :key="i"
+              :label="item.val"
+              :value="item.id"
+            >
+            </el-option>
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="姓名:" prop="name">
+          <el-input
+            v-model="form.name"
+            :maxlength="INPUTLENGTH"
+            show-word-limit
+          ></el-input>
+        </el-form-item>
+
+        <el-form-item label="年代:">
+          <el-input
+            v-model="form.years"
+            placeholder="请输入年代"
+            :maxlength="INPUTLENGTH"
+            show-word-limit
+          ></el-input>
+        </el-form-item>
+
+        <el-form-item label="头衔:" prop="title">
+          <el-input
+            v-model="form.title"
+            placeholder="请输入内容"
+            :maxlength="INPUTLENGTH"
+            show-word-limit
+          ></el-input>
+        </el-form-item>
+
+         <el-form-item label="排序权重:" prop="sort">
+          <el-input-number :max="99999" v-model="form.sort"></el-input-number>
+        </el-form-item>
+
+        <el-form-item label="介绍:" prop="description">
+          <el-input
+            v-model="form.description"
+            type="textarea"
+            :autosize="{ minRows: 2, maxRows: 4 }"
+            placeholder="请输入内容"
+            :maxlength="INPUTLENGTH * 25"
+            show-word-limit
+          ></el-input>
+        </el-form-item>
+
+        <el-form-item label="忠诚的力量:" prop="type">
+          <el-radio-group v-model="form.type">
+            <el-radio label="">无</el-radio>
+            <el-radio label="1">百岁专家</el-radio>
+            <el-radio label="2">英模专家代表</el-radio>
+          </el-radio-group>
+        </el-form-item>
+
+        <el-form-item label="链接名称:" prop="url">
+          <el-input
+            v-model="form.urlName"
+            placeholder="请输入链接名称"
+            :maxlength="INPUTLENGTH"
+            show-word-limit
+          ></el-input>
+        </el-form-item>
+
+        <el-form-item label="跳转链接:" prop="urlName">
+          <el-input
+            placeholder="请输入跳转链接"
+            v-model="form.url"
+            :maxlength="INPUTLENGTH * 5"
+            show-word-limit
+          >
+            <template slot="prepend">https://</template>
+          </el-input>
+        </el-form-item>
+
+        <el-form-item label="照片:" prop="thumb">
+          <el-input v-model="form.thumb" class="fadeDom"></el-input>
+          <uploadThumb
+            :url="thumbUrl"
+            @update="
+              (data) => {
+                form.thumb = data;
+              }
+            "
+            :thumb="form.thumb"
+          />
+        </el-form-item>
+
+        <el-form-item label="视频文件:" prop="filePath">
+          <uploadFile
+            :url="fileUrl"
+            @update="
+              (data) => {
+                (form.videoName = data.fileName), (form.video = data.filePath);
+              }
+            "
+            :filePath="form.filePath"
+            :desc="
+              '支持AVI、mov、rmvb、rm、mp4等格式的视频文件,大小不超过2GB'
+            "
+          />
+
+          <div class="ssvideo">
+            <video
+              class="svideo"
+              v-if="form.video"
+              controls
+              :src="form.video"
+            ></video>
+            <div
+              class="del"
+              @click.stop="(form.video = ''), (form.videoName = '')"
+            >
+              <i class="el-icon-delete"></i>
+            </div>
+          </div>
+        </el-form-item>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import uploadThumb from "@/components/uploadThumb";
+import uploadFile from "@/components/uploadFile";
+
+export default {
+  props: ["data", "rule"],
+  components: { uploadThumb, uploadFile },
+  data() {
+    return {
+      form: this.data,
+      radio: "选中且禁用",
+      thumbUrl: this.$serverName + "cms/expert/upload/img",
+      fileUrl: this.$serverName + "cms/expert/upload/video",
+    };
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.formcon {
+  width: 100%;
+  .formtop {
+    width: 100%;
+    display: flex;
+    justify-content: flex-start;
+    > div {
+      width: 40%;
+      &:first-of-type {
+        margin-right: 5%;
+      }
+    }
+  }
+  .ssvideo {
+    position: relative;
+    max-width: 600px;
+    >video{
+      width: 100%;
+    }
+    .del {
+      position: absolute;
+      right: 10px;
+      top: 10px;
+      cursor: pointer;
+      font-size: 24px;
+      display: none;
+      color: #fff;
+    }
+    &:hover {
+      .del {
+        display: block;
+      }
+    }
+  }
+}
+</style>

backstage/src/pages/content/sweep/componets/mourn.vue → backstage/src/pages/content/expert/componets/mourn.vue


+ 67 - 0
backstage/src/pages/content/expert/componets/status/index.vue

@@ -0,0 +1,67 @@
+<template>
+  <ul>
+    <li @click="onClick(item)" :class="{active:item.id==status}" v-for="(item,i) in statusArr" :key="i">
+      {{item.name}}
+    </li>
+  </ul>
+</template>
+
+<script>
+  
+
+export default {
+  props:['status'],
+  data(){
+    return {
+      statusArr:[
+        {
+          id: "all",
+          name: "全部",
+        },
+        {
+          id: 4,
+          name: "院士",
+        },
+        {
+          id: 1,
+          name: "一级专家",
+        },
+        {
+          id: 2,
+          name: "二级专家",
+        },
+        {
+          id: 3,
+          name: "三级专家",
+        },
+        {
+          id: 5,
+          name: "其他专家",
+        },
+      ]
+    }
+  },
+  methods:{
+    onClick(item){
+      this.$emit('select',item)
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+ul{
+  display: flex;
+  margin-top: 10px;
+  >li{
+    margin-right: 30px;
+    color: #707070;
+    cursor: pointer;
+  }
+  .active{
+    color: #143E3A;
+    padding-bottom: 10px;
+    border-bottom: 2px solid #143E3A;
+  }
+}
+</style>

+ 75 - 0
backstage/src/pages/content/expert/data.js

@@ -0,0 +1,75 @@
+let raw = {
+  expert: [
+    {
+      prop: "name",
+      label: "姓名",
+    },
+
+    {
+      prop: "thumb",
+      label: "专家照片",
+      default: true,
+    },
+    {
+      prop: "years",
+      label: "年代",
+    },
+    {
+      prop: "title",
+      label: "头衔",
+    },
+    {
+      prop: "sort",
+      label: "排序权重",
+    },
+    {
+      prop: "description",
+      label: "介绍",
+    },
+    {
+      prop: "display",
+      label: "是否显示",
+    },
+  ],
+};
+
+let menu = [
+  {
+    id: "expert",
+    name: "专家信息",
+  },
+];
+
+let formKey = {
+  expert: {
+    description: "",
+    level: 1,
+    name: "",
+    sort: 1,
+    thumb: "",
+    title: "",
+    type: "",
+    url: "",
+    urlName: "",
+    video: "",
+    videoName: "",
+    years: "",
+  },
+};
+
+let rules = {
+  expert: {
+    name: [{ required: true, message: "请输入专家姓名", trigger: "blur" }],
+    years: [{ required: true, message: "请输入年代", trigger: "blur" }],
+    description: [
+      { required: true, message: "请输入专家介绍", trigger: "blur" },
+    ],
+    thumb: [{ required: true, message: "请上传专家姓名", trigger: "blur" }],
+  },
+};
+
+let menuStr = {
+  expert: "专家",
+};
+
+export { raw, formKey, menu, rules, menuStr };

+ 3 - 20
backstage/src/pages/content/sweep/edit.vue

@@ -7,7 +7,6 @@
       :type="type"
       :rule="rule"
       :form="form"
-      :status="status"
       @cancel="backList"
       @save="save"
       @submit="submit({ id }, type)"
@@ -17,7 +16,6 @@
         <component
           :data="form"
           :is="cp"
-          :class="{ disable: status !== 0 && status !== 2 }"
         />
       </template>
     </editcon>
@@ -34,24 +32,21 @@
 <script>
 import { mapGetters } from "vuex";
 
-import vmartyr from "./componets/martyr";
-import vmourn from "./componets/mourn";
+import vexpert from "./componets/expert";
 
 import { formKey, rules } from "./data";
 import { save, getDetail } from "@/configue/api";
 
 export default {
   components: {
-    vmartyr,
-    vmourn,
+    vexpert,
   },
   data() {
-    let { type, id, status } = this.$route.params;
+    let { type, id } = this.$route.params;
 
     return {
       type,
       id: String(id),
-      status: Number(status),
       form: "",
       showAudit: false,
     };
@@ -74,18 +69,6 @@ export default {
     save(submit = "", cb = null) {
       this.validate(() => {
         let params = {
-          birthday: "",
-          description: "",
-          dieDay: "",
-          diePlace: "",
-          display: 0,
-          honor: "",
-          nation: "",
-          nativePlace: "",
-          politicsStatus: "",
-          realName: "",
-          sex: 0,
-          thumb: "",
           id: this.id == "none" ? null : this.id,
           ...this.form,
         };

+ 19 - 28
backstage/src/pages/content/sweep/index.vue

@@ -2,30 +2,20 @@
   <div>
     <main-top>
       <div slot='con' v-if="activeSub['新增']">
-        <el-button v-if="$route.params.type == 'martyr'" @click="goto({ id: 'none',status: 0 })" type="primary">登记</el-button>
+        <el-button @click="goto({ id: 'none'})" type="primary">登记</el-button>
       </div>
     </main-top>
-    <div class="tablecon flexcon" >
-      <accordion @select="handleMenu" :menu="menu" :default="subMenu" title="纪念祭扫"/>
+    <div class="tablecon noSubmune" >
       <div class="tablebody">
-        <status :status="status" v-if="$route.params.type=='martyr'" @select="selectStatus"></status>
+        <vstatus :status="status" @select="selectStatus"></vstatus>
         <search>
           <div slot="content" class="searchslot">
-            <span>提交时间:</span>
-            <el-date-picker
-              v-model="search.date"
-              type="daterange"
-              value-format="yyyy-MM-dd"
-              range-separator="-"
-              start-placeholder="开始日期"
-              end-placeholder="结束日期">
-            </el-date-picker>
-            <span>{{keyObj[$route.params.type]}}:</span>
+            <span>姓名:</span>
             <el-input class="elInput paddingmore" :maxlength="25"
               @keydown.enter.native="getList"
                 show-word-limit v-model="search.inputKey" placeholder="请输入关键字"></el-input>
             <el-button @click="getList" type="primary">查询</el-button>
-            <el-button @click="search.date='',search.inputKey='',getList()" >重置</el-button>
+            <el-button @click="search.inputKey='',getList()" >重置</el-button>
 
           </div>
         </search>
@@ -55,8 +45,9 @@
 
 <script>
 
-import {raw,menu,menuStr} from "./data";
+import {raw,menu} from "./data";
 import {getList} from "@/configue/api";
+import status from "./componets/status";
 
 import { mapGetters } from "vuex";
 
@@ -76,13 +67,12 @@ export default {
       page:{
         size:25,
         pageNum:1
-      },
-      keyObj:{
-        'martyr':'烈士姓名',
-        'mourn':'缅怀内容'
       }
     }
   },
+  components:{
+    vstatus:status
+  },
   methods:{
     selectStatus(item){
       this.status = item.id
@@ -94,13 +84,12 @@ export default {
     },
     
     getList(){
-      let {inputKey,date} = this.search
+      let {inputKey} = this.search
       getList(this.subMenu,{
-        date:date,
         pageNum: this.page.pageNum,
         pageSize: this.page.size,
         searchKey: inputKey,
-        status: this.status == 'all' ? '' : this.status
+        level: this.status == 'all' ? '' : this.status
       },data=>{
           this.list = data.data
       })
@@ -120,11 +109,14 @@ export default {
     }
   },
   watch: {
+    status(){
+      this.getList();
+    },
     subMenu:{
       deep:true,
       immediate:true,
-      handler:function (newVal) {
-        this.getAuth(this.activeMenu,menuStr[newVal])
+      handler:function () {
+        this.getAuth(this.activeMenu,'专家')
         this.getList();
       }
     },
@@ -132,15 +124,14 @@ export default {
       deep:true,
       immediate:true,
       handler:function (newVal) {
-        this.getAuth(newVal,menuStr[this.subMenu])
+        this.getAuth(newVal,'专家')
       }
     }
   },
   mounted(){
-    this.getList()
   }
 }
-</script>tra
+</script>
 <style lang="less" scoped>
 
 </style>

backstage/src/pages/content/interaction/componets/sensitive.vue → backstage/src/pages/content/interaction/componets/donate.vue


+ 2 - 2
backstage/src/pages/content/interaction/componets/questionGroup.vue

@@ -1,7 +1,7 @@
 <template>
   <div>
     <el-form-item label="题组标题:" prop="name">
-      <el-input v-model="form.name" :maxlength="INPUTLENGTH" show-word-limit></el-input>
+      <el-input v-model="form.name" :maxlength="INPUTLENGTH * 5" show-word-limit></el-input>
     </el-form-item>
 
     <el-form-item prop="answerStr">
@@ -17,7 +17,7 @@
           </div>
           <div class="qtitle">
             <label class="required">题目:</label>
-            <el-input v-model="item.question" :maxlength="INPUTLENGTH" show-word-limit></el-input>
+            <el-input v-model="item.question" :maxlength="INPUTLENGTH*5" show-word-limit></el-input>
           </div>
 
           <div class="qanswer">

+ 24 - 55
backstage/src/pages/content/interaction/data.js

@@ -5,16 +5,9 @@ let raw = {
       label: "编号",
     },
     {
-      prop: "unit",
-      label: "单位名称",
-    },
-    {
-      prop: "realName",
-      label: "真实姓名",
-    },
-    {
-      prop: "nickName",
+      prop: "name",
       label: "昵称",
+      default:'匿名用户'
     },
     {
       prop: "content",
@@ -37,18 +30,6 @@ let raw = {
       label: "编号",
     },
     {
-      prop: "unit",
-      label: "单位名称",
-    },
-    {
-      prop: "realName",
-      label: "真实姓名",
-    },
-    {
-      prop: "nickName",
-      label: "昵称",
-    },
-    {
       prop: "content",
       label: "弹幕内容",
       width:350
@@ -77,46 +58,34 @@ let raw = {
       label: "题目数",
     },
     {
-      prop: "visit",
-      label: "答题次数",
-    },
-    {
       prop: "userName",
-      label: "提交人",
+      label: "创建人",
     },
     {
       prop: "createTime",
       label: "提交时间",
     },
     {
-      prop: "status",
-      label: "状态",
-    },
-    {
-      prop: "record",
-      label: "审核记录",
-    },
-    {
       prop: "display",
       label: "是否显示"
     }
   ],
-  sensitive: [
+  donate: [
     {
-      prop: "idx",
-      label: "编号",
+      prop: "name",
+      label: "姓名",
     },
     {
-      prop: "name",
-      label: "敏感词",
+      prop: "phone",
+      label: "手机",
     },
     {
-      prop: "userName",
-      label: "提交人",
+      prop: "description",
+      label: "捐赠说明",
     },
     {
       prop: "createTime",
-      label: "提交时间",
+      label: "创建时间",
     }
   ],
   
@@ -127,17 +96,17 @@ let menu = [
     id: 'comment',
     name: "留言管理",
   },
-  // {
-  //   id: 'barrage',
-  //   name: "弹幕管理",
-  // },
-  // {
-  //   id: 'questionGroup',
-  //   name: "答题管理",
-  // },
   {
-    id: 'sensitive',
-    name: "敏感词",
+    id: 'barrage',
+    name: "弹幕管理",
+  },
+  {
+    id: 'questionGroup',
+    name: "答题管理",
+  },
+  {
+    id: 'donate',
+    name: "捐赠管理",
   }
 ];
 
@@ -152,7 +121,7 @@ let formKey = {
     display: 0,
     name: ""
   },
-  sensitive:{ 
+  donate:{ 
  
   }
 }
@@ -186,14 +155,14 @@ let rules = {
     name: [{ required: true, message: "请输入题组标题", trigger: "blur" }],
     answerStr: [{ required: true, validator: checkAnswer, trigger: "change" }],
   },
-  sensitive:{}
+  donate:{}
 }
 
 let menuStr = {
   'comment':'留言',
   'barrage':'弹幕',
   'questionGroup':'答题',
-  'sensitive':'敏感词'
+  'donate':'捐赠管理'
 }
 
 

+ 3 - 5
backstage/src/pages/content/interaction/edit.vue

@@ -7,7 +7,6 @@
       :type="type"
       :rule="rule"
       :form="form"
-      :status="status"
       @cancel="backList"
       @save="save"
       @submit="submit({ id }, type)"
@@ -17,7 +16,6 @@
         <component
           :data="form"
           :is="cp"
-          :class="{ disable: status !== 0 && status !== 2 }"
         />
       </template>
     </editcon>
@@ -35,7 +33,7 @@
 import { mapGetters } from "vuex";
 
 import vcomment from "./componets/comment";
-import vsensitive from "./componets/sensitive";
+import vdonate from "./componets/donate";
 import vbarrage from "./componets/barrage";
 import vquestionGroup from "./componets/questionGroup";
 
@@ -48,7 +46,7 @@ export default {
   components: {
     vcomment,
     vquestionGroup,
-    vsensitive,
+    vdonate,
     vbarrage,
   },
   data() {
@@ -94,7 +92,7 @@ export default {
               return;
             }
             item.answer.forEach((sub) => {
-              if (!sub.name) {
+              if (!sub.name.trim()) {
                 flag = false;
                 return;
               }

+ 12 - 50
backstage/src/pages/content/interaction/index.vue

@@ -4,8 +4,7 @@
       <div slot="con" v-if="activeSub['新增']">
         <el-button
           v-if="
-            $route.params.type == 'questionGroup' ||
-              $route.params.type == 'sensitive'
+            $route.params.type == 'questionGroup'
           "
           @click="addData()"
           type="primary"
@@ -21,44 +20,17 @@
         title="互动模块"
       />
       <div class="tablebody">
-        <status
-          :status="status"
-          v-if="$route.params.type == 'questionGroup'"
-          @select="selectStatus"
-        ></status>
         <search>
           <div slot="content" class="searchslot">
-            <template v-if="$route.params.type != 'sensitive'">
-              <span>提交时间:</span>
-              <el-date-picker
-                v-model="search.date"
-                type="daterange"
-                value-format="yyyy-MM-dd"
-                range-separator="-"
-                start-placeholder="开始日期"
-                end-placeholder="结束日期"
-              >
-              </el-date-picker>
+            <template>
               <span>{{keyObj[$route.params.type]}}:</span>
               <el-input
                 class="elInput paddingmore"
                 :maxlength="25"
                 show-word-limit
                 v-model="search.inputKey"
-                placeholder="请输入关键字"
                 @keydown.enter.native="getList"
-              ></el-input>
-            </template>
-
-            <template v-else>
-              <span>{{keyObj[$route.params.type]}}:</span>
-              <el-input
-                class="elInput paddingmore"
-                :maxlength="25"
-                show-word-limit
-                v-model="search.inputKey"
-                @keydown.enter.native="getList"
-                placeholder="请输入敏感词"
+                placeholder="请输入关键字"
               ></el-input>
             </template>
             <el-button @click="getList" type="primary">查询</el-button>
@@ -67,7 +39,8 @@
                 search = {
                   inputKey: '',
                   date: '',
-                }
+                },
+                getList()
               "
               >重置</el-button
             >
@@ -91,11 +64,9 @@
             "
             @del="del"
             @submit="submit"
+            @refresh="getList"
             :tableData="list"
           >
-            <template slot-scope="{data}" slot="record">
-              <el-button @click="applyDetail(data,'questionGroup')" type="text">审核详情</el-button>
-            </template>
 
           </vtable>
         </div>
@@ -103,7 +74,6 @@
     </div>
 
     <vdialog :show="showApplyDetail" @close="showApplyDetail=false" :tableData="alDetail"></vdialog>
-    <sensitivedialog :show="showSensitiveDetail" @close="getList(),showSensitiveDetail=false" :form="sensitiveWord"/>
 
 
   </div>
@@ -115,17 +85,11 @@ import {raw,menu,menuStr} from "./data";
 import { getList } from "@/configue/api";
 
 import { mapGetters } from "vuex";
-import sensitivedialog from "./componets/sensitive.vue";
 
 export default {
-  components:{sensitivedialog},
   data() {
     return {
       showApplyDetail:false,
-      showSensitiveDetail:false,
-      sensitiveWord:{
-        name:''
-      },
       alDetail:{},
       search: {
         inputKey: "",
@@ -143,7 +107,7 @@ export default {
         'comment':'留言内容',
         'barrage':'弹幕内容',
         'questionGroup':'题组标题',
-        'sensitive':'敏感词',
+        'donate':'捐赠信息',
       }
     };
   },
@@ -153,17 +117,16 @@ export default {
       if (this.$route.params.type == 'questionGroup') {
         this.goto({ id: 'none',status: 0 })
       }
-      else{
-        this.showSensitiveDetail = true
-        this.sensitiveWord= {
-            name:''
-          }
-      }
     },
     selectStatus(item) {
       this.status = item.id;
     },
     handleMenu(data) {
+      this.search={
+        inputKey: "",
+        date: "",
+        state: "",
+      }
       this.$router.push({
         params: { ...this.$route.params, type: data },
       });
@@ -216,7 +179,6 @@ export default {
     }
   },
   mounted() {
-    this.getList();
   },
 };
 </script>

+ 34 - 0
backstage/src/pages/content/sand/componets/mourn.vue

@@ -0,0 +1,34 @@
+<template>
+  <div class="disable">
+    <el-form-item label="单位名称:">
+      <el-input v-model="form.unit" :maxlength="INPUTLENGTH" show-word-limit></el-input>
+    </el-form-item>
+
+    <el-form-item label="真实姓名:">
+      <el-input v-model="form.realName" :maxlength="INPUTLENGTH" show-word-limit></el-input>
+    </el-form-item>
+
+    <el-form-item label="致敬烈士姓名:">
+      <el-input v-model="form.martyrId" :maxlength="INPUTLENGTH" show-word-limit></el-input>
+    </el-form-item>
+
+    <el-form-item label="缅怀内容:" >
+      <el-input v-model="form.content"
+          type="textarea"
+           :maxlength="INPUTLENGTH*4" show-word-limit
+          :autosize="{ minRows: 2, maxRows: 4 }"></el-input>
+    </el-form-item>
+  </div>
+</template>
+
+<script>
+
+export default {
+  props: ["data",'rule'],
+  data() {
+    return {
+      form: this.data
+    };
+  },
+};
+</script>

+ 108 - 0
backstage/src/pages/content/sand/componets/sand.vue

@@ -0,0 +1,108 @@
+<template>
+  <div class="formcon">
+    <div class="formtop">
+      <div class="left">
+        <el-form-item label="中心名称:" prop="level">
+          <span style="color:#999">{{ form.name }}</span>
+        </el-form-item>
+
+        <el-form-item label="介绍:" prop="description">
+          <el-input
+            v-model="form.description"
+            type="textarea"
+            :autosize="{ minRows: 2, maxRows: 4 }"
+            placeholder="请输入内容"
+            :maxlength="INPUTLENGTH * 25"
+            show-word-limit
+          ></el-input>
+        </el-form-item>
+
+        <el-form-item label="照片:" prop="thumb">
+          <el-input v-model="form.thumb" class="fadeDom"></el-input>
+          <uploadThumb
+            :url="thumbUrl"
+            @update="
+              (data) => {
+                form.thumb = data;
+              }
+            "
+            :thumb="form.thumb"
+          />
+        </el-form-item>
+
+        <div v-for="(item, i) in form.urls" :key="i">
+          <el-form-item label="链接名称:" prop="url">
+            <el-input
+              v-model="item.urlName"
+              placeholder="请输入链接名称"
+              :maxlength="INPUTLENGTH/2"
+              show-word-limit
+            ></el-input>
+          </el-form-item>
+
+          <el-form-item label="跳转链接:" prop="urlName">
+            <el-input
+              placeholder="请输入跳转链接"
+              v-model="item.url"
+              :maxlength="INPUTLENGTH*5"
+              show-word-limit
+            >
+              <template slot="prepend">https://</template>
+            </el-input>
+          </el-form-item>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import uploadThumb from "@/components/uploadThumb";
+
+export default {
+  props: ["data", "rule"],
+  components: { uploadThumb },
+  data() {
+    let { urls } = this.data;
+    let tmp = [
+      {
+        url: "",
+        urlName: "",
+      },
+    ];
+
+    if (urls) {
+      tmp = JSON.parse(urls);
+      tmp.forEach((item) => {
+        this.data.url = item.url;
+        this.data.urlName = item.url;
+      });
+    }
+
+    this.data.urls = tmp;
+
+    return {
+      form: this.data,
+      radio: "选中且禁用",
+      thumbUrl: this.$serverName + "cms/sand/upload/img",
+    };
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.formcon {
+  width: 100%;
+  .formtop {
+    width: 100%;
+    display: flex;
+    justify-content: flex-start;
+    > div {
+      width: 40%;
+      &:first-of-type {
+        margin-right: 5%;
+      }
+    }
+  }
+}
+</style>

+ 63 - 0
backstage/src/pages/content/sand/componets/status/index.vue

@@ -0,0 +1,63 @@
+<template>
+  <ul>
+    <li @click="onClick(item)" :class="{active:item.id==status}" v-for="(item,i) in statusArr" :key="i">
+      {{item.name}}
+    </li>
+  </ul>
+</template>
+
+<script>
+  
+
+export default {
+  props:['status'],
+  data(){
+    return {
+      statusArr:[
+        {
+          id: "all",
+          name: "全部",
+        },
+        {
+          id: 4,
+          name: "院士",
+        },
+        {
+          id: 1,
+          name: "一级",
+        },
+        {
+          id: 2,
+          name: "二级",
+        },
+        {
+          id: 3,
+          name: "三级",
+        },
+      ]
+    }
+  },
+  methods:{
+    onClick(item){
+      this.$emit('select',item)
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+ul{
+  display: flex;
+  margin-top: 10px;
+  >li{
+    margin-right: 30px;
+    color: #707070;
+    cursor: pointer;
+  }
+  .active{
+    color: #143E3A;
+    padding-bottom: 10px;
+    border-bottom: 2px solid #143E3A;
+  }
+}
+</style>

+ 52 - 0
backstage/src/pages/content/sand/data.js

@@ -0,0 +1,52 @@
+let raw = {
+  sand: [
+    {
+      prop: "idx",
+      label: "编号",
+    },
+    {
+      prop: "name",
+      label: "中心名称",
+    },
+    {
+      prop: "thumb",
+      label: "中心照片",
+      default: true,
+    },
+    {
+      prop: "description",
+      label: "介绍",
+    },
+  ],
+};
+
+let menu = [
+  {
+    id: "sand",
+    name: "沙盘信息",
+  },
+];
+
+let formKey = {
+  sand: {
+    description: "",
+    thumb: "",
+    urls: "",
+  },
+};
+
+let rules = {
+  sand: {
+    name: [{ required: true, message: "请输入中心姓名", trigger: "blur" }],
+    description: [
+      { required: true, message: "请输入中心介绍", trigger: "blur" },
+    ],
+    thumb: [{ required: true, message: "请上传中心图片", trigger: "change" }],
+  },
+};
+
+let menuStr = {
+  sand: "沙盘",
+};
+
+export { raw, formKey, menu, rules, menuStr };

+ 110 - 0
backstage/src/pages/content/sand/edit.vue

@@ -0,0 +1,110 @@
+<template>
+  <div v-if="form">
+    <main-top></main-top>
+    <editcon
+      :key="type"
+      ref="child"
+      :type="type"
+      :rule="rule"
+      :form="form"
+      @cancel="backList"
+      @save="save"
+      @submit="submit({ id }, type)"
+      @determine="determine"
+    >
+      <template slot-scope="{ form }" slot="content">
+        <component
+          :data="form"
+          :is="cp"
+        />
+      </template>
+    </editcon>
+
+    <editdialog
+      :type="type"
+      :show="showAudit"
+      @close="showAudit = false"
+      :id="id"
+    />
+  </div>
+</template>
+
+<script>
+import { mapGetters } from "vuex";
+
+import vsand from "./componets/sand";
+
+import { formKey, rules } from "./data";
+import { save, getDetail } from "@/configue/api";
+
+export default {
+  components: {
+    vsand,
+  },
+  data() {
+    let { type, id } = this.$route.params;
+
+    return {
+      type,
+      id: String(id),
+      form: "",
+      showAudit: false,
+    };
+  },
+  computed: {
+    ...mapGetters({
+      activeMenu: "activeMenu",
+    }),
+    cp() {
+      return "v" + this.type;
+    },
+    rule() {
+      return rules[this.type];
+    },
+  },
+  mounted() {
+    this.getDetail();
+  },
+  methods: {
+    save(submit = "", cb = null) {
+      this.validate(() => {
+        this.form.urls = this.form.urls.map(item=>{
+          let tt = {
+            url: item.url.trim(),
+            urlName: item.urlName.trim()
+          }
+          return tt
+        })
+
+        let params = {
+          id: this.id == "none" ? null : this.id,
+          ...this.form,
+        };
+        save(this.type, params, () => {
+          if (submit) {
+            cb && cb();
+          } else {
+            this.$alert("编辑成功", "提示", {
+              confirmButtonText: "确定",
+              callback: () => {
+                this.backList();
+              },
+            });
+          }
+        });
+      });
+    },
+
+    async getDetail() {
+      if (this.id == "none") {
+        this.form = this.cloneObject(formKey[this.$route.params.type]);
+      } else {
+        await getDetail(this.type, { id: this.id }, (res) => {
+          this.form = { ...this.form, ...res.data };
+          this.form["display"] = Boolean(this.form["display"]);
+        });
+      }
+    },
+  },
+};
+</script>

+ 123 - 0
backstage/src/pages/content/sand/index.vue

@@ -0,0 +1,123 @@
+<template>
+  <div>
+    <div class="tablecon noSubmune" >
+      <div class="tablebody">
+        <search>
+          <div slot="content" class="searchslot">
+            <span>中心名称:</span>
+            <el-input class="elInput paddingmore" :maxlength="25"
+              @keydown.enter.native="getList"
+                show-word-limit v-model="search.inputKey" placeholder="请输入关键字"></el-input>
+            <el-button @click="getList" type="primary">查询</el-button>
+            <el-button @click="search.inputKey='',getList()" >重置</el-button>
+
+          </div>
+        </search>
+        <div class="table">
+          <vtable 
+          :update="subMenu"
+          :data="data" 
+          :page="page" 
+          :type="subMenu"
+          @pagechange="data=>{page.pageNum = data}"
+          @pagesizechange="data=>{page.size = data}"
+          @del="del"
+          @submit="submit"
+          :tableData="list">
+            <template slot-scope="{data}" slot="record">
+              <el-button @click="applyDetail(data,'martyr')" type="text">审核详情</el-button>
+            </template>
+          </vtable>
+        </div>
+      </div>
+    </div>
+
+    <vdialog :show="showApplyDetail" @close="showApplyDetail=false" :tableData="alDetail"></vdialog>
+
+  </div>
+</template>
+
+<script>
+
+import {raw,menu} from "./data";
+import {getList} from "@/configue/api";
+
+import { mapGetters } from "vuex";
+
+export default {
+  data(){
+    return {
+      showApplyDetail:false,
+      alDetail:{},
+      search:{
+        inputKey:'',
+        date: '',
+        state:'',
+      },
+      menu,
+      list:{},
+      page:{
+        size:25,
+        pageNum:1
+      }
+    }
+  },
+  components:{
+  },
+  methods:{
+  
+    handleMenu(data){
+      this.$router.push({
+        params: {...this.$route.params, type:data} 
+      })
+    },
+    
+    getList(){
+      let {inputKey} = this.search
+      getList(this.subMenu,{
+        pageNum: this.page.pageNum,
+        pageSize: this.page.size,
+        searchKey: inputKey,
+      },data=>{
+          this.list = data.data
+      })
+    }
+    
+  },
+  computed: {
+    ...mapGetters({
+      activeMenu:'activeMenu',
+      activeSub:"activeSub"
+    }),
+    subMenu(){
+      return this.$route.params.type
+    },
+    data(){
+      return raw[this.$route.params.type]
+    }
+  },
+  watch: {
+    subMenu:{
+      deep:true,
+      immediate:true,
+      handler:function () {
+        this.getAuth(this.activeMenu,'沙盘')
+        this.getList();
+      }
+    },
+    activeMenu:{
+      deep:true,
+      immediate:true,
+      handler:function (newVal) {
+        this.getAuth(newVal,'沙盘')
+      }
+    }
+  },
+  mounted(){
+  }
+}
+</script>
+<style lang="less" scoped>
+
+</style>
+

+ 3 - 4
backstage/src/pages/content/scene/index.vue

@@ -21,8 +21,8 @@
               @click="
                 search = {
                   inputKey: '',
-                  date: '',
-                }
+                },
+                getList()
               "
               >重置</el-button
             >
@@ -49,7 +49,7 @@
             <el-table-column slot="operate" label="操作" width="190">
               <template slot-scope="scope">
                 <span class="o-span" v-if="activeSub['编辑']" @click="openLink(scope.row)">编辑</span>
-                <span class="o-span" v-if="activeSub['删除']" @click="delScene(scope.row)">删除</span>
+                <span v-else>-</span>
               </template>
             </el-table-column>
           </vtable>
@@ -153,7 +153,6 @@ export default {
     }
   },
   mounted() {
-    this.getList();
   },
 };
 </script>

+ 0 - 130
backstage/src/pages/content/sweep/componets/martyr.vue

@@ -1,130 +0,0 @@
-<template>
-  <div class="formcon">
-    <div class="formtop">
-      <div class="left">
-        <el-form-item label="烈士姓名:" prop="realName">
-          <el-input v-model="form.realName" :maxlength="INPUTLENGTH" show-word-limit></el-input>
-        </el-form-item>
-
-        <el-form-item label="籍贯:" prop="nativePlace">
-          <el-input v-model="form.nativePlace" :maxlength="INPUTLENGTH" show-word-limit></el-input>
-        </el-form-item>
-
-         <el-form-item label="出生日期:" prop="birthday">
-          <el-input v-model="form.birthday" class="fadeDom"></el-input>
-          <el-date-picker
-            v-model="form.birthday"
-            type="date"
-            value-format="yyyy-MM-dd"
-            placeholder="选择日期">
-          </el-date-picker>
-        </el-form-item>
-
-
-        <el-form-item label="牺牲地点:" prop="diePlace">
-          <el-input v-model="form.diePlace" :maxlength="INPUTLENGTH" show-word-limit></el-input>
-        </el-form-item>
-
-        <el-form-item label="所获荣誉:" prop="honor">
-          <el-input v-model="form.honor" :maxlength="INPUTLENGTH" show-word-limit></el-input>
-        </el-form-item>
-
-        <el-form-item label="民族:" prop="nation">
-          <el-input v-model="form.nation" :maxlength="INPUTLENGTH" show-word-limit></el-input>
-        </el-form-item>
-      </div>
-      <div class="right">
-        <el-form-item label="性别:" prop="sex">
-          <el-radio-group v-model="form.sex">
-            <el-radio :label="0">男</el-radio>
-            <el-radio :label="1">女</el-radio>
-          </el-radio-group>
-        </el-form-item>
-
-        <el-form-item label="政治面貌:" prop="politicsStatus">
-            <el-select v-model="form.politicsStatus" placeholder="请选择">
-              <el-option
-                v-for="(item,i) in g_political"
-                :key="i"
-                :label="item.val"
-                :value="item.val">
-              </el-option>
-            </el-select>
-        </el-form-item>
-
-        <el-form-item label="牺牲日期:" prop="dieDay">
-          <el-input v-model="form.dieDay" class="fadeDom"></el-input>
-          <el-date-picker
-            v-model="form.dieDay"
-            value-format="yyyy-MM-dd"
-            type="date"
-            placeholder="选择日期">
-          </el-date-picker>
-        </el-form-item>
-
-        <el-form-item label="照片:">
-          <uploadThumb
-            :url="thumbUrl"
-            @update="
-              (data) => {
-                form.thumb = data;
-              }
-            "
-            :thumb="form.thumb"
-          />
-        </el-form-item>
-
-        
-      </div>
-    </div>
-
-    <div>
-      <el-form-item label="英烈事迹:" prop="description">
-        <el-input
-          v-model="form.description"
-          type="textarea"
-          :autosize="{ minRows: 2, maxRows: 4 }"
-          placeholder="请输入内容"
-          :maxlength="INPUTLENGTH*4" 
-          show-word-limit
-        ></el-input>
-      </el-form-item>
-
-    </div>
-  </div>
-</template>
-
-<script>
-import uploadThumb from "@/components/uploadThumb";
-
-export default {
-  props: ["data", "rule"],
-  components: { uploadThumb },
-  data() {
-    return {
-      form: this.data,
-      radio: "选中且禁用",
-      thumbUrl: this.$serverName + "cms/goods/upload/thumb",
-      fileUrl: this.$serverName + "cms/goods/upload/model",
-    };
-  },
-};
-</script>
-
-<style lang="less" scoped>
-.formcon {
-  width: 100%;
-  .formtop {
-    width: 100%;
-    display: flex;
-    justify-content: flex-start;
-    >div{
-      width: 40%;
-      &:first-of-type{
-        margin-right: 5%;
-      }
-    }
-    
-  }
-}
-</style>

+ 0 - 132
backstage/src/pages/content/sweep/data.js

@@ -1,132 +0,0 @@
-let raw = {
-  martyr: [
-    {
-      prop: "idx",
-      label: "编号",
-    },
-    {
-      prop: "realName",
-      label: "烈士名字",
-    },
-    {
-      prop: "thumb",
-      label: "照片",
-      default: true
-    },
-    {
-      prop: "visit",
-      label: "缅怀次数",
-    },
-    {
-      prop: "createTime",
-      label: "提交时间",
-    },
-    {
-      prop: "status",
-      label: "状态",
-    },
-    {
-      prop: "record",
-      label: "审核记录",
-    },
-    {
-      prop: "display",
-      label: "是否显示"
-    },
-  ],
-  mourn: [
-    {
-      prop: "idx",
-      label: "编号",
-    },
-    {
-      prop: "unit",
-      label: "单位名称",
-    },
-    {
-      prop: "realName",
-      label: "真实姓名",
-    },
-    {
-      prop: "martyRealName",
-      label: "致敬烈士姓名",
-    },
-    {
-      prop: "content",
-      label: "缅怀内容",
-    },
-    {
-      prop: "createTime",
-      label: "提交时间",
-    },
-    {
-      prop: "display",
-      label: "是否显示"
-    },
-  ]
-  
-}
-
-let menu = [
-  {
-    id: 'martyr',
-    name: "英烈信息",
-  },
-  {
-    id: 'mourn',
-    name: "缅怀致敬",
-  }
-];
-
-let formKey = {
-  martyr:{ 
-    birthday: "",
-    description: "",
-    dieDay: "",
-    diePlace: "",
-    display: 0,
-    honor: "",
-    nation: "",
-    nativePlace: "",
-    politicsStatus: "",
-    realName: "",
-    sex: 0,
-    thumb: ""
-  },
-  mourn:{ 
-    realName:'',
-    martyrId:'',
-    unit:'',
-    content:''
-  }
-}
-
-let rules = {
-  martyr:{
-    birthday: [{ required: true, message: "请输入出生日期", trigger: "blur" }],
-    description: [{ required: true, message: "请输入英烈事迹", trigger: "blur" }],
-    dieDay: [{ required: true, message: "请输入牺牲日期", trigger: "blur" }],
-    diePlace: [{ required: true, message: "请输入牺牲地点", trigger: "blur" }],
-    honor: [{ required: true, message: "请输入所获荣誉", trigger: "blur" }],
-    nation: [{ required: true, message: "请输入民族", trigger: "blur" }],
-    nativePlace: [{ required: true, message: "请输入籍贯", trigger: "blur" }],
-    politicsStatus: [{ required: true, message: "请输入政治面貌", trigger: "blur" }],
-    realName: [{ required: true, message: "请输入烈士姓名", trigger: "blur" }],
-  },
-  mourn:{
-    
-  }
-}
-
-let menuStr = {
-  'martyr':'英烈',
-  'mourn':'缅怀',
-}
-
-export {
-  raw,
-  formKey,
-  menu,
-  rules,
-  menuStr
-}

+ 15 - 11
backstage/src/pages/layout/aside.vue

@@ -4,7 +4,7 @@
   <div class="aside-list">
     <div class="aside-item" v-for="(item,i) in menu" :key="i">
       <div :class="{active:belong==item.id}"><i class="iconfont" :class="item.icon"></i>{{item.name}}</div>
-      <div @click="goto(sub)" v-for="(sub,idx) in item.routes" :key="idx" :class="{activeFont:activeIdx === sub.key}">{{sub.name=='学习园地管理'?'交流学习管理':sub.name}}</div>
+      <div @click="goto(sub)" v-for="(sub,idx) in item.routes" :key="idx" :class="{activeFont:activeIdx === sub.key}">{{sub.name}}</div>
     </div>
   </div>
 </div>
@@ -60,7 +60,7 @@ export default {
     async getResource(){
       let result = await this.$http({
         method: 'GET',
-        url: '/sys/resource/getTreePermissions'
+        url: 'sys/resource/getTreePermissions'
       })
 
       this.tmpRoute = routes.filter(item => {
@@ -73,24 +73,28 @@ export default {
           }
         })
 
-          if (item.type == "system") {
-            if (window.localStorage.getItem("role") == 'sys_admin') {
-                tmp = item
-            }
-            else{
-              tmp = ''
-            }
-          }
+        if (item.type == "system") {
+          // if (window.localStorage.getItem("role") == 'sys_admin') {
+          //     tmp = item
+          // }
+          // else{
+          //   tmp = ''
+          // }
+          tmp = item
+
+        }
         return tmp ? Object.assign(item,tmp) : tmp
       });
 
-      console.log(this.tmpRoute);
+      // console.log(this.tmpRoute);
 
       let temp = this.tmpRoute.filter(item=>{
           return item.key == this.activeIdx
         })
       this.$store.commit("SetActiveMenu", temp[0]);
 
+      // console.log(temp[0]);
+
       this.menu = main.filter(item=>{
         let route = []
         this.tmpRoute.forEach((sub)=>{

+ 127 - 111
backstage/src/pages/layout/head.vue

@@ -1,106 +1,109 @@
 <!--  -->
 <template>
-<div class='header card'>
-  <div class="header-title">
-    <img src="@/assets/img/logo.png" alt="">
-    <span>解放军总医院数字史馆</span>
-  </div>
-  <div class="header-user">
-    <div class="avatars" @click="handleAvatar">
-      <img v-if="userInfo.img" :src="userInfo.img" alt="">
-      <span>{{userInfo.nickName}}</span>
+  <div class="header card">
+    <div class="header-title">
+      <img src="@/assets/img/logo.png" alt="" />
+      <span>解放军总医院数字史馆</span>
+    </div>
+    <div class="header-user">
+      <div class="avatars">
+        <span>{{ userInfo.nickName }}</span>
+        <ul>
+          <li @click="handleAvatar">用户信息</li>
+          <li @click="logoutcomfirm">退出登录</li>
+        </ul>
+      </div>
+      <!-- <div class="logout"><img src="@/assets/img/logout.png" alt="">退出</div> -->
     </div>
-    <div @click="logoutcomfirm" class="logout"><img src="@/assets/img/logout.png" alt="">退出</div>
-  </div>
 
-  <usereditdialog :key="ran" @logout="logout(true)" :form="userInfo" :show="isShowEdit" @close="isShowEdit=false"/>
-  
-</div>
+    <usereditdialog
+      :key="ran"
+      @logout="logout(true)"
+      :form="userInfo"
+      :show="isShowEdit"
+      @close="isShowEdit = false"
+    />
+  </div>
 </template>
 
 <script>
-import usereditdialog from '@/components/editcomponent/usereditdialog'
-import {getSysDetail} from "@/configue/api";
+import usereditdialog from "@/components/editcomponent/usereditdialog";
+import { getSysDetail } from "@/configue/api";
 
 export default {
-  components: {usereditdialog},
-  data () {
+  components: { usereditdialog },
+  data() {
     return {
-      isShowEdit:false,
-      ran:'',
-      userId:'',
-      userInfo:{}
-    }
+      isShowEdit: false,
+      ran: "",
+      userId: "",
+      userInfo: {},
+    };
   },
   watch: {
-    isShowEdit(){
-      this.getDetail()
-    }
+    isShowEdit() {
+      this.getDetail();
+    },
   },
   methods: {
-    handleAvatar(){
+    handleAvatar() {
+      let role = window.localStorage.getItem("role");
 
-      let role =  window.localStorage.getItem("role")
-    
       console.log(this.juese[role]);
-      
 
       if (!this.juese[role]) {
-        return
+        return;
       }
-      this.isShowEdit=true
-      this.ran=Math.random()
+      this.isShowEdit = true;
+      this.ran = Math.random();
     },
-    logoutcomfirm(){
-      this.confirm('确定退出登录?',()=>{
-        this.logout()
-      })
+    logoutcomfirm() {
+      this.confirm("确定退出登录?", () => {
+        this.logout();
+      });
     },
-    getDetail(){
-      getSysDetail('user',{id:this.userId},res=>{
-          this.userInfo = {...res.data}
-      })
+    getDetail() {
+      getSysDetail("user", { id: this.userId }, (res) => {
+        this.userInfo = { ...res.data };
+      });
     },
-    logout (type=null) {
+    logout(type = null) {
       this.$http({
-        method: 'get',
-        url: 'admin/logout'
-      }).then(res => {
+        method: "get",
+        url: "admin/logout",
+      }).then((res) => {
         if (res.code === 0) {
-          window.localStorage.setItem('token', '')
-          window.localStorage.setItem('role', '')
-          this.$alert(type?'修改成功,请重新登录':'退出成功', '提示', {
-            confirmButtonText: '确定',
+          window.localStorage.setItem("token", "");
+          window.localStorage.setItem("role", "");
+          this.$alert(type ? "修改成功,请重新登录" : "退出成功", "提示", {
+            confirmButtonText: "确定",
             callback: () => {
-              window.localStorage.setItem('userInfo', '')
-              this.$router.push('/login')
-            }
-          })
+              window.localStorage.setItem("userInfo", "");
+              this.$router.push("/login");
+            },
+          });
         }
-      })
-    }
+      });
+    },
   },
-  created () {
-
+  created() {},
+  mounted() {
+    this.userId = window.localStorage.getItem("userId") || "";
+    this.getDetail();
   },
-  mounted () {
-    this.userId = window.localStorage.getItem('userId')|| ''
-    this.getDetail()
-  }
-}
+};
 </script>
 
-<style scoped>
+<style lang="less" scoped>
 .header {
-  height: 4.25rem;
   width: 100%;
   display: flex;
   justify-content: space-between;
   align-items: center;
-  line-height: 4.25rem;
-  padding: 0 1.875rem;
+  height: 68px;
+  padding: 0 30px;
   box-sizing: border-box;
-  background-color: #143E3A!important;
+  background-color: #143e3a !important;
 }
 
 .header-title {
@@ -108,54 +111,67 @@ export default {
   font-size: 1.25rem;
   text-align: center;
   vertical-align: middle;
-}
-.header-title img{
-  vertical-align: middle;
-  max-width: 106px;
-  margin-right: 10px;
-}
-.header-title span{
-  vertical-align: middle;
-  display: inline-block;
-  font-size: 24px;
-  letter-spacing: 2px;
-  font-weight: bold;
-}
-.header-user {
-  display: flex;
-  align-items: center;
-  cursor: pointer;
-}
-
-.header-user .logout img {
-  width: 20px;
-  height: 20px;
-  margin-right: 10px;
-}
-
-.header-user .logout {
-  display: flex;
-  align-items: center;
-  cursor: pointer;
-  color: #fff;
+  img {
+    vertical-align: middle;
+    max-width: 106px;
+    margin-right: 10px;
+  }
+  span {
+    vertical-align: middle;
+    display: inline-block;
+    font-size: 24px;
+    letter-spacing: 2px;
+    font-weight: bold;
+  }
 }
 
-.header-user .avatars{
+.header-user {
   display: flex;
   align-items: center;
   cursor: pointer;
-  height: 3rem;
-  margin-right: 10px;
-  color: #fff;
-}
-
-.header-user .avatars span{
-  margin-left: 10px;
-}
-
-.header-user .avatars img{
-  width:3rem;
-  height:3rem;
-  border-radius:50%;
+  line-height: 100%;
+  height: 100%;
+  .avatars {
+    min-width: 100px;
+    cursor: pointer;
+    color: #fff;
+    position: relative;
+    line-height: 100%;
+    height: 100%;
+    text-align: center;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    &:hover{
+      >ul{
+        display: block;
+      }
+    }
+    >span{
+      display: inline-block;
+    }
+    >ul{
+      position: absolute;
+      bottom: -70px;
+      z-index: 9999;
+      left: 50%;
+      transform: translateX(-50%);
+      width: 100%;
+      text-align: center;
+      background: #fff;
+      color: #010101;
+      border: 1px solid #010101;
+      display: none;
+      li{
+        display: inline-block;
+        height: 40px;
+        width: 100%;
+        line-height: 40px;
+        &:hover{
+          background: #f0f0f0;
+        }
+      }
+    }
+  }
 }
 </style>

+ 5 - 3
backstage/src/pages/system/role/componets/manage.vue

@@ -24,18 +24,20 @@ export default {
   data() {
     let tmp = [];
     this.data.permission.forEach((item) => {
+
       item.children &&
         item.children.forEach((sub) => {
           if (sub.children) {
             sub.children.forEach((son) => {
-              if (sub.name=='英烈信息'&&son.name=='新增') {
-                son.name='登记'
-              }
+             
               if (son.authority) {
                 tmp.push(son.id);
               }
             });
           } else {
+            if (item.name=='专家风采管理'&&sub.name=='新增') {
+              sub.name='登记'
+            }
             if (sub.authority) {
               tmp.push(sub.id);
             }

+ 2 - 1
backstage/src/pages/system/role/edit.vue

@@ -7,7 +7,7 @@
       :rule="rule"
       :form="form"
       @cancel="backList"
-      @determine="determine"
+      @save="determine"
     >
       <template slot-scope="{ form }" slot="content">
         <component :data="form" :is="cp" />
@@ -76,6 +76,7 @@ export default {
       });
     },
     determine() {
+      console.log(1111);
       this.validate(() => {
         let params = {
           "resources": [],

+ 1 - 1
backstage/src/pages/system/role/edit/dialog.vue

@@ -18,7 +18,7 @@
           type="textarea"
           :autosize="{ minRows: 2, maxRows: 4 }"
           placeholder="请输入职能描述"
-          :maxlength="INPUTLENGTH*2" show-word-limit
+          :maxlength="INPUTLENGTH*10" show-word-limit
           v-model="form.roleDesc"
         >
         </el-input>

+ 1 - 1
backstage/src/pages/system/user/edit.vue

@@ -8,7 +8,7 @@
       :rule="rule"
       :form="form"
       @cancel="backList"
-      @determine="determine"
+      @save="determine"
     >
       <template slot-scope="{ form }" slot="content">
         <component :data="form" :is="cp" :roleList="roleList" />

+ 4 - 4
backstage/src/pages/system/user/index.vue

@@ -11,7 +11,7 @@
       <div class="tablebody">
         <search>
           <div slot="content" class="searchslot">
-            <span>提交时间:</span>
+            <span>注册时间:</span>
             <el-date-picker
               v-model="search.date"
               type="daterange"
@@ -21,7 +21,7 @@
               end-placeholder="结束日期"
             >
             </el-date-picker>
-            <span>标题:</span>
+            <span>真实姓名:</span>
             <el-input
               class="elInput paddingmore"
               :maxlength="25"
@@ -35,8 +35,8 @@
             <el-select v-model="search.roleId" placeholder="请选择">
               <el-option label="全部"  value="" key=""></el-option>
               <el-option
-                v-for="item in rolelist"
-                :key="item.roleName"
+                v-for="(item,i) in rolelist"
+                :key="i"
                 :label="item.roleName"
                 :value="item.id">
               </el-option>

+ 1 - 1
backstage/src/pages/system/worklog/index.vue

@@ -17,7 +17,7 @@
               end-placeholder="结束日期"
             >
             </el-date-picker>
-            <span>操作人员:</span>
+            <span>操作:</span>
             <el-input
               class="elInput paddingmore"
               :maxlength="25"

文件差异内容过多而无法显示
+ 27056 - 1
backstage/theme/index.css


+ 11 - 0
web/package-lock.json

@@ -10,6 +10,7 @@
       "dependencies": {
         "any-touch": "^1.0.15",
         "axios": "^0.19.2",
+        "canvaskeyframes": "^0.4.2",
         "core-js": "^3.6.5",
         "js-base64": "^3.6.1",
         "swiper": "^5.3.8",
@@ -3540,6 +3541,11 @@
       "integrity": "sha1-WkVBr1MX3CH5H1sk1FMDCjX5GcA=",
       "dev": true
     },
+    "node_modules/canvaskeyframes": {
+      "version": "0.4.2",
+      "resolved": "https://registry.nlark.com/canvaskeyframes/download/canvaskeyframes-0.4.2.tgz",
+      "integrity": "sha1-gSBrKeBYwUUKC29wHeI1ZCGKcLU="
+    },
     "node_modules/case-sensitive-paths-webpack-plugin": {
       "version": "2.3.0",
       "resolved": "https://registry.npm.taobao.org/case-sensitive-paths-webpack-plugin/download/case-sensitive-paths-webpack-plugin-2.3.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcase-sensitive-paths-webpack-plugin%2Fdownload%2Fcase-sensitive-paths-webpack-plugin-2.3.0.tgz",
@@ -17151,6 +17157,11 @@
       "integrity": "sha1-WkVBr1MX3CH5H1sk1FMDCjX5GcA=",
       "dev": true
     },
+    "canvaskeyframes": {
+      "version": "0.4.2",
+      "resolved": "https://registry.nlark.com/canvaskeyframes/download/canvaskeyframes-0.4.2.tgz",
+      "integrity": "sha1-gSBrKeBYwUUKC29wHeI1ZCGKcLU="
+    },
     "case-sensitive-paths-webpack-plugin": {
       "version": "2.3.0",
       "resolved": "https://registry.npm.taobao.org/case-sensitive-paths-webpack-plugin/download/case-sensitive-paths-webpack-plugin-2.3.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcase-sensitive-paths-webpack-plugin%2Fdownload%2Fcase-sensitive-paths-webpack-plugin-2.3.0.tgz",

+ 1 - 0
web/package.json

@@ -10,6 +10,7 @@
   "dependencies": {
     "any-touch": "^1.0.15",
     "axios": "^0.19.2",
+    "canvaskeyframes": "^0.4.2",
     "core-js": "^3.6.5",
     "js-base64": "^3.6.1",
     "swiper": "^5.3.8",

二进制
web/public/model/Build/WebGl-3DMapPage.data


文件差异内容过多而无法显示
+ 7 - 0
web/public/model/Build/WebGl-3DMapPage.framework.js


文件差异内容过多而无法显示
+ 1 - 0
web/public/model/Build/WebGl-3DMapPage.loader.js


二进制
web/public/model/Build/WebGl-3DMapPage.wasm


二进制
web/public/model/TemplateData/favicon.ico


二进制
web/public/model/TemplateData/fullscreen-button.png


二进制
web/public/model/TemplateData/progress-bar-empty-dark.png


二进制
web/public/model/TemplateData/progress-bar-empty-light.png


二进制
web/public/model/TemplateData/progress-bar-full-dark.png


二进制
web/public/model/TemplateData/progress-bar-full-light.png


+ 16 - 0
web/public/model/TemplateData/style.css

@@ -0,0 +1,16 @@
+body { padding: 0; margin: 0 }
+#unity-container { position: absolute }
+#unity-container.unity-desktop { left: 50%; top: 50%; transform: translate(-50%, -50%) }
+#unity-container.unity-mobile { width: 100%; height: 100% }
+#unity-canvas { background: #231F20 }
+.unity-mobile #unity-canvas { width: 100%; height: 100% }
+#unity-loading-bar { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); display: none }
+#unity-logo { width: 154px; height: 130px; background: url('unity-logo-dark.png') no-repeat center }
+#unity-progress-bar-empty { width: 141px; height: 18px; margin-top: 10px; background: url('progress-bar-empty-dark.png') no-repeat center }
+#unity-progress-bar-full { width: 0%; height: 18px; margin-top: 10px; background: url('progress-bar-full-dark.png') no-repeat center }
+#unity-footer { position: relative }
+.unity-mobile #unity-footer { display: none }
+#unity-webgl-logo { float:left; width: 204px; height: 38px; background: url('webgl-logo.png') no-repeat center }
+#unity-build-title { float: right; margin-right: 10px; line-height: 38px; font-family: arial; font-size: 18px }
+#unity-fullscreen-button { float: right; width: 38px; height: 38px; background: url('fullscreen-button.png') no-repeat center }
+#unity-mobile-warning { position: absolute; left: 50%; top: 5%; transform: translate(-50%); background: white; padding: 10px; display: none }

二进制
web/public/model/TemplateData/unity-logo-dark.png


二进制
web/public/model/TemplateData/unity-logo-light.png


二进制
web/public/model/TemplateData/webgl-logo.png


+ 39 - 0
web/public/model/index.html

@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html lang="en-us">
+
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+  <style>
+    * {
+      padding: 0;
+      margin: 0;
+    }
+    html,
+    body {
+      width: 100%;
+      height: 100%;
+    }
+  </style>
+  <title>数字沙盘</title>
+</head>
+
+<body>
+  <canvas id="unity-canvas" style="width: 100%; height: 100%; background: #231F20"></canvas>
+  <script src="Build/WebGl-3DMapPage.loader.js"></script>
+  <script>
+    createUnityInstance(document.querySelector("#unity-canvas"), {
+      dataUrl: "Build/WebGl-3DMapPage.data",
+      frameworkUrl: "Build/WebGl-3DMapPage.framework.js",
+      codeUrl: "Build/WebGl-3DMapPage.wasm",
+      streamingAssetsUrl: "StreamingAssets",
+      companyName: "DefaultCompany",
+      productName: "New Unity Project 1",
+      productVersion: "0.1",
+      // matchWebGLToCanvasSize: false, // Uncomment this to separately control WebGL canvas render size and DOM element size.
+      // devicePixelRatio: 1, // Uncomment this to override low DPI rendering on high DPI displays.
+    });
+  </script>
+</body>
+
+</html>

+ 1 - 1
web/public/scene.html

@@ -12,6 +12,7 @@
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/css/tooltipster.bundle.min.css"/>
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/css/tooltipster-sideTip-borderless.min.css"/>
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/css/main.css?v=2.25"/>
+    <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/css/animate.min.css"/>
     <script>
         var number = window.location.href.substring(window.location.href.indexOf("=") + 1);
         if (number.indexOf("&") != -1) {
@@ -35,7 +36,6 @@
     <script src="<%= VUE_APP_STATIC_DIR %>/js/lib/player-0.0.12.min.js" class="build keep"></script>
     <script src="<%= VUE_APP_STATIC_DIR %>/js/Tween.js"></script>
     <script src="<%= VUE_APP_STATIC_DIR %>/js/manage.js"></script>
-    <script src="<%= VUE_APP_STATIC_DIR %>/js/myShow.js"></script>
     <script src="<%= VUE_APP_STATIC_DIR %>/js/Hot.js"></script>
     <script src="<%= VUE_APP_STATIC_DIR %>/js/main_2020_show.js"></script>
 

+ 3 - 3
web/public/static/css/main.css

@@ -3390,7 +3390,7 @@ a.hasHover:hover, a:active {
 .pinTop.left {
     left: 50%;
     z-index: 99;
-    display: flex;
+    display: none;
     flex-direction: column;
     align-items: center;
     transform: translateX(-50%);
@@ -7087,12 +7087,12 @@ a.hasHover.tag-link:hover {
 	width: 100%;
 	height: 100%;
     pointer-events:none; 
-	z-index: 9101; 
+	z-index: 990; 
     left:0;top:0;
 }
 #hot>div{
     position: absolute;
-    z-index: 999;
+    z-index: 990;
     color: #fff;
     -webkit-user-select: none;
     -moz-user-select: none;

+ 2 - 2
web/public/static/css/oldVer/main0.css

@@ -38,14 +38,14 @@ iframe{
 	height: 100%;
 	/* margin: 80px auto; */
 	display: none;
-	z-index: 101;
+	z-index: 9999;
 	background:  rgba(0,0,0,0.6);
 }
 .popup-content{
 	position: relative;
 	width: 100%;
 	height: 100%;
-	overflow-x: hidden;
+	overflow: hidden;
 }
 #id1{ width: 100%; height: 100%;}
 #popup.wait{

文件差异内容过多而无法显示
+ 1653 - 0
web/public/static/js/Hot copy.js


+ 75 - 60
web/public/static/js/Hot.js

@@ -1,19 +1,9 @@
  
 //合并热点和展览 
-
+g_currentHot = null
 
 window.initHot = function(model){
-    
-    
-    
-
-    
-    
-    
-    
-    
-    
-    
+      
     var objLoader = new THREE.OBJLoader()    
     var _planeGeometry = new THREE.PlaneGeometry(1,1)
     var _boxGeometry = new THREE.BoxBufferGeometry(1,1,1)
@@ -137,10 +127,9 @@ window.initHot = function(model){
     class Hot extends THREE.Object3D{
         constructor(info, source){    
             super()
-            
+             
             
             this.sid = info.sid;
-            info.styleImg = info.styleImg.map(item=>manage.dealURL(item))
             this.preDeal(info, source)// source:来源
             
             this.info = info
@@ -732,7 +721,7 @@ window.initHot = function(model){
              
             let maxCount = browser.isMobile() ? 2000 : 5000
             let c = model.panos.list.length * model.colliders.length
-            if(settings.isEdit || c < maxCount){  
+            if(window.isEdit ||  c < maxCount){  //编辑页面保险起见还是全部算完后才可浏览,就能保证保存全部的visiblePano
                 this.info.visiblePanos = common.getVisiblePano(customPositions,  model.panos.list, {
                     model: model.colliders , posAtPanos  
                 })  
@@ -755,15 +744,15 @@ window.initHot = function(model){
                         console.log(window.hotsi ?(++window.hotsi): (window.hotsi = 1))
                         clearInterval(interval)
                     }
-                }, Hot.visiEveryDurSlice ) 
+                }, Hot.visiEveryDurSlice )// visiEveryDurSlice 等在main中定义
             }
             
         }
         
             
         updateVisible(panos, visibility) { 
-            if(settings.isEdit && editTool.hotpoint.editSpot == this){
-                return true
+            if(window.isEdit && editTool.hotpoint.editSpot == this){
+                return this.visible = true
             }
             
             this.visible = visibility != void 0 ? visibility : (!this.info.visiblePanos || !!panos.find(pano=>this.info.visiblePanos.includes(pano.id)))
@@ -784,7 +773,6 @@ window.initHot = function(model){
                 if(this.plane){ 
                     center = this.plane.getWorldPosition()
                     boundPoint = [ 
-                               
                         new THREE.Vector3(-0.5, 0.5, 0),
                         new THREE.Vector3(0.5, 0.5, 0),
                         new THREE.Vector3(0.5, -0.5, 0),
@@ -860,7 +848,6 @@ window.initHot = function(model){
                         math.getDirByLonLat(maxLon, minLat),
                         math.getDirByLonLat(minLon, maxLat),
                     ] 
- 
                     cornerPoint = dirs.map(e=>{
                         return e.clone().add(pos1) 
                     })
@@ -894,7 +881,7 @@ window.initHot = function(model){
         
         inSight(){
             //return true
-            if(settings.isEdit)return true // 太容易move了
+            if(window.isEdit)return true // 太容易move了
              
             if(player.mode == 'panorama'){
                 if(!player.camera) return
@@ -960,7 +947,6 @@ window.initHot = function(model){
         }                
 
 
-
         switchPlay(state){//手动播放暂停 
             this.pausedByUser = !state
             
@@ -1096,17 +1082,6 @@ window.initHot = function(model){
                 
             var s = t.model.panos.sortByScore(i, n);
              
-                                                    
-                                     
-                                                     
-                                                                             
-                                                                  
-                                                            
-                                              
-                         
-                 
-                           
-                
             return s && 0 < s.length && s[0].pano
         }
          
@@ -1133,25 +1108,25 @@ window.initHot = function(model){
                     div.style.position = 'fixed';
                     div.style.width = div.style.height = "100%";
                     div.style.left = div.style.top = '0';
-                    div.style["z-index"] = "99999"
+                    div.style["z-index"] = "999"
                     
                     var exit = document.createElement("div");
                     exit.style["background-image"] = "url(static/images/vrOffImg.png)";
                     exit.style.position = 'absolute';
                     exit.style.width = exit.style.height = "50px";
-                    exit.style.left = '17px';   exit.style.top = "20px"
+                    exit.style.left = '28px';   exit.style.top = "86px"
                     exit.style.cursor = "pointer";
                     exit.style["background-repeat"] = "no-repeat";
-                    exit.style["background-size"] = "25%"; 
+                    exit.style["background-size"] = "30%"; 
                     exit.style["background-position"] = "center center"; 
                     exit.style["background-color"] = "rgba(0, 0, 0, 0.2)"; 
                     exit.style["border-radius"] = "50%";
                     exit.style["z-index"] = "3"
                     exit.onclick = ()=>{
                         $(div).remove()
-                        if(g_bgAudio && g_bgAudio.pauseByHot){
-                            manage.switchBgmState(true)
-                        }
+                        
+                        Hot.closePopup()
+                        
                     }  
                     
                     var myElement = document.createElement("iframe");
@@ -1165,12 +1140,8 @@ window.initHot = function(model){
                     div.appendChild(exit);
                     div.appendChild(myElement)
                     
+                    SoundManager.play('hot')
                     
-                    if(g_bgAudio && !g_bgAudio.paused){
-                        manage.switchBgmState(false); 
-                        g_bgAudio.pauseByHot = true
-                    } 
-                    if(g_tourAudio)g_tourAudio.pause()
                     
                 }
                 
@@ -1185,15 +1156,13 @@ window.initHot = function(model){
             var popup = document.getElementById("popup");
             
             if (openHot) {
-                g_currentHot = this,
+                g_currentHot = this
                 // popup.style.display = "block",
-                popup.classList.add("wait");
-                var n = document.createElement("iframe");
-                if(g_bgAudio && !g_bgAudio.paused){
-                    manage.switchBgmState(false); 
-                    g_bgAudio.pauseByHot = true
-                } 
-                if(g_tourAudio)g_tourAudio.pause()
+                // popup.classList.add("wait");
+                // var n = document.createElement("iframe");
+                 
+                // SoundManager.play('hot')
+                
                 // var src = getLink(this.info.link   )
                 // n.src = src;
                 // n.id = "id1",
@@ -1222,9 +1191,8 @@ window.initHot = function(model){
             
             var done = function() {
                 player.flyingToTag = !1;
-                openHot && popup.classList.remove("wait");
+                openHot && popup.classList.remove("wait")
                 window.player && window.player.emit('openHotspot', this.sid)
-
             }.bind(this);
         
             
@@ -1233,7 +1201,7 @@ window.initHot = function(model){
                 return;
             }
         
-            var c = /* m.tags.navigate.nearestPano && */ this.closestPanoTowardTag(player.mode, player.currentPano) || player.currentPano
+            var c = this.closestPanoTowardTag(player.mode, player.currentPano) || player.currentPano
               , h = this.mesh.getWorldPosition();
             player.flyingToTag = !0;
             
@@ -1352,8 +1320,8 @@ window.initHot = function(model){
                 }
             }
         } 
+        
         changeBoxHelperDisplay(show){
-                                        
             if(show){
                 this.visible_ = this.visible
                 this.visible = true
@@ -1378,7 +1346,7 @@ window.initHot = function(model){
         
         requestDownload(type,callback) { 
             var plane = this.plane;
-            
+             
             if(type == 'photo'){
                 if(this.photoHasRequestLoad || this.texType != 'photo')return;
                 //console.log('overlay beginDownload : ' + this.sid)
@@ -1394,7 +1362,7 @@ window.initHot = function(model){
                     
                     setTimeout(Hot.loadNext, 50) 
                     hotGroup.children.forEach(e=>{
-                        if(e.info.texSrc == this.info.texSrc){ 
+                        if(e.info.texSrc == this.info.texSrc && e.info.texType == type  ){ 
                             e.material_.color.set("#FFFFFF") 
                             e.material_.opacity = 1;
                             //console.log('overlay loaded: ' + e.sid + " - " + this.info.texSrc.split('/').pop());
@@ -1404,7 +1372,7 @@ window.initHot = function(model){
                             e.texMedia = tex.image
 
                             {//animation不同致使的不能使用同一个texture 
-                                if(settings.isEdit){
+                                if(window.isEdit){
                                     if(animateTexSrcs[e.info.texSrc]){
                                         e.material_.map = tex.clone(); //编辑动画直接不用一个texture, 故而animation也不同
                                         e.material_.map.needsUpdate = true
@@ -1497,7 +1465,7 @@ window.initHot = function(model){
     }
     
     Hot.beginShineHot = function(){  
-        if(!settings.isEdit && shineMats.length == 0)return
+        if(!window.isEdit && shineMats.length == 0)return
         
         
         transitions.trigger({
@@ -1626,7 +1594,54 @@ window.initHot = function(model){
     }  
      */
      
+    //判断是否是移动端,如果是给关闭按钮添加touchstart事件
     
+    
+     
+    
+    Hot.closePopup = ()=>{// 关闭热点页面
+        if(!g_currentHot) return;
+        g_currentHot = null;
+        // var hotPop = document.getElementById('popup'); 
+        //     hotPop.style.display = "none";
+        // document.querySelector(".popup-content") && document.querySelector(".popup-content").removeChild(document.getElementById("id1"));
+        // $("#popup iframe:last").remove();
+         
+        
+        SoundManager.pause('hot', true)//自动播放被中断的音频 (bgm
+        
+         
+        return false
+    }  
+        
+ 
+    if(browser.isMobile()){
+        $('#closepop').on("touchstart",Hot.closePopup); 
+    }else{
+        $('#closepop').on("click",Hot.closePopup); 
+    }
+    
+    
+    
+    Hot.createHotList = function() {
+        var docFragment = document.createDocumentFragment();
+        var hots = hotGroup.children.filter(hot=>hot.info.actionType.openHot);
+        hots = hots.sort((a,b)=>{return a.order - b.order});
+        hots.forEach((hot)=>{
+            var li = document.createElement('li');
+            var span = document.createElement('span');
+            span.innerHTML = hot.info.title || '热点';
+            // console.log(span.innerHTML);
+            li.hot = hot;   // 列表每一项对应一个热点
+            li.appendChild(span);
+            docFragment.appendChild(li);
+             
+        })  
+        var ul = document.querySelector('#hotListContent ul');
+        ul && ul.appendChild(docFragment);
+         
+    }
+            
 
 }
 

文件差异内容过多而无法显示
+ 59051 - 0
web/public/static/js/main_2020_show copy.js


文件差异内容过多而无法显示
+ 410 - 1111
web/public/static/js/main_2020_show.js


+ 705 - 0
web/public/static/js/manage copy.js

@@ -0,0 +1,705 @@
+//管理js文件 获取modeldata.js 判断是否有特殊的字段,如果有就先加载SpecialScene.js 里面有对特殊场景处理的代码 否则就直接加载main
+var Manage = function(){
+    this.weixinURL = "https://res.wx.qq.com/open/js/jweixin-1.2.0.js",
+    this.time = "?"+new Date().getTime();
+    this.loadAudio();
+    // this.loadWeixin();
+}
+// window.isLocal = true
+
+//动态加载js文件
+Manage.prototype.LoadJs = function(_files, succes){
+	/* 已加载文件缓存列表,用于判断文件是否已加载过,若已加载则不再次加载*/
+	var classcodes = [];
+	var FileArray = [];
+    if (typeof _files === "object") {
+        FileArray = _files;
+    } else {
+        /*如果文件列表是字符串,则用,切分成数组*/
+        if (typeof _files === "string") {
+            FileArray = _files.split(",");
+        }
+    }
+    if (FileArray != null && FileArray.length > 0) {
+        var LoadedCount = 0;
+        for (var i = 0; i < FileArray.length; i++) {
+            loadFile(FileArray[i], function() {
+                LoadedCount++;
+                if (LoadedCount == FileArray.length) {
+                	try {
+                		succes();
+                	}
+                    catch(err) {
+					    console.log("err: 您未定义回调");
+					}
+                }
+            })
+        }
+    }
+    /*加载JS文件,url:文件路径,success:加载成功回调函数*/
+    function loadFile(url, success) {
+        if (!FileIsExt(classcodes, url)) {
+            var _ThisType = GetFileType(url);
+            var ThisType = _ThisType.indexOf("?") == -1 ? _ThisType  :  _ThisType.substring(0,_ThisType.indexOf("?"));
+            var fileObj = null;
+            if (ThisType == ".js") {
+                fileObj = document.createElement('script');
+                fileObj.src = url;
+            } else if (ThisType == ".css") {
+                fileObj = document.createElement('link');
+                fileObj.href = url;
+                fileObj.type = "text/css";
+                fileObj.rel = "stylesheet";
+            } else if (ThisType == ".less") {
+                fileObj = document.createElement('link');
+                fileObj.href = url;
+                fileObj.type = "text/css";
+                fileObj.rel = "stylesheet/less";
+            }
+            success = success || function() {};
+            fileObj.onload = fileObj.onreadystatechange = function() {
+                if (!this.readyState || 'loaded' === this.readyState || 'complete' === this.readyState) {
+                    success();
+                    classcodes.push(url)
+                }
+            }
+            document.getElementsByTagName('head')[0].appendChild(fileObj);
+        } else {
+            success();
+        }
+    }
+    /*获取文件类型,后缀名,小写*/
+    function GetFileType(url) {
+        if (url != null && url.length > 0) {
+            return url.substr(url.lastIndexOf(".")).toLowerCase();
+        }
+        return "";
+    }
+    /*文件是否已加载*/
+    function FileIsExt(FileArray, _url) {
+        if (FileArray != null && FileArray.length > 0) {
+            var len = FileArray.length;
+            for (var i = 0; i < len; i++) {
+                if (FileArray[i] == _url) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+	
+};
+
+//获取页面url后面的参数
+Manage.prototype.number = function(variable) {
+	var query = window.location.search.substring(1);
+   	var vars = query.split("&");
+   	for (var i=0;i<vars.length;i++) {
+           	var pair = vars[i].split("=");
+           	if(pair[0] == variable){return pair[1];}
+   	}
+   	return(false);
+};
+
+Manage.prototype.loadWeixin = function() {
+    var that = this;
+    this.LoadJs(that.weixinURL+that.time,function(){ });
+
+}
+
+Manage.prototype.loadAudio = function() { //相关:g_tourAudio \  g_playAudio
+    g_bgAudio = new Audio;
+    g_bgAudio.loop = true;
+    g_bgAudio.autoplay = true;
+    g_bgAudio.id = "bgaudio";
+    
+    //https://www.cnblogs.com/interdrp/p/4211883.html   部分资料
+    g_bgAudio.load();	// iOS 9   还需要额外的 load 一下, 否则直接 play 无效
+    var play = function(){
+        //if(window.tourAudioSta) return;
+         
+        if(this.bgmShouldPlay){
+            this.switchBgmState(true)
+        }
+        
+        document.removeEventListener("touchstart",play);
+        document.removeEventListener("click",play);
+        $('#player')[0] && $('#player')[0].removeEventListener("touchstart", play);
+    }.bind(this);
+    
+    g_bgAudio.oncanplay = ()=>{ 
+        this.switchBgmState(true)
+    }
+    document.addEventListener("WeixinJSBridgeReady", ()=> {
+        this.switchBgmState(true)
+    }, false);
+    
+    document.addEventListener("touchstart", play);//ios需要加个事件才能播放 不能自动播放;如果还有浏览器不行,换成别的交互事件
+    document.addEventListener("click", play);
+    $('#player')[0] && $('#player')[0].addEventListener("touchstart", play);
+    g_bgAudio.addEventListener('ended', ()=>{ 
+        this.switchBgmState(true)
+    }); 
+    
+    
+    
+    $("#volume").find("a").on("click", ()=> { 
+         
+        if($("#volume img")[0].src.indexOf("btn_on.png")>-1)
+        { 
+            this.switchBgmState(true); 
+        }
+        else if($("#volume img")[0].src.indexOf("btn_off.png")>-1)
+        {
+            this.switchBgmState(false);    
+        }
+    }) 
+
+    
+    
+}   
+Manage.prototype.switchBgmState = function(state){
+    if(!g_bgAudio || !g_bgAudio.src) return;
+    this.bgmShouldPlay = state
+    
+    var played = function(){
+        console.log('begin play bgm');
+        g_play = 1; 
+        g_playAudio = g_bgAudio;
+        $("#volume a img").attr("src", "./images/Volume btn_off.png")
+        $("#volume").attr("title", "关闭声音");
+        g_tourAudio && g_tourAudio.pause()
+    }
+    var paused = function(){ 
+        g_play = 0;
+        g_playAudio == g_bgAudio && (g_playAudio =  null)
+        $("#volume a img").attr("src", "./images/Volume btn_on.png")
+        $("#volume").attr("title", "打开声音");
+    }
+    
+    if(state ){
+        g_bgAudio.play(); 
+        if(g_bgAudio.paused){
+            paused()
+        }else{
+            played()
+            return true
+        }            
+    }else{
+        g_bgAudio.pause();
+        paused()
+    } 
+    
+    
+    g_bgAudio.pauseByHot = false
+    g_bgAudio.pauseByTour = false
+}    
+    
+ 
+
+ 
+
+
+ 
+
+
+Manage.prototype.weixinShare = function() {
+    console.log("weixinShare")
+    $.ajax({    
+        url:'https://www.4dage.com/wechat/jssdk/', 
+        type: "post",
+        data : {
+            'url' : location.href.split('#')[0]
+        }, 
+        dataType:"jsonp",     
+        jsonpCallback:"success_jsonp",         
+        success:function(data,textStatus){
+            console.log("weixinShare success")
+            console.log(data.appId)
+            
+            wx.config({
+                // debug : true,
+                appId : data.appId,
+                timestamp : data.timestamp,
+                nonceStr : data.nonceStr,
+                signature : data.signature,
+                jsApiList : [ 'checkJsApi', 'onMenuShareTimeline',
+                        'onMenuShareAppMessage', 'onMenuShareQQ',
+                        'onMenuShareWeibo', 'hideMenuItems',
+                        'showMenuItems', 'hideAllNonBaseMenuItem',
+                        'showAllNonBaseMenuItem', 'translateVoice',
+                        'startRecord', 'stopRecord', 'onRecordEnd',
+                        'playVoice', 'pauseVoice', 'stopVoice',
+                        'uploadVoice', 'downloadVoice', 'chooseImage',
+                        'previewImage', 'uploadImage', 'downloadImage',
+                        'getNetworkType', 'openLocation', 'getLocation',
+                        'hideOptionMenu', 'showOptionMenu', 'closeWindow',
+                        'scanQRCode', 'chooseWXPay',
+                        'openProductSpecificView', 'addCard', 'chooseCard',
+                        'openCard' ]
+            });
+        },    
+        error:function(XMLHttpRequest,textStatus,errorThrown){    
+            console.log("jsonp.error:"+textStatus);    
+        }    
+    }); 
+    
+    var success_jsonp = function(json){
+        console.log(json);
+    };
+
+
+    wx.ready(function(){ 
+        // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行〿
+        //对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中〿
+        //分享到朋友圈 
+        console.log(g_weixinObj)
+        wx.onMenuShareTimeline({ 
+            title: g_weixinObj.title, // 分享标题 
+            link: g_weixinObj.lineLink, // 分享链接 
+            imgUrl: g_weixinObj.imgUrl, // 分享图标 
+            desc: g_weixinObj.desc
+        }); 
+
+        //获取“分享给朋友”按钮点击状态及自定义分享内容接叿
+        wx.onMenuShareAppMessage({ 
+            title: g_weixinObj.title, // 分享标题 
+            desc: g_weixinObj.desc,  // 分享描述 
+            link: g_weixinObj.lineLink, // 分享链接 
+            imgUrl: g_weixinObj.imgUrl, // 分享图标 
+            type: '', // 分享类型,music、video或link,不填默认为link 
+            dataUrl: '' // 如果type是music或video,则要提供数据链接,默认为空 
+        });
+        
+        wx.onMenuShareWeibo({
+            title: g_weixinObj.title, // 分享标题
+            desc: g_weixinObj.desc, // 分享描述
+            link: g_weixinObj.lineLink, // 分享链接
+            imgUrl: g_weixinObj.imgUrl, // 分享图标
+            success: function () { 
+                // 用户确认分享后执行的回调函数
+            },
+            cancel: function () { 
+                // 用户取消分享后执行的回调函数
+            }
+        });
+
+        wx.onMenuShareQZone({
+            title: g_weixinObj.title, // 分享标题
+            desc: g_weixinObj.desc, // 分享描述
+            link: g_weixinObj.lineLink, // 分享链接
+            imgUrl: g_weixinObj.imgUrl, // 分享图标
+            success: function () { 
+                // 用户确认分享后执行的回调函数
+            },
+            cancel: function () { 
+                // 用户取消分享后执行的回调函数
+            }
+        });
+
+        wx.onMenuShareQQ({
+            title: g_weixinObj.title, // 分享标题
+            desc:  g_weixinObj.desc, // 分享描述
+            link: g_weixinObj.lineLink, // 分享链接
+            imgUrl: g_weixinObj.imgUrl, // 分享图标
+            success: function () { 
+                // 用户确认分享后执行的回调函数
+            },
+            cancel: function () { 
+                // 用户取消分享后执行的回调函数
+            }
+        });
+
+        wx.error(function(res){ 
+        // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名〿
+
+        });
+    });
+
+    
+}
+
+
+
+Manage.prototype.dealURL = function(src, type){
+    //music: "///super.4dage.com/data/LYW/edit/20200928_151633415.mp3"
+    //"https://super.4dage.com/data/LYW/edit/20200928_165319399.jpg"]
+    
+   
+    if(window.isLocal && settings.localPrefix!=void 0){//本地将线上的前缀替换
+        var oldPrefix = 'super.4dage.com/';  //最简单的地址写一个,如果有其他完全不一样的地址就用数组逐个判断
+        var index = src.indexOf(oldPrefix);
+        if(index>-1){
+            var wholeOldPrefix = src.slice(0, index+oldPrefix.length);
+            return src.replace(wholeOldPrefix, settings.localPrefix)
+        }
+        
+        // console.error("没有找到合适的本地链接") 
+        return src
+    }else{
+        //add https://
+        var prefix = g_Prefix.replace('https://','').replace('http://','') 
+        if(!src.includes('http:/') && !src.includes('https:/') && src.includes(prefix)){
+            src = 'https://'+src
+        }
+        return src
+    }
+    
+    
+}
+
+
+Manage.prototype.removeSrcPostMark = function(url){//去除texture.load时自动加上的'?'
+    var index = url.indexOf('?')
+    if(index>-1){
+        return url.slice(0, index)
+    }else return url 
+}
+
+
+Manage.prototype.showInfo = function (o) { // ({result:true, title:"发布成功"}); 
+	 
+	var box = $(".resultBox");
+	
+	var title = o.title || o || i18n.get('保存成功');
+	box.children().eq(0).html(title) 
+	
+	
+	//var time = o.time || THREE.Math.clamp((Config.lang=='en') ? title.length*50 : title.length*130 ,1300,5000);
+	var time = o.time ||  THREE.Math.clamp(title.length*130 ,1300,  5000);
+    o.time || console.log("showtime  " + time)
+	
+	//实际有一半的时间在渐变透明度
+	this.showInfoTimer && clearTimeout(this.showInfoTimer) 
+	box.removeClass("animate");//如果之后不久又要showinfo一个的话,先停止前面的animate
+	setTimeout(function () {
+		box.css(
+			{
+				'-webkit-animation-duration': time + 'ms',
+				'animation-duration': time + 'ms'
+			}
+		)
+        if(o.top){
+            box.children().css('top', o.top + "%");
+        }else{
+            box.children().css('top', '' )
+        }
+		box.removeClass("hide");
+		box.addClass("animate");
+		if (o.dontInteract) {//遮挡对屏幕的操作
+			box.css('pointer-events', 'auto')
+		} else {
+			box.css('pointer-events', 'none')
+		}
+		 
+
+		this.showInfoTimer = setTimeout(function () {
+			box.removeClass("animate");
+			box.addClass("hide");
+			this.showInfoTimer = null; 
+		}.bind(this), time + 20)
+
+	}.bind(this), 50)//这个数字太小的话后面触发的没有重新animate的效果 应该要比帧率大吧
+
+
+}//like:  manage.showInfo({title:'a', top:20})
+
+
+
+var manage = new Manage();
+
+//公用的函数
+
+function getQueryVariable(variable)
+{
+       var query = window.location.search.substring(1);
+       var vars = query.split("&");
+       for (var i=0;i<vars.length;i++) {
+               var pair = vars[i].split("=");
+               if(pair[0] == variable){return pair[1];}
+       }
+       return(false);
+}
+
+//隐藏公司Logo
+function showLogo(){
+    $("#myCompany").hide();
+    $("#loaderCoBrandName").hide();
+    $("#title-logo").hide();
+    $(".title-container").css("justify-content","center")
+}
+//czj 添加随机的时间
+function randomTime(){
+    return new Date()
+}
+function matcher(data){
+    if(!data || !g_version ) return data;
+    delete data.model.vision_version;
+    var _data = {
+        files: {
+            "templates": ["images/images{{number}}/{{filename}}"]
+        },
+        model :{
+            sid :window.number,
+            camera_start:
+            data.model.images && data.model.images.length != 0  ? 
+            {
+                camera: {
+                    zoom: "-1",
+                    quaternion: [
+                        JSON.parse(data.model.images[0].metadata).camera_quaternion.z,
+                        JSON.parse(data.model.images[0].metadata).camera_quaternion.w,
+                        JSON.parse(data.model.images[0].metadata).camera_quaternion.x,
+                        JSON.parse(data.model.images[0].metadata).camera_quaternion.y
+                    ]
+                },
+                pano: { uuid: JSON.parse(data.model.images[0].metadata).scan_id },
+                mode: "0"
+            }
+            : ''
+        },
+        sid: window.number,
+        hoticon: {
+            default: "./static/images/4dagePoint2.png",
+            higt: "./static/images/4dagePoint.png"
+        },
+        special: "false",
+        weixinDesc: ""
+    };
+    $.extend(true,data,_data)
+    return data;
+}
+
+function hotMatcher(data={}){
+    //if(!data || !g_version) return data; 
+    if(g_version) {
+        data.tourAudio = data.audio || {};
+    }else{
+        data.tourAudio = {}
+    }
+    return data;
+}
+
+
+var GifTexDeal = {
+    
+    animateObjects : [], 
+    animateTexs : [] ,
+    addAnimation : function(texture, owner, info, id){
+        /* if(this.animateObjects.find(e=> 
+            e.texture == texture && !ifSame(info, e.info) 
+        )) */ 
+        
+        var animation
+        var tex = this.animateTexs.find(e=>e.texture == texture)
+        if(tex){
+            animation = tex
+        }else{
+            animation = {texture,info }
+            this.animateTexs.push(animation)
+            this.setRepeart(animation)
+        }
+        
+        var object = {
+            animation, //默认相同的texture对应的info是一样的, 对应一个animation
+            owner,        
+        }
+         
+        this.animateObjects.push(object)
+        return object
+    },
+    
+    
+    remove : function(object){
+        var index = this.animateObjects.indexOf(object) 
+        if(index>-1){
+            this.animateObjects.splice(index, 1)
+            
+            if(!this.animateObjects.find(e=>e.animation == object.animation)){
+                let i = this.animateTexs.indexOf(object.animation)
+                this.animateTexs.splice(i, 1)
+                object.animation.texture.repeat.set(1,1) 
+            }
+            
+            this.stop(object) 
+            
+        }
+    },
+    setRepeart : function(animation){
+        animation.texture.repeat.set(1/animation.info.cellXcount, 1/animation.info.cellYcount)
+    },
+    start: function(object){ 
+         
+        if(!object || object.started )return;
+        object.started = true
+        if(object.animation.started)return;
+        object.animation.started = true
+        
+        var info = object.animation.info
+        var count = info.cellXcount * info.cellYcount - (info.voidCount || 0)
+     
+        if(count <= 1)return;
+        
+        transitions.start( (progress)=>{
+            var index = Math.floor(count * progress);
+            var indexX =  index % info.cellXcount
+            var indexY =  info.cellYcount - Math.floor(index /info.cellXcount ) - 1;  //uv.offset.y是从下到上的
+            object.animation.texture.offset.x = indexX / info.cellXcount;
+            object.animation.texture.offset.y = indexY / info.cellYcount;
+            
+            //console.log(object.id + " : "+ object.texture.offset.toArray())
+        } , info.duration * (-1), null,/* ()=>{//done  (-1):循环
+            object.started = false
+            object.texture.offset.x = 0;
+            object.texture.offset.y = 0;
+            this.start(object)
+        }, */ 0 ,null, object.id, "gif_"+object.animation.texture.id); 
+
+        
+
+    },
+    
+    
+    stop: function(object){ 
+        if(!object || !object.started)return;
+        object.started = false
+        //只有该object对应的texture对应的所有object都停止了,才能真的停止动画:
+        if(this.animateObjects.find(e=>e.animation == object.animation && e.started)) return;
+        
+         
+        transitions.cancelById("gif_"+object.animation.texture.id);
+        object.animation.texture.offset.set(0,0)
+        object.animation.started = false     
+        
+    }
+}
+
+var CloneObject = function(copyObj, result, isSimpleCopy, extraReplace) {
+    //isSimpleCopy只复制最外层
+    //复制json		result的可能:普通数字或字符串、普通数组、复杂对象
+    if(!copyObj)return copyObj //0 null undefined ''
+    result = result || {};
+    if (copyObj instanceof Array) {
+        /*  if (copyObj[0]instanceof Object) {
+            //不支持含有 [[Object]] 这样二级数组里面还是复杂数据的,普通和复杂的数据混合可能也不支持
+            console.error("不支持含有 [[Object]] 这样二级数组里面还是复杂数据的...")
+        }  
+        
+        return copyObj.slice(0);*/ //如果是数组,直接复制返回(排除数组内是object 
+        return copyObj.map(e=>{
+            if(e instanceof Object){
+                return CloneObject(e)
+            }else return e 
+        })
+       
+    }else{
+        if(copyObj.clone instanceof Function ){ //解决一部分
+            return copyObj.clone()
+        }
+    }
+    for (var key in copyObj) {
+        if (copyObj[key] instanceof Object && !isSimpleCopy)
+            result[key] = CloneObject(copyObj[key]);
+        else
+            result[key] = copyObj[key];
+        //如果是函数类同基本数据,即复制引用
+    }
+    return result;
+}
+;
+var ifSame = function(object1, object2){
+    if(object1 == object2  )return true // 0 != undefined  , 0 == ''
+    else if(!object1 || !object2) return false
+    else if(object1.constructor != object2.constructor){
+        return false
+    }else if(object1 instanceof Array ) {
+        if(object1.length != object2.length)return false;
+        var _object2 = object2.slice(0);
+        
+        for(let i=0;i<object1.length;i++){ 
+            var u = _object2.find(e=>ifSame(object1[i], e));
+            if(u == void 0 && !_object2.includes(u) && !object1.includes(u))return false;
+            else{
+                let index = _object2.indexOf(u);
+                _object2.splice(index,1);
+            }
+        }
+        
+        return true
+    }else if(object1.equals instanceof Function ){//复杂数据仅支持这种,其他的可能卡住?
+        
+        return object1.equals(object2)
+          
+    }else if(typeof object1 == 'number' ||  typeof object1 == 'string'){
+        if(isNaN(object1) && isNaN(object2))return true
+        else return object1 == object2
+        
+    }else if(typeof object1 == "object"){
+        var keys1 = Object.keys(object1)
+        var keys2 = Object.keys(object2)
+        if(!ifSame(keys1,keys2))return false;
+        
+        for(let i in object1){
+            var same = ifSame(object1[i], object2[i]);
+            if(!same)return false
+        }
+        return true
+    }else{
+        console.log('isSame出现例外')
+    }
+    
+    
+    
+    
+    
+}
+
+
+
+
+var SoundPriority = {//暂不支持同时播放
+    currentPlay:null,//当前正在播放list中的哪一个
+    list:[
+        {
+            name:"bg", 
+            level : 0,//越大优先级越高
+            canBeInterrupted : true ,
+            
+        },
+        {
+            name:"boxVideo", 
+            level : 1, 
+            canBeInterrupted : true,
+            checkIfNeedPlay:function(){
+                
+                
+            }
+        },
+        {
+            name:"hot", 
+            level : 2, 
+            canBeInterrupted : true
+        },
+        {
+            name:"tour", 
+            level : 3, 
+            canBeInterrupted : true
+        },
+        
+        
+    ],
+    register:function(){
+        
+        
+        
+    }
+    
+    
+}
+
+//兼容一代的場景
+//請求地址統一管理
+var g_onePregix = "https://bigscene.4dage.com/" //对应一代  http://www.4dmodel.com/SuperPanoramic/index.html?m=55
+var g_version = manage.number("version");
+g_version === "one" ? g_Prefix = g_onePregix : '';
+

+ 640 - 102
web/public/static/js/manage.js

@@ -1,12 +1,363 @@
+  
+var g_ProjectName=window.location.pathname.substring(window.location.pathname.indexOf("/")+1,window.location.pathname.lastIndexOf("/"));
+var g_Prefix="https://super.4dage.com/";
+// var g_Prefix=window.location.href.substring(0,window.location.href.indexOf("/index.html")+1);
+var s = window.location.href.split('/');
+    s.pop();
+//var g_Prefix = s.join('/');
+var g_index=null;
+var g_modeldata=null;
+
+var g_weixinTitle=null;
+
+var g_Hots=null;
+var g_HotMeshes=[];
+var g_HotMeshSize = {
+    g_HotMeshWidth: 0.3,
+    g_HotMeshHeight:0.3
+};
+
+//add表示添加,delete表示删除
+var g_HotStatus=null;
+var g_newHot = [];//存储新加热点
+var g_HotImage= {
+	"point":"https://super.4dage.com/images/4dagePoint2.png",
+	"point2":"https://super.4dage.com/images/4dagePoint.png"
+};	
+var g_saveHot=false;
+
+var g_TextColor=0x7777ff;
+var g_Text=null;
+var g_TextPlaneMesh=[];
+var g_TextIconMesh=[];
+var g_TextIcon="./static/images/text.png";
+var g_SelectTextIndex=null;
+var g_TextShow=null;
+var g_audioPlay=false;
+var g_background=null; 
+var g_roof=null;
+
+var g_data2 = null;//加载的data2.js的内容
+var g_bgAudio=null;//背景音乐
+var g_tourAudio=null;//导览音乐
+var g_play = 1;//表示播放图标状态
+var g_playAudio = null;//当前在播放或当继续播放时应该播放的,是g_bgAudio或g_tourAudio 
+var g_currentHot = null;//当前打开的热点 
+//var g_Texture=null;
+//var g_ChunknameTexture={};   //chunkname和贴图名称对应
+var g_NormalTexture=false;
+var g_SpecularTexture=false;
+var g_DirectionalLight=null;  
+  
+var g_snapShotWidth = 200; //截图下载图片的大小
+var g_snapShotHeight = 140;
+
+//微信分享
+var g_weixinObj = {
+  "title": document.querySelector("head title").innerHTML,
+  "lineLink" : window.location.href,
+  "imgUrl" : "https://www.4dmodel.com/SuperPanoramic/images/weixintitle.jpg",
+  "desc" : "四维时代提供技术支持",
+}
+
+var settings = {
+    hotClickEvent:{
+        video:{
+            playAndPause:true,
+            examine:false,
+            openHot:false 
+        },
+        photo:{
+            examine:false,
+            openHot:false 
+        },
+        shine:{
+            examine:true,
+            openHot:true  
+        }
+    },
+    //默认的:
+    teleportTime:  1500,//瞬间过渡的时间 
+    /* flytimeDistanceMultiplier:150, 
+    flyTime:750,  */
+    tourRotTime:2,  //默认停留2秒
+    //dontExamHot:true  
+    transparentBg: false,
+    bgImg:  null 
+}
+if(window.number == '725'||window.number == '724'){
+    settings.mobileNavHigh = true
+}
+
+
+//共用函数:
+
+
+window.common = null;  
+window.MathLight = null;
+window.math = null
+window.easing = null
+window.lerp = null
+window.transitions = null
+window.browser = null
+window.momentTourBlackNewType = 0//=  number == 'TEST'//true
+ 
+
+
+
+
+
+
+
+
+
+var dealMap = (map)=>{//使不resize  when   image is not power of two
+    map.wrapS = map.wrapT = THREE.ClampToEdgeWrapping;
+    map.minFilter = THREE.LinearFilter;
+    map.magFilter = THREE.LinearFilter;
+    map.generateMipmaps = true;  
+    
+}  
+ 
+ 
+  
+var dom = { 
+	getOffset: function(type, element, parent) { 
+		left = (type == "left") ? element.offsetLeft : element.offsetTop;
+		if (!parent) parent = $("body")[0];
+		while (element = element.offsetParent) { 
+			if (element == parent) break;
+			left += (type == "left") ? element.offsetLeft : element.offsetTop;
+		}
+		return left;
+	}  
+};
+
+
+var getTransformSid = function(){
+    var name
+    if(player.mode == 'panorama'){
+        name = player.currentPano ? player.currentPano.id : 'outside'
+    }else{
+        name = 'outside'
+    }
+    return name
+} 
+ 
+
+
+ 
+var convertTool = { 
+	getPos2d : function(point, camera, dom){//获取一个三维坐标对应屏幕中的二维坐标
+		var camera = camera || player.camera;
+		var dom = dom || player.domElement;
+		var pos = point.clone().project(camera)	//比之前hotspot的计算方式写得简单  project用于3转2(求法同shader); unproject用于2转3 :new r.Vector3(e.x, e.y, -1).unproject(this.camera);
+		
+		var x,y;
+		x = (pos.x + 1) / 2 * dom.clientWidth;
+		y = (1 - (pos.y + 1) / 2) * dom.clientHeight; 
+  
+		var inSight = x <= dom.clientWidth &&  x >= 0    //是否在屏幕中   
+					&& y <= dom.clientHeight &&  y >= 0 
+	 
+	
+		return {
+			pos: new THREE.Vector2(x,y),  // 屏幕像素坐标
+			vector:  pos,   //(范围 -1 ~ 1)
+			trueSide : pos.z<1, //trueSide为false时,即使在屏幕范围内可见,也是反方向的另一个不可以被渲染的点   参见Tag.update
+			inSight : inSight	//在屏幕范围内可见
+		};
+	},
+
+	ifShelter: function(pos3d){//检测某点在视线中是否被mesh遮挡 
+		var ori = player.position
+        var dir = pos3d.clone().sub(ori).normalize()
+        var ray = new THREE.Raycaster(ori, dir) //由外向里 因为模型从内侧是可见的所以从外侧
+	
+		/* if(config.isEdit && publicObjectSet.editor.mainDesign.editing){
+			var o = ray.intersectObjects(publicObjectSet.editor.mainDesign.wallMeshes);
+		}else{ */
+			var o = ray.intersectObjects(player.model.colliders);
+		//} 
+		var len = pos3d.distanceTo(ori);
+		if (o && o.length) {
+			for(var i=0;i<o.length;i++){
+				if(o[i].distance < len){  return true;  }//有遮挡
+			} 
+		} 
+	},
+    
+    
+    /* 
+        拖拽时,获取鼠标在拖拽面上的位置(需要借助另一个intersectPlane面来计算,即和相机方向一样的面,可保证铺满屏幕)
+        但是不一定能获取到,比如鼠标射线不朝向拖拽面时,即使获取也会是一个意外的反方向的交点。
+	 */
+	getPosAtPlane : function(pos, info/* , mouse, camera */){ //pos:与intersectPlane的交点 见笔记
+		var A = pos; 
+        var player = player;      
+        var mouse = player.mouse;
+        var O = new THREE.Vector3(mouse.x, mouse.y, -1).unproject(player.camera);
+		
+		
+		if(info.y != void 0){//地面线的
+        
+            var y = info.y; 
+            
+            if(player.mode == "floorplan"/*  ||  Math.abs(O.x-pos.x)<0.0001 && Math.abs(O.z-pos.z)<0.0001) */){
+            //intersectPlane和地面平行,无交点
+                var x = pos.x, z = pos.z;
+            
+            }else{
+             
+                if(y<player.camera.position.y && O.y <= A.y /* || y>player.camera.position.y && O.y >= A.y  */)return null;  //鼠标射线向上。因为相机一定位于地面以上(地面不会抬高到相机上吧?),所以无交点。
+                if(O.y == A.y){console.log('一样??');return;}
+                if(A.y == y){console.log('一样2??');return;}
+                var r = (O.y-y)/(A.y-y);
+                var x = (r*A.x-O.x)/(r-1);
+                var z = (r*A.z-O.z)/(r-1); 
+			}
+		}else{//垂直的也有越过消失点以后反向变化的情况,但使用时影响不大
+			var N = info.normalVec;
+			var P = info.pullPos;
+			if(N.y != 0 ){console.log('N.y != 0');return;} //仅仅支持垂直于地面的的墙壁,目前都是
+			if(O.z==A.z){console.log('O.z==A.z?');return;}
+			if(N.z!=0 && N.x != 0){//直接用这个通用的也可以,支持斜线的墙
+				//console.log('N.z==0 && N.x == 0?');  
+				var c = ( N.x*(A.x-O.x) + N.y*(A.y-O.y) + N.z*(A.z-O.z));
+				if(c == 0){console.log("分母为0?? return;");return;} 
+				var t = -((N.x*O.x + N.y*O.y + N.z*O.z) - (P.x*N.x + P.y*N.y + P.z*N.z) ) / c
+				var x = t * (A.x - O.x) + O.x;
+				var y = t * (A.y - O.y) + O.y;
+				var z = t * (A.z - O.z) + O.z;
+				/*原理: 已知空间直线L:(x-a)/m=(x-b)/n=(z-c)/p和空间平面π:Ax+By+Cz+D=0;
+				求直线L与平面π的交点的坐标。
+				把直线方程改写成参数形式:设(x-a)/m=(x-b)/n=(z-c)/p=t;
+				则x=mt+a;y=nt+b;z=pt+c;代入平面π的方程得:
+				A(mt+a)+B(nt+b)+C(pt+c)+D=0
+				由此解得t=-(Aa+Bb+Cc+D)/(Am+Bn+Cp)
+				再代入参数方程即得交点的坐标(x,y,z). */
+			}else if(N.x ==0 ){ //z与pullPos相等
+				var z = P.z;
+				if(O.y == A.y){console.log('一样??');return;}
+				if(A.y == y){console.log('一样2??');return;}
+                if(A.z == z){console.log('一样3??');return;}
+				var r = (O.z-z)/(A.z-z);
+				var x = (r*A.x-O.x)/(r-1);
+				var y = (r*A.y-O.y)/(r-1);
+			}else if(N.z == 0){//x与pullPos相等
+				var x = P.x;
+				if(O.y == A.y){console.log('一样??');return;}
+				if(A.y == y){console.log('一样2??');return;}
+                if(A.x == x){console.log('一样3??');return;}
+				var r = (O.x-x)/(A.x-x);
+				var y = (r*A.y-O.y)/(r-1);
+				var z = (r*A.z-O.z)/(r-1);
+			}
+		}   
+		
+		return new THREE.Vector3(x,y,z);
+	},
+
+
+	
+	getMouseIntersect : function(camera, meshes, mouse){//获取鼠标和meshes交点
+		var raycaster = new THREE.Raycaster; 
+		camera.updateMatrixWorld(); 
+		var origin = new THREE.Vector3(mouse.x,mouse.y,-1).unproject(camera)
+		  , end = new THREE.Vector3(mouse.x,mouse.y,1).unproject(camera); 
+		var dir = end.sub(origin).normalize() 
+		raycaster.set(origin, dir);
+		var n = raycaster.intersectObjects(meshes);
+		if (0 === n.length)
+			return null;
+		return n[0];
+		
+	},
+	ifIntersectChunks : function(A,B,options={}){//获取某个线段/射线和meshes的交点 
+		var dir = B.clone().sub(A).normalize();
+		var len = options.InfinityLen ? Infinity :  A.distanceTo(B) + (options.extLen||0);
+		var ray = new THREE.Raycaster(A.clone(), dir, 0, len);
+          
+		var o = ray.intersectObjects(options.model || player.model.colliders);
+		if (o && o.length)return o;
+		  
+		if(options.throughWidth){ //允许最小宽度,防止穿过极小的缝隙导致撞墙感
+			var normal = math.getNormal({points:[{x:A.x, y:A.z},{x:B.x, y:B.z}]});//线段法线
+			normal.multiplyScalar(options.throughWidth)
+			var normalVec3 = new THREE.Vector3(normal.x, 0, normal.y);
+			
+			var A2 = A.clone().add(normalVec3)
+			ray.set(A2, dir);  
+			var o2 = ray.intersectObjects(options.model || player.model.colliders);
+			ray.set(A.clone().add(normalVec3.negate()), dir);
+			if (o2 && o2.length)return o2;
+			var o3 = ray.intersectObjects(options.model || player.model.colliders);
+			if (o3 && o3.length)return o3; 
+		} 
+		return null;
+	},
+    
+	getPosAtSphere : function(pos3d, toPanoPos){
+		var dir = pos3d.clone().sub(toPanoPos); 
+		dir.normalize();//然后计算在球中
+		dir.multiplyScalar(Constants.skyRadius);   
+		dir.add(toPanoPos); 
+		return dir;
+	} ,
+    
+    getScaleForConstantSize : function(op={}){ //获得规定二维大小的mesh的scale值。可以避免因camera的projection造成的mesh视觉大小改变。  来源:tag.updateDisc
+        var w;  
+        var i = new THREE.Vector3, o = new THREE.Vector3, l = new THREE.Vector3, c = new THREE.Vector3, h = new THREE.Vector3
+         
+        if(op.width2d) w = op.width2d //如果恒定二维宽度
+        else{//否则考虑上距离,加一丢丢近大远小的效果
+            var currentDis, nearBound, farBound
+            if(op.camera.type == "OrthographicCamera"){
+                currentDis = (op.camera.right - op.camera.left) / op.camera.zoom
+            }else{
+                currentDis = op.position.distanceTo(op.camera.position);
+            } 
+            w = op.maxSize - ( op.maxSize -  op.minSize) * THREE.Math.smoothstep(currentDis,  op.nearBound,  op.farBound);
+            //maxSize : mesh要表现的最大像素宽度;   nearBound: 最近距离,若比nearBound近,则使用maxSize
+        }
+        i.copy(op.position).project(op.camera),  //tag中心在屏幕上的二维坐标
+        o.set(op.resolution.x / 2, op.resolution.y / 2, 1).multiply(i), //转化成px   -w/2 到 w/2的范围
+        l.set(w / 2, 0, 0).add(o),  //加上tag宽度的一半
+        c.set(2 / op.resolution.x, 2 / op.resolution.y, 1).multiply(l), //再转回  -1 到 1的范围
+        h.copy(c).unproject(op.camera);//再转成三维坐标,求得tag边缘的位置
+        var g = h.distanceTo(op.position)//就能得到tag的三维半径
+    
+        return g  //可能NAN  当相机和position重叠时
+         
+    } 
+    
+    
+    
+}
+
+ 
+
+
+
+
+
+
+
+
+
+
+
+//--------------------------------------
 //管理js文件 获取modeldata.js 判断是否有特殊的字段,如果有就先加载SpecialScene.js 里面有对特殊场景处理的代码 否则就直接加载main
+
+
+
 var Manage = function(){
     this.weixinURL = "https://res.wx.qq.com/open/js/jweixin-1.2.0.js",
     this.time = "?"+new Date().getTime();
     this.loadAudio();
     // this.loadWeixin();
 }
-// window.isLocal = true
-
 //动态加载js文件
 Manage.prototype.LoadJs = function(_files, succes){
 	/* 已加载文件缓存列表,用于判断文件是否已加载过,若已加载则不再次加载*/
@@ -107,98 +458,6 @@ Manage.prototype.loadWeixin = function() {
 
 }
 
-Manage.prototype.loadAudio = function() { //相关:g_tourAudio \  g_playAudio
-    g_bgAudio = new Audio;
-    g_bgAudio.loop = true;
-    g_bgAudio.autoplay = true;
-    g_bgAudio.id = "bgaudio";
-    
-    //https://www.cnblogs.com/interdrp/p/4211883.html   部分资料
-    g_bgAudio.load();	// iOS 9   还需要额外的 load 一下, 否则直接 play 无效
-    var play = function(){
-        //if(window.tourAudioSta) return;
-         
-        if(this.bgmShouldPlay){
-            this.switchBgmState(true)
-        }
-        
-        document.removeEventListener("touchstart",play);
-        document.removeEventListener("click",play);
-        $('#player')[0] && $('#player')[0].removeEventListener("touchstart", play);
-    }.bind(this);
-    
-    g_bgAudio.oncanplay = ()=>{ 
-        this.switchBgmState(true)
-    }
-    document.addEventListener("WeixinJSBridgeReady", ()=> {
-        this.switchBgmState(true)
-    }, false);
-    
-    document.addEventListener("touchstart", play);//ios需要加个事件才能播放 不能自动播放;如果还有浏览器不行,换成别的交互事件
-    document.addEventListener("click", play);
-    $('#player')[0] && $('#player')[0].addEventListener("touchstart", play);
-    g_bgAudio.addEventListener('ended', ()=>{ 
-        this.switchBgmState(true)
-    }); 
-    
-    
-    
-    $("#volume").find("a").on("click", ()=> { 
-         
-        if($("#volume img")[0].src.indexOf("btn_on.png")>-1)
-        { 
-            this.switchBgmState(true); 
-        }
-        else if($("#volume img")[0].src.indexOf("btn_off.png")>-1)
-        {
-            this.switchBgmState(false);    
-        }
-    }) 
-
-    
-    
-}   
-Manage.prototype.switchBgmState = function(state){
-    if(!g_bgAudio || !g_bgAudio.src) return;
-    this.bgmShouldPlay = state
-    
-    var played = function(){
-        console.log('begin play bgm');
-        g_play = 1; 
-        g_playAudio = g_bgAudio;
-        $("#volume a img").attr("src", "./images/Volume btn_off.png")
-        $("#volume").attr("title", "关闭声音");
-        g_tourAudio && g_tourAudio.pause()
-    }
-    var paused = function(){ 
-        g_play = 0;
-        g_playAudio == g_bgAudio && (g_playAudio =  null)
-        $("#volume a img").attr("src", "./images/Volume btn_on.png")
-        $("#volume").attr("title", "打开声音");
-    }
-    
-    if(state ){
-        g_bgAudio.play(); 
-        if(g_bgAudio.paused){
-            paused()
-        }else{
-            played()
-            return true
-        }            
-    }else{
-        g_bgAudio.pause();
-        paused()
-    } 
-    
-    
-    g_bgAudio.pauseByHot = false
-    g_bgAudio.pauseByTour = false
-}    
-    
- 
-
- 
-
 
  
 
@@ -334,7 +593,7 @@ Manage.prototype.dealURL = function(src, type){
             return src.replace(wholeOldPrefix, settings.localPrefix)
         }
         
-        // console.error("没有找到合适的本地链接") 
+        console.error("没有找到合适的本地链接") 
         return src
     }else{
         //add https://
@@ -406,7 +665,6 @@ Manage.prototype.showInfo = function (o) { // ({result:true, title:"发布成功
 
 
 
-var manage = new Manage();
 
 //公用的函数
 
@@ -431,7 +689,7 @@ function showLogo(){
 //czj 添加随机的时间
 function randomTime(){
     return new Date()
-}
+};
 function matcher(data){
     if(!data || !g_version ) return data;
     delete data.model.vision_version;
@@ -460,8 +718,8 @@ function matcher(data){
         },
         sid: window.number,
         hoticon: {
-            default: "./static/images/4dagePoint2.png",
-            higt: "./static/images/4dagePoint.png"
+            default: "https://super.4dage.com/images/4dagePoint2.png",
+            higt: "https://super.4dage.com/images/4dagePoint.png"
         },
         special: "false",
         weixinDesc: ""
@@ -657,8 +915,8 @@ var ifSame = function(object1, object2){
 
 
 
-var SoundPriority = {//暂不支持同时播放
-    currentPlay:null,//当前正在播放list中的哪一个
+/* var SoundManager = {//暂不支持同时播放
+    currentAudio:null,//当前正在播放list中的哪一个
     list:[
         {
             name:"bg", 
@@ -688,15 +946,295 @@ var SoundPriority = {//暂不支持同时播放
         
         
     ],
+    switchPlay:function(){
+        
+    },
     register:function(){
         
         
         
-    }
+    } 
+    
+}
+ */
+ 
+ 
+ 
+//最好能知道应该播放到的currentTime
+var SoundManager = {//暂不支持同时播放
+    currentAudio:null,//当前正在播放list中的哪一个
+    enableSound:true,//是否允许有声音
+    
+    
+    playHistory:[],//被打断的加入播放历史
+    
+    list:[ ],//同一级别可以互相打断 //暂时不做多级别
+    
+     
+    
+    play:function(name, src, currentTime){
+        var object = this.list.find(e=>e.name == name)
+        if(object){
+            if(this.currentAudio){ 
+                this.pause(this.currentAudio.name, false, true)
+                
+            }
+            
+            {//将当前要播放的播放历史中清除
+                let index = this.playHistory.indexOf(object)
+                if(index>-1)this.playHistory.splice(index,1);
+                
+            }
+               
+            
+            this.currentAudio = object
+            if(src){ 
+                this.setSrc(name, src)
+            }
+            if(currentTime!=void 0){
+                object.audio.currentTime = currentTime
+            }
+            if(object.audio){
+                object.audio.load();	// iOS 9   还需要额外的 load 一下, 否则直接 play 无效 *///https://www.cnblogs.com/interdrp/p/4211883.html   部分资料
+                object.audio.play();
+                object.callback && object.callback(true)
+            }
+            Log(name + '  播放 '  )
+        }
+        
+    },
+    
     
+    pause:function(name, autoReplayLast, isInterrupt){//需要能自动恢复上一个被打算的音频。恢复前判断是否还需要播放
+        var object = this.list.find(e=>e.name == name)
+        if(object){
+            this.currentAudio = null
+            
+            
+            if(object.audio){
+                object.audio.pause()
+                object.callback && object.callback(false)
+                Log(name + ' 中断音频 '+  "("+common.getFileNameFromUrl(object.audio.src)+')' )
+            }
+            
+            
+            
+            if(isInterrupt){//一般主动调用不需要加这个
+                this.playHistory.push(object)//如果是被中断的,加入播放历史,等待恢复播放
+            }
+             
+            
+            if(autoReplayLast){ //播放之前的音频。它们是被打断过的。
+                while(this.playHistory.length){ 
+                    var last = this.playHistory.pop();
+                    if(last.src && last.canplay(last.audio)){
+                        this.play(last.name )
+                    }
+                    
+                }
+                
+            }
+            
+            
+        }
+        
+    },
     
+ 
+    
+    setSrc : function(name, src){//不能直接给audio赋src!一定要用这个函数!因为我要拿这里的src来判断有无src,因为貌似audio的src会自动变,''时会变成html的链接
+        var object = this.list.find(e=>e.name == name)
+        object.src = src
+        object.audio.src = src
+        Log(`${object.name} 设置src: ${src}`)
+    },
+    
+    createAudio:function(object={}){//name, level, canplay
+        if(!object.fake){
+            object.audio = new Audio(); 
+            object.audio.loop = !!object.loop;
+            //object.audio.autoplay = true;
+        
+            
+            object.audio.addEventListener('ended', ()=>{ 
+                if(object.loop){//循环
+                    Log(`${object.name} 播放完毕,重新播放`)
+                    object.audio.play()
+                }else{
+                    this.pause(object.name, true);//停止后的后续处理
+                }
+            });
+            
+            
+            object.audio.oncanplaythrough = ()=>{ 
+                Log(`${object.name} canplaythrough  `) 
+            }
+        }
+        
+        this.list.push(object)
+        
+    },
+    
+    
+    
+    initAutoPlay:function(){  //处理设备自动播放限制
+        let play = function(){  
+            if(this.currentAudio && this.currentAudio.audio){
+                this.currentAudio.audio.play() 
+                Log(`${this.currentAudio.name} 自动播放成功`) //即使设置src在这之后好像也能成功播放
+            }else{
+                
+            }
+            document.removeEventListener("touchstart",play);
+            document.removeEventListener("click",play);
+            $('#player')[0] && $('#player')[0].removeEventListener("touchstart", play);
+        }.bind(this);
+        
+        
+        document.addEventListener("WeixinJSBridgeReady", play, false);
+        document.addEventListener("touchstart", play);//ios需要加个事件才能播放 不能自动播放;如果还有浏览器不行,换成别的交互事件
+        document.addEventListener("click", play);
+        $('#player')[0] && $('#player')[0].addEventListener("touchstart", play); 
+            
+         
+    }
+}
+
+
+function Log(value, color, fontSize){
+    color = color || '#13f'
+    fontSize = fontSize || 14
+    console.warn(`%c${value}`, `color:${color};font-size:${fontSize}px`) 
 }
 
+
+
+
+
+
+Manage.prototype.loadAudio = function() { //相关:g_tourAudio \  g_playAudio
+    
+     
+    
+    
+    //热点页面因为挡住了界面,所以暂时不存在别的音频阻止热点音频的可能
+    //box视频都静音,所以暂时不考虑
+    
+    SoundManager.createAudio({
+        name:'bgm',
+        level:0, 
+        src:'',
+        loop:true,
+        canplay:(audio)=>{
+            return this.bgmShouldPlay
+        },
+        callback:(state)=>{//play或pause时随之触发的函数(即使还没开始播放)
+            if(state){
+                $("#volume a img").attr("src", "./static/images/Volume btn_off.png")
+                $("#volume").attr("title", "关闭声音");
+            }else{
+                $("#volume a img").attr("src", "./static/images/Volume btn_on.png")
+                $("#volume").attr("title", "打开声音");
+            }
+        }
+    })  
+    SoundManager.createAudio({
+        name:'tour',
+        level:0, 
+        src:'',
+        loop:false,
+        canplay:(audio)=>{
+            return player.director && player.director.tourIsPlaying && player.director.getAudio()
+        }
+    })
+    SoundManager.createAudio({
+        name:'hot',
+        fake:true,//实际上没有audio. 只是为了来停止和续播其他音频
+        level:1, 
+        src:'',
+        loop:false,
+        canplay:(audio)=>{
+            
+        }
+    })
+     
+    
+    $("#volume").find("a").on("click", ()=> {  
+        if($("#volume img")[0].src.indexOf("btn_on.png")>-1)
+        { 
+            this.switchBgmState(true); 
+        }
+        else if($("#volume img")[0].src.indexOf("btn_off.png")>-1)
+        {
+            this.switchBgmState(false);    
+        }
+    })  
+    
+    this.switchBgmState(true);//初始设置允许播放bgm 
+    SoundManager.initAutoPlay()
+    
+    
+}  
+
+
+ 
+Manage.prototype.switchBgmState = function(state){//按钮的状态完全代表是否应该播放bgm,即使还没加载完
+    this.bgmShouldPlay = state
+    
+    
+    if(state){
+        
+        SoundManager.play('bgm')
+    }else{
+        
+        SoundManager.pause('bgm')
+    }
+    
+    
+    /* if(!g_bgAudio || !g_bgAudio.src) return;
+    
+    
+    var played = function(){
+        console.log('begin play bgm');
+        g_play = 1; 
+        g_playAudio = g_bgAudio;
+        
+        g_tourAudio && g_tourAudio.pause()
+    }
+    var paused = function(){ 
+        g_play = 0;
+        g_playAudio == g_bgAudio && (g_playAudio =  null)
+        
+    }
+    
+    if(state ){
+        g_bgAudio.play(); 
+        if(g_bgAudio.paused){
+            paused()
+        }else{
+            played()
+            return true
+        }            
+    }else{
+        g_bgAudio.pause();
+        paused()
+    } 
+    
+    
+    g_bgAudio.pauseByHot = false
+    g_bgAudio.pauseByTour = false */
+}    
+    
+    
+    
+    
+    
+var manage = new Manage();
+
+ 
+
+
+
 //兼容一代的場景
 //請求地址統一管理
 var g_onePregix = "https://bigscene.4dage.com/" //对应一代  http://www.4dmodel.com/SuperPanoramic/index.html?m=55

+ 0 - 87
web/public/static/js/myShow.js

@@ -1,87 +0,0 @@
-var g_ProjectName=window.location.pathname.substring(window.location.pathname.indexOf("/")+1,window.location.pathname.lastIndexOf("/"));
-var g_Prefix="https://super.4dage.com/";
-// var g_Prefix=window.location.href.substring(0,window.location.href.indexOf("/index.html")+1);
-var s = window.location.href.split('/');
-s.pop();
-//var g_Prefix = s.join('/');
-// var g_Prefix = s.join('/') + '/static/';
-
-var g_index=null;
-var g_modeldata=null;
-
-var g_weixinTitle=null;
-
-var g_Hots=null;
-var g_HotMeshes=[];
-var g_HotMeshSize = {
-  g_HotMeshWidth: 0.3,
-  g_HotMeshHeight:0.3
-};
-
-//add表示添加,delete表示删除
-var g_HotStatus=null;
-var g_newHot = [];//存储新加热点
-var g_HotImage= {
-	"point":"./static/images/4dagePoint2.png",
-	"point2":"./static/images/4dagePoint.png"
-};	
-var g_saveHot=false;
-
-var g_TextColor=0x7777ff;
-var g_Text=null;
-var g_TextPlaneMesh=[];
-var g_TextIconMesh=[];
-var g_TextIcon="./images/text.png";
-var g_SelectTextIndex=null;
-var g_TextShow=null;
-var g_audioPlay=false;
-var g_background=null; 
-var g_roof=null;
-
-var g_data2 = null;//加载的data2.js的内容
-var g_bgAudio=null;//背景音乐
-var g_tourAudio=null;//导览音乐
-var g_play = 1;//表示播放图标状态
-var g_playAudio = null;//当前在播放或当继续播放时应该播放的,是g_bgAudio或g_tourAudio 
-var g_currentHot = null;//当前打开的热点 
-//var g_Texture=null;
-//var g_ChunknameTexture={};   //chunkname和贴图名称对应
-var g_NormalTexture=false;
-var g_SpecularTexture=false;
-var g_DirectionalLight=null;  
-  
-var g_snapShotWidth = 200; //截图下载图片的大小
-var g_snapShotHeight = 140;
-
-//微信分享
-var g_weixinObj = {
-  "title": document.querySelector("head title").innerHTML,
-  "lineLink" : window.location.href,
-  "imgUrl" : "https://www.4dmodel.com/SuperPanoramic/images/weixintitle.jpg",
-  "desc" : "四维时代提供技术支持",
-}
-
-var settings = {
-    localPrefix : 'static/',
-    hotClickEvent:{
-        video:{
-            playAndPause:true,
-            examine:false,
-            openHot:false 
-        },
-        photo:{
-            examine:false,
-            openHot:false 
-        },
-        shine:{
-            examine:true,
-            openHot:true  
-        }
-    },
-    //dontExamHot:true  
-    transparentBg: false,
-    bgImg:  null 
-}
-if(window.number == '725'||window.number == '724'){
-    settings.mobileNavHigh = true
-}

二进制
web/public/xuliezhen/female_1/Bye.png


二进制
web/public/xuliezhen/female_1/Greeting.png


二进制
web/public/xuliezhen/female_1/Right.png


二进制
web/public/xuliezhen/female_1/Speaking1.png


二进制
web/public/xuliezhen/female_1/Speaking2.png


二进制
web/public/xuliezhen/female_1/Speaking3.png


二进制
web/public/xuliezhen/female_1/Speaking4.png


二进制
web/public/xuliezhen/female_1/Speaking5.png


二进制
web/public/xuliezhen/female_1/Stand.png


二进制
web/public/xuliezhen/female_1/Stand2.png


二进制
web/public/xuliezhen/female_1/StandLook.png


二进制
web/public/xuliezhen/female_1/Thanks.png


二进制
web/public/xuliezhen/female_1/Wrong.png


二进制
web/public/xuliezhen/female_2/Bye.png


二进制
web/public/xuliezhen/female_2/Greeting.png


二进制
web/public/xuliezhen/female_2/Right.png


二进制
web/public/xuliezhen/female_2/Speaking1.png


二进制
web/public/xuliezhen/female_2/Speaking2.png


二进制
web/public/xuliezhen/female_2/Speaking3.png


二进制
web/public/xuliezhen/female_2/Speaking4.png


二进制
web/public/xuliezhen/female_2/Speaking5.png


二进制
web/public/xuliezhen/female_2/Stand.png


二进制
web/public/xuliezhen/female_2/Stand2.png


二进制
web/public/xuliezhen/female_2/StandLook.png


二进制
web/public/xuliezhen/female_2/Thanks.png


二进制
web/public/xuliezhen/female_2/Wrong.png


二进制
web/public/xuliezhen/male/Bye.png


+ 0 - 0
web/public/xuliezhen/male/Greeting.png


部分文件因为文件数量过多而无法显示