Compare commits

...

10 Commits
master ... dev

Author SHA1 Message Date
kola-web 957454fa40 bug fix + 活动页面 8 hours ago
kola-web 3a3eecdfc5 帖子编辑附件带上id 10 hours ago
kola-web 2617836a4c ui走查问题处理 11 hours ago
kola-web 5748cc3468 活动页面开发 15 hours ago
kola-web e5eeffffb7 bug fix 2 days ago
kola-web 8e242c2227 首页联调 2 days ago
kola-web 1d07555c45 心率联调 2 days ago
kola-web b554bc3bd8 登录调整 3 days ago
kola-web 04e39b9eb0 首页联调 3 days ago
kola-web 90eae5c44c 复诊记录联调 3 days ago
  1. 2
      project.config.json
  2. 11
      project.private.config.json
  3. 3
      public/images/arrow-right-blue.svg
  4. 9
      public/images/heart-line.svg
  5. 2
      src/api/request.ts
  6. 4
      src/app.json
  7. 54
      src/app.ts
  8. 11
      src/components/pagination/index.scss
  9. 14
      src/components/pagination/index.wxml
  10. 37
      src/components/pickerArea/index.ts
  11. 1324
      src/components/popup/index.scss
  12. 108
      src/components/popup/index.ts
  13. 88
      src/components/popup/index.wxml
  14. 20
      src/components/uploadFile/index.js
  15. 2
      src/components/uploadFile/index.scss
  16. 8
      src/components/uploadFile/index.wxml
  17. 73
      src/custom-tab-bar/index.ts
  18. BIN
      src/images/badge1.png
  19. BIN
      src/images/badge2.png
  20. BIN
      src/images/badge3.png
  21. BIN
      src/images/bg12.png
  22. BIN
      src/images/bg13.png
  23. BIN
      src/images/bg14.png
  24. BIN
      src/images/bg15.png
  25. BIN
      src/images/bg16.png
  26. BIN
      src/images/bg17.png
  27. BIN
      src/images/bg18.png
  28. BIN
      src/images/bg19.png
  29. BIN
      src/images/bg20.png
  30. BIN
      src/images/bg21.png
  31. BIN
      src/images/bg7.png
  32. 22
      src/images/chat/chat-bg.svg
  33. 9
      src/images/chat/chat-btn-bg.svg
  34. 4
      src/images/chat/chat-logo.svg
  35. BIN
      src/images/chat/chat-mascot.png
  36. 5
      src/images/chat/icon-what.svg
  37. 5
      src/images/chat/icon-who.svg
  38. BIN
      src/images/clsoe.png
  39. BIN
      src/images/icon10.png
  40. BIN
      src/images/icon15.png
  41. BIN
      src/images/icon21-active.png
  42. BIN
      src/images/icon21.png
  43. BIN
      src/images/icon22-active.png
  44. BIN
      src/images/icon22.png
  45. BIN
      src/images/icon43.png
  46. BIN
      src/images/icon44.png
  47. BIN
      src/images/icon45.png
  48. BIN
      src/images/icon46.png
  49. BIN
      src/images/icon47.png
  50. BIN
      src/images/icon48.png
  51. BIN
      src/images/icon8-1.png
  52. BIN
      src/images/icon8.png
  53. BIN
      src/images/icon9-1.png
  54. BIN
      src/images/icon9.png
  55. BIN
      src/images/share-img1.png
  56. BIN
      src/images/tabbar/tabbar1-4.png
  57. BIN
      src/images/title1.png
  58. BIN
      src/images/title2.png
  59. 10
      src/pages/articleDetail/index.scss
  60. 4
      src/pages/articleDetail/index.ts
  61. 19
      src/pages/articleDetail/index.wxml
  62. 4
      src/pages/articleVideoDetail/index.ts
  63. 9
      src/pages/bag/index.json
  64. 355
      src/pages/bag/index.scss
  65. 139
      src/pages/bag/index.ts
  66. 144
      src/pages/bag/index.wxml
  67. 18
      src/pages/changeTel/index.ts
  68. 7
      src/pages/chat/index.json
  69. 155
      src/pages/chat/index.scss
  70. 25
      src/pages/chat/index.ts
  71. 55
      src/pages/chat/index.wxml
  72. 28
      src/pages/confirmInfo/index.scss
  73. 52
      src/pages/confirmInfo/index.ts
  74. 13
      src/pages/confirmInfo/index.wxml
  75. 17
      src/pages/drugMap/index.scss
  76. 3
      src/pages/drugMap/index.ts
  77. 11
      src/pages/drugMap/index.wxml
  78. 3
      src/pages/followDetail/index.scss
  79. 79
      src/pages/followDetail/index.ts
  80. 31
      src/pages/followDetail/index.wxml
  81. 8
      src/pages/followForm/index.scss
  82. 217
      src/pages/followForm/index.ts
  83. 66
      src/pages/followForm/index.wxml
  84. 3
      src/pages/health/index.json
  85. 84
      src/pages/health/index.scss
  86. 407
      src/pages/health/index.ts
  87. 121
      src/pages/health/index.wxml
  88. 6
      src/pages/heartDetail/index.scss
  89. 73
      src/pages/heartDetail/index.ts
  90. 18
      src/pages/heartDetail/index.wxml
  91. 3
      src/pages/heartForm/index.json
  92. 21
      src/pages/heartForm/index.scss
  93. 228
      src/pages/heartForm/index.ts
  94. 46
      src/pages/heartForm/index.wxml
  95. 3
      src/pages/hotTopic/index.json
  96. 1
      src/pages/hotTopic/index.scss
  97. 46
      src/pages/hotTopic/index.ts
  98. 9
      src/pages/hotTopic/index.wxml
  99. 3
      src/pages/hotTopicDetail/index.json
  100. 60
      src/pages/hotTopicDetail/index.scss
  101. Some files were not shown because too many files have changed in this diff Show More

2
project.config.json

