Browse Source

心率联调

dev
kola-web 2 days ago
parent
commit
1d07555c45
  1. 19
      src/components/pickerArea/index.ts
  2. 1248
      src/components/popup/index.scss
  3. 69
      src/components/popup/index.wxml
  4. BIN
      src/images/badge1.png
  5. BIN
      src/images/badge2.png
  6. BIN
      src/images/bg13.png
  7. BIN
      src/images/bg14.png
  8. BIN
      src/images/bg15.png
  9. BIN
      src/images/bg16.png
  10. BIN
      src/images/clsoe.png
  11. 1
      src/pages/articleDetail/index.scss
  12. 5
      src/pages/followForm/index.ts
  13. 8
      src/pages/followForm/index.wxml
  14. 68
      src/pages/health/index.scss
  15. 175
      src/pages/health/index.ts
  16. 69
      src/pages/health/index.wxml
  17. 68
      src/pages/heartDetail/index.ts
  18. 16
      src/pages/heartDetail/index.wxml
  19. 3
      src/pages/heartForm/index.json
  20. 157
      src/pages/heartForm/index.ts
  21. 39
      src/pages/heartForm/index.wxml
  22. 8
      src/pages/index/index.scss
  23. 13
      src/pages/index/index.ts
  24. 20
      src/pages/index/index.wxml
  25. 2
      src/pages/myCollection/index.ts
  26. 12
      src/pages/videoList/index.scss
  27. 9
      src/pages/videoList/index.wxml

19
src/components/pickerArea/index.ts

