Procházet zdrojové kódy

Merge branch 'master' of http://39.97.59.228:8013/hrx/goaf-monitoring-system

wangkeyi před 3 měsíci
rodič
revize
dcd41c60ab
24 změnil soubory, kde provedl 2669 přidání a 2665 odebrání
  1. 66 66
      src/components/Application/src/AppLogo.vue
  2. 4 4
      src/components/Configurable/detail/CustomChart.vue
  3. 3 3
      src/components/Configurable/detail/CustomTable.vue
  4. 183 183
      src/components/Container/src/AdaptiveContainer.vue
  5. 82 82
      src/components/Form/src/jeecg/components/formCard/formConfig.vue
  6. 1 1
      src/components/Table/src/BasicTable.vue
  7. 76 76
      src/layouts/default/index.vue
  8. 188 190
      src/layouts/default/menu/index.vue
  9. 179 176
      src/views/analysis/warningAnalysis/connectAnalysis/components/echart-content.vue
  10. 19 21
      src/views/analysis/warningAnalysis/connectAnalysis/components/echart-divder.vue
  11. 48 50
      src/views/analysis/warningAnalysis/connectAnalysis/components/echart-lengend.vue
  12. 40 0
      src/views/analysis/warningAnalysis/connectAnalysis/hooks/form.ts
  13. 20 21
      src/views/analysis/warningAnalysis/connectAnalysis/index.vue
  14. 7 6
      src/views/dashboard/basicInfo/closedStatistics/index.vue
  15. 429 451
      src/views/dashboard/basicInfo/dataQuality/components/DataQualityModal.vue
  16. 6 12
      src/views/dashboard/basicInfo/dataQuality/index.vue
  17. 6 6
      src/views/monitor/sealedMonitor/monitor.data.ts
  18. 132 131
      src/views/sys/login/Login.vue
  19. 192 192
      src/views/sys/login/TokenLoginPage.vue
  20. 1 1
      src/views/system/departUser/index.vue
  21. 90 91
      src/views/system/loginmini/MiniCodelogin.vue
  22. 183 186
      src/views/system/loginmini/MiniForgotpad.vue
  23. 527 529
      src/views/system/loginmini/MiniLogin.vue
  24. 187 187
      src/views/system/loginmini/MiniRegister.vue

+ 66 - 66
src/components/Application/src/AppLogo.vue

@@ -11,84 +11,84 @@
   </div>
 </template>
 <script lang="ts" setup>
-import { computed, unref } from 'vue';
-import { useGlobSetting } from '/@/hooks/setting';
-import { useGo } from '/@/hooks/web/usePage';
-import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
-import { useDesign } from '/@/hooks/web/useDesign';
-import { PageEnum } from '/@/enums/pageEnum';
-import { useUserStore } from '/@/store/modules/user';
+  import { computed, unref } from 'vue';
+  import { useGlobSetting } from '/@/hooks/setting';
+  import { useGo } from '/@/hooks/web/usePage';
+  import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
+  import { useDesign } from '/@/hooks/web/useDesign';
+  import { PageEnum } from '/@/enums/pageEnum';
+  import { useUserStore } from '/@/store/modules/user';
 
-const props = defineProps({
-  /**
-   * The theme of the current parent component
-   */
-  theme: { type: String, validator: (v: string) => ['light', 'dark'].includes(v) },
-  /**
-   * Whether to show title
-   */
-  showTitle: { type: Boolean, default: true },
-  /**
-   * The title is also displayed when the menu is collapsed
-   */
-  alwaysShowTitle: { type: Boolean },
-});
+  const props = defineProps({
+    /**
+     * The theme of the current parent component
+     */
+    theme: { type: String, validator: (v: string) => ['light', 'dark'].includes(v) },
+    /**
+     * Whether to show title
+     */
+    showTitle: { type: Boolean, default: true },
+    /**
+     * The title is also displayed when the menu is collapsed
+     */
+    alwaysShowTitle: { type: Boolean },
+  });
 
-const { prefixCls } = useDesign('app-logo');
-const { getCollapsedShowTitle } = useMenuSetting();
-const userStore = useUserStore();
-const { title } = useGlobSetting();
+  const { prefixCls } = useDesign('app-logo');
+  const { getCollapsedShowTitle } = useMenuSetting();
+  const userStore = useUserStore();
+  const { title } = useGlobSetting();
 
-const go = useGo();
+  const go = useGo();
 
-const getAppLogoClass = computed(() => [prefixCls, props.theme, { 'collapsed-show-title': unref(getCollapsedShowTitle) }]);
+  const getAppLogoClass = computed(() => [prefixCls, props.theme, { 'collapsed-show-title': unref(getCollapsedShowTitle) }]);
 
-const getTitleClass = computed(() => [
-  `${prefixCls}__title`,
-  {
-    'xs:opacity-0': !props.alwaysShowTitle,
-  },
-]);
+  const getTitleClass = computed(() => [
+    `${prefixCls}__title`,
+    {
+      'xs:opacity-0': !props.alwaysShowTitle,
+    },
+  ]);
 
-function goHome() {
-  go(userStore.getUserInfo.homePath || PageEnum.BASE_HOME);
-}
+  function goHome() {
+    go(userStore.getUserInfo.homePath || PageEnum.BASE_HOME);
+  }
 </script>
 <style lang="less" scoped>
-@prefix-cls: ~'@{namespace}-app-logo';
+  @prefix-cls: ~'@{namespace}-app-logo';
 
