瀏覽代碼

fix types

Michael Wang 3 年之前
父節點
當前提交
85d680e87f

+ 6 - 2
src/api/projectParamsManagementPage.ts

@@ -1,15 +1,19 @@
 import { httpApp } from "@/plugins/axiosApp";
 import { responseToFile } from "@/utils/utils";
+import { ProjectCourseResponse } from "@/types";
 
 /** 科目分页查询 */
 export function getProjectCourseList(params: {
   courseId?: number;
   projectId: number;
-  courseName: string;
+  courseName?: string;
   pageNo?: number;
   pageSize?: number;
 }) {
-  return httpApp.post("/api/ess/projectCourse/list", params);
+  return httpApp.post<any, { data: ProjectCourseResponse }>(
+    "/api/ess/projectCourse/list",
+    params
+  );
 }
 
 /** 导入项目参数配置 */

+ 16 - 12
src/components/CommonRangeConfig.vue

@@ -1,10 +1,10 @@
 <template>
   <a-modal
-    title="分段设置"
     v-model:visible="rangeConfigVisible"
+    title="分段设置"
+    okText="确定"
+    cancelText="取消"
     @ok="handleOk"
-    ok-text="确定"
-    cancel-text="取消"
   >
     <div v-if="selectedRangeConfig">
       <a-timeline>
@@ -44,8 +44,8 @@
       <div class="tw-my-4 tw-flex tw-items-center">
         <span style="width: 55px">调整分</span>
         <a-input-number
-          class="tw-rounded-xl"
           v-model:value="rangePoint.adjustScore"
+          class="tw-rounded-xl"
         ></a-input-number>
       </div>
       <a-button type="primary" @click="newRangePoint">新增分割点</a-button>
@@ -56,12 +56,16 @@
 <script setup lang="ts">
 import { getProjectCourseList } from "@/api/projectParamsManagementPage";
 import { RANGE_POINT_TYPE } from "@/constants/constants";
-import { onUpdated, reactive, toRaw, watch } from "vue";
+import { ProjectCourse, RangeConfig } from "@/types";
+import { onUpdated, reactive, watch } from "vue";
 
 const emit = defineEmits(["updated"]);
 