@ -257,17 +257,26 @@ Component({ @@ -257,17 +257,26 @@ Component({
})
},
handleShare() {
const { ProvinceName, ProvinceId, CityName, CityId } = this.data
if (!ProvinceId) {
wx.showToast({ title: '请选择省份', icon: 'none' })
return
}
if (!CityId) {
wx.showToast({ title: '请选择城市', icon: 'none' })
return
}
this.setData({
show: false,
})
this.triggerEvent('change', [
{
label: this.data.ProvinceName,
value: this.data.ProvinceId,
label: ProvinceName,
value: ProvinceId,
},
{
label: this.data.CityName,
value: this.data.CityId,
label: CityName,
value: CityId,
},
])
},
@ -286,7 +295,7 @@ Component({ @@ -286,7 +295,7 @@ Component({
range,
active: 1,
scrollIntoView0: '',
scrollIntoView1: `id${this.data.CityId}`,
scrollIntoView1: this.data.CityId ? `id${this.data.CityId}` : '',
})
},
handleProvince() {

1248
src/components/popup/index.scss

File diff suppressed because it is too large Load Diff

69
src/components/popup/index.wxml

@ -9,35 +9,48 @@ @@ -9,35 +9,48 @@
safe-area-inset-bottom="{{false}}"
root-portal
>
<view class="popup1" wx:if="{{type==='argument'}}">
<image class="logo" src="{{imageUrl}}logo1.png?t={{Timestamp}}"></image>
<view class="title">欢迎加入“愈见守护”</view>
<!-- 心率提醒-引导关注公众号 -->
<view class="popup1" wx:if="{{type==='popup1'}}">
<view class="popup-container" style="background: url('/images/bg13.png') no-repeat top center/100%">
<view class="title">关注“星动守护”</view>
<view class="content">我们将在每周五下午7点提醒您记录</view>
<image class="code" src="/images/bg1.png" show-menu-by-longpress></image>
</view>
</view>
<!-- 保存复诊记录成功-引导关注公众号 -->
<view class="popup2" wx:if="{{type==='popup2'}}">
<view class="popup-container">
<image class="badge" src="/images/badge1.png"></image>
<view class="container" style="background: url('/images/bg15.png') no-repeat top center/100%">
<view class="title">保存复诊记录成功!</view>
<view class="code-wrap" style="background: url('/images/bg14.png') no-repeat top center/100%">
<image class="code" src="/images/bg1.png" show-menu-by-longpress></image>
</view>
<view class="content">
关注“心动守护”公众号
<view></view>
获得服务通知
</view>
</view>
</view>
</view>
<!-- 保持心率成功-引导关注公众号 -->
<view class="popup3" wx:if="{{type==='popup3'}}">
<view class="popup-container">
<image class="badge" src="/images/badge2.png"></image>
<view class="container" style="background: url('/images/bg15.png') no-repeat top center/100%">
<view class="title">保存复诊记录成功!</view>
<view class="code-wrap" style="background: url('/images/bg14.png') no-repeat top center/100%">
<image class="code" src="/images/bg1.png" show-menu-by-longpress></image>
</view>
<view class="content">
亲爱的用户,为了更好地向您提供平台服务保护您的权益,我们完善了
<text class="link" bind:tap="routerTo" data-url="/doc/pages/doc1/index?type=1">《个人信息及隐私政策》</text>
,请您仔细阅读。一旦您开始使用,即表示您已充分理解并同意协议内容。
</view>
<view class="check">
<checkbox
class="checkbox"
model:checked="{{popup1Check1}}"
bind:tap="handlePopup1Check1"
color="#f23a2f"
></checkbox>
<view class="c-content">
我特此同意
<text class="link" bind:tap="routerTo" data-url="/doc/pages/doc1/index?type=1">《个人信息及隐私政策》</text>
规定收集我的相关敏感个人信息
</view>
</view>
<view class="btn1" bind:tap="handleOk">同意并继续</view>
<view class="btn2" bind:tap="handleCancel">不同意</view>
关注“心动守护”公众号
<view></view>
获得服务通知
</view>
</view>
</view>
</view>
<image
wx:if="{{params.close}}"
class="close"
src="{{imageUrl}}icon25.png?t={{Timestamp}}"
bind:tap="handleCancel"
></image>
<image wx:if="{{params.close}}" class="close" src="/images/clsoe.png" bind:tap="handleCancel"></image>
</van-popup>

BIN
src/images/badge1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

BIN
src/images/badge2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

BIN
src/images/bg13.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

BIN
src/images/bg14.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
src/images/bg15.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 KiB

BIN
src/images/bg16.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

BIN
src/images/clsoe.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

1
src/pages/articleDetail/index.scss

@ -169,6 +169,7 @@ page { @@ -169,6 +169,7 @@ page {
position: fixed;
bottom: 0;
left: 0;
z-index: 10;
width: 100%;
padding: 0 30rpx calc(env(safe-area-inset-bottom) + 30rpx) 20rpx;
box-sizing: border-box;

5
src/pages/followForm/index.ts

@ -3,9 +3,10 @@ const app = getApp<IAppOption>() @@ -3,9 +3,10 @@ const app = getApp<IAppOption>()
Page({
data: {
popupShow: false,
popupType: '',
popupType: 'popup2',
popupParams: {
position: 'bottom',
position: 'center',
close: true,
} as any,
topicShow: false,

8
src/pages/followForm/index.wxml

@ -88,3 +88,11 @@ @@ -88,3 +88,11 @@
<view class="send" bind:tap="handleSubmit">保存记录</view>
</view>
</view>
<popup
show="{{popupShow}}"
type="{{popupType}}"
params="{{popupParams}}"
bind:ok="handlePopupOk"
bind:cancel="handlePopupCancel"
></popup>

68
src/pages/health/index.scss

@ -70,6 +70,25 @@ page { @@ -70,6 +70,25 @@ page {
height: 24rpx;
}
}
.week-alert {
display: flex;
align-items: center;
gap: 12rpx;
font-size: 28rpx;
color: rgba(30, 41, 59, 1);
.wx-checkbox-input {
width: 32rpx;
height: 32rpx;
border-radius: 8rpx;
&.wx-checkbox-input-checked {
background: linear-gradient(270deg, #439fc7 0%, #2f82a9 100%);
border-color: transparent;
&::before {
color: #fff;
}
}
}
}
}
.stats-grid {
margin: 32rpx 30rpx 0;
@ -151,6 +170,55 @@ page { @@ -151,6 +170,55 @@ page {
}
}
}
.list {
.list-card {
margin: 24rpx 30rpx;
padding: 32rpx;
border-radius: 32rpx;
border: 2rpx solid #fff;
background: rgba(255, 255, 255, 0.7);
box-shadow: 0 16rpx 64rpx 0 rgba(0, 99, 132, 0.04);
backdrop-filter: blur(10rpx);
.lc-header {
display: flex;
align-items: center;
justify-content: space-between;
.status {
padding: 8rpx 16rpx;
font-size: 24rpx;
border-radius: 12rpx;
&.status1 {
color: rgba(47, 130, 169, 1);
background-color: rgba(47, 130, 169, 0.05);
}
&.status2 {
color: rgba(234, 88, 26, 1);
background-color: rgba(234, 88, 26, 0.08);
}
}
.date {
font-size: 28rpx;
color: rgba(100, 116, 139, 1);
}
}
.row {
margin-top: 32rpx;
display: flex;
.label {
flex-shrink: 0;
font-size: 32rpx;
color: rgba(148, 163, 184, 1);
line-height: 44rpx;
}
.content {
padding-left: 32rpx;
font-size: 32rpx;
color: rgba(30, 41, 59, 1);
line-height: 44rpx;
}
}
}
}
}
.body3 {

175
src/pages/health/index.ts

@ -6,12 +6,12 @@ const PAGE_SIZE = 10 @@ -6,12 +6,12 @@ const PAGE_SIZE = 10
Page({
data: {
popupShow: false,
popupType: '',
popupType: 'popup1',
popupParams: {
position: 'bottom',
close: true,
} as any,
tab: 2,
tab: 0,
offsetTop: 0,
// 复诊记录
@ -21,10 +21,24 @@ Page({ @@ -21,10 +21,24 @@ Page({
pages: 1,
count: 0,
},
startMonth: '',
endMonth: '',
daysSinceLastRevisit: 0,
totalRevisits: 0,
startMonth: '',
endMonth: '',
// 心率记录
heartRateList: [] as any[],
heartRatePagination: {
page: 1,
pages: 1,
count: 0,
},
heartStats: {
lastHeartRate: 0,
attackCount: 0,
maxHeartRate: 0,
},
},
ecDataTrendComponent: null as any,
_loaded: false,
@ -40,8 +54,14 @@ Page({ @@ -40,8 +54,14 @@ Page({
app.waitLogin({ type: 0 }).then(() => {
this._loaded = true
if (this.data.tab === 1) {
this.getHeartStats()
this.getHeartChart()
this.getHeartRateList()
} else if (this.data.tab === 2) {
this.getRevisitList()
this.getLastRevisit()
}
})
},
onReady() {
@ -63,20 +83,35 @@ Page({ @@ -63,20 +83,35 @@ Page({
if (query.tab !== undefined) {
const tab = Number(query.tab)
this.setData({ tab })
if (tab === 2) {
if (tab === 1) {
this.getHeartStats()
this.getHeartChart()
this.getHeartRateList()
} else if (tab === 2) {
this.getRevisitList()
this.getLastRevisit()
}
return
}
}
if (this._loaded && this.data.tab === 2) {
if (this._loaded) {
if (this.data.tab === 1) {
this.getHeartStats()
this.getHeartChart()
this.getHeartRateList()
} else if (this.data.tab === 2) {
this.getRevisitList()
this.getLastRevisit()
}
}
},
onReachBottom() {
if (this.data.tab === 2) {
if (this.data.tab === 1) {
const { heartRatePagination } = this.data
if (heartRatePagination.page < heartRatePagination.pages) {
this.getHeartRateList(heartRatePagination.page + 1, true)
}
} else if (this.data.tab === 2) {
const { revisitPagination } = this.data
if (revisitPagination.page < revisitPagination.pages) {
this.getRevisitList(revisitPagination.page + 1, true)
@ -86,7 +121,11 @@ Page({ @@ -86,7 +121,11 @@ Page({
onChange(e: any) {
const { index } = e.detail
this.setData({ tab: index })
if (index === 2) {
if (index === 1) {
this.getHeartStats()
this.getHeartChart()
this.getHeartRateList()
} else if (index === 2) {
this.getRevisitList()
this.getLastRevisit()
}
@ -134,11 +173,21 @@ Page({ @@ -134,11 +173,21 @@ Page({
},
onStartMonthChange(e: any) {
this.setData({ startMonth: e.detail.value })
if (this.data.tab === 1) {
this.getHeartChart()
this.getHeartRateList()
} else {
this.getRevisitList()
}
},
onEndMonthChange(e: any) {
this.setData({ endMonth: e.detail.value })
if (this.data.tab === 1) {
this.getHeartChart()
this.getHeartRateList()
} else {
this.getRevisitList()
}
},
handleRevisitTap(e: any) {
const { id } = e.currentTarget.dataset
@ -146,13 +195,83 @@ Page({ @@ -146,13 +195,83 @@ Page({
url: `/pages/followDetail/index?id=${id}`,
})
},
handleAddRevisit() {
handleHeartTap(e: any) {
const { id } = e.currentTarget.dataset
wx.navigateTo({
url: `/pages/heartDetail/index?id=${id}`,
})
},
handleAdd() {
if (this.data.tab === 1) {
wx.navigateTo({
url: '/pages/heartForm/index',
})
} else if (this.data.tab === 2) {
wx.navigateTo({
url: '/pages/followForm/index',
})
}
},
initChart() {
const arr = ['2026-06-01', '2026-06-02', '2026-06-03', '2026-06-04', '2026-06-05', '2026-06-06', '2026-06-07']
getHeartRateList(page = 1, append = false) {
const { startMonth, endMonth } = this.data
wx.ajax({
method: 'GET',
url: '?r=psvt/heart-rate-record/list',
data: {
page,
count: PAGE_SIZE,
startMonth,
endMonth,
},
}).then((res: any) => {
const list = res.list || []
this.setData({
heartRateList: append ? this.data.heartRateList.concat(list) : list,
heartRatePagination: {
page: res.page || 1,
pages: res.pages || 1,
count: res.count || 0,
},
})
})
},
getHeartStats() {
wx.ajax({
method: 'GET',
url: '?r=psvt/heart-rate-record/statistics',
}).then((res: any) => {
const lastRecord = res?.lastRecord || {}
this.setData({
heartStats: {
lastHeartRate: lastRecord.heartRate || 0,
attackCount: res?.attackCount || 0,
maxHeartRate: res?.maxHeartRate || 0,
},
})
})
},
getHeartChart() {
const { startMonth, endMonth } = this.data
wx.ajax({
method: 'GET',
url: '?r=psvt/heart-rate-record/chart-data',
data: { startMonth, endMonth },
}).then((res: any) => {
this.initChart(res || [])
})
},
initChart(chartData: any[] = []) {
const xAxisData = chartData.map((item: any) => item.recordDateTime)
const seriesData = chartData.map((item: any) => {
const isAttack = Number(item.isPsvtAttack) === 1
return {
value: Number(item.heartRate),
itemStyle: isAttack
? { color: '#d62828', borderColor: '#fff' }
: { color: '#fff', borderColor: '#46bc70', borderWidth: 2 },
}
})
this.ecDataTrendComponent.init((canvas, width, height, dpr) => {
const chart = echarts.init(canvas, null, {
width,
@ -166,7 +285,7 @@ Page({ @@ -166,7 +285,7 @@ Page({
{
type: 'inside',
startValue: 0,
endValue: 6,
endValue: Math.max(chartData.length - 1, 6),
xAxisIndex: [0],
},
],
@ -222,8 +341,11 @@ Page({ @@ -222,8 +341,11 @@ Page({
type: 'category',
axisLabel: {
color: 'rgba(148, 163, 184, 1)',
formatter: function (value) {
const [_year, month, day] = value.split('-')
formatter: (value) => {
if (!value) return ''
const parts = value.split(' ')
const datePart = parts[0] || ''
const [_year, month, day] = datePart.split('-')
return `${month}/${day}`
},
},
@ -236,7 +358,7 @@ Page({ @@ -236,7 +358,7 @@ Page({
splitLine: {
show: false,
},
data: arr,
data: xAxisData,
},
yAxis: [
{
@ -265,15 +387,22 @@ Page({ @@ -265,15 +387,22 @@ Page({
symbol: 'circle',
symbolSize: 8,
lineStyle: { color: '#46bc70', width: 2 },
data: seriesData,
markArea: {
itemStyle: {
color: 'rgba(45, 190, 141, 0.07)',
},
data: [
{ value: 62, itemStyle: { color: '#fff', borderColor: '#46bc70', borderWidth: 2 } },
{ value: 60, itemStyle: { color: '#fff', borderColor: '#46bc70', borderWidth: 2 } },
{ value: 61, itemStyle: { color: '#fff', borderColor: '#46bc70', borderWidth: 2 } },
{ value: 66, itemStyle: { color: '#d62828', borderColor: '#fff' } },
{ value: 63, itemStyle: { color: '#fff', borderColor: '#46bc70', borderWidth: 2 } },
{ value: 69, itemStyle: { color: '#d62828', borderColor: '#fff' } },
{ value: 64, itemStyle: { color: '#fff', borderColor: '#46bc70', borderWidth: 2 } },
[
{
yAxis: 60,
},
{
yAxis: 100,
},
],
],
},
},
],
}

69
src/pages/health/index.wxml

@ -26,53 +26,82 @@ @@ -26,53 +26,82 @@
<view class="body2">
<view class="body-op">
<view class="date-range">
<picker mode="date">
<view class="date">2026.01</view>
<picker mode="date" fields="month" value="{{startMonth}}" bind:change="onStartMonthChange">
<view class="date">{{startMonth}}</view>
</picker>
-
<picker mode="date">
<view class="date">2026.01</view>
<picker mode="date" fields="month" value="{{endMonth}}" bind:change="onEndMonthChange">
<view class="date">{{endMonth}}</view>
</picker>
<image class="icon" src="{{imageUrl}}icon25.png?t={{Timestamp}}"></image>
</view>
<view class="week-alert">
<checkbox class="check"></checkbox>
每周提醒我
</view>
</view>
<view class="stats-grid">
<view class="stat-card">
<view class="stat-label">最近1次</view>
<view class="stat-value">
<text class="stat-number">59</text>
<text class="stat-number">{{heartStats.lastHeartRate}}</text>
<text class="stat-unit">次/分</text>
</view>
</view>
<view class="stat-card">
<view class="stat-label">最近发作</view>
<view class="stat-value">
<text class="stat-number">2</text>
<text class="stat-number">{{heartStats.attackCount}}</text>
<text class="stat-unit">次</text>
</view>
</view>
<view class="stat-card">
<view class="stat-label">最高心率</view>
<view class="stat-value">
<text class="stat-number">156</text>
<text class="stat-number">{{heartStats.maxHeartRate}}</text>
<text class="stat-unit">次/分</text>
</view>
</view>
</view>
<view class="chart">
<ec-canvas id="chart1" ec="{{ ec }}"></ec-canvas>
<div class="legend">
<div class="l-item">
<div class="dot1"></div>
<view class="legend">
<view class="l-item">
<view class="dot1"></view>
正常心率
</div>
<div class="l-item">
<div class="dot2"></div>
</view>
<view class="l-item">
<view class="dot2"></view>
发作心率
</div>
</div>
</view>
</view>
</view>
<view class="list">
<view
class="list-card"
wx:for="{{heartRateList}}"
wx:key="id"
data-id="{{item.id}}"
bind:tap="handleHeartTap"
>
<view class="lc-header">
<view class="status {{item.isPsvtAttack === 1 ? 'status2' : 'status1'}}">
{{item.isPsvtAttack === 1 ? 'PSVT发作' : '未发作'}}
</view>
<view class="date">{{item.recordDateTime}}</view>
</view>
<view class="row">
<view class="label">心率</view>
<view class="content">{{item.heartRate}}次/分</view>
</view>
<view class="row" wx:if="{{item.remark}}">
<view class="label">备注</view>
<view class="content">{{item.remark}}</view>
</view>
</view>
</view>
<pagination pagination="{{heartRatePagination}}" />
</view>
</van-tab>
<van-tab title="复诊记录">
<view class="body3">
@ -116,6 +145,14 @@ @@ -116,6 +145,14 @@
</van-tabs>
</view>
<view class="fixed-add" bind:tap="handleAddRevisit">
<view class="fixed-add" bind:tap="handleAdd">
<image class="icon" src="{{imageUrl}}icon24.png?t={{Timestamp}}"></image>
</view>
<popup
show="{{popupShow}}"
type="{{popupType}}"
params="{{popupParams}}"
bind:ok="handlePopupOk"
bind:cancel="handlePopupCancel"
></popup>

68
src/pages/heartDetail/index.ts

@ -8,10 +8,54 @@ Page({ @@ -8,10 +8,54 @@ Page({
position: 'bottom',
} as any,
fileList: [] as any[],
id: '',
detail: {} as any,
},
onLoad() {
app.waitLogin({ type: 0 }).then(() => {})
onLoad(options: any) {
if (options.id) {
this.setData({ id: options.id })
app.waitLogin({ type: 'any' }).then(() => {
this.getDetail(options.id)
})
}
},
getDetail(id: string) {
wx.ajax({
method: 'GET',
url: '?r=psvt/heart-rate-record/detail',
data: { id },
}).then((res: any) => {
this.setData({ detail: res || {} })
})
},
handleDelete() {
const { id } = this.data
wx.showModal({
title: '提示',
content: '确定删除该心率记录吗?',
success: (res) => {
if (!res.confirm) return
wx.ajax({
method: 'POST',
url: '?r=psvt/heart-rate-record/delete',
data: { id: Number(id) },
}).then(() => {
wx.showToast({ title: '删除成功', icon: 'success' })
setTimeout(() => {
wx.navigateBack()
}, 1000)
})
},
})
},
handleEdit() {
const { id } = this.data
wx.navigateTo({
url: `/pages/heartForm/index?id=${id}`,
})
},
handleBack() {
wx.navigateBack()
},
handlePopupOk() {
const { popupType } = this.data
@ -71,24 +115,6 @@ Page({ @@ -71,24 +115,6 @@ Page({
})
}
},
handleWechatWork() {
wx.navigateTo({
url: '/pages/wechatWork/index',
})
},
handleSetData(e) {
const { fileList } = this.data
this.setData({
fileList: [...fileList, ...e.detail],
})
},
handleDeleteFile(e) {
const { index } = e.detail
const { fileList } = this.data
this.setData({
fileList: fileList.filter((_, i) => i !== index),
})
},
})
export {}

16
src/pages/heartDetail/index.wxml

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
<navbar fixed custom-style="background:{{background}}" back>
<view class="page-title" slot="left">
<view class="page-title" slot="left" bind:tap="handleBack">
<van-icon name="arrow-left" />
心率记录详情
</view>
@ -13,25 +13,23 @@ @@ -13,25 +13,23 @@
<view class="form-item">
<view class="form-label">日期</view>
<view class="date">
<view class="content">2026.07.06 21:30</view>
<view class="content">{{detail.recordDateTime || ''}}</view>
</view>
</view>
<view class="form-item">
<view class="form-label">心率</view>
<view class="date">
<view class="content">65</view>
<view class="content">{{detail.heartRate || ''}}</view>
</view>
</view>
<view class="form-item">
<view class="form-label">其他备注</view>
<view class="remark">
本次复诊心悸发作频率较上次减少,发作持续时间约5–10分钟,含服药物后可自行缓解。医生建议继续规律服药,避免剧烈运动及情绪激动,定期复查心电图。
<view class="remark">{{detail.remark || ''}}</view>
</view>
</view>
<checkbox class="check" disabled>PSVT发作</checkbox>
<checkbox class="check" disabled checked="{{detail.isPsvtAttack === 1}}">PSVT发作</checkbox>
</view>
<view class="page-footer">
<view class="cancel">删除</view>
<view class="send">编辑</view>
<view class="cancel" bind:tap="handleDelete">删除</view>
<view class="send" bind:tap="handleEdit">编辑</view>
</view>
</view>

3
src/pages/heartForm/index.json

@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
"popup": "/components/popup/index",
"navbar": "/components/navbar/index",
"uploadFile": "/components/uploadFile/index",
"van-popup": "@vant/weapp/popup/index"
"van-popup": "@vant/weapp/popup/index",
"van-datetime-picker": "@vant/weapp/datetime-picker/index"
}
}

157
src/pages/heartForm/index.ts

@ -3,15 +3,144 @@ const app = getApp<IAppOption>() @@ -3,15 +3,144 @@ const app = getApp<IAppOption>()
Page({
data: {
popupShow: false,
popupType: '',
popupType: 'popup3',
popupParams: {
position: 'bottom',
position: 'center',
close: true,
} as any,
fileList: [] as any[],
id: '',
heartRate: '',
recordDateTime: '',
datetimePickerShow: false,
datetimeValue: Date.now(),
isPsvtAttack: 0,
remark: '',
isEdit: false,
},
onLoad(options: any) {
if (options.id) {
this.setData({ id: options.id, isEdit: true })
app.waitLogin({ type: 'any' }).then(() => {
this.getDetail(options.id)
})
} else {
app.waitLogin({ type: 'any' }).then(() => {})
}
},
getDetail(id: string) {
wx.ajax({
method: 'GET',
url: '?r=psvt/heart-rate-record/detail',
data: { id },
}).then((res: any) => {
if (!res) return
const recordDateTime = res.recordDateTime || ''
// 解析为时间戳供picker使用
let datetimeValue = Date.now()
if (recordDateTime) {
const ts = new Date(recordDateTime.replace(/-/g, '/')).getTime()
if (!isNaN(ts)) datetimeValue = ts
}
// 显示格式 YYYY-MM-DD HH:mm(去掉秒)
const display = recordDateTime ? recordDateTime.replace(/:(\d{2})$/, '') : ''
this.setData({
heartRate: String(res.heartRate || ''),
recordDateTime: display,
datetimeValue,
isPsvtAttack: res.isPsvtAttack ?? 0,
remark: res.remark || '',
})
})
},
onHeartRateInput(e: any) {
this.setData({ heartRate: e.detail.value })
},
showDatetimePicker() {
this.setData({ datetimePickerShow: true })
},
hideDatetimePicker() {
this.setData({ datetimePickerShow: false })
},
onDatetimeConfirm(e: any) {
const date = new Date(e.detail)
const y = date.getFullYear()
const m = String(date.getMonth() + 1).padStart(2, '0')
const d = String(date.getDate()).padStart(2, '0')
const h = String(date.getHours()).padStart(2, '0')
const min = String(date.getMinutes()).padStart(2, '0')
const recordDateTime = `${y}-${m}-${d} ${h}:${min}`
this.setData({
recordDateTime,
datetimeValue: e.detail,
datetimePickerShow: false,
})
},
onPsvtAttackChange(e: any) {
const checked = (e.detail.value || []).includes('1')
this.setData({ isPsvtAttack: checked ? 1 : 0 })
},
onRemarkInput(e: any) {
this.setData({ remark: e.detail.value })
},
handleSubmit() {
const { id, heartRate, recordDateTime, isPsvtAttack, remark, isEdit } = this.data
if (!heartRate) {
wx.showToast({ title: '请输入心率数值', icon: 'none' })
return
}
if (!recordDateTime) {
wx.showToast({ title: '请选择日期时间', icon: 'none' })
return
}
// API需要 Y-m-d H:i:s 格式,补秒
const data = {
heartRate: Number(heartRate),
recordDateTime: `${recordDateTime}:00`,
isPsvtAttack,
remark,
}
wx.showLoading({ title: '保存中' })
if (isEdit) {
wx.ajax({
method: 'POST',
url: '?r=psvt/heart-rate-record/update',
data: { id: Number(id), ...data },
})
.then(() => {
wx.hideLoading()
wx.showToast({ title: '保存成功', icon: 'success' })
setTimeout(() => {
wx.navigateBack()
}, 1000)
})
.catch(() => {
wx.hideLoading()
})
} else {
wx.ajax({
method: 'POST',
url: '?r=psvt/heart-rate-record/create',
data,
})
.then(() => {
wx.hideLoading()
wx.showToast({ title: '保存成功', icon: 'success' })
setTimeout(() => {
wx.navigateBack()
}, 1000)
})
.catch(() => {
wx.hideLoading()
})
}
},
onLoad() {
app.waitLogin({ type: 0 }).then(() => {})
handleBack() {
wx.navigateBack()
},
handlePopupOk() {
const { popupType } = this.data
@ -71,24 +200,6 @@ Page({ @@ -71,24 +200,6 @@ Page({
})
}
},
handleWechatWork() {
wx.navigateTo({
url: '/pages/wechatWork/index',
})
},
handleSetData(e) {
const { fileList } = this.data
this.setData({
fileList: [...fileList, ...e.detail],
})
},
handleDeleteFile(e) {
const { index } = e.detail
const { fileList } = this.data
this.setData({
fileList: fileList.filter((_, i) => i !== index),
})
},
})
export {}

39
src/pages/heartForm/index.wxml

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
<navbar fixed custom-style="background:{{background}}" back>
<view class="page-title" slot="left">
<view class="page-title" slot="left" bind:tap="handleBack">
<van-icon name="arrow-left" />
心率记录
</view>
@ -13,27 +13,44 @@ @@ -13,27 +13,44 @@
<view class="rate">
<view class="r-title">当前心率数值</view>
<view class="wrap">
<input class="input" placeholder-class="input-place" type="number" placeholder="00" maxlength="{{3}}" />
<input class="input" placeholder-class="input-place" type="number" placeholder="00" maxlength="{{3}}" value="{{heartRate}}" bindinput="onHeartRateInput" />
<view class="unit">次/分</view>
</view>
</view>
<view class="form-item">
<view class="form-label">日期</view>
<picker mode="date">
<view class="date">
<view class="content" data-place="请选择日期"></view>
<view class="form-label">日期时间</view>
<view class="date" bind:tap="showDatetimePicker">
<view class="content" data-place="请选择日期时间">{{recordDateTime}}</view>
<van-icon class="icon" name="arrow-down" />
</view>
</picker>
</view>
<view class="form-item">
<view class="form-label">其他备注</view>
<textarea class="txa" placeholder-class="txa-place" placeholder="请输入备注内容" maxlength="{{500}}"></textarea>
<textarea class="txa" placeholder-class="txa-place" placeholder="请输入备注内容" value="{{remark}}" bindinput="onRemarkInput" maxlength="{{500}}"></textarea>
</view>
<checkbox class="check">PSVT发作</checkbox>
<checkbox-group bind:change="onPsvtAttackChange">
<checkbox class="check" value="1" checked="{{isPsvtAttack === 1}}">PSVT发作</checkbox>
</checkbox-group>
</view>
<view class="page-footer">
<view class="cancel">取消</view>
<view class="send">保存记录</view>
<view class="cancel" bind:tap="handleBack">取消</view>
<view class="send" bind:tap="handleSubmit">保存记录</view>
</view>
</view>
<van-popup show="{{datetimePickerShow}}" position="bottom" round bind:close="hideDatetimePicker">
<van-datetime-picker
type="datetime"
value="{{datetimeValue}}"
bind:confirm="onDatetimeConfirm"
bind:cancel="hideDatetimePicker"
/>
</van-popup>
<popup
show="{{popupShow}}"
type="{{popupType}}"
params="{{popupParams}}"
bind:ok="handlePopupOk"
bind:cancel="handlePopupCancel"
></popup>

8
src/pages/index/index.scss

@ -150,6 +150,13 @@ page { @@ -150,6 +150,13 @@ page {
display: flex;
flex-direction: column;
justify-content: flex-end;
.title {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
}
}
}
@ -210,6 +217,7 @@ page { @@ -210,6 +217,7 @@ page {
}
.i-list {
margin: 32rpx 30rpx 0;
min-height: 80vh;
.list-card {
margin-top: 32rpx;
padding: 32rpx;

13
src/pages/index/index.ts

@ -22,11 +22,11 @@ Page({ @@ -22,11 +22,11 @@ Page({
sectionList: [] as Array<{ code: string; visible: boolean; subList: any[] }>,
moduleVisible: {
health: true,
'spread1': true,
spread1: true,
'video-big': true,
'spread2': true,
spread2: true,
'qiye-wx': true,
'education': true,
education: true,
} as Record<string, boolean>,
},
onLoad() {
@ -51,10 +51,7 @@ Page({ @@ -51,10 +51,7 @@ Page({
}).then((res: any) => {
const list = res || []
list.forEach((item: any) => {
if (
(item.code === 'spread1' || item.code === 'spread2' || item.code === 'serviceConf') &&
item.subList
) {
if ((item.code === 'spread1' || item.code === 'spread2' || item.code === 'serviceConf') && item.subList) {
item.subList = item.subList.filter((subItem: any) => subItem.showStatus == 1)
}
})
@ -70,8 +67,8 @@ Page({ @@ -70,8 +67,8 @@ Page({
const conf = list.find((item: any) => item.code === code)
return {
code,
visible: conf ? conf.showStatus == 1 : false,
subList: conf?.subList || [],
visible: conf ? (conf.showStatus == 1 && (conf.subList || []).length > 0) : false,
}
})
.sort((a, b) => {

20
src/pages/index/index.wxml

@ -25,7 +25,14 @@ @@ -25,7 +25,14 @@
<!-- code: spread1 首页banner -->
<view class="banner" wx:if="{{item.code==='spread1' && item.visible}}">
<swiper class="swiper1">
<swiper-item wx:for="{{item.subList}}" wx:key="subIndex" wx:for-item="subItem" wx:for-index="subIndex" data-linkurl="{{subItem.linkUrl}}" bind:tap="handleBannerTap">
<swiper-item
wx:for="{{item.subList}}"
wx:key="subIndex"
wx:for-item="subItem"
wx:for-index="subIndex"
data-linkurl="{{subItem.linkUrl}}"
bind:tap="handleBannerTap"
>
<image class="s-img" mode="aspectFill" src="{{subItem.img}}"></image>
</swiper-item>
</swiper>
@ -51,7 +58,14 @@ @@ -51,7 +58,14 @@
<!-- code: spread2 banner2模块 -->
<view class="banner" wx:if="{{item.code==='spread2' && item.visible}}">
<swiper class="swiper2">
<swiper-item wx:for="{{item.subList}}" wx:key="subIndex" wx:for-item="subItem" wx:for-index="subIndex" data-linkurl="{{subItem.linkUrl}}" bind:tap="handleBannerTap">
<swiper-item
wx:for="{{item.subList}}"
wx:key="subIndex"
wx:for-item="subItem"
wx:for-index="subIndex"
data-linkurl="{{subItem.linkUrl}}"
bind:tap="handleBannerTap"
>
<image class="s-img" mode="aspectFill" src="{{subItem.img}}"></image>
</swiper-item>
</swiper>
@ -112,10 +126,10 @@ @@ -112,10 +126,10 @@
</view>
</view>
</view>
</view>
<pagination pagination="{{pagination}}" />
</view>
</view>
</view>
<view wx:if="{{backTop}}" class="back-top" bind:tap="handleBackTop">
<image class="icon" src="{{imageUrl}}icon11.png?t={{Timestamp}}"></image>

2
src/pages/myCollection/index.ts

@ -19,7 +19,7 @@ Page({ @@ -19,7 +19,7 @@ Page({
count: 0,
},
},
onLoad() {
onShow() {
app.waitLogin({ type: 0 }).then(() => {
this.getVideoList()
this.getArticleList()

12
src/pages/videoList/index.scss

@ -5,6 +5,7 @@ page { @@ -5,6 +5,7 @@ page {
.page-title {
font-size: 36rpx;
color: rgba(51, 51, 51, 1);
padding-right: 100rpx;
}
.page {
@ -74,6 +75,16 @@ page { @@ -74,6 +75,16 @@ page {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 48rpx 30rpx;
.card-wrap {
position: relative;
.hot {
position: absolute;
top: -10rpx;
left: 24rpx;
width: 104rpx;
height: 48rpx;
z-index: 1;
}
.card {
display: block;
width: 100%;
@ -136,3 +147,4 @@ page { @@ -136,3 +147,4 @@ page {
}
}
}
}

9
src/pages/videoList/index.wxml

@ -55,13 +55,19 @@ @@ -55,13 +55,19 @@
</view>
<view class="list">
<view
class="card"
class="card-wrap"
wx:for="{{videoList}}"
wx:key="Id"
bind:tap="handleDetail"
data-id="{{item.Id}}"
data-index="{{index}}"
>
<view
class="hot"
wx:if="{{item.IsRecommend==1}}"
style="background: url('{{imageUrl}}bg16.png?t={{Timestamp}}') no-repeat top center/100%"
></view>
<view class="card">
<view class="photo">
<image class="p-img" mode="aspectFill" src="{{item.ImageUrl}}"></image>
<view class="stat">
@ -83,5 +89,6 @@ @@ -83,5 +89,6 @@
<view class="title">{{item.Title}}</view>
</view>
</view>
</view>
<pagination pagination="{{pagination}}" />
</view>

Loading…
Cancel
Save