home0923
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
为query_history表添加user_id字段,并设置为users表id字段的外键
|
||||
"""
|
||||
|
||||
import sqlite3
|
||||
import logging
|
||||
|
||||
# 配置日志
|
||||
handlers = [logging.FileHandler('db_update.log'), logging.StreamHandler()]
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(levelname)s - %(message)s',
|
||||
handlers=handlers
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# 数据库文件路径
|
||||
db_path = 'car_info.db'
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
主函数:连接数据库并为query_history表添加user_id字段
|
||||
"""
|
||||
logger.info("开始为query_history表添加user_id字段")
|
||||
|
||||
try:
|
||||
# 连接数据库
|
||||
conn = sqlite3.connect(db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 检查query_history表是否已经存在user_id字段
|
||||
cursor.execute("PRAGMA table_info(query_history)")
|
||||
columns = cursor.fetchall()
|
||||
|
||||
has_user_id = any(column[1] == 'user_id' for column in columns)
|
||||
|
||||
if has_user_id:
|
||||
logger.info("query_history表已存在user_id字段,无需添加")
|
||||
else:
|
||||
# 添加user_id字段(先不添加外键约束,确保字段可以添加成功)
|
||||
logger.info("开始添加user_id字段")
|
||||
cursor.execute("ALTER TABLE query_history ADD COLUMN user_id INTEGER")
|
||||
conn.commit()
|
||||
logger.info("user_id字段添加成功")
|
||||
|
||||
# 尝试添加外键约束
|
||||
try:
|
||||
logger.info("开始添加外键约束")
|
||||
cursor.execute("""
|
||||
ALTER TABLE query_history
|
||||
ADD CONSTRAINT fk_query_history_user_id
|
||||
FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
""")
|
||||
conn.commit()
|
||||
logger.info("外键约束添加成功")
|
||||
except sqlite3.Error as e:
|
||||
# 在SQLite中,某些版本不支持通过ALTER TABLE直接添加外键约束
|
||||
# 如果添加外键约束失败,记录警告信息并继续
|
||||
logger.warning(f"添加外键约束失败: {str(e)}")
|
||||
logger.warning("将创建临时表并重新创建query_history表来添加外键约束")
|
||||
|
||||
# 创建临时表
|
||||
cursor.execute("""
|
||||
CREATE TABLE query_history_temp (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
department TEXT NOT NULL,
|
||||
query_date TEXT NOT NULL,
|
||||
plate_number TEXT,
|
||||
phone TEXT,
|
||||
results_count INTEGER NOT NULL,
|
||||
query_ip TEXT NOT NULL,
|
||||
user_id INTEGER,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
)
|
||||
""")
|
||||
|
||||
# 复制数据到临时表
|
||||
cursor.execute("""
|
||||
INSERT INTO query_history_temp (
|
||||
id, department, query_date, plate_number,
|
||||
phone, results_count, query_ip
|
||||
)
|
||||
SELECT
|
||||
id, department, query_date, plate_number,
|
||||
phone, results_count, query_ip
|
||||
FROM query_history
|
||||
""")
|
||||
|
||||
# 删除原表
|
||||
cursor.execute("DROP TABLE query_history")
|
||||
|
||||
# 重命名临时表
|
||||
cursor.execute("ALTER TABLE query_history_temp RENAME TO query_history")
|
||||
|
||||
# 提交更改
|
||||
conn.commit()
|
||||
logger.info("通过重新创建表的方式成功添加外键约束")
|
||||
|
||||
# 关闭连接
|
||||
conn.close()
|
||||
logger.info("操作完成")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"操作过程中发生错误: {str(e)}")
|
||||
if 'conn' in locals() and conn:
|
||||
conn.rollback()
|
||||
conn.close()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -73,7 +73,7 @@ def get_pending_queries():
|
||||
|
||||
# 查询query_history表中results_count=-1的所有数据
|
||||
cursor.execute("""
|
||||
SELECT id, department, query_date, plate_number, phone, results_count, query_ip
|
||||
SELECT id, query_date, plate_number, phone, results_count, query_ip, user_id
|
||||
FROM query_history
|
||||
WHERE results_count = -1
|
||||
ORDER BY query_date DESC
|
||||
@@ -90,12 +90,12 @@ def get_pending_queries():
|
||||
for row in rows:
|
||||
pending_query = {
|
||||
'id': row['id'],
|
||||
'department': row['department'],
|
||||
'query_date': row['query_date'],
|
||||
'plate_number': row['plate_number'],
|
||||
'phone': row['phone'],
|
||||
'results_count': row['results_count'],
|
||||
'query_ip': row['query_ip']
|
||||
'query_ip': row['query_ip'],
|
||||
'user_id': row['user_id'] if 'user_id' in row.keys() else None
|
||||
}
|
||||
pending_queries.append(pending_query)
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from flask import Flask, render_template, request, redirect, url_for, session, jsonify
|
||||
from datetime import datetime, timedelta
|
||||
import os
|
||||
import random
|
||||
from flask import Flask, render_template, request, redirect, url_for, session
|
||||
|
||||
# 导入用户模块
|
||||
@@ -58,87 +57,6 @@ def init_db():
|
||||
)
|
||||
''')
|
||||
|
||||
# 插入一些测试车辆数据
|
||||
try:
|
||||
test_cars = [
|
||||
('京A12345', '13800138001', '110101199001011234', '张三', 'zhangsan@example.com', '北京市朝阳区'),
|
||||
('沪B54321', '13900139001', '310101199001012345', '李四', 'lisi@example.com', '上海市静安区'),
|
||||
('粤C67890', '13700137001', '440401199001013456', '王五', 'wangwu@example.com', '广东省珠海市'),
|
||||
('苏D12345', '13600136001', '320401199001014567', '赵六', 'zhaoliu@example.com', '江苏省常州市'),
|
||||
('浙E54321', '13500135001', '330501199001015678', '钱七', 'qianqi@example.com', '浙江省湖州市')
|
||||
]
|
||||
cursor.executemany("INSERT INTO car_owners (plate_number, phone, id_card, name, email, address) VALUES (?, ?, ?, ?, ?, ?)", test_cars)
|
||||
except Exception as e:
|
||||
# 数据已存在或其他错误,忽略
|
||||
print(f"插入测试数据时出错: {e}")
|
||||
|
||||
# 单独处理查询历史演示数据,确保每次都能插入20条记录
|
||||
try:
|
||||
# 先删除现有的演示数据
|
||||
cursor.execute("DELETE FROM query_history WHERE department IN ('IT部', '财务部', '人事部', '市场部', '行政部')")
|
||||
|
||||
# 生成最近20天的随机查询历史
|
||||
provinces = ['京', '沪', '粤', '苏', '浙', '鲁', '豫', '川', '湘', '鄂']
|
||||
cities = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K']
|
||||
departments = ['IT部', '财务部', '人事部', '市场部', '行政部']
|
||||
|
||||
# 获取现有的车辆信息,用于生成能匹配的查询历史
|
||||
cursor.execute("SELECT plate_number, phone FROM car_owners")
|
||||
existing_cars = cursor.fetchall()
|
||||
|
||||
for i in range(20):
|
||||
# 生成随机日期(最近20天内)
|
||||
days_ago = random.randint(0, 19)
|
||||
date = (datetime.now() - timedelta(days=days_ago)).strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
# 70%的概率使用已存在的车辆信息,30%的概率生成随机信息
|
||||
use_existing = random.random() < 0.7
|
||||
|
||||
if use_existing and existing_cars:
|
||||
# 使用已存在的车辆信息
|
||||
car_info = random.choice(existing_cars)
|
||||
if random.choice([True, False]):
|
||||
plate_number = car_info[0]
|
||||
phone = None
|
||||
else:
|
||||
plate_number = None
|
||||
phone = car_info[1]
|
||||
# 确保结果数量正确
|
||||
if plate_number:
|
||||
cursor.execute("SELECT COUNT(*) FROM car_owners WHERE plate_number = ?", (plate_number,))
|
||||
results_count = cursor.fetchone()[0]
|
||||
else:
|
||||
cursor.execute("SELECT COUNT(*) FROM car_owners WHERE phone = ?", (phone,))
|
||||
results_count = cursor.fetchone()[0]
|
||||
else:
|
||||
# 随机生成车牌号或手机号
|
||||
use_plate = random.choice([True, False])
|
||||
if use_plate:
|
||||
plate_number = f"{random.choice(provinces)}{random.choice(cities)}{random.randint(100000, 999999)}"
|
||||
phone = None
|
||||
else:
|
||||
plate_number = None
|
||||
phone = f"1{random.randint(3000000000, 9999999999)}"
|
||||
# 检查是否存在匹配结果
|
||||
if plate_number:
|
||||
cursor.execute("SELECT COUNT(*) FROM car_owners WHERE plate_number = ?", (plate_number,))
|
||||
results_count = cursor.fetchone()[0]
|
||||
else:
|
||||
cursor.execute("SELECT COUNT(*) FROM car_owners WHERE phone = ?", (phone,))
|
||||
results_count = cursor.fetchone()[0]
|
||||
|
||||
# 随机部门
|
||||
department = random.choice(departments)
|
||||
|
||||
# 生成随机IP地址
|
||||
query_ip = f"192.168.{random.randint(0, 255)}.{random.randint(1, 254)}"
|
||||
|
||||
cursor.execute(
|
||||
"INSERT INTO query_history (department, query_date, plate_number, phone, results_count, query_ip) VALUES (?, ?, ?, ?, ?, ?)",
|
||||
(department, date, plate_number, phone, results_count, query_ip)
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"插入查询历史数据时出错: {e}")
|
||||
try:
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
@@ -184,15 +102,16 @@ def query():
|
||||
# 获取客户端IP地址
|
||||
query_ip = request.remote_addr
|
||||
|
||||
# 从用户信息表获取部门信息
|
||||
# 从用户信息表获取用户ID
|
||||
user_id = None
|
||||
try:
|
||||
# 可以复用同一个连接,不需要创建新连接
|
||||
cursor.execute("SELECT department FROM users WHERE username = ?", (session['username'],))
|
||||
user_dept = cursor.fetchone()
|
||||
if user_dept:
|
||||
department = user_dept[0]
|
||||
cursor.execute("SELECT id FROM users WHERE username = ?", (session['username'],))
|
||||
user_info = cursor.fetchone()
|
||||
if user_info:
|
||||
user_id = user_info[0]
|
||||
except Exception as e:
|
||||
print(f"获取部门信息时出错: {e}")
|
||||
print(f"获取用户信息时出错: {e}")
|
||||
|
||||
# 记录查询历史到数据库
|
||||
try:
|
||||
@@ -207,8 +126,8 @@ def query():
|
||||
results_count = len(results)
|
||||
|
||||
cursor.execute(
|
||||
"INSERT INTO query_history (department, query_date, plate_number, phone, results_count, query_ip) VALUES (?, ?, ?, ?, ?, ?)",
|
||||
(department, query_date, plate_number if plate_number else None, phone if phone else None, results_count, query_ip)
|
||||
"INSERT INTO query_history (query_date, plate_number, phone, results_count, query_ip, user_id) VALUES (?, ?, ?, ?, ?, ?)",
|
||||
(query_date, plate_number if plate_number else None, phone if phone else None, results_count, query_ip, user_id)
|
||||
)
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
@@ -300,7 +219,14 @@ def get_recent_queries():
|
||||
cursor = conn.cursor()
|
||||
|
||||
try:
|
||||
cursor.execute("SELECT id, department, query_date, plate_number, phone, results_count, query_ip FROM query_history ORDER BY query_date DESC LIMIT 20")
|
||||
# 使用JOIN操作获取用户姓名和部门信息
|
||||
cursor.execute("""
|
||||
SELECT qh.id, qh.query_date, qh.plate_number, qh.phone, qh.results_count, qh.query_ip, qh.user_id,
|
||||
u.name AS user_name, u.department AS user_department
|
||||
FROM query_history qh
|
||||
LEFT JOIN users u ON qh.user_id = u.id
|
||||
ORDER BY qh.query_date DESC LIMIT 20
|
||||
""")
|
||||
recent_queries = cursor.fetchall()
|
||||
|
||||
# 格式化查询历史数据
|
||||
@@ -308,12 +234,14 @@ def get_recent_queries():
|
||||
for q in recent_queries:
|
||||
formatted_recent_queries.append({
|
||||
'id': q[0],
|
||||
'department': q[1],
|
||||
'query_date': q[2],
|
||||
'plate_number': q[3] if q[3] else '未提供',
|
||||
'phone': q[4] if q[4] else '未提供',
|
||||
'results_count': q[5],
|
||||
'query_ip': q[6]
|
||||
'query_date': q[1],
|
||||
'plate_number': q[2] if q[2] else '未提供',
|
||||
'phone': q[3] if q[3] else '未提供',
|
||||
'results_count': q[4],
|
||||
'query_ip': q[5],
|
||||
'user_id': q[6] if len(q) > 6 else None,
|
||||
'user_name': q[7] if len(q) > 7 else '未知',
|
||||
'user_department': q[8] if len(q) > 8 else '未知'
|
||||
})
|
||||
|
||||
return formatted_recent_queries
|
||||
@@ -340,7 +268,7 @@ if __name__ == '__main__':
|
||||
|
||||
try:
|
||||
init_db()
|
||||
app.run(debug=True)
|
||||
app.run(debug=True,host="0.0.0.0",port=99)
|
||||
finally:
|
||||
# 确保在程序退出时关闭数据库连接
|
||||
close_global_connection()
|
||||
BIN
Binary file not shown.
@@ -0,0 +1,252 @@
|
||||
from DrissionPage._base.chromium import Chromium
|
||||
from DrissionPage._configs.chromium_options import ChromiumOptions
|
||||
from DrissionPage._pages.mix_tab import MixTab
|
||||
from cssselect.parser import parse_simple_selector
|
||||
from config import ConfigManager # 新增导入
|
||||
import time
|
||||
|
||||
class Sinopec_ewcc(object):
|
||||
tab:MixTab
|
||||
# browser:Chromium
|
||||
|
||||
def __init__(self):
|
||||
self.url = 'https://ewcc.sinopec.com'
|
||||
self.url_info= 'ewcc.sinopec'
|
||||
self.browser_path= r'C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe'
|
||||
self.co = ChromiumOptions().set_browser_path(self.browser_path)
|
||||
self.co.ignore_certificate_errors(True)
|
||||
self.browser=Chromium(self.co)
|
||||
self.config_manager = ConfigManager() # 新增配置管理器实例
|
||||
self.ewcc_config = self.config_manager.app_config.get('ewcc', {}) # 修改为通过类访问
|
||||
|
||||
def quit(self ):
|
||||
self.browser.quit()
|
||||
|
||||
def load_cookies(self):
|
||||
cookies = self.ewcc_config.get('cookies', {})
|
||||
print('使用保存的cookies登录')
|
||||
for cookie in cookies:
|
||||
self.browser.set.cookies(cookie)
|
||||
### print(cookie)
|
||||
|
||||
def save_cookies(self):
|
||||
# 保存当前 cookie
|
||||
self.tab.refresh()
|
||||
cookies = self.tab.cookies()
|
||||
### print(cookies)
|
||||
self.ewcc_config['cookies'] = cookies
|
||||
self.ewcc_config['savetime'] = time.time()
|
||||
print("--------------------")
|
||||
self.config_manager.app_config['ewcc'] = self.ewcc_config # 修改为通过类访问
|
||||
self.config_manager.save_config() # 修改为调用类方法
|
||||
|
||||
|
||||
def test(self ):
|
||||
# print(self.browser as Chromium.version )
|
||||
pass
|
||||
|
||||
def open_web(self,url=None):
|
||||
if url is None:
|
||||
url=self.url
|
||||
self.browser.get_tab(url)
|
||||
|
||||
def new_tab(self,url=None):
|
||||
if url is None:
|
||||
url=self.url
|
||||
self.tab=self.browser.new_tab(url)
|
||||
|
||||
|
||||
def find_tab(self,url=None,title=None):
|
||||
if url is None:
|
||||
url=self.url
|
||||
if title is None:
|
||||
title=self.url_info
|
||||
|
||||
try:
|
||||
self.tab= self.browser.get_tab(url=url)
|
||||
print("根据 url 找到标签")
|
||||
except:
|
||||
print("根据 url 没有找到标签")
|
||||
self.tab=None
|
||||
|
||||
if not self.tab:
|
||||
try:
|
||||
self.tab=self.browser.get_tab(title=title)
|
||||
print("根据 标题名 找到 标签")
|
||||
except :
|
||||
print("根据 标题名 没有找到标签")
|
||||
self.tab=None
|
||||
|
||||
return self.tab
|
||||
|
||||
def is_login(self):
|
||||
if self.tab is None:
|
||||
return False
|
||||
time.sleep(2)
|
||||
cur_login=False
|
||||
try:
|
||||
e=None
|
||||
e=self.tab.ele("#userName")
|
||||
print("找到登录成功的标志"+e.text)
|
||||
cur_login=True
|
||||
except Exception as e:
|
||||
print('没有找到登录成功的标志')
|
||||
print(f'{e}')
|
||||
cur_login = False
|
||||
return cur_login
|
||||
|
||||
|
||||
# 判断是否登录 ,如果没有登录 ,则提示十次,间断5秒
|
||||
i = 1
|
||||
time.sleep(2)
|
||||
while i <= 10:
|
||||
cur_login = False
|
||||
try:
|
||||
e = None
|
||||
e = self.tab.ele('@@tag()=span@@text()^忘记密码')
|
||||
### print(e.value)
|
||||
print(f'需要登录 <{i}> :')
|
||||
time.sleep(5)
|
||||
except Exception as e:
|
||||
print('已经登录')
|
||||
print(f'{e}')
|
||||
cur_login = True
|
||||
|
||||
if cur_login:
|
||||
break
|
||||
i += 1
|
||||
if not cur_login:
|
||||
print('登录 失败,强制退出。')
|
||||
return cur_login
|
||||
|
||||
def login(self,username=None,userpass=None,otp=None):
|
||||
self.tab.get(self.url)
|
||||
self.tab.wait.eles_loaded('xpath://*[@id="authen1Form"]/button')
|
||||
time.sleep(5)
|
||||
|
||||
try:
|
||||
ele_div=self.tab.ele('#tab3Con')
|
||||
ele_div.ele('#fs3_username').set.value(self.ewcc_config.get('username','pengf332.hnsy'))
|
||||
time.sleep(1)
|
||||
ele_div.ele('#fs3_password').set.value(self.ewcc_config.get('password','Pf7842158c'))
|
||||
time.sleep(1)
|
||||
ele_div.ele('#fs3_otpOrSms').set.value(otp)
|
||||
time.sleep(1)
|
||||
ele_div.ele('@type=submit').click()
|
||||
except Exception as e:
|
||||
print(e)
|
||||
time.sleep(3)
|
||||
|
||||
### 判断是否有仍然发生的界面
|
||||
try:
|
||||
ele_process = self.tab.ele('#proceed-button')
|
||||
ele_process.click()
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
time.sleep(3)
|
||||
return True
|
||||
|
||||
|
||||
def show_login(self):
|
||||
self.tab.get(self.url)
|
||||
self.tab.wait.eles_loaded('xpath://*[@id="authen1Form"]/button')
|
||||
time.sleep(3)
|
||||
|
||||
try:
|
||||
ele_div=self.tab.ele('#tab3Con')
|
||||
ele_div.ele('#fs3_username').set.value(self.ewcc_config.get('username','pengf332.hnsy'))
|
||||
ele_div.ele('#fs3_password').set.value(self.ewcc_config.get('password','Pf7842158b'))
|
||||
ele_div.ele('#fs3_otpOrSms').set.value(self.ewcc_config.get('otpOrSms','129727'))
|
||||
# ele_div.ele('@type=submit').click()
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
time.sleep(60)
|
||||
return True
|
||||
|
||||
|
||||
def send_message(self):
|
||||
pass
|
||||
|
||||
def query_car_info(self,plate_number=None,phone_number=None,additional_info=None):
|
||||
self.tab.ele("@@tag()=li@@title=订单中心").click()
|
||||
time.sleep(2)
|
||||
self.tab.ele("@@tag()=a@@name=客户信息查询").click()
|
||||
time.sleep(2)
|
||||
myframe = self.tab.get_frame("iframeSOC_CSR_DETAIL")
|
||||
### print(myframe.inner_html)
|
||||
time.sleep(2)
|
||||
|
||||
### print("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
|
||||
ele = myframe.ele("#searchType")
|
||||
### print(ele.inner_html)
|
||||
|
||||
myframe.ele("@@tag()=select@@id=searchType").select.by_text("车牌号")
|
||||
myframe.ele('#searchValue').input(plate_number, clear=True)
|
||||
|
||||
myframe.listen.start('acc/getAccCsrInfo')
|
||||
myframe.ele("@text()=查询").click()
|
||||
DataPacket = myframe.listen.wait()
|
||||
### print(DataPacket.response.body)
|
||||
|
||||
###print("ccccccccccccccccccccccccccccccccccccccc")
|
||||
rtn={}
|
||||
if DataPacket.response.body['success']:
|
||||
total_num = DataPacket.response.body['data']['total']
|
||||
# rtn['length']=total_num
|
||||
# rtn['test']='aaa'
|
||||
rtn=[]
|
||||
eles = myframe.eles("@@name=客户信息详情界面@@text()=详情")
|
||||
for ele in eles:
|
||||
sele = self.tab.ele("@@text()^客户信息查询@@class:J_menuTab")
|
||||
if sele:
|
||||
sele.click()
|
||||
self.tab.listen.start('getAccCsrInfoByCsrid')
|
||||
ele.click()
|
||||
DataPacket = self.tab.listen.wait()
|
||||
### print(DataPacket.response.body)
|
||||
rtn.append(DataPacket.response.body['data'])
|
||||
self.tab.listen.stop()
|
||||
### print(ele.inner_html)
|
||||
|
||||
return rtn
|
||||
|
||||
if __name__ == "__main__":
|
||||
ewcc = Sinopec_ewcc()
|
||||
|
||||
# 1 查找现有的标签
|
||||
print('<1> 查找 现有的标签')
|
||||
ewcc.find_tab() # 新增:查找标签页
|
||||
|
||||
# 2 如果没有登录 ,则使用cookie登录
|
||||
if not ewcc.is_login():
|
||||
print('<2> 找不到对应的网站,使用cookies尝试登录')
|
||||
ewcc.load_cookies()
|
||||
ewcc.new_tab()
|
||||
|
||||
# 3 判断是否登录,如果登录不成功,则使用帐号和密码登录
|
||||
if not ewcc.is_login():
|
||||
print('<3> 找不对应的网站,使用帐号密码登录')
|
||||
# 这里要注意12小时才可以登录一次。
|
||||
# 这里显示登录界面,并等待输入一分钟
|
||||
ewcc.show_login()
|
||||
|
||||
# 4 判断是否登录 ,如果失败,则发送信息到微信上
|
||||
if ewcc.is_login():
|
||||
ewcc.tab.refresh()
|
||||
ewcc.save_cookies()
|
||||
print(" 保存cookies")
|
||||
else:
|
||||
ewcc.send_message()
|
||||
|
||||
# ewcc.query_car_info()
|
||||
|
||||
ewcc.quit()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
import requests
|
||||
import time
|
||||
import logging
|
||||
|
||||
# 配置日志
|
||||
handlers = [logging.FileHandler('query_processor.log'), logging.StreamHandler()]
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(levelname)s - %(message)s',
|
||||
handlers=handlers
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# API基础URL
|
||||
BASE_URL = 'http://localhost:99'
|
||||
|
||||
# 演示数据处理函数
|
||||
def process_query_data(query_data, parameters):
|
||||
"""
|
||||
处理查询数据的演示函数
|
||||
这里使用演示代码代替实际的数据处理逻辑
|
||||
"""
|
||||
# 获取用户ID,如果存在
|
||||
user_id = query_data.get('user_id', '未知')
|
||||
logger.info(f"处理查询数据: ID={query_data['id']}, 车牌号={query_data['plate_number']}, 用户ID={user_id}")
|
||||
|
||||
# 这里是演示处理逻辑
|
||||
# 在实际应用中,这里应该是真实的数据处理代码
|
||||
logger.info(f"使用参数进行处理: {parameters}")
|
||||
|
||||
# 模拟处理过程
|
||||
time.sleep(2) # 模拟处理耗时
|
||||
|
||||
# 返回模拟的处理结果(简单地将results_count设置为随机数1-5)
|
||||
# 实际应用中,应该根据真实处理结果返回相应的值
|
||||
results_count = 3 # 演示用的固定结果数
|
||||
logger.info(f"处理完成,结果数量: {results_count}")
|
||||
|
||||
return results_count
|
||||
|
||||
# 读取参数配置
|
||||
def get_parameters():
|
||||
"""
|
||||
从后端API读取参数配置
|
||||
"""
|
||||
try:
|
||||
url = f'{BASE_URL}/api/parameters'
|
||||
response = requests.get(url)
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
|
||||
if data['success']:
|
||||
logger.info(f"成功获取参数配置: {data['data']}")
|
||||
return data['data']
|
||||
else:
|
||||
logger.error(f"获取参数配置失败: {data['error']}")
|
||||
return None
|
||||
except Exception as e:
|
||||
logger.error(f"获取参数配置时发生错误: {str(e)}")
|
||||
return None
|
||||
|
||||
# 获取待处理查询
|
||||
def get_pending_queries():
|
||||
"""
|
||||
从后端API获取待处理查询
|
||||
"""
|
||||
try:
|
||||
url = f'{BASE_URL}/api/pending-queries'
|
||||
response = requests.get(url)
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
|
||||
if data['success']:
|
||||
logger.info(f"成功获取待处理查询,共 {data['count']} 条")
|
||||
return data['data']
|
||||
else:
|
||||
logger.error(f"获取待处理查询失败: {data['error']}")
|
||||
return []
|
||||
except Exception as e:
|
||||
logger.error(f"获取待处理查询时发生错误: {str(e)}")
|
||||
return []
|
||||
|
||||
# 更新查询结果
|
||||
def update_query_result(query_id, results_count):
|
||||
"""
|
||||
更新查询结果到后端API
|
||||
"""
|
||||
try:
|
||||
url = f'{BASE_URL}/api/update-query-result'
|
||||
data = {
|
||||
'id': query_id,
|
||||
'results_count': results_count
|
||||
}
|
||||
|
||||
response = requests.post(url, json=data)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
|
||||
if result['success']:
|
||||
logger.info(f"成功更新查询结果: ID={query_id}, 结果数量={results_count}")
|
||||
return True
|
||||
else:
|
||||
logger.error(f"更新查询结果失败: {result['error']}")
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error(f"更新查询结果时发生错误: {str(e)}")
|
||||
return False
|
||||
|
||||
# 主处理函数
|
||||
def main():
|
||||
logger.info("查询处理代码启动")
|
||||
|
||||
# 获取参数配置
|
||||
parameters = get_parameters()
|
||||
if not parameters:
|
||||
logger.warning("无法获取参数配置,使用默认参数继续")
|
||||
# 使用默认参数继续
|
||||
parameters = {
|
||||
'param1': 'default1',
|
||||
'param2': 'default2',
|
||||
'param3': 'default3',
|
||||
'param4': 'default4',
|
||||
'param5': 'default5'
|
||||
}
|
||||
|
||||
# 主循环
|
||||
while True:
|
||||
try:
|
||||
# 获取待处理查询
|
||||
pending_queries = get_pending_queries()
|
||||
|
||||
# 处理每条查询
|
||||
for query in pending_queries:
|
||||
# 处理查询数据
|
||||
results_count = process_query_data(query, parameters)
|
||||
|
||||
# 更新查询结果
|
||||
update_query_result(query['id'], results_count)
|
||||
|
||||
# 等待一段时间后再次检查
|
||||
wait_time = 60 # 默认等待60秒
|
||||
# 如果有parameters参数,可以根据参数调整等待时间
|
||||
if parameters and 'polling_interval' in parameters:
|
||||
try:
|
||||
wait_time = int(parameters['polling_interval'])
|
||||
except (ValueError, TypeError):
|
||||
logger.warning(f"无效的轮询间隔参数: {parameters['polling_interval']}")
|
||||
|
||||
logger.info(f"本次处理完成,等待 {wait_time} 秒后再次检查")
|
||||
time.sleep(wait_time)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
logger.info("查询处理器被用户中断")
|
||||
break
|
||||
except Exception as e:
|
||||
logger.error(f"处理过程中发生错误: {str(e)}")
|
||||
# 发生错误时,等待更短的时间后重试
|
||||
time.sleep(30)
|
||||
|
||||
logger.info("查询处理器停止")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,69 @@
|
||||
import sqlite3
|
||||
from db_utils import get_db_connection, close_db_connection
|
||||
|
||||
|
||||
def remove_department_from_query_history():
|
||||
"""
|
||||
从query_history表中删除department字段
|
||||
SQLite不支持直接删除列,采用以下步骤:
|
||||
1. 创建一个不包含department字段的新表
|
||||
2. 将原始表中的数据(除department外)复制到新表
|
||||
3. 删除原始表
|
||||
4. 重命名新表为原始表名
|
||||
5. 重新创建索引和外键约束
|
||||
"""
|
||||
conn = None
|
||||
try:
|
||||
# 获取数据库连接
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
print("开始从query_history表中删除department字段...")
|
||||
|
||||
# 1. 创建临时表,不包含department字段
|
||||
print("1. 创建临时表query_history_new...")
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS query_history_new (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
query_date TEXT NOT NULL,
|
||||
plate_number TEXT,
|
||||
phone TEXT,
|
||||
results_count INTEGER NOT NULL,
|
||||
query_ip TEXT NOT NULL,
|
||||
user_id INTEGER,
|
||||
FOREIGN KEY (user_id) REFERENCES users (id)
|
||||
)
|
||||
''')
|
||||
|
||||
# 2. 复制数据到新表,排除department字段
|
||||
print("2. 复制数据到新表,排除department字段...")
|
||||
cursor.execute('''
|
||||
INSERT INTO query_history_new (id, query_date, plate_number, phone, results_count, query_ip, user_id)
|
||||
SELECT id, query_date, plate_number, phone, results_count, query_ip, user_id
|
||||
FROM query_history
|
||||
''')
|
||||
|
||||
# 3. 删除原表
|
||||
print("3. 删除原始表query_history...")
|
||||
cursor.execute('DROP TABLE IF EXISTS query_history')
|
||||
|
||||
# 4. 重命名新表为原表名
|
||||
print("4. 重命名新表为query_history...")
|
||||
cursor.execute('ALTER TABLE query_history_new RENAME TO query_history')
|
||||
|
||||
# 5. 提交事务
|
||||
conn.commit()
|
||||
print("操作完成:department字段已成功从query_history表中删除!")
|
||||
|
||||
except sqlite3.Error as e:
|
||||
print(f"数据库操作出错:{e}")
|
||||
if conn:
|
||||
conn.rollback()
|
||||
raise
|
||||
finally:
|
||||
if conn:
|
||||
close_db_connection(conn)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
remove_department_from_query_history()
|
||||
@@ -0,0 +1,5 @@
|
||||
# Flask应用依赖
|
||||
flask
|
||||
|
||||
# 查询处理器依赖
|
||||
requests
|
||||
@@ -1,15 +0,0 @@
|
||||
# 设置执行策略以允许运行脚本(仅在首次运行时需要取消注释)
|
||||
# Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process
|
||||
|
||||
# 激活虚拟环境
|
||||
& '.\venv\Scripts\Activate.ps1'
|
||||
|
||||
# 设置Flask应用程序环境变量
|
||||
$env:FLASK_APP = "app.py"
|
||||
$env:FLASK_ENV = "development"
|
||||
|
||||
# 启动Flask服务器,允许外部访问(使用python -m flask确保命令可用)
|
||||
python -m flask run --host=0.0.0.0
|
||||
|
||||
# 保持窗口打开
|
||||
Read-Host "Press Enter to exit"
|
||||
@@ -1,14 +0,0 @@
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
# 设置Flask应用程序环境变量
|
||||
os.environ['FLASK_APP'] = 'app.py'
|
||||
os.environ['FLASK_ENV'] = 'development'
|
||||
|
||||
print("Starting Flask server...")
|
||||
print("Server will be available at http://localhost:5000/")
|
||||
print("To allow external access, it's listening on all interfaces (0.0.0.0)")
|
||||
print("Press Ctrl+C to stop the server")
|
||||
|
||||
# 启动Flask服务器,允许外部访问
|
||||
subprocess.run(['python', '-m', 'flask', 'run', '--host=0.0.0.0'])
|
||||
+134
-175
@@ -91,6 +91,7 @@
|
||||
<th>车牌号</th>
|
||||
<th>手机号</th>
|
||||
<th>状态</th>
|
||||
<th>登录用户</th>
|
||||
<th>登录部门</th>
|
||||
<th>登录IP</th>
|
||||
</tr>
|
||||
@@ -118,7 +119,8 @@
|
||||
{% endif %}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ query.department }}</td>
|
||||
<td>{{ query.user_name }}</td>
|
||||
<td>{{ query.user_department }}</td>
|
||||
<td>{{ query.query_ip }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@@ -136,19 +138,7 @@
|
||||
<input type="hidden" id="add_plate_number">
|
||||
<input type="hidden" id="add_phone">
|
||||
|
||||
<!-- 详情模态框 -->
|
||||
<div id="detailModal" class="fixed inset-0 bg-black/50 z-50 hidden flex items-center justify-center p-4">
|
||||
<div class="bg-white rounded-lg shadow-xl max-w-4xl w-full max-h-[90vh] overflow-y-auto">
|
||||
<div class="p-6" id="modalContent">
|
||||
<!-- 结果列表 -->
|
||||
<div id="resultList" class="hidden">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6" id="carOwnerCards">
|
||||
<!-- 车辆信息卡片会动态添加到这里 -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 详情弹窗已使用layui动态生成,此处不再需要静态模态框 -->
|
||||
|
||||
{% include 'footer.html' %}
|
||||
|
||||
@@ -158,25 +148,23 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// 获取DOM元素
|
||||
var addQueryBtn = document.getElementById('addQueryBtn');
|
||||
var addQueryModal = document.getElementById('addQueryModal');
|
||||
var closeAddModal = document.getElementById('closeAddModal');
|
||||
var cancelAddBtn = document.getElementById('cancelAddBtn');
|
||||
var addQueryForm = document.getElementById('addQueryForm');
|
||||
var addQueryLoading = document.getElementById('addQueryLoading');
|
||||
var detailModal = document.getElementById('detailModal');
|
||||
var closeModal = document.getElementById('closeModal');
|
||||
var loadingState = document.getElementById('loadingState');
|
||||
var noResultState = document.getElementById('noResultState');
|
||||
var resultList = document.getElementById('resultList');
|
||||
var carOwnerCards = document.getElementById('carOwnerCards');
|
||||
|
||||
// 为查询历史记录行添加点击事件
|
||||
// 为查询历史记录行添加单击事件
|
||||
var rows = document.querySelectorAll('tr[data-history-id]');
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
rows[i].addEventListener('click', function() {
|
||||
var historyId = this.getAttribute('data-history-id');
|
||||
loadHistoryDetail(historyId);
|
||||
});
|
||||
// 为了提升用户体验,添加鼠标悬停效果
|
||||
rows[i].style.cursor = 'pointer';
|
||||
rows[i].style.transition = 'background-color 0.2s ease';
|
||||
rows[i].addEventListener('mouseenter', function() {
|
||||
this.style.backgroundColor = '#f5f7fa';
|
||||
});
|
||||
rows[i].addEventListener('mouseleave', function() {
|
||||
this.style.backgroundColor = '';
|
||||
});
|
||||
}
|
||||
|
||||
// 增加查询按钮点击事件
|
||||
@@ -396,48 +384,21 @@
|
||||
});
|
||||
});
|
||||
|
||||
// 移除对已删除元素的引用
|
||||
|
||||
// 点击详情模态框背景关闭
|
||||
detailModal.addEventListener('click', function(e) {
|
||||
if (e.target === detailModal) {
|
||||
// 兼容classList API
|
||||
if (detailModal.classList) {
|
||||
detailModal.classList.add('hidden');
|
||||
} else {
|
||||
detailModal.className += ' hidden';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 详情弹窗已使用layui实现,点击背景关闭功能由layui自动处理
|
||||
|
||||
// 表单提交逻辑已整合到layui弹窗中,不需要单独的表单提交事件
|
||||
|
||||
|
||||
// 加载查询历史详情
|
||||
function loadHistoryDetail(historyId) {
|
||||
// 显示模态框和加载状态
|
||||
// 兼容classList API
|
||||
if (detailModal.classList) {
|
||||
detailModal.classList.remove('hidden');
|
||||
} else {
|
||||
detailModal.className = detailModal.className.replace('hidden', '');
|
||||
}
|
||||
if (loadingState.classList) {
|
||||
loadingState.classList.remove('hidden');
|
||||
} else {
|
||||
loadingState.className = loadingState.className.replace('hidden', '');
|
||||
}
|
||||
if (noResultState.classList) {
|
||||
noResultState.classList.add('hidden');
|
||||
} else {
|
||||
noResultState.className += ' hidden';
|
||||
}
|
||||
if (resultList.classList) {
|
||||
resultList.classList.add('hidden');
|
||||
} else {
|
||||
resultList.className += ' hidden';
|
||||
}
|
||||
carOwnerCards.innerHTML = '';
|
||||
// 创建加载中的弹窗
|
||||
const loadingIndex = layer.load(2, {
|
||||
shade: [0.3, '#fff'],
|
||||
content: '<div style="padding: 20px;"><i class="fa fa-spinner fa-spin mr-2"></i>正在加载详情...</div>',
|
||||
shadeClose: false
|
||||
});
|
||||
|
||||
// 发送AJAX请求获取详情
|
||||
fetch('/query_history_detail/' + historyId)
|
||||
@@ -445,99 +406,135 @@
|
||||
return response.json();
|
||||
})
|
||||
.then(function(data) {
|
||||
// 隐藏加载状态
|
||||
// 兼容classList API
|
||||
if (loadingState.classList) {
|
||||
loadingState.classList.add('hidden');
|
||||
} else {
|
||||
loadingState.className += ' hidden';
|
||||
// 关闭加载弹窗
|
||||
layer.close(loadingIndex);
|
||||
|
||||
// 创建详情弹窗内容
|
||||
let content = '';
|
||||
|
||||
// 转义特殊字符以防止XSS攻击
|
||||
function escapeHtml(text) {
|
||||
const div = document.createElement('div');
|
||||
div.textContent = text || '';
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
if (data.error) {
|
||||
// 显示错误信息
|
||||
noResultState.querySelector('p').textContent = data.error;
|
||||
// 兼容classList API
|
||||
if (noResultState.classList) {
|
||||
noResultState.classList.remove('hidden');
|
||||
} else {
|
||||
noResultState.className = noResultState.className.replace('hidden', '');
|
||||
}
|
||||
content = `
|
||||
<div class="layui-text" style="text-align: center; padding: 60px 40px;">
|
||||
<div style="display: inline-flex; align-items: center; justify-content: center; width: 80px; height: 80px; background-color: #fef0f0; border-radius: 50%; margin-bottom: 20px;">
|
||||
<i class="fa fa-exclamation-circle text-red-500 text-4xl"></i>
|
||||
</div>
|
||||
<p style="color: #666; font-size: 16px;">${data.error}</p>
|
||||
</div>
|
||||
`;
|
||||
} else if (data.car_owners && data.car_owners.length > 0) {
|
||||
// 显示结果列表
|
||||
// 兼容classList API
|
||||
if (resultList.classList) {
|
||||
resultList.classList.remove('hidden');
|
||||
} else {
|
||||
resultList.className = resultList.className.replace('hidden', '');
|
||||
}
|
||||
// 添加查询信息标题
|
||||
content = `
|
||||
<div class="layui-text" style="padding: 15px;">
|
||||
<div class="mb-4 pb-3 border-b border-gray-200">
|
||||
|
||||
</div>
|
||||
<div class="space-y-4" id="carOwnerCards">
|
||||
`;
|
||||
|
||||
// 添加车辆信息卡片
|
||||
for (var i = 0; i < data.car_owners.length; i++) {
|
||||
var carOwner = data.car_owners[i];
|
||||
var card = document.createElement('div');
|
||||
card.className = 'bg-white border border-gray-200 rounded-lg p-5 shadow-sm hover:shadow-md transition-shadow duration-200';
|
||||
|
||||
// 使用字符串拼接替代模板字符串
|
||||
var cardHtml = '';
|
||||
cardHtml += '<h4 class="text-lg font-medium text-gray-800 mb-4 flex items-center">';
|
||||
cardHtml += ' <i class="fa fa-car text-primary mr-2"></i>';
|
||||
cardHtml += ' 车辆信息';
|
||||
cardHtml += '</h4>';
|
||||
cardHtml += '<div class="space-y-3">';
|
||||
cardHtml += ' <div class="flex justify-between items-center">';
|
||||
cardHtml += ' <span class="text-gray-500">车牌号:</span>';
|
||||
cardHtml += ' <span class="font-medium text-gray-800">' + (carOwner.plate_number || '') + '</span>';
|
||||
cardHtml += ' </div>';
|
||||
cardHtml += ' <div class="flex justify-between items-center">';
|
||||
cardHtml += ' <span class="text-gray-500">手机号:</span>';
|
||||
cardHtml += ' <span class="font-medium text-gray-800">' + (carOwner.phone || '') + '</span>';
|
||||
cardHtml += ' </div>';
|
||||
cardHtml += ' <div class="flex justify-between items-center">';
|
||||
cardHtml += ' <span class="text-gray-500">车主姓名:</span>';
|
||||
cardHtml += ' <span class="font-medium text-gray-800">' + (carOwner.name || '') + '</span>';
|
||||
cardHtml += ' </div>';
|
||||
cardHtml += ' <div class="flex justify-between items-center">';
|
||||
cardHtml += ' <span class="text-gray-500">身份证号:</span>';
|
||||
cardHtml += ' <span class="font-medium text-gray-800">' + (carOwner.id_card || '') + '</span>';
|
||||
cardHtml += ' </div>';
|
||||
cardHtml += ' <div class="flex justify-between items-center">';
|
||||
cardHtml += ' <span class="text-gray-500">电子邮箱:</span>';
|
||||
cardHtml += ' <span class="font-medium text-gray-800">' + (carOwner.email || '未提供') + '</span>';
|
||||
cardHtml += ' </div>';
|
||||
cardHtml += ' <div class="flex justify-between items-center">';
|
||||
cardHtml += ' <span class="text-gray-500">居住地址:</span>';
|
||||
cardHtml += ' <span class="font-medium text-gray-800">' + (carOwner.address || '未提供') + '</span>';
|
||||
cardHtml += ' </div>';
|
||||
cardHtml += '</div>';
|
||||
|
||||
card.innerHTML = cardHtml;
|
||||
carOwnerCards.appendChild(card);
|
||||
content += `
|
||||
<div class="bg-white border border-gray-200 rounded-lg shadow-sm">
|
||||
<div class="p-3 grid grid-cols-1 gap-2">
|
||||
<div class="flex items-center p-2">
|
||||
<i class="fa fa-id-card-o text-gray-400 w-8 text-center"></i>
|
||||
<span class="text-gray-500 w-20">车牌号:</span>
|
||||
<span class="font-medium text-gray-800 flex-1">${escapeHtml(carOwner.plate_number)}</span>
|
||||
</div>
|
||||
<div class="flex items-center p-2">
|
||||
<i class="fa fa-mobile text-gray-400 w-8 text-center"></i>
|
||||
<span class="text-gray-500 w-20">手机号:</span>
|
||||
<span class="font-medium text-gray-800 flex-1">${escapeHtml(carOwner.phone)}</span>
|
||||
</div>
|
||||
<div class="flex items-center p-2">
|
||||
<i class="fa fa-user text-gray-400 w-8 text-center"></i>
|
||||
<span class="text-gray-500 w-20">车主姓名:</span>
|
||||
<span class="font-medium text-gray-800 flex-1">${escapeHtml(carOwner.name)}</span>
|
||||
</div>
|
||||
<div class="flex items-center p-2">
|
||||
<i class="fa fa-id-card text-gray-400 w-8 text-center"></i>
|
||||
<span class="text-gray-500 w-20">身份证号:</span>
|
||||
<span class="font-medium text-gray-800 flex-1">${escapeHtml(carOwner.id_card)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
content += `
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
// 显示无结果状态
|
||||
// 兼容classList API
|
||||
if (noResultState.classList) {
|
||||
noResultState.classList.remove('hidden');
|
||||
} else {
|
||||
noResultState.className = noResultState.className.replace('hidden', '');
|
||||
content = `
|
||||
<div class="layui-text" style="text-align: center; padding: 60px 40px;">
|
||||
<div style="display: inline-flex; align-items: center; justify-content: center; width: 80px; height: 80px; background-color: #f5f7fa; border-radius: 50%; margin-bottom: 20px;">
|
||||
<i class="fa fa-search text-gray-300 text-4xl"></i>
|
||||
</div>
|
||||
<p style="color: #666; font-size: 16px; margin-bottom: 8px;">暂无车辆信息</p>
|
||||
<p style="color: #909399; font-size: 14px;">该查询条件下未找到相关车辆信息</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
// 打开详情弹窗 - 优化布局和样式
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: '<i class="fa fa-file-text-o"></i> 查询详情',
|
||||
area: ['700px', 'auto'], // 使用自适应高度
|
||||
offset: '10%',
|
||||
shade: [0.3, '#fff'],
|
||||
shadeClose: true,
|
||||
anim: 2,
|
||||
content: content,
|
||||
btn: ['关闭'],
|
||||
btnAlign: 'c',
|
||||
btnClass: ['layui-btn layui-btn-primary'],
|
||||
skin: 'layui-layer-molv',
|
||||
success: function(layero, index) {
|
||||
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(function(error) {
|
||||
// 隐藏加载状态,显示错误信息
|
||||
// 兼容classList API
|
||||
if (loadingState.classList) {
|
||||
loadingState.classList.add('hidden');
|
||||
} else {
|
||||
loadingState.className += ' hidden';
|
||||
}
|
||||
noResultState.querySelector('p').textContent = '加载详情时发生错误';
|
||||
// 兼容classList API
|
||||
if (noResultState.classList) {
|
||||
noResultState.classList.remove('hidden');
|
||||
} else {
|
||||
noResultState.className = noResultState.className.replace('hidden', '');
|
||||
}
|
||||
// 关闭加载弹窗
|
||||
layer.close(loadingIndex);
|
||||
|
||||
// 显示错误弹窗
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: '<i class="fa fa-exclamation-circle"></i> 加载失败',
|
||||
area: ['360px', 'auto'],
|
||||
offset: '10%',
|
||||
shade: 0.3,
|
||||
shadeClose: false,
|
||||
anim: 2,
|
||||
content: `
|
||||
<div class="layui-text" style="text-align: center; padding: 30px 20px;">
|
||||
<div style="display: inline-flex; align-items: center; justify-content: center; width: 60px; height: 60px; background-color: #fef0f0; border-radius: 50%; margin-bottom: 15px;">
|
||||
<i class="fa fa-exclamation-circle text-red-500 text-3xl"></i>
|
||||
</div>
|
||||
<p style="color: #666; font-size: 14px;">加载详情时发生错误</p>
|
||||
<p style="color: #999; font-size: 12px; margin-top: 8px;">请稍后重试</p>
|
||||
</div>
|
||||
`,
|
||||
btn: ['确定'],
|
||||
btnAlign: 'c',
|
||||
btnClass: ['layui-btn layui-btn-primary'],
|
||||
skin: 'layui-layer-molv'
|
||||
});
|
||||
|
||||
console.error('Error loading history detail:', error);
|
||||
});
|
||||
}
|
||||
@@ -562,43 +559,5 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
// 全局搜索变量
|
||||
var searchQuery = '';
|
||||
</script>
|
||||
|
||||
<script>
|
||||
// ESC键关闭详情弹窗
|
||||
document.addEventListener('keydown', function(e) {
|
||||
// 使用keyCode替代key,提高兼容性
|
||||
var key = e.key || e.keyCode;
|
||||
var isEscape = key === 'Escape' || key === 'Esc' || key === 27;
|
||||
|
||||
var detailModal = document.getElementById('detailModal');
|
||||
var isHidden = false;
|
||||
|
||||
// 兼容classList API
|
||||
if (detailModal.classList) {
|
||||
isHidden = detailModal.classList.contains('hidden');
|
||||
} else {
|
||||
isHidden = detailModal.className.indexOf('hidden') !== -1;
|
||||
}
|
||||
|
||||
if (isEscape && !isHidden) {
|
||||
// 兼容classList API
|
||||
if (detailModal.classList) {
|
||||
detailModal.classList.add('hidden');
|
||||
} else {
|
||||
detailModal.className += ' hidden';
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user