-.@{prefix-cls} {
-  display: flex;
-  align-items: center;
-  padding-left: 7px;
-  cursor: pointer;
-  transition: all 0.2s ease;
-  //左侧菜单模式和左侧菜单混合模式加渐变背景色
-  // &.jeecg-layout-mix-sider-logo,
-  // &.jeecg-layout-menu-logo {
-  //   background: @sider-logo-bg-color;
-  // }
-  // &.light {
-  //   border-bottom: 1px solid @border-color-base;
-  // }
+  .@{prefix-cls} {
+    display: flex;
+    align-items: center;
+    padding-left: 7px;
+    cursor: pointer;
+    transition: all 0.2s ease;
+    //左侧菜单模式和左侧菜单混合模式加渐变背景色
+    // &.jeecg-layout-mix-sider-logo,
+    // &.jeecg-layout-menu-logo {
+    //   background: @sider-logo-bg-color;
+    // }
+    // &.light {
+    //   border-bottom: 1px solid @border-color-base;
+    // }
 
-  &.collapsed-show-title {
-    padding-left: 20px;
-  }
+    &.collapsed-show-title {
+      padding-left: 20px;
+    }
 
-  &.light &__title {
-    color: @primary-color;
-  }
+    &.light &__title {
+      color: @primary-color;
+    }
 
-  &.dark &__title {
-    color: @white;
-  }
+    &.dark &__title {
+      color: @white;
+    }
 
-  &__title {
-    font-size: 18px;
-    font-weight: 600;
-    transition: all 0.5s;
-    line-height: normal;
+    &__title {
+      font-size: 18px;
+      font-weight: 600;
+      transition: all 0.5s;
+      line-height: normal;
+    }
   }
-}
 </style>

+ 4 - 4
src/components/Configurable/detail/CustomChart.vue

@@ -152,7 +152,7 @@
             type: 'value',
             splitLine: { show: false },
             // name: '氧气浓度(%)',
-            name:'',
+            name: '',
             position: 'left',
             min: function (value) {
               return (value.min - 0.5).toFixed(1);
@@ -193,7 +193,7 @@
             type: 'value',
             splitLine: { show: false },
             // name: '大气压(hPa)',
-            name:'',
+            name: '',
             position: 'right',
             min: function (value) {
               return value.min - 5;
@@ -428,8 +428,8 @@
             textStyle: {
               fontSize: 18,
               color: '#000',
-              fontFamily:'DDIN',
-              fontWeight:'700'
+              fontFamily: 'DDIN',
+              fontWeight: '700',
             },
             data: e.data.map((e) => {
               return `${e[0]}: ${e[1]}`;

+ 3 - 3
src/components/Configurable/detail/CustomTable.vue

@@ -126,12 +126,12 @@
 
     /* 第三个子元素:黄色 */
     .table__content_list_row .table__content__list_item_A:nth-child(3) {
-      color: #B39F01;
+      color: #b39f01;
     }
 
     /* 第四个子元素:橙色 */
     .table__content_list_row .table__content__list_item_A:nth-child(4) {
-      color: #E6A23D;
+      color: #e6a23d;
     }
 
     /* 第五个子元素:红色 */
@@ -163,7 +163,7 @@
 
     /* 第二个子元素:蓝色 */
     .table__content_list_row .table__content__list_item_B:nth-child(2) {
-      color: #0052cc;;
+      color: #0052cc;
     }
 
     /* 第三个子元素:绿色 */

+ 183 - 183
src/components/Container/src/AdaptiveContainer.vue

@@ -6,200 +6,200 @@
 </template>
 
 <script lang="ts">
-import { defineComponent, ref, onMounted, onUnmounted } from 'vue';
-import { debounce } from 'lodash-es';
-import { useAppStore } from '/@/store/modules/app';
-import { computed } from 'vue';
-
-// 类型定义
-interface AdaptiveOptions {
-  width?: number;
-  height?: number;
-  baseWidth?: number; // 设计稿基准宽度,用于REM计算
-  minScale?: number; // 最小缩放比例
-  maxScale?: number; // 最大缩放比例
-  debounceTime?: number; // 防抖时间(ms)
-  ratio?: number; // 宽高比
-  tolerance?: number; // 宽高比容忍度
-}
-
-interface ScaleInfo {
-  widthScale: number;
-  heightScale: number;
-  scale: number;
-}
-
-export default defineComponent({
-  name: 'AdaptiveContainer',
-  props: {
-    options: {
-      type: Object as () => AdaptiveOptions,
-      default: () => ({}),
+  import { defineComponent, ref, onMounted, onUnmounted } from 'vue';
+  import { debounce } from 'lodash-es';
+  import { useAppStore } from '/@/store/modules/app';
+  import { computed } from 'vue';
+
+  // 类型定义
+  interface AdaptiveOptions {
+    width?: number;
+    height?: number;
+    baseWidth?: number; // 设计稿基准宽度,用于REM计算
+    minScale?: number; // 最小缩放比例
+    maxScale?: number; // 最大缩放比例
+    debounceTime?: number; // 防抖时间(ms)
+    ratio?: number; // 宽高比
+    tolerance?: number; // 宽高比容忍度
+  }
+
+  interface ScaleInfo {
+    widthScale: number;
+    heightScale: number;
+    scale: number;
+  }
+
+  export default defineComponent({
+    name: 'AdaptiveContainer',
+    props: {
+      options: {
+        type: Object as () => AdaptiveOptions,
+        default: () => ({}),
+      },
     },
-  },
-  setup(props) {
-    const appStore = useAppStore();
-    const containerRef = ref<HTMLElement | null>(null);
-    // const isReady = ref(false);
-
-    // 默认配置
-    const defaultOptions = ref<Required<AdaptiveOptions>>({
-      width: 1920,
-      height: 948,
-      baseWidth: 1920,
-      minScale: 0.5,
-      maxScale: 2,
-      debounceTime: 100,
-      ratio: 16 / 9,
-      tolerance: 0.1,
-    });
-
-    // 合并配置
-    const config = computed(() => {
-      return {
-        ...defaultOptions.value,
-        ...props.options,
+    setup(props) {
+      const appStore = useAppStore();
+      const containerRef = ref<HTMLElement | null>(null);
+      // const isReady = ref(false);
+
+      // 默认配置
+      const defaultOptions = ref<Required<AdaptiveOptions>>({
+        width: 1920,
+        height: 948,
+        baseWidth: 1920,
+        minScale: 0.5,
+        maxScale: 2,
+        debounceTime: 100,
+        ratio: 16 / 9,
+        tolerance: 0.1,
+      });
+
+      // 合并配置
+      const config = computed(() => {
+        return {
+          ...defaultOptions.value,
+          ...props.options,
+        };
+      });
+
+      // 设计稿尺寸
+      const designSize = computed(() => {
+        return {
+          width: config.value.width,
+          height: config.value.height,
+        };
+      });
+
+      /**
+       * 设置REM基准值
+       * @param baseSize 基准大小,默认18px
+       */
+      const setRem = (baseSize: number = 18): void => {
+        try {
+          const baseVal = baseSize / config.value.baseWidth;
+          const vW = window.innerWidth;
+          const rem = vW * baseVal;
+
+          // 设置全局缩放比例(如果有需要)
+          if (typeof window['$size'] !== 'number') {
+            Object.defineProperty(window, '$size', {
+              value: rem / 100,
+              writable: true,
+            });
+          } else {
+            window['$size'] = rem / 100;
+          }
+
+          // document.documentElement.style.fontSize = `${rem}px`;
+        } catch (error) {
+          console.error('设置REM失败:', error);
+          // 回退方案:使用固定REM
+          document.documentElement.style.fontSize = `${baseSize}px`;
+        }
       };
-    });
 
-    // 设计稿尺寸
-    const designSize = computed(() => {
-      return {
-        width: config.value.width,
-        height: config.value.height,
+      /**
+       * 计算缩放比例
+       */
+      const calculateScale = (): ScaleInfo => {
+        const { width: designWidth, height: designHeight } = designSize.value;
+        const { innerWidth: currentWidth, innerHeight: currentHeight } = window;
+        const { minScale, maxScale } = config.value;
+
+        // 计算原始比例
+        const rawWidthScale = currentWidth / designWidth;
+        const rawHeightScale = currentHeight / designHeight;
+
+        // 应用比例限制
+        const widthScale = Math.max(minScale, Math.min(maxScale, rawWidthScale));
+        const heightScale = Math.max(minScale, Math.min(maxScale, rawHeightScale));
+
+        // 选择最小比例保持内容完整显示
+        const scale = Math.min(widthScale, heightScale);
+
+        return { widthScale, heightScale, scale };
       };
-    });
-
-    /**
-     * 设置REM基准值
-     * @param baseSize 基准大小,默认18px
-     */
-    const setRem = (baseSize: number = 18): void => {
-      try {
-        const baseVal = baseSize / config.value.baseWidth;
-        const vW = window.innerWidth;
-        const rem = vW * baseVal;
-
-        // 设置全局缩放比例(如果有需要)
-        if (typeof window['$size'] !== 'number') {
-          Object.defineProperty(window, '$size', {
-            value: rem / 100,
-            writable: true,
-          });
-        } else {
-          window['$size'] = rem / 100;
-        }
 
-        // document.documentElement.style.fontSize = `${rem}px`;
-      } catch (error) {
-        console.error('设置REM失败:', error);
-        // 回退方案:使用固定REM
-        document.documentElement.style.fontSize = `${baseSize}px`;
-      }
-    };
-
-    /**
-     * 计算缩放比例
-     */
-    const calculateScale = (): ScaleInfo => {
-      const { width: designWidth, height: designHeight } = designSize.value;
-      const { innerWidth: currentWidth, innerHeight: currentHeight } = window;
-      const { minScale, maxScale } = config.value;
-
-      // 计算原始比例
-      const rawWidthScale = currentWidth / designWidth;
-      const rawHeightScale = currentHeight / designHeight;
-
-      // 应用比例限制
-      const widthScale = Math.max(minScale, Math.min(maxScale, rawWidthScale));
-      const heightScale = Math.max(minScale, Math.min(maxScale, rawHeightScale));
-
-      // 选择最小比例保持内容完整显示
-      const scale = Math.min(widthScale, heightScale);
-
-      return { widthScale, heightScale, scale };
-    };
-
-    /**
-     * 应用缩放变换
-     */
-    const applyScale = (): void => {
-      if (!containerRef.value) return;
-
-      const container = containerRef.value;
-      const { widthScale, heightScale } = calculateScale();
-
-      // 应用缩放
-      container.style.transform = `scale(${widthScale}, ${heightScale})`;
-      // container.style.transformOrigin = 'top left';
-
-      // 更新store中的比例信息(如果需要)
-      appStore.setWidthScale(widthScale);
-      appStore.setHeightScale(heightScale);
-    };
-
-    /**
-     * 处理窗口大小变化
-     */
-    const handleResize = debounce((): void => {
-      // 更新缩放和REM
-      applyScale();
-      setRem();
-    }, config.value.debounceTime);
-
-    onMounted(async () => {
-      // 生命周期
-      try {
-        if (!containerRef.value) {
-          // if (!document.getElementById('app')) {
-          throw new Error('容器元素未找到');
-        }
+      /**
+       * 应用缩放变换
+       */
+      const applyScale = (): void => {
+        if (!containerRef.value) return;
+
         const container = containerRef.value;
-        const { ratio, tolerance } = config.value;
-        const normalRatio = Math.abs(ratio - container.clientWidth / container.clientHeight) < ratio * tolerance;
-        // const container = document.getElementById('app')!;
-        if (normalRatio) {
-          defaultOptions.value.width = container.clientWidth;
-          defaultOptions.value.height = container.clientHeight;
-        }
+        const { widthScale, heightScale } = calculateScale();
+
+        // 应用缩放
+        container.style.transform = `scale(${widthScale}, ${heightScale})`;
+        // container.style.transformOrigin = 'top left';
 
-        const { width, height } = designSize.value;
-        container.style.width = `${width}px`;
-        container.style.height = `${height}px`;
+        // 更新store中的比例信息(如果需要)
+        appStore.setWidthScale(widthScale);
+        appStore.setHeightScale(heightScale);
+      };
 
+      /**
+       * 处理窗口大小变化
+       */
+      const handleResize = debounce((): void => {
+        // 更新缩放和REM
         applyScale();
         setRem();
-      } catch (error) {
-        console.error('初始化自适应容器失败:', error);
-      }
-
-      window.addEventListener('resize', handleResize);
-    });
-
-    onUnmounted(() => {
-      window.removeEventListener('resize', handleResize);
-    });
-
-    return {
-      containerRef,
-      // isReady,
-    };
-  },
-});
+      }, config.value.debounceTime);
+
+      onMounted(async () => {
+        // 生命周期
+        try {
+          if (!containerRef.value) {
+            // if (!document.getElementById('app')) {
+            throw new Error('容器元素未找到');
+          }
+          const container = containerRef.value;
+          const { ratio, tolerance } = config.value;
+          const normalRatio = Math.abs(ratio - container.clientWidth / container.clientHeight) < ratio * tolerance;
+          // const container = document.getElementById('app')!;
+          if (normalRatio) {
+            defaultOptions.value.width = container.clientWidth;
+            defaultOptions.value.height = container.clientHeight;
+          }
+
+          const { width, height } = designSize.value;
+          container.style.width = `${width}px`;
+          container.style.height = `${height}px`;
+
+          applyScale();
+          setRem();
+        } catch (error) {
+          console.error('初始化自适应容器失败:', error);
+        }
+
+        window.addEventListener('resize', handleResize);
+      });
+
+      onUnmounted(() => {
+        window.removeEventListener('resize', handleResize);
+      });
+
+      return {
+        containerRef,
+        // isReady,
+      };
+    },
+  });
 </script>
 
 <style lang="less" scoped>
-.adaptive-container {
-  // position: relative;
-  // top: 0;
-  // left: 0;
-  overflow: hidden;
-  height: 100%;
-  width: 100%;
-  transform-origin: left top;
-  // z-index: 0;
-  // 防止缩放导致的模糊(开启GPU加速)
-  backface-visibility: hidden;
-  // -webkit-font-smoothing: antialiased;
-}
+  .adaptive-container {
+    // position: relative;
+    // top: 0;
+    // left: 0;
+    overflow: hidden;
+    height: 100%;
+    width: 100%;
+    transform-origin: left top;
+    // z-index: 0;
+    // 防止缩放导致的模糊(开启GPU加速)
+    backface-visibility: hidden;
+    // -webkit-font-smoothing: antialiased;
+  }
 </style>

+ 82 - 82
src/components/Form/src/jeecg/components/formCard/formConfig.vue

@@ -31,91 +31,91 @@
 </template>
 
 <script lang="ts" setup>
-import { ref, reactive, onMounted, nextTick, watch } from 'vue';
-// 替换为你的实际接口请求函数
-import { getEnfMineTreeData } from './mineData.api';
-const props = defineProps({
-  lawDeptOptions: {
-    type: Array,
-    default: <Array<{ label: string; value: string | number }>>[],
-  },
-});
-const emit = defineEmits(['change', 'update:value', 'update:lawDept', 'update:area', 'update:position']);
-const pca = reactive({
-  lawDept: '', // 执法处
-  area: '', // 区域
-  position: '', // 具体位置
-});
+  import { ref, reactive, onMounted, nextTick, watch } from 'vue';
+  // 替换为你的实际接口请求函数
+  import { getEnfMineTreeData } from './mineData.api';
+  const props = defineProps({
+    lawDeptOptions: {
+      type: Array,
+      default: <Array<{ label: string; value: string | number }>>[],
+    },
+  });
+  const emit = defineEmits(['change', 'update:value', 'update:lawDept', 'update:area', 'update:position']);
+  const pca = reactive({
+    lawDept: '', // 执法处
+    area: '', // 区域
+    position: '', // 具体位置
+  });
 
-// 下拉选项列表
-// const lawDeptOptions = ref<Array<{ label: string; value: string | number }>>([]);
-const areaOptions = ref<Array<{ label: string; value: string | number }>>([]);
-const positionOptions = ref<Array<{ label: string; value: string | number }>>([]);
-const rawLawDeptData = ref<any[]>([]); // 保存原始执法处数据以备后续查找
-// // 初始化加载执法处列表
-// const initLawDeptList = async () => {
-//   // 调用获取执法处列表的接口
-//   try {
-//     const res = await getEnfMineTreeData();
-//     rawLawDeptData.value = res; // 保存原始数据以备后续查找
-//     lawDeptOptions.value = res.map((item) => ({
-//       label: item.departName, // 显示执法处名称
-//       value: item.id, // 绑定执法处ID
-//     }));
-//   } catch (error) {
-//     console.error('加载执法处列表失败:', error);
-//   }
-// };
-const handleLawDeptChange = async (depId: string | number) => {
-  pca.area = '';
-  pca.position = '';
-  areaOptions.value = [];
-  positionOptions.value = [];
-  rawLawDeptData.value = props.lawDeptOptions;
-  console.log(rawLawDeptData.value, '222222');
-  const currentDept = rawLawDeptData.value.find((item) => item.id === depId);
-  if (!currentDept) {
-    console.warn('未找到该执法处数据');
-    return;
-  }
-  console.log(currentDept, '1111111');
-  areaOptions.value = currentDept.childDepart.map((child) => ({
-    label: child.departName, // 显示区域名称
-    value: child.id, // 绑定区域ID
-  }));
-};
-// const handleAreaChange = async (areaId: string | number) => {
-//   pca.position = '';
-//   positionOptions.value = [];
-//   // 1. 找到选中的执法处原始数据
-//   const currentDept = rawLawDeptData.value.find((item) => item.id === pca.lawDept);
-//   if (!currentDept) {
-//     console.warn('未找到该执法处数据');
-//     return;
-//   }
-//   // 2. 在执法处的childDepart中找到选中的区域数据
-//   const currentArea = currentDept.childDepart.find((area) => area.id === areaId);
-//   if (!currentArea) {
-//     console.warn('未找到该区域数据');
-//     return;
-//   }
-// };
+  // 下拉选项列表
+  // const lawDeptOptions = ref<Array<{ label: string; value: string | number }>>([]);
+  const areaOptions = ref<Array<{ label: string; value: string | number }>>([]);
+  const positionOptions = ref<Array<{ label: string; value: string | number }>>([]);
+  const rawLawDeptData = ref<any[]>([]); // 保存原始执法处数据以备后续查找
+  // // 初始化加载执法处列表
+  // const initLawDeptList = async () => {
+  //   // 调用获取执法处列表的接口
+  //   try {
+  //     const res = await getEnfMineTreeData();
+  //     rawLawDeptData.value = res; // 保存原始数据以备后续查找
+  //     lawDeptOptions.value = res.map((item) => ({
+  //       label: item.departName, // 显示执法处名称
+  //       value: item.id, // 绑定执法处ID
+  //     }));
+  //   } catch (error) {
+  //     console.error('加载执法处列表失败:', error);
+  //   }
+  // };
+  const handleLawDeptChange = async (depId: string | number) => {
+    pca.area = '';
+    pca.position = '';
+    areaOptions.value = [];
+    positionOptions.value = [];
+    rawLawDeptData.value = props.lawDeptOptions;
+    console.log(rawLawDeptData.value, '222222');
+    const currentDept = rawLawDeptData.value.find((item) => item.id === depId);
+    if (!currentDept) {
+      console.warn('未找到该执法处数据');
+      return;
+    }
+    console.log(currentDept, '1111111');
+    areaOptions.value = currentDept.childDepart.map((child) => ({
+      label: child.departName, // 显示区域名称
+      value: child.id, // 绑定区域ID
+    }));
+  };
+  // const handleAreaChange = async (areaId: string | number) => {
+  //   pca.position = '';
+  //   positionOptions.value = [];
+  //   // 1. 找到选中的执法处原始数据
+  //   const currentDept = rawLawDeptData.value.find((item) => item.id === pca.lawDept);
+  //   if (!currentDept) {
+  //     console.warn('未找到该执法处数据');
+  //     return;
+  //   }
+  //   // 2. 在执法处的childDepart中找到选中的区域数据
+  //   const currentArea = currentDept.childDepart.find((area) => area.id === areaId);
+  //   if (!currentArea) {
+  //     console.warn('未找到该区域数据');
+  //     return;
+  //   }
+  // };
 
-// 页面初始化时加载执法处列表
-onMounted(() => {
-  console.log('接收的执法部门选项:', props.lawDeptOptions);
-});
+  // 页面初始化时加载执法处列表
+  onMounted(() => {
+    console.log('接收的执法部门选项:', props.lawDeptOptions);
+  });
 </script>
 
 <style scoped>
-.custom-cascader {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-}
+  .custom-cascader {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+  }
 
-/* 可选:调整选择框样式,和原JAreaSelect保持一致 */
-.custom-cascader :deep(.ant-select) {
-  border-radius: 4px;
-}
-</style>
+  /* 可选:调整选择框样式,和原JAreaSelect保持一致 */
+  .custom-cascader :deep(.ant-select) {
+    border-radius: 4px;
+  }
+</style>

+ 1 - 1
src/components/Table/src/BasicTable.vue

@@ -549,7 +549,7 @@
       .ant-table-container {
         background-color: unset !important;
 
-        .ant-table-body table{
+        .ant-table-body table {
           background-color: #ffffff;
         }
       }

+ 76 - 76
src/layouts/default/index.vue

@@ -17,93 +17,93 @@
 </template>
 
 <script lang="ts">
-import { defineComponent, computed, unref } from 'vue';
-import { Layout } from 'ant-design-vue';
-import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
+  import { defineComponent, computed, unref } from 'vue';
+  import { Layout } from 'ant-design-vue';
+  import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
 
-import LayoutHeader from './header/index.vue';
-import MultipleTabs from './tabs/index.vue';
-import LayoutContent from './content/index.vue';
-import LayoutSideBar from './sider/index.vue';
-// import SystemSelect from './feature/SystemSelect.vue';
-import SimpleMap from './feature/SimpleMap.vue';
+  import LayoutHeader from './header/index.vue';
+  import MultipleTabs from './tabs/index.vue';
+  import LayoutContent from './content/index.vue';
+  import LayoutSideBar from './sider/index.vue';
+  // import SystemSelect from './feature/SystemSelect.vue';
+  import SimpleMap from './feature/SimpleMap.vue';
 
-// import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
-import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
-import { useDesign } from '/@/hooks/web/useDesign';
-import { useLockPage } from '/@/hooks/web/useLockPage';
+  // import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
+  import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
+  import { useDesign } from '/@/hooks/web/useDesign';
+  import { useLockPage } from '/@/hooks/web/useLockPage';
 
-// import { useAppInject } from '/@/hooks/web/useAppInject';
+  // import { useAppInject } from '/@/hooks/web/useAppInject';
 
-export default defineComponent({
-  name: 'DefaultLayout',
-  components: {
-    LayoutFeatures: createAsyncComponent(() => import('/@/layouts/default/feature/index.vue')),
-    LayoutFooter: createAsyncComponent(() => import('/@/layouts/default/footer/index.vue')),
-    LayoutHeader,
-    LayoutContent,
-    LayoutSideBar,
-    MultipleTabs,
-    Layout,
-    // SystemSelect,
-    SimpleMap,
-  },
-  setup() {
-    const { prefixCls } = useDesign('default-layout');
-    // const { getIsMobile } = useAppInject();
-    // const { getShowFullHeaderRef } = useHeaderSetting();
-    const { getShowSidebar, getIsMixSidebar, getShowMenu } = useMenuSetting();
+  export default defineComponent({
+    name: 'DefaultLayout',
+    components: {
+      LayoutFeatures: createAsyncComponent(() => import('/@/layouts/default/feature/index.vue')),
+      LayoutFooter: createAsyncComponent(() => import('/@/layouts/default/footer/index.vue')),
+      LayoutHeader,
+      LayoutContent,
+      LayoutSideBar,
+      MultipleTabs,
+      Layout,
+      // SystemSelect,
+      SimpleMap,
+    },
+    setup() {
+      const { prefixCls } = useDesign('default-layout');
+      // const { getIsMobile } = useAppInject();
+      // const { getShowFullHeaderRef } = useHeaderSetting();
+      const { getShowSidebar, getIsMixSidebar, getShowMenu } = useMenuSetting();
 
-    // Create a lock screen monitor
-    const lockEvents = useLockPage();
+      // Create a lock screen monitor
+      const lockEvents = useLockPage();
 
-    const layoutClass = computed(() => {
-      let cls: string[] = ['ant-layout'];
-      if (unref(getIsMixSidebar) || unref(getShowMenu)) {
-        cls.push('ant-layout-has-sider');
-      }
-      return cls;
-    });
+      const layoutClass = computed(() => {
+        let cls: string[] = ['ant-layout'];
+        if (unref(getIsMixSidebar) || unref(getShowMenu)) {
+          cls.push('ant-layout-has-sider');
+        }
+        return cls;
+      });
 
-    return {
-      getShowSidebar,
-      prefixCls,
-      getIsMixSidebar,
-      layoutClass,
-      lockEvents,
-    };
-  },
-});
+      return {
+        getShowSidebar,
+        prefixCls,
+        getIsMixSidebar,
+        layoutClass,
+        lockEvents,
+      };
+    },
+  });
 </script>
 <style lang="less">
-@prefix-cls: ~'@{namespace}-default-layout';
+  @prefix-cls: ~'@{namespace}-default-layout';
 
-.@{prefix-cls} {
-  display: flex;
-  width: 100%;
-  min-height: 100%;
-  flex-direction: column;
+  .@{prefix-cls} {
+    display: flex;
+    width: 100%;
+    min-height: 100%;
+    flex-direction: column;
 
-  >.ant-layout {
-    height: 0;
-    margin: 10px;
-    background-color: transparent;
-    position: relative;
-    z-index: @layout-basic-z-index;
-  }
+    > .ant-layout {
+      height: 0;
+      margin: 10px;
+      background-color: transparent;
+      position: relative;
+      z-index: @layout-basic-z-index;
+    }
 
-  &-main {
-    width: 100%;
-    border-top-right-radius: 4px;
-    border-bottom-right-radius: 4px;
-    // background-color: #aaaaaa32;
-    // border: 1px solid @white;
-    box-shadow: inset 0 0 5px 0 @white;
-    background: rgba(255, 255, 255, 0.2);
-    backdrop-filter: blur(14px);
-    // -webkit-backdrop-filter: blur(10px);
-    // 代码逻辑说明:【issues/8709】LayoutContent样式多出1px
-    // margin-left: 1px;
+    &-main {
+      width: 100%;
+      border-top-right-radius: 4px;
+      border-bottom-right-radius: 4px;
+      // background-color: #aaaaaa32;
+      // border: 1px solid @white;
+      box-shadow: inset 0 0 5px 0 @white;
+      background: rgba(255, 255, 255, 0.2);
+      backdrop-filter: blur(14px);
+      // -webkit-backdrop-filter: blur(10px);
+      // 代码逻辑说明:【issues/8709】LayoutContent样式多出1px
+      // margin-left: 1px;
+    }
   }
-}
 </style>

+ 188 - 190
src/layouts/default/menu/index.vue

@@ -1,209 +1,207 @@
 <script lang="tsx">
-import type { PropType, CSSProperties } from 'vue';
-
-import { computed, defineComponent, unref, toRef } from 'vue';
-import { BasicMenu } from '/@/components/Menu';
-import { SimpleMenu } from '/@/components/SimpleMenu';
-// import { AppLogo } from '/@/components/Application';
-
-import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
-
-import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
-import { ScrollContainer } from '/@/components/Container';
-
-import { useGo } from '/@/hooks/web/usePage';
-import { useSplitMenu } from './useLayoutMenu';
-import { openWindow } from '/@/utils';
-import { propTypes } from '/@/utils/propTypes';
-import { isUrl } from '/@/utils/is';
-import { useRootSetting } from '/@/hooks/setting/useRootSetting';
-import { useAppInject } from '/@/hooks/web/useAppInject';
-// import { useDesign } from '/@/hooks/web/useDesign';
-import { useLocaleStore } from '/@/store/modules/locale';
-import { Button } from 'ant-design-vue';
-import { SearchOutlined } from '@ant-design/icons-vue';
-import { useI18n } from '/@/hooks/web/useI18n';
-import { AppSearch } from '/@/components/Application';
-
-
-
-export default defineComponent({
-  name: 'LayoutMenu',
-  props: {
-    theme: propTypes.oneOf(['light', 'dark']),
-
-    splitType: {
-      type: Number as PropType<MenuSplitTyeEnum>,
-      default: MenuSplitTyeEnum.NONE,
+  import type { PropType, CSSProperties } from 'vue';
+
+  import { computed, defineComponent, unref, toRef } from 'vue';
+  import { BasicMenu } from '/@/components/Menu';
+  import { SimpleMenu } from '/@/components/SimpleMenu';
+  // import { AppLogo } from '/@/components/Application';
+
+  import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
+
+  import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
+  import { ScrollContainer } from '/@/components/Container';
+
+  import { useGo } from '/@/hooks/web/usePage';
+  import { useSplitMenu } from './useLayoutMenu';
+  import { openWindow } from '/@/utils';
+  import { propTypes } from '/@/utils/propTypes';
+  import { isUrl } from '/@/utils/is';
+  import { useRootSetting } from '/@/hooks/setting/useRootSetting';
+  import { useAppInject } from '/@/hooks/web/useAppInject';
+  // import { useDesign } from '/@/hooks/web/useDesign';
+  import { useLocaleStore } from '/@/store/modules/locale';
+  import { Button } from 'ant-design-vue';
+  import { SearchOutlined } from '@ant-design/icons-vue';
+  import { useI18n } from '/@/hooks/web/useI18n';
+  import { AppSearch } from '/@/components/Application';
+
+  export default defineComponent({
+    name: 'LayoutMenu',
+    props: {
+      theme: propTypes.oneOf(['light', 'dark']),
+
+      splitType: {
+        type: Number as PropType<MenuSplitTyeEnum>,
+        default: MenuSplitTyeEnum.NONE,
+      },
+
+      isHorizontal: propTypes.bool,
+      // menu Mode
+      menuMode: {
+        type: [String] as PropType<Nullable<MenuModeEnum>>,
+        default: '',
+      },
     },
-
-    isHorizontal: propTypes.bool,
-    // menu Mode
-    menuMode: {
-      type: [String] as PropType<Nullable<MenuModeEnum>>,
-      default: '',
-    },
-  },
-  setup(props) {
-    const go = useGo();
-    const { t } = useI18n();
-
-    const {
-      getMenuMode,
-      getMenuType,
-      getMenuTheme,
-      getCollapsed,
-      getCollapsedShowTitle,
-      getAccordion,
-      getIsHorizontal,
-      getIsSidebarType,
-      getSplit,
-    } = useMenuSetting();
-    const { getShowLogo } = useRootSetting();
-
-    // const { prefixCls } = useDesign('layout-menu');
-
-    const { menusRef } = useSplitMenu(toRef(props, 'splitType'));
-
-    const { getIsMobile } = useAppInject();
-
-    const getComputedMenuMode = computed(() => (unref(getIsMobile) ? MenuModeEnum.INLINE : props.menuMode || unref(getMenuMode)));
-
-    const getComputedMenuTheme = computed(() => props.theme || unref(getMenuTheme));
-
-    const getIsShowLogo = computed(() => unref(getShowLogo) && unref(getIsSidebarType));
-
-    const getUseScroll = computed(() => {
-      return (
-        !unref(getIsHorizontal) &&
-        (unref(getIsSidebarType) || props.splitType === MenuSplitTyeEnum.LEFT || props.splitType === MenuSplitTyeEnum.NONE)
-      );
-    });
-
-    const getWrapperStyle = computed((): CSSProperties => {
-      return {
-        // 代码逻辑说明: 【issues/7548】侧边栏导航模式时会导致下面菜单滚动显示不全
-        height: `calc(100% - ${unref(getIsShowLogo) ? '60px' : '0px'})`,
-      };
-    });
-
-    // const getLogoClass = computed(() => {
-    //   return [
-    //     `${prefixCls}-logo`,
-    //     unref(getComputedMenuTheme),
-    //     {
-    //       [`${prefixCls}--mobile`]: unref(getIsMobile),
-    //     },
-    //   ];
-    // });
-
-    const getCommonProps = computed(() => {
-      const menus = unref(menusRef);
-      return {
-        menus,
-        beforeClickFn: beforeMenuClickFn,
-        items: menus,
-        theme: unref(getComputedMenuTheme),
-        accordion: unref(getAccordion),
-        collapse: unref(getCollapsed),
-        collapsedShowTitle: unref(getCollapsedShowTitle),
-        onMenuClick: handleMenuClick,
-      };
-    });
-    /**
-     * click menu
-     * @param menu
-     */
-    // 代码逻辑说明: VUEN-1144 online 配置成菜单后,打开菜单,显示名称未展示为菜单名称
-    const localeStore = useLocaleStore();
-    function handleMenuClick(path: string, item) {
-      if (item) {
-        localeStore.setPathTitle(path, item.title || '');
+    setup(props) {
+      const go = useGo();
+      const { t } = useI18n();
+
+      const {
+        getMenuMode,
+        getMenuType,
+        getMenuTheme,
+        getCollapsed,
+        getCollapsedShowTitle,
+        getAccordion,
+        getIsHorizontal,
+        getIsSidebarType,
+        getSplit,
+      } = useMenuSetting();
+      const { getShowLogo } = useRootSetting();
+
+      // const { prefixCls } = useDesign('layout-menu');
+
+      const { menusRef } = useSplitMenu(toRef(props, 'splitType'));
+
+      const { getIsMobile } = useAppInject();
+
+      const getComputedMenuMode = computed(() => (unref(getIsMobile) ? MenuModeEnum.INLINE : props.menuMode || unref(getMenuMode)));
+
+      const getComputedMenuTheme = computed(() => props.theme || unref(getMenuTheme));
+
+      const getIsShowLogo = computed(() => unref(getShowLogo) && unref(getIsSidebarType));
+
+      const getUseScroll = computed(() => {
+        return (
+          !unref(getIsHorizontal) &&
+          (unref(getIsSidebarType) || props.splitType === MenuSplitTyeEnum.LEFT || props.splitType === MenuSplitTyeEnum.NONE)
+        );
+      });
+
+      const getWrapperStyle = computed((): CSSProperties => {
+        return {
+          // 代码逻辑说明: 【issues/7548】侧边栏导航模式时会导致下面菜单滚动显示不全
+          height: `calc(100% - ${unref(getIsShowLogo) ? '60px' : '0px'})`,
+        };
+      });
+
+      // const getLogoClass = computed(() => {
+      //   return [
+      //     `${prefixCls}-logo`,
+      //     unref(getComputedMenuTheme),
+      //     {
+      //       [`${prefixCls}--mobile`]: unref(getIsMobile),
+      //     },
+      //   ];
+      // });
+
+      const getCommonProps = computed(() => {
+        const menus = unref(menusRef);
+        return {
+          menus,
+          beforeClickFn: beforeMenuClickFn,
+          items: menus,
+          theme: unref(getComputedMenuTheme),
+          accordion: unref(getAccordion),
+          collapse: unref(getCollapsed),
+          collapsedShowTitle: unref(getCollapsedShowTitle),
+          onMenuClick: handleMenuClick,
+        };
+      });
+      /**
+       * click menu
+       * @param menu
+       */
+      // 代码逻辑说明: VUEN-1144 online 配置成菜单后,打开菜单,显示名称未展示为菜单名称
+      const localeStore = useLocaleStore();
+      function handleMenuClick(path: string, item) {
+        if (item) {
+          localeStore.setPathTitle(path, item.title || '');
+        }
+        go(path);
       }
-      go(path);
-    }
 
-    /**
-     * before click menu
-     * @param menu
-     */
-    async function beforeMenuClickFn(path: string) {
-      if (!isUrl(path)) {
-        return true;
+      /**
+       * before click menu
+       * @param menu
+       */
+      async function beforeMenuClickFn(path: string) {
+        if (!isUrl(path)) {
+          return true;
+        }
+        openWindow(path);
+        return false;
       }
-      openWindow(path);
-      return false;
-    }
 
-    function renderMenu() {
-      const { menus, ...menuProps } = unref(getCommonProps);
-      // console.log(menus);
-      if (!menus || !menus.length) return null;
-      return (
-        <>
-          {!getCollapsed.value ? (
-            <AppSearch class="m-5px">
-              <Button class="w-full">
-                {t('layout.setting.menuSearch')}
-                <SearchOutlined />
-              </Button>
-            </AppSearch>
-          ) : (
-            <AppSearch class="m-5px">
-              <Button shape="circle">
-                <SearchOutlined />
-              </Button>
-            </AppSearch>
-          )}
-          {!props.isHorizontal ? (
-            <SimpleMenu {...menuProps} isSplitMenu={unref(getSplit)} items={menusRef.value} />
-          ) : (
-            <BasicMenu
-              {...(menuProps as any)}
-              isHorizontal={props.isHorizontal}
-              type={unref(getMenuType)}
-              showLogo={unref(getIsShowLogo)}
-              mode={unref(getComputedMenuMode as any)}
-              items={menusRef.value}
-            />
-          )}
-        </>
-      );
-    }
+      function renderMenu() {
+        const { menus, ...menuProps } = unref(getCommonProps);
+        // console.log(menus);
+        if (!menus || !menus.length) return null;
+        return (
+          <>
+            {!getCollapsed.value ? (
+              <AppSearch class="m-5px">
+                <Button class="w-full">
+                  {t('layout.setting.menuSearch')}
+                  <SearchOutlined />
+                </Button>
+              </AppSearch>
+            ) : (
+              <AppSearch class="m-5px">
+                <Button shape="circle">
+                  <SearchOutlined />
+                </Button>
+              </AppSearch>
+            )}
+            {!props.isHorizontal ? (
+              <SimpleMenu {...menuProps} isSplitMenu={unref(getSplit)} items={menusRef.value} />
+            ) : (
+              <BasicMenu
+                {...(menuProps as any)}
+                isHorizontal={props.isHorizontal}
+                type={unref(getMenuType)}
+                showLogo={unref(getIsShowLogo)}
+                mode={unref(getComputedMenuMode as any)}
+                items={menusRef.value}
+              />
+            )}
+          </>
+        );
+      }
 
-    return () => {
-      return <>{unref(getUseScroll) ? <ScrollContainer style={unref(getWrapperStyle)}>{() => renderMenu()}</ScrollContainer> : renderMenu()}</>;
-    };
-  },
-});
+      return () => {
+        return <>{unref(getUseScroll) ? <ScrollContainer style={unref(getWrapperStyle)}>{() => renderMenu()}</ScrollContainer> : renderMenu()}</>;
+      };
+    },
+  });
 </script>
 <style lang="less" scoped>
-// 代码逻辑说明: 【QQYUN-5872】菜单优化,上下滚动条去掉
-.scroll-container :deep(.scrollbar__bar) {
-  display: none;
-}
+  // 代码逻辑说明: 【QQYUN-5872】菜单优化,上下滚动条去掉
+  .scroll-container :deep(.scrollbar__bar) {
+    display: none;
+  }
 </style>
 <style lang="less">
-@prefix-cls: ~'@{namespace}-layout-menu';
-@logo-prefix-cls: ~'@{namespace}-app-logo';
+  @prefix-cls: ~'@{namespace}-layout-menu';
+  @logo-prefix-cls: ~'@{namespace}-app-logo';
 
-.@{prefix-cls} {
-  &-logo {
-    height: @header-height;
-    padding: 10px 4px 10px 10px;
+  .@{prefix-cls} {
+    &-logo {
+      height: @header-height;
+      padding: 10px 4px 10px 10px;
 
-    img {
-      width: @logo-width;
-      height: @logo-width;
+      img {
+        width: @logo-width;
+        height: @logo-width;
+      }
     }
-  }
 
-  &--mobile {
-    .@{logo-prefix-cls} {
-      &__title {
-        opacity: 1;
+    &--mobile {
+      .@{logo-prefix-cls} {
+        &__title {
+          opacity: 1;
+        }
       }
     }
   }
-}
 </style>

+ 179 - 176
src/views/analysis/warningAnalysis/connectAnalysis/components/echart-content.vue

@@ -3,198 +3,201 @@
 </template>
 
 <script setup lang="ts">
-import { ref, onMounted, watch, reactive } from 'vue'
-import { plainOptions, } from '../connectAnalysis.data'
-import * as echarts from 'echarts';
+  import { ref, onMounted, watch, reactive } from 'vue';
+  import { plainOptions } from '../connectAnalysis.data';
+  import * as echarts from 'echarts';
 
-let props = defineProps({
-  echartData: {
-    type: Object,
-    default: () => {
-      return {}
-    }
-  }
-})
-//获取dom元素节点
-let line = ref<any>();
-let myChart = ref()
-let option = reactive({})
+  let props = defineProps({
+    echartData: {
+      type: Object,
+      default: () => {
+        return {};
+      },
+    },
+  });
+  //获取dom元素节点
+  let line = ref<any>();
+  let myChart = ref();
+  let option = reactive({});
 
-function initSeries(param) {
-  if (param.length) {
-    let data = param.map(el => {
-      let seriesD = plainOptions.find(v => v.value == el.label)
-      return {
-        name: seriesD['label'],
-        type: 'line',
-        stack: '',
-        symbol: 'circle',
-        symbolSize: 0,
+  function initSeries(param) {
+    if (param.length) {
+      let data = param.map((el) => {
+        let seriesD = plainOptions.find((v) => v.value == el.label);
+        return {
+          name: seriesD['label'],
+          type: 'line',
+          stack: '',
+          symbol: 'circle',
+          symbolSize: 0,
 
-        itemStyle: {
-          normal: {
-            color: seriesD['color'],
-            lineStyle: {
+          itemStyle: {
+            normal: {
               color: seriesD['color'],
-              width: 1
+              lineStyle: {
+                color: seriesD['color'],
+                width: 1,
+              },
+              areaStyle: {
+                color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
+                  {
+                    offset: 0,
+                    color: seriesD['areaColor'][0],
+                  },
+                  {
+                    offset: 1,
+                    color: seriesD['areaColor'][1],
+                  },
+                ]),
+              },
             },
-            areaStyle: {
-              color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [{
-                offset: 0,
-                color: seriesD['areaColor'][0],
-              }, {
-                offset: 1,
-                color: seriesD['areaColor'][1],
-              }]),
-            }
-          }
-        },
-        data: el.value.map(v => v[el.label])
-      }
-    })
-    return data
+          },
+          data: el.value.map((v) => v[el.label]),
+        };
+      });
+      return data;
+    }
   }
-}
-function getOption() {
-  myChart.value = echarts.init(line.value);
-  myChart.value.setOption(option);
-
-
-}
-function updateEchart(param) {
-  let opt = {
-    grid: {
-      left: '2%',
-      right: '2%',
-      top: '6%',
-      bottom: '2%',
-      containLabel: true
-    },
-    tooltip: {
-      trigger: 'axis',
-      backgroundColor: 'rgba(0, 0, 0, .6)',
-      textStyle: {
-        color: '#fff',
-        fontSize: 12,
+  function getOption() {
+    myChart.value = echarts.init(line.value);
+    myChart.value.setOption(option);
+  }
+  function updateEchart(param) {
+    let opt = {
+      grid: {
+        left: '2%',
+        right: '2%',
+        top: '6%',
+        bottom: '2%',
+        containLabel: true,
       },
-    },
-    xAxis: [
-      {
-        type: 'category',
-        boundaryGap: false,
-        axisLabel: {
-          color: '#74767b',
-          overflow: 'truncate',
-        },
-        axisLine: {
-          show: true,
-          lineStyle: {
-            color: '#3173f0',
-            width: 1,      // 线的宽度
-            type: 'dashed' // 线的类型为虚线
-          }
-        },
-        axisTick: {
-          show: false,
-        },
-        splitLine: {
-          show: true,
-          lineStyle: {
-            type: 'dashed',
-            color: 'rgba(209, 229, 253)'
-          }
-        },
-        data: param.xData || []
-      }
-    ],
-    yAxis: [
-      {
-        type: 'value',
-        name: 'ppm',
-        nameTextStyle: {
-          color: '#74767b',
-          fontSize: 14,
-          lineHeight: 10,
-        },
-        min: 0,
-        // max: 1000,
-        axisLabel: {
-          formatter: '{value}',
-          textStyle: {
-            color: '#74767b'
-          }
-        },
-        axisLine: {
-          show: false,
-          lineStyle: {
-            color: '#27b4c2'
-          }
-        },
-        axisTick: {
-          show: false,
+      tooltip: {
+        trigger: 'axis',
+        backgroundColor: 'rgba(0, 0, 0, .6)',
+        textStyle: {
+          color: '#fff',
+          fontSize: 12,
         },
-        splitLine: {
-          show: true,
-          lineStyle: {
-            type: 'dashed',
-            color: 'rgba(209, 229, 253)'
-          }
-        }
       },
-      {
-        type: 'value',
-        name: '',
-        min: 0,
-        max: 100,
-        axisLabel: {
-          formatter: '{value}',
-          textStyle: {
-            color: '#74767b'
-          }
+      xAxis: [
+        {
+          type: 'category',
+          boundaryGap: false,
+          axisLabel: {
+            color: '#74767b',
+            overflow: 'truncate',
+          },
+          axisLine: {
+            show: true,
+            lineStyle: {
+              color: '#3173f0',
+              width: 1, // 线的宽度
+              type: 'dashed', // 线的类型为虚线
+            },
+          },
+          axisTick: {
+            show: false,
+          },
+          splitLine: {
+            show: true,
+            lineStyle: {
+              type: 'dashed',
+              color: 'rgba(209, 229, 253)',
+            },
+          },
+          data: param.xData || [],
         },
-        axisLine: {
-          show: false,
-          lineStyle: {
-            color: '#186afe'
-          }
+      ],
+      yAxis: [
+        {
+          type: 'value',
+          name: 'ppm',
+          nameTextStyle: {
+            color: '#74767b',
+            fontSize: 14,
+            lineHeight: 10,
+          },
+          min: 0,
+          // max: 1000,
+          axisLabel: {
+            formatter: '{value}',
+            textStyle: {
+              color: '#74767b',
+            },
+          },
+          axisLine: {
+            show: false,
+            lineStyle: {
+              color: '#27b4c2',
+            },
+          },
+          axisTick: {
+            show: false,
+          },
+          splitLine: {
+            show: true,
+            lineStyle: {
+              type: 'dashed',
+              color: 'rgba(209, 229, 253)',
+            },
+          },
         },
-        axisTick: {
-          show: false,
+        {
+          type: 'value',
+          name: '',
+          min: 0,
+          max: 100,
+          axisLabel: {
+            formatter: '{value}',
+            textStyle: {
+              color: '#74767b',
+            },
+          },
+          axisLine: {
+            show: false,
+            lineStyle: {
+              color: '#186afe',
+            },
+          },
+          axisTick: {
+            show: false,
+          },
+          splitLine: {
+            show: true,
+            lineStyle: {
+              type: 'dashed',
+              color: 'rgba(209, 229, 253)',
+            },
+          },
         },
-        splitLine: {
-          show: true,
-          lineStyle: {
-            type: 'dashed',
-            color: 'rgba(209, 229, 253)'
-          }
-        }
-      }
-    ],
-    series: initSeries(param.yData)
-  };
-  option = Object.assign({}, opt)
-  if (myChart.value) {
-    myChart.value.setOption(option, true);
-
+      ],
+      series: initSeries(param.yData),
+    };
+    option = Object.assign({}, opt);
+    if (myChart.value) {
+      myChart.value.setOption(option, true);
+    }
   }
-}
-
-watch(() => props.echartData, (newV, oldV) => {
-  updateEchart(newV)
-}, { deep: true })
 
-onMounted(() => {
-  getOption()
-  window.onresize = function () {
-    myChart.value.resize();
-  };
-})
+  watch(
+    () => props.echartData,
+    (newV, oldV) => {
+      updateEchart(newV);
+    },
+    { deep: true }
+  );
 
+  onMounted(() => {
+    getOption();
+    window.onresize = function () {
+      myChart.value.resize();
+    };
+  });
 </script>
 
 <style lang="less" scoped>
-.echart-line {
-  width: 100%;
-  height: 100%;
-}
+  .echart-line {
+    width: 100%;
+    height: 100%;
+  }
 </style>

+ 19 - 21
src/views/analysis/warningAnalysis/connectAnalysis/components/echart-divder.vue

@@ -6,30 +6,28 @@
   </div>
 </template>
 
-<script setup lang="ts">
-
-</script>
+<script setup lang="ts"></script>
 
 <style lang="less" scoped>
-.divder-line {
-  width: 100%;
-display: flex;
-  .line-l {
-    width: 15px;
-    height: 1px;
-    background-color: #3d7bf0;
-  }
+  .divder-line {
+    width: 100%;
+    display: flex;
+    .line-l {
+      width: 15px;
+      height: 1px;
+      background-color: #3d7bf0;
+    }
 
-  .line-c {
-    width: calc(100% - 30px);
-    height: 1px;
-    border-top: 1px dashed #3d7bf0;
-  }
+    .line-c {
+      width: calc(100% - 30px);
+      height: 1px;
+      border-top: 1px dashed #3d7bf0;
+    }
 
-  .line-r {
-    width: 15px;
-    height: 1px;
-    background-color: #3d7bf0;
+    .line-r {
+      width: 15px;
+      height: 1px;
+      background-color: #3d7bf0;
+    }
   }
-}
 </style>

+ 48 - 50
src/views/analysis/warningAnalysis/connectAnalysis/components/echart-lengend.vue

@@ -8,71 +8,69 @@
 </template>
 
 <script setup lang="ts">
-import { ref } from 'vue'
-import { lengendTitle } from '../connectAnalysis.data'
-
+  import { ref } from 'vue';
+  import { lengendTitle } from '../connectAnalysis.data';
 </script>
 
 <style lang="less" scoped>
-.echart-lengend {
-  width: 100%;
-  height: 100%;
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-
-  .lengend-box {
+  .echart-lengend {
+    width: 100%;
+    height: 100%;
     display: flex;
     align-items: center;
+    justify-content: space-between;
 
-    &:nth-child(1) {
-      .lengend-icon {
-        background-color: #3bd97a;
+    .lengend-box {
+      display: flex;
+      align-items: center;
+
+      &:nth-child(1) {
+        .lengend-icon {
+          background-color: #3bd97a;
+        }
       }
-    }
-    &:nth-child(2) {
-      .lengend-icon {
-        background-color: #f9c74a;
+      &:nth-child(2) {
+        .lengend-icon {
+          background-color: #f9c74a;
+        }
       }
-    }
-    &:nth-child(3) {
-      .lengend-icon {
-        background-color: #ac7bf1;
+      &:nth-child(3) {
+        .lengend-icon {
+          background-color: #ac7bf1;
+        }
       }
-    }
-    &:nth-child(4) {
-      .lengend-icon {
-        background-color: #50b2f9;
+      &:nth-child(4) {
+        .lengend-icon {
+          background-color: #50b2f9;
+        }
       }
-    }
-    &:nth-child(5) {
-      .lengend-icon {
-        background-color: #1fd0da;
+      &:nth-child(5) {
+        .lengend-icon {
+          background-color: #1fd0da;
+        }
       }
-    }
-    &:nth-child(6) {
-      .lengend-icon {
-        background-color: #ff6666;
+      &:nth-child(6) {
+        .lengend-icon {
+          background-color: #ff6666;
+        }
       }
-    }
-    &:nth-child(7) {
-      .lengend-icon {
-        background-color: #3b4bd9;
+      &:nth-child(7) {
+        .lengend-icon {
+          background-color: #3b4bd9;
+        }
       }
-    }
-     &:nth-child(8) {
-      .lengend-icon {
-        background-color: #f18736;
+      &:nth-child(8) {
+        .lengend-icon {
+          background-color: #f18736;
+        }
       }
     }
-  }
-
-  .lengend-icon {
-    width: 10px;
-    height: 10px;
-    border-radius: 50%;
-    margin-right: 6px;
 
+    .lengend-icon {
+      width: 10px;
+      height: 10px;
+      border-radius: 50%;
+      margin-right: 6px;
+    }
   }
-}
 </style>

+ 40 - 0
src/views/analysis/warningAnalysis/connectAnalysis/hooks/form.ts

@@ -0,0 +1,40 @@
+import { ref } from 'vue';
+import { useRoute } from 'vue-router';
+import { getGoafSelectOption } from '/@/views/monitor/sealedMonitor/monitor.api';
+
+export function useInitForm() {
+  // const mineStore = useMineDepartmentStore();
+  const route = useRoute();
+  const loading = ref(false);
+  const innerValue = ref<string>((route.query.mineCode as string) || '');
+  // 给历史数据默认填充的矿码
+
+  if (innerValue.value) {
+    // mineStore.setDepartById(code as string);
+    initGoafOptions(innerValue);
+  }
+
+  // 采空区选择器
+  const goafId = ref('');
+  const goafOptions = ref<any[]>([]);
+
+  function initGoafOptions(mineCode) {
+    loading.value = true;
+    return getGoafSelectOption({ mineCode })
+      .then(({ options, defaultValue }) => {
+        goafOptions.value = options;
+        goafId.value = defaultValue;
+      })
+      .finally(() => {
+        loading.value = false;
+      });
+  }
+
+  return {
+    goafOptions,
+    goafId,
+    innerValue,
+    loading,
+    initGoafOptions,
+  };
+}

+ 20 - 21
src/views/analysis/warningAnalysis/connectAnalysis/index.vue

@@ -23,7 +23,7 @@
           <div class="filter-section param-section">
             <span class="filter-label">密闭名称:</span>
             <Select ref="select" v-model:value="goafId" style="width: 300px" placeholder="请选择老空区">
-              <SelectOption v-for="(item, index) in goafOption" :key="index" :value="item.value">{{ item.label }} </SelectOption>
+              <SelectOption v-for="(item, index) in goafOptions" :key="index" :value="item.value">{{ item.label }} </SelectOption>
             </Select>
           </div>
         </Col>
@@ -42,7 +42,7 @@
         </Col>
         <Col :span="2">
           <div class="filter-section">
-            <Button type="primary" @click="generateChart">
+            <Button type="primary" @click="generateChart" :loading="loading">
               <template #icon>
                 <SvgIcon style="margin-right: 10px" name="shencen" />
               </template>
@@ -82,20 +82,20 @@
   import echartLengend from './components/echart-lengend.vue';
   import echartContent from './components/echart-content.vue';
   import echartDivder from './components/echart-divder.vue';
-  import { getGoafHistory, getGoafList } from './connectAnalysis.api';
+  import { getGoafHistory } from './connectAnalysis.api';
   import { useRouter } from 'vue-router';
   import { useMineDepartmentStore } from '/@/store/modules/mine';
   import { SvgIcon } from '/@/components/Icon';
+  import { useInitForm } from './hooks/form';
+
+  const { goafOptions, goafId, innerValue, loading, initGoafOptions } = useInitForm();
 
   // 组件注册
   const RangePicker: any = DatePicker.RangePicker;
   const { currentRoute } = useRouter();
   // 筛选相关响应式数据
   const dateRange = ref([dayjs().add(-30, 'day'), dayjs()]); // 默认时间范围(近1天)
-  const goafId = ref(''); //采空区id
-  const goafOption = ref<any[]>([]); //采空区列表
   const mineStore = useMineDepartmentStore();
-  const innerValue = ref('');
   const checkList = ref<any[]>(['coVal', 'ch4Val', 'c2h4Val', 'c2h2Val', 'co2Val', 'o2Val', 'sourcePressure', 'temperature']); //当前选中要进行显示的选项
   const echartData = reactive({
     xData: [] as any,
@@ -104,9 +104,8 @@
 
   //煤矿选项切换
   function changeCascader(val) {
-    console.log(val, '111---');
     innerValue.value = val;
-    getGoafListData();
+    initGoafOptions(val);
   }
   //时间选择选项切换
   function changeTime(val) {
@@ -142,18 +141,18 @@
   }
 
   //获取采空区列表
-  async function getGoafListData() {
-    let res = await getGoafList({ mineCode: innerValue.value });
-    console.log(res, '90');
-    goafOption.value =
-      res.map((el) => {
-        return {
-          label: el.devicePos,
-          value: el.id,
-        };
-      }) || [];
-    goafId.value = goafOption.value.length ? (goafId.value ? goafId.value : goafOption.value[0]['value']) : '';
-  }
+  // async function getGoafListData() {
+  //   let res = await getGoafList({ mineCode: innerValue.value });
+  //   console.log(res, '90');
+  //   goafOption.value =
+  //     res.map((el) => {
+  //       return {
+  //         label: el.devicePos,
+  //         value: el.id,
+  //       };
+  //     }) || [];
+  //   goafId.value = goafOption.value.length ? (goafId.value ? goafId.value : goafOption.value[0]['value']) : '';
+  // }
 
   onMounted(async () => {
     const mineCode = currentRoute.value['query']['mineCode']; //传递过来的矿ID
@@ -177,7 +176,7 @@
     border: 1px solid @border-color-base;
     border-radius: 4px;
     // background: @card-bg-color;
-    background-color: @card-bg-color;
+    //background-color: @card-bg-color;
     align-items: center;
     // box-shadow: 0px 0px 8px 1px rgba(202, 211, 225, 1);
   }

+ 7 - 6
src/views/dashboard/basicInfo/closedStatistics/index.vue

@@ -2,10 +2,10 @@
   <div class="p-4">
     <BasicTable @register="registerTable" :scroll="{ x: 'fit-content' }">
       <template #action="{ record }">
-          <button @click="handleGoToPage(record, `/sealed/${record.code}`)" class="action-btn" title="密闭监测数据">
-            <SvgIcon name="view" />
-          </button>
-        </template>
+        <button @click="handleGoToPage(record, `/sealed/${record.code}`)" class="action-btn" title="密闭监测数据">
+          <SvgIcon name="view" />
+        </button>
+      </template>
     </BasicTable>
   </div>
 </template>
@@ -53,7 +53,8 @@
       // }
     });
   }
-</script>>
+</script>
+>
 
 <style lang="less" scoped>
   .action-btn {
@@ -64,4 +65,4 @@
       margin-right: 0;
     }
   }
-</style>
+</style>

+ 429 - 451
src/views/dashboard/basicInfo/dataQuality/components/DataQualityModal.vue

@@ -12,14 +12,7 @@
     destroyOnClose
     :bodyStyle="{ padding: '20px' }"
   >
-    <a-form
-      ref="formRef"
-      :model="formData"
-      :rules="formRules"
-      layout="horizontal"
-      :label-col="{ span: 4 }"
-      :wrapper-col="{ span: 20 }"
-    >
+    <a-form ref="formRef" :model="formData" :rules="formRules" layout="horizontal" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
       <!-- 查看模式 -->
       <div class="que-container" v-if="mode === 'view'">
         <div class="que-status">
@@ -30,11 +23,7 @@
             </span>
           </div>
         </div>
-        <div 
-          class="que-item" 
-          v-for="(item, index) in queList" 
-          :key="index"
-        >
+        <div class="que-item" v-for="(item, index) in queList" :key="index">
           <div class="que-details">
             <div class="que-field">
               <span class="que-value que-goafName">{{ item.goafName || '-' }}</span>
@@ -60,17 +49,11 @@
       <!-- 编辑/新增模式 -->
       <div v-else class="edit-container">
         <!-- 动态渲染topFormSchema字段(编辑/新增模式) -->
-        <div class="mine-base-info" v-if="mode === 'add' ">
-          <a-form-item
-            v-for="schema in topFormSchema"
-            :key="schema.field"
-            :name="schema.field"
-            :label="schema.label"
-            :rules="schema.rules"
-          >
-            <component 
+        <div class="mine-base-info" v-if="mode === 'add'">
+          <a-form-item v-for="schema in topFormSchema" :key="schema.field" :name="schema.field" :label="schema.label" :rules="schema.rules">
+            <component
               :is="getComponent(schema.component)"
-              v-model:value="formData[schema.field]" 
+              v-model:value="formData[schema.field]"
               v-bind="schema.componentProps"
               :placeholder="`请输入${schema.label}`"
               style="width: 100%"
@@ -79,11 +62,7 @@
         </div>
 
         <!-- 问题项编辑区 -->
-        <div 
-          class="que-item" 
-          v-for="(item, index) in queList" 
-          :key="item.orderNum || index"
-        >
+        <div class="que-item" v-for="(item, index) in queList" :key="item.orderNum || index">
           <div class="que-index">问题 {{ index + 1 }}</div>
           <div class="edit-fields">
             <a-form-item
@@ -93,7 +72,7 @@
               :label="schema.label"
               :rules="schema.rules"
             >
-              <component 
+              <component
                 :is="getComponent(schema.component)"
                 v-model:value="item[schema.field]"
                 v-bind="schema.componentProps"
@@ -102,455 +81,454 @@
               />
             </a-form-item>
             <div class="form-actions">
-              <a-button 
-                type="text" 
-                danger 
-                @click="removeItem(index)"
-                :disabled="queList.length <= 1"
-              >
-                删除
-              </a-button>
+              <a-button type="text" danger @click="removeItem(index)" :disabled="queList.length <= 1"> 删除 </a-button>
             </div>
           </div>
         </div>
 
-        <a-button 
-          type="dashed" 
-          class="add-btn"
-          @click="addNewItem"
-        >
-          <plus-outlined /> 新增问题
-        </a-button>
+        <a-button type="dashed" class="add-btn" @click="addNewItem"> <plus-outlined /> 新增问题 </a-button>
       </div>
     </a-form>
   </BasicModal>
 </template>
 
 <script setup lang="ts">
-import { ref, computed, reactive, watch } from 'vue';
-import { BasicModal, useModalInner } from '/@/components/Modal';
-import { formSchema, topFormSchema } from '../dataQuality.data';
-import { Select, Input, DatePicker, message, } from 'ant-design-vue';
-import { PlusOutlined } from '@ant-design/icons-vue';
-import dayjs, { Dayjs } from 'dayjs';
-import MineCascader from '/@/components/Form/src/jeecg/components/MineCascader/MineCascader.vue';
-import type { FormInstance, RuleObject } from 'ant-design-vue/es/form';
-
-// 组件映射表
-const componentMap = {
-  Input,
-  DatePicker,
-  Select,
-  InputTextArea: Input.TextArea,
-  MineCascader
-};
-
-// 定义事件发射
-const emit = defineEmits(['success']);
-
-// 模态框模式:查看/编辑/新增
-const mode = ref<'view' | 'edit' | 'add'>('view');
-// 当前记录数据
-const currentRecord = ref<any>({
-  mineCode: '',
-  mineLinkStatus: '0',
-  queJson: [],
-  isOk: false,
-  updateTime: '',
-  createTime: ''
-});
-// 问题列表
-const queList = ref<any[]>([]);
-
-// 表单实例(用于校验)
-const formRef = ref<FormInstance>();
-// 表单数据聚合(适配Form组件的model)
-const formData = reactive({
-  mineCode: '',
-  queList: queList.value
-});
-
-// 合并表单规则(从schema中提取)
-const formRules = reactive({
-  mineCode: topFormSchema.find(item => item.field === 'mineCode')?.rules || [],
-  queList: {
-    type: 'array',
-    required: true,
-    validator: (rule: RuleObject, value: any[], callback: Function) => {
-      // 校验每个问题项
-      if (value.length === 0) {
-        callback(new Error('至少需要填写一条问题信息'));
-        return;
-      }
-      // 逐个校验问题项的必填字段
-      for (let i = 0; i < value.length; i++) {
-        const item = value[i];
-        // 校验工作面名称
-        if (!item.goafName) {
-          callback(new Error(`第${i+1}条问题:工作面名称不能为空`));
-          return;
-        }
-        // 校验问题描述
-        if (!item.queCon) {
-          callback(new Error(`第${i+1}条问题:问题描述不能为空`));
-          return;
-        }
-        // 校验开始时间
-        if (!item.startTime) {
-          callback(new Error(`第${i+1}条问题:开始时间不能为空`));
-          return;
-        }
-        // 校验结束时间
-        if (!item.endTime) {
-          callback(new Error(`第${i+1}条问题:结束时间不能为空`));
-          return;
-        }
-        // 校验结束时间不能早于开始时间
-        if (dayjs(item.endTime).isBefore(dayjs(item.startTime))) {
-          callback(new Error(`第${i+1}条问题:结束时间不能早于开始时间`));
-          return;
-        }
-        // 校验参数
-        if (!item.param) {
-          callback(new Error(`第${i+1}条问题:参数不能为空`));
-          return;
-        }
-      }
-      callback();
-    }
-  }
-});
-
-// 监听queList变化,同步到formData
-watch(queList, (newVal) => {
-  formData.queList = JSON.parse(JSON.stringify(newVal));
-}, { deep: true, immediate: true });
-
-// 监听currentRecord变化,同步mineCode到formData
-watch(() => currentRecord.value.mineCode, (newVal) => {
-  formData.mineCode = newVal;
-}, { immediate: true });
-
-// 根据组件名获取对应组件
-const getComponent = (componentName: string) => {
-  return componentMap[componentName as keyof typeof componentMap];
-};
-
-// 日期格式化方法
-const formatDate = (date: string | Dayjs | null) => {
-  if (!date) return '';
-  return dayjs(date).format('YYYY-MM-DD HH:mm:ss');
-};
-
-// 根据状态值获取显示文本(在线/离线)
-const getStatusText = (status: string | number) => {
-  return status === '1' || status === 1 ? '在线' : '离线';
-};
-
-// 根据状态值获取样式类
-const getStatusClass = (status: string | number) => {
-  return status === '1' || status === 1 ? 'status-online' : 'status-offline';
-};
-
-// 注册模态框并初始化数据
-const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
-  setModalProps({ confirmLoading: false });
-  
-  // 接收模式参数
-  mode.value = data?.mode || 'view';
-  // 初始化当前记录
-  currentRecord.value = data?.record ? JSON.parse(JSON.stringify(data.record)) : {
+  import { ref, computed, reactive, watch } from 'vue';
+  import { BasicModal, useModalInner } from '/@/components/Modal';
+  import { formSchema, topFormSchema } from '../dataQuality.data';
+  import { Select, Input, DatePicker, message } from 'ant-design-vue';
+  import { PlusOutlined } from '@ant-design/icons-vue';
+  import dayjs, { Dayjs } from 'dayjs';
+  import MineCascader from '/@/components/Form/src/jeecg/components/MineCascader/MineCascader.vue';
+  import type { FormInstance, RuleObject } from 'ant-design-vue/es/form';
+
+  // 组件映射表
+  const componentMap = {
+    Input,
+    DatePicker,
+    Select,
+    InputTextArea: Input.TextArea,
+    MineCascader,
+  };
+
+  // 定义事件发射
+  const emit = defineEmits(['success']);
+
+  // 模态框模式:查看/编辑/新增
+  const mode = ref<'view' | 'edit' | 'add'>('view');
+  // 当前记录数据
+  const currentRecord = ref<any>({
     mineCode: '',
     mineLinkStatus: '0',
     queJson: [],
     isOk: false,
     updateTime: '',
-    createTime: ''
+    createTime: '',
+  });
+  // 问题列表
+  const queList = ref<any[]>([]);
+
+  // 表单实例(用于校验)
+  const formRef = ref<FormInstance>();
+  // 表单数据聚合(适配Form组件的model)
+  const formData = reactive({
+    mineCode: '',
+    queList: queList.value,
+  });
+
+  // 合并表单规则(从schema中提取)
+  const formRules = reactive({
+    mineCode: topFormSchema.find((item) => item.field === 'mineCode')?.rules || [],
+    queList: {
+      type: 'array',
+      required: true,
+      validator: (rule: RuleObject, value: any[], callback: Function) => {
+        // 校验每个问题项
+        if (value.length === 0) {
+          callback(new Error('至少需要填写一条问题信息'));
+          return;
+        }
+        // 逐个校验问题项的必填字段
+        for (let i = 0; i < value.length; i++) {
+          const item = value[i];
+          // 校验工作面名称
+          if (!item.goafName) {
+            callback(new Error(`第${i + 1}条问题:工作面名称不能为空`));
+            return;
+          }
+          // 校验问题描述
+          if (!item.queCon) {
+            callback(new Error(`第${i + 1}条问题:问题描述不能为空`));
+            return;
+          }
+          // 校验开始时间
+          if (!item.startTime) {
+            callback(new Error(`第${i + 1}条问题:开始时间不能为空`));
+            return;
+          }
+          // 校验结束时间
+          if (!item.endTime) {
+            callback(new Error(`第${i + 1}条问题:结束时间不能为空`));
+            return;
+          }
+          // 校验结束时间不能早于开始时间
+          if (dayjs(item.endTime).isBefore(dayjs(item.startTime))) {
+            callback(new Error(`第${i + 1}条问题:结束时间不能早于开始时间`));
+            return;
+          }
+          // 校验参数
+          if (!item.param) {
+            callback(new Error(`第${i + 1}条问题:参数不能为空`));
+            return;
+          }
+        }
+        callback();
+      },
+    },
+  });
+
+  // 监听queList变化,同步到formData
+  watch(
+    queList,
+    (newVal) => {
+      formData.queList = JSON.parse(JSON.stringify(newVal));
+    },
+    { deep: true, immediate: true }
+  );
+
+  // 监听currentRecord变化,同步mineCode到formData
+  watch(
+    () => currentRecord.value.mineCode,
+    (newVal) => {
+      formData.mineCode = newVal;
+    },
+    { immediate: true }
+  );
+
+  // 根据组件名获取对应组件
+  const getComponent = (componentName: string) => {
+    return componentMap[componentName as keyof typeof componentMap];
+  };
+
+  // 日期格式化方法
+  const formatDate = (date: string | Dayjs | null) => {
+    if (!date) return '';
+    return dayjs(date).format('YYYY-MM-DD HH:mm:ss');
+  };
+
+  // 根据状态值获取显示文本(在线/离线)
+  const getStatusText = (status: string | number) => {
+    return status === '1' || status === 1 ? '在线' : '离线';
+  };
+
+  // 根据状态值获取样式类
+  const getStatusClass = (status: string | number) => {
+    return status === '1' || status === 1 ? 'status-online' : 'status-offline';
   };
-  // 同步mineCode到formData
-  formData.mineCode = currentRecord.value.mineCode;
-  
-  // 初始化问题列表
-  if (mode.value === 'add') {
-    // 新增模式:初始化一条空数据
-    queList.value = [{
-      orderNum: '1',
+
+  // 注册模态框并初始化数据
+  const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
+    setModalProps({ confirmLoading: false });
+
+    // 接收模式参数
+    mode.value = data?.mode || 'view';
+    // 初始化当前记录
+    currentRecord.value = data?.record
+      ? JSON.parse(JSON.stringify(data.record))
+      : {
+          mineCode: '',
+          mineLinkStatus: '0',
+          queJson: [],
+          isOk: false,
+          updateTime: '',
+          createTime: '',
+        };
+    // 同步mineCode到formData
+    formData.mineCode = currentRecord.value.mineCode;
+
+    // 初始化问题列表
+    if (mode.value === 'add') {
+      // 新增模式:初始化一条空数据
+      queList.value = [
+        {
+          orderNum: '1',
+          goafName: '',
+          queCon: '',
+          startTime: null,
+          endTime: null,
+          param: '',
+        },
+      ];
+      formData.queList = JSON.parse(JSON.stringify(queList.value));
+      if (formRef.value) {
+        formRef.value.resetFields();
+      }
+    } else {
+      // 编辑/查看模式:解析已有问题数据
+      try {
+        const rawData = currentRecord.value?.queJson
+          ? typeof currentRecord.value.queJson === 'string'
+            ? currentRecord.value.queJson.trim()
+              ? JSON.parse(currentRecord.value.queJson)
+              : [] // 兼容空字符串
+            : currentRecord.value.queJson
+          : [];
+        // 兼容日期格式,避免转换失败
+        queList.value = rawData.map((item: any) => ({
+          ...item,
+          startTime: item.startTime ? dayjs(item.startTime, ['YYYY-MM-DD HH:mm:ss', 'YYYY-MM-DD']) : null,
+          endTime: item.endTime ? dayjs(item.endTime, ['YYYY-MM-DD HH:mm:ss', 'YYYY-MM-DD']) : null,
+        }));
+        // 深拷贝同步到formData,切断引用
+        formData.queList = JSON.parse(JSON.stringify(queList.value));
+      } catch (error) {
+        console.error('解析问题数据失败:', error);
+        message.warning('问题数据格式异常,将显示原始数据');
+        // 保留原始queJson,而非重置为空数据
+        queList.value = currentRecord.value?.queJson ? (typeof currentRecord.value.queJson === 'string' ? [] : currentRecord.value.queJson) : [];
+        formData.queList = JSON.parse(JSON.stringify(queList.value));
+      }
+    }
+    // 重置表单校验状态
+    if (formRef.value) {
+      formRef.value.resetFields();
+    }
+  });
+
+  // 模态框标题计算属性
+  const getTitle = computed(() => {
+    const titleMap = {
+      view: '质量问题详情',
+      edit: '编辑质量问题',
+      add: '新增质量问题',
+    };
+    return titleMap[mode.value];
+  });
+
+  // 新增问题项
+  const addNewItem = () => {
+    const newItem = {
+      orderNum: (queList.value.length + 1).toString(),
       goafName: '',
       queCon: '',
       startTime: null,
       endTime: null,
-      param: ''
-    }];
-    formData.queList = JSON.parse(JSON.stringify(queList.value));
-    if (formRef.value) {
-      formRef.value.resetFields();
-    }
-  } else {
-    // 编辑/查看模式:解析已有问题数据
+      param: '',
+    };
+    queList.value.push(newItem);
+  };
+
+  // 删除问题项
+  const removeItem = (index: number) => {
+    queList.value.splice(index, 1);
+    queList.value.forEach((item, i) => {
+      item.orderNum = (i + 1).toString();
+    });
+  };
+
+  // 提交表单处理
+  async function handleSubmit() {
     try {
-      const rawData = currentRecord.value?.queJson 
-        ? (typeof currentRecord.value.queJson === 'string' 
-          ? (currentRecord.value.queJson.trim() ? JSON.parse(currentRecord.value.queJson) : []) // 兼容空字符串
-          : currentRecord.value.queJson)
-        : [];
-      // 兼容日期格式,避免转换失败
-      queList.value = rawData.map((item: any) => ({
+      // 查看模式直接提交
+      if (mode.value === 'view') {
+        closeModal();
+        return;
+      }
+
+      // 1. 表单校验
+      if (!formRef.value) return;
+      const validateResult = await formRef.value.validate();
+      if (!validateResult) return;
+
+      setModalProps({ confirmLoading: true });
+      // 2. 处理问题列表数据(空日期字段置空,避免空字符串)
+      const submitQueList = queList.value.map((item) => ({
         ...item,
-        startTime: item.startTime ? dayjs(item.startTime, ['YYYY-MM-DD HH:mm:ss', 'YYYY-MM-DD']) : null,
-        endTime: item.endTime ? dayjs(item.endTime, ['YYYY-MM-DD HH:mm:ss', 'YYYY-MM-DD']) : null
+        startTime: item.startTime ? item.startTime.format('YYYY-MM-DD HH:mm:ss') : null,
+        endTime: item.endTime ? item.endTime.format('YYYY-MM-DD HH:mm:ss') : null,
       }));
-      // 深拷贝同步到formData,切断引用
-      formData.queList = JSON.parse(JSON.stringify(queList.value)); 
-    } catch (error) {
-      console.error('解析问题数据失败:', error);
-      message.warning('问题数据格式异常,将显示原始数据');
-      // 保留原始queJson,而非重置为空数据
-      queList.value = currentRecord.value?.queJson 
-        ? (typeof currentRecord.value.queJson === 'string' ? [] : currentRecord.value.queJson) 
-        : [];
-      formData.queList = JSON.parse(JSON.stringify(queList.value));
+      // 3. 构造完整提交数据
+      const now = dayjs().format('YYYY-MM-DD HH:mm:ss');
+      const result = {
+        ...currentRecord.value,
+        mineCode: formData.mineCode,
+        queJson: JSON.stringify(submitQueList),
+        createTime: mode.value === 'add' ? now : currentRecord.value.createTime || now,
+        updateTime: now,
+        isOk: mode.value === 'add' ? false : currentRecord.value.isOk,
+      };
+      console.log('最终提交数据:', result);
+      emit('success', result);
+      closeModal();
+    } catch (error: any) {
+      console.error('提交失败:', error);
+      // 显示校验错误提示
+      message.error(error.message || '表单校验失败,请检查必填项');
+    } finally {
+      setModalProps({ confirmLoading: false });
     }
   }
-  // 重置表单校验状态
-  if (formRef.value) {
-    formRef.value.resetFields();
+</script>
+
+<style scoped>
+  .que-container {
+    display: flex;
+    flex-direction: column;
+    gap: 16px;
   }
-});
-
-// 模态框标题计算属性
-const getTitle = computed(() => {
-  const titleMap = {
-    view: '质量问题详情',
-    edit: '编辑质量问题',
-    add: '新增质量问题'
-  };
-  return titleMap[mode.value];
-});
-
-// 新增问题项
-const addNewItem = () => {
-  const newItem = {
-    orderNum: (queList.value.length + 1).toString(),
-    goafName: '',
-    queCon: '',
-    startTime: null,
-    endTime: null,
-    param: ''
-  };
-  queList.value.push(newItem);
-};
-
-// 删除问题项
-const removeItem = (index: number) => {
-  queList.value.splice(index, 1);
-  queList.value.forEach((item, i) => {
-    item.orderNum = (i + 1).toString();
-  });
-};
 
-// 提交表单处理
-async function handleSubmit() {
-  try {
-    // 查看模式直接提交
-    if (mode.value === 'view') {
-      closeModal();
-      return;
-    }
+  .que-status {
+    display: flex;
+    width: 100%;
+    background-color: #f8f9fc;
+    padding: 8px 16px;
+    align-items: center;
+    border: 1px solid #cad2e0;
+    border-radius: 5px;
+  }
 
-    // 1. 表单校验
-    if (!formRef.value) return;
-    const validateResult = await formRef.value.validate();
-    if (!validateResult) return;
-
-    setModalProps({ confirmLoading: true });
-    // 2. 处理问题列表数据(空日期字段置空,避免空字符串)
-    const submitQueList = queList.value.map((item) => ({
-      ...item,
-      startTime: item.startTime ? item.startTime.format('YYYY-MM-DD HH:mm:ss') : null,
-      endTime: item.endTime ? item.endTime.format('YYYY-MM-DD HH:mm:ss') : null,
-    }));
-    // 3. 构造完整提交数据
-    const now = dayjs().format('YYYY-MM-DD HH:mm:ss');
-    const result = {
-      ...currentRecord.value,
-      mineCode: formData.mineCode,
-      queJson: JSON.stringify(submitQueList),
-      createTime: mode.value === 'add' ? now : (currentRecord.value.createTime || now),
-      updateTime: now,
-      isOk: mode.value === 'add' ? false : currentRecord.value.isOk,
-    };
-    console.log('最终提交数据:', result);
-    emit('success', result);
-    closeModal();
-  } catch (error: any) {
-    console.error('提交失败:', error);
-    // 显示校验错误提示
-    message.error(error.message || '表单校验失败,请检查必填项');
-  } finally {
-    setModalProps({ confirmLoading: false });
+  .mine-info {
+    padding: 12px 16px;
+    border: 1px solid #cad2e0;
+    border-radius: 5px;
+    background-color: #f8f9fc;
   }
-}
-</script>
 
-<style scoped>
-.que-container {
-  display: flex;
-  flex-direction: column;
-  gap: 16px;
-}
-
-.que-status {
-  display: flex;
-  width: 100%;
-  background-color: #f8f9fc;
-  padding: 8px 16px;
-  align-items: center;
-  border: 1px solid #cad2e0;
-  border-radius: 5px;
-}
-
-.mine-info {
-  padding: 12px 16px;
-  border: 1px solid #cad2e0;
-  border-radius: 5px;
-  background-color: #f8f9fc;
-}
-
-.mine-field {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-  margin-bottom: 8px;
-}
-
-.status-dot {
-  position: relative;
-  padding-left: 12px;
-  font-weight: 500;
-}
-
-.status-dot::before {
-  content: '';
-  position: absolute;
-  left: 0;
-  top: 50%;
-  transform: translateY(-50%);
-  width: 6px;
-  height: 6px;
-  border-radius: 50%;
-  background-color: inherit;
-}
-
-.status-online {
-  color: #10952c;
-  font-weight: 500;
-}
-
-.status-offline {
-  color: #f5222d;
-  font-weight: 500;
-}
-
-.status-online.status-dot::before {
-  background-color: #10952c;
-}
-
-.status-offline.status-dot::before {
-  background-color: #f5222d;
-}
-
-.que-item {
-  padding: 8px 16px;
-  border: 1px solid #cad2e0;
-  border-radius: 8px;
-  background-color: #f8f9fc;
-}
-
-.que-index {
-  font-size: 16px;
-  font-weight: 600;
-  color: #1890ff;
-  margin-bottom: 12px;
-  padding-bottom: 8px;
-  border-bottom: 1px dashed #e8e8e8;
-}
-
-.que-details {
-  width: 100%;
-}
-
-.que-field {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-  min-width: 200px;
-  margin-bottom: 10px;
-}
-
-.que-label {
-  font-size: 16px;
-  color: #868789;
-  white-space: nowrap;
-}
-
-.que-value {
-  font-size: 16px;
-  color: #838486;
-  word-break: break-all;
-}
-
-.que-goafName {
-  color: #4c4c4e;
-  font-size: 20px;
-}
-
-.time-field {
-  flex: 1;
-  min-width: 420px;
-}
-
-.time-separator {
-  color: #999;
-  margin: 0 8px;
-}
-
-.edit-container {
-  display: flex;
-  flex-direction: column;
-  gap: 16px;
-}
-
-.mine-base-info {
-  padding: 12px 16px;
-  border: 1px solid #cad2e0;
-  border-radius: 5px;
-  background-color: #f8f9fc;
-}
-
-.edit-fields {
-  width: 100%;
-}
-
-.form-item {
-  display: flex;
-  margin-bottom: 10px;
-  align-items: center;
-}
-
-.form-label {
-  width: 20%;
-  color: #666;
-  font-size: 14px;
-}
-
-.add-btn {
-  margin-top: 8px;
-  width: 100%;
-}
-
-.form-actions {
-  display: flex;
-  justify-content: end;
-  margin-bottom: 8px;
-}
-</style>
+  .mine-field {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    margin-bottom: 8px;
+  }
+
+  .status-dot {
+    position: relative;
+    padding-left: 12px;
+    font-weight: 500;
+  }
+
+  .status-dot::before {
+    content: '';
+    position: absolute;
+    left: 0;
+    top: 50%;
+    transform: translateY(-50%);
+    width: 6px;
+    height: 6px;
+    border-radius: 50%;
+    background-color: inherit;
+  }
+
+  .status-online {
+    color: #10952c;
+    font-weight: 500;
+  }
+
+  .status-offline {
+    color: #f5222d;
+    font-weight: 500;
+  }
+
+  .status-online.status-dot::before {
+    background-color: #10952c;
+  }
+
+  .status-offline.status-dot::before {
+    background-color: #f5222d;
+  }
+
+  .que-item {
+    padding: 8px 16px;
+    border: 1px solid #cad2e0;
+    border-radius: 8px;
+    background-color: #f8f9fc;
+  }
+
+  .que-index {
+    font-size: 16px;
+    font-weight: 600;
+    color: #1890ff;
+    margin-bottom: 12px;
+    padding-bottom: 8px;
+    border-bottom: 1px dashed #e8e8e8;
+  }
+
+  .que-details {
+    width: 100%;
+  }
+
+  .que-field {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    min-width: 200px;
+    margin-bottom: 10px;
+  }
+
+  .que-label {
+    font-size: 16px;
+    color: #868789;
+    white-space: nowrap;
+  }
+
+  .que-value {
+    font-size: 16px;
+    color: #838486;
+    word-break: break-all;
+  }
+
+  .que-goafName {
+    color: #4c4c4e;
+    font-size: 20px;
+  }
+
+  .time-field {
+    flex: 1;
+    min-width: 420px;
+  }
+
+  .time-separator {
+    color: #999;
+    margin: 0 8px;
+  }
+
+  .edit-container {
+    display: flex;
+    flex-direction: column;
+    gap: 16px;
+  }
+
+  .mine-base-info {
+    padding: 12px 16px;
+    border: 1px solid #cad2e0;
+    border-radius: 5px;
+    background-color: #f8f9fc;
+  }
+
+  .edit-fields {
+    width: 100%;
+  }
+
+  .form-item {
+    display: flex;
+    margin-bottom: 10px;
+    align-items: center;
+  }
+
+  .form-label {
+    width: 20%;
+    color: #666;
+    font-size: 14px;
+  }
+
+  .add-btn {
+    margin-top: 8px;
+    width: 100%;
+  }
+
+  .form-actions {
+    display: flex;
+    justify-content: end;
+    margin-bottom: 8px;
+  }
+</style>

+ 6 - 12
src/views/dashboard/basicInfo/dataQuality/index.vue

@@ -104,13 +104,7 @@
       :label-col="{ span: 6 }"
       :wrapper-col="{ span: 18 }"
     >
-      <a-form-item
-        v-for="schema in exportFormSchema"
-        :key="schema.field"
-        :name="schema.field"
-        :label="schema.label"
-        :rules="schema.rules"
-      >
+      <a-form-item v-for="schema in exportFormSchema" :key="schema.field" :name="schema.field" :label="schema.label" :rules="schema.rules">
         <component
           :is="getExportFormComponent(schema.component)"
           v-model:value="exportFormData[schema.field]"
@@ -126,7 +120,7 @@
 <script setup lang="ts">
   import { ref, nextTick, computed, onMounted, reactive } from 'vue';
   import { useRouter } from 'vue-router';
-  import { BasicTable, } from '/@/components/Table';
+  import { BasicTable } from '/@/components/Table';
   import { useModal } from '/@/components/Modal';
   import { Tabs, TabPane, Popconfirm, message, Modal, DatePicker } from 'ant-design-vue';
   import type { FormInstance } from 'ant-design-vue/es/form';
@@ -147,7 +141,7 @@
   // 响应式数据
   const activeKey = ref('unresolved'); // 激活的Tab键
   const pageMode = ref('add');
-  
+
   // 导出Modal相关状态
   const exportModalVisible = ref(false);
   const exportFormRef = ref<FormInstance>();
@@ -171,8 +165,8 @@
 
   // 提取导出表单规则(从exportFormSchema)
   const exportFormRules = reactive({
-    startTime: exportFormSchema.find(item => item.field === 'startTime')?.rules || [],
-    endTime: exportFormSchema.find(item => item.field === 'endTime')?.rules || [],
+    startTime: exportFormSchema.find((item) => item.field === 'startTime')?.rules || [],
+    endTime: exportFormSchema.find((item) => item.field === 'endTime')?.rules || [],
   });
 
   // 导出表单组件映射
@@ -271,7 +265,7 @@
   const [registerUnresolvedTable, { reload: reloadUnresolved }] = tableContextA;
 
   // 已解决表格注册
-  const { tableContext: tableContextB, onExportXls: onExportXlsB  } = useListPage({
+  const { tableContext: tableContextB, onExportXls: onExportXlsB } = useListPage({
     tableProps: {
       api: async (params: any) => {
         return await getDataQuaQueList({ ...params, isOk: true });

+ 6 - 6
src/views/monitor/sealedMonitor/monitor.data.ts

@@ -490,11 +490,11 @@ export const historicalFormSchema: FormSchema[] = [
     component: 'DatePicker',
     componentProps: {
       //日期格式化,页面上显示的值
-      format: 'YYYY-MM-DD hh:mm:ss',
+      format: 'YYYY-MM-DD',
       //返回值格式化(绑定值的格式)
-      valueFormat: 'YYYY-MM-DD hh:mm:ss',
+      valueFormat: 'YYYY-MM-DD 00:00:00',
     },
-    defaultValue: dayjs().add(-30, 'day').format('YYYY-MM-DD hh:mm:ss'),
+    defaultValue: dayjs().add(-30, 'day').format('YYYY-MM-DD'),
     colProps: { span: 6 },
   },
   {
@@ -503,11 +503,11 @@ export const historicalFormSchema: FormSchema[] = [
     component: 'DatePicker',
     componentProps: {
       //日期格式化,页面上显示的值
-      format: 'YYYY-MM-DD hh:mm:ss',
+      format: 'YYYY-MM-DD',
       //返回值格式化(绑定值的格式)
-      valueFormat: 'YYYY-MM-DD hh:mm:ss',
+      valueFormat: 'YYYY-MM-DD 23:59:59',
     },
-    defaultValue: dayjs().format('YYYY-MM-DD hh:mm:ss'),
+    defaultValue: dayjs().format('YYYY-MM-DD'),
     colProps: { span: 6 },
   },
 ];

+ 132 - 131
src/views/sys/login/Login.vue

@@ -1,7 +1,6 @@
 <template>
   <div :class="prefixCls" class="relative w-full h-full px-4">
-    <AppLocalePicker class="absolute text-white top-4 right-4 enter-x xl:text-gray-600" :showText="false"
-      v-if="!sessionTimeout && showLocale" />
+    <AppLocalePicker class="absolute text-white top-4 right-4 enter-x xl:text-gray-600" :showText="false" v-if="!sessionTimeout && showLocale" />
     <AppDarkModeToggle class="absolute top-3 right-7 enter-x" v-if="!sessionTimeout" />
     <span class="-enter-x xl:hidden">
       <AppLogo :alwaysShowTitle="true" />
@@ -22,8 +21,10 @@
           </div>
         </div>
         <div class="flex w-full h-full py-5 xl:h-auto xl:py-0 xl:my-0 xl:w-6/12">
-          <div :class="`${prefixCls}-form`"
-            class="relative w-full px-5 py-8 mx-auto my-auto rounded-md shadow-md xl:ml-16 xl:bg-transparent sm:px-8 xl:p-4 xl:shadow-none sm:w-3/4 lg:w-2/4 xl:w-auto enter-x">
+          <div
+            :class="`${prefixCls}-form`"
+            class="relative w-full px-5 py-8 mx-auto my-auto rounded-md shadow-md xl:ml-16 xl:bg-transparent sm:px-8 xl:p-4 xl:shadow-none sm:w-3/4 lg:w-2/4 xl:w-auto enter-x"
+          >
             <LoginForm />
             <ForgetPasswordForm />
             <RegisterForm />
@@ -36,174 +37,174 @@
   </div>
 </template>
 <script lang="ts" setup>
-import { computed } from 'vue';
-import { AppLogo } from '/@/components/Application';
-import { AppLocalePicker, AppDarkModeToggle } from '/@/components/Application';
-import LoginForm from './LoginForm.vue';
-import ForgetPasswordForm from './ForgetPasswordForm.vue';
-import RegisterForm from './RegisterForm.vue';
-import MobileForm from './MobileForm.vue';
-import QrCodeForm from './QrCodeForm.vue';
-import { useGlobSetting } from '/@/hooks/setting';
-import { useI18n } from '/@/hooks/web/useI18n';
-import { useDesign } from '/@/hooks/web/useDesign';
-import { useLocaleStore } from '/@/store/modules/locale';
-import { useLoginState, LoginStateEnum } from './useLogin';
-defineProps({
-  sessionTimeout: {
-    type: Boolean,
-  },
-});
-
-const globSetting = useGlobSetting();
-const { prefixCls } = useDesign('login');
-const { t } = useI18n();
-const localeStore = useLocaleStore();
-const showLocale = localeStore.getShowPicker;
-const title = computed(() => globSetting?.title ?? '');
-const { handleBackLogin } = useLoginState();
-handleBackLogin();
+  import { computed } from 'vue';
+  import { AppLogo } from '/@/components/Application';
+  import { AppLocalePicker, AppDarkModeToggle } from '/@/components/Application';
+  import LoginForm from './LoginForm.vue';
+  import ForgetPasswordForm from './ForgetPasswordForm.vue';
+  import RegisterForm from './RegisterForm.vue';
+  import MobileForm from './MobileForm.vue';
+  import QrCodeForm from './QrCodeForm.vue';
+  import { useGlobSetting } from '/@/hooks/setting';
+  import { useI18n } from '/@/hooks/web/useI18n';
+  import { useDesign } from '/@/hooks/web/useDesign';
+  import { useLocaleStore } from '/@/store/modules/locale';
+  import { useLoginState, LoginStateEnum } from './useLogin';
+  defineProps({
+    sessionTimeout: {
+      type: Boolean,
+    },
+  });
+
+  const globSetting = useGlobSetting();
+  const { prefixCls } = useDesign('login');
+  const { t } = useI18n();
+  const localeStore = useLocaleStore();
+  const showLocale = localeStore.getShowPicker;
+  const title = computed(() => globSetting?.title ?? '');
+  const { handleBackLogin } = useLoginState();
+  handleBackLogin();
 </script>
 <style lang="less">
-@prefix-cls: ~'@{namespace}-login';
-@logo-prefix-cls: ~'@{namespace}-app-logo';
-@countdown-prefix-cls: ~'@{namespace}-countdown-input';
-@dark-bg: #293146;
+  @prefix-cls: ~'@{namespace}-login';
+  @logo-prefix-cls: ~'@{namespace}-app-logo';
+  @countdown-prefix-cls: ~'@{namespace}-countdown-input';
+  @dark-bg: #293146;
 
-html[data-theme='dark'] {
-  .@{prefix-cls} {
-    background-color: @dark-bg;
+  html[data-theme='dark'] {
+    .@{prefix-cls} {
+      background-color: @dark-bg;
 
-    &::before {
-      background-image: url(/@/assets/svg/login-bg-dark.svg);
-    }
+      &::before {
+        background-image: url(/@/assets/svg/login-bg-dark.svg);
+      }
 
-    .ant-input,
-    .ant-input-password {
-      background-color: #232a3b;
-    }
+      .ant-input,
+      .ant-input-password {
+        background-color: #232a3b;
+      }
 
-    .ant-btn:not(.ant-btn-link):not(.ant-btn-primary) {
-      border: 1px solid #4a5569;
-    }
+      .ant-btn:not(.ant-btn-link):not(.ant-btn-primary) {
+        border: 1px solid #4a5569;
+      }
 
-    &-form {
-      background: transparent !important;
-    }
+      &-form {
+        background: transparent !important;
+      }
 
-    .app-iconify {
-      color: #fff;
+      .app-iconify {
+        color: #fff;
+      }
     }
-  }
-
-  input.fix-auto-fill,
-  .fix-auto-fill input {
-    -webkit-text-fill-color: #c9d1d9 !important;
-    box-shadow: inherit !important;
-  }
-}
-
-.@{prefix-cls} {
-  min-height: 100%;
-  overflow: hidden;
 
-  @media (max-width: @screen-xl) {
-    background-color: #293146;
-
-    .@{prefix-cls}-form {
-      background-color: #fff;
+    input.fix-auto-fill,
+    .fix-auto-fill input {
+      -webkit-text-fill-color: #c9d1d9 !important;
+      box-shadow: inherit !important;
     }
   }
 
-  &::before {
-    position: absolute;
-    top: 0;
-    left: 0;
-    width: 100%;
-    height: 100%;
-    margin-left: -48%;
-    background-image: url(/@/assets/svg/login-bg.svg);
-    background-position: 100%;
-    background-repeat: no-repeat;
-    background-size: auto 100%;
-    content: '';
+  .@{prefix-cls} {
+    min-height: 100%;
+    overflow: hidden;
 
     @media (max-width: @screen-xl) {
-      display: none;
-    }
-  }
-
-  .@{logo-prefix-cls} {
-    position: absolute;
-    top: 12px;
-    height: 30px;
+      background-color: #293146;
 
-    &__title {
-      font-size: 16px;
-      color: #fff;
+      .@{prefix-cls}-form {
+        background-color: #fff;
+      }
     }
 
-    img {
-      width: 32px;
+    &::before {
+      position: absolute;
+      top: 0;
+      left: 0;
+      width: 100%;
+      height: 100%;
+      margin-left: -48%;
+      background-image: url(/@/assets/svg/login-bg.svg);
+      background-position: 100%;
+      background-repeat: no-repeat;
+      background-size: auto 100%;
+      content: '';
+
+      @media (max-width: @screen-xl) {
+        display: none;
+      }
     }
-  }
 
-  .container {
     .@{logo-prefix-cls} {
-      display: flex;
-      width: 60%;
-      height: 80px;
+      position: absolute;
+      top: 12px;
+      height: 30px;
 
       &__title {
-        font-size: 24px;
+        font-size: 16px;
         color: #fff;
       }
 
       img {
-        width: 48px;
+        width: 32px;
       }
     }
-  }
 
-  &-sign-in-way {
-    .anticon {
-      font-size: 22px;
-      color: #888;
-      cursor: pointer;
+    .container {
+      .@{logo-prefix-cls} {
+        display: flex;
+        width: 60%;
+        height: 80px;
+
+        &__title {
+          font-size: 24px;
+          color: #fff;
+        }
 
-      &:hover {
-        color: @primary-color;
+        img {
+          width: 48px;
+        }
       }
     }
-  }
 
-  input:not([type='checkbox']) {
-    min-width: 360px;
+    &-sign-in-way {
+      .anticon {
+        font-size: 22px;
+        color: #888;
+        cursor: pointer;
 
-    @media (max-width: @screen-xl) {
-      min-width: 320px;
+        &:hover {
+          color: @primary-color;
+        }
+      }
     }
 
-    @media (max-width: @screen-lg) {
-      min-width: 260px;
-    }
+    input:not([type='checkbox']) {
+      min-width: 360px;
 
-    @media (max-width: @screen-md) {
-      min-width: 240px;
-    }
+      @media (max-width: @screen-xl) {
+        min-width: 320px;
+      }
+
+      @media (max-width: @screen-lg) {
+        min-width: 260px;
+      }
+
+      @media (max-width: @screen-md) {
+        min-width: 240px;
+      }
 
-    @media (max-width: @screen-sm) {
-      min-width: 160px;
+      @media (max-width: @screen-sm) {
+        min-width: 160px;
+      }
     }
-  }
 
-  .@{countdown-prefix-cls} input {
-    min-width: unset;
-  }
+    .@{countdown-prefix-cls} input {
+      min-width: unset;
+    }
 
-  .ant-divider-inner-text {
-    font-size: 12px;
-    color: @text-color-secondary;
+    .ant-divider-inner-text {
+      font-size: 12px;
+      color: @text-color-secondary;
+    }
   }
-}
 </style>

+ 192 - 192
src/views/sys/login/TokenLoginPage.vue

@@ -11,208 +11,208 @@
 </template>
 
 <script lang="ts">
-/**
- * 地址中携带token,跳转至此页面进行登录操作
- */
-import { useRoute, useRouter } from 'vue-router';
-import { useMessage } from '/@/hooks/web/useMessage';
-import { useUserStore } from '/@/store/modules/user';
-import { useI18n } from '/@/hooks/web/useI18n';
-
-export default {
-  name: 'TokenLogin',
-  setup() {
-    const route = useRoute();
-    let router = useRouter();
-    const { createMessage, notification } = useMessage();
-    const { t } = useI18n();
-    const routeQuery: any = route.query;
-    if (!routeQuery) {
-      createMessage.warning('参数无效');
-    }
-
-    const token = routeQuery['loginToken'];
-    if (!token) {
-      createMessage.warning('token无效');
-    }
-    const userStore = useUserStore();
-    userStore.ThirdLogin({ token, thirdType: 'email', goHome: false }).then((res) => {
-      console.log('res====>doThirdLogin', res);
-      if (res && res.userInfo) {
-        requestSuccess(res);
-      } else {
-        requestFailed(res);
+  /**
+   * 地址中携带token,跳转至此页面进行登录操作
+   */
+  import { useRoute, useRouter } from 'vue-router';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { useUserStore } from '/@/store/modules/user';
+  import { useI18n } from '/@/hooks/web/useI18n';
+
+  export default {
+    name: 'TokenLogin',
+    setup() {
+      const route = useRoute();
+      let router = useRouter();
+      const { createMessage, notification } = useMessage();
+      const { t } = useI18n();
+      const routeQuery: any = route.query;
+      if (!routeQuery) {
+        createMessage.warning('参数无效');
       }
-    });
-
-    function requestFailed(err) {
-      notification.error({
-        message: '登录失败',
-        description: ((err.response || {}).data || {}).message || err.message || '请求出现错误,请稍后再试',
-        duration: 4,
-      });
-    }
-
-    function requestSuccess(res) {
-      let info = routeQuery.info;
-      if (info) {
-        let query = JSON.parse(info);
 
-        // 代码逻辑说明: QQYUN-4882【简流】节点消息通知 邮箱 点击办理跳到了应用首页
-        let path = '';
-        if (query.isLowApp === 1) {
-          path = '/myapps/personalOffice/myTodo';
+      const token = routeQuery['loginToken'];
+      if (!token) {
+        createMessage.warning('token无效');
+      }
+      const userStore = useUserStore();
+      userStore.ThirdLogin({ token, thirdType: 'email', goHome: false }).then((res) => {
+        console.log('res====>doThirdLogin', res);
+        if (res && res.userInfo) {
+          requestSuccess(res);
         } else {
-          let taskId = query.taskId;
-          path = '/task/handle/' + taskId;
+          requestFailed(res);
         }
+      });
 
-        router.replace({ path, query });
-        notification.success({
-          message: t('sys.login.loginSuccessTitle'),
-          description: `${t('sys.login.loginSuccessDesc')}: ${res.userInfo.realname}`,
-          duration: 3,
-        });
-      } else {
+      function requestFailed(err) {
         notification.error({
-          message: '参数失效',
-          description: '页面跳转参数丢失,请查看日志',
+          message: '登录失败',
+          description: ((err.response || {}).data || {}).message || err.message || '请求出现错误,请稍后再试',
           duration: 4,
         });
       }
-    }
-  },
-};
+
+      function requestSuccess(res) {
+        let info = routeQuery.info;
+        if (info) {
+          let query = JSON.parse(info);
+
+          // 代码逻辑说明: QQYUN-4882【简流】节点消息通知 邮箱 点击办理跳到了应用首页
+          let path = '';
+          if (query.isLowApp === 1) {
+            path = '/myapps/personalOffice/myTodo';
+          } else {
+            let taskId = query.taskId;
+            path = '/task/handle/' + taskId;
+          }
+
+          router.replace({ path, query });
+          notification.success({
+            message: t('sys.login.loginSuccessTitle'),
+            description: `${t('sys.login.loginSuccessDesc')}: ${res.userInfo.realname}`,
+            duration: 3,
+          });
+        } else {
+          notification.error({
+            message: '参数失效',
+            description: '页面跳转参数丢失,请查看日志',
+            duration: 4,
+          });
+        }
+      }
+    },
+  };
 </script>
 
 <style scoped>
-html[data-theme='dark'] .app-loading {
-  background-color: #2c344a;
-}
-
-html[data-theme='dark'] .app-loading .app-loading-title {
-  color: rgba(255, 255, 255, 0.85);
-}
-
-.app-loading {
-  display: flex;
-  width: 100%;
-  height: 100%;
-  justify-content: center;
-  align-items: center;
-  flex-direction: column;
-  background-color: #f4f7f9;
-}
-
-.app-loading .app-loading-wrap {
-  position: absolute;
-  top: 50%;
-  left: 50%;
-  display: flex;
-  -webkit-transform: translate3d(-50%, -50%, 0);
-  transform: translate3d(-50%, -50%, 0);
-  justify-content: center;
-  align-items: center;
-  flex-direction: column;
-}
-
-.app-loading .dots {
-  display: flex;
-  padding: 98px;
-  justify-content: center;
-  align-items: center;
-}
-
-.app-loading .app-loading-title {
-  display: flex;
-  margin-top: 30px;
-  font-size: 30px;
-  color: rgba(0, 0, 0, 0.85);
-  justify-content: center;
-  align-items: center;
-}
-
-.app-loading .app-loading-logo {
-  display: block;
-  width: 90px;
-  margin: 0 auto;
-  margin-bottom: 20px;
-}
-
-.dot {
-  position: relative;
-  display: inline-block;
-  width: 48px;
-  height: 48px;
-  margin-top: 30px;
-  font-size: 32px;
-  transform: rotate(45deg);
-  box-sizing: border-box;
-  animation: antRotate 1.2s infinite linear;
-}
-
-.dot i {
-  position: absolute;
-  display: block;
-  width: 20px;
-  height: 20px;
-  background-color: #0065cc;
-  border-radius: 100%;
-  opacity: 0.3;
-  transform: scale(0.75);
-  animation: antSpinMove 1s infinite linear alternate;
-  transform-origin: 50% 50%;
-}
-
-.dot i:nth-child(1) {
-  top: 0;
-  left: 0;
-}
-
-.dot i:nth-child(2) {
-  top: 0;
-  right: 0;
-  -webkit-animation-delay: 0.4s;
-  animation-delay: 0.4s;
-}
-
-.dot i:nth-child(3) {
-  right: 0;
-  bottom: 0;
-  -webkit-animation-delay: 0.8s;
-  animation-delay: 0.8s;
-}
-
-.dot i:nth-child(4) {
-  bottom: 0;
-  left: 0;
-  -webkit-animation-delay: 1.2s;
-  animation-delay: 1.2s;
-}
-
-@keyframes antRotate {
-  to {
-    -webkit-transform: rotate(405deg);
-    transform: rotate(405deg);
-  }
-}
-
-@-webkit-keyframes antRotate {
-  to {
-    -webkit-transform: rotate(405deg);
-    transform: rotate(405deg);
-  }
-}
-
-@keyframes antSpinMove {
-  to {
-    opacity: 1;
-  }
-}
-
-@-webkit-keyframes antSpinMove {
-  to {
-    opacity: 1;
-  }
-}
+  html[data-theme='dark'] .app-loading {
+    background-color: #2c344a;
+  }
+
+  html[data-theme='dark'] .app-loading .app-loading-title {
+    color: rgba(255, 255, 255, 0.85);
+  }
+
+  .app-loading {
+    display: flex;
+    width: 100%;
+    height: 100%;
+    justify-content: center;
+    align-items: center;
+    flex-direction: column;
+    background-color: #f4f7f9;
+  }
+
+  .app-loading .app-loading-wrap {
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    display: flex;
+    -webkit-transform: translate3d(-50%, -50%, 0);
+    transform: translate3d(-50%, -50%, 0);
+    justify-content: center;
+    align-items: center;
+    flex-direction: column;
+  }
+
+  .app-loading .dots {
+    display: flex;
+    padding: 98px;
+    justify-content: center;
+    align-items: center;
+  }
+
+  .app-loading .app-loading-title {
+    display: flex;
+    margin-top: 30px;
+    font-size: 30px;
+    color: rgba(0, 0, 0, 0.85);
+    justify-content: center;
+    align-items: center;
+  }
+
+  .app-loading .app-loading-logo {
+    display: block;
+    width: 90px;
+    margin: 0 auto;
+    margin-bottom: 20px;
+  }
+
+  .dot {
+    position: relative;
+    display: inline-block;
+    width: 48px;
+    height: 48px;
+    margin-top: 30px;
+    font-size: 32px;
+    transform: rotate(45deg);
+    box-sizing: border-box;
+    animation: antRotate 1.2s infinite linear;
+  }
+
+  .dot i {
+    position: absolute;
+    display: block;
+    width: 20px;
+    height: 20px;
+    background-color: #0065cc;
+    border-radius: 100%;
+    opacity: 0.3;
+    transform: scale(0.75);
+    animation: antSpinMove 1s infinite linear alternate;
+    transform-origin: 50% 50%;
+  }
+
+  .dot i:nth-child(1) {
+    top: 0;
+    left: 0;
+  }
+
+  .dot i:nth-child(2) {
+    top: 0;
+    right: 0;
+    -webkit-animation-delay: 0.4s;
+    animation-delay: 0.4s;
+  }
+
+  .dot i:nth-child(3) {
+    right: 0;
+    bottom: 0;
+    -webkit-animation-delay: 0.8s;
+    animation-delay: 0.8s;
+  }
+
+  .dot i:nth-child(4) {
+    bottom: 0;
+    left: 0;
+    -webkit-animation-delay: 1.2s;
+    animation-delay: 1.2s;
+  }
+
+  @keyframes antRotate {
+    to {
+      -webkit-transform: rotate(405deg);
+      transform: rotate(405deg);
+    }
+  }
+
+  @-webkit-keyframes antRotate {
+    to {
+      -webkit-transform: rotate(405deg);
+      transform: rotate(405deg);
+    }
+  }
+
+  @keyframes antSpinMove {
+    to {
+      opacity: 1;
+    }
+  }
+
+  @-webkit-keyframes antSpinMove {
+    to {
+      opacity: 1;
+    }
+  }
 </style>

+ 1 - 1
src/views/system/departUser/index.vue

@@ -48,7 +48,7 @@
 <style lang="less" scoped>
   @import './index.less';
   @ventSpace: zxm;
-  
+
   .@{ventSpace}-tabs-tab {
     padding: 12px !important;
   }

+ 90 - 91
src/views/system/loginmini/MiniCodelogin.vue

@@ -21,8 +21,7 @@
                 </div>
               </div>
               <div class="aui-formButton">
-                <a class="aui-linek-code aui-link-register" @click="goBackHandleClick">{{ t('sys.login.backSignIn')
-                }}</a>
+                <a class="aui-linek-code aui-link-register" @click="goBackHandleClick">{{ t('sys.login.backSignIn') }}</a>
               </div>
             </form>
           </div>
@@ -40,105 +39,105 @@
 </template>
 
 <script lang="ts" setup name="mini-code-login">
-import { ref, onUnmounted } from 'vue';
-import { getLoginQrcode, getQrcodeToken } from '/@/api/sys/user';
-import { useUserStore } from '/@/store/modules/user';
-import { QrCode } from '/@/components/Qrcode/index';
-import ThirdModal from '/@/views/sys/login/ThirdModal.vue';
-// import logoImg from '/@/assets/loginmini/icon/jeecg_logo.png';
-import adTextImg from '/@/assets/loginmini/icon/jeecg_ad_text.png';
-import { useI18n } from '/@/hooks/web/useI18n';
-import { useDesign } from '/@/hooks/web/useDesign';
-import { GithubFilled, WechatFilled, DingtalkCircleFilled, createFromIconfontCN } from '@ant-design/icons-vue';
+  import { ref, onUnmounted } from 'vue';
+  import { getLoginQrcode, getQrcodeToken } from '/@/api/sys/user';
+  import { useUserStore } from '/@/store/modules/user';
+  import { QrCode } from '/@/components/Qrcode/index';
+  import ThirdModal from '/@/views/sys/login/ThirdModal.vue';
+  // import logoImg from '/@/assets/loginmini/icon/jeecg_logo.png';
+  import adTextImg from '/@/assets/loginmini/icon/jeecg_ad_text.png';
+  import { useI18n } from '/@/hooks/web/useI18n';
+  import { useDesign } from '/@/hooks/web/useDesign';
+  import { GithubFilled, WechatFilled, DingtalkCircleFilled, createFromIconfontCN } from '@ant-design/icons-vue';
 
-const IconFont = createFromIconfontCN({
-  scriptUrl: '//at.alicdn.com/t/font_2316098_umqusozousr.js',
-});
-const { prefixCls } = useDesign('minilogin');
-const { t } = useI18n();
-const qrCodeUrl = ref<string>('');
-let timer: IntervalHandle;
-const state = ref('0');
-const thirdModalRef = ref();
-const userStore = useUserStore();
-const emit = defineEmits(['go-back', 'success', 'register']);
-
-//加载二维码信息
-function loadQrCode() {
-  state.value = '0';
-  getLoginQrcode().then((res) => {
-    qrCodeUrl.value = res.qrcodeId;
-    if (res.qrcodeId) {
-      openTimer(res.qrcodeId);
-    }
-  });
-}
-//监控扫码状态
-function watchQrcodeToken(qrcodeId) {
-  getQrcodeToken({ qrcodeId: qrcodeId }).then((res) => {
-    let token = res.token;
-    if (token == '-2') {
-      //二维码过期重新获取
-      loadQrCode();
-      clearInterval(timer);
-    }
-    //扫码成功
-    if (res.success) {
-      state.value = '2';
-      clearInterval(timer);
-      setTimeout(() => {
-        userStore.qrCodeLogin(token);
-      }, 500);
-    }
+  const IconFont = createFromIconfontCN({
+    scriptUrl: '//at.alicdn.com/t/font_2316098_umqusozousr.js',
   });
-}
+  const { prefixCls } = useDesign('minilogin');
+  const { t } = useI18n();
+  const qrCodeUrl = ref<string>('');
+  let timer: IntervalHandle;
+  const state = ref('0');
+  const thirdModalRef = ref();
+  const userStore = useUserStore();
+  const emit = defineEmits(['go-back', 'success', 'register']);
+
+  //加载二维码信息
+  function loadQrCode() {
+    state.value = '0';
+    getLoginQrcode().then((res) => {
+      qrCodeUrl.value = res.qrcodeId;
+      if (res.qrcodeId) {
+        openTimer(res.qrcodeId);
+      }
+    });
+  }
+  //监控扫码状态
+  function watchQrcodeToken(qrcodeId) {
+    getQrcodeToken({ qrcodeId: qrcodeId }).then((res) => {
+      let token = res.token;
+      if (token == '-2') {
+        //二维码过期重新获取
+        loadQrCode();
+        clearInterval(timer);
+      }
+      //扫码成功
+      if (res.success) {
+        state.value = '2';
+        clearInterval(timer);
+        setTimeout(() => {
+          userStore.qrCodeLogin(token);
+        }, 500);
+      }
+    });
+  }
 
-/** 开启定时器 */
-function openTimer(qrcodeId) {
-  watchQrcodeToken(qrcodeId);
-  closeTimer();
-  timer = setInterval(() => {
+  /** 开启定时器 */
+  function openTimer(qrcodeId) {
     watchQrcodeToken(qrcodeId);
-  }, 1500);
-}
+    closeTimer();
+    timer = setInterval(() => {
+      watchQrcodeToken(qrcodeId);
+    }, 1500);
+  }
 
-/** 关闭定时器 */
-function closeTimer() {
-  if (timer) clearInterval(timer);
-}
+  /** 关闭定时器 */
+  function closeTimer() {
+    if (timer) clearInterval(timer);
+  }
 
-/**
- * 第三方登录
- * @param type
- */
-function onThirdLogin(type) {
-  thirdModalRef.value.onThirdLogin(type);
-}
+  /**
+   * 第三方登录
+   * @param type
+   */
+  function onThirdLogin(type) {
+    thirdModalRef.value.onThirdLogin(type);
+  }
 
-/**
- * 初始化表单
- */
-function initFrom() {
-  loadQrCode();
-}
+  /**
+   * 初始化表单
+   */
+  function initFrom() {
+    loadQrCode();
+  }
 
-/**
- * 返回
- */
-function goBackHandleClick() {
-  emit('go-back');
-  closeTimer();
-}
+  /**
+   * 返回
+   */
+  function goBackHandleClick() {
+    emit('go-back');
+    closeTimer();
+  }
 
-onUnmounted(() => {
-  closeTimer();
-});
+  onUnmounted(() => {
+    closeTimer();
+  });
 
-defineExpose({
-  initFrom,
-});
+  defineExpose({
+    initFrom,
+  });
 </script>
 <style lang="less" scoped>
-@import '/@/assets/loginmini/style/home.less';
-@import '/@/assets/loginmini/style/base.less';
+  @import '/@/assets/loginmini/style/home.less';
+  @import '/@/assets/loginmini/style/base.less';
 </style>

+ 183 - 186
src/views/system/loginmini/MiniForgotpad.vue

@@ -42,8 +42,7 @@
                     <a-form-item>
                       <a-input type="text" :placeholder="t('sys.login.smsCode')" v-model:value="formData.smscode" />
                     </a-form-item>
-                    <div v-if="showInterval" class="aui-code-line" @click="getLoginCode">{{
-                      t('component.countdown.normalText') }}</div>
+                    <div v-if="showInterval" class="aui-code-line" @click="getLoginCode">{{ t('component.countdown.normalText') }}</div>
                     <div v-else class="aui-code-line">{{ t('component.countdown.sendText', [unref(timeRuning)]) }}</div>
                   </div>
                 </div>
@@ -54,14 +53,12 @@
                 <div class="aui-account aui-account-line aui-forgot">
                   <a-form-item>
                     <div class="aui-input-line">
-                      <a-input type="password" :placeholder="t('sys.login.passwordPlaceholder')"
-                        v-model:value="pwdFormData.password" />
+                      <a-input type="password" :placeholder="t('sys.login.passwordPlaceholder')" v-model:value="pwdFormData.password" />
                     </div>
                   </a-form-item>
                   <a-form-item>
                     <div class="aui-input-line">
-                      <a-input type="password" :placeholder="t('sys.login.confirmPassword')"
-                        v-model:value="pwdFormData.confirmPassword" />
+                      <a-input type="password" :placeholder="t('sys.login.confirmPassword')" v-model:value="pwdFormData.confirmPassword" />
                     </div>
                   </a-form-item>
                 </div>
@@ -96,201 +93,201 @@
   <CaptchaModal @register="captchaRegisterModal" @ok="getLoginCode" />
 </template>
 <script lang="ts" name="mini-forgotpad" setup>
-import { reactive, ref, toRaw, unref } from 'vue';
-import { useI18n } from '/@/hooks/web/useI18n';
-import { SmsEnum, useFormRules, useFormValid, useLoginState } from '/@/views/sys/login/useLogin';
-import { useMessage } from '/@/hooks/web/useMessage';
-import { getCaptcha, passwordChange, phoneVerify } from '/@/api/sys/user';
-// import logoImg from '/@/assets/loginmini/icon/jeecg_logo.png';
-import adTextImg from '/@/assets/loginmini/icon/jeecg_ad_text.png';
-import successImg from '/@/assets/loginmini/icon/icon-success.png';
-import CaptchaModal from '@/components/jeecg/captcha/CaptchaModal.vue';
-import { useModal } from '@/components/Modal';
-import { ExceptionEnum } from '@/enums/exceptionEnum';
-const [captchaRegisterModal, { openModal: openCaptchaModal }] = useModal();
+  import { reactive, ref, toRaw, unref } from 'vue';
+  import { useI18n } from '/@/hooks/web/useI18n';
+  import { SmsEnum, useFormRules, useFormValid, useLoginState } from '/@/views/sys/login/useLogin';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { getCaptcha, passwordChange, phoneVerify } from '/@/api/sys/user';
+  // import logoImg from '/@/assets/loginmini/icon/jeecg_logo.png';
+  import adTextImg from '/@/assets/loginmini/icon/jeecg_ad_text.png';
+  import successImg from '/@/assets/loginmini/icon/icon-success.png';
+  import CaptchaModal from '@/components/jeecg/captcha/CaptchaModal.vue';
+  import { useModal } from '@/components/Modal';
+  import { ExceptionEnum } from '@/enums/exceptionEnum';
+  const [captchaRegisterModal, { openModal: openCaptchaModal }] = useModal();
 
-//下一步控制
-const activeKey = ref<number>(1);
-const { t } = useI18n();
-const { handleBackLogin } = useLoginState();
-const { notification, createMessage, createErrorModal } = useMessage();
-//是否显示获取验证码
-const showInterval = ref<boolean>(true);
-//60s
-const timeRuning = ref<number>(60);
-//定时器
-const timer = ref<any>(null);
-const formRef = ref();
-const pwdFormRef = ref();
-//账号数据
-const accountInfo = reactive<any>({});
-//手机号表单
-const formData = reactive({
-  mobile: '',
-  smscode: '',
-});
-//密码表单
-const pwdFormData = reactive<any>({
-  password: '',
-  confirmPassword: '',
-});
-const emit = defineEmits(['go-back', 'success', 'register']);
+  //下一步控制
+  const activeKey = ref<number>(1);
+  const { t } = useI18n();
+  const { handleBackLogin } = useLoginState();
+  const { notification, createMessage, createErrorModal } = useMessage();
+  //是否显示获取验证码
+  const showInterval = ref<boolean>(true);
+  //60s
+  const timeRuning = ref<number>(60);
+  //定时器
+  const timer = ref<any>(null);
+  const formRef = ref();
+  const pwdFormRef = ref();
+  //账号数据
+  const accountInfo = reactive<any>({});
+  //手机号表单
+  const formData = reactive({
+    mobile: '',
+    smscode: '',
+  });
+  //密码表单
+  const pwdFormData = reactive<any>({
+    password: '',
+    confirmPassword: '',
+  });
+  const emit = defineEmits(['go-back', 'success', 'register']);
 
-/**
- * 下一步
- */
-async function handleNext() {
-  if (!formData.mobile) {
-    createMessage.warn(t('sys.login.mobilePlaceholder'));
-    return;
-  }
-  if (!formData.smscode) {
-    createMessage.warn(t('sys.login.smsPlaceholder'));
-    return;
-  }
-  const resultInfo = await phoneVerify(
-    toRaw({
-      phone: formData.mobile,
-      smscode: formData.smscode,
-    })
-  );
-  if (resultInfo.success) {
-    Object.assign(accountInfo, {
-      username: resultInfo.result.username,
-      phone: formData.mobile,
-      smscode: formData.smscode,
-    });
-    activeKey.value = 2;
-    setTimeout(() => {
-      pwdFormRef.value.resetFields();
-    }, 300);
-  } else {
-    notification.error({
-      message: '错误提示',
-      description: resultInfo.message || t('sys.api.networkExceptionMsg'),
-      duration: 3,
-    });
+  /**
+   * 下一步
+   */
+  async function handleNext() {
+    if (!formData.mobile) {
+      createMessage.warn(t('sys.login.mobilePlaceholder'));
+      return;
+    }
+    if (!formData.smscode) {
+      createMessage.warn(t('sys.login.smsPlaceholder'));
+      return;
+    }
+    const resultInfo = await phoneVerify(
+      toRaw({
+        phone: formData.mobile,
+        smscode: formData.smscode,
+      })
+    );
+    if (resultInfo.success) {
+      Object.assign(accountInfo, {
+        username: resultInfo.result.username,
+        phone: formData.mobile,
+        smscode: formData.smscode,
+      });
+      activeKey.value = 2;
+      setTimeout(() => {
+        pwdFormRef.value.resetFields();
+      }, 300);
+    } else {
+      notification.error({
+        message: '错误提示',
+        description: resultInfo.message || t('sys.api.networkExceptionMsg'),
+        duration: 3,
+      });
+    }
   }
-}
 
-/**
- * 完成修改密码
- */
-async function finishedPwd() {
-  if (!pwdFormData.password) {
-    createMessage.warn(t('sys.login.passwordPlaceholder'));
-    return;
-  }
-  if (!pwdFormData.confirmPassword) {
-    createMessage.warn(t('sys.login.confirmPassword'));
-    return;
-  }
-  if (pwdFormData.password !== pwdFormData.confirmPassword) {
-    createMessage.warn(t('sys.login.diffPwd'));
-    return;
-  }
-  const resultInfo = await passwordChange(
-    toRaw({
-      username: accountInfo.username,
-      password: pwdFormData.password,
-      smscode: accountInfo.smscode,
-      phone: accountInfo.phone,
-    })
-  );
-  if (resultInfo.success) {
-    accountInfo.password = pwdFormData.password;
-    //修改密码
-    activeKey.value = 3;
-  } else {
-    //错误提示
-    createErrorModal({
-      title: t('sys.api.errorTip'),
-      content: resultInfo.message || t('sys.api.networkExceptionMsg'),
-    });
+  /**
+   * 完成修改密码
+   */
+  async function finishedPwd() {
+    if (!pwdFormData.password) {
+      createMessage.warn(t('sys.login.passwordPlaceholder'));
+      return;
+    }
+    if (!pwdFormData.confirmPassword) {
+      createMessage.warn(t('sys.login.confirmPassword'));
+      return;
+    }
+    if (pwdFormData.password !== pwdFormData.confirmPassword) {
+      createMessage.warn(t('sys.login.diffPwd'));
+      return;
+    }
+    const resultInfo = await passwordChange(
+      toRaw({
+        username: accountInfo.username,
+        password: pwdFormData.password,
+        smscode: accountInfo.smscode,
+        phone: accountInfo.phone,
+      })
+    );
+    if (resultInfo.success) {
+      accountInfo.password = pwdFormData.password;
+      //修改密码
+      activeKey.value = 3;
+    } else {
+      //错误提示
+      createErrorModal({
+        title: t('sys.api.errorTip'),
+        content: resultInfo.message || t('sys.api.networkExceptionMsg'),
+      });
+    }
   }
-}
-/**
- * 下一步
- */
-function nextStepClick() {
-  if (unref(activeKey) == 1) {
-    handleNext();
-  } else if (unref(activeKey) == 2) {
-    finishedPwd();
+  /**
+   * 下一步
+   */
+  function nextStepClick() {
+    if (unref(activeKey) == 1) {
+      handleNext();
+    } else if (unref(activeKey) == 2) {
+      finishedPwd();
+    }
   }
-}
-
-/**
- * 去登录
- */
-function toLogin() {
-  emit('success', { username: accountInfo.username, password: accountInfo.password });
-  initForm();
-}
 
-/**
- * 返回
- */
-function goBack() {
-  emit('go-back');
-  initForm();
-}
+  /**
+   * 去登录
+   */
+  function toLogin() {
+    emit('success', { username: accountInfo.username, password: accountInfo.password });
+    initForm();
+  }
 
-/**
- * 获取手机验证码
- */
-async function getLoginCode() {
-  if (!formData.mobile) {
-    createMessage.warn(t('sys.login.mobilePlaceholder'));
-    return;
+  /**
+   * 返回
+   */
+  function goBack() {
+    emit('go-back');
+    initForm();
   }
-  // 代码逻辑说明: 【QQYUN-9005】同一个IP,1分钟超过5次短信,则提示需要验证码---
-  const result = await getCaptcha({ mobile: formData.mobile, smsmode: SmsEnum.FORGET_PASSWORD }).catch((res) => {
-    if (res.code === ExceptionEnum.PHONE_SMS_FAIL_CODE) {
-      openCaptchaModal(true, {});
+
+  /**
+   * 获取手机验证码
+   */
+  async function getLoginCode() {
+    if (!formData.mobile) {
+      createMessage.warn(t('sys.login.mobilePlaceholder'));
+      return;
     }
-  });
-  if (result) {
-    const TIME_COUNT = 60;
-    if (!unref(timer)) {
-      timeRuning.value = TIME_COUNT;
-      showInterval.value = false;
-      timer.value = setInterval(() => {
-        if (unref(timeRuning) > 0 && unref(timeRuning) <= TIME_COUNT) {
-          timeRuning.value = timeRuning.value - 1;
-        } else {
-          showInterval.value = true;
-          clearInterval(unref(timer));
-          timer.value = null;
-        }
-      }, 1000);
+    // 代码逻辑说明: 【QQYUN-9005】同一个IP,1分钟超过5次短信,则提示需要验证码---
+    const result = await getCaptcha({ mobile: formData.mobile, smsmode: SmsEnum.FORGET_PASSWORD }).catch((res) => {
+      if (res.code === ExceptionEnum.PHONE_SMS_FAIL_CODE) {
+        openCaptchaModal(true, {});
+      }
+    });
+    if (result) {
+      const TIME_COUNT = 60;
+      if (!unref(timer)) {
+        timeRuning.value = TIME_COUNT;
+        showInterval.value = false;
+        timer.value = setInterval(() => {
+          if (unref(timeRuning) > 0 && unref(timeRuning) <= TIME_COUNT) {
+            timeRuning.value = timeRuning.value - 1;
+          } else {
+            showInterval.value = true;
+            clearInterval(unref(timer));
+            timer.value = null;
+          }
+        }, 1000);
+      }
     }
   }
-}
 
-/**
- * 初始化表单
- */
-function initForm() {
-  activeKey.value = 1;
-  Object.assign(formData, { phone: '', smscode: '' });
-  Object.assign(pwdFormData, { password: '', confirmPassword: '' });
-  Object.assign(accountInfo, {});
-  if (unref(timer)) {
-    clearInterval(unref(timer));
-    timer.value = null;
-    showInterval.value = true;
+  /**
+   * 初始化表单
+   */
+  function initForm() {
+    activeKey.value = 1;
+    Object.assign(formData, { phone: '', smscode: '' });
+    Object.assign(pwdFormData, { password: '', confirmPassword: '' });
+    Object.assign(accountInfo, {});
+    if (unref(timer)) {
+      clearInterval(unref(timer));
+      timer.value = null;
+      showInterval.value = true;
+    }
+    setTimeout(() => {
+      formRef.value.resetFields();
+    }, 300);
   }
-  setTimeout(() => {
-    formRef.value.resetFields();
-  }, 300);
-}
 
-defineExpose({
-  initForm,
-});
+  defineExpose({
+    initForm,
+  });
 </script>
 <style lang="less" scoped>
-@import '/@/assets/loginmini/style/home.less';
-@import '/@/assets/loginmini/style/base.less';
+  @import '/@/assets/loginmini/style/home.less';
+  @import '/@/assets/loginmini/style/base.less';
 </style>

+ 527 - 529
src/views/system/loginmini/MiniLogin.vue

@@ -7,47 +7,45 @@
       <div class="aui-content">
         <div class="aui-container">
           <div class="aui-form">
-            <div class="aui-image">
-
-            </div>
+            <div class="aui-image"> </div>
             <div class="aui-formBox">
               <div class="aui-formWell">
                 <div class="aui-flex aui-form-nav investment_title">
-                  <div class="aui-flex-box" :class="activeIndex === 'accountLogin' ? 'activeNav on' : ''"
-                    @click="loginClick('accountLogin')">{{ t('sys.login.signInFormTitle') }}
+                  <div class="aui-flex-box" :class="activeIndex === 'accountLogin' ? 'activeNav on' : ''" @click="loginClick('accountLogin')"
+                    >{{ t('sys.login.signInFormTitle') }}
                   </div>
-
                 </div>
                 <div class="aui-form-box" style="height: 240px">
-                  <a-form ref="loginRef" :model="formData" v-if="activeIndex === 'accountLogin'"
-                    @keyup.enter.native="loginHandleClick">
+                  <a-form ref="loginRef" :model="formData" v-if="activeIndex === 'accountLogin'" @keyup.enter.native="loginHandleClick">
                     <div class="aui-account">
                       <div class="aui-inputClear">
                         <i class="icon icon-code"></i>
                         <a-form-item>
-                          <a-input class="fix-auto-fill" :placeholder="t('sys.login.userName')"
-                            v-model:value="formData.username" />
+                          <a-input class="fix-auto-fill" :placeholder="t('sys.login.userName')" v-model:value="formData.username" />
                         </a-form-item>
                       </div>
                       <div class="aui-inputClear">
                         <i class="icon icon-password"></i>
                         <a-form-item>
-                          <a-input class="fix-auto-fill" type="password" :placeholder="t('sys.login.password')"
-                            v-model:value="formData.password" />
+                          <a-input class="fix-auto-fill" type="password" :placeholder="t('sys.login.password')" v-model:value="formData.password" />
                         </a-form-item>
                       </div>
 
                       <div class="aui-inputClear" v-if="showDepart">
                         <i class="icon icon-depart"></i>
                         <div class="JLoginSelectDept">
-                          <a-select allow-clear style="width: 100%" :bordered="false"
-                            v-model:value="formData.loginOrgCode" :placeholder="t('sys.login.loginOrgCode')">
+                          <a-select
+                            allow-clear
+                            style="width: 100%"
+                            :bordered="false"
+                            v-model:value="formData.loginOrgCode"
+                            :placeholder="t('sys.login.loginOrgCode')"
+                          >
                             <template #suffixIcon>
                               <Icon icon="ant-design:gold-outline" />
                             </template>
                             <template v-for="depart in departList" :key="depart.orgCode">
-                              <a-select-option :value="depart.orgCode">{{ getShortDeptName(depart.label)
-                              }}</a-select-option>
+                              <a-select-option :value="depart.orgCode">{{ getShortDeptName(depart.label) }}</a-select-option>
                             </template>
                           </a-select>
                         </div>
@@ -67,30 +65,31 @@
                   <a-form v-else ref="phoneFormRef" :model="phoneFormData" @keyup.enter.native="loginHandleClick">
                     <div class="aui-account phone">
                       <div class="aui-inputClear phoneClear">
-                        <a-input class="fix-auto-fill" :placeholder="t('sys.login.mobile')"
-                          v-model:value="phoneFormData.mobile" />
+                        <a-input class="fix-auto-fill" :placeholder="t('sys.login.mobile')" v-model:value="phoneFormData.mobile" />
                       </div>
                       <div class="aui-inputClear">
-                        <a-input class="fix-auto-fill" :maxlength="6" :placeholder="t('sys.login.smsCode')"
-                          v-model:value="phoneFormData.smscode" />
+                        <a-input class="fix-auto-fill" :maxlength="6" :placeholder="t('sys.login.smsCode')" v-model:value="phoneFormData.smscode" />
                         <div v-if="showInterval" class="aui-code" @click="getLoginCode">
                           <a>{{ t('component.countdown.normalText') }}</a>
                         </div>
                         <div v-else class="aui-code">
-                          <span class="aui-get-code code-shape">{{ t('component.countdown.sendText',
-                            [unref(timeRuning)]) }}</span>
+                          <span class="aui-get-code code-shape">{{ t('component.countdown.sendText', [unref(timeRuning)]) }}</span>
                         </div>
                       </div>
                       <div class="aui-inputClear" v-if="showDepart">
                         <div class="JLoginSelectDept">
-                          <a-select allow-clear style="width: 100%" :bordered="false"
-                            v-model:value="phoneFormData.loginOrgCode" :placeholder="t('sys.login.loginOrgCode')">
+                          <a-select
+                            allow-clear
+                            style="width: 100%"
+                            :bordered="false"
+                            v-model:value="phoneFormData.loginOrgCode"
+                            :placeholder="t('sys.login.loginOrgCode')"
+                          >
                             <template #suffixIcon>
                               <Icon icon="ant-design:gold-outline" />
                             </template>
                             <template v-for="depart in departList" :key="depart.orgCode">
-                              <a-select-option :value="depart.orgCode">{{ getShortDeptName(depart.label)
-                              }}</a-select-option>
+                              <a-select-option :value="depart.orgCode">{{ getShortDeptName(depart.label) }}</a-select-option>
                             </template>
                           </a-select>
                         </div>
@@ -101,12 +100,11 @@
                 <div class="aui-formButton">
                   <div class="aui-flex">
                     <a-button :loading="loginLoading" class="aui-link-login" type="primary" @click="loginHandleClick">
-                      {{ t('sys.login.loginButton') }}</a-button>
+                      {{ t('sys.login.loginButton') }}</a-button
+                    >
                   </div>
-
                 </div>
               </div>
-
             </div>
           </div>
         </div>
@@ -129,560 +127,560 @@
   </div>
 </template>
 <script lang="ts" setup name="login-mini">
-import { getCaptcha, getCodeInfo } from '/@/api/sys/user';
-import { computed, onMounted, reactive, ref, toRaw, unref, watch } from 'vue';
-import codeImg from '/@/assets/images/checkcode.png';
-import { Rule } from '/@/components/Form';
-import { useUserStore } from '/@/store/modules/user';
-import { useMessage } from '/@/hooks/web/useMessage';
-import { useI18n } from '/@/hooks/web/useI18n';
-import { SmsEnum } from '/@/views/sys/login/useLogin';
-import ThirdModal from '/@/views/sys/login/ThirdModal.vue';
-import MiniForgotpad from './MiniForgotpad.vue';
-import MiniRegister from './MiniRegister.vue';
-import MiniCodelogin from './MiniCodelogin.vue';
-// import logoImg from '/@/assets/loginmini/icon/jeecg_logo.png';
-import adTextImg from '/@/assets/loginmini/icon/jeecg_ad_text.png';
-import { AppLocalePicker, AppDarkModeToggle } from '/@/components/Application';
-import { useLocaleStore } from '/@/store/modules/locale';
-import { createLocalStorage } from '/@/utils/cache';
-import { useDesign } from '/@/hooks/web/useDesign';
-import { useAppInject } from '/@/hooks/web/useAppInject';
-import { GithubFilled, WechatFilled, DingtalkCircleFilled, createFromIconfontCN } from '@ant-design/icons-vue';
-import CaptchaModal from '@/components/jeecg/captcha/CaptchaModal.vue';
-import { useModal } from '@/components/Modal';
-import { ExceptionEnum } from '@/enums/exceptionEnum';
-import { defHttp } from '@/utils/http/axios';
-
-const IconFont = createFromIconfontCN({
-  scriptUrl: '//at.alicdn.com/t/font_2316098_umqusozousr.js',
-});
-const { prefixCls } = useDesign('mini-login');
-const { notification, createMessage } = useMessage();
-const userStore = useUserStore();
-const { t } = useI18n();
-const $ls = createLocalStorage();
-const localeStore = useLocaleStore();
-const showLocale = localeStore.getShowPicker;
-const randCodeData = reactive<any>({
-  randCodeImage: '',
-  requestCodeSuccess: false,
-  checkKey: null,
-});
-// 记住用户名
-const rememberMe = ref<boolean>(false);
-const REMEMBER_USERNAME_KEY = 'LOGIN_REMEMBER_USERNAME';
-//手机号登录还是账号登录
-const activeIndex = ref<string>('accountLogin');
-const type = ref<string>('login');
-//账号登录表单字段
-const formData = reactive<any>({
-  inputCode: '',
-  username: 'admin',
-  password: 'admin123admin',
-  loginOrgCode: '',
-});
-//手机登录表单字段
-const phoneFormData = reactive<any>({
-  mobile: '',
-  smscode: '',
-  loginOrgCode: '',
-});
-const loginRef = ref();
-//第三方登录弹窗
-const thirdModalRef = ref();
-//扫码登录
-const codeRef = ref();
-//是否显示获取验证码
-const showInterval = ref<boolean>(true);
-//60s
-const timeRuning = ref<number>(60);
-//定时器
-const timer = ref<any>(null);
-//忘记密码
-const forgotRef = ref();
-//注册
-const registerRef = ref();
-const loginLoading = ref<boolean>(false);
-const { getIsMobile } = useAppInject();
-const [captchaRegisterModal, { openModal: openCaptchaModal }] = useModal();
-defineProps({
-  sessionTimeout: {
-    type: Boolean,
-  },
-});
-//**********************查询部门逻辑begin**********************************************
-//用户部门
-const departList = ref([]);
-//部门显示
-const showDepart = computed(() => {
-  return departList.value.length > 1;
-});
-//获取部门缩写
-const getShortDeptName = computed(() => {
-  return (deptName) => {
-    if (!deptName) return '';
-    if (deptName.length > 18) {
-      return '...' + deptName.substring(deptName.length - 18, deptName.length);
+  import { getCaptcha, getCodeInfo } from '/@/api/sys/user';
+  import { computed, onMounted, reactive, ref, toRaw, unref, watch } from 'vue';
+  import codeImg from '/@/assets/images/checkcode.png';
+  import { Rule } from '/@/components/Form';
+  import { useUserStore } from '/@/store/modules/user';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { useI18n } from '/@/hooks/web/useI18n';
+  import { SmsEnum } from '/@/views/sys/login/useLogin';
+  import ThirdModal from '/@/views/sys/login/ThirdModal.vue';
+  import MiniForgotpad from './MiniForgotpad.vue';
+  import MiniRegister from './MiniRegister.vue';
+  import MiniCodelogin from './MiniCodelogin.vue';
+  // import logoImg from '/@/assets/loginmini/icon/jeecg_logo.png';
+  import adTextImg from '/@/assets/loginmini/icon/jeecg_ad_text.png';
+  import { AppLocalePicker, AppDarkModeToggle } from '/@/components/Application';
+  import { useLocaleStore } from '/@/store/modules/locale';
+  import { createLocalStorage } from '/@/utils/cache';
+  import { useDesign } from '/@/hooks/web/useDesign';
+  import { useAppInject } from '/@/hooks/web/useAppInject';
+  import { GithubFilled, WechatFilled, DingtalkCircleFilled, createFromIconfontCN } from '@ant-design/icons-vue';
+  import CaptchaModal from '@/components/jeecg/captcha/CaptchaModal.vue';
+  import { useModal } from '@/components/Modal';
+  import { ExceptionEnum } from '@/enums/exceptionEnum';
+  import { defHttp } from '@/utils/http/axios';
+
+  const IconFont = createFromIconfontCN({
+    scriptUrl: '//at.alicdn.com/t/font_2316098_umqusozousr.js',
+  });
+  const { prefixCls } = useDesign('mini-login');
+  const { notification, createMessage } = useMessage();
+  const userStore = useUserStore();
+  const { t } = useI18n();
+  const $ls = createLocalStorage();
+  const localeStore = useLocaleStore();
+  const showLocale = localeStore.getShowPicker;
+  const randCodeData = reactive<any>({
+    randCodeImage: '',
+    requestCodeSuccess: false,
+    checkKey: null,
+  });
+  // 记住用户名
+  const rememberMe = ref<boolean>(false);
+  const REMEMBER_USERNAME_KEY = 'LOGIN_REMEMBER_USERNAME';
+  //手机号登录还是账号登录
+  const activeIndex = ref<string>('accountLogin');
+  const type = ref<string>('login');
+  //账号登录表单字段
+  const formData = reactive<any>({
+    inputCode: '',
+    username: 'admin',
+    password: 'admin123admin',
+    loginOrgCode: '',
+  });
+  //手机登录表单字段
+  const phoneFormData = reactive<any>({
+    mobile: '',
+    smscode: '',
+    loginOrgCode: '',
+  });
+  const loginRef = ref();
+  //第三方登录弹窗
+  const thirdModalRef = ref();
+  //扫码登录
+  const codeRef = ref();
+  //是否显示获取验证码
+  const showInterval = ref<boolean>(true);
+  //60s
+  const timeRuning = ref<number>(60);
+  //定时器
+  const timer = ref<any>(null);
+  //忘记密码
+  const forgotRef = ref();
+  //注册
+  const registerRef = ref();
+  const loginLoading = ref<boolean>(false);
+  const { getIsMobile } = useAppInject();
+  const [captchaRegisterModal, { openModal: openCaptchaModal }] = useModal();
+  defineProps({
+    sessionTimeout: {
+      type: Boolean,
+    },
+  });
+  //**********************查询部门逻辑begin**********************************************
+  //用户部门
+  const departList = ref([]);
+  //部门显示
+  const showDepart = computed(() => {
+    return departList.value.length > 1;
+  });
+  //获取部门缩写
+  const getShortDeptName = computed(() => {
+    return (deptName) => {
+      if (!deptName) return '';
+      if (deptName.length > 18) {
+        return '...' + deptName.substring(deptName.length - 18, deptName.length);
+      }
+      return deptName;
+    };
+  });
+  //监听验证码和输入框的修改
+  watch(
+    () => [formData.inputCode, phoneFormData.smscode],
+    () => {
+      if ((formData.inputCode && formData.inputCode.length == 4) || (phoneFormData.smscode && phoneFormData.smscode.length == 6)) {
+        checkAccount();
+      }
     }
-    return deptName;
-  };
-});
-//监听验证码和输入框的修改
-watch(
-  () => [formData.inputCode, phoneFormData.smscode],
-  () => {
-    if ((formData.inputCode && formData.inputCode.length == 4) || (phoneFormData.smscode && phoneFormData.smscode.length == 6)) {
-      checkAccount();
+  );
+  /**
+   * 监听账号变化,清除部门信息
+   */
+  watch(
+    () => [formData.username, phoneFormData.mobile, activeIndex.value],
+    () => {
+      formData.loginOrgCode = null;
+      phoneFormData.loginOrgCode = null;
+      departList.value = [];
+      if ((formData.inputCode && formData.inputCode.length == 4) || (phoneFormData.smscode && phoneFormData.smscode.length == 6)) {
+        checkAccount();
+      }
     }
+  );
+
+  //初始化数据
+  let deptTimer;
+  function checkAccount() {
+    deptTimer && clearTimeout(deptTimer);
+    deptTimer = setTimeout(async () => {
+      let loginType = activeIndex.value === 'accountLogin' ? 'account' : 'phone';
+      // 验证条件提取
+      const isValidAccount = loginType === 'account' && formData.username && formData.password;
+      const isValidPhone = loginType == 'phone' && phoneFormData.mobile && phoneFormData.smscode;
+      let finalFormData = loginType == 'phone' ? { ...phoneFormData } : { ...formData };
+      if (!isValidAccount && !isValidPhone) {
+        return;
+      }
+      //查询部门信息前,优先进行账户校验
+      if (departList.value && departList.value.length == 0) {
+        let params = { ...finalFormData, loginType: activeIndex.value === 'accountLogin' ? 'account' : 'phone' };
+        if (loginType == 'account') {
+          params['checkKey'] = randCodeData.checkKey;
+        }
+        const res = await defHttp.post(
+          {
+            url: '/sys/loginGetUserDeparts',
+            params: { ...params },
+          },
+          { isTransformResponse: false }
+        );
+        if (res.success && res.result) {
+          let { departs, currentOrgCode } = res.result;
+          // 判断当前部门是否在所属的部门列表中
+          if (departs && departs.length > 0) {
+            // 代码逻辑说明: JHHB-790 用户部门变更,会出现这个情况(因为之前设置的这里只切换部门,过滤了公司和岗位信息)
+            const hasCurrentDepart = departs.some((item) => item.orgCode == currentOrgCode);
+            formData.loginOrgCode = hasCurrentDepart ? currentOrgCode : null;
+            phoneFormData.loginOrgCode = hasCurrentDepart ? currentOrgCode : null;
+            departList.value = departs.map((item) => {
+              return {
+                label: item.departName,
+                value: item.orgCode,
+                orgCode: item.orgCode,
+                departName: item.departName,
+              };
+            });
+          }
+        } else {
+          //createMessage.warn(res.message);
+        }
+      }
+    }, 500);
+  }
+  //**********************查询部门逻辑end*************************************************
+  /**
+   * 获取验证码
+   */
+  function handleChangeCheckCode() {
+    formData.inputCode = '';
+    // 代码逻辑说明: [QQYUN-10775]验证码可以复用 #7674------------
+    randCodeData.checkKey = new Date().getTime() + Math.random().toString(36).slice(-4); // 1629428467008;
+    getCodeInfo(randCodeData.checkKey).then((res) => {
+      randCodeData.randCodeImage = res;
+      randCodeData.requestCodeSuccess = true;
+    });
+  }
+
+  /**
+   * 切换登录方式
+   */
+  function loginClick(type) {
+    activeIndex.value = type;
   }
-);
-/**
- * 监听账号变化,清除部门信息
- */
-watch(
-  () => [formData.username, phoneFormData.mobile, activeIndex.value],
-  () => {
-    formData.loginOrgCode = null;
-    phoneFormData.loginOrgCode = null;
-    departList.value = [];
-    if ((formData.inputCode && formData.inputCode.length == 4) || (phoneFormData.smscode && phoneFormData.smscode.length == 6)) {
-      checkAccount();
+
+  /**
+   * 账号或者手机登录
+   */
+  async function loginHandleClick() {
+    if (unref(activeIndex) === 'accountLogin') {
+      accountLogin();
+    } else {
+      //手机号登录
+      phoneLogin();
     }
   }
-);
-
-//初始化数据
-let deptTimer;
-function checkAccount() {
-  deptTimer && clearTimeout(deptTimer);
-  deptTimer = setTimeout(async () => {
-    let loginType = activeIndex.value === 'accountLogin' ? 'account' : 'phone';
-    // 验证条件提取
-    const isValidAccount = loginType === 'account' && formData.username && formData.password;
-    const isValidPhone = loginType == 'phone' && phoneFormData.mobile && phoneFormData.smscode;
-    let finalFormData = loginType == 'phone' ? { ...phoneFormData } : { ...formData };
-    if (!isValidAccount && !isValidPhone) {
+
+  async function accountLogin() {
+    if (!formData.username) {
+      createMessage.warn(t('sys.login.accountPlaceholder'));
       return;
     }
-    //查询部门信息前,优先进行账户校验
-    if (departList.value && departList.value.length == 0) {
-      let params = { ...finalFormData, loginType: activeIndex.value === 'accountLogin' ? 'account' : 'phone' };
-      if (loginType == 'account') {
-        params['checkKey'] = randCodeData.checkKey;
-      }
-      const res = await defHttp.post(
-        {
-          url: '/sys/loginGetUserDeparts',
-          params: { ...params },
-        },
-        { isTransformResponse: false }
+    if (!formData.password) {
+      createMessage.warn(t('sys.login.passwordPlaceholder'));
+      return;
+    }
+    try {
+      loginLoading.value = true;
+
+      // 密码使用AES加密传输
+      const { userInfo } = await userStore.login(
+        toRaw({
+          password: formData.password,
+          username: formData.username,
+          loginOrgCode: formData.loginOrgCode,
+          captcha: formData.inputCode,
+          checkKey: randCodeData.checkKey,
+          mode: 'none', //不要默认的错误提示
+        })
       );
-      if (res.success && res.result) {
-        let { departs, currentOrgCode } = res.result;
-        // 判断当前部门是否在所属的部门列表中
-        if (departs && departs.length > 0) {
-          // 代码逻辑说明: JHHB-790 用户部门变更,会出现这个情况(因为之前设置的这里只切换部门,过滤了公司和岗位信息)
-          const hasCurrentDepart = departs.some((item) => item.orgCode == currentOrgCode);
-          formData.loginOrgCode = hasCurrentDepart ? currentOrgCode : null;
-          phoneFormData.loginOrgCode = hasCurrentDepart ? currentOrgCode : null;
-          departList.value = departs.map((item) => {
-            return {
-              label: item.departName,
-              value: item.orgCode,
-              orgCode: item.orgCode,
-              departName: item.departName,
-            };
-          });
+      if (userInfo) {
+        notification.success({
+          message: t('sys.login.loginSuccessTitle'),
+          description: `${t('sys.login.loginSuccessDesc')}: ${userInfo.realname}`,
+          duration: 3,
+        });
+        // 登录成功后处理记住用户名
+        if (rememberMe.value && formData.username) {
+          $ls.set(REMEMBER_USERNAME_KEY, formData.username);
+        } else {
+          $ls.remove(REMEMBER_USERNAME_KEY);
         }
-      } else {
-        //createMessage.warn(res.message);
       }
+    } catch (error) {
+      notification.error({
+        message: t('sys.api.errorTip'),
+        description: error.message || t('sys.login.networkExceptionMsg'),
+        duration: 3,
+      });
+      handleChangeCheckCode();
+    } finally {
+      loginLoading.value = false;
     }
-  }, 500);
-}
-//**********************查询部门逻辑end*************************************************
-/**
- * 获取验证码
- */
-function handleChangeCheckCode() {
-  formData.inputCode = '';
-  // 代码逻辑说明: [QQYUN-10775]验证码可以复用 #7674------------
-  randCodeData.checkKey = new Date().getTime() + Math.random().toString(36).slice(-4); // 1629428467008;
-  getCodeInfo(randCodeData.checkKey).then((res) => {
-    randCodeData.randCodeImage = res;
-    randCodeData.requestCodeSuccess = true;
-  });
-}
-
-/**
- * 切换登录方式
- */
-function loginClick(type) {
-  activeIndex.value = type;
-}
-
-/**
- * 账号或者手机登录
- */
-async function loginHandleClick() {
-  if (unref(activeIndex) === 'accountLogin') {
-    accountLogin();
-  } else {
-    //手机号登录
-    phoneLogin();
   }
-}
 
-async function accountLogin() {
-  if (!formData.username) {
-    createMessage.warn(t('sys.login.accountPlaceholder'));
-    return;
-  }
-  if (!formData.password) {
-    createMessage.warn(t('sys.login.passwordPlaceholder'));
-    return;
-  }
-  try {
-    loginLoading.value = true;
-
-    // 密码使用AES加密传输
-    const { userInfo } = await userStore.login(
-      toRaw({
-        password: formData.password,
-        username: formData.username,
-        loginOrgCode: formData.loginOrgCode,
-        captcha: formData.inputCode,
-        checkKey: randCodeData.checkKey,
+  /**
+   * 手机号登录
+   */
+  async function phoneLogin() {
+    if (!phoneFormData.mobile) {
+      createMessage.warn(t('sys.login.mobilePlaceholder'));
+      return;
+    }
+    if (!phoneFormData.smscode) {
+      createMessage.warn(t('sys.login.smsPlaceholder'));
+      return;
+    }
+    try {
+      loginLoading.value = true;
+      const { userInfo }: any = await userStore.phoneLogin({
+        mobile: phoneFormData.mobile,
+        captcha: phoneFormData.smscode,
+        loginOrgCode: phoneFormData.loginOrgCode,
         mode: 'none', //不要默认的错误提示
-      })
-    );
-    if (userInfo) {
-      notification.success({
-        message: t('sys.login.loginSuccessTitle'),
-        description: `${t('sys.login.loginSuccessDesc')}: ${userInfo.realname}`,
-        duration: 3,
       });
-      // 登录成功后处理记住用户名
-      if (rememberMe.value && formData.username) {
-        $ls.set(REMEMBER_USERNAME_KEY, formData.username);
-      } else {
-        $ls.remove(REMEMBER_USERNAME_KEY);
+      if (userInfo) {
+        notification.success({
+          message: t('sys.login.loginSuccessTitle'),
+          description: `${t('sys.login.loginSuccessDesc')}: ${userInfo.realname}`,
+          duration: 3,
+        });
       }
+    } catch (error) {
+      notification.error({
+        message: t('sys.api.errorTip'),
+        description: error.message || t('sys.login.networkExceptionMsg'),
+        duration: 3,
+      });
+    } finally {
+      loginLoading.value = false;
+    }
+  }
+
+  /**
+   * 获取手机验证码
+   */
+  async function getLoginCode() {
+    if (!phoneFormData.mobile) {
+      createMessage.warn(t('sys.login.mobilePlaceholder'));
+      return;
     }
-  } catch (error) {
-    notification.error({
-      message: t('sys.api.errorTip'),
-      description: error.message || t('sys.login.networkExceptionMsg'),
-      duration: 3,
+    // 代码逻辑说明: 【issues/8567】严重:修改密码存在水平越权问题:登录应该用登录模板不应该用忘记密码的模板---
+    const result = await getCaptcha({ mobile: phoneFormData.mobile, smsmode: SmsEnum.LOGIN }).catch((res) => {
+      if (res.code === ExceptionEnum.PHONE_SMS_FAIL_CODE) {
+        openCaptchaModal(true, {});
+      }
     });
-    handleChangeCheckCode();
-  } finally {
-    loginLoading.value = false;
+    if (result) {
+      const TIME_COUNT = 60;
+      if (!unref(timer)) {
+        timeRuning.value = TIME_COUNT;
+        showInterval.value = false;
+        timer.value = setInterval(() => {
+          if (unref(timeRuning) > 0 && unref(timeRuning) <= TIME_COUNT) {
+            timeRuning.value = timeRuning.value - 1;
+          } else {
+            showInterval.value = true;
+            clearInterval(unref(timer));
+            timer.value = null;
+          }
+        }, 1000);
+      }
+    }
   }
-}
-
-/**
- * 手机号登录
- */
-async function phoneLogin() {
-  if (!phoneFormData.mobile) {
-    createMessage.warn(t('sys.login.mobilePlaceholder'));
-    return;
+
+  /**
+   * 第三方登录
+   * @param type
+   */
+  function onThirdLogin(type) {
+    thirdModalRef.value.onThirdLogin(type);
   }
-  if (!phoneFormData.smscode) {
-    createMessage.warn(t('sys.login.smsPlaceholder'));
-    return;
+
+  /**
+   * 忘记密码
+   */
+  function forgetHandelClick() {
+    type.value = 'forgot';
+    setTimeout(() => {
+      forgotRef.value.initForm();
+    }, 300);
   }
-  try {
-    loginLoading.value = true;
-    const { userInfo }: any = await userStore.phoneLogin({
-      mobile: phoneFormData.mobile,
-      captcha: phoneFormData.smscode,
-      loginOrgCode: phoneFormData.loginOrgCode,
-      mode: 'none', //不要默认的错误提示
-    });
-    if (userInfo) {
-      notification.success({
-        message: t('sys.login.loginSuccessTitle'),
-        description: `${t('sys.login.loginSuccessDesc')}: ${userInfo.realname}`,
-        duration: 3,
-      });
-    }
-  } catch (error) {
-    notification.error({
-      message: t('sys.api.errorTip'),
-      description: error.message || t('sys.login.networkExceptionMsg'),
-      duration: 3,
-    });
-  } finally {
-    loginLoading.value = false;
+
+  /**
+   * 返回登录页面
+   */
+  function goBack() {
+    activeIndex.value = 'accountLogin';
+    type.value = 'login';
   }
-}
-
-/**
- * 获取手机验证码
- */
-async function getLoginCode() {
-  if (!phoneFormData.mobile) {
-    createMessage.warn(t('sys.login.mobilePlaceholder'));
-    return;
+
+  /**
+   * 忘记密码/注册账号回调事件
+   * @param value
+   */
+  function handleSuccess(value) {
+    Object.assign(formData, value);
+    Object.assign(phoneFormData, { mobile: '', smscode: '' });
+    type.value = 'login';
+    activeIndex.value = 'accountLogin';
+    handleChangeCheckCode();
   }
-  // 代码逻辑说明: 【issues/8567】严重:修改密码存在水平越权问题:登录应该用登录模板不应该用忘记密码的模板---
-  const result = await getCaptcha({ mobile: phoneFormData.mobile, smsmode: SmsEnum.LOGIN }).catch((res) => {
-    if (res.code === ExceptionEnum.PHONE_SMS_FAIL_CODE) {
-      openCaptchaModal(true, {});
-    }
-  });
-  if (result) {
-    const TIME_COUNT = 60;
-    if (!unref(timer)) {
-      timeRuning.value = TIME_COUNT;
-      showInterval.value = false;
-      timer.value = setInterval(() => {
-        if (unref(timeRuning) > 0 && unref(timeRuning) <= TIME_COUNT) {
-          timeRuning.value = timeRuning.value - 1;
-        } else {
-          showInterval.value = true;
-          clearInterval(unref(timer));
-          timer.value = null;
-        }
-      }, 1000);
-    }
+
+  /**
+   * 注册
+   */
+  function registerHandleClick() {
+    type.value = 'register';
+    setTimeout(() => {
+      registerRef.value.initForm();
+    }, 300);
   }
-}
-
-/**
- * 第三方登录
- * @param type
- */
-function onThirdLogin(type) {
-  thirdModalRef.value.onThirdLogin(type);
-}
-
-/**
- * 忘记密码
- */
-function forgetHandelClick() {
-  type.value = 'forgot';
-  setTimeout(() => {
-    forgotRef.value.initForm();
-  }, 300);
-}
-
-/**
- * 返回登录页面
- */
-function goBack() {
-  activeIndex.value = 'accountLogin';
-  type.value = 'login';
-}
-
-/**
- * 忘记密码/注册账号回调事件
- * @param value
- */
-function handleSuccess(value) {
-  Object.assign(formData, value);
-  Object.assign(phoneFormData, { mobile: '', smscode: '' });
-  type.value = 'login';
-  activeIndex.value = 'accountLogin';
-  handleChangeCheckCode();
-}
-
-/**
- * 注册
- */
-function registerHandleClick() {
-  type.value = 'register';
-  setTimeout(() => {
-    registerRef.value.initForm();
-  }, 300);
-}
-
-/**
- * 注册
- */
-function codeHandleClick() {
-  type.value = 'codeLogin';
-  setTimeout(() => {
-    codeRef.value.initFrom();
-  }, 300);
-}
-
-onMounted(() => {
-  //加载验证码
-  handleChangeCheckCode();
-  // 恢复已记住的用户名
-  const saved = $ls.get(REMEMBER_USERNAME_KEY);
-  if (saved) {
-    formData.username = saved;
-    rememberMe.value = true;
+
+  /**
+   * 注册
+   */
+  function codeHandleClick() {
+    type.value = 'codeLogin';
+    setTimeout(() => {
+      codeRef.value.initFrom();
+    }, 300);
   }
-});
+
+  onMounted(() => {
+    //加载验证码
+    handleChangeCheckCode();
+    // 恢复已记住的用户名
+    const saved = $ls.get(REMEMBER_USERNAME_KEY);
+    if (saved) {
+      formData.username = saved;
+      rememberMe.value = true;
+    }
+  });
 </script>
 
 <style lang="less" scoped>
-@import '/@/assets/loginmini/style/home.less';
-@import '/@/assets/loginmini/style/base.less';
-
-:deep(.ant-input:focus) {
-  box-shadow: none;
-}
-
-.aui-get-code {
-  float: right;
-  position: relative;
-  z-index: 3;
-  background: #ffffff;
-  color: #1573e9;
-  border-radius: 100px;
-  padding: 5px 16px;
-  margin: 7px;
-  border: 1px solid #1573e9;
-  top: 12px;
-}
-
-.aui-get-code:hover {
-  color: #1573e9;
-}
-
-.code-shape {
-  border-color: #dadada !important;
-  color: #aaa !important;
-}
-
-:deep(.jeecg-dark-switch) {
-  position: absolute;
-  margin-right: 10px;
-}
-
-.aui-link-login {
-  height: 42px;
-  padding: 10px 15px;
-  font-size: 14px;
-  border-radius: 8px;
-  margin-top: 15px;
-  margin-bottom: 8px;
-  flex: 1;
-  color: #fff;
-}
-
-.aui-phone-logo {
-  position: absolute;
-  margin-left: 10px;
-  width: 60px;
-  top: 2px;
-  z-index: 4;
-}
-
-.top-3 {
-  top: 0.45rem;
-}
-
-.JLoginSelectDept {
-  margin: 5px auto;
-
-  :deep(.ant-select-selection-placeholder) {
+  @import '/@/assets/loginmini/style/home.less';
+  @import '/@/assets/loginmini/style/base.less';
+
+  :deep(.ant-input:focus) {
+    box-shadow: none;
+  }
+
+  .aui-get-code {
+    float: right;
+    position: relative;
+    z-index: 3;
+    background: #ffffff;
+    color: #1573e9;
+    border-radius: 100px;
+    padding: 5px 16px;
+    margin: 7px;
+    border: 1px solid #1573e9;
+    top: 12px;
+  }
+
+  .aui-get-code:hover {
+    color: #1573e9;
+  }
+
+  .code-shape {
+    border-color: #dadada !important;
+    color: #aaa !important;
+  }
+
+  :deep(.jeecg-dark-switch) {
+    position: absolute;
+    margin-right: 10px;
+  }
+
+  .aui-link-login {
+    height: 42px;
+    padding: 10px 15px;
     font-size: 14px;
-    color: #9a9a9a;
+    border-radius: 8px;
+    margin-top: 15px;
+    margin-bottom: 8px;
+    flex: 1;
+    color: #fff;
+  }
+
+  .aui-phone-logo {
+    position: absolute;
+    margin-left: 10px;
+    width: 60px;
+    top: 2px;
+    z-index: 4;
+  }
+
+  .top-3 {
+    top: 0.45rem;
+  }
+
+  .JLoginSelectDept {
+    margin: 5px auto;
+
+    :deep(.ant-select-selection-placeholder) {
+      font-size: 14px;
+      color: #9a9a9a;
+    }
   }
-}
 </style>
 
 <style lang="less">
-@prefix-cls: ~'@{namespace}-mini-login';
-@dark-bg: #293146;
+  @prefix-cls: ~'@{namespace}-mini-login';
+  @dark-bg: #293146;
 
-html[data-theme='dark'] {
-  .@{prefix-cls} {
-    background-color: @dark-bg !important;
-    background-image: none;
+  html[data-theme='dark'] {
+    .@{prefix-cls} {
+      background-color: @dark-bg !important;
+      background-image: none;
 
-    &::before {
-      background-image: url(/@/assets/svg/login-bg-dark.svg);
-    }
+      &::before {
+        background-image: url(/@/assets/svg/login-bg-dark.svg);
+      }
 
-    .aui-inputClear {
-      background-color: #232a3b !important;
-    }
+      .aui-inputClear {
+        background-color: #232a3b !important;
+      }
 
-    .ant-input,
-    .ant-input-password {
-      background-color: #232a3b !important;
-    }
+      .ant-input,
+      .ant-input-password {
+        background-color: #232a3b !important;
+      }
 
-    .ant-btn:not(.ant-btn-link):not(.ant-btn-primary) {
-      border: 1px solid #4a5569 !important;
-    }
+      .ant-btn:not(.ant-btn-link):not(.ant-btn-primary) {
+        border: 1px solid #4a5569 !important;
+      }
 
-    &-form {
-      background: @dark-bg !important;
-    }
+      &-form {
+        background: @dark-bg !important;
+      }
 
-    .app-iconify {
-      color: #fff !important;
-    }
+      .app-iconify {
+        color: #fff !important;
+      }
 
-    .aui-inputClear input,
-    .aui-input-line input,
-    .aui-choice {
-      color: #c9d1d9 !important;
-    }
+      .aui-inputClear input,
+      .aui-input-line input,
+      .aui-choice {
+        color: #c9d1d9 !important;
+      }
 
-    .aui-formBox {
-      background-color: @dark-bg !important;
-    }
+      .aui-formBox {
+        background-color: @dark-bg !important;
+      }
 
-    .aui-third-text span {
-      background-color: @dark-bg !important;
-    }
+      .aui-third-text span {
+        background-color: @dark-bg !important;
+      }
 
-    .aui-form-nav .aui-flex-box {
-      color: #c9d1d9 !important;
-    }
+      .aui-form-nav .aui-flex-box {
+        color: #c9d1d9 !important;
+      }
 
-    .aui-formButton .aui-linek-code {
-      background: @dark-bg !important;
-      color: white !important;
-    }
+      .aui-formButton .aui-linek-code {
+        background: @dark-bg !important;
+        color: white !important;
+      }
 
-    .aui-code-line {
-      border-left: none !important;
-    }
+      .aui-code-line {
+        border-left: none !important;
+      }
 
-    .ant-checkbox-inner,
-    .aui-success h3 {
-      border-color: #c9d1d9;
-    }
+      .ant-checkbox-inner,
+      .aui-success h3 {
+        border-color: #c9d1d9;
+      }
 
-    // 代码逻辑说明: 【QQYUN-6363】这个样式代码有问题,不在里面,导致表达式有问题------------
-    &-sign-in-way {
-      .anticon {
-        font-size: 22px !important;
-        color: #888 !important;
-        cursor: pointer !important;
+      // 代码逻辑说明: 【QQYUN-6363】这个样式代码有问题,不在里面,导致表达式有问题------------
+      &-sign-in-way {
+        .anticon {
+          font-size: 22px !important;
+          color: #888 !important;
+          cursor: pointer !important;
 
-        &:hover {
-          color: @primary-color !important;
+          &:hover {
+            color: @primary-color !important;
+          }
         }
       }
     }
-  }
 
-  input.fix-auto-fill,
-  .fix-auto-fill input {
-    -webkit-text-fill-color: #c9d1d9 !important;
-    box-shadow: inherit !important;
-  }
+    input.fix-auto-fill,
+    .fix-auto-fill input {
+      -webkit-text-fill-color: #c9d1d9 !important;
+      box-shadow: inherit !important;
+    }
 
-  .ant-divider-inner-text {
-    font-size: 12px !important;
-    color: @text-color-secondary !important;
-  }
+    .ant-divider-inner-text {
+      font-size: 12px !important;
+      color: @text-color-secondary !important;
+    }
 
-  .aui-third-login a {
-    background: transparent;
+    .aui-third-login a {
+      background: transparent;
+    }
   }
-}
 </style>

+ 187 - 187
src/views/system/loginmini/MiniRegister.vue

@@ -18,33 +18,32 @@
                   <a-form-item>
                     <div class="aui-input-line">
                       <Icon class="aui-icon" icon="ant-design:user-outlined" />
-                      <a-input class="fix-auto-fill" type="text" :placeholder="t('sys.login.userName')"
-                        v-model:value="formData.username" />
+                      <a-input class="fix-auto-fill" type="text" :placeholder="t('sys.login.userName')" v-model:value="formData.username" />
                     </div>
                   </a-form-item>
                   <a-form-item>
                     <div class="aui-input-line">
                       <Icon class="aui-icon" icon="ant-design:mobile-outlined" />
-                      <a-input class="fix-auto-fill" type="text" :placeholder="t('sys.login.mobile')"
-                        v-model:value="formData.mobile" />
+                      <a-input class="fix-auto-fill" type="text" :placeholder="t('sys.login.mobile')" v-model:value="formData.mobile" />
                     </div>
                   </a-form-item>
                   <a-form-item>
                     <div class="aui-input-line">
                       <Icon class="aui-icon" icon="ant-design:mail-outlined" />
-                      <a-input class="fix-auto-fill" type="text" :placeholder="t('sys.login.smsCode')"
-                        v-model:value="formData.smscode" />
-                      <div v-if="showInterval" class="aui-code-line" @click="getLoginCode">{{
-                        t('component.countdown.normalText') }}</div>
-                      <div v-else class="aui-code-line">{{ t('component.countdown.sendText', [unref(timeRuning)]) }}
-                      </div>
+                      <a-input class="fix-auto-fill" type="text" :placeholder="t('sys.login.smsCode')" v-model:value="formData.smscode" />
+                      <div v-if="showInterval" class="aui-code-line" @click="getLoginCode">{{ t('component.countdown.normalText') }}</div>
+                      <div v-else class="aui-code-line">{{ t('component.countdown.sendText', [unref(timeRuning)]) }} </div>
                     </div>
                   </a-form-item>
                   <a-form-item>
                     <div class="aui-input-line">
                       <Icon class="aui-icon" icon="ant-design:lock-outlined" />
-                      <a-input class="fix-auto-fill" :type="pwdIndex === 'close' ? 'password' : 'text'"
-                        :placeholder="t('sys.login.password')" v-model:value="formData.password" />
+                      <a-input
+                        class="fix-auto-fill"
+                        :type="pwdIndex === 'close' ? 'password' : 'text'"
+                        :placeholder="t('sys.login.password')"
+                        v-model:value="formData.password"
+                      />
                       <div class="aui-eye">
                         <img :src="eyeKImg" alt="开启" v-if="pwdIndex === 'open'" @click="pwdClick('close')" />
                         <img :src="eyeGImg" alt="关闭" v-else-if="pwdIndex === 'close'" @click="pwdClick('open')" />
@@ -54,13 +53,15 @@
                   <a-form-item>
                     <div class="aui-input-line">
                       <Icon class="aui-icon" icon="ant-design:lock-outlined" />
-                      <a-input class="fix-auto-fill" :type="confirmPwdIndex === 'close' ? 'password' : 'text'"
-                        :placeholder="t('sys.login.confirmPassword')" v-model:value="formData.confirmPassword" />
+                      <a-input
+                        class="fix-auto-fill"
+                        :type="confirmPwdIndex === 'close' ? 'password' : 'text'"
+                        :placeholder="t('sys.login.confirmPassword')"
+                        v-model:value="formData.confirmPassword"
+                      />
                       <div class="aui-eye">
-                        <img :src="eyeKImg" alt="开启" v-if="confirmPwdIndex === 'open'"
-                          @click="confirmPwdClick('close')" />
-                        <img :src="eyeGImg" alt="关闭" v-else-if="confirmPwdIndex === 'close'"
-                          @click="confirmPwdClick('open')" />
+                        <img :src="eyeKImg" alt="开启" v-if="confirmPwdIndex === 'open'" @click="confirmPwdClick('close')" />
+                        <img :src="eyeGImg" alt="关闭" v-else-if="confirmPwdIndex === 'close'" @click="confirmPwdClick('open')" />
                       </div>
                     </div>
                   </a-form-item>
@@ -78,8 +79,7 @@
               </div>
               <div class="aui-formButton">
                 <div class="aui-flex">
-                  <a class="aui-link-login aui-flex-box" @click="registerHandleClick"> {{ t('sys.login.registerButton')
-                  }}</a>
+                  <a class="aui-link-login aui-flex-box" @click="registerHandleClick"> {{ t('sys.login.registerButton') }}</a>
                 </div>
                 <div class="aui-flex">
                   <a class="aui-linek-code aui-flex-box" @click="goBackHandleClick">{{ t('sys.login.backSignIn') }}</a>
@@ -96,193 +96,193 @@
 </template>
 
 <script lang="ts" setup name="mini-register">
-import { ref, reactive, unref, toRaw } from 'vue';
-import { getCaptcha, register } from '/@/api/sys/user';
-import { SmsEnum } from '/@/views/sys/login/useLogin';
-import { useMessage } from '/@/hooks/web/useMessage';
-// import logoImg from '/@/assets/loginmini/icon/jeecg_logo.png';
-import jeecgAdTextImg from '/@/assets/loginmini/icon/jeecg_ad_text.png';
-import eyeKImg from '/@/assets/loginmini/icon/icon-eye-k.png';
-import eyeGImg from '/@/assets/loginmini/icon/icon-eye-g.png';
-import { useI18n } from '/@/hooks/web/useI18n';
-import CaptchaModal from '@/components/jeecg/captcha/CaptchaModal.vue';
-import { useModal } from '@/components/Modal';
-import { ExceptionEnum } from '@/enums/exceptionEnum';
-
-const { t } = useI18n();
-const { notification, createErrorModal, createMessage } = useMessage();
-const emit = defineEmits(['go-back', 'success', 'register']);
-const formRef = ref();
-const formData = reactive<any>({
-  username: '',
-  mobile: '',
-  smscode: '',
-  password: '',
-  confirmPassword: '',
-  policy: false,
-});
-//是否显示获取验证码
-const showInterval = ref<boolean>(true);
-//60s
-const timeRuning = ref<number>(60);
-//定时器
-const timer = ref<any>(null);
-//密码眼睛打开关闭
-const pwdIndex = ref<string>('close');
-//确认密码眼睛打开关闭
-const confirmPwdIndex = ref<string>('close');
-const [captchaRegisterModal, { openModal: openCaptchaModal }] = useModal();
+  import { ref, reactive, unref, toRaw } from 'vue';
+  import { getCaptcha, register } from '/@/api/sys/user';
+  import { SmsEnum } from '/@/views/sys/login/useLogin';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  // import logoImg from '/@/assets/loginmini/icon/jeecg_logo.png';
+  import jeecgAdTextImg from '/@/assets/loginmini/icon/jeecg_ad_text.png';
+  import eyeKImg from '/@/assets/loginmini/icon/icon-eye-k.png';
+  import eyeGImg from '/@/assets/loginmini/icon/icon-eye-g.png';
+  import { useI18n } from '/@/hooks/web/useI18n';
+  import CaptchaModal from '@/components/jeecg/captcha/CaptchaModal.vue';
+  import { useModal } from '@/components/Modal';
+  import { ExceptionEnum } from '@/enums/exceptionEnum';
 
-/**
- * 返回
- */
-function goBackHandleClick() {
-  emit('go-back');
-  initForm();
-}
+  const { t } = useI18n();
+  const { notification, createErrorModal, createMessage } = useMessage();
+  const emit = defineEmits(['go-back', 'success', 'register']);
+  const formRef = ref();
+  const formData = reactive<any>({
+    username: '',
+    mobile: '',
+    smscode: '',
+    password: '',
+    confirmPassword: '',
+    policy: false,
+  });
+  //是否显示获取验证码
+  const showInterval = ref<boolean>(true);
+  //60s
+  const timeRuning = ref<number>(60);
+  //定时器
+  const timer = ref<any>(null);
+  //密码眼睛打开关闭
+  const pwdIndex = ref<string>('close');
+  //确认密码眼睛打开关闭
+  const confirmPwdIndex = ref<string>('close');
+  const [captchaRegisterModal, { openModal: openCaptchaModal }] = useModal();
 
-/**
- * 获取手机验证码
- */
-async function getLoginCode() {
-  if (!formData.mobile) {
-    createMessage.warn(t('sys.login.mobilePlaceholder'));
-    return;
+  /**
+   * 返回
+   */
+  function goBackHandleClick() {
+    emit('go-back');
+    initForm();
   }
-  // 代码逻辑说明: 【QQYUN-9005】同一个IP,1分钟超过5次短信,则提示需要验证码---
-  const result = await getCaptcha({ mobile: formData.mobile, smsmode: SmsEnum.REGISTER }).catch((res) => {
-    if (res.code === ExceptionEnum.PHONE_SMS_FAIL_CODE) {
-      openCaptchaModal(true, {});
+
+  /**
+   * 获取手机验证码
+   */
+  async function getLoginCode() {
+    if (!formData.mobile) {
+      createMessage.warn(t('sys.login.mobilePlaceholder'));
+      return;
     }
-  });
-  if (result) {
-    const TIME_COUNT = 60;
-    if (!unref(timer)) {
-      timeRuning.value = TIME_COUNT;
-      showInterval.value = false;
-      timer.value = setInterval(() => {
-        if (unref(timeRuning) > 0 && unref(timeRuning) <= TIME_COUNT) {
-          timeRuning.value = timeRuning.value - 1;
-        } else {
-          showInterval.value = true;
-          clearInterval(unref(timer));
-          timer.value = null;
-        }
-      }, 1000);
+    // 代码逻辑说明: 【QQYUN-9005】同一个IP,1分钟超过5次短信,则提示需要验证码---
+    const result = await getCaptcha({ mobile: formData.mobile, smsmode: SmsEnum.REGISTER }).catch((res) => {
+      if (res.code === ExceptionEnum.PHONE_SMS_FAIL_CODE) {
+        openCaptchaModal(true, {});
+      }
+    });
+    if (result) {
+      const TIME_COUNT = 60;
+      if (!unref(timer)) {
+        timeRuning.value = TIME_COUNT;
+        showInterval.value = false;
+        timer.value = setInterval(() => {
+          if (unref(timeRuning) > 0 && unref(timeRuning) <= TIME_COUNT) {
+            timeRuning.value = timeRuning.value - 1;
+          } else {
+            showInterval.value = true;
+            clearInterval(unref(timer));
+            timer.value = null;
+          }
+        }, 1000);
+      }
     }
   }
-}
 
-function registerHandleClick() {
-  if (!formData.username) {
-    createMessage.warn(t('sys.login.accountPlaceholder'));
-    return;
-  }
-  if (!formData.mobile) {
-    createMessage.warn(t('sys.login.mobilePlaceholder'));
-    return;
-  }
-  if (!formData.smscode) {
-    createMessage.warn(t('sys.login.smsPlaceholder'));
-    return;
-  }
-  if (!formData.password) {
-    createMessage.warn(t('sys.login.passwordPlaceholder'));
-    return;
-  }
-  if (!formData.confirmPassword) {
-    createMessage.warn(t('sys.login.confirmPassword'));
-    return;
-  }
-  if (formData.password !== formData.confirmPassword) {
-    createMessage.warn(t('sys.login.diffPwd'));
-    return;
-  }
-  if (!formData.policy) {
-    createMessage.warn(t('sys.login.policyPlaceholder'));
-    return;
+  function registerHandleClick() {
+    if (!formData.username) {
+      createMessage.warn(t('sys.login.accountPlaceholder'));
+      return;
+    }
+    if (!formData.mobile) {
+      createMessage.warn(t('sys.login.mobilePlaceholder'));
+      return;
+    }
+    if (!formData.smscode) {
+      createMessage.warn(t('sys.login.smsPlaceholder'));
+      return;
+    }
+    if (!formData.password) {
+      createMessage.warn(t('sys.login.passwordPlaceholder'));
+      return;
+    }
+    if (!formData.confirmPassword) {
+      createMessage.warn(t('sys.login.confirmPassword'));
+      return;
+    }
+    if (formData.password !== formData.confirmPassword) {
+      createMessage.warn(t('sys.login.diffPwd'));
+      return;
+    }
+    if (!formData.policy) {
+      createMessage.warn(t('sys.login.policyPlaceholder'));
+      return;
+    }
+    registerAccount();
   }
-  registerAccount();
-}
 
-/**
- * 注册账号
- */
-async function registerAccount() {
-  try {
-    const resultInfo = await register(
-      toRaw({
-        username: formData.username,
-        password: formData.password,
-        phone: formData.mobile,
-        smscode: formData.smscode,
-      })
-    );
-    if (resultInfo && resultInfo.data.success) {
-      notification.success({
-        description: resultInfo.data.message || t('sys.api.registerMsg'),
-        duration: 3,
-      });
-      emit('success', { username: formData.username, password: formData.password });
-      initForm();
-    } else {
-      notification.warning({
+  /**
+   * 注册账号
+   */
+  async function registerAccount() {
+    try {
+      const resultInfo = await register(
+        toRaw({
+          username: formData.username,
+          password: formData.password,
+          phone: formData.mobile,
+          smscode: formData.smscode,
+        })
+      );
+      if (resultInfo && resultInfo.data.success) {
+        notification.success({
+          description: resultInfo.data.message || t('sys.api.registerMsg'),
+          duration: 3,
+        });
+        emit('success', { username: formData.username, password: formData.password });
+        initForm();
+      } else {
+        notification.warning({
+          message: t('sys.api.errorTip'),
+          description: resultInfo.data.message || t('sys.api.networkExceptionMsg'),
+          duration: 3,
+        });
+      }
+    } catch (error) {
+      notification.error({
         message: t('sys.api.errorTip'),
-        description: resultInfo.data.message || t('sys.api.networkExceptionMsg'),
+        description: error.message || t('sys.api.networkExceptionMsg'),
         duration: 3,
       });
     }
-  } catch (error) {
-    notification.error({
-      message: t('sys.api.errorTip'),
-      description: error.message || t('sys.api.networkExceptionMsg'),
-      duration: 3,
-    });
   }
-}
 
-/**
- * 初始化表单
- */
-function initForm() {
-  Object.assign(formData, { username: '', mobile: '', smscode: '', password: '', confirmPassword: '', policy: false });
-  if (!unref(timer)) {
-    showInterval.value = true;
-    clearInterval(unref(timer));
-    timer.value = null;
+  /**
+   * 初始化表单
+   */
+  function initForm() {
+    Object.assign(formData, { username: '', mobile: '', smscode: '', password: '', confirmPassword: '', policy: false });
+    if (!unref(timer)) {
+      showInterval.value = true;
+      clearInterval(unref(timer));
+      timer.value = null;
+    }
+    formRef.value.resetFields();
   }
-  formRef.value.resetFields();
-}
 
-/**
- * 密码打开或关闭
- * @param value
- */
-function pwdClick(value) {
-  pwdIndex.value = value;
-}
+  /**
+   * 密码打开或关闭
+   * @param value
+   */
+  function pwdClick(value) {
+    pwdIndex.value = value;
+  }
 
-/**
- * 确认密码打开或关闭
- * @param value
- */
-function confirmPwdClick(value) {
-  confirmPwdIndex.value = value;
-}
+  /**
+   * 确认密码打开或关闭
+   * @param value
+   */
+  function confirmPwdClick(value) {
+    confirmPwdIndex.value = value;
+  }
 
-defineExpose({
-  initForm,
-});
+  defineExpose({
+    initForm,
+  });
 </script>
 <style lang="less" scoped>
-@import '/@/assets/loginmini/style/home.less';
-@import '/@/assets/loginmini/style/base.less';
+  @import '/@/assets/loginmini/style/home.less';
+  @import '/@/assets/loginmini/style/base.less';
 
-.aui-input-line .aui-icon {
-  position: absolute;
-  z-index: @layout-basic-z-index;
-  top: 10px;
-  left: 10px;
-  font-size: 20px !important;
-}
+  .aui-input-line .aui-icon {
+    position: absolute;
+    z-index: @layout-basic-z-index;
+    top: 10px;
+    left: 10px;
+    font-size: 20px !important;
+  }
 </style>