Skip to content

uniCloud 与支付组件(一) ​

本页对应 uniCloud 与支付组件,共 8 段视频,约 1 小时 20 分。

学习目标 ​

  • 能解释 uniCloud/云开发与服务端、运维之间的关系,能获取 uni-app 项目 AppID,并按规定先关联云空间再启动项目,说明未关联或顺序错误时会出现的问题。
  • 能使用 uni-file-picker 组件配置上传数量、文件类型、图片预览样式和 v-model,将病情图片上传至云空间,并通过进度条、v-model 返回地址及云存储管理后台验证上传成功。
  • 能基于病情描述、患病时长、是否就诊三个字段编写计算属性,控制“下一步”按钮的 disabled 状态,并通过逐项填写与删除数据验证按钮启用/禁用逻辑。
  • 能使用 Pinia 定义问诊相关 store,区分初始空数据与患者病情数据,使用 storeToRefs 解构保持响应式,完成病情描述数据的持久化缓存并通过刷新页面验证回显。
  • 能使用 uni.showModal 在存在缓存数据时提示用户恢复数据,并根据确认/取消结果保留或清空数据,通过清除本地缓存验证弹窗显示条件。
  • 能通过点击事件获取地址中的 type、pho、deptId 参数并存入 Pinia 与本地缓存,完成跳转到患者选择页面,并验证地址参数、Pinia 状态和本地存储中的数据一致。

知识点 ​

先理解:uniCloud 不是“玄学” ​

为什么需要:很多人一听“云开发”就觉得高级,其实它本质是把服务端、运维中繁琐的服务器配置简化掉,让前端也能写原本后端要写的代码。怎么想:把云空间理解成“已经帮你管好的服务器”,你只管用,不必自己买服务器、配域名、远程开机。怎么做:在 uni-app 里开通并关联 uniCloud 服务空间;开发测试可用免费/开发者版,公司运营按实际情况用付费版。易错点:不要把云开发和“神奇新技术”混为一谈;免费版主要用于开发测试,真正运营通常要付费;开发者版可续期,但要以控制台实际显示为准。

获取 APPID:别拿小程序 APPID 混用 ​

为什么需要:uni-app 项目有自己的应用标识,后续关联云空间、管理项目都要用到。怎么想:先区分“小程序 APPID”和“uni-app 项目 APPID”,名字都叫 APPID,但不是一回事。怎么做:打开项目里的 manifest.json,在“基础配置”里查看“uni-app 应用标识”;没有就点“获取”,有就不用重复获取。也可到管理后台“账号管理—应用管理—我的应用”核对。易错点:把小程序 APPID 填到这里;已有 APPID 还反复点“重新获取”。

启动顺序:先关联云空间,再启动项目 ​

为什么需要:项目启动时若还没关联云空间,后续上传图片、云函数等能力不会生效。怎么想:把“关联空间”当成每天打开项目后的第一步。怎么做:打开项目后先关联 uniCloud 服务空间,再运行项目;如果忘了,停掉项目,重新关联后再启动。易错点:先启动再关联,控制台提示“未关联空间”;以为刷新页面就能补救,实际要按顺序重启。

上传图片:用 uni-file-picker ​

为什么需要:病情描述要上传患处图片,图片不能只存在浏览器内存里,要传到云空间。怎么想:云空间就是服务器,上传组件负责把文件传到已关联的云空间;用 v-model 接上传结果,成功后可拿到图片地址。怎么做:使用扩展组件 uni-file-picker,限制数量、类型和预览样式:

html
<uni-file-picker
  v-model="pic"
  :limit="8"
  file-extname="png,jpg,gif"
  :image-styles="{ width: '80px', height: '80px' }"
/>

上传成功后,pic 中会出现 path 或 url,这就是云存储地址。易错点:只看页面出现图片就以为成功,必须检查 v-model 是否真有数据;上传时没有进度条,大概率是项目没关联云空间;file-extname 写错会导致类型限制不生效。

查看云存储:后台能管理上传结果 ​

为什么需要:要知道图片到底有没有进服务器,以及后续能否删除管理。怎么想:控制台里的“云存储”就是你的文件管理后台。怎么做:进入 uniCloud 控制台,点“云存储/cloud storage”,可看到刚上传的图片,也可删除。易错点:把“本地预览”当成“云端已保存”;上传成功应以 v-model 数据和云存储列表为准。

数据验证:用 disabled + computed ​

