瀏覽代碼

答题,考试结果简单界面

ChengYuXuan 5 年之前
父節點
當前提交
c0c6f111f7

+ 1 - 0
package.json

@@ -12,6 +12,7 @@
     "@mdi/js": "^5.8.55",
     "axios": "^0.21.1",
     "core-js": "^3.6.5",
+    "echarts": "^5.0.1",
     "marked": "^1.2.7",
     "monaco-editor": "^0.21.2",
     "monaco-editor-webpack-plugin": "^2.1.0",

+ 26 - 1
src/api/axios.config.ts

@@ -1,6 +1,9 @@
-import axios, { AxiosError, AxiosInstance, AxiosResponse } from 'axios'
+import axios, { AxiosError, AxiosResponse } from 'axios'
+import store from '@/store/index'
 
 export default function axiosConfig() {
+  axios.defaults.withCredentials = true
+
   axios.interceptors.response.use(
     function(response: AxiosResponse) {
       if (process.env.NODE_ENV === 'development') {
@@ -30,6 +33,28 @@ export default function axiosConfig() {
       return Promise.reject(error)
     }
   )
+
+  axios.interceptors.request.use(
+    function(config) {
+      if (process.env.NODE_ENV === 'development') {
+        console.log('[AXIOS] request config: ', config)
+      }
+      if (store.state.token) {
+        config.headers = {
+          Authorization: store.state.token,
+          ...(config.headers ?? {})
+        }
+      }
+      return config
+    },
+    // Do something with request error
+    function(error) {
+      if (process.env.NODE_ENV === 'development') {
+        console.error('[AXIOS] request error: ', error)
+      }
+      return Promise.reject(error)
+    }
+  )
 }
 
 const portal = process.env.portalUrl

+ 3 - 1
src/api/exam.ts

@@ -9,7 +9,9 @@ import {
   ExamQuestionSerializer
 } from '@/api/types'
 
-export const getAllExamList = (params: Pageable<{ status: ExamStatus }>) => {
+export const getAllExamList = (
+  params: Pageable<{ status?: ExamStatus; id?: ID }>
+) => {
   return axios.get<ReceivedData<Array<ExamSerializer>>>(`${EXAM_MODULE}`, {
     params
   })

+ 3 - 3
src/mock/serializers.js

@@ -131,9 +131,9 @@ const serializersPlugin = (mock) => ({
   EXAM_QUESTION_SERIALIZER: () =>
     mock({
       'id|1-1000': 1,
-      'singleChoiceQuestions|10': ['@SINGLE_CHOICE_QUESTION_SERIALIZER'],
-      'multiChoiceQuestions|5': ['@MULTI_CHOICE_QUESTION_SERIALIZER'],
-      'codeQuestions|2': ['@CODE_QUESTION_SERIALIZER']
+      'singleChoiceQuestions|15': ['@SINGLE_CHOICE_QUESTION_SERIALIZER'],
+      'multiChoiceQuestions|10': ['@MULTI_CHOICE_QUESTION_SERIALIZER'],
+      'codeQuestions|3': ['@CODE_QUESTION_SERIALIZER']
     }),
   QUESTION_DETAIL_SERIALIZER: () => {
     mock({

+ 3 - 2
src/router/exam.ts

@@ -31,8 +31,9 @@ const routes: Array<RouteConfig> = [
       },
       {
         path: 'result',
-        name: 'result'
-        // component: ()=> import(/*webpackChunkName: "exam"*/ '@/views/exam')
+        name: 'result',
+        component: () =>
+          import(/*webpackChunkName: "exam"*/ '@/views/exam/PersonalResult.vue')
       }
     ]
   }

+ 9 - 0
src/router/index.ts

@@ -3,6 +3,7 @@ import VueRouter, { RouteConfig } from 'vue-router'
 import student from '@/router/student'
 import exam from '@/router/exam'
 import teacher from '@/router/teacher'
+import store from '@/store/index'
 Vue.use(VueRouter)
 
 const routes: Array<RouteConfig> = [
@@ -22,4 +23,12 @@ const router = new VueRouter({
   routes
 })
 
+router.beforeEach((to, from, next) => {
+  const { id_token } = to.query
+  if (id_token) {
+    store.commit('setToken', id_token)
+  }
+  next()
+})
+
 export default router

+ 2 - 1
src/store/index.ts

@@ -22,7 +22,8 @@ export const mutations: MutationTree<RootState> = {
 
 export const getters: GetterTree<RootState, RootState> = {
   isStudent: (state) => state.user.role === 'STUDENT',
-  isTeacher: (state) => state.user.role === 'TEACHER'
+  isTeacher: (state) => state.user.role === 'TEACHER',
+  getId: (state) => state.user.id
 }
 
 export default new Vuex.Store({

+ 12 - 0
src/views/Home.vue

@@ -15,6 +15,7 @@
 import Vue from 'vue'
 import Login from '@/views/portal/Login.vue'
 import Register from '@/views/portal/Register.vue'
+import { mapMutations } from 'vuex'
 export default Vue.extend({
   name: 'Home',
   components: {
@@ -23,6 +24,17 @@ export default Vue.extend({
   },
   data() {
     return {}
+  },
+  methods: {
+    ...mapMutations(['setToken', 'setUser'])
+  },
+  beforeRouteLeave(to, from, next) {
+    const { id_token } = to.query
+    if (id_token) {
+      this.setToken(id_token)
+    }
+
+    next()
   }
 })
 </script>

+ 9 - 4
src/views/exam/ExamDetails.vue

@@ -6,11 +6,14 @@
           <v-spacer></v-spacer>
           <v-col cols="3">
             <v-btn color="info" @click="onJoinExam" :loading="joining"
-              >参加考试</v-btn
+              >报名参加</v-btn
             >
           </v-col>
           <v-col cols="3">
-            <router-link :to="{ name: 'exam-pane' }">
+            <router-link
+              :to="{ name: 'exam-pane' }"
+              style="text-decoration: none;"
+            >
               <v-btn color="success">进入考试</v-btn>
             </router-link>
           </v-col>
@@ -32,11 +35,13 @@
         }}
         小时</v-card-text
       >
+
+      <v-card-subtitle class="text-h5 black--text">考试规则</v-card-subtitle>
+      <v-card-text>{{ examInfo.comment }}</v-card-text>
+      <v-card-subtitle class="text-h5 black--text">考试内容</v-card-subtitle>
       <v-card-text class="text-body-1 black--text">
         单选题 道 多选题 道 编程题 道
       </v-card-text>
-      <v-card-subtitle class="text-h5 black--text">考试规则</v-card-subtitle>
-      <v-card-subtitle class="text-h5 black--text">考试内容</v-card-subtitle>
     </v-card>
   </v-container>
 </template>

+ 38 - 41
src/views/exam/ExamPane.vue

@@ -1,6 +1,6 @@
 <template>
   <div>
-    <v-app-bar dense app class="indigo lighten-5">
+    <v-app-bar dense app>
       <v-row>
         <v-col>
           <span class="display-1">{{ examInfo.title }}</span>
@@ -10,6 +10,7 @@
             class="align-self-center"
             :current-time="currentTime"
             :end-time="endTime"
+            @timesUp="onTimesUp"
           ></count-down>
         </v-col>
       </v-row>
@@ -139,39 +140,27 @@
     <v-main class="indigo lighten-5 pa-0">
       <v-container fluid class="pa-2" v-if="currentQuestionIndex >= 0">
         <choice-pane
-          ref="choicePane"
           v-show="isChoiceProblem"
           @nextQuestion="nextQuestion"
           @saveChoiceAnswer="saveChoiceAnswer"
           :total-question-num="curTypeQuestionNum"
           :question="curChoiceQuestion"
         ></choice-pane>
-        <template v-show="!isChoiceProblem">
-          <!--          用一个不显示的tabs,同时渲染所有的代码题面板,控制代码题的切换,使得代码切换保留已写代码-->
-          <!--          <v-tabs v-show="false" v-model="codeIndex">-->
-          <!--            <v-tab v-for="i in codeQuestionNum" :key="i"> {{ i }}</v-tab>-->
-          <!--          </v-tabs>-->
-          <v-window v-model="codeIndex">
-            <v-window-item v-for="i in codeQuestionNum" :key="i">
-              <code-pane
-                :question="codeQuestions[i - 1]"
-                :total-question-num="curTypeQuestionNum"
-                @nextQuestion="nextQuestion"
-                @submitCode="saveSubmittedCode"
-              ></code-pane>
-            </v-window-item>
-          </v-window>
-          <!--          <v-tabs-items v-model="codeIndex">-->
-          <!--            <v-tab-item v-for="i in codeQuestionNum" :key="i">-->
-          <!--              <code-pane-->
-          <!--                :question="codeQuestions[i - 1]"-->
-          <!--                :total-question-num="curTypeQuestionNum"-->
-          <!--                @nextQuestion="nextQuestion"-->
-          <!--                @submitCode="saveSubmittedCode"-->
-          <!--              ></code-pane>-->
-          <!--            </v-tab-item>-->
-          <!--          </v-tabs-items>-->
-        </template>
+        <!--   先用v-if(codeIndex只在初始为负数),再用v-show。只用v-show的时候,会出现第一个代码题editor无法渲染的问题,原因未知-->
+        <v-window
+          :value="codeIndex"
+          v-if="codeIndex >= 0"
+          v-show="!isChoiceProblem"
+        >
+          <v-window-item v-for="i in codeQuestionNum" :key="i">
+            <code-pane
+              :question="codeQuestions[i - 1]"
+              :total-question-num="curTypeQuestionNum"
+              @nextQuestion="nextQuestion"
+              @submitCode="saveSubmittedCode"
+            ></code-pane>
+          </v-window-item>
+        </v-window>
       </v-container>
       <v-snackbar v-model="noticeUnfinished">
         还有题目未作答
@@ -214,7 +203,6 @@ export default Vue.extend({
       singleChoiceQuestions: [] as Array<ChoiceQuestionSerializer>,
       multiChoiceQuestions: [] as Array<ChoiceQuestionSerializer>,
       codeQuestions: [] as Array<CodeQuestionSerializer>,
-      allQuestions: [] as Array<QuestionSerializer>,
       answeredChoices: [] as Array<{ index: number; answered: boolean }>,
       answeredCodes: [] as Array<{ index: number; answered: boolean }>,
       answerStatus: [] as Array<{ index: number; answered: boolean }>,
@@ -277,12 +265,17 @@ export default Vue.extend({
       }
     },
     currentQuestionIndex(val) {
-      if (val > this.choiceQuestionNum) {
+      console.log('before ' + this.codeIndex)
+      if (val >= this.choiceQuestionNum) {
         this.codeIndex = val - this.choiceQuestionNum
       }
+      console.log(this.codeIndex)
     }
   },
   methods: {
+    onTimesUp() {
+      this.submitAnswer()
+    },
     saveSubmittedCode(code: string, lang: string) {
       const changedCodeQuestion = this.codeQuestions[this.codeIndex]
       const changedCodeTuple =
@@ -292,6 +285,10 @@ export default Vue.extend({
       changedCodeTuple.code = code
     },
     saveChoiceAnswer(answer: string | undefined) {
+      if (this.currentQuestionIndex >= this.choiceQuestionNum) {
+        return
+      }
+
       if (answer === undefined) {
         return
       }
@@ -304,11 +301,7 @@ export default Vue.extend({
       }
     },
     onSelectQuestion(target: number) {
-      // this.saveAnswer()
       this.currentQuestionIndex = target - 1
-      if (!this.isChoiceProblem) {
-        this.codeIndex = target - 1 - this.choiceQuestionNum
-      }
     },
     leaveExam() {
       this.exitDialog = false
@@ -342,13 +335,17 @@ export default Vue.extend({
       console.log(codes)
       this.$router.back()
     },
+    prevQuestion() {
+      do {
+        this.currentQuestionIndex =
+          (--this.currentQuestionIndex + this.totalQuestionNum) %
+          this.totalQuestionNum
+      } while (this.answerStatus[this.currentQuestionIndex].answered)
+    },
     nextQuestion() {
-      // if (this.isChoiceProblem) {
-      //   this.saveAnswer(answer.toString())
-      // }
       do {
         this.currentQuestionIndex =
-          ++this.currentQuestionIndex % this.totalQuestionNum
+          (this.currentQuestionIndex + 1) % this.totalQuestionNum
       } while (this.answerStatus[this.currentQuestionIndex].answered)
     },
     fetchData() {
@@ -378,7 +375,7 @@ export default Vue.extend({
               return { ...value, index: index + 1 }
             }) ?? []
 
-          this.allQuestions = [
+          const allQuestions = [
             ...this.singleChoiceQuestions,
             ...this.multiChoiceQuestions,
             ...this.codeQuestions
@@ -390,7 +387,7 @@ export default Vue.extend({
             return { index: index + 1, answer: '' }
           })
 
-          this.answerStatus = this.allQuestions.map((value, index) => {
+          this.answerStatus = allQuestions.map((value, index) => {
             return {
               index: index + 1,
               answered: false
@@ -398,7 +395,7 @@ export default Vue.extend({
           })
 
           this.currentQuestionIndex = 0 // 表示数据初始化完成
-          this.codeIndex = -1
+          console.log(this.codeIndex)
         })
         .catch(() => {
           console.log('No data')

+ 173 - 0
src/views/exam/PersonalResult.vue

@@ -0,0 +1,173 @@
+<template>
+  <v-container>
+    <page-header title="评测报告" :breadcrumb="breadcrumb">
+      <template #extra>
+        <v-row justify="end">
+          <v-col cols="2">
+            <router-link to="/student/exams">
+              <v-btn color="error">返回</v-btn>
+            </router-link>
+          </v-col>
+        </v-row>
+      </template>
+    </page-header>
+    <v-row class="mb-5">
+      <v-col class="d-flex flex-column justify-space-between">
+        <v-card> <div class="rank" ref="grade"></div></v-card>
+        <v-card class="rank" ref="rank"> 排名情况</v-card>
+      </v-col>
+      <v-spacer></v-spacer>
+      <v-col cols="6">
+        <v-card class="cv"> 个人简历</v-card>
+      </v-col>
+    </v-row>
+
+    <v-card>
+      <div class="skill" ref="skill"></div>
+    </v-card>
+  </v-container>
+</template>
+
+<script lang="ts">
+import Vue from 'vue'
+import PageHeader from '@/components/PageHeader.vue'
+import * as echarts from 'echarts'
+export default Vue.extend({
+  name: 'PersonalResult',
+  components: {
+    PageHeader
+  },
+  data() {
+    return {
+      breadcrumb: [
+        {
+          text: '主页',
+          disabled: false,
+          href: '/student/home'
+        },
+        {
+          text: '评测列表',
+          disabled: false,
+          href: '/student/exams'
+        },
+        {
+          text: '成绩报告',
+          disabled: true,
+          href: '/'
+        }
+      ]
+    }
+  },
+  mounted() {
+    const skillRefs = this.$refs.skill
+    const skillChart = echarts.init(skillRefs as HTMLElement)
+    const skillChartOption = {
+      title: {
+        text: '知识点掌握情况'
+      },
+      tooltip: {
+        trigger: 'axis',
+        axisPointer: {
+          // 坐标轴指示器,坐标轴触发有效
+          type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
+        }
+      },
+      legend: {
+        data: ['个人正确率', '平均正确率']
+      },
+      grid: {
+        left: '3%',
+        right: '4%',
+        bottom: '3%',
+        containLabel: true
+      },
+      xAxis: [
+        {
+          type: 'category',
+          data: ['数据结构', '网络', '操作系统', '测试', '设计模式']
+        }
+      ],
+      yAxis: [
+        {
+          type: 'value'
+        }
+      ],
+      series: [
+        {
+          name: '个人正确率',
+          type: 'bar',
+          data: [50, 33, 31, 34, 39]
+        },
+        {
+          name: '平均正确率',
+          type: 'bar',
+          data: [12, 13, 10, 14, 90]
+        }
+      ]
+    }
+    skillChart.setOption(skillChartOption)
+
+    const gradeRefs = this.$refs.grade
+    const gradeChart = echarts.init(gradeRefs as HTMLElement)
+    const gradeChartOptions = {
+      tooltip: {
+        trigger: 'item',
+        formatter: '{a}{b}: {c} ({d}%)'
+      },
+      title: {
+        text: '正确率',
+        left: 'right'
+      },
+      legend: {
+        orient: 'vertical',
+        left: 10,
+        data: ['错误', '正确']
+      },
+      series: [
+        {
+          name: '',
+          type: 'pie',
+          radius: ['50%', '70%'],
+          avoidLabelOverlap: false,
+          label: {
+            show: false
+          },
+          emphasis: {
+            label: {
+              show: true,
+              fontSize: '15',
+              fontWeight: 'bold'
+            }
+          },
+          labelLine: {
+            show: false
+          },
+          data: [
+            { value: 20, name: '错误' },
+            { value: 80, name: '正确' }
+          ]
+        }
+      ]
+    }
+
+    gradeChart.setOption(gradeChartOptions)
+  }
+})
+</script>
+
+<style scoped>
+.rank {
+  width: 20vw;
+  height: 15vh;
+}
+
+.cv {
+  /*width: 30vw;*/
+  height: 40vh;
+}
+
+.skill {
+  /*width: 800px;*/
+  height: 35vh;
+}
+</style>

+ 4 - 2
src/views/exam/components/CountDown.vue

@@ -39,14 +39,16 @@ export default {
       if (this.currentTime === 0) {
         this.content = '加载中...'
       } else {
-        this.current = this.currentTime
-        this.end = this.endTime
+        this.current = new Date().getTime() / 1000
+        // this.current = this.currentTime
+        this.end = this.current + 500
         this.countDown()
       }
     },
     countDown() {
       const self = this
       const timer = setInterval(function() {
+        const realTime = new Date().getTime() / 1000
         const nowTime = new Date(self.current * 1000)
         const endTime = new Date(self.end * 1000)
         const t = endTime.getTime() - nowTime.getTime()

+ 27 - 14
src/views/student/Info.vue

@@ -1,6 +1,20 @@
 <template>
   <v-container>
-    <page-header title="Info" :breadcrumb="breadcrumb"></page-header>
+    <page-header title="个人信息" :breadcrumb="breadcrumb"></page-header>
+    <v-row class="mb-10">
+      <v-col class="d-flex flex-column justify-space-between">
+        <v-card style="height: 40%"> 参与评测次数</v-card>
+        <v-card style="height: 40%"> 平均排名</v-card>
+      </v-col>
+      <v-col class="d-flex flex-column justify-space-between">
+        <v-card style="height: 100%"> 我参加的评测</v-card>
+      </v-col>
+      <v-col cols="6">
+        <v-card class="cv"> 个人简历</v-card>
+      </v-col>
+    </v-row>
+
+    <v-card class="skill"> 知识点掌握情况</v-card>
   </v-container>
 </template>
 
@@ -15,21 +29,20 @@ export default Vue.extend({
   },
   data() {
     return {
-      breadcrumb: [
-        {
-          text: 'Home',
-          disabled: false,
-          href: '/'
-        },
-        {
-          text: 'Info',
-          disabled: true,
-          href: '/'
-        }
-      ]
+      breadcrumb: []
     }
   }
 })
 </script>
 
-<style scoped></style>
+<style scoped>
+.cv {
+  /*width: 30vw;*/
+  height: 40vh;
+}
+
+.skill {
+  /*width: 50vw;*/
+  height: 35vh;
+}
+</style>

+ 0 - 5
src/views/student/StudentHome.vue

@@ -81,11 +81,6 @@ export default Vue.extend({
         name: '评测',
         url: '/student/exams',
         icon: mdiViewList
-      },
-      {
-        name: '题目练习',
-        url: '/student/practice',
-        icon: mdiDetails
       }
     ]
   })

+ 30 - 8
src/views/student/components/StudentExamInfoCard.vue

@@ -7,19 +7,27 @@
           >已结束</v-chip
         >
       </v-col>
-      <v-col align="end" class="mr-3">
-        <v-btn color="primary" class="mx-2" @click="showExamDetail"
-          >查看详情</v-btn
-        >
+      <v-col class="mr-3 d-flex justify-end">
         <v-btn
-          color="secondary"
+          color="success"
           class="mx-2"
           v-if="examInfo.joined === true"
           @click="showExamDetail"
           >开始评测</v-btn
         >
-        <v-btn color="info" class="mx-2" v-else @click="onJoinExam"
-          >参加评测</v-btn
+        <v-btn color="info" v-else @click="onJoinExam" class="mx-2"
+          >报名参加</v-btn
+        >
+        <v-btn
+          v-if="examInfo.status === 'FINISHED'"
+          color="secondary"
+          class="mx-2"
+          @click="onOpenResult"
+        >
+          结果报告
+        </v-btn>
+        <v-btn v-else color="primary" @click="showExamDetail" class="mx-2"
+          >查看详情</v-btn
         >
       </v-col>
     </v-row>
@@ -71,6 +79,16 @@ export default Vue.extend({
   },
   methods: {
     onJoinExam() {},
+    onOpenResult() {
+      const examId = this.examInfo.id?.toString() ?? ''
+
+      this.$router.push({
+        name: 'result',
+        params: {
+          id: examId
+        }
+      })
+    },
     showExamDetail() {
       const examId = this.examInfo.id?.toString()
       if (examId !== undefined) {
@@ -86,4 +104,8 @@ export default Vue.extend({
 })
 </script>
 
-<style scoped></style>
+<style scoped>
+.router-link-active {
+  text-decoration: none;
+}
+</style>

+ 3 - 1
src/views/teacher/ExamManage.vue

@@ -48,6 +48,7 @@ import PageHeader from '@/components/PageHeader.vue'
 import TeacherExamInfoCard from '@/views/teacher/components/TeacherExamInfoCard.vue'
 import { ExamSerializer, PageSerializer } from '@/api/types'
 import { getAllExamList } from '@/api/exam'
+import { mapGetters } from 'vuex'
 
 export default Vue.extend({
   name: 'ExamManage',
@@ -78,6 +79,7 @@ export default Vue.extend({
     }
   },
   methods: {
+    ...mapGetters(['getId']),
     changePage() {
       this.fetchExams()
     },
@@ -86,7 +88,7 @@ export default Vue.extend({
       this.$router.push('/teacher/exam-create')
     },
     fetchExams(page: number = 1) {
-      getAllExamList({ page, limit: 10, status: 'READY' })
+      getAllExamList({ page, limit: 10, id: this.getId() })
         .then(({ data }) => {
           this.examList = data.res ?? []
           this.pageInfo = data.page ?? {}

+ 11 - 4
src/views/teacher/components/TeacherExamInfoCard.vue

@@ -7,13 +7,17 @@
           >已结束</v-chip
         >
       </v-col>
-      <v-col align="end" class="mr-3">
-        <v-btn color="primary" class="mx-2" @click="showExamDetail"
-          >查看详情</v-btn
-        >
+      <v-col class="mr-3 d-flex justify-end">
         <v-btn
+          v-if="examInfo.status === 'FINISHED'"
           color="secondary"
           class="mx-2"
+        >
+          结果报告
+        </v-btn>
+        <v-btn
+          color="warning"
+          class="mx-2"
           v-if="examInfo.status === 'AVAILABLE'"
           @click="onExtendTime"
           >延长时间</v-btn
@@ -21,6 +25,9 @@
         <v-btn color="info" class="mx-2" v-if="examInfo.status === 'READY'"
           >修改评测</v-btn
         >
+        <v-btn color="primary" class="mx-2" @click="showExamDetail"
+          >查看详情</v-btn
+        >
       </v-col>
     </v-row>
     <v-row justify="space-between" dense>

+ 20 - 0
yarn.lock

@@ -3532,6 +3532,14 @@ ecc-jsbn@~0.1.1:
     jsbn "~0.1.0"
     safer-buffer "^2.1.0"
 
+echarts@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.npm.taobao.org/echarts/download/echarts-5.0.1.tgz#b999ff6f515b1aa851ed09576eaf89686b57ce97"
+  integrity sha1-uZn/b1FbGqhR7QlXbq+JaGtXzpc=
+  dependencies:
+    tslib "2.0.3"
+    zrender "5.0.3"
+
 ee-first@1.1.1:
   version "1.1.1"
   resolved "https://registry.npm.taobao.org/ee-first/download/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@@ -8760,6 +8768,11 @@ ts-toolbelt@^6.15.1:
   resolved "https://registry.npm.taobao.org/ts-toolbelt/download/ts-toolbelt-6.15.5.tgz?cache=0&sync_timestamp=1601987713799&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fts-toolbelt%2Fdownload%2Fts-toolbelt-6.15.5.tgz#cb3b43ed725cb63644782c64fbcad7d8f28c0a83"
   integrity sha1-yztD7XJctjZEeCxk+8rX2PKMCoM=
 
+tslib@2.0.3:
+  version "2.0.3"
+  resolved "https://registry.npm.taobao.org/tslib/download/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c"
+  integrity sha1-jgdBrEX8DCJuWKF7/D5kubxsphw=
+
 tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0:
   version "1.14.1"
   resolved "https://registry.npm.taobao.org/tslib/download/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
@@ -9560,3 +9573,10 @@ yorkie@^2.0.0:
     is-ci "^1.0.10"
     normalize-path "^1.0.0"
     strip-indent "^2.0.0"
+
+zrender@5.0.3:
+  version "5.0.3"
+  resolved "https://registry.npm.taobao.org/zrender/download/zrender-5.0.3.tgz?cache=0&sync_timestamp=1610459235695&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fzrender%2Fdownload%2Fzrender-5.0.3.tgz#5e04a55d36455067e4536c8ce9c25093f50f6b68"
+  integrity sha1-XgSlXTZFUGfkU2yM6cJQk/UPa2g=
+  dependencies:
+    tslib "2.0.3"