feat: 初始化员工缺勤分析系统项目
搭建完整的前后端分离架构,实现数据概览、预测分析、聚类分析等核心功能模块 详细版: feat: 初始化员工缺勤分析系统项目 - 后端:基于 Flask 搭建 RESTful API,包含数据概览、特征分析、预测模型、聚类分析四大模块 - 前端:基于 Vue.js 构建单页应用,实现 Dashboard、预测、聚类、因子分析等页面 - 模型:集成随机森林、XGBoost、LightGBM、Stacking 等多种机器学习模型 - 文档:完成需求规格说明、系统架构设计、接口设计、数据设计、UI原型设计等文档
This commit is contained in:
11
backend/api/__init__.py
Normal file
11
backend/api/__init__.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from .overview_routes import overview_bp
|
||||
from .analysis_routes import analysis_bp
|
||||
from .predict_routes import predict_bp
|
||||
from .cluster_routes import cluster_bp
|
||||
|
||||
|
||||
def register_blueprints(app):
|
||||
app.register_blueprint(overview_bp)
|
||||
app.register_blueprint(analysis_bp)
|
||||
app.register_blueprint(predict_bp)
|
||||
app.register_blueprint(cluster_bp)
|
||||
64
backend/api/analysis_routes.py
Normal file
64
backend/api/analysis_routes.py
Normal file
@@ -0,0 +1,64 @@
|
||||
from flask import Blueprint, jsonify, request
|
||||
|
||||
from services.analysis_service import analysis_service
|
||||
|
||||
analysis_bp = Blueprint('analysis', __name__, url_prefix='/api/analysis')
|
||||
|
||||
|
||||
@analysis_bp.route('/importance', methods=['GET'])
|
||||
def get_importance():
|
||||
try:
|
||||
model_type = request.args.get('model', 'rf')
|
||||
result = analysis_service.get_feature_importance(model_type)
|
||||
return jsonify({
|
||||
'code': 200,
|
||||
'message': 'success',
|
||||
'data': result
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
'code': 500,
|
||||
'message': str(e),
|
||||
'data': None
|
||||
}), 500
|
||||
|
||||
|
||||
@analysis_bp.route('/correlation', methods=['GET'])
|
||||
def get_correlation():
|
||||
try:
|
||||
result = analysis_service.get_correlation()
|
||||
return jsonify({
|
||||
'code': 200,
|
||||
'message': 'success',
|
||||
'data': result
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
'code': 500,
|
||||
'message': str(e),
|
||||
'data': None
|
||||
}), 500
|
||||
|
||||
|
||||
@analysis_bp.route('/compare', methods=['GET'])
|
||||
def get_compare():
|
||||
try:
|
||||
dimension = request.args.get('dimension', 'drinker')
|
||||
result = analysis_service.get_group_comparison(dimension)
|
||||
return jsonify({
|
||||
'code': 200,
|
||||
'message': 'success',
|
||||
'data': result
|
||||
})
|
||||
except ValueError as e:
|
||||
return jsonify({
|
||||
'code': 400,
|
||||
'message': str(e),
|
||||
'data': None
|
||||
}), 400
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
'code': 500,
|
||||
'message': str(e),
|
||||
'data': None
|
||||
}), 500
|
||||
68
backend/api/cluster_routes.py
Normal file
68
backend/api/cluster_routes.py
Normal file
@@ -0,0 +1,68 @@
|
||||
from flask import Blueprint, jsonify, request
|
||||
|
||||
from services.cluster_service import cluster_service
|
||||
|
||||
cluster_bp = Blueprint('cluster', __name__, url_prefix='/api/cluster')
|
||||
|
||||
|
||||
@cluster_bp.route('/result', methods=['GET'])
|
||||
def get_result():
|
||||
try:
|
||||
n_clusters = request.args.get('n_clusters', 3, type=int)
|
||||
n_clusters = max(2, min(10, n_clusters))
|
||||
|
||||
result = cluster_service.get_cluster_result(n_clusters)
|
||||
return jsonify({
|
||||
'code': 200,
|
||||
'message': 'success',
|
||||
'data': result
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
'code': 500,
|
||||
'message': str(e),
|
||||
'data': None
|
||||
}), 500
|
||||
|
||||
|
||||
@cluster_bp.route('/profile', methods=['GET'])
|
||||
def get_profile():
|
||||
try:
|
||||
n_clusters = request.args.get('n_clusters', 3, type=int)
|
||||
n_clusters = max(2, min(10, n_clusters))
|
||||
|
||||
result = cluster_service.get_cluster_profile(n_clusters)
|
||||
return jsonify({
|
||||
'code': 200,
|
||||
'message': 'success',
|
||||
'data': result
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
'code': 500,
|
||||
'message': str(e),
|
||||
'data': None
|
||||
}), 500
|
||||
|
||||
|
||||
@cluster_bp.route('/scatter', methods=['GET'])
|
||||
def get_scatter():
|
||||
try:
|
||||
n_clusters = request.args.get('n_clusters', 3, type=int)
|
||||
x_axis = request.args.get('x_axis', 'Age')
|
||||
y_axis = request.args.get('y_axis', 'Absenteeism time in hours')
|
||||
|
||||
n_clusters = max(2, min(10, n_clusters))
|
||||
|
||||
result = cluster_service.get_scatter_data(n_clusters, x_axis, y_axis)
|
||||
return jsonify({
|
||||
'code': 200,
|
||||
'message': 'success',
|
||||
'data': result
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
'code': 500,
|
||||
'message': str(e),
|
||||
'data': None
|
||||
}), 500
|
||||
90
backend/api/overview_routes.py
Normal file
90
backend/api/overview_routes.py
Normal file
@@ -0,0 +1,90 @@
|
||||
from flask import Blueprint, jsonify
|
||||
|
||||
from services.data_service import data_service
|
||||
|
||||
overview_bp = Blueprint('overview', __name__, url_prefix='/api/overview')
|
||||
|
||||
|
||||
@overview_bp.route('/stats', methods=['GET'])
|
||||
def get_stats():
|
||||
try:
|
||||
stats = data_service.get_basic_stats()
|
||||
return jsonify({
|
||||
'code': 200,
|
||||
'message': 'success',
|
||||
'data': stats
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
'code': 500,
|
||||
'message': str(e),
|
||||
'data': None
|
||||
}), 500
|
||||
|
||||
|
||||
@overview_bp.route('/trend', methods=['GET'])
|
||||
def get_trend():
|
||||
try:
|
||||
trend = data_service.get_monthly_trend()
|
||||
return jsonify({
|
||||
'code': 200,
|
||||
'message': 'success',
|
||||
'data': trend
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
'code': 500,
|
||||
'message': str(e),
|
||||
'data': None
|
||||
}), 500
|
||||
|
||||
|
||||
@overview_bp.route('/weekday', methods=['GET'])
|
||||
def get_weekday():
|
||||
try:
|
||||
weekday = data_service.get_weekday_distribution()
|
||||
return jsonify({
|
||||
'code': 200,
|
||||
'message': 'success',
|
||||
'data': weekday
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
'code': 500,
|
||||
'message': str(e),
|
||||
'data': None
|
||||
}), 500
|
||||
|
||||
|
||||
@overview_bp.route('/reasons', methods=['GET'])
|
||||
def get_reasons():
|
||||
try:
|
||||
reasons = data_service.get_reason_distribution()
|
||||
return jsonify({
|
||||
'code': 200,
|
||||
'message': 'success',
|
||||
'data': reasons
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
'code': 500,
|
||||
'message': str(e),
|
||||
'data': None
|
||||
}), 500
|
||||
|
||||
|
||||
@overview_bp.route('/seasons', methods=['GET'])
|
||||
def get_seasons():
|
||||
try:
|
||||
seasons = data_service.get_season_distribution()
|
||||
return jsonify({
|
||||
'code': 200,
|
||||
'message': 'success',
|
||||
'data': seasons
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
'code': 500,
|
||||
'message': str(e),
|
||||
'data': None
|
||||
}), 500
|
||||
102
backend/api/predict_routes.py
Normal file
102
backend/api/predict_routes.py
Normal file
@@ -0,0 +1,102 @@
|
||||
from flask import Blueprint, jsonify, request
|
||||
|
||||
from services.predict_service import predict_service
|
||||
|
||||
predict_bp = Blueprint('predict', __name__, url_prefix='/api/predict')
|
||||
|
||||
|
||||
@predict_bp.route('/single', methods=['POST'])
|
||||
def predict_single():
|
||||
try:
|
||||
data = request.get_json()
|
||||
|
||||
if not data:
|
||||
return jsonify({
|
||||
'code': 400,
|
||||
'message': 'Request body is required',
|
||||
'data': None
|
||||
}), 400
|
||||
|
||||
model_type = data.get('model_type')
|
||||
|
||||
result = predict_service.predict_single(data, model_type)
|
||||
|
||||
return jsonify({
|
||||
'code': 200,
|
||||
'message': 'success',
|
||||
'data': result
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
'code': 500,
|
||||
'message': str(e),
|
||||
'data': None
|
||||
}), 500
|
||||
|
||||
|
||||
@predict_bp.route('/compare', methods=['POST'])
|
||||
def predict_compare():
|
||||
try:
|
||||
data = request.get_json()
|
||||
|
||||
if not data:
|
||||
return jsonify({
|
||||
'code': 400,
|
||||
'message': 'Request body is required',
|
||||
'data': None
|
||||
}), 400
|
||||
|
||||
results = predict_service.predict_compare(data)
|
||||
|
||||
return jsonify({
|
||||
'code': 200,
|
||||
'message': 'success',
|
||||
'data': {
|
||||
'results': results,
|
||||
'total_models': len(results)
|
||||
}
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
'code': 500,
|
||||
'message': str(e),
|
||||
'data': None
|
||||
}), 500
|
||||
|
||||
|
||||
@predict_bp.route('/models', methods=['GET'])
|
||||
def get_models():
|
||||
try:
|
||||
models = predict_service.get_available_models()
|
||||
|
||||
return jsonify({
|
||||
'code': 200,
|
||||
'message': 'success',
|
||||
'data': {
|
||||
'models': models,
|
||||
'total': len(models)
|
||||
}
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
'code': 500,
|
||||
'message': str(e),
|
||||
'data': None
|
||||
}), 500
|
||||
|
||||
|
||||
@predict_bp.route('/model-info', methods=['GET'])
|
||||
def get_model_info():
|
||||
try:
|
||||
result = predict_service.get_model_info()
|
||||
return jsonify({
|
||||
'code': 200,
|
||||
'message': 'success',
|
||||
'data': result
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
'code': 500,
|
||||
'message': str(e),
|
||||
'data': None
|
||||
}), 500
|
||||
Reference in New Issue
Block a user