医疗急救卡
介绍
该小程序实现了form
表单的写入以及对数据的增加,修改,删除,查询的功能。将写入的数据存入小程序的本地缓存Storage
中,对缓存数据进行操作,同时对一些表单数据进行了表单验证功能。
要求
示例
导读指导
1. 什么是本地缓存?
每个微信小程序都可以有自己的本地缓存,可以通过 wx.setStorage/wx.setStorageSync、 wx.getStorage/wx.getStorageSync、 wx.clearStorage/wx.clearStorageSync
wx.removeStorage/wx.removeStorageSync
对本地缓存进行读写和清理。上面的set和get都有对应的Sync方法,带Sync的方法为同步方法、不带Sync的方法为异步方法。
缓存可以保存数组、数值、字符串、对象。
不懂可以继续看一看官方文档
微信开放文档
2.什么是form表单?
表单。将组件内的用户输入的switch input checkbox slider radio picker 提交。
当点击 form 表单中 form-type 为 submit 的 button 组件时,会将表单组件中的 value 值进行提交,需要在表单组件中加上 name 来作为 key。
先看一下部分代码
在代码
<form bindsubmit="{{!create ? 'onSubmit':'Updated'}}" bindreset="
{{!create ? 'onReset':'Deleted'}}">
我采取了动态绑定函数。在上一个音乐播放器中也是这样,
因为这样写可以省略许多的代码,使代码格式简洁。
因为创建表单信息和修改表单信息,都是通过对整个form进行操作。
当点击完成创建按钮时,表单会调用onSubmit函数,同时拿到整个表单中的值。
写入的值可以通过 e.detail.value 拿取。
<view class="demo-box" wx:if="{{!create}}">
<button class="button" formType="submit">完成创建</button>
<button class="button" formType="reset">重置医疗急救卡</button>
</view>
<view class="demo-box" wx:else>
<button class="button" bindtap="Callphone">打电话给紧急联系人</button>
<button class="button" formType="submit">编辑医疗急救卡</button>
<button class="button" formType="reset" bindtap="onReset">删除医疗急救卡 </button>
<button class="button" bindtap="Clear">删除所有医疗急救卡</button>
</view>
wxml
<!--pages/saveCard/saveCard.wxml-->
<view class="container">
<view class="demo-box">
<form bindsubmit="{{!create ? 'onSubmit':'Updated'}}"
bindreset="{{!create ?
'onReset':'Deleted'}}">
<view class="box center">
<picker end="{{Time}}" fields="day" name="date" mode="date"
bindchange="dateChange">
<span class="title">出生日期
</span>
{{date}}
</picker>
</view>
<view class="box">
<text class="title">医疗状况</text>
<scroll-view class="scroll" scroll-y>
<textarea placeholder="无" name="health" value="{{health}}" />
</scroll-view>
</view>
<view class="box">
<text class="title">医疗笔记</text>
<scroll-view class="scroll" scroll-y>
<textarea placeholder="无" name="note" value="{{note}}" />
</scroll-view>
</view>
<view class="box">
<text class="title">过敏反应</text>
<scroll-view class="scroll" scroll-y>
<textarea placeholder="无" name="action" value="{{action}}" />
</scroll-view>
</view>
<view class="box">
<text class="title">用药</text>
<scroll-view class="scroll" scroll-y>
<textarea placeholder="无" name="medicine" value="{{medicine}}" />
</scroll-view>
</view>
<view class="box center">
<picker name="blood" class="" mode="selector" range="{{blood}}"
bindchange="selectorChange">
<span class="title">血型
</span>
{{selector}}
</picker>
</view>
<view class="box center">
<span class="title">器官捐赠者
</span>
<switch name="switch" bindchange="switchChange" />
</view>
<view class="box center">
<view class="high">
<view class="title">身高
</view>
<input name="high" value="{{high}}" type="number" />厘米
</view>
<view class="weight">
<view class="title">体重
</view>
<input name="weight" value="{{weight}}" type="number" />千克
</view>
</view>
<view class="box">
<span class="title">紧急联系人号码
</span>
<input name="phoneNumber" value="{{phoneNumber}}" type="number" />
</view>
<view class="demo-box" wx:if="{{!create}}">
<button class="button" formType="submit">完成创建</button>
<button class="button" formType="reset">重置医疗急救卡</button>
</view>
<view class="demo-box" wx:else>
<button class="button" bindtap="Callphone">打电话给紧急联系人</button>
<button class="button" formType="submit">编辑医疗急救卡</button>
<button class="button" formType="reset"
bindtap="onReset">删除医疗急救卡</button>
<button class="button" bindtap="Clear">删除所有医疗急救卡</button>
</view>
</form>
</view>
</view>
正式开启小程序实战
时间选择器-picker
wxml
// End 是picker 自带的api 可以对时间选择器进行范围控制
// 我采取了动态绑定 实现了 当前选择器不能选择超过当前日子的时间
// fields有效值 year,month,day,表示选择器的粒度
<view class="box center">
<picker end="{{Time}}" fields="day" name="date" mode="date" bindchange="dateChange">
<span class="title">出生日期
</span>
{{date}}
</picker>
</view>
// 获取当前时间 并转换格式 year-month-day
let month = Number(new Date().getMonth() + 1) < 10 ? '0' +
Number(new Date().getMonth() +
1) : Number(new Date().getMonth() + 1)
let day = new Date().getDate() < 10 ? '0' + new Date().getDate()
: new Date().getDate()
var Time = new Date().getFullYear() + '-' + month + '-' + day
// 确保时间 是动态 的数据
onLoad(options) {
this.setData({
Time: Time
})
},
// 动态改变选择器的值
dateChange: function (e) {
let value = e.detail.value;
this.setData({
date: value
})
},
textarea文本输入框
文本输入框只能有一行显示,并且带有滚动效果。
wxml
利用scroll-y 实现滚动效果 不过要设置一个固定的高度。
<view class="box">
<text class="title">医疗状况</text>
<scroll-view class="scroll" scroll-y>
<textarea placeholder="无" name="health" value="{{health}}" />
</scroll-view>
</view>
单列选择器-血型-picker
注意这里的selector通过表单拿到的数据为blood的一个下标
因为 blood: [‘未知’, ‘A型’, ‘B型’, ‘C型’, ‘AB型’, ‘O型’]
wxml
<view class="box center">
<picker name="blood" class="" mode="selector" range="{{blood}}"
bindchange="selectorChange">
<span class="title">血型
</span>
{{selector}}
</picker>
</view>
js
// 动态改变选择器的值
// 将拿到的i进行重新获取 血型再继续赋值
selectorChange: function (e) {
let i = e.detail.value;
let value = this.data.blood[i];
this.setData({
selector: value
})
},
switch选择器
注意事项,就是在管理页面显示的时候我们是以 是,否 显示,所以要创建一个键值对对象包含该值
而创建页中,我们只是单纯以switch
开关显示。
wxml
创建页
<view class="box center">
<span class="title">器官捐赠者
</span>
<switch checked="{{Donated}} name="switch" bindchange="switchChange" />
</view>
管理页
显示
<view class="box center">
<view class="small-box">
<span class="title">是否是器官捐赠者 </span>
{{Donated[switch]}}
</view>
</view>
修改
// checked 动态绑定
<view class="box center">
<span class="title">器官捐赠者
</span>
<switch checked="{{switch}}" name="switch" bindchange="switchChange" />
</view>
js
// 创建页
Donated: false,
switchChange: function (e) {4
let value = e.detail.value;
this.setData({
Donated: value
})
}
// 管理页
Donated: {
false: '否',
true: '是'
},
switch: '',
单文本输入框
wxml
<view class="box center">
<view class="high">
<view class="title">身高
</view>
<input name="high" value="{{high}}" type="number" />厘米
</view>
<view class="weight">
<view class="title">体重
</view>
<input name="weight" value="{{weight}}" type="number" />千克
</view>
</view>
创建功能实现
实现了表单验证功能,保证出生日期,血型,以及电话号码为必填项,且非必填会自动默认为空。
将表单提交中拿到的血型的下标 重新拿取血型值,并赋值给缓存中的blood
,将数据存入到本地缓存,并创建一个独特的key。
js
onSubmit(e) {
// console.log(e.detail);
var that = this;
// 实现表单验证
if (e.detail.value.date === '') {
wx.showToast({
title: '出生日期为空',
duration: 500,
icon: 'none'
})
} else if (e.detail.value.blood === '') {
wx.showToast({
title: '血型未选择',
duration: 500,
icon: 'none'
})
} else if (e.detail.value.phoneNumber === '') {
wx.showToast({
title: '电话号码为空',
duration: 500,
icon: 'none'
})
} else {
// 非必填项 默认为空
if (this.data.health === '') {
e.detail.value.health = '空'
}
if (this.data.note === '') {
e.detail.value.note = '空'
}
if (this.data.action === '') {
e.detail.value.action = '空'
}
if (this.data.medicine === '') {
e.detail.value.medicine = '空'
}
// 将表单提交的数据进行赋值
that.setData({
create: true,
date: e.detail.value.date,
health: e.detail.value.health,
note: e.detail.value.note,
action: e.detail.value.action,
medicine: e.detail.value.medicine,
Donated: e.detail.value.switch,
high: e.detail.value.high,
weight: e.detail.value.weight,
phoneNumber: e.detail.value.phoneNumber
})
// console.log(e.detail.value);
let i = e.detail.value.blood
e.detail.value.blood = that.data.blood[i]
// console.log('form发生了submit事件,携带数据为:', e.detail.value)
// console.log(this.data);
// 最后进行介绍
if (!app.globalData.Number.includes(app.globalData.count)) {
app.globalData.Number.push(app.globalData.count)
app.globalData.count++;
} else {
app.globalData.count++;
if(app.globalData.Number.includes(app.globalData.count)){
for(let i=1;i<app.globalData.Number.length;i++){
if(!app.globalData.Number.includes(i)){
app.globalData.Number.push(i)
}
}
}
else{
app.globalData.Number.push(app.globalData.count)
}
}
// console.log(app.globalData.count, '???', app.globalData.Number);
wx.setStorage({
key: myCard + app.globalData.Number[app.globalData.Number.length-1],
data: e.detail.value,
// 若开启加密存储,setStorage 和 getStorage 需要同时声明 encrypt 的值为 true
success: function (res) {
wx.showToast({
title: myCard + app.globalData.Number[app.globalData.Number.length-1] + '创建成功',
icon: 'none',
duration: 500
})
}
})
}
},
删除功能
部分删除
删除当前正在编辑的数据,如果删除完后,按弹窗的取消将返回首页,按确定将再次进行一次删除操作。如果数据被删完了,则弹出数据为0,无法删除的提示,并且返回首页。
js
Deleted: function (e) {
if (app.globalData.count === 0 && app.globalData.Number[app.globalData.Number.length - 1] === 0) {
wx.showToast({
title: '数据为0,无法删除',
icon: 'none'
})
setTimeout(() => {
wx.navigateBack({
url: '/pages/index/index',
})
}, 1000)
} else {
let name = myCard + app.globalData.Number[app.globalData.Number.length-1]
wx.removeStorage({
key: name,
success: function (res) {
// wx.showToast({
// title: name+'删除成功',
// icon: 'none'
// })
wx.showModal({
title: '是否要继续删除',
content: '',
complete: (res) => {
if (res.cancel) {
wx.showToast({
title: myCard + app.globalData.Number[app.globalData.Number.length-1] + '删除成功',
icon: 'none'
})
setTimeout(() => {
wx.navigateBack({
url: '/pages/index/index',
})
}, 1000)
app.globalData.count--;
app.globalData.Number.pop()
// console.log(app.globalData.count, '!!!', app.globalData.Number);
}
if (res.confirm) {
if (app.globalData.count === 0 && app.globalData.Number[app.globalData.Number.length - 1]) {
wx.showToast({
title: '数据为0,无法删除,请先创建数据',
icon: 'none'
})
setTimeout(() => {
wx.navigateBack({
url: '/pages/index/index',
})
}, 1000)
} else {
wx.removeStorage({
key: myCard + app.globalData.Number[app.globalData.Number.length - 1],
success: function (res) {
wx.showToast({
title: myCard + app.globalData.Number[app.globalData.Number.length - 1] + '删除成功',
icon: 'none'
})
app.globalData.count--;
app.globalData.Number.pop();
// console.log(app.globalData.count, '!!!', app.globalData.Number);
}
})
}
}
}
})
}
})
}
},
全部删除
将本地缓存的数据利用wx.clearStorage();
全部删除。同时将数据重新置空,并且返回首页
js
Clear: function (e) {
this.setData({
date: '',
health: '',
note: '',
action: '',
medicine: '',
selector: '',
Donated: false,
high: '',
weight: '',
phoneNumber: ''
})
wx.clearStorage();
app.globalData.count = 0;
app.globalData.Number = [0];
wx.showToast({
title: '所有数据已全部删除',
icon: 'none',
duration: 500
})
setTimeout(() => {
wx.navigateBack({
url: '/pages/index/index',
})
}, 1000)
}
由于文章篇幅问题,还有数据编辑函数,以及管理页面,按患者的序号进行管理的代码先不介绍了。大致与创建差不多。
不过有一个前面留下的难点。
难点就是实现管理页对数据进行删除,而不影响创建页创建数据。
换个说法。就是比如我们创建了四个患者的数据,当我们在管理页时对患者1的数据进行删除。当我们重新回到创建页时,创建数据,系统默认我们创建的内容是患者1。也就是不会让数据存在空档。
首先我在app.js中
全局创建了两个属性
globalData: {
count : 0, // 患者数量
// 其中Number 更像是一个栈,栈底每次存的都是当前要处理数据的患者的序号
// 添加数据 就将该序号进栈,删除数据 就将该数据进行出栈。
Number:[0] // 当前要处理数据的患者的序号
}
其次在创建页拿取app.js中的数据
const app = getApp()
// 判断 是否 经过了管理数据 对数据进行选择型删除
// 按照正常顺序对数据进行删除 那么 个数 刚好与对应的 序号一致
// 创建 0 [0] 1 [0,1] 2 [0,1,2]
//删除 1 [0,1]
if (!app.globalData.Number.includes(app.globalData.count)) {
// 非正常删除
// 2 [0,1,2] 删除了序号为1的数据
// 1 [0,2] 因为栈里面没有1 于是将1先入栈 当前要管理的数据序号为1
// 然后数量+1 count++
app.globalData.Number.push(app.globalData.count)
app.globalData.count++;
}
else {
// 非正常删除的另一种情况
// 3 [0,1,2,3]
// 对1 进行删除
// 2 [0,2,3]
栈里面包含 序号为2的患者
于是我们就要重新给新的患者取序号,可是如果我们继续count++,
然后赋值发现去掉患者序号为3 发现又重复了。
于是我们开始从1开始遍历,直到找到一个栈里面不存在且靠前的一个序号。1将它入栈
// 3 [0,2,3,1]
app.globalData.count++;
if(app.globalData.Number.includes(app.globalData.count)){
for(let i=1;i<app.globalData.Number.length;i++){
if(!app.globalData.Number.includes(i)){
app.globalData.Number.push(i)
}
}
}
// 正常删除
// 按照正常顺序对数据进行删除 那么 个数 刚好与对应的 序号一致
// 创建 0 [0] 1 [0,1] 2 [0,1,2]
//删除 1 [0,1]
// 添加 2 [0,1,2]
else{
app.globalData.Number.push(app.globalData.count)
}
}
删除栈里面指定序号的序号
// 个数先进行减1
app.globalData.count--;
// console.log(num);
// 特别注意因为count 为数字 存到数组里也是数字
//但是 输入的number 为字符串 要转换格式 才能删除
// 拿到指定元素 在栈里的下标 删除1个
let i = app.globalData.Number.indexOf(Number(num));
app.globalData.Number.splice(i,1);
源码链接
文章不易,希望大佬给动动小手,给我点个赞。谢谢!!!
原文链接:https://juejin.cn/post/7218208891707752485 作者:Mr-Wang-Y-P