tmp
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
// components/order-stats/index.js
|
||||
// 首页订单统计卡片:全部完成 / 本月完成 / 未完成
|
||||
const API = require('../../utils/api.js')
|
||||
|
||||
Component({
|
||||
data: {
|
||||
allCount: 0,
|
||||
allFee: 0,
|
||||
monthCount: 0,
|
||||
monthFee: 0,
|
||||
uncompletedCount: 0,
|
||||
uncompletedFee: 0
|
||||
},
|
||||
|
||||
lifetimes: {
|
||||
attached() {
|
||||
this.load()
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* 拉取订单记录并统计三个口径(数量与费用)
|
||||
* 全部完成:status === 'completed'
|
||||
* 本月完成:completed 且预约日期在本月
|
||||
* 未完成:status !== 'completed'
|
||||
* 费用取 payment.totalFee 合计
|
||||
*/
|
||||
load() {
|
||||
API.escort.getAllRecords({ page: 1, pageSize: 200 })
|
||||
.then(res => {
|
||||
if (res.code !== 0) return
|
||||
const records = res.data.records || []
|
||||
const now = new Date()
|
||||
const year = now.getFullYear()
|
||||
const month = now.getMonth()
|
||||
const feeOf = (item) => Number(item.payment && item.payment.totalFee) || 0
|
||||
|
||||
let allCount = 0
|
||||
let allFee = 0
|
||||
let monthCount = 0
|
||||
let monthFee = 0
|
||||
let uncompletedCount = 0
|
||||
let uncompletedFee = 0
|
||||
|
||||
records.forEach(item => {
|
||||
if (item.status === 'completed') {
|
||||
allCount++
|
||||
allFee += feeOf(item)
|
||||
const d = item.schedule && item.schedule.date
|
||||
? new Date(item.schedule.date)
|
||||
: null
|
||||
if (d && !isNaN(d.getTime()) && d.getFullYear() === year && d.getMonth() === month) {
|
||||
monthCount++
|
||||
monthFee += feeOf(item)
|
||||
}
|
||||
} else {
|
||||
uncompletedCount++
|
||||
uncompletedFee += feeOf(item)
|
||||
}
|
||||
})
|
||||
|
||||
this.setData({ allCount, allFee, monthCount, monthFee, uncompletedCount, uncompletedFee })
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('获取订单统计失败', err)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"component": true
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<view class="os-section">
|
||||
<view class="os-header">
|
||||
<text class="os-title">订单统计</text>
|
||||
</view>
|
||||
<view class="os-card">
|
||||
<view class="os-item">
|
||||
<text class="os-num green">{{allCount || 0}}</text>
|
||||
<text class="os-label">全部完成</text>
|
||||
<text class="os-fee">¥{{allFee || 0}}</text>
|
||||
</view>
|
||||
<view class="os-divider"></view>
|
||||
<view class="os-item">
|
||||
<text class="os-num blue">{{monthCount || 0}}</text>
|
||||
<text class="os-label">本月完成</text>
|
||||
<text class="os-fee">¥{{monthFee || 0}}</text>
|
||||
</view>
|
||||
<view class="os-divider"></view>
|
||||
<view class="os-item">
|
||||
<text class="os-num orange">{{uncompletedCount || 0}}</text>
|
||||
<text class="os-label">未完成</text>
|
||||
<text class="os-fee">¥{{uncompletedFee || 0}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -0,0 +1,109 @@
|
||||
/* components/order-stats/index.wxss */
|
||||
|
||||
.os-section {
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
|
||||
.os-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.os-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #1a1a1a;
|
||||
margin-left: 8rpx;
|
||||
letter-spacing: 1rpx;
|
||||
}
|
||||
|
||||
.os-card {
|
||||
background: linear-gradient(135deg, #ffffff 0%, #f3fbf8 100%);
|
||||
border-radius: 24rpx;
|
||||
box-shadow: 0 4rpx 20rpx rgba(23, 195, 165, 0.10);
|
||||
padding: 36rpx 0 32rpx;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 左上角装饰色块,呼应首页头部渐变 */
|
||||
.os-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -40rpx;
|
||||
left: -40rpx;
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, rgba(45, 211, 111, 0.10), rgba(23, 195, 165, 0.10));
|
||||
}
|
||||
|
||||
.os-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.os-num {
|
||||
font-size: 48rpx;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
font-family: 'DIN Alternate', -apple-system, sans-serif;
|
||||
}
|
||||
|
||||
.os-num.green {
|
||||
color: #2dd36f;
|
||||
}
|
||||
|
||||
.os-num.blue {
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.os-num.orange {
|
||||
color: #ff9f43;
|
||||
}
|
||||
|
||||
.os-label {
|
||||
margin-top: 12rpx;
|
||||
font-size: 24rpx;
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
.os-fee {
|
||||
margin-top: 10rpx;
|
||||
font-size: 22rpx;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
padding: 4rpx 16rpx;
|
||||
border-radius: 20rpx;
|
||||
background: rgba(26, 26, 46, 0.05);
|
||||
}
|
||||
|
||||
.os-item:nth-child(1) .os-fee {
|
||||
color: #1ea55c;
|
||||
background: rgba(45, 211, 111, 0.12);
|
||||
}
|
||||
|
||||
.os-item:nth-child(3) .os-fee {
|
||||
color: #3d8fe0;
|
||||
background: rgba(64, 158, 255, 0.12);
|
||||
}
|
||||
|
||||
.os-item:nth-child(5) .os-fee {
|
||||
color: #e08a1e;
|
||||
background: rgba(255, 159, 67, 0.14);
|
||||
}
|
||||
|
||||
.os-divider {
|
||||
width: 1rpx;
|
||||
margin: 8rpx 0;
|
||||
background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, #e8e8e8 30%, #e8e8e8 70%, rgba(0, 0, 0, 0) 100%);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"component": true
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user