无人机管理后台前端(已迁走)
张含笑
2025-06-07 42082b9f915d9e4008eb8250be28cbd3f3c61795
Merge branch 'refs/heads/master' into feature/v2.0.0/后台管理数据中心
23 files modified
13 files added
990 ■■■■ changed files
index.html 18 ●●●●● patch | view | raw | blame | history
public/img/bg/mainLogo.png patch | view | raw | blame | history
src/api/device-setting/index.js 57 ●●●●● patch | view | raw | blame | history
src/assets/images/layoutBg.png patch | view | raw | blame | history
src/assets/images/workbench/db1.svg 10 ●●●●● patch | view | raw | blame | history
src/assets/images/workbench/db2.svg 12 ●●●●● patch | view | raw | blame | history
src/assets/images/workbench/db3.svg 10 ●●●●● patch | view | raw | blame | history
src/assets/images/workbench/db4.svg 10 ●●●●● patch | view | raw | blame | history
src/assets/images/workbench/db5.svg 5 ●●●●● patch | view | raw | blame | history
src/assets/images/workbench/ev1.svg 10 ●●●●● patch | view | raw | blame | history
src/assets/images/workbench/ev2.svg 10 ●●●●● patch | view | raw | blame | history
src/assets/images/workbench/fy1.svg 5 ●●●●● patch | view | raw | blame | history
src/assets/images/workbench/jc1.svg 5 ●●●●● patch | view | raw | blame | history
src/assets/images/workbench/st7.svg 11 ●●●●● patch | view | raw | blame | history
src/page/index/index.vue 10 ●●●●● patch | view | raw | blame | history
src/page/index/logo.vue 41 ●●●● patch | view | raw | blame | history
src/page/index/setting.vue 8 ●●●● patch | view | raw | blame | history
src/page/index/sidebar/index.vue 22 ●●●●● patch | view | raw | blame | history
src/page/index/tags.vue 6 ●●●●● patch | view | raw | blame | history
src/page/index/top/index.vue 29 ●●●●● patch | view | raw | blame | history
src/page/index/top/top-lock.vue 2 ●●● patch | view | raw | blame | history
src/page/index/top/top-qna.vue 17 ●●●●● patch | view | raw | blame | history
src/page/index/top/top-search.vue 16 ●●●●● patch | view | raw | blame | history
src/permission copy 2.js 71 ●●●●● patch | view | raw | blame | history
src/permission copy.js 133 ●●●●● patch | view | raw | blame | history
src/permission.js 62 ●●●●● patch | view | raw | blame | history
src/styles/common.scss 2 ●●● patch | view | raw | blame | history
src/styles/theme/white.scss 5 ●●●●● patch | view | raw | blame | history
src/styles/top.scss 5 ●●●●● patch | view | raw | blame | history
src/views/device/components/DockControlPanel.vue 207 ●●●●● patch | view | raw | blame | history
src/views/system/user.vue 131 ●●●● patch | view | raw | blame | history
src/views/system/userinfo.vue 13 ●●●● patch | view | raw | blame | history
src/views/tickets/orderLog.vue 27 ●●●●● patch | view | raw | blame | history
src/views/wel/components/backlog.vue 12 ●●●● patch | view | raw | blame | history
src/views/wel/components/calendarBox.vue 4 ●●●● patch | view | raw | blame | history
src/views/wel/index.vue 4 ●●●● patch | view | raw | blame | history
index.html
@@ -12,6 +12,7 @@
  <meta name="apple-mobile-web-app-status-bar-style" content="black" />
  <meta name="format-detection" content="telephone=no" />
  <link rel="icon" href="/img/bg/index_logo2.png" />
  <link rel="stylesheet" href="/fonts/font.css" />
  <link rel="stylesheet" href="/iconfont/index.css" />
  <link rel="stylesheet" href="/iconfont/avue/iconfont.css" />
  <link rel="stylesheet" href="/iconfont/saber/iconfont.css" />
@@ -34,17 +35,14 @@
<body class="theme-white">
  <div id="app">
    <div id="loader-wrapper">
      <!-- <div class='loader-box'>
      <span>无</span>
      <span>人</span>
      <span>机</span>
      <span>后</span>
      <span>台</span>
       <div class='loader-box'>
      <span>综</span>
      <span>合</span>
      <span>管</span>
      <span>理</span>
      <span>系</span>
      <span>统</span>
    </div> -->
      <span>平</span>
      <span>台</span>
    </div>
      <div class="loader-title">系统加载中</div>
    </div>
  </div>
@@ -72,4 +70,4 @@
    });
  </script> -->
</html>
</html>
public/img/bg/mainLogo.png

src/api/device-setting/index.js
@@ -29,10 +29,65 @@
 */
export const setThermalCurrentPaletteStyle = (deviceSn, workspaceId, param) => {
  return request({
    // /manage/api/v1/devices/selectDevicePage
    // url: `/localApi/manage/api/v1/devices/${workspaceId}/devices/${deviceSn}/setThermalCurrentPaletteStyle`,
    url: `/drone-device-core/manage/api/v1/devices/${workspaceId}/devices/${deviceSn}/setThermalCurrentPaletteStyle`,
    method: 'put',
    data: param,
  })
}
/**
 * 照片存储设置
 * @param {机场编码} sn
 * @param {*} body
 * @returns
 */
export const setPhotoStorageSet = (sn, param) => {
  return request({
    //  url: `/localApi/control/api/v1/devices/${sn}/payload/photoStorageSet`,
    url: `/drone-device-core/control/api/v1/devices/${sn}/payload/photoStorageSet`,
    method: 'post',
    data: param,
  })
}
/**
 * 视频存储设置
 * @param {机场编码} sn
 * @param {*} body
 * @returns
 */
