Explorar el Código

组卷作业对接

shmily1213 hace 1 mes
padre
commit
4f57daadf9

+ 9 - 1
src/api/modules/study.ts

@@ -1,6 +1,6 @@
 import { ApiResponse, ApiResponseList } from "@/types";
 import flyio from "../flyio";
-import { DirectedSchool, Examinee, ExamPaper, ExamPaperSubmit, GetExamPaperRequestDTO, Knowledge, KnowledgeListRequestDTO, KnowledgeRecord, OpenExamineeRequestDTO, PracticeHistory, PracticeRecord, SimulatedRecord, SimulationExamSubject, SimulationTestInfo, StudyPlan, Subject, SubjectListRequestDTO, VideoStudyRecord } from "@/types/study";
+import { DirectedSchool, Examinee, ExamPaper, ExamPaperSubmit, GetExamPaperRequestDTO, Knowledge, KnowledgeListRequestDTO, KnowledgeRecord, OpenExamineeRequestDTO, PaperWork, PracticeHistory, PracticeRecord, SimulatedRecord, SimulationExamSubject, SimulationTestInfo, StudyPlan, Subject, SubjectListRequestDTO, VideoStudyRecord } from "@/types/study";
 
 /**
  * 获取学习计划
@@ -226,4 +226,12 @@ export function getPracticeHistory({pageNum, pageSize}: {pageNum: number, pageSi
  */
 export function getTextbooksPracticeHistory() {
   return flyio.get('/front/student/record/coursePractice', {}) as Promise<ApiResponseList<PracticeHistory>>;
+}
+
+export function getPaperWorkList() {
+  return flyio.get('/front/student/record/test', {}) as Promise<ApiResponseList<PaperWork>>;
+}
+
+export function getPaperWorkStatistic() {
+  return flyio.get('/front/student/paperStats', {}) as Promise<ApiResponse<Record<string, number>[]>>;
 }

+ 5 - 1
src/common/enum.ts

@@ -249,7 +249,11 @@ export enum EnumPaperType {
   /**
    * 教材同步练习
    */
-  COURSE = 'Course'
+  COURSE = 'Course',
+  /**
+   * 测试卷
+   */
+  TEST = 'Test'
 }
 
 export enum EnumReviewMode {

+ 29 - 0
src/main.ts

@@ -10,6 +10,7 @@ import { useRequest } from '@/utils/request'
 import tool from '@/utils/uni-tool'
 import * as Pinia from 'pinia';
 import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
+import { useImage } from '@/hooks/useImage';
 
 // #ifndef VUE3
 import Vue from 'vue'
@@ -94,6 +95,34 @@ export function createApp() {
     }
   })
 
+  const { resolvePath } = useImage();
+  uni.$zp = {
+    config: {
+      'default-page-size': 20,
+      'refresher-title-style': {
+        fontSize: '28rpx'
+      },
+      'loading-more-title-custom-style': {
+        fontSize: '26rpx'
+      }
+      // 'empty-view-img-style': {
+      //   width: '364rpx',
+      //   height: '252rpx'
+      // },
+      // 'empty-view-img': resolvePath('/pagesStudy/static/image/icon-empty.png'),
+      // 'empty-view-title-style': {
+      //   color: '#B3B3B3',
+      //   fontSize: '30rpx',
+      //   marginTop: '40rpx'
+      // },
+      // 'empty-view-style': {
+      //   marginTop: '-200rpx'
+      // }
+    }
+  }
+
+  console.log(uni.$zp)
+
   const pinia = Pinia.createPinia();
   app.use(pinia);
   pinia.use(piniaPluginPersistedstate);

+ 1 - 1
src/pagesStudy/pages/exam-start/exam-start.vue

