Browse Source

优化界面

tianyabing 2 years ago
parent
commit
8d9a2f0a85
52 changed files with 11967 additions and 581 deletions
  1. 1 0
      index.html
  2. 15 0
      package-lock.json
  3. 1 0
      package.json
  4. 24 24
      src/api/dashboard/apiDashboard.js
  5. 9 0
      src/api/system/apiLogin.js
  6. 6 0
      src/api/work/apiWorkMeeting.js
  7. 10 4
      src/components/common/query.vue
  8. 4 0
      src/components/common/timeLine.vue
  9. 3 3
      src/components/dashboard/message/dashboardMsgList.vue
  10. 1 0
      src/components/dashboard/portrait/supermarket/supermarketTrendChart.vue
  11. 9 3
      src/components/dashboard/portrait/supermarketPortrait.vue
  12. 4 1
      src/components/home/ContainerAside.vue
  13. 114 22
      src/components/home/HomeHeader.vue
  14. 4 5
      src/components/life/restaurant/components/lifeRestDailyMenu.vue
  15. 4 2
      src/components/life/supermarket/components/lifeSupermarketTopTable.vue
  16. 28 7
      src/components/scene/energy/common/deviceCardAir.vue
  17. 143 45
      src/components/scene/energy/sceneEnergyAircondition/airconditioningCard.vue
  18. 154 1
      src/components/scene/energy/sceneEnergyLight.vue
  19. 154 1
      src/components/scene/energy/sceneEnergyWater.vue
  20. 85 8
      src/components/scene/meeting/config/meetingRoomConfig.vue
  21. 130 31
      src/components/scene/meeting/config/meetingRoomDeviceTable.vue
  22. 1 1
      src/components/scene/meeting/config/meetingRoomItem.vue
  23. 7 4
      src/components/security/alarm/securityAlarmGrid.vue
  24. 2 2
      src/components/security/alarm/securityAlarmInfo.vue
  25. 19 7
      src/components/security/camera/hkwsCamera.vue
  26. 1 8
      src/components/security/common/securityDeviceSelect.vue
  27. 2 2
      src/components/security/device/securityDevice.vue
  28. 129 389
      src/components/work/meeting/workMeeting.vue
  29. 5 1
      src/main.js
  30. 5 0
      src/plugins/hkws/h5player.min.js
  31. 225 0
      src/plugins/hkws/playctrl1/AudioRenderer.js
  32. 711 0
      src/plugins/hkws/playctrl1/DecodeWorker.js
  33. 0 0
      src/plugins/hkws/playctrl1/Decoder.js
  34. 396 0
      src/plugins/hkws/playctrl1/SuperRender_10.js
  35. 8 0
      src/plugins/hkws/playctrl2/Decoder.js
  36. BIN
      src/plugins/hkws/playctrl2/Decoder.wasm
  37. 0 0
      src/plugins/hkws/playctrl2/Decoder.worker.js
  38. 8 0
      src/plugins/hkws/playctrl3/Decoder.js
  39. BIN
      src/plugins/hkws/playctrl3/Decoder.wasm
  40. 0 0
      src/plugins/hkws/playctrl3/Decoder.worker.js
  41. 2907 0
      src/plugins/hkws/talk/AudioInterCom.js
  42. BIN
      src/plugins/hkws/talk/AudioInterCom.wasm
  43. 3492 0
      src/plugins/hkws/talkW/AudioInterCom.js
  44. BIN
      src/plugins/hkws/talkW/AudioInterCom.wasm
  45. 234 0
      src/plugins/hkws/talkW/AudioInterCom.worker.js
  46. 2733 0
      src/plugins/hkws/transform/libSystemTransform.js
  47. BIN
      src/plugins/hkws/transform/libSystemTransform.wasm
  48. 120 0
      src/plugins/hkws/transform/systemTransform-worker.js
  49. 16 3
      src/stores/index.js
  50. 11 0
      src/utils/dateUtil.js
  51. 7 1
      src/utils/request.js
  52. 25 6
      src/views/LoginView.vue

+ 1 - 0
index.html

@@ -6,6 +6,7 @@
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <title>智慧楼宇平台</title>
     <script type="module" src="/src/plugins/gverify.js"></script>
+    <script type="module" src="/src/plugins/hkws/h5player.min.js"></script>
   </head>
   <body>
     <div id="app"></div>

+ 15 - 0
package-lock.json

@@ -17,6 +17,7 @@
         "hikvs-web": "^1.0.4",
         "moment": "^2.29.4",
         "pinia": "^2.0.16",
+        "pinia-plugin-persistedstate": "^3.1.0",
         "qs": "^6.11.0",
         "vue": "^2.7.14",
         "vue-router": "^3.5.4"
@@ -4770,6 +4771,14 @@
         }
       }
     },
+    "node_modules/pinia-plugin-persistedstate": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmmirror.com/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-3.1.0.tgz",
+      "integrity": "sha512-8UN+vYMEPBdgNLwceY08mi5olI0wkYaEb8b6hD6xW7SnBRuPydWHlEhZvUWgNb/ibuf4PvufpvtS+dmhYjJQOw==",
+      "peerDependencies": {
+        "pinia": "^2.0.0"
+      }
+    },
     "node_modules/pinia/node_modules/vue-demi": {
       "version": "0.13.11",
       "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.11.tgz",
@@ -10177,6 +10186,12 @@
         }
       }
     },