export const setVideoStorageSet = (sn, param) => {
  return request({
    //  url: `/localApi/control/api/v1/devices/${sn}/payload/videoStorageSet`,
    url: `/drone-device-core/control/api/v1/devices/${sn}/payload/videoStorageSet`,
    method: 'post',
    data: param
    ,
  })
}
// 获取live_status
export const getLiveStatus = (sn) => {
  return request({
    url: `/drone-device-core/manage/api/v1/live/getLiveStatus/${sn}`,
    method: 'get',
  })
}
// 视频流设置方法
export const setStreamsSwitch = (param) => {
  return request({
    url: `/drone-device-core/manage/api/v1/live/streams/switch`,
    method: 'post',
    data: param
  })
}
// 控制台-云台拍照录像动作
export const photoAndVideoCmd = (droneSn,mode) => {
  return request({
    url: `/drone-device-core/droneAirport/liveStreamApi/switch/vedioMode`,
    method: 'get',
    params: {
      droneSn,
      mode
    }
   })
}
src/assets/images/layoutBg.png
src/assets/images/workbench/db1.svg
New file
@@ -0,0 +1,10 @@
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Frame" clip-path="url(#clip0_843_2377)">
<path id="Vector" d="M12.8436 8.56691H10.8438C10.4004 8.56691 10 8.30177 9.8269 7.89366L9.14253 6.28043C9.04321 6.0462 9.10693 5.77784 9.29619 5.60778C9.97222 5.00074 10.3389 4.05724 10.1235 3.03771C9.91055 2.02843 9.09404 1.21281 8.08433 1.00201C6.35288 0.640491 4.82856 1.95211 4.82856 3.61984C4.82856 4.42272 5.18467 5.13888 5.74526 5.62843C5.94038 5.79879 6.00938 6.07096 5.90815 6.30944L5.23608 7.89366C5.06294 8.30177 4.66245 8.56691 4.21919 8.56691H2.15449C1.85449 8.56691 1.61133 8.81007 1.61133 9.11007V11.238C1.61133 11.538 1.85449 11.7812 2.15449 11.7812H12.8436C13.1436 11.7812 13.3868 11.538 13.3868 11.238V9.11022C13.3869 8.81022 13.1438 8.56691 12.8436 8.56691ZM12.5893 12.8571H2.41772C2.26816 12.8571 2.14702 12.9783 2.14702 13.1278V13.6578C2.14702 13.8074 2.26816 13.9285 2.41772 13.9285H12.5893C12.7389 13.9285 12.86 13.8074 12.86 13.6578V13.1278C12.86 12.9784 12.7389 12.8571 12.5893 12.8571Z" fill="#FF472F"/>
</g>
<defs>
<clipPath id="clip0_843_2377">
<rect width="15" height="15" fill="white"/>
</clipPath>
</defs>
</svg>
src/assets/images/workbench/db2.svg
New file
@@ -0,0 +1,12 @@
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Frame" clip-path="url(#clip0_845_1260)">
<path id="Vector" d="M12.054 10.9821H10.4468C10.1522 10.9821 9.91113 10.7411 9.91113 10.4464V8.57141H10.9826V9.9107H12.054V10.9821Z" fill="#FF472F"/>
<path id="Vector_2" d="M10.4467 13.6607C8.67885 13.6607 7.23242 12.2143 7.23242 10.4465C7.23242 8.67861 8.67885 7.23218 10.4467 7.23218C12.2146 7.23218 13.661 8.67861 13.661 10.4465C13.661 12.2143 12.2146 13.6607 10.4467 13.6607ZM10.4467 8.30361C9.26814 8.30361 8.30385 9.26789 8.30385 10.4465C8.30385 11.625 9.26814 12.5893 10.4467 12.5893C11.6253 12.5893 12.5896 11.625 12.5896 10.4465C12.5896 9.26789 11.6253 8.30361 10.4467 8.30361Z" fill="#FF472F"/>
<path id="Vector_3" d="M6.1603 10.4464H4.55315V9.37495H6.29422C6.42815 8.8928 6.61565 8.43745 6.9103 8.03566H4.55315V6.96423H7.95494C8.65137 6.4553 9.50851 6.16066 10.446 6.16066C11.4639 6.16066 12.4014 6.50888 13.1246 7.09816V1.87495C13.1246 1.5803 12.8835 1.33923 12.5889 1.33923H1.87458C1.57994 1.33923 1.33887 1.5803 1.33887 1.87495V13.1249C1.33887 13.4196 1.57994 13.6607 1.87458 13.6607H7.60672C6.7228 12.8839 6.1603 11.7321 6.1603 10.4464ZM4.55315 4.55352H9.9103V5.62495H4.55315V4.55352Z" fill="#FF472F"/>
</g>
<defs>
<clipPath id="clip0_845_1260">
<rect width="15" height="15" fill="white"/>
</clipPath>
</defs>
</svg>
src/assets/images/workbench/db3.svg
New file
@@ -0,0 +1,10 @@
<svg width="13" height="14" viewBox="0 0 13 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Frame" clip-path="url(#clip0_843_1275)">
<path id="Vector" d="M0.457105 13.997C0.390133 13.9968 0.323958 13.9813 0.262968 13.9515C0.201979 13.9217 0.14757 13.8783 0.10335 13.8241C0.0649838 13.7768 0.0366646 13.721 0.0203671 13.6607C0.0040695 13.6004 0.000185622 13.5369 0.00898619 13.4748C0.00631382 13.4108 0.0160936 13.3469 0.0376986 13.2871C0.0593035 13.2274 0.092257 13.1732 0.134447 13.128C0.176636 13.0828 0.227131 13.0476 0.282695 13.0246C0.338258 13.0017 0.397665 12.9914 0.457105 12.9947H2.00546V8.33733C2.00364 7.70546 2.11834 7.07949 2.3429 6.49572C2.56747 5.91196 2.89743 5.38203 3.31365 4.93667C4.1563 4.03019 5.29459 3.51434 6.48554 3.49923C7.67549 3.50133 8.816 4.01208 9.65648 4.91926C10.4969 5.82644 10.9686 7.05583 10.9679 8.33733V12.9977H12.5157C12.6443 12.9991 12.7674 13.0545 12.8587 13.1522C12.95 13.2498 13.0023 13.3819 13.0045 13.5205C13.0071 13.5844 12.9972 13.6482 12.9756 13.7079C12.9539 13.7675 12.9209 13.8216 12.8788 13.8666C12.8366 13.9117 12.7861 13.9468 12.7306 13.9697C12.6751 13.9926 12.6157 14.0027 12.5563 13.9994L0.457105 13.997ZM4.87897 9.24164H6.90992L6.3906 12.2473L8.94087 8.25456H6.90936L7.42924 5.24886L4.87897 9.24164ZM10.5655 5.28598L12.2111 4.44251C12.2687 4.40526 12.3332 4.38218 12.4 4.37492C12.4668 4.36766 12.5343 4.3764 12.5976 4.40052C12.7335 4.44194 12.8527 4.53077 12.9367 4.65307C12.9687 4.70656 12.9892 4.76711 12.9966 4.83025C13.0041 4.8934 12.9983 4.95754 12.9797 5.01796C12.9611 5.07838 12.9302 5.13354 12.8892 5.1794C12.8482 5.22525 12.7982 5.26063 12.7428 5.28293L11.099 6.12337L10.5655 5.28598ZM0.246896 5.24155C0.194356 5.21754 0.147118 5.18184 0.108279 5.13681C0.0694395 5.09177 0.0398745 5.0384 0.0215206 4.9802C0.00316666 4.92199 -0.00356191 4.86027 0.00177562 4.79908C0.00711316 4.73788 0.0243964 4.67859 0.052493 4.62509C0.0882376 4.56151 0.137753 4.5082 0.196802 4.46973C0.255851 4.43126 0.322676 4.40876 0.391559 4.40418C0.45532 4.37863 0.523711 4.36935 0.591362 4.37706C0.659014 4.38477 0.724086 4.40926 0.781471 4.44861L2.44002 5.33102L1.90375 6.12519L0.246896 5.24155ZM8.94029 2.92112L9.76536 1.13619C9.79484 1.07407 9.8355 1.01888 9.88497 0.973855C9.93445 0.928826 9.99175 0.89485 10.0535 0.873906C10.1521 0.865559 10.2511 0.883535 10.3417 0.926242C10.4468 1.01889 10.5202 1.14668 10.5502 1.28934C10.5802 1.432 10.5651 1.58136 10.5073 1.71373L9.68228 3.49925L8.94029 2.92112ZM2.50952 1.73808C2.44226 1.60978 2.42179 1.4591 2.45208 1.31543C2.48238 1.17175 2.56128 1.04538 2.67339 0.960941C2.71595 0.916167 2.77054 0.887002 2.8294 0.877604C2.88825 0.868207 2.94835 0.879056 3.00114 0.908605C3.05604 0.9321 3.10604 0.96712 3.14824 1.01163C3.19045 1.05614 3.224 1.10924 3.24696 1.16785L4.06636 2.92903L3.28821 3.49925L2.50952 1.73808ZM6.5036 2.62475V0.577527C6.495 0.441761 6.53364 0.307409 6.612 0.200646C6.69035 0.0938827 6.8028 0.0223558 6.92745 0C7.1744 0 7.31624 0.262295 7.31624 0.577527V2.62474L6.5036 2.62475Z" fill="#FF7411"/>
</g>
<defs>
<clipPath id="clip0_843_1275">
<rect width="13" height="14" fill="white"/>
</clipPath>
</defs>
</svg>
src/assets/images/workbench/db4.svg
New file
@@ -0,0 +1,10 @@
<svg width="13" height="14" viewBox="0 0 13 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Frame" clip-path="url(#clip0_843_1282)">
<path id="Vector" d="M0.457105 13.997C0.390133 13.9968 0.323958 13.9813 0.262968 13.9515C0.201979 13.9217 0.14757 13.8783 0.10335 13.8241C0.0649838 13.7768 0.0366646 13.721 0.0203671 13.6607C0.0040695 13.6004 0.000185622 13.5369 0.00898619 13.4748C0.00631382 13.4108 0.0160936 13.3469 0.0376986 13.2871C0.0593035 13.2274 0.092257 13.1732 0.134447 13.128C0.176636 13.0828 0.227131 13.0476 0.282695 13.0246C0.338258 13.0017 0.397665 12.9914 0.457105 12.9947H2.00546V8.33733C2.00364 7.70546 2.11834 7.07949 2.3429 6.49572C2.56747 5.91196 2.89743 5.38203 3.31365 4.93667C4.1563 4.03019 5.29459 3.51434 6.48554 3.49923C7.67549 3.50133 8.816 4.01208 9.65648 4.91926C10.4969 5.82644 10.9686 7.05583 10.9679 8.33733V12.9977H12.5157C12.6443 12.9991 12.7674 13.0545 12.8587 13.1522C12.95 13.2498 13.0023 13.3819 13.0045 13.5205C13.0071 13.5844 12.9972 13.6482 12.9756 13.7079C12.9539 13.7675 12.9209 13.8216 12.8788 13.8666C12.8366 13.9117 12.7861 13.9468 12.7306 13.9697C12.6751 13.9926 12.6157 14.0027 12.5563 13.9994L0.457105 13.997ZM4.87897 9.24164H6.90992L6.3906 12.2473L8.94087 8.25456H6.90936L7.42924 5.24886L4.87897 9.24164ZM10.5655 5.28598L12.2111 4.44251C12.2687 4.40526 12.3332 4.38218 12.4 4.37492C12.4668 4.36766 12.5343 4.3764 12.5976 4.40052C12.7335 4.44194 12.8527 4.53077 12.9367 4.65307C12.9687 4.70656 12.9892 4.76711 12.9966 4.83025C13.0041 4.8934 12.9983 4.95754 12.9797 5.01796C12.9611 5.07838 12.9302 5.13354 12.8892 5.1794C12.8482 5.22525 12.7982 5.26063 12.7428 5.28293L11.099 6.12337L10.5655 5.28598ZM0.246896 5.24155C0.194356 5.21754 0.147118 5.18184 0.108279 5.13681C0.0694395 5.09177 0.0398745 5.0384 0.0215206 4.9802C0.00316666 4.92199 -0.00356191 4.86027 0.00177562 4.79908C0.00711316 4.73788 0.0243964 4.67859 0.052493 4.62509C0.0882376 4.56151 0.137753 4.5082 0.196802 4.46973C0.255851 4.43126 0.322676 4.40876 0.391559 4.40418C0.45532 4.37863 0.523711 4.36935 0.591362 4.37706C0.659014 4.38477 0.724086 4.40926 0.781471 4.44861L2.44002 5.33102L1.90375 6.12519L0.246896 5.24155ZM8.94029 2.92112L9.76536 1.13619C9.79484 1.07407 9.8355 1.01888 9.88497 0.973855C9.93445 0.928826 9.99175 0.89485 10.0535 0.873906C10.1521 0.865559 10.2511 0.883535 10.3417 0.926242C10.4468 1.01889 10.5202 1.14668 10.5502 1.28934C10.5802 1.432 10.5651 1.58136 10.5073 1.71373L9.68228 3.49925L8.94029 2.92112ZM2.50952 1.73808C2.44226 1.60978 2.42179 1.4591 2.45208 1.31543C2.48238 1.17175 2.56128 1.04538 2.67339 0.960941C2.71595 0.916167 2.77054 0.887002 2.8294 0.877604C2.88825 0.868207 2.94835 0.879056 3.00114 0.908605C3.05604 0.9321 3.10604 0.96712 3.14824 1.01163C3.19045 1.05614 3.224 1.10924 3.24696 1.16785L4.06636 2.92903L3.28821 3.49925L2.50952 1.73808ZM6.5036 2.62475V0.577527C6.495 0.441761 6.53364 0.307409 6.612 0.200646C6.69035 0.0938827 6.8028 0.0223558 6.92745 0C7.1744 0 7.31624 0.262295 7.31624 0.577527V2.62474L6.5036 2.62475Z" fill="#FFC300"/>
</g>
<defs>
<clipPath id="clip0_843_1282">
<rect width="13" height="14" fill="white"/>
</clipPath>
</defs>
</svg>
src/assets/images/workbench/db5.svg
New file
@@ -0,0 +1,5 @@
<svg width="13" height="13" viewBox="0 0 13 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Vector">
<path id="Vector_2" d="M6.50497 8.95365e-05C5.2193 -0.000920188 3.96221 0.379373 2.89269 1.09287C1.82317 1.80637 0.989274 2.82102 0.496464 4.00848C0.00365405 5.19595 -0.125929 6.5029 0.124105 7.76402C0.374138 9.02514 0.992557 10.1838 1.90114 11.0934C2.80973 12.003 3.96767 12.6228 5.2285 12.8743C6.48934 13.1257 7.79643 12.9976 8.98446 12.5062C10.1725 12.0147 11.1881 11.182 11.9028 10.1133C12.6175 9.04459 12.9993 7.78794 12.9997 6.50227C13.0052 5.64749 12.841 4.80011 12.5166 4.00925C12.1923 3.21838 11.7142 2.49974 11.1101 1.89496C10.506 1.29018 9.78793 0.811283 8.99743 0.486019C8.20694 0.160756 7.35975 -0.00441047 6.50497 8.95365e-05ZM10.2865 10.7767C10.0527 9.81828 9.50474 8.96574 8.72993 8.35505C7.95513 7.74436 6.99815 7.4107 6.01162 7.40728V9.21731C6.01681 9.26183 6.01215 9.30694 5.99795 9.34945C5.98375 9.39196 5.96037 9.43083 5.92947 9.46329C5.86106 9.52278 5.77345 9.55554 5.6828 9.55554C5.59214 9.55554 5.50453 9.52278 5.43612 9.46329L2.47649 6.08921C2.39435 6.08921 2.39435 6.00567 2.39435 5.92677C2.38877 5.88153 2.39324 5.83561 2.40744 5.79229C2.42164 5.74897 2.44522 5.70932 2.47649 5.67615L5.51827 2.30672C5.57905 2.26585 5.65063 2.24403 5.72387 2.24403C5.79711 2.24403 5.86869 2.26585 5.92947 2.30672C5.96093 2.3388 5.98467 2.37762 5.9989 2.42023C6.01314 2.46285 6.01748 2.50815 6.01162 2.55269V4.36272C6.61656 4.3615 7.2158 4.47975 7.77493 4.71069C8.33406 4.94162 8.84208 5.2807 9.26984 5.70847C9.69761 6.13623 10.0367 6.64425 10.2676 7.20338C10.4986 7.76251 10.6168 8.36175 10.6156 8.96669C10.6269 9.58588 10.5151 10.2011 10.2865 10.7767Z" fill="#4200DD"/>
</g>
</svg>
src/assets/images/workbench/ev1.svg
New file
@@ -0,0 +1,10 @@
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Frame" clip-path="url(#clip0_843_1754)">
<path id="Vector" d="M4.98322 1.69254C5.01098 1.66397 5.04532 1.64264 5.08324 1.63041C5.12116 1.61819 5.16149 1.61544 5.20072 1.62242C6.32647 1.82267 6.79334 2.62854 6.97297 3.34254C7.06222 3.69729 7.08359 4.03704 7.08322 4.28567C7.08322 4.34417 7.08172 4.39817 7.07984 4.44617C7.16497 4.42067 7.30409 4.34154 7.43234 4.06817C7.47959 3.96654 7.54559 3.86117 7.64497 3.79704C7.70269 3.75925 7.77022 3.73918 7.83922 3.73929C7.91159 3.73929 7.97422 3.76292 8.02334 3.79254C8.11447 3.84767 8.17709 3.93504 8.21984 4.00779C8.26559 4.08579 8.30497 4.17654 8.33909 4.27029C8.47034 4.63067 8.55959 5.13879 8.56184 5.40467C8.65784 6.59154 8.30422 7.46642 7.67609 8.04092C7.05359 8.61017 6.19297 8.85617 5.32447 8.85617C4.44472 8.85617 3.59084 8.55692 2.97622 7.96667C2.35709 7.37192 1.99934 6.49892 2.08747 5.39567C2.18872 4.14129 3.09359 3.59717 3.81622 3.18917L3.90509 3.13929C4.24259 2.94954 4.52009 2.79354 4.71022 2.60529C4.80809 2.50779 4.87334 2.41029 4.90822 2.30529C4.94272 2.20179 4.95322 2.07542 4.91947 1.91192C4.91136 1.87293 4.91294 1.83254 4.92405 1.7943C4.93516 1.75606 4.95548 1.72112 4.98322 1.69254ZM4.06184 5.61242C4.06184 5.54777 4.03616 5.48577 3.99045 5.44006C3.94474 5.39435 3.88274 5.36867 3.81809 5.36867C3.75344 5.36867 3.69145 5.39435 3.64573 5.44006C3.60002 5.48577 3.57434 5.54777 3.57434 5.61242C3.57434 5.84141 3.61944 6.06816 3.70708 6.27972C3.79471 6.49128 3.92315 6.68351 4.08507 6.84544C4.41209 7.17245 4.85562 7.35617 5.31809 7.35617C5.38274 7.35617 5.44474 7.33049 5.49045 7.28477C5.53616 7.23906 5.56184 7.17706 5.56184 7.11242C5.56184 7.04777 5.53616 6.98577 5.49045 6.94006C5.44474 6.89435 5.38274 6.86867 5.31809 6.86867C4.98491 6.86867 4.66538 6.73631 4.42979 6.50072C4.1942 6.26513 4.06184 5.9456 4.06184 5.61242Z" fill="#1C5CFF"/>
</g>
<defs>
<clipPath id="clip0_843_1754">
<rect width="9" height="9" fill="white" transform="translate(0.818359 0.737305)"/>
</clipPath>
</defs>
</svg>
src/assets/images/workbench/ev2.svg
New file
@@ -0,0 +1,10 @@
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Frame" clip-path="url(#clip0_843_1751)">
<path id="Vector" d="M4.98322 1.81144C5.01098 1.78287 5.04532 1.76153 5.08324 1.74931C5.12116 1.73708 5.16149 1.73434 5.20072 1.74131C6.32647 1.94156 6.79334 2.74744 6.97297 3.46144C7.06222 3.81619 7.08359 4.15594 7.08322 4.40456C7.08322 4.46306 7.08172 4.51706 7.07984 4.56506C7.16497 4.53956 7.30409 4.46044 7.43234 4.18706C7.47959 4.08544 7.54559 3.98006 7.64497 3.91594C7.70269 3.87815 7.77022 3.85808 7.83922 3.85819C7.91159 3.85819 7.97422 3.88181 8.02334 3.91144C8.11447 3.96656 8.17709 4.05394 8.21984 4.12669C8.26559 4.20469 8.30497 4.29544 8.33909 4.38919C8.47034 4.74956 8.55959 5.25769 8.56184 5.52356C8.65784 6.71044 8.30422 7.58531 7.67609 8.15981C7.05359 8.72906 6.19297 8.97506 5.32447 8.97506C4.44472 8.97506 3.59084 8.67581 2.97622 8.08556C2.35709 7.49081 1.99934 6.61781 2.08747 5.51456C2.18872 4.26019 3.09359 3.71606 3.81622 3.30806L3.90509 3.25819C4.24259 3.06844 4.52009 2.91244 4.71022 2.72419C4.80809 2.62669 4.87334 2.52919 4.90822 2.42419C4.94272 2.32069 4.95322 2.19431 4.91947 2.03081C4.91136 1.99182 4.91294 1.95144 4.92405 1.9132C4.93516 1.87495 4.95548 1.84002 4.98322 1.81144ZM4.06184 5.73131C4.06184 5.66667 4.03616 5.60467 3.99045 5.55896C3.94474 5.51324 3.88274 5.48756 3.81809 5.48756C3.75344 5.48756 3.69145 5.51324 3.64573 5.55896C3.60002 5.60467 3.57434 5.66667 3.57434 5.73131C3.57434 5.96031 3.61944 6.18706 3.70708 6.39862C3.79471 6.61018 3.92315 6.80241 4.08507 6.96433C4.41209 7.29135 4.85562 7.47506 5.31809 7.47506C5.38274 7.47506 5.44474 7.44938 5.49045 7.40367C5.53616 7.35796 5.56184 7.29596 5.56184 7.23131C5.56184 7.16667 5.53616 7.10467 5.49045 7.05896C5.44474 7.01324 5.38274 6.98756 5.31809 6.98756C4.98491 6.98756 4.66538 6.85521 4.42979 6.61962C4.1942 6.38402 4.06184 6.06449 4.06184 5.73131Z" fill="#008158"/>
</g>
<defs>
<clipPath id="clip0_843_1751">
<rect width="9" height="9" fill="white" transform="translate(0.818359 0.856201)"/>
</clipPath>
</defs>
</svg>
src/assets/images/workbench/fy1.svg
New file
@@ -0,0 +1,5 @@
<svg width="40" height="39" viewBox="0 0 40 39" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="&#229;&#155;&#190;&#229;&#177;&#130; 5 1">
<rect id="&#229;&#155;&#190;&#229;&#177;&#130; 5 1_2" x="0.130859" y="0.578125" width="39.1758" height="38.4"/>
</g>
</svg>
src/assets/images/workbench/jc1.svg
New file
@@ -0,0 +1,5 @@
<svg width="35" height="40" viewBox="0 0 35 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="1">
<rect id="1_2" x="0.800781" y="0.275146" width="34.0068" height="38.9354"/>
</g>
</svg>
src/assets/images/workbench/st7.svg
New file
@@ -0,0 +1,11 @@
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Frame" clip-path="url(#clip0_75_6544)">
<path id="Vector" d="M7.57812 1.49829C4.19543 1.49829 1.45312 4.2406 1.45312 7.62329C1.45312 11.006 4.19543 13.7483 7.57812 13.7483C10.9608 13.7483 13.7031 11.006 13.7031 7.62329C13.7031 4.2406 10.9608 1.49829 7.57812 1.49829ZM7.57812 12.8733C4.67859 12.8733 2.32812 10.5228 2.32812 7.62329C2.32812 4.72376 4.67859 2.37329 7.57812 2.37329C10.4777 2.37329 12.8281 4.72376 12.8281 7.62329C12.8281 10.5228 10.4777 12.8733 7.57812 12.8733Z" fill="#5C6476"/>
<path id="Vector_2" d="M11.0781 8.06079C11.0781 7.94476 11.032 7.83348 10.95 7.75143C10.8679 7.66938 10.7567 7.62329 10.6406 7.62329H7.57812V4.56079C7.57812 4.44476 7.53203 4.33348 7.44998 4.25143C7.36794 4.16938 7.25666 4.12329 7.14062 4.12329C7.02459 4.12329 6.91331 4.16938 6.83127 4.25143C6.74922 4.33348 6.70312 4.44476 6.70312 4.56079V8.06079C6.70312 8.17682 6.74922 8.2881 6.83127 8.37015C6.91331 8.4522 7.02459 8.49829 7.14062 8.49829H10.6406C10.7567 8.49829 10.8679 8.4522 10.95 8.37015C11.032 8.2881 11.0781 8.17682 11.0781 8.06079Z" fill="#5C6476"/>
</g>
<defs>
<clipPath id="clip0_75_6544">
<rect width="14" height="14" fill="white" transform="translate(0.578125 0.623291)"/>
</clipPath>
</defs>
</svg>
src/page/index/index.vue
@@ -10,7 +10,9 @@
        <!-- 顶部导航栏 -->
        <top ref="top" />
        <!-- 顶部标签卡 -->
        <tags />
        <div class="tags-box">
          <tags />
        </div>
        <search class="avue-view" v-show="isSearch"></search>
        <!-- 主体视图层 -->
        <div id="avue-view" v-show="!isSearch" v-if="isRefresh">
@@ -126,4 +128,10 @@
//     }
//   }
// }
.tags-box{
  background: transparent;
  padding: 0 10px;
  --el-color-primary: rgba(20, 65, 255, 1);
}
</style>
src/page/index/logo.vue
@@ -2,18 +2,19 @@
  <div class="avue-logo">
    <transition name="fade">
      <span v-if="getScreen(isCollapse)" class="avue-logo_subtitle" key="0">
        {{ website.logo }}
<!--        {{ website.logo }}-->
        <img class="logoImg" src="/img/bg/mainLogo.png" alt=""/>
      </span>
    </transition>
    <transition-group name="fade">
      <template v-if="getScreen(!isCollapse)">
        <div class="fadeStyle">
    <img class="img" src="/img/bg/mainLogo.png" alt="" width="50%" height="50%" />
    <!-- <span style="font-size: 20px;"  key="1">
        {{ this.parentDeptInfo.sysName }}
    </span> -->
</div>
          <img class="logoImg" src="/img/bg/mainLogo.png" alt=""/>
          <div class="titleName">综合管理平台</div>
          <!-- <span style="font-size: 20px;"  key="1">
              {{ this.parentDeptInfo.sysName }}
          </span> -->
        </div>
      </template>
    </transition-group>
  </div>
@@ -27,8 +28,7 @@
  data() {
    return {};
  },
  created() {
  },
  created() {},
  computed: {
    ...mapGetters(['isCollapse']),
    ...mapGetters(['userInfo']),
@@ -38,7 +38,28 @@
};
</script>
<style scoped lang="scss">
.avue-logo{
  box-shadow: none;
}
.avue-logo_subtitle{
  .logoImg{
    width: 80%;
  }
}
.fadeStyle {
display: flex; align-items: left; gap: 5px; margin: 8px 8px 10px 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  .logoImg{
    width: 50px;
    height: 20px;
  }
  .titleName{
    font-family: YouSheBiaoTiHei, YouSheBiaoTiHei;
    font-weight: 400;
    font-size: 24px;
    color: #1C5CFF;
  }
}
</style>
src/page/index/setting.vue
@@ -8,21 +8,21 @@
  ></el-button>
  <el-drawer append-to-body :with-header="false" v-model="show" size="30%">
    <div class="setting">
      <h5>导航模式</h5>
<!--      <h5>导航模式</h5>
      <div class="setting-checkbox">
        <el-tooltip class="item" effect="dark" content="侧边菜单布局" placement="top">
          <div
            @click="setting.sidebar = 'vertical'"
            class="setting-checkbox-item setting-checkbox-item--side"
            class="setting-checkbox-item setting-checkbox-item&#45;&#45;side"
          ></div>
        </el-tooltip>
        <el-tooltip class="item" effect="dark" content="顶部菜单布局" placement="top">
          <div
            @click="setting.sidebar = 'horizontal'"
            class="setting-checkbox-item setting-checkbox-item--top"
            class="setting-checkbox-item setting-checkbox-item&#45;&#45;top"
          ></div>
        </el-tooltip>
      </div>
      </div>-->
      <h5>页面布局</h5>
      <div class="setting-checkbox">
        <div class="setting-item" v-for="(item, index) in list1" :key="index">
src/page/index/sidebar/index.vue
@@ -38,4 +38,24 @@
  },
};
</script>
<style lang="scss" scoped></style>
<style lang="scss" scoped>
.el-menu{
  :deep(){
    .el-menu-item.is-active{
      background: linear-gradient( 90deg, rgba(179,194,255,0.02) 0%, rgba(20,65,255,0.09) 100%) !important;
      border-radius: 16px 16px 16px 16px;
      i,span{
        color: rgba(20, 65, 255, 1) !important;
      }
    }
    .el-sub-menu i{
      font-size: 16px;
    }
    .el-menu-item i{
      font-size: 16px;
    }
  }
}
</style>
src/page/index/tags.vue
@@ -166,3 +166,9 @@
  },
}
</script>
<style lang="scss" scoped>
.avue-tags{
  border-radius: 4px;
}
</style>
src/page/index/top/index.vue
@@ -7,22 +7,18 @@
      </div>
    </div>
    <div class="top-bar__title">
      <top-menu ref="topMenu" v-if="setting.menu"></top-menu>
<!--      <top-menu ref="topMenu" v-if="setting.menu"></top-menu>-->
      <top-search class="top-bar__item" v-if="setting.search"></top-search>
    </div>
    <div class="top-bar__right">
      <div v-if="setting.lock" class="top-bar__item">
        <top-lock></top-lock>
      </div>
      <div class="top-bar__item">
        <top-qna></top-qna>
      </div>
      <div class="top-bar__item" v-if="setting.fullscreen">
        <top-full></top-full>
      <div class="icon-box">
        <top-lock v-if="setting.lock"/>
        <top-qna title="帮助中心"/>
        <top-full v-if="setting.fullscreen" title="全屏"/>
      </div>
      <div class="top-user">
        <img class="top-bar__img" :src="userInfo.avatar " />
        <el-dropdown>
          <span class="el-dropdown-link">
            {{ userInfo.real_name }}
@@ -32,9 +28,9 @@
          </span>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item>
<!--              <el-dropdown-item>
                <router-link to="/">{{ $t('navbar.dashboard') }}</router-link>
              </el-dropdown-item>
              </el-dropdown-item>-->
              <el-dropdown-item>
                <router-link to="/info/index">{{ $t('navbar.userinfo') }}</router-link>
              </el-dropdown-item>
@@ -139,6 +135,15 @@
  display: flex !important;
  align-items: center;
  height: 100%;
  .icon-box{
    display: flex;
    align-items: center;
    gap: 0 20px;
    >*{
      cursor: pointer;
    }
  }
}
.top-bar__item {
src/page/index/top/top-lock.vue
@@ -1,6 +1,6 @@
<template>
  <span v-if="text" @click="handleLock">{{ text }}</span>
  <i v-else class="icon-suoping" @click="handleLock"></i>
  <i v-else class="icon-suoping" @click="handleLock" title="锁屏"></i>
  <el-dialog title="设置锁屏密码" v-model="box" width="30%" append-to-body>
    <el-form :model="form" ref="form" label-width="80px">
      <el-form-item
src/page/index/top/top-qna.vue
@@ -65,16 +65,11 @@
<style lang="scss" scoped>
.top-qna {
  display: inline-block !important;
  padding: 5px;
  .help-icon {
    font-size: 20px !important;
    cursor: pointer;
    color: #FFFFFF; /* 白色 */
    display: inline-block !important;
    line-height: 1 !important;
  }
  display: flex;
  align-items: center;
  font-size: 18px;
  justify-content: center;
  cursor: pointer;
}
/* 优化弹出框样式 */
@@ -128,4 +123,4 @@
    }
  }
}
</style>
</style>
src/page/index/top/top-search.vue
@@ -1,6 +1,6 @@
<template>
  <el-autocomplete
    class="top-search"
    class="top-search ztzf-top-search"
    popper-class="my-autocomplete"
    v-model="value"
    :fetch-suggestions="querySearch"
