Michael Wang преди 3 години
родител
ревизия
3c935bd71f

+ 15 - 0
src/api/projectCompareManagementPage.ts

@@ -0,0 +1,15 @@
+import { httpApp } from "@/plugins/axiosApp";
+import { SASPaper, ServerPageResponse } from "@/types";
+
+/** 项目分页查询 */
+export function getProjectCompareList(params: {
+  contrastProjectId: number;
+  projectIds: number[];
+  pageNo: number;
+  pageSize: number;
+}) {
+  return httpApp.post<any, ServerPageResponse<SASPaper>>(
+    "/api/ess/contrast/paper/page",
+    params
+  );
+}

+ 8 - 0
src/components/Layout.vue

@@ -45,6 +45,14 @@
               项目列表
             </router-link>
           </a-menu-item>
+          <a-menu-item key="22">
+            <router-link
+              activeClass="active-route"
+              to="/project/projectCompareManagement"
+            >
+              关联分析
+            </router-link>
+          </a-menu-item>
         </a-sub-menu>
       </a-menu>
     </div>

+ 53 - 0
src/components/ProjectsSelect.vue

@@ -0,0 +1,53 @@
+<template>
+  <a-select
+    placeholder="请选择项目"
+    allowClear
+    style="width: 140px"
+    :mode="isMultiple ? 'multiple' : undefined"
+    @change="handleChange"
+  >
+    <a-select-option
+      v-for="(item, index) in optionList"
+      :key="index"
+      :value="item.id"
+    >
+      {{ item.name }}
+    </a-select-option>
+  </a-select>
+</template>
+
+<script setup lang="ts">
+import { getProjectList } from "@/api/projectManagementPage";
+import { onMounted, computed, onUpdated } from "vue";
+
+const props =
+  defineProps<{ value?: null | number | number[]; rootOrgId: number }>();
+const emit = defineEmits(["update:value"]);
+
+let optionList = $ref<{ id: number; name: string }[]>([]);
+
+async function fetchData() {
+  if (!props.rootOrgId) return;
+  const res = await getProjectList({
+    // id: props.projectId,
+    rootOrgId: props.rootOrgId,
+    pageNo: 1,
+    pageSize: 100,
+  });
+  optionList = res.data.content;
+}
+onMounted(fetchData);
+onUpdated(fetchData);
+
+const isMultiple = computed(() => Array.isArray(props.value));
+
+// const valueStr = computed(() => {
+//   let res: undefined | number | string = props.value ?? undefined;
+//   // if (typeof res === "number") res = props.value + "";
+//   return res as undefined | string;
+// });
+
+function handleChange(v: string) {
+  emit("update:value", v);
+}
+</script>

+ 222 - 0
src/features/projectCompareManagement/ProjectCompareManagement.vue

