feat: P1 合盘/星座/问答与测测完整设计包及模拟器取证工具
落地 synastry/star/ask API 与 H5 页面,补齐 cece-frontend-re complete-design 证据文档,并加入 Android 模拟器截图抓取脚本。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
/** Build / parse client-side share landing query (no server). */
|
||||
|
||||
export type PortraitSharePayload = {
|
||||
type: 'portrait'
|
||||
title: string
|
||||
line: string
|
||||
keywords: string[]
|
||||
}
|
||||
|
||||
export type RelationSharePayload = {
|
||||
type: 'relation'
|
||||
me: string
|
||||
other: string
|
||||
diff: string
|
||||
keywords: string[]
|
||||
}
|
||||
|
||||
export type SharePayload = PortraitSharePayload | RelationSharePayload
|
||||
|
||||
export function buildSharePath(payload: SharePayload): string {
|
||||
const q = new URLSearchParams()
|
||||
q.set('type', payload.type)
|
||||
if (payload.type === 'portrait') {
|
||||
if (payload.title) q.set('t', payload.title)
|
||||
if (payload.line) q.set('l', payload.line)
|
||||
if (payload.keywords.length) q.set('k', payload.keywords.slice(0, 6).join(','))
|
||||
} else {
|
||||
if (payload.me) q.set('me', payload.me)
|
||||
if (payload.other) q.set('ot', payload.other)
|
||||
if (payload.diff) q.set('d', payload.diff)
|
||||
if (payload.keywords.length) q.set('k', payload.keywords.slice(0, 6).join(','))
|
||||
}
|
||||
return `/share?${q.toString()}`
|
||||
}
|
||||
|
||||
export function parseShareQuery(query: Record<string, unknown>): SharePayload | null {
|
||||
const type = String(query.type || '')
|
||||
const keywords = String(query.k || '')
|
||||
.split(',')
|
||||
.map((s) => s.trim())
|
||||
.filter(Boolean)
|
||||
if (type === 'portrait') {
|
||||
const title = String(query.t || '')
|
||||
const line = String(query.l || '')
|
||||
if (!title && !line && !keywords.length) return null
|
||||
return { type: 'portrait', title, line, keywords }
|
||||
}
|
||||
if (type === 'relation') {
|
||||
const me = String(query.me || '')
|
||||
const other = String(query.ot || '')
|
||||
const diff = String(query.d || '')
|
||||
if (!me && !other && !diff) return null
|
||||
return { type: 'relation', me, other, diff, keywords }
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export async function copyText(text: string): Promise<boolean> {
|
||||
try {
|
||||
if (navigator.clipboard?.writeText) {
|
||||
await navigator.clipboard.writeText(text)
|
||||
return true
|
||||
}
|
||||
} catch {
|
||||
/* fall through */
|
||||
}
|
||||
try {
|
||||
const ta = document.createElement('textarea')
|
||||
ta.value = text
|
||||
ta.style.position = 'fixed'
|
||||
ta.style.left = '-9999px'
|
||||
document.body.appendChild(ta)
|
||||
ta.select()
|
||||
const ok = document.execCommand('copy')
|
||||
document.body.removeChild(ta)
|
||||
return ok
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user