plan-mixin.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /**
  2. * 方案管理 mixin
  3. * 负责:方案列表加载、子方案选择、模式切换时刷新方案
  4. */
  5. import { getCustomPlanList, getCustomPlanDetail, deleteCustomPlan, getProfessionalPlanList, getProfessionalPlanDetail, getMasterPlanList, getMasterPlanDetail } from '@/utils/api/care.js'
  6. export default {
  7. data() {
  8. return {
  9. planList: [], // 当前模式下的方案列表
  10. selectedPlan: null, // 当前选中的方案 { id, name, description }
  11. isShowPlanDrawer: false, // 方案选择弹窗
  12. planLoading: false
  13. }
  14. },
  15. methods: {
  16. /**
  17. * 切换模式 - 覆盖原始changeMode,加入方案加载逻辑
  18. */
  19. changeMode(mode) {
  20. this.isShowDrawer2 = false
  21. if (this.modeType === mode) return
  22. this.modeType = mode
  23. // 切换模式时重置方案选择
  24. this.selectedPlan = null
  25. this.planList = []
  26. // 非休闲模式加载对应方案列表
  27. if (mode !== 0) {
  28. this.loadPlanList(mode)
  29. }
  30. // 停止音频(休闲模式专属)
  31. if (mode !== 0 && this._stopAudioOnModeChange) {
  32. this._stopAudioOnModeChange()
  33. }
  34. },
  35. /**
  36. * 加载指定模式的方案列表
  37. * @param {Number} mode - 1专业 2自定义 3延年圣手
  38. */
  39. async loadPlanList(mode) {
  40. this.planLoading = true
  41. try {
  42. let res
  43. if (mode === 2) {
  44. // 自定义模式 - 使用自定义方案列表接口
  45. res = await getCustomPlanList()
  46. if (res && Array.isArray(res)) {
  47. this.planList = res.map(item => ({
  48. id: item.id,
  49. name: item.name || '未命名方案',
  50. description: item.description || '',
  51. symptoms: item.symptoms || '',
  52. status: item.status,
  53. useCount: item.useCount || 0,
  54. avgRating: item.avgRating
  55. }))
  56. } else {
  57. this.planList = []
  58. }
  59. } else if (mode === 1) {
  60. // 专业模式 - 使用专业模式方案列表接口
  61. res = await getProfessionalPlanList()
  62. this.planList = this._mapSystemPlanList(res)
  63. } else if (mode === 3) {
  64. // 延年圣手模式 - 使用延年圣手方案列表接口
  65. res = await getMasterPlanList()
  66. this.planList = this._mapSystemPlanList(res)
  67. }
  68. } catch (e) {
  69. console.error('加载方案列表失败', e)
  70. this.planList = []
  71. }
  72. this.planLoading = false
  73. },
  74. /** 映射系统方案列表数据(专业模式/延年圣手模式通用) */
  75. _mapSystemPlanList(res) {
  76. if (res && Array.isArray(res)) {
  77. return res.map(item => ({
  78. id: item.id,
  79. name: item.name || item.title || '未命名方案',
  80. description: item.description || item.remark || '',
  81. steps: item.stepCount || item.steps || 0,
  82. duration: item.totalDuration || item.duration || 0
  83. }))
  84. }
  85. // 兼容分页结构
  86. if (res && res.records) {
  87. return res.records.map(item => ({
  88. id: item.id,
  89. name: item.name || item.title || '未命名方案',
  90. description: item.description || item.remark || '',
  91. steps: item.stepCount || item.steps || 0,
  92. duration: item.totalDuration || item.duration || 0
  93. }))
  94. }
  95. return []
  96. },
  97. /** 打开方案选择弹窗 */
  98. showPlanDrawer() {
  99. if (this.planList.length === 0 && this.modeType !== 0) {
  100. this.loadPlanList(this.modeType)
  101. }
  102. this.isShowPlanDrawer = true
  103. },
  104. /** 选择方案 */
  105. selectPlan(plan) {
  106. this.selectedPlan = plan
  107. this.isShowPlanDrawer = false
  108. // 选中方案后,可在此触发方案数据加载到curCase
  109. this._applyPlanToCase(plan)
  110. },
  111. /** 跳转新增自定义方案 */
  112. goAddCustomPlan() {
  113. uni.navigateTo({
  114. url: `/pages/device/acupointEdit/acupointEdit?profileId=${this.profileId}&mode=create`
  115. })
  116. },
  117. /** 跳转编辑自定义方案 */
  118. goEditCustomPlan(plan) {
  119. this.isShowPlanDrawer = false
  120. uni.navigateTo({
  121. url: `/pages/device/acupointEdit/acupointEdit?profileId=${this.profileId}&mode=edit&planId=${plan.id}`
  122. })
  123. },
  124. /** 删除自定义方案 */
  125. confirmDeletePlan(plan) {
  126. uni.showModal({
  127. title: '确认删除',
  128. content: `确定删除方案「${plan.name}」?删除后不可恢复。`,
  129. success: async (res) => {
  130. if (res.confirm) {
  131. try {
  132. await deleteCustomPlan(plan.id)
  133. uni.showToast({ title: '删除成功', icon: 'success' })
  134. // 从列表中移除
  135. this.planList = this.planList.filter(p => p.id !== plan.id)
  136. // 如果删除的是当前选中的方案,清空选择
  137. if (this.selectedPlan && this.selectedPlan.id === plan.id) {
  138. this.selectedPlan = null
  139. }
  140. } catch (e) {
  141. console.error('删除方案失败', e)
  142. uni.showToast({ title: '删除失败', icon: 'none' })
  143. }
  144. }
  145. }
  146. })
  147. },
  148. /**
  149. * 将方案数据应用到当前穴位配置
  150. */
  151. async _applyPlanToCase(plan) {
  152. if (!plan || !plan.id) return
  153. try {
  154. let res
  155. if (this.modeType === 2) {
  156. // 自定义模式 - 使用自定义方案详情接口
  157. res = await getCustomPlanDetail(plan.id)
  158. } else if (this.modeType === 1) {
  159. // 专业模式 - 使用专业模式方案详情接口
  160. res = await getProfessionalPlanDetail(plan.id)
  161. } else if (this.modeType === 3) {
  162. // 延年圣手模式 - 使用延年圣手方案详情接口
  163. res = await getMasterPlanDetail(plan.id)
  164. }
  165. if (res && res.steps) {
  166. this.curCase = res.steps.map(step => ({
  167. id: step.acupointId || step.id,
  168. name: step.acupointName || '',
  169. time: step.duration || 15,
  170. temperature: step.temperature || 42,
  171. _x: step.x || 0,
  172. _y: step.y || 0
  173. }))
  174. this.curCaseIndex = 0
  175. }
  176. } catch (e) {
  177. console.error('加载方案详情失败', e)
  178. }
  179. }
  180. }
  181. }