|
|
@@ -0,0 +1,377 @@
|
|
|
+<template>
|
|
|
+ <div style="display: flex">
|
|
|
+ <!-- 1.作文展示区域 -->
|
|
|
+ <div style="width: 40%; height: 90vh; margin: 10px; position: relative;">
|
|
|
+ <el-breadcrumb :separator-icon="ArrowRight" style="height: 30px; align-content: center; margin-left: 6px">
|
|
|
+ <el-breadcrumb-item :to="{ path: `/home/Assignment/${assignmentId}/edit` }">写作</el-breadcrumb-item>
|
|
|
+ <el-breadcrumb-item><span style="color: rgba(22,119,255,0.62); font-weight: bold; cursor:pointer;">智能批改</span></el-breadcrumb-item>
|
|
|
+ </el-breadcrumb>
|
|
|
+
|
|
|
+ <el-card shadow="never">
|
|
|
+ <!-- 原文标识 -->
|
|
|
+ <div style="display: flex;justify-content: center;align-items: center;width: 100px; height: 50px; background-color:var(--system-color); position: absolute; top: 40px; left: 0; clip-path: polygon(0 0, 100% 0, 80% 50%, 100% 100%, 0 100%);">
|
|
|
+ <span style="margin-left: -20px;color: white">原文</span>
|
|
|
+ </div>
|
|
|
+ <!-- 作文内容展示区域 -->
|
|
|
+ <div style="white-space: pre-wrap; margin-top: 80px; line-height: 30px">
|
|
|
+ <el-scrollbar height="760px">
|
|
|
+ <span style="position: relative;">
|
|
|
+ <template v-if="data.sentenceEvaluationList?.length != 0">
|
|
|
+ <span v-for="sentenceEvaluation in data.sentenceEvaluationList"
|
|
|
+ :key="sentenceEvaluation.id"
|
|
|
+ :style="{ 'text-decoration': 'underline', 'text-decoration-color': 'pink', 'text-decoration-thickness': '3px', 'text-decoration-style': 'dashed', 'background-color': sentenceEvaluation.id === highlightSentenceId? 'rgba(255, 192, 203, 0.3)' : 'transparent' }">
|
|
|
+ {{ sentenceEvaluation.sentence }}
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <span
|
|
|
+ :style="{ 'text-decoration': 'underline', 'text-decoration-color': 'pink', 'text-decoration-thickness': '3px', 'text-decoration-style': 'dashed'}">
|
|
|
+ {{ data.overallEvaluation?.content }}
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ </span>
|
|
|
+ </el-scrollbar>
|
|
|
+ </div>
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+
|
|
|
+
|
|
|
+ <!-- 2.AI评价区域 -->
|
|
|
+ <div style="width: 40%; margin: 10px; height: 89vh;">
|
|
|
+ <div class="combined-box">
|
|
|
+ <div style="display: flex">
|
|
|
+ <div
|
|
|
+ class="trapezoid"
|
|
|
+ :class="{ active: selected === 'trapezoid' }"
|
|
|
+ @click="selected = 'trapezoid'"
|
|
|
+ >
|
|
|
+ 整体评价
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ class="trapezoid2"
|
|
|
+ :class="{ active: selected === 'trapezoid2' }"
|
|
|
+ @click="selected = 'trapezoid2'"
|
|
|
+ >
|
|
|
+ 逐句评价
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="rectangle">
|
|
|
+ <template v-if="selected === 'trapezoid'">
|
|
|
+ <el-scrollbar height="820px">
|
|
|
+ <div style="display: flex;align-items: flex-start;margin-bottom: 15px;">
|
|
|
+ <div>
|
|
|
+ <!--展示头像-->
|
|
|
+ <!--<el-avatar src="@/image/seecoderLogo.png" :size="32" :shape="'circle'">-->
|
|
|
+ <!--</el-avatar>-->
|
|
|
+ <div style="border-radius: 50%; background-color:#fff; width: 40px; height: 40px;display: flex;justify-content: center;align-items: center;">
|
|
|
+ <img src="@/image/seecoderLogo.png" width="32" >
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div style="margin-left: 15px">
|
|
|
+ <!--名字-->
|
|
|
+ <div style="margin-bottom: 2px">SEEAI英语助手</div>
|
|
|
+ <!--内容-->
|
|
|
+ <div style="background-color: #f0f0f0;padding: 8px 12px;border-radius: 16px;white-space: pre-line;box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);">
|
|
|
+ {{ data.overallEvaluation?.evaluation }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-scrollbar>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <el-scrollbar height="820px">
|
|
|
+ <div style="display: flex; flex-direction: column;">
|
|
|
+ <template v-if="data.sentenceEvaluationList?.length == 0">
|
|
|
+ 暂无逐句评价
|
|
|
+ </template>
|
|
|
+ <el-card v-for="sentenceEvaluation in data.sentenceEvaluationList"
|
|
|
+ :key="sentenceEvaluation.id"
|
|
|
+ style="cursor: pointer; margin-bottom: 10px; position: relative;" shadow="hover"
|
|
|
+ @mouseenter="highlightSentenceId = sentenceEvaluation.id"
|
|
|
+ @mouseleave="highlightSentenceId = sentenceEvaluation.id"
|
|
|
+ >
|
|
|
+ <div style="display: flex;justify-content: center;align-items: center;width: 20px; height: 100%; background-color: pink; position: absolute; top: 0; left: calc(100% - 20px)">
|
|
|
+ </div>
|
|
|
+ <div style="padding-right: 30px">
|
|
|
+ {{ sentenceEvaluation.evaluation }}
|
|
|
+ </div>
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+ </el-scrollbar>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 3.历史版本选择区域 -->
|
|
|
+ <el-card
|
|
|
+ style="
|
|
|
+ width: 15%; /* 固定宽度代替百分比 */
|
|
|
+ height: 90vh;
|
|
|
+ margin: 10px 0 10px auto; /* 关键:左侧自动边距 */
|
|
|
+ border-left: 1px solid #e4e7ed;
|
|
|
+ border-radius: 0 8px 8px 0;
|
|
|
+ box-shadow: -2px 0 4px rgba(0,0,0,0.05);
|
|
|
+ /*position: sticky; !* 新增固定定位 *!*/
|
|
|
+ right: 0;
|
|
|
+ "
|
|
|
+ shadow="never"
|
|
|
+ >
|
|
|
+ <div style="
|
|
|
+ position: relative;
|
|
|
+ height: 100%;
|
|
|
+ padding: 20px 10px;
|
|
|
+ ">
|
|
|
+ <!-- 版本选择标题 -->
|
|
|
+ <div style="
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: -20px;
|
|
|
+ width: 80px;
|
|
|
+ height: 40px;
|
|
|
+ background: var(--system-color);
|
|
|
+ clip-path: polygon(0 0, 100% 0, 90% 50%, 100% 100%, 0 100%);
|
|
|
+ color: white;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding-left: 12px;
|
|
|
+ font-size: 13px;
|
|
|
+ ">
|
|
|
+ 版本历史
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 版本列表 -->
|
|
|
+ <el-scrollbar height="800px" style="margin-top: 50px;">
|
|
|
+ <div
|
|
|
+ v-for="version in data.versionList"
|
|
|
+ :key="version.id"
|
|
|
+ class="version-item"
|
|
|
+ :class="{ active: selectedVersion === version.version }"
|
|
|
+ @click="getEvaluation(version.version)"
|
|
|
+ >
|
|
|
+ <div class="version-marker"></div>
|
|
|
+ <div class="version-info">
|
|
|
+ <div class="version-time">{{ version.time }}</div>
|
|
|
+ <div class="version-author">v{{ version.version }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-scrollbar>
|
|
|
+
|
|
|
+ <!-- 当前版本提示 -->
|
|
|
+ <div style="
|
|
|
+ position: absolute;
|
|
|
+ bottom: 10px;
|
|
|
+ left: 10px;
|
|
|
+ right: 10px;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #666;
|
|
|
+ ">
|
|
|
+ 当前选择:v{{ selectedVersion }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+ import {onMounted, reactive, ref, watch} from "vue";
|
|
|
+ import useApis from "@/apis";
|
|
|
+ import MyComponent from "@/views/AIEvaluationPage/MyComponent.vue";
|
|
|
+ import {ElMessage} from "element-plus";
|
|
|
+ import {useRoute} from "vue-router";
|
|
|
+ import {useStore} from "@/store";
|
|
|
+ import { ArrowRight } from "@element-plus/icons-vue";
|
|
|
+
|
|
|
+ const apis = useApis()
|
|
|
+ const store = useStore()
|
|
|
+ const highlightSentenceId = ref(-1)
|
|
|
+ const selected = ref('trapezoid');
|
|
|
+ const route = useRoute()
|
|
|
+ const assignmentId = Number(route.params.assignmentId)
|
|
|
+ const data = reactive<{
|
|
|
+ overallEvaluation: OverallEvaluation | null;
|
|
|
+ sentenceEvaluationList: SentenceEvaluation[];
|
|
|
+ versionList: []
|
|
|
+ }>({
|
|
|
+ overallEvaluation: null,
|
|
|
+ sentenceEvaluationList: [],
|
|
|
+ versionList: []
|
|
|
+ })
|
|
|
+ const selectedVersion = ref(1.2)
|
|
|
+
|
|
|
+ const toEvaluation = () => {
|
|
|
+ apis.overAllEvaluation(assignmentId, store.user.id)
|
|
|
+ .then(res => {
|
|
|
+ if(res.data.code === 200){
|
|
|
+ // getEvaluation()
|
|
|
+ }else if(res.data.code === 400){
|
|
|
+ ElMessage.error(res.data.msg)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(err => {
|
|
|
+ console.log(err)
|
|
|
+ })
|
|
|
+ apis.sentenceEvaluation(assignmentId,store.user.id)
|
|
|
+ .then(res => {
|
|
|
+ if(res.data.code === 200){
|
|
|
+ // getEvaluation()
|
|
|
+ }else if(res.data.code === 400){
|
|
|
+ ElMessage.error(res.data.msg)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(err => {
|
|
|
+ console.log(err)
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ const getEvaluation = (version: number) => {
|
|
|
+ selectedVersion.value = version
|
|
|
+ apis.getOverall(assignmentId,store.user.id,version)
|
|
|
+ .then(res => {
|
|
|
+ // console.log(res)
|
|
|
+ data.overallEvaluation = res.data.data
|
|
|
+ })
|
|
|
+ .catch(err => {
|
|
|
+ console.log(err)
|
|
|
+ data.overallEvaluation = {} as OverallEvaluation
|
|
|
+ })
|
|
|
+ apis.getSentence(assignmentId,store.user.id,version)
|
|
|
+ .then(res => {
|
|
|
+ // console.log(res)
|
|
|
+ if(res.data.code === 200){
|
|
|
+ data.sentenceEvaluationList = res.data.data
|
|
|
+ } else {
|
|
|
+ data.sentenceEvaluationList = []
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(err => {
|
|
|
+ console.log(err)
|
|
|
+ data.sentenceEvaluationList = []
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ const getEvaluationVersionList = () => {
|
|
|
+ apis.getEvaluationVersionList(assignmentId, store.user.id)
|
|
|
+ .then(res => {
|
|
|
+ // 从未批改过
|
|
|
+ if(res.data.data.length === 0){
|
|
|
+ data.versionList = []
|
|
|
+ } else {
|
|
|
+ data.versionList = res.data.data
|
|
|
+ getEvaluation(res.data.data[0].version)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(err => {
|
|
|
+ console.log(err)
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ onMounted(() => {
|
|
|
+ // toEvaluation()
|
|
|
+ // getEvaluation()
|
|
|
+ getEvaluationVersionList()
|
|
|
+ })
|
|
|
+</script>
|
|
|
+
|
|
|
+<script lang="ts">
|
|
|
+export default {
|
|
|
+ name: "AIEvaluationPage"
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+
|
|
|
+.combined-box {
|
|
|
+ width: 100%; /* 整体宽度 */
|
|
|
+ height: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.trapezoid {
|
|
|
+ width: 100px; /* 梯形底边长度 */
|
|
|
+ height: 0;
|
|
|
+ border-bottom: 30px solid #cfcfcf; /* 梯形高度和颜色 */
|
|
|
+ border-right: 20px solid transparent;
|
|
|
+ line-height: 30px; /* 与 border-bottom 高度相等 */
|
|
|
+ text-align: center; /* 水平居中 */
|
|
|
+ z-index: 1;
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
+
|
|
|
+.trapezoid2 {
|
|
|
+ width: 100px; /* 梯形底边长度 */
|
|
|
+ height: 0;
|
|
|
+ border-bottom: 30px solid #cfcfcf; /* 梯形高度和颜色 */
|
|
|
+ border-right: 20px solid transparent;
|
|
|
+ border-left: 20px solid transparent;
|
|
|
+ margin-left: -20px;
|
|
|
+ z-index: 2;
|
|
|
+ line-height: 30px; /* 与 border-bottom 高度相等 */
|
|
|
+ text-align: center; /* 水平居中 */
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
+
|
|
|
+.trapezoid.active {
|
|
|
+ border-bottom: 30px solid #fff;
|
|
|
+ z-index: 10;
|
|
|
+}
|
|
|
+
|
|
|
+.trapezoid2.active {
|
|
|
+ border-bottom: 30px solid #fff;
|
|
|
+ z-index: 10;
|
|
|
+}
|
|
|
+
|
|
|
+.rectangle {
|
|
|
+ width: 100%; /* 长方形宽度 */
|
|
|
+ height: calc(100% - 30px - 2vh); /* 长方形高度 */
|
|
|
+ border-top: none; /* 去掉顶部边框,使其与梯形无缝连接 */
|
|
|
+ /* 长方形底部的圆角 */
|
|
|
+ align-items: center;
|
|
|
+ padding: 20px;
|
|
|
+ background-color: #fff; /* 长方形的背景颜色 */
|
|
|
+ border-radius: 0 5px 5px 5px;
|
|
|
+}
|
|
|
+
|
|
|
+.version-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 8px;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ border-radius: 4px;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.2s;
|
|
|
+ box-sizing: border-box;
|
|
|
+}
|
|
|
+
|
|
|
+.version-item:hover {
|
|
|
+ background: #f5f7fa;
|
|
|
+}
|
|
|
+
|
|
|
+.version-item.active {
|
|
|
+ background: rgba(89, 125, 59, 0.1);
|
|
|
+ border: 1px solid rgba(89, 125, 59, 0.3);
|
|
|
+ box-sizing: border-box;
|
|
|
+}
|
|
|
+
|
|
|
+.version-marker {
|
|
|
+ width: 8px;
|
|
|
+ height: 8px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: #cfcfcf;
|
|
|
+ margin-right: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.version-item.active .version-marker {
|
|
|
+ background: var(--system-color);
|
|
|
+}
|
|
|
+
|
|
|
+.version-time {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #333;
|
|
|
+}
|
|
|
+
|
|
|
+.version-author {
|
|
|
+ font-size: 10px;
|
|
|
+ color: #999;
|
|
|
+}
|
|
|
+</style>
|