Bladeren bron

添加教材同步练习功能

shmily1213 5 dagen geleden
bovenliggende
commit
67c88d4be8

+ 20 - 2
src/api/modules/study.ts

@@ -68,6 +68,15 @@ export function getKnowledgeList(params: KnowledgeListRequestDTO) {
   return flyio.get('/front/paper/knowledge', params) as Promise<ApiResponse<Knowledge[]>>;
 }
 
+/**
+ * 获取教材同步知识点
+ * @param params 
+ * @returns 
+ */
+export function getTextbooksKnowledgeList() {
+  return flyio.get('/front/paper/courseKnowledge', {}) as Promise<ApiResponse<Knowledge[]>>;
+}
+
 /**
  * 开卷
  * @param params 
@@ -203,6 +212,15 @@ export function correctQuestion(params: { questionid: number, remark: string })
  * @param params 
  * @returns 
  */
-export function getPracticeHistory(params: { directed: boolean }) {
-  return flyio.get('/front/student/record/practice', params) as Promise<ApiResponseList<PracticeHistory>>;
+export function getPracticeHistory() {
+  return flyio.get('/front/student/record/practice', {}) as Promise<ApiResponseList<PracticeHistory>>;
+}
+
+/**
+ * 获取教材同步练习记录
+ * @param params 
+ * @returns 
+ */
+export function getTextbooksPracticeHistory() {
+  return flyio.get('/front/student/record/coursePractice', {}) as Promise<ApiResponseList<PracticeHistory>>;
 }

+ 5 - 1
src/common/enum.ts

@@ -241,7 +241,11 @@ export enum EnumPaperType {
   /**
    * 考试
    */
-  SIMULATED = 'Simulated'
+  SIMULATED = 'Simulated',
+  /**
+   * 教材同步练习
+   */
+  COURSE = 'Course'
 }
 
 export enum EnumReviewMode {

+ 4 - 0
src/components/ie-picker/ie-picker.vue

@@ -182,6 +182,10 @@ const handleClick = () => {
   if (props.disabled) {
     return;
   }
+  if (!props.list.length) {
+    uni.$ie.showToast('暂无数据');
+    return;
+  }
   init();
   isOpen.value = true;
   pickerRef.value.open();

+ 100 - 100
src/components/mx-tabs-swiper/mx-tabs-swiper.vue

@@ -1,65 +1,66 @@
 <template>
-    <!-- NOTE:min-h-1在使用useElementSize时非常重要 -->
-    <view ref="container" class="h-full fx-col flex-1 min-h-1">
-        <uv-tabs :current="current" :list="tabs" :key-name="keyName" v-bind="tabBindings"
-                 class="bg-white bd-b-1" @change="handleTabChange">
-            <template v-if="$slots.tab" #default="scope">
-                <slot name="tab" v-bind="scope"/>
-            </template>
-        </uv-tabs>
-        <uv-line v-if="border"/>
-        <view>
-          <slot name="header"></slot>
-        </view>
-        <view class="flex-1 min-h-1">
-          <!-- :style="{height: swiperHeight+'px'}" -->
-          <swiper :current="current" class="h-full" v-bind="swiperBindings"
-                @change="handleSwiperChange">
-            <swiper-item v-for="t in tabs" :key="t.name">
-                <!-- 延迟渲染 -->
-                <!-- 如果配置相同的template可共享卡槽 -->
-                <!-- 内容如果要支持滚动,请使用css class - .tabs-swiper-content -->
-                <keep-alive v-if="lazy">
-                    <slot v-if="t.show" :name="t.template||template||t.name" v-bind="t"/>
-                </keep-alive>
-                <slot v-else :name="t.template||template||t.name" v-bind="t"/>
-            </swiper-item>
+  <!-- NOTE:min-h-1在使用useElementSize时非常重要 -->
+  <view ref="container" class="h-full fx-col flex-1 min-h-1">
+    <uv-tabs :current="current" :list="tabs" :key-name="keyName" v-bind="tabBindings" class="bg-white bd-b-1"
+      @change="handleTabChange">
+      <template v-if="$slots.tab" #default="scope">
+        <slot name="tab" v-bind="scope" />
+      </template>
+    </uv-tabs>
+    <uv-line v-if="border" />
+    <view>
+      <slot name="header"></slot>
+    </view>
+    <view class="flex-1 min-h-1 relative">
+      <!-- :style="{height: swiperHeight+'px'}" -->
+      <view class="absolute inset-0">
+        <swiper :current="current" class="h-full" v-bind="swiperBindings" @change="handleSwiperChange">
+          <swiper-item v-for="t in tabs" :key="t.name">
+            <!-- 延迟渲染 -->
+            <!-- 如果配置相同的template可共享卡槽 -->
+            <!-- 内容如果要支持滚动,请使用css class - .tabs-swiper-content -->
+            <keep-alive v-if="lazy">
+              <slot v-if="t.show" :name="t.template || template || t.name" v-bind="t" />
+            </keep-alive>
+            <slot v-else :name="t.template || template || t.name" v-bind="t" />
+          </swiper-item>
         </swiper>
-        </view>
+      </view>
     </view>
+  </view>
 </template>
 
 <script setup>
-import {ref, computed, watch} from 'vue'
+import { ref, computed, watch } from 'vue'
 import _ from "lodash";
-import {createPropDefine} from "@/utils";
-import {useElementSize} from "@vueuse/core";
+import { createPropDefine } from "@/utils";
+import { useElementSize } from "@vueuse/core";
 
 const props = defineProps({
-    // support synchronization
-    modelValue: createPropDefine(0, Number),
-    tabs: createPropDefine([], Array),
-    keyName: createPropDefine('name'),
-    // other options of uv-tabs
-    tabOptions: createPropDefine(null, Object),
-    // other uni-app swiper options
-    swiperOptions: createPropDefine(null, Object),
-    // support lazy rendering, default is true
-    lazy: createPropDefine(true, Boolean),
-    // whether cache all tabs? if not use cacheSize, higher priority than cacheSize
-    cacheAll: createPropDefine(false, Boolean),
-    // cached accessed tab. <=0 means cache all.
-    cacheSize: createPropDefine(5, Number),
-    // tab content will render after delay time, recommended for complex dynamic content.
-    // related to lazy, default is true
-    delay: createPropDefine(true, Boolean),
-    preload: createPropDefine(true, Boolean), // 一般情况下preload会非常平滑,但有大请求时可以禁用
-    // bigger than the animation time。 default 400ms.
-    delayTime: createPropDefine(400, Number),
-    border: createPropDefine(false, Boolean),
-    tabsHeight: createPropDefine(44, Number),
-    // 统一指定模板,优先级低于tab.template,因为有时候让tab指定template会破坏原数据结构
-    template: createPropDefine('')
+  // support synchronization
+  modelValue: createPropDefine(0, Number),
+  tabs: createPropDefine([], Array),
+  keyName: createPropDefine('name'),
+  // other options of uv-tabs
+  tabOptions: createPropDefine(null, Object),
+  // other uni-app swiper options
+  swiperOptions: createPropDefine(null, Object),
+  // support lazy rendering, default is true
+  lazy: createPropDefine(true, Boolean),
+  // whether cache all tabs? if not use cacheSize, higher priority than cacheSize
+  cacheAll: createPropDefine(false, Boolean),
+  // cached accessed tab. <=0 means cache all.
+  cacheSize: createPropDefine(5, Number),
+  // tab content will render after delay time, recommended for complex dynamic content.
+  // related to lazy, default is true
+  delay: createPropDefine(true, Boolean),
+  preload: createPropDefine(true, Boolean), // 一般情况下preload会非常平滑,但有大请求时可以禁用
+  // bigger than the animation time。 default 400ms.
+  delayTime: createPropDefine(400, Number),
+  border: createPropDefine(false, Boolean),
+  tabsHeight: createPropDefine(44, Number),
+  // 统一指定模板,优先级低于tab.template,因为有时候让tab指定template会破坏原数据结构
+  template: createPropDefine('')
 })
 const emits = defineEmits(['update:modelValue', 'change'])
 
@@ -67,69 +68,68 @@ const emits = defineEmits(['update:modelValue', 'change'])
 const current = ref(0)
 const cachedTabs = ref([])
 const container = ref(null)
-const {height} = useElementSize(container)
+const { height } = useElementSize(container)
 const swiperHeight = computed(() => height.value - props.tabsHeight - (props.border ? 1 : 0))
 
 const tabBindings = computed(() => {
-    // make some default options for u-tabs here
-    return {
-        scrollable: props.tabs.length > 4,
-        itemStyle: {height: props.tabsHeight + 'px'},
-        ...props.tabOptions
-    }
+  // make some default options for u-tabs here
+  return {
+    scrollable: props.tabs.length > 4,
+    itemStyle: { height: props.tabsHeight + 'px' },
+    ...props.tabOptions
+  }
 })
 const swiperBindings = computed(() => {
-    // make some default options for uni-app swiper here
-    return {
-        ...props.swiperOptions
-    }
+  // make some default options for uni-app swiper here
+  return {
+    ...props.swiperOptions
+  }
 })
 
 // 保持localCurrent与props.current同步,即props优先级更高
-watch(() => props.modelValue, (val) => current.value = val, {immediate: true})
+watch(() => props.modelValue, (val) => current.value = val, { immediate: true })
 
 watch([current, () => props.tabs], ([current]) => {
-    const {cacheAll, cacheSize, tabs, delay, preload, delayTime} = props
-    if (!tabs.length) return // no data, wait for tabs ready.
+  const { cacheAll, cacheSize, tabs, delay, preload, delayTime } = props
+  if (!tabs.length) return // no data, wait for tabs ready.
 
-    // delay control, first tab must render immediately.
-    const effectDelay = cachedTabs.value.length && delay ? delayTime : 0
+  // delay control, first tab must render immediately.
+  const effectDelay = cachedTabs.value.length && delay ? delayTime : 0
 
-    // cache tabs, keep accessed sequence.
-    const next = [current]
-    if (preload) {
-        // keep current -1 +1 in cache list while preload=true.
-        // this will make swiper action much-much smooth.
-        if (current + 1 < tabs.length) next.unshift(current + 1)
-        if (current - 1 >= 0) next.unshift(current - 1)
-    }
-    _.pull(cachedTabs.value, ...next)
-    cachedTabs.value.push(...next)
-    while (!cacheAll && cacheSize && cachedTabs.value.length > cacheSize) {
-        cachedTabs.value.shift()
-    }
+  // cache tabs, keep accessed sequence.
+  const next = [current]
+  if (preload) {
+    // keep current -1 +1 in cache list while preload=true.
+    // this will make swiper action much-much smooth.
+    if (current + 1 < tabs.length) next.unshift(current + 1)
+    if (current - 1 >= 0) next.unshift(current - 1)
+  }
+  _.pull(cachedTabs.value, ...next)
+  cachedTabs.value.push(...next)
+  while (!cacheAll && cacheSize && cachedTabs.value.length > cacheSize) {
+    cachedTabs.value.shift()
+  }
 
-    // reset show property of all tabs
-    if (effectDelay) {
-        setTimeout(() => {
-            tabs.forEach((t, i) => t.show = cachedTabs.value.includes(i))
-        }, effectDelay)
-    } else {
-        tabs.forEach((t, i) => t.show = cachedTabs.value.includes(i))
-    }
-}, {immediate: true})
+  // reset show property of all tabs
+  if (effectDelay) {
+    setTimeout(() => {
+      tabs.forEach((t, i) => t.show = cachedTabs.value.includes(i))
+    }, effectDelay)
+  } else {
+    tabs.forEach((t, i) => t.show = cachedTabs.value.includes(i))
+  }
+}, { immediate: true })
 
-const handleTabChange = function ({index}) {
-    current.value = index
-    emits('update:modelValue', current.value)
-    emits('change', current.value)
+const handleTabChange = function ({ index }) {
+  current.value = index
+  emits('update:modelValue', current.value)
+  emits('change', current.value)
 }
 const handleSwiperChange = function (e) {
-    current.value = e.detail.current
-    emits('update:modelValue', current.value)
-    emits('change', current.value)
+  current.value = e.detail.current
+  emits('update:modelValue', current.value)
+  emits('change', current.value)
 }
 </script>
 
-<style>
-</style>
+<style></style>

+ 12 - 0
src/pages.json

@@ -667,6 +667,18 @@
           "style": {
             "navigationBarTitleText": ""
           }
+        },
+        {
+          "path": "pages/textbooks-practice/textbooks-practice",
+          "style": {
+            "navigationBarTitleText": ""
+          }
+        },
+        {
+          "path": "pages/textbooks-practice-history/textbooks-practice-history",
+          "style": {
+            "navigationBarTitleText": ""
+          }
         }
       ]
     }

