修改了登录功能,保证后台服务正常启动后,才能正常登录。
This commit is contained in:
parent
2b0acd819e
commit
21c6611619
112
backend/app.py
112
backend/app.py
@ -242,81 +242,61 @@ def api_health_check():
|
|||||||
@app.route('/api/auth/login', methods=['POST'])
|
@app.route('/api/auth/login', methods=['POST'])
|
||||||
def login():
|
def login():
|
||||||
"""用户登录"""
|
"""用户登录"""
|
||||||
max_retries = 3
|
try:
|
||||||
retry_delay = 1 # 1秒延迟
|
data = flask_request.get_json()
|
||||||
|
username = data.get('username')
|
||||||
|
password = data.get('password')
|
||||||
|
if not username or not password:
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'message': '用户名或密码不能为空'
|
||||||
|
}), 400
|
||||||
|
|
||||||
for attempt in range(max_retries):
|
# 使用数据库验证用户
|
||||||
try:
|
user = db_manager.authenticate_user(username, password)
|
||||||
data = flask_request.get_json()
|
|
||||||
username = data.get('username')
|
if user:
|
||||||
password = data.get('password')
|
# 检查用户是否已激活
|
||||||
if not username or not password:
|
if not user['is_active']:
|
||||||
return jsonify({
|
return jsonify({
|
||||||
'success': False,
|
'success': False,
|
||||||
'message': '用户名或密码不能为空'
|
'message': '账户未激活,请联系管理员审核'
|
||||||
}), 400
|
}), 403
|
||||||
|
|
||||||
# 使用数据库验证用户
|
# 构建用户数据
|
||||||
user = db_manager.authenticate_user(username, password)
|
user_data = {
|
||||||
|
'id': user['id'],
|
||||||
|
'username': user['username'],
|
||||||
|
'name': user['name'],
|
||||||
|
'role': 'admin' if user['user_type'] == 'admin' else 'user',
|
||||||
|
'user_type': user['user_type'],
|
||||||
|
'avatar': ''
|
||||||
|
}
|
||||||
|
|
||||||
if user:
|
# 生成token(实际项目中应使用JWT等安全token)
|
||||||
# 检查用户是否已激活
|
token = f"token_{username}_{int(time.time())}"
|
||||||
if not user['is_active']:
|
|
||||||
return jsonify({
|
|
||||||
'success': False,
|
|
||||||
'message': '账户未激活,请联系管理员审核'
|
|
||||||
}), 403
|
|
||||||
|
|
||||||
# 构建用户数据
|
logger.info(f'用户 {username} 登录成功')
|
||||||
user_data = {
|
|
||||||
'id': user['id'],
|
|
||||||
'username': user['username'],
|
|
||||||
'name': user['name'],
|
|
||||||
'role': 'admin' if user['user_type'] == 'admin' else 'user',
|
|
||||||
'user_type': user['user_type'],
|
|
||||||
'avatar': ''
|
|
||||||
}
|
|
||||||
|
|
||||||
# 生成token(实际项目中应使用JWT等安全token)
|
return jsonify({
|
||||||
token = f"token_{username}_{int(time.time())}"
|
'success': True,
|
||||||
|
'data': {
|
||||||
|
'token': token,
|
||||||
|
'user': user_data
|
||||||
|
},
|
||||||
|
'message': '登录成功'
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
logger.warning(f'用户 {username} 登录失败:用户名或密码错误')
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'message': '用户名或密码错误'
|
||||||
|
}), 401
|
||||||
|
|
||||||
logger.info(f'用户 {username} 登录成功')
|
except Exception as e:
|
||||||
|
logger.error(f'登录失败: {e}')
|
||||||
|
return jsonify({'success': False, 'message': '登录失败'}), 500
|
||||||
|
|
||||||
return jsonify({
|
|
||||||
'success': True,
|
|
||||||
'data': {
|
|
||||||
'token': token,
|
|
||||||
'user': user_data
|
|
||||||
},
|
|
||||||
'message': '登录成功'
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
logger.warning(f'用户 {username} 登录失败:用户名或密码错误')
|
|
||||||
return jsonify({
|
|
||||||
'success': False,
|
|
||||||
'message': '用户名或密码错误'
|
|
||||||
}), 401
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f'登录失败 (尝试 {attempt + 1}/{max_retries}): {e}')
|
|
||||||
|
|
||||||
# 如果是最后一次尝试,直接返回错误
|
|
||||||
if attempt == max_retries - 1:
|
|
||||||
logger.error(f'登录失败,已达到最大重试次数 ({max_retries})')
|
|
||||||
return jsonify({
|
|
||||||
'success': False,
|
|
||||||
'message': '系统异常,请稍后重试'
|
|
||||||
}), 500
|
|
||||||
|
|
||||||
# 延迟后重试
|
|
||||||
logger.info(f'等待 {retry_delay} 秒后重试...')
|
|
||||||
time.sleep(retry_delay)
|
|
||||||
|
|
||||||
# 理论上不会执行到这里,但为了安全起见
|
|
||||||
return jsonify({
|
|
||||||
'success': False,
|
|
||||||
'message': '系统异常,请稍后重试'
|
|
||||||
}), 500
|
|
||||||
|
|
||||||
@app.route('/api/auth/register', methods=['POST'])
|
@app.route('/api/auth/register', methods=['POST'])
|
||||||
def register():
|
def register():
|
||||||
|
@ -64,7 +64,7 @@ class CameraManager(BaseDevice):
|
|||||||
self.backend_name = backend_name
|
self.backend_name = backend_name
|
||||||
|
|
||||||
# 额外可调的降采样宽度(不改变外部配置语义,仅内部优化传输)
|
# 额外可调的降采样宽度(不改变外部配置语义,仅内部优化传输)
|
||||||
self._tx_max_width = int(config.get('tx_max_width', 640))
|
self._tx_max_width = int(config.get('tx_max_width', 1920))
|
||||||
|
|
||||||
# 流控制
|
# 流控制
|
||||||
self.streaming_thread = None
|
self.streaming_thread = None
|
||||||
@ -862,7 +862,7 @@ class CameraManager(BaseDevice):
|
|||||||
self.fps = config.get('fps', 30)
|
self.fps = config.get('fps', 30)
|
||||||
self.buffer_size = config.get('buffer_size', 1)
|
self.buffer_size = config.get('buffer_size', 1)
|
||||||
self.fourcc = config.get('fourcc', 'MJPG')
|
self.fourcc = config.get('fourcc', 'MJPG')
|
||||||
self._tx_max_width = int(config.get('tx_max_width', 640))
|
self._tx_max_width = int(config.get('tx_max_width', 1920))
|
||||||
# 新增:动态更新重连/阈值配置
|
# 新增:动态更新重连/阈值配置
|
||||||
self.max_reconnect_attempts = int(config.get('max_reconnect_attempts', self.max_reconnect_attempts))
|
self.max_reconnect_attempts = int(config.get('max_reconnect_attempts', self.max_reconnect_attempts))
|
||||||
self.reconnect_delay = float(config.get('reconnect_delay', self.reconnect_delay))
|
self.reconnect_delay = float(config.get('reconnect_delay', self.reconnect_delay))
|
||||||
|
@ -565,7 +565,7 @@
|
|||||||
<HistoryDashboard v-if="historyDialogVisible" :patientId="patientId"/>
|
<HistoryDashboard v-if="historyDialogVisible" :patientId="patientId"/>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<div v-if="isBig" style="position: fixed;top: 0;right: 0;
|
<div v-if="isBig" style="position: fixed;top: 0;right: 0;
|
||||||
width: 70%;height: 100vh;z-index: 9999;background: red;border: 2px solid #b0b0b0">
|
width: 100%;height: 100vh;z-index: 9999;background: red;border: 2px solid #b0b0b0">
|
||||||
<svg @click="isBig=false" style="position: absolute;right: 10px;top:10px;cursor: pointer;" t="1760175800150" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5743" width="24" height="24"><path d="M796 163.1L511.1 448l-285-285-63.9 64 285 285-285 285 63.8 63.8 285-285 285 285 63.8-63.8-285-285 285-285-63.8-63.9z" fill="#ffffff" p-id="5744"></path></svg>
|
<svg @click="isBig=false" style="position: absolute;right: 10px;top:10px;cursor: pointer;" t="1760175800150" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5743" width="24" height="24"><path d="M796 163.1L511.1 448l-285-285-63.9 64 285 285-285 285 63.8 63.8 285-285 285 285 63.8-63.8-285-285 285-285-63.8-63.9z" fill="#ffffff" p-id="5744"></path></svg>
|
||||||
<img v-if="isBig" :src="(cameraStatus === '已连接' && rtspImgSrc) ? rtspImgSrc : noImageSvg" alt=""
|
<img v-if="isBig" :src="(cameraStatus === '已连接' && rtspImgSrc) ? rtspImgSrc : noImageSvg" alt=""
|
||||||
style="width: 100%;height: calc(100%);object-fit:contain;background:#323232;" />
|
style="width: 100%;height: calc(100%);object-fit:contain;background:#323232;" />
|
||||||
|
@ -56,7 +56,7 @@
|
|||||||
|
|
||||||
<!-- 操作按钮 -->
|
<!-- 操作按钮 -->
|
||||||
<div class="button-group">
|
<div class="button-group">
|
||||||
<el-button type="primary" class="login-btn" @click="handleLogin" :loading="isLoading">登录</el-button>
|
<el-button type="primary" class="login-btn" @click="handleLogin" :loading="isLoading">{{ isLoading ? '登录中...' : '登录' }}</el-button>
|
||||||
<el-button class="register-btn" @click="switchToRegister">注册</el-button>
|
<el-button class="register-btn" @click="switchToRegister">注册</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
@ -217,7 +217,7 @@ import { useAuthStore } from '../stores'
|
|||||||
import { User, Lock, View, Hide, Phone } from '@element-plus/icons-vue'
|
import { User, Lock, View, Hide, Phone } from '@element-plus/icons-vue'
|
||||||
|
|
||||||
import bg from '@/assets/bg.png'
|
import bg from '@/assets/bg.png'
|
||||||
import { getBackendUrl } from '../services/api.js'
|
import { getBackendUrl,systemAPI } from '../services/api.js'
|
||||||
const BACKEND_URL = getBackendUrl()
|
const BACKEND_URL = getBackendUrl()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const authStore = useAuthStore()
|
const authStore = useAuthStore()
|
||||||
@ -415,6 +415,7 @@ const handleRegisterSubmit = async () => {
|
|||||||
|
|
||||||
// 登录处理
|
// 登录处理
|
||||||
const handleLogin = async () => {
|
const handleLogin = async () => {
|
||||||
|
isLoading.value = true
|
||||||
// 验证用户名
|
// 验证用户名
|
||||||
if (!form.value.account) {
|
if (!form.value.account) {
|
||||||
showError('请输入登录账号!')
|
showError('请输入登录账号!')
|
||||||
@ -427,8 +428,34 @@ const handleLogin = async () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
// 网络访问测试(最多重试3次,每次延迟2秒)
|
||||||
isLoading.value = true
|
let healthOk = false
|
||||||
|
for (let attempt = 1; attempt <= 3; attempt++) {
|
||||||
|
try {
|
||||||
|
const result = await systemAPI.health()
|
||||||
|
if (result && result.status === 'healthy') {
|
||||||
|
healthOk = true
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
// 后台返回非 healthy 状态
|
||||||
|
if (attempt === 3) {
|
||||||
|
showError('后台服务异常,请稍后重试!')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 2000))
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// 捕获异常,等待后重试
|
||||||
|
if (attempt === 3) {
|
||||||
|
showError('网络访问失败,请检查连接后重试!')
|
||||||
|
isLoading.value = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 2000))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
const result = await authStore.login({
|
const result = await authStore.login({
|
||||||
username: form.value.account,
|
username: form.value.account,
|
||||||
password: form.value.password
|
password: form.value.password
|
||||||
@ -455,6 +482,7 @@ const handleLogin = async () => {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showError('登录失败,请检查网络连接后重试!')
|
showError('登录失败,请检查网络连接后重试!')
|
||||||
|
isLoading.value = false
|
||||||
} finally {
|
} finally {
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user