为什么需要:病情描述、患病时长、是否就诊过没填完时,“下一步”不应可点;图片允许不上传。怎么想:按钮是否禁用,取决于三个必填值是否都不为空。怎么做:

js
const isEnabled = computed(() => {
  return desc.value !== '' &&
    duration.value !== '' &&
    flag.value !== ''
})

按钮上写 :disabled="!isEnabled"。易错点:三个判断少写显式比较,结果可能变成 0/1 而不是布尔值;忘记取反,导致“填完反而禁用”;把图片也设成必填。

病情数据缓存:Pinia + storeToRefs ​

为什么需要:用户填完病情后刷新或返回,数据不应凭空消失;再次进入时可提示“是否恢复之前填写的数据”。怎么想:页面刷新后变量内存会丢,所以要持久化到本地;用 Pinia 管理问诊数据,并只持久化需要跨页面/刷新保留的字段。怎么做:在 consult store 中定义 info、initialValue、type、consultId、depId,持久化 info 等;页面中不能直接解构 store,否则丢响应式,要用 storeToRefs:

js
const store = useConsultStore()
const { info, initialValue } = storeToRefs(store)

易错点:直接解构导致页面不更新;把 initialValue 也持久化,取消时无法清空;无缓存也弹恢复提示。

恢复提示与清空:uni.showModal ​

为什么需要:自动回填会让用户觉得“莫名其妙”,应让用户选择是否恢复。怎么想:有缓存才弹窗;确认则保留,取消则用 initialValue 覆盖清空。怎么做:

js
uni.showModal({
  title: '提示',
  content: '是否恢复之前填写的数据',
  confirmText: '确认',
  cancelText: '取消',
  success(res) {
    if (!res.confirm) {
      info.value = { ...initialValue.value }
    }
  }
})

易错点:没有缓存也弹;取消时只改某个子字段,导致清不干净;忘记 confirm 为 true、取消为 false 的判断。

地址参数缓存:按钮跳转时存 Pinia ​

为什么需要:从首页到快速问诊可用链接拼参数,但当前“下一步”是按钮,继续拼长地址很麻烦,且这些参数要跨页面使用。怎么想:链接场景拼地址省事;按钮场景监听点击事件,把地址参数存 Pinia 再跳转更省事。怎么做:用 defineProps 接收地址参数,点击“下一步”时存入 store 并跳转:

js
const props = defineProps({
  type: String,
  consultId: String,
  depId: String
})

store.type = props.type
store.consultId = props.consultId
store.depId = props.depId
uni.navigateTo({ url: '/pages/patient/index' })

易错点:参数名与地址中的名字不一致;先跳转再存导致下页取不到;store 中没定义对应字段;需要跨页面的字段忘记持久化。

本节目标与云空间认知 ​

本节要实现“病情描述上传图片”,并顺带完成数据验证、图片云存储查看、病情数据缓存和地址参数缓存。先明确:uniCloud 云开发不是神秘新技术,本质是把服务器、运维、后端的一部分工作简化了。为什么需要?因为上传图片必须有服务端存储;怎么想?把云空间当成已配置好的服务器;怎么做?先在 HBuilderX 中关联服务空间,再启动项目;易错点:顺序必须是“先关联、再启动”。转写中反复调试发现:若启动时未关联,运行后会提示未关联空间;此时应停项目、关联后重启。另外要在 manifest.json 的基础配置中获取 uni-app 项目 AppID,注意它不等同于小程序 AppID。

(若原笔记无图,此处仅保留说明,不编造链接。)

上传图片组件:uni-file-picker ​

为什么需要?病情描述要允许患者上传患处图片;怎么想?使用扩展组件 uni-file-picker,它可把文件上传到已关联的云空间;怎么做?在页面中放入组件,配置 v-model 接收上传结果,limit 限制张数,file-extname 限制扩展名,image-styles 调整预览宽高和边框。示例:

vue
<uni-file-picker
  v-model="pic"
  :limit="8"
  file-extname="png,jpg,jpeg"
  :image-styles="{ width: '80px', height: '80px' }"
/>
js
const pic = ref([]) // 病情图片,字段名按后端接口命名为 pic

易错点:组件本身会自动上传到已关联云空间,但必须用 v-model 接收结果;上传成功后可看到 pic 中多出对象,里面有 path 或 url,即云存储地址。转写中调试:若选择图片后出现蓝色进度条,说明云空间关联生效;若只显示图片却没有进度条,大概率是项目未关联云空间。上传后还可在 uniCloud 后台“云存储 / cloud storage”中查看和管理图片。

