const echarts = require('../../../components/ec-canvas/echarts.js') Page({ data: { fold1: true, fold2: true, // 用户信息 pharmacistName: '', pharmacistAvatar: '', pharmacyName: '', // 待处理患者数 pendingCount: 0, // 统计数据 invitePatientCount: 0, jumpPatientCount: 0, enrollPatientCount: 0, // 适应症统计 indicationStats: [] as Array<{ indicationId: number indicationName: string invitePatientCount: number jumpPatientCount: number enrollPatientCount: number }>, // 图表数据 chartData: [] as Array<{ date: string, count: number }>, // 日期范围 startDate: '', endDate: '', // 统计类型: day-日统计, month-月统计 statType: 'day', }, ecDataTrendComponent1_1: null as any, async onLoad() { const app = getApp() // 药店端页面,仅允许药店人员(4)访问 app.waitLogin({ types: [4] }).then(() => { this.getUserInfo() this.getPendingCount() this.getStatistics() this.getPatientChart() }) // 初始化日期范围为最近30天 const endDate = this.formatDate(new Date()) const startDate = this.formatDate(new Date(Date.now() - 30 * 24 * 60 * 60 * 1000)) this.setData({ startDate, endDate, }) }, // 格式化日期 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}` }, // 获取用户信息 getUserInfo() { wx.ajax({ method: 'GET', url: '/app/pharmacist/pharmacist/profile', }).then((res: any) => { this.setData({ pharmacistName: res.name, pharmacistAvatar: res.avatar, pharmacyName: res.pharmacyName, }) }).catch(() => { // 接口失败时使用模拟数据 this.setData({ pharmacistName: '李药师', pharmacistAvatar: '', pharmacyName: '康泰大药房(人民路店)', }) }) }, // 获取待处理患者数 getPendingCount() { wx.ajax({ method: 'GET', url: '/app/pharmacist/pharmacist/pending-count', }).then((res: any) => { this.setData({ pendingCount: res.count || 0, }) }).catch(() => { // 接口失败时使用模拟数据 this.setData({ pendingCount: 12, }) }) }, // 获取统计数据看板 getStatistics() { 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 || [], }) }).catch(() => { // 接口失败时使用模拟数据 this.setData({ invitePatientCount: 156, jumpPatientCount: 128, enrollPatientCount: 89, indicationStats: [ { indicationId: 1, indicationName: '斑块状银屑病', invitePatientCount: 80, jumpPatientCount: 65, enrollPatientCount: 45 }, { indicationId: 2, indicationName: '溃疡性结肠炎', invitePatientCount: 45, jumpPatientCount: 38, enrollPatientCount: 28 }, { indicationId: 3, indicationName: '克罗恩病', invitePatientCount: 31, jumpPatientCount: 25, enrollPatientCount: 16 }, ], }) }) }, // 获取邀约患者统计图表 getPatientChart() { wx.ajax({ method: 'GET', url: '/app/pharmacist/pharmacist/patient-chart', data: { type: this.data.statType, startDate: this.data.startDate, endDate: this.data.endDate, }, }).then((res: any) => { const list = res.list || [] this.setData({ chartData: list, }) this.initChartBar(list) }).catch(() => { // 接口失败时使用模拟数据 const mockData = this.generateMockChartData() this.setData({ chartData: mockData, }) this.initChartBar(mockData) }) }, // 生成模拟图表数据 generateMockChartData() { const list: any[] = [] const days = this.data.statType === 'day' ? 30 : 12 for (let i = 0; i < days; i++) { const date = new Date() if (this.data.statType === 'day') { date.setDate(date.getDate() - (days - 1 - i)) list.push({ date: this.formatDate(date), count: Math.floor(Math.random() * 30) + 5, }) } else { date.setMonth(date.getMonth() - (days - 1 - i)) list.push({ date: `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`, count: Math.floor(Math.random() * 300) + 50, }) } } return list }, // 切换统计类型 switchStatType(e: WechatMiniprogram.CustomEvent) { const type = e.currentTarget.dataset.type this.setData({ statType: type, }) this.getPatientChart() }, // 日期选择变化 onDateChange(e: WechatMiniprogram.CustomEvent) { const { field } = e.currentTarget.dataset const value = e.detail.value // 验证日期范围 if (field === 'startDate' && this.data.endDate && value > this.data.endDate) { wx.showToast({ title: '开始时间不能大于结束时间', icon: 'none', }) return } if (field === 'endDate' && this.data.startDate && value < this.data.startDate) { wx.showToast({ title: '结束时间不能小于开始时间', icon: 'none', }) return } this.setData({ [field]: value, }) // 重新加载图表数据 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: string[] = [] list.forEach((item) => { x.push(item.date || item.StatMonth) y1.push(item.count || item.MonthInvitePCount) }) const option = { 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: y1, }, { name: '邀约患者数', type: 'bar', stack: 'a', width: 4, color: '#FFA64D', barWidth: 12, data: y1, }, ], 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() { wx.navigateTo({ url: '/doctor/pages/stat/index', }) }, handleFold(e) { const { key } = e.currentTarget.dataset this.setData({ [key]: !this.data[key], }) }, })