Browse Source

很多地方增加了科目选择下拉框,以及其他需求开发

刘洋 2 năm trước cách đây
mục cha
commit
aefad7afb8
29 tập tin đã thay đổi với 485 bổ sung113 xóa
  1. 10 3
      src/api/api-types/expert.d.ts
  2. 5 3
      src/api/api-types/marking.d.ts
  3. BIN
      src/assets/images/tab_lxr.png
  4. BIN
      src/assets/images/tab_lxr_active.png
  5. BIN
      src/assets/images/tab_xx.png
  6. BIN
      src/assets/images/tab_xx_active.png
  7. 4 1
      src/components/shared/StandardDialog.vue
  8. 2 1
      src/components/shared/message/Message.vue
  9. 44 14
      src/components/shared/message/MessageList.vue
  10. 21 8
      src/components/shared/message/MessageSend.vue
  11. 36 17
      src/components/shared/message/MessageWindow.vue
  12. 49 2
      src/hooks/useOptions.ts
  13. 27 15
      src/modules/analysis/marking-progress/components/TotalProgress.vue
  14. 25 5
      src/modules/analysis/personnel-statistics/hooks/useStatisticsFilter.ts
  15. 26 3
      src/modules/analysis/personnel-statistics/index.vue
  16. 20 3
      src/modules/expert/assess/index.vue
  17. 25 4
      src/modules/expert/expert/index.vue
  18. 19 2
      src/modules/expert/sample/index.vue
  19. 20 3
      src/modules/expert/standard/index.vue
  20. 20 3
      src/modules/expert/training/index.vue
  21. 20 3
      src/modules/marking/arbitration/index.vue
  22. 3 2
      src/modules/marking/marking-standard/index.vue
  23. 20 3
      src/modules/marking/problem/index.vue
  24. 20 3
      src/modules/marking/repeat/index.vue
  25. 20 3
      src/modules/marking/similar/index.vue
  26. 20 3
      src/modules/monitor/system-check/index.vue
  27. 1 1
      src/modules/monitor/training-monitoring-detail/index.vue
  28. 18 5
      src/modules/quality/ending-check/components/EndCheck.vue
  29. 10 3
      src/modules/quality/subjective-check/index.vue

+ 10 - 3
src/api/api-types/expert.d.ts

@@ -16,7 +16,7 @@ export namespace Expert {
     type: string
   }
   type GetSampleList = BaseDefine<
-    MultipleQuery<{ mainNumber?: number | string; paperType: 'SAMPLE_A' | 'SAMPLE_B' }>,
+    MultipleQuery<{ mainNumber?: number | string; paperType: 'SAMPLE_A' | 'SAMPLE_B'; subjectCode?: string }>,
     MultipleResult<SamplePaperListItem>
   >
 
@@ -32,7 +32,10 @@ export namespace Expert {
     secretNumber: number
   }
 
-  type GetRfSampleList = BaseDefine<MultipleQuery<{ mainNumber?: number | string }>, MultipleResult<RfSampleListItem>>
+  type GetRfSampleList = BaseDefine<
+    MultipleQuery<{ mainNumber?: number | string; subjectCode?: string }>,
+    MultipleResult<RfSampleListItem>
+  >
 
   type UpdateMarkScore = BaseDefine<{ id?: number; scores: number[] }>
 
@@ -54,6 +57,7 @@ export namespace Expert {
       dispensed: boolean | ''
       scoreStart?: number | string
       scoreEnd?: number | string
+      subjectCode?: string
     }>,
     MultipleResult<StandardListItem>
   >
