123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- import {computed, ref} from 'vue'
- import {createEventHook, injectLocal, provideLocal} from "@vueuse/core";
- import {empty} from "@/uni_modules/uv-ui-tools/libs/function/test";
- import {
- commitExamineePaper,
- commitExamineeQuestion,
- scoreExamineeQuestion,
- scoreFinish
- } from "@/api/webApi/studentEvaluating";
- import mxConst from "@/common/mxConst";
- import _ from "lodash";
- import {toast} from "@/uni_modules/uv-ui-tools/libs/function";
- const key = Symbol('PAPER_SERVICE')
- // 尽量保持只需要依靠paper/paper.questions中计算的相关API在paperService中
- // 与userData计算相关的API集中的questionService中
- export const useProvidePaperService = function (paperDataRef, overrideService = {}) {
- const paper = paperDataRef
- // 因为注入服务时paper可能还没有返回,为了方便注入时的有明确的属性名参考,这里将可能有用的属性抄了一遍。
- const props = {
- paperName: computed(() => paper.value?.name),
- allowAnswer: computed(() => paper.value?.allowAnswer),
- allowScore: computed(() => paper.value?.allowScore),
- questions: computed(() => paper.value?.questions || []),
- examineeId: computed(() => paper.value?.examineeId),
- examineeType: computed(() => paper.value?.examineeType),
- scoringType: computed(() => paper.value?.scoringType),
- remaining: computed(() => paper.value?.remaining),
- // for fast query by questionId
- questionsMap: computed(() => _.keyBy(props.questions.value, 'questionId'))
- }
- // 事件定义
- const events = {
- questionChange: createEventHook(), // display question change(index change)
- answerChange: createEventHook(), // user answered question
- answerComplete: createEventHook(), // all questions are answered
- scoreChange: createEventHook(), // user scored question
- scoreComplete: createEventHook(), // all questions are scored
- continueNext: createEventHook() // continue next paper
- }
- // data & service define
- const index = ref(0)
- const loading = ref(false)
- const current = computed(() => props.questions.value[index.value] || {})
- const hasNext = computed(() => index.value < props.questions.value.length - 1)
- const hasPrev = computed(() => index.value > 0)
- // methods
- const methods = {
- reset: () => {
- paper.value = {}
- index.value = 0
- loading.value = false
- },
- isObjective: (q) => mxConst.question.isObjective(q.typeId),
- isCheckbox: (q) => mxConst.question.isCheckbox(q.typeId),
- isRadio: (q) => mxConst.question.isRadio(q.typeId),
- isAnswerCorrect: (q) => q.answers?.length && q.answer == q.answers[0].toString(),
- tryGoNext: () => {
- if (!hasNext.value) return toast('已经是最后一题了')
- index.value += 1
- },
- tryGoPrev: () => {
- if (!hasPrev.value) return toast('已经是第一题了')
- index.value -= 1
- },
- goToQuestion: (q) => {
- const idx = props.questions.value.indexOf(q)
- if (idx > -1) index.value = idx
- },
- commitQuestion: async (commits) => {
- if (empty(commits)) return
- if (loading.value) return
- try {
- loading.value = true
- const examineeId = props.examineeId.value
- const examineeType = props.examineeType.value
- const commit = {examineeId, examineeType, questions: commits}
- await commitExamineeQuestion(commit)
- await events.answerChange.trigger(commits)
- } finally {
- loading.value = false
- }
- },
- commitPaper: async () => {
- if (loading.value) return
- try {
- // uni.showLoading() // 不需要,交卷时有自定义弹窗
- loading.value = true
- const examineeId = props.examineeId.value
- const examineeType = props.examineeType.value
- const commit = {examineeId, examineeType}
- await commitExamineePaper(commit)
- await events.answerComplete.trigger()
- } finally {
- loading.value = false
- // uni.hideLoading()
- }
- },
- scoreQuestion: async (commits) => {
- if (empty(commits)) return
- if (loading.value) return
- try {
- loading.value = true
- const examineeId = props.examineeId.value
- const examineeType = props.examineeType.value
- const commit = {examineeId, examineeType, questions: commits}
- await scoreExamineeQuestion(commit)
- await events.scoreChange.trigger(commits)
- } finally {
- loading.value = false
- }
- },
- scorePaper: async () => {
- if (loading.value) return
- try {
- uni.showLoading()
- loading.value = true
- const examineeId = props.examineeId.value
- const examineeType = props.examineeType.value
- const commit = {examineeId, examineeType}
- await scoreFinish(commit)
- await events.scoreComplete.trigger()
- } finally {
- loading.value = false
- uni.hideLoading()
- }
- },
- triggerContinueNext: async () => {
- await events.continueNext.trigger()
- }
- }
- // api that should combine `props` & `methods`
- const extend = {
- isAllObjective: computed(() => {
- return props.questions.value.every(q => methods.isObjective(q))
- }),
- answerCompletedTips: computed(() => {
- const type = props.scoringType.value + ''
- const source = {
- "1": `客观题已自动计分,主观题需要手动计分`,
- "2": `此卷为老师阅卷,需要学生交卷后老师进行阅卷计分`,
- "3": `此卷为系统阅卷,提交后系统自动计分`
- }
- return source[type] || source['1']
- })
- }
- const options = {
- loading,
- paper,
- ...props,
- onAnswerChange: events.answerChange.on,
- onAnswerComplete: events.answerComplete.on,
- onScoreChange: events.scoreChange.on,
- onScoreComplete: events.scoreComplete.on,
- onContinueNext: events.continueNext.on,
- index,
- current,
- hasNext,
- hasPrev,
- ...methods,
- ...extend,
- ...overrideService
- }
- provideLocal(key, options)
- return options
- }
- export const useInjectPaperService = function () {
- return injectLocal(key)
- }
|