@@ -361,7 +361,7 @@ const handleGuideClose = () => {
 const loadData = async () => {
   uni.$ie.showLoading();
   const { paperType } = prevData.value;
-  if (paperType === EnumPaperType.PRACTICE || paperType === EnumPaperType.COURSE) {
+  if (paperType === EnumPaperType.PRACTICE || paperType === EnumPaperType.COURSE || paperType === EnumPaperType.TEST) {
     loadPracticeData();
   } else if (paperType === EnumPaperType.SIMULATED) {
     loadSimulationData();

+ 71 - 0
src/pagesStudy/pages/homework/components/paper-work.vue

@@ -0,0 +1,71 @@
+<template>
+  <view class="bg-white">
+    <view class="border-bottom flex items-center justify-between py-32 px-25 leading-27">
+      <view class="text-28 text-fore-light flex items-center">
+        <view class="w-12 h-12 rounded-full bg-[#E5E5E5]"></view>
+        <view class="ml-10">2025年09月20日</view>
+        <view class="ml-20">发布人: 李老师</view>
+      </view>
+      <view>
+        未完成
+      </view>
+    </view>
+    <view class="px-46 py-30 relative">
+      <view>
+        <text class="text-28 text-fore-title font-bold">长沙民政职业技术学院-大数据与会计</text>
+        <text
+          class="ml-10 bg-[#F0FDF4] text-[#22C55E] border border-solid border-[#22C55E] text-20 rounded-4 px-10 py-2">定向</text>
+      </view>
+      <view class="mt-40 ml-20 text-24 ">
+        <view>
+          <text class="text-fore-light">得分/总分:</text>
+          <text class="text-fore-title">-/300</text>
+        </view>
+        <view class="mt-14">
+          <text class="text-fore-light">科目/批次:</text>
+          <text class="text-fore-title">{{ batchName }}</text>
+        </view>
+        <view class="mt-14">
+          <text class="text-fore-light">所属校区:</text>
+          <text class="text-fore-title">培训校区</text>
+        </view>
+      </view>
+      <view class="absolute right-50 top-100">
+        <!-- <view class="px-28 py-10 border border-solid border-primary rounded-full text-24 text-primary bg-[#EEF8FD]">详情
+        </view> -->
+        <view class="text-24 text-white bg-primary px-28 py-10 rounded-full" @click="handleStart">去完成</view>
+      </view>
+    </view>
+  </view>
+</template>
+<script lang="ts" setup>
+import { EnumPaperType } from '@/common/enum';
+import { useTransferPage } from '@/hooks/useTransferPage';
+import { Study } from '@/types';
+const { transferTo } = useTransferPage();
+const props = defineProps<{
+  data: Study.PaperWork;
+}>();
+
+const batchName = computed(() => {
+  const names = props.data.name.split('_');
+  return `${names[0]}(${names[1]})`
+})
+
+const handleStart = () => {
+  console.log(props.data);
+  transferTo('/pagesStudy/pages/exam-start/exam-start', {
+    data: {
+      name: '知识点练习-' + props.data.name,
+      paperType: EnumPaperType.TEST,
+      practiceInfo: {
+        // name: node.name,
+        // relateId: 24,
+        relateId: 767,
+        directed: true
+      },
+    }
+  });
+}
+</script>
+<style lang="scss" scoped></style>

+ 33 - 15
src/pagesStudy/pages/homework/homework.vue

@@ -8,12 +8,12 @@
     <view class="flex-1 min-h-1 relative">
       <view class="absolute inset-0">
         <z-paging ref="paging" :fixed="false" v-model="dataList" :safe-area-inset-bottom="true"
-          :use-safe-area-placeholder="true" :auto="false" empty-view-text="暂无发布组卷作业~"
+          :use-safe-area-placeholder="true" :auto="false" bg-color="#F6F8FA" empty-view-text="暂无发布组卷作业~"
           :empty-view-img="resolvePath('/pagesStudy/static/image/icon-empty.png')" :empty-view-style="emptyViewStyle"
           :empty-view-img-style="emptyViewImgStyle" :empty-view-title-style="emptyViewTextStyle" @query="handleQuery">
-          <view v-if="dataList.length > 0" class="pt-10">
-            <view class="card-item" v-for="item in dataList" :key="item.id">
-              <activity-item :data="item" />
+          <view v-if="dataList.length > 0" class="">
+            <view class="mt-20" v-for="item in dataList" :key="item.id">
+              <paper-work-item :data="item" />
             </view>
           </view>
         </z-paging>
@@ -24,6 +24,10 @@
 
 <script lang="ts" setup>
 import { useImage } from '@/hooks/useImage';
+import PaperWorkItem from './components/paper-work.vue';
+import { getPaperWorkList, getPaperWorkStatistic } from '@/api/modules/study';
+import { Study } from '@/types';
+
 const { resolvePath } = useImage();
 const activeStyle = {
   color: '#1A1A1A'
@@ -43,21 +47,21 @@ const emptyViewTextStyle = {
   fontSize: '30rpx',
   marginTop: '40rpx'
 }
-const list = [
+const list = ref([
   {
     name: '全部(0)',
-    value: 'all'
+    value: '全部'
   },
   {
     name: '未完成(0)',
-    value: 'special'
+    value: '未完成'
   },
   {
     name: '已完成(0)',
-    value: 'special'
+    value: '已完成'
   }
-]
-const dataList = ref<any[]>([]);
+])
+const dataList = ref<Study.PaperWork[]>([]);
 const paging = ref<any>(null);
 const handleTabChange = (item: any) => {
   console.log(item);
@@ -65,17 +69,31 @@ const handleTabChange = (item: any) => {
 }
 const handleQuery = (page: number, pageSize: number) => {
   uni.$ie.showLoading();
-  setTimeout(() => {
+  getPaperWorkList().then(res => {
+    paging.value.complete(res.rows);
+  }).catch(err => {
+    paging.value.complete(false);
+  }).finally(() => {
     uni.$ie.hideLoading();
-    paging.value.complete([]);
-  }, 1000);
+  });
+
 }
-const click = (item: any) => {
-  console.log(item);
+const loadStatistic = () => {
+  getPaperWorkStatistic().then(res => {
+    list.value.forEach(item => {
+      const cate = res.data.find(c => c.hasOwnProperty(item.value))
+      if (cate) {
+        item.name = `${item.value}(${cate[item.value]})`;
+      }
+    });
+  });
 }
 
+loadStatistic();
+
 onMounted(() => {
   paging.value.reload();
+
 });
 </script>
 

+ 1 - 1
src/pagesStudy/pages/knowledge-practice/knowledge-practice.vue

@@ -70,7 +70,7 @@ const loadKnowledgeList = async () => {
       directed: prevData.value.directed
     });
     treeData.value = data as Study.KnowledgeNode[];
-    pagingRef.value.complete(data, data.length);
+    pagingRef.value.complete(data);
   } catch (error) {
     console.log(error);
     pagingRef.value.complete(false);

+ 26 - 16
src/pagesStudy/pages/textbooks-practice/textbooks-practice.vue

@@ -1,16 +1,20 @@
 <template>
-  <ie-page ref="iePageRef">
-    <ie-navbar :title="pageTitle" />
-    <view class="px-30 py-16 bg-back">
-      <view class="flex items-center justify-end gap-x-4" @click="handleViewHistory">
-        <uv-icon name="clock" size="16" color="#31A0FC"></uv-icon>
-        <text class="text-28 text-primary">查看记录</text>
-        <uv-icon name="arrow-right" size="16" color="#31A0FC"></uv-icon>
+  <ie-page>
+    <z-paging ref="pagingRef" v-model="treeData" :loading-more-enabled="false" :auto="false" @query="loadKnowledgeList">
+      <template #top>
+        <ie-navbar :title="pageTitle" />
+        <view class="px-30 py-16 bg-back">
+          <view class="flex items-center justify-end gap-x-4" @click="handleViewHistory">
+            <uv-icon name="clock" size="16" color="#31A0FC"></uv-icon>
+            <text class="text-28 text-primary">查看记录</text>
+            <uv-icon name="arrow-right" size="16" color="#31A0FC"></uv-icon>
+          </view>
+        </view>
+      </template>
+      <view class="px-40">
+        <knowledgeTree :tree-data="treeData" @start-practice="handleStartPractice" />
       </view>
-    </view>
-    <view class="px-40">
-      <knowledgeTree :tree-data="treeData" @start-practice="handleStartPractice" />
-    </view>
+    </z-paging>
   </ie-page>
 </template>
 
@@ -23,11 +27,12 @@ import * as Study from '@/types/study';
 import { EnumPaperType, EnumUserRole } from '@/common/enum';
 import { useUserStore } from '@/store/userStore';
 import { useAuth } from '@/hooks/useAuth';
-const { prevData, transferTo } = useTransferPage();
 
+const { prevData, transferTo } = useTransferPage();
 const userStore = useUserStore();
-const iePageRef = ref<InstanceType<typeof IePage>>();
+const pagingRef = ref();
 const { hasPermission } = useAuth();
+
 const pageTitle = computed(() => {
   return '教材同步练习';
 });
@@ -39,20 +44,22 @@ const handleViewHistory = () => {
     data: {}
   });
 }
-const loadKnowledgeList = async () => {
+
+const loadKnowledgeList = async (page: number, size: number) => {
   try {
     uni.$ie.showLoading();
     const { data } = await getTextbooksKnowledgeList();
     treeData.value = data as Study.KnowledgeNode[];
+    pagingRef.value.complete(data);
   } catch (error) {
     console.log(error);
+    pagingRef.value.complete(false);
   } finally {
     uni.$ie.hideLoading();
   }
 }
 
 const handleStartPractice = async (node: Study.KnowledgeNode) => {
-  // const isVip = await userStore.checkVip();
   const hasAuth = hasPermission([EnumUserRole.VIP, EnumUserRole.AGENT, EnumUserRole.TEACHER]);
   if (hasAuth) {
     transferTo('/pagesStudy/pages/exam-start/exam-start', {
@@ -69,7 +76,10 @@ const handleStartPractice = async (node: Study.KnowledgeNode) => {
 }
 
 onShow(() => {
-  loadKnowledgeList();
+  nextTick(() => {
+    // 下拉刷新数据
+    pagingRef.value?.refresh();
+  });
 });
 </script>
 

+ 4 - 0
src/static/style/tailwind.scss

@@ -38,6 +38,10 @@
     box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.08);
   }
 
+  .border-bottom {
+    border-bottom: 1px solid #E5E5E5;
+  }
+
   .sibling-border-top {
     &+.sibling-border-top {
       border-top: 1px solid #E5E5E5;

+ 13 - 0
src/types/study.ts

@@ -364,4 +364,17 @@ export interface PracticeHistory {
   endTime: string;
   examineeId: number;
   paperName: string;
+}
+
+/**
+ * 组卷作业
+ */
+export interface PaperWork {
+  id: number,
+  name: string,
+  subjectId: number,
+  total: number,
+  state: number,
+  subjectName: string,
+  date: string
 }

+ 4 - 4
src/uni_modules/z-paging/components/z-paging/js/z-paging-utils.js

@@ -199,13 +199,13 @@ function deepCopy(obj) {
 function _handleDefaultConfig() {
 	// 确保只加载一次全局配置
 	if (configLoaded) return;
-	// 优先从config.js中读取
+	// 默认从config.js中读取
 	if (zLocalConfig && Object.keys(zLocalConfig).length) {
 		config = zLocalConfig;
 	}
-	// 如果在config.js中读取不到,则尝试到uni.$zp读取
-	if (!config && uni.$zp) {
-		config = uni.$zp.config;
+	// uni.$zp的优先级更高
+	if (uni.$zp) {
+		config = Object.assign(config, uni.$zp.config);
 	}
 	// 将config中的短横线写法全部转为驼峰写法,使得读取配置时可以直接通过key去匹配,而非读取每个配置时候再去转,减少不必要的性能开支
 	config = config ? Object.keys(config).reduce((result, key) => {

+ 1 - 1
tsconfig.json

@@ -36,7 +36,7 @@
     "src/**/*.vue",
     "src/**/*.d.ts",
     "src/uni_modules/**/*.d.ts"
-, "src/config.js"  ],
+, "src/config.js", "src/uni_modules/z-paging/config/index.js"  ],
   "exclude": [
     "node_modules",
     "dist",