第一版本
This commit is contained in:
parent
1c69d38cee
commit
4b9f936347
Binary file not shown.
Binary file not shown.
@ -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
4
src/types/silly-datetime.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
declare module 'silly-datetime' {
|
||||
export function format(date: Date | number | string, pattern?: string): string;
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/* 内部切换动画:上下滑 + 淡入淡出(支持正/反向) */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user