Browse Source

feat: 自定义查询结果页

chenhao 2 years ago
parent
commit
a4788fb5a1

+ 6 - 0
src/api/marking.ts

@@ -12,6 +12,12 @@ const MarkingApi: DefineApiModule<Marking.ApiMap> = {
   },
   /** 自定义查询 - 获取快捷查询列表 */
   getCustomQueryConfigList: '/api/custom/query/list',
+  /** 自定义查询 - 浏览 */
+  viewCustomQuery: '/api/custom/query/view',
+  /** 自定义查询 - 修改卷型 */
+  updateCustomPaperType: '/api/custom/query/create/reference',
+  /** 自定义查询 - 修改分数 */
+  updateCustomPaperScore: '/api/custom/query/mark',
   /** 查看评分标准 */
   getMarkingStandard: '/api/mark/markstandard',
   /** 获取评卷任务 */

+ 6 - 4
src/components/shared/ImagePreview.vue

@@ -1,7 +1,7 @@
 <template>
   <base-dialog v-model="visible" title="试卷预览" :footer="false" :modal="false" draggable class="preview-dialog">
     <div class="preview-content">
-      <img :src="url" alt="" />
+      <img v-show="!!url" :src="url" alt="" />
     </div>
   </base-dialog>
 </template>
@@ -12,7 +12,7 @@ import useVModel from '@/hooks/useVModel'
 
 const props = defineProps<{
   modelValue: boolean
-  url: string
+  url?: string
 }>()
 const visible = useVModel(props)
 </script>
@@ -22,8 +22,10 @@ const visible = useVModel(props)
   margin-left: 70%;
   .preview-content {
     width: 100%;
-    max-width: 300px;
-    max-height: 600px;
+    min-width: 300px;
+    min-height: 400px;
+    max-width: 600px;
+    max-height: 800px;
     img {
       width: 100%;
       height: 100%;

+ 3 - 3
src/components/shared/MarkHistoryList.vue

@@ -21,11 +21,11 @@ import type { EpTableColumn } from 'global-type'
 
 const props = withDefaults(
   defineProps<{
-    modelValue: boolean
+    modelValue?: boolean
     type?: 'task' | 'secret'
     id: number | string | undefined
-    modal: boolean
-    showLevel: boolean
+    modal?: boolean
+    showLevel?: boolean
   }>(),
   {
     type: 'task',

+ 1 - 1
src/hooks/useTable.ts

@@ -107,7 +107,7 @@ const useTable = <
       currentPage: baseParams.pageNumber,
       pageSize: baseParams.pageSize,
       pageCount: pageCount.value,
-      total: total,
+      total: total.value,
     })
   })
 

+ 10 - 0
src/modules/admin-data/task-setting/components/GroupSetting.vue

@@ -0,0 +1,10 @@
+<template>
+  <div class=""></div>
+</template>
+
+<script setup lang="ts" name="GroupSetting">
+/** 任务设置 - 按小组设置 */
+import { reactive, ref } from 'vue'
+</script>
+
+<style scoped lang="scss"></style>

+ 10 - 0
src/modules/admin-data/task-setting/components/MarkerSetting.vue

@@ -0,0 +1,10 @@
+<template>
+  <div class=""></div>
+</template>
+
+<script setup lang="ts" name="MarkerSetting">
+/** 任务设置 - 按评卷员设置 */
+import { reactive, ref } from 'vue'
+</script>
+
+<style scoped lang="scss"></style>

+ 164 - 19
src/modules/marking/inquiry-result/index.vue

@@ -1,6 +1,7 @@
 <template>
   <div class="flex direction-column full">
     <mark-header :exclude-operations="['remark', 'problem', 'example', 'delete']" @click="onOperationClick">
+      <el-button class="m-l-base m-r-auto" size="small" type="primary" @click="onEditScore">修改给分</el-button>
     </mark-header>
     <div class="flex flex-1 overflow-hidden p-base mark-container">
       <div
@@ -13,13 +14,13 @@
         </span>
         <right-button class="next-button" @click="checkNext" />
         <div class="flex-1 p-base scroll-auto mark-content-paper">
