251 lines
9.8 KiB
Plaintext
251 lines
9.8 KiB
Plaintext
<view class="container">
|
||
<!-- 自定义返回按钮 -->
|
||
<view class="nav-back" bindtap="handleBack">
|
||
<text class="back-icon">⇠</text>
|
||
<text class="back-text">返回</text>
|
||
</view>
|
||
<!-- 1. 牌阵选择状态 - 卡片式V2 -->
|
||
<view class="spread-select-area" wx:if="{{state === 'spread_select'}}">
|
||
<!-- 顶部标题区域 -->
|
||
<view class="spread-header">
|
||
<text class="spread-title">选择适合你的牌阵</text>
|
||
<text class="spread-subtitle">不同的问题,需要不同的展开方式</text>
|
||
</view>
|
||
|
||
<!-- 标签筛选条 -->
|
||
<view class="tags-area">
|
||
<scroll-view class="tags-scroll" scroll-x="true" enable-flex="true">
|
||
<view class="tag-item {{activeTag === item ? 'active' : ''}}"
|
||
wx:for="{{spreadTags}}"
|
||
wx:key="*this"
|
||
bindtap="filterSpreads"
|
||
data-tag="{{item}}">
|
||
<text>{{item}}</text>
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
|
||
<!-- 两列卡片网格 -->
|
||
<view class="spread-grid">
|
||
<view class="spread-card"
|
||
wx:for="{{filteredSpreads}}"
|
||
wx:key="id"
|
||
bindtap="selectSpread"
|
||
data-id="{{item.id}}">
|
||
|
||
<!-- 右上角标签角标 -->
|
||
<view class="card-badge" wx:if="{{item.tags[0]}}">
|
||
<text>{{item.tags[0]}}</text>
|
||
</view>
|
||
|
||
<!-- 牌阵名称 -->
|
||
<text class="card-name">{{item.name}}</text>
|
||
|
||
<!-- 描述 -->
|
||
<text class="card-desc">{{item.description}}</text>
|
||
|
||
<!-- 底部信息 -->
|
||
<view class="card-footer">
|
||
<text class="card-count">{{item.cardCount}} 张牌</text>
|
||
<text class="card-cost">消耗 {{item.cost}} 积分</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 1.5 提问状态 - 沉浸式仪式感版本 -->
|
||
<view class="asking-area" wx:if="{{state === 'asking'}}">
|
||
<view class="title-area">
|
||
<text class="app-title">请输入你想询问的问题</text>
|
||
<text class="instruction">心中默念问题,塔罗牌将为你指引方向</text>
|
||
</view>
|
||
<!-- 中央塔罗卡片式输入区 -->
|
||
<view class="input-card">
|
||
<textarea
|
||
class="question-input"
|
||
placeholder="例如:我们的关系会如何发展?我是否应该换工作?这个合作值得继续吗?"
|
||
placeholder-class="placeholder-style"
|
||
bindinput="onQuestionInput"
|
||
value="{{question}}"
|
||
maxlength="200"
|
||
></textarea>
|
||
<text class="char-count">{{question.length}}/200</text>
|
||
|
||
<!-- 新增:质量评分显示 -->
|
||
<view class="quality-indicator" wx:if="{{questionQuality && question.length > 0}}">
|
||
<text class="quality-icon">{{questionQuality.icon}}</text>
|
||
<text class="quality-text">提问质量:{{questionQuality.level}}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 温和分割线 -->
|
||
<view class="divider"></view>
|
||
|
||
<!-- 塔罗低语区域 -->
|
||
<view class="whispers-area">
|
||
<text class="whispers-title">塔罗为你低语…</text>
|
||
<scroll-view class="whispers-scroll" scroll-x="true" enable-flex="true">
|
||
<view class="whisper-card {{selectedWhisperIndex === index ? 'selected' : ''}}"
|
||
wx:for="{{tarotWhispers}}"
|
||
wx:key="text"
|
||
bindtap="selectWhisper"
|
||
data-index="{{index}}"
|
||
data-question="{{item.text}}">
|
||
<text class="whisper-text">{{item.text}}</text>
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
|
||
<button class="start-btn" bindtap="confirmQuestion">开启塔罗指引</button>
|
||
</view>
|
||
|
||
<!-- 2. 洗牌状态 (展示动画) -->
|
||
<view class="ritual-area" wx:if="{{state === 'shuffling'}}">
|
||
<view class="shuffling-container">
|
||
<image class="shuffling-card" wx:for="{{[1,2,3,4,5]}}" wx:key="*this" src="{{cardBackImage}}" mode="aspectFill" style="animation-delay: {{index * 0.2}}s"></image>
|
||
</view>
|
||
<text class="ritual-hint">正在感应你的能量,请保持内心平静...</text>
|
||
</view>
|
||
|
||
<!-- 3. 抽牌状态 (展开牌面供选择) -->
|
||
<view class="drawing-area" wx:if="{{state === 'drawing'}}">
|
||
<view class="title-area">
|
||
<text class="app-title">请挑选 {{selectedSpread.cardCount}} 张牌</text>
|
||
<text class="instruction">凭直觉选出触动你的卡牌</text>
|
||
</view>
|
||
<!-- 抽牌槽位(仅占位符) -->
|
||
<view class="slots-container {{selectedSpread.id}}">
|
||
<view class="slot-item" wx:for="{{selectedSpread.cardCount}}" wx:key="index">
|
||
<view class="slot-placeholder">
|
||
<text class="slot-num">{{index + 1}}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 牌堆:卡牌会直接从这里飞到上方槽位 -->
|
||
<view class="fan-deck">
|
||
<view
|
||
class="fan-card {{helper.isSelected(drawnCardIndices, index) ? 'is-selected' : ''}}"
|
||
wx:for="{{20}}"
|
||
wx:key="*this"
|
||
style="transform: {{helper.getTransform(drawnCardIndices, index, selectedSpread.cardCount)}};"
|
||
bindtap="onCardTap"
|
||
data-index="{{index}}"
|
||
>
|
||
<image class="card-back-sm" src="{{cardBackImage}}" mode="aspectFill"></image>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 简单辅助逻辑 -->
|
||
<wxs module="helper">
|
||
module.exports.isSelected = function(indices, currentIdx) {
|
||
return indices.indexOf(currentIdx) !== -1;
|
||
};
|
||
|
||
module.exports.getTransform = function(indices, currentIdx, count) {
|
||
var pos = indices.indexOf(currentIdx);
|
||
if (pos !== -1) {
|
||
// 每排最多5张牌
|
||
var maxPerRow = 5;
|
||
var row = Math.floor(pos / maxPerRow); // 第几排(0或1)
|
||
var col = pos % maxPerRow; // 该排的第几个
|
||
var cardsInRow = (row === 0) ? Math.min(count, maxPerRow) : (count - maxPerRow);
|
||
|
||
// 槽位:宽100rpx + gap 20rpx = 120rpx 间距
|
||
var slotWidth = 100;
|
||
var gap = 20;
|
||
var slotSpacing = slotWidth + gap;
|
||
|
||
// 计算该排槽位的水平居中偏移
|
||
// 从该排中间位置开始计算
|
||
var centerOffset = (col - (cardsInRow - 1) / 2) * slotSpacing;
|
||
|
||
// 垂直偏移计算
|
||
// 第一排槽位:向上 -520rpx(已验证接近正确)
|
||
// 第二排:需要减少向上的距离
|
||
// 槽位高度160 + gap 20 = 180,但实际可能需要微调
|
||
var firstRowY = -520;
|
||
var secondRowOffset = 200; // 增加偏移量,让第二排更接近fan-deck
|
||
var yOffset = firstRowY + (row * secondRowOffset); // row=0: -520, row=1: -320
|
||
|
||
// 位移并缩小到0.65
|
||
return 'translate(' + centerOffset + 'rpx, ' + yOffset + 'rpx) scale(0.65) rotate(0deg)';
|
||
} else {
|
||
// 保持在牌堆中的放射状
|
||
return 'rotate(' + ((currentIdx - 10) * 8) + 'deg)';
|
||
}
|
||
};
|
||
</wxs>
|
||
<view class="draw-count">{{drawnCardIndices.length}} / {{selectedSpread.cardCount}}</view>
|
||
<button class="confirm-draw-btn" wx:if="{{drawnCardIndices.length === selectedSpread.cardCount}}" bindtap="confirmDraw">开启解读</button>
|
||
</view>
|
||
|
||
<!-- 4. 翻牌与结果展示状态 -->
|
||
<!-- 4. 翻牌与结果展示状态 -->
|
||
<view class="result-area" wx:if="{{state === 'flipping' || state === 'revealed'}}">
|
||
<!-- 卡牌阵列 -->
|
||
<view class="spread-display {{selectedSpread.id}}">
|
||
<view class="card-slot" wx:for="{{drawnCards}}" wx:key="index">
|
||
<text class="pos-name">{{selectedSpread.positions[index]}}(第{{index + 1}}张)</text>
|
||
<view class="flip-scene" bindtap="revealNext" data-index="{{index}}">
|
||
<view class="flip-card {{index < revealedCount ? 'flipped' : ''}}">
|
||
<view class="card-face face-back">
|
||
<image class="card-image" src="{{cardBackImage}}" mode="widthFix"></image>
|
||
</view>
|
||
<view class="card-face face-front">
|
||
<image class="card-image {{item.isReversed ? 'reversed' : ''}}" src="{{item.image}}" mode="widthFix"></image>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<text class="card-name-sm" wx:if="{{index < revealedCount}}">{{item.name}}{{item.isReversed ? '(逆)' : ''}}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 解读区域 -->
|
||
<view class="interpretation-area" wx:if="{{revealedCount === selectedSpread.cardCount}}" animation="{{infoAnimation}}">
|
||
<view class="loading-ai" wx:if="{{isAiLoading}}">
|
||
<text class="loading-dot">···</text>
|
||
<text>{{aiLoadingText}}</text>
|
||
</view>
|
||
|
||
<view class="structured-result" wx:else>
|
||
<view class="theme-box">
|
||
<text class="label">核心主题</text>
|
||
<text class="content">{{aiResult.theme}}</text>
|
||
</view>
|
||
|
||
<view class="info-grid">
|
||
<view class="info-item">
|
||
<text class="label">当前状态</text>
|
||
<text class="content">{{aiResult.status}}</text>
|
||
</view>
|
||
<view class="info-item">
|
||
<text class="label">潜在影响</text>
|
||
<text class="content">{{aiResult.influence}}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 整体趋势 -->
|
||
<view class="story-box" wx:if="{{spreadStory}}">
|
||
<text class="label">整体趋势</text>
|
||
<text class="content">{{spreadStory}}</text>
|
||
</view>
|
||
|
||
<view class="pos-meanings">
|
||
<view class="pos-meaning-item" wx:for="{{aiResult.positions}}" wx:key="posName">
|
||
<text class="pos-title">{{item.posName}}</text>
|
||
<text class="pos-text">在【{{questionType}}】来看:{{item.posMeaning}}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="advice-box">
|
||
<text class="label">行动建议</text>
|
||
<text class="content">{{aiResult.advice}}</text>
|
||
</view>
|
||
|
||
<button class="reset-btn" bindtap="resetSpread">重新开启</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|