@@ -0,0 +1,222 @@
+<template>
+  <div>
+    <div class="tw-bg-white tw-p-5 tw-rounded-xl tw-mb-5">
+      <ProjectsSelect
+        v-if="rootOrgId"
+        v-model:value="projectIds"
+        :rootOrgId="rootOrgId"
+        placeholder="请选择分析项目"
+        style="width: 400px !important"
+      />
+      <span class="tw-mr-4"></span>
+      <ProjectsSelect
+        v-if="rootOrgId"
+        v-model:value="contrastProjectId"
+        :rootOrgId="rootOrgId"
+        placeholder="请选择参照项目"
+      />
+      <span class="tw-mr-4"></span>
+      <a-button class="query-btn" @click="clickSearch">对比</a-button>
+    </div>
+
+    <div class="tw-bg-white tw-p-5 tw-rounded-xl">
+      <a-table
+        rowKey="id"
+        :columns="columns"
+        :data-source="data"
+        :pagination="{
+          pageSize: pageSize,
+          current: pageNo,
+          total: totalElements,
+          showTotal: () => ``,
+          onChange: (pageNoChanged, pageSizeChanged) => {
+            pageNo = pageNoChanged;
+            pageSize = pageSizeChanged;
+          },
+        }"
+      >
+        <template #courseName="{ record }">
+          <a>{{ record.courseName }}({{ record.courseCode }})</a>
+        </template>
+        <template #action="{ record }">
+          <span>
+            <a-button
+              v-if="record.projectId !== contrastProjectId"
+              @click="goCompareDetail(record)"
+              >查看详情</a-button
+            >
+          </span>
+        </template>
+      </a-table>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { getProjectCompareList } from "@/api/projectCompareManagementPage";
+import router from "@/router";
+import { useMainStore } from "@/store";
+import { SASPaper } from "@/types";
+import { message } from "ant-design-vue";
+import { watch, onMounted } from "vue";
+
+const store = useMainStore();
+store.currentLocation = "项目管理 / 关联分析";
+
+let rootOrgId = $ref(undefined as unknown as number);
+
+let projectIds: number[] = $ref([]);
+let contrastProjectId: number = $ref();
+
+let data = $ref<SASPaper[]>([]);
+let pageSize = $ref(10);
+let pageNo = $ref(1);
+let totalElements = $ref(0);
+
+async function clickSearch() {
+  pageNo = 1;
+  await fetchData();
+}
+
+watch(() => [pageNo, pageSize], fetchData);
+
+async function fetchData() {
+  if (projectIds.length === 0) {
+    void message.warn("请选择对比项目");
+    return;
+  }
+  if (typeof contrastProjectId !== "number") {
+    void message.warn("请选择参照项目");
+    return;
+  }
+  const res = await getProjectCompareList({
+    projectIds,
+    contrastProjectId,
+    pageSize,
+    pageNo,
+  });
+  // console.log(res);
+  data = res.data.content.map((v) => {
+    v.avgScore = Math.round(v.avgScore * 100) / 100;
+    v.stdev = Math.round(v.stdev * 100) / 100;
+    v.coefficient = Math.round(v.coefficient * 100) / 100;
+    v.reliability1 = Math.round(v.reliability1 * 100) / 100;
+    v.reliability2 = Math.round(v.reliability2 * 100) / 100;
+    v.difficulty = Math.round(v.difficulty * 100) / 100;
+    return v;
+  });
+  pageNo = res.data.pageNo;
+  pageSize = res.data.pageSize;
+  totalElements = res.data.totalElements;
+}
+
+const columns = [
+  {
+    title: "科目",
+    dataIndex: "courseName",
+    slots: { customRender: "courseName" },
+    width: 140,
+  },
+  {
+    title: "项目名称",
+    dataIndex: "projectName",
+    width: 150,
+  },
+  {
+    title: "试卷名称",
+    dataIndex: "paperName",
+  },
+  {
+    title: "满分",
+    dataIndex: "totalScore",
+  },
+  {
+    title: "最高分",
+    dataIndex: "maxScore",
+  },
+  {
+    title: "最低分",
+    dataIndex: "minScore",
+  },
+  {
+    title: "全距",
+    dataIndex: "allRange",
+  },
+  {
+    title: "平均分",
+    dataIndex: "avgScore",
+  },
+  {
+    title: "标准差",
+    dataIndex: "stdev",
+  },
+  {
+    title: "差异系数",
+    dataIndex: "coefficient",
+  },
+  {
+    title: "信度1",
+    dataIndex: "reliability1",
+  },
+  {
+    title: "信度2",
+    dataIndex: "reliability2",
+  },
+  {
+    title: "难度",
+    dataIndex: "difficulty",
+  },
+  {
+    title: "操作",
+    key: "action",
+    slots: { customRender: "action" },
+    // slots: {
+    //   customRender: ({ text, index }) => {
+    //     console.log(text, index);
+    //     const obj = {
+    //       children: text,
+    //       props: {} as any,
+    //     };
+    //     if (index === 2) {
+    //       obj.props.rowSpan = 2;
+    //     }
+    //     // These two are merged into above cell
+    //     if (index === 3) {
+    //       obj.props.rowSpan = 0;
+    //     }
+    //     if (index === 4) {
+    //       obj.props.colSpan = 0;
+    //     }
+    //     return obj;
+    //   },
+    // },
+  },
+];
+
+onMounted(() => {
+  rootOrgId = store.userInfo.rootOrgId;
+});
+
+async function goCompareDetail(courseCode: string) {
+  await router.push({
+    path: "compareDetail",
+    state: { courseCode, contrastProjectId, projectIds },
+  });
+}
+</script>
+
+<style>
+.need-compute span {
+  color: red;
+  animation: 1s ease-in-out 1s infinite alternate scale_text;
+}
+
+@keyframes scale_text {
+  from {
+    transform: scale(1);
+  }
+  to {
+    transform: scale(1.1);
+  }
+}
+</style>

+ 7 - 0
src/router/index.ts

@@ -78,6 +78,13 @@ const routes = [
         path: "allAnalysis/:projectId",
         component: () => import("@/features/allAnalysis/AllAnalysis2.vue"),
       },
+      {
+        path: "projectCompareManagement",
+        component: () =>
+          import(
+            "@/features/projectCompareManagement/ProjectCompareManagement.vue"
+          ),
+      },
     ],
     component: Layout,
   },