✨ Challenge Submit
This commit is contained in:
parent
ffa7f097af
commit
961508449f
6
.idea/deno.xml
Normal file
6
.idea/deno.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DenoSettings">
|
||||
<option name="useDeno" value="true" />
|
||||
</component>
|
||||
</project>
|
@ -1,15 +1,26 @@
|
||||
<template>
|
||||
<n-message-provider>
|
||||
<n-dialog-provider>
|
||||
<nuxt-layout>
|
||||
<nuxt-loading-indicator />
|
||||
<nuxt-page />
|
||||
</nuxt-layout>
|
||||
</n-dialog-provider>
|
||||
</n-message-provider>
|
||||
<n-config-provider :theme-overrides="theme">
|
||||
<n-message-provider>
|
||||
<n-dialog-provider>
|
||||
<nuxt-layout>
|
||||
<nuxt-loading-indicator />
|
||||
<nuxt-page />
|
||||
</nuxt-layout>
|
||||
</n-dialog-provider>
|
||||
</n-message-provider>
|
||||
</n-config-provider>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { NMessageProvider, NDialogProvider } from "naive-ui";
|
||||
import { NConfigProvider, NMessageProvider, NDialogProvider } from "naive-ui";
|
||||
import "@/assets/css/index.css";
|
||||
|
||||
const theme = {
|
||||
"common": {
|
||||
"primaryColor": "#e7bf72",
|
||||
"primaryColorHover": "#f1ca7a",
|
||||
"primaryColorPressed": "#d6b26b",
|
||||
"primaryColorSuppl": "#c49e55"
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
@ -20,4 +20,9 @@ code, pre {
|
||||
|
||||
pre {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #c49e55;
|
||||
text-decoration: none;
|
||||
}
|
Binary file not shown.
21
application/components/problem/preview/program.vue
Normal file
21
application/components/problem/preview/program.vue
Normal file
@ -0,0 +1,21 @@
|
||||
<template>
|
||||
<n-card>
|
||||
<n-code :hljs="hljs" :language="language" :code="props.answers?.code" />
|
||||
</n-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { NCard, NCode } from "naive-ui";
|
||||
import hljs from "highlight.js/lib/core";
|
||||
import cpp from "highlight.js/lib/languages/cpp";
|
||||
|
||||
hljs.registerLanguage("cpp", cpp);
|
||||
|
||||
const props = defineProps<{
|
||||
challenge: any,
|
||||
problem: any,
|
||||
answers: any,
|
||||
}>();
|
||||
|
||||
const language = computed(() => props.answers?.language ?? "text");
|
||||
</script>
|
@ -26,6 +26,7 @@
|
||||
"@ibm/plex": "^6.3.0",
|
||||
"@nuxtjs/mdc": "^0.2.8",
|
||||
"@supabase/supabase-js": "^2.39.0",
|
||||
"highlight.js": "^11.9.0",
|
||||
"prismjs": "^1.29.0"
|
||||
}
|
||||
}
|
||||
|
@ -12,17 +12,52 @@
|
||||
</n-page-header>
|
||||
</template>
|
||||
|
||||
<section>
|
||||
<div id="answering-content" v-if="challenge?.status === 'in-progress'">
|
||||
<problem-solution-program
|
||||
v-if="problem.type === 'programming'"
|
||||
v-model:answers="answers"
|
||||
:challenge="challenge"
|
||||
:problem="problem"
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div id="preview-challenge" class="flex flex-col gap-4" v-else>
|
||||
<div>
|
||||
<div class="font-bold">状态</div>
|
||||
<div class="case-capital">{{ challenge?.status?.replaceAll("-", " ") }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-bold">问题</div>
|
||||
<div>
|
||||
<nuxt-link target="_blank" :to="`/problems/${challenge.problem}`">
|
||||
#{{ challenge?.problem }} | {{ problem?.title }}
|
||||
</nuxt-link>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-bold">答案</div>
|
||||
<client-only>
|
||||
<div class="mt-2 mx-[-4px]">
|
||||
<problem-preview-program
|
||||
v-if="problem.type === 'programming'"
|
||||
:answers="answers"
|
||||
:challenge="challenge"
|
||||
:problem="problem"
|
||||
/>
|
||||
</div>
|
||||
</client-only>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-bold">结果</div>
|
||||
<n-card embedded class="mt-2 mx-[-4px]">
|
||||
<div v-if="challenge?.details?.cases"></div>
|
||||
<n-empty v-else description="未进行判题,暂无挑战结果" />
|
||||
</n-card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #action>
|
||||
<div class="w-full flex justify-between">
|
||||
<div v-if="challenge?.status === 'in-progress'" id="answering-widgets" class="w-full flex justify-between">
|
||||
<div class="flex gap-2">
|
||||
<n-button secondary circle class="rounded-[4px]" type="warning" :disabled="submitting" @click="save">
|
||||
<template #icon>
|
||||
@ -41,7 +76,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { NButton, NCard, NPageHeader, NTag, NIcon, useDialog, useMessage } from "naive-ui";
|
||||
import { NButton, NCard, NPageHeader, NTag, NIcon, NEmpty, useDialog, useMessage } from "naive-ui";
|
||||
import { Save } from "@vicons/carbon";
|
||||
|
||||
const route = useRoute();
|
||||
@ -124,6 +159,36 @@ function abandon() {
|
||||
}
|
||||
|
||||
async function submit() {
|
||||
await save();
|
||||
|
||||
const instance = dialog.warning({
|
||||
title: "警告",
|
||||
content: "你确定要提交吗?确认提交后无法再次修改答案,等待判题可能需要一段时间。",
|
||||
positiveText: "确定",
|
||||
negativeText: "不确定",
|
||||
onPositiveClick: async () => {
|
||||
instance.loading = true;
|
||||
|
||||
const inst = message.loading("正在提交中,请稍后……");
|
||||
|
||||
const { error } = await client
|
||||
.from("challenges")
|
||||
// @ts-ignore
|
||||
.update<any>({ status: "submitted" })
|
||||
.eq("id", challenge.id);
|
||||
|
||||
if (error != null) {
|
||||
message.error(`Something went wrong... ${error.message}`);
|
||||
}
|
||||
|
||||
inst.destroy();
|
||||
message.success("提交成功!即将跳转结果页面……");
|
||||
|
||||
const delay = (ms: number) => new Promise(res => setTimeout(res, ms));
|
||||
|
||||
await delay(1850);
|
||||
reloadNuxtApp();
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
39
supabase/functions/judge-challenges/index.ts
Normal file
39
supabase/functions/judge-challenges/index.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { createClient } from "https://esm.sh/@supabase/supabase-js";
|
||||
|
||||
Deno.serve(async (req) => {
|
||||
try {
|
||||
const client = createClient(
|
||||
Deno.env.get('SUPABASE_URL') ?? '',
|
||||
Deno.env.get('SUPABASE_ANON_KEY') ?? '',
|
||||
{ global: { headers: { Authorization: req.headers.get('Authorization')! } } }
|
||||
)
|
||||
|
||||
const { data, error } = await client
|
||||
.from('challenges')
|
||||
.select<any, any>('*')
|
||||
.eq('status', 'submitted')
|
||||
|
||||
if (error) {
|
||||
throw error
|
||||
}
|
||||
|
||||
return new Response(JSON.stringify({ data }), {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
status: 200,
|
||||
})
|
||||
} catch (err) {
|
||||
return new Response(String(err?.message ?? err), { status: 500 })
|
||||
}
|
||||
});
|
||||
|
||||
/* To invoke locally:
|
||||
|
||||
1. Run `supabase start` (see: https://supabase.com/docs/reference/cli/supabase-start)
|
||||
2. Make an HTTP request:
|
||||
|
||||
curl -i --location --request POST 'http://127.0.0.1:54321/functions/v1/judge-challenges' \
|
||||
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{"name":"Functions"}'
|
||||
|
||||
*/
|
Loading…
Reference in New Issue
Block a user