+    "pinia-plugin-persistedstate": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmmirror.com/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-3.1.0.tgz",
+      "integrity": "sha512-8UN+vYMEPBdgNLwceY08mi5olI0wkYaEb8b6hD6xW7SnBRuPydWHlEhZvUWgNb/ibuf4PvufpvtS+dmhYjJQOw==",
+      "requires": {}
+    },
     "pkg-types": {
       "version": "1.0.1",
       "resolved": "https://registry.npmmirror.com/pkg-types/-/pkg-types-1.0.1.tgz",

+ 1 - 0
package.json

@@ -17,6 +17,7 @@
     "hikvs-web": "^1.0.4",
     "moment": "^2.29.4",
     "pinia": "^2.0.16",
+    "pinia-plugin-persistedstate": "^3.1.0",
     "qs": "^6.11.0",
     "vue": "^2.7.14",
     "vue-router": "^3.5.4"

+ 24 - 24
src/api/dashboard/apiDashboard.js

@@ -1,98 +1,98 @@
 import Request from "@/utils/request";
 // 获取楼层概览
 const getFloorOverview = (param) => {
-    return Request.get('/dashboard/getBuildingSituation', param)
+    return Request.post('/dashboard/getBuildingSituation', param)
 }
 // 获取空间概览
 const getSpaceOverview = (param) => {
-    return Request.get('/dashboard/getSpaceOverview', param)
+    return Request.post('/dashboard/getSpaceOverview', param)
 }
 // 获取碳配额概览
 const getCarbonOverview = (param) => {
-    return Request.get('/dashboard/getCarbonQuota', param)
+    return Request.post('/dashboard/getCarbonQuota', param)
 }
 // 获取光伏发电概览
 const getPvPowerOverview = (param) => {
-    return Request.get('/dashboard/getPhotovoltaicPower', param)
+    return Request.post('/dashboard/getPhotovoltaicPower', param)
 }
 // 获取光伏发电概览
 const getPvProfitOverview = (param) => {
-    return Request.get('/dashboard/getPhotovoltaicProfit', param)
+    return Request.post('/dashboard/getPhotovoltaicProfit', param)
 }
 
 // 获取人员核心指标
 const getPersonCoreData = (param) => {
-    return Request.get('/personnel/getPersonnelInfoCount', param)
+    return Request.post('/personnel/getPersonnelInfoCount', param)
 }
 // 获取人员统计信息
 const getPersonEnterSummary = (param) => {
-    return Request.get('/personnel/getPersonnelInfoList', param)
+    return Request.post('/personnel/getPersonnelInfoList', param)
 }
 
 // 获取餐厅核心指标
 const getRestCoreData = (param) => {
-    return Request.get('/dining_room/getRestaurantConsumption', param)
+    return Request.post('/dining_room/getRestaurantConsumption', param)
 }
 
 const getRestTrendData = (param) => {
-    return Request.get('/dining_room/getRestaurantConsumptionChart', param)
+    return Request.post('/dining_room/getRestaurantConsumptionChart', param)
 }
 
 // 商超
 const getSuperMarketCoreData = (param) => {
-    return Request.get('/dashboard_supermarket/getSupermarketCoreIndicators', param)
+    return Request.post('/dashboard_supermarket/getSupermarketCoreIndicators', param)
 }
 const getSuperMarketTrendData = (param) => {
-    return Request.get('/dashboard_supermarket/getSupermarketInfoList', param)
+    return Request.post('/dashboard_supermarket/getSupermarketInfoList', param)
 }
 
 // 用电
 const getElectricityCoreData = (param) => {
-    return Request.get('/electricity/getElectricityCoreIndicators', param)
+    return Request.post('/electricity/getElectricityCoreIndicators', param)
 }
 const getElectricityTrendData = (param) => {
-    return Request.get('/electricity/getElectricityInfoList', param)
+    return Request.post('/electricity/getElectricityInfoList', param)
 }
 const getElectricityCircleInfoList = (param) => {
-    return Request.get('/electricity/getElectricityCircleInfoList', param)
+    return Request.post('/electricity/getElectricityCircleInfoList', param)
 }
 
 // 用水
 const getWaterCoreData = (param) => {
-    return Request.get('/water/getWaterCoreIndicators', param)
+    return Request.post('/water/getWaterCoreIndicators', param)
 }
 const getWaterTrendData = (param) => {
-    return Request.get('/water/getWaterInfoList', param)
+    return Request.post('/water/getWaterInfoList', param)
 }
 const getWaterCircleInfoList = (param) => {
-    return Request.get('/water/getWaterCircleInfoList', param)
+    return Request.post('/water/getWaterCircleInfoList', param)
 }
 
 // 用热
 const getHotCoreData = (param) => {
-    return Request.get('/use_heat/getUseHeatCoreIndicators', param)
+    return Request.post('/use_heat/getUseHeatCoreIndicators', param)
 }
 const getHotTrendData = (param) => {
-    return Request.get('/use_heat/getUseHeatInfoList', param)
+    return Request.post('/use_heat/getUseHeatInfoList', param)
 }
 
 // 用冷
 const getColdCoreData = (param) => {
-    return Request.get('/use_cold/getUseColdCoreIndicators', param)
+    return Request.post('/use_cold/getUseColdCoreIndicators', param)
 }
 const getColdTrendData = (param) => {
-    return Request.get('/use_cold/getUseColdInfoList', param)
+    return Request.post('/use_cold/getUseColdInfoList', param)
 }
 
 // 资产
 const getMoneyCoreData = (param) => {
-    return Request.get('/asset/getAssetCoreIndicators', param)
+    return Request.post('/asset/getAssetCoreIndicators', param)
 }
 const getMoneyLifeData = (param) => {
-    return Request.get('/asset/getAssetLife', param)
+    return Request.post('/asset/getAssetLife', param)
 }
 const getMoneyDistributionData = (param) => {
-    return Request.get('/asset/getInvestmentDistribution', param)
+    return Request.post('/asset/getInvestmentDistribution', param)
 }
 
 

+ 9 - 0
src/api/system/apiLogin.js

@@ -0,0 +1,9 @@
+import Request from "@/utils/request";
+
+const login = (param) => {
+  return Request.post('/system_user/login', param);
+}
+
+export default {
+    login
+}

+ 6 - 0
src/api/work/apiWorkMeeting.js

@@ -9,7 +9,13 @@ const getMeetingCostTrend = (timeRange) => {
     return Request.post('/meeting/getMeetingCostTrend', timeRange)
 }
 
+// 获取会议列表
+const getMeetingRecords = (timeRange) => {
+    return Request.post('/meeting/getConferenceRoomInfo', timeRange)
+}
+
 export default {
     getCoreData,
     getMeetingCostTrend,
+    getMeetingRecords,
 }

+ 10 - 4
src/components/common/query.vue

@@ -14,8 +14,7 @@
         </a-select>
       </a-form-item>
       <a-form-item label="楼层:" class="formItem" v-if="visible.floor">
-        <a-select default-value="0" style="width: 120px" v-model="formData.floorId">
-          <a-select-option value="0"> 全部 </a-select-option>
+        <a-select default-value="1" style="width: 120px" v-model="formData.floorId">
           <a-select-option v-for="item in floorData" :key="item.value" :value="item.value"> {{ item.label }} </a-select-option>
         </a-select>
       </a-form-item>
@@ -50,6 +49,7 @@ export default {
     show: Array,
     reset: Function,
     search: Function,
+    floorOptions: Array,
   },
   emits: ['update:queryData'],
   setup(props, context) {
@@ -109,7 +109,7 @@ export default {
           label: "B1"
         },
         {
-          value: 1,
+          value: '1',
           label: "1F"
         },
         {
@@ -177,8 +177,14 @@ export default {
     }
   },
   mounted() {
+    if (this.floorOptions) {
+      this.floorData = this.floorOptions;
+    }
     if (this.queryData) {
-      this.formData = JSON.parse(JSON.stringify(this.queryData))
+      this.formData = JSON.parse(JSON.stringify(this.queryData));
+      if (this.queryData.floorId == '0') {
+        this.formData.floorId = '1'
+      }
       this.oriQueryData = JSON.parse(JSON.stringify(this.queryData));
     }
   },

+ 4 - 0
src/components/common/timeLine.vue

@@ -22,6 +22,8 @@
             :key="index"
             :class="['timeDuan', 'timeDuan' + index]"
             :ref="'timeDuan' + index"
+            @click="select(item)"
+            style="cursor:pointer"
             :style="{ width: item.width, left: item.positionX }"
           ></div>
         </div>
@@ -42,6 +44,7 @@
 <script>
 export default {
   props: {
+    select: Function,
     startTime: Number,
     endTime: Number,
     huiyiInfo: Array,
@@ -104,6 +107,7 @@ export default {
       // let everyMinuteWidth = (this.$refs.timeLine.clientWidth - 25) / totalTimeMinute;
 
       this.huiyiInfoRender = this.huiyiInfo.map(function (item) {
+        console.log(item)
         // item.name;
         let minute =
           (new Date(item.endTime) - new Date(item.startTime)) / 1000 / 60;

+ 3 - 3
src/components/dashboard/message/dashboardMsgList.vue

@@ -30,19 +30,19 @@ export default {
           <span v-if="item.isRead" style="color: rgba(153,153,153,0.58);">【已阅】</span>
           <span v-else>【待阅】</span>
 
-          <span class="msg-warn" v-if="item.type == 1" style="color: #5495f1"
+          <span class="msg-warn" v-if="item.type == 1" style="color: #2ea8e6"
             >①</span
           >
           <span
             class="msg-warn"
             v-else-if="item.type == 2"
-            style="color: #3bc5b0"
+            style="color: #39bae6"
             >②</span
           >
           <span
             class="msg-warn"
             v-else-if="item.type == 3"
-            style="color: #f1934e"
+            style="color: #7ed4e6"
             >③</span
           >
           <span class="msg-warn" v-else></span>

+ 1 - 0
src/components/dashboard/portrait/supermarket/supermarketTrendChart.vue

@@ -131,6 +131,7 @@ export default {
   props: {
     height: Number,
     data: Array,
+    queryData: Object,
   },
   mounted() {
     this.$nextTick(()=>{

+ 9 - 3
src/components/dashboard/portrait/supermarketPortrait.vue

@@ -4,7 +4,13 @@ import SupermarketTrendChart from "@/components/dashboard/portrait/supermarket/s
 import api from "@/api/dashboard/apiDashboard";
 export default {
   data() {
+    let range = this.$util.dateUtil.getNearlyMonthRange();
     return {
+      queryData: {
+        companyId: '0',
+        deptId: '0',
+        timeRange: range
+      },
       coreData: [
         {
           type: 0,
@@ -53,10 +59,10 @@ export default {
   },
   methods: {
     init() {
-      this.getCoreData()
+      this.getCoreData(this.queryData)
     },
     getCoreData() {
-      api.getSuperMarketCoreData().then(res=>{
+      api.getSuperMarketCoreData(this.queryData).then(res=>{
         this.coreData[0].num = res.list[0].value
         this.coreData[0].historyNum = res.list[0].compare
         this.coreData[1].num = res.list[1].value
@@ -77,7 +83,7 @@ export default {
       <CoreData :data-list="coreData"></CoreData>
     </div>
     <div style="padding: 15px">
-      <SupermarketTrendChart :height="chartHeight"></SupermarketTrendChart>
+      <SupermarketTrendChart :height="chartHeight" :query-data="queryData"></SupermarketTrendChart>
     </div>
   </div>
 </template>

+ 4 - 1
src/components/home/ContainerAside.vue

@@ -28,9 +28,12 @@ export default {
       }
       if (matchRoutes.length===2) {
         this.toRoute(this.menuList[0].router)
-      } else if (matchRoutes.length>2) {
+      } else if (matchRoutes.length===3) {
         let route = this.$route.matched[2];
         this.toRoute(route.path)
+      } else if (matchRoutes.length>3) {
+        let route = this.$route.matched[3];
+        this.toRoute(route.path)
       }
     },
     handleClick(item) {

+ 114 - 22
src/components/home/HomeHeader.vue

@@ -1,5 +1,6 @@
 <script>
 import logoPng from '@/assets/images/logo.png'
+
 export default {
   props: {
     leftVisible: Boolean,
@@ -16,9 +17,35 @@ export default {
     return methods
   },
   data() {
+    let validatePass = (rule, value, callback) => {
+      if (value === '') {
+        callback(new Error('请再次输入密码'));
+      } else if (value !== this.updPwdForm.newpwd) {
+        callback(new Error("两次输入密码不匹配"));
+      } else {
+        callback();
+      }
+    };
     return {
       logoPng,
-      hasMsg: true,
+      hasMsg: false,
+      updPwdVisible: false,
+      confirmLoading: false,
+      updPwdForm: {},
+      updPwdFormRules: {
+        oldpwd: [
+          {required: true, message: '请输入密码', trigger: 'blur'},
+          {required: true, message: '请输入密码', trigger: 'change'},
+        ],
+        newpwd: [
+          {required: true, message: '请输入新密码', trigger: 'change'},
+          {min: 6, message: '长度至少为6位', trigger: 'change'},
+        ],
+        confirmPwd: [
+          {validator: validatePass, trigger: 'change'},
+          {validator: validatePass, trigger: 'blur'},
+        ]
+      }
     }
   },
   mounted() {
@@ -30,6 +57,20 @@ export default {
     },
     handleBuildingChange(val) {
       this.$store.paramStore().buildingId = val;
+    },
+    toUpdPassword() {
+      this.updPwdVisible = true
+    },
+    handleOk() {
+      this.$message.warning('当前暂不允许修改密码');
+    },
+    handleCancel() {
+      this.updPwdVisible = false;
+      this.updPwdForm = {};
+    },
+    logout() {
+      this.$store.userStore().logout();
+      this.$router.push('/login')
     }
   },
 }
@@ -38,10 +79,10 @@ export default {
 <template>
   <div class="header">
     <div v-show="isLogin" class="fold" @click="toggleLeftVisible">
-      <a-icon type="unordered-list" class="icon" />
+      <a-icon type="unordered-list" class="icon"/>
     </div>
     <div class="systemInfo">
-      <a-avatar class="logo" shape="square" :src="logoPng" />
+      <a-avatar class="logo" shape="square" :src="logoPng"/>
       <div class="title">
         智慧运营管理中心
       </div>
@@ -50,7 +91,7 @@ export default {
     <div v-show="isLogin" class="project">
       <a-select class="project-select" default-value="1" @change="handleBuildingChange">
         <template #suffixIcon>
-          <a-icon type="caret-down" style="color: white" />
+          <a-icon type="caret-down" style="color: white"/>
         </template>
 
         <a-select-option value="1">
@@ -60,34 +101,70 @@ export default {
     </div>
 
     <div class="header-btn">
-      <a-icon type="desktop" class="icon" />
-      <a-icon type="mobile" class="icon" />
+      <a-icon type="desktop" class="icon"/>
+      <a-icon type="mobile" class="icon"/>
       <span v-show="isLogin">
-        <a-icon type="question-circle" class="icon" />
-        <a-icon v-if="!hasMsg" type="bell" class="icon" @click="toNotice" />
+        <a-icon type="question-circle" class="icon"/>
+        <a-icon v-if="!hasMsg" type="bell" class="icon" @click="toNotice"/>
         <a-badge v-if="hasMsg" dot :offset="[-15, 15]" @click="toNotice">
-          <a-icon type="bell" class="icon" />
+          <a-icon type="bell" class="icon"/>
         </a-badge>
       </span>
     </div>
 
     <div v-show="isLogin" class="userInfo">
-      <a-avatar class="user-avatar" icon="user" />
-      <a-button class="usernameBtn" type="link" style="color: white;font-size: 18px">
-        <a-icon type="user"></a-icon>
-        <span style="display: inline-block;margin-left: 8px">admin</span>
-      </a-button>
+      <a-avatar class="user-avatar" icon="user"/>
+
+      <a-dropdown>
+        <a-button class="usernameBtn" type="link" style="color: white;font-size: 18px">
+          <a-icon type="user"></a-icon>
+          <span style="display: inline-block;margin-left: 8px"> {{ $store.userStore().userInfo.userName }} </span>
+        </a-button>
+        <a-menu slot="overlay">
+          <a-menu-item>
+            <a href="javascript:;" style="text-align: center" @click="toUpdPassword">修改密码</a>
+          </a-menu-item>
+          <a-menu-item>
+            <a href="javascript:;" style="text-align: center" @click="logout">退出登录</a>
+          </a-menu-item>
+        </a-menu>
+      </a-dropdown>
+
       <!--<div class="userDetail">-->
-        <!--<div class="username">-->
-        <!--  <a-button class="usernameBtn" type="link" style="color: white;font-size: 18px">-->
-        <!--    <div style="padding: 0 5px 0 0">-->
-        <!--      <a-icon type="user"></a-icon>-->
-        <!--      <span style="display: inline-block;margin-left: 8px">admin</span>-->
-        <!--    </div>-->
-        <!--  </a-button>-->
-        <!--</div>-->
+      <!--<div class="username">-->
+      <!--  <a-button class="usernameBtn" type="link" style="color: white;font-size: 18px">-->
+      <!--    <div style="padding: 0 5px 0 0">-->
+      <!--      <a-icon type="user"></a-icon>-->
+      <!--      <span style="display: inline-block;margin-left: 8px">admin</span>-->
+      <!--    </div>-->
+      <!--  </a-button>-->
+      <!--</div>-->
       <!--</div>-->
     </div>
+
+
+    <!--修改密码-->
+    <a-modal
+        title="修改密码"
+        v-if="updPwdVisible"
+        :visible="updPwdVisible"
+        :confirm-loading="confirmLoading"
+        @ok="handleOk"
+        @cancel="handleCancel"
+    >
+      <a-form-model ref="updPwdForm" :model="updPwdForm" :rules="updPwdFormRules" :label-col="{span:4}" :wrapperCol="{span:18}">
+        <a-form-model-item label="原密码" prop="oldpwd">
+          <a-input-password v-model="updPwdForm.oldpwd" placeholder="请输入原密码"/>
+        </a-form-model-item>
+        <a-form-model-item label="新密码" prop="newpwd">
+          <a-input-password v-model="updPwdForm.newpwd" placeholder="请输入新密码"/>
+        </a-form-model-item>
+        <a-form-model-item label="确认密码" prop="confirmPwd">
+          <a-input-password v-model="updPwdForm.confirmPwd" placeholder="再次输入新密码"/>
+        </a-form-model-item>
+      </a-form-model>
+    </a-modal>
+
   </div>
 </template>
 
@@ -99,23 +176,28 @@ export default {
   padding-left: 2px;
   border-bottom: 1px solid @primary-color;
   background: url("@/assets/images/header-bg.png");
+
   > div {
     display: inline-flex;
   }
+
   .fold {
     margin: auto 2px;
   }
+
   .systemInfo {
     vertical-align: top;
     color: white;
     letter-spacing: 4px;
     margin-left: 12px;
+
     .logo {
       vertical-align: top;
       margin-right: 10px;
       margin-top: 15px;
       pointer-events: none;
     }
+
     .title {
       display: inline-block;
       vertical-align: top;
@@ -126,10 +208,12 @@ export default {
       //font-family: PingFangSC-Bold,serif;
     }
   }
+
   .project {
     vertical-align: top;
     margin-top: 15px;
     margin-left: 15px;
+
     .project-select {
       width: 180px;
     }
@@ -138,20 +222,24 @@ export default {
   .userInfo {
     height: 60px;
     padding: 0 15px;
+
     .user-avatar {
       margin-top: 15px;
       margin-right: 3px;
       color: #f56a00;
       background-color: #fde3cf;
     }
+
     .usernameBtn {
       margin-top: 15px !important;
       border-radius: 15px;
     }
+
     .usernameBtn:hover {
       background-color: #3c9cd3;
     }
   }
+
   .header-btn {
     .icon {
       font-size: 20px;
@@ -159,10 +247,12 @@ export default {
       text-align: center;
       padding-top: 13px;
     }
+
     margin-left: auto;
   }
 
 }
+
 .icon {
   font-size: 24px;
   color: white;
@@ -171,9 +261,11 @@ export default {
   cursor: pointer;
   border-radius: 8px;
 }
+
 .icon:hover {
   background-color: #186399;
 }
+
 /deep/ .ant-select-selection {
   background-color: #2f8cc8;
   border: 1px solid #2f8cc8;

+ 4 - 5
src/components/life/restaurant/components/lifeRestDailyMenu.vue

@@ -13,11 +13,10 @@
       <span v-if="text==2">汤</span>
     </template>
     <template #price="text, record">
-      <span v-for="(value,key,index) in text" :key="key" >
-        <span v-if="index!=0">/</span>
-        {{ key+''+value }}元
-
-      </span>
+        <span v-for="(value, key, index) in JSON.parse(text)" :key = index>
+          <span v-if="index!=0">/</span>
+          {{key+value}}
+        </span>元
     </template>
   </a-table>
 </template>

+ 4 - 2
src/components/life/supermarket/components/lifeSupermarketTopTable.vue

@@ -33,8 +33,10 @@ export default {
         },
         {
           title: "销量",
-          dataIndex: "salesVolume",
-          key: "salesVolume",
+          dataIndex: "salesvolume",
+          key: "salesvolume",
+          width: 80,
+          align: 'center'
         },
         {
           title: "单价",

+ 28 - 7
src/components/scene/energy/common/deviceCardAir.vue

@@ -1,18 +1,18 @@
 <template>
-  <div class="deviceCardAir">
+  <div class="deviceCardAir" :style="{backgroundColor: color}">
 
     <div class="deviceCardAir-top">
       <span>#{{ item.id }}</span>
-      <span class="anticon" style="float: right;border-radius: 15px;cursor: pointer;padding: 6px 8px 7px;margin-right: 15px">
+      <span @click="toggle(item)" class="anticon" style="float: right;border-radius: 15px;cursor: pointer;padding: 6px 8px 7px;margin-right: 15px">
         <a-icon type="poweroff"  />
       </span>
     </div>
 
     <div class="deviceCardAir-content">
       <div style="font-size: 18px;width: 20px;margin-left: 20px;margin-top: 12px;display: inline-block">
-        <span v-if="item.mode=='hot'">制热</span>
-        <span v-if="item.mode=='unline'">-</span>
-        <span v-if="item.mode=='cold'">制冷</span>
+        <span v-if="item.online && item.mode=='hot'">制热</span>
+        <span v-if="item.online && item.mode=='cold'">制冷</span>
+        <span v-if="!item.online">-</span>
       </div>
       <div style="display: inline-block;font-size: 25px;vertical-align: top;padding-top: 20px;margin-left: 10%">
         <span>{{ item.tm }}ºC</span>
@@ -34,12 +34,33 @@
 <script>
 export default {
   data() {
-    return {}
+    return {
+      color: '',
+    }
   },
   props: {
     item: Object,
+    toggle: Function
+  },
+  watch: {
+    "item.online": function (val) {
+      if (this.item.online && this.item.mode=='hot') {
+        this.color='#f09b68'
+      } else if (this.item.online && this.item.mode=='cold') {
+        this.color='#2ea8e5';
+      } else {
+        this.color='#bebebe'
+      }
+    },
   },
   mounted() {
+    if (this.item.online && this.item.mode=='hot') {
+      this.color='#f09b68'
+    } else if (this.item.online && this.item.mode=='cold') {
+      this.color='#2ea8e5';
+    } else {
+      this.color='#bebebe'
+    }
   },
   methods: {
 
@@ -68,7 +89,7 @@ export default {
     //padding: 6px;
   }
   .anticon:hover {
-    background-color: #2f8cc8;
+    background-color: rgba(182, 182, 182, 0.7);
   }
 }
 </style>

+ 143 - 45
src/components/scene/energy/sceneEnergyAircondition/airconditioningCard.vue

@@ -2,11 +2,11 @@
   <div class="sceneCard">
 
     <div class="sceneCard-query">
-      <Query :query-data.sync="queryData" :search="search" >
+      <Query :query-data.sync="queryData" :search="search" :reset="reset" >
         <template #extraItem>
 
           <a-form-model-item label="开关:" class="formItem">
-            <a-select default-value="0" style="width: 100px" v-model="queryData.switch">
+            <a-select default-value="0" style="width: 120px" v-model="queryData.switch">
               <a-select-option value="0"> 全部 </a-select-option>
               <a-select-option value="1"> 开 </a-select-option>
               <a-select-option value="2"> 关 </a-select-option>
@@ -14,23 +14,33 @@
           </a-form-model-item>
 
           <a-form-model-item label="模式:" class="formItem">
-            <a-select default-value="0" style="width: 100px" v-model="queryData.switch">
+            <a-select default-value="0" style="width: 120px" v-model="queryData.mode">
               <a-select-option value="0"> 全部 </a-select-option>
-              <a-select-option value="1"> 制冷 </a-select-option>
-              <a-select-option value="2"> 制热 </a-select-option>
+              <a-select-option value="cold"> 制冷 </a-select-option>
+              <a-select-option value="hot"> 制热 </a-select-option>
             </a-select>
           </a-form-model-item>
 
           <a-form-model-item label="温度:" class="formItem">
-            <a-select default-value="0" style="width: 100px" v-model="queryData.switch">
+            <a-select default-value="0" style="width: 120px" v-model="queryData.tm">
               <a-select-option value="0"> 全部 </a-select-option>
+              <a-select-option value="18"> 18°C </a-select-option>
+              <a-select-option value="19"> 19°C </a-select-option>
+              <a-select-option value="20"> 20°C </a-select-option>
+              <a-select-option value="21"> 21°C </a-select-option>
+              <a-select-option value="22"> 22°C </a-select-option>
+              <a-select-option value="23"> 23°C </a-select-option>
+              <a-select-option value="24"> 24°C </a-select-option>
+              <a-select-option value="25"> 25°C </a-select-option>
               <a-select-option value="26"> 26°C </a-select-option>
+              <a-select-option value="27"> 27°C </a-select-option>
+              <a-select-option value="28"> 28°C </a-select-option>
             </a-select>
           </a-form-model-item>
 
-          <a-form-model-item label="设备编号:" class="formItem">
-            <a-input v-model="queryData.deviceNo" placeholder="请输入设备编号" />
-          </a-form-model-item>
+          <!--<a-form-model-item label="设备编号:" class="formItem">-->
+          <!--  <a-input v-model="queryData.deviceNo" placeholder="请输入设备编号" />-->
+          <!--</a-form-model-item>-->
 
         </template>
       </Query>
@@ -39,8 +49,8 @@
     <div class="sceneCard-control">
       <div style="display: inline-block;width: 50%;text-align: left">
         <a-space>
-          <a-button style="font-size: 12px" size="small" ><a-icon type="poweroff" />全开</a-button>
-          <a-button style="font-size: 12px" size="small"><a-icon type="poweroff" />全关</a-button>
+          <a-button style="font-size: 12px" size="small" @click="allPowerOff"><a-icon type="poweroff" />全开</a-button>
+          <a-button style="font-size: 12px" size="small" @click="allPowerOn"><a-icon type="poweroff" />全关</a-button>
           <a-button type="primary" size="small" style="font-size: 12px" >批量执行策略</a-button>
         </a-space>
       </div>
@@ -60,7 +70,10 @@
             按分组
           </a-select-option>
         </a-select>
-        <a-button type="link"><a-icon type="unordered-list" />列表模式</a-button>
+        <a-button type="link" @click="toggleShowCard"><a-icon type="unordered-list" />
+          <span v-if="showCard">列表模式</span>
+          <span v-if="!showCard">卡片模式</span>
+        </a-button>
       </div>
     </div>
 
@@ -68,16 +81,16 @@
       <div class="airContainer-left">
         <div class="deviceFloorIndex">
           <a-input-search placeholder="请输入楼层"></a-input-search>
-          <a-anchor :getContainer="getContainer" :target-offset="100"  style="margin-top: 12px">
+          <a-anchor :getContainer="getContainer" :target-offset="100"  style="margin-top: 12px" @change="floorChange">
             <template v-for="item in floors" >
               <a-anchor-link :href="'#'+item.label" :key="item.value" >
                 <template #title>
-                  <span style="display: inline-block;padding-left: 5px; width: 20px;height: 40px;overflow: hidden">
-                    <div style="position: absolute;top: 15px;left: -2px;width: 4px;height: 4px;border-radius: 2px;background-color: #2EA8E6"></div>
-                    <div style="width: 18px;height: 18px;border-bottom: 1px dashed #2EA8E6;" ></div>
-                    <div style="width: 18px;height: 18px;border-left: 1px dashed #2EA8E6" ></div>
-                  </span>
-                  {{ item.title }}
+                  <!--<span style="display: inline-block;padding-left: 5px; width: 20px;height: 40px;overflow: hidden">-->
+                  <!--  <div style="position: absolute;top: 15px;left: -2px;width: 4px;height: 4px;border-radius: 2px;background-color: #2EA8E6"></div>-->
+                  <!--  <div style="width: 18px;height: 18px;border-bottom: 1px dashed #2EA8E6;" ></div>-->
+                  <!--  <div style="width: 18px;height: 18px;border-left: 1px dashed #2EA8E6" ></div>-->
+                  <!--</span>-->
+                  {{ item.label }}
                 </template>
               </a-anchor-link>
             </template>
@@ -87,14 +100,24 @@
       </div>
       <div class="airContainer-right" ref="airContainerRight">
         <template v-for="item in floors">
-          <div :key="item.value" style="margin-bottom: 15px">
-            <a-divider :id="item.label" style="margin: 0 0 15px;padding: 0" orientation="left" dashed >{{ item.label }}</a-divider>
-            <div style="padding: 0 15px">
-              <a-row :gutter="[30,12]">
-                <a-col v-for="device in item.devices" :key="device.id" :span="6"><DeviceCardAir :item="device" /></a-col>
-              </a-row>
+          <template v-if="showCard">
+            <div :key="item.value" style="margin-bottom: 15px">
+              <a-divider :id="item.label" style="margin: 0 0 15px;padding: 0" orientation="left" dashed >{{ item.label }}</a-divider>
+              <div style="padding: 0 15px">
+                <a-row :gutter="[30,12]">
+                  <a-col v-for="device in item.devices" :key="device.id" :span="6">
+                    <DeviceCardAir :item="device" :toggle="toggleOnline"  />
+                  </a-col>
+                </a-row>
+              </div>
+            </div>
+          </template>
+          <template v-if="!showCard">
+            <div :key="item.value" :id="item.label" v-show="currFloor==item.label">
+              <a-table></a-table>
             </div>
-          </div>
+          </template>
+
         </template>
       </div>
     </div>
@@ -113,9 +136,14 @@ export default {
   },
   data() {
     return {
+      currFloor: '1F',
+      showCard: true,
       queryData: {
-        switch: '0'
+        switch: '0',
+        mode: '0',
+        tm: '0'
       },
+      oriFloors: [],
       floors: [
         {
           label: '1F',
@@ -125,22 +153,26 @@ export default {
               id: '1101-1',
               mode: 'hot',
               tm: '26',
-              wind: '一级'
+              wind: '一级',
+              online: true
             },{
               id: '1101-2',
               mode: 'hot',
               tm: '26',
-              wind: '一级'
+              wind: '一级',
+              online: true
             },{
               id: '1102-1',
               mode: 'hot',
               tm: '26',
-              wind: '一级'
+              wind: '一级',
+              online: true
             },{
               id: '1102-2',
               mode: 'hot',
               tm: '26',
-              wind: '一级'
+              wind: '一级',
+              online: true
             },
           ]
         },
@@ -150,14 +182,16 @@ export default {
           devices: [
             {
               id: '2101-1',
-              mode: 'hot',
+              mode: 'cold',
               tm: '26',
-              wind: '一级'
+              wind: '一级',
+              online: true
             },{
               id: '2101-2',
               mode: 'hot',
               tm: '26',
-              wind: '一级'
+              wind: '一级',
+              online: true
             }
           ]
         },
@@ -169,12 +203,14 @@ export default {
               id: '3101-1',
               mode: 'hot',
               tm: '26',
-              wind: '一级'
+              wind: '一级',
+              online: true
             },{
               id: '3101-2',
               mode: 'hot',
               tm: '26',
-              wind: '一级'
+              wind: '一级',
+              online: true
             }
           ]
         },
@@ -186,12 +222,14 @@ export default {
               id: '3101-1',
               mode: 'hot',
               tm: '26',
-              wind: '一级'
+              wind: '一级',
+              online: true
             },{
               id: '3101-2',
               mode: 'hot',
               tm: '26',
-              wind: '一级'
+              wind: '一级',
+              online: true
             }
           ]
         },
@@ -203,12 +241,14 @@ export default {
               id: '3101-1',
               mode: 'hot',
               tm: '26',
-              wind: '一级'
+              wind: '一级',
+              online: true,
             },{
               id: '3101-2',
               mode: 'hot',
               tm: '26',
-              wind: '一级'
+              wind: '一级',
+              online: true
             }
           ]
         },
@@ -220,12 +260,14 @@ export default {
               id: '3101-1',
               mode: 'hot',
               tm: '26',
-              wind: '一级'
+              wind: '一级',
+              online: true
             },{
               id: '3101-2',
               mode: 'hot',
               tm: '26',
-              wind: '一级'
+              wind: '一级',
+              online: true
             }
           ]
         },
@@ -237,12 +279,14 @@ export default {
               id: '3101-1',
               mode: 'hot',
               tm: '26',
-              wind: '一级'
+              wind: '一级',
+              online: true
             },{
               id: '3101-2',
               mode: 'hot',
               tm: '26',
-              wind: '一级'
+              wind: '一级',
+              online: true
             }
           ]
         },
@@ -250,13 +294,67 @@ export default {
     }
   },
   mounted() {
+    this.oriFloors = JSON.parse(JSON.stringify(this.floors));
   },
   methods: {
+    reset() {
+      this.floors = JSON.parse(JSON.stringify(this.oriFloors));
+    },
     search() {
-
+      let objarr = JSON.parse(JSON.stringify(this.oriFloors));
+      let app = this
+      objarr.forEach(item=>{
+        if (item.devices) {
+          item.devices = item.devices.filter(item=>{
+            if (!app.queryData.switch || app.queryData.switch=='0') {
+            } else {
+              return app.queryData.switch==item.online
+            }
+            if (!app.queryData.mode || app.queryData.mode=='0') {
+            } else {
+              return app.queryData.mode==item.mode
+            }
+            if (!app.queryData.tm || app.queryData.tm=='0') {
+            } else {
+              return app.queryData.tm==item.tm
+            }
+            return true;
+          })
+        }
+      })
+      this.floors = objarr
+    },
+    toggleOnline(device) {
+      device.online=!device.online;
+    },
+    floorChange(val) {
+      let obj = val.replace('#','')
+      this.currFloor = obj;
+      //console.log(this.currFloor)
     },
     getContainer() {
       return this.$refs.airContainerRight
+    },
+    toggleShowCard() {
+      this.showCard = !this.showCard;
+    },
+    allPowerOn() {
+      this.floors.forEach(item=>{
+        if (item.devices) {
+          item.devices.forEach(i=>{
+            i.online = false
+          })
+        }
+      })
+    },
+    allPowerOff() {
+      this.floors.forEach(item=>{
+        if (item.devices) {
+          item.devices.forEach(i=>{
+            i.online = true
+          })
+        }
+      })
     }
   }
 }

+ 154 - 1
src/components/scene/energy/sceneEnergyLight.vue

@@ -1,11 +1,164 @@
 <template>
+  <div class="container">
+    <div class="sceneEnergy-top">
+      <div class="dashboardPortrait-select">
+        <a-checkable-tag v-model="tagCheck.air" color="white" class="dashboardPortrait-select-tag"
+                         @change="handleTagSelect('air')">
+          <span class="dashboardPortrait-select-text">空调总览</span>
+        </a-checkable-tag>
+        <a-checkable-tag v-model="tagCheck.methods" color="white" class="dashboardPortrait-select-tag"
+                         @change="handleTagSelect('methods')">
+          <span class="dashboardPortrait-select-text">智能策略</span>
+        </a-checkable-tag>
+      </div>
+    </div>
 
+    <div class="dashboardPortrait-body">
+      <AirconditioningCard v-if="currCheck == 'air'" />
+    </div>
+
+  </div>
 </template>
 
 <script>
-export default {}
+import timeRange from "@/components/common/timeRange.vue";
+import AirconditioningCard from "@/components/scene/energy/sceneEnergyAircondition/airconditioningCard.vue";
+
+export default {
+  components: {
+    AirconditioningCard,
+    timeRange,
+  },
+  data() {
+    return {
+      currCheck: '',
+      tagCheck: {
+        air: false,
+        methods: false,
+      },
+    };
+  },
+  mounted() {
+    this.handleTagSelect('air');
+  },
+  methods: {
+    handleTagSelect(item) {
+      for (const key in this.tagCheck) {
+        this.tagCheck[key] = false;
+      }
+      this.currCheck = item;
+      this.tagCheck[item] = true;
+    },
+
+  }
+}
 </script>
 
 <style lang="less" scoped>
+.container {
+  width: 100%;
+  height: 100%;
+  background-color: #ffffff;
+  border-radius: 4px;
+  padding: 15px;
+
+  .ant-tabs {
+    width: 100%;
+    height: 100%;
+
+    /deep/ .ant-tabs-content {
+      width: 100%;
+      height: calc(100% - 36px);
+    }
+
+    /deep/ .ant-tabs-bar {
+      border-bottom: 0px solid transparent;
+      margin-bottom: 5px;
+
+      .ant-tabs-tab {
+        font-size: 16px;
+        font-weight: bold;
+        font-family: SourceHanSansSC;
+        padding: 4px 4px;
+        margin: 0 32px 0 0;
+
+        &.ant-tabs-tab-active {
+          color: #156de4;
+        }
+      }
+
+      .ant-tabs-ink-bar {
+        width: 72px !important;
+        background-color: #156de4;
+      }
+    }
+  }
+
+  .search_container {
+    border-radius: 4px;
+    background: #cecece29;
+    margin-bottom: 5px;
+
+    .ant-advanced-search-form {
+      padding: 8px;
+      background: #fbfbfb;
+      // border: 1px solid #d9d9d9;
+      // border-radius: 6px
+    }
+
+    .ant-advanced-search-form .ant-form-item {
+      display: flex;
+      margin-bottom: 0px;
+
+      /deep/ .ant-form-item-label {
+        min-width: 60px;
+      }
+    }
+
+    .ant-advanced-search-form .ant-form-item-control-wrapper {
+      flex: 1
+    }
+
+    .ant-select {
+      width: 180px;
+    }
+  }
+
+  .aircon_resutlt_container {
+    height: calc(100% - 103px);
+
+    .ant-layout-sider {
+      background-color: #f5f5f5;
+      padding: 4px 4px;
+
+      // .list_container {}
+
+      .ant-list-item-meta-title {
+        text-indent: 40px;
+      }
+    }
+
+    .ant-layout {
+      height: 100%;
+      background-color: transparent;
+
+      .ant-layout-content {
+        overflow: hidden;
+      }
+    }
+  }
+
+  .footer {
+    height: 60px;
+    line-height: 60px;
+    margin-right: 50px;
+    padding-top: 14px;
+
+    .ant-pagination {
+      float: right;
+    }
+  }
+
 
+}
 </style>

+ 154 - 1
src/components/scene/energy/sceneEnergyWater.vue

@@ -1,11 +1,164 @@
 <template>
+  <div class="container">
+    <div class="sceneEnergy-top">
+      <div class="dashboardPortrait-select">
+        <a-checkable-tag v-model="tagCheck.air" color="white" class="dashboardPortrait-select-tag"
+                         @change="handleTagSelect('air')">
+          <span class="dashboardPortrait-select-text">空调总览</span>
+        </a-checkable-tag>
+        <a-checkable-tag v-model="tagCheck.methods" color="white" class="dashboardPortrait-select-tag"
+                         @change="handleTagSelect('methods')">
+          <span class="dashboardPortrait-select-text">智能策略</span>
+        </a-checkable-tag>
+      </div>
+    </div>
 
+    <div class="dashboardPortrait-body">
+      <AirconditioningCard v-if="currCheck == 'air'" />
+    </div>
+
+  </div>
 </template>
 
 <script>
-export default {}
+import timeRange from "@/components/common/timeRange.vue";
+import AirconditioningCard from "@/components/scene/energy/sceneEnergyAircondition/airconditioningCard.vue";
+
+export default {
+  components: {
+    AirconditioningCard,
+    timeRange,
+  },
+  data() {
+    return {
+      currCheck: '',
+      tagCheck: {
+        air: false,
+        methods: false,
+      },
+    };
+  },
+  mounted() {
+    this.handleTagSelect('air');
+  },
+  methods: {
+    handleTagSelect(item) {
+      for (const key in this.tagCheck) {
+        this.tagCheck[key] = false;
+      }
+      this.currCheck = item;
+      this.tagCheck[item] = true;
+    },
+
+  }
+}
 </script>
 
 <style lang="less" scoped>
+.container {
+  width: 100%;
+  height: 100%;
+  background-color: #ffffff;
+  border-radius: 4px;
+  padding: 15px;
+
+  .ant-tabs {
+    width: 100%;
+    height: 100%;
+
+    /deep/ .ant-tabs-content {
+      width: 100%;
+      height: calc(100% - 36px);
+    }
+
+    /deep/ .ant-tabs-bar {
+      border-bottom: 0px solid transparent;
+      margin-bottom: 5px;
+
+      .ant-tabs-tab {
+        font-size: 16px;
+        font-weight: bold;
+        font-family: SourceHanSansSC;
+        padding: 4px 4px;
+        margin: 0 32px 0 0;
+
+        &.ant-tabs-tab-active {
+          color: #156de4;
+        }
+      }
+
+      .ant-tabs-ink-bar {
+        width: 72px !important;
+        background-color: #156de4;
+      }
+    }
+  }
+
+  .search_container {
+    border-radius: 4px;
+    background: #cecece29;
+    margin-bottom: 5px;
+
+    .ant-advanced-search-form {
+      padding: 8px;
+      background: #fbfbfb;
+      // border: 1px solid #d9d9d9;
+      // border-radius: 6px
+    }
+
+    .ant-advanced-search-form .ant-form-item {
+      display: flex;
+      margin-bottom: 0px;
+
+      /deep/ .ant-form-item-label {
+        min-width: 60px;
+      }
+    }
+
+    .ant-advanced-search-form .ant-form-item-control-wrapper {
+      flex: 1
+    }
+
+    .ant-select {
+      width: 180px;
+    }
+  }
+
+  .aircon_resutlt_container {
+    height: calc(100% - 103px);
+
+    .ant-layout-sider {
+      background-color: #f5f5f5;
+      padding: 4px 4px;
+
+      // .list_container {}
+
+      .ant-list-item-meta-title {
+        text-indent: 40px;
+      }
+    }
+
+    .ant-layout {
+      height: 100%;
+      background-color: transparent;
+
+      .ant-layout-content {
+        overflow: hidden;
+      }
+    }
+  }
+
+  .footer {
+    height: 60px;
+    line-height: 60px;
+    margin-right: 50px;
+    padding-top: 14px;
+
+    .ant-pagination {
+      float: right;
+    }
+  }
+
 
+}
 </style>

+ 85 - 8
src/components/scene/meeting/config/meetingRoomConfig.vue

@@ -22,7 +22,7 @@
             <span class="ioc-form-label">类别</span>
           </template>
           <a-select v-model="basicInfo.type" style="width: 200px;" >
-            <a-select-option v-for="(val, key) in typeOptions" :value="key">{{ val }}</a-select-option>
+            <a-select-option v-for="(val, key) in typeOptions" :key="key" :value="key">{{ val }}</a-select-option>
           </a-select>
         </a-form-model-item>
         <a-form-model-item prop="floor">
@@ -30,7 +30,7 @@
             <span class="ioc-form-label">楼层</span>
           </template>
           <a-select v-model="basicInfo.floor" style="width: 200px;" placeholder="请选择楼层">
-            <a-select-option v-for="(val, key) in floorOptions" :value="key">{{ val }}</a-select-option>
+            <a-select-option v-for="(val, key) in floorOptions" :key="key" :value="key">{{ val }}</a-select-option>
           </a-select>
         </a-form-model-item>
         <a-form-model-item prop="room">
@@ -38,7 +38,7 @@
             <span class="ioc-form-label">房间</span>
           </template>
           <a-select v-model="basicInfo.room" style="width: 200px;" placeholder="请选择房间">
-            <a-select-option v-for="(val, key) in roomOptions" :value="key">{{ val }}</a-select-option>
+            <a-select-option v-for="(val, key) in roomOptions" :key="key" :value="key">{{ val }}</a-select-option>
           </a-select>
         </a-form-model-item>
         <a-form-model-item prop="weight">
@@ -68,7 +68,7 @@
 
     <div class="meetingRoomConfig-devices" v-if="currStep===1">
       <div style="padding: 15px 0 0;margin: 12px auto 0;background-color: #fafafa">
-        <a-descriptions :column="5" style="margin: 0 30px">
+        <a-descriptions :column="3" style="margin: 0 30px">
           <a-descriptions-item label="场景名称">{{basicInfo.name}}</a-descriptions-item>
           <a-descriptions-item label="类别">{{ typeOptions[basicInfo.type] }}</a-descriptions-item>
           <a-descriptions-item label="楼层">{{ floorOptions[basicInfo.floor] }}</a-descriptions-item>
@@ -78,14 +78,14 @@
       </div>
 
       <div>
-        <MeetingRoomDeviceTable />
+        <MeetingRoomDeviceTable :device-option="deviceOption" :data.sync="deviceTableData" />
       </div>
     </div>
 
     <div class="meetingRoomConfig-test" v-if="currStep===2">
       <div style="padding-left: 15px;color: #333333;font-size: 16px;margin-top: 18px">基本信息</div>
       <div style="padding: 15px 0 0;margin: 12px auto 0;background-color: #fafafa">
-        <a-descriptions :column="5" style="margin: 0 30px">
+        <a-descriptions :column="3" style="margin: 0 30px">
           <a-descriptions-item label="场景名称">{{basicInfo.name}}</a-descriptions-item>
           <a-descriptions-item label="类别">{{ typeOptions[basicInfo.type] }}</a-descriptions-item>
           <a-descriptions-item label="楼层">{{ floorOptions[basicInfo.floor] }}</a-descriptions-item>
@@ -94,6 +94,39 @@
         </a-descriptions>
       </div>
       <div style="padding-left: 15px;color: #333333;font-size: 16px;margin-top: 18px">策略信息</div>
+      <div style="padding: 8px 20px;max-height: 300px;overflow-y: auto">
+        <div v-for="(item, index) in deviceTableData" :key="index" style="margin: 8px 0; background-color: rgba(73,146,215,0.1);border-radius: 8px;padding: 15px 8px 0">
+          <!--<span style="margin-left: 20px">所属平台:{{item.platform}}</span>-->
+          <!--<span style="margin-left: 8px">设备:{{ item.deviceType }}</span>-->
+          <!--<div >{{item}}</div>-->
+          <a-descriptions :column="3" style="margin: 0 30px">
+            <a-descriptions-item label="序号">{{index}}</a-descriptions-item>
+            <a-descriptions-item label="所属平台">{{item.platform}}</a-descriptions-item>
+            <a-descriptions-item label="设备">{{ item.deviceLabel }}</a-descriptions-item>
+            <a-descriptions-item label="策略" :span="3">
+              <div style="color: #888888">
+                <template v-if="item.deviceType=='door'">
+                  <span v-if="item.deviceForm.requireSign">需要签到 &nbsp; </span>
+                  <span>
+                  <span v-if="item.deviceForm.allowEnter=='1'">参会人员可以进入 &nbsp;<nbsp/></span>
+                  <span v-else-if="item.deviceForm.allowEnter=='2'">邀请人可以进入 &nbsp;<nbsp/></span>
+                  <span v-else>任何人可以进入</span>
+                </span>
+                </template>
+                <template v-if="item.deviceType=='air'">
+                  <span v-if="item.deviceForm.openAir">会议期间打开空调 &nbsp;<nbsp/></span>
+                  <span v-if="item.deviceForm.airTm && item.deviceForm.airTm!='' ">温度设置为{{item.deviceForm.airTm}}度 &nbsp;<nbsp/> </span>
+                  <span v-if="item.deviceForm.concatSensor ">  关联人体传感器 &nbsp;<nbsp/> </span>
+                </template>
+                <template v-if="item.deviceType=='light'">
+                  <span v-if="item.deviceForm.openLight">会议期间打开灯光 &nbsp; </span>
+                  <span v-if="item.deviceForm.concatSensor ">  关联人体传感器 &nbsp; </span>
+                </template>
+              </div>
+            </a-descriptions-item>
+          </a-descriptions>
+        </div>
+      </div>
     </div>
 
     <div style="text-align: center;margin-top: 20px;margin-bottom: 15px" >
@@ -101,9 +134,9 @@
       <div v-show="currStep>0" style="display: inline-block;width: 30px"></div>
       <a-button v-if="currStep<2" @click="next" style="margin: 0 auto; width: 120px;background-color: #2EA8E6;color: #ffffff">下一步</a-button>
       <div v-if="currStep==2" style="display: inline-block">
-        <a-button @click="test" style="margin: 0 auto; width: 120px;">测试</a-button>
+        <a-button @click="test" style="margin: 0 auto; width: 120px;" :loading="testLoading">测试</a-button>
         <div style="display: inline-block;width: 30px"></div>
-        <a-button @click="finish" style="margin: 0 auto; width: 120px;background-color: #2EA8E6;color: #ffffff">完成创建</a-button>
+        <a-button @click="finish" style="margin: 0 auto; width: 120px;background-color: #2EA8E6;color: #ffffff" :loading="finishLoading">完成创建</a-button>
       </div>
     </div>
   </div>
@@ -117,9 +150,13 @@ export default {
     Card,
     MeetingRoomDeviceTable
   },
+  props: {
+    close: Function
+  },
   data() {
     return {
       currStep: 0,
+      deviceTableData: [],
       typeOptions: {
         "1": '智慧会议室',
         "2": '普通会议室',
@@ -134,6 +171,23 @@ export default {
         "702": "702室",
         "703": "703室",
       },
+      deviceOption: {
+        "1": {
+          label: '门禁设备',
+          deviceType: 'door',
+          system: '闸机系统'
+        },
+        "2": {
+          label: '空调',
+          deviceType: 'air',
+          system: '能源系统'
+        },
+        "3": {
+          label: '灯光',
+          deviceType: 'light',
+          system: '能源系统'
+        },
+      },
       basicInfo: {
         type: '1',
         weight: '1'
@@ -157,6 +211,8 @@ export default {
         ],
       },
       deviceConfigs: [],
+      testLoading: false,
+      finishLoading: false,
     }
   },
   mounted() {
@@ -175,6 +231,27 @@ export default {
       } else {
         this.currStep = this.currStep+1;
       }
+    },
+    test() {
+      this.testLoading = true;
+      let app = this;
+      setTimeout(function () {
+        app.testLoading = false;
+        app.$notification.success({
+          message: '测试成功',
+        });
+      }, 5000)
+    },
+    finish() {
+      this.finishLoading = true;
+      let app = this;
+      setTimeout(function () {
+        app.finishLoading = false;
+        app.$notification.success({
+          message: '配置策略成功',
+        });
+        app.close()
+      }, 2000)
     }
   }
 }

+ 130 - 31
src/components/scene/meeting/config/meetingRoomDeviceTable.vue

@@ -1,31 +1,96 @@
 <template>
   <div class="meetingRoom">
     <div style="padding: 6px">
-      <a-button type="primary" style="height: 25px;font-size: 13px" @click="addOperation">新增</a-button>
-      <a-button type="primary" style="height: 25px;font-size: 13px">批量删除</a-button>
+      <a-button type="link" style="font-size: 13px;padding: 0 15px;margin: 5px 0;border: 1px solid #2EA8E6;color: #2EA8E6" @click="addOperation" icon="plus-square">
+        添加设备
+      </a-button>
+      <!--<a-button type="primary" style="height: 25px;font-size: 13px" @click="batchDelete">批量删除</a-button>-->
     </div>
 
     <div style="padding: 6px">
       <span style="font-size: 12px;color: #CDCDCD">关联系统会顺序触发,请明确场景中关联设备的执行顺序,再添加.</span>
     </div>
+    <!--:row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"-->
     <a-table :rowKey="(record, index) => index" ref="table"
-             :row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
+
              :columns="columns"
              :show-header="true"
              :data-source="tableData"
              :pagination="false"
+             :scroll="{ y: 300 }"
     >
       <template #device="text,record">
         <a-select style="width: 200px" v-model="record.device" @select="val=>handleDeviceChange(val, record)">
-          <a-select-option v-for="(val, key) in deviceOption" :value="key">{{val.label}}</a-select-option>
+          <a-select-option v-for="(val, key) in deviceOption" :value="key">{{ val.label }}</a-select-option>
         </a-select>
       </template>
       <template #status="text,record">
-        <a-switch v-model="record.status" />
+        <a-switch v-model="record.status"/>
       </template>
       <template #operation="text,record">
-        <a-button type="link" :disabled="!record.status">编辑</a-button>
-        <a-button type="link"  @click="delOperation(record)">删除</a-button>
+        <!--<a-button type="link" :disabled="!record.status">编辑</a-button>-->
+        <a-button type="link" @click="delOperation(record)">删除</a-button>
+      </template>
+      <template #platform="text,record">
+        <span v-if="deviceOption[record.device]">{{ deviceOption[record.device].system }}</span>
+        <span v-else></span>
+      </template>
+      <template #expandedRowRender="record">
+        <div style="width: 100%;height: 100%">
+          <a-form-model :model="record.deviceForm" layout="inline">
+            <template v-if="record.deviceType=='door'">
+
+              <a-form-model-item label="是否需要签到" style="margin-left: 10px">
+                <a-switch v-model="record.deviceForm.requireSign" />
+              </a-form-model-item>
+
+              <a-form-model-item label="可通过人员" style="margin-left: 30%">
+                <a-radio-group v-model="record.deviceForm.allowEnter" >
+                  <a-radio  v-for="item in doorOptions.allowOptions" :value="item.value">{{ item.label }}</a-radio>
+                </a-radio-group>
+              </a-form-model-item>
+
+              <a-alert style="margin-top: 10px" message="到预定时间后,方可进入会议室." banner />
+            </template>
+
+            <template v-if="record.deviceType=='air'">
+              <a-form-model-item label="规定时间打开空调" >
+                <a-switch v-model="record.deviceForm.openAir" />
+              </a-form-model-item>
+              <a-form-model-item label="空调温度" v-if="record.deviceForm.openAir">
+                <a-select v-model="record.deviceForm.airTm" style="width: 100px">
+                  <a-select-option value="18">18ºC</a-select-option>
+                  <a-select-option value="19">19ºC</a-select-option>
+                  <a-select-option value="20">20ºC</a-select-option>
+                  <a-select-option value="21">21ºC</a-select-option>
+                  <a-select-option value="22">22ºC</a-select-option>
+                  <a-select-option value="23">23ºC</a-select-option>
+                  <a-select-option value="24">24ºC</a-select-option>
+                  <a-select-option value="25">25ºC</a-select-option>
+                  <a-select-option value="26">26ºC</a-select-option>
+                  <a-select-option value="27">27ºC</a-select-option>
+                  <a-select-option value="28">28ºC</a-select-option>
+                  <a-select-option value="29">29ºC</a-select-option>
+                  <a-select-option value="30">30ºC</a-select-option>
+                </a-select>
+              </a-form-model-item>
+              <a-form-model-item label="关联人体传感器"  style="margin-left: 25%">
+                <a-switch v-model="record.deviceForm.concatSensor" />
+              </a-form-model-item>
+              <a-alert style="margin-top: 10px" message="夏季空调最高温度为 26 ºC;冬季室温最低温度为 20 ºC。" banner />
+            </template>
+
+            <template v-if="record.deviceType=='light'">
+              <a-form-model-item label="规定时间打开灯光" >
+                <a-switch v-model="record.deviceForm.openLight" />
+              </a-form-model-item>
+              <a-form-model-item label="关联人体传感器"  style="margin-left: 25%">
+                <a-switch v-model="record.deviceForm.concatSensor" />
+              </a-form-model-item>
+              <a-alert style="margin-top: 10px" message="会议结束 5 分钟后自动关闭灯光" banner />
+            </template>
+          </a-form-model>
+        </div>
       </template>
     </a-table>
   </div>
@@ -35,6 +100,20 @@
 export default {
   data() {
     return {
+      doorOptions: {
+        allowOptions: [
+          {
+            label: '任何人',
+            value: '1'
+          },{
+            label: '邀请人',
+            value: '2'
+          },{
+            label: '参会人员',
+            value: '3'
+          },
+        ]
+      },
       selectedRowKeys: [],
       columns: [
         {
@@ -43,7 +122,7 @@ export default {
           key: 'index',
           width: 60,
           align: 'center',
-          customRender: (text,record,index) => `${index+1}`,
+          customRender: (text, record, index) => `${index + 1}`,
         },
         {
           title: '设备',
@@ -51,19 +130,20 @@ export default {
           key: 'device',
           align: 'center',
           width: 220,
-          scopedSlots: { customRender: 'device' },
+          scopedSlots: {customRender: 'device'},
         },
         {
           title: '所属系统平台',
           dataIndex: 'platform',
           key: 'platform',
-          align: 'center'
+          align: 'center',
+          scopedSlots: {customRender: 'platform'},
         },
         {
           title: '状态',
           dataIndex: 'status',
           key: 'status',
-          scopedSlots: { customRender: 'status' },
+          scopedSlots: {customRender: 'status'},
           width: 100,
           align: 'center'
         },
@@ -73,45 +153,64 @@ export default {
           key: 'operation',
           width: 200,
           align: 'center',
-          scopedSlots: { customRender: 'operation' },
+          scopedSlots: {customRender: 'operation'},
         },
       ],
-      tableData: [
-        {
-          device: '1',
-          platform: '闸机系统'
-        }
-      ],
-      deviceOption: {
-        "1": {
-          label: '门禁设备',
-          system: '闸机系统'
-        },
-        "2": {
-          label: '空调',
-          system: '能源系统'
-        },
-      },
+      tableData: [],
+
     }
   },
+  props: {
+    data: Array,
+    deviceOption: Object
+  },
   mounted() {
+    console.log(this.data)
+    this.tableData = JSON.parse(JSON.stringify(this.data));
+  },
+  emits: ['update:data'],
+  setup(props, context) {
+    const methods = {
+      updateData(val) {
+        context.emit('update:data', val)
+      },
+    }
+    return methods
+  },
+  watch: {
+    "tableData": {
+      handler: function (val) {
+        this.updateData(val);
+      },
+      deep: true
+    }
   },
   methods: {
     onSelectChange(val) {
-
+      this.selectedRowKeys = val
     },
     addOperation() {
-      this.tableData.push({});
+      this.tableData.push({deviceForm: {}});
+    },
+    batchDelete() {
+      this.selectedRowKeys.forEach(i=>{
+        if (i>=0) {
+          this.tableData.splice(i, 1);
+          this.selectedRowKeys = [];
+        }
+      })
     },
     delOperation(record) {
       let index = this.tableData.indexOf(record);
-      if (index && index>-1) {
+      if (index && index > -1) {
         this.tableData.splice(index, 1)
       }
     },
     handleDeviceChange(val, record) {
       if (val) {
         record.platform = this.deviceOption[val].system
+        record.deviceType = this.deviceOption[val].deviceType
+        record.deviceLabel = this.deviceOption[val].label
       }
     }
   }

+ 1 - 1
src/components/scene/meeting/config/meetingRoomItem.vue

@@ -43,7 +43,7 @@
     <a-modal v-if="configVisible" v-model="configVisible" title="配置策略" :width="1000" style="height: 650px;overflow-y: auto"
              :footer="null"
     >
-      <MeetingRoomConfig  />
+      <MeetingRoomConfig :close="()=>{this.configVisible=false}" />
     </a-modal>
 
 

+ 7 - 4
src/components/security/alarm/securityAlarmGrid.vue

@@ -8,8 +8,10 @@
               <SecurityDeviceSelect></SecurityDeviceSelect>
             </div>
           </a-col>
-          <a-col :span="20">
-            <div></div>
+          <a-col :span="20" style="height: 90%">
+            <div style="height: 100%">
+              <HkwsCamera />
+            </div>
           </a-col>
         </a-row>
       </div>
@@ -18,12 +20,13 @@
 </template>
 
 <script>
-import Card from "@/components/common/card.vue";
+import HkwsCamera from "@/components/security/camera/hkwsCamera.vue";
 import SecurityDeviceSelect from "@/components/security/common/securityDeviceSelect.vue";
 
 export default {
   components: {
-    SecurityDeviceSelect
+    SecurityDeviceSelect,
+    HkwsCamera
   }
 }
 </script>

+ 2 - 2
src/components/security/alarm/securityAlarmInfo.vue

@@ -1,10 +1,10 @@
 <template>
   <div class="securityAlarmInfo">
     <a-row style="height: 100%">
-      <a-col :span="6" style="height: 100%">
+      <a-col :span="4" style="height: 100%">
         <security-device-select/>
       </a-col>
-      <a-col :span="18" style="height: 100%;padding: 15px">
+      <a-col :span="20" style="height: 100%;padding: 15px">
         <div class="securityAlarmInfo-query">
           <Query :show="['time']" :query-data.sync="formData" :search="search">
             <template #extraItem>

+ 19 - 7
src/components/security/camera/hkwsCamera.vue

@@ -1,5 +1,5 @@
 <template>
-  <hik-comp class="hkws-camera" :playConfig="playConfig"
+  <hik-comp ref="hkws" class="hkws-camera" :playConfig="playConfig"
             :nameId="jkInfo.nameId" :cameraIndexCode="jkInfo.cameraIndexCode" />
 
 </template>
@@ -10,20 +10,20 @@ export default {
     return {
       jkInfo: {
         nameId: "playWnd1", // nameId 具有唯一性,否则无效,如果有多个,一定不能重复
-        cameraIndexCode: "xxxx",  // 监控点编号
+        cameraIndexCode: "4d43345c64744929b68e6a76678d60b1",  // 监控点编号
       }
     }
   },
   computed: {
     playConfig: function () {
       return {
-        appkey: "",
-        secret: "",
-        ip: "",
+        appkey: "23546469",
+        secret: "Mgv0uhy7D2rnbKb6k17W",
+        ip: "182.92.242.51",
         playMode: 0,
         port: 443,
-        snapDir: "D:\\SnapDir",
-        videoDir: "D:\\VideoDir",
+        snapDir: "/SnapDir",
+        videoDir: "/VideoDir",
         layout: "1x1",
         enableHTTPS: 1,
         encryptedFields: 'secret',
@@ -33,6 +33,18 @@ export default {
         toolBarButtonIDs: "4098",
       }
     }
+  },
+  mounted() {
+    console.log(this.$refs.hkws)
+
+  },
+  beforeDestroy() {
+    this.$refs.hkws.oWebControl.JS_StopService('window')
+        .then(() => {})
+        .catch((err) => console.log(err))
+    this.$refs.hkws.oWebControl.JS_DestroyWnd()
+        .then(() => {})
+        .catch((err) => console.log(err))
   }
 }
 </script>

+ 1 - 8
src/components/security/common/securityDeviceSelect.vue

@@ -50,14 +50,7 @@ export default {
               slots: {
                 icon: 'camera',
               },
-            },
-            {
-              title: '水浸设备1',
-              key: '0-0-1',
-              slots: {
-                icon: 'water',
-              },
-            },
+            }
           ],
         },
       ],

+ 2 - 2
src/components/security/device/securityDevice.vue

@@ -1,10 +1,10 @@
 <template>
   <div class="securityDevice">
     <a-row style="height: 100%">
-      <a-col :span="6" style="height: 100%">
+      <a-col :span="4" style="height: 100%">
         <SecurityDeviceSelect />
       </a-col>
-      <a-col :span="18" style="height: 100%">
+      <a-col :span="20" style="height: 100%">
         <div class="securityDevice-content">
           <Card title="可交互设备">
             <!--<a-divider style="padding: 0;margin: 0;"/>-->

+ 129 - 389
src/components/work/meeting/workMeeting.vue

@@ -5,6 +5,7 @@
         :show="['company', 'floor', 'time']"
         :query-data.sync="queryData"
         :reset="reset"
+        :floor-options="floorOptions"
         :search="search"
       ></query>
       <card :title="'核心指标'">
@@ -27,12 +28,13 @@
                   >
                     <!-- style="width: 100px" -->
                     <!-- :open-keys.sync="openKeys" -->
-                    <a-menu-item
-                      v-for="(item, index) in tabsArr"
-                      :key="index + ''"
-                    >
-                      {{ item.title }}
-                    </a-menu-item>
+                    <template v-for="(value,key) in roomInfo">
+                      <a-menu-item v-for="item in value" :key="item.value" v-if="key==queryData.floorId"
+                      >
+                        {{ item.value }}
+                      </a-menu-item>
+                    </template>
+
                   </a-menu>
                 </a-col>
                 <a-col :span="3">
@@ -43,12 +45,13 @@
                 </a-col>
                 <a-col :span="19">
                   <timeline
-                    v-for="(item, index) in tabsItemArr"
+                    v-for="(value, key, index) in meetingInfo"
                     :key="index"
+                    :select="currCheckMeeting"
                     v-bind="{
                       startTime: 8,
-                      endTime: 17,
-                      huiyiInfo: item.shiyong,
+                      endTime: 18,
+                      huiyiInfo: value,
                     }"
                     :style="{ height: '60px' }"
                   ></timeline>
@@ -63,7 +66,7 @@
                       >
                     </template>
                     <div class="workMeeting-left-detail-content">
-                      智慧楼宇产品会议
+                      {{ currMeeting.subject }}
                     </div>
                   </a-descriptions-item>
                   <a-descriptions-item>
@@ -72,8 +75,8 @@
                         >会议配置:</span
                       >
                     </template>
-                    <div class="workMeeting-left-detail-content">
-                      智慧会议场景配置1
+                    <div class="workMeeting-left-detail-content" v-if="currMeeting.subject">
+                      智慧场景策略配置
                     </div>
                   </a-descriptions-item>
                   <a-descriptions-item>
@@ -83,7 +86,7 @@
                       >
                     </template>
                     <div class="workMeeting-left-detail-content">
-                      北京电信规划设计院-创新产品研发中心
+                      {{ deptData[currMeeting.deptId] }}
                     </div>
                   </a-descriptions-item>
                   <a-descriptions-item>
@@ -94,7 +97,7 @@
                     </template>
                     <div
                       class="workMeeting-left-detail-content"
-                      style="background-color: #ffffff"
+                      style="background-color: #ffffff" v-if="currMeeting.subject"
                     >
                       30元/小时
                     </div>
@@ -105,19 +108,12 @@
                         >参会人员:</span
                       >
                     </template>
-                    <div style="width: 100%; vertical-align: top">
-                      <div
-                        style="
-                          display: inline-block;
-                          vertical-align: top;
-                          margin: 1px 3px;
-                        "
-                      >
-                        <a-avatar
-                          src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"
-                        />
-                        <div>张三</div>
-                      </div>
+                    <div style="width: 100%; vertical-align: top" v-if="currMeeting.subject">
+                      <div style=" display: inline-block; vertical-align: top; margin: 1px 3px;"><a-avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"/><div>张三</div></div>
+                      <div style=" display: inline-block; vertical-align: top; margin: 1px 3px;"><a-avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"/><div>张雪峰</div></div>
+                      <div style=" display: inline-block; vertical-align: top; margin: 1px 3px;"><a-avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"/><div>张明</div></div>
+                      <div style=" display: inline-block; vertical-align: top; margin: 1px 3px;"><a-avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"/><div>李阳</div></div>
+                      <div style=" display: inline-block; vertical-align: top; margin: 1px 3px;"><a-avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"/><div>王佳佳</div></div>
                     </div>
                   </a-descriptions-item>
                   <a-descriptions-item>
@@ -128,7 +124,7 @@
                     </template>
                     <div
                       class="workMeeting-left-detail-content"
-                      style="background-color: #ffffff"
+                      style="background-color: #ffffff" v-if="currMeeting.subject"
                     >
                       35元/小时
                     </div>
@@ -176,56 +172,66 @@ export default {
     WorkMeetingCostTrend,
   },
   data() {
-    const listData = [];
-    for (let i = 0; i < 100; i++) {
-      listData.push({
-        index: i + 1,
-        name: "物理饭",
-        department: "技术开发部门",
-        time: "2023.02.03 00:00:00",
-      });
-    }
     let timeRange = this.$util.dateUtil.getNearlyMonthRange();
     return {
       timeArr: [
         {
-          id: 1,
+          id: 0,
           weekday: "周一",
           date: "",
         },
         {
-          id: 2,
+          id: 1,
           weekday: "周二",
           date: "",
         },
         {
-          id: 3,
+          id: 2,
           weekday: "周三",
           date: "",
         },
         {
-          id: 4,
+          id: 3,
           weekday: "周四",
           date: "",
         },
         {
-          id: 5,
+          id: 4,
           weekday: "周五",
           date: "",
         },
       ],
+      deptData: {
+        "0": '业务一部',
+        "1": '业务二部',
+        "2": '业务三部',
+      },
       queryData: {
         companyId: "0",
-        floorId: "0",
+        floorId: "7",
         timeRange: timeRange,
       },
+      currRoom: '701',
+      floorOptions: [
+        {
+          value: '7',
+          label: "7F"
+        },
+        {
+          value: '8',
+          label: "8F"
+        },
+        {
+          value: '9',
+          label: "9F"
+        }
+      ],
       columns: [
         { title: "序号", dataIndex: "index", key: "1", width: 48 },
         { title: "姓名", dataIndex: "name", key: "2", width: 60 },
         { title: "部门", dataIndex: "department", key: "3", width: 80 },
         { title: "最后进入时间", dataIndex: "time", key: "4", width: 90 },
       ],
-      listData: listData,
       coreData: [
         {
           title: "会议室饱和度(月)",
@@ -261,353 +267,71 @@ export default {
           content: "",
         },
       ],
-      defaultSelectedKeys: ["0"],
+      defaultSelectedKeys: ["701",'801','901'],
       tabsItemArr: [],
-      tabsArr: [
-        {
-          title: "701",
-          focus: true,
-          content: [
-            {
-              date: "2023.08.01",
-              week: "周一",
-              shiyong: [
-                {
-                  name: "1",
-                  startTime: "2023.08.01 08:40:00",
-                  endTime: "2023.08.01 10:40:00",
-                },
-                {
-                  name: "2",
-                  startTime: "2023.08.01 12:25:00",
-                  endTime: "2023.08.01 13:42:00",
-                },
-                {
-                  name: "3",
-                  startTime: "2023.08.01 15:21:00",
-                  endTime: "2023.08.01 16:22:00",
-                },
-              ],
-            },
-            {
-              date: "2023.08.02",
-              week: "周二",
-              shiyong: [
-                {
-                  name: "1",
-                  startTime: "2023.08.01 08:40:00",
-                  endTime: "2023.08.01 10:40:00",
-                },
-                {
-                  name: "2",
-                  startTime: "2023.08.01 12:25:00",
-                  endTime: "2023.08.01 13:42:00",
-                },
-                {
-                  name: "3",
-                  startTime: "2023.08.01 15:21:00",
-                  endTime: "2023.08.01 16:22:00",
-                },
-              ],
-            },
-            {
-              date: "2023.08.03",
-              week: "周三",
-              shiyong: [
-                {
-                  name: "1",
-                  startTime: "2023.08.01 08:40:00",
-                  endTime: "2023.08.01 10:40:00",
-                },
-                {
-                  name: "2",
-                  startTime: "2023.08.01 12:25:00",
-                  endTime: "2023.08.01 13:42:00",
-                },
-                {
-                  name: "3",
-                  startTime: "2023.08.01 15:21:00",
-                  endTime: "2023.08.01 16:22:00",
-                },
-              ],
-            },
-            {
-              date: "2023.08.04",
-              week: "周四",
-              shiyong: [
-                {
-                  name: "1",
-                  startTime: "2023.08.01 08:40:00",
-                  endTime: "2023.08.01 10:40:00",
-                },
-                {
-                  name: "2",
-                  startTime: "2023.08.01 12:25:00",
-                  endTime: "2023.08.01 13:42:00",
-                },
-                {
-                  name: "3",
-                  startTime: "2023.08.01 15:21:00",
-                  endTime: "2023.08.01 16:22:00",
-                },
-              ],
-            },
-            {
-              date: "2023.08.05",
-              week: "周五",
-              shiyong: [
-                {
-                  name: "1",
-                  startTime: "2023.08.01 08:40:00",
-                  endTime: "2023.08.01 10:40:00",
-                },
-                {
-                  name: "2",
-                  startTime: "2023.08.01 12:25:00",
-                  endTime: "2023.08.01 13:42:00",
-                },
-                {
-                  name: "3",
-                  startTime: "2023.08.01 15:21:00",
-                  endTime: "2023.08.01 16:22:00",
-                },
-              ],
-            },
-          ],
-        },
-        {
-          title: "702",
-          focus: false,
-          content: [
-            {
-              date: "2023.08.01",
-              week: "周一",
-              shiyong: [
-                {
-                  name: "1",
-                  startTime: "2023.08.01 08:40:00",
-                  endTime: "2023.08.01 10:40:00",
-                },
-                {
-                  name: "2",
-                  startTime: "2023.08.01 12:25:00",
-                  endTime: "2023.08.01 13:42:00",
-                },
-                {
-                  name: "3",
-                  startTime: "2023.08.01 15:21:00",
-                  endTime: "2023.08.01 16:22:00",
-                },
-              ],
-            },
-            {
-              date: "2023.08.02",
-              week: "周二",
-              shiyong: [
-                {
-                  name: "1",
-                  startTime: "2023.08.01 08:40:00",
-                  endTime: "2023.08.01 10:40:00",
-                },
-                {
-                  name: "2",
-                  startTime: "2023.08.01 12:25:00",
-                  endTime: "2023.08.01 13:42:00",
-                },
-                {
-                  name: "3",
-                  startTime: "2023.08.01 15:21:00",
-                  endTime: "2023.08.01 16:22:00",
-                },
-              ],
-            },
-            {
-              date: "2023.08.03",
-              week: "周三",
-              shiyong: [
-                {
-                  name: "1",
-                  startTime: "2023.08.01 08:40:00",
-                  endTime: "2023.08.01 10:40:00",
-                },
-                {
-                  name: "2",
-                  startTime: "2023.08.01 12:25:00",
-                  endTime: "2023.08.01 13:42:00",
-                },
-                {
-                  name: "3",
-                  startTime: "2023.08.01 15:21:00",
-                  endTime: "2023.08.01 16:22:00",
-                },
-              ],
-            },
-            {
-              date: "2023.08.04",
-              week: "周四",
-              shiyong: [
-                {
-                  name: "1",
-                  startTime: "2023.08.01 08:40:00",
-                  endTime: "2023.08.01 10:40:00",
-                },
-                {
-                  name: "2",
-                  startTime: "2023.08.01 12:25:00",
-                  endTime: "2023.08.01 13:42:00",
-                },
-                {
-                  name: "3",
-                  startTime: "2023.08.01 15:21:00",
-                  endTime: "2023.08.01 16:22:00",
-                },
-              ],
-            },
-            {
-              date: "2023.08.05",
-              week: "周五",
-              shiyong: [
-                {
-                  name: "1",
-                  startTime: "2023.08.01 08:40:00",
-                  endTime: "2023.08.01 10:40:00",
-                },
-                {
-                  name: "2",
-                  startTime: "2023.08.01 12:25:00",
-                  endTime: "2023.08.01 13:42:00",
-                },
-                {
-                  name: "3",
-                  startTime: "2023.08.01 15:21:00",
-                  endTime: "2023.08.01 16:22:00",
-                },
-              ],
-            },
-          ],
-        },
-        {
-          title: "703",
-          content: [
-            {
-              date: "2023.08.01",
-              week: "周一",
-              shiyong: [
-                {
-                  name: "1",
-                  startTime: "2023.08.01 08:40:00",
-                  endTime: "2023.08.01 10:40:00",
-                },
-                {
-                  name: "2",
-                  startTime: "2023.08.01 12:25:00",
-                  endTime: "2023.08.01 13:42:00",
-                },
-                {
-                  name: "3",
-                  startTime: "2023.08.01 15:21:00",
-                  endTime: "2023.08.01 16:22:00",
-                },
-              ],
-            },
-            {
-              date: "2023.08.02",
-              week: "周二",
-              shiyong: [
-                {
-                  name: "1",
-                  startTime: "2023.08.01 08:40:00",
-                  endTime: "2023.08.01 10:40:00",
-                },
-                {
-                  name: "2",
-                  startTime: "2023.08.01 12:25:00",
-                  endTime: "2023.08.01 13:42:00",
-                },
-                {
-                  name: "3",
-                  startTime: "2023.08.01 15:21:00",
-                  endTime: "2023.08.01 16:22:00",
-                },
-              ],
-            },
-            {
-              date: "2023.08.03",
-              week: "周三",
-              shiyong: [
-                {
-                  name: "1",
-                  startTime: "2023.08.01 08:40:00",
-                  endTime: "2023.08.01 10:40:00",
-                },
-                {
-                  name: "2",
-                  startTime: "2023.08.01 12:25:00",
-                  endTime: "2023.08.01 13:42:00",
-                },
-                {
-                  name: "3",
-                  startTime: "2023.08.01 15:21:00",
-                  endTime: "2023.08.01 16:22:00",
-                },
-              ],
-            },
-            {
-              date: "2023.08.04",
-              week: "周四",
-              shiyong: [
-                {
-                  name: "1",
-                  startTime: "2023.08.01 08:40:00",
-                  endTime: "2023.08.01 10:40:00",
-                },
-                {
-                  name: "2",
-                  startTime: "2023.08.01 12:25:00",
-                  endTime: "2023.08.01 13:42:00",
-                },
-                {
-                  name: "3",
-                  startTime: "2023.08.01 15:21:00",
-                  endTime: "2023.08.01 16:22:00",
-                },
-              ],
-            },
-            {
-              date: "2023.08.05",
-              week: "周五",
-              shiyong: [
-                {
-                  name: "1",
-                  startTime: "2023.08.01 08:40:00",
-                  endTime: "2023.08.01 10:40:00",
-                },
-                {
-                  name: "2",
-                  startTime: "2023.08.01 12:25:00",
-                  endTime: "2023.08.01 13:42:00",
-                },
-                {
-                  name: "3",
-                  startTime: "2023.08.01 15:21:00",
-                  endTime: "2023.08.01 16:22:00",
-                },
-              ],
-            },
-          ],
-        },
-      ],
+      roomInfo: {
+        "7": [
+          {
+            label: '701',
+            value: '701'
+          },
+          {
+            label: '702',
+            value: '702'
+          },
+          {
+            label: '703',
+            value: '703'
+          },
+        ],
+        "8": [
+          {
+            label: '801',
+            value: '801'
+          },
+          {
+            label: '802',
+            value: '802'
+          },
+          {
+            label: '803',
+            value: '803'
+          },
+        ],
+        "9": [
+          {
+            label: '901',
+            value: '901'
+          },
+          {
+            label: '902',
+            value: '902'
+          },
+          {
+            label: '903',
+            value: '903'
+          },
+        ]
+      },
+      meetingInfo: {
+
+      },
+      currMeeting: {}
     };
   },
   mounted() {
-    this.changeTab(1);
+    //this.changeTab(1);
     this.init();
     this.setDate();
+    this.getMeetingRecordData();
   },
   methods: {
     init() {
       this.$store.loadingStore().loadingWithApi(this.getCoreData(), 2000);
     },
+    currCheckMeeting(val) {
+      this.currMeeting = val;
+    },
     setDate() {
       this.timeArr = this.timeArr.map((v) => {
         return {
@@ -630,18 +354,34 @@ export default {
         this.$refs.WorkMeetingCostTrend.getData()
       );
     },
-    handleChange(value) {
-      console.log(`selected ${value}`);
-    },
-    getTimeRange() {
-      this.$refs.timeRange.getTimeRange(); // 获取时间段
+    getMeetingRecordData() {
+      let params = {};
+      Object.assign(params, this.queryData);
+      params.timeRange = this.$util.dateUtil.getCurrWeekRange();
+      let resultObj = {};
+      let app = this;
+      this.timeArr.forEach(i=>{
+        resultObj[i.date] = []
+      })
+      this.meetingInfo = resultObj
+      apiWorkMeeting.getMeetingRecords(params).then(res=>{
+        let arr = res.filter(item=>item.room==this.currRoom)
+        for (let i = 0; i < arr.length; i++) {
+          let obj = app.$moment(arr[i].startTime).format('yyyy/MM/DD')
+          resultObj[obj].push(arr[i])
+        }
+        this.meetingInfo = resultObj
+      })
+
     },
     huiyiClick(e) {
-      this.changeTab(e.key);
-    },
-    changeTab(index) {
-      this.tabsItemArr = this.tabsArr[index].content;
+      //this.changeTab(e.key);
+      this.currRoom = e.key;
+      this.getMeetingRecordData()
     },
+    //changeTab(index) {
+    //  this.tabsItemArr = this.tabsArr[index].content;
+    //},
     getCoreData() {
       return apiWorkMeeting.getCoreData(this.queryData).then((res) => {
         this.coreData[0].num = res.list[0].value;

+ 5 - 1
src/main.js

@@ -7,6 +7,7 @@ import * as echarts from 'echarts';
 import 'animate.css/animate.min.css'
 
 import { PiniaVuePlugin, createPinia } from 'pinia'
+import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
 
 // 全局方法
 import util from '@/utils/index'
@@ -30,11 +31,14 @@ Vue.use(hikComp)
 Vue.use(Antd) 
 Vue.use(PiniaVuePlugin)
 
+const pinia = createPinia()
+pinia.use(piniaPluginPersistedstate);
+
 new Vue({
   router,
   data: {
     moment,
   },
-  pinia: createPinia(),
+  pinia: pinia,
   render: h => h(App),
 }).$mount('#app')

File diff suppressed because it is too large
+ 5 - 0
src/plugins/hkws/h5player.min.js


+ 225 - 0
src/plugins/hkws/playctrl1/AudioRenderer.js

@@ -0,0 +1,225 @@
+/**
+ * Created by wangweijie5 on 2016/12/16.
+ */
+
+"use strict";
+
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+var __instance = function () {
+    var instance = void 0;
+    return function (newInstance) {
+        if (newInstance) instance = newInstance;
+        return instance;
+    };
+}();
+
+var AudioRenderer = function () {
+    function AudioRenderer() {
+        _classCallCheck(this, AudioRenderer);
+
+        if (__instance()) return __instance();
+
+        // 确保只有单例
+        if (AudioRenderer.unique !== undefined) {
+            return AudioRenderer.unique;
+        }
+
+        AudioRenderer.unique = this;
+
+        this.oAudioContext = null;
+        this.currentVolume = 0.8; // 初始音量
+        this.bSetVolume = false;
+        this.gainNode = null;
+        this.iWndNum = -1; // 窗口号
+        this.mVolumes = new Map(); // 用于存储所有音量
+
+        // Init AudioContext
+        var AudioContext = window.AudioContext || window.webkitAudioContext;
+        this.oAudioContext = new AudioContext();
+
+        this.writeString = function (view, offset, string) {
+            for (var i = 0; i < string.length; i++) {
+                view.setUint8(offset + i, string.charCodeAt(i));
+            }
+        };
+
+        this.setBufferToDataview = function (output, offset, input) {
+            for (var i = 0; i < input.length; i++, offset++) {
+                output.setUint8(offset, input[i]);
+            }
+        };
+
+        __instance(this);
+    }
+
+    /**
+     * @synopsis 音频播放
+     *
+     *  @param dataBuf [IN] 音频缓存
+     *  @param dataLen [IN] 缓存长度
+     *  @param audioInfo [IN] 音频参数
+     *
+     * @returns 状态码
+     */
+
+
+    _createClass(AudioRenderer, [{
+        key: 'Play',
+        value: function Play(dataBuf, dataLen, audioInfo) {
+            var bufferData = new ArrayBuffer(44 + dataLen);
+            var viewTalk = new DataView(bufferData);
+            var sampleRates = audioInfo.samplesPerSec;
+            var channels = audioInfo.channels;
+            var bitsPerSample = audioInfo.bitsPerSample;
+
+            //console.log("audiorender sampleRates"+sampleRates+"channels:"+channels+"bitsPerSample:"+bitsPerSample);
+
+            /* RIFF identifier */
+            this.writeString(viewTalk, 0, 'RIFF');
+            /* file length */
+            viewTalk.setUint32(4, 32 + dataLen * 2, true);
+            /* RIFF type */
+            this.writeString(viewTalk, 8, 'WAVE');
+            /* format chunk identifier */
+            this.writeString(viewTalk, 12, 'fmt ');
+            /* format chunk length */
+            viewTalk.setUint32(16, 16, true);
+            /* sample format (raw) */
+            viewTalk.setUint16(20, 1, true);
+            /* channel count */
+            viewTalk.setUint16(22, channels, true);
+            /* sample rate */
+            viewTalk.setUint32(24, sampleRates, true);
+            /* byte rate (sample rate * block align) */
+            viewTalk.setUint32(28, sampleRates * 2, true);
+            /* block align (channel count * bytes per sample)/8 */
+            viewTalk.setUint16(32, channels * bitsPerSample / 8, true);
+            /* bits per sample */
+            viewTalk.setUint16(34, bitsPerSample, true);
+            /* data chunk identifier */
+            this.writeString(viewTalk, 36, 'data');
+            /* data chunk length */
+            viewTalk.setUint32(40, dataLen, true);
+            this.setBufferToDataview(viewTalk, 44, dataBuf);
+
+            var self = this;
+            this.oAudioContext.decodeAudioData(viewTalk.buffer, function (buffer) {
+
+                var bufferSource = self.oAudioContext.createBufferSource();
+                if (bufferSource == null) {
+                    return -1;
+                }
+
+                bufferSource.buffer = buffer;
+                bufferSource.start(0);
+
+                if (self.gainNode == null || self.bSetVolume) {
+                    self.gainNode = self.oAudioContext.createGain();
+                    // self.gainNode.gain.value = self.currentVolume;
+                    // // self.currentVolume = self.gainNode.gain.value;
+                    // self.gainNode.connect(self.oAudioContext.destination);
+
+                    self.bSetVolume = false;
+                }
+
+                self.gainNode.gain.value = self.currentVolume;
+                // self.currentVolume = self.gainNode.gain.value;
+                self.gainNode.connect(self.oAudioContext.destination);
+
+                bufferSource.connect(self.gainNode);
+            }, function (e) {
+                console.log("decode error");
+                return -1;
+            });
+
+            return 0;
+        }
+
+        /**
+         * @synopsis 停止播放
+         *
+         * @returns 返回音量
+         */
+
+    }, {
+        key: 'Stop',
+        value: function Stop() {
+            if (this.gainNode != null) {
+                this.gainNode.disconnect();
+                this.gainNode = null;
+            }
+
+            // this.oAudioContext.close();
+
+            // AudioRenderer.unique = undefined;
+            // __instance() = null;
+            return true;
+        }
+
+        /**
+         * @synopsis 设置音量
+         *
+         *  @param iVolume [IN] 音量
+         *
+         * @returns 状态码
+         */
+
+    }, {
+        key: 'SetVolume',
+        value: function SetVolume(iVolume) {
+            this.bSetVolume = true;
+            this.currentVolume = iVolume;
+
+            // 储存当前窗口设置音量值
+            this.mVolumes.set(this.iWndNum, iVolume);
+            return true;
+        }
+
+        /**
+         * @synopsis 设置窗口号
+         *
+         *  @param iWndNum [IN] 窗口号
+         *
+         * @returns 状态码
+         */
+
+    }, {
+        key: 'SetWndNum',
+        value: function SetWndNum(iWndNum) {
+            this.iWndNum = iWndNum;
+
+            // 获取当前窗口设置音量值
+            var iVolume = this.mVolumes.get(iWndNum);
+            if (iVolume == undefined) {
+                iVolume = 0.8; // 默认音量
+            }
+            this.currentVolume = iVolume;
+
+            return true;
+        }
+
+        /**
+         * @synopsis 获取音量
+         *
+         * @returns 返回音量
+         */
+
+    }, {
+        key: 'GetVolume',
+        value: function GetVolume() {
+            // 获取当前窗口设置音量值
+            var iVolume = this.mVolumes.get(this.iWndNum);
+            if (iVolume == undefined) {
+                iVolume = 0.8; // 默认音量
+            }
+
+            return iVolume;
+        }
+    }]);
+
+    return AudioRenderer;
+}();
+//# sourceMappingURL=AudioRenderer.js.map

+ 711 - 0
src/plugins/hkws/playctrl1/DecodeWorker.js

@@ -0,0 +1,711 @@
+/**
+ * Created by wangweijie5 on 2016/12/5.
+ */
+(function (event) {
+    const AUDIO_TYPE = 0;	// 音频
+    const VIDEO_TYPE = 1;   // 视频
+    const PRIVT_TYPE = 2;  // 私有帧
+
+    const PLAYM4_AUDIO_FRAME = 100; // 音频帧
+    const PLAYM4_VIDEO_FRAME = 101; // 视频帧
+
+    const PLAYM4_OK = 1;
+    const PLAYM4_DECODE_ERROR = 44 	// 解码失败
+    const PLAYM4_NOT_KEYFRAME = 48; 	// 非关键帧
+    const PLAYM4_NEED_MORE_DATA = 31;   // 需要更多数据才能解析
+    const PLAYM4_SYS_NOT_SUPPORT = 16; 	// 不支持
+
+    const PLAYM4_PARA_ENCODER_ERROR                     = 71;  //音频编码参数错误
+    const PLAYM4_PRECONDITION_ENCODER_ERROR             = 72;  //不满足音频编码条件错误
+    const PLAYM4_ENCODER_ERROR                          = 73;  //音频编码失败
+    const PLAYM4_CREATE_ENCODER_ERROR                   = 74;  //创建音频编码器失败
+    const PLAYM4_NOSUPPORT_ENCODER_ERROR                = 75;  //音频编码不支持
+    const PLAYM4_ALLOC_MEMORY_ENCODER_ERROR	            = 76;  //音频编码相关内存申请失败
+    const PLAYM4_BUF_OVER_ENCODER_ERROR                 = 77;  //音频编码相关buffer满
+    const PLAYM4_NEED_MORE_DATA_ENCODER_ERROR           = 78;  //音频编码需要更多数据进行编码
+    const PLAYM4_CALL_ORDER_ENCODER_ERROR               = 79;  //音频编码调用顺序错误
+
+    const PLAYM4_ITYPE_DECODE_ERROR                     =100;   //定位后送进来的第一帧I帧解码失败
+    const PLAYM4_FIRST_FRAME_NOT_ICURRENT               =101;   //定位后送进来的第一帧不是定位帧所在的I帧(Ni>Mp)
+
+
+    importScripts('Decoder.js');
+    Module.addOnPostRun(function () {
+        postMessage({'function': "loaded"});
+    });
+
+    var iStreamMode = 0;  // 流模式
+
+    var bOpenMode = false;
+    var bOpenStream = false;
+    
+    var funGetFrameData = null;
+    var funGetAudFrameData = null;
+	
+	var bWorkerPrintLog=false;//worker层log开关
+
+    onmessage = function (event)
+    {
+        var eventData = event.data;
+        var res = 0;
+        switch (eventData.command)
+        {
+			case "printLog":
+			    let downloadFlag=eventData.data;
+			    if(downloadFlag===true)
+                {
+                    bWorkerPrintLog=true;
+                    res = Module._SetPrintLogFlag(downloadFlag);
+                }
+			    else
+                {
+                    bWorkerPrintLog=false;
+                    res = Module._SetPrintLogFlag(downloadFlag);
+                }
+
+				if (res !== PLAYM4_OK)
+                {
+					console.log("DecodeWorker.js: PlayerSDK print log failed,res"+res);
+                    postMessage({'function': "printLog", 'errorCode': res});
+                }
+				break;
+            case "SetPlayPosition":
+                let nFrameNumOrTime=eventData.data;
+                let enPosType=eventData.type;
+                res = Module._SetPlayPosition(nFrameNumOrTime,enPosType);
+                if (res !== PLAYM4_OK)
+                {
+                    postMessage({'function': "SetPlayPosition", 'errorCode': res});
+                    return;
+                }
+                //有没有buffer需要清除
+
+                break;
+            case "SetStreamOpenMode":
+                iStreamMode = eventData.data;
+                res = Module._SetStreamOpenMode(iStreamMode);
+                if (res !== PLAYM4_OK)
+                {
+                    postMessage({'function': "SetStreamOpenMode", 'errorCode': res});
+                    return;
+                }
+                bOpenMode = true;
+                break;
+
+            case "OpenStream":
+                // 接收到的数据
+                var iHeadLen = eventData.dataSize;
+                var pHead = Module._malloc(iHeadLen + 4);
+                if (pHead === null)
+                {
+                    return;
+                }
+                var aHead = Module.HEAPU8.subarray(pHead, pHead + iHeadLen);
+                aHead.set(eventData.data);
+                res = Module._OpenStream(pHead, iHeadLen, eventData.bufPoolSize);
+                postMessage({'function': "OpenStream", 'errorCode': res});
+                if (res !== PLAYM4_OK)
+                {
+                    //释放内存
+                    Module._free(pHead);
+                    pHead = null;
+                    return;
+                }
+                bOpenStream = true;
+
+                // 加4字节长度信息
+                var a32 = new Uint32Array([iHeadLen]);
+                var a8 = new Uint8Array(a32.buffer);
+                var tempBuf = new Uint8Array(iHeadLen + 4);
+                tempBuf.set(a8, 0);
+                tempBuf.set(eventData.data, 4);
+                a32 = null;
+                a8 = null;
+
+                aHead = Module.HEAPU8.subarray(pHead, pHead + iHeadLen + 4);
+                aHead.set(tempBuf);
+                tempBuf = null;
+
+                res = Module._InputData(pHead, iHeadLen + 4);
+                if (res !== PLAYM4_OK)
+                {
+                    postMessage({'function': "InputData", 'errorCode': res});
+                    Module._free(pHead);
+                    pHead = null;
+                    return;
+                }
+
+                // 释放内存
+                Module._free(pHead);
+                pHead = null;
+
+                if (funGetFrameData === null) {
+                    funGetFrameData = Module.cwrap('GetFrameData', 'number');
+                }
+
+                if (iStreamMode === 0) {
+                    // Module._GetFrameData();
+                    funGetFrameData();
+                }
+                break;
+
+            case "InputData":
+                // 接收到的数据
+                var iLen = eventData.dataSize;
+                if(bWorkerPrintLog)
+                {
+                    console.log("<<<Worker: DecodeWorker-InputData iLen:"+iLen);
+                }
+                
+                if (iLen > 0)
+                {
+                    var pInputData = Module._malloc(iLen);
+                    if (pInputData === null)
+                    {
+                        return;
+                    }
+                    var inputData = new Uint8Array(eventData.data);
+                    // var aInputData = Module.HEAPU8.subarray(pInputData, pInputData + iLen);
+                    // aInputData.set(inputData);
+                    Module.writeArrayToMemory(inputData, pInputData);
+                    inputData = null;
+                    res = Module._InputData(pInputData, iLen);
+                    //console.log("DecodeWorker-InputData-ret:%d", res);
+					if(bWorkerPrintLog)
+					{
+						console.log("<<<Worker:InputData result:"+ +res);
+					}
+					
+                    if (res !== PLAYM4_OK)
+                    {
+                        if (res === 98)
+                        {
+                            res = 1;
+                        }
+                        postMessage({'function': "InputData", 'errorCode': res});
+                    }
+                    Module._free(pInputData);
+                    pInputData = null;
+                }
+
+                /////////////////////
+                if (funGetFrameData === null)
+                {
+                    funGetFrameData = Module.cwrap('GetFrameData', 'number');
+                }
+
+                while (bOpenMode && bOpenStream)
+                {
+                    
+                    var ret = getFrameData(funGetFrameData);
+                    // 直到获取视频帧或数据不足为止
+                    if (PLAYM4_VIDEO_FRAME === ret || PLAYM4_NEED_MORE_DATA === ret)
+                    {
+                        break;
+                    }
+                }
+                break;
+
+            case "SetSecretKey":
+                var keyLen = eventData.nKeyLen;
+                var pKeyData = Module._malloc(keyLen);
+                if (pKeyData === null) {
+                    return;
+                }
+                var nKeySize = eventData.data.length
+                var bufData = stringToBytes (eventData.data);
+                var aKeyData = Module.HEAPU8.subarray(pKeyData, pKeyData + keyLen);
+                aKeyData.set(new Uint8Array(bufData));
+
+                res = Module._SetSecretKey(eventData.nKeyType, pKeyData, keyLen, nKeySize);
+                if (res !== PLAYM4_OK) {
+                    postMessage({'function': "SetSecretKey", 'errorCode': res});
+                    Module._free(pKeyData);
+                    pKeyData = null;
+                    return;
+                }
+
+                Module._free(pKeyData);
+                pKeyData = null;
+                break;
+
+            case "GetBMP":
+                var nBMPWidth = eventData.width;
+                var nBMPHeight = eventData.height;
+                var pYUVData = eventData.data;
+                var nYUVSize = nBMPWidth * nBMPHeight * 3 / 2;
+                var oBMPCropRect = eventData.rect;
+
+                var pDataYUV = Module._malloc(nYUVSize);
+                if (pDataYUV === null) {
+                    return;
+                }
+
+                Module.writeArrayToMemory(new Uint8Array(pYUVData, 0, nYUVSize), pDataYUV);
+
+                // 分配BMP空间
+                var nBmpSize = nBMPWidth * nBMPHeight * 4 + 60;
+                var pBmpData = Module._malloc(nBmpSize);
+                var pBmpSize = Module._malloc(4);
+                if (pBmpData === null || pBmpSize === null) {
+                    Module._free(pDataYUV);
+                    pDataYUV = null;
+
+                    if (pBmpData != null) {
+                        Module._free(pBmpData);
+                        pBmpData = null;
+                    }
+
+                    if (pBmpSize != null) {
+                        Module._free(pBmpSize);
+                        pBmpSize = null;
+                    }
+                    return;
+                }
+
+               //Module._memset(pBmpSize, nBmpSize, 4); // 防止bmp截图出现输入数据过大的错误码
+                Module.setValue(pBmpSize, nBmpSize, "i32"); 
+                res = Module._GetBMP(pDataYUV, nYUVSize, pBmpData, pBmpSize,
+                    oBMPCropRect.left, oBMPCropRect.top, oBMPCropRect.right, oBMPCropRect.bottom);
+                if (res !== PLAYM4_OK) {
+                    postMessage({'function': "GetBMP", 'errorCode': res});
+                    Module._free(pDataYUV);
+                    pDataYUV = null;
+                    Module._free(pBmpData);
+                    pBmpData = null;
+                    Module._free(pBmpSize);
+                    pBmpSize = null;
+                    return;
+                }
+
+                // 获取BMP图片大小
+                var nBmpDataSize = Module.getValue(pBmpSize, "i32");
+
+                // 获取BMP图片数据
+                var aBmpData = new Uint8Array(nBmpDataSize);
+                aBmpData.set(Module.HEAPU8.subarray(pBmpData, pBmpData + nBmpDataSize));
+
+                postMessage({'function': "GetBMP", 'data': aBmpData, 'errorCode': res}, [aBmpData.buffer]);
+                aBmpData=null;
+                if (pDataYUV != null) {
+                    Module._free(pDataYUV);
+                    pDataYUV = null;
+                }
+                if (pBmpData != null) {
+                    Module._free(pBmpData);
+                    pBmpData = null;
+                }
+                if (pBmpSize != null) {
+                    Module._free(pBmpSize);
+                    pBmpSize = null;
+                }
+                break;
+
+            case "GetJPEG":
+                var nJpegWidth = eventData.width;
+                var nJpegHeight = eventData.height;
+                var pYUVData1 = eventData.data;
+                var nYUVSize1 = nJpegWidth * nJpegHeight * 3 / 2;
+                var oJpegCropRect = eventData.rect;
+
+                var pDataYUV1 = Module._malloc(nYUVSize1);
+                if (pDataYUV1 === null) {
+                    return;
+                }
+
+                Module.writeArrayToMemory(new Uint8Array(pYUVData1, 0, nYUVSize1), pDataYUV1);
+
+                // 分配JPEG空间
+                var pJpegData = Module._malloc(nYUVSize1);
+                var pJpegSize = Module._malloc(4);
+                if (pJpegData === null || pJpegSize === null) {
+                    if (pJpegData != null) {
+                        Module._free(pJpegData);
+                        pJpegData = null;
+                    }
+
+                    if (pJpegSize != null) {
+                        Module._free(pJpegSize);
+                        pJpegSize = null;
+                    }
+
+                    if (pDataYUV1 != null) {
+                        Module._free(pDataYUV1);
+                        pDataYUV1 = null;
+                    }
+                    return;
+                }
+
+                Module.setValue(pJpegSize, nJpegWidth * nJpegHeight * 2, "i32");    // JPEG抓图,输入缓冲长度不小于当前帧YUV大小
+
+                res = Module._GetJPEG(pDataYUV1, nYUVSize1, pJpegData, pJpegSize,
+                    oJpegCropRect.left, oJpegCropRect.top, oJpegCropRect.right, oJpegCropRect.bottom);
+                if (res !== PLAYM4_OK) {
+                    postMessage({'function': "GetJPEG", 'errorCode': res});
+                    if (pJpegData != null) {
+                        Module._free(pJpegData);
+                        pJpegData = null;
+                    }
+
+                    if (pJpegSize != null) {
+                        Module._free(pJpegSize);
+                        pJpegSize = null;
+                    }
+
+                    if (pDataYUV1 != null) {
+                        Module._free(pDataYUV1);
+                        pDataYUV1 = null;
+                    }
+                    return;
+                }
+
+                // 获取JPEG图片大小
+                var nJpegSize = Module.getValue(pJpegSize, "i32");
+
+                // 获取JPEG图片数据
+                var aJpegData = new Uint8Array(nJpegSize);
+                aJpegData.set(Module.HEAPU8.subarray(pJpegData, pJpegData + nJpegSize));
+
+                postMessage({'function': "GetJPEG", 'data': aJpegData, 'errorCode': res}, [aJpegData.buffer]);
+
+                nJpegSize = null;
+                aJpegData = null;
+
+                if (pDataYUV1 != null) {
+                    Module._free(pDataYUV1);
+                    pDataYUV1 = null;
+                }
+                if (pJpegData != null) {
+                    Module._free(pJpegData);
+                    pJpegData = null;
+                }
+                if (pJpegSize != null) {
+                    Module._free(pJpegSize);
+                    pJpegSize = null;
+                }
+                break;
+
+            case "SetDecodeFrameType":
+                var nFrameType = eventData.data;
+                res = Module._SetDecodeFrameType(nFrameType);
+                if (res !== PLAYM4_OK) {
+                    postMessage({'function': "SetDecodeFrameType", 'errorCode': res});
+                    return;
+                }
+                break;
+
+            case "DisplayRegion":
+                var nRegionNum = eventData.nRegionNum;
+                var srcRect = eventData.srcRect;
+                var hDestWnd = eventData.hDestWnd;
+                var bEnable = eventData.bEnable;
+
+                res = Module._SetDisplayRegion(nRegionNum, srcRect, hDestWnd, bEnable);
+                if (res !== PLAYM4_OK) {
+                    postMessage({'function': "DisplayRegion", 'errorCode': res});
+                    return;
+                }
+                break;
+
+            case "CloseStream":
+                res = Module._CloseStream();
+                if (res !== PLAYM4_OK) {
+                    postMessage({'function': "CloseStream", 'errorCode': res});
+                    return;
+                }
+                break;
+
+            case "SetIFrameDecInterval":
+                Module._SetIFrameDecInterval(eventData.data);
+                break;
+			case "SetLostFrameMode":
+			    Module._SetLostFrameMode(eventData.data);
+				break;
+			
+                /*******************************************worker音频编码相关接口实现**********************************************************/
+            case "CreateAudEncode":
+			
+                res = Module._CreateAudEncode(eventData.encodertype);
+                
+                postMessage({'function':"CreateAudEncode",'errorCode':res});
+                break;
+            case "SetAudEncodeParam":
+                
+                res = Module._SetAudEncodeParam(eventData.samplerate, eventData.channel, eventData.bitrate, eventData.bitwidth);
+			
+                postMessage({'function':"SetAudEncodeParam",'errorCode':res});
+                break;
+            case "DestroyAudEncode":
+               
+                res = Module._DestroyAudEncode();
+                
+                postMessage({'function':"DestroyAudEncode",'errorCode':res});
+                break;
+            case "InputAudEncodeData":
+			    if(bWorkerPrintLog)
+				{
+					console.log("<<<Worker: 20200113 DecodeWorker-InputAudEncodeData 1");
+				}
+                
+                var iLen = eventData.dataSize;
+                if(iLen > 0)
+                {
+                    
+                    var pAudInputData = Module._malloc(iLen);
+                    if (pAudInputData === null)
+                    {
+                        return;
+                    }
+                    var audinputData = new Uint8Array(eventData.data);
+                    Module.writeArrayToMemory(audinputData, pAudInputData);
+                    audinputData = null;
+                    res = Module._InputAudEncodeData(pAudInputData, iLen);
+					if(bWorkerPrintLog)
+					{
+						console.log("<<<Worker: 20200113 DecodeWorker-InputAudEncodeData 2 res:"+res);
+					}
+                    
+                    if(res == PLAYM4_OK)  //接口返回成功,表明已编码好一帧音频数据
+                    {
+                        
+                        if (funGetAudFrameData === null)
+                        {
+                            funGetAudFrameData = Module.cwrap('GetAudFrameData', 'number');
+                        }
+                        if(bWorkerPrintLog)
+						{
+							console.log("<<<Worker: 20200113 DecodeWorker-InputAudEncodeData 2-1 succ");
+						}
+                        //调用C++ GetAudFrameData
+                        var ret = getAudFrameData(funGetAudFrameData);
+                    }
+                    Module._free(pAudInputData);
+                    pAudInputData = null;
+                }
+                break;
+            default:
+                break;
+        }
+    };
+
+    function getOSDTime(oFrameInfo) {
+        var iYear = oFrameInfo.year;
+        var iMonth = oFrameInfo.month;
+        var iDay = oFrameInfo.day;
+        var iHour = oFrameInfo.hour;
+        var iMinute = oFrameInfo.minute;
+        var iSecond = oFrameInfo.second;
+
+        if (iMonth < 10) {
+            iMonth = "0" + iMonth;
+        }
+        if (iDay < 10) {
+            iDay = "0" + iDay;
+        }
+        if (iHour < 10) {
+            iHour = "0" + iHour;
+        }
+        if (iMinute < 10) {
+            iMinute = "0" + iMinute;
+        }
+        if (iSecond < 10) {
+            iSecond = "0" + iSecond;
+        }
+
+        return iYear + "-" + iMonth + "-" + iDay + " " + iHour + ":" + iMinute + ":" + iSecond;
+    }
+
+    function getAudFrameData(fun)
+    {
+		if(bWorkerPrintLog)
+		{
+			console.log("<<<Worker: DecodeWorker-getAudFrameData 1");
+		}
+    
+        var res = fun(); // 调用C++GetAudFrameData函数
+        if(res === PLAYM4_OK)
+        {
+            var oFrameInfo = Module._GetAudFrameInfo();
+            var iSize = oFrameInfo.frameSize;
+            if (0 === iSize)
+            {
+                return null;
+            }
+
+            var pEncodeAud = Module._GetAudFrameBuffer();
+            if(pEncodeAud == null)
+            {
+                return null;
+            }
+            var aEncodeAudData = new Uint8Array(iSize);
+            aEncodeAudData.set(Module.HEAPU8.subarray(pEncodeAud, pEncodeAud + iSize));
+			if(bWorkerPrintLog)
+			{
+				console.log("<<<Worker: DecodeWorker-getAudFrameData 2");
+			}
+            
+            //获取到音频编码帧数据通过worker返回
+            postMessage({'function':"GetAudEncodeData",'data':aEncodeAudData.buffer,'dataSize':iSize, 'errorCode': res});
+        }
+        else
+        {
+            postMessage({'function':"GetAudEncodeData",'data':null,'dataSize':-1, 'errorCode': res});
+        }
+        oFrameInfo=null;
+        pEncodeAud=null;
+        aEncodeAudData=null;
+        return res;
+    }
+
+    // 获取帧数据
+    function getFrameData(fun)
+    {
+    // function getFrameData() {
+        // 获取帧数据
+        // var res = Module._GetFrameData();
+        var res = fun();
+        if(bWorkerPrintLog)
+        {
+            console.log("<<<Worker: getFrameData Result:"+res);
+        }
+
+        if (res === PLAYM4_OK)
+        {
+            var oFrameInfo = Module._GetFrameInfo();
+            switch (oFrameInfo.frameType)
+            {
+                case AUDIO_TYPE:
+                    var iSize = oFrameInfo.frameSize;
+                    if (0 === iSize)
+                    {
+                        return -1;
+                    }
+                    var pPCM = Module._GetFrameBuffer();
+                    // var audioBuf = new ArrayBuffer(iSize);
+                    var aPCMData = new Uint8Array(iSize);
+                    aPCMData.set(Module.HEAPU8.subarray(pPCM, pPCM + iSize));
+                    if(bWorkerPrintLog)
+                    {
+                        console.log("<<<Worker: audio media Info: nSise:"+ oFrameInfo.frameSize+",nSampleRate:"+oFrameInfo.samplesPerSec+',channel:'+oFrameInfo.channels+',bitsPerSample:'+oFrameInfo.bitsPerSample);
+                    }
+                    postMessage({
+                        'function': "GetFrameData", 'type': "audioType", 'data': aPCMData.buffer,
+                        'frameInfo': oFrameInfo, 'errorCode': res
+                    }, [aPCMData.buffer]);
+
+                    oFrameInfo = null;
+                    pPCM = null;
+                    aPCMData = null;
+                    return PLAYM4_AUDIO_FRAME;
+
+                case VIDEO_TYPE:
+                    var szOSDTime = getOSDTime(oFrameInfo);
+
+                    var iWidth = oFrameInfo.width;
+                    var iHeight = oFrameInfo.height;
+
+                    var iYUVSize = iWidth * iHeight * 3 / 2;
+                    if (0 === iYUVSize)
+                    {
+                        return -1;
+                    }
+
+                    var pYUV = Module._GetFrameBuffer();
+
+                    // 图像数据渲染后压回,若从主码流切到子码流,存在数组大小与图像大小不匹配现象
+                    var aYUVData = new Uint8Array(iYUVSize);
+                    aYUVData.set(Module.HEAPU8.subarray(pYUV, pYUV + iYUVSize));
+                    if(bWorkerPrintLog)
+                    {
+                        console.log("<<<Worker: InputData-getFrameData Video: Width:"+ oFrameInfo.width+",Height:"+oFrameInfo.height+",timeStamp:"+oFrameInfo.timeStamp);
+                    }
+
+                    postMessage({
+                      'function': "GetFrameData", 'type': "videoType", 'data': aYUVData.buffer,
+                   'dataLen': aYUVData.length,'osd': szOSDTime, 'frameInfo': oFrameInfo, 'errorCode': res
+                    }, [aYUVData.buffer]);
+
+                    oFrameInfo = null;
+                    pYUV = null;
+                    aYUVData = null;
+                    return PLAYM4_VIDEO_FRAME;
+
+                case PRIVT_TYPE:
+                    postMessage({
+                        'function': "GetFrameData", 'type': "", 'data': null,
+                        'dataLen': -1, 'osd': 0, 'frameInfo': null, 'errorCode': PLAYM4_SYS_NOT_SUPPORT
+                    });
+                    return PLAYM4_SYS_NOT_SUPPORT;
+
+                default:
+                    postMessage({
+                        'function': "GetFrameData", 'type': "", 'data': null,
+                        'dataLen': -1, 'osd': 0, 'frameInfo': null, 'errorCode': PLAYM4_SYS_NOT_SUPPORT
+                    });
+                    return PLAYM4_SYS_NOT_SUPPORT;
+            }
+        }
+        else {
+            //解码失败返回裸数据
+            if(PLAYM4_DECODE_ERROR===res)
+            {
+                var rawInfo=Module._GetRawDataInfo();
+                var pRawData = Module._GetRawDataBuffer();
+                var aRawData = new Uint8Array(rawInfo.isize);
+                aRawData.set(Module.HEAPU8.subarray(pRawData, pRawData + rawInfo.isize));
+                postMessage({
+                    'function': "GetRawData", 'type': "", 'data':aRawData.buffer,
+                    'rawDataLen': rawInfo.isize, 'osd': 0, 'frameInfo': null, 'errorCode': res
+                });
+                rawInfo=null;
+                pRawData=null;
+                aRawData=null;
+            }
+            //定位返回的错误
+            if(PLAYM4_FIRST_FRAME_NOT_ICURRENT===res|| PLAYM4_ITYPE_DECODE_ERROR===res)
+            {
+                postMessage({
+                    'function': "GetFrameData", 'type': "", 'data': null,
+                    'dataLen': -1, 'osd': 0, 'frameInfo': null, 'errorCode': res
+                });
+            }
+            //需要更多数据
+            if (PLAYM4_NEED_MORE_DATA === res || PLAYM4_SYS_NOT_SUPPORT === res || PLAYM4_NOT_KEYFRAME === res){
+                postMessage({
+                    'function': "GetFrameData", 'type': "", 'data': null,
+                    'dataLen': -1, 'osd': 0, 'frameInfo': null, 'errorCode': res
+                });
+            }
+            return res;
+        }
+    }
+
+    // 开始计算时间
+    function startTime() {
+        return new Date().getTime();
+    }
+
+    // 结束计算时间
+    function endTime() {
+        return new Date().getTime();
+    }
+
+    // 字母字符串转byte数组
+    function stringToBytes ( str ) {
+        var ch, st, re = [];
+        for (var i = 0; i < str.length; i++ ) {
+            ch = str.charCodeAt(i);  // get char
+            st = [];                 // set up "stack"
+            do {
+                st.push( ch & 0xFF );  // push byte to stack
+                ch = ch >> 8;          // shift value down by 1 byte
+            }
+            while ( ch );
+            // add stack contents to result
+            // done because chars have "wrong" endianness
+            re = re.concat( st.reverse() );
+        }
+        // return an array of bytes
+        return re;
+    }
+})();

File diff suppressed because it is too large
+ 0 - 0
src/plugins/hkws/playctrl1/Decoder.js


+ 396 - 0
src/plugins/hkws/playctrl1/SuperRender_10.js

@@ -0,0 +1,396 @@
+"use strict";
+ //顶点着色器
+//attribute修饰符用于声明由浏览器(javascript)传输给顶点着色器的变量值;
+// vertexPos即我们定义的顶点坐标;
+// gl_Position是一个内建的传出变量。
+var vertexYUVShader = [
+    'attribute vec4 vertexPos;',
+    'attribute vec2 texturePos;',
+    'varying vec2 textureCoord;',
+
+    'void main()',
+    '{',
+        'gl_Position = vertexPos;',
+        'textureCoord = texturePos;',
+    '}'
+    ].join('\n');
+    //像素着色器(yuv->rgb)
+var fragmentYUVShader = [
+    'precision highp float;',
+    'varying highp vec2 textureCoord;',
+    'uniform sampler2D ySampler;',
+    'uniform sampler2D uSampler;',
+    'uniform sampler2D vSampler;',
+    'const mat4 YUV2RGB = mat4',
+    '(',
+        '1.1643828125, 0, 1.59602734375, -.87078515625,',
+        '1.1643828125, -.39176171875, -.81296875, .52959375,',
+        '1.1643828125, 2.017234375, 0, -1.081390625,',
+        '0, 0, 0, 1',
+    ');',
+  
+    'void main(void) {',
+        'highp float y = texture2D(ySampler,  textureCoord).r;',
+        'highp float u = texture2D(uSampler,  textureCoord).r;',
+        'highp float v = texture2D(vSampler,  textureCoord).r;',
+        'gl_FragColor = vec4(y, u, v, 1) * YUV2RGB;',
+    '}'
+    ].join('\n');
+
+(function (root, factory) {
+    root.SuperRender = factory();
+}(this, function () {
+    
+    function RenderManager(canvas) {
+
+        this.canvasElement = document.getElementById(canvas);
+
+        this.initContextGL();
+
+        if(this.contextGL) {
+            this.YUVProgram = this.initProgram(vertexYUVShader, fragmentYUVShader);
+            this.initBuffers();
+            this.initTextures();
+        }
+    };
+
+    /**
+     * 初始化WebGL上下文
+     */
+    RenderManager.prototype.initContextGL = function() {
+        
+        var canvas = this.canvasElement;
+
+        var gl = null;
+
+        try {
+            gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
+        } catch (e) {
+            gl = null;
+        }
+
+        if(!gl || typeof gl.getParameter !== "function") {
+            gl = null;
+        }
+
+        this.contextGL = gl;
+
+        console.log("WebGL1.0");
+    };
+
+    /**
+     * 初始化着色器程序
+     * @param vertexShaderScript    顶点着色器脚本
+     * @param fragmentShaderScript  片段着色器脚本
+     */
+    RenderManager.prototype.initProgram = function(vertexShaderScript, fragmentShaderScript) {
+        
+        var gl = this.contextGL;
+        
+        var vertexShader = gl.createShader(gl.VERTEX_SHADER); //创建定点着色器
+        gl.shaderSource(vertexShader, vertexShaderScript);
+        gl.compileShader(vertexShader);
+        if(!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
+            console.log('Vertex shader failed to compile: ' + gl.getShaderInfoLog(vertexShader));
+        }
+
+        var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
+        gl.shaderSource(fragmentShader, fragmentShaderScript);
+        gl.compileShader(fragmentShader);
+        if(!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
+            console.log('Fragment shader failed to compile: ' + gl.getShaderInfoLog(fragmentShader));
+        }
+
+        var program = gl.createProgram();
+        gl.attachShader(program, vertexShader);
+        gl.attachShader(program, fragmentShader);
+        gl.linkProgram(program);
+        if(!gl.getProgramParameter(program, gl.LINK_STATUS)) {
+            console.log('Program failed to compile: ' + gl.getProgramInfoLog(program));
+        }
+        
+        gl.deleteShader(vertexShader);
+        gl.deleteShader(fragmentShader);
+
+        return program;
+    };
+
+    /**
+     * 初始化数据缓存
+     */
+    RenderManager.prototype.initBuffers = function() {
+        
+        var gl = this.contextGL;
+    
+        var vertexPosBuffer = gl.createBuffer();
+        gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
+        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 1, -1, 1, 1, -1, -1, -1]), gl.STATIC_DRAW);
+        gl.bindBuffer(gl.ARRAY_BUFFER, null);
+
+        var texturePosBuffer = gl.createBuffer();
+        gl.bindBuffer(gl.ARRAY_BUFFER, texturePosBuffer);
+        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 0, 0, 0, 1, 1, 0, 1]), gl.DYNAMIC_DRAW);
+        gl.bindBuffer(gl.ARRAY_BUFFER, null);
+
+        this.vertexPosBuffer  = vertexPosBuffer;
+        this.texturePosBuffer = texturePosBuffer;
+    };
+
+    /**
+     * 创建纹理
+     */
+    RenderManager.prototype.initTexture = function() {
+
+        var gl = this.contextGL;
+
+        var textureRef = gl.createTexture();
+        gl.bindTexture(gl.TEXTURE_2D, textureRef);
+        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+        gl.bindTexture(gl.TEXTURE_2D, null);
+
+        return textureRef;
+    };
+
+    /**
+     * 初始化YUV纹理
+     */
+    RenderManager.prototype.initTextures = function() {
+        
+        var gl = this.contextGL;
+        
+        var program = this.YUVProgram;
+        gl.useProgram(program);
+        
+        var yTextureRef = this.initTexture();
+        var ySamplerRef = gl.getUniformLocation(program, 'ySampler');
+        gl.uniform1i(ySamplerRef, 0);
+        this.yTextureRef = yTextureRef;
+
+        var uTextureRef = this.initTexture();
+        var uSamplerRef = gl.getUniformLocation(program, 'uSampler');
+        gl.uniform1i(uSamplerRef, 1);
+        this.uTextureRef = uTextureRef;
+
+        var vTextureRef = this.initTexture();
+        var vSamplerRef = gl.getUniformLocation(program, 'vSampler');
+        gl.uniform1i(vSamplerRef, 2);
+        this.vTextureRef = vTextureRef;
+        
+        gl.useProgram(null);
+    };
+
+    /**
+     * 显示帧数据
+     * @param nWidth    宽度
+     * @param nHeight   高度
+     * @param nHeight   帧数据
+     */
+    RenderManager.prototype.SR_DisplayFrameData = function(nWidth, nHeight, pData,dWidth,dHeight) {
+
+        if(nWidth <= 0 || nHeight <= 0)
+        {
+            return;
+        }
+
+        var gl = this.contextGL;
+
+        if(null == pData)
+        {
+            gl.clearColor(0.0, 0.0, 0.0, 0.0);
+            gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+            return;
+        }
+
+        var canvas = this.canvasElement;
+
+        this.nWindowWidth = canvas.width;
+        this.nWindowHeight = canvas.height;
+        
+        var nWindowWidth = this.nWindowWidth;
+        var nWindowHeight = this.nWindowHeight;
+
+        gl.clearColor(0.8, 0.8, 1.0, 1.0);
+        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+        gl.viewport(0, 0, nWindowWidth, nWindowHeight);
+
+        this.updateFrameData(nWidth, nHeight, pData,dWidth,dHeight);
+
+        var program = this.YUVProgram;
+        gl.useProgram(program);
+
+        var vertexPosBuffer = this.vertexPosBuffer;
+        gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
+        var vertexPosRef = gl.getAttribLocation(program, 'vertexPos');
+        gl.enableVertexAttribArray(vertexPosRef);
+        gl.vertexAttribPointer(vertexPosRef, 2, gl.FLOAT, false, 0, 0);
+        gl.bindBuffer(gl.ARRAY_BUFFER, null);
+
+        var texturePosBuffer = this.texturePosBuffer;
+        gl.bindBuffer(gl.ARRAY_BUFFER, texturePosBuffer);
+        var texturePosRef = gl.getAttribLocation(program, 'texturePos');
+        gl.enableVertexAttribArray(texturePosRef);
+        gl.vertexAttribPointer(texturePosRef, 2, gl.FLOAT, false, 0, 0);
+        gl.bindBuffer(gl.ARRAY_BUFFER, null);
+
+        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 
+
+        gl.disableVertexAttribArray(vertexPosRef);
+        gl.disableVertexAttribArray(texturePosRef);
+
+        gl.useProgram(null);
+    };
+
+    /**
+     * 上传YUV数据到纹理
+     * @param nWidth    宽度
+     * @param nHeight   高度
+     * @param nHeight   帧数据
+     */
+    RenderManager.prototype.updateFrameData = function(width, height, data,dWidth,dHeight) {
+
+        var gl = this.contextGL;
+
+        var yTextureRef = this.yTextureRef;
+        var uTextureRef = this.uTextureRef;
+        var vTextureRef = this.vTextureRef;
+
+        var i420Data = data;
+        // debugger;
+		if(width == dWidth && height == dHeight)
+		{
+			var yDataLength = width * height;
+			var yData = i420Data.subarray(0, yDataLength);
+			gl.activeTexture(gl.TEXTURE0);
+			gl.bindTexture(gl.TEXTURE_2D, yTextureRef);
+			gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, width, height, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, yData);
+			
+			var cbDataLength = width/2 * height/2;
+			var cbData = i420Data.subarray(width*height, width*height + cbDataLength);
+			gl.activeTexture(gl.TEXTURE1);
+			gl.bindTexture(gl.TEXTURE_2D, uTextureRef);
+			gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, width/2, height/2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, cbData);
+			
+			var crDataLength = cbDataLength;
+			var crData = i420Data.subarray(width*height + width*height/4, width*height + width*height/4 + crDataLength);
+			gl.activeTexture(gl.TEXTURE2);
+			gl.bindTexture(gl.TEXTURE_2D, vTextureRef);
+			gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, width/2, height/2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, crData);
+			
+		}
+        else
+		{
+			 // //裁剪宽
+			var yDataLength = dWidth * dHeight;
+			var yData=new Uint8Array(yDataLength) ;
+			for(var i=0;i<dHeight;i++)
+			{
+				//var ySonData=new Uint8Array(dWidth) ;
+				var ySonData = i420Data.subarray(i*width, i*width+dWidth);
+				for (var j = 0; j < dWidth; j++) {
+					yData[i*dWidth + j] = ySonData[j];
+				}
+			}
+			gl.activeTexture(gl.TEXTURE0);
+			gl.bindTexture(gl.TEXTURE_2D, yTextureRef);
+			gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, dWidth, dHeight, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, yData);
+			yData=null;
+			ySonData=null;
+
+			var cbDataLength = dWidth/2 * dHeight/2;
+			var cbData =new Uint8Array(cbDataLength);
+			//var cbSonData=new Uint8Array(dWidth/2) ;
+			for(var i=0;i<dHeight/2;i++)
+			{
+				 var cbSonData = i420Data.subarray(width*height+i*width/2, width*height+i*width/2+dWidth/2);
+				for (var j = 0; j < dWidth/2; j++) {
+					cbData[i*dWidth/2 + j] = cbSonData[j];
+				}
+			}
+			gl.activeTexture(gl.TEXTURE1);
+			gl.bindTexture(gl.TEXTURE_2D, uTextureRef);
+			gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, dWidth/2, dHeight/2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, cbData);
+			cbData=null;
+			cbSonData=null;
+
+			var crDataLength = cbDataLength;
+			var crData = new Uint8Array(crDataLength);
+			for(var i=0;i<dHeight/2;i++)
+			{
+				var crSonData = i420Data.subarray(width*height*5/4+i*width/2, width*height*5/4+i*width/2+dWidth/2);
+				for (var j = 0; j < dWidth/2; j++) {
+					crData[i*dWidth/2 + j] = crSonData[j];
+				}
+			}
+			gl.activeTexture(gl.TEXTURE2);
+			gl.bindTexture(gl.TEXTURE_2D, vTextureRef);
+			gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, dWidth/2, dHeight/2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, crData);
+			crData=null;
+			crSonData=null;
+		}
+       
+    };
+
+    /**
+     * 设置显示区域
+     * @param stDisplayRect    显示区域
+     */
+    RenderManager.prototype.SR_SetDisplayRect = function(stDisplayRect) {
+
+        var gl = this.contextGL;
+
+        var nWindowWidth = this.nWindowWidth;
+        var nWindowHeight = this.nWindowHeight;
+        
+        var texturePosValues = null;
+        
+        if(stDisplayRect && nWindowWidth > 0 && nWindowHeight > 0) {
+            var fLeft = stDisplayRect.left / nWindowWidth;
+            var fTop = stDisplayRect.top / nWindowHeight;
+            var fRight = stDisplayRect.right / nWindowWidth;
+            var fBottom = stDisplayRect.bottom / nWindowHeight;
+
+            texturePosValues = new Float32Array([fRight, fTop, fLeft, fTop, fRight, fBottom, fLeft, fBottom]);
+        }
+        else {
+            texturePosValues = new Float32Array([1, 0, 0, 0, 1, 1, 0, 1]);
+        }
+
+        var texturePosBuffer = this.texturePosBuffer;
+
+        gl.bindBuffer(gl.ARRAY_BUFFER, texturePosBuffer);
+        gl.bufferSubData(gl.ARRAY_BUFFER, 0, texturePosValues);
+        gl.bindBuffer(gl.ARRAY_BUFFER, null);
+    };
+
+    /**
+     * 释放显示资源
+     */
+    RenderManager.prototype.SR_Destroy = function() {
+
+        var gl = this.contextGL;
+        
+        var YUVProgram = this.YUVProgram;
+        gl.deleteProgram(YUVProgram);
+
+        var vertexPosBuffer = this.vertexPosBuffer;
+        var texturePosBuffer = this.texturePosBuffer;
+        
+        gl.deleteBuffer(vertexPosBuffer);
+        gl.deleteBuffer(texturePosBuffer);
+
+        var yTextureRef = this.yTextureRef;
+        var uTextureRef = this.uTextureRef;
+        var vTextureRef = this.vTextureRef;
+        gl.deleteTexture(yTextureRef);
+        gl.deleteTexture(uTextureRef);
+        gl.deleteTexture(vTextureRef);
+		//gl.getExtension('WEBGL_lose_context').loseContext();
+    };
+
+    return RenderManager;
+
+}));

File diff suppressed because it is too large
+ 8 - 0
src/plugins/hkws/playctrl2/Decoder.js


BIN
src/plugins/hkws/playctrl2/Decoder.wasm


File diff suppressed because it is too large
+ 0 - 0
src/plugins/hkws/playctrl2/Decoder.worker.js


File diff suppressed because it is too large
+ 8 - 0
src/plugins/hkws/playctrl3/Decoder.js


BIN
src/plugins/hkws/playctrl3/Decoder.wasm


File diff suppressed because it is too large
+ 0 - 0
src/plugins/hkws/playctrl3/Decoder.worker.js


File diff suppressed because it is too large
+ 2907 - 0
src/plugins/hkws/talk/AudioInterCom.js


BIN
src/plugins/hkws/talk/AudioInterCom.wasm


File diff suppressed because it is too large
+ 3492 - 0
src/plugins/hkws/talkW/AudioInterCom.js


BIN
src/plugins/hkws/talkW/AudioInterCom.wasm


+ 234 - 0
src/plugins/hkws/talkW/AudioInterCom.worker.js

@@ -0,0 +1,234 @@
+/**
+ * @license
+ * Copyright 2015 The Emscripten Authors
+ * SPDX-License-Identifier: MIT
+ */
+
+// Pthread Web Worker startup routine:
+// This is the entry point file that is loaded first by each Web Worker
+// that executes pthreads on the Emscripten application.
+
+// Thread-local:
+var initializedJS = false; // Guard variable for one-time init of the JS state (currently only embind types registration)
+
+var Module = {};
+
+function assert(condition, text) {
+  if (!condition) abort('Assertion failed: ' + text);
+}
+
+function threadPrintErr() {
+  var text = Array.prototype.slice.call(arguments).join(' ');
+  console.error(text);
+}
+function threadAlert() {
+  var text = Array.prototype.slice.call(arguments).join(' ');
+  postMessage({cmd: 'alert', text: text, threadId: Module['_pthread_self']()});
+}
+// We don't need out() for now, but may need to add it if we want to use it
+// here. Or, if this code all moves into the main JS, that problem will go
+// away. (For now, adding it here increases code size for no benefit.)
+var out = function() {
+  throw 'out() is not defined in worker.js.';
+}
+var err = threadPrintErr;
+this.alert = threadAlert;
+
+Module['instantiateWasm'] = function(info, receiveInstance) {
+  // Instantiate from the module posted from the main thread.
+  // We can just use sync instantiation in the worker.
+  var instance = new WebAssembly.Instance(Module['wasmModule'], info);
+  // TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193,
+  // the above line no longer optimizes out down to the following line.
+  // When the regression is fixed, we can remove this if/else.
+  receiveInstance(instance);
+  // We don't need the module anymore; new threads will be spawned from the main thread.
+  Module['wasmModule'] = null;
+  return instance.exports;
+};
+
+function moduleLoaded() {
+}
+
+this.onmessage = function(e) {
+  try {
+    if (e.data.cmd === 'load') { // Preload command that is called once per worker to parse and load the Emscripten code.
+
+      // Module and memory were sent from main thread
+      Module['wasmModule'] = e.data.wasmModule;
+
+      Module['wasmMemory'] = e.data.wasmMemory;
+
+      Module['buffer'] = Module['wasmMemory'].buffer;
+
+      Module['ENVIRONMENT_IS_PTHREAD'] = true;
+
+      if (typeof e.data.urlOrBlob === 'string') {
+        importScripts(e.data.urlOrBlob);
+      } else {
+        var objectUrl = URL.createObjectURL(e.data.urlOrBlob);
+        importScripts(objectUrl);
+        URL.revokeObjectURL(objectUrl);
+      }
+      JSAudioInterComModule(Module).then(function (instance) {
+        Module = instance;
+        moduleLoaded();
+      });
+
+    } else if (e.data.cmd === 'objectTransfer') {
+      Module['PThread'].receiveObjectTransfer(e.data);
+    } else if (e.data.cmd === 'run') {
+      // This worker was idle, and now should start executing its pthread entry
+      // point.
+      // performance.now() is specced to return a wallclock time in msecs since
+      // that Web Worker/main thread launched. However for pthreads this can
+      // cause subtle problems in emscripten_get_now() as this essentially
+      // would measure time from pthread_create(), meaning that the clocks
+      // between each threads would be wildly out of sync. Therefore sync all
+      // pthreads to the clock on the main browser thread, so that different
+      // threads see a somewhat coherent clock across each of them
+      // (+/- 0.1msecs in testing).
+      Module['__performance_now_clock_drift'] = performance.now() - e.data.time;
+
+      // Pass the thread address inside the asm.js scope to store it for fast access that avoids the need for a FFI out.
+      Module['__emscripten_thread_init'](e.data.threadInfoStruct, /*isMainBrowserThread=*/0, /*isMainRuntimeThread=*/0);
+
+      // Establish the stack frame for this thread in global scope
+      // The stack grows downwards
+      var max = e.data.stackBase;
+      var top = e.data.stackBase + e.data.stackSize;
+      assert(e.data.threadInfoStruct);
+      assert(top != 0);
+      assert(max != 0);
+      assert(top > max);
+      // Also call inside JS module to set up the stack frame for this pthread in JS module scope
+      Module['establishStackSpace'](top, max);
+      Module['PThread'].receiveObjectTransfer(e.data);
+      Module['PThread'].threadInit();
+
+      // Embind must initialize itself on all threads, as it generates support JS.
+      // We only do this once per worker since they get reused
+      if (!initializedJS) {
+        Module['___embind_register_native_and_builtin_types']();
+        initializedJS = true;
+      }
+
+      try {
+        // pthread entry points are always of signature 'void *ThreadMain(void *arg)'
+        // Native codebases sometimes spawn threads with other thread entry point signatures,
+        // such as void ThreadMain(void *arg), void *ThreadMain(), or void ThreadMain().
+        // That is not acceptable per C/C++ specification, but x86 compiler ABI extensions
+        // enable that to work. If you find the following line to crash, either change the signature
+        // to "proper" void *ThreadMain(void *arg) form, or try linking with the Emscripten linker
+        // flag -s EMULATE_FUNCTION_POINTER_CASTS=1 to add in emulation for this x86 ABI extension.
+        var result = Module['invokeEntryPoint'](e.data.start_routine, e.data.arg);
+
+        Module['checkStackCookie']();
+        if (Module['keepRuntimeAlive']()) {
+          Module['PThread'].setExitStatus(result);
+        } else {
+          Module['PThread'].threadExit(result);
+        }
+      } catch(ex) {
+        if (ex === 'Canceled!') {
+          Module['PThread'].threadCancel();
+        } else if (ex != 'unwind') {
+          // FIXME(sbc): Figure out if this is still needed or useful.  Its not
+          // clear to me how this check could ever fail.  In order to get into
+          // this try/catch block at all we have already called bunch of
+          // functions on `Module`.. why is this one special?
+          if (typeof(Module['_emscripten_futex_wake']) !== "function") {
+            err("Thread Initialisation failed.");
+            throw ex;
+          }
+          // ExitStatus not present in MINIMAL_RUNTIME
+          if (ex instanceof Module['ExitStatus']) {
+            if (Module['keepRuntimeAlive']()) {
+              err('Pthread 0x' + Module['_pthread_self']().toString(16) + ' called exit(), staying alive due to noExitRuntime.');
+            } else {
+              err('Pthread 0x' + Module['_pthread_self']().toString(16) + ' called exit(), calling threadExit.');
+              Module['PThread'].threadExit(ex.status);
+            }
+          }
+          else
+          {
+            Module['PThread'].threadExit(-2);
+            throw ex;
+          }
+        } else {
+          // else e == 'unwind', and we should fall through here and keep the pthread alive for asynchronous events.
+          err('Pthread 0x' + Module['_pthread_self']().toString(16) + ' completed its pthread main entry point with an unwind, keeping the pthread worker alive for asynchronous operation.');
+        }
+      }
+    } else if (e.data.cmd === 'cancel') { // Main thread is asking for a pthread_cancel() on this thread.
+      if (Module['_pthread_self']()) {
+        Module['PThread'].threadCancel();
+      }
+    } else if (e.data.target === 'setimmediate') {
+      // no-op
+    } else if (e.data.cmd === 'processThreadQueue') {
+      if (Module['_pthread_self']()) { // If this thread is actually running?
+        Module['_emscripten_current_thread_process_queued_calls']();
+      }
+    } else {
+      err('worker.js received unknown command ' + e.data.cmd);
+      err(e.data);
+    }
+  } catch(ex) {
+    err('worker.js onmessage() captured an uncaught exception: ' + ex);
+    if (ex && ex.stack) err(ex.stack);
+    throw ex;
+  }
+};
+
+// Node.js support
+if (typeof process === 'object' && typeof process.versions === 'object' && typeof process.versions.node === 'string') {
+  // Create as web-worker-like an environment as we can.
+  self = {
+    location: {
+      href: __filename
+    }
+  };
+
+  var onmessage = this.onmessage;
+
+  var nodeWorkerThreads = require('worker_threads');
+
+  global.Worker = nodeWorkerThreads.Worker;
+
+  var parentPort = nodeWorkerThreads.parentPort;
+
+  parentPort.on('message', function(data) {
+    onmessage({ data: data });
+  });
+
+  var nodeFS = require('fs');
+
+  var nodeRead = function(filename) {
+    return nodeFS.readFileSync(filename, 'utf8');
+  };
+
+  function globalEval(x) {
+    global.require = require;
+    global.Module = Module;
+    eval.call(null, x);
+  }
+
+  importScripts = function(f) {
+    globalEval(nodeRead(f));
+  };
+
+  postMessage = function(msg) {
+    parentPort.postMessage(msg);
+  };
+
+  if (typeof performance === 'undefined') {
+    performance = {
+      now: function() {
+        return Date.now();
+      }
+    };
+  }
+}
+
+

File diff suppressed because it is too large
+ 2733 - 0
src/plugins/hkws/transform/libSystemTransform.js


BIN
src/plugins/hkws/transform/libSystemTransform.wasm


+ 120 - 0
src/plugins/hkws/transform/systemTransform-worker.js

@@ -0,0 +1,120 @@
+importScripts('libSystemTransform.js');
+    const RECORDRTP = 0;  //录制一份未经过转封装的码流原始数据,用于定位问题
+    let dataType = 1;
+    
+    // 转封装库回调函数
+    self.STCallBack = function (fileIndex,indexLen, data, dataLen)
+    {
+        //stFrameInfo的类型见DETAIL_FRAME_INFO
+		let stFrameInfo = Module._GetDetialFrameInfo();
+        let nIsMp4Index = stFrameInfo.nIsMp4Index;
+		//console.log("FrameType is " , stFrameInfo);	
+		//console.log("nIsMp4Index is " + nIsMp4Index);
+        //debugger
+        var pData = null;
+        pData = new Uint8Array(dataLen);
+        pData.set(Module.HEAPU8.subarray(data, data + dataLen));
+        if (dataType === 1) {
+            if (pData[0] == 0x49 && pData[1] == 0x4d && pData[2] == 0x4b && pData[3] == 0x48) {//码流头丢掉
+                return;
+            }
+            postMessage({type: "outputData", buf: pData, dType: 1});
+            dataType = 2;
+        } else {
+            if (nIsMp4Index) {
+                postMessage({type: "outputData", buf: pData, dType: 6}); //6:索引类型
+            } else {
+                postMessage({type: "outputData", buf: pData, dType: 2}); //2:码流
+            }
+        }
+
+        //stFrameInfo的类型见DETAIL_FRAME_INFO
+		//let stFrameInfo = Module._GetDetialFrameInfo();
+		//let stFrameType = stFrameInfo.nFrameType;
+		//let nFrameNum = stFrameInfo.nFrameNum;
+		//let nTimeStamp = stFrameInfo.nTimeStamp;
+        //let nIsMp4Index = stFrameInfo.nIsMp4Index;
+		
+		//console.log("FrameType is " + stFrameType);	
+		//console.log("nIsMp4Index is " + nIsMp4Index);	
+        
+    }
+
+    // self.Module = { memoryInitializerRequest: loadMemInitFile(), TOTAL_MEMORY: 128*1024*1024 };
+    // importScripts('SystemTransform.js');
+
+    self.Module['onRuntimeInitialized'] = function (){
+        postMessage({type: "loaded"});
+    }
+    onmessage = function (e) {
+        var data = e.data;
+        if ("create" === data.type) {
+            if (RECORDRTP) {
+                postMessage({type: "created"});
+                postMessage({type: "outputData", buf: data.buf, dType: 1});
+            } else {
+                var iHeadLen = data.len;
+                var pHead = Module._malloc(iHeadLen);
+    
+                self.writeArrayToMemory(new Uint8Array(data.buf), pHead);
+                var iTransType = data.packType;//目标格式
+                var iRet = Module._CreatHandle(pHead, iTransType, 4096);
+                if (iRet != 0) {
+                    console.log("_CreatHandle failed!" + iRet);
+                } else {
+                    iRet = Module._SysTransRegisterDataCallBack();			
+                    if(iRet != 0)
+                    {
+                        console.log("_SysTransRegisterDataCallBack Failed:" + iRet);
+                    }
+
+                    iRet = Module._SysTransStart(null, null);
+                    if(iRet != 0)
+                    {
+                        console.log("_SysTransStart Failed:" + iRet);
+                    }
+                    postMessage({type: "created"});
+                }
+            }
+
+        } else if ("inputData" === data.type) {
+            if (RECORDRTP) {
+                var aFileData = new Uint8Array(data.buf);  // 拷贝一份
+                var iBufferLen = aFileData.length;
+                var szBufferLen = iBufferLen.toString(16);
+                if (szBufferLen.length === 1) {
+                    szBufferLen = "000" + szBufferLen;
+                } else if (szBufferLen.length === 2) {
+                    szBufferLen = "00" + szBufferLen;
+                } else if (szBufferLen.length === 3) {
+                    szBufferLen = "0" + szBufferLen;
+                }
+                var aData = [0, 0, parseInt(szBufferLen.substring(0, 2), 16), parseInt(szBufferLen.substring(2, 4), 16)];
+                for(var iIndex = 0, iDataLength = aFileData.length; iIndex < iDataLength; iIndex++) {
+                    aData[iIndex + 4] = aFileData[iIndex]
+                }
+                var dataUint8 = new Uint8Array(aData);
+                postMessage({type: "outputData", buf: dataUint8.buffer, dType: 2});
+            } else {
+                let pInputDataBuf = Module._malloc(data.len);
+                var idataLen = data.len;
+                self.writeArrayToMemory(new Uint8Array(data.buf), pInputDataBuf);
+                    // 输入数据,每次最多2m
+                let pp = Module._SysTransInputData(0, pInputDataBuf, idataLen);
+                if(pp != 0) {
+                    //console.log("InputData Failed:" + pp);
+                }
+                Module._free(pInputDataBuf);
+            }
+        } else if ("release" === data.type) {
+            var iRet = Module._SysTransStop();
+            if (iRet != 0) {
+                console.log("_SysTransStop Failed:", iRet);
+            }
+            Module._SysTransRelease();
+            if (iRet != 0) {
+                console.log("_SysTransRelease Failed:", iRet);
+            }
+            close();
+        }
+    };

+ 16 - 3
src/stores/index.js

@@ -58,10 +58,21 @@ const userStore = defineStore('ioc-user', {
         token: '',
     }),
     getters: {
-        userToken: state => state.token,
-        userInfo: state => state.userInfo,
+        getToken: state => state.token,
     },
-    actions: {},
+    actions: {
+        setToken(token) {
+            this.token = token;
+        },
+        setUserInfo(obj) {
+            this.userInfo = obj;
+        },
+        logout() {
+            this.token = '';
+            this.userInfo = {};
+        }
+    },
+    persist: true
 })
 
 const paramStore = defineStore('ioc-param', {
@@ -80,6 +91,8 @@ const loadingStore = defineStore('ioc-loading', {
             this.open();
             func.then(()=>{
                 this.close(delay)
+            }).catch(err=>{
+                this.close()
             })
         },
         open() {

+ 11 - 0
src/utils/dateUtil.js

@@ -12,6 +12,16 @@ const getNearlyMonthRange = () => {
     };
 }
 
+// 获取当前周日期范围
+const getCurrWeekRange = () => {
+    let startDate = moment().weekday(0).format(dateFormat);
+    let endDate =moment().weekday(6).format(dateFormat);
+    return {
+        startDate: startDate,
+        endDate: endDate
+    };
+}
+
 // 获取当前日期时间
 const getCurrDateTime = () => {
     return moment().format(dateTimeFormat);
@@ -19,5 +29,6 @@ const getCurrDateTime = () => {
 
 export default {
     getNearlyMonthRange,
+    getCurrWeekRange,
     getCurrDateTime,
 }

+ 7 - 1
src/utils/request.js

@@ -1,6 +1,8 @@
 import axios from 'axios'
 import qs from 'qs'
 import { message } from 'ant-design-vue'
+import router from "@/router";
+import stores from "@/stores";
 
 // 创建 axios 实例
 const service = axios.create({
@@ -54,11 +56,15 @@ function req(method, url, params) {
       url,
       data: params,
       headers: {
-
+        "token": stores.userStore().token
       },
     }).then((response) => {
       if (response.data.code == 200) {
         resolve(response.data.data)
+      } else if (response.data.code == 203) {
+        router.push('/login');
+      } else {
+        message.error(response.data.msg)
       }
     }).catch((err) => {
       message.error(err.message)

+ 25 - 6
src/views/LoginView.vue

@@ -1,10 +1,12 @@
 <script>
 import userData from "@/data/json/user.json"
+import apiLogin from "@/api/system/apiLogin";
 
 export default {
   data() {
     return {
       userData,
+      loginLoading: false,
       form: {
         code: '',
         username: '',
@@ -25,10 +27,27 @@ export default {
     callback(key) {
       //console.log(key);
     },
+    onChange(val) {
+      console.log(val)
+    },
     handleSubmit() {
+      let app = this;
+      app.loginLoading = true;
       let valid = this.GVerify.validate(this.form.code)
       if (valid) {
-
+        apiLogin.login(this.form).then(res=>{
+          app.loginLoading = false;
+          app.$store.userStore().setToken(res.token);
+          app.$store.userStore().setUserInfo(res.userInfo);
+          app.$message.success("登录成功")
+          app.$router.push("/")
+        }).catch(err=>{
+          app.loginLoading = false;
+        })
+      } else {
+        this.$message.error("验证码错误");
+        this.GVerify.refresh();
+        app.loginLoading = false;
       }
     }
   },
@@ -44,23 +63,23 @@ export default {
           <div class="loginForm">
             <a-form :form="form">
               <a-form-item>
-                <a-input v-model="form.username" style="height: 40px;" placeholder="账户/邮件账户">
+                <a-input v-model="form.username" style="height: 40px;letter-spacing: 1px" placeholder="账户/邮件账户" @keyup.enter.native="handleSubmit">
                   <a-icon slot="prefix" type="user" style="font-size: 16px;height: 25px;color: #a8a8a8;"/>
                 </a-input>
               </a-form-item>
               <a-form-item>
-                <a-input-password v-model="form.password" style="height: 40px" placeholder="密码">
+                <a-input-password v-model="form.password" style="height: 40px;letter-spacing: 1px" placeholder="密码" @keyup.enter.native="handleSubmit">
                   <a-icon slot="prefix" type="lock" style="font-size: 16px;height: 23px;color: #a8a8a8"/>
                 </a-input-password>
               </a-form-item>
               <a-form-item>
-                <a-input v-model="form.code" placeholder="请输入验证码"
-                         style="width: 200px;height: 32px;display: inline-block;vertical-align: middle"/>
+                <a-input v-model="form.code" placeholder="请输入验证码" :maxLength="4" @keyup.enter.native="handleSubmit"
+                         style="width: 200px;height: 32px;display: inline-block;vertical-align: middle;letter-spacing: 2px"/>
                 <div id="verify-code" title="点击更换"></div>
               </a-form-item>
               <a-form-item>
                 <div style="height: 20px"></div>
-                <a-button type="primary" @click="handleSubmit"
+                <a-button type="primary" @click="handleSubmit" :loading="loginLoading"
                           style="width: 100%;height: 32px;font-size: 17px;letter-spacing: 5px">
                   登录
                 </a-button>

Some files were not shown because too many files changed in this diff