home.ts 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054
  1. import PageContainerBehavior from "../../core/behavior/page-container.behavior";
  2. import I18nBehavior from "../../i18n/behavior";
  3. import {
  4. DraggableSheetBehavior,
  5. getDraggableSheetContext,
  6. } from "../../core/behavior/draggableSheet.behavior";
  7. import { login } from "../../lib/logic";
  8. import { useRouteQuery } from "../../utils/route-query";
  9. import { appUpdate } from "../../lib/wx/update";
  10. import { addPatientOnlineRecordClockIn } from "./request";
  11. import { Get } from "../../lib/request/method";
  12. const { shared, Easing, timing } = wx.worklet;
  13. const offset = shared(0);
  14. const menus = ["shareAppMessage", "shareTimeline"];
  15. // pages/home/home.ts
  16. import {
  17. getPatients,
  18. healthReportMethod,
  19. healthIndexMethod,
  20. getSolarTerms,
  21. getShortScienceList,
  22. getPatientDescription,
  23. getNotDealLists,
  24. getCareList,
  25. } from "./request";
  26. import { toCertificationPage, toChats } from "./router";
  27. import { Post } from "../../lib/request/method";
  28. // import { useLocation } from "../../lib/use/use-location";
  29. Page({
  30. data: {
  31. i18n: {
  32. common: { title: '生活助理', zy: '' },
  33. home: { analysis: '评估', consult: '聊天', __showRecord__: false, __showDisplay__: false },
  34. report: { title: '报告' },
  35. healthTeach: { title: '' },
  36. },
  37. NoteTitle: "",
  38. isShowComplete: true,
  39. careList: [],
  40. displayList: [] as {
  41. id: number;
  42. conditioningProgramType: string;
  43. operateBy?: string;
  44. operateTime: string;
  45. frequencyType: string; // 频次类型
  46. frequencyMeasure: string; // 总用量
  47. arrangeDate: string; // 下一次开始日期
  48. finishCount: number; // 完成量
  49. conditioningProgramName: string; // 调养计划名称
  50. conditioningProgramSupplierName: string; // 调养计划供应商名称
  51. expanded: boolean;
  52. }[],
  53. allExpanded: false,
  54. fixedHeight: "370rpx",
  55. tabbarValue: "/pages/home/home",
  56. tabbarHidden: false,
  57. pageHeight: "100vh", // 默认值
  58. popupList: [] as AnyArray,
  59. isShowPopup: false,
  60. isCompleting: false, // 防止重复点击标志
  61. patients: [] as (App.Patient.Model & { isDefault: "Y" | "N" })[],
  62. patient: null as App.Patient.Model | null,
  63. patientDescription: "",
  64. healthId: "",
  65. healthReport: { data: null, message: "", loading: true },
  66. healthIndex: { data: [], message: "" },
  67. position: {} as AnyObject,
  68. location: {} as AnyObject,
  69. solarTerms: {} as AnyObject,
  70. sheet: false,
  71. scienceList: [] as AnyArray,
  72. leftColumnList: [] as AnyArray,
  73. rightColumnList: [] as AnyArray,
  74. scienceListPage: 1,
  75. scienceListSize: 10,
  76. scienceListTotal: 0,
  77. scienceListLoading: false,
  78. scienceListHasMore: true,
  79. refreshing: false,
  80. _loaded: false,
  81. statusList: [] as AnyArray,
  82. switchType: "",
  83. carouselLoading: {} as Record<string | number, boolean>,
  84. carouselMediaList: [] as Array<{
  85. type: "image" | "video";
  86. src: string;
  87. }>,
  88. // 是否在咨询中
  89. isConsulting: false,
  90. // 是否有新消息
  91. hasNewMessage: false,
  92. },
  93. behaviors: [
  94. I18nBehavior,
  95. PageContainerBehavior,
  96. DraggableSheetBehavior(".draggable-sheet-wrapper"),
  97. ],
  98. async getCareLists() {
  99. const currentExpandedStates = this.data.displayList.map((item: any) => ({
  100. id: item.id,
  101. expanded: item.expanded,
  102. }));
  103. const res = await getCareList();
  104. if (res && res.length > 0) {
  105. res.forEach((item: any) => {
  106. item.carouselMediaList = [];
  107. // 添加photo
  108. if (item.photo) {
  109. item.carouselMediaList.push({
  110. type: "image",
  111. src: item.photo,
  112. });
  113. }
  114. // 添加itemImgFirst
  115. if (item?.itemImgFirst) {
  116. item.carouselMediaList.push({
  117. type: "image",
  118. src: item.itemImgFirst,
  119. });
  120. }
  121. // 添加itemVideoFirst
  122. if (item?.itemVideoFirst) {
  123. item.carouselMediaList.push({
  124. type: "video",
  125. src: item.itemVideoFirst,
  126. });
  127. }
  128. });
  129. // 先设置 careList
  130. this.setData({
  131. careList: res,
  132. });
  133. await this.updateDisplayList(currentExpandedStates);
  134. setTimeout(() => {
  135. res.forEach((item: any, index: number) => {
  136. if (item.carouselMediaList && item.carouselMediaList.length > 0) {
  137. this.setData({
  138. [`careList[${index}].carouselMediaList`]: [
  139. ...item.carouselMediaList,
  140. ],
  141. });
  142. // 同时更新 displayList
  143. const displayIndex = this.data.displayList.findIndex(
  144. (displayItem: any) => displayItem.id === item.id
  145. );
  146. if (displayIndex !== -1) {
  147. this.setData({
  148. [`displayList[${displayIndex}].carouselMediaList`]: [
  149. ...item.carouselMediaList,
  150. ],
  151. });
  152. }
  153. }
  154. });
  155. }, 100);
  156. }
  157. },
  158. async onLoad(options) {
  159. appUpdate();
  160. const query = useRouteQuery(options.scene!);
  161. if (query.ys) wx.setStorageSync("doctorId", query.ys);
  162. if (options.scene) wx.setStorageSync("scene", options.scene);
  163. this.initFabAnimated();
  164. if (options.switchType) {
  165. this.setData({
  166. switchType: options.switchType,
  167. });
  168. }
  169. },
  170. async onShow() {
  171. wx.showShareMenu({ withShareTicket: true, menus }).then();
  172. await this.load();
  173. // 如果是从一体机扫码进来的 有switchType值就直接跳转到注册页面
  174. if (
  175. this.data.switchType &&
  176. ((this.data.patient as any)?.isPerfectInfo ?? true)
  177. ) {
  178. wx.navigateTo({
  179. url: "/module/user/pages/user-certification/user-certification?type=home",
  180. });
  181. }
  182. // 检查咨询状态
  183. this.checkConsultationStatus();
  184. // 如果用户没有手机号每次进入页面都提示 点击跳到注册页补充
  185. // todo 要先判断用户有没有手机号 isPerfectInfo是true 就出来弹窗提示用户
  186. // if ((this.data.patient as any)?.isPerfectInfo ?? true) {
  187. // wx.showModal({
  188. // title: "提示",
  189. // content: "手机号为空,请补充",
  190. // success: (res) => {
  191. // if (res.confirm) {
  192. // wx.navigateTo({
  193. // url: "/module/user/pages/user-certification/user-certification?type=home",
  194. // });
  195. // }
  196. // },
  197. // });
  198. // }
  199. },
  200. onHide() {
  201. wx.hideShareMenu({ menus }).then();
  202. offset.value = timing(
  203. 0,
  204. { duration: 100, easing: (<any>Easing).linear },
  205. () => {
  206. "worklet";
  207. }
  208. );
  209. },
  210. onShareAppMessage(_opts): WechatMiniprogram.Page.ICustomShareContent {
  211. return {
  212. title: `健康为基,从容赏生活之美`,
  213. imageUrl: `https://wx.hzliuzhi.com/media/healthManager/wx/share.jpg`,
  214. path: `/pages/home/home`,
  215. };
  216. },
  217. onShareTimeline() {
  218. return {
  219. title: `健康为基,从容赏生活之美`,
  220. };
  221. },
  222. async updateDisplayList(
  223. preserveExpandedStates?: Array<{
  224. id: number;
  225. expanded: boolean;
  226. }>
  227. ) {
  228. const { careList, allExpanded } = this.data;
  229. console.log(careList, "careList")
  230. let newDisplayList: any[] =
  231. allExpanded || careList.length <= 4 ? careList : careList.slice(0, 4);
  232. // 如果有保存的展开状态,则恢复它们
  233. if (preserveExpandedStates && preserveExpandedStates.length > 0) {
  234. newDisplayList = newDisplayList.map((item: any) => {
  235. const savedState = preserveExpandedStates.find(
  236. (state) => state.id === item.id
  237. );
  238. if (savedState) {
  239. return {
  240. ...item,
  241. expanded: savedState.expanded,
  242. };
  243. }
  244. return item;
  245. });
  246. }
  247. this.setData({
  248. displayList: newDisplayList,
  249. });
  250. console.log(this.data.displayList, "this.data.displayList11111")
  251. },
  252. toggleAll() {
  253. this.setData(
  254. { allExpanded: !this.data.allExpanded },
  255. this.updateDisplayList
  256. );
  257. },
  258. toggleItem(e: any) {
  259. const index = e.currentTarget.dataset.index;
  260. const key = `displayList[${index}].expanded`;
  261. this.setData({ [key]: !this.data.displayList[index].expanded });
  262. },
  263. // 核销记录
  264. onRecord(e: any) {
  265. const id = e.currentTarget.dataset.id;
  266. if (id) {
  267. wx.navigateTo({
  268. url: `/module/care/pages/care/verifyRecord?id=${id}`,
  269. });
  270. } else {
  271. wx.showToast({
  272. title: "暂无核销记录",
  273. icon: "none",
  274. });
  275. }
  276. },
  277. // 去预约
  278. onAppointment(e: any) {
  279. const id = e.currentTarget.dataset.id;
  280. if (id) {
  281. wx.navigateTo({
  282. url: `/module/care/pages/offlineTreatment/offlineTreatment?id=${id}`,
  283. });
  284. }
  285. },
  286. // 长按复制机构名称
  287. onCopyInstitutionName(e: any) {
  288. const name = e.currentTarget.dataset.name;
  289. if (name) {
  290. wx.setClipboardData({
  291. data: name,
  292. success: () => wx.showToast({ title: "已复制", icon: "none" }),
  293. });
  294. }
  295. },
  296. onClose() {
  297. this.setData({
  298. isShowPopup: false,
  299. });
  300. },
  301. // 打卡
  302. pushCard(e: any) {
  303. const id = e.currentTarget.dataset.id;
  304. wx.navigateTo({
  305. url: `/module/article/pages/punch-card/punch-card?id=${id}`,
  306. });
  307. },
  308. calculatePageHeight() {
  309. const systemInfo = wx.getSystemInfoSync();
  310. const windowHeight = systemInfo.windowHeight; // 屏幕可用高度
  311. // 获取 tabbar 高度
  312. const query = wx.createSelectorQuery();
  313. query
  314. .select(".t-tabbar")
  315. .boundingClientRect((rect) => {
  316. if (rect) {
  317. const tabbarHeight = rect.height;
  318. const contentHeight = windowHeight - tabbarHeight;
  319. this.setData({
  320. pageHeight: `${contentHeight}px`,
  321. });
  322. }
  323. })
  324. .exec();
  325. },
  326. getNotDealList() {
  327. getNotDealLists().then((res) => {
  328. if (res.length > 0) {
  329. this.setData({
  330. popupList: res,
  331. isShowPopup: true,
  332. NoteTitle: res[0].title,
  333. });
  334. } else {
  335. this.setData({
  336. popupList: [],
  337. isShowPopup: false,
  338. NoteTitle: "",
  339. });
  340. }
  341. });
  342. },
  343. showFollowPopup() {
  344. this.getNotDealList();
  345. },
  346. onVisibleChange(e: { detail: { visible: any } }) {
  347. this.setData({
  348. isShowPopup: e.detail.visible,
  349. });
  350. },
  351. async goComplete(e: {
  352. currentTarget: { dataset: { page: string; id: number; title: string } };
  353. }) {
  354. if (this.data.isCompleting) {
  355. return;
  356. }
  357. this.setData({ isCompleting: true });
  358. try {
  359. const { title } = e.currentTarget.dataset;
  360. let page = e.currentTarget.dataset.page;
  361. let id = e.currentTarget.dataset.id;
  362. if (page === "/module/chats/pages/index/index") {
  363. if (title === "健康评估") {
  364. wx.setStorageSync("isAnalysis", 4);
  365. toChats("questionnaire", 2);
  366. } else {
  367. wx.setStorageSync("isAnalysis", 2);
  368. wx.setStorageSync("workId", id);
  369. wx.navigateTo({
  370. url: `${page}?component=questionnaire&messageType=1&id=${id}`,
  371. });
  372. }
  373. } else if (page === "/module/article/pages/science-info/science-info") {
  374. try {
  375. const res = await Get(`/psarticle/clickPsaNotice`, {
  376. params: { noticeSendRecordId: id },
  377. });
  378. const url = res?.data;
  379. const item = {
  380. url,
  381. };
  382. wx.navigateTo({
  383. url: `${page}`,
  384. }).then((res) => {
  385. res.eventChannel.emit("load", item);
  386. });
  387. } catch (error) {
  388. console.log(error);
  389. }
  390. } else {
  391. const status = 'pending';
  392. // 随访
  393. wx.navigateTo({ url: `${page}?id=${id}&status=${status}` });
  394. }
  395. } finally {
  396. setTimeout(() => {
  397. this.setData({ isCompleting: false });
  398. }, 500);
  399. }
  400. },
  401. // 随访评估报告已出
  402. goSeeFollowReport() {
  403. wx.navigateTo({ url: "/module/follow/pages/evaluation/report" });
  404. },
  405. async load(forceLogin = false) {
  406. try {
  407. await login(forceLogin);
  408. wx.showLoading({ title: "加载中" });
  409. const { patient } = await getPatients(/*this.data.patientId*/);
  410. // if (!patient) await toCertificationPage();
  411. if (!patient) {
  412. /*if (wx.getStorageSync("doctorId")) {
  413. toCertificationPage();
  414. }*/
  415. this.setData({
  416. "healthReport.loading": false,
  417. isShowComplete: true,
  418. });
  419. } else {
  420. this.setData({ patient });
  421. this.observerPatient(patient);
  422. }
  423. wx.hideLoading();
  424. } catch (error: any) {
  425. await wx
  426. .showModal({
  427. title: `加载失败`,
  428. content: `${error?.errMsg ?? error?.message ?? ""}`,
  429. showCancel: false,
  430. confirmText: `重新加载`,
  431. })
  432. .catch(() => { });
  433. await this.load(true);
  434. return;
  435. }
  436. // 加载健康宣教的文章
  437. this.loadScienceList(true);
  438. if (!this.data._loaded) {
  439. getSolarTerms()
  440. .then((solarTerms) => {
  441. this.setData({ solarTerms });
  442. })
  443. .catch(() => { });
  444. this.setData({ _loaded: true });
  445. }
  446. },
  447. async _getHealthReport() {
  448. wx.showLoading({ title: "加载中" });
  449. this.setData({ "healthReport.loading": true });
  450. try {
  451. const data = await healthReportMethod();
  452. if (!data) {
  453. this.setData({
  454. isShowComplete: true,
  455. });
  456. } else {
  457. this.setData({
  458. isShowComplete: false,
  459. });
  460. }
  461. this.setData({
  462. "healthReport.data": data,
  463. "healthReport.loading": false,
  464. healthId: data?.healthAnalysisReportId,
  465. });
  466. let arr2 = [
  467. [
  468. {
  469. title: "健康状态",
  470. value: data?.willillStateName ? `${data?.willillStateName}` : "",
  471. },
  472. {
  473. title: "程度",
  474. value: data?.willillDegreeName ? `${data?.willillDegreeName}` : "",
  475. },
  476. {
  477. title: "表现",
  478. value: data?.willillFunctionName
  479. ? `${data?.willillFunctionName}`
  480. : "",
  481. },
  482. ],
  483. [
  484. {
  485. title: "中医证素",
  486. value: data?.factorItemSummary ? `${data?.factorItemSummary}` : "",
  487. },
  488. ],
  489. [
  490. {
  491. title: "体质",
  492. value: data?.constitutionGroupName
  493. ? `${data?.constitutionGroupName}`
  494. : "",
  495. },
  496. ],
  497. ];
  498. this.setData({
  499. statusList: arr2,
  500. });
  501. } catch (error: any) {
  502. wx.showToast({
  503. title: error.errMsg || "加载失败",
  504. icon: "none",
  505. });
  506. this.setData({
  507. "healthReport.data": [],
  508. "healthReport.loading": false,
  509. "healthReport.message": error.errMsg,
  510. healthId: "",
  511. });
  512. }
  513. wx.hideLoading();
  514. },
  515. async _getAbnormalHealthIndex() {
  516. this.setData({ "healthIndex.loading": true });
  517. try {
  518. const data = await healthIndexMethod();
  519. this.setData({
  520. "healthIndex.data": data
  521. .map((item: AnyObject) => item.abnormalDesc)
  522. .filter(Boolean),
  523. "healthIndex.loading": false,
  524. });
  525. } catch (error: any) {
  526. this.setData({
  527. "healthIndex.data": [],
  528. "healthIndex.loading": false,
  529. "healthIndex.message": error.errMsg,
  530. });
  531. }
  532. },
  533. onBodyModel(event: WechatMiniprogram.TouchEvent) {
  534. if (event.detail?.position === "LB") {
  535. this.toReportPage();
  536. } else if (event.detail?.position === "item0") {
  537. const report = this.data.healthReport.data as unknown as AnyObject;
  538. this.setData({
  539. position: {
  540. LT: [
  541. "willillState",
  542. "willillDegree",
  543. "willillSocial",
  544. "willillFunction",
  545. ]
  546. .map((key) => {
  547. const title = report[`${key}Name`];
  548. const description = report[`${key}Description`];
  549. return title || description ? { title, description } : null;
  550. })
  551. .filter(Boolean),
  552. },
  553. });
  554. this.showDraggableSheet();
  555. } else if (event.detail?.position === "item2") {
  556. const report = this.data.healthReport.data as unknown as AnyObject;
  557. const get = (key: string) => ({ [key]: report[key] });
  558. this.setData({
  559. position: {
  560. RT: {
  561. ...get("constitutionGroupName"),
  562. ...get("constitutionGroupDefinition"),
  563. ...get("faceImg"),
  564. ...get("faceAnalysisResult"),
  565. ...get("tongueAnalysisResult"),
  566. ...get("upImg"),
  567. ...get("downImg"),
  568. },
  569. },
  570. });
  571. this.showDraggableSheet();
  572. } else if (event.detail?.position === "item1") {
  573. const report = this.data.healthReport.data as unknown as AnyObject;
  574. const get = (key: string) => ({ [key]: report[key] });
  575. this.setData({
  576. position: {
  577. RB: {
  578. ...get("diagnoseSyndromeSummary"),
  579. ...get("diagnoseSyndromes"),
  580. ...get("factorItemSummary"),
  581. ...get("factorItems"),
  582. },
  583. },
  584. });
  585. this.showDraggableSheet();
  586. } else if (event.detail?.position === "CT") {
  587. this.setData({
  588. position: {
  589. CT: this.data.healthIndex.data.map(
  590. (item, index) => `${index + 1}、${item}`
  591. ),
  592. },
  593. });
  594. this.showDraggableSheet();
  595. }
  596. },
  597. tabValue() {
  598. this.setData({
  599. position: {
  600. CT: this.data.healthIndex.data.map(
  601. (item, index) => `${index + 1}、${item}`
  602. ),
  603. },
  604. });
  605. this.showDraggableSheet();
  606. },
  607. initFabAnimated() {
  608. (<any>this).applyAnimatedStyle(".fab-wrapper", () => {
  609. "worklet";
  610. return { right: `${Math.min(offset.value, 36) - 36}px` };
  611. });
  612. (<any>this).applyAnimatedStyle(".fab-1", () => {
  613. "worklet";
  614. return { transform: `translateY(${-offset.value}px)` };
  615. });
  616. (<any>this).applyAnimatedStyle(".fab-2", () => {
  617. "worklet";
  618. return {
  619. transform: `translateX(${-offset.value}px) translateY(${-offset.value / 2
  620. }px)`,
  621. };
  622. });
  623. (<any>this).applyAnimatedStyle(".fab-3", () => {
  624. "worklet";
  625. return {
  626. transform: `translateX(${-offset.value}px) translateY(${offset.value / 2
  627. }px)`,
  628. };
  629. });
  630. (<any>this).applyAnimatedStyle(".fab-4", () => {
  631. "worklet";
  632. return { transform: `translateY(${offset.value}px)` };
  633. });
  634. },
  635. onFabTap() {
  636. const value = Math.abs(offset.value - 72);
  637. offset.value = timing(
  638. value,
  639. { duration: 500, easing: (<any>Easing).linear },
  640. () => {
  641. "worklet";
  642. if (offset.value > 0) offset.value = 72;
  643. }
  644. );
  645. },
  646. async toChatsPage() {
  647. if (!this.data.patient?.patientId) {
  648. try {
  649. await this.load();
  650. } catch (error: any) {
  651. wx.showModal({
  652. title: "出错了",
  653. content: error?.errMsg ?? error?.message ?? "错误,请重试",
  654. showCancel: false,
  655. });
  656. return;
  657. }
  658. }
  659. const page = "/module/chats/pages/index/index";
  660. wx.navigateTo({
  661. url: `${page}?component=guide&isShowGuide=true`,
  662. });
  663. wx.setStorageSync("isAnalysis", 3);
  664. },
  665. toSciencePage() {
  666. wx.navigateTo({ url: `/module/article/pages/science-list/science-list` });
  667. },
  668. async toReportPage() {
  669. // const { patient } = await getPatients(/*this.data.patientId*/);
  670. if (!this.data.patient) await toCertificationPage();
  671. else {
  672. const id = this.data.healthId;
  673. if (id)
  674. wx.navigateTo({ url: `/module/health/pages/report/report?id=${id}` });
  675. else wx.showToast({ title: "暂无分析报告", icon: "none" });
  676. }
  677. },
  678. onDraggableSizeUpdate(e: any) {
  679. "worklet";
  680. if (e.pixels < 1) {
  681. wx.worklet.runOnJS(this.hideDraggableSheet.bind(this))();
  682. }
  683. },
  684. showDraggableSheet() {
  685. getDraggableSheetContext.call(this).scrollTo({
  686. size: 0.5,
  687. pixels: 600,
  688. animated: true,
  689. duration: 300,
  690. easingFunction: "ease",
  691. });
  692. this.setData({ sheet: true });
  693. },
  694. hideDraggableSheet(event?: any) {
  695. if (event) {
  696. getDraggableSheetContext.call(this).scrollTo({
  697. size: 0,
  698. animated: true,
  699. duration: 300,
  700. easingFunction: "ease",
  701. });
  702. }
  703. this.setData({ position: {}, sheet: false });
  704. },
  705. async loadScienceList(reset = false) {
  706. if (this.data.scienceListLoading) {
  707. return;
  708. }
  709. if (!reset && !this.data.scienceListHasMore) {
  710. return;
  711. }
  712. if (reset) {
  713. this.setData({
  714. scienceListPage: 1,
  715. scienceListHasMore: true,
  716. scienceList: [],
  717. leftColumnList: [],
  718. rightColumnList: [],
  719. });
  720. }
  721. this.setData({ scienceListLoading: true });
  722. try {
  723. const page = reset ? 1 : this.data.scienceListPage;
  724. const {
  725. data,
  726. total,
  727. page: currentPage,
  728. } = await getShortScienceList(page, this.data.scienceListSize);
  729. const newList = reset ? data : [...this.data.scienceList, ...data];
  730. const hasMore = newList.length < total;
  731. this.setData({
  732. scienceList: newList,
  733. scienceListTotal: total,
  734. scienceListPage: currentPage + 1,
  735. scienceListHasMore: hasMore,
  736. scienceListLoading: false,
  737. });
  738. this.distributeCardsToColumns(newList, reset);
  739. } catch (error) {
  740. this.setData({ scienceListLoading: false });
  741. wx.showToast({
  742. title: "加载失败,请重试",
  743. icon: "none",
  744. });
  745. }
  746. },
  747. // 下拉刷新
  748. async onRefreshScienceList() {
  749. this.setData({ refreshing: true });
  750. await this.loadScienceList(true);
  751. this.setData({ refreshing: false });
  752. },
  753. // 上拉加载更多
  754. onLoadMoreScienceList() {
  755. if (this.data.scienceListHasMore && !this.data.scienceListLoading) {
  756. this.loadScienceList(false);
  757. }
  758. },
  759. // 将卡片分配到两列,实现瀑布流布局
  760. distributeCardsToColumns(list: AnyArray, reset = false) {
  761. // 如果是重置,使用空数组;否则过滤出新增的卡片
  762. const itemsToDistribute = reset
  763. ? list
  764. : list.filter(
  765. (item: any) =>
  766. !this.data.leftColumnList.some(
  767. (existing: any) => existing.id === item.id
  768. ) &&
  769. !this.data.rightColumnList.some(
  770. (existing: any) => existing.id === item.id
  771. )
  772. );
  773. if (itemsToDistribute.length === 0) return;
  774. // 计算当前两列的高度(重置时两列已为空,高度为0)
  775. let leftHeight = reset
  776. ? 0
  777. : this.data.leftColumnList.reduce(
  778. (sum: number, item: any) => sum + this.estimateCardHeight(item),
  779. 0
  780. );
  781. let rightHeight = reset
  782. ? 0
  783. : this.data.rightColumnList.reduce(
  784. (sum: number, item: any) => sum + this.estimateCardHeight(item),
  785. 0
  786. );
  787. const leftColumn = reset ? [] : [...this.data.leftColumnList];
  788. const rightColumn = reset ? [] : [...this.data.rightColumnList];
  789. itemsToDistribute.forEach((item: any) => {
  790. const estimatedHeight = this.estimateCardHeight(item);
  791. if (leftHeight <= rightHeight) {
  792. leftColumn.push(item);
  793. leftHeight += estimatedHeight;
  794. } else {
  795. rightColumn.push(item);
  796. rightHeight += estimatedHeight;
  797. }
  798. });
  799. this.setData({
  800. leftColumnList: leftColumn,
  801. rightColumnList: rightColumn,
  802. });
  803. },
  804. estimateCardHeight(item: any): number {
  805. let height = 0;
  806. if (item.briefImg) {
  807. const imgMinHeight = 120;
  808. const imgMaxHeight = 260;
  809. const imgHeightRange = imgMaxHeight - imgMinHeight;
  810. const idHash = item.id
  811. ? String(item.id)
  812. .split("")
  813. .reduce((acc: number, char: string) => acc + char.charCodeAt(0), 0)
  814. : 0;
  815. const imgHeight = imgMinHeight + (idHash % imgHeightRange);
  816. height += imgHeight;
  817. }
  818. const title = item.title || "";
  819. const titleLength = title.length;
  820. const charsPerLine = 12;
  821. const titleLines = Math.min(Math.ceil(titleLength / charsPerLine), 3);
  822. const titleHeight = titleLines * 24;
  823. const contentPadding = 24;
  824. const metaHeight = 40;
  825. height += titleHeight + contentPadding + metaHeight;
  826. height += 12;
  827. height += 4;
  828. if (!item.briefImg) {
  829. const minContentHeight =
  830. titleHeight + contentPadding + metaHeight + 12 + 4;
  831. if (height < minContentHeight) {
  832. height = minContentHeight;
  833. }
  834. }
  835. return Math.round(height);
  836. },
  837. observerPatient(model: { patientId: string; sex: "0" | "1" }) {
  838. wx.setStorageSync("patientId", model.patientId);
  839. this._getHealthReport();
  840. this._getAbnormalHealthIndex();
  841. const patientIcon = { 0: "gender-male", 1: "gender-female" }[model.sex];
  842. const patientIconColor = { 0: "#0f40f5", 1: "#E560B3" }[model.sex];
  843. this.setData({ patientIcon, patientIconColor });
  844. getPatientDescription(model).then((patientDescription) => {
  845. this.setData({ patientDescription });
  846. });
  847. // 获取未处理随访列表
  848. this.getNotDealList();
  849. // 获取调养计划
  850. this.getCareLists();
  851. },
  852. // 没有健康分析去做健康分析
  853. goHealthAnalyze() {
  854. wx.redirectTo({
  855. url: `/module/chats/pages/index/index?component=guide&isShowGuide=true`,
  856. });
  857. wx.setStorageSync("showGuideActive", 1);
  858. wx.setStorageSync("isAnalysis", 3);
  859. },
  860. // 检查咨询状态
  861. async checkConsultationStatus() {
  862. //获取正在咨询中的咨询id
  863. const res = await Post("/consultManage/getConsultIng");
  864. const isConsulting = !!res.data?.id;
  865. const hasNewMessage = res.data?.patientUnreadCount > 0;
  866. // 是否有新消息
  867. this.setData({ hasNewMessage });
  868. if (isConsulting) {
  869. // 保存咨询id,标记咨询未结束
  870. wx.setStorageSync("consultId", res.data);
  871. wx.setStorageSync("consultEnded", false);
  872. this.setData({
  873. isConsulting: true,
  874. });
  875. } else {
  876. // 没有咨询,清理相关数据
  877. wx.setStorageSync("consultEnded", true);
  878. wx.removeStorageSync("consultId");
  879. this.setData({
  880. isConsulting: false,
  881. hasNewMessage: false,
  882. });
  883. }
  884. },
  885. // 跳转到咨询页面
  886. goToConsultation() {
  887. // 跳转之后 未读的消息变为已读 就没有最新消息了 不显示绿点
  888. this.setData({ hasNewMessage: false });
  889. // 跳转到咨询页面,显示 message-consult 组件
  890. wx.navigateTo({
  891. url: `/module/chats/pages/index/index?component=questionnaire&messageType=3`,
  892. });
  893. wx.setStorageSync("isAnalysis", 5);
  894. },
  895. async isGoPunchcard(e: any) {
  896. const { id, signintime } = e.currentTarget.dataset;
  897. // 已经打卡了
  898. if (signintime) {
  899. // 已打卡 跳转到打卡页面
  900. wx.navigateTo({
  901. url: `/module/article/pages/punch-card/punch-card?id=${id}`,
  902. });
  903. } else {
  904. // 打卡
  905. const cardId = e.currentTarget.dataset.id;
  906. await addPatientOnlineRecordClockIn(cardId);
  907. wx.showToast({
  908. title: "打卡成功",
  909. icon: "success",
  910. duration: 1500,
  911. });
  912. await this.refreshCareListsWithState();
  913. }
  914. },
  915. async refreshCareListsWithState() {
  916. // 保存当前的展开状态
  917. const currentExpandedStates = this.data.displayList.map((item: any) => ({
  918. id: item.id,
  919. expanded: item.expanded,
  920. carouselMediaList: item.carouselMediaList,
  921. }));
  922. // 获取新数据
  923. const res = await getCareList();
  924. if (res && res.length > 0) {
  925. res.forEach((item: any) => {
  926. const oldItem = currentExpandedStates.find(
  927. (state) => state.id === item.id
  928. );
  929. if (oldItem && oldItem.carouselMediaList) {
  930. item.carouselMediaList = oldItem.carouselMediaList;
  931. } else {
  932. item.carouselMediaList = [];
  933. // 添加photo
  934. if (item.photo) {
  935. item.carouselMediaList.push({
  936. type: "image",
  937. src: item.photo,
  938. });
  939. }
  940. // 添加itemImgFirst
  941. if (item?.itemImgFirst) {
  942. item.carouselMediaList.push({
  943. type: "image",
  944. src: item.itemImgFirst,
  945. });
  946. }
  947. // 添加itemVideoFirst
  948. if (item?.itemVideoFirst) {
  949. item.carouselMediaList.push({
  950. type: "video",
  951. src: item.itemVideoFirst,
  952. });
  953. }
  954. }
  955. });
  956. // 更新 careList
  957. this.setData({
  958. careList: res,
  959. });
  960. // 更新 displayList 并恢复展开状态
  961. const { allExpanded } = this.data;
  962. let newDisplayList: any[] =
  963. allExpanded || res.length <= 4 ? res : res.slice(0, 4);
  964. // 恢复展开状态
  965. newDisplayList = newDisplayList.map((item: any) => {
  966. const savedState = currentExpandedStates.find(
  967. (state) => state.id === item.id
  968. );
  969. if (savedState) {
  970. return {
  971. ...item,
  972. expanded: savedState.expanded,
  973. carouselMediaList:
  974. savedState.carouselMediaList || item.carouselMediaList,
  975. };
  976. }
  977. return item;
  978. });
  979. this.setData({
  980. displayList: newDisplayList,
  981. });
  982. console.log(this.data.displayList, "this.data.displayList")
  983. }
  984. },
  985. /**
  986. * 轮播组件进入/退出全屏时,隐藏/显示底部 tabbar,防止遮挡视频进度条
  987. */
  988. onCarouselFullscreenChange(e: { detail?: { fullScreen?: boolean } }) {
  989. const fullScreen = !!e.detail?.fullScreen;
  990. this.setData({
  991. tabbarHidden: fullScreen,
  992. });
  993. },
  994. });