fix: pass public source through signup navigation

master
weizong song 4 months ago
parent f29b0143de
commit b3e7c2a318

@ -15,15 +15,21 @@ import './admin/routeMeta'
const MainLayout = () => import('../layouts/MainLayout.vue') const MainLayout = () => import('../layouts/MainLayout.vue')
function participantRootRedirect() { function sourceQueryFrom(to: { query?: Record<string, unknown> }): { src: string } | undefined {
const src = typeof to.query?.src === 'string' ? to.query.src.trim() : ''
return /^[A-Za-z0-9_-]{2,64}$/.test(src) ? { src } : undefined
}
function participantRootRedirect(to?: { query?: Record<string, unknown> }) {
const t = localStorage.getItem(TOKEN_KEY) const t = localStorage.getItem(TOKEN_KEY)
const s = localStorage.getItem(PARTICIPANT_COMPETITION_SLUG_KEY) const s = localStorage.getItem(PARTICIPANT_COMPETITION_SLUG_KEY)
const query = to ? sourceQueryFrom(to) : undefined
if (s) { if (s) {
return t return t
? { name: 'participant-apply', params: { slug: s }, replace: true as const } ? { name: 'participant-apply', params: { slug: s }, query, replace: true as const }
: { name: 'participant-login', params: { slug: s }, replace: true as const } : { name: 'participant-login', params: { slug: s }, query, replace: true as const }
} }
return { path: '/c', replace: true as const } return { path: '/c', query, replace: true as const }
} }
const router = createRouter({ const router = createRouter({
@ -173,9 +179,13 @@ router.beforeEach(async (to) => {
if (to.matched.some((r) => r.meta.requiresAuth) && !participantToken) { if (to.matched.some((r) => r.meta.requiresAuth) && !participantToken) {
const slug = to.params.slug != null ? String(to.params.slug) : '' const slug = to.params.slug != null ? String(to.params.slug) : ''
if (slug) { if (slug) {
return { name: 'participant-login', params: { slug }, query: { redirect: to.fullPath } } return {
name: 'participant-login',
params: { slug },
query: { redirect: to.fullPath, ...sourceQueryFrom(to) },
}
} }
return { path: '/c', query: { redirect: to.fullPath } } return { path: '/c', query: { redirect: to.fullPath, ...sourceQueryFrom(to) } }
} }
if (to.meta.guestOnly && participantToken) { if (to.meta.guestOnly && participantToken) {

@ -11,6 +11,11 @@ interface ResolveResponse {
source_name?: string source_name?: string
} }
function normalizeSourceCode(value: unknown): string | null {
const sourceCode = typeof value === 'string' ? value.trim() : ''
return /^[A-Za-z0-9_-]{2,64}$/.test(sourceCode) ? sourceCode : null
}
function nowMs(): number { function nowMs(): number {
return Date.now() return Date.now()
} }
@ -39,6 +44,14 @@ function writePublicSourceCache(sourceCode: string): void {
} }
export function readPublicSourceCodeForAttribution(): string | null { export function readPublicSourceCodeForAttribution(): string | null {
const currentUrlSourceCode =
typeof window !== 'undefined'
? normalizeSourceCode(new URLSearchParams(window.location.search).get('src'))
: null
if (currentUrlSourceCode) {
return currentUrlSourceCode
}
if (!storageAvailable()) return null if (!storageAvailable()) return null
const sourceCode = window.localStorage.getItem(SOURCE_CODE_KEY)?.trim() ?? '' const sourceCode = window.localStorage.getItem(SOURCE_CODE_KEY)?.trim() ?? ''
const checkedAtRaw = window.localStorage.getItem(SOURCE_CHECKED_AT_KEY)?.trim() ?? '' const checkedAtRaw = window.localStorage.getItem(SOURCE_CHECKED_AT_KEY)?.trim() ?? ''
@ -56,7 +69,7 @@ export function readPublicSourceCodeForAttribution(): string | null {
async function resolvePublicSource(sourceCode: string): Promise<string | null> { async function resolvePublicSource(sourceCode: string): Promise<string | null> {
const trimmed = sourceCode.trim() const trimmed = sourceCode.trim()
if (!/^[A-Za-z0-9_-]{2,64}$/.test(trimmed)) return null if (!normalizeSourceCode(trimmed)) return null
const qs = new URLSearchParams({ source_code: trimmed }) const qs = new URLSearchParams({ source_code: trimmed })
const res = await fetch(`${getApiBase()}/api/v1/public/source-channels/resolve?${qs.toString()}`, { const res = await fetch(`${getApiBase()}/api/v1/public/source-channels/resolve?${qs.toString()}`, {

@ -1,8 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue' import { ref } from 'vue'
import { useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import 'bootstrap/dist/css/bootstrap.min.css' import 'bootstrap/dist/css/bootstrap.min.css'
const route = useRoute()
const router = useRouter() const router = useRouter()
const slugInput = ref('') const slugInput = ref('')
const error = ref('') const error = ref('')
@ -14,7 +15,12 @@ function navigate() {
error.value = '请填写访问地址' error.value = '请填写访问地址'
return return
} }
void router.push({ name: 'participant-login', params: { slug: s } }) const src = typeof route.query.src === 'string' ? route.query.src.trim() : ''
void router.push({
name: 'participant-login',
params: { slug: s },
query: /^[A-Za-z0-9_-]{2,64}$/.test(src) ? { src } : undefined,
})
} }
</script> </script>

Loading…
Cancel
Save