You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

643 lines
18 KiB

const echarts = require('../../../components/ec-canvas/echarts.js')
Page({
data: {
fold1: true,
fold2: true,
// 用户信息
pharmacistName: '',
pharmacistAvatar: '',
pharmacyName: '',
// 项目列表
projectList: [] as Array<{ projectId: number; projectName: string; projectDescription: string }>,
currentProjectId: 0,
currentProjectName: '',
projectIndex: 0,
// 待处理患者数
pendingCount: 0,
jumpPendingCount: 0,
enrollPendingCount: 0,
// 累计统计数据
invitePatientCount: 0,
jumpPatientCount: 0,
enrollPatientCount: 0,
// 累计适应症统计
indicationStats: [] as Array<{
indicationId: number
indicationName: string
invitePatientCount: number
jumpPatientCount: number
enrollPatientCount: number
}>,
// 日/月度统计数据
dailyInvitePatientCount: 0,
dailyJumpPatientCount: 0,
dailyEnrollPatientCount: 0,
// 日/月度适应症统计
dailyIndicationStats: [] as Array<{
indicationId: number
indicationName: string
invitePatientCount: number
jumpPatientCount: number
enrollPatientCount: number
}>,
// 图表数据
chartData: [] as Array<{
date: string
invitePatientCount: number
jumpPatientCount: number
enrollPatientCount: number
}>,
// 日期范围 - 邀约患者统计卡片(单日)
startDate: '',
today: '',
// 统计卡片显示用的月份(YYYY-MM)
startMonth: '',
// 日期范围 - 图表(日期范围)
chartStartDate: '',
chartEndDate: '',
// 图表显示用的月份(YYYY-MM)
chartStartMonth: '',
chartEndMonth: '',
// 统计类型: day-日统计, month-月统计
statType: 'day',
},
ecDataTrendComponent1_1: null as any,
async onLoad() {
const app = getApp<IAppOption>()
// 药店端页面,仅允许药店人员(4)访问
app.waitLogin({ types: [4] }).then(() => {
this.getUserInfo()
this.getProjectList()
})
// 初始化日期
const today = this.formatDate(new Date())
const currentMonth = this.formatMonth(new Date())
const defaultStartDate = this.formatDate(new Date(Date.now() - 30 * 24 * 60 * 60 * 1000))
const defaultStartMonth = this.formatMonth(new Date(Date.now() - 365 * 24 * 60 * 60 * 1000))
this.setData({
today,
// 邀约患者统计卡片(单日)- 默认为今天
startDate: today,
startMonth: currentMonth,
// 图表(日期范围)- 默认为最近30天
chartStartDate: defaultStartDate,
chartEndDate: today,
// 图表月份显示 - 默认为最近12个月
chartStartMonth: defaultStartMonth,
chartEndMonth: currentMonth,
})
},
// 格式化日期
formatDate(date: Date): string {
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
},
// 格式化月份(YYYY-MM)
formatMonth(date: Date): string {
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
return `${year}-${month}`
},
// 获取用户信息
getUserInfo() {
wx.ajax({
method: 'GET',
url: '/app/pharmacist/pharmacist/profile',
}).then((res: any) => {
this.setData({
pharmacistName: res.name,
pharmacistAvatar: res.avatar,
pharmacyName: res.pharmacyName,
})
})
},
// 获取项目列表
getProjectList() {
wx.ajax({
method: 'GET',
url: '/app/pharmacist/pharmacist/project-list',
}).then((res: any) => {
const projectList = res.list || []
const currentProjectId = res.currentProjectId || projectList[0]?.projectId || 0
const currentProject = projectList.find((item: any) => item.projectId === currentProjectId) || projectList[0]
const projectIndex = projectList.findIndex((item: any) => item.projectId === currentProjectId)
this.setData({
projectList,
currentProjectId,
currentProjectName: currentProject?.projectName || '',
projectIndex: projectIndex >= 0 ? projectIndex : 0,
})
// 获取其他数据
this.getPendingCount()
this.getTotalStatistics()
this.getDailyStatistics()
this.getPatientChart()
})
},
// 切换项目
onProjectChange(e: WechatMiniprogram.CustomEvent) {
const index = e.detail.value
const project = this.data.projectList[index]
if (project && project.projectId !== this.data.currentProjectId) {
// 先调用切换项目接口
wx.ajax({
method: 'POST',
url: '/app/pharmacist/pharmacist/switch-project',
data: {
projectId: project.projectId,
},
})
.then(() => {
// 切换成功后更新页面数据
this.setData({
currentProjectId: project.projectId,
currentProjectName: project.projectName,
projectIndex: index,
})
// 重新加载数据
this.getPendingCount()
this.getTotalStatistics()
this.getDailyStatistics()
this.getPatientChart()
wx.showToast({
title: '切换成功',
icon: 'success',
})
})
.catch(() => {
wx.showToast({
title: '切换失败',
icon: 'none',
})
})
}
},
// 获取待处理患者数
getPendingCount() {
wx.ajax({
method: 'GET',
url: '/app/pharmacist/pharmacist/pending-count',
})
.then((res: any) => {
this.setData({
pendingCount: res.totalPendingCount || 0,
jumpPendingCount: res.jumpPendingCount || 0,
enrollPendingCount: res.enrollPendingCount || 0,
})
})
.catch(() => {
// 接口失败时使用默认值
this.setData({
pendingCount: 0,
jumpPendingCount: 0,
enrollPendingCount: 0,
})
})
},
// 获取累计统计数据看板
getTotalStatistics() {
wx.ajax({
method: 'GET',
url: '/app/pharmacist/pharmacist/statistics',
}).then((res: any) => {
this.setData({
invitePatientCount: res.invitePatientCount || 0,
jumpPatientCount: res.jumpPatientCount || 0,
enrollPatientCount: res.enrollPatientCount || 0,
indicationStats: res.indicationStats || [],
})
})
},
// 获取日/月度统计数据看板
getDailyStatistics() {
// 根据统计类型格式化日期
const statDate =
this.data.statType === 'month'
? this.data.startMonth // YYYY-MM
: this.data.startDate // YYYY-MM-DD
wx.ajax({
method: 'GET',
url: '/app/pharmacist/pharmacist/patient-statistics',
data: {
statDate,
type: this.data.statType,
},
}).then((res: any) => {
this.setData({
dailyInvitePatientCount: res.invitePatientCount || 0,
dailyJumpPatientCount: res.jumpPatientCount || 0,
dailyEnrollPatientCount: res.enrollPatientCount || 0,
dailyIndicationStats: res.indicationStats || [],
})
})
},
// 获取邀约患者统计图表(使用 chart 的日期范围)
getPatientChart() {
// 根据统计类型格式化日期
const startDate =
this.data.statType === 'month'
? this.data.chartStartMonth // YYYY-MM
: this.data.chartStartDate // YYYY-MM-DD
const endDate =
this.data.statType === 'month'
? this.data.chartEndMonth // YYYY-MM
: this.data.chartEndDate // YYYY-MM-DD
wx.ajax({
method: 'GET',
url: '/app/pharmacist/pharmacist/patient-chart',
data: {
type: this.data.statType,
startDate,
endDate,
},
}).then((res: any) => {
const list = res || []
// 转换为图表需要的格式
const chartData = list.map((item: any) => ({
date: item.statDate,
invitePatientCount: item.invitePatientCount || 0,
jumpPatientCount: item.jumpPatientCount || 0,
enrollPatientCount: item.enrollPatientCount || 0,
}))
this.setData({
chartData,
})
this.initChartBar(chartData)
})
},
// 切换统计类型
switchStatType(e: WechatMiniprogram.CustomEvent) {
const type = e.currentTarget.dataset.type
const isMonth = type === 'month'
// 根据统计类型重置日期范围
let startDate = this.data.startDate
let startMonth = this.data.startMonth
let chartStartDate = this.data.chartStartDate
let chartEndDate = this.data.chartEndDate
let chartStartMonth = this.data.chartStartMonth
let chartEndMonth = this.data.chartEndMonth
if (isMonth) {
// 切换到月统计,设置默认月份
startMonth = this.formatMonth(new Date())
startDate = `${startMonth}-01`
// 图表月份范围为最近12个月
chartEndMonth = this.formatMonth(new Date())
chartStartMonth = this.formatMonth(new Date(Date.now() - 365 * 24 * 60 * 60 * 1000))
chartEndDate = `${chartEndMonth}-01`
chartStartDate = `${chartStartMonth}-01`
} else {
// 切换到日统计,设置默认日期为今天
startDate = this.formatDate(new Date())
startMonth = startDate.substring(0, 7)
// 图表日期范围为最近30天
chartEndDate = this.formatDate(new Date())
chartStartDate = this.formatDate(new Date(Date.now() - 30 * 24 * 60 * 60 * 1000))
chartEndMonth = chartEndDate.substring(0, 7)
chartStartMonth = chartStartDate.substring(0, 7)
}
this.setData({
statType: type,
startDate,
startMonth,
chartStartDate,
chartEndDate,
chartStartMonth,
chartEndMonth,
})
this.getDailyStatistics()
this.getPatientChart()
},
// 日期选择变化
onDateChange(e: WechatMiniprogram.CustomEvent) {
const value = e.detail.value // YYYY-MM-DD 或 YYYY-MM
// 月统计时,value 是 YYYY-MM 格式,需要补全为 YYYY-MM-DD
const isMonth = value.length === 7
const fullDate = isMonth ? `${value}-01` : value
const monthValue = isMonth ? value : value.substring(0, 7)
this.setData({
startDate: fullDate,
startMonth: monthValue,
})
// 重新加载日/月度统计数据
this.getDailyStatistics()
},
// 切换到上一天/上月
prevDate() {
const isMonth = this.data.statType === 'month'
let newDate: Date
let startDate: string
let startMonth: string
if (isMonth) {
// 月统计:切换到上个月
const currentDate = new Date(this.data.startDate)
newDate = new Date(currentDate.getFullYear(), currentDate.getMonth() - 1, 1)
startDate = this.formatDate(newDate)
startMonth = this.formatMonth(newDate)
} else {
// 日统计:切换到上一天
const currentDate = new Date(this.data.startDate)
newDate = new Date(currentDate.getTime() - 24 * 60 * 60 * 1000)
startDate = this.formatDate(newDate)
startMonth = startDate.substring(0, 7)
}
this.setData({ startDate, startMonth })
// 重新加载日/月度统计数据
this.getDailyStatistics()
},
// 切换到下一天/下月
nextDate() {
const isMonth = this.data.statType === 'month'
const today = new Date()
let newDate: Date
let startDate: string
let startMonth: string
if (isMonth) {
// 月统计:切换到下个月
const currentDate = new Date(this.data.startDate)
newDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 1)
// 最大月份不能大于当前月份
const currentMonth = new Date(today.getFullYear(), today.getMonth(), 1)
if (newDate > currentMonth) {
wx.showToast({
title: '不能选择未来月份',
icon: 'none',
})
return
}
startDate = this.formatDate(newDate)
startMonth = this.formatMonth(newDate)
} else {
// 日统计:切换到下一天
const currentDate = new Date(this.data.startDate)
newDate = new Date(currentDate.getTime() + 24 * 60 * 60 * 1000)
// 最大日期不能大于当前日期
if (newDate > today) {
wx.showToast({
title: '不能选择未来日期',
icon: 'none',
})
return
}
startDate = this.formatDate(newDate)
startMonth = startDate.substring(0, 7)
}
this.setData({ startDate, startMonth })
// 重新加载日/月度统计数据
this.getDailyStatistics()
},
// 图表日期选择变化(开始日期)
onChartStartDateChange(e: WechatMiniprogram.CustomEvent) {
const value = e.detail.value // YYYY-MM-DD 或 YYYY-MM
const chartEndDate = this.data.chartEndDate
// 月统计时,value 是 YYYY-MM 格式,需要补全为 YYYY-MM-DD
const isMonth = value.length === 7
const fullDate = isMonth ? `${value}-01` : value
const monthValue = isMonth ? value : value.substring(0, 7)
// 验证日期范围
if (chartEndDate && fullDate > chartEndDate) {
wx.showToast({
title: '开始时间不能大于结束时间',
icon: 'none',
})
return
}
this.setData({
chartStartDate: fullDate,
chartStartMonth: monthValue,
})
this.getPatientChart()
},
// 图表日期选择变化(结束日期)
onChartEndDateChange(e: WechatMiniprogram.CustomEvent) {
const value = e.detail.value // YYYY-MM-DD 或 YYYY-MM
const chartStartDate = this.data.chartStartDate
// 月统计时,value 是 YYYY-MM 格式,需要补全为 YYYY-MM-DD
const isMonth = value.length === 7
const fullDate = isMonth ? `${value}-01` : value
const monthValue = isMonth ? value : value.substring(0, 7)
// 验证日期范围
if (chartStartDate && fullDate < chartStartDate) {
wx.showToast({
title: '结束时间不能小于开始时间',
icon: 'none',
})
return
}
this.setData({
chartEndDate: fullDate,
chartEndMonth: monthValue,
})
this.getPatientChart()
},
initChartBar(list: any[]) {
return new Promise((reslove) => {
this.ecDataTrendComponent1_1 = this.selectComponent('#chart1_1')
this.ecDataTrendComponent1_1.init((canvas, width, height, dpr) => {
const chart = echarts.init(canvas, null, {
width,
height,
devicePixelRatio: dpr,
})
canvas.setChart(chart)
const x: string[] = []
const y1: number[] = []
const y2: number[] = []
const y3: number[] = []
list.forEach((item) => {
x.push(item.date)
y1.push(item.enrollPatientCount)
y2.push(item.jumpPatientCount)
y3.push(item.invitePatientCount)
})
const option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
},
formatter (params) {
let result = `${params[0].axisValue }\n`
params.forEach((item, index) => {
result += `${item.marker } ${ item.seriesName }: ${ item.value }`
if (index < params.length - 1) {
result += '\n'
}
})
return result
},
},
legend: {
top: 0,
right: 0,
itemWidth: 8,
itemHeight: 8,
icon: 'rect',
lineStyle: {
width: '0',
},
textStyle: {
color: '#B5B8BB',
fontSize: '12',
},
},
grid: {
top: '10%',
left: '3%',
right: '4%',
bottom: '0',
containLabel: true,
},
xAxis: [
{
type: 'category',
axisTick: {
show: false,
},
axisLabel: {
fontSize: 10,
color: '#B5B8BB',
},
axisLine: {
show: false,
},
data: x,
},
],
yAxis: [
{
type: 'value',
minInterval: 1,
splitLine: {
lineStyle: {
type: 'dashed',
},
},
axisLabel: {
fontSize: 10,
color: '#B5B8BB',
formatter(value) {
return Math.abs(value)
},
},
},
],
series: [
{
name: '入组患者数',
type: 'bar',
stack: 'a',
color: '#FF5722',
barWidth: 12,
data: y1,
},
{
name: '跳转患者数',
type: 'bar',
stack: 'a',
color: '#FF8A4C',
barWidth: 12,
data: y2,
},
{
name: '邀约患者数',
type: 'bar',
stack: 'a',
width: 4,
color: '#FFA64D',
barWidth: 12,
data: y3,
},
],
dataZoom: {
type: 'inside',
startValue: x.length - 6,
endValue: x.length - 1,
filterMode: 'none',
},
}
chart.setOption(option)
reslove(chart)
return chart
})
})
},
handleInvite() {
wx.navigateTo({
url: '/doctor/pages/invite/index',
})
},
handleStat() {
const { chartStartDate, chartEndDate, statType } = this.data
wx.navigateTo({
url: `/doctor/pages/stat/index?startDate=${chartStartDate}&endDate=${chartEndDate}&type=${statType}`,
})
},
handleFold(e) {
const { key } = e.currentTarget.dataset
this.setData({
[key]: !this.data[key],
})
},
})