Browse Source

feat: 主题样式调整

zhangjie 4 days ago
parent
commit
444bc09c06

+ 1 - 8
config/vite.config.base.ts

@@ -39,12 +39,5 @@ export default defineConfig({
     'process.env': {},
     'process.env': {},
     '__VUE_PROD_HYDRATION_MISMATCH_DETAILS__': false,
     '__VUE_PROD_HYDRATION_MISMATCH_DETAILS__': false,
   },
   },
-  css: {
-    preprocessorOptions: {
-      scss: {
-        api: 'modern-compiler',
-        additionalData: `@use "@/assets/style/var.scss" as *;`,
-      },
-    },
-  },
+  css: {},
 });
 });

+ 1 - 1
config/vite.config.dev.ts

@@ -1,5 +1,5 @@
 import { mergeConfig, loadEnv } from 'vite';
 import { mergeConfig, loadEnv } from 'vite';
-import eslint from 'vite-plugin-eslint';
+// import eslint from 'vite-plugin-eslint';
 import baseConfig from './vite.config.base';
 import baseConfig from './vite.config.base';
 
 
 const env = loadEnv('development', process.cwd(), '');
 const env = loadEnv('development', process.cwd(), '');

+ 1 - 0
package.json

@@ -78,6 +78,7 @@
     "sass": "^1.89.2",
     "sass": "^1.89.2",
     "typescript": "^4.8.4",
     "typescript": "^4.8.4",
     "unplugin-auto-import": "^19.3.0",
     "unplugin-auto-import": "^19.3.0",
+    "unplugin-element-plus": "^0.10.0",
     "unplugin-vue-components": "^0.24.1",
     "unplugin-vue-components": "^0.24.1",
     "vite": "^3.2.5",
     "vite": "^3.2.5",
     "vite-plugin-compression": "^0.5.1",
     "vite-plugin-compression": "^0.5.1",

+ 16 - 0
pnpm-lock.yaml

@@ -50,6 +50,7 @@ specifiers:
   sass: ^1.89.2
   sass: ^1.89.2
   typescript: ^4.8.4
   typescript: ^4.8.4
   unplugin-auto-import: ^19.3.0
   unplugin-auto-import: ^19.3.0
+  unplugin-element-plus: ^0.10.0
   unplugin-vue-components: ^0.24.1
   unplugin-vue-components: ^0.24.1
   vite: ^3.2.5
   vite: ^3.2.5
   vite-plugin-compression: ^0.5.1
   vite-plugin-compression: ^0.5.1
@@ -113,6 +114,7 @@ devDependencies:
   sass: 1.89.2
   sass: 1.89.2
   typescript: 4.9.5
   typescript: 4.9.5
   unplugin-auto-import: 19.3.0_@vueuse+core@9.13.0
   unplugin-auto-import: 19.3.0_@vueuse+core@9.13.0
+  unplugin-element-plus: 0.10.0
   unplugin-vue-components: 0.24.1_rollup@2.79.2+vue@3.5.16
   unplugin-vue-components: 0.24.1_rollup@2.79.2+vue@3.5.16
   vite: 3.2.11_sass@1.89.2
   vite: 3.2.11_sass@1.89.2
   vite-plugin-compression: 0.5.1_vite@3.2.11
   vite-plugin-compression: 0.5.1_vite@3.2.11
@@ -2546,6 +2548,10 @@ packages:
     resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
     resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
     engines: {node: '>= 0.4'}
     engines: {node: '>= 0.4'}
 
 
+  /es-module-lexer/1.7.0:
+    resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
+    dev: true
+
   /es-object-atoms/1.1.1:
   /es-object-atoms/1.1.1:
     resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
     resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
     engines: {node: '>= 0.4'}
     engines: {node: '>= 0.4'}
@@ -6765,6 +6771,16 @@ packages:
       unplugin-utils: 0.2.4
       unplugin-utils: 0.2.4
     dev: true
     dev: true
 
 
+  /unplugin-element-plus/0.10.0:
+    resolution: {integrity: sha512-oRSW0x6U58xBOWKy8TcoVZNA8ElIpfp3TUJRLQI6ey/E9PpjHl9/deeTAZNt8D57Li4OA4pCJtM6p2cb4Ff4ZA==}
+    engines: {node: '>=18.12.0'}
+    dependencies:
+      es-module-lexer: 1.7.0
+      magic-string: 0.30.17
+      unplugin: 2.3.5
+      unplugin-utils: 0.2.4
+    dev: true
+
   /unplugin-utils/0.2.4:
   /unplugin-utils/0.2.4:
     resolution: {integrity: sha512-8U/MtpkPkkk3Atewj1+RcKIjb5WBimZ/WSLhhR3w6SsIj8XJuKTacSP8g+2JhfSGw0Cb125Y+2zA/IzJZDVbhA==}
     resolution: {integrity: sha512-8U/MtpkPkkk3Atewj1+RcKIjb5WBimZ/WSLhhR3w6SsIj8XJuKTacSP8g+2JhfSGw0Cb125Y+2zA/IzJZDVbhA==}
     engines: {node: '>=18.12.0'}
     engines: {node: '>=18.12.0'}

+ 13 - 3
src/assets/style/base.scss

@@ -21,10 +21,20 @@
     padding: 0;
     padding: 0;
   }
   }
   &.is-filter {
   &.is-filter {
-    padding-bottom: 4px;
+    border: 1px solid var(--color-border);
+    padding-bottom: 1px;
+
+    .el-form-item {
+      margin-bottom: 15px;
+      margin-right: 16px;
+    }
+    .el-form-item__label {
+      padding-right: 8px;
+      color: var(--color-text-dark);
+    }
 
 
-    .el-form + .el-space {
-      padding-bottom: 10px;
+    + .part-box {
+      border: 1px solid var(--color-border);
     }
     }
   }
   }
 
 

+ 85 - 38
src/assets/style/element-custom.scss

@@ -1,37 +1,18 @@
-// el-btn
-.el-btn + .el-btn {
-  margin-left: 10px;
-}
-.el-btn-text {
-  &:not(.el-btn-only-icon) .el-btn-icon {
-    margin-right: 4px;
-  }
-}
-// .el-pagination
+// .el-table
 .el-table {
 .el-table {
   & + .el-pagination {
   & + .el-pagination {
-    margin-top: 10px;
+    margin-top: 16px;
   }
   }
-}
-.el-pagination {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
 
 
-  .el-pagination-item {
-    border: 1px solid var(--color-border);
-    line-height: 30px;
-  }
-  .el-pagination-item-active {
-    border-color: var(--color-primary);
-    background-color: var(--color-primary);
-    color: #fff;
-  }
-  .el-select-view-single {
-    border-color: var(--color-border);
+  th.el-table__cell {
+    background-image: linear-gradient(180deg, #f9f9f9 0%, #f1f1f1 100%);
   }
   }
-  .el-pagination-total {
-    flex-grow: 2;
+
+  &.is-scrolling-none {
+    th.el-table-fixed-column--left,
+    th.el-table-fixed-column--right {
+      background-image: linear-gradient(180deg, #f9f9f9 0%, #f1f1f1 100%);
+    }
   }
   }
 }
 }
 
 
@@ -54,15 +35,56 @@
   }
   }
 }
 }
 
 
-// el-input
-// .el-input-wrapper,
-// .el-select-view-single {
-//   border-color: #d9d9d9;
-//   background-color: transparent;
-//   &:hover {
-//     border-color: #bebebe;
-//   }
-// }
+// .el-pagination
+.el-pagination {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+
+  .el-pager li {
+    border: 1px solid var(--el-border-color-lighter);
+    line-height: 30px;
+    border-radius: 6px;
+
+    &.is-active {
+      color: var(--color-primary);
+      background: #e8f7ff;
+      border: 1px solid #c3e7fe;
+    }
+  }
+  .el-pagination__jump {
+    color: var(--color-text-gray);
+
+    .el-input__wrapper {
+      border-radius: 6px;
+      padding: 1px 5px;
+    }
+  }
+  .el-pagination__editor.el-input {
+    width: 50px;
+  }
+
+  .el-select-view-single {
+    border-color: var(--color-border);
+  }
+  .el-pagination-total {
+    flex-grow: 2;
+  }
+
+  .el-pagination__sizes .el-select {
+    width: 100px;
+  }
+  .el-pagination__sizes .el-select__wrapper {
+    border-radius: 6px;
+  }
+}
+
+// el-input-number
+.el-input-number {
+  .el-input__inner {
+    text-align: left;
+  }
+}
 
 
 // el-modal
 // el-modal
 .el-modal-wrapper {
 .el-modal-wrapper {
@@ -135,3 +157,28 @@
     }
     }
   }
   }
 }
 }
+
+// .el-dialog
+.el-dialog {
+  padding: 0;
+  border-radius: 8px;
+  .el-dialog__header {
+    height: 46px;
+    background: linear-gradient(180deg, #f9f9f9 0%, #f1f1f1 100%);
+    border-radius: 8px 8px 0px 0px;
+    padding: 11px 20px 10px;
+    border-bottom: 1px solid #dce3eb;
+  }
+  .el-dialog__headerbtn {
+    width: 50px;
+    height: 46px;
+    font-size: 20px;
+    line-height: 50px;
+  }
+  .el-dialog__body {
+    padding: 20px;
+  }
+  .el-dialog__footer {
+    padding: 10px 20px 20px;
+  }
+}

+ 15 - 7
src/assets/style/element.scss

@@ -1,12 +1,20 @@
 /* just override what you need */
 /* just override what you need */
-@forward 'element-plus/theme-chalk/src/common/var.scss' with (
-  $colors: (
-    'primary': (
-      'base': #0673f9,
-    ),
-  )
-);
+// @forward 'element-plus/theme-chalk/src/common/var.scss' with (
+//   $colors: (
+//     'primary': (
+//       'base': #0673f9,
+//     ),
+//   ),
+//   $table: (
+//     'border-color': #e5e5e5,
+//   )
+// );
 
 
 // If you just import on demand, you can ignore the following content.
 // If you just import on demand, you can ignore the following content.
 // 如果你想导入所有样式:
 // 如果你想导入所有样式:
 // @use 'element-plus/theme-chalk/src/index.scss' as *;
 // @use 'element-plus/theme-chalk/src/index.scss' as *;
+@use 'element-plus/theme-chalk/src/message.scss';
+@use 'element-plus/theme-chalk/src/message-box.scss';
+@use 'element-plus/theme-chalk/src/dialog.scss';
+@use 'element-plus/theme-chalk/src/alert.scss';
+@use 'element-plus/theme-chalk/src/notification.scss';

+ 150 - 45
src/assets/style/home.scss

@@ -1,27 +1,55 @@
 /* home */
 /* home */
 .home-body {
 .home-body {
   background: var(--color-background);
   background: var(--color-background);
-  padding: 76px 20px 50px 240px;
+  padding: 72px 16px 16px 216px;
   min-height: 100vh;
   min-height: 100vh;
   position: relative;
   position: relative;
+  transition: padding-left 0.3s;
 }
 }
 
 
 /* navs */
 /* navs */
 .home-navs {
 .home-navs {
   position: fixed;
   position: fixed;
-  width: 220px;
-  top: 56px;
+  width: 201px;
+  top: 0;
   left: 0;
   left: 0;
   bottom: 0;
   bottom: 0;
   z-index: 100;
   z-index: 100;
   overflow: auto;
   overflow: auto;
   font-size: 14px;
   font-size: 14px;
-  background: var(--color-white);
-  .el-menu-home {
-    padding: 16px 8px;
+  background: #e5f4ff;
+  border-right: 1px solid var(--color-border);
+
+  .home-title {
+    padding: 16px 24px;
+    display: flex;
+    align-items: center;
 
 
     .svg-icon {
     .svg-icon {
-      margin-top: -3px;
+      font-size: 24px;
+      margin-right: 8px;
+    }
+
+    h1 {
+      font-weight: 700;
+      font-size: 16px;
+    }
+  }
+  .el-menu {
+    background-color: transparent;
+    border-right: none;
+    &.el-menu-home {
+      padding: 16px 8px;
+    }
+
+    .svg-icon {
+      margin-right: 8px;
+      font-size: 16px;
+      color: #b8cade;
+    }
+    .el-sub-menu__icon-arrow {
+      color: #a4b4c6;
+      font-size: 14px;
     }
     }
 
 
     .el-menu-item {
     .el-menu-item {
@@ -29,11 +57,28 @@
       min-height: 38px;
       min-height: 38px;
       line-height: 20px;
       line-height: 20px;
       white-space: normal;
       white-space: normal;
+      margin: 4px 0;
+      color: var(--color-text-dark);
+      padding-left: 16px;
+      border-radius: 6px;
 
 
       &.is-active {
       &.is-active {
-        font-weight: 500;
-        color: var(--color-primary);
-        background-color: var(--color-primary-light);
+        background: var(--color-primary);
+        box-shadow: 0px 4px 8px #7fc3ff;
+        color: var(--color-white);
+      }
+    }
+    .el-sub-menu {
+      &.is-active {
+        .svg-icon,
+        .el-sub-menu__title,
+        .el-sub-menu__icon-arrow {
+          color: var(--color-primary);
+        }
+      }
+
+      .el-menu-item {
+        padding-left: 44px !important;
       }
       }
     }
     }
     .el-sub-menu__title {
     .el-sub-menu__title {
@@ -48,57 +93,70 @@
 /* head */
 /* head */
 .home-header {
 .home-header {
   position: fixed;
   position: fixed;
-  width: 100%;
   height: 56px;
   height: 56px;
   top: 0;
   top: 0;
-  left: 0;
+  right: 0;
+  left: 201px;
   z-index: 99;
   z-index: 99;
-  padding: 12px 16px 11px;
+  padding: 11px 16px 11px;
   background-color: #fff;
   background-color: #fff;
 
 
   display: flex;
   display: flex;
   align-items: center;
   align-items: center;
   justify-content: space-between;
   justify-content: space-between;
   border-bottom: 1px solid var(--color-border);
   border-bottom: 1px solid var(--color-border);
+  transition: left 0.3s;
 
 
-  .home-title {
-    font-size: 20px;
-    font-weight: bold;
+  .home-exam {
+    display: flex;
+    align-items: center;
+
+    .el-button {
+      padding: 9px 8px;
+      margin-right: 10px;
+      height: 34px;
+    }
+
+    .svg-icon {
+      font-size: 18px;
+    }
+
+    > span {
+      font-weight: 500;
+      color: var(--color-text-dark);
+      font-size: 16px;
+    }
   }
   }
 
 
-  .home-action {
-    &-item {
-      display: inline-block;
-      vertical-align: middle;
-      height: 32px;
-      line-height: 32px;
-      padding: 0 8px;
-      font-weight: 400;
-      border-radius: var(--border-radius-small);
-
-      &:not(:first-child) {
-        margin-left: 8px;
-      }
+  .home-tips {
+    height: 34px;
+    background: #e8f3ff;
+    border: 1px solid #c3deff;
+    border-radius: 6px;
+    padding: 5px 12px;
+    color: var(--color-primary);
 
 
-      .svg-icon {
-        font-size: 18px;
-      }
+    display: flex;
+    align-items: center;
 
 
-      .svg-icon + span {
-        margin-left: 6px;
-      }
-      > span {
-        display: inline-block;
-        vertical-align: middle;
-      }
+    .svg-icon {
+      margin-right: 8px;
+      font-size: 20px;
+    }
+  }
 
 
-      &.cursor {
-        cursor: pointer;
+  .home-action {
+    .el-button {
+      padding: 9px 8px;
+      margin-right: 10px;
+      height: 34px;
+      margin: 0;
+      color: var(--color-text-dark);
+      font-size: 16px;
+    }
 
 
-        &:hover {
-          background-color: var(--color-background);
-        }
-      }
+    .svg-icon {
+      font-size: 18px;
     }
     }
   }
   }
 }
 }
@@ -196,3 +254,50 @@
     color: var(--color-text-gray);
     color: var(--color-text-gray);
   }
   }
 }
 }
+
+.home.is-collapse {
+  .home-navs {
+    width: 64px;
+    overflow-x: hidden;
+
+    .home-title {
+      padding: 16px 5px;
+      justify-content: center;
+      .svg-icon {
+        margin: 0;
+      }
+
+      > h1 {
+        display: none;
+      }
+    }
+
+    .el-menu {
+      .svg-icon {
+        margin: 0;
+      }
+      .el-menu-item {
+        padding: 0 5px;
+        justify-content: center;
+
+        > span {
+          display: none;
+        }
+      }
+      .el-sub-menu__title {
+        padding: 0 5px;
+        justify-content: center;
+
+        > span {
+          display: none;
+        }
+      }
+    }
+  }
+  .home-body {
+    padding-left: 80px;
+  }
+  .home-header {
+    left: 64px;
+  }
+}

+ 11 - 6
src/assets/style/var.scss

@@ -1,4 +1,4 @@
-body {
+:root {
   /* color -------------------> */
   /* color -------------------> */
   --color-text-dark: #262626;
   --color-text-dark: #262626;
   --color-text-dark-1: #595959;
   --color-text-dark-1: #595959;
@@ -7,9 +7,9 @@ body {
   --color-text-gray-2: #bfbfbf;
   --color-text-gray-2: #bfbfbf;
   --color-text-gray-3: #d3d5e0;
   --color-text-gray-3: #d3d5e0;
   --color-text-gray-4: #e0e1eb;
   --color-text-gray-4: #e0e1eb;
-  --color-border: #e5e5e5;
+  --color-border: #dce3eb;
   --color-border-bold: #d5d5d5;
   --color-border-bold: #d5d5d5;
-  --color-background: #f2f3f5;
+  --color-background: #f6fcff;
   --form-color-border: #d9d9d9;
   --form-color-border: #d9d9d9;
 
 
   /* status */
   /* status */
@@ -43,7 +43,12 @@ body {
   --font-family: SourceHanSansCN, 'Helvetica Neue', Helvetica, 'PingFang SC',
   --font-family: SourceHanSansCN, 'Helvetica Neue', Helvetica, 'PingFang SC',
     'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;
     'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;
 
 
-  // arco
-  --border-radius-small: 4px;
-  --color-text-1: --color-text-dark-1;
+  // element
+  --el-color-primary: var(--color-primary);
+  --el-border-color-lighter: #e5e5e5;
+
+  .el-table {
+    --el-table-header-text-color: var(--color-text-dark);
+    --el-table-text-color: var(--color-text-dark);
+  }
 }
 }

+ 0 - 0
src/assets/svgs/icon-issue.svg → src/assets/svgs/icon-issue-paper.svg


+ 2 - 2
src/components/svg-icon/index.vue

@@ -20,7 +20,7 @@
   import IconHome from '../../assets/svgs/icon-home.svg?component';
   import IconHome from '../../assets/svgs/icon-home.svg?component';
   import IconImport from '../../assets/svgs/icon-import.svg?component';
   import IconImport from '../../assets/svgs/icon-import.svg?component';
   import IconInit from '../../assets/svgs/icon-init.svg?component';
   import IconInit from '../../assets/svgs/icon-init.svg?component';
-  import IconIssue from '../../assets/svgs/icon-issue.svg?component';
+  import IconIssuePaper from '../../assets/svgs/icon-issue-paper.svg?component';
   import IconJump from '../../assets/svgs/icon-jump.svg?component';
   import IconJump from '../../assets/svgs/icon-jump.svg?component';
   import IconLog from '../../assets/svgs/icon-log.svg?component';
   import IconLog from '../../assets/svgs/icon-log.svg?component';
   import IconLogo from '../../assets/svgs/icon-logo.svg?component';
   import IconLogo from '../../assets/svgs/icon-logo.svg?component';
@@ -80,7 +80,7 @@
     IconHome,
     IconHome,
     IconImport,
     IconImport,
     IconInit,
     IconInit,
-    IconIssue,
+    IconIssuePaper,
     IconJump,
     IconJump,
     IconLog,
     IconLog,
     IconLogo,
     IconLogo,

+ 1 - 1
src/hooks/table.ts

@@ -13,7 +13,7 @@ export default function useTable<T extends Record<string, any>>(
     pageNumber: 1,
     pageNumber: 1,
     pageSize: 20,
     pageSize: 20,
     total: 0,
     total: 0,
-    layout: ` prev, pager, next, jumper,sizes, ->, total`,
+    layout: `total, ->, sizes, prev, pager, next, jumper`,
   });
   });
 
 
   interface SortConfig {
   interface SortConfig {

+ 39 - 20
src/layout/default-layout.vue

@@ -1,33 +1,47 @@
 <template>
 <template>
-  <div class="home">
+  <div class="home" :class="isCollapse ? 'is-collapse' : ''">
     <div class="home-header">
     <div class="home-header">
-      <div>
-        <h1 class="home-title">云阅卷</h1>
+      <div class="home-exam">
+        <el-button text @click="toggleCollapse">
+          <svg-icon name="icon-menu" />
+        </el-button>
+        <span>当前考试:{{ curExamName }}</span>
+      </div>
+      <div class="home-tips">
+        <svg-icon name="icon-ai" />
+        <span>AI检测预计耗时12小时35分后完成</span>
       </div>
       </div>
       <div class="home-action">
       <div class="home-action">
-        <!-- <div class="home-action-item">
-          <svg-icon name="icon-user" fill="#BFBFBF" />
-          <span :title="userStore.name">{{ userStore.name }}</span>
-        </div> -->
         <el-tooltip content="修改密码" placement="bottom-end">
         <el-tooltip content="修改密码" placement="bottom-end">
-          <div class="home-action-item cursor" @click="toResetPwd">
-            <svg-icon name="icon-user" fill="#BFBFBF" />
-            <span :title="userStore.name">{{ userStore.name }}</span>
-          </div>
+          <el-button text @click="toResetPwd">
+            <svg-icon name="icon-user" />
+            <!-- <span :title="userStore.name">{{ userStore.name }}</span> -->
+            <span :title="userStore.name" style="margin-left: 6px"
+              >姓名(角色)</span
+            >
+          </el-button>
         </el-tooltip>
         </el-tooltip>
+        <el-button text @click="toLogout">
+          <svg-icon name="icon-notice" />
+        </el-button>
         <el-tooltip content="退出登录" placement="bottom-end">
         <el-tooltip content="退出登录" placement="bottom-end">
-          <div class="home-action-item cursor" @click="toLogout">
+          <el-button text @click="toLogout">
             <svg-icon name="icon-logout" />
             <svg-icon name="icon-logout" />
-          </div>
+          </el-button>
         </el-tooltip>
         </el-tooltip>
       </div>
       </div>
     </div>
     </div>
 
 
     <div class="home-navs">
     <div class="home-navs">
+      <div class="home-title">
+        <svg-icon name="icon-logo" />
+        <h1>云阅卷</h1>
+      </div>
       <el-menu
       <el-menu
         v-if="appStore.appMenus && appStore.appMenus.length"
         v-if="appStore.appMenus && appStore.appMenus.length"
         class="el-menu-home"
         class="el-menu-home"
         :default-active="curRouteName"
         :default-active="curRouteName"
+        :collapse="isCollapse"
         @select="toMenuItem"
         @select="toMenuItem"
       >
       >
         <template v-for="submenu in appStore.appMenus">
         <template v-for="submenu in appStore.appMenus">
@@ -36,10 +50,8 @@
             :key="submenu.url"
             :key="submenu.url"
             :index="submenu.url"
             :index="submenu.url"
           >
           >
-            <template #icon>
-              <svg-icon :name="`icon-${submenu.url}`" />
-            </template>
             <template #title>
             <template #title>
+              <svg-icon v-if="submenu.icon" :name="submenu.icon" />
               <span>{{ submenu.name }}</span>
               <span>{{ submenu.name }}</span>
             </template>
             </template>
 
 
@@ -52,6 +64,7 @@
             </el-menu-item>
             </el-menu-item>
           </el-sub-menu>
           </el-sub-menu>
           <el-menu-item v-else :key="submenu.url + 'menu'" :index="submenu.url">
           <el-menu-item v-else :key="submenu.url + 'menu'" :index="submenu.url">
+            <svg-icon v-if="submenu.icon" :name="submenu.icon" />
             <span>{{ submenu.name }}</span>
             <span>{{ submenu.name }}</span>
           </el-menu-item>
           </el-menu-item>
         </template>
         </template>
@@ -78,8 +91,6 @@
       <div class="home-view">
       <div class="home-view">
         <router-view />
         <router-view />
       </div>
       </div>
-
-      <Footer class="home-footer" />
     </div>
     </div>
   </div>
   </div>
 
 
@@ -88,13 +99,12 @@
 </template>
 </template>
 
 
 <script lang="ts" setup>
 <script lang="ts" setup>
-  import { onMounted, ref, watch } from 'vue';
+  import { computed, onMounted, ref, watch } from 'vue';
   import { useRoute, useRouter } from 'vue-router';
   import { useRoute, useRouter } from 'vue-router';
   import { useAppStore, useUserStore } from '@/store';
   import { useAppStore, useUserStore } from '@/store';
   import { ElMessageBox } from 'element-plus';
   import { ElMessageBox } from 'element-plus';
 
 
   import ResetPwd from '@/views/login/ResetPwd.vue';
   import ResetPwd from '@/views/login/ResetPwd.vue';
-  import Footer from '@/components/footer/index.vue';
 
 
   defineOptions({
   defineOptions({
     name: 'DefaultLayout',
     name: 'DefaultLayout',
@@ -107,12 +117,21 @@
 
 
   const curRouteName = ref('');
   const curRouteName = ref('');
   const fesetPwdRef = ref();
   const fesetPwdRef = ref();
+  const isCollapse = ref(false);
+
+  const curExamName = computed(() => {
+    return appStore.curExam?.name ?? '';
+  });
 
 
   function initData() {
   function initData() {
     curRouteName.value = route.name as string;
     curRouteName.value = route.name as string;
     // console.log(route.name);
     // console.log(route.name);
   }
   }
 
 
+  function toggleCollapse() {
+    isCollapse.value = !isCollapse.value;
+  }
+
   function toMenuItem(val: string) {
   function toMenuItem(val: string) {
     router.push({ name: val });
     router.push({ name: val });
   }
   }

+ 25 - 0
src/store/modules/app/menuData.ts

@@ -34,6 +34,7 @@ export const adminMenus = [
     id: 1,
     id: 1,
     name: '主页导览',
     name: '主页导览',
     url: 'HomeGuide',
     url: 'HomeGuide',
+    icon: 'icon-home',
     type: 'MENU',
     type: 'MENU',
     parentId: -1,
     parentId: -1,
     sequence: 1,
     sequence: 1,
@@ -43,6 +44,7 @@ export const adminMenus = [
     id: 2,
     id: 2,
     name: '用户管理',
     name: '用户管理',
     url: 'UserManage',
     url: 'UserManage',
+    icon: 'icon-user-manage',
     type: 'MENU',
     type: 'MENU',
     parentId: -1,
     parentId: -1,
     sequence: 2,
     sequence: 2,
@@ -52,6 +54,7 @@ export const adminMenus = [
     id: 3,
     id: 3,
     name: '考试管理',
     name: '考试管理',
     url: 'ExamManage',
     url: 'ExamManage',
+    icon: 'icon-exam-manage',
     type: 'MENU',
     type: 'MENU',
     parentId: -1,
     parentId: -1,
     sequence: 2,
     sequence: 2,
@@ -61,6 +64,7 @@ export const adminMenus = [
     id: 4,
     id: 4,
     name: '考生管理',
     name: '考生管理',
     url: 'StudentManage',
     url: 'StudentManage',
+    icon: 'icon-student-manage',
     type: 'MENU',
     type: 'MENU',
     parentId: -1,
     parentId: -1,
     sequence: 2,
     sequence: 2,
@@ -70,6 +74,7 @@ export const adminMenus = [
     id: 5,
     id: 5,
     name: '扫描进度',
     name: '扫描进度',
     url: 'ScanManage',
     url: 'ScanManage',
+    icon: 'icon-scan-progress',
     type: 'MENU',
     type: 'MENU',
     parentId: -1,
     parentId: -1,
     sequence: 2,
     sequence: 2,
@@ -79,6 +84,7 @@ export const adminMenus = [
     id: 6,
     id: 6,
     name: '科目管理',
     name: '科目管理',
     url: 'SubjectManage',
     url: 'SubjectManage',
+    icon: 'icon-subject-manage',
     type: 'MENU',
     type: 'MENU',
     parentId: -1,
     parentId: -1,
     sequence: 2,
     sequence: 2,
@@ -87,6 +93,7 @@ export const adminMenus = [
   {
   {
     id: 7,
     id: 7,
     name: '评卷管理',
     name: '评卷管理',
+    icon: 'icon-mark-manage',
     url: 'mark',
     url: 'mark',
     type: 'MENU',
     type: 'MENU',
     parentId: -1,
     parentId: -1,
@@ -97,6 +104,7 @@ export const adminMenus = [
     id: 8,
     id: 8,
     name: '评卷进度',
     name: '评卷进度',
     url: 'MarkProgress',
     url: 'MarkProgress',
+    icon: '',
     type: 'MENU',
     type: 'MENU',
     parentId: 7,
     parentId: 7,
     sequence: 1,
     sequence: 1,
@@ -105,6 +113,7 @@ export const adminMenus = [
   {
   {
     id: 9,
     id: 9,
     name: '科目评卷管理',
     name: '科目评卷管理',
+    icon: '',
     url: 'MarkManage',
     url: 'MarkManage',
     type: 'MENU',
     type: 'MENU',
     parentId: 7,
     parentId: 7,
@@ -115,6 +124,7 @@ export const adminMenus = [
     id: 10,
     id: 10,
     name: '打回管理',
     name: '打回管理',
     url: 'back',
     url: 'back',
+    icon: 'icon-reject-manage',
     type: 'MENU',
     type: 'MENU',
     parentId: -1,
     parentId: -1,
     sequence: 2,
     sequence: 2,
@@ -124,6 +134,7 @@ export const adminMenus = [
     id: 11,
     id: 11,
     name: '打回卷',
     name: '打回卷',
     url: 'RejectManage',
     url: 'RejectManage',
+    icon: 'icon-reject-manage',
     type: 'MENU',
     type: 'MENU',
     parentId: 10,
     parentId: 10,
     sequence: 1,
     sequence: 1,
@@ -133,6 +144,7 @@ export const adminMenus = [
     id: 111,
     id: 111,
     name: '打回记录',
     name: '打回记录',
     url: 'RejectRecord',
     url: 'RejectRecord',
+    icon: 'icon-back-record',
     type: 'MENU',
     type: 'MENU',
     parentId: 10,
     parentId: 10,
     sequence: 1,
     sequence: 1,
@@ -142,6 +154,7 @@ export const adminMenus = [
     id: 12,
     id: 12,
     name: '打回统计',
     name: '打回统计',
     url: 'RejectStatistics',
     url: 'RejectStatistics',
+    icon: 'icon-reject-statistics',
     type: 'MENU',
     type: 'MENU',
     parentId: 10,
     parentId: 10,
     sequence: 2,
     sequence: 2,
@@ -151,6 +164,7 @@ export const adminMenus = [
     id: 13,
     id: 13,
     name: '问题卷管理',
     name: '问题卷管理',
     url: 'IssuePaper',
     url: 'IssuePaper',
+    icon: 'icon-issue-paper',
     type: 'MENU',
     type: 'MENU',
     parentId: -1,
     parentId: -1,
     sequence: 2,
     sequence: 2,
@@ -160,6 +174,7 @@ export const adminMenus = [
     id: 14,
     id: 14,
     name: '成绩复核',
     name: '成绩复核',
     url: 'ScoreReview',
     url: 'ScoreReview',
+    icon: 'icon-score-review',
     type: 'MENU',
     type: 'MENU',
     parentId: -1,
     parentId: -1,
     sequence: 2,
     sequence: 2,
@@ -169,6 +184,7 @@ export const adminMenus = [
     id: 15,
     id: 15,
     name: '复核进度统计',
     name: '复核进度统计',
     url: 'ScoreReviewStatistics',
     url: 'ScoreReviewStatistics',
+    icon: 'icon-score-review-statistics',
     type: 'MENU',
     type: 'MENU',
     parentId: 14,
     parentId: 14,
     sequence: 2,
     sequence: 2,
@@ -178,6 +194,7 @@ export const adminMenus = [
     id: 16,
     id: 16,
     name: '全卷复核',
     name: '全卷复核',
     url: 'AllReview',
     url: 'AllReview',
+    icon: 'icon-all-review',
     type: 'MENU',
     type: 'MENU',
     parentId: 14,
     parentId: 14,
     sequence: 2,
     sequence: 2,
@@ -187,6 +204,7 @@ export const adminMenus = [
     id: 17,
     id: 17,
     name: '成绩校验',
     name: '成绩校验',
     url: 'ScoreCheck',
     url: 'ScoreCheck',
+    icon: 'icon-score-check',
     type: 'MENU',
     type: 'MENU',
     parentId: 14,
     parentId: 14,
     sequence: 2,
     sequence: 2,
@@ -196,6 +214,7 @@ export const adminMenus = [
     id: 18,
     id: 18,
     name: '成绩查询',
     name: '成绩查询',
     url: 'ScoreQuery',
     url: 'ScoreQuery',
+    icon: 'icon-score-query',
     type: 'MENU',
     type: 'MENU',
     parentId: -1,
     parentId: -1,
     sequence: 2,
     sequence: 2,
@@ -205,6 +224,7 @@ export const adminMenus = [
     id: 19,
     id: 19,
     name: '科目分析',
     name: '科目分析',
     url: 'AnalysisManage',
     url: 'AnalysisManage',
+    icon: 'icon-subject-analysis',
     type: 'MENU',
     type: 'MENU',
     parentId: -1,
     parentId: -1,
     sequence: 2,
     sequence: 2,
@@ -214,6 +234,7 @@ export const adminMenus = [
     id: 20,
     id: 20,
     name: '数据检查',
     name: '数据检查',
     url: 'DataCheck',
     url: 'DataCheck',
+    icon: 'icon-data-check',
     type: 'MENU',
     type: 'MENU',
     parentId: -1,
     parentId: -1,
     sequence: 2,
     sequence: 2,
@@ -223,6 +244,7 @@ export const adminMenus = [
     id: 21,
     id: 21,
     name: '人工确认',
     name: '人工确认',
     url: 'ManualConfirm',
     url: 'ManualConfirm',
+    icon: 'icon-manual-confirm',
     type: 'MENU',
     type: 'MENU',
     parentId: 20,
     parentId: 20,
     sequence: 2,
     sequence: 2,
@@ -232,6 +254,7 @@ export const adminMenus = [
     id: 22,
     id: 22,
     name: '识别结果检查',
     name: '识别结果检查',
     url: 'ResultCheck',
     url: 'ResultCheck',
+    icon: 'icon-result-check',
     type: 'MENU',
     type: 'MENU',
     parentId: 20,
     parentId: 20,
     sequence: 2,
     sequence: 2,
@@ -241,6 +264,7 @@ export const adminMenus = [
     id: 23,
     id: 23,
     name: '图片检查',
     name: '图片检查',
     url: 'ImageCheck',
     url: 'ImageCheck',
+    icon: 'icon-image-check',
     type: 'MENU',
     type: 'MENU',
     parentId: 20,
     parentId: 20,
     sequence: 2,
     sequence: 2,
@@ -250,6 +274,7 @@ export const adminMenus = [
     id: 24,
     id: 24,
     name: '操作日志',
     name: '操作日志',
     url: 'LogManage',
     url: 'LogManage',
+    icon: 'icon-log',
     type: 'MENU',
     type: 'MENU',
     parentId: -1,
     parentId: -1,
     sequence: 2,
     sequence: 2,

+ 2 - 0
src/store/modules/app/types.ts

@@ -4,6 +4,7 @@ export interface UserMenuItem {
   id: number;
   id: number;
   name: string;
   name: string;
   url: string;
   url: string;
+  icon: string;
   type: string;
   type: string;
   parentId: number;
   parentId: number;
   sequence: number;
   sequence: number;
@@ -14,6 +15,7 @@ export type AppMenuItem = {
   id: number;
   id: number;
   name: string;
   name: string;
   url: string;
   url: string;
+  icon: string;
   type: string;
   type: string;
   parentId: number;
   parentId: number;
   sequence: number;
   sequence: number;

+ 23 - 23
src/views/login/ResetInfo.vue

@@ -56,7 +56,7 @@
       </el-form-item>
       </el-form-item>
       <el-form-item>
       <el-form-item>
         <el-button type="primary" style="width: 100%" link @click="goBack"
         <el-button type="primary" style="width: 100%" link @click="goBack"
-          >退</el-button
+          >退</el-button
         >
         >
       </el-form-item>
       </el-form-item>
     </el-form>
     </el-form>
@@ -97,55 +97,55 @@
       {
       {
         required: true,
         required: true,
         message: '请输入姓名',
         message: '请输入姓名',
-        trigger: 'blur',
+        trigger: 'change',
       },
       },
     ],
     ],
     employeeId: [
     employeeId: [
       {
       {
         required: true,
         required: true,
         message: '请输入工号',
         message: '请输入工号',
-        trigger: 'blur',
+        trigger: 'change',
       },
       },
     ],
     ],
     newPassword: [
     newPassword: [
       {
       {
         required: true,
         required: true,
         message: '请输入新密码',
         message: '请输入新密码',
-        trigger: 'blur',
+        trigger: 'change',
       },
       },
       {
       {
         min: 6,
         min: 6,
         message: '密码长度不能少于6位',
         message: '密码长度不能少于6位',
-        trigger: 'blur',
+        trigger: 'change',
       },
       },
     ],
     ],
     confirmPassword: [
     confirmPassword: [
       {
       {
         required: true,
         required: true,
         validator: validateConfirmPassword,
         validator: validateConfirmPassword,
-        trigger: 'blur',
+        trigger: 'change',
       },
       },
     ],
     ],
   };
   };
 
 
   async function submit() {
   async function submit() {
-    const err = await formRef.value?.validate();
-    if (err) {
-      setLoading(true);
-      try {
-        // const res = await updateUserProfile(formData); // 调用API更新用户信息
-        // if (res) {
-        ElMessage.success('资料完善成功,请重新登录');
-        // 清空store信息,跳转到登录页
-        // userStore.resetInfo();
-        // appStore.resetInfo();
-        router.push({ name: 'Login' }); // 假设登录页路由名称为 Login
-        // }
-      } catch (e) {
-        // console.error(e);
-      } finally {
-        setLoading(false);
-      }
+    const valid = await formRef.value?.validate().catch(() => false);
+    if (!valid) return;
+
+    setLoading(true);
+    try {
+      // const res = await updateUserProfile(formData); // 调用API更新用户信息
+      // if (res) {
+      ElMessage.success('资料完善成功,请重新登录');
+      // 清空store信息,跳转到登录页
+      // userStore.resetInfo();
+      // appStore.resetInfo();
+      router.push({ name: 'Login' }); // 假设登录页路由名称为 Login
+      // }
+    } catch (e) {
+      // console.error(e);
+    } finally {
+      setLoading(false);
     }
     }
   }
   }
 
 

+ 2 - 2
src/views/login/ResetPwd.vue

@@ -111,8 +111,8 @@
   /* confirm */
   /* confirm */
   const { loading, setLoading } = useLoading();
   const { loading, setLoading } = useLoading();
   async function confirm() {
   async function confirm() {
-    const err = await formRef.value?.validate().catch(() => {});
-    if (err) return;
+    const valid = await formRef.value?.validate().catch(() => false);
+    if (!valid) return;
 
 
     setLoading(true);
     setLoading(true);
     const datas = {
     const datas = {

+ 5 - 3
src/views/login/SwitchExam.vue

@@ -11,7 +11,7 @@
       size="large"
       size="large"
       label-position="top"
       label-position="top"
     >
     >
-      <el-form-item prop="exam">
+      <el-form-item prop="examId">
         <SelectExam
         <SelectExam
           v-model="formData.examId"
           v-model="formData.examId"
           size="large"
           size="large"
@@ -30,7 +30,7 @@
       </el-form-item>
       </el-form-item>
       <el-form-item>
       <el-form-item>
         <el-button type="primary" style="width: 100%" link @click="handleGoBack"
         <el-button type="primary" style="width: 100%" link @click="handleGoBack"
-          >退</el-button
+          >退</el-button
         >
         >
       </el-form-item>
       </el-form-item>
     </el-form>
     </el-form>
@@ -56,6 +56,7 @@
       {
       {
         required: true,
         required: true,
         message: '请选择考试',
         message: '请选择考试',
+        trigger: 'change',
       },
       },
     ],
     ],
   };
   };
@@ -69,8 +70,9 @@
 
 
   // 确认按钮点击事件
   // 确认按钮点击事件
   const handleSubmit = async () => {
   const handleSubmit = async () => {
-    const valid = await formRef.value?.validate().catch(() => {});
+    const valid = await formRef.value?.validate().catch(() => false);
     if (!valid) return;
     if (!valid) return;
+
     console.log('选择的考试ID:', formData.examId);
     console.log('选择的考试ID:', formData.examId);
     appStore.setInfo({ curExam: selectExam.value });
     appStore.setInfo({ curExam: selectExam.value });
     // 提交成功后的操作,例如跳转到其他页面
     // 提交成功后的操作,例如跳转到其他页面

+ 4 - 4
src/views/login/login.vue

@@ -76,13 +76,13 @@
     account: [
     account: [
       {
       {
         required: true,
         required: true,
-        message: '请输入账号',
+        message: '请输入登录账号',
       },
       },
     ],
     ],
     password: [
     password: [
       {
       {
         required: true,
         required: true,
-        message: '请输入密码',
+        message: '请输入登录密码',
       },
       },
     ],
     ],
   };
   };
@@ -90,8 +90,8 @@
   /* submit */
   /* submit */
   const { loading, setLoading } = useLoading();
   const { loading, setLoading } = useLoading();
   async function submit() {
   async function submit() {
-    const err = await formRef.value?.validate().catch(() => {});
-    if (err) return;
+    const valid = await formRef.value?.validate().catch(() => false);
+    if (!valid) return;
 
 
     setLoading(true);
     setLoading(true);
     const data = await login(formData).catch(() => {});
     const data = await login(formData).catch(() => {});

+ 8 - 2
src/views/reject/RejectManage.vue

@@ -51,7 +51,13 @@
     </el-form>
     </el-form>
   </div>
   </div>
   <div class="part-box">
   <div class="part-box">
-    <el-table class="page-table" :data="dataList" :loading="loading">
+    <el-table
+      class="page-table"
+      :data="dataList"
+      :loading="loading"
+      border
+      stripe
+    >
       <el-table-column type="index" label="序号" width="60" />
       <el-table-column type="index" label="序号" width="60" />
       <el-table-column property="subject" label="科目" min-width="100" />
       <el-table-column property="subject" label="科目" min-width="100" />
       <el-table-column property="groupNo" label="分组序号" width="100" />
       <el-table-column property="groupNo" label="分组序号" width="100" />
@@ -76,7 +82,7 @@
       </el-table-column>
       </el-table-column>
       <el-table-column label="操作" width="100" fixed="right">
       <el-table-column label="操作" width="100" fixed="right">
         <template #default="scope">
         <template #default="scope">
-          <el-button size="small" link @click="onViewDetail(scope.row)">
+          <el-button type="primary" link @click="onViewDetail(scope.row)">
             查看详情
             查看详情
           </el-button>
           </el-button>
         </template>
         </template>