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
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], |
|
}) |
|
}, |
|
})
|
|
|