transition.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. <template>
  2. <view class="content">
  3. <!-- 个人信息 -->
  4. <view class="blur-bg-2"></view>
  5. <view class="top-btn">
  6. <view class="back x-c" @click="$navBack()">
  7. <image src='/static/image/new/icon_back.svg'></image>
  8. 返回
  9. </view>
  10. <view class="title x-c">
  11. <image src='/static/image/new/img_title1.svg'></image>
  12. <text>脉诊</text>
  13. <image src='/static/image/new/img_title2.svg'></image>
  14. </view>
  15. <view class="index x-c" @click="goIndex">
  16. <image src='/static/image/new/icon_home.svg'></image>
  17. 首页
  18. </view>
  19. </view>
  20. <view class="userBox y-bc">
  21. <view class="tranBox">
  22. <view>引导动画</view>
  23. </view>
  24. <view class="btnBox">
  25. <view class="timer x-c" v-if="status == 'init'|| status == 'disinfecting'">
  26. <image src='/static/image/new/icon_safe.svg'></image>
  27. 一键消毒,安心检测~
  28. </view>
  29. <view class="timer2 y-c" v-if="status == 'fail'">
  30. <image src='/static/image/new/icon_sad.svg'></image>
  31. 采集失败,调整下姿势,再试一试呢
  32. </view>
  33. <view class="timer3 y-c" v-if="status == 'collecting'">
  34. <view class="progress">
  35. <u-line-progress :percentage="30" :showText="false" height="18" inactiveColor="#fff" activeColor="#3CD3AD"></u-line-progress>
  36. </view>
  37. 正在精准采集中...
  38. </view>
  39. <view class="timer4 y-c" v-if="status == 'guide'">
  40. <view class="item x-c">
  41. <image src='/static/image/new/icon_item.svg'></image>
  42. 请将手放在脉诊垫上
  43. </view>
  44. <view class="item x-c">
  45. <image src='/static/image/new/icon_item.svg'></image>
  46. 手腕放松,掌心向上
  47. </view>
  48. </view>
  49. <view class="timer5 y-c" v-if="status == 'sensing'">
  50. <view class="progress">
  51. <u-loading-icon mode="circle" color="#3CD3AD" size="62"></u-loading-icon>
  52. </view>
  53. 正在感知您的脉象 请保持放松
  54. </view>
  55. <view class="btn" @click="toConnect" v-if="status == 'init'">去脉诊</view>
  56. <!-- <view class="btn" @click="start" v-if="status == 'init'">一键消毒</view>
  57. <view class="btn loading-btn" v-if="status == 'disinfecting'">
  58. <u-loading-icon color="#fff" size="48"></u-loading-icon>消毒中
  59. </view>
  60. <view class="btn" @click="restartDetect" v-if="status == 'fail'">重新检测</view> -->
  61. </view>
  62. </view>
  63. <view v-if="isShow" class="mask">
  64. <view class="popup-container">
  65. <image class="bg" src='/static/image/new/bg_popup.svg'></image>
  66. <view class="title-t x-c">
  67. <image src='/static/image/new/img_title1.svg'></image>
  68. <text>提示</text>
  69. <image src='/static/image/new/img_title2.svg'></image>
  70. </view>
  71. <view class="title-r">点击确认查看检测报告</view>
  72. <!-- <image style="width: 200px;height: 200px;margin-bottom: 20px;" :src="qUrl"></image> -->
  73. <view class="x-c">
  74. <!-- <view class="btn-l" @click="close">取消</view> -->
  75. <view class="btn-r" @click="closeP">确认</view>
  76. </view>
  77. </view>
  78. </view>
  79. </view>
  80. </template>
  81. <script>
  82. import {
  83. getUserInfoByUserId,
  84. getUserInfo
  85. } from '@/api/user.js';
  86. import {
  87. addPulse
  88. } from '@/api/healthTongue.js'
  89. export default {
  90. data() {
  91. return {
  92. // 状态:init(初始)/disinfecting(消毒中)/collecting(采集ing)/fail(失败)/guide(引导)
  93. status: 'init',
  94. progressPercent: 0, // 进度条百分比
  95. progressTimer: null ,// 定时器
  96. showProgress: false, // 是否显示进度条
  97. info: null,
  98. // 插件实例
  99. tyPulse: null,
  100. // 状态
  101. initStatus: false,
  102. deviceConnected: false,
  103. measuring: false,
  104. // 设备信息
  105. deviceInfo: null,
  106. // 测量相关
  107. measureProgress: 0,
  108. currentStage: '待机',
  109. lastResult: null,
  110. appId: "nehijR6y",
  111. appSecret: "f740435d1b84b9944a52f064dd1ecf6e8a76f546",
  112. uid: "userid000067",
  113. qUrl: '',
  114. isShow:false,
  115. initData:{},
  116. user:{}
  117. }
  118. },
  119. onLoad(option) {
  120. //this.startCountDown();
  121. this.initPlugin()
  122. },
  123. onShow() {
  124. this.user=JSON.parse(uni.getStorageSync('userInfo'));
  125. // 清除所有定时器,防止内存泄漏
  126. clearInterval(this.progressTimer);
  127. this.progressTimer = null;
  128. },
  129. methods: {
  130. //开始消毒
  131. start() {
  132. this.status = 'disinfecting';
  133. //this.status = 'sensing';
  134. this.showProgress = true;
  135. // 模拟消毒进度
  136. this.progressPercent = 0;
  137. this.progressTimer = setInterval(() => {
  138. if (this.progressPercent >= 100) {
  139. clearInterval(this.progressTimer);
  140. this.progressTimer = null;
  141. // 消毒完成后进入引导状态
  142. this.status = 'guide';
  143. this.showProgress = false;
  144. // 3秒后自动进入脉象感知状态
  145. setTimeout(() => {
  146. this.startSensePulse();
  147. }, 3000);
  148. return;
  149. }
  150. this.progressPercent += 2;
  151. }, 100);
  152. },
  153. /**
  154. * 开始感知脉象
  155. */
  156. startSensePulse() {
  157. this.status = 'sensing';
  158. this.showProgress = false;
  159. // 模拟脉象感知过程(5秒)
  160. setTimeout(() => {
  161. // 感知完成后进入精准采集状态
  162. this.startCollect();
  163. }, 5000);
  164. },
  165. /**
  166. * 开始精准采集
  167. */
  168. startCollect() {
  169. this.status = 'collecting';
  170. this.showProgress = true;
  171. this.progressPercent = 0;
  172. // 模拟采集进度(随机失败/成功)
  173. this.progressTimer = setInterval(() => {
  174. if (this.progressPercent >= 100) {
  175. clearInterval(this.progressTimer);
  176. this.progressTimer = null;
  177. // 随机模拟采集结果(70%成功,30%失败)
  178. const isSuccess = Math.random() > 0.3;
  179. if (isSuccess) {
  180. // 采集成功,跳转到分析页面
  181. //this.goAnalysis();
  182. } else {
  183. // 采集失败
  184. this.status = 'fail';
  185. this.showProgress = false;
  186. }
  187. return;
  188. }
  189. this.progressPercent += 1;
  190. }, 150);
  191. },
  192. //重新检测
  193. restartDetect() {
  194. this.status = 'init';
  195. },
  196. //跳转分析
  197. goAnalysis() {
  198. uni.redirectTo({
  199. url: '/pages/index/loading', // 替换为实际分析页面路径
  200. fail: (err) => {
  201. console.error('跳转失败:', err);
  202. uni.showToast({
  203. title: '跳转失败',
  204. icon: 'none'
  205. });
  206. }
  207. });
  208. },
  209. // 初始化插件
  210. async initPlugin() {
  211. try {
  212. // this.addLog('开始初始化插件...');
  213. // 获取插件实例
  214. this.tyPulse = uni.requireNativePlugin('TyPulseManager');
  215. if (!this.tyPulse) {
  216. throw new Error('无法获取插件实例');
  217. }
  218. // 初始化
  219. await new Promise((resolve, reject) => {
  220. this.tyPulse.initSDK(this.appId, this.appSecret, this.uid, (
  221. result) => {
  222. if (result.success) {
  223. resolve();
  224. } else {
  225. reject(new Error(result.error));
  226. }
  227. });
  228. });
  229. this.initStatus = true;
  230. console.log('插件初始化成功');
  231. // uni.showToast({
  232. // title: '初始化成功',
  233. // icon: 'success'
  234. // });
  235. } catch (error) {
  236. console.log(`初始化失败: ${error.message}`);
  237. uni.showToast({
  238. title: '初始化失败',
  239. icon: 'error'
  240. });
  241. }
  242. },
  243. toMeasure() {
  244. try {
  245. // 设置自动屏幕方向
  246. this.tyPulse.toMeasure((result) => {
  247. if (result.success) {
  248. if (result.cmdType == "pulseResult") {
  249. this.info = result;
  250. console.log('脉诊回调结果:', result);
  251. this.addPulse()
  252. }
  253. if (result.cmdType == "deviceConnect") {
  254. //获取设备信息
  255. this.getDeviceInfo();
  256. }
  257. }
  258. });
  259. } catch (error) {
  260. console.log(`测脉失败: ${error.message}`);
  261. }
  262. },
  263. // 获取设备信息
  264. getDeviceInfo() {
  265. try {
  266. this.tyPulse.getDeviceInfo((result) => {
  267. if (result.success && result.data) {
  268. this.deviceInfo = result.data;
  269. this.deviceConnected = result.data.isConnected;
  270. //console.log('设备信息获取成功:' + JSON.stringify(result.data));
  271. }
  272. });
  273. } catch (error) {
  274. console.log(`获取设备信息失败: ${error.message}`);
  275. }
  276. },
  277. toConnect() {
  278. // if (this.$isEmpty(this.selectUser)) {
  279. // uni.showToast({
  280. // title: '请先选择就诊人',
  281. // icon: 'none'
  282. // });
  283. // return;
  284. // }
  285. this.isConnect = true
  286. this.toMeasure()
  287. },
  288. addPulse() {
  289. if (this.$isEmpty(this.info)) {
  290. uni.showToast({
  291. title: '测量失败,请重试',
  292. icon: 'none'
  293. });
  294. return;
  295. }
  296. const data = {
  297. userId: this.user.fsUserId,
  298. sex: this.user.sex,
  299. name: this.user.username,
  300. pulseEquipmentResult: {
  301. reportData: JSON.parse(this.info.reportData),
  302. success: this.info.success,
  303. measureId: this.info.measureId,
  304. pulseUrl: JSON.parse(this.info.pr)
  305. }
  306. }
  307. console.log("qxj addPulse data",data);
  308. uni.showLoading({
  309. title: "处理中...",
  310. mask: true
  311. })
  312. addPulse(data).then(res => {
  313. console.log('zaizz', data, res)
  314. if (res.code == 200) {
  315. uni.hideLoading();
  316. //this.qUrl = res.codeImage
  317. this.isConnect = false
  318. this.isResult = true
  319. } else {
  320. uni.hideLoading();
  321. this.isConnect = false
  322. this.errMsg = res.msg;
  323. uni.showToast({
  324. icon: 'none',
  325. title: res.msg,
  326. });
  327. }
  328. },
  329. rej => {}
  330. );
  331. },
  332. closeP() {
  333. this.isResult = false
  334. uni.navigateTo({
  335. url: "/pages/user/healthReportOld?userId="+this.user.fsUserId
  336. })
  337. },
  338. //首页
  339. goIndex() {
  340. uni.reLaunch({
  341. url: '/pages/index/index',
  342. animationType: 'none',
  343. animationDuration: 2000
  344. })
  345. },
  346. }
  347. }
  348. </script>
  349. <style scoped lang="scss">
  350. page {
  351. background: #fff;
  352. font-size: 16px
  353. }
  354. /* 遮罩层样式 */
  355. .mask {
  356. position: fixed;
  357. top: 0;
  358. left: 0;
  359. right: 0;
  360. bottom: 0;
  361. background-color: rgba(0, 0, 0, 0.5);
  362. display: flex;
  363. justify-content: center;
  364. align-items: center;
  365. z-index: 999;
  366. animation: fadeIn 0.3s ease;
  367. }
  368. /* 弹窗容器样式 */
  369. .popup-container {
  370. //width: 50%;
  371. width: 620px;
  372. height: 352px;
  373. background: #FFFFFF;
  374. border-radius: 39px 39px 39px 39px;
  375. animation: scaleIn 0.3s ease;
  376. overflow: hidden;
  377. display: flex;
  378. flex-direction: column;
  379. align-items: center;
  380. justify-content: space-between;
  381. padding:43px;
  382. position: relative;
  383. .bg{
  384. width: 100%;
  385. height: 244px;
  386. position: absolute;
  387. top:0
  388. }
  389. .title-t {
  390. image{
  391. width: 153px;
  392. height: 25px;
  393. }
  394. text{
  395. font-family: PingFang SC, PingFang SC;
  396. font-weight: 500;
  397. font-size: 32px;
  398. color: #333333;
  399. margin: 0 10px;
  400. }
  401. }
  402. .title-r {
  403. font-family: PingFang SC, PingFang SC;
  404. font-weight: 400;
  405. font-size: 28px;
  406. color: #333333;
  407. }
  408. .btn-l{
  409. display: flex;
  410. align-items: center;
  411. justify-content: center;
  412. font-family: PingFang SC, PingFang SC;
  413. font-weight: 600;
  414. font-size: 28px;
  415. color: #37C3A0;
  416. width: 220px;
  417. height: 64px;
  418. border-radius: 121px 121px 121px 121px;
  419. border: 2px solid #37C3A0;
  420. margin-right: 40px;
  421. }
  422. .btn-r {
  423. display: flex;
  424. align-items: center;
  425. justify-content: center;
  426. width: 220px;
  427. height: 64px;
  428. background: #37C3A0;
  429. border-radius: 121px 121px 121px 121px;
  430. font-family: PingFang SC, PingFang SC;
  431. font-weight: 600;
  432. font-size: 28px;
  433. color: #FFFFFF;
  434. }
  435. }
  436. .content {
  437. width: 100%;
  438. height: 100vh;
  439. background: #D8F6EF;
  440. padding: 28px;
  441. display: flex;
  442. flex-direction: column;
  443. .blur-bg-2 {
  444. width: 350px;
  445. height: 350px;
  446. background: #FFFDCC;
  447. // opacity: 0.47;
  448. filter: blur(200px);
  449. position: absolute;
  450. z-index: 1;
  451. top: 60px;
  452. right: calc(0px - 107px);
  453. pointer-events: none
  454. }
  455. }
  456. .top-btn {
  457. display: flex;
  458. align-items: center;
  459. justify-content: space-between;
  460. z-index: 2;
  461. .back {
  462. width: 140px;
  463. height: 48px;
  464. background: rgba(255, 255, 255, 0.64);
  465. border-radius: 45px 45px 45px 45px;
  466. border: 2px solid #FFFFFF;
  467. font-family: PingFang SC, PingFang SC;
  468. font-weight: 500;
  469. font-size: 22px;
  470. color: #327E6F;
  471. image {
  472. margin-right: 4px;
  473. width: 24px;
  474. height: 24px;
  475. }
  476. }
  477. .title {
  478. font-family: PingFang SC, PingFang SC;
  479. font-weight: 600;
  480. font-size: 36px;
  481. color: #327E6F;
  482. line-height: 54px;
  483. text {
  484. margin: 0 14px;
  485. }
  486. image {
  487. width: 153px;
  488. height: 25px;
  489. }
  490. }
  491. .index {
  492. width: 140px;
  493. height: 48px;
  494. background: rgba(255, 255, 255, 0.64);
  495. border-radius: 55px 55px 55px 55px;
  496. border: 2px solid #FFFFFF;
  497. font-family: PingFang SC, PingFang SC;
  498. font-weight: 500;
  499. font-size: 22px;
  500. color: #327E6F;
  501. image {
  502. margin-right: 4px;
  503. width: 24px;
  504. height: 24px;
  505. }
  506. }
  507. }
  508. .userBox {
  509. flex: 1;
  510. margin-top: 28px;
  511. background: rgba(255, 255, 255, 0.7);
  512. border-radius: 24px 24px 24px 24px;
  513. padding: 27px 40px;
  514. z-index: 9;
  515. .tranBox {
  516. display: flex;
  517. align-items: center;
  518. flex-direction: column;
  519. justify-content: center;
  520. margin-top: 85px;
  521. width: 727px;
  522. height: 442px;
  523. background: #FFFFFF;
  524. border-radius: 36px 36px 36px 36px;
  525. view {
  526. font-family: PingFang SC, PingFang SC;
  527. font-weight: 600;
  528. font-size: 40px;
  529. color: #7FD7C5;
  530. }
  531. image {
  532. width: 99px;
  533. height: 99px;
  534. }
  535. .title {
  536. margin-top: 42px;
  537. width: 468px;
  538. height: 57px;
  539. line-height: 57px;
  540. text-align: center;
  541. font-family: PingFang SC, PingFang SC;
  542. font-weight: 500;
  543. font-size: 35px;
  544. color: #333333;
  545. background-image: url(/static/image/new/img_cloud.svg);
  546. background-repeat: no-repeat;
  547. position: relative;
  548. background-size: 100% 100%;
  549. }
  550. .text {
  551. margin-top: 11px;
  552. font-family: PingFang SC, PingFang SC;
  553. font-weight: 400;
  554. font-size: 28px;
  555. color: #333333;
  556. }
  557. }
  558. .btnBox {
  559. display: flex;
  560. align-items: center;
  561. flex-direction: column;
  562. .timer {
  563. font-family: PingFang SC, PingFang SC;
  564. font-weight: 400;
  565. font-size: 32px;
  566. color: #333333;
  567. line-height: 72px;
  568. image {
  569. width: 32px;
  570. height: 32px;
  571. margin-right: 20px;
  572. }
  573. }
  574. .timer2 {
  575. font-family: PingFang SC, PingFang SC;
  576. font-weight: 400;
  577. font-size: 28px;
  578. color: #333333;
  579. line-height: 38px;
  580. image {
  581. width: 84px;
  582. height: 84px;
  583. }
  584. }
  585. .timer3 {
  586. font-family: PingFang SC, PingFang SC;
  587. font-weight: 400;
  588. font-size: 28px;
  589. color: #333333;
  590. line-height: 72px;
  591. margin-bottom: 56px;
  592. .progress{
  593. width: 420px;
  594. margin-bottom: 33px;
  595. }
  596. }
  597. .timer4 {
  598. margin-bottom: 60px;
  599. font-family: PingFang SC, PingFang SC;
  600. font-weight: 400;
  601. font-size: 32px;
  602. color: #333333;
  603. line-height: 48px;
  604. .item{
  605. margin-top: 28px;
  606. }
  607. image {
  608. width: 32px;
  609. height: 32px;
  610. margin-right: 30px;
  611. }
  612. }
  613. .timer5 {
  614. margin-bottom: 56px;
  615. font-family: PingFang SC, PingFang SC;
  616. font-weight: 400;
  617. font-size: 28px;
  618. color: #333333;
  619. line-height: 45px;
  620. .progress{
  621. margin-bottom: 32px;
  622. }
  623. }
  624. .btn {
  625. margin-top: 28px;
  626. margin-bottom: 29px;
  627. display: flex;
  628. align-items: center;
  629. justify-content: center;
  630. width: 360px;
  631. height: 68px;
  632. background: #37C3A0;
  633. border-radius: 121px 121px 121px 121px;
  634. font-family: PingFang SC, PingFang SC;
  635. font-weight: 600;
  636. font-size: 28px;
  637. color: #FFFFFF;
  638. transition: all 0.3s;
  639. // 消毒中按钮样式
  640. &.loading-btn {
  641. display: flex;
  642. align-items: center;
  643. justify-content: center;
  644. background: #37C3A0;
  645. opacity: 0.6;
  646. pointer-events: none; // 禁用点击
  647. }
  648. }
  649. }
  650. }
  651. </style>