update icons

This commit is contained in:
2024-06-27 02:15:27 +00:00
parent 4637c9479b
commit 905e13b740
18 changed files with 222 additions and 92 deletions

View File

@@ -7,6 +7,7 @@ import { isDesktop } from "~/shared/composables/breakpoints"
import { NTag } from "naive-ui"
import TitleWithTag from "./components/TitleWithTag.vue"
import { Icon } from "@iconify/vue"
import { renderTableTitle } from "~/utils/renders"
const total = ref(0)
const content = ref("")
@@ -19,30 +20,30 @@ const query = reactive({
const columns: DataTableColumn<Announcement>[] = [
{
key: "title",
title: "公告标题",
title: renderTableTitle("公告标题", "streamline-emojis:fire"),
render: (row) => h(TitleWithTag, { title: row.title, top: row.top }),
minWidth: 300,
},
{
key: "tag",
title: "标签",
title: renderTableTitle("标签", "fluent-emoji-flat:keycap-hashtag"),
render: (row) => h(NTag, () => row.tag || "公告"),
},
{
key: "create_time",
title: "发布时间",
title: renderTableTitle("发布时间", "fluent-emoji-flat:eight-oclock"),
render: (row) => parseTime(row.create_time),
width: 180,
},
{
key: "last_update_time",
title: "更新时间",
title: renderTableTitle("更新时间", "fluent-emoji-flat:eleven-thirty"),
render: (row) => parseTime(row.last_update_time),
width: 180,
},
{
key: "username",
title: "发布人",
title: renderTableTitle("发布人", "streamline-emojis:ghost"),
render: (row) => row.created_by.username,
width: 120,
},

View File

@@ -16,7 +16,7 @@ const contestStore = useContestStore()
<template #trigger>
<n-button>
<template #icon>
<Icon icon="openmoji:compass"></Icon>
<Icon icon="streamline-emojis:exclamation-mark"></Icon>
</template>
比赛信息
</n-button>

View File

@@ -35,7 +35,7 @@ const passwordFormVisible = computed(
<n-space align="center">
<Icon
v-if="contestStore.isPrivate"
icon="openmoji:locked"
icon="streamline-emojis:locked-with-key"
:width="30"
:height="30"
></Icon>

View File

@@ -8,6 +8,7 @@ import ContestTitle from "~/shared/components/ContestTitle.vue"
import Pagination from "~/shared/components/Pagination.vue"
import { useUserStore } from "~/shared/store/user"
import { toggleLogin } from "~/shared/composables/modal"
import { renderTableTitle } from "~/utils/renders"
const route = useRoute()
const router = useRouter()
@@ -30,7 +31,7 @@ const options: SelectOption[] = [
const columns: DataTableColumn<Contest>[] = [
{
title: "状态",
title: renderTableTitle("状态", "streamline-emojis:collision"),
key: "status",
width: 100,
render: (row) =>
@@ -41,19 +42,19 @@ const columns: DataTableColumn<Contest>[] = [
),
},
{
title: "比赛",
title: renderTableTitle("比赛", "streamline-emojis:bouquet"),
key: "title",
minWidth: 360,
render: (row) => h(ContestTitle, { contest: row }),
},
{
title: "开始时间",
title: renderTableTitle("开始时间", "fluent-emoji-flat:eleven-thirty"),
key: "start_time",
width: 180,
render: (row) => parseTime(row.start_time),
},
{
title: "比赛时长",
title: renderTableTitle("比赛时长", "streamline-emojis:fishing-pole"),
key: "duration",
width: 180,
render: (row) => duration(row.start_time, row.end_time),

View File

@@ -2,6 +2,7 @@
import { ProblemFiltered } from "utils/types"
import ProblemStatus from "~/oj/problem/components/ProblemStatus.vue"
import { useContestStore } from "~/oj/store/contest"
import { renderTableTitle } from "~/utils/renders"
const props = defineProps<{ contestID: string }>()
@@ -9,15 +10,33 @@ const router = useRouter()
const contestStore = useContestStore()
const problemsColumns: DataTableColumn<ProblemFiltered>[] = [
{
title: "状态",
title: renderTableTitle("状态", "streamline-emojis:musical-note"),
key: "status",
width: 60,
width: 100,
render: (row) => h(ProblemStatus, { status: row.status }),
},
{ title: "编号", key: "_id", width: 60 },
{ title: "题目", key: "title", minWidth: 200 },
{ title: "总提交数", key: "submission", width: 100 },
{ title: "通过率", key: "rate", width: 100 },
{
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: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) {

View File

@@ -8,6 +8,7 @@ import { secondsToDuration } from "utils/functions"
import { ContestStatus } from "~/utils/constants"
import { useContestStore } from "~/oj/store/contest"
import { Icon } from "@iconify/vue"
import { renderTableTitle } from "~/utils/renders"
interface Props {
contestID: string
@@ -44,15 +45,18 @@ const query = reactive({
const columns = ref<DataTableColumn<ContestRank>[]>([
{
title: "排名",
title: renderTableTitle("编号", "fluent-emoji-flat:input-numbers"),
key: "id",
width: 60,
width: 80,
fixed: "left",
align: "center",
render: (_, index) => index + (query.page - 1) * query.limit + 1,
},
{
title: "用户",
title: renderTableTitle(
"用户",
"streamline-emojis:smiling-face-with-sunglasses",
),
key: "username",
width: 120,
fixed: "left",
@@ -69,9 +73,12 @@ const columns = ref<DataTableColumn<ContestRank>[]>([
),
},
{
title: "正确数/总提交",
title: renderTableTitle(
"正确数/总提交",
"streamline-emojis:artist-palette",
),
key: "submission",
width: 120,
width: 140,
align: "center",
render: (row) => h(AcAndSubmission, { rank: row }),
},
@@ -133,9 +140,9 @@ async function addColumns() {
if (status.is_first_ac) {
acTime = [
h(Icon, {
icon: "openmoji:1st-place-medal",
height: 24,
width: 24,
icon: "fluent-emoji:1st-place-medal",
height: 20,
width: 20,
}),
h("span", secondsToDuration(status.ac_time)),
]

View File

@@ -5,6 +5,7 @@ import { problem } from "oj/composables/problem"
import { Problem, ProblemStatus } from "utils/types"
import { createTestSubmission } from "utils/judge"
import { useThemeVars } from "naive-ui"
import { Icon } from "@iconify/vue"
type Sample = Problem["samples"][number] & {
id: number
@@ -99,17 +100,37 @@ function type(status: ProblemStatus) {
<n-tag>{{ problem._id }}</n-tag>
<h2 class="problemTitle">{{ problem.title }}</h2>
</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>
<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>
<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 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>

View File

@@ -8,6 +8,7 @@ import { isDesktop } from "~/shared/composables/breakpoints"
import SubmissionResultTag from "~/shared/components/SubmissionResultTag.vue"
import Pagination from "~/shared/components/Pagination.vue"
import { NButton } from "naive-ui"
import { renderTableTitle } from "~/utils/renders"
const userStore = useUserStore()
const route = useRoute()
@@ -15,7 +16,7 @@ const router = useRouter()
const columns: DataTableColumn<Submission>[] = [
{
title: "提交时间",
title: renderTableTitle("提交时间", "noto:seven-oclock"),
key: "create_time",
width: 200,
render: (row) =>
@@ -25,7 +26,7 @@ const columns: DataTableColumn<Submission>[] = [
),
},
{
title: "编号",
title: renderTableTitle("编号", "fluent-emoji-flat:input-numbers"),
key: "id",
minWidth: 160,
render: (row) => {
@@ -48,13 +49,16 @@ const columns: DataTableColumn<Submission>[] = [
},
},
{
title: "状态",
title: renderTableTitle("状态", "streamline-emojis:panda-face"),
key: "status",
width: 140,
render: (row) => h(SubmissionResultTag, { result: row.result }),
},
{
title: "语言",
title: renderTableTitle(
"语言",
"streamline-emojis:globe-showing-europe-africa",
),
key: "language",
width: 100,
render: (row) => LANGUAGE_SHOW_VALUE[row.language],

View File

@@ -9,6 +9,7 @@ import { getProblemTagList } from "~/shared/api"
import Pagination from "~/shared/components/Pagination.vue"
import { isDesktop } from "~/shared/composables/breakpoints"
import { Icon } from "@iconify/vue"
import { renderTableTitle } from "~/utils/renders"
interface Tag {
id: number
@@ -150,29 +151,48 @@ onMounted(() => {
const baseColumns: DataTableColumn<ProblemFiltered>[] = [
{
title: "状态",
title: renderTableTitle("状态", "streamline-emojis:musical-note"),
key: "status",
width: 60,
width: 80,
align: "center",
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",
width: 100,
render: (row) =>
h(NTag, { type: getTagColor(row.difficulty) }, () => row.difficulty),
},
{
title: "标签",
title: renderTableTitle("标签", "fluent-emoji-flat:keycap-hashtag"),
key: "tags",
width: 260,
render: (row) =>
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(() =>

View File

@@ -20,10 +20,10 @@ const tooltip = computed(() => {
<span v-if="index > 3">{{ index }}</span>
<n-tooltip v-else>
<template #trigger>
<n-icon :size="20">
<Icon v-if="index === 1" icon="openmoji:1st-place-medal"></Icon>
<Icon v-if="index === 2" icon="openmoji:2nd-place-medal"></Icon>
<Icon v-if="index === 3" icon="openmoji:3rd-place-medal"></Icon>
<n-icon :size="24">
<Icon v-if="index === 1" icon="fluent-emoji:1st-place-medal"></Icon>
<Icon v-if="index === 2" icon="fluent-emoji:2nd-place-medal"></Icon>
<Icon v-if="index === 3" icon="fluent-emoji:3rd-place-medal"></Icon>
</n-icon>
</template>
{{ tooltip }}

View File

@@ -6,6 +6,7 @@ import { Rank } from "utils/types"
import { getRank } from "oj/api"
import { getACRate } from "utils/functions"
import Index from "./components/Index.vue"
import { renderTableTitle } from "~/utils/renders"
const router = useRouter()
const data = ref<Rank[]>([])
@@ -28,15 +29,18 @@ async function listRanks() {
const columns: DataTableColumn<Rank>[] = [
{
title: "排名",
title: renderTableTitle("排名", "streamline-emojis:flexed-biceps-1"),
key: "index",
width: 80,
width: 100,
align: "center",
render: (_, index) =>
h(Index, { index, page: query.page, limit: query.limit }),
},
{
title: "用户",
title: renderTableTitle(
"用户",
"streamline-emojis:smiling-face-with-sunglasses",
),
key: "username",
width: 200,
render: (row) =>
@@ -50,13 +54,31 @@ const columns: DataTableColumn<Rank>[] = [
() => 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",
width: 100,
width: 120,
align: "center",
render: (row) => getACRate(row.accepted_number, row.submission_number),
},
]

View File

@@ -8,7 +8,7 @@ defineEmits(["click", "search"])
<n-button text type="info" @click="$emit('click')"><slot></slot></n-button>
<n-button text @click="$emit('search')">
<template #icon>
<Icon icon="openmoji:filter"></Icon>
<Icon icon="streamline-emojis:magnifying-glass-tilted-left"></Icon>
</template>
</n-button>
</n-flex>

View File

@@ -5,7 +5,7 @@
</n-button>
<n-button text @click="goto">
<template #icon>
<Icon icon="openmoji:backhand-index-pointing-right"></Icon>
<Icon icon="streamline-emojis:backhand-index-pointing-right-1"></Icon>
</template>
</n-button>
</n-flex>

View File

@@ -17,6 +17,7 @@ import ButtonWithSearch from "./components/ButtonWithSearch.vue"
import StatisticsPanel from "./components/StatisticsPanel.vue"
import SubmissionLink from "./components/SubmissionLink.vue"
import SubmissionDetail from "./detail.vue"
import { renderTableTitle } from "~/utils/renders"
interface Query {
username: string
@@ -155,7 +156,7 @@ watch(
const columns = computed(() => {
const res: DataTableColumn<Submission>[] = [
{
title: "提交时间",
title: renderTableTitle("提交时间", "noto:seven-oclock"),
key: "create_time",
width: 200,
render: (row) =>
@@ -165,7 +166,7 @@ const columns = computed(() => {
),
},
{
title: "提交编号",
title: renderTableTitle("提交编号", "fluent-emoji-flat:input-numbers"),
key: "id",
minWidth: 160,
render: (row) =>
@@ -175,13 +176,13 @@ const columns = computed(() => {
}),
},
{
title: "状态",
title: renderTableTitle("状态", "streamline-emojis:panda-face"),
key: "status",
width: 160,
render: (row) => h(SubmissionResultTag, { result: row.result }),
},
{
title: "题目",
title: renderTableTitle("题目", "streamline-emojis:blossom"),
key: "problem",
width: 160,
render: (row) =>
@@ -195,25 +196,33 @@ const columns = computed(() => {
),
},
{
title: "执行耗时",
title: renderTableTitle("执行耗时", "streamline-emojis:snail"),
key: "time",
width: 120,
align: "center",
render: (row) => submissionTimeFormat(row.statistic_info.time_cost),
},
{
title: "占用内存",
title: renderTableTitle("占用内存", "streamline-emojis:bell"),
key: "memory",
width: 120,
align: "center",
render: (row) => submissionMemoryFormat(row.statistic_info.memory_cost),
},
{
title: "语言",
title: renderTableTitle(
"语言",
"streamline-emojis:globe-showing-europe-africa",
),
key: "language",
width: 120,
render: (row) => LANGUAGE_SHOW_VALUE[row.language],
},
{
title: "用户",
title: renderTableTitle(
"用户",
"streamline-emojis:smiling-face-with-sunglasses",
),
key: "username",
minWidth: 160,
render: (row) =>
@@ -229,7 +238,7 @@ const columns = computed(() => {
]
if (!route.params.contestID && userStore.isSuperAdmin) {
res.push({
title: "选项",
title: renderTableTitle("选项", "streamline-emojis:wrench"),
key: "rejudge",
render: (row) =>
h(

View File

@@ -9,9 +9,9 @@ defineProps<{ contest: Contest }>()
<n-flex>
<Icon
v-if="contest.contest_type === ContestType.private"
:height="20"
:width="20"
icon="openmoji:locked"
:height="24"
:width="24"
icon="streamline-emojis:locked-with-key"
></Icon>
<span>{{ contest.title }}</span>
</n-flex>

View File

@@ -7,7 +7,7 @@ const [copied, toggle] = useToggle()
const { start } = useTimeoutFn(() => toggle(false), 1000, { immediate: false })
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) {
copy(value)

View File

@@ -33,18 +33,25 @@ function renderIcon(icon: string) {
}
const avatars = [
"openmoji:glowing-star",
"openmoji:heart-with-ribbon",
"openmoji:flag-china",
"openmoji:fish-cake-with-swirl",
"openmoji:astronaut",
"openmoji:alien-monster",
"openmoji:zany-face",
"openmoji:eyes",
"openmoji:desktop-computer",
"openmoji:watermelon",
"openmoji:cheese-wedge",
"openmoji:wrapped-gift",
"streamline-emojis:man-with-chinese-cap-1",
"streamline-emojis:cat-face",
"streamline-emojis:china",
"streamline-emojis:chicken",
"streamline-emojis:eyes",
"streamline-emojis:elephant",
"streamline-emojis:hear-no-evil-monkey",
"streamline-emojis:panda-face",
"streamline-emojis:penguin-1",
"streamline-emojis:rooster",
"streamline-emojis:star-struck-1",
"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)])
@@ -62,35 +69,35 @@ const menus = computed<MenuOption[]>(() => [
{
label: () => h(RouterLink, { to: "/" }, { default: () => "题库" }),
key: "problem",
icon: renderIcon("openmoji:jack-o-lantern"),
icon: renderIcon("streamline-emojis:jack-o-lantern"),
},
{
label: () =>
h(RouterLink, { to: "/submission" }, { default: () => "提交" }),
key: "submission",
icon: renderIcon("openmoji:clown-face"),
icon: renderIcon("streamline-emojis:lemon"),
},
{
label: () => h(RouterLink, { to: "/contest" }, { default: () => "比赛" }),
key: "contest",
icon: renderIcon("openmoji:face-with-tears-of-joy"),
icon: renderIcon("streamline-emojis:direct-hit"),
},
{
label: () => h(RouterLink, { to: "/rank" }, { default: () => "排名" }),
key: "rank",
icon: renderIcon("openmoji:sports-medal"),
icon: renderIcon("streamline-emojis:crown"),
},
{
label: () =>
h(RouterLink, { to: "/announcement" }, { default: () => "公告" }),
key: "announcement",
icon: renderIcon("openmoji:hamburger"),
icon: renderIcon("streamline-emojis:police-car-light"),
},
{
label: () => h(RouterLink, { to: "/admin" }, { default: () => "后台" }),
show: userStore.isAdminRole,
key: "admin",
icon: renderIcon("openmoji:hacker-cat"),
icon: renderIcon("streamline-emojis:unicorn-face"),
},
])
@@ -98,6 +105,7 @@ const options: Array<DropdownOption | DropdownDividerOption> = [
{
label: "我的主页",
key: "home",
icon: renderIcon("streamline-emojis:clipboard"),
props: {
onClick: () => router.push("/user"),
},
@@ -105,6 +113,7 @@ const options: Array<DropdownOption | DropdownDividerOption> = [
{
label: "我的消息",
key: "message",
icon: renderIcon("streamline-emojis:herb"),
props: {
onClick: () => router.push("/message"),
},
@@ -112,6 +121,7 @@ const options: Array<DropdownOption | DropdownDividerOption> = [
{
label: "我的提交",
key: "status",
icon: renderIcon("streamline-emojis:bar-chart"),
props: {
onClick: () => router.push("/submission?myself=1"),
},
@@ -119,12 +129,18 @@ const options: Array<DropdownOption | DropdownDividerOption> = [
{
label: "我的设置",
key: "setting",
icon: renderIcon("streamline-emojis:game-dice"),
props: {
onClick: () => router.push("/setting"),
},
},
{ type: "divider" },
{ label: "退出", key: "logout", props: { onClick: handleLogout } },
{
label: "退出",
key: "logout",
icon: renderIcon("streamline-emojis:bathtub"),
props: { onClick: handleLogout },
},
]
function goHome() {
@@ -147,7 +163,10 @@ function goHome() {
</n-space>
<n-space align="center">
<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-button
v-if="
@@ -161,10 +180,8 @@ function goHome() {
<div v-if="userStore.isFinished">
<n-dropdown v-if="userStore.isAuthed" :options="options">
<n-button @click="getRandomAvatar">
<template #icon>
<Icon :icon="avatar"></Icon>
</template>
{{ userStore.user!.username }}
<Icon :icon="avatar" :height="24" :width="24"></Icon>
<span style="padding-left: 8px">{{ userStore.user!.username }}</span>
</n-button>
</n-dropdown>
<n-space align="center" v-else>

9
src/utils/renders.ts Normal file
View 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,
])
}