-const props =
-  defineProps<{ projectId: number; courseId: number; rangeConfig: any }>();
+const props = defineProps<{
+  projectId: number;
+  courseId: number;
+  rangeConfig: RangeConfig[];
+}>();
 
 let rangeConfigVisible = $ref(false);
 const showModal = () => {
@@ -69,8 +73,8 @@ const showModal = () => {
 };
 defineExpose({ showModal });
 
-let selectedRangeConfig = $ref([]);
-let courseSetting = $ref({});
+let selectedRangeConfig = $ref<RangeConfig[]>([]);
+let courseSetting = $ref({} as ProjectCourse);
 
 watch(
   () => props.rangeConfig,
@@ -101,7 +105,7 @@ let rangePoint = reactive({
   type: "",
 });
 
-async function newRangePoint() {
+function newRangePoint() {
   if (!rangePoint.type) return;
   if (!rangePoint.adjustScore) {
     rangePoint.adjustScore = 0;
@@ -125,7 +129,7 @@ async function newRangePoint() {
     rangePoint.baseScore = 0;
     rangePoint.adjustScore = 0;
   }
-  selectedRangeConfig.push({ ...rangePoint });
+  selectedRangeConfig.push({ ...rangePoint } as RangeConfig);
   // let t = toRaw(selectedRangeConfig);
   // t.sort((a, b) => a.baseScore + a.adjustScore - (b.baseScore + b.adjustScore));
   // console.log(t);
@@ -143,7 +147,7 @@ function handleDeleteRangePoint(item: any) {
   selectedRangeConfig = selectedRangeConfig.filter((v) => v !== item);
 }
 
-async function handleOk() {
+function handleOk() {
   emit("updated", selectedRangeConfig);
   rangeConfigVisible = false;
 }

+ 3 - 3
src/components/CourseSelect.vue

@@ -2,12 +2,12 @@
   <a-select
     placeholder="请选择科目"
     allowClear
-    show-search
+    showSearch
     :value="valueStr"
+    style="width: 200px"
+    :filterOption="false"
     @search="handleSearch"
     @change="handleChange"
-    style="width: 200px"
-    :filter-option="false"
   >
     <a-select-option
       v-for="(item, index) in optionList"

+ 1 - 1
src/components/CourseTypeSelect.vue

@@ -4,8 +4,8 @@
     allowClear
     :disabled="props.disabled"
     :value="valueStr"
-    @change="handleChange"
     style="width: 120px"
+    @change="handleChange"
   >
     <a-select-option value="PUBLIC">公共科目</a-select-option>
     <a-select-option value="MAJOR">专业科目</a-select-option>

+ 2 - 2
src/components/ExplainModal.vue

@@ -1,10 +1,10 @@
 <template>
   <a-modal
-    title="报告说明信息页"
     ref="theModal"
     v-model:visible="visible"
+    title="报告说明信息页"
+    okText="确定"
     @ok="visible = false"
-    ok-text="确定"
   >
     <a-form>
       <a-form-item label="报告类别">

+ 2 - 0
src/components/404.vue → src/components/PageError404.vue

@@ -1,3 +1,5 @@
 <template>
   <div class="tw-text-center tw-text-3xl">页面没找到(404)</div>
 </template>
+
+<script setup lang="ts"></script>

+ 1 - 1
src/components/PaperTypeSelect.vue

@@ -4,8 +4,8 @@
     allowClear
     :disabled="props.disabled"
     :value="valueStr"
-    @change="handleChange"
     style="width: 120px"
+    @change="handleChange"
   >
     <a-select-option
       v-for="(item, index) in optionList"

+ 4 - 4
src/components/ProjectCourseSelect.vue

@@ -2,13 +2,13 @@
   <a-select
     placeholder="请选择科目"
     allowClear
-    show-search
+    showSearch
     :value="valueStr"
-    @search="handleSearch"
-    @change="handleChange"
     style="width: 200px"
     :disabled="props.disabled"
-    :filter-option="false"
+    :filterOption="false"
+    @search="handleSearch"
+    @change="handleChange"
   >
     <a-select-option
       v-for="(item, index) in optionList"

+ 1 - 1
src/components/ProjectSelect.vue

@@ -3,8 +3,8 @@
     placeholder="请选择项目"
     allowClear
     :value="valueStr"
-    @change="handleChange"
     style="width: 140px"
+    @change="handleChange"
   >
     <a-select-option
       v-for="(item, index) in optionList"

+ 1 - 1
src/components/ProjectStatusSelect.vue

@@ -4,8 +4,8 @@
     allowClear
     :disabled="props.disabled"
     :value="valueStr"
-    @change="handleChange"
     style="width: 120px"
+    @change="handleChange"
   >
     <a-select-option
       v-for="(item, index) in PROJECT_STATUS"

+ 14 - 7
src/components/QmButton.vue

@@ -1,15 +1,15 @@
 <template>
   <!-- FIXED: 从 vue 3.1.5 升级到 3.2.1 时这里出错了,slot也要有key -->
   <a-button v-bind="newAttrs" :loading="inInterval" @click="insideClick">
-    <template v-for="(_, slot) of $slots" v-slot:[slot]="scope">
-      <slot :name="asAny(slot)" v-bind="asAny(scope)" :key="slot" />
+    <template v-for="(_, slot) of $slots" #[slot]="scope" :key="slot">
+      <slot v-bind="asAny(scope)" :key="slot" :name="asAny(slot)" />
     </template>
     <!-- <slot name="default" /> -->
   </a-button>
 </template>
 
 <script lang="ts">
-import { reactive, ref } from "vue";
+import { reactive } from "vue";
 
 // 默认loading一秒,以免重复点击
 export default {
@@ -26,16 +26,23 @@ export default {
     // @ts-ignore
     delete newAttrs["onClick"];
 
-    let inInterval = ref(false);
+    let inInterval = $ref(false);
     const insideClick = (e: MouseEvent) => {
-      inInterval.value = true;
-      setTimeout(() => (inInterval.value = false), props.clickTimeout);
+      inInterval = true;
+      // false warning
+      // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
+      setTimeout(() => (inInterval = false), props.clickTimeout);
+      // eslint-disable-next-line @typescript-eslint/no-unsafe-call
       parentOnClick(e);
+      // 确保焦点不停留在此处,以免Enter键触发
+      // @ts-ignore
+      // eslint-disable-next-line @typescript-eslint/no-unsafe-call
+      e.target?.blur();
     };
     // newAttrs.onClick = insideClick;
 
     function asAny(input: any): any {
-      return input as any;
+      return input;
     }
     return { newAttrs, inInterval, insideClick, asAny };
   },

+ 2 - 2
src/components/RoleSelect.vue

@@ -3,8 +3,8 @@
     placeholder="请选择角色"
     allowClear
     :value="valueStr"
-    @change="handleChange"
     style="width: 140px"
+    @change="handleChange"
   >
     <a-select-option
       v-for="(item, index) in optionList"
@@ -43,7 +43,7 @@ async function fetchData() {
 const valueStr = computed(() => {
   let res: undefined | number = props.value ?? undefined;
   // if (typeof res === "number") res = props.value;
-  return res as undefined | number;
+  return res ;
 });
 
 function handleChange(v: string) {

+ 1 - 1
src/components/RootOrgSelect.vue

@@ -3,8 +3,8 @@
     placeholder="请选择顶级机构"
     allowClear
     :value="valueStr"
-    @change="handleChange"
     style="width: 140px"
+    @change="handleChange"
   >
     <a-select-option
       v-for="(item, index) in optionList"

+ 1 - 1
src/components/StateSelect.vue

@@ -4,8 +4,8 @@
     allowClear
     :disabled="props.disabled"
     :value="valueStr"
-    @change="handleChange"
     style="width: 80px"
+    @change="handleChange"
   >
     <a-select-option value="true">启用</a-select-option>
     <a-select-option value="false">禁止</a-select-option>

+ 21 - 13
src/features/allAnalysis/ScoreFirstTryRate.vue

@@ -25,9 +25,11 @@
               <th>本科目难度</th>
               <th>占总分权重(%)</th>
             </tr>
-            <tr v-for="(item2, index) in item.totalScoreRange" :key="index">
+            <tr v-for="(item2, index2) in item.totalScoreRange" :key="index2">
               <td>
-                {{ scoreTitle(item.totalScoreRangeTitle[index]) || "全体考生" }}
+                {{
+                  scoreTitle(item.totalScoreRangeTitle[index2]) || "全体考生"
+                }}
               </td>
               <td v-number-to-percent>
                 {{ item2.countRate }}
@@ -62,7 +64,7 @@
 </template>
 
 <script setup lang="ts">
-import { useMainStore } from "@/store";
+// import { useMainStore } from "@/store";
 import { onMounted } from "vue";
 import { useRoute } from "vue-router";
 import {
@@ -72,32 +74,37 @@ import {
 import EventBus from "@/plugins/eventBus";
 import { message } from "ant-design-vue";
 import { RANGE_POINT_TYPE } from "@/constants/constants";
+import { RangeConfig, SasCourse } from "@/types";
 
 let activeKey = $ref(["0"]);
-const store = useMainStore();
+// const store = useMainStore();
 
-let rootOrgId = $ref(undefined as unknown as number);
+// let rootOrgId = $ref(undefined as unknown as number);
 let courseId = $ref(undefined as undefined | number);
 const route = useRoute();
 const projectId = +route.params.projectId;
 
-let data = $ref([]);
+let data = $ref<SasCourse[]>([]);
 async function fetchData() {
   const res = await getSasCourseList({
     projectId,
     courseId,
   });
   // console.log(Object.keys(JSON.parse(res.data[0].scoreRange)));
-  res.data = res.data.map((v: any) => {
-    v.totalScoreRange = JSON.parse(v.totalScoreRange || "{}");
-    v.totalScoreRangeTitle = JSON.parse(v.totalScoreRangeTitle || "{}");
+  res.data = res.data.map((v) => {
+    v.totalScoreRange = JSON.parse(
+      <string>(<unknown>v.totalScoreRange) || "{}"
+    );
+    v.totalScoreRangeTitle = JSON.parse(
+      <string>(<unknown>v.totalScoreRangeTitle) || "{}"
+    );
     return v;
   });
   data = res.data;
 }
 
 onMounted(async () => {
-  rootOrgId = store.userInfo.rootOrgId;
+  // rootOrgId = store.userInfo.rootOrgId;
   await fetchData();
 });
 
@@ -106,7 +113,7 @@ let selectedCourseId = $ref(0);
 
 let rangeConfigRef = $ref(null);
 
-const openRangeConfigModal = (item: any) => {
+const openRangeConfigModal = (item: SasCourse) => {
   selectedCourseId = item.courseId;
   selectedRangeConfig = JSON.parse(item.totalRangeConfig || "0") || [
     {
@@ -115,7 +122,8 @@ const openRangeConfigModal = (item: any) => {
       adjustScore: 0,
     },
   ];
-  // @ts-ignore
+  // @ts-ignore https://github.com/vuejs/vue-next/issues/4397
+  // eslint-disable-next-line @typescript-eslint/no-unsafe-call
   rangeConfigRef.showModal();
 };
 
@@ -128,7 +136,7 @@ async function handleRangeConfigUpdate(rangeConfig: any) {
   void message.success({ content: "操作成功" });
 }
 
-function scoreTitle(rangeConfig: any) {
+function scoreTitle(rangeConfig: RangeConfig) {
   if (!rangeConfig) return false;
   if (rangeConfig.type === "ZERO") return "0-";
 

+ 2 - 2
src/features/paperAnalysis/DifficultyDistriTable.vue

@@ -65,7 +65,7 @@
 </template>
 
 <script setup lang="ts">
-import { QuestionGroup } from "@/types";
+import { SASQuestionGroup } from "@/types";
 
-const props = defineProps<{ questions: QuestionGroup[] }>();
+const props = defineProps<{ questions: SASQuestionGroup[] }>();
 </script>

+ 12 - 11
src/features/paperAnalysis/QuestionDifficultyGroup.vue

@@ -21,11 +21,11 @@
           <td>{{ item.mainNumber }}</td>
           <td>{{ item.subNumber }}</td>
           <td
-            v-for="(item, index) in item.difficulityLevel"
-            :key="index"
+            v-for="(item2, index2) in item.difficulityLevel"
+            :key="index2"
             v-round-number
           >
-            {{ item }}
+            {{ item2 }}
           </td>
         </tr>
       </table>
@@ -55,11 +55,11 @@
           <td>{{ item.mainNumber }}</td>
           <td>{{ item.subNumber }}</td>
           <td
-            v-for="(item, index) in item.difficulityGroupLevel"
-            :key="index"
+            v-for="(item2, index2) in item.difficulityGroupLevel"
+            :key="index2"
             v-round-number
           >
-            {{ item }}
+            {{ item2 }}
           </td>
         </tr>
       </table>
@@ -101,12 +101,12 @@
 import { setPaperRangeConfig } from "@/api/paperAnalysisPage";
 import { RANGE_POINT_TYPE } from "@/constants/constants";
 import EventBus from "@/plugins/eventBus";
-import { Question } from "@/types";
+import { RangeConfig, SASQuestion } from "@/types";
 import { message } from "ant-design-vue";
 import { EChartsOption } from "echarts";
 
 const props = defineProps<{
-  questions: Question[];
+  questions: SASQuestion[];
   totalScore: number;
   rangeConfig?: string;
   projectId: number;
@@ -139,7 +139,8 @@ const openRangeConfigModal = () => {
       adjustScore: 0,
     },
   ];
-  // @ts-ignore
+  // @ts-ignore https://github.com/vuejs/vue-next/issues/4397
+  // eslint-disable-next-line @typescript-eslint/no-unsafe-call
   rangeConfigRef.showModal();
 };
 
@@ -153,7 +154,7 @@ async function handleRangeConfigUpdate(rangeConfig: any) {
   void message.success({ content: "操作成功" });
 }
 
-function scoreTitle(rangeConfig: any) {
+function scoreTitle(rangeConfig: RangeConfig) {
   if (!rangeConfig) return false;
   if (rangeConfig.type === "ZERO") return "0-";
 
@@ -162,7 +163,7 @@ function scoreTitle(rangeConfig: any) {
   }${rangeConfig.adjustScore > 0 ? "+" : ""}${rangeConfig.adjustScore})-`;
 }
 
-function questionOptions(question: Question) {
+function questionOptions(question: SASQuestion) {
   const xAxis = [];
   for (let i = 0; i * 10 < props.totalScore; i++) {
     xAxis.push(i * 10 + "-");

+ 7 - 7
src/features/projectDataManagement/ProjectDataManagement.vue

@@ -45,9 +45,9 @@
 import {
   getProjectList,
   importProjectDataSource,
-  logsOfProject,
 } from "@/api/projectManagementPage";
 import { useMainStore } from "@/store";
+import { Project } from "@/types";
 import { downloadFileURL, goBack } from "@/utils/utils";
 import { message } from "ant-design-vue";
 import { onMounted, computed } from "vue";
@@ -60,7 +60,7 @@ let rootOrgId = $ref(undefined as unknown as number);
 
 const route = useRoute();
 const projectId = +route.params.projectId;
-let data = $ref([]);
+let data = $ref<Project[]>([]);
 
 let project: any = computed(() => data[0] || {});
 
@@ -82,7 +82,7 @@ onMounted(async () => {
 });
 
 async function downloadTpl() {
-  downloadFileURL("/api/ess/project/template");
+  await downloadFileURL("/api/ess/project/template");
 }
 
 async function handleImport() {
@@ -98,8 +98,8 @@ async function handleImport() {
   void message.success({ content: "导入成功" });
 }
 
-async function handleLogsOfProject() {
-  await logsOfProject(projectId);
-  void message.success({ content: "操作成功" });
-}
+// async function handleLogsOfProject() {
+//   await logsOfProject(projectId);
+//   void message.success({ content: "操作成功" });
+// }
 </script>

+ 4 - 4
src/features/projectPapersManagement/ProjectPapersManagement.vue

@@ -1,15 +1,15 @@
 <template>
   <div>
     <div class="tw-bg-white tw-p-5 tw-rounded-xl tw-mb-5">
-      <ProjectSelect :project-id="projectId" v-model:value="projectId" />
+      <ProjectSelect v-model:value="projectId" :projectId="projectId" />
       <span class="tw-mr-4"></span>
-      <CourseSelect :root-org-id="rootOrgId" v-model:value="courseId" />
+      <CourseSelect v-model:value="courseId" :rootOrgId="rootOrgId" />
       <span class="tw-mr-4"></span>
       <CourseTypeSelect v-model:value="courseType" />
       <span class="tw-mr-4"></span>
       <PaperTypeSelect v-model:value="paperType" />
       <span class="tw-mr-4"></span>
-      <a-button @click="search" class="query-btn">查询</a-button>
+      <a-button class="query-btn" @click="search">查询</a-button>
 
       <div class="tw-float-right tw-flex tw-gap-2">
         <a-button @click="goAllAnalysis">整体分析</a-button>
@@ -19,7 +19,7 @@
 
     <div class="tw-bg-white tw-p-5 tw-rounded-xl">
       <a-table
-        row-key="id"
+        rowKey="id"
         :columns="columns"
         :data-source="data"
         :pagination="{

+ 2 - 1
src/features/projectParamsManagement/ProjectParamsManagement.vue

@@ -107,6 +107,7 @@ import {
   updateProjectCourse,
 } from "@/api/projectParamsManagementPage";
 import { useMainStore } from "@/store";
+import { ProjectCourse } from "@/types";
 import { downloadFileURL, goBack } from "@/utils/utils";
 import { message } from "ant-design-vue";
 import { watch, onMounted, ref, reactive, toRaw, h } from "vue";
@@ -120,7 +121,7 @@ let courseId = $ref(undefined as undefined | number);
 const route = useRoute();
 const projectId = +route.params.projectId;
 
-let data = $ref([]);
+let data = $ref<ProjectCourse[]>([]);
 let pageSize = $ref(10);
 let pageNo = $ref(1);
 let totalElements = $ref(0);

+ 2 - 2
src/features/roleManagement/RoleManagement.vue

@@ -6,11 +6,11 @@
     >
       <RootOrgSelect v-model:value="rootOrgId" />
       <span class="tw-mr-4"></span>
-      <a-button @click="search" class="query-btn">查询</a-button>
+      <a-button class="query-btn" @click="search">查询</a-button>
     </div>
 
     <div class="tw-bg-white tw-p-5 tw-rounded-xl">
-      <a-table row-key="id" :columns="columns" :data-source="data">
+      <a-table rowKey="id" :columns="columns" :data-source="data">
         <template #enable="{ text }">
           <a>{{ $filters.booleanEnableDisableFilter(text) }}</a>
         </template>

+ 1 - 1
src/main.ts

@@ -45,7 +45,7 @@ app.use(router);
 app.use(createPinia());
 app.config.globalProperties.$filters = filters;
 
-app.component("v-chart", ECharts);
+app.component("VChart", ECharts);
 app.directive("round-number", roundNumber);
 app.directive("number-to-percent", numberToPercent);
 

+ 1 - 1
src/router/index.ts

@@ -84,7 +84,7 @@ const routes = [
   {
     path: "/:pathMatch(.*)*",
     name: "NotFound",
-    component: () => import("@/components/404.vue"),
+    component: () => import("@/components/PageError404.vue"),
   },
 ] as RouteRecordRaw[];
 

+ 29 - 2
src/types/index.ts

@@ -8,6 +8,27 @@ export type Course_Type = "PUBLIC" | "MAJOR";
 
 export type Privilege_Type = "COURSE" | "ORG";
 
+// Generated by https://quicktype.io
+
+export interface ProjectCourse {
+  courseCode: string;
+  courseId: number;
+  courseName: string;
+  courseType: Course_Type;
+  id: number;
+  nationalScore: number;
+  nationalTotalScore: number;
+  projectId: number;
+  projectName: string;
+  retestScore: number;
+  retestTotalScore: number;
+  totalScoreLine: number;
+}
+
+export interface ProjectCourseResponse extends Pagination {
+  content: ProjectCourse[];
+}
+
 // 科目成绩(总分)频率分布-科目成绩占初试总分权重
 export interface SasCourse {
   courseCode: string;
@@ -21,8 +42,14 @@ export interface SasCourse {
   totalCount: number;
   totalRangeConfig: string;
   totalScore: number;
-  totalScoreRange: string;
-  totalScoreRangeTitle: string;
+  totalScoreRange: {
+    countRate: number;
+    avgTotalScore: number;
+    avgScore: number;
+    difficulty: number;
+    scoreRate: number;
+  }[];
+  totalScoreRangeTitle: any; // {title}
 
   segements: number[][]; // 前端自用
   rangeSegements: (string | number | boolean)[][]; // 前端自用

+ 2 - 2
src/utils/utils.ts

@@ -22,8 +22,8 @@ export async function responseToFile(response: AxiosResponse) {
     //Here, when the JSON file is returned, the JSON.stringify Processing, other types of files do not need to be processed
     //const blob = new Blob([JSON.stringify(data)], ...)
     const blob = new Blob([data], { type: headers["content-type"] });
-    let dom = document.createElement("a");
-    let url = window.URL.createObjectURL(blob);
+    const dom = document.createElement("a");
+    const url = window.URL.createObjectURL(blob);
     dom.href = url;
     dom.download = decodeURI(fileName);
     dom.style.display = "none";