2026-01-19 18:03:45 +08:00
|
|
|
|
<script setup lang="ts">
|
2026-01-23 18:16:03 +08:00
|
|
|
|
import { NButton, NForm, NFormItem, NInput, NInputNumber, NModal, NSelect, type SelectOption } from 'naive-ui'
|
2026-01-21 16:29:38 +08:00
|
|
|
|
import { ref, watch } from 'vue'
|
2026-01-23 18:16:03 +08:00
|
|
|
|
import { VueDraggable } from 'vue-draggable-plus'
|
2026-01-27 09:48:42 +08:00
|
|
|
|
import { roundTypeOptions, scoreTypeOptions, timeOptions, uiTypeOptions } from '@/constants/business'
|
2026-01-21 16:29:38 +08:00
|
|
|
|
import { useQuestionConfig } from './useQuestionConfig'
|
2026-01-21 08:41:36 +08:00
|
|
|
|
|
|
|
|
|
|
const props = defineProps<{
|
|
|
|
|
|
modelValue: {
|
2026-01-21 16:29:38 +08:00
|
|
|
|
rounds: Array<{
|
|
|
|
|
|
id: string
|
|
|
|
|
|
name: string
|
2026-01-23 18:16:03 +08:00
|
|
|
|
roundType: string
|
2026-01-27 09:48:42 +08:00
|
|
|
|
questions: Array<{
|
|
|
|
|
|
id: string
|
|
|
|
|
|
value: string | null
|
|
|
|
|
|
time: number
|
|
|
|
|
|
title: string
|
|
|
|
|
|
scoreType: Api.Competition.QuestionScoreType
|
2026-01-28 08:33:36 +08:00
|
|
|
|
score: number
|
2026-01-27 09:48:42 +08:00
|
|
|
|
uiType?: string
|
|
|
|
|
|
templateId?: string
|
|
|
|
|
|
}>
|
2026-01-21 16:29:38 +08:00
|
|
|
|
}>
|
2026-01-21 08:41:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
}>()
|
2026-01-21 16:29:38 +08:00
|
|
|
|
const {
|
2026-01-23 18:16:03 +08:00
|
|
|
|
// getRoundScore,
|
2026-01-21 16:29:38 +08:00
|
|
|
|
getRoundTime,
|
|
|
|
|
|
totalStats,
|
|
|
|
|
|
questionOptions,
|
|
|
|
|
|
addRound,
|
|
|
|
|
|
removeRound,
|
|
|
|
|
|
addQuestion,
|
|
|
|
|
|
removeQuestion,
|
|
|
|
|
|
validate,
|
|
|
|
|
|
reset,
|
|
|
|
|
|
} = useQuestionConfig(props)
|
|
|
|
|
|
|
2026-01-27 09:48:42 +08:00
|
|
|
|
const templateIdOptions: SelectOption[] = [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: '模板1',
|
|
|
|
|
|
value: 't1',
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: '模版2',
|
|
|
|
|
|
value: 't2',
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: '模版3',
|
|
|
|
|
|
value: 't3',
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: '模版4',
|
|
|
|
|
|
value: 't4',
|
|
|
|
|
|
},
|
|
|
|
|
|
]
|
|
|
|
|
|
|
2026-01-21 16:29:38 +08:00
|
|
|
|
// 模态框控制
|
|
|
|
|
|
const showAddModal = ref(false)
|
|
|
|
|
|
const newRoundForm = ref({
|
|
|
|
|
|
name: '',
|
|
|
|
|
|
count: 10,
|
2026-01-23 18:16:03 +08:00
|
|
|
|
roundType: roundTypeOptions[0].value,
|
2026-01-21 08:41:36 +08:00
|
|
|
|
})
|
|
|
|
|
|
|
2026-01-21 16:29:38 +08:00
|
|
|
|
function handleOpenAddModal() {
|
|
|
|
|
|
newRoundForm.value = {
|
2026-01-27 09:48:42 +08:00
|
|
|
|
name: `第${(props.modelValue?.rounds?.length || 0) + 1}轮 星·诗词大会`,
|
2026-01-21 16:29:38 +08:00
|
|
|
|
count: 10,
|
2026-01-23 18:16:03 +08:00
|
|
|
|
roundType: roundTypeOptions[0].value,
|
2026-01-21 08:41:36 +08:00
|
|
|
|
}
|
2026-01-21 16:29:38 +08:00
|
|
|
|
showAddModal.value = true
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function handleConfirmAdd() {
|
|
|
|
|
|
if (!newRoundForm.value.name) {
|
|
|
|
|
|
window.$message?.warning('请输入环节名称')
|
|
|
|
|
|
return
|
2026-01-21 08:41:36 +08:00
|
|
|
|
}
|
2026-01-27 09:48:42 +08:00
|
|
|
|
addRound(newRoundForm.value.name, newRoundForm.value.count, newRoundForm.value.roundType as Api.Competition.CompetitionRoundType)
|
2026-01-21 16:29:38 +08:00
|
|
|
|
showAddModal.value = false
|
2026-01-21 08:41:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-21 16:29:38 +08:00
|
|
|
|
// 初始化默认数据
|
2026-01-23 18:16:03 +08:00
|
|
|
|
watch(() => props.modelValue, (val) => {
|
|
|
|
|
|
// 确保所有题目都有ID,用于拖拽排序
|
|
|
|
|
|
if (val?.rounds) {
|
|
|
|
|
|
val.rounds.forEach((round) => {
|
|
|
|
|
|
if (!round.questions) {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
round.questions.forEach((q: any) => {
|
|
|
|
|
|
if (!q.id) {
|
|
|
|
|
|
q.id = `q_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
// eslint-disable-next-line no-console
|
|
|
|
|
|
console.log(val, '拖动后的重新顺序')
|
|
|
|
|
|
}, { immediate: true, deep: true })
|
2026-01-21 16:29:38 +08:00
|
|
|
|
|
|
|
|
|
|
defineExpose({ validate, reset })
|
2026-01-19 18:03:45 +08:00
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<template>
|
2026-01-21 16:29:38 +08:00
|
|
|
|
<div class="h-full flex flex-col">
|
|
|
|
|
|
<!-- 顶部标题栏 -->
|
|
|
|
|
|
<div class="mb-8 flex items-center justify-between">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<div class="text-2xl text-gray-800 font-bold tracking-tight">
|
|
|
|
|
|
赛程题包配置
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="mt-2 flex items-center gap-4 text-sm text-gray-500">
|
|
|
|
|
|
<span>您可以为比赛添加多个阶段的题包,并自定义题目、分值与限时。</span>
|
2026-01-23 18:16:03 +08:00
|
|
|
|
<div
|
|
|
|
|
|
v-if="totalStats.count > 0"
|
|
|
|
|
|
class="flex items-center gap-3 border border-gray-100 rounded-lg bg-gray-50 px-3 py-1 text-xs font-bold"
|
|
|
|
|
|
>
|
2026-01-21 16:29:38 +08:00
|
|
|
|
<div class="flex items-center gap-1">
|
|
|
|
|
|
<span class="text-gray-400">总题数</span>
|
|
|
|
|
|
<span class="text-sm text-gray-700">{{ totalStats.count }}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="h-3 w-[1px] bg-gray-200" />
|
|
|
|
|
|
<div class="h-3 w-[1px] bg-gray-200" />
|
|
|
|
|
|
<div class="flex items-center gap-1">
|
|
|
|
|
|
<span class="text-gray-400">总时长</span>
|
|
|
|
|
|
<span class="text-sm text-blue-500">{{ totalStats.time }}s</span>
|
2026-01-20 10:58:42 +08:00
|
|
|
|
</div>
|
2026-01-19 18:03:45 +08:00
|
|
|
|
</div>
|
2026-01-21 16:29:38 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-01-23 18:16:03 +08:00
|
|
|
|
<NButton
|
|
|
|
|
|
type="primary" class="shadow-blue-500/20 shadow-lg !h-10 !rounded-lg !px-6 !font-bold"
|
|
|
|
|
|
@click="handleOpenAddModal"
|
|
|
|
|
|
>
|
2026-01-21 16:29:38 +08:00
|
|
|
|
<template #icon>
|
|
|
|
|
|
<icon-ic-round-plus />
|
|
|
|
|
|
</template>
|
|
|
|
|
|
新增赛程题包
|
|
|
|
|
|
</NButton>
|
|
|
|
|
|
</div>
|
2026-01-19 18:03:45 +08:00
|
|
|
|
|
2026-01-21 16:29:38 +08:00
|
|
|
|
<!-- 空状态 -->
|
2026-01-23 18:16:03 +08:00
|
|
|
|
<div
|
|
|
|
|
|
v-if="!props.modelValue?.rounds?.length"
|
|
|
|
|
|
class="flex flex-col flex-1 items-center justify-center border-2 border-gray-100 rounded-2xl border-dashed bg-gray-50/30"
|
|
|
|
|
|
>
|
2026-01-21 16:29:38 +08:00
|
|
|
|
<div class="h-34 w-34 flex items-center justify-center rounded-3xl bg-gray-100 text-gray-300">
|
|
|
|
|
|
<icon-ic-outline-folder-off class="text-5xl" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="mt-6 text-lg text-gray-400 font-bold">
|
|
|
|
|
|
暂无配置题包
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="mt-2 text-sm text-gray-500">
|
|
|
|
|
|
请点击右上角按钮开始添加比赛环节
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 列表内容 -->
|
|
|
|
|
|
<div v-else class="flex flex-col gap-6 pb-10">
|
2026-01-23 18:16:03 +08:00
|
|
|
|
<div
|
|
|
|
|
|
v-for="(round, roundIndex) in props.modelValue?.rounds" :key="round.id"
|
|
|
|
|
|
class="group relative overflow-hidden border border-gray-100 rounded-2xl bg-white p-1 shadow-sm transition-all hover:shadow-md"
|
|
|
|
|
|
>
|
2026-01-21 16:29:38 +08:00
|
|
|
|
<!-- 侧边装饰条 -->
|
|
|
|
|
|
<div class="absolute bottom-0 left-0 top-0 w-1.5 bg-blue-500" />
|
|
|
|
|
|
|
|
|
|
|
|
<div class="p-6 pl-8">
|
|
|
|
|
|
<!-- 头部信息 -->
|
|
|
|
|
|
<div class="mb-4 flex items-center justify-between">
|
|
|
|
|
|
<div class="flex items-center gap-4">
|
|
|
|
|
|
<div class="h-8 w-1.5 rounded-full bg-blue-500" />
|
2026-01-27 09:48:42 +08:00
|
|
|
|
<NTag type="primary" class="!text-blue-500">
|
2026-01-23 18:16:03 +08:00
|
|
|
|
{{ roundTypeOptions.find((item) => item.value === round.roundType)?.label || '未知类型' }}
|
|
|
|
|
|
</NTag>
|
2026-01-21 16:29:38 +08:00
|
|
|
|
<div class="flex items-center gap-3">
|
|
|
|
|
|
<NInput
|
2026-01-23 18:16:03 +08:00
|
|
|
|
v-model:value="round.name" placeholder="请输入环节名称" :bordered="false"
|
2026-01-21 16:29:38 +08:00
|
|
|
|
class="border transition-all !w-80 !border-transparent !rounded-lg !bg-transparent !text-xl !font-bold focus-within:shadow-sm focus-within:!border-blue-500 hover:!border-gray-200 focus-within:!bg-white"
|
2026-01-20 10:58:42 +08:00
|
|
|
|
/>
|
2026-01-21 16:29:38 +08:00
|
|
|
|
<div class="flex items-center gap-2">
|
2026-01-23 18:16:03 +08:00
|
|
|
|
<div
|
|
|
|
|
|
class="flex items-center gap-1 rounded-full bg-gray-100 px-3 py-1 text-xs text-gray-500 font-bold"
|
|
|
|
|
|
>
|
2026-01-21 16:29:38 +08:00
|
|
|
|
<icon-ic-outline-format-list-numbered class="text-sm" />
|
|
|
|
|
|
{{ round.questions.length }} 题
|
|
|
|
|
|
</div>
|
2026-01-23 18:16:03 +08:00
|
|
|
|
<!-- <div class="flex items-center gap-1 border border-orange-100 rounded-full bg-orange-50 px-3 py-1 text-xs text-orange-500 font-bold">
|
2026-01-21 16:29:38 +08:00
|
|
|
|
<icon-ic-round-star-border class="text-sm" />
|
|
|
|
|
|
{{ getRoundScore(roundIndex) }} 分
|
2026-01-23 18:16:03 +08:00
|
|
|
|
</div> -->
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="flex items-center gap-1 border border-blue-100 rounded-full bg-blue-50 px-3 py-1 text-xs text-blue-500 font-bold"
|
|
|
|
|
|
>
|
2026-01-21 16:29:38 +08:00
|
|
|
|
<icon-ic-outline-access-time class="text-sm" />
|
|
|
|
|
|
{{ getRoundTime(roundIndex) }} 秒
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-01-20 10:58:42 +08:00
|
|
|
|
</div>
|
2026-01-19 18:03:45 +08:00
|
|
|
|
</div>
|
2026-01-21 16:29:38 +08:00
|
|
|
|
|
|
|
|
|
|
<div class="flex items-center gap-3">
|
2026-01-23 18:16:03 +08:00
|
|
|
|
<NButton
|
|
|
|
|
|
secondary circle class="!text-gray-400 hover:!bg-blue-50 hover:!text-blue-500"
|
|
|
|
|
|
@click="addQuestion(roundIndex)"
|
|
|
|
|
|
>
|
2026-01-21 16:29:38 +08:00
|
|
|
|
<template #icon>
|
|
|
|
|
|
<icon-ic-round-plus class="!text-xl" />
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</NButton>
|
2026-01-23 18:16:03 +08:00
|
|
|
|
<NButton
|
|
|
|
|
|
secondary circle class="!text-gray-400 hover:!bg-red-50 hover:!text-red-500"
|
|
|
|
|
|
@click="removeRound(roundIndex)"
|
|
|
|
|
|
>
|
2026-01-21 16:29:38 +08:00
|
|
|
|
<template #icon>
|
|
|
|
|
|
<icon-ic-outline-delete class="!text-xl" />
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</NButton>
|
2026-01-20 10:58:42 +08:00
|
|
|
|
</div>
|
2026-01-19 18:03:45 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-01-21 16:29:38 +08:00
|
|
|
|
<!-- 题目列表 -->
|
2026-01-23 18:16:03 +08:00
|
|
|
|
<VueDraggable
|
2026-01-27 09:48:42 +08:00
|
|
|
|
v-model="round.questions" :animation="300" handle=".drag-handle" class="flex flex-col gap-3"
|
2026-01-23 18:16:03 +08:00
|
|
|
|
ghost-class="ghost"
|
|
|
|
|
|
>
|
2026-01-19 18:03:45 +08:00
|
|
|
|
<div
|
2026-01-23 18:16:03 +08:00
|
|
|
|
v-for="(item, qIdx) in round.questions" :key="item.id"
|
2026-01-27 09:48:42 +08:00
|
|
|
|
class="group/item flex flex-col gap-3 border border-gray-100 rounded-xl bg-white p-3 transition-all hover:border-blue-200 hover:shadow-sm"
|
2026-01-19 18:03:45 +08:00
|
|
|
|
>
|
2026-01-27 09:48:42 +08:00
|
|
|
|
<!-- 第一行:序号、标题、删除按钮 -->
|
|
|
|
|
|
<div class="flex items-center justify-between gap-3">
|
|
|
|
|
|
<div class="flex flex-1 items-center gap-3">
|
|
|
|
|
|
<div class="flex items-center gap-2">
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="drag-handle flex cursor-grab items-center justify-center rounded p-1 text-gray-400 transition-colors active:cursor-grabbing hover:bg-gray-100 hover:text-blue-500"
|
|
|
|
|
|
>
|
|
|
|
|
|
<icon-mdi-drag class="text-xl" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span
|
|
|
|
|
|
class="w-6 flex-shrink-0 text-center text-sm text-gray-300 font-bold transition-colors group-hover/item:text-blue-500"
|
|
|
|
|
|
>
|
|
|
|
|
|
{{ String(qIdx + 1).padStart(2, '0') }}
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 标题 -->
|
|
|
|
|
|
<div class="flex flex-1 items-center gap-2 rounded-lg bg-gray-50 px-3 py-1.5">
|
|
|
|
|
|
<icon-ic-outline-title class="text-gray-400" />
|
|
|
|
|
|
<span class="whitespace-nowrap text-sm text-gray-400 font-bold">标题:</span>
|
|
|
|
|
|
<NInput
|
|
|
|
|
|
v-model:value="item.title" class="flex-1 !bg-transparent" size="small" :bordered="false"
|
|
|
|
|
|
placeholder="请输入题目标题"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
2026-01-23 18:16:03 +08:00
|
|
|
|
</div>
|
2026-01-21 16:29:38 +08:00
|
|
|
|
|
2026-01-27 09:48:42 +08:00
|
|
|
|
<!-- 删除按钮 -->
|
|
|
|
|
|
<NButton
|
|
|
|
|
|
text class="transition-opacity !text-gray-300 hover:!text-red-500"
|
|
|
|
|
|
@click="removeQuestion(roundIndex, qIdx)"
|
|
|
|
|
|
>
|
|
|
|
|
|
<icon-ic-outline-delete class="!text-xl" />
|
|
|
|
|
|
</NButton>
|
2026-01-21 16:29:38 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-01-27 09:48:42 +08:00
|
|
|
|
<!-- 第二行:配置项 -->
|
|
|
|
|
|
<div class="grid grid-cols-12 gap-3">
|
|
|
|
|
|
<!-- 题型 -->
|
|
|
|
|
|
<div class="col-span-4">
|
|
|
|
|
|
<NSelect
|
|
|
|
|
|
v-model:value="item.value" :options="questionOptions" placeholder="请选择题目类型" size="small"
|
|
|
|
|
|
class="font-medium"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
2026-01-21 16:29:38 +08:00
|
|
|
|
|
2026-01-27 09:48:42 +08:00
|
|
|
|
<!-- UItype -->
|
|
|
|
|
|
<div class="col-span-4">
|
|
|
|
|
|
<NSelect
|
|
|
|
|
|
v-model:value="item.uiType" :options="uiTypeOptions" placeholder="请选择UI类型"
|
|
|
|
|
|
size="small" class="font-medium"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
2026-01-21 16:29:38 +08:00
|
|
|
|
|
2026-01-27 09:48:42 +08:00
|
|
|
|
<!-- templateId -->
|
|
|
|
|
|
<div class="col-span-4">
|
|
|
|
|
|
<NSelect
|
|
|
|
|
|
v-model:value="item.templateId" :options="templateIdOptions" placeholder="请选择模板"
|
|
|
|
|
|
size="small" class="font-medium"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
2026-01-23 18:16:03 +08:00
|
|
|
|
|
2026-01-27 09:48:42 +08:00
|
|
|
|
<!-- 时间 -->
|
2026-01-28 08:33:36 +08:00
|
|
|
|
<div class="col-span-4 flex items-center gap-2 rounded-lg bg-gray-50 px-3 py-1.5">
|
2026-01-27 09:48:42 +08:00
|
|
|
|
<icon-ic-outline-timer class="text-gray-400" />
|
|
|
|
|
|
<span class="whitespace-nowrap text-sm text-gray-400 font-bold">答题时间:</span>
|
|
|
|
|
|
<NSelect
|
|
|
|
|
|
v-model:value="item.time" :options="timeOptions" class="flex-1 !bg-transparent" size="small"
|
|
|
|
|
|
:bordered="false"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<span class="text-xs text-gray-400 font-bold">S</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 分数规则 -->
|
2026-01-28 08:33:36 +08:00
|
|
|
|
<div class="col-span-4 flex items-center gap-2 rounded-lg bg-gray-50 px-3 py-1.5">
|
2026-01-27 09:48:42 +08:00
|
|
|
|
<icon-streamline-sharp:type-area-remix class="text-gray-400" />
|
|
|
|
|
|
<span class="whitespace-nowrap text-sm text-gray-400 font-bold">分数规则:</span>
|
|
|
|
|
|
<NSelect
|
|
|
|
|
|
v-model:value="item.scoreType" :options="scoreTypeOptions as unknown as SelectOption[]"
|
|
|
|
|
|
class="flex-1 !bg-transparent" size="small" :bordered="false"
|
|
|
|
|
|
/>
|
2026-01-28 08:33:36 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 分数 -->
|
|
|
|
|
|
<div class="col-span-4 flex items-center gap-2 rounded-lg bg-gray-50 px-3 py-1.5">
|
|
|
|
|
|
<icon-ic-round-star-border class="text-gray-400" />
|
|
|
|
|
|
<span class="whitespace-nowrap text-sm text-gray-400 font-bold">分数:</span>
|
|
|
|
|
|
<NInputNumber
|
|
|
|
|
|
v-model:value="item.score" :min="0" :show-button="false" class="flex-1 !bg-transparent"
|
|
|
|
|
|
size="small" :bordered="false" placeholder="0"
|
|
|
|
|
|
/>
|
2026-01-27 09:48:42 +08:00
|
|
|
|
<span class="text-xs text-gray-400 font-bold">分</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-01-19 18:03:45 +08:00
|
|
|
|
</div>
|
2026-01-23 18:16:03 +08:00
|
|
|
|
</VueDraggable>
|
2026-01-19 18:03:45 +08:00
|
|
|
|
</div>
|
2026-01-21 16:29:38 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 新增题包弹窗 -->
|
|
|
|
|
|
<NModal v-model:show="showAddModal" transform-origin="center">
|
|
|
|
|
|
<div class="w-[480px] rounded-2xl bg-white p-8 shadow-2xl">
|
|
|
|
|
|
<div class="mb-8 flex flex-col items-center gap-4 text-center">
|
|
|
|
|
|
<div class="h-14 w-14 flex items-center justify-center rounded-2xl bg-blue-50 text-blue-500">
|
|
|
|
|
|
<icon-ic-round-library-add class="text-3xl" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<div class="text-xl text-gray-800 font-bold">
|
|
|
|
|
|
新建环节题包
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="mt-1 text-sm text-gray-500">
|
|
|
|
|
|
请输入环节名称与题目预设数量
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<NForm size="large">
|
|
|
|
|
|
<NFormItem label="环节/题包名称">
|
2026-01-27 09:48:42 +08:00
|
|
|
|
<NInput v-model:value="newRoundForm.name" placeholder="例如:第一轮 星·诗词大会" />
|
2026-01-21 16:29:38 +08:00
|
|
|
|
</NFormItem>
|
2026-01-23 18:16:03 +08:00
|
|
|
|
<NFormItem label="环节/题包类型">
|
|
|
|
|
|
<NSelect
|
|
|
|
|
|
v-model:value="newRoundForm.roundType" :options="roundTypeOptions as unknown as SelectOption[]"
|
|
|
|
|
|
placeholder="请选择环节类型..." :bordered="true" class="font-medium"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</NFormItem>
|
2026-01-21 16:29:38 +08:00
|
|
|
|
<NFormItem label="初始化题目数量">
|
|
|
|
|
|
<NInputNumber v-model:value="newRoundForm.count" :min="1" :max="50" class="w-full" />
|
|
|
|
|
|
</NFormItem>
|
|
|
|
|
|
</NForm>
|
|
|
|
|
|
|
2026-01-23 18:16:03 +08:00
|
|
|
|
<NButton
|
|
|
|
|
|
type="primary" block size="large" class="mt-4 !h-12 !rounded-xl !text-lg !font-bold"
|
|
|
|
|
|
@click="handleConfirmAdd"
|
|
|
|
|
|
>
|
2026-01-21 16:29:38 +08:00
|
|
|
|
生成题包卡片
|
|
|
|
|
|
</NButton>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</NModal>
|
2026-01-19 18:03:45 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
2026-01-23 18:16:03 +08:00
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
.ghost {
|
|
|
|
|
|
@apply opacity-50 bg-blue-50 border-2 border-dashed border-blue-300;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|