病情数据验证与按钮禁用 ​

为什么需要?避免用户未填关键信息就点“下一步”;怎么想?文字描述、患病时长、是否就诊过三项不能为空,图片可不传;怎么做?给按钮加 :disabled,用计算属性判断三项是否都有值:

js
const isEnabled = computed(() => {
  return !!consult.desc && !!consult.duration && !!consult.flag
})
vue
<button :disabled="!isEnabled">下一步</button>

易错点:转写中一开始计算属性返回了 0/1,原因是布尔项没有参与判断,需三项都判断,保证结果为布尔值;disabled 为真时按钮禁用,因此绑定时要取反。样式上可用属性选择器 [disabled] 给禁用按钮置灰。

病情数据缓存:Pinia 持久化与确认框 ​

为什么需要?用户离开或刷新后,之前填写的数据应可恢复;怎么想?数据不能只放页面内存,要放 Pinia 并持久化到本地;怎么做?在 consult store 中定义 info 和 initialValue,只持久化 info;页面通过 storeToRefs 解构以保持响应式:

js
import { storeToRefs } from 'pinia'
const consultStore = useConsultStore()
const { info } = storeToRefs(consultStore)

页面加载时用 uni.showModal 询问是否恢复:

js
uni.showModal({
  title: '提示',
  content: '是否恢复之前填写的数据?',
  confirmText: '确认',
  cancelText: '取消',
  confirmColor: '#00aa00',
  success(res) {
    if (res.cancel) {
      consultStore.info = consultStore.initialValue
    }
  }
})

易错点:没有缓存时不要弹窗,应先判断本地是否有数据;点“取消”时用 initialValue 覆盖当前数据即可清空。转写中验证:确认后保留数据,取消后表单和图片清空。

地址参数缓存到 Pinia ​

为什么需要?后续提交不仅需要病情描述,还需要类型、科室 ID 等,跨多个页面传递;怎么想?链接跳转时拼参数方便,但到按钮跳转时,把参数存入 Pinia 更方便;怎么做?在“下一步”点击事件中读取地址参数,存入 store,再 uni.navigateTo 到患者选择页。
易错点:读取参数名必须与地址中的参数名一致;需要跨页使用的 type、consultId、deptId 要持久化,而仅当前页使用的 info 不必持久化。转写中验证:点击下一步后,Pinia 与本地存储中都能看到这三个参数,页面也正常跳到 patient 页。

本节要解决的问题 ​

病情描述页有三个关键数据:文字描述、患病时长、是否就诊过。转写稿里明确:图片可以不上传,但前三个数据必须都有值;只要有一个为空,“下一步”按钮就应该是灰色不可点的。
为什么需要:如果按钮一直可点,用户漏填也能进入下一页,后面提交时才发现数据不全,体验和校验都会变差。
怎么想:按钮是否禁用,不直接写死,而是由一个“计算属性”根据三个字段实时算出来。
怎么做:模板里给按钮绑定 :disabled,计算属性返回布尔值。
易错点:不要把 disabled 写死;图片不参与必填校验。

按钮禁用与样式 ​

转写稿中按钮本身是 button,加了 disabled 后点击事件也不生效。为了让用户看得出“禁用”,又用属性选择器给带 disabled 的按钮加了灰色样式。

html
<button
  class="uni-button"
  :disabled="!canNext"
  @click="onNextStepClick"
>
  下一步
</button>
css
.uni-button[disabled] {
  color: #999;
  background: #eee;
}

为什么需要:只逻辑禁用、不视觉禁用,用户会反复点。
怎么想:disabled 控制能不能点,属性选择器控制看起来能不能点。
怎么做::disabled="!canNext",canNext 为真时按钮可用。
易错点:属性选择器要写在按钮类名后面;不要只改颜色而忘了 disabled 属性。

计算属性的推导与调试 ​

转写稿里的推导是:描述不为空、患病时长不为空、是否就诊不为空,三个条件同时成立才允许下一步。调试时先刷新页面,三个值都为空,按钮应为灰;逐项填写,只有第三项也填完按钮才变亮。

js
import { computed } from 'vue'

const canNext = computed(() => {
  return Boolean(form.desc) &&
         Boolean(form.duration) &&
         Boolean(form.flag)
})

