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,111 @@
|
||||
<template>
|
||||
<div v-if="open" class="mask" @click.self="$emit('close')">
|
||||
<div class="sheet">
|
||||
<header>
|
||||
<h3>分享卡</h3>
|
||||
<button type="button" class="x" @click="$emit('close')">关闭</button>
|
||||
</header>
|
||||
<ShareCard v-bind="card" />
|
||||
<p v-if="status" class="status">{{ status }}</p>
|
||||
<div class="btns">
|
||||
<button type="button" :disabled="busy" @click="copyLink">复制链接</button>
|
||||
<button v-if="canNative" type="button" class="ghost" :disabled="busy" @click="nativeShare">系统分享</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import ShareCard from './ShareCard.vue'
|
||||
import { buildSharePath, copyText, type SharePayload } from '../lib/shareLink'
|
||||
|
||||
const props = defineProps<{
|
||||
open: boolean
|
||||
payload: SharePayload | null
|
||||
}>()
|
||||
defineEmits<{ close: [] }>()
|
||||
|
||||
const busy = ref(false)
|
||||
const status = ref('')
|
||||
|
||||
const card = computed(() => {
|
||||
const p = props.payload
|
||||
if (!p) return {}
|
||||
if (p.type === 'portrait') {
|
||||
return {
|
||||
type: 'portrait' as const,
|
||||
title: p.title,
|
||||
line: p.line,
|
||||
keywords: p.keywords,
|
||||
ctaLabel: '查看完整成长报告',
|
||||
}
|
||||
}
|
||||
return {
|
||||
type: 'relation' as const,
|
||||
title: '我的方式 vs TA 的方式',
|
||||
rows: [
|
||||
p.me ? `我的沟通方式:${p.me}` : '',
|
||||
p.other ? `TA 的沟通方式:${p.other}` : '',
|
||||
p.diff ? `了解彼此 → ${p.diff}` : '了解彼此 → 查看关系理解',
|
||||
].filter(Boolean),
|
||||
keywords: p.keywords,
|
||||
ctaLabel: '了解彼此 → 查看关系理解',
|
||||
}
|
||||
})
|
||||
|
||||
const canNative = computed(() => typeof navigator !== 'undefined' && typeof navigator.share === 'function')
|
||||
|
||||
function absoluteShareURL(): string {
|
||||
if (!props.payload) return location.origin
|
||||
return `${location.origin}${buildSharePath(props.payload)}`
|
||||
}
|
||||
|
||||
async function copyLink() {
|
||||
busy.value = true
|
||||
status.value = ''
|
||||
const ok = await copyText(absoluteShareURL())
|
||||
status.value = ok ? '链接已复制' : '复制失败,请手动复制地址栏'
|
||||
busy.value = false
|
||||
}
|
||||
|
||||
async function nativeShare() {
|
||||
if (!props.payload || !navigator.share) return
|
||||
busy.value = true
|
||||
status.value = ''
|
||||
try {
|
||||
await navigator.share({
|
||||
title: '愈心谷',
|
||||
text: props.payload.type === 'relation' ? '看看我们的相处方式' : '看看我的个人画像',
|
||||
url: absoluteShareURL(),
|
||||
})
|
||||
status.value = '已唤起系统分享'
|
||||
} catch {
|
||||
status.value = ''
|
||||
} finally {
|
||||
busy.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.mask{
|
||||
position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:40;
|
||||
display:flex;align-items:flex-end;justify-content:center;padding:12px;
|
||||
}
|
||||
.sheet{
|
||||
width:100%;max-width:430px;background:#fff5f3;border-radius:20px 20px 12px 12px;
|
||||
padding:16px;max-height:90vh;overflow:auto;
|
||||
}
|
||||
header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px}
|
||||
h3{font-size:16px;margin:0}
|
||||
.x{border:none;background:transparent;color:#999;font-size:13px}
|
||||
.btns{display:flex;gap:8px;margin-top:14px}
|
||||
.btns button{
|
||||
flex:1;border:none;border-radius:22px;padding:11px;color:#fff;font-weight:600;
|
||||
background:linear-gradient(135deg,#ff7a6e,var(--yxg-pri));
|
||||
}
|
||||
.btns button.ghost{background:#fff;color:var(--yxg-pri);border:1px solid #f0c0bc}
|
||||
.btns button:disabled{opacity:.6}
|
||||
.status{font-size:12px;color:#888;margin-top:10px;text-align:center}
|
||||
</style>
|
||||
Reference in New Issue
Block a user