编程题、SQL 题两张出题页一起改:两栏 3 : 2,右栏头上「收起 ›」,收起后剩一条竖着的「学生看到的样子」点了再展开;收没收记在本机 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
151bbdcb50
commit
dd10e64b38
5 files changed
+115
-8
No files matched your search
@@ -14,6 +14,8 @@ import { errorCode, errorMessage, isApiError } from "utils/api"
|
||||
import { DIFFICULTY, STORAGE_KEY } from "utils/constants"
|
||||
import { createZipBlob, getTagColor, unique } from "utils/functions"
|
||||
import type { AdminProblem, BlankProblem, SqlConfig, Tag, Testcase } from "utils/types"
|
||||
import PreviewStrip from "./components/PreviewStrip.vue"
|
||||
import { usePreviewCollapsed } from "./components/previewCollapse"
|
||||
import {
|
||||
createContestProblem,
|
||||
createProblem,
|
||||
@@ -53,6 +55,7 @@ const props = defineProps<{
|
||||
const message = useMessage()
|
||||
const router = useRouter()
|
||||
const theme = useThemeVars()
|
||||
const previewCollapsed = usePreviewCollapsed()
|
||||
const isDark = useDark()
|
||||
|
||||
const isCreate = computed(() => !props.problemID)
|
||||
@@ -445,7 +448,7 @@ onMounted(async () => {
|
||||
</template>
|
||||
</PageHeader>
|
||||
|
||||
<div v-if="ready" class="sqlEditor">
|
||||
<div v-if="ready" class="sqlEditor" :class="{ collapsed: previewCollapsed }">
|
||||
<!-- 左:写 -->
|
||||
<div class="write">
|
||||
<section class="card">
|
||||
@@ -634,7 +637,7 @@ onMounted(async () => {
|
||||
</div>
|
||||
|
||||
<!-- 右:学生看到的 -->
|
||||
<aside class="preview" aria-label="学生看到的样子">
|
||||
<aside v-show="!previewCollapsed" class="preview" aria-label="学生看到的样子">
|
||||
<div class="previewHead">
|
||||
<b>学生看到的样子</b>
|
||||
<div class="grow"></div>
|
||||
@@ -643,6 +646,9 @@ onMounted(async () => {
|
||||
第 {{ i + 1 }} 组<span v-if="statusOf(g) === 'error'" class="error"> ✗</span>
|
||||
</n-radio-button>
|
||||
</n-radio-group>
|
||||
<n-button size="small" quaternary title="收起,专心写左边" @click="previewCollapsed = true">
|
||||
收起 ›
|
||||
</n-button>
|
||||
</div>
|
||||
<div class="page">
|
||||
<div class="titleRow">
|
||||
@@ -703,6 +709,7 @@ onMounted(async () => {
|
||||
</template>
|
||||
</div>
|
||||
</aside>
|
||||
<PreviewStrip v-if="previewCollapsed" @expand="previewCollapsed = false" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -711,16 +718,22 @@ onMounted(async () => {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* 写的一边是主角,看的一边小一点(用户 2026-10-09:编辑区域要大);右栏可以收起来 */
|
||||
.sqlEditor {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 560px) minmax(0, 1fr);
|
||||
grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
|
||||
gap: 20px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.sqlEditor.collapsed {
|
||||
grid-template-columns: minmax(0, 1fr) 36px;
|
||||
}
|
||||
|
||||
/* 窄屏(老师的小笔记本)放不下两栏:预览挪到下面 */
|
||||
@media (max-width: 1180px) {
|
||||
.sqlEditor {
|
||||
.sqlEditor,
|
||||
.sqlEditor.collapsed {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ const props = defineProps<{
|
||||
}>()
|
||||
|
||||
const tab = defineModel<PreviewTab>("tab", { required: true })
|
||||
const emit = defineEmits<{ renderState: [ok: boolean] }>()
|
||||
const emit = defineEmits<{ renderState: [ok: boolean]; collapse: [] }>()
|
||||
|
||||
const theme = useThemeVars()
|
||||
const isDark = useDark()
|
||||
@@ -117,6 +117,9 @@ onMounted(() => nextTick(render))
|
||||
流程图
|
||||
</n-radio-button>
|
||||
</n-radio-group>
|
||||
<n-button size="small" quaternary title="收起,专心写左边" @click="emit('collapse')">
|
||||
收起 ›
|
||||
</n-button>
|
||||
</div>
|
||||
|
||||
<!-- 题面 -->
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
<script setup lang="ts">
|
||||
import { useThemeVars } from "naive-ui"
|
||||
|
||||
/**
|
||||
* 出题页右栏「学生看到的样子」收起来之后剩下的那一条:竖着贴在右边,点一下展开。
|
||||
* 收不收记在本机(usePreviewCollapsed),下次打开出题页照旧
|
||||
*/
|
||||
defineEmits<{ expand: [] }>()
|
||||
|
||||
const theme = useThemeVars()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button class="strip" title="展开「学生看到的样子」" @click="$emit('expand')">
|
||||
<span class="arrow">‹</span>
|
||||
<span class="text">学生看到的样子</span>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.strip {
|
||||
position: sticky;
|
||||
top: 12px;
|
||||
height: 220px;
|
||||
padding: 10px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
border: 1px solid v-bind("theme.borderColor");
|
||||
border-radius: 6px;
|
||||
background: v-bind("theme.cardColor");
|
||||
color: v-bind("theme.textColor2");
|
||||
font: inherit;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.strip:hover {
|
||||
color: v-bind("theme.primaryColor");
|
||||
border-color: v-bind("theme.primaryColor");
|
||||
}
|
||||
|
||||
.arrow {
|
||||
font-size: 16px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.text {
|
||||
writing-mode: vertical-rl;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
/* 窄屏预览本来就在下面,收起后是横着的一条 */
|
||||
@media (max-width: 1180px) {
|
||||
.strip {
|
||||
position: static;
|
||||
height: 40px;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
.text {
|
||||
writing-mode: horizontal-tb;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* 出题页右栏「学生看到的样子」收没收起来。两张出题页(编程题、SQL 题)共用一个开关,
|
||||
* 记在本机:老师想专心写的时候收起来,下次打开还是收着的
|
||||
*/
|
||||
export function usePreviewCollapsed() {
|
||||
return useStorage("oj2:admin-problem-preview-collapsed", false)
|
||||
}
|
||||
@@ -22,6 +22,8 @@ import {
|
||||
import AstRulesEditor from "./components/AstRulesEditor.vue"
|
||||
import CaseTable from "./components/CaseTable.vue"
|
||||
import CodePreview from "./components/CodePreview.vue"
|
||||
import PreviewStrip from "./components/PreviewStrip.vue"
|
||||
import { usePreviewCollapsed } from "./components/previewCollapse"
|
||||
import {
|
||||
caseFiles,
|
||||
caseStatus,
|
||||
@@ -458,6 +460,7 @@ const open = reactive({
|
||||
more: false,
|
||||
})
|
||||
const preview = ref<PreviewTab>("statement")
|
||||
const previewCollapsed = usePreviewCollapsed()
|
||||
|
||||
watch(
|
||||
() => open.write,
|
||||
@@ -842,7 +845,7 @@ onMounted(async () => {
|
||||
</template>
|
||||
</PageHeader>
|
||||
|
||||
<div v-if="ready" class="codeEditor">
|
||||
<div v-if="ready" class="codeEditor" :class="{ collapsed: previewCollapsed }">
|
||||
<!-- 左:写 -->
|
||||
<div class="write">
|
||||
<div v-if="draftRestored" class="notice">上次没保存的草稿已经恢复</div>
|
||||
@@ -1273,7 +1276,9 @@ onMounted(async () => {
|
||||
</div>
|
||||
|
||||
<!-- 右:学生看到的 -->
|
||||
<!-- 收起时用 v-show 不卸载:流程图渲染成没成功(mermaidOk)还要接着报给保存按钮 -->
|
||||
<CodePreview
|
||||
v-show="!previewCollapsed"
|
||||
v-model:tab="preview"
|
||||
:display-id="form._id"
|
||||
:title="form.title"
|
||||
@@ -1293,7 +1298,9 @@ onMounted(async () => {
|
||||
:mermaid-code="form.mermaidCode"
|
||||
:flowchart-hint="form.flowchartHint"
|
||||
@render-state="mermaidOk = $event"
|
||||
@collapse="previewCollapsed = true"
|
||||
/>
|
||||
<PreviewStrip v-if="previewCollapsed" @expand="previewCollapsed = false" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1314,16 +1321,22 @@ onMounted(async () => {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* 写的一边是主角,看的一边小一点(用户 2026-10-09:编辑区域要大);右栏可以收起来 */
|
||||
.codeEditor {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 600px) minmax(0, 1fr);
|
||||
grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
|
||||
gap: 20px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.codeEditor.collapsed {
|
||||
grid-template-columns: minmax(0, 1fr) 36px;
|
||||
}
|
||||
|
||||
/* 窄屏(老师的小笔记本)放不下两栏:预览挪到下面 */
|
||||
@media (max-width: 1180px) {
|
||||
.codeEditor {
|
||||
.codeEditor,
|
||||
.codeEditor.collapsed {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user