报名列表增加用户渠道展示

master
weizong song 3 months ago
parent f9e367b0c6
commit e1e09a671f

@ -4,4 +4,4 @@ import { RouterView } from 'vue-router'
<template>
<RouterView />
</template>
</template>

@ -102,6 +102,7 @@ export interface AdminApplicationListParams {
track?: string
keyword?: string
signup_channel_id?: number
public_source_channel_id?: number
}
export type AdminApplicationExportMode = 'xlsx' | 'selected' | 'all'

@ -18,4 +18,6 @@ router.afterEach(() => {
void capturePublicSourceFromLocation()
})
document.documentElement.dataset.adminBuildMarker = '2026-06-19-frontend-rebuild'
createApp(App).use(pinia).use(router).use(ElementPlus, { locale: zhCn }).mount('#app')

@ -20,6 +20,7 @@ import {
listSignupChannels,
updateSignupChannel,
} from '../../../api/admin/signupChannels'
import { listPublicSourceChannels } from '../../../api/admin/publicSourceChannels'
import {
downloadAdminApplicationFile,
exportAdminApplications,
@ -37,6 +38,7 @@ import type {
CompetitionTrackPayload,
CompetitionTrackRow,
FormSchemaRow,
PublicSourceChannelRow,
SignupChannelPayload,
SignupChannelRow,
} from '../../../api/admin/types'
@ -99,6 +101,8 @@ const tracks = ref<CompetitionTrackRow[]>([])
const tracksLoading = ref(false)
const channels = ref<SignupChannelRow[]>([])
const channelsLoading = ref(false)
const publicSourceChannels = ref<PublicSourceChannelRow[]>([])
const publicSourceChannelsLoading = ref(false)
const applications = ref<AdminApplicationRow[]>([])
const selectedApplications = ref<AdminApplicationRow[]>([])
const applicationsLoading = ref(false)
@ -117,6 +121,7 @@ const applicationFilters = ref({
status: 'submitted',
track: '',
signup_channel_id: undefined as number | undefined,
public_source_channel_id: undefined as number | undefined,
})
const trackDialogVisible = ref(false)
@ -289,6 +294,7 @@ watch(tabKey, (t) => {
if (t === 'channels') void refreshChannels()
if (t === 'applications') {
void refreshChannels()
void refreshPublicSourceChannels()
void refreshApplications()
}
if (t === 'signupForm') void refreshSignupSchemas()
@ -637,6 +643,18 @@ async function refreshChannels() {
}
}
async function refreshPublicSourceChannels() {
publicSourceChannelsLoading.value = true
try {
publicSourceChannels.value = await listPublicSourceChannels()
} catch (e) {
publicSourceChannels.value = []
ElMessage.error(e instanceof Error ? e.message : '加载用户渠道列表失败')
} finally {
publicSourceChannelsLoading.value = false
}
}
function applicationStatusLabel(status: string): string {
if (status === 'submitted') return '已提交'
if (status === 'draft') return '草稿'
@ -714,6 +732,7 @@ async function refreshApplications(page = applicationPager.value.page) {
status: applicationFilters.value.status || undefined,
track: applicationFilters.value.track || undefined,
signup_channel_id: applicationFilters.value.signup_channel_id || undefined,
public_source_channel_id: applicationFilters.value.public_source_channel_id || undefined,
})
applications.value = res.data
applicationPager.value = {
@ -730,7 +749,13 @@ async function refreshApplications(page = applicationPager.value.page) {
}
function resetApplicationFilters() {
applicationFilters.value = { keyword: '', status: 'submitted', track: '', signup_channel_id: undefined }
applicationFilters.value = {
keyword: '',
status: 'submitted',
track: '',
signup_channel_id: undefined,
public_source_channel_id: undefined,
}
void refreshApplications(1)
}
@ -752,6 +777,7 @@ async function exportApplications(mode: AdminApplicationExportMode) {
status: applicationFilters.value.status || undefined,
track: applicationFilters.value.track || undefined,
signup_channel_id: applicationFilters.value.signup_channel_id || undefined,
public_source_channel_id: applicationFilters.value.public_source_channel_id || undefined,
application_ids:
mode === 'selected' ? selectedApplications.value.map((row) => row.id) : undefined,
},
@ -1430,7 +1456,7 @@ onMounted(() => {
</el-select>
<el-select
v-model="applicationFilters.signup_channel_id"
placeholder="渠道"
placeholder="报名渠道"
clearable
filterable
teleported
@ -1443,6 +1469,22 @@ onMounted(() => {
:value="channel.id"
/>
</el-select>
<el-select
v-model="applicationFilters.public_source_channel_id"
placeholder="用户渠道"
clearable
filterable
teleported
:loading="publicSourceChannelsLoading"
class="application-filter-select application-filter-channel"
>
<el-option
v-for="channel in publicSourceChannels"
:key="channel.id"
:label="`${channel.source_name}(${channel.source_code})`"
:value="channel.id"
/>
</el-select>
</div>
<div class="application-actions">
<el-dropdown trigger="click" @command="exportApplications">
@ -1499,7 +1541,7 @@ onMounted(() => {
</template>
</el-table-column>
<el-table-column prop="track_title" label="赛道" min-width="130" show-overflow-tooltip />
<el-table-column label="渠道" min-width="150" show-overflow-tooltip>
<el-table-column label="报名渠道" min-width="150" show-overflow-tooltip>
<template #default="{ row }">
<span class="cell-muted">
{{
@ -2207,7 +2249,7 @@ onMounted(() => {
.application-filters {
display: grid;
grid-template-columns: minmax(220px, 1fr) 130px 130px minmax(180px, 220px);
grid-template-columns: minmax(220px, 1fr) repeat(4, minmax(130px, 180px));
gap: 8px;
align-items: center;
}

Loading…
Cancel
Save