@ -66,7 +66,7 @@
], ],
"include": [] "include": []
}, },
"appid": "wxd9e68fd8ad8cc3f6", "appid": "wx903aa29742dad363",
"scripts": { "scripts": {
"beforeCompile": "pnpm run beforeCompile", "beforeCompile": "pnpm run beforeCompile",
"beforePreview": "pnpm run beforeCompile", "beforePreview": "pnpm run beforeCompile",

11
project.private.config.json

@ -23,13 +23,20 @@
"miniprogram": { "miniprogram": {
"list": [ "list": [
{ {
"name": "修改手机号", "name": "随行包",
"pathName": "pages/changeTel/index", "pathName": "pages/bag/index",
"query": "", "query": "",
"scene": null, "scene": null,
"launchMode": "default" "launchMode": "default"
}, },
{ {
"name": "修改手机号",
"pathName": "pages/changeTel/index",
"query": "",
"launchMode": "default",
"scene": null
},
{
"name": "隐私协议", "name": "隐私协议",
"pathName": "doc/pages/doc/index", "pathName": "doc/pages/doc/index",
"query": "", "query": "",

3
public/images/arrow-right-blue.svg

@ -0,0 +1,3 @@
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.14286 6.85714H0V5.14286H5.14286V0H6.85714V5.14286H12V6.85714H6.85714V12H5.14286V6.85714Z" fill="#2F82A9"/>
</svg>

After

Width:  |  Height:  |  Size: 222 B

9
public/images/heart-line.svg

@ -0,0 +1,9 @@
<svg width="97" height="25" viewBox="0 0 97 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.44" d="M0 13.5699H3.01554L5.02591 11.057L6.53368 15.0777L8.04145 13.5699L9.04663 16.5855L12.0622 0.502591L13.5699 24.1244L15.5803 11.057L16.5855 14.5751L17.0881 13.5699H18.0933L20.1036 10.5544L21.6114 13.5699H97" stroke="url(#paint0_linear_48838_377)" stroke-width="1.00518" stroke-linejoin="round"/>
<defs>
<linearGradient id="paint0_linear_48838_377" x1="0" y1="12.3135" x2="97" y2="12.3135" gradientUnits="userSpaceOnUse">
<stop stop-color="#2F82A9"/>
<stop offset="1" stop-color="#2F82A9" stop-opacity="0"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 658 B

2
src/api/request.ts

@ -78,5 +78,5 @@ function errPicker(err) {
if (typeof err === 'string') { if (typeof err === 'string') {
return err return err
} }
return err.data || err.msg || err.errMsg || (err.detail && err.detail.errMsg) || '未知错误' return err.data || err.msg || err.message || err.errMsg || (err.detail && err.detail.errMsg) || '未知错误'
} }

4
src/app.json

@ -26,7 +26,9 @@
"pages/myComment/index", "pages/myComment/index",
"pages/myCollection/index", "pages/myCollection/index",
"pages/userInfo/index", "pages/userInfo/index",
"pages/changeTel/index" "pages/changeTel/index",
"pages/bag/index",
"pages/chat/index"
], ],
"subPackages": [ "subPackages": [
{ {

54
src/app.ts

@ -25,15 +25,15 @@ App<IAppOption>({
globalData: { globalData: {
// dev // dev
// appid:wx903aa29742dad363 // appid:wx903aa29742dad363
// url: 'https://m.psvt.hbraas.com', url: 'https://m.psvt.hbraas.com',
// upFileUrl: 'https://m.psvt.hbraas.com/', upFileUrl: 'https://m.psvt.hbraas.com/',
// imageUrl: 'https://m.psvt.hbraas.com/psvt/', imageUrl: 'https://m.psvt.hbraas.com/psvt/',
// pro // pro
// appid:wxd9e68fd8ad8cc3f6 // appid:wxd9e68fd8ad8cc3f6
url: 'https://m.psvt.hbsaas.com', // url: 'https://m.psvt.hbsaas.com',
upFileUrl: 'https://m.psvt.hbsaas.com/', // upFileUrl: 'https://m.psvt.hbsaas.com/',
imageUrl: 'https://m.psvt.hbsaas.com/psvt/', // imageUrl: 'https://m.psvt.hbsaas.com/psvt/',
Timestamp: new Date().getTime(), Timestamp: new Date().getTime(),
@ -61,9 +61,18 @@ App<IAppOption>({
}) })
}, },
onShow(options) { onShow(options) {
console.log('DEBUGPRINT[316]: app.ts:63: options=', JSON.stringify(options))
let sceneData: any = {}
if (options.query.scene) { if (options.query.scene) {
this.globalData.scene = parseScene(options.query.scene) as { workerId: string } sceneData = parseScene(options.query.scene) || {}
} }
// 渠道码:优先取 scene 中解析的 cid,其次取 query 中直接传入的 cid
const channelId = sceneData.cid || sceneData.channelId || options.query.cid || ''
if (channelId) {
sceneData.channelId = channelId
}
this.globalData.scene = sceneData
this.startLogin() this.startLogin()
}, },
startLogin(callback?: () => void) { startLogin(callback?: () => void) {
@ -91,9 +100,7 @@ App<IAppOption>({
return new Promise((resolve) => { return new Promise((resolve) => {
const checkLogin = () => { const checkLogin = () => {
if (this.globalData.loginState) { if (this.globalData.loginState) {
if (this.checkLoginType(type)) { resolve(this.checkLoginType(type, false))
resolve()
}
return return
} }
setTimeout(() => { setTimeout(() => {
@ -103,7 +110,7 @@ App<IAppOption>({
checkLogin() checkLogin()
}) })
}, },
checkLoginType(type = 'any') { checkLoginType(type = 'any', confirm = false) {
const { isLogin, isReg } = this.globalData.initLoginInfo const { isLogin, isReg } = this.globalData.initLoginInfo
if (type === 'any') { if (type === 'any') {
@ -111,18 +118,18 @@ App<IAppOption>({
} }
if (!isLogin) { if (!isLogin) {
this.redirectToLogin('/pages/login/index') this.redirectToLogin('/pages/login/index', confirm)
return false return false
} }
if (!isReg) { if (!isReg) {
this.redirectToLogin('/pages/confirmInfo/index') this.redirectToLogin('/pages/confirmInfo/index', confirm)
return false return false
} }
return true return true
}, },
redirectToLogin(path) { redirectToLogin(path, confirm) {
// 获取当前页面路径 // 获取当前页面路径
const pages = getCurrentPages() const pages = getCurrentPages()
const currentPage = pages[pages.length - 1] const currentPage = pages[pages.length - 1]
@ -137,15 +144,22 @@ App<IAppOption>({
this.globalData.loginRedirectUrl = query ? `${currentUrl}?${query}` : currentUrl this.globalData.loginRedirectUrl = query ? `${currentUrl}?${query}` : currentUrl
} }
if (currentUrl.includes('login/index')) return if (currentUrl.includes('login/index')) return
if (confirm) {
wx.showModal({
title: '提示',
content: '授权登录后,可体验更好的服务',
success: () => {
wx.reLaunch({
url: path,
})
},
})
return
}
wx.reLaunch({ wx.reLaunch({
url: path, url: path,
}) })
// wx.showModal({ return
// title: '提示',
// content: '授权登录后,可体验更好的服务',
// success: () => {
// },
// })
}, },
mpBehavior(data: { PageName: string }) { mpBehavior(data: { PageName: string }) {
const url = '?r=wtx/mp-behavior/add' const url = '?r=wtx/mp-behavior/add'

11
src/components/pagination/index.scss

@ -1,6 +1,9 @@
/* components/pagination/index.wxss */ /* components/pagination/index.wxss */
.none { .pagination {
display: block; --divider-text-color: rgba(148, 163, 184, 1);
margin: 30rpx auto; .none {
width: 80%; display: block;
margin: 30rpx auto;
width: 80%;
}
} }

14
src/components/pagination/index.wxml

@ -1,6 +1,8 @@
<image class="none" src="{{imageUrl}}none.png" wx:if="{{pagination.count==0}}"></image> <view class="pagination">
<van-divider contentPosition="center" wx:elif="{{pagination.page<pagination.pages}}"> <image class="none" src="{{imageUrl}}none.png" wx:if="{{pagination.count==0}}"></image>
<van-loading /> <van-divider contentPosition="center" wx:elif="{{pagination.page<pagination.pages}}">
加载中... <van-loading />
</van-divider> 加载中...
<van-divider contentPosition="center" wx:elif="{{pagination.page>=pagination.pages}}">没有更多了</van-divider> </van-divider>
<van-divider contentPosition="center" wx:elif="{{pagination.page>=pagination.pages}}">没有更多了</van-divider>
</view>

37
src/components/pickerArea/index.ts

@ -257,19 +257,31 @@ Component({
}) })
}, },
handleShare() { handleShare() {
const { ProvinceName, ProvinceId, CityName, CityId, range } = this.data
if (!ProvinceId) {
wx.showToast({ title: '请选择省份', icon: 'none' })
return
}
if (range && range.length && !CityId) {
wx.showToast({ title: '请选择城市', icon: 'none' })
return
}
this.setData({ this.setData({
show: false, show: false,
}) })
this.triggerEvent('change', [ const result: any = [
{ {
label: this.data.ProvinceName, label: ProvinceName,
value: this.data.ProvinceId, value: ProvinceId,
}, },
{ ]
label: this.data.CityName, if (CityId) {
value: this.data.CityId, result.push({
}, label: CityName,
]) value: CityId,
})
}
this.triggerEvent('change', result)
}, },
handleSelect(e) { handleSelect(e) {
const { id } = e.currentTarget.dataset const { id } = e.currentTarget.dataset
@ -281,12 +293,17 @@ Component({
getRangeList() { getRangeList() {
const { area, ProvinceId } = this.data const { area, ProvinceId } = this.data
if (!ProvinceId) return if (!ProvinceId) return
const range = area.filter((item: any) => item.value == ProvinceId)[0].children const province = area.filter((item: any) => item.value == ProvinceId)[0]
const range = province?.children || []
if (range.length === 0) {
this.setData({ range, active: 0 })
return
}
this.setData({ this.setData({
range, range,
active: 1, active: 1,
scrollIntoView0: '', scrollIntoView0: '',
scrollIntoView1: `id${this.data.CityId}`, scrollIntoView1: this.data.CityId ? `id${this.data.CityId}` : '',
}) })
}, },
handleProvince() { handleProvince() {

1324
src/components/popup/index.scss

File diff suppressed because it is too large Load Diff

108
src/components/popup/index.ts

@ -21,20 +21,14 @@ Component({
observers: { observers: {
show(val) { show(val) {
if (val) { if (val) {
if (this.data.type === 'TCenter') { if (this.data.type === 'popup1') {
this.setData({ this.getCodeImg('103')
TCenterId: this.data.params.hospitalId,
})
} }
if (this.data.type === 'inhibitors') { if (this.data.type === 'popup2') {
this.setData({ this.getCodeImg('101')
inhibitorsId: this.data.params.drugId || '',
inhibitorsName: this.data.params.drugName || '',
inhibitorsContent: this.data.params.content || '',
})
} }
if (this.data.type === 'publicCard') { if (this.data.type === 'popup3') {
this.getCodeImg() this.getCodeImg('102')
} }
} }
}, },
@ -58,101 +52,17 @@ Component({
}, },
methods: { methods: {
handleOk() { handleOk() {
const { type, inhibitorsId, inhibitorsName, inhibitorsContent } = this.data
if (type === 'argument' && !this.data.popup1Check1) {
wx.showToast({
title: '请同意隐私政策',
icon: 'none',
})
return
}
if (type === 'TCenter') {
if (!this.data.TCenterId) {
wx.showToast({
title: '请选择治疗中心',
icon: 'none',
})
return
}
this.triggerEvent('ok', { id: this.data.TCenterId })
return
}
if (type === 'inhibitors') {
if (!inhibitorsId) {
wx.showToast({
title: '请选择抑制剂',
icon: 'none',
})
return
}
if (inhibitorsName === '其他' && !inhibitorsContent) {
wx.showToast({
title: '请填写其他抑制剂',
icon: 'none',
})
return
}
this.triggerEvent('ok', { id: inhibitorsId, name: inhibitorsName, content: inhibitorsContent })
return
}
if (type === 'selectDoctor') {
if (!this.data.selectDoctorId) {
wx.showToast({
title: '请选择医生',
icon: 'none',
})
return
}
this.triggerEvent('ok', { id: this.data.selectDoctorId })
return
}
this.triggerEvent('ok') this.triggerEvent('ok')
}, },
handleCancel() { handleCancel() {
this.triggerEvent('cancel') this.triggerEvent('cancel')
}, },
routerTo(e: any) { getCodeImg(ChannelType = '') {
const { url } = e.currentTarget.dataset
wx.navigateTo({
url,
})
},
handlePopup1Check1() {
if (this.data.popup1Check1) {
}
},
handleSelectStatus(e) {
const { status } = e.currentTarget.dataset
this.triggerEvent('ok', { type: 'selectStatusComplete', status })
},
handleSelectTCenter(e) {
const { id } = e.currentTarget.dataset
this.setData({
TCenterId: id,
})
},
handleSelectDoctor(e) {
const { id } = e.currentTarget.dataset
this.setData({
selectDoctorId: id,
})
},
handleSelectInhibitors(e) {
const { id, name } = e.currentTarget.dataset
this.setData({
inhibitorsId: id,
inhibitorsName: name,
})
},
getCodeImg() {
wx.ajax({ wx.ajax({
method: 'GET', method: 'GET',
url: '?r=wtx/common/get-channel-wx-code', url: '?r=psvt/common/get-channel-wx-code',
data: { data: {
ChannelType: 2, ChannelType,
}, },
}).then((res) => { }).then((res) => {
this.setData({ this.setData({

88
src/components/popup/index.wxml

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

20
src/components/uploadFile/index.js

@ -15,6 +15,10 @@ Component({
type: Boolean, type: Boolean,
value: true, value: true,
}, },
fileType: {
type: String,
value: 'image',
},
// 附件data // 附件data
fileList: { fileList: {
type: Array, type: Array,
@ -222,9 +226,15 @@ Component({
}) })
}, },
handleAction() { handleAction() {
this.setData({ // this.setData({
show: true, // show: true,
}) // })
if (this.data.fileType === 'file') {
this.selectFiles()
} else {
this.selectMedia()
}
}, },
onSelect(e) { onSelect(e) {
const { id } = e.currentTarget.dataset const { id } = e.currentTarget.dataset
@ -247,8 +257,8 @@ Component({
count = maxNum - fileList.length count = maxNum - fileList.length
} }
wx.chooseMedia({ wx.chooseMedia({
mediaType: ['image', 'video'], mediaType: this.data.fileType,
count: count, count,
sourceType: ['album', 'camera'], sourceType: ['album', 'camera'],
sizeType: ['original'], sizeType: ['original'],
success: (res) => { success: (res) => {

2
src/components/uploadFile/index.scss

@ -57,7 +57,7 @@
justify-content: center; justify-content: center;
font-size: 28rpx; font-size: 28rpx;
color: rgba(255, 255, 255, 1); color: rgba(255, 255, 255, 1);
background: var(--, linear-gradient(270deg, #439fc7 0%, #2f82a9 100%)); background: linear-gradient(270deg, #439fc7 0%, #2f82a9 100%);
box-sizing: border-box; box-sizing: border-box;
} }
} }

8
src/components/uploadFile/index.wxml

@ -10,7 +10,11 @@
></image> ></image>
<image wx:else class="sub-image" mode="aspectFill" src="{{imageUrl}}{{item.fileType}}.png?t={{Timestamp}}"></image> <image wx:else class="sub-image" mode="aspectFill" src="{{imageUrl}}{{item.fileType}}.png?t={{Timestamp}}"></image>
<view class="item_mask"> <view class="item_mask">
<image class="item_mask_icon" wx:if="{{item.fileType === 'video'}}" src="{{imageUrl}}icon17.png?t={{Timestamp}}"></image> <image
class="item_mask_icon"
wx:if="{{item.fileType === 'video'}}"
src="{{imageUrl}}icon17.png?t={{Timestamp}}"
></image>
<view class="clear" wx:if="{{delete}}" catchtap="deleteFile" data-item="{{item}}" data-index="{{index}}"> <view class="clear" wx:if="{{delete}}" catchtap="deleteFile" data-item="{{item}}" data-index="{{index}}">
<van-icon name="cross" /> <van-icon name="cross" />
</view> </view>
@ -26,8 +30,6 @@
</view> </view>
</view> </view>
<!-- <van-action-sheet title=" " show="{{ show }}" actions="{{ actions }}" bind:close="onClose" bind:select="onSelect" /> -->
<van-popup <van-popup
show="{{ show }}" show="{{ show }}"
custom-styple="background-color: rgba(247, 247, 250, 1);" custom-styple="background-color: rgba(247, 247, 250, 1);"

73
src/custom-tab-bar/index.ts

@ -16,28 +16,28 @@ Component({
icon: 'tabbar1-1', icon: 'tabbar1-1',
iconActive: 'tabbar1-1-active', iconActive: 'tabbar1-1-active',
}, },
// {
// pagePath: '/pages/wall/index',
// text: '交流墙',
// icon: 'tabbar1-2',
// iconActive: 'tabbar1-2-active',
// },
{ {
pagePath: '', pagePath: '/pages/wall/index',
text: '交流墙',
icon: 'tabbar1-2',
iconActive: 'tabbar1-2-active',
},
{
pagePath: '/pages/chat/index',
custom: true, custom: true,
}, },
// {
// pagePath: '/pages/health/index',
// text: '健康管理',
// icon: 'tabbar1-2',
// iconActive: 'tabbar1-2-active',
// },
{ {
pagePath: '/pages/my/index', pagePath: '/pages/health/index',
text: '我的', text: '健康管理',
icon: 'tabbar1-3', icon: 'tabbar1-3',
iconActive: 'tabbar1-3-active', iconActive: 'tabbar1-3-active',
}, },
{
pagePath: '/pages/my/index',
text: '我的',
icon: 'tabbar1-4',
iconActive: 'tabbar1-4-active',
},
], ],
}, },
observers: {}, observers: {},
@ -45,21 +45,48 @@ Component({
ready() { ready() {
const pagePath = getCurrentPageUrl() const pagePath = getCurrentPageUrl()
const active = this.data.list.findIndex((item) => item.pagePath === pagePath) const active = this.data.list.findIndex((item) => item.pagePath === pagePath)
this.setData({ const wallConfig = app.globalData.wallConfig
active, if (wallConfig) {
anyWhere: app.globalData.anyWhere, const list: any[] = [...this.data.list]
}) const wallIndex = list.findIndex((item: any) => item.pagePath === '/pages/wall/index')
if (wallIndex > -1) {
list[wallIndex] = { ...list[wallIndex], text: wallConfig.navName || '交流墙' }
}
this.setData({ active, list, anyWhere: app.globalData.anyWhere })
} else {
this.setData({ active, anyWhere: app.globalData.anyWhere })
app.waitLogin?.({ type: 1 }).then(() => {
wx.ajax({
method: 'GET',
url: '?r=psvt/wall/get-config',
loading: false,
showMsg: false,
}).then((res: any) => {
const config = res || {}
app.globalData.wallConfig = config
this.updateWallName(config.navName || '交流墙')
})
})
}
}, },
}, },
methods: { methods: {
updateWallName(name: string) {
const list: any[] = [...this.data.list]
const wallIndex = list.findIndex((item: any) => item.pagePath === '/pages/wall/index')
if (wallIndex > -1) {
list[wallIndex] = { ...list[wallIndex], text: name }
this.setData({ list })
}
},
handleNav(e) { handleNav(e) {
const { index } = e.currentTarget.dataset const { index } = e.currentTarget.dataset
const { list } = this.data const { list } = this.data
const pagePath = list[index].pagePath const pagePath = list[index].pagePath
if (!pagePath) { const custom = list[index].custom
wx.showToast({ if (custom) {
title: '功能开发中,敬请期待', wx.navigateTo({
icon: 'none', url: '/pages/chat/index',
}) })
} }
wx.switchTab({ wx.switchTab({

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/badge3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

BIN
src/images/bg12.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 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/bg17.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
src/images/bg18.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

BIN
src/images/bg19.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

BIN
src/images/bg20.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

BIN
src/images/bg21.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 KiB

BIN
src/images/bg7.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 291 KiB

After

Width:  |  Height:  |  Size: 792 KiB

22
src/images/chat/chat-bg.svg

@ -0,0 +1,22 @@
<svg width="730" height="554" viewBox="0 0 730 554" fill="none" xmlns="http://www.w3.org/2000/svg">
<g opacity="0.68">
<g opacity="0.28" filter="url(#filter0_f_48838_6242)">
<circle cx="267.447" cy="267.447" r="163.59" fill="#429EC5"/>
</g>
<g opacity="0.28" filter="url(#filter1_f_48838_6242)">
<circle cx="501.075" cy="324.978" r="125.069" fill="#EA581A" fill-opacity="0.32"/>
</g>
</g>
<defs>
<filter id="filter0_f_48838_6242" x="-0.000198473" y="-0.000198473" width="534.893" height="534.893" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="51.9" result="effect1_foregroundBlur_48838_6242"/>
</filter>
<filter id="filter1_f_48838_6242" x="272.149" y="96.0525" width="457.851" height="457.851" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="51.9" result="effect1_foregroundBlur_48838_6242"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

9
src/images/chat/chat-btn-bg.svg

@ -0,0 +1,9 @@
<svg width="152" height="49" viewBox="0 0 152 49" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M132 0C143.046 0 152 8.95431 152 20C152 30.5155 143.885 39.1342 133.575 39.9375L133.972 48.585L118.385 40H20C8.95431 40 0 31.0457 0 20C0 8.95431 8.95431 3.86555e-07 20 0H132Z" fill="url(#paint0_linear_48838_6303)"/>
<defs>
<linearGradient id="paint0_linear_48838_6303" x1="152" y1="24.2925" x2="1.25832e-06" y2="24.2925" gradientUnits="userSpaceOnUse">
<stop stop-color="#439FC7"/>
<stop offset="1" stop-color="#2F82A9"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 562 B

4
src/images/chat/chat-logo.svg

@ -0,0 +1,4 @@
<svg width="38" height="30" viewBox="0 0 38 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20.7931 5.98187C20.8544 5.98187 21.9141 8.66806 24.9744 8.26452C28.4275 7.80799 30.5754 4.46146 34.7976 5.87181C39.0199 7.28216 38.6885 13.5268 35.9964 16.6003C34.6258 18.1614 32.0278 19.9142 26.795 19.8979H26.2263C25.4244 19.8979 24.7985 19.5066 24.5243 18.6587L24.1398 17.2198L22.3191 27.3328C22.0859 28.6535 20.1834 28.6616 19.9421 27.3409L18.3219 16.0948L17.5691 19.2172C17.3113 20.4481 16.0921 21.3979 14.6929 21.3979H10.5811C10.3929 21.3979 9.67285 21.1696 9.67285 20.5664C9.67285 19.7471 10.3929 19.6615 10.5811 19.6615H14.3451C15.3802 19.5147 15.6094 18.8829 15.8098 18.1696L17.3154 10.7673C17.7655 9.60557 19.4716 9.78492 19.6679 11.0159L21.3045 22.637L22.7855 14.6519C22.9615 13.4331 24.6634 13.266 25.0726 14.4277L26.0463 17.819C26.1036 18.0188 26.2877 18.1573 26.4964 18.1573H27.3187C33.6193 18.2266 35.3786 10.7999 32.842 8.96969C30.1826 7.04982 28.2188 9.89906 24.9089 9.25095C21.6768 8.61914 20.789 5.97779 20.789 5.97779L20.7931 5.98187Z" fill="#1C6287"/>
<path d="M10.7307 27.7068C11.5803 28.7292 10.4692 29.3824 9.734 28.7982C8.19409 27.581 6.71545 26.303 5.22456 24.5219C-2.85079 14.882 -0.293799 6.79602 4.37903 2.72665C8.42692 -0.799053 15.9631 -1.60238 19.9415 4.5605C21.3426 6.7311 22.5149 8.28095 24.3366 8.87331C26.0236 9.42103 28.3273 8.68262 28.3273 8.68262C23.438 10.3258 21.8123 8.71507 18.0095 6.3619C11.4414 2.29253 5.80457 6.90556 4.99582 12.3179C3.92155 19.5032 8.47593 24.9966 10.7307 27.7028V27.7068Z" fill="#EB5902"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
src/images/chat/chat-mascot.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

5
src/images/chat/icon-what.svg

@ -0,0 +1,5 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.93427 2.93427C4.89045 0.978091 7.2457 0 10 0C12.7543 0 15.1095 0.978091 17.0657 2.93427C19.0219 4.89045 20 7.2457 20 10C20 12.7543 19.0219 15.1095 17.0657 17.0657C15.1095 19.0219 12.7543 20 10 20C7.2457 20 4.89045 19.0219 2.93427 17.0657C0.978091 15.1095 0 12.7543 0 10C0 7.2457 0.978091 4.89045 2.93427 2.93427Z" fill="#3C8CB1"/>
<path d="M10.0004 4.00635C8.90491 4.00635 7.96595 4.39758 7.18347 5.18006C6.401 5.96253 6.00977 6.9015 6.00977 7.99696H7.9816C7.9816 7.46488 8.18504 7.00322 8.59193 6.61198C8.99881 6.22075 9.46829 6.02513 10.0004 6.02513C10.5325 6.02513 11.0019 6.22075 11.4088 6.61198C11.8157 7.00322 12.0192 7.46488 12.0192 7.99696C12.0192 8.43514 11.8627 8.82638 11.5497 9.17067C11.2367 9.51496 10.8924 9.80447 10.5168 10.0392C10.1412 10.274 9.79693 10.6495 9.48394 11.166C9.17095 11.6824 9.01446 12.3006 9.01446 13.0204H10.9863C10.9863 12.3006 11.4871 11.4946 12.4886 10.6026C13.4902 9.71057 13.991 8.84203 13.991 7.99696C13.991 6.9015 13.5997 5.96253 12.8173 5.18006C12.0348 4.39758 11.0958 4.00635 10.0004 4.00635Z" fill="white"/>
<path d="M9.01446 14.0063V16.0251H10.9863V14.0063H9.01446Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

5
src/images/chat/icon-who.svg

@ -0,0 +1,5 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.93427 2.93427C4.89045 0.978091 7.2457 0 10 0C12.7543 0 15.1095 0.978091 17.0657 2.93427C19.0219 4.89045 20 7.2457 20 10C20 12.7543 19.0219 15.1095 17.0657 17.0657C15.1095 19.0219 12.7543 20 10 20C7.2457 20 4.89045 19.0219 2.93427 17.0657C0.978091 15.1095 0 12.7543 0 10C0 7.2457 0.978091 4.89045 2.93427 2.93427Z" fill="#3C8CB1"/>
<path d="M10.0004 4.00635C8.90491 4.00635 7.96595 4.39758 7.18347 5.18006C6.401 5.96253 6.00977 6.9015 6.00977 7.99696H7.9816C7.9816 7.46488 8.18504 7.00322 8.59193 6.61198C8.99881 6.22075 9.46829 6.02513 10.0004 6.02513C10.5325 6.02513 11.0019 6.22075 11.4088 6.61198C11.8157 7.00322 12.0192 7.46488 12.0192 7.99696C12.0192 8.43514 11.8627 8.82638 11.5497 9.17067C11.2367 9.51496 10.8924 9.80447 10.5168 10.0392C10.1412 10.274 9.79693 10.6495 9.48394 11.166C9.17095 11.6824 9.01446 12.3006 9.01446 13.0204H10.9863C10.9863 12.3006 11.4871 11.4946 12.4886 10.6026C13.4902 9.71057 13.991 8.84203 13.991 7.99696C13.991 6.9015 13.5997 5.96253 12.8173 5.18006C12.0348 4.39758 11.0958 4.00635 10.0004 4.00635Z" fill="white"/>
<path d="M9.01446 14.0063V16.0251H10.9863V14.0063H9.01446Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/images/clsoe.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
src/images/icon10.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 356 B

After

Width:  |  Height:  |  Size: 567 B

BIN
src/images/icon15.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
src/images/icon21-active.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 750 B

BIN
src/images/icon21.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 750 B

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
src/images/icon22-active.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 B

BIN
src/images/icon22.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 700 B

After

Width:  |  Height:  |  Size: 910 B

BIN
src/images/icon43.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
src/images/icon44.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
src/images/icon45.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 615 B

BIN
src/images/icon46.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 684 B

BIN
src/images/icon47.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 660 B

BIN
src/images/icon48.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 841 B

BIN
src/images/icon8-1.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 822 B

After

Width:  |  Height:  |  Size: 812 B

BIN
src/images/icon8.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 815 B

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/images/icon9-1.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 500 B

After

Width:  |  Height:  |  Size: 717 B

BIN
src/images/icon9.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 692 B

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/images/share-img1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 783 KiB

BIN
src/images/tabbar/tabbar1-4.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 791 B

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
src/images/title1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
src/images/title2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

10
src/pages/articleDetail/index.scss

@ -9,13 +9,15 @@ page {
gap: 20rpx; gap: 20rpx;
.tag { .tag {
height: 48rpx; height: 48rpx;
padding: 4rpx 16rpx; padding: 0 16rpx;
font-size: 24rpx; font-size: 24rpx;
color: rgba(47, 130, 169, 1); color: rgba(47, 130, 169, 1);
border-radius: 12rpx; border-radius: 12rpx;
background: rgba(47, 130, 169, 0.05); background: rgba(47, 130, 169, 0.05);
box-sizing: border-box; box-sizing: border-box;
line-height: 32rpx; display: flex;
align-items: center;
justify-content: center;
} }
} }
.title { .title {
@ -169,6 +171,7 @@ page {
position: fixed; position: fixed;
bottom: 0; bottom: 0;
left: 0; left: 0;
z-index: 10;
width: 100%; width: 100%;
padding: 0 30rpx calc(env(safe-area-inset-bottom) + 30rpx) 20rpx; padding: 0 30rpx calc(env(safe-area-inset-bottom) + 30rpx) 20rpx;
box-sizing: border-box; box-sizing: border-box;
@ -230,6 +233,9 @@ page {
box-sizing: border-box; box-sizing: border-box;
font-size: 32rpx; font-size: 32rpx;
color: rgba(47, 130, 169, 1); color: rgba(47, 130, 169, 1);
.arrow {
font-weight: bold;
}
} }
} }
} }

4
src/pages/articleDetail/index.ts

@ -37,7 +37,7 @@ Page({
}) })
}, },
handleCompliment() { handleCompliment() {
if (!app.checkLoginType(1)) return if (!app.checkLoginType(1, true)) return
const { detail, id } = this.data const { detail, id } = this.data
if (detail.IsCompliment) return if (detail.IsCompliment) return
wx.ajax({ wx.ajax({
@ -52,7 +52,7 @@ Page({
}) })
}, },
handleCollect() { handleCollect() {
if (!app.checkLoginType(1)) return if (!app.checkLoginType(1, true)) return
const { detail, id } = this.data const { detail, id } = this.data
if (detail.IsCollect) { if (detail.IsCollect) {
wx.ajax({ wx.ajax({

19
src/pages/articleDetail/index.wxml

@ -19,7 +19,13 @@
<view class="title">相关推荐</view> <view class="title">相关推荐</view>
</view> </view>
<view class="r-list"> <view class="r-list">
<view class="list-card" wx:for="{{detail.Recommends}}" wx:key="Id" bind:tap="handleRecommendTap" data-id="{{item.Id}}"> <view
class="list-card"
wx:for="{{detail.Recommends}}"
wx:key="Id"
bind:tap="handleRecommendTap"
data-id="{{item.Id}}"
>
<view class="photo-wrap"> <view class="photo-wrap">
<image class="photo" mode="aspectFill" src="{{item.TitlePicLink}}"></image> <image class="photo" mode="aspectFill" src="{{item.TitlePicLink}}"></image>
<view class="type1" wx:if="{{item.Type==='1'}}">图文</view> <view class="type1" wx:if="{{item.Type==='1'}}">图文</view>
@ -51,12 +57,18 @@
<view class="op-wrap"> <view class="op-wrap">
<!-- 点赞 --> <!-- 点赞 -->
<view class="op" bind:tap="handleCompliment"> <view class="op" bind:tap="handleCompliment">
<image class="icon" src="{{detail.IsCompliment ? imageUrl + 'icon9-active.png?t=' + Timestamp : imageUrl + 'icon9.png?t=' + Timestamp}}"></image> <image
class="icon"
src="{{detail.IsCompliment ? imageUrl + 'icon9-active.png?t=' + Timestamp : imageUrl + 'icon9.png?t=' + Timestamp}}"
></image>
<view class="num {{detail.IsCompliment ? 'active1' : ''}}">{{detail.ComplimentNum || 0}}</view> <view class="num {{detail.IsCompliment ? 'active1' : ''}}">{{detail.ComplimentNum || 0}}</view>
</view> </view>
<!-- 收藏 --> <!-- 收藏 -->
<view class="op" bind:tap="handleCollect"> <view class="op" bind:tap="handleCollect">
<image class="icon" src="{{detail.IsCollect ? imageUrl + 'icon28-active.png?t=' + Timestamp : imageUrl + 'icon28.png?t=' + Timestamp}}"></image> <image
class="icon"
src="{{detail.IsCollect ? imageUrl + 'icon28-active.png?t=' + Timestamp : imageUrl + 'icon28.png?t=' + Timestamp}}"
></image>
<view class="num {{detail.IsCollect ? 'active2' : ''}}">{{detail.CollectionPeopleNum || 0}}</view> <view class="num {{detail.IsCollect ? 'active2' : ''}}">{{detail.CollectionPeopleNum || 0}}</view>
</view> </view>
<!-- 分享 --> <!-- 分享 -->
@ -69,6 +81,7 @@
</view> </view>
<view class="next" wx:if="{{next.Id}}" bind:tap="handleNext"> <view class="next" wx:if="{{next.Id}}" bind:tap="handleNext">
下一篇 下一篇
<van-icon class="arrow" name="arrow" />
</view> </view>
</view> </view>
</view> </view>

4
src/pages/articleVideoDetail/index.ts

@ -182,7 +182,7 @@ Page({
this.setData({ [`videoList[${index}].drag`]: false }) this.setData({ [`videoList[${index}].drag`]: false })
}, },
handleCompliment() { handleCompliment() {
if (!app.checkLoginType(1)) return if (!app.checkLoginType(1, true)) return
const { current, videoList } = this.data const { current, videoList } = this.data
const video = videoList[current] const video = videoList[current]
if (video.IsCompliment) return if (video.IsCompliment) return
@ -198,7 +198,7 @@ Page({
}) })
}, },
handleCollect() { handleCollect() {
if (!app.checkLoginType(1)) return if (!app.checkLoginType(1, true)) return
const { current, videoList } = this.data const { current, videoList } = this.data
const video = videoList[current] const video = videoList[current]
const isCollect = video.IsCollect const isCollect = video.IsCollect

9
src/pages/bag/index.json

@ -0,0 +1,9 @@
{
"navigationStyle": "custom",
"usingComponents": {
"popup": "/components/popup/index",
"navbar": "/components/navbar/index",
"van-popup": "@vant/weapp/popup/index",
"van-icon": "@vant/weapp/icon/index"
}
}

355
src/pages/bag/index.scss

@ -0,0 +1,355 @@
page {
background-color: #f7fafc;
}
.page-title {
font-size: 36rpx;
color: rgba(51, 51, 51, 1);
padding-right: 100rpx;
}
.page {
padding-bottom: 260rpx;
.hero {
padding: 0 40rpx;
display: flex;
align-items: flex-start;
justify-content: space-between;
.hero-text {
padding-top: 78rpx;
.hero-title1 {
display: block;
width: 233rpx;
}
.hero-title2 {
margin-top: 20rpx;
display: block;
width: 353rpx;
height: 56rpx;
}
.hero-sub {
margin-top: 24rpx;
font-size: 28rpx;
font-weight: 400;
color: #64748b;
line-height: 40rpx;
}
}
.hero-decor {
margin-top: 48rpx;
width: 356rpx;
height: 356rpx;
flex-shrink: 0;
}
}
.card {
margin: 30rpx;
padding: 0;
border-radius: 32rpx;
border: 2rpx solid #fff;
background: rgba(255, 255, 255, 0.7);
box-shadow: 0 8rpx 64rpx 0 rgba(0, 99, 132, 0.08);
backdrop-filter: blur(10rpx);
overflow: hidden;
}
.step {
display: flex;
align-items: center;
gap: 24rpx;
padding: 24rpx 32rpx;
background: rgba(47, 130, 169, 0.08);
border: 2rpx solid #fff;
border-radius: 24rpx;
margin: 32rpx 32rpx 0;
.step-badge {
width: 64rpx;
height: 64rpx;
border-radius: 50%;
background: linear-gradient(270deg, #439fc7 0%, #2f82a9 100%);
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 29rpx;
font-weight: 700;
line-height: 44rpx;
flex-shrink: 0;
}
.step-title {
font-size: 36rpx;
font-weight: 500;
color: #2f82a9;
line-height: 44rpx;
}
}
.card-body {
padding: 48rpx 32rpx 54rpx;
.card-desc {
padding-left: 12rpx;
width: 400rpx;
font-size: 28rpx;
color: #64748b;
line-height: 38rpx;
padding-right: 20rpx;
white-space: pre-line;
}
.upload-grid {
margin-top: 53rpx;
}
.rejected {
margin-top: 24rpx;
padding: 16rpx 24rpx;
border-radius: 16rpx;
background: rgba(186, 26, 26, 0.08);
box-sizing: border-box;
font-size: 28rpx;
color: rgba(186, 26, 26, 1);
line-height: 40rpx;
display: flex;
.icon {
margin-top: 4rpx;
display: inline-block;
flex-shrink: 0;
margin-right: 16rpx;
width: 32rpx;
height: 32rpx;
vertical-align: -4rpx;
}
.blod {
display: inline-block;
font-weight: bold;
}
}
}
.upload-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 24rpx;
.upload-item {
aspect-ratio: 1 / 1;
.upload-empty {
width: 100%;
height: 100%;
border-radius: 24rpx;
background: #f7fafc;
border: 2rpx dashed rgba(148, 163, 184, 0.26);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 16rpx;
box-sizing: border-box;
.upload-icon {
width: 56rpx;
height: 56rpx;
}
.upload-placeholder {
font-size: 28rpx;
color: rgba(148, 163, 184, 0.51);
}
}
.upload {
position: relative;
width: 100%;
height: 100%;
border-radius: 24rpx;
overflow: hidden;
.u-img {
display: block;
width: 100%;
height: 100%;
}
.mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.29);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.icon {
width: 44rpx;
height: 44rpx;
}
.status {
margin-top: 12rpx;
font-size: 28rpx;
color: rgba(255, 255, 255, 1);
}
}
.del {
position: absolute;
right: 0;
top: 0;
width: 40rpx;
height: 40rpx;
z-index: 9;
background-color: rgba(4, 4, 4, 0.31);
border-radius: 0 16rpx;
color: #fff;
font-size: 28rpx;
display: flex;
align-items: center;
justify-content: center;
}
}
}
}
.card-body2 {
padding: 36rpx 32rpx 32rpx;
.c-item {
display: flex;
gap: 20rpx;
&.c-item2 {
margin-top: 50rpx;
}
.aside {
flex-shrink: 0;
display: flex;
flex-direction: column;
align-items: center;
gap: 16rpx;
padding-bottom: 23rpx;
.order {
width: 40rpx;
height: 40rpx;
border-radius: 50%;
font-size: 24rpx;
color: rgba(255, 255, 255, 1);
background: linear-gradient(270deg, #439fc7 0%, #2f82a9 100%);
display: flex;
align-items: center;
justify-content: center;
}
.line {
flex: 1;
border-right: 1px dashed rgba(47, 130, 169, 0.38);
}
}
.container {
flex: 1;
.title {
font-size: 32rpx;
color: rgba(30, 41, 59, 1);
font-weight: bold;
}
.content {
width: 338rpx;
margin-top: 12rpx;
font-size: 28rpx;
line-height: 40rpx;
color: rgba(100, 116, 139, 1);
.high {
display: inline;
color: rgba(47, 130, 169, 1);
}
}
.share {
margin-top: 24rpx;
display: flex;
align-items: center;
gap: 34rpx;
.share-img {
width: 212rpx;
height: 318rpx;
border-radius: 32rpx;
}
.btn {
padding: 8rpx 16rpx;
font-size: 32rpx;
color: rgba(47, 130, 169, 1);
line-height: 48rpx;
border-radius: 12rpx;
border: 1px solid rgba(47, 130, 169, 0.16);
box-sizing: border-box;
}
}
.upload-grid {
margin-top: 24rpx;
gap: 22rpx;
}
}
}
}
.consent {
margin: 32rpx 30rpx;
font-size: 26rpx;
color: rgba(148, 163, 184, 1);
line-height: 40rpx;
.check-content {
padding-top: 4rpx;
display: inline-block;
}
.wx-checkbox-input {
width: 32rpx;
height: 32rpx;
border-radius: 8rpx;
&.wx-checkbox-input-checked {
border-color: #fff !important;
background: linear-gradient(270deg, #439fc7 0%, #2f82a9 100%);
background-clip: border-box;
&::before {
font-size: 28rpx;
color: #fff;
}
}
}
}
.footer {
display: flex;
gap: 24rpx;
padding: 24rpx 30rpx calc(env(safe-area-inset-bottom) + 24rpx);
box-sizing: border-box;
.btn {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 24rpx 0;
border-radius: 24rpx;
.btn-title {
font-size: 32rpx;
font-weight: 700;
color: #fff;
line-height: 44rpx;
}
.btn-sub {
font-size: 28rpx;
font-weight: 400;
color: #fff;
line-height: 40rpx;
}
}
.btn-disabled {
background: rgba(148, 163, 184, 0.5);
}
.btn-primary {
background: linear-gradient(270deg, #439fc7 0%, #2f82a9 100%);
}
}
}

139
src/pages/bag/index.ts

@ -0,0 +1,139 @@
type UploadStatus = 'reviewing' | 'approved' | 'rejected'
interface UploadItem {
url: string
status: UploadStatus
rejectReason?: string
}
const app = getApp<IAppOption>()
Page({
data: {
popupShow: false,
popupType: 'popup4',
popupParams: {
position: 'center',
close: true,
} as any,
id: '',
detail: {} as any,
// 上传列表(已上传项),null 表示空位待上传
step1Slots: [null, null, null] as (UploadItem | null)[],
step2Slots: [null, null, null] as (UploadItem | null)[],
agreed: false,
},
onLoad() {},
onShow() {},
handleBack() {
wx.navigateBack()
},
// 选择并上传图片
handleChooseMedia(e: any) {
const { step, index } = e.currentTarget.dataset
const key = step === 1 ? 'step1Slots' : 'step2Slots'
const slots = [...this.data[key]]
wx.chooseMedia({
count: 1,
mediaType: ['image'],
sourceType: ['album', 'camera'],
sizeType: ['original', 'compressed'],
success: (res) => {
const tempFile = res.tempFiles[0]
this.uploadImage(tempFile.tempFilePath, key, index, slots)
},
})
},
// 上传图片到服务器
uploadImage(filePath: string, key: string, index: number, slots: (UploadItem | null)[]) {
wx.showLoading({ title: '正在上传' })
const url = `${app.globalData.upFileUrl}?r=file-service/upload-img`
wx.uploadFile({
filePath,
name: 'file',
url,
success: (res) => {
const data = JSON.parse(res.data)
const imgUrl = data.data.Url
// 新上传默认为审核中状态
slots[index] = { url: imgUrl, status: 'reviewing' }
this.setData({ [key]: [...slots] })
},
fail: () => {
wx.showToast({ title: '上传失败', icon: 'error' })
},
complete: () => {
wx.hideLoading()
},
})
},
// 预览图片
handlePreviewImage(e: any) {
const { step, index } = e.currentTarget.dataset
const key = step === 1 ? 'step1Slots' : 'step2Slots'
const slots = this.data[key] as (UploadItem | null)[]
const urls = slots.filter((item): item is UploadItem => !!item).map((item) => item.url)
wx.previewImage({ current: urls[index] || urls[0], urls })
},
// 删除上传项(仅审核中、驳回可删)
handleDeleteUpload(e: any) {
const { step, index } = e.currentTarget.dataset
const key = step === 1 ? 'step1Slots' : 'step2Slots'
const slots = [...this.data[key]]
slots[index] = null
this.setData({ [key]: [...slots] })
},
toggleAgree() {
this.setData({ agreed: !this.data.agreed })
},
handleDownloadPoster() {
wx.showToast({ title: '海报下载开发中', icon: 'none' })
},
// 获取已上传(非驳回)的图片 URL 列表
getValidImages(slots: (UploadItem | null)[]): string[] {
return slots
.filter((item): item is UploadItem => !!item && item.status !== 'rejected')
.map((item) => item.url)
},
handleStep1Submit() {
const { step1Slots, agreed } = this.data
const validImages = this.getValidImages(step1Slots as (UploadItem | null)[])
if (!validImages.length) {
wx.showToast({ title: '请先上传病例', icon: 'none' })
return
}
if (!agreed) {
wx.showToast({ title: '请先勾选确认', icon: 'none' })
return
}
wx.showToast({ title: '提交开发中', icon: 'none' })
},
handleAllSubmit() {
const { step1Slots, step2Slots, agreed } = this.data
const valid1 = this.getValidImages(step1Slots as (UploadItem | null)[])
const valid2 = this.getValidImages(step2Slots as (UploadItem | null)[])
if (!valid1.length || !valid2.length) {
wx.showToast({ title: '请完成全部任务', icon: 'none' })
return
}
if (!agreed) {
wx.showToast({ title: '请先勾选确认', icon: 'none' })
return
}
wx.showToast({ title: '提交开发中', icon: 'none' })
},
})
export {}

144
src/pages/bag/index.wxml

@ -0,0 +1,144 @@
<navbar fixed custom-style="background:{{background}}" back>
<view class="page-title" slot="left" bind:tap="handleBack">
<van-icon name="arrow-left" />
</view>
</navbar>
<view
class="page"
style="background: url('{{imageUrl}}bg6.png?t={{Timestamp}}') no-repeat top center/100% 478rpx;padding-top: {{pageTop}}px;"
>
<view class="hero">
<view class="hero-text">
<image class="hero-title1" mode="widthFix" src="{{imageUrl}}title1.png?t={{Timestamp}}"></image>
<image class="hero-title2" mode="widthFix" src="{{imageUrl}}title2.png?t={{Timestamp}}"></image>
<view class="hero-sub">
上传病例并完成任务,领取
<view></view>
安心随行礼包
</view>
</view>
<image class="hero-decor" src="{{imageUrl}}bg19.png?t={{Timestamp}}" mode="aspectFill"></image>
</view>
<view class="card" style="background: url('{{imageUrl}}bg18.png?t={{Timestamp}}') no-repeat top 100rpx right -53rpx/385rpx 355rpx">
<view class="step">
<view class="step-badge">1</view>
<view class="step-title">上传病例,获得随行小礼</view>
</view>
<view class="card-body">
<view class="card-desc">上传您的病例即可获得专属随行小礼哦~病历,诊断证明,心电图照片 任意一项</view>
<view class="upload-grid">
<view class="upload-item" wx:for="{{step1Slots}}" wx:key="index" data-step="1" data-index="{{index}}">
<view class="upload-empty" bind:tap="handleChooseMedia" data-step="1" data-index="{{index}}" wx:if="{{item}}">
<image class="upload-icon" src="{{imageUrl}}icon44.png?t={{Timestamp}}" mode="aspectFit"></image>
<view class="upload-placeholder">待上传</view>
</view>
<view class="upload">
<image class="u-img" src="{{imageUrl}}bg1.png?t={{Timestamp}}"></image>
<view class="mask">
<image class="icon" src="{{imageUrl}}icon45.png?t={{Timestamp}}"></image>
<view class="status">审核中</view>
<!-- <image class="icon" src="{{imageUrl}}icon45.png?t={{Timestamp}}"></image> -->
<!-- <view class="status">驳回</view> -->
<!-- <image class="icon" src="{{imageUrl}}icon46.png?t={{Timestamp}}"></image> -->
<!-- <view class="status">审核通过</view> -->
</view>
<view class="del">
<van-icon name="cross" />
</view>
</view>
</view>
</view>
<view class="rejected">
<image class="icon" src="{{imageUrl}}icon39.png?t={{Timestamp}}"></image>
<view>
<view class="blod">驳回原因:</view>
驳回原因:清上传病例、诊断证明心点图照片确诊信息
</view>
</view>
</view>
</view>
<view class="card">
<view class="step">
<view class="step-badge">2</view>
<view class="step-title">分享星动守护 解锁安心随行礼</view>
</view>
<view class="card-body2" style="background: url('{{imageUrl}}bg19.png?t={{Timestamp}}') no-repeat top 0 right 8rpx/252rpx 234rpx">
<view class="c-item">
<view class="aside">
<view class="order">1</view>
<view class="line"></view>
</view>
<view class="container">
<view class="title">发布到小红书</view>
<view class="content">
推荐星动守护平台分享到小红书,带上话题:
<view class="high">#星动守护PSVT小助手</view>
</view>
<view class="share">
<image class="share-img" mode="aspectFill" src="{{imageUrl}}share-img1.png?t={{Timestamp}}"></image>
<view class="btn">一键下载</view>
</view>
</view>
</view>
<view class="c-item c-item2">
<view class="aside">
<view class="order">2</view>
</view>
<view class="container">
<view class="title">上传发布截图</view>
<view class="content">用于确认任务是否完成</view>
<view class="upload-grid">
<view class="upload-item" wx:for="{{step1Slots}}" wx:key="index" data-step="1" data-index="{{index}}">
<view
class="upload-empty"
bind:tap="handleChooseMedia"
data-step="1"
data-index="{{index}}"
wx:if="{{!item}}"
>
<image class="upload-icon" src="{{imageUrl}}icon44.png?t={{Timestamp}}" mode="aspectFit"></image>
<view class="upload-placeholder">待上传</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
<view class="consent">
<checkbox class="check">
<view class="check-content">我已确认上传内容真实有效,并同意用于活动资格审核。</view>
</checkbox>
</view>
<view class="footer">
<block wx:if="{{true}}">
<view class="btn btn-disabled" bind:tap="handleStep1Submit">
<view class="btn-title">完成第1步任务</view>
<view class="btn-sub">领取随心小礼></view>
</view>
<view class="btn btn-primary" bind:tap="handleAllSubmit">
<view class="btn-title">完成全部任务</view>
<view class="btn-sub">领取随行大礼包></view>
</view>
</block>
<view class="btn btn-primary" wx:elif="{{false}}">
<view class="btn-title">添加客服,获得审批结果></view>
</view>
<view class="btn btn-primary" wx:elif="{{false}}">
<view class="btn-title">重新提交</view>
</view>
</view>
</view>
<popup
show="{{popupShow}}"
type="{{popupType}}"
params="{{popupParams}}"
bind:ok="handlePopupOk"
bind:cancel="handlePopupCancel"
></popup>

18
src/pages/changeTel/index.ts

@ -62,16 +62,30 @@ Page({
}) })
}, },
handleSubmit() { handleSubmit() {
const { mobile, code } = this.data
if (!mobile) {
wx.showToast({
title: '请输入手机号',
icon: 'none',
})
return
}
if (!code) {
wx.showToast({
icon: 'none',
title: '请输入验证码',
})
return
}
wx.showModal({ wx.showModal({
title: '确定修改此手机号?', title: '确定修改此手机号?',
confirmColor: '#F64A3A', confirmColor: '#F64A3A',
success: (res) => { success: (res) => {
if (!res.confirm) return if (!res.confirm) return
const { mobile, code } = this.data
const { registrationSource, registChannel, regBusinessId } = app.globalData const { registrationSource, registChannel, regBusinessId } = app.globalData
wx.ajax({ wx.ajax({
method: 'POST', method: 'POST',
url: '?r=psvt/account/update-telephone', url: '?r=psvt/user/update-telephone',
data: { data: {
mobile, mobile,
code, code,

7
src/pages/chat/index.json

@ -0,0 +1,7 @@
{
"navigationStyle": "custom",
"usingComponents": {
"navbar": "/components/navbar/index",
"van-icon": "@vant/weapp/icon/index"
}
}

155
src/pages/chat/index.scss

@ -0,0 +1,155 @@
page {
background-color: #f7fafc;
}
.page-title {
font-size: 36rpx;
color: rgba(51, 51, 51, 1);
padding-right: 100rpx;
}
.page {
position: relative;
min-height: 100vh;
padding-bottom: 60rpx;
}
.bg-pattern {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 692rpx;
opacity: 0.68;
pointer-events: none;
}
// 吉祥物区域
.mascot-wrap {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 32rpx;
position: relative;
}
.greeting-bubble {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 304rpx;
height: 98rpx;
.greeting-bg {
position: absolute;
width: 100%;
height: 100%;
}
.greeting-text {
position: relative;
z-index: 1;
font-size: 32rpx;
font-weight: 700;
color: #fff;
line-height: 48rpx;
}
}
.mascot {
width: 302rpx;
height: 384rpx;
margin-top: 12rpx;
}
// 信息卡片
.info-card {
margin: 24rpx 30rpx 0;
padding: 32rpx;
background: #fff;
border-radius: 32rpx;
}
.card-header {
display: flex;
align-items: center;
gap: 14rpx;
margin-bottom: 24rpx;
.card-icon {
width: 40rpx;
height: 40rpx;
flex-shrink: 0;
}
.card-title {
font-size: 32rpx;
font-weight: 700;
color: #2f82a9;
line-height: 48rpx;
}
}
.card-desc {
font-size: 28rpx;
font-weight: 400;
color: #475569;
line-height: 48rpx;
}
// 升级按钮
.upgrade-btn {
margin: 48rpx auto 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 434rpx;
padding: 16rpx 0;
background: linear-gradient(270deg, #439fc7 0%, #2f82a9 100%);
border-radius: 32rpx;
.upgrade-line1 {
font-size: 28rpx;
font-weight: 700;
color: #fff;
line-height: 42rpx;
}
.upgrade-line2 {
font-size: 28rpx;
font-weight: 400;
color: #fff;
line-height: 42rpx;
}
}
// 通知勾选
.notify {
margin: 32rpx 30rpx;
font-size: 26rpx;
color: rgba(148, 163, 184, 1);
line-height: 40rpx;
display: flex;
align-items: center;
justify-content: center;
.check-content {
padding-top: 4rpx;
display: inline-block;
}
.wx-checkbox-input {
width: 32rpx;
height: 32rpx;
border-radius: 8rpx;
&.wx-checkbox-input-checked {
border-color: #fff !important;
background: linear-gradient(270deg, #439fc7 0%, #2f82a9 100%);
background-clip: border-box;
&::before {
font-size: 28rpx;
color: #fff;
}
}
}
}

25
src/pages/chat/index.ts

@ -0,0 +1,25 @@
Page({
data: {
notifyChecked: false,
},
onLoad() {},
onShow() {},
handleBack() {
wx.navigateBack()
},
toggleNotify() {
const notifyChecked = !this.data.notifyChecked
this.setData({ notifyChecked })
if (notifyChecked) {
wx.showToast({ title: '已开启上线通知', icon: 'none' })
}
},
handleNotify() {
if (!this.data.notifyChecked) {
this.setData({ notifyChecked: true })
wx.showToast({ title: '已开启上线通知', icon: 'none' })
}
},
})
export {}

55
src/pages/chat/index.wxml

@ -0,0 +1,55 @@
<navbar fixed custom-style="background:{{background}}" back>
<view class="page-title" slot="left" bind:tap="handleBack">
<van-icon name="arrow-left" />
</view>
</navbar>
<view
class="page"
style="background: url('{{imageUrl}}bg6.png?t={{Timestamp}}') no-repeat top center/100% 478rpx;padding-top: {{pageTop}}px;"
>
<!-- 背景装饰 -->
<image class="bg-pattern" src="{{imageUrl}}chat/chat-bg.svg?t={{Timestamp}}" mode="aspectFill"></image>
<!-- 吉祥物 + 问候气泡 -->
<view class="mascot-wrap">
<view class="greeting-bubble">
<image class="greeting-bg" src="{{imageUrl}}chat/chat-btn-bg.svg?t={{Timestamp}}" mode="aspectFill"></image>
<text class="greeting-text">Hello,我是小豚</text>
</view>
<image class="mascot" src="{{imageUrl}}chat/chat-mascot.png?t={{Timestamp}}" mode="aspectFill"></image>
</view>
<!-- 卡片:我是谁 -->
<view class="info-card">
<view class="card-header">
<image class="card-icon" src="{{imageUrl}}chat/icon-who.svg?t={{Timestamp}}" mode="aspectFit"></image>
<text class="card-title">我是谁</text>
</view>
<view class="card-desc">hello,我是你的智能助手小豚,为你提供阵发性 室上速健康科普与慢病管理服务。</view>
</view>
<!-- 卡片:我能干嘛 -->
<view class="info-card">
<view class="card-header">
<image class="card-icon" src="{{imageUrl}}chat/icon-what.svg?t={{Timestamp}}" mode="aspectFit"></image>
<text class="card-title">我能干嘛</text>
</view>
<view class="card-desc">
作为阵发性室上速(PSVT)智能助手,我将为你 提供解答疾病问题、指导急性发作处理、提醒定
期复诊等全周期健康管理服务,你有任何关于 PSVT的问题都可随时咨询我。往后日常生活里,
我将长久相伴,全程守护你的健康。
</view>
</view>
<!-- 升级中按钮 -->
<view class="upgrade-btn" bind:tap="handleNotify">
<view class="upgrade-line1">我在努力学习升级中,</view>
<view class="upgrade-line2">很快就和您见面啦!</view>
</view>
<!-- 上线通知勾选 -->
<view class="notify" bind:tap="toggleNotify">
<checkbox class="check">上线时通知我</checkbox>
</view>
</view>

28
src/pages/confirmInfo/index.scss

@ -22,11 +22,11 @@ page {
height: 48rpx; height: 48rpx;
text-align: center; text-align: center;
font-size: 32rpx; font-size: 32rpx;
color: rgba(39, 66, 164, 1); color: #fff;
line-height: 48rpx; line-height: 48rpx;
border-radius: 50%; border-radius: 50%;
background-color: rgba(255, 255, 255, 1); background-color: rgba(255, 255, 255, 0.32);
border: 8rpx solid rgba(255, 255, 255, 0.16); border: 8rpx solid rgba(255, 255, 255, 0.32);
background-clip: content-box; background-clip: content-box;
} }
.icon { .icon {
@ -39,10 +39,20 @@ page {
color: rgba(255, 255, 255, 0.54); color: rgba(255, 255, 255, 0.54);
} }
&.active { &.active {
.order {
color: rgba(47, 130, 169, 1);
background-color: #fff;
}
.name { .name {
font-weight: bold;
color: rgba(255, 255, 255, 1); color: rgba(255, 255, 255, 1);
} }
} }
&.last {
.order {
background-color: #fff;
}
}
} }
.line { .line {
margin: 30rpx -10rpx 0; margin: 30rpx -10rpx 0;
@ -81,6 +91,14 @@ page {
background-color: #fff; background-color: #fff;
border-radius: 32rpx; border-radius: 32rpx;
.row { .row {
&:last-of-type {
.select1,
.select2,
.select3,
.select4 {
margin-bottom: 0;
}
}
.row-title { .row-title {
font-size: 32rpx; font-size: 32rpx;
color: rgba(30, 41, 59, 1); color: rgba(30, 41, 59, 1);
@ -101,10 +119,11 @@ page {
justify-content: center; justify-content: center;
font-size: 32rpx; font-size: 32rpx;
color: rgba(71, 85, 105, 1); color: rgba(71, 85, 105, 1);
box-sizing: border-box;
&.active { &.active {
color: #fff; color: #fff;
background: linear-gradient(270deg, #439fc7 0%, #2f82a9 100%); background: linear-gradient(270deg, #439fc7 0%, #2f82a9 100%);
border-color: transparent; border: none;
} }
} }
} }
@ -124,6 +143,7 @@ page {
gap: 16rpx; gap: 16rpx;
font-size: 32rpx; font-size: 32rpx;
color: rgba(71, 85, 105, 1); color: rgba(71, 85, 105, 1);
box-sizing: border-box;
.icon { .icon {
width: 40rpx; width: 40rpx;
height: 40rpx; height: 40rpx;

52
src/pages/confirmInfo/index.ts

@ -1,8 +1,11 @@
import dayjs from 'dayjs'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
interface OptionItem { interface OptionItem {
value: number value: number
label: string label: string
subTitle?: string
} }
Page({ Page({
@ -10,6 +13,8 @@ Page({
menuTop: 0, menuTop: 0,
step: 1, step: 1,
today: dayjs().format('YYYY-MM-DD'),
// 基础数据列表 (from API 1.7) // 基础数据列表 (from API 1.7)
ageRangeList: [] as OptionItem[], ageRangeList: [] as OptionItem[],
genderList: [] as OptionItem[], genderList: [] as OptionItem[],
@ -29,17 +34,15 @@ Page({
diagnosisStatus: 0 as number, diagnosisStatus: 0 as number,
diagnosisTime: '', diagnosisTime: '',
surgeryStatus: 0 as number, surgeryStatus: 0 as number,
currentMonth: '',
}, },
onLoad() { onLoad() {
const menuRes = wx.getMenuButtonBoundingClientRect() const menuRes = wx.getMenuButtonBoundingClientRect()
const now = new Date()
const currentMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`
this.setData({ this.setData({
menuTop: menuRes.top, menuTop: menuRes.top,
currentMonth,
}) })
this.getBaseData() app.waitLogin({ type: 'any' }).then(() => {
this.getBaseData()
})
}, },
getBaseData() { getBaseData() {
wx.ajax({ wx.ajax({
@ -50,14 +53,21 @@ Page({
if (Array.isArray(list)) { if (Array.isArray(list)) {
return list.map((item) => { return list.map((item) => {
const key = Object.keys(item)[0] const key = Object.keys(item)[0]
return { value: Number(key), label: item[key] } const val = item[key]
if (val && typeof val === 'object') {
return { value: Number(key), label: val.title, subTitle: val.subTitle }
}
return { value: Number(key), label: val }
}) })
} }
if (list && typeof list === 'object') { if (list && typeof list === 'object') {
return Object.keys(list).map((key) => ({ return Object.keys(list).map((key) => {
value: Number(key), const val = list[key]
label: list[key], if (val && typeof val === 'object') {
})) return { value: Number(key), label: val.title, subTitle: val.subTitle }
}
return { value: Number(key), label: val }
})
} }
return [] return []
} }
@ -77,12 +87,14 @@ Page({
}, },
handleAreaChange(e: any) { handleAreaChange(e: any) {
const [province, city] = e.detail const [province, city] = e.detail
const cityId = city?.value || ''
const cityName = city?.label || ''
this.setData({ this.setData({
provinceId: province.value, provinceId: province.value,
provinceName: province.label, provinceName: province.label,
cityId: city.value, cityId,
cityName: city.label, cityName,
regionText: [province.label, city.label].filter(Boolean).join(' '), regionText: [province.label, cityName].filter(Boolean).join(' '),
}) })
}, },
handleDiagnosisTimeChange(e: WechatMiniprogram.PickerChange) { handleDiagnosisTimeChange(e: WechatMiniprogram.PickerChange) {
@ -106,12 +118,16 @@ Page({
this.setData({ step: 1 }) this.setData({ step: 1 })
}, },
handleSubmit() { handleSubmit() {
const { diagnosisStatus, surgeryStatus } = this.data const { diagnosisStatus, diagnosisTime, surgeryStatus } = this.data
if (!diagnosisStatus) { if (!diagnosisStatus) {
wx.showToast({ title: '请选择确诊状态', icon: 'none' }) wx.showToast({ title: '请选择确诊状态', icon: 'none' })
return return
} }
if (!surgeryStatus) { if (diagnosisStatus === 2 && !diagnosisTime) {
wx.showToast({ title: '请选择确诊时间', icon: 'none' })
return
}
if (diagnosisStatus === 2 && !surgeryStatus) {
wx.showToast({ title: '请选择手术状态', icon: 'none' }) wx.showToast({ title: '请选择手术状态', icon: 'none' })
return return
} }
@ -124,7 +140,6 @@ Page({
cityId, cityId,
cityName, cityName,
diagnosisStatus: ds, diagnosisStatus: ds,
diagnosisTime,
surgeryStatus: ss, surgeryStatus: ss,
} = this.data } = this.data
const channelId = app.globalData.scene?.channelId || '' const channelId = app.globalData.scene?.channelId || ''
@ -151,8 +166,11 @@ Page({
}).then(() => { }).then(() => {
app.globalData.initLoginInfo.isReg = 1 app.globalData.initLoginInfo.isReg = 1
app.globalData.initLoginInfo.isLogin = 1 app.globalData.initLoginInfo.isLogin = 1
const redirectUrl = app.globalData.loginRedirectUrl let redirectUrl = app.globalData.loginRedirectUrl || ''
app.globalData.loginRedirectUrl = '' app.globalData.loginRedirectUrl = ''
if (redirectUrl.includes('login') || redirectUrl.includes('confirmInfo') || redirectUrl.includes('start')) {
redirectUrl = ''
}
wx.reLaunch({ wx.reLaunch({
url: redirectUrl ? `/${redirectUrl}` : '/pages/index/index', url: redirectUrl ? `/${redirectUrl}` : '/pages/index/index',
}) })

13
src/pages/confirmInfo/index.wxml

@ -4,7 +4,7 @@
> >
<image class="logo" src="{{imageUrl}}logo1.png?t={{Timestamp}}"></image> <image class="logo" src="{{imageUrl}}logo1.png?t={{Timestamp}}"></image>
<view class="page-header"> <view class="page-header">
<view class="item {{step==1 &&'active'}}"> <view class="item {{step>1 &&'last'}} {{step==1 &&'active'}}">
<view class="order" wx:if="{{step===1}}">1</view> <view class="order" wx:if="{{step===1}}">1</view>
<view class="order" wx:else><image class="icon" src="{{imageUrl}}icon3.png?t={{Timestamp}}"></image></view> <view class="order" wx:else><image class="icon" src="{{imageUrl}}icon3.png?t={{Timestamp}}"></image></view>
<view class="name">基础信息</view> <view class="name">基础信息</view>
@ -17,7 +17,7 @@
</view> </view>
<view class="tip"> <view class="tip">
<image class="icon" src="{{imageUrl}}icon4.png?t={{Timestamp}}"></image> <image class="icon" src="{{imageUrl}}icon4.png?t={{Timestamp}}"></image>
<view class="content">这些信息将用于优化内容推荐与服务提醒,不作为诊断或 治疗建议依据。</view> <view class="content">这些信息将用于优化内容推荐与服务提醒,不作为诊断或治疗建议依据。</view>
</view> </view>
<!-- Step 1: 基础信息 --> <!-- Step 1: 基础信息 -->
@ -32,7 +32,9 @@
bind:tap="handleSelect" bind:tap="handleSelect"
data-key="ageRange" data-key="ageRange"
data-value="{{item.value}}" data-value="{{item.value}}"
>{{item.label}}</view> >
{{item.label}}
</view>
</view> </view>
</view> </view>
<view class="row"> <view class="row">
@ -85,13 +87,14 @@
data-value="{{item.value}}" data-value="{{item.value}}"
> >
<view class="title">{{item.label}}</view> <view class="title">{{item.label}}</view>
<view class="content" wx:if="{{item.subTitle}}">{{item.subTitle}}</view>
</view> </view>
</view> </view>
</view> </view>
<view class="row" wx:if="{{diagnosisStatus===2}}"> <view class="row" wx:if="{{diagnosisStatus===2}}">
<view class="row-title">确诊时间</view> <view class="row-title">确诊时间</view>
<view class="select3"> <view class="select3">
<picker mode="date" fields="month" bindchange="handleDiagnosisTimeChange" end="{{currentMonth}}"> <picker mode="date" fields="month" bindchange="handleDiagnosisTimeChange" end="{{today}}">
<view class="picker-content"> <view class="picker-content">
<view class="content" data-place="选择确诊时间">{{diagnosisTime || ''}}</view> <view class="content" data-place="选择确诊时间">{{diagnosisTime || ''}}</view>
<image class="icon" src="{{imageUrl}}icon7.png?t={{Timestamp}}"></image> <image class="icon" src="{{imageUrl}}icon7.png?t={{Timestamp}}"></image>
@ -99,7 +102,7 @@
</picker> </picker>
</view> </view>
</view> </view>
<view class="row"> <view class="row" wx:if="{{diagnosisStatus===2}}">
<view class="row-title">是否接受过相关手术治疗</view> <view class="row-title">是否接受过相关手术治疗</view>
<view class="select4"> <view class="select4">
<view <view

17
src/pages/drugMap/index.scss

@ -2,22 +2,23 @@ page {
background: #f7fafc; background: #f7fafc;
} }
.page-title { .page-title {
width: 266rpx; font-size: 36rpx;
height: 58rpx; color: rgba(51, 51, 51, 1);
padding-right: 100rpx;
} }
.page { .page {
.logo { .logo {
margin: 436rpx auto 0; margin: 294rpx auto 0;
display: block; display: block;
width: 204rpx; width: 700rpx;
height: 264rpx; height: 450rpx;
} }
.content { .content {
margin-top: 34rpx; margin-top: 34rpx;
text-align: center; text-align: center;
font-size: 40rpx; font-size: 36rpx;
color: rgba(30, 41, 59, 1); color: rgba(148, 163, 184, 1);
line-height: 64rpx; line-height: 60rpx;
} }
} }

3
src/pages/drugMap/index.ts

@ -3,6 +3,9 @@ const _app = getApp<IAppOption>();
Page({ Page({
data: {}, data: {},
onLoad() {}, onLoad() {},
handleBack() {
wx.navigateBack()
},
}); });
export {} export {}

11
src/pages/drugMap/index.wxml

@ -1,9 +1,14 @@
<navbar fixed custom-style="background:{{background}}" back> <navbar fixed custom-style="background:{{background}}" back>
<image class="page-title" slot="left" src="{{imageUrl}}logo2.png?t={{Timestamp}}"></image> <view class="page-title" slot="left" bind:tap="handleBack">
<van-icon name="arrow-left" />
</view>
</navbar> </navbar>
<view class="page" style="background: url('{{imageUrl}}bg6.png?t={{Timestamp}}') no-repeat top center/100%;padding-top: {{pageTop}}rpx;"> <view
<image class="logo" src="{{imageUrl}}bg5.png?t={{Timestamp}}"></image> class="page"
style="background: url('{{imageUrl}}bg6.png?t={{Timestamp}}') no-repeat top center/100%;padding-top: {{pageTop}}rpx;"
>
<image class="logo" src="{{imageUrl}}bg12.png?t={{Timestamp}}"></image>
<view class="content"> <view class="content">
我们正在全力打造购药地图服务 我们正在全力打造购药地图服务
<view></view> <view></view>

3
src/pages/followDetail/index.scss

@ -5,6 +5,7 @@ page {
.page-title { .page-title {
font-size: 36rpx; font-size: 36rpx;
color: rgba(51, 51, 51, 1); color: rgba(51, 51, 51, 1);
padding-right: 100rpx;
} }
.page { .page {
@ -126,7 +127,7 @@ page {
color: rgba(100, 116, 139, 1); color: rgba(100, 116, 139, 1);
} }
.send { .send {
background: var(--, linear-gradient(270deg, #439fc7 0%, #2f82a9 100%)); background: linear-gradient(270deg, #439fc7 0%, #2f82a9 100%);
color: #fff; color: #fff;
border-color: transparent; border-color: transparent;
} }

79
src/pages/followDetail/index.ts

@ -8,13 +8,61 @@ Page({
position: 'bottom', position: 'bottom',
} as any, } as any,
topicShow: false, id: '',
replayShow: true, detail: {} as any,
},
fileList: [] as any[], onLoad(options: any) {
if (options.id) {
this.setData({ id: options.id })
}
},
onShow() {
app.waitLogin({ type: 1 }).then(() => {
this.getDetail(this.data.id)
})
}, },
onLoad() { getDetail(id: string) {
app.waitLogin({ type: 0 }).then(() => {}) wx.ajax({
method: 'GET',
url: '?r=psvt/revisit-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/revisit-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/followForm/index?id=${id}`,
})
},
handlePreviewImage(e: any) {
const { url } = e.currentTarget.dataset
const { detail } = this.data
wx.previewImage({
current: url,
urls: detail.images || [],
})
}, },
handlePopupOk() { handlePopupOk() {
const { popupType } = this.data const { popupType } = this.data
@ -79,23 +127,8 @@ Page({
url: '/pages/wechatWork/index', url: '/pages/wechatWork/index',
}) })
}, },
handleSetData(e) { handleBack() {
const { fileList } = this.data wx.navigateBack()
this.setData({
fileList: [...fileList, ...e.detail],
})
},
handleDeleteFile(e) {
const { index } = e.detail
const { fileList } = this.data
this.setData({
fileList: fileList.filter((_, i) => i !== index),
})
},
topicClose() {
this.setData({
topicShow: false,
})
}, },
}) })

31
src/pages/followDetail/index.wxml

@ -1,5 +1,5 @@
<navbar fixed custom-style="background:{{background}}" back> <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" /> <van-icon name="arrow-left" />
复诊记录详情 复诊记录详情
</view> </view>
@ -13,43 +13,40 @@
<view class="form-item"> <view class="form-item">
<view class="form-label">日期</view> <view class="form-label">日期</view>
<view class="date"> <view class="date">
<view class="content" data-place="请选择日期">2026.07.06 21:30</view> <view class="content">{{detail.visitDate || ''}}</view>
</view> </view>
</view> </view>
<view class="form-item"> <view class="form-item">
<view class="form-label"> <view class="form-label">
上传图片 上传图片
<view class="sub">可上传复诊病历、处方单或检查结果</view>
</view> </view>
<view class="photo9"> <view class="photo9" wx:if="{{detail.images && detail.images.length}}">
<view class="p-item" wx:for="{{3}}" wx:key="index"> <view class="p-item" wx:for="{{detail.images}}" wx:key="*this" data-url="{{item}}" bind:tap="handlePreviewImage">
<image class="p-img" mode="aspectFill" src="{{imageUrl}}bg1.png?t={{Timestamp}}"></image> <image class="p-img" mode="aspectFill" src="{{item}}"></image>
</view> </view>
</view> </view>
</view> </view>
<view class="form-item"> <view class="form-item">
<view class="form-label">发作时感受</view> <view class="form-label">是否更新处方</view>
<view class="select1"> <view class="select1">
<view class="s-item active">是</view> <view class="s-item {{detail.isUpdatePrescription === 1 ? 'active' : ''}}">是</view>
<view class="s-item">否</view> <view class="s-item {{detail.isUpdatePrescription === 0 ? 'active' : ''}}">否</view>
</view> </view>
</view> </view>
<view class="form-item"> <view class="form-item">
<view class="form-label">发作时处理方式</view> <view class="form-label">是否手术诊断</view>
<view class="select1"> <view class="select1">
<view class="s-item active">是</view> <view class="s-item {{detail.isUpdateSurgery === 1 ? 'active' : ''}}">是</view>
<view class="s-item">否</view> <view class="s-item {{detail.isUpdateSurgery === 0 ? 'active' : ''}}">否</view>
</view> </view>
</view> </view>
<view class="form-item"> <view class="form-item">
<view class="form-label">其他备注</view> <view class="form-label">其他备注</view>
<view class="remark"> <view class="remark">{{detail.remark || ''}}</view>
本次复诊心悸发作频率较上次减少,发作持续时间约5–10分钟,含服药物后可自行缓解。医生建议继续规律服药,避免剧烈运动及情绪激动,定期复查心电图。
</view>
</view> </view>
</view> </view>
<view class="page-footer"> <view class="page-footer">
<view class="cancel">删除</view> <view class="cancel" bind:tap="handleDelete">删除</view>
<view class="send">编辑</view> <view class="send" bind:tap="handleEdit">编辑</view>
</view> </view>
</view> </view>

8
src/pages/followForm/index.scss

@ -5,6 +5,7 @@ page {
.page-title { .page-title {
font-size: 36rpx; font-size: 36rpx;
color: rgba(51, 51, 51, 1); color: rgba(51, 51, 51, 1);
padding-right: 100rpx;
} }
.page { .page {
@ -74,10 +75,11 @@ page {
} }
} }
.txa { .txa {
padding: 32rpx; padding: 24rpx 32rpx;
width: 100%; width: 100%;
height: 240rpx; height: 240rpx;
font-size: 28rpx; font-size: 32rpx;
line-height: 48rpx;
color: rgba(30, 41, 59, 1); color: rgba(30, 41, 59, 1);
box-sizing: border-box; box-sizing: border-box;
background: #f9fafb; background: #f9fafb;
@ -123,7 +125,7 @@ page {
color: rgba(100, 116, 139, 1); color: rgba(100, 116, 139, 1);
} }
.send { .send {
background: var(--, linear-gradient(270deg, #439fc7 0%, #2f82a9 100%)); background: linear-gradient(270deg, #439fc7 0%, #2f82a9 100%);
color: #fff; color: #fff;
border-color: transparent; border-color: transparent;
} }

217
src/pages/followForm/index.ts

@ -1,74 +1,182 @@
import dayjs from 'dayjs'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
Page({ Page({
data: { data: {
popupShow: false, popupShow: false,
popupType: '', popupType: 'popup2',
popupParams: { popupParams: {
position: 'bottom', position: 'center',
close: true,
} as any, } as any,
topicShow: false,
replayShow: true,
id: '',
visitDate: '',
fileList: [] as any[], fileList: [] as any[],
isUpdatePrescription: 0,
isUpdateSurgery: 0,
remark: '',
isEdit: false,
endDate: dayjs().format('YYYY-MM-DD'),
userInfo: {} as any,
}, },
onLoad() { onLoad(options: any) {
app.waitLogin({ type: 0 }).then(() => {}) if (options.id) {
}, this.setData({ id: options.id, isEdit: true })
handlePopupOk() { app.waitLogin({ type: 'any' }).then(() => {
const { popupType } = this.data app.getUserInfo().then((res) => {
if (popupType === 'argument') { this.setData({
wx.ajax({ userInfo: res,
method: 'POST', })
url: '?r=wtx/user/agree-guest-privacy', })
data: { this.getDetail(options.id)
WorkerId: app.globalData.scene?.workerId || '', })
}, } else {
}).then(() => { app.waitLogin({ type: 'any' }).then(() => {
this.setData({ app.getUserInfo().then((res) => {
popupShow: false, this.setData({
popupType: '', userInfo: res,
popupParams: {}, })
}) })
const waitBindDoctorId = app.globalData.waitBindDoctorId
if (waitBindDoctorId) {
this.handleBindDoctor(waitBindDoctorId)
}
}) })
} }
if (popupType === 'conformBindDoctorConform') { },
getDetail(id: string) {
wx.ajax({
method: 'GET',
url: '?r=psvt/revisit-record/detail',
data: { id },
}).then((res: any) => {
if (!res) return
const fileList = (res.images || []).map((url: string) => ({
url,
fileType: 'image',
name: url,
}))
this.setData({ this.setData({
popupShow: false, visitDate: res.visitDate || '',
fileList,
isUpdatePrescription: res.isUpdatePrescription ?? 0,
isUpdateSurgery: res.isUpdateSurgery ?? 0,
remark: res.remark || '',
}) })
})
},
onDateChange(e: any) {
const selectedDate = e.detail.value
if (dayjs(selectedDate).isAfter(dayjs(), 'day')) {
wx.showToast({ title: '不能选择未来日期', icon: 'none' })
return
}
this.setData({ visitDate: selectedDate })
},
handleSetData(e: any) {
const { fileList } = this.data
this.setData({
fileList: [...fileList, ...e.detail],
})
},
handleDeleteFile(e: any) {
const { index } = e.detail
const { fileList } = this.data
this.setData({
fileList: fileList.filter((_, i) => i !== index),
})
},
handlePrescriptionChange(e: any) {
const { value } = e.currentTarget.dataset
this.setData({ isUpdatePrescription: value })
},
handleSurgeryChange(e: any) {
const { value } = e.currentTarget.dataset
this.setData({ isUpdateSurgery: value })
},
onRemarkInput(e: any) {
this.setData({ remark: e.detail.value })
},
handleSubmit() {
const { id, visitDate, fileList, isUpdatePrescription, isUpdateSurgery, remark, isEdit, userInfo } = this.data
if (!visitDate) {
wx.showToast({ title: '请选择复诊日期', icon: 'none' })
return
}
const images = fileList.map((item: any) => item.url)
const data = {
visitDate,
images,
isUpdatePrescription,
isUpdateSurgery,
remark,
}
wx.showLoading({ title: '保存中' })
if (isEdit) {
wx.ajax({ wx.ajax({
method: 'POST', method: 'POST',
url: '?r=wtx/account/wait-bind-doctor', url: '?r=psvt/revisit-record/update',
data: { data: { id: Number(id), ...data },
doctorId: app.globalData.waitBindDoctorId, })
}, .then(() => {
}).then(() => { wx.hideLoading()
wx.navigateTo({ wx.showToast({ title: '保存成功', icon: 'success' })
url: `/patient/pages/login/index`, setTimeout(() => {
wx.navigateBack()
}, 1000)
}) })
.catch(() => {
wx.hideLoading()
})
} else {
wx.ajax({
method: 'POST',
url: '?r=psvt/revisit-record/create',
data,
}) })
.then(() => {
wx.hideLoading()
if (userInfo.isFollow == 1) {
wx.showToast({ title: '保存成功', icon: 'success' })
setTimeout(() => {
wx.navigateBack()
}, 1000)
} else {
this.setData({
popupShow: true,
popupType: 'popup2',
popupParams: {
position: 'center',
close: true,
},
})
}
})
.catch(() => {
wx.hideLoading()
})
} }
}, },
handlePopupCancel() { handlePopupOk() {
const { popupType } = this.data const { popupType } = this.data
if (popupType === 'argument') { if (popupType == 'popup2') {
wx.exitMiniProgram() this.setData({ popupShow: false })
wx.navigateBack()
} }
if (popupType === 'conformBindDoctorConform') { },
this.setData({ handlePopupCancel() {
popupShow: false, const { popupType } = this.data
}) if (popupType == 'popup2') {
wx.ajax({ this.setData({ popupShow: false })
method: 'POST', wx.navigateBack()
url: '?r=wtx/account/wait-bind-doctor',
data: {
doctorId: app.globalData.waitBindDoctorId,
},
}).then(() => {
app.globalData.waitBindDoctorId = ''
})
} }
}, },
handleWechatWork() { handleWechatWork() {
@ -76,18 +184,13 @@ Page({
url: '/pages/wechatWork/index', url: '/pages/wechatWork/index',
}) })
}, },
handleSetData(e) { topicClose() {
const { fileList } = this.data
this.setData({ this.setData({
fileList: [...fileList, ...e.detail], topicShow: false,
}) })
}, },
handleDeleteFile(e) { handleBack() {
const { index } = e.detail wx.navigateBack()
const { fileList } = this.data
this.setData({
fileList: fileList.filter((_, i) => i !== index),
})
}, },
}) })

66
src/pages/followForm/index.wxml

@ -1,7 +1,7 @@
<navbar fixed custom-style="background:{{background}}" back> <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" /> <van-icon name="arrow-left" />
复诊记录 {{isEdit?"编辑":"添加"}}复诊记录
</view> </view>
</navbar> </navbar>
@ -12,9 +12,9 @@
<view class="form"> <view class="form">
<view class="form-item"> <view class="form-item">
<view class="form-label">日期</view> <view class="form-label">日期</view>
<picker mode="date"> <picker mode="date" value="{{visitDate}}" bind:change="onDateChange" end="{{endDate}}">
<view class="date"> <view class="date">
<view class="content" data-place="请选择日期"></view> <view class="content" data-place="请选择日期">{{visitDate}}</view>
<van-icon class="icon" name="arrow-down" /> <van-icon class="icon" name="arrow-down" />
</view> </view>
</picker> </picker>
@ -26,6 +26,7 @@
</view> </view>
<view class="upload-wrap"> <view class="upload-wrap">
<uploadFile <uploadFile
maxNum="{{10}}"
fileList="{{fileList}}" fileList="{{fileList}}"
bind:setData="handleSetData" bind:setData="handleSetData"
bind:deleteFile="handleDeleteFile" bind:deleteFile="handleDeleteFile"
@ -34,26 +35,65 @@
</view> </view>
</view> </view>
<view class="form-item"> <view class="form-item">
<view class="form-label">发作时感受</view> <view class="form-label">是否更新处方</view>
<view class="select1"> <view class="select1">
<view class="s-item active">是</view> <view
<view class="s-item">否</view> class="s-item {{isUpdatePrescription === 1 ? 'active' : ''}}"
data-value="{{1}}"
bind:tap="handlePrescriptionChange"
>
</view>
<view
class="s-item {{isUpdatePrescription === 0 ? 'active' : ''}}"
data-value="{{0}}"
bind:tap="handlePrescriptionChange"
>
</view>
</view> </view>
</view> </view>
<view class="form-item"> <view class="form-item">
<view class="form-label">发作时处理方式</view> <view class="form-label">是否手术诊断</view>
<view class="select1"> <view class="select1">
<view class="s-item active">是</view> <view
<view class="s-item">否</view> class="s-item {{isUpdateSurgery === 1 ? 'active' : ''}}"
data-value="{{1}}"
bind:tap="handleSurgeryChange"
>
</view>
<view
class="s-item {{isUpdateSurgery === 0 ? 'active' : ''}}"
data-value="{{0}}"
bind:tap="handleSurgeryChange"
>
</view>
</view> </view>
</view> </view>
<view class="form-item"> <view class="form-item">
<view class="form-label">其他备注</view> <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> </view>
</view> </view>
<view class="page-footer"> <view class="page-footer">
<view class="cancel">取消</view> <view class="cancel" bind:tap="handleBack">取消</view>
<view class="send">保存记录</view> <view class="send" bind:tap="handleSubmit">保存记录</view>
</view> </view>
</view> </view>
<popup
show="{{popupShow}}"
type="{{popupType}}"
params="{{popupParams}}"
bind:ok="handlePopupOk"
bind:cancel="handlePopupCancel"
></popup>

3
src/pages/health/index.json

@ -5,6 +5,7 @@
"navbar": "/components/navbar/index", "navbar": "/components/navbar/index",
"van-tab": "@vant/weapp/tab/index", "van-tab": "@vant/weapp/tab/index",
"van-tabs": "@vant/weapp/tabs/index", "van-tabs": "@vant/weapp/tabs/index",
"ec-canvas": "/components/ec-canvas/ec-canvas" "ec-canvas": "/components/ec-canvas/ec-canvas",
"pagination": "/components/pagination/index"
} }
} }

84
src/pages/health/index.scss

@ -29,6 +29,7 @@ page {
} }
.tab-active-class { .tab-active-class {
font-size: 32rpx; font-size: 32rpx;
font-weight: bold;
} }
.tab-class { .tab-class {
font-size: 28rpx; font-size: 28rpx;
@ -70,6 +71,31 @@ page {
height: 24rpx; height: 24rpx;
} }
} }
.week-alert {
display: flex;
align-items: center;
gap: 12rpx;
font-size: 28rpx;
color: rgba(30, 41, 59, 1);
.w-content {
display: inline-block;
vertical-align: middle;
}
.wx-checkbox-input {
width: 32rpx;
height: 32rpx;
border-radius: 8rpx;
&.wx-checkbox-input-checked {
border-color: #fff !important;
background: linear-gradient(270deg, #439fc7 0%, #2f82a9 100%);
background-clip: border-box;
&::before {
font-size: 28rpx;
color: #fff;
}
}
}
}
} }
.stats-grid { .stats-grid {
margin: 32rpx 30rpx 0; margin: 32rpx 30rpx 0;
@ -151,6 +177,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 { .body3 {
@ -159,7 +234,7 @@ page {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
gap: 20rpx; gap: 30rpx;
.date-range { .date-range {
padding: 0 32rpx; padding: 0 32rpx;
border-radius: 100rpx; border-radius: 100rpx;
@ -179,6 +254,10 @@ page {
} }
} }
.total { .total {
flex: 1;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
font-size: 24rpx; font-size: 24rpx;
color: rgba(100, 116, 139, 1); color: rgba(100, 116, 139, 1);
.high { .high {
@ -206,6 +285,7 @@ page {
border-radius: 12rpx; border-radius: 12rpx;
background: rgba(47, 130, 169, 0.05); background: rgba(47, 130, 169, 0.05);
box-sizing: border-box; box-sizing: border-box;
font-weight: bold;
} }
.date { .date {
color: #64748b; color: #64748b;
@ -256,7 +336,7 @@ page {
width: 128rpx; width: 128rpx;
height: 128rpx; height: 128rpx;
border-radius: 19998rpx; border-radius: 19998rpx;
background: var(--, linear-gradient(270deg, #439fc7 0%, #2f82a9 100%)); background: linear-gradient(270deg, #439fc7 0%, #2f82a9 100%);
box-shadow: 0 40rpx 50rpx -10rpx rgba(47, 130, 169, 0.38); box-shadow: 0 40rpx 50rpx -10rpx rgba(47, 130, 169, 0.38);
box-sizing: border-box; box-sizing: border-box;
display: flex; display: flex;

407
src/pages/health/index.ts

@ -1,44 +1,302 @@
import dayjs from 'dayjs'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
const echarts = require('@/components/ec-canvas/echarts.js') const echarts = require('@/components/ec-canvas/echarts.js')
const PAGE_SIZE = 10
Page({ Page({
data: { data: {
popupShow: false, popupShow: false,
popupType: '', popupType: 'popup1',
popupParams: { popupParams: {
position: 'bottom', close: true,
} as any, } as any,
tab: 1, tab: 0,
offsetTop: 0, offsetTop: 0,
// 复诊记录
revisitList: [] as any[],
revisitPagination: {
page: 1,
pages: 1,
count: 0,
},
daysSinceLastRevisit: 0,
totalRevisits: 0,
startMonth: '',
endMonth: '',
// 心率记录
heartRateList: [] as any[],
heartRatePagination: {
page: 1,
pages: 1,
count: 0,
},
heartStats: {
lastHeartRate: 0,
attackCount: 0,
maxHeartRate: 0,
},
userInfo: {} as any,
}, },
ecDataTrendComponent: null as any, ecDataTrendComponent: null as any,
_loaded: false,
onLoad() { onLoad() {
const now = new Date()
const endMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`
const startDate = new Date(now.getFullYear(), now.getMonth() - 6, 1)
const startMonth = `${startDate.getFullYear()}-${String(startDate.getMonth() + 1).padStart(2, '0')}`
this.setData({ startMonth, endMonth })
this.ecDataTrendComponent = this.selectComponent('#chart1') this.ecDataTrendComponent = this.selectComponent('#chart1')
this.initChart() this.initChart()
app.waitLogin({ type: 0 }).then(() => {})
app.waitLogin({ type: 1 }).then(() => {
this._loaded = true
if (this.data.tab === 0) {
this.getHeartStats()
this.getHeartChart()
this.getHeartRateList()
} else if (this.data.tab === 1) {
this.getRevisitList()
this.getLastRevisit()
}
app.getUserInfo().then((res) => {
this.setData({ userInfo: res })
})
})
}, },
onReady() { onReady() {
const { statusBarHeight } = wx.getSystemInfoSync() const { statusBarHeight } = wx.getSystemInfoSync()
const navBarHeight = 44 const navBarHeight = 44
this.setData({ offsetTop: statusBarHeight + navBarHeight }) this.setData({ offsetTop: statusBarHeight + navBarHeight })
}, },
initChart() { onShow() {
const arr = ['2026-06-01', '2026-06-02', '2026-06-03', '2026-06-04', '2026-06-05', '2026-06-06', '2026-06-07'] const tabBarParams = app.globalData.tabBarParams || {}
const params = tabBarParams['pages/health/index']
if (params) {
delete tabBarParams['pages/health/index']
app.globalData.tabBarParams = tabBarParams
const query: Record<string, string> = {}
params.split('&').forEach((kv: string) => {
const [k, v] = kv.split('=')
if (k) query[k] = v
})
if (query.tab !== undefined) {
const tab = Number(query.tab)
this.setData({ tab })
if (tab === 0) {
this.getHeartStats()
this.getHeartChart()
this.getHeartRateList()
} else if (tab === 1) {
this.getRevisitList()
this.getLastRevisit()
}
return
}
}
if (this._loaded) {
if (this.data.tab === 0) {
this.getHeartStats()
this.getHeartChart()
this.getHeartRateList()
} else if (this.data.tab === 1) {
this.getRevisitList()
this.getLastRevisit()
}
}
},
onReachBottom() {
if (this.data.tab === 0) {
const { heartRatePagination } = this.data
if (heartRatePagination.page < heartRatePagination.pages) {
this.getHeartRateList(heartRatePagination.page + 1, true)
}
} else if (this.data.tab === 1) {
const { revisitPagination } = this.data
if (revisitPagination.page < revisitPagination.pages) {
this.getRevisitList(revisitPagination.page + 1, true)
}
}
},
onChange(e: any) {
const { index } = e.detail
this.setData({ tab: index })
if (index === 0) {
this.getHeartStats()
this.getHeartChart()
this.getHeartRateList()
} else if (index === 1) {
this.getRevisitList()
this.getLastRevisit()
}
},
getRevisitList(page = 1, append = false) {
const { startMonth, endMonth } = this.data
wx.ajax({
method: 'GET',
url: '?r=psvt/revisit-record/list',
data: {
page,
count: PAGE_SIZE,
startMonth,
endMonth,
},
}).then((res: any) => {
const totalCount = Number(res.count) || 0
const list = (res.list || []).map((item: any, index: number) => {
const globalIndex = (page - 1) * PAGE_SIZE + index
return {
...item,
seqNum: globalIndex + 1,
}
})
this.setData({
revisitList: append ? this.data.revisitList.concat(list) : list,
revisitPagination: {
page: res.page || 1,
pages: res.pages || 1,
count: totalCount,
},
totalRevisits: totalCount,
})
})
},
getLastRevisit() {
wx.ajax({
method: 'GET',
url: '?r=psvt/revisit-record/last-revisit',
}).then((res: any) => {
this.setData({
daysSinceLastRevisit: res?.daysSinceLastRevisit ?? 0,
})
})
},
onStartMonthChange(e: any) {
this.setData({ startMonth: e.detail.value })
if (this.data.tab === 0) {
this.getHeartChart()
this.getHeartRateList()
} else {
this.getRevisitList()
}
},
onEndMonthChange(e: any) {
this.setData({ endMonth: e.detail.value })
if (this.data.tab === 0) {
this.getHeartChart()
this.getHeartRateList()
} else {
this.getRevisitList()
}
},
handleRevisitTap(e: any) {
const { id } = e.currentTarget.dataset
wx.navigateTo({
url: `/pages/followDetail/index?id=${id}`,
})
},
handleHeartTap(e: any) {
const { id } = e.currentTarget.dataset
wx.navigateTo({
url: `/pages/heartDetail/index?id=${id}`,
})
},
handleAdd() {
if (this.data.tab === 0) {
wx.navigateTo({
url: '/pages/heartForm/index',
})
} else if (this.data.tab === 1) {
wx.navigateTo({
url: '/pages/followForm/index',
})
}
},
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 || []).map((item) => {
item.recordDateTime = dayjs(item.recordDateTime).format('YYYY-MM-DD HH:mm')
return item
})
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),
isAttack,
itemStyle: isAttack
? { color: '#d62828', borderColor: '#fff' }
: { color: '#fff', borderColor: '#46bc70', borderWidth: 2 },
}
})
this.ecDataTrendComponent.init((canvas, width, height, dpr) => { this.ecDataTrendComponent.init((canvas, width, height, dpr) => {
let chart = echarts.init(canvas, null, { const chart = echarts.init(canvas, null, {
width: width, width,
height: height, height,
devicePixelRatio: dpr, devicePixelRatio: dpr,
}) })
canvas.setChart(chart) canvas.setChart(chart)
var option = { const option = {
dataZoom: [ dataZoom: [
{ {
type: 'inside', type: 'inside',
startValue: 0, startValue: 0,
endValue: 6, // 修正:数组下标0~6,原来7会越界 endValue: Math.max(chartData.length - 1, 6),
xAxisIndex: [0], xAxisIndex: [0],
}, },
], ],
@ -54,8 +312,12 @@ Page({
fontSize: 10, fontSize: 10,
}, },
order: 'seriesDesc', order: 'seriesDesc',
formatter: (params: any) => {
const p = params[0]
const name = p.data.isAttack ? '发作心率' : '正常心率'
return `${p.axisValueLabel}\n${p.marker}${name} ${p.value}`
},
}, },
// 双图例自定义样式,匹配原图空心绿圈+实心红点
legend: { legend: {
bottom: 0, bottom: 0,
padding: 0, padding: 0,
@ -95,8 +357,11 @@ Page({
type: 'category', type: 'category',
axisLabel: { axisLabel: {
color: 'rgba(148, 163, 184, 1)', color: 'rgba(148, 163, 184, 1)',
formatter: function (value) { formatter: (value) => {
const [_year, month, day] = value.split('-') if (!value) return ''
const parts = value.split(' ')
const datePart = parts[0] || ''
const [_year, month, day] = datePart.split('-')
return `${month}/${day}` return `${month}/${day}`
}, },
}, },
@ -109,7 +374,7 @@ Page({
splitLine: { splitLine: {
show: false, show: false,
}, },
data: arr, data: xAxisData,
}, },
yAxis: [ yAxis: [
{ {
@ -133,22 +398,27 @@ Page({
], ],
series: [ series: [
{ {
// 单条主线,所有点位都有数值,折线完整连续无断点
name: '心率', name: '心率',
type: 'line', type: 'line',
symbol: 'circle', symbol: 'circle',
symbolSize: 8, symbolSize: 8,
lineStyle: { color: '#46bc70', width: 2 }, lineStyle: { color: '#46bc70', width: 2 },
// 每个点位单独配置样式,发作点红色实心,其余白色空心绿边框 data: seriesData,
data: [ markArea: {
{ value: 62, itemStyle: { color: '#fff', borderColor: '#46bc70', borderWidth: 2 } }, itemStyle: {
{ value: 60, itemStyle: { color: '#fff', borderColor: '#46bc70', borderWidth: 2 } }, color: 'rgba(45, 190, 141, 0.07)',
{ value: 61, itemStyle: { color: '#fff', borderColor: '#46bc70', borderWidth: 2 } }, },
{ value: 66, itemStyle: { color: '#d62828', borderColor: '#fff' } }, // 发作红点 data: [
{ 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,
},
],
],
},
}, },
], ],
} }
@ -157,68 +427,45 @@ Page({
return chart return chart
}) })
}, },
handlePopupOk() { handleRateTip() {
const { popupType } = this.data const { userInfo } = this.data
if (popupType === 'argument') { wx.ajax({
wx.ajax({ method: 'POST',
method: 'POST', url: '?r=psvt/user/set-tips',
url: '?r=wtx/user/agree-guest-privacy', data: {
data: { isHeartRateTips: Number(!userInfo.isHeartRateTips),
WorkerId: app.globalData.scene?.workerId || '', },
}, }).then(() => {
}).then(() => { if (!userInfo.isHeartRateTips) {
this.setData({ if (userInfo.isFollow == 1) {
popupShow: false, wx.showToast({
popupType: '', icon: 'none',
popupParams: {}, title: '设置成功,我们将在每周五下午7点提醒您记录',
}) duration: 3000,
const waitBindDoctorId = app.globalData.waitBindDoctorId })
if (waitBindDoctorId) { } else {
this.handleBindDoctor(waitBindDoctorId) this.setData({
popupShow: true,
popupType: 'popup1',
})
} }
}) }
}
if (popupType === 'conformBindDoctorConform') {
this.setData({ this.setData({
popupShow: false, ['userInfo.isHeartRateTips']: !userInfo.isHeartRateTips,
})
wx.ajax({
method: 'POST',
url: '?r=wtx/account/wait-bind-doctor',
data: {
doctorId: app.globalData.waitBindDoctorId,
},
}).then(() => {
wx.navigateTo({
url: `/patient/pages/login/index`,
})
}) })
})
},
handlePopupOk() {
const { popupType } = this.data
if (popupType === 'popup1') {
this.setData({ popupShow: false })
} }
}, },
handlePopupCancel() { handlePopupCancel() {
const { popupType } = this.data const { popupType } = this.data
if (popupType === 'argument') { if (popupType === 'popup1') {
wx.exitMiniProgram() this.setData({ popupShow: false })
} }
if (popupType === 'conformBindDoctorConform') {
this.setData({
popupShow: false,
})
wx.ajax({
method: 'POST',
url: '?r=wtx/account/wait-bind-doctor',
data: {
doctorId: app.globalData.waitBindDoctorId,
},
}).then(() => {
app.globalData.waitBindDoctorId = ''
})
}
},
handleDetail() {
wx.navigateTo({
url: '/pages/wallDetail/index',
})
}, },
}) })

121
src/pages/health/index.wxml

@ -6,11 +6,6 @@
class="page" class="page"
style="background: url('{{imageUrl}}bg6.png?t={{Timestamp}}') no-repeat top center/100% 478rpx;padding-top: {{pageTop}}px;" style="background: url('{{imageUrl}}bg6.png?t={{Timestamp}}') no-repeat top center/100% 478rpx;padding-top: {{pageTop}}px;"
> >
<!-- <swiper class="banner"> -->
<!-- <swiper-item> -->
<!-- <image class="b-img" mode="aspectFill" src="{{imageUrl}}bg1.png?t={{Timestamp}}"></image> -->
<!-- </swiper-item> -->
<!-- </swiper> -->
<van-tabs <van-tabs
class="tabs" class="tabs"
active="{{ tab }}" active="{{ tab }}"
@ -26,100 +21,146 @@
nav-class="nav-calss" nav-class="nav-calss"
offset-top="{{offsetTop}}" offset-top="{{offsetTop}}"
> >
<van-tab title="健康量表">内容 1</van-tab>
<van-tab title="心率记录"> <van-tab title="心率记录">
<view class="body2"> <view class="body2">
<view class="body-op"> <view class="body-op">
<view class="date-range"> <view class="date-range">
<picker mode="date"> <picker mode="date" fields="month" value="{{startMonth}}" bind:change="onStartMonthChange">
<view class="date">2026.01</view> <view class="date">{{startMonth}}</view>
</picker> </picker>
- -
<picker mode="date"> <picker mode="date" fields="month" value="{{endMonth}}" bind:change="onEndMonthChange">
<view class="date">2026.01</view> <view class="date">{{endMonth}}</view>
</picker> </picker>
<image class="icon" src="{{imageUrl}}icon25.png?t={{Timestamp}}"></image> <image class="icon" src="{{imageUrl}}icon25.png?t={{Timestamp}}"></image>
</view> </view>
<view class="week-alert">
<checkbox class="check" checked="{{userInfo.isHeartRateTips}}" bind:tap="handleRateTip">
<view class="w-content">每周提醒我</view>
</checkbox>
</view>
</view> </view>
<view class="stats-grid"> <view class="stats-grid">
<view class="stat-card"> <view class="stat-card">
<view class="stat-label">最近1次</view> <view class="stat-label">最近1次</view>
<view class="stat-value"> <view class="stat-value">
<text class="stat-number">59</text> <text class="stat-number">{{heartStats.lastHeartRate}}</text>
<text class="stat-unit">次/分</text> <text class="stat-unit">次/分</text>
</view> </view>
</view> </view>
<view class="stat-card"> <view class="stat-card">
<view class="stat-label">最近发作</view> <view class="stat-label">总共发作</view>
<view class="stat-value"> <view class="stat-value">
<text class="stat-number">2</text> <text class="stat-number">{{heartStats.attackCount}}</text>
<text class="stat-unit">次</text> <text class="stat-unit">次</text>
</view> </view>
</view> </view>
<view class="stat-card"> <view class="stat-card">
<view class="stat-label">最高心率</view> <view class="stat-label">最高心率</view>
<view class="stat-value"> <view class="stat-value">
<text class="stat-number">156</text> <text class="stat-number">{{heartStats.maxHeartRate}}</text>
<text class="stat-unit">次/分</text> <text class="stat-unit">次/分</text>
</view> </view>
</view> </view>
</view> </view>
<view class="chart"> <view class="chart">
<ec-canvas id="chart1" ec="{{ ec }}"></ec-canvas> <ec-canvas id="chart1" ec="{{ ec }}"></ec-canvas>
<div class="legend"> <view class="legend">
<div class="l-item"> <view class="l-item">
<div class="dot1"></div> <view class="dot1"></view>
正常心率 正常心率
</div> </view>
<div class="l-item"> <view class="l-item">
<div class="dot2"></div> <view class="dot2"></view>
发作心率 发作心率
</div> </view>
</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> </view>
</van-tab> </van-tab>
<van-tab title="复诊记录"> <van-tab title="复诊记录">
<view class="body3"> <view class="body3">
<view class="body-op"> <view class="body-op">
<view class="date-range"> <view class="date-range">
<picker mode="date"> <picker mode="date" fields="month" value="{{startMonth}}" bind:change="onStartMonthChange">
<view class="date">2026.01</view> <view class="date">{{startMonth}}</view>
</picker> </picker>
- -
<picker mode="date"> <picker mode="date" fields="month" value="{{endMonth}}" bind:change="onEndMonthChange">
<view class="date">2026.01</view> <view class="date">{{endMonth}}</view>
</picker> </picker>
<image class="icon" src="{{imageUrl}}icon25.png?t={{Timestamp}}"></image> <image class="icon" src="{{imageUrl}}icon25.png?t={{Timestamp}}"></image>
</view> </view>
<view class="total"> <view class="total">
共复诊 <view>
<view class="high">3</view> 共复诊
次 距上次复诊 <view class="high">{{totalRevisits}}</view>
<view class="high">12</view>
</view>
<view>
距上次复诊
<view class="high">{{daysSinceLastRevisit}}</view>
</view>
</view> </view>
</view> </view>
<view class="list"> <view class="list">
<view class="card" wx:for="{{10}}" wx:key="index"> <view class="card" wx:for="{{revisitList}}" wx:key="id" data-id="{{item.id}}" bind:tap="handleRevisitTap">
<view class="c-header"> <view class="c-header">
<view class="label">第4次复诊</view> <view class="label">第{{item.seqNum}}次复诊</view>
<view class="date">2026.7.12</view> <view class="date">{{item.visitDate}}</view>
</view> </view>
<view class="photo9"> <view class="photo9" wx:if="{{item.images && item.images.length}}">
<view class="p-item" wx:for="{{3}}" wx:key="index"> <view class="p-item" wx:for="{{item.images}}" wx:for-item="img" wx:key="*this">
<image class="p-img" mode="aspectFill" src="{{imageUrl}}bg1.png?t={{Timestamp}}"></image> <image class="p-img" mode="aspectFill" src="{{img}}"></image>
</view> </view>
</view> </view>
<view class="title">未更新处方</view> <view class="title">
<view class="content">医生建议持续监测心律指标、评估药物疗效与不良反应,动态调整治…</view> {{item.isUpdatePrescription ? '已更新处方' : '未更新处方'}};{{isUpdateSurgery ? '已更新手术诊断' :
'未手术诊断'}}
</view>
<view class="content" wx:if="{{item.remark}}">{{item.remark}}</view>
</view> </view>
</view> </view>
<pagination pagination="{{revisitPagination}}" />
</view> </view>
</van-tab> </van-tab>
</van-tabs> </van-tabs>
</view> </view>
<view class="fixed-add"> <view class="fixed-add" bind:tap="handleAdd">
<image class="icon" src="{{imageUrl}}icon24.png?t={{Timestamp}}"></image> <image class="icon" src="{{imageUrl}}icon24.png?t={{Timestamp}}"></image>
</view> </view>
<popup
show="{{popupShow}}"
type="{{popupType}}"
params="{{popupParams}}"
bind:ok="handlePopupOk"
bind:cancel="handlePopupCancel"
></popup>

6
src/pages/heartDetail/index.scss

@ -116,9 +116,11 @@ page {
height: 32rpx; height: 32rpx;
border-radius: 8rpx; border-radius: 8rpx;
&.wx-checkbox-input-checked { &.wx-checkbox-input-checked {
border-color: #fff !important;
background: linear-gradient(270deg, #439fc7 0%, #2f82a9 100%); background: linear-gradient(270deg, #439fc7 0%, #2f82a9 100%);
border-color: transparent; background-clip: border-box;
&::before { &::before {
font-size: 28rpx;
color: #fff; color: #fff;
} }
} }
@ -152,7 +154,7 @@ page {
color: rgba(100, 116, 139, 1); color: rgba(100, 116, 139, 1);
} }
.send { .send {
background: var(--, linear-gradient(270deg, #439fc7 0%, #2f82a9 100%)); background: linear-gradient(270deg, #439fc7 0%, #2f82a9 100%);
color: #fff; color: #fff;
border-color: transparent; border-color: transparent;
} }

73
src/pages/heartDetail/index.ts

@ -1,3 +1,5 @@
import dayjs from 'dayjs'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
Page({ Page({
@ -8,10 +10,57 @@ Page({
position: 'bottom', position: 'bottom',
} as any, } as any,
fileList: [] as any[], id: '',
detail: {} as any,
},
onLoad(options: any) {
if (options.id) {
this.setData({ id: options.id })
}
},
onShow() {
app.waitLogin({ type: 1 }).then(() => {
this.getDetail(this.data.id)
})
},
getDetail(id: string) {
wx.ajax({
method: 'GET',
url: '?r=psvt/heart-rate-record/detail',
data: { id },
}).then((res: any) => {
res.recordDateTime = dayjs(res.recordDateTime).format('YYYY-MM-DD HH:mm')
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)
})
},
})
}, },
onLoad() { handleEdit() {
app.waitLogin({ type: 0 }).then(() => {}) const { id } = this.data
wx.navigateTo({
url: `/pages/heartForm/index?id=${id}`,
})
},
handleBack() {
wx.navigateBack()
}, },
handlePopupOk() { handlePopupOk() {
const { popupType } = this.data const { popupType } = this.data
@ -71,24 +120,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 {} export {}

18
src/pages/heartDetail/index.wxml

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

3
src/pages/heartForm/index.json

@ -4,6 +4,7 @@
"popup": "/components/popup/index", "popup": "/components/popup/index",
"navbar": "/components/navbar/index", "navbar": "/components/navbar/index",
"uploadFile": "/components/uploadFile/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"
} }
} }

21
src/pages/heartForm/index.scss

@ -13,15 +13,18 @@ page {
margin: 30rpx; margin: 30rpx;
padding: 32rpx; padding: 32rpx;
border-radius: 32rpx; border-radius: 32rpx;
border: 2rpx solid #fff; border: 1px solid #fff;
background: rgba(255, 255, 255, 0.7); background: rgba(255, 255, 255, 0.7);
box-shadow: 0 8rpx 64rpx 0 rgba(0, 99, 132, 0.08); box-shadow: 0 8rpx 64rpx 0 rgba(0, 99, 132, 0.08);
backdrop-filter: blur(10rpx); backdrop-filter: blur(10rpx);
box-sizing: border-box; box-sizing: border-box;
.rate { .rate {
margin-bottom: 56rpx;
padding: 32rpx; padding: 32rpx;
border-radius: 24rpx; border-radius: 24rpx;
background-color: #fff; border: 1px solid #f1f5f9;
background: #fff;
box-shadow: 0 8rpx 64rpx 0 rgba(0, 99, 132, 0.08);
.r-title { .r-title {
font-size: 32rpx; font-size: 32rpx;
color: rgba(71, 85, 105, 1); color: rgba(71, 85, 105, 1);
@ -46,7 +49,6 @@ page {
color: rgba(148, 163, 184, 0.37); color: rgba(148, 163, 184, 0.37);
} }
.unit { .unit {
width: 200rpx;
flex-shrink: 0; flex-shrink: 0;
font-size: 40rpx; font-size: 40rpx;
color: rgba(148, 163, 184, 1); color: rgba(148, 163, 184, 1);
@ -90,14 +92,15 @@ page {
} }
} }
.icon { .icon {
color: rgba(71, 85, 105, 1); color: rgba(148, 163, 184, 1);
} }
} }
.txa { .txa {
padding: 32rpx; padding: 24rpx 32rpx;
width: 100%; width: 100%;
height: 240rpx; height: 240rpx;
font-size: 28rpx; font-size: 32rpx;
line-height: 48rpx;
color: rgba(30, 41, 59, 1); color: rgba(30, 41, 59, 1);
box-sizing: border-box; box-sizing: border-box;
background: #f9fafb; background: #f9fafb;
@ -120,9 +123,11 @@ page {
height: 32rpx; height: 32rpx;
border-radius: 8rpx; border-radius: 8rpx;
&.wx-checkbox-input-checked { &.wx-checkbox-input-checked {
border-color: #fff !important;
background: linear-gradient(270deg, #439fc7 0%, #2f82a9 100%); background: linear-gradient(270deg, #439fc7 0%, #2f82a9 100%);
border-color: transparent; background-clip: border-box;
&::before { &::before {
font-size: 28rpx;
color: #fff; color: #fff;
} }
} }
@ -156,7 +161,7 @@ page {
color: rgba(100, 116, 139, 1); color: rgba(100, 116, 139, 1);
} }
.send { .send {
background: var(--, linear-gradient(270deg, #439fc7 0%, #2f82a9 100%)); background: linear-gradient(270deg, #439fc7 0%, #2f82a9 100%);
color: #fff; color: #fff;
border-color: transparent; border-color: transparent;
} }

228
src/pages/heartForm/index.ts

@ -1,93 +1,191 @@
import dayjs from "dayjs"
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
Page({ Page({
data: { data: {
popupShow: false, popupShow: false,
popupType: '', popupType: 'popup3',
popupParams: { popupParams: {
position: 'bottom', position: 'center',
close: true,
} as any, } as any,
fileList: [] as any[], id: '',
}, heartRate: '',
onLoad() { recordDateTime: dayjs().format("YYYY-MM-DD HH:mm"),
app.waitLogin({ type: 0 }).then(() => {}) datetimePickerShow: false,
datetimeValue: Date.now(),
maxDate: Date.now(),
isPsvtAttack: 0,
remark: '',
isEdit: false,
userInfo: {} as any,
}, },
handlePopupOk() { onLoad(options: any) {
const { popupType } = this.data if (options.id) {
if (popupType === 'argument') { this.setData({ id: options.id, isEdit: true })
wx.ajax({ app.waitLogin({ type: 1 }).then(() => {
method: 'POST', this.getDetail(options.id)
url: '?r=wtx/user/agree-guest-privacy', app.getUserInfo().then((res) => {
data: { this.setData({
WorkerId: app.globalData.scene?.workerId || '', userInfo: res,
}, })
}).then(() => { })
this.setData({ })
popupShow: false, } else {
popupType: '', app.waitLogin({ type: 1 }).then(() => {
popupParams: {}, app.getUserInfo().then((res) => {
this.setData({
userInfo: res,
})
}) })
const waitBindDoctorId = app.globalData.waitBindDoctorId
if (waitBindDoctorId) {
this.handleBindDoctor(waitBindDoctorId)
}
}) })
} }
if (popupType === 'conformBindDoctorConform') { },
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({ this.setData({
popupShow: false, heartRate: String(res.heartRate || ''),
}) recordDateTime: display,
wx.ajax({ datetimeValue,
method: 'POST', isPsvtAttack: res.isPsvtAttack ?? 0,
url: '?r=wtx/account/wait-bind-doctor', remark: res.remark || '',
data: {
doctorId: app.globalData.waitBindDoctorId,
},
}).then(() => {
wx.navigateTo({
url: `/patient/pages/login/index`,
})
}) })
})
},
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)
if (date.getTime() > Date.now()) {
wx.showToast({ title: '不能选择未来时间', icon: 'none' })
return
} }
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,
})
}, },
handlePopupCancel() { onPsvtAttackChange(e: any) {
const { popupType } = this.data const checked = (e.detail.value || []).includes('1')
if (popupType === 'argument') { this.setData({ isPsvtAttack: checked ? 1 : 0 })
wx.exitMiniProgram() },
onRemarkInput(e: any) {
this.setData({ remark: e.detail.value })
},
handleSubmit() {
const { id, heartRate, recordDateTime, isPsvtAttack, remark, isEdit, userInfo } = this.data
if (!heartRate) {
wx.showToast({ title: '请输入心率数值', icon: 'none' })
return
} }
if (popupType === 'conformBindDoctorConform') { if (!recordDateTime) {
this.setData({ wx.showToast({ title: '请选择日期时间', icon: 'none' })
popupShow: false, 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({ wx.ajax({
method: 'POST', method: 'POST',
url: '?r=wtx/account/wait-bind-doctor', url: '?r=psvt/heart-rate-record/create',
data: { data,
doctorId: app.globalData.waitBindDoctorId,
},
}).then(() => {
app.globalData.waitBindDoctorId = ''
}) })
.then(() => {
wx.hideLoading()
if (userInfo.isFollow == 1) {
wx.showToast({ title: '保存成功', icon: 'success' })
setTimeout(() => {
wx.navigateBack()
}, 1000)
} else {
this.setData({
popupShow: true,
popupType: 'popup3',
popupParams: {
position: 'center',
close: true,
},
})
}
})
.catch(() => {
wx.hideLoading()
})
} }
}, },
handleWechatWork() { handleBack() {
wx.navigateTo({ wx.navigateBack()
url: '/pages/wechatWork/index',
})
}, },
handleSetData(e) { handlePopupOk() {
const { fileList } = this.data const { popupType } = this.data
this.setData({ if (popupType == 'popup3') {
fileList: [...fileList, ...e.detail], this.setData({ popupShow: false })
}) wx.navigateBack()
}
}, },
handleDeleteFile(e) { handlePopupCancel() {
const { index } = e.detail const { popupType } = this.data
const { fileList } = this.data if (popupType == 'popup3') {
this.setData({ this.setData({ popupShow: false })
fileList: fileList.filter((_, i) => i !== index), wx.navigateBack()
}) }
}, },
}) })

46
src/pages/heartForm/index.wxml

@ -1,7 +1,7 @@
<navbar fixed custom-style="background:{{background}}" back> <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" /> <van-icon name="arrow-left" />
心率记录 {{isEdit?"编辑":"添加"}}心率记录
</view> </view>
</navbar> </navbar>
@ -13,27 +13,45 @@
<view class="rate"> <view class="rate">
<view class="r-title">当前心率数值</view> <view class="r-title">当前心率数值</view>
<view class="wrap"> <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 class="unit">次/分</view>
</view> </view>
</view> </view>
<view class="form-item"> <view class="form-item">
<view class="form-label">日期</view> <view class="form-label">日期时间</view>
<picker mode="date"> <view class="date" bind:tap="showDatetimePicker">
<view class="date"> <view class="content" data-place="请选择日期时间">{{recordDateTime}}</view>
<view class="content" data-place="请选择日期"></view> <van-icon class="icon" name="arrow-down" />
<van-icon class="icon" name="arrow-down" /> </view>
</view>
</picker>
</view> </view>
<view class="form-item"> <view class="form-item">
<view class="form-label">其他备注</view> <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> </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>
<view class="page-footer"> <view class="page-footer">
<view class="cancel">取消</view> <view class="cancel" bind:tap="handleBack">取消</view>
<view class="send">保存记录</view> <view class="send" bind:tap="handleSubmit">保存记录</view>
</view> </view>
</view> </view>
<van-popup show="{{datetimePickerShow}}" position="bottom" round bind:close="hideDatetimePicker">
<van-datetime-picker
type="datetime"
value="{{datetimeValue}}"
max-date="{{maxDate}}"
bind:confirm="onDatetimeConfirm"
bind:cancel="hideDatetimePicker"
/>
</van-popup>
<popup
show="{{popupShow}}"
type="{{popupType}}"
params="{{popupParams}}"
bind:ok="handlePopupOk"
bind:cancel="handlePopupCancel"
></popup>

3
src/pages/hotTopic/index.json

@ -2,6 +2,7 @@
"navigationStyle": "custom", "navigationStyle": "custom",
"usingComponents": { "usingComponents": {
"popup": "/components/popup/index", "popup": "/components/popup/index",
"navbar": "/components/navbar/index" "navbar": "/components/navbar/index",
"pagination": "/components/pagination/index"
} }
} }

1
src/pages/hotTopic/index.scss

@ -5,6 +5,7 @@ page {
.page-title { .page-title {
font-size: 36rpx; font-size: 36rpx;
color: #fff; color: #fff;
padding-right: 100rpx;
} }
.page { .page {

46
src/pages/hotTopic/index.ts

@ -7,9 +7,50 @@ Page({
popupParams: { popupParams: {
position: 'bottom', position: 'bottom',
} as any, } as any,
topicList: [] as Array<any>,
topicPagination: {
page: 1,
pages: 1,
count: 0,
},
}, },
onLoad() { onLoad() {
app.waitLogin({ type: 0 }).then(() => {}) app.waitLogin({ type: 1 }).then(() => {})
},
onShow() {
this.getTopicList()
},
getTopicList(page = 1, append = false) {
wx.ajax({
method: 'GET',
url: '?r=psvt/topic/list',
data: {
page,
count: 10,
},
}).then((res: any) => {
const list = res.list || []
this.setData({
topicList: append ? this.data.topicList.concat(list) : list,
topicPagination: {
page: res.page || 1,
pages: res.pages || 1,
count: Number(res.count) || 0,
},
})
})
},
onReachBottom() {
const { topicPagination } = this.data
if (topicPagination.page < topicPagination.pages) {
this.getTopicList(topicPagination.page + 1, true)
}
},
handleTopicTap(e: any) {
const { id } = e.currentTarget.dataset
wx.navigateTo({
url: `/pages/hotTopicDetail/index?id=${id}`,
})
}, },
handlePopupOk() { handlePopupOk() {
const { popupType } = this.data const { popupType } = this.data
@ -74,6 +115,9 @@ Page({
url: '/pages/wechatWork/index', url: '/pages/wechatWork/index',
}) })
}, },
handleBack() {
wx.navigateBack()
},
}) })
export {} export {}

9
src/pages/hotTopic/index.wxml

@ -1,5 +1,5 @@
<navbar fixed custom-style="background:{{background}}" back> <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" /> <van-icon name="arrow-left" />
</view> </view>
</navbar> </navbar>
@ -10,11 +10,12 @@
> >
<view class="container"> <view class="container">
<view class="tp-list"> <view class="tp-list">
<view class="li" wx:for="{{10}}" wx:key="index"> <view class="li" wx:for="{{topicList}}" wx:key="id" bind:tap="handleTopicTap" data-id="{{item.id}}">
<view class="num">{{index+1}}</view> <view class="num">{{index+1}}</view>
<view class="content"># 我的心悸经历</view> <view class="content"># {{item.topicName}}</view>
<view class="total">230篇帖子</view> <view class="total">{{item.postCount}}篇帖子</view>
</view> </view>
</view> </view>
<pagination pagination="{{topicPagination}}" />
</view> </view>
</view> </view>

3
src/pages/hotTopicDetail/index.json

@ -2,6 +2,7 @@
"navigationStyle": "custom", "navigationStyle": "custom",
"usingComponents": { "usingComponents": {
"popup": "/components/popup/index", "popup": "/components/popup/index",
"navbar": "/components/navbar/index" "navbar": "/components/navbar/index",
"pagination": "/components/pagination/index"
} }
} }

60
src/pages/hotTopicDetail/index.scss

@ -5,11 +5,12 @@ page {
.page-title { .page-title {
font-size: 36rpx; font-size: 36rpx;
color: #fff; color: #fff;
padding-right: 100rpx;
} }
.page { .page {
.info { .info {
margin: 56rpx 30rpx 0; margin: 86rpx 30rpx 0;
.i-header { .i-header {
display: flex; display: flex;
align-items: center; align-items: center;
@ -31,7 +32,7 @@ page {
} }
} }
.container { .container {
margin-top: 64rpx; margin-top: 32rpx;
padding-bottom: 120rpx; padding-bottom: 120rpx;
border-radius: 32rpx 32rpx 0 0; border-radius: 32rpx 32rpx 0 0;
overflow: hidden; overflow: hidden;
@ -52,6 +53,7 @@ page {
&.active { &.active {
font-size: 32rpx; font-size: 32rpx;
color: rgba(47, 130, 169, 1); color: rgba(47, 130, 169, 1);
font-weight: bold;
&::after { &::after {
content: ''; content: '';
width: 32rpx; width: 32rpx;
@ -74,7 +76,7 @@ page {
padding: 36rpx 32rpx 12rpx; padding: 36rpx 32rpx 12rpx;
border-radius: 32rpx; border-radius: 32rpx;
border: 2rpx solid #f1f5f9; border: 2rpx solid #f1f5f9;
background: #fff; background: rgba(255, 255, 255, 0.7);
box-shadow: 0 16rpx 48rpx -8rpx rgba(0, 99, 132, 0.06); box-shadow: 0 16rpx 48rpx -8rpx rgba(0, 99, 132, 0.06);
box-sizing: border-box; box-sizing: border-box;
.user { .user {
@ -111,23 +113,45 @@ page {
line-height: 32rpx; line-height: 32rpx;
box-sizing: border-box; box-sizing: border-box;
} }
.content { .title {
margin-top: 32rpx; margin-top: 32rpx;
font-size: 32rpx; font-size: 32rpx;
color: rgba(24, 28, 30, 1); color: rgba(24, 28, 30, 1);
font-weight: bold;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.content {
margin-top: 12rpx;
font-size: 32rpx;
color: rgba(24, 28, 30, 1);
line-height: 52rpx; line-height: 52rpx;
.c-topic { .c-topic {
display: inline; display: inline;
font-size: 32rpx; font-size: 32rpx;
color: rgba(47, 130, 169, 1); color: rgba(47, 130, 169, 1);
} }
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
} }
.tags { .tags {
margin-top: 24rpx; margin-top: 24rpx;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: nowrap;
gap: 16rpx; gap: 16rpx;
overflow-x: auto;
overflow-y: hidden;
&::-webkit-scrollbar {
display: none;
}
.tag { .tag {
flex-shrink: 0;
padding: 0 24rpx; padding: 0 24rpx;
height: 48rpx; height: 48rpx;
font-size: 24rpx; font-size: 24rpx;
@ -143,6 +167,24 @@ page {
height: 352rpx; height: 352rpx;
border-radius: 24rpx; border-radius: 24rpx;
} }
.video-cover {
position: relative;
overflow: hidden;
.p-img {
width: 100%;
height: 100%;
border-radius: 24rpx;
}
}
.play-icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 80rpx;
height: 80rpx;
z-index: 1;
}
.photo9 { .photo9 {
margin-top: 24rpx; margin-top: 24rpx;
display: grid; display: grid;
@ -151,11 +193,17 @@ page {
.p-item { .p-item {
width: 100%; width: 100%;
aspect-ratio: 1 / 1; aspect-ratio: 1 / 1;
position: relative;
overflow: hidden;
.p-img { .p-img {
width: 100%; width: 100%;
height: 100%; height: 100%;
border-radius: 24rpx; border-radius: 24rpx;
} }
.play-icon {
width: 56rpx;
height: 56rpx;
}
} }
} }
.comment { .comment {
@ -204,7 +252,7 @@ page {
width: 128rpx; width: 128rpx;
height: 128rpx; height: 128rpx;
border-radius: 19998rpx; border-radius: 19998rpx;
background: var(--, linear-gradient(270deg, #439fc7 0%, #2f82a9 100%)); background: linear-gradient(270deg, #439fc7 0%, #2f82a9 100%);
box-shadow: 0 40rpx 50rpx -10rpx rgba(47, 130, 169, 0.38); box-shadow: 0 40rpx 50rpx -10rpx rgba(47, 130, 169, 0.38);
box-sizing: border-box; box-sizing: border-box;
display: flex; display: flex;

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save