|
@@ -0,0 +1,204 @@
|
|
|
+<template>
|
|
|
+ <div
|
|
|
+ v-if="store.currentTask"
|
|
|
+ style="
|
|
|
+ max-width: 250px;
|
|
|
+ min-width: 250px;
|
|
|
+ border: 1px solid grey;
|
|
|
+ padding-left: 6px;
|
|
|
+ padding-right: 6px;
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <div>
|
|
|
+ <h1 class="text-3xl text-center" @click="toggleKeyMouse">键盘给分</h1>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <h1 class="text-3xl text-center">
|
|
|
+ 总分:{{ store.currentMarkResult?.markerScore || 0 }}
|
|
|
+ </h1>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div v-if="store.currentTask && store.currentTask.questionList">
|
|
|
+ <template
|
|
|
+ v-for="(question, index) in store.currentTask?.questionList"
|
|
|
+ :key="index"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ @click="chooseQuestion(question)"
|
|
|
+ class="question rounded p-1 mb-2"
|
|
|
+ :class="isCurrentQuestion(question) && 'current-question'"
|
|
|
+ >
|
|
|
+ <div class="flex justify-between">
|
|
|
+ <div>
|
|
|
+ <div>
|
|
|
+ {{ question.title }} {{ question.mainNumber }}-{{
|
|
|
+ question.subNumber
|
|
|
+ }}
|
|
|
+ </div>
|
|
|
+ <div class="text-center text-3xl">
|
|
|
+ {{ question.score || 0 }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <div class="text-center">间隔{{ question.intervalScore }}分</div>
|
|
|
+ <div class="text-3xl">
|
|
|
+ {{ question.minScore }} ~ {{ question.maxScore }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script lang="ts">
|
|
|
+import { Question } from "@/types";
|
|
|
+import { isNumber } from "lodash";
|
|
|
+import { computed, defineComponent, onMounted, onUnmounted, watch } from "vue";
|
|
|
+import { findCurrentTaskMarkResult, store } from "./store";
|
|
|
+
|
|
|
+export default defineComponent({
|
|
|
+ name: "MarkBoardKeyBoard",
|
|
|
+ emits: ["submit"],
|
|
|
+ setup(props, { emit }) {
|
|
|
+ function toggleKeyMouse() {
|
|
|
+ if (store.setting.uiSetting["normal.mode"] === "keyboard") {
|
|
|
+ store.setting.uiSetting["normal.mode"] = "mouse";
|
|
|
+ } else {
|
|
|
+ store.setting.uiSetting["normal.mode"] = "keyboard";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const markResult = findCurrentTaskMarkResult();
|
|
|
+
|
|
|
+ const questionScoreSteps = computed(() => {
|
|
|
+ const question = store.currentQuestion;
|
|
|
+ if (!question) return [];
|
|
|
+
|
|
|
+ const steps = [];
|
|
|
+ for (
|
|
|
+ let i = 0;
|
|
|
+ i <= question.maxScore - question.score;
|
|
|
+ i += question.intervalScore
|
|
|
+ ) {
|
|
|
+ steps.push(i);
|
|
|
+ }
|
|
|
+ if ((question.maxScore - question.score) % question.intervalScore !== 0) {
|
|
|
+ steps.push(question.maxScore - question.score);
|
|
|
+ }
|
|
|
+
|
|
|
+ return steps;
|
|
|
+ });
|
|
|
+
|
|
|
+ function isCurrentQuestion(question: Question) {
|
|
|
+ return (
|
|
|
+ store.currentQuestion?.mainNumber === question.mainNumber &&
|
|
|
+ store.currentQuestion?.subNumber === question.subNumber
|
|
|
+ );
|
|
|
+ }
|
|
|
+ watch(
|
|
|
+ () => store.currentTask,
|
|
|
+ () => {
|
|
|
+ store.currentQuestion = undefined;
|
|
|
+ store.currentScore = undefined;
|
|
|
+ }
|
|
|
+ );
|
|
|
+ watch(
|
|
|
+ () => store.currentQuestion,
|
|
|
+ () => {
|
|
|
+ store.currentScore = undefined;
|
|
|
+ }
|
|
|
+ );
|
|
|
+ function chooseQuestion(question: Question) {
|
|
|
+ store.currentQuestion = question;
|
|
|
+ }
|
|
|
+
|
|
|
+ let keyPressTimestamp = 0;
|
|
|
+ let keys: string[] = [];
|
|
|
+ function numberKeyListener(event: KeyboardEvent) {
|
|
|
+ // console.log(event);
|
|
|
+ if (!store.currentQuestion || !store.currentTask) return;
|
|
|
+
|
|
|
+ // 处理Enter跳下一题或submit
|
|
|
+ if (event.key === "Enter") {
|
|
|
+ if (!isNumber(store.currentQuestion.score)) {
|
|
|
+ // 当前题赋分不通过,Enter无效
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const idx = store.currentTask?.questionList.findIndex(
|
|
|
+ (q) =>
|
|
|
+ q.mainNumber === store.currentQuestion?.mainNumber &&
|
|
|
+ q.subNumber === store.currentQuestion.subNumber
|
|
|
+ );
|
|
|
+ if (idx + 1 === store.currentTask?.questionList.length) {
|
|
|
+ submit();
|
|
|
+ } else {
|
|
|
+ chooseQuestion(store.currentTask.questionList[idx + 1]);
|
|
|
+ }
|
|
|
+ keys = [];
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (event.timeStamp - keyPressTimestamp > 1.5 * 1000) {
|
|
|
+ keys = [];
|
|
|
+ }
|
|
|
+ keyPressTimestamp = event.timeStamp;
|
|
|
+ keys.push(event.key);
|
|
|
+ if (isNaN(parseFloat(keys.join("")))) {
|
|
|
+ keys = [];
|
|
|
+ }
|
|
|
+ if (event.key === "Escape") {
|
|
|
+ keys = [];
|
|
|
+ }
|
|
|
+ const score = parseFloat(keys.join(""));
|
|
|
+ if (isNumber(score) && questionScoreSteps.value.includes(score)) {
|
|
|
+ store.currentQuestion.score = score;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ onMounted(() => {
|
|
|
+ document.addEventListener("keydown", numberKeyListener);
|
|
|
+ });
|
|
|
+ onUnmounted(() => {
|
|
|
+ document.removeEventListener("keydown", numberKeyListener);
|
|
|
+ });
|
|
|
+
|
|
|
+ function submit() {
|
|
|
+ emit("submit");
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ store,
|
|
|
+ toggleKeyMouse,
|
|
|
+ markResult,
|
|
|
+ isCurrentQuestion,
|
|
|
+ chooseQuestion,
|
|
|
+ questionScoreSteps,
|
|
|
+ submit,
|
|
|
+ };
|
|
|
+ },
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.question {
|
|
|
+ min-width: 80px;
|
|
|
+ border: 1px solid grey;
|
|
|
+}
|
|
|
+.current-question {
|
|
|
+ border: 1px solid yellowgreen;
|
|
|
+ background-color: lightblue;
|
|
|
+}
|
|
|
+.single-score {
|
|
|
+ width: 30px;
|
|
|
+ height: 30px;
|
|
|
+ display: grid;
|
|
|
+ place-content: center;
|
|
|
+
|
|
|
+ border: 1px solid black;
|
|
|
+ border-radius: 5px;
|
|
|
+}
|
|
|
+.current-score {
|
|
|
+ border: 1px solid yellowgreen;
|
|
|
+ background-color: lightblue;
|
|
|
+}
|
|
|
+</style>
|