fix click textarea.
This commit is contained in:
@@ -3,6 +3,7 @@ import { deleteContestProblem, deleteProblem } from "~/admin/api"
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
problemID: number
|
problemID: number
|
||||||
|
problemDisplayID: string
|
||||||
}
|
}
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
const emit = defineEmits(["deleted"])
|
const emit = defineEmits(["deleted"])
|
||||||
@@ -37,13 +38,20 @@ function goEdit() {
|
|||||||
const name = route.name!.toString().replace("list", "edit")
|
const name = route.name!.toString().replace("list", "edit")
|
||||||
router.push({ name, params: { problemID: props.problemID } })
|
router.push({ name, params: { problemID: props.problemID } })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function goCheck() {
|
||||||
|
const data = router.resolve("/problem/" + props.problemDisplayID)
|
||||||
|
window.open(data.href, "_blank")
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<n-space align="center">
|
<n-space align="center">
|
||||||
<n-button size="small" secondary type="primary" @click="goEdit">
|
<n-button size="small" secondary type="primary" @click="goEdit">
|
||||||
编辑
|
编辑
|
||||||
</n-button>
|
</n-button>
|
||||||
<n-button size="small" secondary type="info">查看</n-button>
|
<n-button size="small" secondary type="info" @click="goCheck">
|
||||||
|
查看
|
||||||
|
</n-button>
|
||||||
<n-popconfirm @positive-click="handleDeleteProblem">
|
<n-popconfirm @positive-click="handleDeleteProblem">
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<n-button secondary size="small" type="error">删除</n-button>
|
<n-button secondary size="small" type="error">删除</n-button>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { unique } from "~/utils/functions"
|
|||||||
import { BlankProblem, LANGUAGE, Tag } from "~/utils/types"
|
import { BlankProblem, LANGUAGE, Tag } from "~/utils/types"
|
||||||
import { getProblemTagList } from "~/shared/api"
|
import { getProblemTagList } from "~/shared/api"
|
||||||
import { LANGUAGE_SHOW_VALUE, CODE_TEMPLATES } from "~/utils/constants"
|
import { LANGUAGE_SHOW_VALUE, CODE_TEMPLATES } from "~/utils/constants"
|
||||||
|
import download from "~/utils/download"
|
||||||
import {
|
import {
|
||||||
createContestProblem,
|
createContestProblem,
|
||||||
createProblem,
|
createProblem,
|
||||||
@@ -192,8 +192,9 @@ async function handleUploadTestcases({ file }: UploadCustomRequestOptions) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: 还没有完成
|
function downloadTestcases() {
|
||||||
function downloadTestcases() {}
|
download("test_case?problem_id=" + problem.id)
|
||||||
|
}
|
||||||
|
|
||||||
// 题目是否有漏写的
|
// 题目是否有漏写的
|
||||||
function detectProblemCompletion() {
|
function detectProblemCompletion() {
|
||||||
@@ -265,7 +266,6 @@ async function submit() {
|
|||||||
if (notComplete) return
|
if (notComplete) return
|
||||||
getTemplate()
|
getTemplate()
|
||||||
problem.tags = [...newTags.value, ...fromExistingTags.value]
|
problem.tags = [...newTags.value, ...fromExistingTags.value]
|
||||||
console.log(problem)
|
|
||||||
const api = {
|
const api = {
|
||||||
"admin problem create": createProblem,
|
"admin problem create": createProblem,
|
||||||
"admin problem edit": editProblem,
|
"admin problem edit": editProblem,
|
||||||
@@ -299,7 +299,7 @@ async function submit() {
|
|||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (err.data === "Display ID already exists") {
|
if (err.data === "Display ID already exists") {
|
||||||
message.error("显示编号重复了,请换一个编号")
|
message.error("显示编号重复了,请换一个显示编号")
|
||||||
} else {
|
} else {
|
||||||
message.error(err.data)
|
message.error(err.data)
|
||||||
}
|
}
|
||||||
@@ -307,15 +307,14 @@ async function submit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
listTags()
|
|
||||||
getProblemDetail()
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
route.name === "admin problem create" ||
|
route.name === "admin problem create" ||
|
||||||
route.name === "admin contest problem create"
|
route.name === "admin contest problem create"
|
||||||
) {
|
) {
|
||||||
toggleReady(true)
|
toggleReady(true)
|
||||||
}
|
}
|
||||||
|
listTags()
|
||||||
|
getProblemDetail()
|
||||||
})
|
})
|
||||||
|
|
||||||
watch([fromExistingTags, newTags], (tags) => {
|
watch([fromExistingTags, newTags], (tags) => {
|
||||||
@@ -443,7 +442,13 @@ watch([fromExistingTags, newTags], (tags) => {
|
|||||||
{{ problem.test_case_score.length }}
|
{{ problem.test_case_score.length }}
|
||||||
条测试用例
|
条测试用例
|
||||||
</div>
|
</div>
|
||||||
<n-button tertiary type="info" size="small" @click="downloadTestcases">
|
<n-button
|
||||||
|
v-if="problem.id"
|
||||||
|
tertiary
|
||||||
|
type="info"
|
||||||
|
size="small"
|
||||||
|
@click="downloadTestcases"
|
||||||
|
>
|
||||||
下载
|
下载
|
||||||
</n-button>
|
</n-button>
|
||||||
</n-space>
|
</n-space>
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ const columns: DataTableColumn<AdminProblemFiltered>[] = [
|
|||||||
render: (row) =>
|
render: (row) =>
|
||||||
h(Actions, {
|
h(Actions, {
|
||||||
problemID: row.id,
|
problemID: row.id,
|
||||||
|
problemDisplayID: row._id,
|
||||||
onDeleted: listProblems,
|
onDeleted: listProblems,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ async function handleLogout() {
|
|||||||
|
|
||||||
onMounted(userStore.getMyProfile)
|
onMounted(userStore.getMyProfile)
|
||||||
|
|
||||||
const menus: MenuOption[] = [
|
const menus = computed<MenuOption[]>(() => [
|
||||||
{
|
{
|
||||||
label: () =>
|
label: () =>
|
||||||
h(RouterLink, { to: "/learn/step-1" }, { default: () => "自学" }),
|
h(RouterLink, { to: "/learn/step-1" }, { default: () => "自学" }),
|
||||||
@@ -51,9 +51,14 @@ const menus: MenuOption[] = [
|
|||||||
label: () => h(RouterLink, { to: "/rank" }, { default: () => "排名" }),
|
label: () => h(RouterLink, { to: "/rank" }, { default: () => "排名" }),
|
||||||
key: "rank",
|
key: "rank",
|
||||||
},
|
},
|
||||||
]
|
{
|
||||||
|
label: () => h(RouterLink, { to: "/admin" }, { default: () => "后台" }),
|
||||||
|
show: userStore.isAdminRole,
|
||||||
|
key: "admin",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
const options = computed<Array<DropdownOption | DropdownDividerOption>>(() => [
|
const options: Array<DropdownOption | DropdownDividerOption> = [
|
||||||
{
|
{
|
||||||
label: "我的主页",
|
label: "我的主页",
|
||||||
key: "home",
|
key: "home",
|
||||||
@@ -75,17 +80,9 @@ const options = computed<Array<DropdownOption | DropdownDividerOption>>(() => [
|
|||||||
onClick: () => router.push("/setting"),
|
onClick: () => router.push("/setting"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: "后台管理",
|
|
||||||
key: "admin",
|
|
||||||
show: userStore.isAdminRole,
|
|
||||||
props: {
|
|
||||||
onClick: () => router.push("/admin"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ type: "divider" },
|
{ type: "divider" },
|
||||||
{ label: "退出", key: "logout", props: { onClick: handleLogout } },
|
{ label: "退出", key: "logout", props: { onClick: handleLogout } },
|
||||||
])
|
]
|
||||||
|
|
||||||
function run() {
|
function run() {
|
||||||
console.log(code.value)
|
console.log(code.value)
|
||||||
|
|||||||
@@ -39,6 +39,12 @@ onBeforeUnmount(() => {
|
|||||||
if (editor) editor.destroy()
|
if (editor) editor.destroy()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function onClick() {
|
||||||
|
if (!editorRef.value) return
|
||||||
|
editorRef.value.blur()
|
||||||
|
editorRef.value.focus()
|
||||||
|
}
|
||||||
|
|
||||||
function handleCreated(editor: IDomEditor) {
|
function handleCreated(editor: IDomEditor) {
|
||||||
editorRef.value = editor
|
editorRef.value = editor
|
||||||
}
|
}
|
||||||
@@ -66,6 +72,7 @@ async function customUpload(file: File, insertFn: InsertFnType) {
|
|||||||
mode="simple"
|
mode="simple"
|
||||||
/>
|
/>
|
||||||
<Editor
|
<Editor
|
||||||
|
@click="onClick"
|
||||||
:style="{ minHeight: props.minHeight + 'px' }"
|
:style="{ minHeight: props.minHeight + 'px' }"
|
||||||
v-model="rawHtml"
|
v-model="rawHtml"
|
||||||
:defaultConfig="editorConfig"
|
:defaultConfig="editorConfig"
|
||||||
|
|||||||
23
src/utils/download.ts
Normal file
23
src/utils/download.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import axios from "axios"
|
||||||
|
|
||||||
|
const http = axios.create({
|
||||||
|
baseURL: "/api/admin",
|
||||||
|
responseType: "blob",
|
||||||
|
xsrfHeaderName: "X-CSRFToken",
|
||||||
|
xsrfCookieName: "csrftoken",
|
||||||
|
})
|
||||||
|
|
||||||
|
async function download(url: string) {
|
||||||
|
const res = await http.get(url)
|
||||||
|
const headers = res.headers
|
||||||
|
const link = document.createElement("a")
|
||||||
|
link.href = window.URL.createObjectURL(
|
||||||
|
new window.Blob([res.data], { type: headers["content-type"] })
|
||||||
|
)
|
||||||
|
link.download = (headers["content-disposition"] || "").split("filename=")[1]
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
link.remove()
|
||||||
|
}
|
||||||
|
|
||||||
|
export default download
|
||||||
Reference in New Issue
Block a user