去掉协会 WebView 和魔方账密页,微信登录与咨询接口共用同一 token 和拦截器。 Co-authored-by: Cursor <cursoragent@cursor.com>
120 lines
4.8 KiB
Vue
120 lines
4.8 KiB
Vue
<template>
|
||
<yxg-page title="人格匹配">
|
||
<view v-if="!report" class="card">
|
||
<text class="h1">看见彼此的相处模式</text>
|
||
<text class="desc">填写 TA 的称呼与生日,对照性格与默契。</text>
|
||
<input class="inp" v-model="otherName" placeholder="TA 的称呼" />
|
||
<view class="rels">
|
||
<view v-for="o in relationOptions" :key="o.value" class="rel" :class="{ on: relationType === o.value }" @click="relationType = o.value">
|
||
<text>{{ o.label }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="date-row">
|
||
<input class="inp sm" type="number" v-model="oy" placeholder="年" />
|
||
<input class="inp sm" type="number" v-model="om" placeholder="月" />
|
||
<input class="inp sm" type="number" v-model="od" placeholder="日" />
|
||
</view>
|
||
<text v-if="error" class="err">{{ error }}</text>
|
||
<view class="btn" :class="{ off: loading }" @click="run"><text>{{ loading ? '分析中…' : '开始匹配' }}</text></view>
|
||
</view>
|
||
<view v-else class="card">
|
||
<text class="h1">{{ fitLabel || '相处参考' }}</text>
|
||
<text class="lead">{{ diff }}</text>
|
||
<text class="meta">我:{{ meStyle }}</text>
|
||
<text class="meta">TA:{{ otherStyle }}</text>
|
||
<text v-if="harmony != null" class="idx">默契 {{ harmony }}</text>
|
||
<view class="navs">
|
||
<view class="btn ghost" @click="report = null"><text>再测一次</text></view>
|
||
<view class="btn" @click="yxgGo(`/reports/${report.id}`)"><text>完整报告</text></view>
|
||
</view>
|
||
</view>
|
||
</yxg-page>
|
||
</template>
|
||
|
||
<script setup>
|
||
import YxgPage from '@/components/yxg/yxg-page.vue'
|
||
import { yxgApi } from '@/util/yxgApi.js'
|
||
import { ensureAccount, ensureOtherProfile, findSelfProfile } from '@/util/yxgAuth.js'
|
||
import { yxgGo } from '@/util/yxgNav.js'
|
||
|
||
const relationOptions = [
|
||
{ value: 'partner', label: '伴侣' },
|
||
{ value: 'friend', label: '朋友' },
|
||
{ value: 'family', label: '家人' },
|
||
{ value: 'other', label: '其他' },
|
||
]
|
||
const otherName = ref('TA')
|
||
const relationType = ref('partner')
|
||
const oy = ref('')
|
||
const om = ref('')
|
||
const od = ref('')
|
||
const loading = ref(false)
|
||
const error = ref('')
|
||
const report = ref(null)
|
||
|
||
const summary = computed(() => report.value?.summary || {})
|
||
const meStyle = computed(() => String(summary.value.me_style || ''))
|
||
const otherStyle = computed(() => String(summary.value.other_style || ''))
|
||
const diff = computed(() => String(summary.value.diff_one_liner || summary.value.one_liner || ''))
|
||
const fitLabel = computed(() => String(summary.value.fit_label || ''))
|
||
const harmony = computed(() => (typeof summary.value.harmony_index === 'number' ? summary.value.harmony_index : null))
|
||
|
||
async function run() {
|
||
const y = Number(oy.value), m = Number(om.value), d = Number(od.value)
|
||
if (!y || !m || !d) {
|
||
error.value = '请填写 TA 的完整生日'
|
||
return
|
||
}
|
||
loading.value = true
|
||
error.value = ''
|
||
if (!(await ensureAccount('/relation'))) {
|
||
loading.value = false
|
||
return
|
||
}
|
||
try {
|
||
const self = await findSelfProfile()
|
||
if (!self) {
|
||
error.value = '请先完善自己的生日档案'
|
||
yxgGo('/profile')
|
||
return
|
||
}
|
||
const birth = `${y}-${String(m).padStart(2, '0')}-${String(d).padStart(2, '0')}`
|
||
const other = await ensureOtherProfile({
|
||
birth_date: birth,
|
||
display_name: otherName.value || 'TA',
|
||
relation_type: relationType.value,
|
||
})
|
||
const out = await yxgApi.createRelationInsight(self.id, other.id)
|
||
report.value = out.report || out
|
||
} catch (e) {
|
||
error.value = e instanceof Error ? e.message : '分析失败'
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style>
|
||
page { background-color: #ffd1c7; }
|
||
</style>
|
||
<style scoped>
|
||
.card { margin: 12px 16px; padding: 18px 16px; background: #fff; border-radius: 18px; }
|
||
.h1 { display: block; font-size: 20px; font-weight: 700; color: #333; }
|
||
.desc, .lead, .meta { display: block; margin-top: 8px; font-size: 14px; color: #555; line-height: 1.55; }
|
||
.inp { width: 100%; height: 42px; background: #fdfaf8; border-radius: 12px; padding: 0 12px; box-sizing: border-box; margin-top: 12px; }
|
||
.rels { display: flex; gap: 8px; margin-top: 12px; }
|
||
.rel { flex: 1; height: 36px; border-radius: 999px; background: #f7f2ef; display: flex; align-items: center; justify-content: center; font-size: 13px; color: #666; }
|
||
.rel.on { background: #ffe4e4; color: #e54d42; }
|
||
.date-row { display: flex; gap: 8px; margin-top: 12px; }
|
||
.inp.sm { flex: 1; margin-top: 0; text-align: center; }
|
||
.err { display: block; margin-top: 8px; color: #e54d42; font-size: 13px; }
|
||
.idx { display: block; margin-top: 10px; font-size: 16px; font-weight: 700; color: #e54d42; }
|
||
.navs { display: flex; gap: 10px; margin-top: 16px; }
|
||
.btn {
|
||
flex: 1; height: 42px; border-radius: 999px; background: #e54d42; color: #fff;
|
||
display: flex; align-items: center; justify-content: center; font-weight: 700; margin-top: 12px;
|
||
}
|
||
.btn.ghost { background: #f7f2ef; color: #8a4a3a; }
|
||
.btn.off { opacity: 0.5; }
|
||
</style>
|