1 parent
23844ae301
commit
d25b5dbe6d
268 files changed
+3684
-8861
No files matched your search
@@ -62,15 +62,9 @@ async function handleUpdateStatus() {
|
||||
|
||||
<template>
|
||||
<n-flex>
|
||||
<n-button size="small" secondary type="primary" @click="goEdit">
|
||||
编辑
|
||||
</n-button>
|
||||
<n-button size="small" secondary type="info" @click="goDetail">
|
||||
详情
|
||||
</n-button>
|
||||
<n-button size="small" secondary type="warning" @click="openStatusModal">
|
||||
状态
|
||||
</n-button>
|
||||
<n-button size="small" secondary type="primary" @click="goEdit"> 编辑 </n-button>
|
||||
<n-button size="small" secondary type="info" @click="goDetail"> 详情 </n-button>
|
||||
<n-button size="small" secondary type="warning" @click="openStatusModal"> 状态 </n-button>
|
||||
<n-popconfirm @positive-click="handleDeleteProblemSet">
|
||||
<template #trigger>
|
||||
<n-button secondary size="small" type="error">删除</n-button>
|
||||
@@ -79,20 +73,11 @@ async function handleUpdateStatus() {
|
||||
</n-popconfirm>
|
||||
</n-flex>
|
||||
|
||||
<n-modal
|
||||
v-model:show="showStatusModal"
|
||||
preset="card"
|
||||
title="更新题单状态"
|
||||
style="width: 400px"
|
||||
>
|
||||
<n-modal v-model:show="showStatusModal" preset="card" title="更新题单状态" style="width: 400px">
|
||||
<n-space vertical>
|
||||
<n-form>
|
||||
<n-form-item label="状态" required>
|
||||
<n-select
|
||||
v-model:value="newStatus"
|
||||
:options="statusOptions"
|
||||
placeholder="选择状态"
|
||||
/>
|
||||
<n-select v-model:value="newStatus" :options="statusOptions" placeholder="选择状态" />
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</n-space>
|
||||
|
||||
@@ -55,9 +55,7 @@ defineEmits<Emits>()
|
||||
title: '条件值',
|
||||
key: 'condition_value',
|
||||
render: (row) => {
|
||||
return row.conditionType === 'all_problems'
|
||||
? '-'
|
||||
: row.conditionValue
|
||||
return row.conditionType === 'all_problems' ? '-' : row.conditionValue
|
||||
},
|
||||
},
|
||||
{ title: '描述', key: 'description' },
|
||||
|
||||
@@ -28,9 +28,7 @@ const emit = defineEmits<Emits>()
|
||||
const badgeName = ref("")
|
||||
const badgeDescription = ref("")
|
||||
const badgeIcon = ref("")
|
||||
const badgeConditionType = ref<"all_problems" | "problem_count" | "score">(
|
||||
"all_problems",
|
||||
)
|
||||
const badgeConditionType = ref<"all_problems" | "problem_count" | "score">("all_problems")
|
||||
const badgeConditionValue = ref(1)
|
||||
|
||||
// 预设奖章图标选项
|
||||
@@ -99,12 +97,7 @@ watch(
|
||||
<n-input v-model:value="badgeName" placeholder="请输入奖章名称" />
|
||||
</n-form-item>
|
||||
<n-form-item label="描述">
|
||||
<n-input
|
||||
v-model:value="badgeDescription"
|
||||
type="textarea"
|
||||
placeholder="奖章描述"
|
||||
required
|
||||
/>
|
||||
<n-input v-model:value="badgeDescription" type="textarea" placeholder="奖章描述" required />
|
||||
</n-form-item>
|
||||
<n-form-item label="图标" required>
|
||||
<n-flex align="center" gap="small">
|
||||
@@ -115,17 +108,13 @@ watch(
|
||||
:style="{
|
||||
width: '60px',
|
||||
height: '60px',
|
||||
border:
|
||||
badgeIcon === option.value
|
||||
? '2px solid #1890ff'
|
||||
: '1px solid #d9d9d9',
|
||||
border: badgeIcon === option.value ? '2px solid #1890ff' : '1px solid #d9d9d9',
|
||||
borderRadius: '4px',
|
||||
cursor: 'pointer',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundColor:
|
||||
badgeIcon === option.value ? '#f0f8ff' : 'transparent',
|
||||
backgroundColor: badgeIcon === option.value ? '#f0f8ff' : 'transparent',
|
||||
}"
|
||||
>
|
||||
<n-image
|
||||
@@ -147,10 +136,7 @@ watch(
|
||||
:options="conditionTypeOptions"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
label="条件值"
|
||||
v-if="badgeConditionType !== 'all_problems'"
|
||||
>
|
||||
<n-form-item label="条件值" v-if="badgeConditionType !== 'all_problems'">
|
||||
<n-input-number
|
||||
style="width: 120px"
|
||||
v-model:value="badgeConditionValue"
|
||||
|
||||
@@ -21,9 +21,7 @@ defineEmits<Emits>()
|
||||
<div>
|
||||
<n-flex justify="space-between" align="center" style="margin-bottom: 16px">
|
||||
<h3>题目列表</h3>
|
||||
<n-button type="primary" @click="$emit('add-problem')">
|
||||
添加题目
|
||||
</n-button>
|
||||
<n-button type="primary" @click="$emit('add-problem')"> 添加题目 </n-button>
|
||||
</n-flex>
|
||||
<n-data-table
|
||||
:columns="[
|
||||
|
||||
@@ -75,16 +75,10 @@ watch(
|
||||
<n-input :value="problem.title" disabled />
|
||||
</n-form-item>
|
||||
<n-form-item v-else label="题目ID" required>
|
||||
<n-input
|
||||
v-model:value="problemId"
|
||||
placeholder="请输入题目的显示ID(如:1001)"
|
||||
/>
|
||||
<n-input v-model:value="problemId" placeholder="请输入题目的显示ID(如:1001)" />
|
||||
</n-form-item>
|
||||
<n-form-item label="顺序">
|
||||
<n-input-number
|
||||
v-model:value="problemOrder"
|
||||
placeholder="题目在题单中的顺序"
|
||||
/>
|
||||
<n-input-number v-model:value="problemOrder" placeholder="题目在题单中的顺序" />
|
||||
</n-form-item>
|
||||
<n-form-item label="是否必做">
|
||||
<n-switch v-model:value="problemRequired" />
|
||||
@@ -93,11 +87,7 @@ watch(
|
||||
<n-input-number v-model:value="problemScore" placeholder="题目分数" />
|
||||
</n-form-item>
|
||||
<n-form-item label="提示">
|
||||
<n-input
|
||||
v-model:value="problemHint"
|
||||
type="textarea"
|
||||
placeholder="题目提示"
|
||||
/>
|
||||
<n-input v-model:value="problemHint" type="textarea" placeholder="题目提示" />
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<template #footer>
|
||||
|
||||
@@ -22,8 +22,7 @@ const progressColumns = [
|
||||
title: "加入时间",
|
||||
key: "joinTime",
|
||||
width: 180,
|
||||
render: (row: AdminProblemSetProgress) =>
|
||||
parseTime(row.joinTime, "YYYY-MM-DD HH:mm:ss"),
|
||||
render: (row: AdminProblemSetProgress) => parseTime(row.joinTime, "YYYY-MM-DD HH:mm:ss"),
|
||||
},
|
||||
{ title: "已完成", key: "completedProblemsCount", width: 100 },
|
||||
{ title: "总题目", key: "totalProblemsCount", width: 100 },
|
||||
@@ -31,8 +30,7 @@ const progressColumns = [
|
||||
title: "进度",
|
||||
key: "progressPercentage",
|
||||
width: 100,
|
||||
render: (row: AdminProblemSetProgress) =>
|
||||
`${row.progressPercentage.toFixed(0)}%`,
|
||||
render: (row: AdminProblemSetProgress) => `${row.progressPercentage.toFixed(0)}%`,
|
||||
},
|
||||
{
|
||||
title: "是否完成",
|
||||
|
||||
@@ -237,10 +237,7 @@ onMounted(() => {
|
||||
</n-tab-pane>
|
||||
|
||||
<n-tab-pane name="progress" tab="进度管理">
|
||||
<ProgressManagement
|
||||
:progress="progress"
|
||||
@remove-user="handleRemoveUser"
|
||||
/>
|
||||
<ProgressManagement :progress="progress" @remove-user="handleRemoveUser" />
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
|
||||
|
||||
@@ -23,10 +23,7 @@ const formData = ref<CreateProblemSetData & Partial<EditProblemSetData>>({
|
||||
// n-date-picker 按浏览器本地渲染,所以要平移一次再绑定(见 utils/functions.ts
|
||||
// 的 toPickerValue)。`formData.endTime` 里始终存**真实时刻**,只有喂给选择器那一步换。
|
||||
const endTimeTimestamp = computed({
|
||||
get: () =>
|
||||
formData.value.endTime
|
||||
? toPickerValue(formData.value.endTime.getTime())
|
||||
: null,
|
||||
get: () => (formData.value.endTime ? toPickerValue(formData.value.endTime.getTime()) : null),
|
||||
set: (val: number | null) => {
|
||||
formData.value.endTime = val ? new Date(fromPickerValue(val)) : null
|
||||
},
|
||||
@@ -89,11 +86,7 @@ async function handleSubmit() {
|
||||
}
|
||||
router.push({ name: "admin problemset list" })
|
||||
} catch (err) {
|
||||
message.error(
|
||||
(isEdit.value ? "更新" : "创建") +
|
||||
"题单失败:" +
|
||||
errorMessage(err, "未知错误"),
|
||||
)
|
||||
message.error((isEdit.value ? "更新" : "创建") + "题单失败:" + errorMessage(err, "未知错误"))
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
@@ -58,11 +58,7 @@ const columns: DataTableColumn<AdminProblemSet>[] = [
|
||||
Hard: { type: "error" as const, text: "困难" },
|
||||
}
|
||||
const config = difficultyMap[row.difficulty]
|
||||
return h(
|
||||
NTag,
|
||||
{ type: config.type, size: "small" },
|
||||
{ default: () => config.text },
|
||||
)
|
||||
return h(NTag, { type: config.type, size: "small" }, { default: () => config.text })
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -76,11 +72,7 @@ const columns: DataTableColumn<AdminProblemSet>[] = [
|
||||
draft: { type: "info" as const, text: "草稿" },
|
||||
}
|
||||
const config = statusMap[row.status]
|
||||
return h(
|
||||
NTag,
|
||||
{ type: config.type, size: "small" },
|
||||
{ default: () => config.text },
|
||||
)
|
||||
return h(NTag, { type: config.type, size: "small" }, { default: () => config.text })
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -146,20 +138,14 @@ watchDebounced(() => query.keyword, listProblemSets, {
|
||||
})
|
||||
|
||||
// 监听其他查询条件变化
|
||||
watch(
|
||||
() => [query.page, query.limit, query.difficulty, query.status],
|
||||
listProblemSets,
|
||||
)
|
||||
watch(() => [query.page, query.limit, query.difficulty, query.status], listProblemSets)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-flex class="titleWrapper" justify="space-between">
|
||||
<n-flex align="center">
|
||||
<h2 class="title">题单管理</h2>
|
||||
<n-button
|
||||
type="primary"
|
||||
@click="$router.push({ name: 'admin problemset create' })"
|
||||
>
|
||||
<n-button type="primary" @click="$router.push({ name: 'admin problemset create' })">
|
||||
新建题单
|
||||
</n-button>
|
||||
</n-flex>
|
||||
@@ -194,11 +180,7 @@ watch(
|
||||
</n-flex>
|
||||
</n-flex>
|
||||
<n-data-table striped :columns="columns" :data="problemSets" />
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:limit="query.limit"
|
||||
v-model:page="query.page"
|
||||
/>
|
||||
<Pagination :total="total" v-model:limit="query.limit" v-model:page="query.page" />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
Reference in new issue
Block a user