-          <img :src="dataUrl" alt="" class="paper-img" :style="{ 'background-color': frontColor }" />
+          <img :src="current?.filePath" alt="" class="paper-img" :style="{ 'background-color': frontColor }" />
         </div>
       </div>
       <div class="p-base radius-base fill-blank scroll-auto m-l-base table-view">
         <div class="flex items-center justify-between detail-info-table-header">
           <el-button custom-1 size="small" class="detail-info-label">
-            <span class="">总数:</span>
+            <span class="">自定抽查卷共:</span>
             <span class="m-l-extra-small detail-info-label-num">{{ pagination.total }}</span>
           </el-button>
           <el-pagination
@@ -36,6 +37,7 @@
           ref="tableRef"
           size="small"
           v-bind="pagination"
+          highlight-current-row
           :data="tableData"
           :columns="columns"
           @current-change="onCurrentChange"
@@ -44,13 +46,32 @@
       </div>
     </div>
   </div>
-  <image-preview v-model="previewModalVisible" :url="MockImg"></image-preview>
-  <mark-history-list :id="currentViewHistory?.taskId" v-model="visibleHistory" type="secret"></mark-history-list>
+  <image-preview v-model="previewModalVisible" :url="current?.filePath"></image-preview>
+  <mark-history-list :id="currentViewHistory?.taskId" v-model="visibleHistory"></mark-history-list>
+  <scoring-panel-with-confirm
+    v-model:visible="editScoreVisible"
+    v-model:score="modelScore"
+    :main-number="current?.mainNumber"
+    modal
+    :toggle-modal="false"
+    @submit="onSubmit"
+  ></scoring-panel-with-confirm>
+  <base-dialog v-model="setExpertPaperVisible" title="设置专家卷" :footer="false">
+    <base-form size="small" :model="setExpertModel" :items="items" :label-width="useVW(100)">
+      <template #form-item-confirm>
+        <confirm-button
+          class="m-t-base"
+          @confirm="onConfirmSetExpert"
+          @cancel="setExpertPaperVisible = false"
+        ></confirm-button>
+      </template>
+    </base-form>
+  </base-dialog>
 </template>
 
 <script setup lang="ts" name="MarkingInquiryResult">
 /** 自定义查询结果 */
-import { reactive, ref, computed } from 'vue'
+import { ref, computed, watch, reactive } from 'vue'
 import { useRoute } from 'vue-router'
 import { ElButton, ElPagination } from 'element-plus'
 import { useSetImgBg } from '@/hooks/useSetImgBg'
@@ -58,29 +79,39 @@ import useFetch from '@/hooks/useFetch'
 import useTable from '@/hooks/useTable'
 import useTableCheck from '@/hooks/useTableCheck'
 import useMarkHeader from '@/hooks/useMarkHeader'
+import useVW from '@/hooks/useVW'
+import ConfirmButton from '@/components/common/ConfirmButton.vue'
+import BaseForm from '@/components/element/BaseForm.vue'
+import BaseDialog from '@/components/element/BaseDialog.vue'
 import MarkHeader from '@/components/shared/MarkHeader.vue'
 import BaseTable from '@/components/element/BaseTable.vue'
 import MarkHistoryList from '@/components/shared/MarkHistoryList.vue'
 import RightButton from '@/components/shared/RightButton.vue'
 import SvgIcon from '@/components/common/SvgIcon.vue'
 import ImagePreview from '@/components/shared/ImagePreview.vue'
+import ScoringPanelWithConfirm from '@/components/shared/ScoringPanelWithConfirm.vue'
 
 import MockImg from '@/assets/mock/SAMPA-1.jpg'
-import type { LocationQuery } from 'vue-router'
+
 import type { SetImgBgOption } from '@/hooks/useSetImgBg'
 import type { ExtractMultipleApiResponse, ExtractApiParams, ExtractApiResponse } from 'api-type'
-import type { MarkHeaderInstance, EpTableColumn } from 'global-type'
+import type { MarkHeaderInstance, EpTableColumn, EpFormItem } from 'global-type'
 
 type RowType = ExtractMultipleApiResponse<'getCustomQueryTasks'> & { index: number }
 
 const { query } = useRoute()
 