@@ -76,6 +80,7 @@ export namespace Expert {
     MultipleQuery<{
       mainNumber?: number | string
       forceGroupNumber?: number
+      subjectCode?: string
     }>,
     MultipleResult<ExpertAssessListItem>
   >
@@ -99,7 +104,9 @@ export namespace Expert {
       mainNumber?: number | string
       forceGroupNumber?: number
       paperType: ExpertPickType
-      role: Exclude<ROLE, 'ADMIN'>
+      // role: Exclude<ROLE, 'ADMIN'>
+      role: string
+      subjectCode?: string
     }>,
     MultipleResult<ExpertPickListItem>
   >

+ 5 - 3
src/api/api-types/marking.d.ts

@@ -66,7 +66,7 @@ export namespace Marking {
   }>
 
   type GetMarkingStandard = BaseDefine<
-    null,
+    any,
     { examId: number; mainNumber: number | string; subjectCode: string; url: string }
   >
 
@@ -142,6 +142,7 @@ export namespace Marking {
     mainNumber?: number | string
     problemType: ProblemType | ''
     status: '' | 'INITIAL' | 'PROCESSED'
+    subjectCode?: string
   }
 
   interface ProblemListItem {
@@ -218,7 +219,7 @@ export namespace Marking {
   }
 
   type GetArbitrationList = BaseDefine<
-    MultipleQuery<{ mainNumber?: number | string; status: ArbitrationStatus | '' }>,
+    MultipleQuery<{ mainNumber?: number | string; status: ArbitrationStatus | ''; subjectCode?: string }>,
     MultipleResult<ArbitrationListItem>
   >
 
@@ -241,7 +242,7 @@ export namespace Marking {
   }
 
   type GetReMarkPaperList = BaseDefine<
-    MultipleQuery<{ mainNumber?: number | string; confirm: boolean }>,
+    MultipleQuery<{ mainNumber?: number | string; confirm: boolean; subjectCode?: string }>,
     MultipleResult<ReMarkPaperListItem>
   >
 
@@ -296,6 +297,7 @@ export namespace Marking {
     MultipleQuery<{
       mainNumber?: number | string
       status: 'INITIAL' | 'NOT_SAME' | 'SAME' | '' | null
+      subjectCode?: string
     }>,
     MultipleResult<SamePaperListItem>
   >

BIN
src/assets/images/tab_lxr.png


BIN
src/assets/images/tab_lxr_active.png


BIN
src/assets/images/tab_xx.png


BIN
src/assets/images/tab_xx_active.png


+ 4 - 1
src/components/shared/StandardDialog.vue

@@ -19,6 +19,9 @@ import { ref, computed } from 'vue'
 import { Close } from '@element-plus/icons-vue'
 import { ElIcon } from 'element-plus'
 import useFetch from '@/hooks/useFetch'
+import useMainStore from '@/store/main'
+
+const mainStore = useMainStore()
 
 const props = defineProps<{
   modelValue: boolean
@@ -30,7 +33,7 @@ const closeDialog = () => {
 }
 
 const { fetch: fetchStandard, result: standardRes } = useFetch('getMarkingStandard')
-fetchStandard()
+fetchStandard({ subjectCode: mainStore?.myUserInfo?.subjectCode, mainNumber: mainStore?.myUserInfo?.mainNumber })
 const iframeSrc = computed(() => {
   return standardRes.value?.url
     ? standardRes.value?.url + '#view=FitH&scrollbar=0&toolbar=0&statusbar=0&messages=0&navpanes=0'

+ 2 - 1
src/components/shared/message/Message.vue

@@ -223,13 +223,14 @@ bus.on('fast-send-msg', () => {
     width: 24px;
     height: 18px;
     line-height: 18px;
-    right: -2px;
+    right: -11px;
     top: -10px;
     text-align: center;
     color: $color--white;
     font-size: 10px;
     border-radius: 4px;
     background-color: $DangerColor;
+    z-index: 1;
   }
 }
 .message-popover-content {

+ 44 - 14
src/components/shared/message/MessageList.vue

@@ -36,18 +36,20 @@
             <el-icon><close /></el-icon>
           </div>
         </div>
-        <div ref="historyMsgWrap" class="flex-1 overflow-hidden p-base scroll-auto">
+        <div class="flex-1 p-base">
           <!-- <pre
             class="full-h radius-base p-extra-base scroll-y-auto message-info-content"
             @click="onContentClick"
             v-html="currentMessage?.content"
           ></pre> -->
-          <div v-for="(message, index) in history" :key="index" class="m-b-base history-box">
-            <div class="m-b-mini message-header">
-              <span class="m-r-base user-name">{{ message.sendUserName }}</span>
-              <span class="message-time">{{ message.sendTime }}</span>
+          <div ref="historyMsgWrap" class="history-box scroll-auto">
+            <div v-for="(message, index) in historyReverse" :key="index" class="m-b-base">
+              <div class="m-b-mini message-header">
+                <span class="m-r-base user-name">{{ message.sendUserName }}</span>
+                <span class="message-time">{{ message.sendTime }}</span>
+              </div>
+              <div class="history-message-info-content" @click="onContentClick" v-html="message.content"></div>
             </div>
-            <div class="history-message-info-content" @click="onContentClick" v-html="message.content"></div>
           </div>
         </div>
         <div class="p-base" style="padding-top: 0">
@@ -84,7 +86,7 @@
 
 <script setup lang="ts" name="MessageList">
 /** 消息列表*/
-import { ref, watch, onUnmounted, computed, nextTick } from 'vue'
+import { ref, watch, onUnmounted, computed, nextTick, unref } from 'vue'
 import { ElButton, ElIcon, ElMessage } from 'element-plus'
 import { Close } from '@element-plus/icons-vue'
 import useFetch from '@/hooks/useFetch'
@@ -100,6 +102,9 @@ const historyMsgWrap = ref()
 const mainStore = useMainStore()
 const emits = defineEmits(['close', 'change-type', 'reply'])
 const { fetch: getMessageHistory, result: history, loading } = useFetch('getMessageHistory')
+const historyReverse = computed(() => {
+  return ((history.value as any) || []).reverse()
+})
 /** 图片预览 */
 const previewModalVisible = ref<boolean>(false)
 /** 消息内容 */
@@ -112,12 +117,21 @@ const showHistory = ref<boolean>(false)
 const { fetch: getMessageList, result: messageList } = useFetch('getMessageList')
 
 const currentMessage = ref<MessageType>()
-watch(history, () => {
-  nextTick(() => {
-    console.log(historyMsgWrap.value.scrollHeight)
-  })
+function scrollToBottom() {
+  let scrollHeight = historyMsgWrap.value.scrollHeight
+  if (scrollHeight > 200) {
+    historyMsgWrap.value.scrollTop = scrollHeight - 200 + 100
+  }
+}
+watch(historyReverse, (newVal: any, oldVal: any) => {
+  let oldV = unref(oldVal)
+  if ((oldV || []).length == 0) {
+    nextTick(() => {
+      scrollToBottom()
+    })
+  }
 })
-watch(currentMessage, () => {
+watch(currentMessage, (newVal: any, oldVal: any) => {
   if (currentMessage.value) {
     useFetch('handleReadMessage')
       .fetch({ id: currentMessage.value.id })
@@ -127,7 +141,13 @@ watch(currentMessage, () => {
           currentMessage.value.unReadCount = 0
         }
         if (currentMessage.value?.sendUserId) {
-          getMessageHistory({ sendUserId: currentMessage.value.sendUserId })
+          getMessageHistory({ sendUserId: currentMessage.value.sendUserId }).then(() => {
+            let newV = unref(newVal)
+            let oldV = unref(oldVal)
+            if (newV.id != oldV.id) {
+              setTimeout(scrollToBottom, 1)
+            }
+          })
         }
       })
   }
@@ -149,6 +169,11 @@ const onSendMessage = async () => {
     })
     ElMessage.success('发送成功')
     messageContent.value = ''
+    if (currentMessage.value?.sendUserId) {
+      getMessageHistory({ sendUserId: currentMessage.value.sendUserId }).then(() => {
+        setTimeout(scrollToBottom, 1)
+      })
+    }
     // emit('close')
   } catch (error) {
     console.error(error)
@@ -213,12 +238,17 @@ onUnmounted(() => {
 .message-list-modal {
   width: 750px;
   background-color: transparent;
-
+  border-top-left-radius: 0;
+  border-bottom-left-radius: 0;
   .message-info-container {
     // width: 600px;
     width: calc(100% - 260px);
     position: relative;
     .history-box {
+      height: 200px;
+      border: 1px solid #eee;
+      border-radius: 4px;
+      padding: 15px;
       .message-header {
         color: $color--primary;
       }

+ 21 - 8
src/components/shared/message/MessageSend.vue

@@ -49,12 +49,13 @@
             <div class="limit-tip">{{ messageContent.length }} / 2000</div>
           </div>
         </div>
-        <div class="p-base flex items-center justify-end">
-          <el-button v-show="showSendPaper" size="small" plain @click="sendCurrentPaper">发送当前试卷</el-button>
+        <div class="p-base flex items-center justify-between">
+          <el-button v-if="showSendPaper" size="small" plain @click="sendCurrentPaper">发送当前试卷</el-button>
+          <span v-else></span>
           <el-button size="small" type="primary" :disabled="!allowSend" :loading="loading" @click="onSendMessage">
             发送
           </el-button>
-          <el-button v-if="checkedUsers.length == 1" size="small" plain @click="toggleHistory">历史消息</el-button>
+          <!-- <el-button v-if="checkedUsers.length == 1" size="small" plain @click="toggleHistory">历史消息</el-button> -->
         </div>
       </div>
       <message-history
@@ -94,12 +95,20 @@ const props = defineProps<{
   replyUserName?: string | null
 }>()
 const customNodeClass = (data: any, node: any) => {
-  if (data.online === true) {
-    return 'is-online'
-  } else if (data.online === false) {
-    return 'is-offline'
+  // if (data.online === true) {
+  //   return 'is-online'
+  // } else if (data.online === false) {
+  //   return 'is-offline'
+  // }
+  if (data.data) {
+    if (data.data.online) {
+      return 'is-online'
+    } else {
+      return 'is-offline'
+    }
+  } else {
+    return null
   }
-  return null
 }
 /** cleat warning */
 const emit = defineEmits(['close', 'change-type', 'reply'])
@@ -296,6 +305,8 @@ const toggleHistory = () => {
 .message-list-modal {
   background-color: transparent;
   width: 750px;
+  border-top-left-radius: 0;
+  border-bottom-left-radius: 0;
   .tree-box {
     width: 260px;
     height: 446px;
@@ -350,10 +361,12 @@ const toggleHistory = () => {
         .send-user {
           font-size: $SmallFont;
           color: $RegularFontColor;
+          height: 38px;
           .user-name {
             min-width: 320px;
             padding: 10px 12px;
             border: $OnePixelLine;
+            height: 100%;
             .checked-users {
               // overflow: hidden;
               // white-space: nowrap;

+ 36 - 17
src/components/shared/message/MessageWindow.vue

@@ -1,8 +1,18 @@
 <template>
   <base-dialog v-model="visible" unless canoverflow :footer="false" class="message-dialog" destroy-on-close>
     <div class="left-tabs-box">
-      <div class="left-tab-item" :class="{ active: modalType === 'view' }" @click="modalType = 'view'">消息</div>
-      <div class="left-tab-item" :class="{ active: modalType === 'send' }" @click="modalType = 'send'">联系人</div>
+      <!-- <div class="left-tab-item" :class="{ active: modalType === 'view' }" @click="modalType = 'view'">消息</div>
+      <div class="left-tab-item" :class="{ active: modalType === 'send' }" @click="modalType = 'send'">联系人</div> -->
+      <div class="left-tab-item" :class="{ active: modalType === 'view' }" @click="modalType = 'view'">
+        <img v-if="modalType === 'view'" src="../../../assets/images/tab_xx_active.png" />
+        <img v-else src="../../../assets/images/tab_xx.png" />
+        <p>消息</p>
+      </div>
+      <div class="left-tab-item" :class="{ active: modalType === 'send' }" @click="modalType = 'send'">
+        <img v-if="modalType === 'send'" src="../../../assets/images/tab_lxr_active.png" />
+        <img v-else src="../../../assets/images/tab_lxr.png" />
+        <p>联系人</p>
+      </div>
     </div>
     <component
       :is="MessageWindowContent"
@@ -90,25 +100,34 @@ const leftMsgClick = (msg: any) => {
   position: relative;
   .left-tabs-box {
     position: absolute;
-    width: 50px;
-    height: 160px;
-    left: -50px;
-    top: 6px;
+    width: 60px;
+    height: 100%;
+    left: -60px;
+    top: 0;
+    background-color: #fff;
+    padding: 10px 5px;
+    border-top-left-radius: 6px;
+    border-bottom-left-radius: 6px;
     .left-tab-item {
-      background-color: #fafafa;
-      height: 50%;
-      border-top-left-radius: 6px;
-      border-bottom-left-radius: 6px;
-      padding: 0 15px;
-      display: flex;
-      justify-content: center;
-      align-items: center;
+      width: 50px;
+      height: 50px;
+      border-radius: 6px;
       text-align: center;
-      font-size: 14px;
       cursor: pointer;
+      margin-top: 10px;
+      color: #666;
+      font-size: 8px;
+      padding-top: 8px;
+      &:hover {
+        background-color: #f3f3f3;
+      }
+      img {
+        width: 16px;
+        margin-bottom: 1px;
+      }
       &.active {
-        background-color: var(--el-color-primary-light-3);
-        color: #fff;
+        background-color: #f3f3f3;
+        color: #0091ff;
       }
     }
   }

+ 49 - 2
src/hooks/useOptions.ts

@@ -27,6 +27,9 @@ const useOptions = (
   subjectEnable: boolean | null = true
 ) => {
   const mainStore = useMainStore()
+  const isChooseAllOptionMap = reactive<any>({
+    question: false,
+  })
 
   const userInfo = computed(() => {
     return mainStore?.myUserInfo
@@ -40,6 +43,14 @@ const useOptions = (
     return userInfo?.value?.role === 'CHIEF'
   })
 
+  const isExpert = computed(() => {
+    return userInfo?.value?.role === 'EXPERT'
+  })
+
+  const isLeader = computed(() => {
+    return userInfo?.value?.role === 'SECTION_LEADER'
+  })
+
   const dataModel = reactive<DataModel>(unref(initModel) || {})
 
   if (isRef(initModel)) {
@@ -73,6 +84,14 @@ const useOptions = (
   } = useFetch('getQuestionGroupList')
 
   const subjectList = computed(() => {
+    // const arr: any =
+    //   subjectResult.value?.result?.map((subject) => {
+    //     return { ...subject, value: subject.code, label: `${subject.code}-${subject.name}` }
+    //   }) || []
+    // if (isExpert.value) {
+    //   arr.unshift({ label: '全部', value: void 0 })
+    // }
+    // return arr
     return (
       subjectResult.value?.result?.map((subject) => {
         return { ...subject, value: subject.code, label: `${subject.code}-${subject.name}` }
@@ -81,6 +100,19 @@ const useOptions = (
   })
 
   const mainQuestionList = computed<any[]>(() => {
+    // const arr =
+    //   mainQuestionListResult.value?.map((v: any) => {
+    //     return {
+    //       ...v,
+    //       label: `${v.mainNumber}-${v.title}`,
+    //       value: v.mainNumber,
+    //     }
+    //   }) || []
+    // if (isExpert.value || isLeader.value) {
+    //   arr.unshift({ label: '全部', value: void 0 })
+    // }
+    // return arr
+
     return (
       mainQuestionListResult.value?.map((v: any) => {
         return {
@@ -104,7 +136,7 @@ const useOptions = (
   })
 
   const groupListWithAll = computed(() => {
-    return groupList.value?.length && (isAdmin.value || isChief.value)
+    return groupList.value?.length && (isAdmin.value || isChief.value || isExpert.value || isLeader.value)
       ? [{ label: '全部', value: void 0 } as unknown as Group].concat(groupList.value)
       : groupList.value
   })
@@ -122,6 +154,10 @@ const useOptions = (
       if (!dataModel.group && userInfo.value?.markingGroupNumber && !(isAdmin.value || isChief.value)) {
         dataModel.group = userInfo.value.markingGroupNumber
       }
+      // if (isExpert.value || isLeader.value) {
+      //   dataModel.question = void 0
+      //   isChooseAllOptionMap.question = true
+      // }
     },
     { immediate: true }
   )
@@ -145,6 +181,7 @@ const useOptions = (
     // [() => dataModel.question, () => dataModel.question],
     [() => dataModel.question],
     () => {
+      isChooseAllOptionMap.question = !dataModel.question
       if (types.includes('group') && dataModel.subject && dataModel.question) {
         // resetGroupList()
         // changeModelValue('group')(void 0)
@@ -189,7 +226,15 @@ const useOptions = (
   const destroyInit = watch(
     [dataModel, isAdmin, isChief],
     () => {
-      if (types.every((t) => dataModel[t] || (t === 'group' && (isAdmin.value || isChief.value)))) {
+      if (
+        types.every(
+          // (t) =>
+          //   dataModel[t] ||
+          //   (!dataModel[t] && isChooseAllOptionMap[t]) ||
+          //   (t === 'group' && (isAdmin.value || isChief.value))
+          (t) => dataModel[t] || (t === 'group' && (isAdmin.value || isChief.value))
+        )
+      ) {
         nextTick(() => {
           initCallbacks.forEach((cb) => cb(dataModel))
           initFinish.value = true
@@ -224,6 +269,8 @@ const useOptions = (
     onOptionInit,
     changeModelValue,
     forceRefresh,
+    isExpert,
+    isLeader,
   }
 }
 

+ 27 - 15
src/modules/analysis/marking-progress/components/TotalProgress.vue

@@ -1,6 +1,10 @@
 <template>
   <div class="p-base p-b-base m-b-base radius-base fill-blank total-progress-box">
-    <base-form size="small" :model="model" :items="items"></base-form>
+    <base-form size="small" :model="model" :items="items">
+      <template #form-item-button>
+        <el-button class="m-l-base" :loading="loading" type="primary" @click="onSearch">查询</el-button>
+      </template>
+    </base-form>
     <div class="total-progress-info">
       <div class="p-t-base p-b-extra-small table-title">整体进度</div>
 
@@ -51,6 +55,7 @@
 <script setup lang="ts" name="TotalProgress">
 /** 评卷进度 */
 import { reactive, watch, computed, ref, nextTick } from 'vue'
+import { ElButton } from 'element-plus'
 import VueECharts from 'vue-echarts'
 import { minus } from '@/utils/common'
 import BaseForm from '@/components/element/BaseForm.vue'
@@ -71,18 +76,18 @@ provideInitOption({ renderer: 'svg' })
 const canLoadTopChart = ref(false)
 // const { subjectList, dataModel, changeModelValue } = useOptions(['subject'])
 
-const { subjectList, mainQuestionList, changeModelValue, dataModel } = useOptions(['subject', 'question'])
+const { subjectList, mainQuestionList, changeModelValue, dataModel, onOptionInit } = useOptions(['subject', 'question'])
 
 const model = reactive<any>({
   subjectCode: dataModel.subject || '',
   //todo
-  mainNumber: null,
+  questionMainNumber: null,
 })
 watch(
   dataModel,
   () => {
     model.subjectCode = dataModel.subject || ''
-    model.mainNumber = dataModel.question || ''
+    model.questionMainNumber = dataModel.question
   },
   { deep: true, immediate: true }
 )
@@ -101,16 +106,20 @@ const items = computed<EpFormItem[]>(() => [
     labelWidth: '52px',
     slotType: 'select',
     label: '大题',
-    prop: 'mainNumber',
+    prop: 'questionMainNumber',
     slot: {
       placeholder: '选择大题',
       options: mainQuestionList.value,
       onChange: changeModelValue('question'),
-      disabled: true,
     },
     rowKey: 'row-1',
     colProp: { span: 5 },
   },
+  {
+    rowKey: 'row-1',
+    slotName: 'button',
+    colProp: { span: 5 },
+  },
 ])
 
 /** 整体进度 */
@@ -171,7 +180,7 @@ const totalColumns: EpTableColumn<TotalProgress>[] = [
   },
 ]
 
-const { fetch: getMarkProgress, result: markProgressResult } = useFetch('getMarkProgress')
+const { fetch: getMarkProgress, result: markProgressResult, loading } = useFetch('getMarkProgress')
 
 /** 将汇总行放到数组最后 */
 const totalProgressData = computed(() => {
@@ -197,14 +206,17 @@ watch(
   }
 )
 
-watch(
-  () => model.subjectCode,
-  (v) => {
-    v && getMarkProgress(model)
-  },
-  { immediate: true }
-)
-
+// watch(
+//   [() => model.subjectCode, () => model.questionMainNumber],
+//   (v) => {
+//     v && getMarkProgress(model)
+//   },
+//   { immediate: true }
+// )
+function onSearch() {
+  getMarkProgress(model)
+}
+onOptionInit(onSearch)
 const currentMainQuestion = ref<TotalProgress>()
 
 const currentMainName = computed(() => {

+ 25 - 5
src/modules/analysis/personnel-statistics/hooks/useStatisticsFilter.ts

@@ -26,13 +26,15 @@ const useStatisticsFilter = () => {
     'group',
   ])
   const curDayRange = getCurDayRange()
-  const model = reactive<FormMode>({
+  const model = reactive<any>({
     subjectCode: dataModel.subject || '',
     questionMainNumber: dataModel.question,
     markingGroupNumbers: dataModel.group,
     time: [curDayRange[0], curDayRange[1]],
     hasJudge: ['true'],
     expand: [],
+    markerId: '',
+    online: '',
   })
   const { fetch: getMarkerList, result: markerList } = useFetch('getMarkerList')
   watch(
@@ -44,6 +46,7 @@ const useStatisticsFilter = () => {
           mainNumber: model.questionMainNumber,
           markingGroupNumber: model.markingGroupNumbers,
         })
+        model.markerId = ''
       }
     },
     {
@@ -82,6 +85,7 @@ const useStatisticsFilter = () => {
   const TwoRowSpan5 = defineColumn(_, 'row-2', { span: 5 })
   const TwoRowSpan8 = defineColumn(_, 'row-2', { span: 8 })
   const TwoRowSpan3 = defineColumn(_, 'row-2', { span: 3 })
+  const TwoRowSpan4 = defineColumn(_, 'row-2', { span: 4 })
 
   const items = computed<EpFormItem[]>(() => [
     OneRowSpan4({
@@ -122,10 +126,13 @@ const useStatisticsFilter = () => {
       slotType: 'select',
       prop: 'markerId',
       slot: {
-        options: markerList?.value?.map((marker) => ({
-          value: marker.id,
-          label: marker.loginName ? `${marker.loginName}-${marker.name}` : marker.name,
-        })),
+        options: [
+          { label: '全部', value: '' },
+          ...(markerList?.value || []).map((marker) => ({
+            value: marker.id,
+            label: marker.loginName ? `${marker.loginName}-${marker.name}` : marker.name,
+          })),
+        ],
         filterable: true,
         clearable: true,
       },
@@ -151,6 +158,19 @@ const useStatisticsFilter = () => {
         endPlaceholder: '结束时间',
       },
     }),
+    TwoRowSpan4({
+      labelWidth: '52px',
+      prop: 'online',
+      label: '人员',
+      slotType: 'select',
+      slot: {
+        options: [
+          { label: '全部', value: '' },
+          { label: '在线', value: true },
+          { label: '离线', value: false },
+        ],
+      },
+    }),
     TwoRowSpan3({
       prop: 'expand',
       label: '展开明细',

+ 26 - 3
src/modules/analysis/personnel-statistics/index.vue

@@ -47,7 +47,7 @@
 
 <script setup lang="ts" name="AnalysisPersonnelStatistics">
 /** 人员数据统计 */
-import { computed, onMounted, ref, reactive } from 'vue'
+import { computed, onMounted, ref, watch } from 'vue'
 import { omit } from 'lodash-es'
 import { ElButton, ElIcon, ElCheckboxGroup, ElCheckbox } from 'element-plus'
 import BaseForm from '@/components/element/BaseForm.vue'
@@ -68,6 +68,8 @@ const showColumnsSetting = ref(false)
 function cancel() {
   showColumnsSetting.value = false
 }
+let searchMarkerId = ref<any>('')
+let searchOnline = ref<any>('')
 
 const columnMap: any = {
   markingGroupNumber: '小组',
@@ -119,7 +121,26 @@ onMounted(() => {
 const { fetch, result, loading } = useFetch('getStatisticsByGroup')
 
 const data = computed<ExtractApiResponse<'getStatisticsByGroup'>>(() => {
-  const groupList = result?.value?.slice(0) || []
+  let groupList = result?.value?.slice(0) || []
+  groupList = groupList
+    .map((groupItem: any) => {
+      if (groupItem.markingGroupNumber === 0) {
+        return groupItem
+      } else {
+        if (groupItem.markerDetails && groupItem.markerDetails.length) {
+          groupItem.markerDetails = groupItem.markerDetails.filter((marker: any) => {
+            return (
+              (searchMarkerId.value === '' || marker.markerId === searchMarkerId.value) &&
+              (searchOnline.value === '' || marker.online === searchOnline.value)
+            )
+          })
+        }
+        return groupItem.markerDetails && groupItem.markerDetails.length ? groupItem : null
+      }
+    })
+    .filter((v: any) => !!v)
+  console.log('groupList:', groupList)
+
   const totalIndex = groupList.findIndex((v) => v.markingGroupNumber === 0)
   return fetchModel.value.expand
     ? groupList
@@ -135,7 +156,9 @@ const data = computed<ExtractApiResponse<'getStatisticsByGroup'>>(() => {
 
 /** 刷新按钮 */
 function onSearch() {
-  fetch(omit(fetchModel.value, 'expand'))
+  searchMarkerId.value = model.markerId
+  searchOnline.value = model.online
+  fetch(omit(fetchModel.value, 'expand', 'markerId', 'online'))
 }
 
 onOptionInit(onSearch)

+ 20 - 3
src/modules/expert/assess/index.vue

@@ -155,16 +155,21 @@ const onOperationClick: OperationClick = ({ type, value }) => {
   operationHandles[type]?.(value)
 }
 
-const { mainQuestionList, dataModel, changeModelValue, onOptionInit } = useOptions(['question'])
+const { subjectList, mainQuestionList, dataModel, changeModelValue, onOptionInit, isLeader, isExpert } = useOptions([
+  'subject',
+  'question',
+])
 
 const formModel = reactive<ExtractApiParams<'getExpertAssessList'>>({
   mainNumber: dataModel.question,
   pageNumber: 1,
   pageSize: 9999999,
+  subjectCode: dataModel.subject,
 })
 
 watch(dataModel, () => {
   formModel.mainNumber = dataModel.question
+  formModel.subjectCode = dataModel.subject
 })
 
 const { fetch: getForceCheckGroupList, result: forceCheckGroup } = useFetch('getForceCheckGroupList')
@@ -184,16 +189,28 @@ const { defineColumn, _ } = useForm()
 const span10 = defineColumn(_, '', { span: 10 })
 
 const formItems = computed<EpFormItem[]>(() => [
+  span10({
+    rowKey: 'row-1',
+    label: '科目',
+    prop: 'subjectCode',
+    slotType: 'select',
+    labelWidth: '46px',
+    slot: { options: subjectList.value, onChange: changeModelValue('subject'), disabled: !isExpert.value },
+  }),
   span10({
     rowKey: 'row-1',
     label: '大题',
     prop: 'mainNumber',
     slotType: 'select',
     labelWidth: '46px',
-    slot: { options: mainQuestionList.value, onChange: changeModelValue('question'), disabled: true },
+    slot: {
+      options: mainQuestionList.value,
+      onChange: changeModelValue('question'),
+      disabled: !isExpert.value && !isLeader.value,
+    },
   }),
   span10({
-    rowKey: 'row-1',
+    rowKey: 'row-2',
     label: '组号',
     prop: 'forceGroupNumber',
     slotType: 'select',

+ 25 - 4
src/modules/expert/expert/index.vue

@@ -107,6 +107,9 @@ useFetch('getRoleList')
         label: item.roleName,
       }
     })
+    if (ROLE_OPTION.value.length) {
+      formModel.role = ROLE_OPTION.value[0].value
+    }
   })
 /** 给分板 */
 const editScoreVisible = ref<boolean>(true)
@@ -179,15 +182,20 @@ const onOperationClick: OperationClick = ({ type, value }) => {
   operationHandles[type]?.(value)
 }
 
-const { mainQuestionList, dataModel, changeModelValue, onOptionInit } = useOptions(['question'])
+const { subjectList, mainQuestionList, dataModel, changeModelValue, onOptionInit, isLeader, isExpert } = useOptions([
+  'subject',
+  'question',
+])
 
 const formModel = reactive<ExtractApiParams<'getExpertPickList'>>({
   mainNumber: dataModel.question,
   forceGroupNumber: void 0,
-  role: 'CHIEF',
+  // role: 'CHIEF',
+  role: '',
   paperType: 'RF',
   pageNumber: 1,
   pageSize: 9999999,
+  subjectCode: dataModel.subject,
 })
 
 watch(
@@ -201,6 +209,7 @@ watch(
 
 watch(dataModel, () => {
   formModel.mainNumber = dataModel.question
+  formModel.subjectCode = dataModel.subject
 })
 
 const { fetch: getForceCheckGroupList, result: forceCheckGroup } = useFetch('getForceCheckGroupList')
@@ -221,16 +230,28 @@ const span10 = defineColumn(_, '', { span: 10 })
 
 const formItems = computed<EpFormItem[]>(() => {
   const items = [
+    span10({
+      rowKey: 'row-1',
+      label: '科目',
+      prop: 'subjectCode',
+      slotType: 'select',
+      labelWidth: '46px',
+      slot: { options: subjectList.value, onChange: changeModelValue('subject'), disabled: !isExpert.value },
+    }),
     span10({
       rowKey: 'row-1',
       label: '大题',
       prop: 'mainNumber',
       slotType: 'select',
       labelWidth: '46px',
-      slot: { options: mainQuestionList.value, onChange: changeModelValue('question'), disabled: true },
+      slot: {
+        options: mainQuestionList.value,
+        onChange: changeModelValue('question'),
+        disabled: !isExpert.value && !isLeader.value,
+      },
     }),
     span10({
-      rowKey: 'row-1',
+      rowKey: 'row-2',
       label: '角色',
       prop: 'role',
       slotType: 'select',

+ 19 - 2
src/modules/expert/sample/index.vue

@@ -154,16 +154,21 @@ const onOperationClick: OperationClick = ({ type, value }) => {
   operationHandles[type]?.(value)
 }
 
-const { mainQuestionList, dataModel, changeModelValue, onOptionInit } = useOptions(['question'])
+const { subjectList, mainQuestionList, dataModel, changeModelValue, onOptionInit, isExpert, isLeader } = useOptions([
+  'subject',
+  'question',
+])
 
 const formModel = reactive<ExtractApiParams<'getRfSampleList'>>({
   mainNumber: dataModel.question,
   pageNumber: 1,
   pageSize: 9999999,
+  subjectCode: dataModel.subject,
 })
 
 watch(dataModel, () => {
   formModel.mainNumber = dataModel.question
+  formModel.subjectCode = dataModel.subject
 })
 
 const { defineColumn, _ } = useForm()
@@ -171,13 +176,25 @@ const { defineColumn, _ } = useForm()
 const span10 = defineColumn(_, '', { span: 10 })
 
 const formItems = computed<EpFormItem[]>(() => [
+  span10({
+    rowKey: 'row-1',
+    label: '科目',
+    prop: 'subjectCode',
+    slotType: 'select',
+    labelWidth: '46px',
+    slot: { options: subjectList.value, onChange: changeModelValue('subject'), disabled: !isExpert.value },
+  }),
   span10({
     rowKey: 'row-1',
     label: '大题',
     prop: 'mainNumber',
     labelWidth: '46px',
     slotType: 'select',
-    slot: { options: mainQuestionList.value, onChange: changeModelValue('question'), disabled: true },
+    slot: {
+      options: mainQuestionList.value,
+      onChange: changeModelValue('question'),
+      disabled: !isExpert.value && !isLeader.value,
+    },
   }),
   { rowKey: 'row-1', slotName: 'search', labelWidth: '10px', colProp: { span: 4 } },
 ])

+ 20 - 3
src/modules/expert/standard/index.vue

@@ -93,7 +93,10 @@ const onOperationClick: OperationClick = ({ type, value }) => {
   operationHandles[type]?.(value)
 }
 
-const { mainQuestionList, dataModel, changeModelValue, onOptionInit } = useOptions(['question'])
+const { subjectList, mainQuestionList, dataModel, changeModelValue, onOptionInit, isExpert, isLeader } = useOptions([
+  'subject',
+  'question',
+])
 
 const formModel = reactive<ExtractApiParams<'getStandardList'>>({
   mainNumber: dataModel.question,
@@ -102,10 +105,12 @@ const formModel = reactive<ExtractApiParams<'getStandardList'>>({
   scoreEnd: '',
   pageNumber: 1,
   pageSize: 9999999,
+  subjectCode: dataModel.subject,
 })
 
 watch(dataModel, () => {
   formModel.mainNumber = dataModel.question
+  formModel.subjectCode = dataModel.subject
 })
 
 const { formRef, elFormRef, defineColumn, _ } = useForm()
@@ -114,16 +119,28 @@ const span10 = defineColumn(_, '', { span: 10 })
 const span5 = defineColumn(_, '', { span: 5 })
 
 const formItems = computed<EpFormItem[]>(() => [
+  span10({
+    rowKey: 'row-1',
+    label: '科目',
+    prop: 'subjectCode',
+    slotType: 'select',
+    labelWidth: '46px',
+    slot: { options: subjectList.value, onChange: changeModelValue('subject'), disabled: !isExpert.value },
+  }),
   span10({
     rowKey: 'row-1',
     label: '大题',
     prop: 'mainNumber',
     slotType: 'select',
     labelWidth: '46px',
-    slot: { options: mainQuestionList.value, onChange: changeModelValue('question'), disabled: true },
+    slot: {
+      options: mainQuestionList.value,
+      onChange: changeModelValue('question'),
+      disabled: !isExpert.value && !isLeader.value,
+    },
   }),
   span10({
-    rowKey: 'row-1',
+    rowKey: 'row-2',
     label: '分发',
     prop: 'dispensed',
     slotType: 'select',

+ 20 - 3
src/modules/expert/training/index.vue

@@ -124,17 +124,22 @@ const onOperationClick: OperationClick = ({ type, value }) => {
   operationHandles[type]?.(value)
 }
 
-const { mainQuestionList, dataModel, changeModelValue, onOptionInit } = useOptions(['question'])
+const { subjectList, mainQuestionList, dataModel, changeModelValue, onOptionInit, isLeader, isExpert } = useOptions([
+  'subject',
+  'question',
+])
 
 const formModel = reactive<ExtractApiParams<'getSampleList'>>({
   mainNumber: dataModel.question,
   paperType: 'SAMPLE_A',
   pageNumber: 1,
   pageSize: 9999999,
+  subjectCode: dataModel.subject,
 })
 
 watch(dataModel, () => {
   formModel.mainNumber = dataModel.question
+  formModel.subjectCode = dataModel.subject
 })
 
 const { defineColumn, _ } = useForm()
@@ -142,16 +147,28 @@ const { defineColumn, _ } = useForm()
 const span10 = defineColumn(_, '', { span: 10 })
 
 const formItems = computed<EpFormItem[]>(() => [
+  span10({
+    rowKey: 'row-1',
+    label: '科目',
+    prop: 'subjectCode',
+    slotType: 'select',
+    labelWidth: '46px',
+    slot: { options: subjectList.value, onChange: changeModelValue('subject'), disabled: !isExpert.value },
+  }),
   span10({
     rowKey: 'row-1',
     label: '大题',
     prop: 'mainNumber',
     slotType: 'select',
     labelWidth: '46px',
-    slot: { options: mainQuestionList.value, onChange: changeModelValue('question'), disabled: true },
+    slot: {
+      options: mainQuestionList.value,
+      onChange: changeModelValue('question'),
+      disabled: !isExpert.value && !isLeader.value,
+    },
   }),
   span10({
-    rowKey: 'row-1',
+    rowKey: 'row-2',
     label: '组号',
     prop: 'paperType',
     slotType: 'select',

+ 20 - 3
src/modules/marking/arbitration/index.vue

@@ -141,17 +141,22 @@ const onOperationClick: OperationClick = ({ type, value }) => {
   operationHandles[type]?.(value)
 }
 
-const { mainQuestionList, dataModel, changeModelValue, onOptionInit } = useOptions(['question'])
+const { subjectList, mainQuestionList, dataModel, changeModelValue, onOptionInit, isExpert, isLeader } = useOptions([
+  'subject',
+  'question',
+])
 
 const formModel = reactive<ExtractApiParams<'getArbitrationList'>>({
   mainNumber: dataModel.question,
   status: 'INITIAL',
   pageNumber: 1,
   pageSize: 9999999,
+  subjectCode: dataModel.subject,
 })
 
 watch(dataModel, () => {
   formModel.mainNumber = dataModel.question
+  formModel.subjectCode = dataModel.subject
 })
 
 const { defineColumn, _ } = useForm()
@@ -159,16 +164,28 @@ const { defineColumn, _ } = useForm()
 const span10 = defineColumn(_, '', { span: 10 })
 
 const formItems = computed<EpFormItem[]>(() => [
+  span10({
+    rowKey: 'row-1',
+    label: '科目',
+    prop: 'subjectCode',
+    slotType: 'select',
+    labelWidth: '46px',
+    slot: { options: subjectList.value, onChange: changeModelValue('subject'), disabled: !isExpert.value },
+  }),
   span10({
     rowKey: 'row-1',
     label: '大题',
     prop: 'mainNumber',
     slotType: 'select',
     labelWidth: '46px',
-    slot: { options: mainQuestionList.value, onChange: changeModelValue('question'), disabled: true },
+    slot: {
+      options: mainQuestionList.value,
+      onChange: changeModelValue('question'),
+      disabled: !isExpert.value && !isLeader.value,
+    },
   }),
   span10({
-    rowKey: 'row-1',
+    rowKey: 'row-2',
     label: '状态',
     prop: 'status',
     slotType: 'select',

+ 3 - 2
src/modules/marking/marking-standard/index.vue

@@ -9,10 +9,11 @@
 <script setup lang="ts" name="MarkingStandardNav">
 /** 评分标准 */
 import useFetch from '@/hooks/useFetch'
-
+import useMainStore from '@/store/main'
+const mainStore = useMainStore()
 const { fetch, result } = useFetch('getMarkingStandard')
 
-fetch()
+fetch({ subjectCode: mainStore?.myUserInfo?.subjectCode, mainNumber: mainStore?.myUserInfo?.mainNumber })
 </script>
 
 <style scoped lang="scss">

+ 20 - 3
src/modules/marking/problem/index.vue

@@ -174,7 +174,10 @@ const onOperationClick: OperationClick = ({ type, value }) => {
   operationHandles[type]?.(value)
 }
 
-const { mainQuestionList, dataModel, changeModelValue, onOptionInit } = useOptions(['question'])
+const { subjectList, mainQuestionList, dataModel, changeModelValue, onOptionInit, isExpert, isLeader } = useOptions([
+  'subject',
+  'question',
+])
 
 const formModel = reactive<ExtractApiParams<'getProblemHistory'>>({
   mainNumber: dataModel.question,
@@ -182,10 +185,12 @@ const formModel = reactive<ExtractApiParams<'getProblemHistory'>>({
   status: 'INITIAL',
   pageNumber: 1,
   pageSize: 9999999,
+  subjectCode: dataModel.subject,
 })
 
 watch(dataModel, () => {
   formModel.mainNumber = dataModel.question
+  formModel.subjectCode = dataModel.subject
 })
 
 const { defineColumn, _ } = useForm()
@@ -193,16 +198,28 @@ const { defineColumn, _ } = useForm()
 const span10 = defineColumn(_, '', { span: 10 })
 
 const formItems = computed<EpFormItem[]>(() => [
+  span10({
+    rowKey: 'row-1',
+    label: '科目',
+    prop: 'subjectCode',
+    slotType: 'select',
+    labelWidth: '46px',
+    slot: { options: subjectList.value, onChange: changeModelValue('subject'), disabled: !isExpert.value },
+  }),
   span10({
     rowKey: 'row-1',
     label: '大题',
     prop: 'mainNumber',
     labelWidth: '46px',
     slotType: 'select',
-    slot: { options: mainQuestionList.value, onChange: changeModelValue('question'), disabled: true },
+    slot: {
+      options: mainQuestionList.value,
+      onChange: changeModelValue('question'),
+      disabled: !isExpert.value && !isLeader.value,
+    },
   }),
   span10({
-    rowKey: 'row-1',
+    rowKey: 'row-2',
     label: '状态',
     prop: 'status',
     slotType: 'select',

+ 20 - 3
src/modules/marking/repeat/index.vue

@@ -153,17 +153,22 @@ const onOperationClick: OperationClick = ({ type, value }) => {
   operationHandles[type]?.(value)
 }
 
-const { mainQuestionList, dataModel, changeModelValue, onOptionInit } = useOptions(['question'])
+const { subjectList, mainQuestionList, dataModel, changeModelValue, onOptionInit, isExpert, isLeader } = useOptions([
+  'subject',
+  'question',
+])
 
 const formModel = reactive<ExtractApiParams<'getReMarkPaperList'>>({
   mainNumber: dataModel.question,
   confirm: false,
   pageNumber: 1,
   pageSize: 9999999,
+  subjectCode: dataModel.subject,
 })
 
 watch(dataModel, () => {
   formModel.mainNumber = dataModel.question
+  formModel.subjectCode = dataModel.subject
 })
 
 const { defineColumn, _ } = useForm()
@@ -171,16 +176,28 @@ const { defineColumn, _ } = useForm()
 const span10 = defineColumn(_, '', { span: 10 })
 
 const formItems = computed<EpFormItem[]>(() => [
+  span10({
+    rowKey: 'row-1',
+    label: '科目',
+    prop: 'subjectCode',
+    slotType: 'select',
+    labelWidth: '46px',
+    slot: { options: subjectList.value, onChange: changeModelValue('subject'), disabled: !isExpert.value },
+  }),
   span10({
     rowKey: 'row-1',
     label: '大题',
     prop: 'mainNumber',
     slotType: 'select',
     labelWidth: '46px',
-    slot: { options: mainQuestionList.value, onChange: changeModelValue('question'), disabled: true },
+    slot: {
+      options: mainQuestionList.value,
+      onChange: changeModelValue('question'),
+      disabled: !isExpert.value && !isLeader.value,
+    },
   }),
   span10({
-    rowKey: 'row-1',
+    rowKey: 'row-2',
     label: '状态',
     labelWidth: '46px',
     prop: 'confirm',

+ 20 - 3
src/modules/marking/similar/index.vue

@@ -90,17 +90,22 @@ const onOperationClick: OperationClick = ({ type, value }) => {
   operationHandles[type]?.(value)
 }
 
-const { mainQuestionList, dataModel, changeModelValue, onOptionInit } = useOptions(['question'])
+const { subjectList, mainQuestionList, dataModel, changeModelValue, onOptionInit, isExpert, isLeader } = useOptions([
+  'subject',
+  'question',
+])
 
 const formModel = reactive<ExtractApiParams<'getSimilarPaperList'>>({
   mainNumber: dataModel.question,
   status: '',
   pageNumber: 1,
   pageSize: 9999999,
+  subjectCode: dataModel.subject,
 })
 
 watch(dataModel, () => {
   formModel.mainNumber = dataModel.question
+  formModel.subjectCode = dataModel.subject
 })
 
 const { defineColumn, _ } = useForm()
@@ -108,16 +113,28 @@ const { defineColumn, _ } = useForm()
 const span10 = defineColumn(_, '', { span: 10 })
 
 const formItems = computed<EpFormItem[]>(() => [
+  span10({
+    rowKey: 'row-1',
+    label: '科目',
+    prop: 'subjectCode',
+    slotType: 'select',
+    labelWidth: '46px',
+    slot: { options: subjectList.value, onChange: changeModelValue('subject'), disabled: !isExpert.value },
+  }),
   span10({
     rowKey: 'row-1',
     label: '大题',
     prop: 'mainNumber',
     slotType: 'select',
     labelWidth: '46px',
-    slot: { options: mainQuestionList.value, onChange: changeModelValue('question'), disabled: true },
+    slot: {
+      options: mainQuestionList.value,
+      onChange: changeModelValue('question'),
+      disabled: !isExpert.value && !isLeader.value,
+    },
   }),
   span10({
-    rowKey: 'row-1',
+    rowKey: 'row-2',
     label: '雷同判定',
     labelWidth: '86px',
     prop: 'status',

+ 20 - 3
src/modules/monitor/system-check/index.vue

@@ -202,7 +202,10 @@ const onOperationClick: OperationClick = ({ type, value }) => {
   operationHandles[type]?.(value)
 }
 
-const { mainQuestionList, dataModel, changeModelValue, onOptionInit } = useOptions(['question'])
+const { subjectList, mainQuestionList, dataModel, changeModelValue, onOptionInit, isLeader, isExpert } = useOptions([
+  'subject',
+  'question',
+])
 
 const formModel = reactive<any>({
   mainNumber: dataModel.question,
@@ -210,6 +213,7 @@ const formModel = reactive<any>({
   level: '',
   // pageNumber: 1,
   // pageSize: 9999999,
+  subjectCode: dataModel.subject,
 })
 
 const hideHeaderButtons = computed(() => {
@@ -218,6 +222,7 @@ const hideHeaderButtons = computed(() => {
 
 watch(dataModel, () => {
   formModel.mainNumber = dataModel.question
+  formModel.subjectCode = dataModel.subject
 })
 
 const { defineColumn, _ } = useForm()
@@ -225,16 +230,28 @@ const { defineColumn, _ } = useForm()
 const span10 = defineColumn(_, '', { span: 10 })
 
 const formItems = computed<EpFormItem[]>(() => [
+  span10({
+    rowKey: 'row-1',
+    label: '科目',
+    prop: 'subjectCode',
+    slotType: 'select',
+    labelWidth: '46px',
+    slot: { options: subjectList.value, onChange: changeModelValue('subject'), disabled: !isExpert.value },
+  }),
   span10({
     rowKey: 'row-1',
     label: '大题',
     prop: 'mainNumber',
     slotType: 'select',
     labelWidth: '46px',
-    slot: { options: mainQuestionList.value, onChange: changeModelValue('question'), disabled: true },
+    slot: {
+      options: mainQuestionList.value,
+      onChange: changeModelValue('question'),
+      disabled: !isExpert.value && !isLeader.value,
+    },
   }),
   span10({
-    rowKey: 'row-1',
+    rowKey: 'row-2',
     label: '档次',
     prop: 'level',
     slotType: 'select',

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

@@ -27,7 +27,7 @@
             <span class="m-l-extra-small detail-info-label-num">{{ monitorDetail?.length }}</span>
           </el-button>
         </div>
-        <div class="flex-1 scroll-auto">
+        <div class="flex-1 scroll-auto m-t-mini">
           <base-table
             ref="tableRef"
             border

+ 18 - 5
src/modules/quality/ending-check/components/EndCheck.vue

@@ -255,10 +255,16 @@ const rules: EpFormRules = {
   loginName: [{ required: true, message: '请输入指定评卷员账号' }],
 }
 
-const { mainQuestionList, groupListWithAll, onOptionInit, dataModel, changeModelValue } = useOptions([
-  'question',
-  'group',
-])
+const {
+  subjectList,
+  mainQuestionList,
+  groupListWithAll,
+  onOptionInit,
+  dataModel,
+  changeModelValue,
+  isExpert,
+  isLeader,
+} = useOptions(['subject', 'question', 'group'])
 
 /** 搜索 */
 const model = reactive<ExtractApiParams<'unProcessProblemList'>>({
@@ -296,6 +302,13 @@ const OneRow = defineColumn(_, 'row-1', { span: 6 })
 const btnRow = defineColumn(_, 'row-1', { span: 2 })
 
 const items = computed<EpFormItem[]>(() => [
+  OneRow({
+    label: '科目',
+    prop: 'subjectCode',
+    slotType: 'select',
+    labelWidth: '46px',
+    slot: { options: subjectList.value, onChange: changeModelValue('subject'), disabled: !isExpert.value },
+  }),
   OneRow({
     label: '大题',
     prop: 'questionMainNumber',
@@ -304,7 +317,7 @@ const items = computed<EpFormItem[]>(() => [
     slot: {
       options: mainQuestionList.value,
       onChange: changeModelValue('question'),
-      disabled: true,
+      disabled: !isExpert.value && !isLeader.value,
     },
   }),
   OneRow({

+ 10 - 3
src/modules/quality/subjective-check/index.vue

@@ -224,7 +224,10 @@ const onOperationClick: OperationClick = ({ type, value }) => {
   operationHandles[type]?.(value)
 }
 
-const { subjectList, mainQuestionList, dataModel, changeModelValue, onOptionInit } = useOptions(['subject', 'question'])
+const { subjectList, mainQuestionList, dataModel, changeModelValue, onOptionInit, isExpert, isLeader } = useOptions([
+  'subject',
+  'question',
+])
 
 const formModel = reactive<ExtractApiParams<'getSubjectiveCheckList'>>({
   subjectCode: dataModel.subject || '',
@@ -261,14 +264,18 @@ const formItems = computed<EpFormItem[]>(() => [
     label: '科目',
     prop: 'subjectCode',
     slotType: 'select',
-    slot: { options: subjectList.value, onChange: changeModelValue('subject'), disabled: true },
+    slot: { options: subjectList.value, onChange: changeModelValue('subject'), disabled: !isExpert.value },
   }),
   span10({
     rowKey: 'row-1',
     label: '大题',
     prop: 'mainNumber',
     slotType: 'select',
-    slot: { options: mainQuestionList.value, onChange: changeModelValue('question'), disabled: true },
+    slot: {
+      options: mainQuestionList.value,
+      onChange: changeModelValue('question'),
+      disabled: !isExpert.value && !isLeader.value,
+    },
   }),
   { rowKey: 'row-1', slotName: 'search', labelWidth: '10px', colProp: { span: 4 } },
   span12({