feat: deaw

This commit is contained in:
zzc
2026-01-20 20:49:19 +08:00
parent 9d5b9b6812
commit 3fa5b1c58b
3 changed files with 128 additions and 28 deletions

8
api/fortune.js Normal file
View File

@@ -0,0 +1,8 @@
import { request } from "@/utils/request.js";
export const drawFortune = async () => {
return request({
url: "/api/blessing/fortune/draw",
method: "GET",
});
};

8
api/system.js Normal file
View File

@@ -0,0 +1,8 @@
import { request } from "@/utils/request.js";
export const abilityCheck = async (scene) => {
return request({
url: "/api/blessing/ability/check?scene=" + scene,
method: "GET",
});
};

View File

@@ -46,29 +46,42 @@
<!-- 结果状态运势卡片 --> <!-- 结果状态运势卡片 -->
<view class="state-result" v-else> <view class="state-result" v-else>
<view class="result-card" id="result-card"> <view
<view class="card-header"> class="result-card"
<text class="year-tag">2026 乙巳年</text> id="result-card"
</view> :class="{ 'image-mode': !!currentFortune.imageUrl }"
<view class="card-body"> >
<view class="icon-circle"> <template v-if="currentFortune.imageUrl">
<text class="result-icon"></text> <image
:src="currentFortune.imageUrl"
mode="widthFix"
class="fortune-image"
/>
</template>
<template v-else>
<view class="card-header">
<text class="year-tag">2026 乙巳年</text>
</view> </view>
<text class="result-title">{{ currentFortune.title }}</text> <view class="card-body">
<view class="divider"></view> <view class="icon-circle">
<text class="result-desc">{{ currentFortune.desc }}</text> <text class="result-icon"></text>
<text class="result-sub">旧岁千般皆如意新年万事定称心</text> </view>
</view> <text class="result-title">{{ currentFortune.title }}</text>
<view class="card-footer"> <view class="divider"></view>
<view class="footer-left"> <text class="result-desc">{{ currentFortune.desc }}</text>
<text class="sub-en">LUCKY CHARM</text> <text class="result-sub">旧岁千般皆如意新年万事定称心</text>
<text class="sub-cn">每日运势签</text>
</view> </view>
<view class="footer-right"> <view class="card-footer">
<text class="scan-tip">长按识别\n扫码祈福</text> <view class="footer-left">
<view class="qr-code"></view> <text class="sub-en">LUCKY CHARM</text>
<text class="sub-cn">每日运势签</text>
</view>
<view class="footer-right">
<text class="scan-tip">长按识别\n扫码祈福</text>
<view class="qr-code"></view>
</view>
</view> </view>
</view> </template>
</view> </view>
<view class="result-actions"> <view class="result-actions">
@@ -102,9 +115,13 @@
<script setup> <script setup>
import { ref, onUnmounted } from "vue"; import { ref, onUnmounted } from "vue";
import { getBavBarHeight } from "@/utils/system"; import { getBavBarHeight } from "@/utils/system";
import { onLoad, onShow } from "@dcloudio/uni-app";
import { abilityCheck } from "@/api/system.js";
import { drawFortune } from "@/api/fortune.js";
const status = ref("initial"); // initial, shaking, result const status = ref("initial"); // initial, shaking, result
const remainingCount = ref(1); const remainingCount = ref(0);
const canUse = ref(true);
// 音效控制 // 音效控制
const audioContext = uni.createInnerAudioContext(); const audioContext = uni.createInnerAudioContext();
@@ -118,6 +135,19 @@ audioContext.onEnded(() => {
} }
}); });
onLoad(() => {});
onShow(() => {
checkDrawStatus();
});
const checkDrawStatus = async () => {
const res = await abilityCheck("fortune_draw");
if (res.canUse) {
remainingCount.value = res.remain;
}
};
onUnmounted(() => { onUnmounted(() => {
audioContext.destroy(); audioContext.destroy();
}); });
@@ -140,7 +170,7 @@ const goBack = () => {
} }
}; };
const startShake = () => { const startShake = async () => {
if (remainingCount.value <= 0) { if (remainingCount.value <= 0) {
uni.showToast({ title: "今日次数已用完", icon: "none" }); uni.showToast({ title: "今日次数已用完", icon: "none" });
return; return;
@@ -153,12 +183,26 @@ const startShake = () => {
audioContext.play(); audioContext.play();
// 模拟摇晃动画和数据请求 // 模拟摇晃动画和数据请求
setTimeout(() => { const minTime = 2000;
const idx = Math.floor(Math.random() * fortunes.length); const startT = Date.now();
currentFortune.value = fortunes[idx];
status.value = "result"; try {
remainingCount.value--; const res = await drawFortune();
}, 2000);
const endT = Date.now();
const waitTime = Math.max(0, minTime - (endT - startT));
setTimeout(() => {
currentFortune.value = res;
status.value = "result";
remainingCount.value--;
}, waitTime);
} catch (e) {
setTimeout(() => {
status.value = "initial";
uni.showToast({ title: "网络请求失败", icon: "none" });
}, minTime);
}
}; };
const reset = () => { const reset = () => {
@@ -166,6 +210,36 @@ const reset = () => {
}; };
const saveCard = () => { const saveCard = () => {
if (currentFortune.value.imageUrl) {
uni.showLoading({ title: "保存中..." });
uni.downloadFile({
url: currentFortune.value.imageUrl,
success: (res) => {
if (res.statusCode === 200) {
uni.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: () => {
uni.hideLoading();
uni.showToast({ title: "已保存到相册" });
},
fail: () => {
uni.hideLoading();
uni.showToast({ title: "保存失败", icon: "none" });
},
});
} else {
uni.hideLoading();
uni.showToast({ title: "下载失败", icon: "none" });
}
},
fail: () => {
uni.hideLoading();
uni.showToast({ title: "下载失败", icon: "none" });
},
});
return;
}
uni.showLoading({ title: "生成中..." }); uni.showLoading({ title: "生成中..." });
const ctx = uni.createCanvasContext("shareCanvas"); const ctx = uni.createCanvasContext("shareCanvas");
@@ -416,6 +490,16 @@ const saveCard = () => {
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
margin-bottom: 30px; margin-bottom: 30px;
} }
.result-card.image-mode {
padding: 0;
overflow: hidden;
background: transparent;
}
.fortune-image {
width: 100%;
display: block;
border-radius: 16px;
}
.card-header { .card-header {
text-align: center; text-align: center;
margin-bottom: 30px; margin-bottom: 30px;