edit problem.
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import http from "utils/http"
|
import http from "utils/http"
|
||||||
import {
|
import {
|
||||||
|
AdminProblem,
|
||||||
BlankProblem,
|
BlankProblem,
|
||||||
Problem,
|
|
||||||
TestcaseUploadedReturns,
|
TestcaseUploadedReturns,
|
||||||
User,
|
User,
|
||||||
} from "~/utils/types"
|
} from "~/utils/types"
|
||||||
@@ -21,7 +21,7 @@ export async function getProblemList(
|
|||||||
params: { paging: true, offset, limit, keyword, contest_id: contestID },
|
params: { paging: true, offset, limit, keyword, contest_id: contestID },
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
results: res.data.results.map((result: Problem) => ({
|
results: res.data.results.map((result: AdminProblem) => ({
|
||||||
id: result.id,
|
id: result.id,
|
||||||
_id: result._id,
|
_id: result._id,
|
||||||
title: result.title,
|
title: result.title,
|
||||||
@@ -41,16 +41,16 @@ export function deleteContestProblem(id: number) {
|
|||||||
return http.delete("admin/contest/problem", { params: { id } })
|
return http.delete("admin/contest/problem", { params: { id } })
|
||||||
}
|
}
|
||||||
|
|
||||||
export function editProblem(problem: Problem | BlankProblem) {
|
export function editProblem(problem: AdminProblem | BlankProblem) {
|
||||||
return http.put("admin/problem", problem)
|
return http.put("admin/problem", problem)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function editContestProblem(problem: Problem | BlankProblem) {
|
export function editContestProblem(problem: AdminProblem | BlankProblem) {
|
||||||
return http.put("admin/contest/problem", problem)
|
return http.put("admin/contest/problem", problem)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getProblem(id: number) {
|
export function getProblem(id: string | number) {
|
||||||
return http.get("admin/problem", { params: { id } })
|
return http.get<AdminProblem>("admin/problem", { params: { id } })
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getContestProblem(id: number) {
|
export function getContestProblem(id: number) {
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ function goEdit() {
|
|||||||
<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-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>
|
||||||
|
|||||||
@@ -13,10 +13,12 @@ import {
|
|||||||
createProblem,
|
createProblem,
|
||||||
editContestProblem,
|
editContestProblem,
|
||||||
editProblem,
|
editProblem,
|
||||||
|
getProblem,
|
||||||
uploadTestcases,
|
uploadTestcases,
|
||||||
} from "../api"
|
} from "../api"
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
problemID?: string
|
||||||
contestID?: string
|
contestID?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +68,8 @@ const currentActiveTemplate = ref<LANGUAGE>("C")
|
|||||||
const existingTags = shallowRef<Tag[]>([])
|
const existingTags = shallowRef<Tag[]>([])
|
||||||
const fromExistingTags = shallowRef<string[]>([])
|
const fromExistingTags = shallowRef<string[]>([])
|
||||||
const newTags = shallowRef<string[]>([])
|
const newTags = shallowRef<string[]>([])
|
||||||
const [needTemplate] = useToggle(false)
|
const [needTemplate, toggleNeedTemplate] = useToggle(false)
|
||||||
|
const [ready, toggleReady] = useToggle(false)
|
||||||
|
|
||||||
const difficultyOptions: SelectOption[] = [
|
const difficultyOptions: SelectOption[] = [
|
||||||
{ label: "简单", value: "Low" },
|
{ label: "简单", value: "Low" },
|
||||||
@@ -87,6 +90,53 @@ const tagOptions = computed(() =>
|
|||||||
existingTags.value.map((tag) => ({ label: tag.name, value: tag.name }))
|
existingTags.value.map((tag) => ({ label: tag.name, value: tag.name }))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async function getProblemDetail() {
|
||||||
|
if (!props.problemID) return
|
||||||
|
const { data } = await getProblem(props.problemID)
|
||||||
|
toggleReady(true)
|
||||||
|
problem.id = data.id
|
||||||
|
problem._id = data._id
|
||||||
|
problem.title = data.title
|
||||||
|
problem.description = data.description
|
||||||
|
problem.input_description = data.input_description
|
||||||
|
problem.output_description = data.output_description
|
||||||
|
problem.time_limit = data.time_limit
|
||||||
|
problem.memory_limit = data.memory_limit
|
||||||
|
problem.memory_limit = data.memory_limit
|
||||||
|
problem.difficulty = data.difficulty
|
||||||
|
problem.visible = data.visible
|
||||||
|
problem.share_submission = data.share_submission
|
||||||
|
problem.tags = data.tags
|
||||||
|
problem.languages = data.languages
|
||||||
|
problem.template = data.template
|
||||||
|
problem.samples = data.samples
|
||||||
|
problem.samples = data.samples
|
||||||
|
problem.spj = data.spj
|
||||||
|
problem.spj_language = data.spj_language
|
||||||
|
problem.spj_code = data.spj_code
|
||||||
|
problem.spj_compile_ok = data.spj_compile_ok
|
||||||
|
problem.test_case_id = data.test_case_id
|
||||||
|
problem.test_case_score = data.test_case_score
|
||||||
|
problem.rule_type = data.rule_type
|
||||||
|
problem.hint = data.hint
|
||||||
|
problem.source = data.source
|
||||||
|
problem.io_mode = data.io_mode
|
||||||
|
if (problem.contest_id) {
|
||||||
|
problem.contest_id = problem.contest_id
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下面是用来显示的:
|
||||||
|
// 代码模板 和 模板开关
|
||||||
|
problem.languages.forEach((lang) => {
|
||||||
|
if (data.template[lang]) {
|
||||||
|
template[lang] = data.template[lang]
|
||||||
|
toggleNeedTemplate(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// 标签
|
||||||
|
fromExistingTags.value = data.tags
|
||||||
|
}
|
||||||
|
|
||||||
async function listTags() {
|
async function listTags() {
|
||||||
const res = await getProblemTagList()
|
const res = await getProblemTagList()
|
||||||
existingTags.value = res.data
|
existingTags.value = res.data
|
||||||
@@ -145,6 +195,7 @@ async function handleUploadTestcases({ file }: UploadCustomRequestOptions) {
|
|||||||
// TODO: 还没有完成
|
// TODO: 还没有完成
|
||||||
function downloadTestcases() {}
|
function downloadTestcases() {}
|
||||||
|
|
||||||
|
// 题目是否有漏写的
|
||||||
function detectProblemCompletion() {
|
function detectProblemCompletion() {
|
||||||
let flag = false
|
let flag = false
|
||||||
// 标题
|
// 标题
|
||||||
@@ -229,7 +280,12 @@ async function submit() {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await api!(problem)
|
await api!(problem)
|
||||||
message.success("恭喜你 💐 出题成功")
|
if (
|
||||||
|
route.name === "admin problem create" ||
|
||||||
|
route.name === "admin contest problem create"
|
||||||
|
) {
|
||||||
|
message.success("恭喜你 💐 出题成功")
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
route.name === "admin problem create" ||
|
route.name === "admin problem create" ||
|
||||||
route.name === "admin problem edit"
|
route.name === "admin problem edit"
|
||||||
@@ -252,6 +308,14 @@ async function submit() {
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
listTags()
|
listTags()
|
||||||
|
getProblemDetail()
|
||||||
|
|
||||||
|
if (
|
||||||
|
route.name === "admin problem create" ||
|
||||||
|
route.name === "admin contest problem create"
|
||||||
|
) {
|
||||||
|
toggleReady(true)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
watch([fromExistingTags, newTags], (tags) => {
|
watch([fromExistingTags, newTags], (tags) => {
|
||||||
@@ -293,12 +357,21 @@ watch([fromExistingTags, newTags], (tags) => {
|
|||||||
</n-form-item>
|
</n-form-item>
|
||||||
</n-form>
|
</n-form>
|
||||||
<TextEditor
|
<TextEditor
|
||||||
|
v-if="ready"
|
||||||
v-model:value="problem.description"
|
v-model:value="problem.description"
|
||||||
title="题目本体"
|
title="题目本体"
|
||||||
:min-height="300"
|
:min-height="300"
|
||||||
/>
|
/>
|
||||||
<TextEditor v-model:value="problem.input_description" title="输入的描述" />
|
<TextEditor
|
||||||
<TextEditor v-model:value="problem.output_description" title="输出的描述" />
|
v-if="ready"
|
||||||
|
v-model:value="problem.input_description"
|
||||||
|
title="输入的描述"
|
||||||
|
/>
|
||||||
|
<TextEditor
|
||||||
|
v-if="ready"
|
||||||
|
v-model:value="problem.output_description"
|
||||||
|
title="输出的描述"
|
||||||
|
/>
|
||||||
<div class="box" v-for="(sample, index) in problem.samples" :key="index">
|
<div class="box" v-for="(sample, index) in problem.samples" :key="index">
|
||||||
<n-space justify="space-between" align="center">
|
<n-space justify="space-between" align="center">
|
||||||
<strong>测试样例 {{ index + 1 }}</strong>
|
<strong>测试样例 {{ index + 1 }}</strong>
|
||||||
@@ -329,7 +402,7 @@ watch([fromExistingTags, newTags], (tags) => {
|
|||||||
<n-button class="addSamples box" tertiary type="primary" @click="addSample">
|
<n-button class="addSamples box" tertiary type="primary" @click="addSample">
|
||||||
添加用例
|
添加用例
|
||||||
</n-button>
|
</n-button>
|
||||||
<TextEditor v-model:value="problem.hint" title="提示" />
|
<TextEditor v-if="ready" v-model:value="problem.hint" title="提示" />
|
||||||
<n-form>
|
<n-form>
|
||||||
<n-form-item label="题目的来源">
|
<n-form-item label="题目的来源">
|
||||||
<n-input
|
<n-input
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ const columns: DataTableColumn<AdminProblemFiltered>[] = [
|
|||||||
{
|
{
|
||||||
title: "选项",
|
title: "选项",
|
||||||
key: "actions",
|
key: "actions",
|
||||||
width: 200,
|
width: 250,
|
||||||
render: (row) =>
|
render: (row) =>
|
||||||
h(Actions, {
|
h(Actions, {
|
||||||
problemID: row.id,
|
problemID: row.id,
|
||||||
|
|||||||
@@ -72,6 +72,18 @@ export interface Tag {
|
|||||||
name: string
|
name: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TestcaseUploadedReturns {
|
||||||
|
id: string
|
||||||
|
info: Testcase[]
|
||||||
|
spj: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Testcase {
|
||||||
|
input_name: string
|
||||||
|
output_name: string
|
||||||
|
score: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface Problem {
|
export interface Problem {
|
||||||
_id: string
|
_id: string
|
||||||
id: number
|
id: number
|
||||||
@@ -112,6 +124,32 @@ export interface Problem {
|
|||||||
visible: boolean
|
visible: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type AdminProblem = Problem & AlterProblem
|
||||||
|
|
||||||
|
interface AlterProblem {
|
||||||
|
spj_language: string
|
||||||
|
spj_code: string
|
||||||
|
spj_compile_ok: boolean
|
||||||
|
test_case_id: string
|
||||||
|
test_case_score: Testcase[]
|
||||||
|
contest_id?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExcludeKeys =
|
||||||
|
| "id"
|
||||||
|
| "created_by"
|
||||||
|
| "create_time"
|
||||||
|
| "last_update_time"
|
||||||
|
| "my_status"
|
||||||
|
| "contest"
|
||||||
|
| "statistic_info"
|
||||||
|
| "accepted_number"
|
||||||
|
| "submission_number"
|
||||||
|
| "total_score"
|
||||||
|
|
||||||
|
export type BlankProblem = Omit<Problem, ExcludeKeys> &
|
||||||
|
AlterProblem & { id?: number }
|
||||||
|
|
||||||
export interface ProblemFiltered {
|
export interface ProblemFiltered {
|
||||||
_id: string
|
_id: string
|
||||||
id: number
|
id: number
|
||||||
@@ -262,42 +300,3 @@ export interface ContestRank {
|
|||||||
submission_info: { [key: string]: SubmissionInfo }
|
submission_info: { [key: string]: SubmissionInfo }
|
||||||
contest: number
|
contest: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TestcaseUploadedReturns {
|
|
||||||
id: string
|
|
||||||
info: Testcase[]
|
|
||||||
spj: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Testcase {
|
|
||||||
stripped_output_md5: string
|
|
||||||
input_size: number
|
|
||||||
output_size: number
|
|
||||||
input_name: string
|
|
||||||
output_name: string
|
|
||||||
score?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
interface AlterProblem {
|
|
||||||
spj_language: string
|
|
||||||
spj_code: string
|
|
||||||
spj_compile_ok: boolean
|
|
||||||
test_case_id: string
|
|
||||||
test_case_score: Testcase[]
|
|
||||||
contest_id?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
type ExcludeKeys =
|
|
||||||
| "id"
|
|
||||||
| "created_by"
|
|
||||||
| "create_time"
|
|
||||||
| "last_update_time"
|
|
||||||
| "my_status"
|
|
||||||
| "contest"
|
|
||||||
| "statistic_info"
|
|
||||||
| "accepted_number"
|
|
||||||
| "submission_number"
|
|
||||||
| "total_score"
|
|
||||||
|
|
||||||
export type BlankProblem = Omit<Problem, ExcludeKeys> &
|
|
||||||
AlterProblem & { id?: number }
|
|
||||||
|
|||||||
Reference in New Issue
Block a user