添加提交详情页
This commit is contained in:
@@ -4,6 +4,9 @@
|
|||||||
<n-flex>
|
<n-flex>
|
||||||
<n-button quaternary @click="download" :disabled="!showDL">下载</n-button>
|
<n-button quaternary @click="download" :disabled="!showDL">下载</n-button>
|
||||||
<n-button quaternary @click="open">全屏</n-button>
|
<n-button quaternary @click="open">全屏</n-button>
|
||||||
|
<n-button quaternary v-if="props.submissionId" @click="copyLink">
|
||||||
|
复制链接
|
||||||
|
</n-button>
|
||||||
<n-flex v-if="!!submission.id">
|
<n-flex v-if="!!submission.id">
|
||||||
<n-button quaternary @click="emits('showCode')">查看代码</n-button>
|
<n-button quaternary @click="emits('showCode')">查看代码</n-button>
|
||||||
<n-popover v-if="submission.my_score === 0">
|
<n-popover v-if="submission.my_score === 0">
|
||||||
@@ -21,21 +24,24 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { watchDebounced } from "@vueuse/core"
|
import { watchDebounced } from "@vueuse/core"
|
||||||
import { computed, onMounted, useTemplateRef } from "vue"
|
import { computed, onMounted, useTemplateRef } from "vue"
|
||||||
import { Icon } from "@iconify/vue"
|
import { useRouter } from "vue-router"
|
||||||
import { Submission } from "../api"
|
import { Submission } from "../api"
|
||||||
import { submission } from "../store/submission"
|
import { submission } from "../store/submission"
|
||||||
import { useMessage } from "naive-ui"
|
import { useMessage } from "naive-ui"
|
||||||
|
import copy from "copy-text-to-clipboard"
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
html: string
|
html: string
|
||||||
css: string
|
css: string
|
||||||
js: string
|
js: string
|
||||||
|
submissionId?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
const emits = defineEmits(["afterScore", "showCode"])
|
const emits = defineEmits(["afterScore", "showCode"])
|
||||||
|
|
||||||
const message = useMessage()
|
const message = useMessage()
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
const iframe = useTemplateRef<HTMLIFrameElement>("iframe")
|
const iframe = useTemplateRef<HTMLIFrameElement>("iframe")
|
||||||
const showDL = computed(() => props.html || props.css || props.js)
|
const showDL = computed(() => props.html || props.css || props.js)
|
||||||
@@ -80,11 +86,24 @@ function download() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function open() {
|
function open() {
|
||||||
|
if (props.submissionId) {
|
||||||
|
const data = router.resolve({
|
||||||
|
name: "submission",
|
||||||
|
params: { id: props.submissionId },
|
||||||
|
})
|
||||||
|
window.open(data.href, "_blank")
|
||||||
|
} else {
|
||||||
const newTab = window.open("/usercontent.html")
|
const newTab = window.open("/usercontent.html")
|
||||||
if (!newTab) return
|
if (!newTab) return
|
||||||
newTab.document.open()
|
newTab.document.open()
|
||||||
newTab.document.write(getContent())
|
newTab.document.write(getContent())
|
||||||
newTab.document.close()
|
newTab.document.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyLink() {
|
||||||
|
copy(`${document.location.origin}/submission/${props.submissionId}`)
|
||||||
|
message.success("该提交的链接已复制")
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateScore(score: number) {
|
async function updateScore(score: number) {
|
||||||
|
|||||||
51
src/pages/Submission.vue
Normal file
51
src/pages/Submission.vue
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { onMounted, defineProps, useTemplateRef } from "vue"
|
||||||
|
import { Submission } from "../api"
|
||||||
|
import type { SubmissionAll } from "../utils/type"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
|
const iframe = useTemplateRef<HTMLIFrameElement>("iframe")
|
||||||
|
|
||||||
|
async function init() {
|
||||||
|
const submission: SubmissionAll = await Submission.get(props.id)
|
||||||
|
|
||||||
|
if (!iframe.value) return
|
||||||
|
const doc = iframe.value.contentDocument
|
||||||
|
if (doc) {
|
||||||
|
doc.open()
|
||||||
|
doc.write(`<!DOCTYPE html>
|
||||||
|
<html lang="zh-Hans-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>预览</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<style>${submission.css}</style>
|
||||||
|
<link rel="stylesheet" href="/normalize.min.css" />
|
||||||
|
<script src="/jquery.min.js"><\/script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
${submission.html}
|
||||||
|
<script type="module">${submission.js}<\/script>
|
||||||
|
</body>
|
||||||
|
</html>`)
|
||||||
|
doc.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(init)
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<iframe class="iframe" ref="iframe"></iframe>
|
||||||
|
</template>
|
||||||
|
<style scoped>
|
||||||
|
.iframe {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -32,6 +32,7 @@
|
|||||||
:html="html"
|
:html="html"
|
||||||
:css="css"
|
:css="css"
|
||||||
:js="js"
|
:js="js"
|
||||||
|
:submission-id="submission.id"
|
||||||
@after-score="afterScore"
|
@after-score="afterScore"
|
||||||
@show-code="codeModal = true"
|
@show-code="codeModal = true"
|
||||||
/>
|
/>
|
||||||
@@ -128,7 +129,11 @@ const columns: DataTableColumn<SubmissionOut>[] = [
|
|||||||
render: (row) =>
|
render: (row) =>
|
||||||
h(
|
h(
|
||||||
NButton,
|
NButton,
|
||||||
{ quaternary: true, onClick: () => getSubmissionByID(row.id) },
|
{
|
||||||
|
quaternary: submission.value.id !== row.id,
|
||||||
|
type: submission.value.id === row.id ? "primary" : "default",
|
||||||
|
onClick: () => getSubmissionByID(row.id),
|
||||||
|
},
|
||||||
() => "查看",
|
() => "查看",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@@ -190,5 +195,6 @@ onUnmounted(() => {
|
|||||||
.container {
|
.container {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
height: calc(100% - 43px);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -11,6 +11,12 @@ const routes = [
|
|||||||
name: "submissions",
|
name: "submissions",
|
||||||
component: () => import("./pages/Submissions.vue"),
|
component: () => import("./pages/Submissions.vue"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/submission/:id",
|
||||||
|
name: "submission",
|
||||||
|
component: () => import("./pages/Submission.vue"),
|
||||||
|
props: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/dashboard",
|
path: "/dashboard",
|
||||||
name: "dashboard",
|
name: "dashboard",
|
||||||
|
|||||||
Reference in New Issue
Block a user