Selaa lähdekoodia

[Feat 0000]角色管理、分站管理功能优化

bobo04052021@163.com 3 päivää sitten
vanhempi
commit
262e734fdf

+ 251 - 245
src/layouts/default/header/components/VoiceBroadcast.vue

@@ -16,6 +16,7 @@
         <div class="badge-box">
           <ClearOutlined style="font-size: 20px; color: #fff" @click="clearInfo" />
           <SoundOutlined :class="{ 'no-play': !isBroad }" style="font-size: 20px; color: #fff" @click="handleBroad" />
+          <CloseOutlined style="font-size: 20px; color: #fff" @click="closeWarningBroad" />
         </div>
       </div>
       <div class="broadcast-context">
@@ -46,292 +47,297 @@
   </div>
 </template>
 <script lang="ts">
-  import { Tooltip, Badge } from 'ant-design-vue';
-  import { SoundOutlined, ClearOutlined, BellOutlined, WarningOutlined } from '@ant-design/icons-vue';
-  import Icon from '/@/components/Icon';
-  import { defineComponent, ref, unref, onMounted, nextTick } from 'vue';
-  import { defHttp } from '/@/utils/http/axios';
-  import { useRouter } from 'vue-router';
-  import { connectWebSocket, onWebSocket } from '/@/hooks/web/useWebSocket';
-  import { getToken } from '/@/utils/auth';
-  import { useUserStore } from '/@/store/modules/user';
-  import { useGlobSetting } from '/@/hooks/setting';
-  import SpeakVoice from './notify/speakVoice';
-  import { useDrag } from '@/hooks/event/useDrag';
-  import dayjs from 'dayjs';
-  export default defineComponent({
-    name: 'VoiceBroadcast',
-    components: { Icon, Tooltip, Badge, SoundOutlined, ClearOutlined, BellOutlined, WarningOutlined },
+import { Tooltip, Badge } from 'ant-design-vue';
+import { SoundOutlined, ClearOutlined, BellOutlined, WarningOutlined, CloseOutlined } from '@ant-design/icons-vue';
+import Icon from '/@/components/Icon';
+import { defineComponent, ref, unref, onMounted, nextTick } from 'vue';
+import { defHttp } from '/@/utils/http/axios';
+import { useRouter } from 'vue-router';
+import { connectWebSocket, onWebSocket } from '/@/hooks/web/useWebSocket';
+import { getToken } from '/@/utils/auth';
+import { useUserStore } from '/@/store/modules/user';
+import { useGlobSetting } from '/@/hooks/setting';
+import SpeakVoice from './notify/speakVoice';
+import { useDrag } from '@/hooks/event/useDrag';
+import dayjs from 'dayjs';
+export default defineComponent({
+  name: 'VoiceBroadcast',
+  components: { Icon, Tooltip, Badge, SoundOutlined, ClearOutlined, BellOutlined, WarningOutlined, CloseOutlined },
 
-    setup() {
-      // debugger;
-      let speakVoice;
-      const userStore = useUserStore();
-      const glob = useGlobSetting();
-      const router = useRouter();
-      const list = (params) => defHttp.get({ url: '/safety/ventanalyAlarmLog/list', params });
-      const cleanAlarm = () => defHttp.get({ url: '/safety/ventanalyAlarmLog/cleanAlarmLog' });
-      const activeKey = ref(0);
-      const isShowWarningBroad = ref(false);
-      const isBroad = ref(true);
-      const isWarningDot = ref(false);
-      const broadcastList = ref([]);
-      function showWarningBroad() {
-        isShowWarningBroad.value = !isShowWarningBroad.value;
-        if (isShowWarningBroad.value) {
-          toSelectList(0);
-          nextTick(() => {
-            const dom = document.getElementById('VoiceBroadcast');
-            if (dom) useDrag(dom);
-          });
-        }
-      }
-      function handleBroad() {
-        isBroad.value = !isBroad.value;
+  setup() {
+    // debugger;
+    let speakVoice;
+    const userStore = useUserStore();
+    const glob = useGlobSetting();
+    const router = useRouter();
+    const list = (params) => defHttp.get({ url: '/safety/ventanalyAlarmLog/list', params });
+    const cleanAlarm = () => defHttp.get({ url: '/safety/ventanalyAlarmLog/cleanAlarmLog' });
+    const activeKey = ref(0);
+    const isShowWarningBroad = ref(false);
+    const isBroad = ref(true);
+    const isWarningDot = ref(false);
+    const broadcastList = ref([]);
+    function showWarningBroad() {
+      isShowWarningBroad.value = !isShowWarningBroad.value;
+      if (isShowWarningBroad.value) {
+        toSelectList(0);
+        nextTick(() => {
+          const dom = document.getElementById('VoiceBroadcast');
+          if (dom) useDrag(dom);
+        });
       }
+    }
+    function handleBroad() {
+      isBroad.value = !isBroad.value;
+    }
+    //点击关闭预警信息弹窗
+    function closeWarningBroad() {
+      isShowWarningBroad.value = false;
+    }
 
-      async function clearInfo() {
-        await cleanAlarm();
-        const res = await list({ pageSize: 20, devicetype: '', sort: 'createTime', delFlag: 0, nwartype_end: '999' });
-        broadcastList.value = res['records'];
-      }
+    async function clearInfo() {
+      await cleanAlarm();
+      const res = await list({ pageSize: 20, devicetype: '', sort: 'createTime', delFlag: 0, nwartype_end: '999' });
+      broadcastList.value = res['records'];
+    }
 
-      async function toSelectList(key) {
-        activeKey.value = key;
-        const res = await list({
-          pageSize: 20,
-          devicetype: '',
-          isok: key == 1 ? 0 : key == 2 ? 1 : null,
-          sort: 'createTime',
-          delFlag: 0,
-          nwartype_end: '999',
-        });
-        broadcastList.value = res['records'];
-        const isHasWarning = broadcastList.value.findIndex((item) => !item['isok']);
-        if (key !== 2) isWarningDot.value = isHasWarning > -1 ? true : false;
-      }
+    async function toSelectList(key) {
+      activeKey.value = key;
+      const res = await list({
+        pageSize: 20,
+        devicetype: '',
+        isok: key == 1 ? 0 : key == 2 ? 1 : null,
+        sort: 'createTime',
+        delFlag: 0,
+        nwartype_end: '999',
+      });
+      broadcastList.value = res['records'];
+      const isHasWarning = broadcastList.value.findIndex((item) => !item['isok']);
+      if (key !== 2) isWarningDot.value = isHasWarning > -1 ? true : false;
+    }
 
-      async function toMore() {
-        await router.push({ path: '/monitorChannel/device-monitor/warningHistory/home' });
-        showWarningBroad();
-      }
+    async function toMore() {
+      await router.push({ path: '/monitorChannel/device-monitor/warningHistory/home' });
+      showWarningBroad();
+    }
 
-      // 初始化 WebSocket
-      function initWebSocket() {
-        let token = getToken();
-        //将登录token生成一个短的标识
-        // let wsClientId = md5(token);
-        // let userId = unref(userStore.getUserInfo).id + '_' + wsClientId;
-        let userId = unref(userStore.getUserInfo).id + '?token=' + token;
-        console.log(userStore.getUserInfo, 'userId---');
-        // WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
-        // let url = glob.wsUrl?.replace('https://', 'wss://').replace('http://', 'ws://') + '/websocket/' + userId;
-        let url = 'http://' + window.location.hostname + ':9999'?.replace('https://', 'wss://').replace('http://', 'ws://') + '/websocket/' + userId;
-        console.log(url, 'url------');
-        connectWebSocket(url);
-        onWebSocket(onWebSocketMessage);
-      }
+    // 初始化 WebSocket
+    function initWebSocket() {
+      let token = getToken();
+      //将登录token生成一个短的标识
+      // let wsClientId = md5(token);
+      // let userId = unref(userStore.getUserInfo).id + '_' + wsClientId;
+      let userId = unref(userStore.getUserInfo).id + '?token=' + token;
+      console.log(userStore.getUserInfo, 'userId---');
+      // WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
+      // let url = glob.wsUrl?.replace('https://', 'wss://').replace('http://', 'ws://') + '/websocket/' + userId;
+      let url = 'http://' + window.location.hostname + ':9999'?.replace('https://', 'wss://').replace('http://', 'ws://') + '/websocket/' + userId;
+      console.log(url, 'url------');
+      connectWebSocket(url);
+      onWebSocket(onWebSocketMessage);
+    }
 
-      async function onWebSocketMessage(data) {
-        console.log('WebSocket 监测消息--------------》', data);
-        if (data.topic === 'warn' || data.cmd === 'user') {
-          if (isBroad.value) {
-            await speakVoice.getSpeechCnVoices();
-            const messageText = data['warndata'];
-            speakVoice.handleReply(messageText);
-            const time = dayjs().format('YYYY-MM-DD HH:mm:ss');
-            console.log(time + '语音播报开始报警------>', data);
-          }
-          if (!isShowWarningBroad.value) {
-            isWarningDot.value = true;
-          } else {
-            isWarningDot.value = false;
-          }
-          setTimeout(() => {
-            if (isShowWarningBroad.value) {
-              toSelectList(0);
-            }
-          }, 0);
+    async function onWebSocketMessage(data) {
+      console.log('WebSocket 监测消息--------------》', data);
+      if (data.topic === 'warn' || data.cmd === 'user') {
+        if (isBroad.value) {
+          await speakVoice.getSpeechCnVoices();
+          const messageText = data['warndata'];
+          speakVoice.handleReply(messageText);
+          const time = dayjs().format('YYYY-MM-DD HH:mm:ss');
+          console.log(time + '语音播报开始报警------>', data);
+        }
+        if (!isShowWarningBroad.value) {
+          isWarningDot.value = true;
+        } else {
+          isWarningDot.value = false;
         }
+        setTimeout(() => {
+          if (isShowWarningBroad.value) {
+            toSelectList(0);
+          }
+        }, 0);
       }
-      onMounted(() => {
-        speakVoice = new SpeakVoice();
-        nextTick(async () => {
-          initWebSocket();
-          await toSelectList(1);
-        });
-        window.speechSynthesis.onvoiceschanged = () => {
-          console.log('语音列表已更新');
-        };
+    }
+    onMounted(() => {
+      speakVoice = new SpeakVoice();
+      nextTick(async () => {
+        initWebSocket();
+        await toSelectList(1);
       });
-
-      return {
-        showWarningBroad,
-        isShowWarningBroad,
-        activeKey,
-        toSelectList,
-        broadcastList,
-        toMore,
-        isBroad,
-        handleBroad,
-        clearInfo,
-        isWarningDot,
+      window.speechSynthesis.onvoiceschanged = () => {
+        console.log('语音列表已更新');
       };
-    },
-  });
+    });
+
+    return {
+      showWarningBroad,
+      isShowWarningBroad,
+      activeKey,
+      toSelectList,
+      broadcastList,
+      toMore,
+      isBroad,
+      handleBroad,
+      clearInfo,
+      closeWarningBroad,
+      isWarningDot,
+    };
+  },
+});
 </script>
 <style lang="less" scoped>
-  .btn {
-    line-height: 30px;
-    margin-right: 10px;
-    cursor: pointer;
-    display: flex;
-  }
+.btn {
+  line-height: 30px;
+  margin-right: 10px;
+  cursor: pointer;
+  display: flex;
+}
 
-  .no-play {
-    position: relative;
-    &::after {
-      position: absolute;
-      width: 70%;
-      height: 100%;
-      content: '';
-      left: 15%;
-      top: 0;
-      background: linear-gradient(
-        to bottom left,
-        transparent 0%,
-        transparent calc(50% - 1px),
-        #ffffff 50%,
-        transparent calc(50% + 1px),
-        transparent 100%
-      );
-    }
+.no-play {
+  position: relative;
+  &::after {
+    position: absolute;
+    width: 70%;
+    height: 100%;
+    content: '';
+    left: 15%;
+    top: 0;
+    background: linear-gradient(
+      to bottom left,
+      transparent 0%,
+      transparent calc(50% - 1px),
+      #ffffff 50%,
+      transparent calc(50% + 1px),
+      transparent 100%
+    );
   }
+}
 
-  .broadcast {
-    width: 500px;
-    height: 350px;
-    border-radius: 4px;
-    position: fixed;
-    top: 57px;
-    right: 2px;
-    background-color: rgb(255, 255, 255);
-    background: url('../../../../assets/images/warn-dialog-bg.png') no-repeat center;
-    background-size: 100% 100%;
-    z-index: 9999999;
-    color: #fff;
+.broadcast {
+  width: 500px;
+  height: 350px;
+  border-radius: 4px;
+  position: fixed;
+  top: 57px;
+  right: 2px;
+  background-color: rgb(255, 255, 255);
+  background: url('../../../../assets/images/warn-dialog-bg.png') no-repeat center;
+  background-size: 100% 100%;
+  z-index: 9999999;
+  color: #fff;
 
-    .title {
-      height: 32px;
-      padding: 0 20px;
+  .title {
+    height: 32px;
+    padding: 0 20px;
 
-      :deep(.ant-badge:not(.ant-badge-status)) {
-        margin-right: 40px !important;
-      }
+    :deep(.ant-badge:not(.ant-badge-status)) {
+      margin-right: 40px !important;
+    }
 
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    margin-bottom: 5px;
+
+    .message-title {
+      font-size: 18px;
+      padding-top: 10px;
+    }
+
+    .badge-box {
       display: flex;
       align-items: center;
-      justify-content: space-between;
-      margin-bottom: 5px;
+      padding-top: 10px;
+      .badge-title {
+        display: inline-block;
+        width: 62px;
+        line-height: 32px;
+        background-color: #2174f0;
+        border-radius: 26px;
+        text-align: center;
+        color: #fff;
+        padding-bottom: 2px;
+      }
+    }
+  }
 
-      .message-title {
-        font-size: 18px;
-        padding-top: 10px;
+  .broadcast-context {
+    .context-tab {
+      display: flex;
+      padding: 20px;
+      .context-tab-item {
+        line-height: 24px;
+        background-color: #6b6b6b;
+        border-radius: 24px;
+        text-align: center;
+        padding: 0 10px;
+        color: #fff;
+        margin: 5px;
+        cursor: pointer;
+        font-size: 14px;
       }
 
-      .badge-box {
-        display: flex;
-        align-items: center;
-        padding-top: 10px;
-        .badge-title {
-          display: inline-block;
-          width: 62px;
-          line-height: 32px;
-          background-color: #2174f0;
-          border-radius: 26px;
-          text-align: center;
-          color: #fff;
-          padding-bottom: 2px;
-        }
+      .context-tab-item-active {
+        background-color: #2174f0;
       }
     }
 
-    .broadcast-context {
-      .context-tab {
-        display: flex;
-        padding: 20px;
-        .context-tab-item {
-          line-height: 24px;
-          background-color: #6b6b6b;
-          border-radius: 24px;
-          text-align: center;
-          padding: 0 10px;
-          color: #fff;
-          margin: 5px;
-          cursor: pointer;
-          font-size: 14px;
-        }
+    .context-box {
+      flex: 1;
+      padding: 0 10px;
+      height: 200px;
+      overflow-y: auto;
 
-        .context-tab-item-active {
-          background-color: #2174f0;
-        }
+      .no-context {
+        display: flex;
+        justify-content: center;
+        padding-top: 30px;
+        font-size: 16px;
       }
 
-      .context-box {
-        flex: 1;
-        padding: 0 10px;
-        height: 200px;
-        overflow-y: auto;
-
-        .no-context {
-          display: flex;
-          justify-content: center;
-          padding-top: 30px;
-          font-size: 16px;
-        }
+      .context-detail {
+        display: flex;
+        justify-content: space-between;
+        line-height: 24px;
+        padding: 0px 16px;
 
-        .context-detail {
+        div {
           display: flex;
-          justify-content: space-between;
-          line-height: 24px;
-          padding: 0px 16px;
+          justify-content: flex-start;
 
-          div {
-            display: flex;
-            justify-content: flex-start;
-
-            &:nth-child(1) {
-              width: 44%;
-            }
+          &:nth-child(1) {
+            width: 44%;
+          }
 
-            &:nth-child(2) {
-              width: 40%;
-            }
+          &:nth-child(2) {
+            width: 40%;
+          }
 
-            &:nth-child(3) {
-              width: 25%;
-            }
+          &:nth-child(3) {
+            width: 25%;
+          }
 
-            &:nth-child(4) {
-              width: 15%;
-            }
+          &:nth-child(4) {
+            width: 15%;
           }
         }
       }
-      .more {
-        position: absolute;
-        left: 24px;
-        bottom: 10px;
-        cursor: pointer;
+    }
+    .more {
+      position: absolute;
+      left: 24px;
+      bottom: 10px;
+      cursor: pointer;
 
-        &:hover {
-          color: #2174f0;
-        }
+      &:hover {
+        color: #2174f0;
       }
     }
   }
-  :deep(.zxm-badge-count) {
-    width: 8px;
-    height: 8px;
-  }
+}
+:deep(.zxm-badge-count) {
+  width: 8px;
+  height: 8px;
+}
 </style>

+ 238 - 232
src/layouts/default/header/components/VoiceBroadcastGsd.vue

@@ -12,6 +12,7 @@
         <div class="badge-box">
           <ClearOutlined style="font-size: 20px; color: #fff" @click="clearInfo" />
           <SoundOutlined :class="{ 'no-play': !isBroad }" style="font-size: 20px; color: #fff" @click="handleBroad" />
+          <CloseOutlined style="font-size: 20px; color: #fff" @click="closeWarningBroad" />
         </div>
       </div>
       <div class="broadcast-context">
@@ -34,279 +35,284 @@
   </div>
 </template>
 <script lang="ts">
-  import { SoundOutlined, ClearOutlined, BellOutlined, WarningOutlined } from '@ant-design/icons-vue';
-  import { defineComponent, ref, unref, onMounted, nextTick, computed } from 'vue';
-  import { useRouter } from 'vue-router';
-  import { connectWebSocket, onWebSocket } from '/@/hooks/web/useWebSocket';
-  import { getToken } from '/@/utils/auth';
-  import { useUserStore } from '/@/store/modules/user';
-  import { useGlobSetting } from '/@/hooks/setting';
-  import SpeakVoice from './notify/speakVoice';
+import { SoundOutlined, ClearOutlined, BellOutlined, WarningOutlined, CloseOutlined } from '@ant-design/icons-vue';
+import { defineComponent, ref, unref, onMounted, nextTick, computed } from 'vue';
+import { useRouter } from 'vue-router';
+import { connectWebSocket, onWebSocket } from '/@/hooks/web/useWebSocket';
+import { getToken } from '/@/utils/auth';
+import { useUserStore } from '/@/store/modules/user';
+import { useGlobSetting } from '/@/hooks/setting';
+import SpeakVoice from './notify/speakVoice';
 
-  import { useDrag } from '@/hooks/event/useDrag';
-  export default defineComponent({
-    name: 'VoiceBroadcast',
-    components: { SoundOutlined, ClearOutlined, BellOutlined, WarningOutlined },
+import { useDrag } from '@/hooks/event/useDrag';
+export default defineComponent({
+  name: 'VoiceBroadcast',
+  components: { SoundOutlined, ClearOutlined, BellOutlined, WarningOutlined, CloseOutlined },
 
-    setup() {
-      let speakVoice;
-      let broadcastList = ref<any[]>([]);
-      const userStore = useUserStore();
-      const glob = useGlobSetting();
-      const router = useRouter();
-      const activeKey = ref(0);
-      const isShowWarningBroad = ref(false);
-      const isBroad = ref(false);
-      const isWarningDot = ref(false);
+  setup() {
+    let speakVoice;
+    let broadcastList = ref<any[]>([]);
+    const userStore = useUserStore();
+    const glob = useGlobSetting();
+    const router = useRouter();
+    const activeKey = ref(0);
+    const isShowWarningBroad = ref(false);
+    const isBroad = ref(false);
+    const isWarningDot = ref(false);
 
-      //点击切换预警信息弹窗显示
-      function showWarningBroad() {
-        isShowWarningBroad.value = !isShowWarningBroad.value;
-        if (isShowWarningBroad.value) {
-          nextTick(() => {
-            const dom = document.getElementById('VoiceBroadcast');
-            if (dom) useDrag(dom);
-          });
-        }
-      }
-      function handleBroad() {
-        isBroad.value = !isBroad.value;
-      }
-      async function clearInfo() {
-        broadcastList.value = [];
-        localStorage.removeItem('messageArr');
+    //点击切换预警信息弹窗显示
+    function showWarningBroad() {
+      isShowWarningBroad.value = !isShowWarningBroad.value;
+      if (isShowWarningBroad.value) {
+        nextTick(() => {
+          const dom = document.getElementById('VoiceBroadcast');
+          if (dom) useDrag(dom);
+        });
       }
+    }
+    //点击关闭预警信息弹窗
+    function closeWarningBroad() {
+      isShowWarningBroad.value = false;
+    }
+    function handleBroad() {
+      isBroad.value = !isBroad.value;
+    }
+    async function clearInfo() {
+      broadcastList.value = [];
+      localStorage.removeItem('messageArr');
+    }
 
-      //点击跳转预警历史详情
-      async function toMore() {
-        await router.push({ path: '/monitorChannel/device-monitor/warningHistory/company/home' });
-        showWarningBroad();
-      }
+    //点击跳转预警历史详情
+    async function toMore() {
+      await router.push({ path: '/monitorChannel/device-monitor/warningHistory/company/home' });
+      showWarningBroad();
+    }
 
-      // 初始化 WebSocket
-      function initWebSocket() {
-        let token = getToken();
-        //将登录token生成一个短的标识
-        // let wsClientId = md5(token);
-        // let userId = unref(userStore.getUserInfo).id + '_' + wsClientId;
-        let userId = unref(userStore.getUserInfo).id + '?token=' + token;
-        // WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
-        let url = 'http://' + window.location.hostname + ':9999'?.replace('https://', 'wss://').replace('http://', 'ws://') + '/websocket/' + userId;
-        connectWebSocket(url);
-        onWebSocket(onWebSocketMessage);
-      }
+    // 初始化 WebSocket
+    function initWebSocket() {
+      let token = getToken();
+      //将登录token生成一个短的标识
+      // let wsClientId = md5(token);
+      // let userId = unref(userStore.getUserInfo).id + '_' + wsClientId;
+      let userId = unref(userStore.getUserInfo).id + '?token=' + token;
+      // WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
+      let url = 'http://' + window.location.hostname + ':9999'?.replace('https://', 'wss://').replace('http://', 'ws://') + '/websocket/' + userId;
+      connectWebSocket(url);
+      onWebSocket(onWebSocketMessage);
+    }
 
-      async function onWebSocketMessage(data) {
-        console.log('WebSocket 监测消息--------------》', data);
-        if (data.topic === 'warn') {
-          const messageText = data['warndata'];
-          const msgList = [...broadcastList.value];
-          if (msgList.length <= 20) {
-            msgList.push({ label: messageText });
-            localStorage.removeItem('messageArr');
-            localStorage.setItem('messageArr', msgList as any);
-          } else {
-            msgList.shift();
-            msgList.push({ label: messageText });
-            localStorage.removeItem('messageArr');
-            localStorage.setItem('messageArr', msgList as any);
-          }
-          broadcastList.value = msgList;
-          if (isBroad.value) {
-            await speakVoice.getSpeechCnVoices();
-            speakVoice.handleReply(messageText);
-            const time = dayjs().format('YYYY-MM-DD HH:mm:ss');
-            console.log(time + '语音播报开始报警------>', data);
-          }
-          //   const messageText = '这是一个测试';
-          if (!isShowWarningBroad.value) {
-            isWarningDot.value = true;
-          } else {
-            isWarningDot.value = false;
-          }
+    async function onWebSocketMessage(data) {
+      console.log('WebSocket 监测消息--------------》', data);
+      if (data.topic === 'warn') {
+        const messageText = data['warndata'];
+        const msgList = [...broadcastList.value];
+        if (msgList.length <= 20) {
+          msgList.push({ label: messageText });
+          localStorage.removeItem('messageArr');
+          localStorage.setItem('messageArr', msgList as any);
+        } else {
+          msgList.shift();
+          msgList.push({ label: messageText });
+          localStorage.removeItem('messageArr');
+          localStorage.setItem('messageArr', msgList as any);
+        }
+        broadcastList.value = msgList;
+        if (isBroad.value) {
+          await speakVoice.getSpeechCnVoices();
+          speakVoice.handleReply(messageText);
+          const time = dayjs().format('YYYY-MM-DD HH:mm:ss');
+          console.log(time + '语音播报开始报警------>', data);
+        }
+        //   const messageText = '这是一个测试';
+        if (!isShowWarningBroad.value) {
+          isWarningDot.value = true;
+        } else {
+          isWarningDot.value = false;
         }
       }
-      onMounted(() => {
-        speakVoice = new SpeakVoice();
-        nextTick(async () => {
-          initWebSocket();
-        });
-        window.speechSynthesis.onvoiceschanged = () => {
-          console.log('语音列表已更新');
-        };
+    }
+    onMounted(() => {
+      speakVoice = new SpeakVoice();
+      nextTick(async () => {
+        initWebSocket();
       });
-
-      return {
-        showWarningBroad,
-        isShowWarningBroad,
-        activeKey,
-        broadcastList,
-        toMore,
-        clearInfo,
-        isWarningDot,
-        handleBroad,
-        isBroad,
+      window.speechSynthesis.onvoiceschanged = () => {
+        console.log('语音列表已更新');
       };
-    },
-  });
+    });
+
+    return {
+      showWarningBroad,
+      isShowWarningBroad,
+      activeKey,
+      broadcastList,
+      toMore,
+      clearInfo,
+      isWarningDot,
+      handleBroad,
+      closeWarningBroad,
+      isBroad,
+    };
+  },
+});
 </script>
 <style lang="less" scoped>
-  .btn {
-    line-height: 30px;
-    margin-right: 10px;
-    cursor: pointer;
-    display: flex;
-  }
+.btn {
+  line-height: 30px;
+  margin-right: 10px;
+  cursor: pointer;
+  display: flex;
+}
 
-  .no-play {
-    position: relative;
-    &::after {
-      position: absolute;
-      width: 70%;
-      height: 100%;
-      content: '';
-      left: 15%;
-      top: 0;
-      background: linear-gradient(
-        to bottom left,
-        transparent 0%,
-        transparent calc(50% - 1px),
-        #ffffff 50%,
-        transparent calc(50% + 1px),
-        transparent 100%
-      );
-    }
+.no-play {
+  position: relative;
+  &::after {
+    position: absolute;
+    width: 70%;
+    height: 100%;
+    content: '';
+    left: 15%;
+    top: 0;
+    background: linear-gradient(
+      to bottom left,
+      transparent 0%,
+      transparent calc(50% - 1px),
+      #ffffff 50%,
+      transparent calc(50% + 1px),
+      transparent 100%
+    );
   }
+}
 
-  .broadcast {
-    width: 500px;
-    height: 350px;
-    border-radius: 4px;
-    position: fixed;
-    top: 50px;
-    right: 20px;
-    background-color: rgb(255, 255, 255);
-    background: url('../../../../assets/images/warn-dialog-bg.png') no-repeat center;
-    background-size: 100% 100%;
-    z-index: 9999999;
-    color: #fff;
+.broadcast {
+  width: 500px;
+  height: 350px;
+  border-radius: 4px;
+  position: fixed;
+  top: 50px;
+  right: 20px;
+  background-color: rgb(255, 255, 255);
+  background: url('../../../../assets/images/warn-dialog-bg.png') no-repeat center;
+  background-size: 100% 100%;
+  z-index: 9999999;
+  color: #fff;
 
-    .title {
-      height: 32px;
-      padding: 0 20px;
+  .title {
+    height: 32px;
+    padding: 0 20px;
 
-      :deep(.ant-badge:not(.ant-badge-status)) {
-        margin-right: 40px !important;
-      }
+    :deep(.ant-badge:not(.ant-badge-status)) {
+      margin-right: 40px !important;
+    }
 
-      display: flex;
-      align-items: center;
-      justify-content: space-between;
-      margin-bottom: 5px;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    margin-bottom: 5px;
 
-      .message-title {
-        font-size: 18px;
-        padding-top: 10px;
-      }
+    .message-title {
+      font-size: 18px;
+      padding-top: 10px;
+    }
 
-      .badge-box {
-        display: flex;
-        align-items: center;
-        padding-top: 10px;
+    .badge-box {
+      display: flex;
+      align-items: center;
+      padding-top: 10px;
 
-        .badge-title {
-          display: inline-block;
-          width: 62px;
-          line-height: 32px;
-          background-color: #2174f0;
-          border-radius: 26px;
-          text-align: center;
-          color: #fff;
-          padding-bottom: 2px;
-        }
+      .badge-title {
+        display: inline-block;
+        width: 62px;
+        line-height: 32px;
+        background-color: #2174f0;
+        border-radius: 26px;
+        text-align: center;
+        color: #fff;
+        padding-bottom: 2px;
       }
     }
+  }
 
-    .broadcast-context {
-      .context-tab {
-        display: flex;
-        padding: 20px;
+  .broadcast-context {
+    .context-tab {
+      display: flex;
+      padding: 20px;
 
-        .context-tab-item {
-          line-height: 24px;
-          background-color: #6b6b6b;
-          border-radius: 24px;
-          text-align: center;
-          padding: 0 10px;
-          color: #fff;
-          margin: 5px;
-          cursor: pointer;
-          font-size: 14px;
-        }
+      .context-tab-item {
+        line-height: 24px;
+        background-color: #6b6b6b;
+        border-radius: 24px;
+        text-align: center;
+        padding: 0 10px;
+        color: #fff;
+        margin: 5px;
+        cursor: pointer;
+        font-size: 14px;
+      }
 
-        .context-tab-item-active {
-          background-color: #2174f0;
-        }
+      .context-tab-item-active {
+        background-color: #2174f0;
       }
+    }
 
-      .context-box {
-        flex: 1;
-        padding: 0 10px;
-        height: 200px;
-        overflow-y: auto;
+    .context-box {
+      flex: 1;
+      padding: 0 10px;
+      height: 200px;
+      overflow-y: auto;
 
-        .no-context {
-          display: flex;
-          justify-content: center;
-          padding-top: 30px;
-          font-size: 16px;
-        }
+      .no-context {
+        display: flex;
+        justify-content: center;
+        padding-top: 30px;
+        font-size: 16px;
+      }
 
-        .context-detail {
-          width: 100%;
-          display: flex;
-          justify-content: space-between;
-          line-height: 24px;
-          padding: 0px 16px;
+      .context-detail {
+        width: 100%;
+        display: flex;
+        justify-content: space-between;
+        line-height: 24px;
+        padding: 0px 16px;
 
-          // div {
-          //     display: flex;
-          //     justify-content: flex-start;
+        // div {
+        //     display: flex;
+        //     justify-content: flex-start;
 
-          //     &:nth-child(1) {
-          //         width: 44%;
-          //     }
+        //     &:nth-child(1) {
+        //         width: 44%;
+        //     }
 
-          //     &:nth-child(2) {
-          //         width: 40%;
-          //     }
+        //     &:nth-child(2) {
+        //         width: 40%;
+        //     }
 
-          //     &:nth-child(3) {
-          //         width: 25%;
-          //     }
+        //     &:nth-child(3) {
+        //         width: 25%;
+        //     }
 
-          //     &:nth-child(4) {
-          //         width: 15%;
-          //     }
-          // }
-        }
+        //     &:nth-child(4) {
+        //         width: 15%;
+        //     }
+        // }
       }
+    }
 
-      .more {
-        position: absolute;
-        left: 24px;
-        bottom: 10px;
-        cursor: pointer;
+    .more {
+      position: absolute;
+      left: 24px;
+      bottom: 10px;
+      cursor: pointer;
 
-        &:hover {
-          color: #2174f0;
-        }
+      &:hover {
+        color: #2174f0;
       }
     }
   }
+}
 
-  :deep(.zxm-badge-count) {
-    width: 8px;
-    height: 8px;
-  }
+:deep(.zxm-badge-count) {
+  width: 8px;
+  height: 8px;
+}
 </style>

+ 1 - 0
src/store/modules/permission.ts

@@ -242,6 +242,7 @@ export const usePermissionStore = defineStore({
                   hasIndex =
                     menuItem.component === 'layouts/default/index' ||
                     menuItem.component === 'layouts/RouteView' ||
+                    menuItem.component === 'vent/home/configurable/vent182' ||
                     menuItem.path === '/dashboard/analysis';
                 }
                 // 条件2:判断图标是否带有 冒号

+ 49 - 44
src/views/system/role/components/RoleDrawer.vue

@@ -4,50 +4,55 @@
   </BasicDrawer>
 </template>
 <script lang="ts" setup>
-  import { ref, computed, unref, useAttrs } from 'vue';
-  import { BasicForm, useForm } from '/src/components/Form';
-  import { BasicDrawer, useDrawerInner } from '/src/components/Drawer';
-  import { BasicTree, TreeItem } from '/src/components/Tree';
-  import { formSchema } from '../role.data';
-  import { saveOrUpdateRole } from '../role.api';
-  // 声明Emits
-  const emit = defineEmits(['success', 'register']);
-  const attrs = useAttrs();
-  const isUpdate = ref(true);
-  const [registerForm, { setProps, resetFields, setFieldsValue, validate }] = useForm({
-    labelWidth: 90,
-    schemas: formSchema,
-    showActionButtonGroup: false,
-  });
-  const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
-    resetFields();
-    isUpdate.value = !!data?.isUpdate;
+import { ref, computed, unref, useAttrs } from 'vue';
+import { BasicForm, useForm } from '/src/components/Form';
+import { BasicDrawer, useDrawerInner } from '/src/components/Drawer';
+import { BasicTree, TreeItem } from '/src/components/Tree';
+import { formSchema } from '../role.data';
+import { saveOrUpdateRole } from '../role.api';
+// 声明Emits
+const emit = defineEmits(['success', 'register']);
+const attrs = useAttrs();
+const isUpdate = ref(true);
+const [registerForm, { setProps, resetFields, setFieldsValue, validate }] = useForm({
+  labelWidth: 90,
+  schemas: formSchema,
+  showActionButtonGroup: false,
+});
+const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
+  resetFields();
+  isUpdate.value = !!data?.isUpdate;
+  setDrawerProps({ confirmLoading: false });
+  if (unref(isUpdate)) {
+    setFieldsValue({
+      ...data.record,
+    });
+  }
+  //禁用表单
+  setProps({ disabled: !attrs.showFooter });
+});
+/**
+ * 标题
+ */
+const getTitle = computed(() => (!unref(isUpdate) ? '新增角色' : '编辑角色'));
+/**
+ * 提交
+ */
+async function handleSubmit() {
+  try {
+    const values = await validate();
+    setDrawerProps({ confirmLoading: true });
+    // //提交表单
+    // await saveOrUpdateRole(values, isUpdate.value);
+    // closeDrawer();
+    await saveOrUpdateRole(values, isUpdate.value);
+    closeDrawer();
+    emit('success', {
+      isUpdate: unref(isUpdate),
+      record: values,
+    });
+  } finally {
     setDrawerProps({ confirmLoading: false });
-    if (unref(isUpdate)) {
-      setFieldsValue({
-        ...data.record,
-      });
-    }
-    //禁用表单
-    setProps({ disabled: !attrs.showFooter });
-  });
-  /**
-   * 标题
-   */
-  const getTitle = computed(() => (!unref(isUpdate) ? '新增角色' : '编辑角色'));
-  /**
-   * 提交
-   */
-  async function handleSubmit() {
-    try {
-      const values = await validate();
-      setDrawerProps({ confirmLoading: true });
-      //提交表单
-      await saveOrUpdateRole(values, isUpdate.value);
-      closeDrawer();
-      emit('success');
-    } finally {
-      setDrawerProps({ confirmLoading: false });
-    }
   }
+}
 </script>

+ 147 - 147
src/views/system/role/components/RolePermissionDrawer.vue

@@ -46,161 +46,161 @@
   </BasicDrawer>
 </template>
 <script lang="ts" setup>
-  import { ref, computed, unref, onMounted } from 'vue';
-  import { BasicDrawer, useDrawer, useDrawerInner } from '/src/components/Drawer';
-  import { BasicTree, TreeItem } from '/src/components/Tree';
-  import { PopConfirmButton } from '/@/components/Button';
-  import RoleDataRuleDrawer from './RoleDataRuleDrawer.vue';
-  import { queryTreeListForRole, queryRolePermission, saveRolePermission } from '../role.api';
-  const emit = defineEmits(['register']);
-  //树的信息
-  const treeData = ref<TreeItem[]>([]);
-  //树的全部节点信息
-  const allTreeKeys = ref([]);
-  //树的选择节点信息
-  const checkedKeys = ref([]);
-  const defaultCheckedKeys = ref([]);
-  //树的选中的节点信息
-  const selectedKeys = ref([]);
-  const roleId = ref('');
-  //树的实例
-  const treeRef = ref(null);
-  const loading = ref(false);
+import { ref, computed, unref, onMounted } from 'vue';
+import { BasicDrawer, useDrawer, useDrawerInner } from '/src/components/Drawer';
+import { BasicTree, TreeItem } from '/src/components/Tree';
+import { PopConfirmButton } from '/@/components/Button';
+import RoleDataRuleDrawer from './RoleDataRuleDrawer.vue';
+import { queryTreeListForRole, queryRolePermission, saveRolePermission } from '../role.api';
+const emit = defineEmits(['register']);
+//树的信息
+const treeData = ref<TreeItem[]>([]);
+//树的全部节点信息
+const allTreeKeys = ref([]);
+//树的选择节点信息
+const checkedKeys = ref([]);
+const defaultCheckedKeys = ref([]);
+//树的选中的节点信息
+const selectedKeys = ref([]);
+const roleId = ref('');
+//树的实例
+const treeRef = ref(null);
+const loading = ref(false);
 
-  //展开折叠的key
-  const expandedKeys = ref<any>([]);
-  //父子节点选中状态是否关联
-  const checkStrictly = ref<boolean>(true);
-  const [registerDrawer1, { openDrawer: openDataRuleDrawer }] = useDrawer();
-  const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
-    await reset();
-    setDrawerProps({ confirmLoading: false, loading: true });
-    roleId.value = data.roleId;
-    //初始化数据
-    const roleResult = await queryTreeListForRole();
-    treeData.value = roleResult.treeList;
-    allTreeKeys.value = roleResult.ids;
-    expandedKeys.value = roleResult.ids;
-    //初始化角色菜单数据
-    const permResult = await queryRolePermission({ roleId: unref(roleId) });
-    checkedKeys.value = permResult;
-    defaultCheckedKeys.value = permResult;
-    setDrawerProps({ loading: false });
-  });
-  /**
-   * 点击选中
-   */
-  function onCheck(o) {
-    checkedKeys.value = o.checked ? o.checked : o;
-  }
-  /**
-   * 选中节点,打开数据权限抽屉
-   */
-  function onTreeNodeSelect(key) {
-    if (key && key.length > 0) {
-      selectedKeys.value = key;
-    }
-    openDataRuleDrawer(true, { functionId: unref(selectedKeys)[0], roleId: unref(roleId) });
+//展开折叠的key
+const expandedKeys = ref<any>([]);
+//父子节点选中状态是否关联
+const checkStrictly = ref<boolean>(true);
+const [registerDrawer1, { openDrawer: openDataRuleDrawer }] = useDrawer();
+const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
+  await reset();
+  setDrawerProps({ confirmLoading: false, loading: true });
+  roleId.value = data.roleId;
+  //初始化数据
+  const roleResult = await queryTreeListForRole();
+  treeData.value = roleResult.treeList;
+  allTreeKeys.value = roleResult.ids;
+  expandedKeys.value = [];
+  //初始化角色菜单数据
+  const permResult = await queryRolePermission({ roleId: unref(roleId) });
+  checkedKeys.value = permResult;
+  defaultCheckedKeys.value = permResult;
+  setDrawerProps({ loading: false });
+});
+/**
+ * 点击选中
+ */
+function onCheck(o) {
+  checkedKeys.value = o.checked ? o.checked : o;
+}
+/**
+ * 选中节点,打开数据权限抽屉
+ */
+function onTreeNodeSelect(key) {
+  if (key && key.length > 0) {
+    selectedKeys.value = key;
   }
-  /**
-   * 数据重置
-   */
-  function reset() {
-    treeData.value = [];
-    allTreeKeys.value = [];
-    checkedKeys.value = [];
-    defaultCheckedKeys.value = [];
-    selectedKeys.value = [];
-    roleId.value = '';
+  openDataRuleDrawer(true, { functionId: unref(selectedKeys)[0], roleId: unref(roleId) });
+}
+/**
+ * 数据重置
+ */
+function reset() {
+  treeData.value = [];
+  allTreeKeys.value = [];
+  checkedKeys.value = [];
+  defaultCheckedKeys.value = [];
+  selectedKeys.value = [];
+  roleId.value = '';
+}
+/**
+ * 获取tree实例
+ */
+function getTree() {
+  const tree = unref(treeRef);
+  if (!tree) {
+    throw new Error('tree is null!');
   }
-  /**
-   * 获取tree实例
-   */
-  function getTree() {
-    const tree = unref(treeRef);
-    if (!tree) {
-      throw new Error('tree is null!');
-    }
-    return tree;
+  return tree;
+}
+/**
+ * 提交
+ */
+async function handleSubmit(exit) {
+  let params = {
+    roleId: unref(roleId),
+    permissionIds: unref(getTree().getCheckedKeys()).join(','),
+    lastpermissionIds: unref(defaultCheckedKeys).join(','),
+  };
+  //update-begin-author:taoyan date:2023-2-11 for: issues/352 VUE角色授权重复保存
+  if (loading.value === false) {
+    await doSave(params);
+  } else {
+    console.log('请等待上次执行完毕!');
   }
-  /**
-   * 提交
-   */
-  async function handleSubmit(exit) {
-    let params = {
-      roleId: unref(roleId),
-      permissionIds: unref(getTree().getCheckedKeys()).join(','),
-      lastpermissionIds: unref(defaultCheckedKeys).join(','),
-    };
-    //update-begin-author:taoyan date:2023-2-11 for: issues/352 VUE角色授权重复保存
-    if (loading.value === false) {
-      await doSave(params);
-    } else {
-      console.log('请等待上次执行完毕!');
-    }
-    if (exit) {
-      // 如果关闭
-      closeDrawer();
-    } else {
-      // 没有关闭需要重新获取选中数据
-      const permResult = await queryRolePermission({ roleId: unref(roleId) });
-      defaultCheckedKeys.value = permResult;
-    }
+  if (exit) {
+    // 如果关闭
+    closeDrawer();
+  } else {
+    // 没有关闭需要重新获取选中数据
+    const permResult = await queryRolePermission({ roleId: unref(roleId) });
+    defaultCheckedKeys.value = permResult;
   }
+}
 
-  // VUE角色授权重复保存 #352
-  async function doSave(params) {
-    loading.value = true;
-    await saveRolePermission(params);
-    setTimeout(() => {
-      loading.value = false;
-    }, 500);
-  }
-  //update-end-author:taoyan date:2023-2-11 for: issues/352 VUE角色授权重复保存
+// VUE角色授权重复保存 #352
+async function doSave(params) {
+  loading.value = true;
+  await saveRolePermission(params);
+  setTimeout(() => {
+    loading.value = false;
+  }, 500);
+}
+//update-end-author:taoyan date:2023-2-11 for: issues/352 VUE角色授权重复保存
 
-  /**
-   * 树菜单选择
-   * @param key
-   */
-  function treeMenuClick({ key }) {
-    if (key === 'checkAll') {
-      checkedKeys.value = allTreeKeys.value;
-    } else if (key === 'cancelCheck') {
-      checkedKeys.value = [];
-    } else if (key === 'openAll') {
-      expandedKeys.value = allTreeKeys.value;
-    } else if (key === 'closeAll') {
-      expandedKeys.value = [];
-    } else if (key === 'relation') {
-      checkStrictly.value = false;
-    } else {
-      checkStrictly.value = true;
-    }
+/**
+ * 树菜单选择
+ * @param key
+ */
+function treeMenuClick({ key }) {
+  if (key === 'checkAll') {
+    checkedKeys.value = allTreeKeys.value;
+  } else if (key === 'cancelCheck') {
+    checkedKeys.value = [];
+  } else if (key === 'openAll') {
+    expandedKeys.value = allTreeKeys.value;
+  } else if (key === 'closeAll') {
+    expandedKeys.value = [];
+  } else if (key === 'relation') {
+    checkStrictly.value = false;
+  } else {
+    checkStrictly.value = true;
   }
+}
 </script>
 
 <style lang="less" scoped>
-  /** 固定操作按钮 */
-  .jeecg-basic-tree {
-    position: absolute;
-    width: 618px;
-  }
-  //update-begin---author:wangshuai ---date:20230202  for:抽屉弹窗标题图标下拉样式------------
-  .line {
-    height: 1px;
-    width: 100%;
-    border-bottom: 1px solid #f0f0f0;
-  }
-  .more-icon {
-    font-size: 20px !important;
-    color: rgb(255, 255, 255);
-    display: inline-flex;
-    float: right;
-    margin-right: 2px;
-    cursor: pointer;
-  }
-  :deep(.jeecg-tree-header) {
-    border-bottom: none;
-  }
-  //update-end---author:wangshuai ---date:20230202  for:抽屉弹窗标题图标下拉样式------------
-</style>
+/** 固定操作按钮 */
+.jeecg-basic-tree {
+  position: absolute;
+  width: 618px;
+}
+//update-begin---author:wangshuai ---date:20230202  for:抽屉弹窗标题图标下拉样式------------
+.line {
+  height: 1px;
+  width: 100%;
+  border-bottom: 1px solid #f0f0f0;
+}
+.more-icon {
+  font-size: 20px !important;
+  color: rgb(255, 255, 255);
+  display: inline-flex;
+  float: right;
+  margin-right: 2px;
+  cursor: pointer;
+}
+:deep(.jeecg-tree-header) {
+  border-bottom: none;
+}
+//update-end---author:wangshuai ---date:20230202  for:抽屉弹窗标题图标下拉样式------------
+</style>

+ 223 - 148
src/views/system/role/index.vue

@@ -28,7 +28,7 @@
   <!--角色用户表格-->
   <RoleUserTable @register="roleUserDrawer" />
   <!--角色编辑抽屉-->
-  <RoleDrawer @register="registerDrawer" @success="reload" :showFooter="showFooter" />
+  <RoleDrawer @register="registerDrawer" @success="handleRoleSaveSuccess" :showFooter="showFooter" />
   <!--角色详情-->
   <RoleDesc @register="registerDesc"></RoleDesc>
   <!--角色菜单授权抽屉-->
@@ -37,161 +37,236 @@
   <RoleIndexModal @register="registerIndexModal" />
 </template>
 <script lang="ts" name="system-role" setup>
-  import { ref } from 'vue';
-  import { BasicTable, TableAction } from '/@/components/Table';
-  import { useDrawer } from '/@/components/Drawer';
-  import { useModal } from '/@/components/Modal';
-  import RoleDrawer from './components/RoleDrawer.vue';
-  import RoleDesc from './components/RoleDesc.vue';
-  import RolePermissionDrawer from './components/RolePermissionDrawer.vue';
-  import RoleIndexModal from './components/RoleIndexModal.vue';
-  import RoleUserTable from './components/RoleUserTable.vue';
-  import { columns, searchFormSchema } from './role.data';
-  import { list, deleteRole, batchDeleteRole, getExportUrl, getImportUrl } from './role.api';
-  import { useListPage } from '/@/hooks/system/useListPage';
-  const showFooter = ref(true);
-  const [roleUserDrawer, { openDrawer: openRoleUserDrawer }] = useDrawer();
-  const [registerDrawer, { openDrawer }] = useDrawer();
-  const [registerModal, { openModal }] = useModal();
-  const [registerIndexModal, { openModal: openIndexModal }] = useModal();
-  const [rolePermissionDrawer, { openDrawer: openRolePermissionDrawer }] = useDrawer();
-  const [registerDesc, { openDrawer: openRoleDesc }] = useDrawer();
+import { ref } from 'vue';
+import { BasicTable, TableAction } from '/@/components/Table';
+import { useDrawer } from '/@/components/Drawer';
+import { useModal } from '/@/components/Modal';
+import RoleDrawer from './components/RoleDrawer.vue';
+import RoleDesc from './components/RoleDesc.vue';
+import RolePermissionDrawer from './components/RolePermissionDrawer.vue';
+import RoleIndexModal from './components/RoleIndexModal.vue';
+import RoleUserTable from './components/RoleUserTable.vue';
+import { columns, searchFormSchema } from './role.data';
+// 引入对应接口
+import {
+  list,
+  deleteRole,
+  batchDeleteRole,
+  getExportUrl,
+  getImportUrl,
+  queryTreeListForRole,
+  queryRolePermission,
+  saveRolePermission,
+} from './role.api';
+import { useListPage } from '/@/hooks/system/useListPage';
 
-  // 列表页面公共参数、方法
-  const { prefixCls, tableContext, onImportXls, onExportXls } = useListPage({
-    designScope: 'role-template',
-    tableProps: {
-      title: '系统角色列表',
-      api: list,
-      columns: columns,
-      formConfig: {
-        // update-begin--author:liaozhiyang---date:20230803---for:【QQYUN-5873】查询区域lablel默认居左
-        labelWidth:65,
-        rowProps: { gutter: 24 },
-        // update-end--author:liaozhiyang---date:20230803---for:【QQYUN-5873】查询区域lablel默认居左
-        schemas: searchFormSchema,
-      },
-      actionColumn: {
-        width: 120,
-      },
-      rowSelection: null,
-      //自定义默认排序
-      defSort: {
-        column: 'id',
-        order: 'desc',
-      },
+const showFooter = ref(true);
+const [roleUserDrawer, { openDrawer: openRoleUserDrawer }] = useDrawer();
+const [registerDrawer, { openDrawer }] = useDrawer();
+const [registerModal, { openModal }] = useModal();
+const [registerIndexModal, { openModal: openIndexModal }] = useModal();
+const [rolePermissionDrawer, { openDrawer: openRolePermissionDrawer }] = useDrawer();
+const [registerDesc, { openDrawer: openRoleDesc }] = useDrawer();
+
+// 列表页面公共参数、方法
+const { prefixCls, tableContext, onImportXls, onExportXls } = useListPage({
+  designScope: 'role-template',
+  tableProps: {
+    title: '系统角色列表',
+    api: list,
+    columns: columns,
+    formConfig: {
+      labelWidth: 65,
+      rowProps: { gutter: 24 },
+      schemas: searchFormSchema,
     },
-    exportConfig: {
-      name: '角色列表',
-      url: getExportUrl,
+    actionColumn: {
+      width: 120,
     },
-    importConfig: {
-      url: getImportUrl,
+    rowSelection: null,
+    defSort: {
+      column: 'id',
+      order: 'desc',
     },
-  });
-  const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
+  },
+  exportConfig: {
+    name: '角色列表',
+    url: getExportUrl,
+  },
+  importConfig: {
+    url: getImportUrl,
+  },
+});
+const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
 
-  /**
-   * 新增
-   */
-  function handleCreate() {
-    showFooter.value = true;
-    openDrawer(true, {
-      isUpdate: false,
-    });
-  }
-  /**
-   * 编辑
-   */
-  function handleEdit(record: Recordable) {
-    showFooter.value = true;
-    openDrawer(true, {
-      record,
-      isUpdate: true,
-    });
-  }
-  /**
-   * 详情
-   */
-  function handleDetail(record) {
-    showFooter.value = false;
-    openRoleDesc(true, {
-      record,
-      isUpdate: true,
+/**
+ * 递归收集当前节点 + 全部子节点id
+ * @param node 树节点
+ */
+function collectAllNodeIds(node: Recordable): string[] {
+  const ids: string[] = [node.key];
+  if (node.children && node.children.length > 0) {
+    node.children.forEach((child) => {
+      ids.push(...collectAllNodeIds(child));
     });
   }
-  /**
-   * 删除事件
-   */
-  async function handleDelete(record) {
-    await deleteRole({ id: record.id }, reload);
-  }
-  /**
-   * 批量删除事件
-   */
-  async function batchHandleDelete() {
-    await batchDeleteRole({ ids: selectedRowKeys.value }, reload);
-  }
-  /**
-   * 角色授权弹窗
-   */
-  function handlePerssion(record) {
-    openRolePermissionDrawer(true, { roleId: record.id });
-  }
+  return ids;
+}
 
-  /**
-   * 首页配置弹窗
-   */
-  function handleIndexConfig(roleCode) {
-    openIndexModal(true, { roleCode });
-  }
-  /**
-   * 角色用户
-   */
-  function handleUser(record) {
-    //onSelectChange(selectedRowKeys)
-    openRoleUserDrawer(true, record);
-  }
-  /**
-   * 操作栏
-   */
-  function getTableAction(record) {
-    return [
-      {
-        label: '用户',
-        onClick: handleUser.bind(null, record),
-      },
-      {
-        label: '授权',
-        onClick: handlePerssion.bind(null, record),
-      },
-    ];
+/**
+ * 角色新增/编辑保存回调
+ */
+async function handleRoleSaveSuccess(res: Recordable) {
+  console.log(res, 'res新增1111111');
+  const { isUpdate, record } = res;
+
+  // 只处理新增
+  if (!isUpdate && record?.roleCode) {
+    try {
+      // 1. 请求全部角色列表,用来根据roleCode查询新增角色ID
+      const rolePageRes = await list({ pageNo: 1, pageSize: 9999 });
+      // defHttp 已将响应解包,直接返回 result 字段内容,即 { records: [], total: N }
+      const roleList = rolePageRes.records || [];
+      // 根据唯一编码匹配新增角色
+      const newRoleInfo = roleList.find((item) => item.roleCode === record.roleCode);
+
+      if (!newRoleInfo || !newRoleInfo.id) {
+        console.warn('未能匹配到新增角色,跳过自动授权');
+        reload();
+        return;
+      }
+      const targetRoleId = newRoleInfo.id;
+
+      // 2. 获取权限树,取第一个根节点及其全部子节点授权
+      const treeResult = await queryTreeListForRole();
+      const treeList = treeResult.treeList;
+      if (!Array.isArray(treeList) || treeList.length === 0) {
+        reload();
+        return;
+      }
+      const firstRootNode = treeList[0];
+      const targetIdArr = collectAllNodeIds(firstRootNode);
+      const permissionIdsStr = targetIdArr.join(',');
+
+      // 3. 查询角色旧权限
+      const oldCheckedArr = await queryRolePermission({ roleId: targetRoleId });
+      const lastIdsStr = (Array.isArray(oldCheckedArr) ? oldCheckedArr : []).join(',');
+
+      // 4. 静默授权保存
+      const saveParams = {
+        roleId: targetRoleId,
+        permissionIds: permissionIdsStr,
+        lastpermissionIds: lastIdsStr,
+      };
+      await saveRolePermission(saveParams);
+      console.log('✅自动授权完成');
+    } catch (err) {
+      console.error('新增角色自动授权异常:', err);
+    }
   }
+  reload();
+}
 
-  /**
-   * 下拉操作栏
-   */
-  function getDropDownAction(record) {
-    return [
-      {
-        label: '编辑',
-        onClick: handleEdit.bind(null, record),
-      },
-      {
-        label: '详情',
-        onClick: handleDetail.bind(null, record),
-      },
-      {
-        label: '删除',
-        popConfirm: {
-          title: '是否确认删除',
-          confirm: handleDelete.bind(null, record),
-        },
-      },
-      {
-        label: '首页配置',
-        onClick: handleIndexConfig.bind(null, record.roleCode),
+/**
+ * 新增
+ */
+function handleCreate() {
+  showFooter.value = true;
+  openDrawer(true, {
+    isUpdate: false,
+  });
+}
+/**
+ * 编辑
+ */
+function handleEdit(record: Recordable) {
+  showFooter.value = true;
+  openDrawer(true, {
+    record,
+    isUpdate: true,
+  });
+}
+/**
+ * 详情
+ */
+function handleDetail(record) {
+  showFooter.value = false;
+  openRoleDesc(true, {
+    record,
+    isUpdate: true,
+  });
+}
+/**
+ * 删除事件
+ */
+async function handleDelete(record) {
+  await deleteRole({ id: record.id }, reload);
+}
+/**
+ * 批量删除事件
+ */
+async function batchHandleDelete() {
+  await batchDeleteRole({ ids: selectedRowKeys.value }, reload);
+}
+/**
+ * 角色授权弹窗
+ */
+function handlePerssion(record) {
+  openRolePermissionDrawer(true, { roleId: record.id });
+}
+
+/**
+ * 首页配置弹窗
+ */
+function handleIndexConfig(roleCode) {
+  openIndexModal(true, { roleCode });
+}
+/**
+ * 角色用户
+ */
+function handleUser(record) {
+  openRoleUserDrawer(true, record);
+}
+/**
+ * 操作栏
+ */
+function getTableAction(record) {
+  return [
+    {
+      label: '用户',
+      onClick: handleUser.bind(null, record),
+    },
+    {
+      label: '授权',
+      onClick: handlePerssion.bind(null, record),
+    },
+  ];
+}
+
+/**
+ * 下拉操作栏
+ */
+function getDropDownAction(record) {
+  return [
+    {
+      label: '编辑',
+      onClick: handleEdit.bind(null, record),
+    },
+    {
+      label: '详情',
+      onClick: handleDetail.bind(null, record),
+    },
+    {
+      label: '删除',
+      popConfirm: {
+        title: '是否确认删除',
+        confirm: handleDelete.bind(null, record),
       },
-    ];
-  }
-</script>
+    },
+    {
+      label: '首页配置',
+      onClick: handleIndexConfig.bind(null, record.roleCode),
+    },
+  ];
+}
+</script>