+ 0 - 1
src/pagesMain/pages/index/components/index-banner.vue

@@ -43,7 +43,6 @@ const navigateTo = async (item: MenuItem) => {
   }
 }
 const validMenus = computed(() => {
-  console.log(userStore.isAuditor)
   const menus: MenuItem[] = [
     {
       name: '学习备考',

+ 1 - 1
src/pagesStudy/components/knowledge-tree-node.vue

@@ -9,7 +9,7 @@
             <view class="block text-28 text-fore-title font-bold ellipsis-1">{{ nodeData.name }}</view>
             <view class="mt-4 text-24 text-fore-light flex items-center">
               <progress class="w-100 rounded-full overflow-hidden" :percent="getProgressPercent(nodeData)"
-                :show-text="false" activeColor="#31a0fc" backgroundColor="#E3F4FA" />
+                :show-text="false" activeColor="#31a0fc" backgroundColor="#efefef" />
               <text class="ml-10 text-primary">{{ nodeData.finishedCount }}</text>
               <text>/{{ nodeData.questionCount }}道</text>
               <text class="ml-10">正确率</text>

+ 4 - 3
src/pagesStudy/components/knowledge-tree.vue

@@ -42,13 +42,14 @@ const ensureItemProperties = (item: Study.KnowledgeNode) => {
 
 // 初始化数据
 const initializeData = (sourceData: Study.KnowledgeNode[]): Study.KnowledgeNode[] => {
-  return sourceData.map(item => {
+  return sourceData.map((item, index) => {
+    const oldItem = initializedData.value[index];
     const children = initializeData(item.children || []);
     return {
       ...item,
-      isExpanded: item.isExpanded ?? false,
+      isExpanded: oldItem?.isExpanded ?? false,
       isLeaf: !item.children || item.children.length === 0,
-      actualHeight: item.actualHeight ?? 0,
+      actualHeight: oldItem?.actualHeight ?? 0,
       children
     };
   });

+ 3 - 2
src/pagesStudy/pages/exam-start/exam-start.vue

@@ -210,10 +210,11 @@ const handleSubmit = (tempSave: boolean = false) => {
           await nextTick();
           transferTo('/pagesStudy/pages/knowledge-practice-detail/knowledge-practice-detail', {
             data: {
+              paperType: prevData.value.paperType,
               examineeId: examineeId.value,
               name: prevData.value.practiceInfo?.name,
               directed: prevData.value.practiceInfo?.directed
-            },
+            } as Transfer.PracticeResultPageOptions,
             type: 'redirectTo'
           });
         }, 2500);
@@ -359,7 +360,7 @@ const handleGuideClose = () => {
 const loadData = async () => {
   uni.$ie.showLoading();
   const { paperType } = prevData.value;
-  if (paperType === EnumPaperType.PRACTICE) {
+  if (paperType === EnumPaperType.PRACTICE || paperType === EnumPaperType.COURSE) {
     loadPracticeData();
   } else if (paperType === EnumPaperType.SIMULATED) {
     loadSimulationData();

+ 8 - 1
src/pagesStudy/pages/index/compoentns/index-banner.vue

@@ -30,7 +30,10 @@
 import { useTransferPage } from '@/hooks/useTransferPage';
 import { getStudyPlan, getDirectedSchool } from '@/api/modules/study';
 import { OPEN_VIP_POPUP } from '@/types/injectionSymbols';
+import { useUserStore } from '@/store/userStore';
+
 const { transferTo } = useTransferPage();
+const userStore = useUserStore();
 const openVipPopup = inject(OPEN_VIP_POPUP);
 const handleOpenPlan = async () => {
   const { data } = await getStudyPlan();
@@ -45,7 +48,11 @@ const handleOpenPlan = async () => {
   }
 };
 const handleTest = () => {
-
+  if (userStore.isVip || userStore.isTeacher) {
+    transferTo('/pagesStudy/pages/textbooks-practice/textbooks-practice');
+  } else {
+    openVipPopup?.();
+  }
 };
 </script>
 <style lang="scss" scoped></style>

+ 3 - 2
src/pagesStudy/pages/knowledge-practice-detail/knowledge-practice-detail.vue

@@ -81,7 +81,7 @@ const handleQuestionDetail = (item: Study.Question) => {
   transferTo('/pagesStudy/pages/exam-start/exam-start', {
     data: {
       name: paperName.value,
-      paperType: EnumPaperType.PRACTICE,
+      paperType: prevData.value.paperType || EnumPaperType.PRACTICE,
       readonly: true,
       questionId: item.id,
       practiceInfo: {
@@ -96,12 +96,13 @@ const handleQuestionDetail = (item: Study.Question) => {
 const handleStartPractice = () => {
   const { knowledgeId } = examineeData.value || {};
   if (!knowledgeId) {
+    console.error('knowledgeId is null');
     return;
   }
   transferTo('/pagesStudy/pages/exam-start/exam-start', {
     data: {
       name: paperName.value,
-      paperType: EnumPaperType.PRACTICE,
+      paperType: prevData.value.paperType || EnumPaperType.PRACTICE,
       practiceInfo: {
         name: prevData.value.name,
         relateId: knowledgeId,

+ 3 - 3
src/pagesStudy/pages/knowledge-practice-history/knowledge-practice-history.vue

@@ -28,12 +28,14 @@ import { useTransferPage } from '@/hooks/useTransferPage';
 import { getPracticeHistory } from '@/api/modules/study';
 import { Study } from '@/types';
 import { Transfer } from '@/types';
+import { EnumPaperType } from '@/common/enum';
 const { prevData, transferTo } = useTransferPage<{}, Transfer.PracticeResultPageOptions>();
 const { baseStickyTop } = useNavbar();
 const historyList = ref<Study.PracticeHistory[]>([]);
 const handleViewHistory = (value: Study.PracticeHistory) => {
   transferTo('/pagesStudy/pages/knowledge-practice-detail/knowledge-practice-detail', {
     data: {
+      paperType: EnumPaperType.PRACTICE,
       examineeId: value.examineeId,
       name: value.paperName,
       directed: value.directed === 1
@@ -43,9 +45,7 @@ const handleViewHistory = (value: Study.PracticeHistory) => {
 const loadData = async () => {
   uni.$ie.showLoading();
   try {
-    const { rows } = await getPracticeHistory({
-      directed: true
-    });
+    const { rows } = await getPracticeHistory();
     historyList.value = rows.map(item => {
       return {
         ...item,

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

@@ -91,7 +91,7 @@ const handleStartPractice = async (node: Study.KnowledgeNode) => {
 watch(() => currentSubjectIndex.value, () => {
   loadKnowledgeList();
 }, {
-  immediate: true
+  immediate: false
 });
 
 const loadData = async () => {

+ 64 - 0
src/pagesStudy/pages/textbooks-practice-history/textbooks-practice-history.vue

@@ -0,0 +1,64 @@
+<template>
+  <ie-page bg-color="#F6F8FA" :fix-height="true">
+    <ie-navbar title="教材同步练习记录" />
+    <view class="mt-20">
+      <view v-for="(item, index) in historyList" :key="index"
+        class="bg-white px-40 py-30 flex items-center sibling-border-top">
+        <view class="flex-1">
+          <view class="text-28">
+            <text class=" text-fore-light">知识点:</text>
+            <text class="text-fore-title">{{ item.paperName }}</text>
+          </view>
+          <view class="mt-10 text-28">
+            <text class=" text-fore-light">完成时间:</text>
+            <text class="text-fore-title">{{ item.endTime }}</text>
+          </view>
+        </view>
+        <view class="text-24 text-white bg-primary w-fit px-40 py-12 rounded-full text-center"
+          @click="handleViewHistory(item)">
+          查看
+        </view>
+      </view>
+    </view>
+  </ie-page>
+</template>
+<script lang="ts" setup>
+import { useNavbar } from '@/hooks/useNavbar';
+import { useTransferPage } from '@/hooks/useTransferPage';
+import { getTextbooksPracticeHistory } from '@/api/modules/study';
+import { Study } from '@/types';
+import { Transfer } from '@/types';
+import { EnumPaperType } from '@/common/enum';
+const { prevData, transferTo } = useTransferPage<{}, Transfer.PracticeResultPageOptions>();
+const { baseStickyTop } = useNavbar();
+const historyList = ref<Study.PracticeHistory[]>([]);
+const handleViewHistory = (value: Study.PracticeHistory) => {
+  transferTo('/pagesStudy/pages/knowledge-practice-detail/knowledge-practice-detail', {
+    data: {
+      paperType: EnumPaperType.COURSE,
+      examineeId: value.examineeId,
+      name: value.paperName,
+      directed: value.directed === 1
+    } as Transfer.PracticeResultPageOptions,
+  });
+}
+const loadData = async () => {
+  uni.$ie.showLoading();
+  try {
+    const { rows } = await getTextbooksPracticeHistory();
+    historyList.value = rows.map(item => {
+      return {
+        ...item,
+        endTime: uni.$uv.timeFormat(item.endTime, 'yyyy-mm-dd hh:MM:ss')
+      } as Study.PracticeHistory;
+    });
+  } finally {
+    uni.$ie.hideLoading();
+  }
+}
+onLoad(() => {
+  console.log(prevData.value)
+  loadData();
+});
+</script>
+<style lang="scss" scoped></style>

+ 75 - 0
src/pagesStudy/pages/textbooks-practice/textbooks-practice.vue

@@ -0,0 +1,75 @@
+<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>
+      </view>
+    </view>
+    <view class="px-40">
+      <knowledgeTree :tree-data="treeData" @start-practice="handleStartPractice" />
+    </view>
+  </ie-page>
+</template>
+
+<script lang="ts" setup>
+import IePage from '@/components/ie-page/ie-page.vue';
+import { useTransferPage } from '@/hooks/useTransferPage';
+import { getTextbooksKnowledgeList } from '@/api/modules/study';
+import knowledgeTree from '@/pagesStudy/components/knowledge-tree.vue';
+import * as Study from '@/types/study';
+import { EnumPaperType } from '@/common/enum';
+import { useUserStore } from '@/store/userStore';
+const { prevData, transferTo } = useTransferPage();
+
+const userStore = useUserStore();
+const iePageRef = ref<InstanceType<typeof IePage>>();
+const pageTitle = computed(() => {
+  return '教材同步练习';
+});
+
+const treeData = ref<Study.KnowledgeNode[]>([]);
+
+const handleViewHistory = () => {
+  transferTo('/pagesStudy/pages/textbooks-practice-history/textbooks-practice-history', {
+    data: {}
+  });
+}
+const loadKnowledgeList = async () => {
+  try {
+    uni.$ie.showLoading();
+    const { data } = await getTextbooksKnowledgeList();
+    treeData.value = data as Study.KnowledgeNode[];
+  } catch (error) {
+    console.log(error);
+  } finally {
+    uni.$ie.hideLoading();
+  }
+}
+
+const handleStartPractice = async (node: Study.KnowledgeNode) => {
+  const isVip = await userStore.checkVip();
+  if (isVip) {
+    transferTo('/pagesStudy/pages/exam-start/exam-start', {
+      data: {
+        name: '教材同步练习-' + node.name,
+        paperType: EnumPaperType.COURSE,
+        practiceInfo: {
+          name: node.name,
+          relateId: node.id
+        },
+      }
+    });
+  } else {
+    iePageRef.value?.showVipPopup();
+  }
+}
+
+onShow(() => {
+  loadKnowledgeList();
+});
+</script>
+
+<style></style>

+ 5 - 1
src/pagesSystem/pages/login/login.vue

@@ -147,7 +147,7 @@ const handleLogin = async () => {
     submitLogin();
   } else if (loginType.value === 'card') {
     captchaRef.value.open();
-    userStore.rememberPwd = !!rememberPassword.value[0];
+    userStore.rememberLoginInfo(!!rememberPassword.value[0], cardNo.value, cardPassword.value);
     // submitLogin();
   }
 }
@@ -251,6 +251,10 @@ const handleValid = (data: { code: string; uuid: string }) => {
 
 onLoad(() => {
   rememberPassword.value[0] = userStore.rememberPwd;
+  if (userStore.rememberPwd) {
+    cardNo.value = userStore.cardNo;
+    cardPassword.value = userStore.cardPassword;
+  }
 });
 </script>
 

+ 12 - 0
src/store/userStore.ts

@@ -32,6 +32,8 @@ export const useUserStore = defineStore('ie-user', {
       examType: '',
     },
     rememberPwd: false,
+    cardPassword: '',
+    cardNo: '',
     directedSchoolList: [],
     practiceSettings: {
       reviewMode: EnumReviewMode.AFTER_SUBMIT,
@@ -214,6 +216,16 @@ export const useUserStore = defineStore('ie-user', {
         });
       });
     },
+    rememberLoginInfo(remember: boolean, cardNo: string, cardPassword: string) {
+      this.rememberPwd = remember;
+      if (remember) {
+        this.cardNo = cardNo;
+        this.cardPassword = cardPassword;
+      } else {
+        this.cardNo = '';
+        this.cardPassword = '';
+      }
+    },
     logout() {
       this.accessToken = null;
       this.user = null;

+ 2 - 0
src/types/index.ts

@@ -87,6 +87,8 @@ export interface UserStoreState {
     examType: string;
   };
   rememberPwd: boolean;
+  cardPassword: string;
+  cardNo: string;
   directedSchoolList: Study.DirectedSchool[];
   practiceSettings: Study.PracticeSettings;
 }

+ 1 - 0
src/types/transfer.ts

@@ -9,6 +9,7 @@ export interface PracticeResultPageOptions {
   examineeId: number;
   name: string;
   directed: boolean;
+  paperType: EnumPaperType;
 }
 
 /**