236 lines
5.9 KiB
Vue
236 lines
5.9 KiB
Vue
<template>
|
||
<scroll-view class="panel-scroll" scroll-y>
|
||
<view class="head-card">
|
||
<text class="head-title">今日约会建议</text>
|
||
<text class="head-date">{{ todayLabel }}</text>
|
||
<text class="head-note">以下内容根据你在「我是谁」「约会准备」中的填写自动生成,仅供当日参考。</text>
|
||
</view>
|
||
|
||
<view v-if="emptyHint" class="empty-wrap">
|
||
<text class="empty-title">还没有足够的信息</text>
|
||
<text class="empty-desc">请先在「我是谁」和「约会准备」里填写内容,保存后再来查看约会建议。</text>
|
||
</view>
|
||
|
||
<view v-else class="list">
|
||
<view v-for="(line, idx) in lines" :key="idx" class="advice-item">
|
||
<text class="advice-index">{{ idx + 1 }}</text>
|
||
<text class="advice-text">{{ line }}</text>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
</template>
|
||
|
||
<script>
|
||
const KEY_WHO = 'xixi_who_am_i';
|
||
const KEY_MEET = 'xixi_first_meeting';
|
||
|
||
function formatToday() {
|
||
const d = new Date();
|
||
const wk = ['日', '一', '二', '三', '四', '五', '六'];
|
||
return `${d.getFullYear()}年${d.getMonth() + 1}月${d.getDate()}日 星期${wk[d.getDay()]}`;
|
||
}
|
||
|
||
function trimSnippet(text, max) {
|
||
if (text == null || text === '') return '';
|
||
const s = String(text).trim().replace(/\s+/g, ' ');
|
||
if (!s) return '';
|
||
return s.length > max ? s.slice(0, max) + '…' : s;
|
||
}
|
||
|
||
function buildLines(who, meet) {
|
||
const w = who && typeof who === 'object' ? who : {};
|
||
const m = meet && typeof meet === 'object' ? meet : {};
|
||
const hasWho = !!(w.selfIntro && String(w.selfIntro).trim()) || !!(w.partnerExpect && String(w.partnerExpect).trim());
|
||
const hasMeet =
|
||
!!(m.relationshipStatus && String(m.relationshipStatus).trim()) || !!(m.meetingGoal && String(m.meetingGoal).trim());
|
||
if (!hasWho && !hasMeet) {
|
||
return { empty: true, lines: [] };
|
||
}
|
||
|
||
const lines = [];
|
||
|
||
lines.push('下面几条结合你在「我是谁」「约会准备」中的填写整理,方便你出门前快速过一遍思路。');
|
||
|
||
if (m.relationshipStatus) {
|
||
const sn = trimSnippet(m.relationshipStatus, 56);
|
||
lines.push(
|
||
`关系阶段你描述为「${sn}」:聊天节奏与对方投入程度尽量匹配这一阶段,不必急于定义关系,也避免过度冷淡让对方不安。`,
|
||
);
|
||
}
|
||
|
||
if (m.meetingGoal) {
|
||
const sn = trimSnippet(m.meetingGoal, 72);
|
||
lines.push(
|
||
`本次见面你希望「${sn}」:可以准备 1~2 个轻松的小话题或问题,自然带入即可,不必像完成任务一样逐项核对。`,
|
||
);
|
||
}
|
||
|
||
if (w.selfIntro) {
|
||
lines.push(
|
||
'「我是谁」里你写到的特点:今天选 1~2 点最想被对方感受到的,用小事或简短例子带过即可,留一点空间让对方慢慢了解你。',
|
||
);
|
||
}
|
||
|
||
if (w.partnerExpect) {
|
||
lines.push(
|
||
'关于对另一半的期待:更适合在互动中观察对方的言行是否合拍,用好奇和分享代替盘问,减少「考察感」。',
|
||
);
|
||
}
|
||
|
||
lines.push('见面时多倾听、适当复述对方话里的关键词,让对方感到被听懂;适当留白比一直找话题更重要。');
|
||
lines.push('若短暂冷场,可以从环境、共同经历或轻松八卦切入,不必为「必须有趣」而焦虑。');
|
||
lines.push('结束前可以自然聊聊今天的感受、是否愉快,再顺势看下次是否方便再约,不给对方过大压力。');
|
||
|
||
return { empty: false, lines };
|
||
}
|
||
|
||
export default {
|
||
name: 'XixiDatingAdvice',
|
||
props: {
|
||
refreshTick: {
|
||
type: Number,
|
||
default: 0,
|
||
},
|
||
},
|
||
data() {
|
||
return {
|
||
todayLabel: formatToday(),
|
||
emptyHint: true,
|
||
lines: [],
|
||
};
|
||
},
|
||
watch: {
|
||
refreshTick() {
|
||
this.regenerate();
|
||
},
|
||
},
|
||
mounted() {
|
||
this.regenerate();
|
||
},
|
||
methods: {
|
||
regenerate() {
|
||
this.todayLabel = formatToday();
|
||
let who = {};
|
||
let meet = {};
|
||
try {
|
||
const rawW = uni.getStorageSync(KEY_WHO);
|
||
if (rawW && typeof rawW === 'object') who = rawW;
|
||
} catch (e) {
|
||
/* ignore */
|
||
}
|
||
try {
|
||
const rawM = uni.getStorageSync(KEY_MEET);
|
||
if (rawM && typeof rawM === 'object') meet = rawM;
|
||
} catch (e) {
|
||
/* ignore */
|
||
}
|
||
const { empty, lines } = buildLines(who, meet);
|
||
this.emptyHint = empty;
|
||
this.lines = lines;
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style scoped>
|
||
.panel-scroll {
|
||
height: 100%;
|
||
box-sizing: border-box;
|
||
padding: 24rpx 28rpx 40rpx;
|
||
}
|
||
|
||
.head-card {
|
||
background: #fff;
|
||
border-radius: 20rpx;
|
||
padding: 28rpx;
|
||
margin-bottom: 24rpx;
|
||
box-shadow: 0 4rpx 24rpx rgba(233, 30, 140, 0.06);
|
||
}
|
||
|
||
.head-title {
|
||
display: block;
|
||
font-size: 34rpx;
|
||
font-weight: 600;
|
||
color: #333;
|
||
margin-bottom: 12rpx;
|
||
}
|
||
|
||
.head-date {
|
||
display: block;
|
||
font-size: 26rpx;
|
||
color: #e91e8c;
|
||
margin-bottom: 16rpx;
|
||
}
|
||
|
||
.head-note {
|
||
display: block;
|
||
font-size: 24rpx;
|
||
color: #888;
|
||
line-height: 1.55;
|
||
}
|
||
|
||
.empty-wrap {
|
||
background: #fff;
|
||
border-radius: 20rpx;
|
||
padding: 48rpx 32rpx;
|
||
text-align: center;
|
||
box-shadow: 0 4rpx 24rpx rgba(233, 30, 140, 0.04);
|
||
}
|
||
|
||
.empty-title {
|
||
display: block;
|
||
font-size: 30rpx;
|
||
font-weight: 600;
|
||
color: #333;
|
||
margin-bottom: 16rpx;
|
||
}
|
||
|
||
.empty-desc {
|
||
font-size: 26rpx;
|
||
color: #888;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.advice-item {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: flex-start;
|
||
background: #fff;
|
||
border-radius: 20rpx;
|
||
padding: 24rpx 24rpx 24rpx 20rpx;
|
||
margin-bottom: 20rpx;
|
||
box-shadow: 0 4rpx 20rpx rgba(233, 30, 140, 0.06);
|
||
}
|
||
|
||
.advice-item:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.advice-index {
|
||
flex-shrink: 0;
|
||
width: 44rpx;
|
||
height: 44rpx;
|
||
line-height: 44rpx;
|
||
text-align: center;
|
||
font-size: 24rpx;
|
||
font-weight: 600;
|
||
color: #fff;
|
||
background: linear-gradient(135deg, #ff6b9d, #e91e8c);
|
||
border-radius: 12rpx;
|
||
margin-right: 16rpx;
|
||
margin-top: 4rpx;
|
||
}
|
||
|
||
.advice-text {
|
||
flex: 1;
|
||
font-size: 28rpx;
|
||
color: #444;
|
||
line-height: 1.65;
|
||
}
|
||
</style>
|