([])
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(() => {
{
:value="channel.id"
/>
+
+
+
@@ -1499,7 +1541,7 @@ onMounted(() => {
-
+
{{
@@ -1516,6 +1558,17 @@ onMounted(() => {
+
+
+
+ {{
+ row.public_source_channel
+ ? `${row.public_source_channel.source_name}(${row.public_source_channel.source_code})`
+ : row.public_source_code || '—'
+ }}
+
+
+
{{ row.files_count }}
@@ -2204,7 +2257,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;
}
diff --git a/vite.config.ts b/vite.config.ts
index 90eb773..9c724fa 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -2,13 +2,23 @@
import history from 'connect-history-api-fallback'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
-import { defineConfig } from 'vite'
+import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import { viteStaticCopy } from 'vite-plugin-static-copy'
import type { Plugin } from 'vite'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
-const laravelPublicAdmin = path.resolve(__dirname, '../xxfcyds2026-backend/public/admin')
+
+function resolveBuildOutDir(rawPath: string | undefined): string {
+ const configured = rawPath?.trim()
+ if (!configured) {
+ return path.resolve(__dirname, 'dist/admin')
+ }
+
+ return path.isAbsolute(configured)
+ ? configured
+ : path.resolve(__dirname, configured)
+}
function spaHistoryFallback(): Plugin {
const middleware = history({ index: '/index.html' })
@@ -28,42 +38,47 @@ function spaHistoryFallback(): Plugin {
}
// https://vite.dev/config/
-export default defineConfig(({ mode }) => ({
- base: mode === 'production' ? '/admin/' : '/',
- build: {
- outDir: laravelPublicAdmin,
- emptyOutDir: true,
- },
- plugins: [
- vue(),
- spaHistoryFallback(),
- /** 勿在 dev 对 /frontend/prototype 挂 sirv:会与 import prototype.css 冲突(返回 text/css 导致动态 import .vue 失败) */
- viteStaticCopy({
- targets: [
- {
- src: 'frontend/prototype/**/*',
- dest: 'frontend/prototype',
- rename: { stripBase: 2 },
+export default defineConfig(({ mode }) => {
+ const env = loadEnv(mode, __dirname, '')
+ const adminOutDir = resolveBuildOutDir(env.FRONTEND_BUILD_OUT_DIR)
+
+ return {
+ base: mode === 'production' ? '/admin/' : '/',
+ build: {
+ outDir: adminOutDir,
+ emptyOutDir: true,
+ },
+ plugins: [
+ vue(),
+ spaHistoryFallback(),
+ /** 勿在 dev 对 /frontend/prototype 挂 sirv:会与 import prototype.css 冲突(返回 text/css 导致动态 import .vue 失败) */
+ viteStaticCopy({
+ targets: [
+ {
+ src: 'frontend/prototype/**/*',
+ dest: 'frontend/prototype',
+ rename: { stripBase: 2 },
+ },
+ ],
+ }),
+ ],
+ server: {
+ open: '/',
+ proxy: {
+ '/api': {
+ // cxxfds-service;与本机 php artisan serve 端口一致(8000 常被其它 Laravel 占用时改用 8001)
+ target: 'http://127.0.0.1:8002',
+ changeOrigin: true,
},
- ],
- }),
- ],
- server: {
- open: '/',
- proxy: {
- '/api': {
- // cxxfds-service;与本机 php artisan serve 端口一致(8000 常被其它 Laravel 占用时改用 8001)
- target: 'http://127.0.0.1:8002',
- changeOrigin: true,
},
},
- },
- preview: {
- proxy: {
- '/api': {
- target: 'http://127.0.0.1:8002',
- changeOrigin: true,
+ preview: {
+ proxy: {
+ '/api': {
+ target: 'http://127.0.0.1:8002',
+ changeOrigin: true,
+ },
},
},
- },
-}))
+ }
+})