@@ -86,7 +86,21 @@
};
</script>
<style lang="scss">
.ztzf-top-search{
  display: flex !important;
  width: 150px;
  align-items: center;
  .el-input__inner{
    background: #ffffff !important;
    border-radius: 80px 80px 80px 80px;
    padding: 0 20px;
    &::placeholder {
      color:rgba(172, 172, 172, 1) !important;
    }
  }
}
.my-autocomplete {
  li {
    line-height: normal !important;
src/permission copy 2.js
New file
@@ -0,0 +1,71 @@
/*
 * @Author: GuLiMmo 2820890765@qq.com
 * @Date: 2024-08-23 10:51:53
 * @LastEditors: GuLiMmo 2820890765@qq.com
 * @LastEditTime: 2024-08-29 14:10:56
 * @FilePath: /drone-web-manage/src/permission.js
 * @Description:
 * Copyright (c) 2024 by GuLiMmo, All Rights Reserved.
 */
import router from './router/'
import store from './store'
import { getToken } from '@/utils/auth'
import { getUrlParams } from './utils/validate'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
NProgress.configure({ showSpinner: false })
const lockPage = '/lock' //锁屏页
const urlParams = getUrlParams(window.location.href)
router.beforeEach((to, from, next) => {
  const meta = to.meta || {}
  const isMenu = meta.menu === undefined ? to.query.menu : meta.menu
  store.commit('SET_IS_MENU', isMenu === undefined)
  if (getToken()) {
    if (store.getters.isLock && to.path !== lockPage) {
      //如果系统激活锁屏,全部跳转到锁屏页
      next({ path: lockPage })
    } else if (to.path === '/login') {
      //如果登录成功访问登录页跳转到主页
      next({ path: '/' })
    } else {
      const systemToken = store.getters.token || urlParams?.token
      if (systemToken === 0) {
        store.dispatch('FedLogOut').then(() => {
          next({ path: '/login' })
        })
      } else {
        const meta = to.meta || {}
        const query = to.query || {}
        if (meta.target) {
          window.open(query.url.replace(/#/g, '&'))
          return
        } else if (meta.isTab !== false) {
          store.commit('ADD_TAG', {
            name: query.name || to.name,
            path: to.path,
            fullPath: to.path,
            params: to.params,
            query: to.query,
            meta: meta,
          })
        }
        next()
      }
    }
  } else {
    //判断是否需要认证,没有登录访问去登录页
    if (meta.isAuth === false) {
      next()
    } else {
      next('/login')
    }
  }
})
router.afterEach(to => {
  NProgress.done()
  let title = router.$avueRouter.generateTitle(to, { label: 'name' })
  router.$avueRouter.setTitle(title)
  store.commit('SET_IS_SEARCH', false)
})
src/permission copy.js
New file
@@ -0,0 +1,133 @@
/*
 * @Author: GuLiMmo 2820890765@qq.com
 * @Date: 2024-08-23 10:51:53
 * @LastEditors: GuLiMmo 2820890765@qq.com
 * @LastEditTime: 2024-08-29 14:10:56
 * @FilePath: /drone-web-manage/src/permission.js
 * @Description:
 * Copyright (c) 2024 by GuLiMmo, All Rights Reserved.
 */
import { getStore } from '@/utils/store'
import router from './router/'
import store from './store'
import { getToken } from '@/utils/auth'
import { getUrlParams } from './utils/validate'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
NProgress.configure({ showSpinner: false })
const lockPage = '/lock' //锁屏页
const urlParams = getUrlParams(window.location.href)
function findRouteByPath (routes, targetPath) {
  // 遍历数组中的每个路由对象
  for (const route of routes) {
    // 如果当前路由的path匹配目标路径,直接返回
    if (route.path === targetPath) {
      return route
    }
    // 如果有子路由,递归查找
    if (route.children && route.children.length > 0) {
      const foundInChildren = findRouteByPath(route.children, targetPath)
      if (foundInChildren) {
        return foundInChildren
      }
    }
  }
  // 遍历完所有路由都没找到,返回null
  return null
}
router.beforeEach((to, from, next) => {
  const meta = to.meta || {}
  const isMenu = meta.menu === undefined ? to.query.menu : meta.menu
  store.commit('SET_IS_MENU', isMenu === undefined)
  const menuAll = getStore({ name: 'menuAll' })
  if (!menuAll) {
    store.dispatch('GetMenu').then(data => {
      if (data.length !== 0) {
        router.$avueRouter.formatRoutes(data, true)
        let newMenu = getStore({ name: 'menuAll' })
        let firstMenu = newMenu[0]
        let toMenu = findRouteByPath(newMenu, to.path)
        store.commit('ADD_TAG', {
          name: firstMenu.name,
          path: firstMenu.path,
          fullPath: firstMenu.path,
          params: firstMenu.params || {},
          query: firstMenu.query || {},
          meta: firstMenu.meta || {},
        })
        store.commit('ADD_TAG', {
          name: toMenu.name,
          path: toMenu.path,
          fullPath: toMenu.path,
          params: toMenu.params || {},
          query: toMenu.query || {},
          meta: toMenu.meta || {},
        })
        next(to.fullPath)
      }
    })
    return
  }
  if (getToken()) {
    if (store.getters.isLock && to.path !== lockPage) {
      //如果系统激活锁屏,全部跳转到锁屏页
      next({ path: lockPage })
    } else if (to.path === '/login') {
      //如果登录成功访问登录页跳转到主页
      next({ path: '/' })
    } else {
      const systemToken = store.getters.token || urlParams?.token
      if (systemToken === 0) {
        store.dispatch('FedLogOut').then(() => {
          next({ path: '/login' })
        })
      } else {
        const meta = to.meta || {}
        const query = to.query || {}
        if (meta.target) {
          window.open(query.url.replace(/#/g, '&'))
          return
        } else if (meta.isTab !== false) {
          store.commit('ADD_TAG', {
            name: query.name || to.name,
            path: to.path,
            fullPath: to.path,
            params: to.params,
            query: to.query,
            meta: meta,
          })
        }
        next()
      }
    }
  } else {
    //判断是否需要认证,没有登录访问去登录页
    if (meta.isAuth === false) {
      next()
    } else {
      next('/login')
    }
  }
})
router.afterEach(to => {
  NProgress.done()
  let title = router.$avueRouter.generateTitle(to, { label: 'name' })
  router.$avueRouter.setTitle(title)
  store.commit('SET_IS_SEARCH', false)
})
src/permission.js
@@ -7,6 +7,8 @@
 * @Description:
 * Copyright (c) 2024 by GuLiMmo, All Rights Reserved.
 */
import { getStore } from '@/utils/store'
import router from './router/'
import store from './store'
import { getToken } from '@/utils/auth'
@@ -17,10 +19,70 @@
const lockPage = '/lock' //锁屏页
const urlParams = getUrlParams(window.location.href)
function findRouteByPath (routes, targetPath) {
  // 遍历数组中的每个路由对象
  for (const route of routes) {
    // 如果当前路由的path匹配目标路径,直接返回
    if (route.path === targetPath) {
      return route
    }
    // 如果有子路由,递归查找
    if (route.children && route.children.length > 0) {
      const foundInChildren = findRouteByPath(route.children, targetPath)
      if (foundInChildren) {
        return foundInChildren
      }
    }
  }
  // 遍历完所有路由都没找到,返回null
  return null
}
router.beforeEach((to, from, next) => {
  const meta = to.meta || {}
  const isMenu = meta.menu === undefined ? to.query.menu : meta.menu
  store.commit('SET_IS_MENU', isMenu === undefined)
  const menuAll = getStore({ name: 'menuAll' })
  if (!menuAll) {
    store.dispatch('GetMenu').then(data => {
      if (data.length !== 0) {
        router.$avueRouter.formatRoutes(data, true)
        let newMenu = getStore({ name: 'menuAll' })
        let firstMenu = newMenu[0]
        let toMenu = findRouteByPath(newMenu, to.path)
        store.commit('ADD_TAG', {
          name: firstMenu.name,
          path: firstMenu.path,
          fullPath: firstMenu.path,
          params: firstMenu.params || {},
          query: firstMenu.query || {},
          meta: firstMenu.meta || {},
        })
        store.commit('ADD_TAG', {
          name: toMenu.name,
          path: toMenu.path,
          fullPath: toMenu.path,
          params: toMenu.params || {},
          query: toMenu.query || {},
          meta: toMenu.meta || {},
        })
        next(to.fullPath)
      }
    })
    return
  }
  if (getToken()) {
    if (store.getters.isLock && to.path !== lockPage) {
      //如果系统激活锁屏,全部跳转到锁屏页
src/styles/common.scss
@@ -22,6 +22,7 @@
  display: flex;
  height: 1080px;
  width: 1920px;
  background: url("@/assets/images/layoutBg.png")  no-repeat center / 100% 100%;
  overflow: hidden;
  &--horizontal {
@@ -75,7 +76,6 @@
  box-sizing: border-box;
  overflow: hidden;
  // background: #f0f2f5;
  background: linear-gradient( 180deg, #EEF3FE 0%, #F8F9FB 100%);
}
#avue-view {
src/styles/theme/white.scss
@@ -36,7 +36,7 @@
  .avue-top,
  .avue-logo,
  .tags-container {
    background-color: #409EFF;
    background-color: transparent;
  }
  .avue-sidebar--tip {
@@ -58,7 +58,8 @@
    color: #fff;
    i {
      color: #fff;
      cursor: pointer;
      color: rgba(20, 65, 255, 1);
    }
  }
src/styles/top.scss
@@ -44,9 +44,9 @@
.top-search {
  line-height: $top_height;
  position: absolute !important;
  right: 200px;
  right: 300px;
  top: 0;
  width: 300px;
  width: 250px;
  .el-input__wrapper {
    font-size: 13px;
@@ -71,7 +71,6 @@
.top-bar__right {
  height: $top_height;
  position: absolute;
  margin-top: 2px;
  top: 0;
  i {
src/views/device/components/DockControlPanel.vue
@@ -19,31 +19,64 @@
            <div class="item-status">{{ cmdItem.status }}</div>
          </div>
          <div class="control-cmd-item-right">
            <el-button :disabled="!debugStatus || cmdItem.disabled" :loading="cmdItem.loading" size="small" type="primary"
              @click="sendControlCmd(cmdItem, index)">
            <el-button :disabled="!debugStatus || cmdItem.disabled" :loading="cmdItem.loading" size="small"
              type="primary" @click="sendControlCmd(cmdItem, index)">
              {{ cmdItem.operateText }}
            </el-button>
          </div>
        </div>
      </div>
      <el-divider v-if="deviceInfo">无人机设置</el-divider>
      <!-- 设置 0:白热,1:黑热,2:描红,3:医疗,5:彩虹 1,6:铁红,8:北极,11:熔岩,12:热铁,13:彩虹 2 -->
      <div class="control-cmd-box">
        <div class="control-cmd-item" v-for="(item, index) in cameras">
          <div class="control-cmd-item-left">调色盘样式 {{ item.payload_index }}</div>
          <div class="control-cmd-item-right">
      <div class="control-cmd-box" v-for="(item, index) in cameras">
        <div>
          <el-form-item label="摄像头设置">
            <el-select @change="cameraSettings($event, item)" v-model="videoValue" placeholder="请选择">
              <el-option v-for="item in videoType" :key="item.value" :label="item.label" :value="item.value">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="调色盘样式" v-if="videoValue == 'ir'">
            <el-select @change="changs($event, item)" v-model="valueStyle" placeholder="请选择">
              <el-option v-for="item in paletteOptions" :key="item.value" :label="item.label" :value="item.value">
              </el-option>
            </el-select>
          </div>
          </el-form-item>
        </div>
        <div>
          <el-form-item label="相机模式">
            <el-select @change="photoAndVideoCmdSettings($event, item)" v-model="cameraModeValue" placeholder="请选择">
              <el-option v-for="item in cameraMode" :key="item.value" :label="item.label" :value="item.value">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="照片存储设置" v-if="cameraModeValue == 0">
            <el-select v-model="photo_storage_settings" collapse-tags @change="photoStorageTypeChang($event, item)"
              multiple placeholder="请选择">
              <el-option v-for="item in photoStorageType" :key="item.value" :label="item.label" :value="item.value">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="视频存储设置" v-if="cameraModeValue == 1">
            <el-select v-model="video_storage_settings" collapse-tags @change="videoStorageTypeChang($event, item)"
              multiple placeholder="请选择">
              <el-option v-for="item in photoStorageType" :key="item.value" :label="item.label" :value="item.value">
              </el-option>
            </el-select>
          </el-form-item>
        </div>
      </div>
    </div>
  </div>
</template>
<script setup>
import { ElMessage } from 'element-plus';
import EventBus from '@/event-bus'
import { EBizCode, ELocalStorageKey, ERouterName } from '@/types'
import { useConnectWebSocket } from '@/hooks/use-connect-websocket'
@@ -53,18 +86,58 @@
import { useDockControl } from './use-dock-control'
import { EDockModeCode } from '@/types/device'
import { updateDeviceCmdInfoByOsd, updateDeviceCmdInfoByExecuteInfo } from '@/utils/device-cmd'
import { setThermalCurrentPaletteStyle } from '@/api/device-setting'
import { setThermalCurrentPaletteStyle, setPhotoStorageSet, setVideoStorageSet, getLiveStatus, setStreamsSwitch, photoAndVideoCmd } from '@/api/device-setting'
import Store from '@/store'
const valueStyle = ref(0)
const cameraModeValue = ref(0)
const videoValue = ref("zoom")
const photo_storage_settings = ref([])
const video_storage_settings = ref([])
// 定义一个数据videoList
const videoList = reactive([])
// 摄像头信息
let cameras = reactive([])
// let cameras = reactive([
//   {
//     camera_mode: 0,
//     liveview_world_region: {
//       bottom: 0.5515424609184265,
//       left: 0.42740535736083984,
//       right: 0.5581043362617493,
//       top: 0.42277535796165466
//     },
//     payload_index: "81-0-0",
//     photo_state: 0,
//     record_time: 0,
//     recording_state: 0,
//     remain_photo_num: 3931,
//     remain_record_duration: 0,
//     zoom_factor: 6.9999943,
//     ir_zoom_factor: 2,
//     photo_storage_settings: [
//       "vision",
//       "ir"
//     ],
//     video_storage_settings: [
//       "vision"
//     ]
//   }
// ])
// 无人机信息
let deviceInfo = ref()
// camera_mode {"0":"拍照","1":"录像","2":"智能低光","3":"全景拍照","-1":"不支持的模式"}
const cameraMode = [
  { label: '拍照', value: 0 },
  { label: '录像', value: 1 },
  { label: '智能低光', value: 2 },
  { label: '全景拍照', value: 3 },
  // { label: '不支持的模式', value: -1 },
]
// 调色盘选项数据
const paletteOptions = [
@@ -78,6 +151,22 @@
  { label: '熔岩', value: 11 },
  { label: '热铁', value: 12 },
  { label: '彩虹2', value: 13 },
]
// 视频类型 ZOOM("zoom"), WIDE("wide"), THERMAL("thermal"), NORMAL("normal"), IR("ir");
const videoType = [
  { label: '变焦', value: 'zoom' },
  { label: '广角', value: 'wide' },
  // { label: '热红外', value: 'thermal' },
  // { label: '正常', value: 'normal' },
  { label: '红外', value: 'ir' },
]
// 拍照存储类型{current, wide, zoom, ir},可多选
const photoStorageType = [
  { label: '当前', value: 'current' },
  { label: '广角', value: 'wide' },
  { label: '变焦', value: 'zoom' },
  { label: '可见光', value: 'vision' },
  { label: '红外', value: 'ir' },
]
const props = defineProps(['sn', 'deviceInfo'])
@@ -103,7 +192,7 @@
watch(
  () => Store.state.device.videoSurveillance,
  newObj => {
    console.log('视频类型监听中', newObj)
    // console.log('视频类型监听中', newObj)
    if (newObj && newObj.live_status && newObj.live_status.length) {
      let arr = newObj.live_status || []
      if (videoList.length == arr.length) {
@@ -112,8 +201,14 @@
      arr.forEach(element => {
        let video_id = element.video_id
        element.payIndex = video_id.split('/')[1].split('-')[1]
        if (props.deviceInfo.child_sn == video_id.split('/')[0]) {
          if (element.video_type == 'normal' || element.video_type == 'thermal') {
            videoValue.value = 'wide'
          } else {
            videoValue.value = element.video_type
          }
        }
      })
      // videoList.length = 0 // 清空数组
      videoList.push(...arr) // 添加新元素
    }
  },
@@ -135,7 +230,14 @@
      devices['dock'] = value.dockInfo[props.deviceInfo.device_sn]
      devices['gateway'] = value.gatewayInfo
      let cameraList = value.deviceInfo[props.deviceInfo.child_sn]?.cameras || []
      cameras = reactive([...cameraList])
      cameras = cameraList
      // console.log('设备osd.cameras信息变化', cameras)
      // 判断cameras列表长度是否为0,如果为0,则不执行后续操作
      if (cameras.length > 0) {
        cameraModeValue.value = cameras[0].camera_mode
        photo_storage_settings.value = cameras[0]?.photo_storage_settings ?? [];
        video_storage_settings.value = cameras[0]?.video_storage_settings ?? [];
      }
      deviceInfo = ref(value.deviceInfo[props.deviceInfo.child_sn])
      updateDeviceCmdInfoByOsd(cmdList.value, devices)
    }
@@ -145,9 +247,26 @@
    deep: true,
  }
)
onMounted(() => {
  getLiveStatuss()
});
async function getLiveStatuss() {
  let result = await getLiveStatus(props.sn)
  result.data.data.live_status.forEach(item => {
    if (props.deviceInfo.child_sn == item.video_id.split('/')[0]) {
      if (item.video_type == 'normal' || item.video_type == 'thermal') {
        videoValue.value = 'wide'
      } else {
        videoValue.value = item.video_type
      }
    }
  })
}
// 远程控制开关
async function onDeviceStatusChange (status) {
async function onDeviceStatusChange(status) {
  let result = false
  if (status) {
    result = await dockDebugOnOff(props.sn, true)
@@ -166,7 +285,7 @@
const { sendDockControlCmd, dockDebugOnOff } = useDockControl()
async function sendControlCmd (cmdItem, index) {
async function sendControlCmd(cmdItem, index) {
  const params = {
    sn: props.sn,
    cmd: cmdItem.cmdKey,
@@ -270,7 +389,7 @@
useConnectWebSocket(messageHandler, webSorketUrl)
// 添加 changs 方法
async function changs (value, item) {
async function changs(value, item) {
  const payload = {
    [item.payload_index]: {
      thermal_current_palette_style: value
@@ -278,8 +397,62 @@
  }
  console.log('payload', payload)
  let data = await setThermalCurrentPaletteStyle(props.sn, props.deviceInfo.workspace_id, payload)
  if (data.code === 0) {
    message.success('修改成功')
  if (data.data.code === 0) {
    ElMessage.success('修改成功');
  }
}
// 摄像头设置
async function cameraSettings(value, item) {
  const payload = {
    // 1581F6Q8D245U00G57GJ/81-0-0/normal-0
    video_id: props.deviceInfo.child_sn + '/' + item.payload_index + '/normal-0',
    video_type: value
  }
  let data = await setStreamsSwitch(payload)
  if (data.data.code === 0) {
    ElMessage.success('修改成功');
  }
}
// 相机模式设置
async function photoAndVideoCmdSettings(value, item) {
  // photo 0 video_start 1 video_stop
  item.camera_mode = value
  let data = await photoAndVideoCmd(props.deviceInfo.child_sn, value)
  if (data.data.code == 0) {
    ElMessage.success('修改成功');
  }
}
// 照片存储设置
async function photoStorageTypeChang(value, item) {
  // value 不能为空
  if (!value) {
    ElMessage.error('请选择存储方式');
    return;
  }
  const payload = {
    payload_index: item.payload_index,
    photo_storage_settings: value
  }
  item.photo_storage_settings = value
  let data = await setPhotoStorageSet(props.sn, payload)
  if (data.data.code == 0) {
    ElMessage.success('修改成功');
  }
}
// 视频存储设置
async function videoStorageTypeChang(value, item) {
  if (!value) {
    ElMessage.error('请选择存储方式');
    return;
  }
  const payload = {
    payload_index: item.payload_index,
    video_storage_settings: value
  }
  item.video_storage_settings = value
  let data = await setVideoStorageSet(props.sn, payload)
  if (data.data.code == 0) {
    ElMessage.success('修改成功');
  }
}
</script>
src/views/system/user.vue
@@ -66,6 +66,7 @@
          <template #userTypeName="{ row }">
            <el-tag>{{ row.userTypeName }}</el-tag>
          </template>
        </avue-crud>
        <el-dialog title="用户角色配置" append-to-body v-model="roleBox" width="345px">
          <el-tree :data="roleGrantList" show-checkbox check-strictly default-expand-all node-key="id" ref="treeRole"
@@ -153,7 +154,10 @@
      }
    };
    return {
      form: {},
      form: {
        flightStartTime: null, // 飞行事件开始时间
        flightEndTime: null, // 飞行事件结束时间
      },
      search: {},
      roleBox: false,
      excelBox: false,
@@ -363,13 +367,7 @@
                viewDisplay: false,
                rules: [{ required: true, validator: validatePass2, trigger: 'blur' }],
              },
              {
                label: '到期时间',
                prop: 'expireTime',
                type: 'datetime',
                format: 'YYYY-MM-DD HH:mm:ss',
                valueFormat: 'YYYY-MM-DD HH:mm:ss',
              },
            ],
          },
          {
@@ -503,24 +501,58 @@
                  },
                ],
              },
              // {
              //   label: '所属岗位',
              //   prop: 'postId',
              //   type: 'tree',
              //   multiple: true,
              //   dicData: [],
              //   props: {
              //     label: 'postName',
              //     value: 'id',
              //   },
              //   rules: [
              //     {
              //       required: true,
              //       message: '请选择所属岗位',
              //       trigger: 'click',
              //     },
              //   ],
              // },
            ],
          },
           {
            label: '登录限制',
            prop: '',
            icon: 'el-icon-s-custom',
            column: [
               {
                label: '到期时间',
                prop: 'expireTime',
                type: 'datetime',
                format: 'YYYY-MM-DD HH:mm:ss',
                valueFormat: 'YYYY-MM-DD HH:mm:ss',
              },
                {
                label: '次数限制',
                prop: 'maxLoginNum',
                type: 'input',
              },
               {
                label: '飞行开始时间',
                prop: 'flightStartTime',
               type: 'time',
                 format: 'HH:mm',
                valueFormat: 'HH:mm',
                rules: [
                  {
                    required: false,
                    message: '请输入飞行开始时间',
                    trigger: 'blur',
                  },
                ],
              },
              {
                label: '飞行结束时间',
                prop: 'flightEndTime',
                type: 'time',
                format: 'HH:mm',
                valueFormat: 'HH:mm',
                rules: [
                  {
                    required: false,
                    message: '请输入飞行结束时间',
                    trigger: 'blur',
                  },
                ],
              },
            ],
          },
        ],
@@ -732,6 +764,23 @@
      });
    },
    rowSave(row, done, loading) {
      // 格式化时间数据
       if (row.flightStartTime && row.flightEndTime) {
    // 验证 flightEndTime 是否小于 flightStartTime
   const [startHours, startMinutes] = row.flightStartTime.split(':').map(Number);
    const [endHours, endMinutes] = row.flightEndTime.split(':').map(Number);
    const startTotalMinutes = startHours * 60 + startMinutes;
    const endTotalMinutes = endHours * 60 + endMinutes;
    if (endTotalMinutes < startTotalMinutes) {
        this.$message.error('飞行结束时间不能小于飞行开始时间');
            loading();
        return;
    }
       }
      row.deptId = func.join(row.deptId);
      row.roleId = func.join(row.roleId);
      row.postId = func.join(row.postId);
@@ -753,6 +802,28 @@
      );
    },
    rowUpdate(row, index, done, loading) {
         // 格式化时间数据
      // if (row.flightStartTime) {
      //   row.flightStartTime = this.formatTime(row.flightStartTime);
      // }
      // if (row.flightEndTime) {
      //   row.flightEndTime = this.formatTime(row.flightEndTime);
      // }
       if (row.flightStartTime && row.flightEndTime) {
    // 验证 flightEndTime 是否小于 flightStartTime
   const [startHours, startMinutes] = row.flightStartTime.split(':').map(Number);
    const [endHours, endMinutes] = row.flightEndTime.split(':').map(Number);
    const startTotalMinutes = startHours * 60 + startMinutes;
    const endTotalMinutes = endHours * 60 + endMinutes;
    if (endTotalMinutes < startTotalMinutes) {
        this.$message.error('飞行结束时间不能小于飞行开始时间');
           loading();
        return ;
      }
       }
      row.deptId = func.join(row.deptId);
      row.roleId = func.join(row.roleId);
      row.postId = func.join(row.postId);
@@ -987,6 +1058,7 @@
          if (this.form.hasOwnProperty('postId')) {
            this.form.postId = func.split(this.form.postId);
          }
        });
      }
      this.initFlag = true;
@@ -1081,6 +1153,13 @@
        this.selectionClear();
      });
    },
    formatTime(time) {
      // 格式化时间为 HH:mm
      const date = new Date(time);
      const hours = String(date.getHours()).padStart(2, '0');
      const minutes = String(date.getMinutes()).padStart(2, '0');
      return `${hours}:${minutes}`;
    },
  },
};
</script>
src/views/system/userinfo.vue
@@ -7,7 +7,7 @@
        v-model="form"
        @tab-click="handleTabClick"
        @submit="handleSubmit"
      >
        <template #email="{ disabled, size }">
            <el-input
@@ -50,8 +50,6 @@
    handleSubmit(form, done) {
      if (this.index === 0) {
        form.name = form.realName;
        console.log('form, done', form, done);
        updateInfo(form).then(
          res => {
            if (res.data.success) {
@@ -78,8 +76,11 @@
            if (res.data.success) {
              this.$message({
                type: 'success',
                message: '修改密码成功!',
                message: '修改密码成功,请重新登录!',
              });
              this.$store.dispatch('LogOut').then(() => {
                this.$router.push({ path: '/login' })
              })
            } else {
              this.$message({
                type: 'error',
@@ -99,7 +100,6 @@
      if (this.index === 0) {
        getUserInfo().then(res => {
          const user = res.data.data;
          this.form = {
            id: user.id,
            avatar: user.avatar ? user.avatar :defaultAva,
@@ -108,8 +108,7 @@
            phone: user.phone,
            email: user.email,
          };
          // console.log('用户信息',user);
        });
      }
    },
src/views/tickets/orderLog.vue
@@ -1189,6 +1189,20 @@
      this.detailVisible = true;
  // 更新航线列表,追加 wayline_file_region_vo 数据
  if (data.wayline_file_region_vo) {
    const newWayline = data.wayline_file_region_vo;
    // 检查是否已经存在于 this.wayLineList 中
    const isDuplicate = this.wayLineList.some(
      (item) => item.wayline_id === newWayline.wayline_id
    );
    if (!isDuplicate) {
      this.wayLineList.push(newWayline);
    }
  }
      this.initMapLine(data.device_map_infos);
    },
    async handleCheckDetail(row) {
@@ -1197,7 +1211,20 @@
      this.form = {
        ...data,
      };
  // 更新航线列表,追加 wayline_file_region_vo 数据
  // 更新航线列表,追加 wayline_file_region_vo 数据
  if (data.wayline_file_region_vo) {
    const newWayline = data.wayline_file_region_vo;
    // 检查是否已经存在于 this.wayLineList 中
    const isDuplicate = this.wayLineList.some(
      (item) => item.wayline_id === newWayline.wayline_id
    );
    if (!isDuplicate) {
      this.wayLineList.push(newWayline);
    }
  }
      // 更新机巢列表
      this.device_sns = data.device_list;
      this.detailVisibleCopy = true;
src/views/wel/components/backlog.vue
@@ -60,12 +60,12 @@
</template>
<script setup>
import st7 from '@/assets/images/workbench/st7.png';
import db1 from '@/assets/images/workbench/db1.png';
import db2 from '@/assets/images/workbench/db2.png';
import db3 from '@/assets/images/workbench/db3.png';
import db4 from '@/assets/images/workbench/db4.png';
import db5 from '@/assets/images/workbench/db5.png';
import st7 from '@/assets/images/workbench/st7.svg';
import db1 from '@/assets/images/workbench/db1.svg';
import db2 from '@/assets/images/workbench/db2.svg';
import db3 from '@/assets/images/workbench/db3.svg';
import db4 from '@/assets/images/workbench/db4.svg';
import db5 from '@/assets/images/workbench/db5.svg';
import { getOrderCountApi, addOrderRecordApi, getOrderOrEventApi } from '@/api/home/index';
import { onMounted } from 'vue';
import { useRouter } from 'vue-router';
src/views/wel/components/calendarBox.vue
@@ -26,8 +26,8 @@
import dayjs from 'dayjs';
import { jobEventBar, getCalen } from '@/api/home/index';
import { useRouter } from 'vue-router';
import ev1 from '@/assets/images/workbench/ev1.png';
import ev2 from '@/assets/images/workbench/ev2.png';
import ev1 from '@/assets/images/workbench/ev1.svg';
import ev2 from '@/assets/images/workbench/ev2.svg';
import { ElMessage } from 'element-plus'
const router = useRouter();
const events = ref({});
src/views/wel/index.vue
@@ -63,7 +63,7 @@
              <!-- 飞行统计 -->
              <div class="flyOrder">
                <div class="fytitle">
                  <img src="@/assets/images/workbench/fy1.png" alt="" />
                   <img :src="fy1" alt="" />
                  <span>飞行统计</span>
                </div>
                <div class="flycenter">
@@ -110,7 +110,7 @@
import overviewImg3 from '@/assets/images/workbench/tc3.svg';
import overviewImg4 from '@/assets/images/workbench/tc4.svg';
import overviewImg5 from '@/assets/images/workbench/tc5.svg';
import fy1 from '@/assets/images/workbench/fy1.png';
import flyImg1 from '@/assets/images/workbench/fy2.svg';
import flyImg2 from '@/assets/images/workbench/fy3.svg';
import flyImg3 from '@/assets/images/workbench/fy4.svg';