update icons
This commit is contained in:
@@ -7,6 +7,7 @@ import { isDesktop } from "~/shared/composables/breakpoints"
|
|||||||
import { NTag } from "naive-ui"
|
import { NTag } from "naive-ui"
|
||||||
import TitleWithTag from "./components/TitleWithTag.vue"
|
import TitleWithTag from "./components/TitleWithTag.vue"
|
||||||
import { Icon } from "@iconify/vue"
|
import { Icon } from "@iconify/vue"
|
||||||
|
import { renderTableTitle } from "~/utils/renders"
|
||||||
|
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
const content = ref("")
|
const content = ref("")
|
||||||
@@ -19,30 +20,30 @@ const query = reactive({
|
|||||||
const columns: DataTableColumn<Announcement>[] = [
|
const columns: DataTableColumn<Announcement>[] = [
|
||||||
{
|
{
|
||||||
key: "title",
|
key: "title",
|
||||||
title: "公告标题",
|
title: renderTableTitle("公告标题", "streamline-emojis:fire"),
|
||||||
render: (row) => h(TitleWithTag, { title: row.title, top: row.top }),
|
render: (row) => h(TitleWithTag, { title: row.title, top: row.top }),
|
||||||
minWidth: 300,
|
minWidth: 300,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "tag",
|
key: "tag",
|
||||||
title: "标签",
|
title: renderTableTitle("标签", "fluent-emoji-flat:keycap-hashtag"),
|
||||||
render: (row) => h(NTag, () => row.tag || "公告"),
|
render: (row) => h(NTag, () => row.tag || "公告"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "create_time",
|
key: "create_time",
|
||||||
title: "发布时间",
|
title: renderTableTitle("发布时间", "fluent-emoji-flat:eight-oclock"),
|
||||||
render: (row) => parseTime(row.create_time),
|
render: (row) => parseTime(row.create_time),
|
||||||
width: 180,
|
width: 180,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "last_update_time",
|
key: "last_update_time",
|
||||||
title: "更新时间",
|
title: renderTableTitle("更新时间", "fluent-emoji-flat:eleven-thirty"),
|
||||||
render: (row) => parseTime(row.last_update_time),
|
render: (row) => parseTime(row.last_update_time),
|
||||||
width: 180,
|
width: 180,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "username",
|
key: "username",
|
||||||
title: "发布人",
|
title: renderTableTitle("发布人", "streamline-emojis:ghost"),
|
||||||
render: (row) => row.created_by.username,
|
render: (row) => row.created_by.username,
|
||||||
width: 120,
|
width: 120,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ const contestStore = useContestStore()
|
|||||||
<template #trigger>
|
<template #trigger>
|
||||||
<n-button>
|
<n-button>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<Icon icon="openmoji:compass"></Icon>
|
<Icon icon="streamline-emojis:exclamation-mark"></Icon>
|
||||||
</template>
|
</template>
|
||||||
比赛信息
|
比赛信息
|
||||||
</n-button>
|
</n-button>
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ const passwordFormVisible = computed(
|
|||||||
<n-space align="center">
|
<n-space align="center">
|
||||||
<Icon
|
<Icon
|
||||||
v-if="contestStore.isPrivate"
|
v-if="contestStore.isPrivate"
|
||||||
icon="openmoji:locked"
|
icon="streamline-emojis:locked-with-key"
|
||||||
:width="30"
|
:width="30"
|
||||||
:height="30"
|
:height="30"
|
||||||
></Icon>
|
></Icon>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import ContestTitle from "~/shared/components/ContestTitle.vue"
|
|||||||
import Pagination from "~/shared/components/Pagination.vue"
|
import Pagination from "~/shared/components/Pagination.vue"
|
||||||
import { useUserStore } from "~/shared/store/user"
|
import { useUserStore } from "~/shared/store/user"
|
||||||
import { toggleLogin } from "~/shared/composables/modal"
|
import { toggleLogin } from "~/shared/composables/modal"
|
||||||
|
import { renderTableTitle } from "~/utils/renders"
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -30,7 +31,7 @@ const options: SelectOption[] = [
|
|||||||
|
|
||||||
const columns: DataTableColumn<Contest>[] = [
|
const columns: DataTableColumn<Contest>[] = [
|
||||||
{
|
{
|
||||||
title: "状态",
|
title: renderTableTitle("状态", "streamline-emojis:collision"),
|
||||||
key: "status",
|
key: "status",
|
||||||
width: 100,
|
width: 100,
|
||||||
render: (row) =>
|
render: (row) =>
|
||||||
@@ -41,19 +42,19 @@ const columns: DataTableColumn<Contest>[] = [
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "比赛",
|
title: renderTableTitle("比赛", "streamline-emojis:bouquet"),
|
||||||
key: "title",
|
key: "title",
|
||||||
minWidth: 360,
|
minWidth: 360,
|
||||||
render: (row) => h(ContestTitle, { contest: row }),
|
render: (row) => h(ContestTitle, { contest: row }),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "开始时间",
|
title: renderTableTitle("开始时间", "fluent-emoji-flat:eleven-thirty"),
|
||||||
key: "start_time",
|
key: "start_time",
|
||||||
width: 180,
|
width: 180,
|
||||||
render: (row) => parseTime(row.start_time),
|
render: (row) => parseTime(row.start_time),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "比赛时长",
|
title: renderTableTitle("比赛时长", "streamline-emojis:fishing-pole"),
|
||||||
key: "duration",
|
key: "duration",
|
||||||
width: 180,
|
width: 180,
|
||||||
render: (row) => duration(row.start_time, row.end_time),
|
render: (row) => duration(row.start_time, row.end_time),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import { ProblemFiltered } from "utils/types"
|
import { ProblemFiltered } from "utils/types"
|
||||||
import ProblemStatus from "~/oj/problem/components/ProblemStatus.vue"
|
import ProblemStatus from "~/oj/problem/components/ProblemStatus.vue"
|
||||||
import { useContestStore } from "~/oj/store/contest"
|
import { useContestStore } from "~/oj/store/contest"
|
||||||
|
import { renderTableTitle } from "~/utils/renders"
|
||||||
|
|
||||||
const props = defineProps<{ contestID: string }>()
|
const props = defineProps<{ contestID: string }>()
|
||||||
|
|
||||||
@@ -9,15 +10,33 @@ const router = useRouter()
|
|||||||
const contestStore = useContestStore()
|
const contestStore = useContestStore()
|
||||||
const problemsColumns: DataTableColumn<ProblemFiltered>[] = [
|
const problemsColumns: DataTableColumn<ProblemFiltered>[] = [
|
||||||
{
|
{
|
||||||
title: "状态",
|
title: renderTableTitle("状态", "streamline-emojis:musical-note"),
|
||||||
key: "status",
|
key: "status",
|
||||||
width: 60,
|
width: 100,
|
||||||
render: (row) => h(ProblemStatus, { status: row.status }),
|
render: (row) => h(ProblemStatus, { status: row.status }),
|
||||||
},
|
},
|
||||||
{ title: "编号", key: "_id", width: 60 },
|
{
|
||||||
{ title: "题目", key: "title", minWidth: 200 },
|
title: renderTableTitle("编号", "fluent-emoji-flat:input-numbers"),
|
||||||
{ title: "总提交数", key: "submission", width: 100 },
|
key: "_id",
|
||||||
{ title: "通过率", key: "rate", width: 100 },
|
width: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: renderTableTitle("题目", "streamline-emojis:rice-ball"),
|
||||||
|
key: "title",
|
||||||
|
minWidth: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: renderTableTitle("提交数", "streamline-emojis:clinking-beer-mugs"),
|
||||||
|
key: "submission",
|
||||||
|
align: "center",
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: renderTableTitle("通过率", "streamline-emojis:clapping-hands-1"),
|
||||||
|
key: "rate",
|
||||||
|
align: "center",
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
function rowProps(row: ProblemFiltered) {
|
function rowProps(row: ProblemFiltered) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { secondsToDuration } from "utils/functions"
|
|||||||
import { ContestStatus } from "~/utils/constants"
|
import { ContestStatus } from "~/utils/constants"
|
||||||
import { useContestStore } from "~/oj/store/contest"
|
import { useContestStore } from "~/oj/store/contest"
|
||||||
import { Icon } from "@iconify/vue"
|
import { Icon } from "@iconify/vue"
|
||||||
|
import { renderTableTitle } from "~/utils/renders"
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
contestID: string
|
contestID: string
|
||||||
@@ -44,15 +45,18 @@ const query = reactive({
|
|||||||
|
|
||||||
const columns = ref<DataTableColumn<ContestRank>[]>([
|
const columns = ref<DataTableColumn<ContestRank>[]>([
|
||||||
{
|
{
|
||||||
title: "排名",
|
title: renderTableTitle("编号", "fluent-emoji-flat:input-numbers"),
|
||||||
key: "id",
|
key: "id",
|
||||||
width: 60,
|
width: 80,
|
||||||
fixed: "left",
|
fixed: "left",
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (_, index) => index + (query.page - 1) * query.limit + 1,
|
render: (_, index) => index + (query.page - 1) * query.limit + 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "用户",
|
title: renderTableTitle(
|
||||||
|
"用户",
|
||||||
|
"streamline-emojis:smiling-face-with-sunglasses",
|
||||||
|
),
|
||||||
key: "username",
|
key: "username",
|
||||||
width: 120,
|
width: 120,
|
||||||
fixed: "left",
|
fixed: "left",
|
||||||
@@ -69,9 +73,12 @@ const columns = ref<DataTableColumn<ContestRank>[]>([
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "正确数/总提交",
|
title: renderTableTitle(
|
||||||
|
"正确数/总提交",
|
||||||
|
"streamline-emojis:artist-palette",
|
||||||
|
),
|
||||||
key: "submission",
|
key: "submission",
|
||||||
width: 120,
|
width: 140,
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (row) => h(AcAndSubmission, { rank: row }),
|
render: (row) => h(AcAndSubmission, { rank: row }),
|
||||||
},
|
},
|
||||||
@@ -133,9 +140,9 @@ async function addColumns() {
|
|||||||
if (status.is_first_ac) {
|
if (status.is_first_ac) {
|
||||||
acTime = [
|
acTime = [
|
||||||
h(Icon, {
|
h(Icon, {
|
||||||
icon: "openmoji:1st-place-medal",
|
icon: "fluent-emoji:1st-place-medal",
|
||||||
height: 24,
|
height: 20,
|
||||||
width: 24,
|
width: 20,
|
||||||
}),
|
}),
|
||||||
h("span", secondsToDuration(status.ac_time)),
|
h("span", secondsToDuration(status.ac_time)),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { problem } from "oj/composables/problem"
|
|||||||
import { Problem, ProblemStatus } from "utils/types"
|
import { Problem, ProblemStatus } from "utils/types"
|
||||||
import { createTestSubmission } from "utils/judge"
|
import { createTestSubmission } from "utils/judge"
|
||||||
import { useThemeVars } from "naive-ui"
|
import { useThemeVars } from "naive-ui"
|
||||||
|
import { Icon } from "@iconify/vue"
|
||||||
|
|
||||||
type Sample = Problem["samples"][number] & {
|
type Sample = Problem["samples"][number] & {
|
||||||
id: number
|
id: number
|
||||||
@@ -99,17 +100,37 @@ function type(status: ProblemStatus) {
|
|||||||
<n-tag>{{ problem._id }}</n-tag>
|
<n-tag>{{ problem._id }}</n-tag>
|
||||||
<h2 class="problemTitle">{{ problem.title }}</h2>
|
<h2 class="problemTitle">{{ problem.title }}</h2>
|
||||||
</n-space>
|
</n-space>
|
||||||
<p class="title" :style="style">描述</p>
|
<p class="title" :style="style">
|
||||||
|
<n-flex align="center">
|
||||||
|
<Icon icon="streamline-emojis:sparkles"></Icon>
|
||||||
|
描述
|
||||||
|
</n-flex>
|
||||||
|
</p>
|
||||||
<div class="content" v-html="problem.description"></div>
|
<div class="content" v-html="problem.description"></div>
|
||||||
|
|
||||||
<p class="title" :style="style">输入</p>
|
<p class="title" :style="style">
|
||||||
|
<n-flex align="center">
|
||||||
|
<Icon icon="streamline-emojis:four-leaf-clover"></Icon>
|
||||||
|
输入
|
||||||
|
</n-flex>
|
||||||
|
</p>
|
||||||
<div class="content" v-html="problem.input_description"></div>
|
<div class="content" v-html="problem.input_description"></div>
|
||||||
|
|
||||||
<p class="title" :style="style">输出</p>
|
<p class="title" :style="style">
|
||||||
|
<n-flex align="center">
|
||||||
|
<Icon icon="streamline-emojis:herb"></Icon>
|
||||||
|
输出
|
||||||
|
</n-flex>
|
||||||
|
</p>
|
||||||
<div class="content" v-html="problem.output_description"></div>
|
<div class="content" v-html="problem.output_description"></div>
|
||||||
|
|
||||||
<div v-if="problem.hint">
|
<div v-if="problem.hint">
|
||||||
<p class="title" :style="style">提示</p>
|
<p class="title" :style="style">
|
||||||
|
<n-flex align="center">
|
||||||
|
<Icon icon="streamline-emojis:seedling"></Icon>
|
||||||
|
提示
|
||||||
|
</n-flex>
|
||||||
|
</p>
|
||||||
<div class="content" v-html="problem.hint"></div>
|
<div class="content" v-html="problem.hint"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { isDesktop } from "~/shared/composables/breakpoints"
|
|||||||
import SubmissionResultTag from "~/shared/components/SubmissionResultTag.vue"
|
import SubmissionResultTag from "~/shared/components/SubmissionResultTag.vue"
|
||||||
import Pagination from "~/shared/components/Pagination.vue"
|
import Pagination from "~/shared/components/Pagination.vue"
|
||||||
import { NButton } from "naive-ui"
|
import { NButton } from "naive-ui"
|
||||||
|
import { renderTableTitle } from "~/utils/renders"
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
@@ -15,7 +16,7 @@ const router = useRouter()
|
|||||||
|
|
||||||
const columns: DataTableColumn<Submission>[] = [
|
const columns: DataTableColumn<Submission>[] = [
|
||||||
{
|
{
|
||||||
title: "提交时间",
|
title: renderTableTitle("提交时间", "noto:seven-oclock"),
|
||||||
key: "create_time",
|
key: "create_time",
|
||||||
width: 200,
|
width: 200,
|
||||||
render: (row) =>
|
render: (row) =>
|
||||||
@@ -25,7 +26,7 @@ const columns: DataTableColumn<Submission>[] = [
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "编号",
|
title: renderTableTitle("编号", "fluent-emoji-flat:input-numbers"),
|
||||||
key: "id",
|
key: "id",
|
||||||
minWidth: 160,
|
minWidth: 160,
|
||||||
render: (row) => {
|
render: (row) => {
|
||||||
@@ -48,13 +49,16 @@ const columns: DataTableColumn<Submission>[] = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "状态",
|
title: renderTableTitle("状态", "streamline-emojis:panda-face"),
|
||||||
key: "status",
|
key: "status",
|
||||||
width: 140,
|
width: 140,
|
||||||
render: (row) => h(SubmissionResultTag, { result: row.result }),
|
render: (row) => h(SubmissionResultTag, { result: row.result }),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "语言",
|
title: renderTableTitle(
|
||||||
|
"语言",
|
||||||
|
"streamline-emojis:globe-showing-europe-africa",
|
||||||
|
),
|
||||||
key: "language",
|
key: "language",
|
||||||
width: 100,
|
width: 100,
|
||||||
render: (row) => LANGUAGE_SHOW_VALUE[row.language],
|
render: (row) => LANGUAGE_SHOW_VALUE[row.language],
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { getProblemTagList } from "~/shared/api"
|
|||||||
import Pagination from "~/shared/components/Pagination.vue"
|
import Pagination from "~/shared/components/Pagination.vue"
|
||||||
import { isDesktop } from "~/shared/composables/breakpoints"
|
import { isDesktop } from "~/shared/composables/breakpoints"
|
||||||
import { Icon } from "@iconify/vue"
|
import { Icon } from "@iconify/vue"
|
||||||
|
import { renderTableTitle } from "~/utils/renders"
|
||||||
|
|
||||||
interface Tag {
|
interface Tag {
|
||||||
id: number
|
id: number
|
||||||
@@ -150,29 +151,48 @@ onMounted(() => {
|
|||||||
|
|
||||||
const baseColumns: DataTableColumn<ProblemFiltered>[] = [
|
const baseColumns: DataTableColumn<ProblemFiltered>[] = [
|
||||||
{
|
{
|
||||||
title: "状态",
|
title: renderTableTitle("状态", "streamline-emojis:musical-note"),
|
||||||
key: "status",
|
key: "status",
|
||||||
width: 60,
|
width: 80,
|
||||||
|
align: "center",
|
||||||
render: (row) => h(ProblemStatus, { status: row.status }),
|
render: (row) => h(ProblemStatus, { status: row.status }),
|
||||||
},
|
},
|
||||||
{ title: "编号", key: "_id", width: 100 },
|
|
||||||
{ title: "题目", key: "title", minWidth: 200 },
|
|
||||||
{
|
{
|
||||||
title: "难度",
|
title: renderTableTitle("编号", "fluent-emoji-flat:input-numbers"),
|
||||||
|
key: "_id",
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: renderTableTitle("题目", "streamline-emojis:rice-ball"),
|
||||||
|
key: "title",
|
||||||
|
minWidth: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: renderTableTitle("难度", "streamline-emojis:mushroom"),
|
||||||
key: "difficulty",
|
key: "difficulty",
|
||||||
width: 100,
|
width: 100,
|
||||||
render: (row) =>
|
render: (row) =>
|
||||||
h(NTag, { type: getTagColor(row.difficulty) }, () => row.difficulty),
|
h(NTag, { type: getTagColor(row.difficulty) }, () => row.difficulty),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "标签",
|
title: renderTableTitle("标签", "fluent-emoji-flat:keycap-hashtag"),
|
||||||
key: "tags",
|
key: "tags",
|
||||||
width: 260,
|
width: 260,
|
||||||
render: (row) =>
|
render: (row) =>
|
||||||
h(NSpace, () => row.tags.map((t) => h(NTag, { key: t }, () => t))),
|
h(NSpace, () => row.tags.map((t) => h(NTag, { key: t }, () => t))),
|
||||||
},
|
},
|
||||||
{ title: "提交数", key: "submission", width: 100 },
|
{
|
||||||
{ title: "通过率", key: "rate", width: 100 },
|
title: renderTableTitle("提交数", "streamline-emojis:clinking-beer-mugs"),
|
||||||
|
key: "submission",
|
||||||
|
align: "center",
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: renderTableTitle("通过率", "streamline-emojis:clapping-hands-1"),
|
||||||
|
key: "rate",
|
||||||
|
width: 100,
|
||||||
|
align: "center",
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
const columns = computed(() =>
|
const columns = computed(() =>
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ const tooltip = computed(() => {
|
|||||||
<span v-if="index > 3">{{ index }}</span>
|
<span v-if="index > 3">{{ index }}</span>
|
||||||
<n-tooltip v-else>
|
<n-tooltip v-else>
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<n-icon :size="20">
|
<n-icon :size="24">
|
||||||
<Icon v-if="index === 1" icon="openmoji:1st-place-medal"></Icon>
|
<Icon v-if="index === 1" icon="fluent-emoji:1st-place-medal"></Icon>
|
||||||
<Icon v-if="index === 2" icon="openmoji:2nd-place-medal"></Icon>
|
<Icon v-if="index === 2" icon="fluent-emoji:2nd-place-medal"></Icon>
|
||||||
<Icon v-if="index === 3" icon="openmoji:3rd-place-medal"></Icon>
|
<Icon v-if="index === 3" icon="fluent-emoji:3rd-place-medal"></Icon>
|
||||||
</n-icon>
|
</n-icon>
|
||||||
</template>
|
</template>
|
||||||
{{ tooltip }}
|
{{ tooltip }}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { Rank } from "utils/types"
|
|||||||
import { getRank } from "oj/api"
|
import { getRank } from "oj/api"
|
||||||
import { getACRate } from "utils/functions"
|
import { getACRate } from "utils/functions"
|
||||||
import Index from "./components/Index.vue"
|
import Index from "./components/Index.vue"
|
||||||
|
import { renderTableTitle } from "~/utils/renders"
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const data = ref<Rank[]>([])
|
const data = ref<Rank[]>([])
|
||||||
@@ -28,15 +29,18 @@ async function listRanks() {
|
|||||||
|
|
||||||
const columns: DataTableColumn<Rank>[] = [
|
const columns: DataTableColumn<Rank>[] = [
|
||||||
{
|
{
|
||||||
title: "排名",
|
title: renderTableTitle("排名", "streamline-emojis:flexed-biceps-1"),
|
||||||
key: "index",
|
key: "index",
|
||||||
width: 80,
|
width: 100,
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (_, index) =>
|
render: (_, index) =>
|
||||||
h(Index, { index, page: query.page, limit: query.limit }),
|
h(Index, { index, page: query.page, limit: query.limit }),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "用户",
|
title: renderTableTitle(
|
||||||
|
"用户",
|
||||||
|
"streamline-emojis:smiling-face-with-sunglasses",
|
||||||
|
),
|
||||||
key: "username",
|
key: "username",
|
||||||
width: 200,
|
width: 200,
|
||||||
render: (row) =>
|
render: (row) =>
|
||||||
@@ -50,13 +54,31 @@ const columns: DataTableColumn<Rank>[] = [
|
|||||||
() => row.user.username,
|
() => row.user.username,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{ title: "个性签名", key: "mood", minWidth: 200 },
|
|
||||||
{ title: "已解决", key: "accepted_number", width: 100 },
|
|
||||||
{ title: "提交数", key: "submission_number", width: 100 },
|
|
||||||
{
|
{
|
||||||
title: "正确率",
|
title: renderTableTitle(
|
||||||
|
"个性签名",
|
||||||
|
"streamline-emojis:no-one-under-eighteen",
|
||||||
|
),
|
||||||
|
key: "mood",
|
||||||
|
minWidth: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: renderTableTitle("已解决", "streamline-emojis:raised-fist-1"),
|
||||||
|
key: "accepted_number",
|
||||||
|
width: 120,
|
||||||
|
align: "center",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: renderTableTitle("提交数", "streamline-emojis:rocket"),
|
||||||
|
key: "submission_number",
|
||||||
|
width: 120,
|
||||||
|
align: "center",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: renderTableTitle("正确率", "streamline-emojis:wrapped-gift-1"),
|
||||||
key: "rate",
|
key: "rate",
|
||||||
width: 100,
|
width: 120,
|
||||||
|
align: "center",
|
||||||
render: (row) => getACRate(row.accepted_number, row.submission_number),
|
render: (row) => getACRate(row.accepted_number, row.submission_number),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ defineEmits(["click", "search"])
|
|||||||
<n-button text type="info" @click="$emit('click')"><slot></slot></n-button>
|
<n-button text type="info" @click="$emit('click')"><slot></slot></n-button>
|
||||||
<n-button text @click="$emit('search')">
|
<n-button text @click="$emit('search')">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<Icon icon="openmoji:filter"></Icon>
|
<Icon icon="streamline-emojis:magnifying-glass-tilted-left"></Icon>
|
||||||
</template>
|
</template>
|
||||||
</n-button>
|
</n-button>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
</n-button>
|
</n-button>
|
||||||
<n-button text @click="goto">
|
<n-button text @click="goto">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<Icon icon="openmoji:backhand-index-pointing-right"></Icon>
|
<Icon icon="streamline-emojis:backhand-index-pointing-right-1"></Icon>
|
||||||
</template>
|
</template>
|
||||||
</n-button>
|
</n-button>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import ButtonWithSearch from "./components/ButtonWithSearch.vue"
|
|||||||
import StatisticsPanel from "./components/StatisticsPanel.vue"
|
import StatisticsPanel from "./components/StatisticsPanel.vue"
|
||||||
import SubmissionLink from "./components/SubmissionLink.vue"
|
import SubmissionLink from "./components/SubmissionLink.vue"
|
||||||
import SubmissionDetail from "./detail.vue"
|
import SubmissionDetail from "./detail.vue"
|
||||||
|
import { renderTableTitle } from "~/utils/renders"
|
||||||
|
|
||||||
interface Query {
|
interface Query {
|
||||||
username: string
|
username: string
|
||||||
@@ -155,7 +156,7 @@ watch(
|
|||||||
const columns = computed(() => {
|
const columns = computed(() => {
|
||||||
const res: DataTableColumn<Submission>[] = [
|
const res: DataTableColumn<Submission>[] = [
|
||||||
{
|
{
|
||||||
title: "提交时间",
|
title: renderTableTitle("提交时间", "noto:seven-oclock"),
|
||||||
key: "create_time",
|
key: "create_time",
|
||||||
width: 200,
|
width: 200,
|
||||||
render: (row) =>
|
render: (row) =>
|
||||||
@@ -165,7 +166,7 @@ const columns = computed(() => {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "提交编号",
|
title: renderTableTitle("提交编号", "fluent-emoji-flat:input-numbers"),
|
||||||
key: "id",
|
key: "id",
|
||||||
minWidth: 160,
|
minWidth: 160,
|
||||||
render: (row) =>
|
render: (row) =>
|
||||||
@@ -175,13 +176,13 @@ const columns = computed(() => {
|
|||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "状态",
|
title: renderTableTitle("状态", "streamline-emojis:panda-face"),
|
||||||
key: "status",
|
key: "status",
|
||||||
width: 160,
|
width: 160,
|
||||||
render: (row) => h(SubmissionResultTag, { result: row.result }),
|
render: (row) => h(SubmissionResultTag, { result: row.result }),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "题目",
|
title: renderTableTitle("题目", "streamline-emojis:blossom"),
|
||||||
key: "problem",
|
key: "problem",
|
||||||
width: 160,
|
width: 160,
|
||||||
render: (row) =>
|
render: (row) =>
|
||||||
@@ -195,25 +196,33 @@ const columns = computed(() => {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "执行耗时",
|
title: renderTableTitle("执行耗时", "streamline-emojis:snail"),
|
||||||
key: "time",
|
key: "time",
|
||||||
width: 120,
|
width: 120,
|
||||||
|
align: "center",
|
||||||
render: (row) => submissionTimeFormat(row.statistic_info.time_cost),
|
render: (row) => submissionTimeFormat(row.statistic_info.time_cost),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "占用内存",
|
title: renderTableTitle("占用内存", "streamline-emojis:bell"),
|
||||||
key: "memory",
|
key: "memory",
|
||||||
width: 120,
|
width: 120,
|
||||||
|
align: "center",
|
||||||
render: (row) => submissionMemoryFormat(row.statistic_info.memory_cost),
|
render: (row) => submissionMemoryFormat(row.statistic_info.memory_cost),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "语言",
|
title: renderTableTitle(
|
||||||
|
"语言",
|
||||||
|
"streamline-emojis:globe-showing-europe-africa",
|
||||||
|
),
|
||||||
key: "language",
|
key: "language",
|
||||||
width: 120,
|
width: 120,
|
||||||
render: (row) => LANGUAGE_SHOW_VALUE[row.language],
|
render: (row) => LANGUAGE_SHOW_VALUE[row.language],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "用户",
|
title: renderTableTitle(
|
||||||
|
"用户",
|
||||||
|
"streamline-emojis:smiling-face-with-sunglasses",
|
||||||
|
),
|
||||||
key: "username",
|
key: "username",
|
||||||
minWidth: 160,
|
minWidth: 160,
|
||||||
render: (row) =>
|
render: (row) =>
|
||||||
@@ -229,7 +238,7 @@ const columns = computed(() => {
|
|||||||
]
|
]
|
||||||
if (!route.params.contestID && userStore.isSuperAdmin) {
|
if (!route.params.contestID && userStore.isSuperAdmin) {
|
||||||
res.push({
|
res.push({
|
||||||
title: "选项",
|
title: renderTableTitle("选项", "streamline-emojis:wrench"),
|
||||||
key: "rejudge",
|
key: "rejudge",
|
||||||
render: (row) =>
|
render: (row) =>
|
||||||
h(
|
h(
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ defineProps<{ contest: Contest }>()
|
|||||||
<n-flex>
|
<n-flex>
|
||||||
<Icon
|
<Icon
|
||||||
v-if="contest.contest_type === ContestType.private"
|
v-if="contest.contest_type === ContestType.private"
|
||||||
:height="20"
|
:height="24"
|
||||||
:width="20"
|
:width="24"
|
||||||
icon="openmoji:locked"
|
icon="streamline-emojis:locked-with-key"
|
||||||
></Icon>
|
></Icon>
|
||||||
<span>{{ contest.title }}</span>
|
<span>{{ contest.title }}</span>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const [copied, toggle] = useToggle()
|
|||||||
const { start } = useTimeoutFn(() => toggle(false), 1000, { immediate: false })
|
const { start } = useTimeoutFn(() => toggle(false), 1000, { immediate: false })
|
||||||
|
|
||||||
const COPY = h(Icon, { icon: "emojione:clipboard" })
|
const COPY = h(Icon, { icon: "emojione:clipboard" })
|
||||||
const OK = h(Icon, { icon: "openmoji:check-mark" })
|
const OK = h(Icon, { icon: "noto-v1:check-mark" })
|
||||||
|
|
||||||
function handleClick(value: string) {
|
function handleClick(value: string) {
|
||||||
copy(value)
|
copy(value)
|
||||||
|
|||||||
@@ -33,18 +33,25 @@ function renderIcon(icon: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const avatars = [
|
const avatars = [
|
||||||
"openmoji:glowing-star",
|
"streamline-emojis:man-with-chinese-cap-1",
|
||||||
"openmoji:heart-with-ribbon",
|
"streamline-emojis:cat-face",
|
||||||
"openmoji:flag-china",
|
"streamline-emojis:china",
|
||||||
"openmoji:fish-cake-with-swirl",
|
"streamline-emojis:chicken",
|
||||||
"openmoji:astronaut",
|
"streamline-emojis:eyes",
|
||||||
"openmoji:alien-monster",
|
"streamline-emojis:elephant",
|
||||||
"openmoji:zany-face",
|
"streamline-emojis:hear-no-evil-monkey",
|
||||||
"openmoji:eyes",
|
"streamline-emojis:panda-face",
|
||||||
"openmoji:desktop-computer",
|
"streamline-emojis:penguin-1",
|
||||||
"openmoji:watermelon",
|
"streamline-emojis:rooster",
|
||||||
"openmoji:cheese-wedge",
|
"streamline-emojis:star-struck-1",
|
||||||
"openmoji:wrapped-gift",
|
"streamline-emojis:tomato",
|
||||||
|
"streamline-emojis:rocket",
|
||||||
|
"streamline-emojis:sparkles",
|
||||||
|
"streamline-emojis:money-bag",
|
||||||
|
"streamline-emojis:ghost",
|
||||||
|
"streamline-emojis:game-dice",
|
||||||
|
"streamline-emojis:ewe-1",
|
||||||
|
"streamline-emojis:artist-palette",
|
||||||
]
|
]
|
||||||
|
|
||||||
const avatar = ref(avatars[Math.floor(Math.random() * avatars.length)])
|
const avatar = ref(avatars[Math.floor(Math.random() * avatars.length)])
|
||||||
@@ -62,35 +69,35 @@ const menus = computed<MenuOption[]>(() => [
|
|||||||
{
|
{
|
||||||
label: () => h(RouterLink, { to: "/" }, { default: () => "题库" }),
|
label: () => h(RouterLink, { to: "/" }, { default: () => "题库" }),
|
||||||
key: "problem",
|
key: "problem",
|
||||||
icon: renderIcon("openmoji:jack-o-lantern"),
|
icon: renderIcon("streamline-emojis:jack-o-lantern"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: () =>
|
label: () =>
|
||||||
h(RouterLink, { to: "/submission" }, { default: () => "提交" }),
|
h(RouterLink, { to: "/submission" }, { default: () => "提交" }),
|
||||||
key: "submission",
|
key: "submission",
|
||||||
icon: renderIcon("openmoji:clown-face"),
|
icon: renderIcon("streamline-emojis:lemon"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: () => h(RouterLink, { to: "/contest" }, { default: () => "比赛" }),
|
label: () => h(RouterLink, { to: "/contest" }, { default: () => "比赛" }),
|
||||||
key: "contest",
|
key: "contest",
|
||||||
icon: renderIcon("openmoji:face-with-tears-of-joy"),
|
icon: renderIcon("streamline-emojis:direct-hit"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: () => h(RouterLink, { to: "/rank" }, { default: () => "排名" }),
|
label: () => h(RouterLink, { to: "/rank" }, { default: () => "排名" }),
|
||||||
key: "rank",
|
key: "rank",
|
||||||
icon: renderIcon("openmoji:sports-medal"),
|
icon: renderIcon("streamline-emojis:crown"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: () =>
|
label: () =>
|
||||||
h(RouterLink, { to: "/announcement" }, { default: () => "公告" }),
|
h(RouterLink, { to: "/announcement" }, { default: () => "公告" }),
|
||||||
key: "announcement",
|
key: "announcement",
|
||||||
icon: renderIcon("openmoji:hamburger"),
|
icon: renderIcon("streamline-emojis:police-car-light"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: () => h(RouterLink, { to: "/admin" }, { default: () => "后台" }),
|
label: () => h(RouterLink, { to: "/admin" }, { default: () => "后台" }),
|
||||||
show: userStore.isAdminRole,
|
show: userStore.isAdminRole,
|
||||||
key: "admin",
|
key: "admin",
|
||||||
icon: renderIcon("openmoji:hacker-cat"),
|
icon: renderIcon("streamline-emojis:unicorn-face"),
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -98,6 +105,7 @@ const options: Array<DropdownOption | DropdownDividerOption> = [
|
|||||||
{
|
{
|
||||||
label: "我的主页",
|
label: "我的主页",
|
||||||
key: "home",
|
key: "home",
|
||||||
|
icon: renderIcon("streamline-emojis:clipboard"),
|
||||||
props: {
|
props: {
|
||||||
onClick: () => router.push("/user"),
|
onClick: () => router.push("/user"),
|
||||||
},
|
},
|
||||||
@@ -105,6 +113,7 @@ const options: Array<DropdownOption | DropdownDividerOption> = [
|
|||||||
{
|
{
|
||||||
label: "我的消息",
|
label: "我的消息",
|
||||||
key: "message",
|
key: "message",
|
||||||
|
icon: renderIcon("streamline-emojis:herb"),
|
||||||
props: {
|
props: {
|
||||||
onClick: () => router.push("/message"),
|
onClick: () => router.push("/message"),
|
||||||
},
|
},
|
||||||
@@ -112,6 +121,7 @@ const options: Array<DropdownOption | DropdownDividerOption> = [
|
|||||||
{
|
{
|
||||||
label: "我的提交",
|
label: "我的提交",
|
||||||
key: "status",
|
key: "status",
|
||||||
|
icon: renderIcon("streamline-emojis:bar-chart"),
|
||||||
props: {
|
props: {
|
||||||
onClick: () => router.push("/submission?myself=1"),
|
onClick: () => router.push("/submission?myself=1"),
|
||||||
},
|
},
|
||||||
@@ -119,12 +129,18 @@ const options: Array<DropdownOption | DropdownDividerOption> = [
|
|||||||
{
|
{
|
||||||
label: "我的设置",
|
label: "我的设置",
|
||||||
key: "setting",
|
key: "setting",
|
||||||
|
icon: renderIcon("streamline-emojis:game-dice"),
|
||||||
props: {
|
props: {
|
||||||
onClick: () => router.push("/setting"),
|
onClick: () => router.push("/setting"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ type: "divider" },
|
{ type: "divider" },
|
||||||
{ label: "退出", key: "logout", props: { onClick: handleLogout } },
|
{
|
||||||
|
label: "退出",
|
||||||
|
key: "logout",
|
||||||
|
icon: renderIcon("streamline-emojis:bathtub"),
|
||||||
|
props: { onClick: handleLogout },
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
function goHome() {
|
function goHome() {
|
||||||
@@ -147,7 +163,10 @@ function goHome() {
|
|||||||
</n-space>
|
</n-space>
|
||||||
<n-space align="center">
|
<n-space align="center">
|
||||||
<n-dropdown v-if="isMobile" :options="menus">
|
<n-dropdown v-if="isMobile" :options="menus">
|
||||||
<n-button>菜单</n-button>
|
<n-button>
|
||||||
|
<Icon icon="streamline-emojis:clipboard" :height="24" :width="24"></Icon>
|
||||||
|
<span style="padding-left: 8px">菜单</span>
|
||||||
|
</n-button>
|
||||||
</n-dropdown>
|
</n-dropdown>
|
||||||
<n-button
|
<n-button
|
||||||
v-if="
|
v-if="
|
||||||
@@ -161,10 +180,8 @@ function goHome() {
|
|||||||
<div v-if="userStore.isFinished">
|
<div v-if="userStore.isFinished">
|
||||||
<n-dropdown v-if="userStore.isAuthed" :options="options">
|
<n-dropdown v-if="userStore.isAuthed" :options="options">
|
||||||
<n-button @click="getRandomAvatar">
|
<n-button @click="getRandomAvatar">
|
||||||
<template #icon>
|
<Icon :icon="avatar" :height="24" :width="24"></Icon>
|
||||||
<Icon :icon="avatar"></Icon>
|
<span style="padding-left: 8px">{{ userStore.user!.username }}</span>
|
||||||
</template>
|
|
||||||
{{ userStore.user!.username }}
|
|
||||||
</n-button>
|
</n-button>
|
||||||
</n-dropdown>
|
</n-dropdown>
|
||||||
<n-space align="center" v-else>
|
<n-space align="center" v-else>
|
||||||
|
|||||||
9
src/utils/renders.ts
Normal file
9
src/utils/renders.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { Icon } from "@iconify/vue"
|
||||||
|
import { NFlex } from "naive-ui"
|
||||||
|
|
||||||
|
export function renderTableTitle(title: string, icon: string): any {
|
||||||
|
return h(NFlex, { align: "center", size: 4 }, () => [
|
||||||
|
h(Icon, { icon: icon, width: 20, height: 20 }),
|
||||||
|
title,
|
||||||
|
])
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user