|
@@ -1,125 +0,0 @@
|
|
|
-<template>
|
|
|
- <template v-for="(track, index) in trackList" :key="index">
|
|
|
- <div
|
|
|
- class="score-container"
|
|
|
- :class="[focusedTrack(track) && 'score-animation']"
|
|
|
- :style="computeTopAndLeft(track)"
|
|
|
- >
|
|
|
- <span
|
|
|
- :id="`a-${track.mainNumber}-${track.subNumber}-${track.offsetY}-${track.offsetX}`"
|
|
|
- class="tw-m-auto"
|
|
|
- >
|
|
|
- {{ track.unanswered ? "空" : track.score }}
|
|
|
- </span>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- <template v-for="(tag, index) in specialTagList" :key="index">
|
|
|
- <div class="score-container" :style="computeTopAndLeft(tag)">
|
|
|
- <span class="tw-m-auto">
|
|
|
- {{ tag.tagName }}
|
|
|
- </span>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
-</template>
|
|
|
-
|
|
|
-<script setup lang="ts">
|
|
|
-import type { SpecialTag, Track } from "@/types";
|
|
|
-import { store } from "@/store/store";
|
|
|
-import { toRefs, watch } from "vue";
|
|
|
-import { message } from "ant-design-vue";
|
|
|
-
|
|
|
-const props = defineProps<{
|
|
|
- trackList: Array<Track>;
|
|
|
- specialTagList: Array<SpecialTag>;
|
|
|
- originalImageWidth: number;
|
|
|
- originalImageHeight: number;
|
|
|
-}>();
|
|
|
-const { trackList } = toRefs(props);
|
|
|
-
|
|
|
-const focusedTrack = (track: Track) => {
|
|
|
- return store.focusTracks.includes(track);
|
|
|
-};
|
|
|
-const computeTopAndLeft = (track: Track | SpecialTag) => {
|
|
|
- const topInsideSlice = track.offsetY;
|
|
|
- const leftInsideSlice = track.offsetX;
|
|
|
- const topInsideSliceRatio = topInsideSlice / props.originalImageHeight;
|
|
|
- const leftInsideSliceRatio = leftInsideSlice / props.originalImageWidth;
|
|
|
- if (
|
|
|
- topInsideSliceRatio < 0 ||
|
|
|
- topInsideSliceRatio > 1 ||
|
|
|
- leftInsideSliceRatio < 0 ||
|
|
|
- leftInsideSliceRatio > 1
|
|
|
- ) {
|
|
|
- void message.error("轨迹坐标有误,可能是图片被修改过,请联系管理员!");
|
|
|
- }
|
|
|
-
|
|
|
- return {
|
|
|
- top: topInsideSliceRatio * 100 + "%",
|
|
|
- left: leftInsideSliceRatio * 100 + "%",
|
|
|
- "font-size":
|
|
|
- (store.setting.uiSetting["score.fontSize.scale"] || 1) *
|
|
|
- store.setting.uiSetting["answer.paper.scale"] *
|
|
|
- 2.2 +
|
|
|
- "em",
|
|
|
- };
|
|
|
-};
|
|
|
-
|
|
|
-watch(
|
|
|
- () => store.focusTracks.length,
|
|
|
- () => {
|
|
|
- if (store.focusTracks.length === 0) return;
|
|
|
- const minImageIndex = Math.min(
|
|
|
- ...store.focusTracks.map((t) => t.offsetIndex)
|
|
|
- );
|
|
|
- const minImageOffsetY = Math.min(
|
|
|
- ...store.focusTracks
|
|
|
- .filter((t) => t.offsetIndex === minImageIndex)
|
|
|
- .map((t) => t.offsetY)
|
|
|
- );
|
|
|
- const topTrack = store.focusTracks.find(
|
|
|
- (t) => t.offsetIndex === minImageIndex && t.offsetY === minImageOffsetY
|
|
|
- );
|
|
|
- if (topTrack) {
|
|
|
- document
|
|
|
- .querySelector(
|
|
|
- `#a-${topTrack.mainNumber}-${topTrack.subNumber}-${topTrack.offsetY}-${topTrack.offsetX}`
|
|
|
- )
|
|
|
- ?.scrollIntoView({ behavior: "smooth" });
|
|
|
- }
|
|
|
- }
|
|
|
-);
|
|
|
-</script>
|
|
|
-
|
|
|
-<style scoped>
|
|
|
-.score-container {
|
|
|
- position: absolute;
|
|
|
- display: flex;
|
|
|
- place-content: center;
|
|
|
- color: red;
|
|
|
-
|
|
|
- /* to center score */
|
|
|
- width: 200px;
|
|
|
- height: 200px;
|
|
|
- margin-top: -100px;
|
|
|
- margin-left: -100px;
|
|
|
-
|
|
|
- /* to click through div */
|
|
|
- pointer-events: none;
|
|
|
-}
|
|
|
-.score-animation {
|
|
|
- animation: 2s ease-in-out 0s infinite alternate change_size;
|
|
|
-}
|
|
|
-
|
|
|
-@keyframes change_size {
|
|
|
- from {
|
|
|
- font-size: 2em;
|
|
|
- margin-top: -100px;
|
|
|
- margin-left: -100px;
|
|
|
- }
|
|
|
- to {
|
|
|
- font-size: 4em;
|
|
|
- margin-top: -80px;
|
|
|
- margin-left: -80px;
|
|
|
- }
|
|
|
-}
|
|
|
-</style>
|