feat: 电子药箱小程序 - 4Tab药品管理

- 电子药箱: 药品库存管理 + 手动录入 + 今日用药打卡
- 药品百科: 搜索 + 分类筛选 + 20种药品静态数据
- 惠教中心: 4条药品使用指南课程
- 我的: 家庭成员信息管理
- 自定义TabBar + navigation-bar组件
- SVG药品分类插图
This commit is contained in:
陈誉午
2026-07-29 11:20:52 +08:00
commit 994b267f5c
683 changed files with 43849 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
{
"usingComponents": {
"navigation-bar": "/components/navigation-bar/navigation-bar"
}
}
+80
View File
@@ -0,0 +1,80 @@
/* pages/common/red/red.wxss */
.body {
// display: flex;
// justify-content: center;
// flex-direction: column;
// flex: 1;
width: 750rpx;
.bg {
background-color: #f25f4d;
margin: 24rpx;
margin-bottom:0rpx ;
max-height:100%;
border-radius: 24rpx;
display: flex;
flex-direction: column;
position: relative;
overflow: hidden;
.content {
background-color: #f15642;
position: absolute;
top: 0;
width: 100%;
height: 13vh;
border-bottom-left-radius: 50%;
border-bottom-right-radius: 50%;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}
.item-container {
width: 100%;
margin-top: 13vh;
.content-item {
color: #fed9b2;
margin: 24rpx;
height: 75vh;
overflow: auto;
}
.item {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
padding: 8px 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.15);
.avatar {
width: 80rpx;
height: 80rpx;
border-radius: 20rpx;
}
.info{
width: 89%;
.nickname {
margin-left: 24rpx;
display: flex;
justify-content: space-between;
font-size: 36rpx;
font-weight: 800;
}
.time{
margin-left: 24rpx;
display: flex;
justify-content: space-between;
}
}
}
}
}
}
.safeBottom{
width: 100%;
// background: yellow;
display: block;
}
+90
View File
@@ -0,0 +1,90 @@
// pages/common/red/red.ts
import { wxLogin } from '../../../utils/wx-api'
import { request } from '../../../utils/request'
const app = getApp<IAppOption>()
const defaultAvatarUrl =
'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0'
const formatDate = (isoString: string): string => {
const date = new Date(isoString);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}`;
};
const getState = (state: number) => {
switch (state) {
case 40:
return '领取成功'
case 50:
return '红包已过期'
default:
return '正在发放中'
}
}
Page({
data: {
list: [] as any[],
defaultAvatarUrl: defaultAvatarUrl,
safeBottom: app.globalData.safeBottom,
safeTop: app.globalData.safeTop
},
async onLoad(options: { state: string }) {
// const bool = await app.login('red');
// if (!bool) return;
try {
const code = await wxLogin();
let res;
const loginRes = await request({
options: {
url: '/operation/vdo-red/auth-resultV1', //领取红包
method: "GET",
data: {
code: code.code,
state: options.state
}
},
needLogin:false
})
res = await request({
options: {
url: '/operation/vdo-red/result', //查询红包
data: {
openId: loginRes,
state: options.state
}
},
needLogin:false
})
const list = res.data.map((item: any) => ({
...item,
date: formatDate(item.createdTime),
stateText: getState(item.state)
}))
this.setData({ list })
// res = { //mock
// data: [
// {
// avatar: defaultAvatarUrl,
// nickname: 'x5',
// amount: 13343,
// date: '2025-11-21 09:11',
// state: 40
// }
// ]
// }
} catch (e) {
wx.redirectTo({
url: '/pages/error/error?msg=请求错误'
})
return
}
},
})
+29
View File
@@ -0,0 +1,29 @@
<!--pages/common/red/red.wxml-->
<!-- <navigation-bar title="红包详情" back="{{false}}" color="black" background="#FFF"></navigation-bar> -->
<view class="body">
<view class="bg"
style="height: calc(100vh - {{safeBottom}}rpx - {{safeTop}}rpx);margin-top: {{safeTop}}rpx;">
<view class="content"></view>
<view class="item-container">
<view class="content-item">
<block wx:for="{{list}}" wx:key="openId">
<view class="item">
<image class="avatar" src="{{item.avatar ||defaultAvatarUrl}}"></image>
<view class="info">
<view class="nickname">
<text class="name">{{item.nickname}}</text>
<text class="price">{{item.amount / 100}}元</text>
</view>
<view class="time">
<text>{{item.date}}</text>
<text>{{item.stateText}}</text>
</view>
</view>
</view>
</block>
</view>
</view>
</view>
<div class="safeBottom" style="height: {{safeBottom}}rpx;"></div>
</view>