转写稿里出现了一个小瑕疵:结果变成了 0/1,不是纯布尔值。原因是布尔字段参与 && 时没有显式判断。用 Boolean(...) 或显式比较,保证最终返回 true/false。

为什么需要:按钮状态必须随三个字段实时变化。
怎么想:三个条件用逻辑与连接,任何一个不满足就禁用。
怎么做:计算属性返回布尔值,模板取反后交给 disabled。
易错点:ref 数据在 JS 里要 .value;字段名要和后端接口一致;图片字段不要加进必填条件。

上传图片与云存储验证 ​

图片虽可不传,但上传成功与否要能确认。转写稿用 uni-file-picker,通过 v-model 拿上传结果,limit 限制张数,file-extname 限制 png/jpg 等,imageStyles 改预览宽高和边框。

html
<uni-file-picker
  v-model="form.pic"
  limit="8"
  file-extname="png,jpg,jpeg"
  :imageStyles="{ width: '80px', height: '80px' }"
/>

调试时看两点:上传时是否有进度条;v-model 对应数据里是否出现 path/url。转写稿强调:没有进度条,大概率是项目没有先关联云空间再启动。
易错点:先关联 uniCloud 空间,再启动项目;上传后可在云存储后台查看和删除图片。

数据缓存与恢复提示(关联步骤) ​

转写稿还补了缓存:用户再次进入页面时,用 showModal 询问是否恢复上次填写的数据;点取消时用 initialValue 把数据清空。Pinia 中定义 initialValue 和 info,只持久化需要跨页面/刷新保留的数据;解构要用 storeToRefs 保持响应式。

js
uni.showModal({
  title: '提示',
  content: '是否恢复之前填写的数据?',
  success(res) {
    if (!res.confirm) {
      consult.info = { ...consult.initialValue }
    }
  }
})

易错点:没有缓存也弹窗会吓到用户,应先判断本地是否有缓存;直接解构 store 会丢响应式。

地址参数缓存与跳转(关联步骤) ​

点“下一步”时,把地址里的 type、科室 ID 等参数取出来存进 Pinia,再跳转下一页,避免地址越拼越长。参数名必须和地址中的参数名一致,先存再跳。

js
const type = options.type
const depId = options.depId

consult.type = type
consult.depId = depId

uni.navigateTo({ url: '/patient/index' })

小结 ​

本节核心是“三个必填字段控制按钮禁用”:用计算属性算布尔值,用 :disabled 控制点击,用样式给出视觉反馈;图片可选,但要验证上传结果。缓存和地址参数是后续联动步骤,调试时重点看布尔值、字段名和云空间关联顺序。

代码示例 ​

示例一:病情描述上传图片(uni-file-picker → uniCloud 云存储) ​

vue
<template>
  <view class="desc-page">
    <view class="title">病情描述</view>

    <textarea
      v-model="info.desc"
      class="desc-input"
      placeholder="请描述您的病情(必填)"
      maxlength="200"
    />

    <!-- 只要项目已关联 uniCloud 空间,这个组件就会自动把文件传到云存储 -->
    <uni-file-picker
      v-model="info.pic"
      :limit="8"
      file-extname="png,jpg,gif"
      :image-styles="{ width: '60px', height: '60px', border: 'none' }"
      @select="onSelect"
      @progress="onProgress"
      @success="onSuccess"
      @delete="onDelete"
    />
  </view>
</template>

<script setup>
import { ref } from 'vue'

// pic 用来接收上传成功后的结果:数组,元素里有 path / url
const info = ref({
  desc: '',
  pic: []
})

const onSelect = (e) => {
  console.log('选中文件', e.tempFilePaths)
}
const onProgress = (e) => {
  console.log('上传进度', e.progress) // 上传大图时会一直变化
}
const onSuccess = (e) => {
  console.log('上传成功', e)
}
const onDelete = (e) => {
  console.log('删除', e)
}
</script>

<style>
.desc-input {
  width: 100%;
  height: 200rpx;
  background-color: #f5f5f5;
}
</style>

要点解释 / 易错点

  • v-model="info.pic":uni-file-picker 支持 v-model,它有两个作用——上传成功后把结果(含 path、url)写回数组,以及回显已上传的图片。v-model 必须写完整,只写一半会直接报错。
  • file-extname="png,jpg,gif":限定可上传的后缀(extension);limit="8":最多 8 张。
  • :image-styles:改的是预览图的宽高、边框,跟上传逻辑无关,只是 UI。
  • 最关键的易错点:组件之所以能上传,是因为项目已经关联了 uniCloud 服务空间。判断是否关联成功的小技巧——选择图片后有没有蓝色进度条;有进度条=已关联,没进度条但图片出来了=大概率没关联。另外打开项目要先关联空间、再启动项目,顺序反了关联不生效,只能停掉重跑。
  • 上传后到「云空间 → 云存储(cloud storage)」里能看到文件,那里也可以直接删除。

示例二:病情描述数据验证(计算属性控制按钮 disabled) ​

vue
<template>
  <view class="desc-page">
    <textarea v-model="info.desc" placeholder="请描述您的病情(必填)" />

    <radio-group v-model="info.duration">
      <label><radio value="一周内" />一周内</label>
      <label><radio value="一个月内" />一个月内</label>
      <label><radio value="半年内" />半年内</label>
    </radio-group>

    <radio-group v-model="info.flag">
      <label><radio :value="true" />就诊过</label>
      <label><radio :value="false" />未就诊</label>
    </radio-group>

    <!-- 图片不限制,可以不上传 -->
    <button class="uni-button" :disabled="!canNext" @click="onNextStep">
      下一步
    </button>
  </view>
</template>

<script setup>
import { ref, computed } from 'vue'

const info = ref({
  desc: '',        // 病情描述
  duration: '',    // 患病时长
  flag: null,      // 是否就诊过
  pic: []          // 图片(允许为空)
})

// 三个必填项都有值,才允许点击下一步
const canNext = computed(() => {
  const { desc, duration, flag } = info.value
  return desc !== '' && duration !== '' && flag !== null && flag !== ''
})

const onNextStep = () => {
  uni.navigateTo({ url: '/pages/patient/index' })
}
</script>

<style>
/* 属性选择器:按钮带 disabled 属性时才生效 */
.uni-button[disabled] {
  background-color: #cccccc !important;
  color: #ffffff !important;
}
</style>

要点解释 / 易错点

  • :disabled="!canNext":canNext 为 true(三项都填了)→ !canNext 为 false → 不渲染 disabled 属性,按钮可点;反之变灰。注意要取反,因为 disabled 是「禁用」语义。
  • 按钮本身要写 :disabled 才有禁用效果,只写 @click 是不管用的;[disabled] 是属性选择器,用来给禁用态换颜色。
  • 三个条件都必须写显式判断。易错点:flag 是「是否就诊过」,false 也是有效值,如果直接写 desc && duration && flag,用户选了「未就诊」就会被判成没填。所以必须写成 flag !== null && flag !== ''。
  • 另一个易错点:radio-group 的 value 容易被转成字符串或 0/1,导致布尔类型判断失效;出现「值不是布尔」时先检查是不是少了某个 !== '' 的判断。
  • 图片 pic 不参与校验——业务上允许不上传。

示例三:病情数据缓存(pinia + 持久化 + showModal 恢复数据) ​

js
// stores/consult.js
import { ref } from 'vue'
import { defineStore } from 'pinia'

export const useConsultStore = defineStore('consult', () => {
  // 1. 空数据模板:点「取消」时用它整体覆盖,实现一键清空
  const initialValue = ref({
    desc: '',
    duration: '',
    flag: null,
    pic: []
  })

  // 2. 页面真正使用的病情数据,初始就是空模板
  const info = ref({ ...initialValue.value })

  // 3. 地址参数,跨页面使用,也放进 store
  const type = ref('')
  const depId = ref('')
  const docId = ref('')

  return { initialValue, info, type, depId, docId }
}, {
  // 只持久化这里列出的数据;initialValue 只是模板,不用缓存
  persist: {
    paths: ['info', 'type', 'depId', 'docId']
  }
})
vue
<!-- pages/description/index.vue -->
<script setup>
import { storeToRefs } from 'pinia'
import { useConsultStore } from '@/stores/consult'

const consult = useConsultStore()

// 必须用 storeToRefs 解构,直接解构会丢响应式
const { info } = storeToRefs(consult)

// 页面一进来就判断:本地到底有没有缓存过数据
const hasCache =
  info.value.desc !== '' || info.value.duration !== '' || info.value.flag !== null

if (hasCache) {
  uni.showModal({
    title: '提示',
    content: '是否恢复之前填写的数据?',
    confirmText: '确认',
    cancelText: '取消',
    confirmColor: '#00b96b',
    success: (res) => {
      if (!res.confirm) {
        // 点取消:用空模板覆盖,数据就清空了
        info.value = { ...consult.initialValue }
      }
    }
  })
}
</script>

要点解释 / 易错点

  • 页面刷新、甚至退回首页再进来,数据还在,说明数据不能放组件内存,必须落到本地存储;用 pinia 的 persist 指定 paths,等于「点谁谁缓存」。
  • 最容易踩的坑:const { info } = consult 解构后不再是响应式数据,页面不会跟着变,必须 storeToRefs(consult) 再解构。
  • 两个数据分工:initialValue 是空模板(只用来清空,不缓存),info 才是页面 v-model 绑定的真数据(要缓存)。名字保持一致,页面代码就不用改。
  • uni.showModal:res.confirm 为 true 是「确认」,false 是「取消」;confirmText / cancelText / confirmColor 可自定义文案和颜色。
  • 必须加 hasCache 判断:本地根本没缓存还弹窗,用户会更懵;只有缓存里真有数据才提示。点「取消」时才执行 info.value = { ...consult.initialValue } 把数据清空。
  • 地址参数(type / depId / docId)也一起存进 store 并持久化,是为了避免在页面间不断拼长地址;但「下一步」这类按钮场景要在点击事件里先 deffiend 取参、再赋值进 store,最后才 navigateTo 跳转。

常见错误 ​

  1. 打开项目后直接运行,云空间不生效 → 未先关联 uniCloud 空间就启动项目 → 先关联云空间,再重启/启动项目。
  2. 把小程序 APPID 当成 uni-app 项目 APPID 使用 → 两个 APPID 概念混淆 → 在 manifest.json 基础配置中获取当前 uni-app 项目 APPID。
  3. 图片看似上传成功,但后续取不到数据 → 只看页面预览,未检查 v-model 结果或上传进度条 → 同时验证 v-model 中是否有 path/url,并观察上传进度条。
  4. 按钮禁用逻辑出现 0/1 而非布尔值 → 计算属性中省略了某个布尔判断 → 三个必填条件都显式比较,确保最终结果为布尔值。
  5. 从 Pinia 解构后页面不随数据变化 → 直接解构导致响应式丢失 → 使用 storeToRefs 后再解构。
  6. 一进页面就弹恢复缓存提示 → 未判断本地是否真有缓存 → 先读本地缓存,有缓存才调用 showModal。
  7. 点“取消”后旧数据仍回显 → 未用初始空数据覆盖当前数据 → 用 initialValue 重置对应状态。
  8. 点“下一步”后地址参数没进 Pinia → 未在点击事件中取值,或参数名与地址不一致 → 在 onNextStep 中按地址参数名获取并写入 store,再跳转。

练习 ​

  1. 复现“未关联云空间就启动项目”的场景,记录报错现象,并按正确顺序修复。
  2. 上传一张图片,分别通过页面预览、v-model 数据、云存储管理后台三处确认上传结果。
  3. 实现病情描述页按钮禁用逻辑,要求三个必填项都填写后才可点击,并验证结果为布尔值。
  4. 实现“恢复之前填写的数据”弹窗:有缓存才提示,确认则保留,取消则清空。
  5. 从上一页地址参数中取出 type、科室、医生 ID,存入 Pinia 并跳转下一页,刷新后验证持久化结果。

课堂画面 ​

课堂画面 01

课堂画面 02

课堂画面 03

课堂画面 04

课堂画面 05

课堂画面 06

原视频对照 ​

#视频时长
1uniCloud空间介绍10:36
2优医咨询-病情描述上传图片11:12
3优医咨询-病情描述数据验证10:48
4优医咨询-查看云存储的图片02:06
5优医咨询-病情数据缓存-112:23
6优医咨询-病情数据缓存-209:55
7优医咨义昌-病情数据缓存-310:12
8优医咨询-地址参数缓存13:12

小结 ​

  1. 云空间使用前先关联,再启动项目,顺序不能反。
  2. uni-app 项目 APPID 与小程序 APPID 要区分。
  3. 图片上传成功要以 v-model 数据和上传进度为依据,不能只看预览。
  4. 按钮是否禁用应由计算属性统一控制,并保证布尔结果。
  5. Pinia 解构取值要使用 storeToRefs,避免响应式丢失。
  6. 缓存恢复提示必须先判断本地是否存在缓存。
  7. 取消恢复缓存时,用初始空数据覆盖当前数据完成清空。
  8. 跨页面参数可放 Pinia,点击“下一步”时写入 store 并跳转。