每日运势小程序

This commit is contained in:
cjd
2025-11-09 18:41:07 +08:00
parent 1cc0241cda
commit abd82782af
34 changed files with 2204 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
const fortuneStore = require("../../store/fortuneStore");
const { normalizeFortunePayload } = require("../../utils/fortuneFormatter");
const { formatDisplayDateTime } = require("../../utils/date");
const messages = require("../../constants/messages");
const { getPageSafeTop } = require("../../utils/safeArea");
const { formatRegionDisplay, normalizeRegionArray } = require("../../utils/region");
function showToast(title) {
if (typeof tt === "undefined" || !tt.showToast) {
console.warn("Toast:", title);
return;
}
tt.showToast({
title,
icon: "none",
duration: 2000
});
}
Page({
data: {
safeAreaTop: 64,
recordTime: "",
fortuneDate: "",
summary: "",
narrative: "",
dimensions: [],
luckyGuide: null,
profile: null,
overallScore: 0,
city: ""
},
onLoad(options) {
this.updateSafeAreaPadding();
fortuneStore.loadHistory();
const id = options && options.id ? options.id : "";
if (!id) {
showToast(messages.HISTORY_NOT_FOUND);
this.safeBack();
return;
}
const record = fortuneStore.getHistoryById(id);
if (!record) {
showToast(messages.HISTORY_NOT_FOUND);
this.safeBack();
return;
}
const normalized = normalizeFortunePayload(record.fortune);
if (!normalized) {
showToast(messages.HISTORY_NOT_FOUND);
this.safeBack();
return;
}
const snapshot = record.formSnapshot || {};
const regionValue = normalizeRegionArray(snapshot.birthRegion);
const fallbackSegments = [snapshot.birthProvince, snapshot.birthCity, snapshot.birthDistrict].filter(Boolean);
const cityLabel = formatRegionDisplay(regionValue, fallbackSegments);
this.setData(
Object.assign({}, normalized, {
recordTime: formatDisplayDateTime(record.createdAt),
city: cityLabel || snapshot.birthCity || ""
})
);
},
handleBack() {
this.safeBack();
},
updateSafeAreaPadding() {
const padding = getPageSafeTop();
this.setData({ safeAreaTop: padding });
},
safeBack() {
if (typeof tt !== "undefined" && tt.navigateBack) {
tt.navigateBack();
}
}
});

View File

@@ -0,0 +1,3 @@
{
"navigationStyle": "custom"
}

View File

@@ -0,0 +1,112 @@
<view class="page">
<scroll-view class="content" scroll-y="true" style="padding-top: {{safeAreaTop}}px;">
<view class="record-card">
<text class="record-label">保存时间</text>
<text class="record-value">{{recordTime}}</text>
<text class="record-label">测算城市</text>
<text class="record-value">{{city}}</text>
</view>
<view class="summary-card">
<view class="summary-header">
<view>
<text class="summary-title">整体指数</text>
<text class="summary-date">{{fortuneDate || '历史记录'}}</text>
</view>
<text class="summary-score">{{overallScore}}</text>
</view>
<text class="summary-text" tt:if="{{summary}}">{{summary}}</text>
</view>
<view class="lucky-card" tt:if="{{luckyGuide}}">
<view class="card-title">
<text>吉祥元素</text>
<text class="element-tag">{{luckyGuide.element}}</text>
</view>
<view class="guide-row" tt:if="{{luckyGuide.colorText}}">
<text class="guide-label">幸运色</text>
<text class="guide-value">{{luckyGuide.colorText}}</text>
</view>
<view class="guide-row" tt:if="{{luckyGuide.directionText}}">
<text class="guide-label">方位</text>
<text class="guide-value">{{luckyGuide.directionText}}</text>
</view>
<view class="guide-row" tt:if="{{luckyGuide.activitiesText}}">
<text class="guide-label">建议</text>
<text class="guide-value">{{luckyGuide.activitiesText}}</text>
</view>
<view class="time-slots" tt:if="{{luckyGuide.bestTimeSlots.length}}">
<block tt:for="{{luckyGuide.bestTimeSlots}}" tt:key="label">
<view class="time-slot">
<text class="time-label">{{item.label}}</text>
<text class="time-period">{{item.period}}</text>
<text class="time-reason">{{item.reason}}</text>
</view>
</block>
</view>
</view>
<view class="dimension-card" tt:if="{{dimensions.length}}">
<view class="card-title">
<text>六维运势</text>
</view>
<view class="dimension-grid">
<block tt:for="{{dimensions}}" tt:key="key">
<view class="dimension-item">
<view class="dimension-header">
<text class="dimension-icon">{{item.icon}}</text>
<view>
<text class="dimension-title">{{item.title}}</text>
<text class="dimension-trend">{{item.trendText}}</text>
</view>
<text class="dimension-score">{{item.score}}</text>
</view>
<text class="dimension-insight">{{item.insight}}</text>
<text class="dimension-suggestion">{{item.suggestion}}</text>
</view>
</block>
</view>
</view>
<view class="profile-card" tt:if="{{profile}}">
<view class="card-title">
<text>命盘摘要</text>
<text class="card-subtitle">{{profile.birthCity}}</text>
</view>
<view class="profile-row">
<text class="profile-label">出生信息</text>
<text class="profile-value">{{profile.birthDateTime}}</text>
</view>
<view class="pillars">
<block tt:for="{{profile.birthPillars}}" tt:key="label">
<view class="pillar">
<text class="pillar-label">{{item.label}}</text>
<text class="pillar-value">{{item.value}}</text>
</view>
</block>
</view>
<view class="elements" tt:if="{{profile.distribution.length}}">
<block tt:for="{{profile.distribution}}" tt:key="element">
<view class="element-bar">
<text class="element-label">{{item.element}}</text>
<view class="bar-track">
<view class="bar-fill" style="width: {{item.width}};"></view>
</view>
<text class="element-percent">{{item.percent}}%</text>
</view>
</block>
</view>
</view>
<view class="narrative-card" tt:if="{{narrative}}">
<view class="card-title">
<text>解读</text>
</view>
<text class="narrative-text">{{narrative}}</text>
</view>
<view class="actions">
<button class="secondary" bindtap="handleBack">返回</button>
</view>
</scroll-view>
</view>

View File

@@ -0,0 +1,21 @@
@import "../result/index.ttss";
.record-card {
background: rgba(255, 255, 255, 0.08);
border-radius: 24rpx;
padding: 28rpx;
margin-bottom: 28rpx;
border: 1px solid rgba(255, 255, 255, 0.08);
}
.record-label {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.55);
}
.record-value {
display: block;
font-size: 30rpx;
color: #fff7e3;
margin-bottom: 16rpx;
}