v1.1 - Added question context analysis and spread story features
This commit is contained in:
parent
d9edbf0562
commit
71a73908fa
|
|
@ -4,6 +4,8 @@ const DEEPSEEK_BASE_URL = 'https://api.deepseek.com/chat/completions';
|
||||||
|
|
||||||
// --- 数据导入 ---
|
// --- 数据导入 ---
|
||||||
const { minorArcana } = require('../../data/tarot/index');
|
const { minorArcana } = require('../../data/tarot/index');
|
||||||
|
const { getQuestionType } = require('../../utils/questionType');
|
||||||
|
const { generateSpreadStory } = require('../../utils/spreadStory');
|
||||||
|
|
||||||
// --- Prompt 模板定义 ---
|
// --- Prompt 模板定义 ---
|
||||||
|
|
||||||
|
|
@ -179,6 +181,8 @@ Page({
|
||||||
// 1. 状态管理: spread_select, idle, shuffling, drawing, flipping, revealed
|
// 1. 状态管理: spread_select, idle, shuffling, drawing, flipping, revealed
|
||||||
state: 'spread_select', // 初始进入牌阵选择
|
state: 'spread_select', // 初始进入牌阵选择
|
||||||
selectedSpread: null,
|
selectedSpread: null,
|
||||||
|
question: '', // 用户输入的问题
|
||||||
|
questionType: '综合问题', // 问题类型
|
||||||
drawnCardIndices: [], // 用户选中的牌索引
|
drawnCardIndices: [], // 用户选中的牌索引
|
||||||
drawnCards: [], // 实际抽到的牌对象
|
drawnCards: [], // 实际抽到的牌对象
|
||||||
revealedCount: 0, // 已翻开的数量
|
revealedCount: 0, // 已翻开的数量
|
||||||
|
|
@ -195,6 +199,7 @@ Page({
|
||||||
// AI 相关
|
// AI 相关
|
||||||
isAiLoading: false,
|
isAiLoading: false,
|
||||||
aiExplanation: '',
|
aiExplanation: '',
|
||||||
|
spreadStory: '', // 综合故事线
|
||||||
|
|
||||||
// 3. 前缀文案列表(随机抽取)
|
// 3. 前缀文案列表(随机抽取)
|
||||||
prefixList: [
|
prefixList: [
|
||||||
|
|
@ -410,6 +415,17 @@ Page({
|
||||||
const spread = this.data.spreads.find(s => s.id === id);
|
const spread = this.data.spreads.find(s => s.id === id);
|
||||||
this.setData({
|
this.setData({
|
||||||
selectedSpread: spread,
|
selectedSpread: spread,
|
||||||
|
state: 'asking' // 先进入提问状态
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// --- 1.5 确认问题并开始洗牌 ---
|
||||||
|
confirmQuestion: function () {
|
||||||
|
const question = this.data.question.trim();
|
||||||
|
const questionType = getQuestionType(question);
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
questionType: questionType,
|
||||||
state: 'shuffling'
|
state: 'shuffling'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -419,6 +435,13 @@ Page({
|
||||||
}, 2500);
|
}, 2500);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 输入问题
|
||||||
|
onQuestionInput: function (e) {
|
||||||
|
this.setData({
|
||||||
|
question: e.detail.value
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
// --- 2. 抽牌逻辑 ---
|
// --- 2. 抽牌逻辑 ---
|
||||||
onCardTap: function (e) {
|
onCardTap: function (e) {
|
||||||
const index = e.currentTarget.dataset.index;
|
const index = e.currentTarget.dataset.index;
|
||||||
|
|
@ -524,8 +547,10 @@ Page({
|
||||||
if (res.data && res.data.choices && res.data.choices[0]) {
|
if (res.data && res.data.choices && res.data.choices[0]) {
|
||||||
try {
|
try {
|
||||||
const aiResult = JSON.parse(res.data.choices[0].message.content);
|
const aiResult = JSON.parse(res.data.choices[0].message.content);
|
||||||
|
const spreadStory = generateSpreadStory(drawnCards);
|
||||||
this.setData({
|
this.setData({
|
||||||
aiResult,
|
aiResult,
|
||||||
|
spreadStory: spreadStory,
|
||||||
isAiLoading: false
|
isAiLoading: false
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,26 @@
|
||||||
</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-area">
|
||||||
|
<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>
|
||||||
|
<button class="start-btn" bindtap="confirmQuestion" hover-class="btn-hover">开始抽牌</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 2. 洗牌状态 (展示动画) -->
|
<!-- 2. 洗牌状态 (展示动画) -->
|
||||||
<view class="ritual-area" wx:if="{{state === 'shuffling'}}">
|
<view class="ritual-area" wx:if="{{state === 'shuffling'}}">
|
||||||
<view class="shuffling-container">
|
<view class="shuffling-container">
|
||||||
|
|
@ -143,10 +163,16 @@
|
||||||
</view>
|
</view>
|
||||||
</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-meanings">
|
||||||
<view class="pos-meaning-item" wx:for="{{aiResult.positions}}" wx:key="posName">
|
<view class="pos-meaning-item" wx:for="{{aiResult.positions}}" wx:key="posName">
|
||||||
<text class="pos-title">{{item.posName}}</text>
|
<text class="pos-title">{{item.posName}}</text>
|
||||||
<text class="pos-text">{{item.posMeaning}}</text>
|
<text class="pos-text">在【{{questionType}}】来看:{{item.posMeaning}}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -442,3 +442,82 @@ page {
|
||||||
0%, 100% { opacity: 0.3; transform: scale(0.9); }
|
0%, 100% { opacity: 0.3; transform: scale(0.9); }
|
||||||
50% { opacity: 1; transform: scale(1.1); }
|
50% { opacity: 1; transform: scale(1.1); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 整体趋势故事框 */
|
||||||
|
.story-box {
|
||||||
|
background: linear-gradient(135deg, rgba(201, 160, 220, 0.1), rgba(138, 138, 157, 0.05));
|
||||||
|
padding: 30rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
border-left: 4rpx solid #c9a0dc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.story-box .label {
|
||||||
|
display: block;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #c9a0dc;
|
||||||
|
margin-bottom: 15rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 2rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.story-box .content {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #e0e0e0;
|
||||||
|
line-height: 1.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 提问区域样式 */
|
||||||
|
.asking-area {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 60rpx 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-area {
|
||||||
|
width: 100%;
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
border-radius: 20rpx;
|
||||||
|
padding: 30rpx;
|
||||||
|
margin-bottom: 60rpx;
|
||||||
|
border: 1px solid rgba(201, 160, 220, 0.2);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.question-input {
|
||||||
|
width: 100%;
|
||||||
|
height: 300rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.placeholder-style {
|
||||||
|
color: rgba(255, 255, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.char-count {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 20rpx;
|
||||||
|
right: 30rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: #8a8a9d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.start-btn {
|
||||||
|
background: #c9a0dc;
|
||||||
|
color: #1a1a2e;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 24rpx 100rpx;
|
||||||
|
border-radius: 50rpx;
|
||||||
|
box-shadow: 0 4rpx 20rpx rgba(201, 160, 220, 0.3);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-hover {
|
||||||
|
transform: scale(0.98);
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
function getQuestionType(question) {
|
||||||
|
if (!question) return "综合问题";
|
||||||
|
|
||||||
|
if (/爱|恋|关系|复合|分手|对象|感情|桃花|结婚|老公|老婆|男友|女友/.test(question)) {
|
||||||
|
return "感情关系";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (/工作|事业|面试|跳槽|职场|公司|升职|离职|创业|项目/.test(question)) {
|
||||||
|
return "事业工作";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (/钱|收入|财务|投资|赚钱|债|工资|薪水|理财/.test(question)) {
|
||||||
|
return "金钱财务";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (/学习|考试|上岸|成绩|学校|考研|留学|进修/.test(question)) {
|
||||||
|
return "学业成长";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (/健康|身体|状态|焦虑|压力|睡眠|精神/.test(question)) {
|
||||||
|
return "健康状态";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "综合问题";
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getQuestionType: getQuestionType
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
function generateSpreadStory(cards) {
|
||||||
|
if (!cards || cards.length < 2) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const names = cards.map(c => c.name).join("、");
|
||||||
|
|
||||||
|
return "从整体牌阵来看,你当前的经历更像是一个逐步发展的过程。" +
|
||||||
|
"这些牌(" + names + ")并不是孤立存在的,而是在描述一个连续的变化。" +
|
||||||
|
"它提示你关注事情的发展方向,而不仅仅是单一阶段。";
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
generateSpreadStory: generateSpreadStory
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue