Files
ljwx-health/ljwx-bigscreen-bak/app/static/js/modules/app-initializer.js
T
brunoandClaude Sonnet 4.5 7ca86bce38 feat(health): Sprint 9 - Behavioral Recommendation Engine + Compilation Fixes
## Sprint 9 Implementation (100% Complete)

### New Features
1. **Behavioral Recommendation Engine**
   - Priority scoring algorithm: (Severity × 0.5) + (Feasibility × 0.3) + (User Attention × 0.2)
   - 4 recommendation strategies: Exercise, Sleep, Diet, Attention
   - Top 5 prioritized recommendations per user
   - Automatic behavioral profile generation (scheduled daily 03:30)

2. **Trend Analysis System**
   - 30-day trend analysis with linear regression
   - Trend classification: IMPROVING/STABLE/DECLINING
   - Time series data extraction for visualization
   - Milestone identification (best/worst dates)

### New APIs (6 endpoints)
- POST /api/health/behavioral-recommendations/generate
- GET  /api/health/behavioral-recommendations/query
- POST /api/health/behavioral-recommendations/batch-generate
- GET  /api/health/behavioral-trends/query

### Deliverables
- 20 new files: 4 DTOs, 5 strategies, 3 services, 3 controllers, 5 test files
- 3,800+ lines of production code
- 62+ unit test cases, 10 integration test cases
- Architecture documentation (450 lines)
- Sprint 9 completion summary (700+ lines)

## Compilation Fixes (Pre-existing Code)

### Fixed Errors
1. **Java 11+ Compatibility**
   - Replaced deprecated @Resource with @Autowired (8 files)
   - Fixed javax.annotation.Resource → org.springframework.beans.factory.annotation.Autowired

2. **Import Path Corrections**
   - Fixed SysUserMapper path: com.ljwx.modules.system.mapper → com.ljwx.modules.system.repository.mapper
   - Fixed SysUser entity path: com.ljwx.modules.system.entity → com.ljwx.modules.system.domain.entity

3. **Result API Alignment**
   - Fixed Result.ok() method calls in RiskProfileController
   - Updated import: com.ljwx.common.api.Result → com.ljwx.common.api.vo.Result
   - Aligned Sprint 9 controllers with correct Result API

4. **User Entity Field Mapping**
   - Calculated age from birthday instead of using non-existent getAge()
   - Used position field instead of non-existent getPositionType()

5. **Dependency Injection**
   - Added BehavioralProfileService as @Autowired field in HealthBaselineScoreTasks
   - Removed manual bean lookup via non-existent ApplicationContextProvider

### Modified Files (Compilation Fixes)
- RiskProfileService.java
- RiskProfileController.java
- RiskProfileServiceTest.java
- CardiovascularRiskAssessor.java
- RespiratoryRiskAssessor.java
- SleepRiskAssessor.java
- ExerciseRiskAssessor.java
- RiskTrendAnalysisService.java
- HealthBaselineScoreTasks.java
- BehavioralProfileController.java
- BehavioralRecommendationController.java
- BehavioralTrendController.java

## Test Results
- ✅ Compilation: SUCCESS (Java 21)
- ✅ Application: Started successfully on port 9998
- ✅ OpenAPI: Exported (458 endpoints, 550 schemas)

## Reference
- Sprint 9 Summary: docs/02-architecture/sprint9-completion-summary.md
- Architecture Doc: docs/02-architecture/phase2-behavioral-recommendation-architecture.md

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-21 07:48:01 +08:00

234 lines
6.1 KiB
JavaScript

// ============================================
// LJWX BigScreen - 应用初始化模块
// 从 main.html 提取 (Phase 7 优化)
// ============================================
/**
* 应用初始化管理器
* 统一管理所有事件监听器和初始化流程
*/
const AppInitializer = {
// 初始化标志
initialized: false,
// 全局变量引用
globalCharts: null,
currentDept: '',
currentUser: '',
/**
* 主初始化函数
* 在 DOMContentLoaded 事件中调用
*/
init() {
if (this.initialized) {
console.warn('⚠️ AppInitializer 已经初始化,跳过重复初始化');
return;
}
console.log('🚀 开始应用初始化...');
// 1. 初始化租户信息
this.initTenantInfo();
// 2. 初始化筛选面板
this.initFilterPanel();
// 3. 初始化日期选择器
this.initDatePicker();
// 4. 初始化健康卡片
this.initHealthCards();
// 5. 延迟初始化图表和数据
setTimeout(() => {
this.initChartsAndData();
}, 100);
// 6. 绑定全局事件
this.bindGlobalEvents();
this.initialized = true;
console.log('✅ 应用初始化完成');
},
/**
* 初始化租户信息显示
*/
initTenantInfo() {
const tenantIdElement = document.getElementById('tenantId');
if (tenantIdElement && window.GLOBAL_CUSTOMER_ID) {
tenantIdElement.textContent = window.GLOBAL_CUSTOMER_ID;
console.log('✅ 租户信息初始化完成:', window.GLOBAL_CUSTOMER_ID);
}
// 调用全局初始化租户信息函数(如果存在)
if (typeof window.initializeTenantInfo === 'function') {
window.initializeTenantInfo();
}
},
/**
* 初始化筛选面板
*/
initFilterPanel() {
const filterToggle = document.getElementById('filterToggle');
if (filterToggle && typeof window.toggleFilter === 'function') {
filterToggle.addEventListener('click', window.toggleFilter);
console.log('✅ 筛选面板初始化完成');
}
// 初始化搜索筛选器
if (typeof window.initSearchFilter === 'function') {
window.initSearchFilter();
}
},
/**
* 初始化日期选择器
*/
initDatePicker() {
if (typeof window.initStatsDatePicker === 'function') {
window.initStatsDatePicker();
console.log('✅ 日期选择器初始化完成');
}
},
/**
* 初始化健康卡片
*/
initHealthCards() {
if (typeof window.initializeHealthCards === 'function') {
window.initializeHealthCards();
console.log('✅ 健康卡片初始化完成');
}
},
/**
* 初始化图表和数据
*/
initChartsAndData() {
console.log('📊 开始初始化图表和数据...');
// 1. 初始化图表
if (typeof window.initCharts === 'function') {
this.globalCharts = window.initCharts();
window.globalCharts = this.globalCharts; // 暴露到全局
console.log('✅ 图表初始化完成');
}
// 2. 初始化地图(延迟执行,避免阻塞)
setTimeout(() => {
this.initMap();
}, 200);
// 3. 等待地图初始化后刷新数据
setTimeout(() => {
this.refreshData();
// 4. 设置定时刷新(每60秒)
setInterval(() => {
if (typeof window.refreshData === 'function') {
window.refreshData();
}
}, 60000);
console.log('✅ 定时数据刷新已启动(60秒间隔)');
}, 1500);
},
/**
* 初始化地图
*/
initMap() {
console.log('🗺️ 开始初始化地图...');
if (typeof window.initializeMap === 'function') {
try {
const urlParams = new URLSearchParams(window.location.search);
const userId = urlParams.get('userId') || null;
window.initializeMap(window.GLOBAL_CUSTOMER_ID, userId);
console.log('✅ 地图初始化完成');
} catch (error) {
console.error('❌ 地图初始化失败:', error);
}
} else {
console.warn('⚠️ initializeMap 函数未定义,跳过地图初始化');
}
},
/**
* 刷新数据
*/
refreshData() {
if (typeof window.refreshData === 'function') {
window.refreshData();
console.log('✅ 初始数据加载完成');
}
},
/**
* 绑定全局事件
*/
bindGlobalEvents() {
// 1. 全局点击事件 - 筛选面板自动收起
document.addEventListener('click', (event) => {
const filterPanel = document.querySelector('.filter-panel');
const filterToggle = document.querySelector('.filter-toggle');
if (filterPanel && filterToggle) {
// 如果点击的不是筛选面板内的元素且面板是展开的
if (!filterPanel.contains(event.target) &&
!filterToggle.contains(event.target) &&
filterPanel.classList.contains('expanded')) {
if (typeof window.toggleFilter === 'function') {
window.toggleFilter();
}
}
}
});
// 2. 阻止筛选面板内的点击事件冒泡
const filterPanel = document.querySelector('.filter-panel');
if (filterPanel) {
filterPanel.addEventListener('click', (event) => {
event.stopPropagation();
});
}
// 3. 快捷键 - Ctrl+I 切换信息面板
document.addEventListener('keydown', (e) => {
if (e.key === 'i' && e.ctrlKey) {
if (typeof window.toggleInfoPanel === 'function') {
window.toggleInfoPanel();
}
}
});
console.log('✅ 全局事件绑定完成');
},
/**
* 获取全局图表实例
*/
getGlobalCharts() {
return this.globalCharts;
}
};
// ============================================
// 自动初始化
// ============================================
document.addEventListener('DOMContentLoaded', () => {
AppInitializer.init();
});
// ============================================
// 模块导出 - 暴露到全局作用域
// ============================================
window.AppInitializer = AppInitializer;
// 设置模块加载完成标志
window.appInitializerModuleLoaded = true;
console.log('✅ app-initializer.js 应用初始化模块加载完成');