|
|
|
|
import sqlite3
|
|
|
|
|
import json
|
|
|
|
|
import os # 添加os模块导入
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
from utils import Globals
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DatabaseManager:
|
|
|
|
|
def __init__(self, dbPath="procedures.db"):
|
|
|
|
|
# 修改:使用跨平台的路径构造方式
|
|
|
|
|
project_dir = os.path.join(os.getcwd(), 'project', str(Globals.getValue('currentPro')))
|
|
|
|
|
db_dir = os.path.join(project_dir, 'db')
|
|
|
|
|
|
|
|
|
|
# 确保目录存在
|
|
|
|
|
os.makedirs(db_dir, exist_ok=True)
|
|
|
|
|
|
|
|
|
|
self.dbPath = os.path.join(db_dir, 'procedures.db')
|
|
|
|
|
print(f"数据库路径: {self.dbPath}")
|
|
|
|
|
self.conn = sqlite3.connect(self.dbPath)
|
|
|
|
|
self.cursor = self.conn.cursor()
|
|
|
|
|
self.createTables()
|
|
|
|
|
|
|
|
|
|
def createTables(self):
|
|
|
|
|
# 创建分类表
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
CREATE TABLE IF NOT EXISTS categories (
|
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
|
|
name TEXT UNIQUE NOT NULL
|
|
|
|
|
)
|
|
|
|
|
""")
|
|
|
|
|
|
|
|
|
|
# 创建规程表
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
CREATE TABLE IF NOT EXISTS procedures (
|
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
|
|
category_id INTEGER,
|
|
|
|
|
name TEXT NOT NULL,
|
|
|
|
|
number TEXT,
|
|
|
|
|
type TEXT,
|
|
|
|
|
content TEXT, -- 存储解析后的JSON数据
|
|
|
|
|
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
FOREIGN KEY(category_id) REFERENCES categories(id)
|
|
|
|
|
)
|
|
|
|
|
""")
|
|
|
|
|
|
|
|
|
|
# 创建规程执行历史表(每次执行记录一条)
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
CREATE TABLE IF NOT EXISTS procedure_execution_history (
|
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
|
|
procedure_id INTEGER NOT NULL,
|
|
|
|
|
start_time TEXT NOT NULL,
|
|
|
|
|
end_time TEXT,
|
|
|
|
|
result BOOLEAN, -- 总体结果
|
|
|
|
|
report_path TEXT, -- 报告路径
|
|
|
|
|
step_results TEXT -- 新增:存储所有步骤执行结果的JSON
|
|
|
|
|
)
|
|
|
|
|
""")
|
|
|
|
|
|
|
|
|
|
# 创建关键词字段库表
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
CREATE TABLE IF NOT EXISTS step_keywords (
|
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
|
|
keyword TEXT NOT NULL,
|
|
|
|
|
operation_type TEXT NOT NULL,
|
|
|
|
|
description TEXT,
|
|
|
|
|
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
UNIQUE(keyword, operation_type)
|
|
|
|
|
)
|
|
|
|
|
""")
|
|
|
|
|
|
|
|
|
|
# 插入默认分类
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
INSERT OR IGNORE INTO categories (name) VALUES
|
|
|
|
|
('默认分类'),
|
|
|
|
|
('紧急规程'),
|
|
|
|
|
('测试规程'),
|
|
|
|
|
('维护规程')
|
|
|
|
|
""")
|
|
|
|
|
|
|
|
|
|
# 插入默认关键词
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
INSERT OR IGNORE INTO step_keywords (keyword, operation_type, description) VALUES
|
|
|
|
|
('设置', 'set', '设置操作类型'),
|
|
|
|
|
('检查', 'check', '检查操作类型'),
|
|
|
|
|
('等待', 'wait', '等待操作类型'),
|
|
|
|
|
('接收', 'deltaT', '接收操作类型'),
|
|
|
|
|
('配置', 'set', '配置操作类型'),
|
|
|
|
|
('验证', 'check', '验证操作类型'),
|
|
|
|
|
('暂停', 'wait', '暂停操作类型'),
|
|
|
|
|
('获取', 'deltaT', '获取操作类型')
|
|
|
|
|
""")
|
|
|
|
|
|
|
|
|
|
# 确保procedures表有report_path列
|
|
|
|
|
try:
|
|
|
|
|
self.cursor.execute("ALTER TABLE procedures ADD COLUMN report_path TEXT DEFAULT ''")
|
|
|
|
|
except sqlite3.OperationalError:
|
|
|
|
|
pass # 列已存在则忽略错误
|
|
|
|
|
|
|
|
|
|
# 创建操作历史表
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
CREATE TABLE IF NOT EXISTS operation_history (
|
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
|
|
execution_id INTEGER NOT NULL,
|
|
|
|
|
operation_type TEXT NOT NULL,
|
|
|
|
|
operation_detail TEXT,
|
|
|
|
|
operation_time TEXT NOT NULL,
|
|
|
|
|
FOREIGN KEY(execution_id) REFERENCES procedure_execution_history(id)
|
|
|
|
|
)
|
|
|
|
|
""")
|
|
|
|
|
self.conn.commit()
|
|
|
|
|
|
|
|
|
|
def getCategories(self):
|
|
|
|
|
self.cursor.execute("SELECT id, name FROM categories ORDER BY name")
|
|
|
|
|
return self.cursor.fetchall()
|
|
|
|
|
|
|
|
|
|
def addCategory(self, name):
|
|
|
|
|
try:
|
|
|
|
|
self.cursor.execute("INSERT INTO categories (name) VALUES (?)", (name,))
|
|
|
|
|
self.conn.commit()
|
|
|
|
|
return True
|
|
|
|
|
except sqlite3.IntegrityError:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def deleteCategory(self, categoryId):
|
|
|
|
|
# 检查是否为默认分类
|
|
|
|
|
self.cursor.execute("SELECT name FROM categories WHERE id = ?", (categoryId,))
|
|
|
|
|
categoryName = self.cursor.fetchone()[0]
|
|
|
|
|
if categoryName == "默认分类":
|
|
|
|
|
return False # 默认分类不可删除
|
|
|
|
|
|
|
|
|
|
self.cursor.execute("SELECT id FROM categories WHERE name = '默认分类'")
|
|
|
|
|
defaultCatId = self.cursor.fetchone()[0]
|
|
|
|
|
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
UPDATE procedures
|
|
|
|
|
SET category_id = ?
|
|
|
|
|
WHERE category_id = ?
|
|
|
|
|
""", (defaultCatId, categoryId))
|
|
|
|
|
|
|
|
|
|
self.cursor.execute("DELETE FROM categories WHERE id = ?", (categoryId,))
|
|
|
|
|
self.conn.commit()
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def addProcedure(self, categoryId, name, number, type, content, reportPath=""):
|
|
|
|
|
"""添加新规程到数据库"""
|
|
|
|
|
contentJson = json.dumps(content, ensure_ascii=False)
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
INSERT INTO procedures (category_id, name, number, type, content, report_path)
|
|
|
|
|
VALUES (?, ?, ?, ?, ?, ?)
|
|
|
|
|
""", (categoryId, name, number, type, contentJson, reportPath))
|
|
|
|
|
self.conn.commit()
|
|
|
|
|
return self.cursor.lastrowid
|
|
|
|
|
|
|
|
|
|
def getProcedures(self, categoryId=None):
|
|
|
|
|
if categoryId:
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
SELECT id, name, number, type, created_at
|
|
|
|
|
FROM procedures
|
|
|
|
|
WHERE category_id = ?
|
|
|
|
|
ORDER BY name
|
|
|
|
|
""", (categoryId,))
|
|
|
|
|
else:
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
SELECT id, name, number, type, created_at
|
|
|
|
|
FROM procedures
|
|
|
|
|
ORDER BY name
|
|
|
|
|
""")
|
|
|
|
|
return self.cursor.fetchall()
|
|
|
|
|
|
|
|
|
|
def getProcedureContent(self, procedureId):
|
|
|
|
|
self.cursor.execute("SELECT content FROM procedures WHERE id = ?", (procedureId,))
|
|
|
|
|
result = self.cursor.fetchone()
|
|
|
|
|
if result:
|
|
|
|
|
return json.loads(result[0])
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
def deleteProcedure(self, procedureId):
|
|
|
|
|
self.cursor.execute("DELETE FROM procedures WHERE id = ?", (procedureId,))
|
|
|
|
|
self.conn.commit()
|
|
|
|
|
return self.cursor.rowcount > 0
|
|
|
|
|
|
|
|
|
|
def insertProcedureExecution(self, procedureId, startTime, result=None, reportPath="", stepResults="[]"):
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
INSERT INTO procedure_execution_history
|
|
|
|
|
(procedure_id, start_time, result, report_path, step_results)
|
|
|
|
|
VALUES (?, ?, ?, ?, ?)
|
|
|
|
|
""", (procedureId, startTime, result, reportPath, stepResults))
|
|
|
|
|
self.conn.commit()
|
|
|
|
|
return self.cursor.lastrowid
|
|
|
|
|
|
|
|
|
|
def updateStepResults(self, executionId, stepResults):
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
UPDATE procedure_execution_history
|
|
|
|
|
SET step_results = ?
|
|
|
|
|
WHERE id = ?
|
|
|
|
|
""", (json.dumps(stepResults), executionId))
|
|
|
|
|
self.conn.commit()
|
|
|
|
|
return self.cursor.rowcount > 0
|
|
|
|
|
|
|
|
|
|
def getStepResults(self, executionId):
|
|
|
|
|
"""根据执行ID获取步骤结果 - 修正SQL语句"""
|
|
|
|
|
# 修正:使用正确的列名 execution_id -> id
|
|
|
|
|
self.cursor.execute("SELECT step_results FROM procedure_execution_history WHERE id=?", (executionId,))
|
|
|
|
|
row = self.cursor.fetchone()
|
|
|
|
|
if row:
|
|
|
|
|
return json.loads(row[0])
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
def getExecutionHistory(self, filterText=None):
|
|
|
|
|
query = """
|
|
|
|
|
SELECT
|
|
|
|
|
peh.id,
|
|
|
|
|
p.name || '(' || p.number || ')' AS full_name, -- 拼接规程全名
|
|
|
|
|
p.type,
|
|
|
|
|
peh.start_time,
|
|
|
|
|
peh.report_path
|
|
|
|
|
FROM procedure_execution_history peh
|
|
|
|
|
JOIN procedures p ON peh.procedure_id = p.id
|
|
|
|
|
WHERE peh.report_path IS NOT NULL
|
|
|
|
|
"""
|
|
|
|
|
params = []
|
|
|
|
|
|
|
|
|
|
if filterText:
|
|
|
|
|
query += " AND (p.name LIKE ? OR p.number LIKE ? OR p.type LIKE ?)"
|
|
|
|
|
searchTerm = f"%{filterText}%"
|
|
|
|
|
params = [searchTerm, searchTerm, searchTerm]
|
|
|
|
|
|
|
|
|
|
self.cursor.execute(query, params)
|
|
|
|
|
return self.cursor.fetchall()
|
|
|
|
|
|
|
|
|
|
def updateExecutionReportPath(self, executionId, reportPath):
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
UPDATE procedure_execution_history
|
|
|
|
|
SET report_path = ?
|
|
|
|
|
WHERE id = ?
|
|
|
|
|
""", (reportPath, executionId))
|
|
|
|
|
self.conn.commit()
|
|
|
|
|
return self.cursor.rowcount > 0
|
|
|
|
|
|
|
|
|
|
def deleteExecutionHistory(self, executionIds):
|
|
|
|
|
"""删除指定的执行历史记录及其相关操作历史 - 方法名已修正"""
|
|
|
|
|
if not executionIds:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# 转换为整数列表
|
|
|
|
|
ids = [int(id) for id in executionIds]
|
|
|
|
|
|
|
|
|
|
# 删除操作历史记录
|
|
|
|
|
self.cursor.executemany(
|
|
|
|
|
"DELETE FROM operation_history WHERE execution_id = ?",
|
|
|
|
|
[(id,) for id in ids]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# 删除执行历史记录
|
|
|
|
|
self.cursor.executemany(
|
|
|
|
|
"DELETE FROM procedure_execution_history WHERE id = ?",
|
|
|
|
|
[(id,) for id in ids]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
self.conn.commit()
|
|
|
|
|
return True
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"删除执行历史失败: {str(e)}")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def getExecutionDetails(self, executionId):
|
|
|
|
|
"""获取执行记录的完整详情"""
|
|
|
|
|
try:
|
|
|
|
|
# 获取执行记录基本信息
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
SELECT
|
|
|
|
|
peh.id,
|
|
|
|
|
p.id AS procedure_id,
|
|
|
|
|
p.name AS procedure_name,
|
|
|
|
|
p.content AS procedure_content,
|
|
|
|
|
peh.step_results
|
|
|
|
|
FROM procedure_execution_history peh
|
|
|
|
|
JOIN procedures p ON peh.procedure_id = p.id
|
|
|
|
|
WHERE peh.id = ?
|
|
|
|
|
""", (executionId,))
|
|
|
|
|
row = self.cursor.fetchone()
|
|
|
|
|
|
|
|
|
|
if not row:
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
# 解析数据
|
|
|
|
|
details = {
|
|
|
|
|
"execution_id": row[0],
|
|
|
|
|
"procedure_id": row[1],
|
|
|
|
|
"procedure_name": row[2],
|
|
|
|
|
"procedure_content": json.loads(row[3]),
|
|
|
|
|
"step_results": json.loads(row[4])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return details
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"获取执行详情失败: {str(e)}")
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
def updateProcedureCategory(self, procedureId, newCategoryId):
|
|
|
|
|
"""更新规程的分类"""
|
|
|
|
|
try:
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
UPDATE procedures
|
|
|
|
|
SET category_id = ?
|
|
|
|
|
WHERE id = ?
|
|
|
|
|
""", (newCategoryId, procedureId))
|
|
|
|
|
self.conn.commit()
|
|
|
|
|
return self.cursor.rowcount > 0
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"更新规程分类失败: {str(e)}")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def saveOperationHistory(self, executionId, operationType, operationDetail, operationTime):
|
|
|
|
|
"""保存操作历史记录"""
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
INSERT INTO operation_history
|
|
|
|
|
(execution_id, operation_type, operation_detail, operation_time)
|
|
|
|
|
VALUES (?, ?, ?, ?)
|
|
|
|
|
""", (executionId, operationType, operationDetail, operationTime))
|
|
|
|
|
self.conn.commit()
|
|
|
|
|
return self.cursor.lastrowid
|
|
|
|
|
|
|
|
|
|
def close(self):
|
|
|
|
|
self.conn.close()
|
|
|
|
|
|
|
|
|
|
# 关键词字段库相关方法
|
|
|
|
|
def getStepKeywords(self, operationType=None):
|
|
|
|
|
"""获取关键词列表"""
|
|
|
|
|
if operationType:
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
SELECT id, keyword, operation_type, description, created_at
|
|
|
|
|
FROM step_keywords
|
|
|
|
|
WHERE operation_type = ?
|
|
|
|
|
ORDER BY keyword
|
|
|
|
|
""", (operationType,))
|
|
|
|
|
else:
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
SELECT id, keyword, operation_type, description, created_at
|
|
|
|
|
FROM step_keywords
|
|
|
|
|
ORDER BY keyword
|
|
|
|
|
""")
|
|
|
|
|
return self.cursor.fetchall()
|
|
|
|
|
|
|
|
|
|
def addStepKeyword(self, keyword, operationType, description=""):
|
|
|
|
|
"""添加关键词"""
|
|
|
|
|
try:
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
INSERT INTO step_keywords (keyword, operation_type, description)
|
|
|
|
|
VALUES (?, ?, ?)
|
|
|
|
|
""", (keyword, operationType, description))
|
|
|
|
|
self.conn.commit()
|
|
|
|
|
return self.cursor.lastrowid
|
|
|
|
|
except sqlite3.IntegrityError:
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
def updateStepKeyword(self, keywordId, newKeyword, operationType, description=""):
|
|
|
|
|
"""更新关键词"""
|
|
|
|
|
try:
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
UPDATE step_keywords
|
|
|
|
|
SET keyword = ?, operation_type = ?, description = ?
|
|
|
|
|
WHERE id = ?
|
|
|
|
|
""", (newKeyword, operationType, description, keywordId))
|
|
|
|
|
self.conn.commit()
|
|
|
|
|
return self.cursor.rowcount > 0
|
|
|
|
|
except sqlite3.IntegrityError:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def deleteStepKeyword(self, keywordId):
|
|
|
|
|
"""删除关键词"""
|
|
|
|
|
self.cursor.execute("DELETE FROM step_keywords WHERE id = ?", (keywordId,))
|
|
|
|
|
self.conn.commit()
|
|
|
|
|
return self.cursor.rowcount > 0
|
|
|
|
|
|
|
|
|
|
def getKeywordByText(self, text):
|
|
|
|
|
"""根据文本查找匹配的关键词"""
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
SELECT keyword, operation_type
|
|
|
|
|
FROM step_keywords
|
|
|
|
|
WHERE ? LIKE '%' || keyword || '%'
|
|
|
|
|
ORDER BY LENGTH(keyword) DESC
|
|
|
|
|
""", (text,))
|
|
|
|
|
return self.cursor.fetchall()
|
|
|
|
|
|
|
|
|
|
def getOperationTypes(self):
|
|
|
|
|
"""获取所有操作类型"""
|
|
|
|
|
self.cursor.execute("""
|
|
|
|
|
SELECT DISTINCT operation_type
|
|
|
|
|
FROM step_keywords
|
|
|
|
|
ORDER BY operation_type
|
|
|
|
|
""")
|
|
|
|
|
return [row[0] for row in self.cursor.fetchall()]
|