Files
yuxingu-Miniprogram-dev/pages/yxg/relation.vue
T
jackyu66gitandCursor b09d82df8d feat: 小程序统一走 Go 后台,咨询与登录切到 /api/v1
去掉协会 WebView 和魔方账密页,微信登录与咨询接口共用同一 token 和拦截器。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-15 00:26:28 +08:00

120 lines
4.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>