This commit is contained in:
lik
2026-09-03 11:35:21 +08:00
parent f8f7afceb8
commit b4c8bf0add
45 changed files with 2989 additions and 426 deletions
+80
View File
@@ -0,0 +1,80 @@
// components/patient-info/index.js
// 患者/健康档案两行信息项组件
// 第一行:姓名 + 性别(左) · 年龄(右)
// 第二行:电话(左,可选拨打) · 所在地(右)
//
// 两种用法:
// 1. 直接传展示字段(name/sexLabel/ageText/mobile/locationText),适用于列表批量渲染
// 2. 只传 profile-id,组件内部加载档案:优先读全局缓存(utils/store.js),未命中再请求
// 加载完成后触发 loaded 事件(携带档案原始文档),展示字段以加载结果为准
const store = require('../../utils/store.js')
const { calcAge } = require('../../utils/format.js')
Component({
properties: {
name: { type: String, value: '' },
sexLabel: { type: String, value: '' },
ageText: { type: String, value: '' },
mobile: { type: String, value: '' },
locationText: { type: String, value: '' },
// 是否显示"拨打"并触发 call 事件
dial: { type: Boolean, value: false },
// 健康档案ID:传入后组件内部加载,展示字段以加载结果为准
profileId: {
type: String,
value: '',
observer(newVal) {
if (newVal) this.loadProfile(newVal)
}
},
// 是否读取缓存:true 缓存优先(默认),false 直接请求最新数据(请求成功后仍回填缓存)
useCache: { type: Boolean, value: true }
},
methods: {
onCallTap() {
if (!this.data.mobile) return
this.triggerEvent('call', { mobile: this.data.mobile })
},
/**
* 按档案ID加载:缓存优先,未命中再请求
*/
loadProfile(id) {
const cached = store.getProfile(id)
if (cached) {
this.applyProfile(cached)
return
}
const API = require('../../utils/api.js')
API.healthProfile.getProfileById(id)
.then(res => {
if (res.code !== 0 || !res.data || !res.data.profile) return
const profile = res.data.profile
store.cacheProfile(profile)
this.applyProfile(profile)
})
.catch(err => {
console.error('获取健康档案失败', err)
})
},
/**
* 将档案文档映射为展示字段,并抛出 loaded 事件
*/
applyProfile(profile) {
const p = profile.profile || {}
const loc = profile.location || {}
const age = calcAge(p.birth)
const sexLabel = p.sex === 'male' ? '男' : (p.sex === 'female' ? '女' : '')
this.setData({
name: p.name || '',
sexLabel,
ageText: age ? `${age}` : '',
mobile: p.mobile || '',
locationText: [loc.province, loc.city].filter(Boolean).join(' ')
})
this.triggerEvent('loaded', { profile })
}
}
})
+3
View File
@@ -0,0 +1,3 @@
{
"component": true
}
+21
View File
@@ -0,0 +1,21 @@
<view class="pi-item">
<view class="pi-avatar">
<text>{{name[0]}}</text>
</view>
<view class="pi-main">
<view class="pi-line">
<view class="pi-name-row">
<text class="pi-name">{{name}}</text>
<text wx:if="{{sexLabel}}" class="pi-sex {{sexLabel === '男' ? 'male' : 'female'}}">{{sexLabel}}</text>
</view>
<text wx:if="{{ageText}}" class="pi-extra">{{ageText}}</text>
</view>
<view class="pi-line">
<view class="pi-mobile-wrap">
<text class="pi-mobile">{{mobile || '暂无电话'}}</text>
<text wx:if="{{dial && mobile}}" class="pi-call" catchtap="onCallTap">拨打</text>
</view>
<text wx:if="{{locationText}}" class="pi-extra">{{locationText}}</text>
</view>
</view>
</view>
+93
View File
@@ -0,0 +1,93 @@
.pi-item {
display: flex;
align-items: center;
}
.pi-avatar {
width: 72rpx;
height: 72rpx;
border-radius: 50%;
background-color: #e6f9f3;
color: #1abc9c;
font-size: 30rpx;
font-weight: 600;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.pi-main {
flex: 1;
min-width: 0;
margin-left: 20rpx;
}
.pi-line {
display: flex;
align-items: center;
justify-content: space-between;
}
.pi-line + .pi-line {
margin-top: 6rpx;
}
.pi-name-row {
display: flex;
align-items: center;
gap: 12rpx;
min-width: 0;
}
.pi-name {
font-size: 30rpx;
font-weight: 600;
color: #1a1a1a;
}
.pi-sex {
font-size: 20rpx;
padding: 2rpx 12rpx;
border-radius: 8rpx;
font-weight: 500;
flex-shrink: 0;
}
.pi-sex.male {
background: rgba(26, 188, 156, 0.1);
color: #1abc9c;
}
.pi-sex.female {
background: rgba(234, 102, 150, 0.1);
color: #ea6696;
}
.pi-mobile-wrap {
display: flex;
align-items: center;
min-width: 0;
}
.pi-mobile {
font-size: 24rpx;
color: #888888;
}
.pi-call {
font-size: 24rpx;
color: #1abc9c;
font-weight: 500;
margin-left: 8rpx;
}
.pi-extra {
font-size: 24rpx;
color: #888888;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-left: 16rpx;
flex-shrink: 0;
}