主题
首页列表与云开发环境(四)
本页对应 首页列表与云开发环境,共 6 段视频,约 38 分钟。
学习目标
- 能够使用
defineProps获取页面地址中的type与level参数,并在跳转病情描述页时拼接科室id,构造包含type、level、deptId三个查询参数的 URL,点击科室后可在地址栏验证参数正确。 - 能够将病情描述页的模板与样式接入项目并替换原页面内容,使页面正常渲染在线医生静态区域、文字描述输入框、患病时长选项和是否就诊选项。
- 能够定义患病时长与是否就诊的选项数组,使用
v-for渲染列表,通过点击事件传递value并与当前选中值比较来动态添加active类,实现任一时刻仅一个选项高亮且默认无选中。 - 能够使用
ref定义病情描述表单数据,使用v-model获取文字描述,通过选项点击回写患病时长和是否就诊值,并在调试器中验证三项数据随用户操作正确更新。 - 能够登录 uniCloud 控制台创建阿里云免费服务空间,并在 HBuilderX 中通过项目右键创建阿里云云开发环境、关联对应服务空间,确认项目出现云开发环境目录且重启项目后关联生效。
知识点
一、地址参数要一路带完整
为什么需要:用户从“急速问诊 → 三甲医院 → 消化内科”一路选过来,进入病情描述页后,页面必须知道三件事:问诊类型、医院级别、科室。前两个参数地址栏里已有,科室参数没有,所以新页面会不知道用户选的是消化内科。
怎么想:先在病情描述页用 defineProps 接收地址上的 type 和原有医院级别参数;科室 ID 不单独请求,而是在遍历二级科室时从当前项自身取 ID,再拼到 navigator 的跳转地址里。地址参数本质都是字符串,不要因为看到 1、2 就当成数字类型。
怎么做:关键结构如下,参数名以项目实际为准,长参数名建议复制,避免手写错。
js
// 病情描述页接收地址参数
defineProps({
type: String,
原参数名: String
})html
<!-- 二级科室遍历项中拼三个参数 -->
<navigator
:url="`/description?type=${props.type}&原参数名=${props.原参数名}&id=${item.id}`"
>
{{ item.name }}
</navigator>易错点:defineProps 里的名字必须和地址参数名一致;& 不能丢;科室 ID 要从二级科室的遍历项取,不要拿到一级科室;点“消化内科”后要检查地址栏,转写稿中的验证结果是出现 2(急速问诊)、1(三甲)和科室 ID。
二、病情描述页先把页面壳搭出来
为什么需要:选完科室后还差一步:用户要先描述病情,系统再分配医生。这个页面本质上是一个表单页。
怎么想:把 description/index.vue 的布局和 index.scss 样式拿过来,替换原内容;静态的“在线医生”区域不用管,重点保留文本域、患病时长、是否就诊、图片上传区域。
怎么做:先完成布局和样式,再逐步实现表单数据、tab 切换、图片上传。图片上传放到最后,因为会用到 uni-app 云开发。
易错点:不要一开始就混着写上传逻辑;静态区域不要误绑定数据;文本域、tab、上传区要按表单结构组织,后续才好做验证。
三、患病时长 tab:交互用 value,不用索引
为什么需要:既要点谁谁高亮,又要把用户选中的值交给后端。转写稿强调,1、2、3、4 不是随便定的,是后端接口规定的;是否就诊的 0/1 也一样。
怎么想:构造数组后 v-for 遍历,每个元素绑定点击事件,点击时把 item.value 传给函数,再赋值给病情数据中的选中值字段。高亮条件用 item.value === 选中值。
怎么做:
html
<div
v-for="item in timeList"
:key="item.value"
:class="{ active: form.time === item.value }"
@click="onTimeTagClick(item.value)"
>
{{ item.text }}
</div>js
const form = ref({ time: '', desc: '', visited: '' })
function onTimeTagClick(value) {
form.value.time = value
}易错点与调试:一开始所有 tab 都高亮,是因为每个元素都无条件加了 active,要改成条件类名;点击报 undefined,是定义数据时忘了 ref,加上后通过 .value 访问;初始值给空字符串,既不会默认选中,也方便后续表单验证。
四、病情文字说明直接用 v-model
为什么需要:文字说明是用户主动填写,最容易获取。
怎么想:把 textarea 绑定到病情数据对象的描述字段,不用额外事件。
怎么做:
html
<textarea v-model="form.desc"></textarea>易错点:绑定层级要落在表单对象内部;字段名建议复制,防止拼错;验证时看初始为空、输入后数据同步变化。
五、图片上传前先创建并关联云空间
为什么需要:图片要上传到服务器。uni-app 可以用云开发,不必先调后端上传接口。
怎么想:先开通 uniCloud 服务空间,选阿里云免费空间;再让项目和云空间关联,否则代码无法使用。
怎么做:登录 uniCloud 控制台,新建服务空间,选阿里云免费版,命名可用 consult-patient;在项目目录右键“创建 uniCloud 云开发环境”,选阿里云;再右键“关联”选择刚建的空间;最后重启项目生效。
易错点:项目与云空间不会自动关联;腾讯云没有同样免费额度;免费空间一个月后可续期;不完成关联,后续上传代码无法写。
一、这一节在整条业务线上的位置
前面我们已经能把用户从「急速问诊 → 三甲医院 → 消化内科」一路选到科室了。但选完科室还没到「问医生」,中间还差一步:让患者先把自己的情况描述清楚,也就是「病情描述」页。这个页面的作用是把病情、患病时长、是否就诊过、病情图片这些信息收集起来,后端再据此分配医生。
所以这一节要干两件事:一是把科室 ID 继续拼到跳转地址里,保证下一页知道「你选的是哪个科室」;二是把病情描述页的结构、数据和 tab 切换交互做出来。图片上传因为要依赖云开发,放到后面单独处理。
二、跳转时把科室 ID 一起带上
为什么需要?现在地址栏里只有两个参数:type(2 表示急速问诊)和医院级别(1 表示三甲)。用户点了「消化内科」跳过去时,新页面根本看不出选的是哪个科室,所以必须再加一个科室 ID。这个 ID 接口里是有的,展开任意一个二级科室的网络请求就能看到 id 字段。
怎么想?先把地址上的两个参数拿到,再在遍历二级科室时把 item.id 拼上去,最终凑成三个参数。
怎么做?在科室页用 defineProps 接收地址参数,名字必须和地址栏里的参数名一致:
js
// 参数名要和地址栏中的一致,类型统一写 String(地址参数本质是字符串)
const props = defineProps({
type: String, // 2 = 急速问诊
level: String // 1 = 三甲
})然后在 navigator 上拼地址,注意用反引号,& 不能丢:
html
<navigator
v-for="item in secondList"
:key="item.id"
:url="`/pages/description/index?type=${props.type}&level=${props.level}&id=${item.id}`"
>易错点:① 用单引号写字符串,${} 就不生效了;② 多个参数之间的 & 漏掉,后面参数全被当成第一个参数的值;③ id 这个名字是接口规定的,不能自己改。
三、病情描述页的结构
把 pages/description/index.vue 的模板和 index.scss 样式贴过来。页面从上到下是:静态的在线医生头像区(纯静态,不用管)、病情文字描述 textarea、患病时长 tab、是否就诊过 tab、图片上传区。
这个页面本质就是一个表单,所以后面要做的功能也就清楚了:取表单数据、tab 切换、图片上传、表单验证。
四、患病时长:用数据驱动 tab
为什么需要?四个时长选项如果写四份死标签,高亮判断和取值都要复制四遍。用数组 + v-for 遍历,才能统一处理。
怎么想?这个 tab 和之前做过的 tab 是同一套路,区别只在比较的依据。
怎么做?数组里的 value 不是随便写的 1、2、3、4,而是后端接口规定的值,交互和提交数据共用它:
js
// 不需要 ref:这份数据全程不改,用普通常量还能省一点开销
const timeList = [
{ text: '一周内', value: 1 },
{ text: '一个月内', value: 2 },
{ text: '半年内', value: 3 },
{ text: '半年以上', value: 4 }
]
const formData = ref({
desc: '',
time: '',
isVisit: ''
})
function onTimeTagClick(value) {
formData.value.time = value
}html
<view
v-for="item in timeList"
:key="item.value"
:class="{ active: formData.time === item.value }"
@click="onTimeTagClick(item.value)"
>
{{ item.text }}
</view>调试过程里踩过一个坑:点击时报 undefined,原因是 formData 定义时漏了 ref,没有 .value 可访问。补上 ref 之后点击正常,值会从空串变成 1、2、3。
五、为什么这里比较 value 而不是索引
以往的 tab 都是拿索引 index 做比较,这次刻意换成 value,原因是:value 就是最终要提交给后端的数据。用索引只能做交互,还得再想办法把值取出来;用 value 做交互,点一下既完成高亮,又顺手拿到了要提交的值,一举两得。
初始值不要给 1 或 2,给空串。给了 1 就默认选中「一周内」,用户没选也会有值,后面做表单验证反而麻烦。空串不匹配任何一个 value,四个选项就都不高亮。
「是否就诊过」逻辑完全一样:0 表示没就诊过,1 表示就诊过,同样是接口规定的值。
六、文字描述用 v-model
textarea 是用户主动输入的,最简单:
html
<textarea v-model="formData.desc" placeholder="请描述您的病情"></textarea>易错点:v-model 一定要写在 textarea 标签上,别写到外层包裹的 view 上;formData.desc 拼错不会报错,只会静默失效,建议从定义处复制。
七、开通并关联云开发空间
图片上传用 uni-app 的云开发,比调后端上传接口简单。步骤:登录云开发控制台 → 新建服务空间,选阿里云(有 0 元免费空间,一个月到期点续期即可无限用)→ 名字建议 consult-patient → 立即购买(0 元)。然后回到项目,在项目目录右键「创建 uniCloud 云开发环境」,选阿里云;再右键「关联」服务空间,选中刚才建的那个。不关联,后面上传代码根本没法写。关联后需要重启项目才生效。
从科室选择到病情描述:先把参数带全
为什么需要:用户从“急速问诊 → 三甲医院 → 消化内科”一路点进来,到了病情描述页,页面必须知道“问诊类型、医院类型、科室”。否则后续分配医生、提交表单时不知道用户选的是哪条业务线。
怎么想:地址栏里已经能看到两个参数:type 表示问诊类型,另一个参数表示医院类型;但科室信息看不出来,所以跳转到 description 页面时还要再拼一个科室 ID。课堂中明确说:三个参数分别是问诊类型、医院类型、科室 ID,其中科室 ID 来自二级科室数据里的 id 字段。
怎么做:在页面里用 defineProps 接收地址参数,参数名要和地址栏一致,类型按字符串声明。转写稿里的“deefine crop”应纠正为 defineProps,“死追营”应理解为 String。地址参数即使看起来是数字,本质上也是字符串。跳转时用模板字符串拼参数,& 不能丢:
html
<navigator
:url="`/pages/description/index?type=${props.type}&hospital=${props.hospital}&id=${item.id}`"
>
跳转
</navigator>易错点:参数名不要自己随便起;& 漏写会导致后一个参数丢失;科室 ID 要在遍历二级科室时取,不要拿到一级科室;defineProps 里声明的名字要和地址参数对应。
页面结构:把病情描述当成表单
为什么需要:病情描述页不是纯展示页,用户要填写文字、选择患病时长、选择是否就诊过,还要上传图片。它本质上是一个表单。
怎么想:先熟悉结构:顶部“在线医生”区域是纯静态的,可以先折叠不管;下面才是患者信息。文字说明区域是文本域,可以直接用 v-model;患病时长和是否就诊过是两组 tab 切换;图片上传放到最后,用云开发处理。
怎么做:先定义表单数据对象,至少包含三项:病情文字描述、患病时长、是否就诊过。文字说明用 v-model 绑定:
html
<textarea v-model="form.desc"></textarea>易错点:不要一上来就写上传;先把前三个数据搞定。文字说明虽然简单,但变量名要复制准确,避免手写错。
患病时长为什么用数组渲染
为什么需要:患病时长有“一周内、一个月内、半年内、半年以上”等选项,如果每个 tab 都手写一遍,结构重复、选中态也难维护。
怎么想:把它当成 tab 切换。遍历数组生成每一项,遍历时能拿到 text 和 value。课堂中强调:value 的 1、2、3、4 不是随便定的,而是后端接口规定的;是否就诊过的 0/1 也一样。
怎么做:定义一个不会修改的数组,不必用 ref:
js
const timeList = [
{ text: '一周内', value: 1 },
{ text: '一个月内', value: 2 },
{ text: '半年内', value: 3 },
{ text: '半年以上', value: 4 }
]模板中遍历:
html
<view
v-for="item in timeList"
:key="item.value"
:class="{ active: form.time === item.value }"
@click="changeTime(item.value)"
>
{{ item.text }}
</view>易错点:v-for 的 :key 用不重复的 value;不要把所有项都加上 active,否则会出现“全都高亮”。
选中态为什么比较 value 而不是 index
为什么需要:只做交互时,用索引也能高亮;但提交给后端时需要的是 value,不是第几项。课堂中特意用 value 做交互,就是为了“既完成切换,又拿到用户选中的值”。
怎么想:给表单数据一个初始值,比如空字符串或 0,让默认不选中,后面做校验更方便。点击时把当前项的 value 传给函数,函数再赋给表单数据。
怎么做:
js
const form = reactive({
desc: '',
time: '',
visited: ''
})
function changeTime(value) {
form.time = value
}点击“一个月内”时,form.time 变成 2,模板中 form.time === item.value 的项才加 active。
易错点:转写稿调试时出现 undefined,原因是把 ref 丢了,导致不能访问 .value;补回 ref 后才正常。另一个易错点是 class 写成固定值,导致每项都高亮。下面“是否就诊过”用同样思路再做一遍即可。
图片上传与云开发:先完成环境准备
为什么需要:图片要上传到服务器。uni-app 可以使用云开发,不必先调后端上传接口。
怎么想:先申请阿里云免费服务空间,再让项目和云空间关联。课堂中说明:创建云空间不等于项目已关联,必须右键项目创建 uniCloud 云开发环境,再关联服务空间。
怎么做:按课堂步骤选择阿里云免费空间,项目右键创建云开发环境,右键关联服务空间,最后重启项目生效。图片上传代码留到下一节。
易错点:只建空间不关联,后面上传无法进行;关联后要重启项目才生效。
代码示例
代码 1:二级科室列表页(三个参数一起往下传)
vue
<!-- pages/department/index.vue -->
<template>
<view class="dept-list">
<!-- 二级科室列表:在 v-for 内部才能拿到每个科室自己的 id -->
<navigator
v-for="item in subDeptList"
:key="item.id"
class="dept-item"
:url="`/pages/description/index?type=${props.type}&illnessType=${props.illnessType}&deptId=${item.id}`"
>
<text>{{ item.name }}</text>
</navigator>
</view>
</template>
<script setup>
import { ref } from 'vue'
// 1. 先把地址栏上的两个参数接住
// 参数名必须和上一页链接里写的名字一模一样,怕写错就复制过来
const props = defineProps({
type: String, // 问诊类型:急速问诊 / 普通问诊
illnessType: String // 第二个参数(名字照抄项目里上一页的写法)
})
// 2. 二级科室列表,数据来自二级科室接口
// 接口返回的每一项里自带 id,遍历时直接就能拿到
const subDeptList = ref([])
</script>
<style scoped>
.dept-item {
padding: 30rpx;
border-bottom: 1rpx solid #eee;
}
</style>要点解释
defineProps就是用来接地址栏参数的,type这个名字不是随便起的:上一页链接里叫type,这里就必须叫type。- 地址栏上的参数全都是字符串,所以声明成
String,不要写成Number。 - 三个参数之间必须用
&连接,少一个&后面那个参数就丢了;顺序无所谓,但三个都要带上。 deptId这个名字是接口规定的,不能自己改成id或deptid,否则后端接不到。item.id必须在v-for的作用域里取,写到循环外面拿不到;navigator的url前面必须加:并用反引号模板字符串才能拼变量。
代码 2:病情描述页(tab 切换 + 表单数据)
vue
<!-- pages/description/index.vue -->
<template>
<view class="description">
<!-- 在线医生:纯静态结构,不用处理 -->
<view class="doctor-online">
<text class="online-text">在线医生</text>
</view>
<!-- 患者信息 -->
<view class="patient-info">
<!-- 病情文字描述:表单元素直接用 v-model -->
<textarea
v-model="info.desc"
class="desc-input"
placeholder="请描述您的病情(症状、程度等)"
/>
<!-- 患病时长:遍历数据做 tab 切换 -->
<view class="tag-list">
<view
v-for="item in timeList"
:key="item.value"
class="tag"
:class="{ active: info.time === item.value }"
@click="onTimeTagClick(item.value)"
>
{{ item.text }}
</view>
</view>
<!-- 是否就诊过:逻辑和上面完全一样 -->
<view class="tag-list">
<view
v-for="item in visitList"
:key="item.value"
class="tag"
:class="{ active: info.visit === item.value }"
@click="onVisitTagClick(item.value)"
>
{{ item.text }}
</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue'
// 患病时长:value 是后端接口规定的值,不是随手写的 1、2、3、4
// 不用 ref,因为这组数据从头到尾不会被改,直接当常量用
const timeList = [
{ text: '一周内', value: 1 },
{ text: '一个月内', value: 2 },
{ text: '半年内', value: 3 },
{ text: '半年以上', value: 4 }
]
// 是否就诊过:0 = 没就诊过,1 = 就诊过(同样是后端规定)
const visitList = [
{ text: '没就诊过', value: 0 },
{ text: '就诊过', value: 1 }
]
// 病情数据:初始值给空,保证默认都不高亮,也方便后面做表单校验
const info = ref({
desc: '', // 病情文字描述
time: '', // 患病时长
visit: '' // 是否就诊过
})
// 点击切换患病时长:把传过来的 value 赋给 info.time
const onTimeTagClick = (value) => {
info.value.time = value // 注意 .value 不能丢
}
// 点击切换是否就诊过
const onVisitTagClick = (value) => {
info.value.visit = value
}
</script>
<style scoped>
.description { padding: 20rpx; }
.desc-input {
width: 100%;
height: 200rpx;
padding: 20rpx;
box-sizing: border-box;
border: 1rpx solid #eee;
}
.tag-list { display: flex; flex-wrap: wrap; margin-top: 20rpx; }
.tag {
padding: 10rpx 30rpx;
margin-right: 20rpx;
font-size: 28rpx;
border: 1rpx solid #ddd;
border-radius: 8rpx;
}
.tag.active {
color: #fff;
background-color: #2b7afb;
border-color: #2b7afb;
}
</style>要点解释
- 高亮判断用
info.time === item.value而不是索引值:value既是判断条件,又是将来要提交给后端的值,一步到位;用索引值只能做交互,还得再换算一次。 value的 1/2/3/4 和 0/1 是后端接口规定的,不能为了写交互自己随便定。info用ref包了一层,函数里赋值必须写info.value.time;模板里 Vue 会自动解包,所以模板写info.time。漏掉.value会报undefined之类的错误。- 初始值给空字符串
'',所以一进页面所有标签都不高亮;如果给1,那一周内会默认选中。 :key用item.value而不是索引,保证不重复;v-model只能加在textarea、input这类表单元素上,不能加在view上。class="tag"和:class="{ active: ... }"可以同时写,Vue 会把它们合并,不会互相覆盖。
常见错误
跳转后新页面取不到 type、illnessType 参数
- 现象:进入病情描述页时
defineProps拿到的值是undefined,或页面提示缺少参数。 - 原因:在列表页拼接跳转地址时把已有的两个参数丢了,只拼了科室 ID;或者
defineProps里声明的字段名与地址栏问号后面的 key 拼写不一致。 - 修法:跳转 URL 固定拼三个参数,用反引号模板串 +
&连接;defineProps的字段名直接从跳转处复制,避免手写。建议写成?type=${type}&illnessType=${illnessType}&departmentId=${item.id}这类形式,逐项核对。
- 现象:进入病情描述页时
defineProps报 “not defined” 或取值时提示找不到属性- 现象:控制台出现
defineProps is not defined;或后续写xxx.value时报 undefined。 - 原因:漏写
import { defineProps } from 'vue'(或按项目约定从 vue 导入),或声明了 props 却当成普通变量直接.value访问。 - 修法:补齐导入语句;props 按项目约定访问(模板里直接用名字,脚本里按 props 对象取值),不要把 props 与
ref混用。
- 现象:控制台出现
tab 切换时所有项一起高亮
- 现象:进入页面后“一周内/一个月内/半年内”全部带上了 active 类名。
- 原因:
:class里写了固定类名字符串,没有加判断条件;或判断依据写成了恒真表达式。 - 修法:改成
:class="{ active: form.illnessTime === item.value }",让类名由数据比较结果决定,而不是无条件添加。
点击 tab 后高亮不切换,或切换了但提交值为空
- 现象:点击某一项界面无变化;或界面变了但最终提交的时长字段始终是初始值。
- 原因:点击事件里修改的是索引而不是被选中的 value;或只改了局部变量没改表单对象字段;或
ref漏写导致赋值不生效。 - 修法:点击时把当前项的
value传给处理函数,函数内把表单对应字段赋值为该 value;确认表单对象是用ref/reactive声明的,赋值时带上.value(ref 场景)。
给患病时长设了默认选中,用户没操作就提交了
- 现象:用户未选择时长也能继续,提交数据里带着一个“一周内”。
- 原因:初始化时把时长字段写成了
1(或某个有效枚举值),导致默认命中某一项。 - 修法:初始值设为空字符串或 0 这类不属于枚举范围的值,让所有项默认不高亮;后续做非空校验时也更方便。
把 1/2/3/4、0/1 当成自己随便定的交互值
- 现象:交互跑通了,但对接接口时数值对不上,后端返回参数错误。
- 原因:为了写高亮效果随意定义了枚举值,没有对照接口文档。
- 修法:枚举值以后端接口规定为准(如时长 1=一周内、2=一个月内……,就诊 0=未就诊、1=就诊过);交互直接用这套 value 做比较和提交,不要另造一套索引映射。
图片上传相关:云空间建了但项目用不了
- 现象:调用上传时报错,或提示找不到云开发环境。
- 原因:只在控制台创建了服务空间,没有在项目里创建云开发环境并做关联;或关联后没有重启项目。
- 修法:项目目录右键创建 uniCloud 云开发环境(选阿里云)→ 右键关联到已建的服务空间 → 重启项目使其生效。注意免费空间有期限,到期需续期。
练习
参数链路补全:从科室列表页点击某个二级科室,跳转到病情描述页,要求地址栏同时带上问诊类型、医院类型、科室 ID 三个参数,并在病情描述页用
defineProps接收后打印到控制台验证。故意把其中一个参数名写错,观察报错表现并修正。tab 组件化:把“患病时长”和“是否就诊过”两组 tab 抽成同一套逻辑(可复制结构,也可抽公共组件),要求:数据由数组遍历渲染;点击时更新表单字段;高亮由“当前字段值 === 项的 value”决定;初始状态全部不高亮。
枚举值校验:给病情描述页加一段提交前校验——时长未选、是否就诊未选、文字描述为空时分别给出提示并阻止提交。要求校验逻辑基于接口规定的枚举值(时长 1~4、就诊 0/1),而不是基于索引。
表单数据收集:用
v-model绑定文字描述,配合两组 tab 的选中值,组装出一个包含description、illnessTime、isVisited三个字段的提交对象,点击“下一步”时在控制台打印该对象,确认三项都有值。云环境联通验证:完成服务空间创建 → 项目内创建云开发环境 → 关联 → 重启项目,然后写一个最小验证:调用一次上传或读取云能力的接口,确认能正常返回而不是报“环境不存在”。
课堂画面