+/** 给分板 */
+const editScoreVisible = ref<boolean>(false)
+
 /** 图片预览 */
 const previewModalVisible = ref<boolean>(false)
 
-const mockTask = ref<{ mainNumber: number }>({
-  mainNumber: 1,
-})
+/** 设置专家卷 */
+const setExpertPaperVisible = ref<boolean>(false)
+
+/** 分数 */
+const modelScore = ref<number[]>([])
 
 const {
   rotate,
@@ -113,11 +144,20 @@ const onRefresh = () => {
   fetchTable()
 }
 
+/** 设置专家卷 */
+const onBookmark = () => {
+  setExpertPaperVisible.value = true
+}
+
 /** 预览试卷 */
 const onPreview = () => {
   previewModalVisible.value = true
 }
 
+const onEditScore = () => {
+  editScoreVisible.value = true
+}
+
 type OperationClick = MarkHeaderInstance['onClick']
 
 type OperationType = Parameters<Exclude<OperationClick, undefined>>[0]['type']
@@ -131,6 +171,7 @@ const operationHandles: Partial<Record<OperationType, (...args: any) => void>> =
   'background-color': setBackgroundColor,
   refresh: onRefresh,
   standard: onViewStandard,
+  bookmark: onBookmark,
 }
 
 const onOperationClick: OperationClick = ({ type, value }) => {
@@ -138,12 +179,12 @@ const onOperationClick: OperationClick = ({ type, value }) => {
 }
 
 const columns: EpTableColumn<RowType>[] = [
-  { label: '评卷员', prop: 'markerName' },
   { label: '密号', prop: 'secretNumber' },
-  { label: '给分', prop: 'markerScore' },
-  { label: '客观分', prop: 'objectiveScore' },
-  { label: '客主比', prop: 'markerRatio' },
+  { label: '评卷员', prop: 'markerName' },
+  { label: '评卷员给分', prop: 'markerScore' },
+  { label: '组长给分', prop: 'objectiveScore' },
   { label: '评卷时间', prop: 'markTime' },
+  { label: '抽查次数', prop: 'customCheckNumber' },
 ]
 
 const transformQuery = (query: Record<string, string>) => {
@@ -155,9 +196,11 @@ const transformQuery = (query: Record<string, string>) => {
   return params
 }
 
-const { pagination, data, fetchTable } = useTable('getCustomQueryTasks', {
-  ...transformQuery(query as Record<string, string>),
-})
+const { pagination, data, fetchTable } = useTable(
+  'getCustomQueryTasks',
+  transformQuery(query as Record<string, string>),
+  { pageSize: 20 }
+)
 
 const {
   tableRef,
@@ -170,9 +213,111 @@ const {
   onCurrentChange,
 } = useTableCheck(data)
 
-console.log(query)
+watch(current, () => {
+  if (current.value) {
+    useFetch('viewCustomQuery').fetch({ taskId: current.value.taskId })
+  }
+})
+
+type SetExpertModel = {
+  paperType: ExtractApiParams<'updateCustomPaperType'>['paperType']
+  forceGroupNumber?: 'A' | 'B' | number
+}
+
+const setExpertModel = reactive<SetExpertModel>({
+  paperType: 'FORCE',
+  forceGroupNumber: 'A',
+})
+
+const { fetch: getForceCheckGroupList, result: forceCheckGroupListResult } = useFetch('getForceCheckGroupList')
 
-const { fetch: getCustomQueryTasks, result: customQueryTasks } = useFetch('getCustomQueryTasks')
+const forceCheckGroup = computed(() =>
+  forceCheckGroupListResult?.value?.map((group) => {
+    return { ...group, label: group.forceGroupNumber, labelSlot: `第${group.forceGroupNumber}组` }
+  })
+)
+
+watch(
+  query,
+  () => {
+    if (query.subjectCode && query.mainNumber) {
+      getForceCheckGroupList({ subjectCode: query.subjectCode as string, mainNumber: +query.mainNumber })
+    }
+  },
+  { deep: true, immediate: true }
+)
+
+const items = computed<EpFormItem[]>(() => {
+  let paperTypeItems: EpFormItem[] = [
+    {
+      label: '当前试卷设置为',
+      prop: 'paperType',
+      slotType: 'radio',
+      slot: {
+        options: [
+          { label: 'FORCE', slotLabel: '考核卷' },
+          { label: 'RF', slotLabel: '样卷' },
+          { label: 'STANDARD', slotLabel: '标准卷' },
+        ],
+      },
+    },
+  ]
+  let forceGroupNumberItems: EpFormItem[] = [
+    {
+      label: '考核卷组',
+      prop: 'forceGroupNumber',
+      slotType: 'radio',
+      slot: { options: [{ label: 'A' }, { label: 'B' }, ...forceCheckGroup.value] },
+    },
+  ]
+  return paperTypeItems
+    .concat(setExpertModel.paperType === 'FORCE' ? forceGroupNumberItems : [])
+    .concat({ slotName: 'confirm' })
+})
+
+const getPaperTypeAndGroupNumber = (
+  params: SetExpertModel
+): { paperType: ExpertPickType; forceGroupNumber?: number } => {
+  if (['RF', 'STANDARD'].includes(params.paperType)) {
+    return {
+      paperType: params.paperType,
+      forceGroupNumber: void 0,
+    }
+  } else if (params.forceGroupNumber === 'A' || params.forceGroupNumber === 'B') {
+    return {
+      paperType: params.forceGroupNumber === 'A' ? 'SAMPLE_A' : 'SAMPLE_B',
+      forceGroupNumber: void 0,
+    }
+  } else {
+    return {
+      paperType: 'FORCE',
+      forceGroupNumber: params.forceGroupNumber,
+    }
+  }
+}
+
+/** 确定设置专家卷 */
+const onConfirmSetExpert = async () => {
+  if (!current.value) {
+    return
+  }
+  try {
+    await useFetch('updateCustomPaperType').fetch({
+      taskId: current.value.taskId,
+      ...getPaperTypeAndGroupNumber(setExpertModel),
+    })
+    setExpertPaperVisible.value = false
+  } catch (error) {
+    console.error(error)
+  }
+}
+
+/** 确定给分 */
+const onSubmit = () => {
+  if (current.value) {
+    useFetch('updateCustomPaperScore').fetch({ taskId: current.value.taskId, scores: modelScore.value })
+  }
+}
 </script>
 
 <style scoped lang="scss">

+ 22 - 14
src/modules/marking/inquiry/index.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="p-base full mark-inquiry-view">
     <div class="full radius-base fill-blank p-large">
-      <base-form :disabled="saving" :label-width="useVW(72)" :items="items" :model="model">
+      <base-form ref="formRef" :disabled="saving" :label-width="useVW(72)" :rules="rules" :items="items" :model="model">
         <template #form-item-button-group>
           <el-button type="primary" @click="onSearch">抽查</el-button>
           <!-- <el-button type="primary">高级抽查</el-button> -->
@@ -30,7 +30,7 @@ import { computed, reactive, ref, watch } from 'vue'
 import { useRouter } from 'vue-router'
 import { ElButton, ElInput } from 'element-plus'
 import { omit } from 'lodash-es'
-import { typeOf, isDefine } from '@/utils/common'
+import { filterEmpty } from '@/utils/common'
 import BaseForm from '@/components/element/BaseForm.vue'
 import BaseDialog from '@/components/element/BaseDialog.vue'
 import BaseSelect from '@/components/element/BaseSelect.vue'
@@ -40,14 +40,14 @@ import useFetch from '@/hooks/useFetch'
 import useOptions from '@/hooks/useOptions'
 import useVW from '@/hooks/useVW'
 
-import type { EpFormItem } from 'global-type'
+import type { EpFormItem, EpFormRules } from 'global-type'
 import type { ExtractApiParams } from 'api-type'
 
 const { push } = useRouter()
 
 const shortQueryConfig = ref<ExtractApiParams<'setCustomQueryConfig'>['params']>()
 
-const { defineColumn, _ } = useForm()
+const { formRef, elFormRef, defineColumn, _ } = useForm()
 
 type FormModel = Omit<ExtractApiParams<'setCustomQueryConfig'>['params'], 'timeStart' | 'timeEnd'> & { time: string[] }
 
@@ -104,6 +104,11 @@ const ThreeRow = Span5(_, 'row-3')
 const FourRow = Span5(_, 'row-4')
 const ElevenRow5 = Span5(_, 'row-11')
 
+const rules: EpFormRules = {
+  subjectCode: [{ required: true, message: '请选择科目' }],
+  mainNumber: [{ required: true, message: '请选择大题' }],
+}
+
 const items = computed<EpFormItem[]>(() => [
   OneRow({
     label: '科目',
@@ -209,9 +214,10 @@ const items = computed<EpFormItem[]>(() => [
 ])
 
 function getSearchParams(obj: Record<string, string | number | boolean>) {
+  const query = filterEmpty(obj)
   let params: Record<string, string> = {}
-  for (let k in obj) {
-    params[k] = `${obj[k]}`
+  for (let k in query) {
+    params[k] = `${query[k]}`
   }
   return params
 }
@@ -219,14 +225,16 @@ function getSearchParams(obj: Record<string, string | number | boolean>) {
 /** 抽查 */
 const onSearch = async () => {
   try {
-    push({
-      name: 'MarkingInquiryResult',
-      query: getSearchParams({
-        ...omit(model, 'time'),
-        timeStart: model.time?.[0],
-        timeEnd: model.time?.[1],
-      }),
-    })
+    const valid = await elFormRef?.value?.validate()
+    valid &&
+      push({
+        name: 'MarkingInquiryResult',
+        query: getSearchParams({
+          ...omit(model, 'time'),
+          timeStart: model.time?.[0],
+          timeEnd: model.time?.[1],
+        }),
+      })
   } catch (error) {
     console.error(error)
   }

+ 0 - 11
src/store/layout.ts

@@ -22,17 +22,6 @@ export function getMenuRotes() {
 
   const tempRoutes = router.getRoutes()
 
-  /** 给后端配置权限的菜单路由 */
-  console.log(
-    tempRoutes
-      .filter((route) => !route.path.startsWith('/example') && route.meta.menu)
-      .map((_) => ({
-        name: _.name,
-        path: _.path,
-        label: _.meta.label,
-      }))
-  )
-
   const routesMap = tempRoutes
     .map((_, i) => _.meta?.menuId + '-' + i)
     .filter((_) => !_.startsWith('undefined'))

+ 22 - 0
types/api.d.ts

@@ -383,6 +383,22 @@ declare module 'api-type' {
 
     type GetCustomQueryConfigList = BaseDefine<{ name: string }, { name: string; params: CustomQuery }[]>
 
+    /** 自定义查询 - 浏览 */
+    type ViewCustomQuery = BaseDefine<{ taskId: number }>
+
+    /** 自定义查询 - 修改卷型 */
+    type UpdateCustomPaperType = BaseDefine<{
+      taskId?: number
+      paperType: ExpertPickType
+      forceGroupNumber?: number
+    }>
+
+    /** 自定义查询 - 修改分数 */
+    type UpdateCustomPaperScore = BaseDefine<{
+      taskId?: number
+      scores: number[]
+    }>
+
     type GetMarkingStandard = BaseDefine<null, { examId: number; mainNumber: number; subjectCode: string; url: string }>
 
     interface Question {
@@ -615,6 +631,12 @@ declare module 'api-type' {
       setCustomQueryConfig: SetCustomQueryConfig
       /** 自定义查询 - 获取快捷查询列表 */
       getCustomQueryConfigList: GetCustomQueryConfigList
+      /** 自定义查询 - 浏览 */
+      viewCustomQuery: ViewCustomQuery
+      /** 自定义查询 - 修改卷型 */
+      updateCustomPaperType: UpdateCustomPaperType
+      /** 自定义查询 - 修改分数 */
+      updateCustomPaperScore: UpdateCustomPaperScore
       /** 查看评分标准 */
       getMarkingStandard: GetMarkingStandard
       /** 获取评卷任务 */