Commit a6f517df by luoqi

fix:回访功能

parent 6eff61eb

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

......@@ -71,4 +71,5 @@ node_modules/
.env.production
# Docker volumes
docker-volumes/
\ No newline at end of file
docker-volumes/
.history
\ No newline at end of file
......@@ -168,10 +168,10 @@ callback_results_cache = {}
if CALLBACK_AVAILABLE:
try:
# 直接使用环境变量构建数据库配置
db_host = os.getenv('DB_HOST', 'mysql')
db_port = int(os.getenv('DB_PORT', '3306'))
db_user = os.getenv('DB_USER', 'callback_user')
db_password = os.getenv('DB_PASSWORD', '')
db_host = os.getenv('DB_HOST', 'localhost') # 本地开发默认使用localhost
db_port = int(os.getenv('DB_PORT', '3306')) # 本地开发使用Docker映射的端口3306
db_user = os.getenv('DB_USER', 'callback_user') # 使用Docker创建的用户
db_password = os.getenv('DB_PASSWORD', 'dev_password_123') # 使用Docker的callback_user密码
db_name = os.getenv('DB_NAME', 'callback_system')
print(f"尝试连接数据库: {db_host}:{db_port}")
......@@ -370,6 +370,16 @@ def save_callback_record():
# 添加AI反馈
if data.get('aiFeedbackType'):
callback_record += f", AI反馈: {data['aiFeedbackType']}"
# 添加备注信息
if result == '不成功' and data.get('failureReasonNote'):
callback_record += f", 不成功备注: {data['failureReasonNote']}"
elif result == '放弃回访' and data.get('abandonReasonNote'):
callback_record += f", 放弃回访备注: {data['abandonReasonNote']}"
# 添加AI反馈备注
if data.get('aiFeedbackNote'):
callback_record += f", AI反馈备注: {data['aiFeedbackNote']}"
# 在记录末尾添加原始结果标识,用于解析
callback_record += f" | ORIGINAL_RESULT: {result}"
......@@ -381,6 +391,14 @@ def save_callback_record():
callback_methods=data['callbackMethods'],
callback_record=callback_record, # 使用构建好的回访记录内容
callback_result=result, # 传递回访结果
next_appointment_time=data.get('nextAppointmentTime'),
failure_reason=data.get('failureReason'),
abandon_reason=data.get('abandonReason'),
ai_feedback_type=data.get('aiFeedbackType'),
failure_reason_note=data.get('failureReasonNote'),
abandon_reason_note=data.get('abandonReasonNote'),
ai_feedback_note=data.get('aiFeedbackNote'),
callback_status=data.get('callbackStatus', '已回访'),
operator=current_user # 使用从session获取的真实用户名
)
record_id = db_manager.save_record(record)
......@@ -1275,8 +1293,11 @@ if __name__ == '__main__':
print(f" - Session超时: {auth_system.session_timeout // 3600}小时")
try:
app.run(host='0.0.0.0', port=5000, debug=False)
# 本地开发使用5001端口,Docker使用5000端口
port = int(os.getenv('PORT', 5001))
print(f"🌐 服务器将在端口 {port} 启动")
app.run(host='0.0.0.0', port=port, debug=False)
except Exception as e:
print(f"❌ 启动服务器失败: {e}")
import traceback
traceback.print_exc()
\ No newline at end of file
traceback.print_exc()
\ No newline at end of file
......@@ -24,9 +24,11 @@ def fix_single_file(file_path):
if match:
# 在tailwind.config之前插入API_BASE_URL设置
api_code = """ // 设置API基础URL
window.API_BASE_URL = 'http://localhost:4002';
api_code = """ // 设置API基础URL - 根据当前页面端口动态配置
const currentPort = window.location.port || (window.location.protocol === 'https:' ? '443' : '80');
const apiPort = currentPort === '5001' ? '5001' : '4002'; // 本地开发用5001,Docker用4002
window.API_BASE_URL = `http://localhost:${apiPort}`;
"""
new_content = content.replace(
......
......@@ -6,18 +6,7 @@
<title>管理员仪表板 - 通善口腔</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<style>
/* 管理员页面优化 */
.stat-card {
transition: transform 0.2s ease;
}
.stat-card:hover {
transform: scale(1.02);
}
</style>
</head>
</head>
<body class="bg-gray-50 min-h-screen">
<div class="container mx-auto px-4 py-8">
<div class="mb-8">
......@@ -26,7 +15,7 @@
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
<div class="bg-white rounded-lg shadow p-6 stat-card">
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center">
<div class="flex-shrink-0">
<i class="fas fa-hospital text-2xl text-blue-600"></i>
......@@ -38,7 +27,7 @@
</div>
</div>
<div class="bg-white rounded-lg shadow p-6 stat-card">
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center">
<div class="flex-shrink-0">
<i class="fas fa-users text-2xl text-green-600"></i>
......@@ -50,7 +39,7 @@
</div>
</div>
<div class="bg-white rounded-lg shadow p-6 stat-card">
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center">
<div class="flex-shrink-0">
<i class="fas fa-phone text-2xl text-yellow-600"></i>
......@@ -62,7 +51,7 @@
</div>
</div>
<div class="bg-white rounded-lg shadow p-6 stat-card">
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center">
<div class="flex-shrink-0">
<i class="fas fa-chart-line text-2xl text-purple-600"></i>
......@@ -84,171 +73,5 @@
</a>
</div>
</div>
<script>
// 检查用户登录状态
async function checkAuth() {
try {
const response = await fetch('/api/user-info');
const result = await response.json();
if (!result.success) {
// 未登录,重定向到登录页
window.location.href = '/login';
return;
}
// 显示用户信息
displayUserInfo(result.user);
// 检查页面访问权限
await checkPageAccess(result.user);
} catch (error) {
console.error('认证检查失败:', error);
window.location.href = '/login';
}
}
function displayUserInfo(user) {
// 在页面头部添加用户信息栏
const header = document.querySelector('header') || document.querySelector('body');
const userInfoBar = document.createElement('div');
userInfoBar.className = 'bg-gray-800 text-white py-2 px-4 flex justify-between items-center text-sm';
userInfoBar.innerHTML = `
<div class="flex items-center space-x-4">
<span><i class="fas fa-user mr-1"></i>${user.realName} (${user.username})</span>
<span><i class="fas fa-hospital mr-1"></i>${user.clinicName}</span>
<span class="px-2 py-1 bg-blue-600 rounded text-xs">
${user.role === 'admin' ? '管理员' : '门诊用户'}
</span>
</div>
<div class="flex items-center space-x-2">
<button onclick="showUserMenu()" class="hover:bg-gray-700 px-2 py-1 rounded">
<i class="fas fa-cog mr-1"></i>设置
</button>
<button onclick="logout()" class="hover:bg-red-600 px-2 py-1 rounded">
<i class="fas fa-sign-out-alt mr-1"></i>登出
</button>
</div>
`;
if (header.tagName === 'HEADER') {
header.parentNode.insertBefore(userInfoBar, header);
} else {
header.insertBefore(userInfoBar, header.firstChild);
}
// 存储用户信息到全局变量
window.currentUser = user;
}
async function checkPageAccess(user) {
// 检查当前页面的访问权限
const path = window.location.pathname;
// 提取门诊ID
const clinicMatch = path.match(/\/clinic_([^\/]+)\//);
if (clinicMatch) {
const clinicFolder = 'clinic_' + clinicMatch[1];
// 映射文件夹名到clinic_id
const clinicMapping = {
'clinic_xuexian': 'clinic_xuexian',
'clinic_dafeng': 'clinic_dafeng',
'clinic_dongting': 'clinic_dongting',
'clinic_helai': 'clinic_helai',
'clinic_hongdou': 'clinic_hongdou',
'clinic_huishan': 'clinic_huishan',
'clinic_mashan': 'clinic_mashan',
'clinic_hospital': 'clinic_hospital',
'clinic_xinwu': 'clinic_xinwu'
};
const clinicId = clinicMapping[clinicFolder];
if (clinicId) {
try {
const response = await fetch(`/api/check-access/${clinicId}`);
const result = await response.json();
if (!result.has_access) {
showAccessDenied();
return;
}
} catch (error) {
console.error('权限检查失败:', error);
}
}
}
}
function showAccessDenied() {
document.body.innerHTML = `
<div class="min-h-screen bg-gray-50 flex items-center justify-center">
<div class="bg-white p-8 rounded-lg shadow-lg text-center max-w-md">
<div class="text-red-500 text-6xl mb-4">
<i class="fas fa-ban"></i>
</div>
<h1 class="text-2xl font-bold text-gray-900 mb-4">访问被拒绝</h1>
<p class="text-gray-600 mb-6">您无权访问此门诊的数据</p>
<button onclick="window.history.back()"
class="bg-blue-600 text-white px-6 py-2 rounded hover:bg-blue-700">
返回上页
</button>
<button onclick="logout()"
class="ml-2 bg-gray-600 text-white px-6 py-2 rounded hover:bg-gray-700">
重新登录
</button>
</div>
</div>
`;
}
function showUserMenu() {
// 显示用户菜单(可扩展)
alert('用户设置功能开发中...');
}
function logout() {
if (confirm('确定要登出吗?')) {
fetch('/api/logout', {method: 'POST'})
.then(() => window.location.href = '/login')
.catch(() => window.location.href = '/login');
}
}
// 页面加载时检查认证
</script>
<script>
// 管理员专用功能
async function checkAdminAuth() {
try {
const response = await fetch('/api/user-info');
const result = await response.json();
if (!result.success) {
window.location.href = '/login';
return;
}
if (result.user.role !== 'admin') {
showAccessDenied();
return;
}
displayUserInfo(result.user);
} catch (error) {
console.error('管理员认证检查失败:', error);
window.location.href = '/login';
}
}
// 替换原有的认证检查
document.addEventListener('DOMContentLoaded', checkAdminAuth);
</script>
</body>
</body>
</html>
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment