Kaynağa Gözat

bug fix and release

刘洋 2 yıl önce
ebeveyn
işleme
2803171452
38 değiştirilmiş dosya ile 343 ekleme ve 43 silme
  1. 22 1
      src/App.vue
  2. 3 0
      src/api/api-types/user.d.ts
  3. 1 0
      src/api/user.ts
  4. BIN
      src/assets/images/lock_screen.png
  5. 23 0
      src/components/common/LockEntry.vue
  6. 4 0
      src/components/shared/MarkHeader.vue
  7. 75 0
      src/layout/LockScreen.vue
  8. 10 2
      src/layout/main/MainHeader.vue
  9. 1 1
      src/layout/main/MenuItem.vue
  10. 2 2
      src/main.ts
  11. 8 3
      src/modules/admin-user/manage/hooks/useUserManageFilter.ts
  12. 3 3
      src/modules/analysis/group-monitoring-detail/index.vue
  13. 11 3
      src/modules/analysis/monitoring/index.vue
  14. 108 0
      src/modules/analysis/personnel-compare/hooks/useCompareFilter.ts
  15. 23 0
      src/modules/analysis/personnel-compare/index.vue
  16. 1 1
      src/modules/analysis/personnel-statistics/components/SetWorkload.vue
  17. 1 1
      src/modules/analysis/view-marked-detail/index.vue
  18. 1 1
      src/modules/example/ImageModify.vue
  19. 1 1
      src/modules/expert/assess/index.vue
  20. 1 1
      src/modules/expert/expert/index.vue
  21. 1 1
      src/modules/expert/sample/index.vue
  22. 1 1
      src/modules/expert/standard/index.vue
  23. 1 1
      src/modules/expert/training/index.vue
  24. 1 1
      src/modules/marking/arbitration/index.vue
  25. 1 1
      src/modules/marking/assess/index.vue
  26. 1 1
      src/modules/marking/inquiry-result/index.vue
  27. 1 1
      src/modules/marking/mark/index.vue
  28. 1 1
      src/modules/marking/problem/index.vue
  29. 1 1
      src/modules/marking/repeat/index.vue
  30. 1 1
      src/modules/marking/training-record/index.vue
  31. 1 1
      src/modules/marking/view-sample/index.vue
  32. 1 1
      src/modules/monitor/system-check/index.vue
  33. 7 7
      src/modules/monitor/training-monitoring-detail/index.vue
  34. 1 1
      src/modules/quality/self-check-detail/index.vue
  35. 1 1
      src/modules/quality/subjective-check/index.vue
  36. 4 0
      src/plugins/request/index.ts
  37. 13 2
      src/router/analysis.ts
  38. 6 0
      src/store/main.ts

+ 22 - 1
src/App.vue

@@ -3,7 +3,8 @@ import { ElConfigProvider } from 'element-plus'
 import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
 import useMainStore from '@/store/main'
 import useMainLayoutStore from '@/store/layout'
-
+import LockScreen from '@/layout/LockScreen.vue'
+import { onMounted } from 'vue'
 const mainStore = useMainStore()
 const mainLayoutStore = useMainLayoutStore()
 
@@ -18,11 +19,31 @@ window.addEventListener('online', () => {
 window.addEventListener('offline', () => {
   mainStore.setOnline(false)
 })
+function keyBoardScroll(e: any) {
+  let imgWrap = document.querySelector('img-wrap')
+  if (!imgWrap) {
+    return
+  }
+  let word = e.key
+  let t = imgWrap.scrollTop
+  if (word === 'ArrowDown') {
+    t -= 20
+  } else if (word === 'ArrowUp') {
+    t += 20
+  } else {
+    e.returnValue = false
+  }
+  imgWrap.scrollTop = t
+}
+onMounted(() => {
+  document.addEventListener('keydown', keyBoardScroll)
+})
 </script>
 
 <template>
   <el-config-provider :locale="zhCn">
     <RouterView></RouterView>
+    <lock-screen v-if="mainStore.lockScreenStatus"></lock-screen>
   </el-config-provider>
 </template>
 

+ 3 - 0
src/api/api-types/user.d.ts

@@ -227,6 +227,8 @@ export namespace User {
   /** 获取试卷配置信息 */
   type GetUserMarkConfig = BaseDefine<null, Record<string, MarkConfig>>
 
+  type UnlockScreen = BaseDefine<{ password: string }, any>
+
   /** >>> user api end <<< */
   export interface ApiMap {
     userLogin: UserLogin
@@ -251,5 +253,6 @@ export namespace User {
     setUserMarkConfig: SetUserMarkConfig
     /** 获取试卷配置信息 */
     getUserMarkConfig: GetUserMarkConfig
+    unLockScreen: UnlockScreen
   }
 }

+ 1 - 0
src/api/user.ts

@@ -47,6 +47,7 @@ const UserApi: DefineApiModule<User.ApiMap> = {
   setUserMarkConfig: '/api/user/config/set',
   /** 获取试卷配置信息 */
   getUserMarkConfig: '/api/user/config/get',
+  unLockScreen: 'api/user/unlock',
 }
 
 export default UserApi

BIN
src/assets/images/lock_screen.png


+ 23 - 0
src/components/common/LockEntry.vue

@@ -0,0 +1,23 @@
+<template>
+  <!-- <el-tooltip class="lock-entry" effect="dark" content="锁屏" placement="bottom"> -->
+  <div class="lock-box" title="锁屏" @click="lockOpen">
+    <img src="../../assets/images/lock_screen.png" class="lock" title="锁屏" />
+  </div>
+  <!-- </el-tooltip> -->
+</template>
+<script lang="ts" setup name="LockEntry">
+// import { ElTooltip } from 'element-plus'
+import useMainStore from '@/store/main'
+const mainStore = useMainStore()
+const lockOpen = () => {
+  mainStore.setLockScreen(true)
+}
+</script>
+<style lang="scss" scoped>
+.lock-box {
+  cursor: pointer;
+  .lock {
+    height: 22px;
+  }
+}
+</style>

+ 4 - 0
src/components/shared/MarkHeader.vue

@@ -21,6 +21,9 @@
 
     <div class="flex flex-1 items-center mark-header">
       <slot></slot>
+      <span class="data-item">
+        <lock-entry />
+      </span>
       <span class="data-item">
         <message :reply-user-id="props.replyUserId" :paper-path="props.paperPath"></message>
       </span>
@@ -52,6 +55,7 @@ import { logout } from '@/utils/shared'
 import { sessionStorage } from '@/plugins/storage'
 import useFetch from '@/hooks/useFetch'
 import BaseDialog from '@/components/element/BaseDialog.vue'
+import LockEntry from '../common/LockEntry.vue'
 type ButtonType =
   | 'back'
   | 'scale-up'

+ 75 - 0
src/layout/LockScreen.vue

@@ -0,0 +1,75 @@
+<template>
+  <div class="lock-screen flex justify-center items-center">
+    <div class="flex items-center">
+      <img src="../assets/images/lock_screen.png" class="m-r-base" />
+      <el-form ref="ruleFormRef" :model="form" :rules="rules">
+        <el-form-item label="" prop="pwd">
+          <el-input v-model="form.pwd" class="pwd-input" size="large" placeholder="请输入登录密码解锁"></el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" size="large" class="m-l-base" @click="submit">确定</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+  </div>
+</template>
+<script lang="ts" setup name="LockScreen">
+import { ElInput, ElButton, ElForm, ElMessage } from 'element-plus'
+import { reactive, ref } from 'vue'
+import useFetch from '@/hooks/useFetch'
+import useMainStore from '@/store/main'
+const mainStore = useMainStore()
+const ruleFormRef = ref()
+const form = reactive({
+  pwd: '',
+})
+const rules = reactive({
+  pwd: [
+    {
+      required: true,
+      message: '请输入登录密码',
+      trigger: 'blur',
+    },
+  ],
+})
+const submit = async () => {
+  if (!form.pwd) {
+    ElMessage.error('请输入登录密码')
+    return
+  }
+  useFetch('unLockScreen')
+    .fetch({ password: form.pwd })
+    .then((res) => {
+      mainStore.setLockScreen(false)
+    })
+  //   await formEl.validate((valid: any, fields: any) => {
+  //     console.log(valid, fields)
+  //     if (valid) {
+  //       useFetch('unLockScreen')
+  //         .fetch({ password: form.pwd })
+  //         .then((res) => {
+  //           alert(1)
+  //         })
+  //     } else {
+  //       console.log('error submit!', fields)
+  //     }
+  //   })
+}
+</script>
+<style lang="scss" scoped>
+.lock-screen {
+  position: fixed;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  top: 0;
+  z-index: 1000;
+  background: rgba(0, 0, 0, 0.9);
+  .pwd-input {
+    width: 200px;
+  }
+  img {
+    height: 40px;
+  }
+}
+</style>

+ 10 - 2
src/layout/main/MainHeader.vue

@@ -9,14 +9,18 @@
     <div class="flex-1 flex items-center header-info-view">
       <div>当前考试: {{ mainStore?.myUserInfo?.examName }}</div>
       <current-time class="m-l-auto m-r-base"></current-time>
-      <div class="m-r-base">
+      <div class="m-r-base m-l-base">
+        <lock-entry></lock-entry>
+      </div>
+      <div class="m-r-base m-l-base">
         <message
           :reply-user-id="props.replyUserId"
           :message-visible="props.messageVisible"
           :in-layout="inLayout"
         ></message>
       </div>
-      <div class="m-r-base">
+
+      <div class="m-r-base m-l-base">
         <user-info></user-info>
       </div>
       <div class="grid fill-light-gray pointer close-icon" @click="logout()">
@@ -35,6 +39,7 @@ import useMainStore from '@/store/main'
 import CurrentTime from '@/components/shared/CurrentTime.vue'
 import Message from '@/components/shared/message/Message.vue'
 import UserInfo from '@/components/shared/UserInfo.vue'
+import LockEntry from '@/components/common/LockEntry.vue'
 
 const props = defineProps<{
   replyUserId?: number | null
@@ -61,6 +66,9 @@ const mainStore = useMainStore()
   }
   .collapse-icon {
     padding: $ExtraSmallGapSpace;
+    position: relative;
+    bottom: -1px;
+    font-size: 16px;
   }
   .header-info-view {
     color: $RegularFontColor;

+ 1 - 1
src/layout/main/MenuItem.vue

@@ -95,7 +95,7 @@ const props = defineProps<{
 }>()
 
 const menuInfo = computed(() => {
-  console.log('menuInfo:', { ...props.menu, children: props.menu.children || [] })
+  // console.log('menuInfo:', { ...props.menu, children: props.menu.children || [] })
   return { ...props.menu, children: props.menu.children || [] }
 })
 

+ 2 - 2
src/main.ts

@@ -6,7 +6,7 @@ import useECharts from '@/plugins/echarts'
 import bootstrap from '@/bootstrap'
 import { setupDirectives } from '@/directives'
 import 'virtual:svg-icons-register'
-import { ElLoading } from 'element-plus'
+import { ElLoading, ElTooltip } from 'element-plus'
 import 'element-plus/theme-chalk/el-loading.css'
 import '@style/app.scss'
 
@@ -14,7 +14,7 @@ import 'element-plus/theme-chalk/src/message.scss'
 
 const app = createApp(App)
 setupDirectives(app)
-app.use(createPinia()).use(router).use(ElLoading)
+app.use(createPinia()).use(router).use(ElLoading).use(ElTooltip)
 useECharts()
 
 app.mount('#app')

+ 8 - 3
src/modules/admin-user/manage/hooks/useUserManageFilter.ts

@@ -2,11 +2,12 @@ import { ref, reactive, computed, watch } from 'vue'
 import { ROLE_OPTION, StatusMap } from '@/constants/dicts'
 import useForm from '@/hooks/useForm'
 import useOptions, { DataModel } from '@/hooks/useOptions'
-
+import useMainStore from '@/store/main'
 import type { EpFormItem, InstanceForm, EpFormRows } from 'global-type'
 import type { ExtractMultipleApiParams } from '@/api/api'
 
 const useUserManageFilter = () => {
+  const mainStore = useMainStore()
   const { subjectList, mainQuestionList, changeModelValue, dataModel } = useOptions(['subject', 'question'])
 
   const { elFormRef, formRef, defineColumn, _ } = useForm()
@@ -16,7 +17,7 @@ const useUserManageFilter = () => {
   const model = reactive<ExtractMultipleApiParams<'getUserList'>>({
     subjectCode: dataModel.subject || '',
     mainNumber: dataModel.question,
-    enable: true,
+    // enable: true,
     loginName: '',
     name: '',
     role: void 0,
@@ -46,6 +47,7 @@ const useUserManageFilter = () => {
       prop: 'subjectCode',
       slot: {
         placeholder: '选择科目',
+        disabled: mainStore.loginInfo?.role === 'CHIEF',
         options: subjectList.value,
         onChange: changeModelValue('subject'),
         clearable: true,
@@ -57,6 +59,7 @@ const useUserManageFilter = () => {
       prop: 'mainNumber',
       slot: {
         placeholder: '选择大题',
+        disabled: mainStore.loginInfo?.role === 'CHIEF',
         options: mainQuestionList.value,
         onChange: changeModelValue('question'),
         clearable: true,
@@ -68,7 +71,9 @@ const useUserManageFilter = () => {
       prop: 'role',
       slot: {
         placeholder: '用户角色',
-        options: ROLE_OPTION,
+        options: ROLE_OPTION.filter((option) => {
+          return !(mainStore.loginInfo?.role === 'CHIEF' && option.value === 'CHIEF')
+        }),
         clearable: true,
       },
     }),

+ 3 - 3
src/modules/analysis/group-monitoring-detail/index.vue

@@ -6,7 +6,7 @@
       <user-info></user-info>
     </div>
     <div class="flex fill-blank detail-info">
-      <div class="flex p-base detail-info-chart" style="width: 50%">
+      <div class="flex p-base detail-info-chart" style="width: 56%">
         <div class="flex-1">
           <vue-echarts class="full" :option="markerSubjectiveChartsOption"></vue-echarts>
         </div>
@@ -14,7 +14,7 @@
           <vue-echarts class="full" :option="markerObjectiveChartsOption"></vue-echarts>
         </div>
       </div>
-      <div class="flex direction-column p-extra-small" style="width: 50%">
+      <div class="flex direction-column p-extra-small" style="width: 44%">
         <div class="flex items-center justify-between detail-info-table-header m-b-mini">
           <el-button custom-1 size="small" class="detail-info-label">
             <span class="">{{ dataType }}试卷总数:</span>
@@ -50,7 +50,7 @@
     </div>
     <div class="flex-1 p-t-base flex overflow-hidden">
       <div class="flex direction-column flex-1 overflow-hidden radius-base fill-blank relative paper-view">
-        <div class="flex-1 p-extra-small scroll-auto">
+        <div class="flex-1 p-extra-small scroll-auto img-wrap">
           <img :src="current?.filePath" alt="" class="paper-img" />
         </div>
         <span class="preview" @click="onPreview">

+ 11 - 3
src/modules/analysis/monitoring/index.vue

@@ -39,7 +39,7 @@
           border
           stripe
           size="small"
-          :columns="getColumns(activeCard.valueLabel)"
+          :columns="getColumns(activeCard.valueLabel, true)"
           :data="sortableResult[activeCard.dataField]"
         >
         </base-table>
@@ -242,12 +242,14 @@ const getTableProps: (hasAll: boolean) => EpTableProps = (hasAll) => {
 }
 
 const getColumns = (
-  valueLabel: string
+  valueLabel: string,
+  sortable?: boolean
 ): EpTableColumn<ExtractArrayValue<ExtractRecordValue<ExtractApiResponse<'getStatistics'>>>>[] => {
-  return [
+  let columns = [
     {
       label: '老师ID',
       align: 'center',
+      prop: 'markerName',
       formatter(row) {
         return row.markerId === 0 ? (
           '全体'
@@ -260,6 +262,12 @@ const getColumns = (
     },
     { label: valueLabel, prop: 'value', align: 'center' },
   ]
+  return sortable
+    ? columns.map((item: any) => {
+        item.sortable = true
+        return item
+      })
+    : columns
 }
 
 const activeCard = ref<Card>()

+ 108 - 0
src/modules/analysis/personnel-compare/hooks/useCompareFilter.ts

@@ -0,0 +1,108 @@
+import useOptions from '@/hooks/useOptions'
+import { omit } from 'lodash-es'
+import useForm from '@/hooks/useForm'
+
+import { reactive, computed, watch } from 'vue'
+const useCompareFilter = () => {
+  const { subjectList, mainQuestionList, groupListWithAll, changeModelValue, dataModel, onOptionInit } = useOptions([
+    'subject',
+    'question',
+    'group',
+  ])
+  const model = reactive({
+    subjectCode: dataModel.subject || '',
+    questionMainNumber: dataModel.question,
+    markingGroupNumbers: dataModel.group,
+    time: [],
+  })
+  const fetchModel = computed(() => {
+    return Object.assign(omit(model, 'time'), {
+      startTime: model.time?.[0],
+      endTime: model.time?.[1],
+      markingGroupNumbers:
+        typeof model.markingGroupNumbers === 'number' ? [model.markingGroupNumbers] : model.markingGroupNumbers,
+    })
+  })
+  const { formRef, elFormRef, defineColumn, _ } = useForm()
+  watch(dataModel, () => {
+    model.subjectCode = dataModel.subject || ''
+    model.questionMainNumber = dataModel.question
+    model.markingGroupNumbers = dataModel.group
+  })
+
+  const rows = reactive({
+    'row-1': {},
+  })
+  const OneRowSpan4 = defineColumn(_, 'row-1', { span: 4 })
+  const OneRowSpan3 = defineColumn(_, 'row-1', { span: 3 })
+  const OneRowSpan2 = defineColumn(_, 'row-1', { span: 2 })
+
+  const items = computed(() => [
+    OneRowSpan4({
+      labelWidth: '52px',
+      label: '科目',
+      prop: 'subjectCode',
+      slotType: 'select',
+      slot: {
+        options: subjectList.value,
+        onChange: changeModelValue('subject'),
+        disabled: true,
+      },
+    }),
+    OneRowSpan4({
+      prop: 'questionMainNumber',
+      label: '大题',
+      slotType: 'select',
+      slot: {
+        options: mainQuestionList.value,
+        onChange: changeModelValue('question'),
+        disabled: true,
+      },
+    }),
+    OneRowSpan4({
+      prop: 'markingGroupNumbers',
+      label: '小组',
+      slotType: 'select',
+      slot: {
+        options: groupListWithAll.value,
+        onChange: changeModelValue('group'),
+      },
+    }),
+
+    OneRowSpan4({
+      labelWidth: '52px',
+      label: '时间',
+      slotType: 'dateTime',
+      prop: 'time',
+      slot: {
+        type: 'datetimerange',
+        valueFormat: 'YYYYMMDDHHmmss',
+        startPlaceholder: '开始时间',
+        endPlaceholder: '结束时间',
+      },
+    }),
+    OneRowSpan3({
+      prop: 'expand',
+      label: '',
+      slotType: 'checkbox',
+      slot: {
+        options: [{ label: '历史对比' }],
+      },
+    }),
+    OneRowSpan3({
+      labelWidth: '20px',
+      slotName: 'button-group',
+    }),
+  ])
+
+  return {
+    formRef,
+    elFormRef,
+    model,
+    fetchModel,
+    items,
+    rows,
+    onOptionInit,
+  }
+}
+export default useCompareFilter

+ 23 - 0
src/modules/analysis/personnel-compare/index.vue

@@ -0,0 +1,23 @@
+<template>
+  <div class="personnel-compare-view full">
+    <div class="p-l-base p-r-base p-t-medium-base fill-blank filter-form" style="padding-bottom: 10px">
+      <base-form size="small" :label-width="'88px'" :model="model" :items="items">
+        <template #form-item-button-group>
+          <el-button type="primary" @click="onSearch">查询</el-button>
+        </template>
+      </base-form>
+    </div>
+    <div class="flex-1 p-small"></div>
+  </div>
+</template>
+<script setup lang="ts" name="PersonnelCompare">
+import BaseForm from '@/components/element/BaseForm.vue'
+import { ElButton } from 'element-plus'
+import useCompareFilter from './hooks/useCompareFilter'
+const { model, fetchModel, items, onOptionInit } = useCompareFilter()
+
+const onSearch = () => {
+  console.log('search')
+}
+</script>
+<style scoped lang="scss"></style>

+ 1 - 1
src/modules/analysis/personnel-statistics/components/SetWorkload.vue

@@ -19,7 +19,7 @@
         {{ data?.markerName }}
       </template>
       <el-form-item>
-        <span class="tip">*为0时表示不限制任务量</span>
+        <span class="tip" style="color: red">*为0时表示不限制任务量</span>
       </el-form-item>
       <el-form-item>
         <confirm-button @confirm="onConfirm" @cancel="onCancel"></confirm-button>

+ 1 - 1
src/modules/analysis/view-marked-detail/index.vue

@@ -17,7 +17,7 @@
           <svg-icon name="preview"></svg-icon>
         </span>
         <right-button class="next-button" @click="checkNext" />
-        <div class="flex-1 p-base scroll-auto mark-content-paper">
+        <div class="flex-1 p-base scroll-auto mark-content-paper img-wrap">
           <img :src="dataUrl" alt="" class="paper-img" :style="{ 'background-color': frontColor }" />
         </div>
         <scoring-panel-with-confirm

+ 1 - 1
src/modules/example/ImageModify.vue

@@ -3,7 +3,7 @@
     <mark-header :exclude-operations="['delete', 'bookmark']" @click="onOperationClick"> </mark-header>
     <div class="flex-1 overflow-hidden p-base mark-container">
       <div
-        class="p-base radius-base full fill-blank scroll-auto mark-content"
+        class="p-base radius-base full fill-blank scroll-auto mark-content img-wrap"
         :class="{ 'text-center': center }"
         :style="{ 'background-color': backgroundColor }"
       >

+ 1 - 1
src/modules/expert/assess/index.vue

@@ -17,7 +17,7 @@
           <svg-icon name="preview"></svg-icon>
         </span>
         <right-button class="next-button" @click="checkNext" />
-        <div class="flex-1 p-base scroll-auto mark-content-paper">
+        <div class="flex-1 p-base scroll-auto mark-content-paper img-wrap">
           <img :src="dataUrl" alt="" class="paper-img" :style="{ 'background-color': frontColor }" />
         </div>
         <scoring-panel-with-confirm

+ 1 - 1
src/modules/expert/expert/index.vue

@@ -17,7 +17,7 @@
           <svg-icon name="preview"></svg-icon>
         </span>
         <right-button class="next-button" @click="checkNext" />
-        <div class="flex-1 p-base scroll-auto mark-content-paper">
+        <div class="flex-1 p-base scroll-auto mark-content-paper img-wrap">
           <img :src="dataUrl" alt="" class="paper-img" :style="{ 'background-color': frontColor }" />
         </div>
         <scoring-panel-with-confirm

+ 1 - 1
src/modules/expert/sample/index.vue

@@ -17,7 +17,7 @@
           <svg-icon name="preview"></svg-icon>
         </span>
         <right-button class="next-button" @click="checkNext" />
-        <div class="flex-1 p-base scroll-auto mark-content-paper">
+        <div class="flex-1 p-base scroll-auto mark-content-paper img-wrap">
           <img :src="dataUrl" alt="" class="paper-img" :style="{ 'background-color': frontColor }" />
         </div>
         <scoring-panel-with-confirm

+ 1 - 1
src/modules/expert/standard/index.vue

@@ -9,7 +9,7 @@
           <svg-icon name="preview"></svg-icon>
         </span>
         <right-button class="next-button" @click="checkNext" />
-        <div class="flex-1 p-base scroll-auto mark-content-paper">
+        <div class="flex-1 p-base scroll-auto mark-content-paper img-wrap">
           <img :src="dataUrl" alt="" class="paper-img" :style="{ 'background-color': frontColor }" />
         </div>
       </div>

+ 1 - 1
src/modules/expert/training/index.vue

@@ -15,7 +15,7 @@
           <svg-icon name="preview"></svg-icon>
         </span>
         <right-button class="next-button" @click="checkNext" />
-        <div class="flex-1 p-base scroll-auto mark-content-paper">
+        <div class="flex-1 p-base scroll-auto mark-content-paper img-wrap">
           <img :src="dataUrl" alt="" class="paper-img" :style="{ 'background-color': frontColor }" />
         </div>
       </div>

+ 1 - 1
src/modules/marking/arbitration/index.vue

@@ -15,7 +15,7 @@
           <svg-icon name="preview"></svg-icon>
         </span>
         <right-button class="next-button" @click="checkNext" />
-        <div class="flex-1 p-base scroll-auto mark-content-paper">
+        <div class="flex-1 p-base scroll-auto mark-content-paper img-wrap">
           <img :src="dataUrl" alt="" class="paper-img" :style="{ 'background-color': frontColor }" />
         </div>
         <scoring-panel-with-confirm

+ 1 - 1
src/modules/marking/assess/index.vue

@@ -320,7 +320,7 @@ const sendHandler = () => {
         width: 90px;
         text-align: right;
       }
-      .val {
+      .value {
         flex: 1;
       }
     }

+ 1 - 1
src/modules/marking/inquiry-result/index.vue

@@ -17,7 +17,7 @@
           <svg-icon name="preview"></svg-icon>
         </span>
         <right-button class="next-button" @click="checkNext" />
-        <div class="flex-1 p-base scroll-auto mark-content-paper">
+        <div class="flex-1 p-base scroll-auto mark-content-paper img-wrap">
           <img :src="dataUrl" alt="" class="paper-img" :style="{ 'background-color': frontColor }" />
         </div>
         <scoring-panel-with-confirm

+ 1 - 1
src/modules/marking/mark/index.vue

@@ -25,7 +25,7 @@
         <span v-if="currentTask" class="preview" @click="onPreview">
           <svg-icon name="preview"></svg-icon>
         </span>
-        <div v-if="currentTask" :class="{ 'text-center': center }">
+        <div v-if="currentTask" :class="{ 'text-center': center }" class="img-wrap">
           <img :src="dataUrl" alt="" class="paper-img" :style="{ 'background-color': frontColor }" />
         </div>
       </div>

+ 1 - 1
src/modules/marking/problem/index.vue

@@ -28,7 +28,7 @@
           <svg-icon name="preview"></svg-icon>
         </span>
         <right-button class="next-button" @click="checkNext" />
-        <div class="flex-1 p-base scroll-auto mark-content-paper">
+        <div class="flex-1 p-base scroll-auto mark-content-paper img-wrap">
           <img :src="dataUrl" alt="" class="paper-img" :style="{ 'background-color': frontColor }" />
         </div>
         <scoring-panel-with-confirm

+ 1 - 1
src/modules/marking/repeat/index.vue

@@ -25,7 +25,7 @@
           <svg-icon name="preview"></svg-icon>
         </span>
         <right-button class="next-button" @click="checkNext" />
-        <div class="flex-1 p-base scroll-auto mark-content-paper">
+        <div class="flex-1 p-base scroll-auto mark-content-paper img-wrap">
           <img :src="dataUrl" alt="" class="paper-img" :style="{ 'background-color': frontColor }" />
         </div>
         <scoring-panel-with-confirm

+ 1 - 1
src/modules/marking/training-record/index.vue

@@ -12,7 +12,7 @@
         :style="{ 'background-color': backgroundColor }"
       >
         <right-button class="next-button" @click="checkNext" />
-        <div class="flex-1 p-base scroll-auto mark-content-paper">
+        <div class="flex-1 p-base scroll-auto mark-content-paper img-wrap">
           <img :src="dataUrl" alt="" class="paper-img" :style="{ 'background-color': frontColor }" />
         </div>
       </div>

+ 1 - 1
src/modules/marking/view-sample/index.vue

@@ -12,7 +12,7 @@
         :style="{ 'background-color': backgroundColor }"
       >
         <right-button class="next-button" @click="checkNext" />
-        <div class="flex-1 p-base scroll-auto mark-content-paper">
+        <div class="flex-1 p-base scroll-auto mark-content-paper img-wrap">
           <img :src="dataUrl" alt="" class="paper-img" :style="{ 'background-color': frontColor }" />
         </div>
       </div>

+ 1 - 1
src/modules/monitor/system-check/index.vue

@@ -20,7 +20,7 @@
           <svg-icon name="preview"></svg-icon>
         </span>
         <right-button class="next-button" @click="checkNext" />
-        <div class="flex-1 p-base scroll-auto mark-content-paper">
+        <div class="flex-1 p-base scroll-auto mark-content-paper img-wrap">
           <img :src="dataUrl" alt="" class="paper-img" :style="{ 'background-color': frontColor }" />
         </div>
       </div>

+ 7 - 7
src/modules/monitor/training-monitoring-detail/index.vue

@@ -16,7 +16,7 @@
           <svg-icon name="preview"></svg-icon>
         </span>
         <right-button class="next-button" @click="checkNext" />
-        <div class="flex-1 p-base scroll-auto mark-content-paper">
+        <div class="flex-1 p-base scroll-auto mark-content-paper img-wrap">
           <img :src="dataUrl" alt="" class="paper-img" :style="{ 'background-color': frontColor }" />
         </div>
       </div>
@@ -123,13 +123,13 @@ const onOperationClick: OperationClick = ({ type, value }) => {
 }
 
 const columns: EpTableColumn<RowType>[] = [
-  { label: '密号', prop: 'secretNumber' },
-  { label: '标准分', prop: 'score' },
-  { label: '评卷给分', prop: 'markScore' },
+  { label: '密号', prop: 'secretNumber', width: 100, fixed: 'left' },
+  { label: '标准分', prop: 'score', width: 60 },
+  { label: '评卷给分', prop: 'markScore', width: 75 },
   // { label: '分组', prop: 'group' },
-  { label: '分组', prop: 'groupName' },
-  { label: '评卷员', prop: 'markerName' },
-  { label: '评卷时间', prop: 'markTime' },
+  { label: '分组', prop: 'groupName', width: 60 },
+  { label: '评卷员', prop: 'markerName', minWidth: 60 },
+  { label: '评卷时间', prop: 'markTime', width: 150 },
 ]
 
 const { fetch: getTrainingMonitorDetail, result: trainingMonitorDetail } = useFetch('getTrainingMonitorDetail')

+ 1 - 1
src/modules/quality/self-check-detail/index.vue

@@ -18,7 +18,7 @@
           <svg-icon name="preview"></svg-icon>
         </span>
         <right-button class="next-button" @click="checkNext" />
-        <div class="flex-1 p-base scroll-auto mark-content-paper">
+        <div class="flex-1 p-base scroll-auto mark-content-paper img-wrap">
           <img :src="dataUrl" alt="" class="paper-img" :style="{ 'background-color': frontColor }" />
         </div>
       </div>

+ 1 - 1
src/modules/quality/subjective-check/index.vue

@@ -18,7 +18,7 @@
           <svg-icon name="preview"></svg-icon>
         </span>
         <right-button class="next-button" @click="checkNext" />
-        <div class="flex-1 p-base scroll-auto mark-content-paper">
+        <div class="flex-1 p-base scroll-auto mark-content-paper img-wrap">
           <img :src="dataUrl" alt="" class="paper-img" :style="{ 'background-color': frontColor }" />
         </div>
         <scoring-panel-with-confirm

+ 4 - 0
src/plugins/request/index.ts

@@ -65,6 +65,10 @@ request.interceptors.response.use(
   async (error: AxiosError<any>) => {
     console.log('resp error:', error)
     if (!error.config?.noToast && error?.code !== 'ERR_CANCELED') {
+      if (error.message === 'Network Error') {
+        toastError('网络错误,服务器连接异常')
+        return
+      }
       if (error.isAxiosError) {
         if (
           error.response &&

+ 13 - 2
src/router/analysis.ts

@@ -48,6 +48,17 @@ const routes: RouteRecordRaw[] = [
           sort: 3,
         },
       },
+      {
+        name: 'AnalysisPersonnelCompare',
+        path: 'personnel-compare',
+        component: () => import('@/modules/analysis/personnel-compare/index.vue'),
+        meta: {
+          label: '人员对比',
+          menu: true,
+          menuId: 'analysis-personnel_compare',
+          sort: 4,
+        },
+      },
       {
         name: 'AnalysisMarkingProgress',
         path: 'marking-progress',
@@ -56,7 +67,7 @@ const routes: RouteRecordRaw[] = [
           label: '评卷进度统计',
           menu: true,
           menuId: 'analysis-marking_progress',
-          sort: 4,
+          sort: 5,
         },
       },
       {
@@ -67,7 +78,7 @@ const routes: RouteRecordRaw[] = [
           label: '小组监控',
           menu: true,
           menuId: 'analysis-group_monitoring',
-          sort: 5,
+          sort: 6,
         },
       },
     ],

+ 6 - 0
src/store/main.ts

@@ -13,6 +13,7 @@ interface MainStoreState {
   userMarkConfig: ExtractApiResponse<'getUserMarkConfig'>
   newMsgs: { newCount: number; messages: any[] }
   online: boolean
+  lockScreenStatus: boolean
 }
 
 interface MainStoreActions {
@@ -21,6 +22,7 @@ interface MainStoreActions {
   setUserMarkConfig: (config: ExtractApiResponse<'getUserMarkConfig'>) => void
   setNewMsgs: (msgData: { newCount: number; messages: any[] }) => void
   setOnline: (bool: boolean) => void
+  setLockScreen: (bool: boolean) => void
 }
 
 const useMainStore = defineStore<'main', MainStoreState, Record<string, any>, MainStoreActions>('main', {
@@ -42,9 +44,13 @@ const useMainStore = defineStore<'main', MainStoreState, Record<string, any>, Ma
       userMarkConfig: {},
       newMsgs: { newCount: 0, messages: [] },
       online: true,
+      lockScreenStatus: false,
     }
   },
   actions: {
+    setLockScreen(bool: boolean) {
+      this.lockScreenStatus = !!bool
+    },
     setOnline(bool: boolean) {
       this.online = !!bool
     },