|
@@ -0,0 +1,257 @@
|
|
|
+<template>
|
|
|
+ <a-modal
|
|
|
+ v-model:open="visible"
|
|
|
+ width="100%"
|
|
|
+ :footer="false"
|
|
|
+ :closable="false"
|
|
|
+ :mask="false"
|
|
|
+ :maskClosable="false"
|
|
|
+ :keyboard="false"
|
|
|
+ wrapClassName="recog-arbitrate-edit-dialog"
|
|
|
+ >
|
|
|
+ <div class="recog-edit">
|
|
|
+ <div class="recog-row">
|
|
|
+ <div class="recog-col is-static is-col2">
|
|
|
+ <div class="modal-box">
|
|
|
+ <p class="box-title">{{ recogTitle }}</p>
|
|
|
+ <p class="box-cont">{{ recogTitleDesc }}</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="recog-col is-grow">
|
|
|
+ <div class="modal-box modal-origin">
|
|
|
+ <div class="modal-origin-body" :style="areaImgStyle">
|
|
|
+ <img
|
|
|
+ v-if="recogData.areaImg"
|
|
|
+ ref="areaImgRef"
|
|
|
+ :src="recogData.areaImg"
|
|
|
+ alt="截图"
|
|
|
+ @load="areaImgLoad"
|
|
|
+ />
|
|
|
+ <template v-if="recogData.type === 'question'">
|
|
|
+ <div
|
|
|
+ v-for="(option, index) in recogData.options.slice(1)"
|
|
|
+ :key="option"
|
|
|
+ class="select-option"
|
|
|
+ :style="getOptionStyle(index)"
|
|
|
+ @click="selectOption(option)"
|
|
|
+ ></div>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="recog-col is-static is-col2">
|
|
|
+ <div class="modal-box is-btn" @click="changePrevTaskDetail">
|
|
|
+ <p class="box-title">左键</p>
|
|
|
+ <p class="box-cont">上一个</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="recog-row">
|
|
|
+ <div class="recog-col is-static is-col1">
|
|
|
+ <div class="modal-box">
|
|
|
+ <p class="box-title">一评结果</p>
|
|
|
+ <p class="box-cont">{{ recogData.result1 }}</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="recog-col is-static is-col1">
|
|
|
+ <div class="modal-box">
|
|
|
+ <p class="box-title">二评结果</p>
|
|
|
+ <p class="box-cont">{{ recogData.result2 }}</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="recog-col is-grow">
|
|
|
+ <div class="modal-box modal-options">
|
|
|
+ <a-button
|
|
|
+ v-for="option in recogData.options"
|
|
|
+ :key="option"
|
|
|
+ :type="selectResult.includes(option) ? 'primary' : 'default'"
|
|
|
+ @click="selectOption(option)"
|
|
|
+ >{{ option === "#" ? "空" : option }}</a-button
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="recog-col is-static is-col2">
|
|
|
+ <div class="modal-box is-btn" @click="onConfirm">
|
|
|
+ <p class="box-title">Enter键</p>
|
|
|
+ <p class="box-cont">下一个</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </a-modal>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+import { ref, computed, watch, onBeforeUnmount } from "vue";
|
|
|
+import { message } from "ant-design-vue";
|
|
|
+import useModal from "@/hooks/useModal";
|
|
|
+
|
|
|
+import { RecognizeArbitrateTaskDetail } from "@/ap/types/recognizeCheck";
|
|
|
+import { getBoxImageSize } from "@/utils/tool";
|
|
|
+import { useUserStore } from "@/store";
|
|
|
+
|
|
|
+defineOptions({
|
|
|
+ name: "RecogArbitrateEditDialog",
|
|
|
+});
|
|
|
+
|
|
|
+/* modal */
|
|
|
+const { visible, open, close } = useModal();
|
|
|
+defineExpose({ open, close });
|
|
|
+
|
|
|
+const props = defineProps<{
|
|
|
+ recogData: RecognizeArbitrateTaskDetail;
|
|
|
+}>();
|
|
|
+
|
|
|
+const emit = defineEmits(["confirm", "prev"]);
|
|
|
+const userStore = useUserStore();
|
|
|
+
|
|
|
+const selectResult = ref([] as string[]);
|
|
|
+
|
|
|
+const titles = {
|
|
|
+ question: "客观题",
|
|
|
+ absent: "缺考",
|
|
|
+ breach: "违纪",
|
|
|
+ paperType: "卷型",
|
|
|
+};
|
|
|
+const recogTitle = computed(() => {
|
|
|
+ return titles[props.recogData.type];
|
|
|
+});
|
|
|
+
|
|
|
+const recogTitleDesc = computed(() => {
|
|
|
+ if (props.recogData.type === "question") {
|
|
|
+ return `#${props.recogData.index}`;
|
|
|
+ }
|
|
|
+ return "--";
|
|
|
+});
|
|
|
+
|
|
|
+function getOptionStyle(index: number): Record<string, any> {
|
|
|
+ const optionSize = props.recogData.optionSizes[index];
|
|
|
+ const option = props.recogData.options[index + 1];
|
|
|
+ const borderColor = selectResult.value.includes(option)
|
|
|
+ ? userStore.recogFillSet.fillColor
|
|
|
+ : userStore.recogFillSet.unfillColor;
|
|
|
+ return {
|
|
|
+ width: `${optionSize.w}px`,
|
|
|
+ height: `${optionSize.h}px`,
|
|
|
+ left: `${optionSize.x}px`,
|
|
|
+ top: `${optionSize.y}px`,
|
|
|
+ borderColor,
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+const areaImgRef = ref();
|
|
|
+const areaImgStyle = ref({});
|
|
|
+function areaImgLoad() {
|
|
|
+ const areaImgDom = areaImgRef.value as HTMLImageElement;
|
|
|
+ const boxDom = areaImgDom.parentNode?.parentNode as HTMLDivElement;
|
|
|
+
|
|
|
+ const imgSize = getBoxImageSize({
|
|
|
+ box: {
|
|
|
+ width: boxDom.offsetWidth - 22,
|
|
|
+ height: boxDom.offsetHeight - 22,
|
|
|
+ },
|
|
|
+ img: {
|
|
|
+ width: areaImgDom.naturalWidth,
|
|
|
+ height: areaImgDom.naturalHeight,
|
|
|
+ },
|
|
|
+ rotate: 0,
|
|
|
+ });
|
|
|
+ const rate = imgSize.width / areaImgDom.naturalWidth;
|
|
|
+ areaImgStyle.value = {
|
|
|
+ width: `${areaImgDom.naturalWidth}px`,
|
|
|
+ height: `${areaImgDom.naturalHeight}px`,
|
|
|
+ transform: `scale(${rate}) translate(-50%, -50%)`,
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+function selectOption(option: string) {
|
|
|
+ if (!props.recogData) return;
|
|
|
+
|
|
|
+ // 单选直接赋值
|
|
|
+ if (!props.recogData.multiple) {
|
|
|
+ selectResult.value = [option];
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 多选情况
|
|
|
+ // 空直接赋值,空值与其他互斥
|
|
|
+ if (option === "#") {
|
|
|
+ selectResult.value = ["#"];
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ let result = selectResult.value.filter((item) => item !== "#");
|
|
|
+ if (result.includes(option)) {
|
|
|
+ result = result.filter((item) => item !== option);
|
|
|
+ } else {
|
|
|
+ result.push(option);
|
|
|
+ }
|
|
|
+ // 保证result的顺序和options的顺序是一致的
|
|
|
+ selectResult.value = props.recogData.options.filter((item) =>
|
|
|
+ result.includes(item)
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+// 键盘事件
|
|
|
+function registKeyEvent() {
|
|
|
+ document.addEventListener("keydown", keyEventHandle);
|
|
|
+}
|
|
|
+function removeKeyEvent() {
|
|
|
+ document.removeEventListener("keydown", keyEventHandle);
|
|
|
+}
|
|
|
+
|
|
|
+function keyEventHandle(e: KeyboardEvent) {
|
|
|
+ if (e.repeat) return;
|
|
|
+
|
|
|
+ if (e.keyCode == 13) {
|
|
|
+ e.preventDefault();
|
|
|
+ onConfirm();
|
|
|
+ return;
|
|
|
+ } else if (e.code === "ArrowLeft") {
|
|
|
+ e.preventDefault();
|
|
|
+ emit("prev");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function onConfirm() {
|
|
|
+ if (!selectResult.value.length) {
|
|
|
+ message.error("请完成仲裁结果!");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ emit("confirm", selectResult.value);
|
|
|
+}
|
|
|
+
|
|
|
+// init
|
|
|
+watch(
|
|
|
+ () => visible.value,
|
|
|
+ (val) => {
|
|
|
+ if (val) {
|
|
|
+ modalOpenHandle();
|
|
|
+ } else {
|
|
|
+ removeKeyEvent();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ immediate: true,
|
|
|
+ }
|
|
|
+);
|
|
|
+
|
|
|
+watch(
|
|
|
+ () => props.recogData,
|
|
|
+ (val) => {
|
|
|
+ if (!val) return;
|
|
|
+ selectResult.value = [...props.recogData.result];
|
|
|
+ }
|
|
|
+);
|
|
|
+
|
|
|
+function modalOpenHandle() {
|
|
|
+ selectResult.value = [...props.recogData.result];
|
|
|
+ registKeyEvent();
|
|
|
+}
|
|
|
+
|
|
|
+onBeforeUnmount(() => {
|
|
|
+ removeKeyEvent();
|
|
|
+});
|
|
|
+</script>
|