第一版本

This commit is contained in:
mzhang93 2026-04-25 15:12:16 +08:00
parent 1c69d38cee
commit 4b9f936347
7 changed files with 70 additions and 22 deletions

Binary file not shown.

Binary file not shown.

View File

@ -184,8 +184,8 @@ const displayMainValue = computed(() => {
<style scoped lang="scss">
.report-metric-card {
width: 158px;
height: 158px;
width: 168px;
height: 168px;
box-sizing: border-box;
background: #fff;
border-radius: 12px;

4
src/types/silly-datetime.d.ts vendored Normal file
View File

@ -0,0 +1,4 @@
declare module 'silly-datetime' {
export function format(date: Date | number | string, pattern?: string): string;
}

View File

@ -13,7 +13,6 @@
:src="tipsVideoSrc"
muted
playsinline
autoplay
preload="auto"
@ended="onTipsEnded"
@timeupdate="onTipsTimeUpdate"
@ -63,7 +62,7 @@ import { Capacitor } from '@capacitor/core';
import { StatusBar, Style } from '@capacitor/status-bar';
import { CameraPreview } from '@capgo/camera-preview';
import { Circle as VanCircle } from 'vant';
import { computed, onBeforeUnmount, onMounted, ref } from 'vue';
import { computed, nextTick, onBeforeUnmount, onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
import tips2Url from '@/assets/step2/2.mp4?url';
@ -81,7 +80,8 @@ const PREVIEW_ASPECT = 4 / 3; // 4:3不裁剪想更宽可改 16/9
const RETICLE_CENTER_Y = 0.3;
const tipsVideoEl = ref<HTMLVideoElement | null>(null);
const showTipsVideo = ref(true);
// /
const showTipsVideo = ref(false);
const tipsVideoSrc = computed(() => tips2Url);
let navigatingToStep3 = false;
function onTipsTimeUpdate() {
@ -119,7 +119,7 @@ function onTipsEnded() {
// 100% videoFilePath step3
if (!navigatingToStep3) {
navigatingToStep3 = true;
setTimeout(() => {
// setTimeout(() => {
queueMicrotask(async () => {
try {
await teardownRecorder(); // sessionStorage['step2_video_path']
@ -127,7 +127,7 @@ function onTipsEnded() {
router.push('/step3');
}
});
}, 5000);
// }, 2000);
}
}
@ -247,6 +247,7 @@ onMounted(async () => {
document.documentElement.classList.add('step2-camera-active');
progress.value = 0;
currentRate.value = 0;
showTipsVideo.value = false;
if (!Capacitor.isNativePlatform()) {
statusText.value = '请在真机或模拟器Capacitor中打开以使用前置录像';
@ -267,11 +268,23 @@ onMounted(async () => {
try {
await setupNativeRecorder();
//
// /
showTipsVideo.value = true;
await nextTick();
tryPlayTips();
} catch (e) {
console.error(e);
statusText.value = '无法启动相机或麦克风,请检查系统权限';
showTipsVideo.value = false;
const el = tipsVideoEl.value;
if (el) {
try {
el.pause();
el.currentTime = 0;
} catch {
/* ignore */
}
}
}
});

View File

@ -21,7 +21,7 @@
import { Capacitor } from '@capacitor/core';
import { ref, onMounted } from 'vue';
import { useRouter } from 'vue-router';
import { format } from 'silly-datetime';
const showHelp = ref(true);
const router = useRouter();
const start = () => {
@ -147,12 +147,40 @@ onMounted(async () => {
// router.push('/step4');
return;
}
try {
const now =
typeof performance !== 'undefined' && typeof performance.now === 'function'
? () => performance.now()
: () => Date.now();
const t0 = now();
const tBlob0 = now();
const blob = await videoUrlToBlob(videoPath);
const tBlob1 = now();
const tDataUrl0 = now();
const dataUrl = await blobToDataUrl(blob);
const tDataUrl1 = now();
const tArk0 = now();
const result = await analyzeVideoWithArk(dataUrl);
const tArk1 = now();
sessionStorage.setItem('step2_ark_result', JSON.stringify(result));
const tSave = now();
const timing = {
total_ms: Math.round(tSave - t0),
steps_ms: {
videoUrlToBlob: Math.round(tBlob1 - tBlob0),
blobToDataUrl: Math.round(tDataUrl1 - tDataUrl0),
analyzeVideoWithArk: Math.round(tArk1 - tArk0),
saveResult: Math.round(tSave - tArk1)
}
};
sessionStorage.setItem('step3_timing', JSON.stringify(timing));
router.push('/step4');
} catch (e: any) {
console.error(e);
@ -161,7 +189,7 @@ onMounted(async () => {
}
// / step4
});
</script>
@ -233,6 +261,7 @@ onMounted(async () => {
align-items: center;
justify-content: center;
gap: 10px;
.tips-icon {
width: 32px;
height: 32px;
@ -250,6 +279,7 @@ onMounted(async () => {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}

View File

@ -47,12 +47,13 @@
</div>
<div class="r" @click="router.replace('/')"><img src="@/assets/close.png" alt=""></div>
</div>
<div class="main">
<div v-html="summaryText" class="summary-text"> </div>
<!-- <div class="main">
<img class="tips" src="@/assets/step5/tips.png" alt="">
<img class="ip" src="@/assets/step1/ip.png" alt="">
</div>
<div class="info">
</div> -->
<!-- <div class="info">
<div class="title">以下是你的心理压力指数MSI指标</div>
<div class="msi-card">
<div class="msi-score">
@ -84,7 +85,7 @@
</p>
<p> 适度参与户外活动如散步慢跑瑜伽每周 2-3 每次 30 分钟以上通过运动释放负面情绪提升身心愉悦感</p>
</div>
</div>
</div> -->
</div>
</Transition>
</div>
@ -139,7 +140,7 @@ if (arkResult) {
// console.log(summaryText.value); //
data.value = JSON.parse(result?.output[1]?.content[0]?.text);
creatTime.value = format(new Date(result.created_at ? result.created_at * 1000 : new Date()), 'YYYY-MM-DD HH:mm:ss')
summaryText.value = data.value?.brief_report?.summary_text;
list1.value = [
{
type: 4 as const,
@ -363,7 +364,7 @@ if (arkResult) {
.l {
position: absolute;
width: 155px;
width: 168px;
top: 125px;
left: -222px;
display: flex;
@ -374,7 +375,7 @@ if (arkResult) {
.r {
position: absolute;
width: 155px;
width: 168px;
top: 125px;
right: -222px;
display: flex;
@ -399,9 +400,6 @@ if (arkResult) {
padding: 0 24px;
box-sizing: border-box;
}
}
/* 详情页(原 step5的样式直接复用 */
@ -409,7 +407,7 @@ if (arkResult) {
padding-top: 52px;
display: flex;
flex-direction: column;
justify-content: space-between;
// justify-content: space-between;
.top {
position: relative;
@ -583,6 +581,9 @@ if (arkResult) {
}
}
}
.summary-text{
padding: 50px;
}
}
/* 内部切换动画:上下滑 + 淡入淡出(支持正/反向) */