原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | 优医咨询-地址传递参数 | 06:04 |
| 2 | 优医咨询-病情描述模板 | 03:03 |
| 3 | 优医咨询-病情描述患病时长处理 | 16:53 |
| 4 | 优医咨询-病情描述文字说明 | 05:20 |
| 5 | 优医咨询-申请阿里云空间 | 04:14 |
| 6 | 优医咨询-创建云开发环境 | 03:18 |
小结
- 页面间传参是链式的:上一页拿到什么就必须原样往下带,新增参数只能追加,不能覆盖。地址栏里出现三个参数,才说明当前上下文(问诊类型 + 医院类型 + 科室)是完整的。
defineProps的字段名必须与地址栏 key 完全一致,最稳的做法是从跳转处复制过来,不要凭记忆手写。- 列表渲染时数据本身就带 ID,不需要额外请求,遍历时顺手拼进跳转地址即可。
- tab 类交互优先用数组遍历 + 条件类名实现,而不是写死几个 div;条件判断用
value比用索引更划算,因为 value 同时就是要提交的数据。 - 交互用的值和提交给后端的值是同一套,枚举以接口文档为准;自己另造索引映射,后面必然要再写一层转换。
- 表单类页面的默认值要谨慎:给了有效枚举值就等于替用户做了选择,初始给空值既符合交互预期,也方便做必填校验。
- 图片上传走云开发比对接后端接口更省事,但前置条件(建空间、建环境、关联、重启)一个都不能少,否则代码写得再对也传不上去。