1075 lines
33 KiB
C++
1075 lines
33 KiB
C++
#include "datamanagementwidget.h"
|
|
#include "overlaydialogswidget.h"
|
|
#include <QHeaderView>
|
|
#include <QScrollArea>
|
|
#include <QDateTime>
|
|
#include <QFileDialog>
|
|
#include <QStorageInfo>
|
|
#include <QListView>
|
|
#include <QCalendarWidget>
|
|
#include <QTextCharFormat>
|
|
|
|
// 样式常量定义
|
|
const QString DataManagementWidget::LABEL_STYLE = R"(
|
|
QLabel {
|
|
color: #333333;
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
}
|
|
)";
|
|
|
|
const QString DataManagementWidget::BUTTON_STYLE = R"(
|
|
QPushButton {
|
|
background-color: #f5f5f5;
|
|
color: #333333;
|
|
border: 1px solid #ddd;
|
|
border-radius: 6px;
|
|
padding: 8px 16px;
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
min-height: 36px;
|
|
}
|
|
QPushButton:hover {
|
|
background-color: #e8e8e8;
|
|
border-color: #ccc;
|
|
}
|
|
QPushButton:pressed {
|
|
background-color: #d0d0d0;
|
|
}
|
|
)";
|
|
|
|
const QString DataManagementWidget::PRIMARY_BUTTON_STYLE = R"(
|
|
QPushButton {
|
|
background-color: #2196F3;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 6px;
|
|
padding: 8px 16px;
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
min-height: 36px;
|
|
}
|
|
QPushButton:hover {
|
|
background-color: #1976D2;
|
|
}
|
|
QPushButton:pressed {
|
|
background-color: #1565C0;
|
|
}
|
|
)";
|
|
|
|
const QString DataManagementWidget::DANGER_BUTTON_STYLE = R"(
|
|
QPushButton {
|
|
background-color: #f44336;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 6px;
|
|
padding: 8px 16px;
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
min-height: 36px;
|
|
}
|
|
QPushButton:hover {
|
|
background-color: #d32f2f;
|
|
}
|
|
QPushButton:pressed {
|
|
background-color: #c62828;
|
|
}
|
|
)";
|
|
|
|
const QString DataManagementWidget::INPUT_STYLE = R"(
|
|
QLineEdit, QComboBox, QDateEdit {
|
|
background-color: white;
|
|
border: 1px solid #ddd;
|
|
border-radius: 6px;
|
|
padding: 8px 12px;
|
|
font-size: 14px;
|
|
min-height: 36px;
|
|
}
|
|
QLineEdit:focus, QComboBox:focus, QDateEdit:focus {
|
|
border-color: #2196F3;
|
|
}
|
|
QComboBox::drop-down, QDateEdit::drop-down {
|
|
subcontrol-origin: padding;
|
|
subcontrol-position: center right;
|
|
width: 30px;
|
|
border: none;
|
|
}
|
|
QComboBox::down-arrow, QDateEdit::down-arrow {
|
|
image: url(:/icons/arrow_down.svg);
|
|
width: 14px;
|
|
height: 14px;
|
|
}
|
|
QCalendarWidget {
|
|
background-color: white;
|
|
border: 1px solid #ccc;
|
|
border-radius: 8px;
|
|
}
|
|
QCalendarWidget QToolButton {
|
|
color: #333;
|
|
background-color: transparent;
|
|
border: none;
|
|
border-radius: 4px;
|
|
padding: 8px;
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
}
|
|
QCalendarWidget QToolButton:hover {
|
|
background-color: #e3f2fd;
|
|
}
|
|
QCalendarWidget QMenu {
|
|
background-color: white;
|
|
border: 1px solid #ccc;
|
|
}
|
|
QCalendarWidget QMenu::item {
|
|
padding: 8px 20px;
|
|
}
|
|
QCalendarWidget QMenu::item:selected {
|
|
background-color: #2196F3;
|
|
color: white;
|
|
}
|
|
QCalendarWidget QSpinBox {
|
|
background-color: white;
|
|
border: 1px solid #ddd;
|
|
border-radius: 4px;
|
|
padding: 4px;
|
|
font-size: 14px;
|
|
}
|
|
QCalendarWidget QAbstractItemView {
|
|
background-color: white;
|
|
selection-background-color: #2196F3;
|
|
selection-color: white;
|
|
font-size: 14px;
|
|
}
|
|
QCalendarWidget QAbstractItemView:enabled {
|
|
color: #333;
|
|
}
|
|
QCalendarWidget QAbstractItemView:disabled {
|
|
color: #999;
|
|
}
|
|
)";
|
|
|
|
const QString DataManagementWidget::TABLE_STYLE = R"(
|
|
QTableWidget {
|
|
background-color: white;
|
|
border: 1px solid #ddd;
|
|
border-radius: 8px;
|
|
gridline-color: #eee;
|
|
font-size: 13px;
|
|
}
|
|
QTableWidget::item {
|
|
padding: 8px;
|
|
border-bottom: 1px solid #eee;
|
|
}
|
|
QTableWidget::item:selected {
|
|
background-color: #e3f2fd;
|
|
color: #333;
|
|
}
|
|
QHeaderView::section {
|
|
background-color: #f5f5f5;
|
|
color: #333;
|
|
font-weight: 600;
|
|
padding: 10px;
|
|
border: none;
|
|
border-bottom: 2px solid #2196F3;
|
|
}
|
|
)";
|
|
|
|
const QString DataManagementWidget::GROUP_STYLE = R"(
|
|
QGroupBox {
|
|
background-color: white;
|
|
border: 1px solid #e0e0e0;
|
|
border-radius: 8px;
|
|
margin-top: 16px;
|
|
padding: 16px;
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
}
|
|
QGroupBox::title {
|
|
subcontrol-origin: margin;
|
|
subcontrol-position: top left;
|
|
left: 16px;
|
|
padding: 0 8px;
|
|
color: #333;
|
|
}
|
|
)";
|
|
|
|
DataManagementWidget::DataManagementWidget(QWidget *parent)
|
|
: QWidget(parent)
|
|
{
|
|
setupUI();
|
|
populateSampleData();
|
|
updateStorageInfo();
|
|
}
|
|
|
|
void DataManagementWidget::setupUI()
|
|
{
|
|
setStyleSheet("background-color: #f5f5f5;");
|
|
|
|
QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
|
mainLayout->setContentsMargins(0, 0, 0, 0);
|
|
mainLayout->setSpacing(0);
|
|
|
|
// 标题栏
|
|
QWidget *headerWidget = new QWidget;
|
|
headerWidget->setFixedHeight(60);
|
|
headerWidget->setStyleSheet("background-color: #2196F3;");
|
|
|
|
QHBoxLayout *headerLayout = new QHBoxLayout(headerWidget);
|
|
headerLayout->setContentsMargins(16, 0, 16, 0);
|
|
|
|
m_backBtn = new QPushButton("← 返回");
|
|
m_backBtn->setStyleSheet(
|
|
"QPushButton { background: rgba(255,255,255,0.2); color: white; border: none; "
|
|
"border-radius: 6px; padding: 8px 16px; font-size: 14px; }"
|
|
"QPushButton:hover { background: rgba(255,255,255,0.3); }");
|
|
m_backBtn->setCursor(Qt::PointingHandCursor);
|
|
connect(m_backBtn, &QPushButton::clicked, this, &DataManagementWidget::backRequested);
|
|
|
|
m_titleLabel = new QLabel("数据管理");
|
|
m_titleLabel->setStyleSheet("color: white; font-size: 18px; font-weight: bold;");
|
|
m_titleLabel->setAlignment(Qt::AlignCenter);
|
|
|
|
headerLayout->addWidget(m_backBtn);
|
|
headerLayout->addWidget(m_titleLabel, 1);
|
|
|
|
// 占位,保持标题居中
|
|
auto *spacer = new QWidget(this);
|
|
spacer->setFixedWidth(80);
|
|
headerLayout->addWidget(spacer);
|
|
|
|
mainLayout->addWidget(headerWidget);
|
|
|
|
// 内容区域
|
|
QScrollArea *scrollArea = new QScrollArea;
|
|
scrollArea->setWidgetResizable(true);
|
|
scrollArea->setFrameShape(QFrame::NoFrame);
|
|
scrollArea->setStyleSheet("QScrollArea { background-color: #f5f5f5; border: none; }");
|
|
|
|
QWidget *contentWidget = new QWidget;
|
|
QVBoxLayout *contentLayout = new QVBoxLayout(contentWidget);
|
|
contentLayout->setContentsMargins(16, 16, 16, 16);
|
|
contentLayout->setSpacing(16);
|
|
|
|
// 存储信息面板
|
|
contentLayout->addWidget(createStorageInfoPanel());
|
|
|
|
// 筛选面板
|
|
contentLayout->addWidget(createFilterPanel());
|
|
|
|
// 工具栏
|
|
contentLayout->addWidget(createToolBar());
|
|
|
|
// 数据表格
|
|
contentLayout->addWidget(createDataTable(), 1);
|
|
|
|
scrollArea->setWidget(contentWidget);
|
|
mainLayout->addWidget(scrollArea, 1);
|
|
}
|
|
|
|
QWidget *DataManagementWidget::createStorageInfoPanel()
|
|
{
|
|
QWidget *panel = new QWidget;
|
|
panel->setStyleSheet(R"(
|
|
QWidget {
|
|
background-color: white;
|
|
border-radius: 8px;
|
|
}
|
|
)");
|
|
panel->setFixedHeight(100);
|
|
|
|
QHBoxLayout *layout = new QHBoxLayout(panel);
|
|
layout->setContentsMargins(20, 16, 20, 16);
|
|
layout->setSpacing(40);
|
|
|
|
// 存储使用情况
|
|
QVBoxLayout *storageLayout = new QVBoxLayout;
|
|
storageLayout->setSpacing(8);
|
|
|
|
QLabel *storageTitle = new QLabel("存储空间");
|
|
storageTitle->setStyleSheet("font-size: 12px; color: #888;");
|
|
storageLayout->addWidget(storageTitle);
|
|
|
|
m_storageUsedLabel = new QLabel("0 MB / 0 GB");
|
|
m_storageUsedLabel->setStyleSheet("font-size: 16px; font-weight: 600; color: #333;");
|
|
storageLayout->addWidget(m_storageUsedLabel);
|
|
|
|
m_storageProgressBar = new QProgressBar;
|
|
m_storageProgressBar->setFixedHeight(6);
|
|
m_storageProgressBar->setTextVisible(false);
|
|
m_storageProgressBar->setStyleSheet(R"(
|
|
QProgressBar {
|
|
background-color: #e0e0e0;
|
|
border-radius: 3px;
|
|
}
|
|
QProgressBar::chunk {
|
|
background-color: #4CAF50;
|
|
border-radius: 3px;
|
|
}
|
|
)");
|
|
storageLayout->addWidget(m_storageProgressBar);
|
|
|
|
layout->addLayout(storageLayout, 1);
|
|
|
|
// 记录数量
|
|
QVBoxLayout *recordLayout = new QVBoxLayout;
|
|
recordLayout->setSpacing(8);
|
|
|
|
QLabel *recordTitle = new QLabel("校准记录");
|
|
recordTitle->setStyleSheet("font-size: 12px; color: #888;");
|
|
recordLayout->addWidget(recordTitle);
|
|
|
|
m_recordCountLabel = new QLabel("0 条");
|
|
m_recordCountLabel->setStyleSheet("font-size: 24px; font-weight: 600; color: #2196F3;");
|
|
recordLayout->addWidget(m_recordCountLabel);
|
|
|
|
layout->addLayout(recordLayout);
|
|
|
|
// 快捷操作
|
|
QVBoxLayout *actionLayout = new QVBoxLayout;
|
|
actionLayout->setSpacing(8);
|
|
|
|
m_syncBtn = new QPushButton("云端同步");
|
|
m_syncBtn->setStyleSheet(PRIMARY_BUTTON_STYLE);
|
|
m_syncBtn->setFixedWidth(100);
|
|
connect(m_syncBtn, &QPushButton::clicked, this, &DataManagementWidget::onSyncClicked);
|
|
actionLayout->addWidget(m_syncBtn);
|
|
|
|
layout->addLayout(actionLayout);
|
|
|
|
return panel;
|
|
}
|
|
|
|
QWidget *DataManagementWidget::createFilterPanel()
|
|
{
|
|
QWidget *panel = new QWidget;
|
|
panel->setStyleSheet(R"(
|
|
QWidget {
|
|
background-color: white;
|
|
border-radius: 8px;
|
|
}
|
|
)");
|
|
|
|
QVBoxLayout *layout = new QVBoxLayout(panel);
|
|
layout->setContentsMargins(16, 16, 16, 16);
|
|
layout->setSpacing(12);
|
|
|
|
QLabel *filterTitle = new QLabel("筛选条件");
|
|
filterTitle->setStyleSheet("font-size: 14px; font-weight: 600; color: #333;");
|
|
layout->addWidget(filterTitle);
|
|
|
|
QHBoxLayout *filterLayout = new QHBoxLayout;
|
|
filterLayout->setSpacing(12);
|
|
|
|
// 数据类型
|
|
QVBoxLayout *categoryLayout = new QVBoxLayout;
|
|
QLabel *categoryLabel = new QLabel("数据类型");
|
|
categoryLabel->setStyleSheet("font-size: 12px; color: #666;");
|
|
categoryLayout->addWidget(categoryLabel);
|
|
|
|
m_categoryCombo = new QComboBox;
|
|
m_categoryCombo->setFixedWidth(150);
|
|
m_categoryCombo->addItems({"全部", "校准记录", "测量数据", "诊断日志", "系统日志"});
|
|
m_categoryCombo->setCursor(Qt::PointingHandCursor);
|
|
|
|
// 设置下拉列表视图
|
|
QListView *listView = new QListView(m_categoryCombo);
|
|
listView->setStyleSheet(R"(
|
|
QListView {
|
|
background-color: white;
|
|
border: 1px solid #ccc;
|
|
border-radius: 6px;
|
|
outline: none;
|
|
}
|
|
QListView::item {
|
|
height: 40px;
|
|
padding-left: 12px;
|
|
border: none;
|
|
}
|
|
QListView::item:hover {
|
|
background-color: #e3f2fd;
|
|
}
|
|
QListView::item:selected {
|
|
background-color: #2196F3;
|
|
color: white;
|
|
}
|
|
)");
|
|
m_categoryCombo->setView(listView);
|
|
|
|
m_categoryCombo->setStyleSheet(R"(
|
|
QComboBox {
|
|
background-color: white;
|
|
border: 1px solid #ddd;
|
|
border-radius: 6px;
|
|
padding: 8px 12px;
|
|
font-size: 14px;
|
|
min-height: 36px;
|
|
}
|
|
QComboBox:hover {
|
|
border-color: #2196F3;
|
|
}
|
|
QComboBox::drop-down {
|
|
subcontrol-origin: padding;
|
|
subcontrol-position: center right;
|
|
width: 30px;
|
|
border: none;
|
|
}
|
|
QComboBox::down-arrow {
|
|
image: url(:/icons/arrow_down.svg);
|
|
width: 14px;
|
|
height: 14px;
|
|
}
|
|
)");
|
|
|
|
connect(m_categoryCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
|
this, &DataManagementWidget::onCategoryChanged);
|
|
categoryLayout->addWidget(m_categoryCombo);
|
|
filterLayout->addLayout(categoryLayout);
|
|
|
|
// 开始日期
|
|
QVBoxLayout *startLayout = new QVBoxLayout;
|
|
QLabel *startLabel = new QLabel("开始日期");
|
|
startLabel->setStyleSheet("font-size: 12px; color: #666;");
|
|
startLayout->addWidget(startLabel);
|
|
|
|
m_startDateEdit = new QDateEdit;
|
|
m_startDateEdit->setFixedWidth(140);
|
|
m_startDateEdit->setCalendarPopup(true);
|
|
m_startDateEdit->setDate(QDate::currentDate().addMonths(-1));
|
|
m_startDateEdit->setCursor(Qt::PointingHandCursor);
|
|
setupDateEditStyle(m_startDateEdit);
|
|
startLayout->addWidget(m_startDateEdit);
|
|
filterLayout->addLayout(startLayout);
|
|
|
|
// 结束日期
|
|
QVBoxLayout *endLayout = new QVBoxLayout;
|
|
QLabel *endLabel = new QLabel("结束日期");
|
|
endLabel->setStyleSheet("font-size: 12px; color: #666;");
|
|
endLayout->addWidget(endLabel);
|
|
|
|
m_endDateEdit = new QDateEdit;
|
|
m_endDateEdit->setFixedWidth(140);
|
|
m_endDateEdit->setCalendarPopup(true);
|
|
m_endDateEdit->setDate(QDate::currentDate());
|
|
m_endDateEdit->setCursor(Qt::PointingHandCursor);
|
|
setupDateEditStyle(m_endDateEdit);
|
|
endLayout->addWidget(m_endDateEdit);
|
|
filterLayout->addLayout(endLayout);
|
|
|
|
// 搜索框
|
|
QVBoxLayout *searchLayout = new QVBoxLayout;
|
|
QLabel *searchLabel = new QLabel("关键字搜索");
|
|
searchLabel->setStyleSheet("font-size: 12px; color: #666;");
|
|
searchLayout->addWidget(searchLabel);
|
|
|
|
QHBoxLayout *searchInputLayout = new QHBoxLayout;
|
|
m_searchEdit = new QLineEdit;
|
|
m_searchEdit->setStyleSheet(INPUT_STYLE);
|
|
m_searchEdit->setPlaceholderText("输入设备序列号、操作员等");
|
|
searchInputLayout->addWidget(m_searchEdit, 1);
|
|
|
|
m_searchBtn = new QPushButton("搜索");
|
|
m_searchBtn->setStyleSheet(PRIMARY_BUTTON_STYLE);
|
|
m_searchBtn->setFixedWidth(80);
|
|
connect(m_searchBtn, &QPushButton::clicked, this, &DataManagementWidget::onSearchClicked);
|
|
searchInputLayout->addWidget(m_searchBtn);
|
|
|
|
searchLayout->addLayout(searchInputLayout);
|
|
filterLayout->addLayout(searchLayout, 1);
|
|
|
|
layout->addLayout(filterLayout);
|
|
|
|
return panel;
|
|
}
|
|
|
|
QWidget *DataManagementWidget::createToolBar()
|
|
{
|
|
QWidget *toolbar = new QWidget;
|
|
toolbar->setStyleSheet("background-color: transparent;");
|
|
|
|
QHBoxLayout *layout = new QHBoxLayout(toolbar);
|
|
layout->setContentsMargins(0, 0, 0, 0);
|
|
layout->setSpacing(12);
|
|
|
|
m_selectAllCheck = new QCheckBox("全选");
|
|
m_selectAllCheck->setStyleSheet("font-size: 14px; color: #666;");
|
|
connect(m_selectAllCheck, &QCheckBox::stateChanged, this, &DataManagementWidget::onSelectAllChanged);
|
|
layout->addWidget(m_selectAllCheck);
|
|
|
|
layout->addStretch();
|
|
|
|
m_refreshBtn = new QPushButton("刷新");
|
|
m_refreshBtn->setStyleSheet(BUTTON_STYLE);
|
|
m_refreshBtn->setFixedWidth(80);
|
|
connect(m_refreshBtn, &QPushButton::clicked, this, &DataManagementWidget::onRefreshClicked);
|
|
layout->addWidget(m_refreshBtn);
|
|
|
|
m_exportBtn = new QPushButton("导出");
|
|
m_exportBtn->setStyleSheet(PRIMARY_BUTTON_STYLE);
|
|
m_exportBtn->setFixedWidth(80);
|
|
connect(m_exportBtn, &QPushButton::clicked, this, &DataManagementWidget::onExportClicked);
|
|
layout->addWidget(m_exportBtn);
|
|
|
|
m_backupBtn = new QPushButton("备份");
|
|
m_backupBtn->setStyleSheet(BUTTON_STYLE);
|
|
m_backupBtn->setFixedWidth(80);
|
|
connect(m_backupBtn, &QPushButton::clicked, this, &DataManagementWidget::onBackupClicked);
|
|
layout->addWidget(m_backupBtn);
|
|
|
|
m_restoreBtn = new QPushButton("恢复");
|
|
m_restoreBtn->setStyleSheet(BUTTON_STYLE);
|
|
m_restoreBtn->setFixedWidth(80);
|
|
connect(m_restoreBtn, &QPushButton::clicked, this, &DataManagementWidget::onRestoreClicked);
|
|
layout->addWidget(m_restoreBtn);
|
|
|
|
m_deleteBtn = new QPushButton("删除选中");
|
|
m_deleteBtn->setStyleSheet(DANGER_BUTTON_STYLE);
|
|
m_deleteBtn->setFixedWidth(100);
|
|
connect(m_deleteBtn, &QPushButton::clicked, this, &DataManagementWidget::onDeleteClicked);
|
|
layout->addWidget(m_deleteBtn);
|
|
|
|
m_clearHistoryBtn = new QPushButton("清空历史");
|
|
m_clearHistoryBtn->setStyleSheet(DANGER_BUTTON_STYLE);
|
|
m_clearHistoryBtn->setFixedWidth(100);
|
|
connect(m_clearHistoryBtn, &QPushButton::clicked, this, &DataManagementWidget::onClearHistoryClicked);
|
|
layout->addWidget(m_clearHistoryBtn);
|
|
|
|
return toolbar;
|
|
}
|
|
|
|
QWidget *DataManagementWidget::createDataTable()
|
|
{
|
|
QWidget *tableContainer = new QWidget;
|
|
tableContainer->setStyleSheet(R"(
|
|
QWidget {
|
|
background-color: white;
|
|
border-radius: 8px;
|
|
}
|
|
)");
|
|
|
|
QVBoxLayout *layout = new QVBoxLayout(tableContainer);
|
|
layout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
m_dataTable = new QTableWidget;
|
|
m_dataTable->setStyleSheet(TABLE_STYLE);
|
|
m_dataTable->setColumnCount(7);
|
|
m_dataTable->setHorizontalHeaderLabels({"", "记录ID", "类型", "设备序列号", "操作员", "时间", "状态"});
|
|
|
|
// 设置列宽
|
|
m_dataTable->setColumnWidth(0, 40); // 复选框
|
|
m_dataTable->setColumnWidth(1, 100); // 记录ID
|
|
m_dataTable->setColumnWidth(2, 100); // 类型
|
|
m_dataTable->setColumnWidth(3, 150); // 设备序列号
|
|
m_dataTable->setColumnWidth(4, 100); // 操作员
|
|
m_dataTable->setColumnWidth(5, 160); // 时间
|
|
m_dataTable->horizontalHeader()->setStretchLastSection(true);
|
|
|
|
m_dataTable->setSelectionBehavior(QAbstractItemView::SelectRows);
|
|
m_dataTable->setAlternatingRowColors(true);
|
|
m_dataTable->verticalHeader()->setVisible(false);
|
|
m_dataTable->setShowGrid(false);
|
|
|
|
connect(m_dataTable, &QTableWidget::cellDoubleClicked,
|
|
this, &DataManagementWidget::onRecordDoubleClicked);
|
|
|
|
layout->addWidget(m_dataTable);
|
|
|
|
return tableContainer;
|
|
}
|
|
|
|
void DataManagementWidget::populateSampleData()
|
|
{
|
|
// 示例数据
|
|
struct RecordData
|
|
{
|
|
QString id;
|
|
QString type;
|
|
QString serial;
|
|
QString op;
|
|
QString time;
|
|
QString status;
|
|
};
|
|
|
|
QList<RecordData> sampleData = {
|
|
{"REC-2024-0001", "校准记录", "SN-A12345678", "张工", "2024-01-15 09:30:25", "成功"},
|
|
{"REC-2024-0002", "测量数据", "SN-B87654321", "李工", "2024-01-15 10:15:42", "成功"},
|
|
{"REC-2024-0003", "诊断日志", "SN-A12345678", "系统", "2024-01-15 11:00:00", "完成"},
|
|
{"REC-2024-0004", "校准记录", "SN-C11223344", "王工", "2024-01-14 14:22:18", "成功"},
|
|
{"REC-2024-0005", "测量数据", "SN-A12345678", "张工", "2024-01-14 15:45:33", "异常"},
|
|
{"REC-2024-0006", "系统日志", "-", "系统", "2024-01-14 16:00:00", "信息"},
|
|
{"REC-2024-0007", "校准记录", "SN-D55667788", "李工", "2024-01-13 09:10:05", "成功"},
|
|
{"REC-2024-0008", "测量数据", "SN-B87654321", "王工", "2024-01-13 10:30:15", "成功"},
|
|
{"REC-2024-0009", "诊断日志", "SN-C11223344", "系统", "2024-01-12 08:00:00", "警告"},
|
|
{"REC-2024-0010", "校准记录", "SN-A12345678", "张工", "2024-01-12 11:20:45", "成功"},
|
|
};
|
|
|
|
m_dataTable->setRowCount(sampleData.size());
|
|
|
|
for (int row = 0; row < sampleData.size(); ++row)
|
|
{
|
|
const auto &data = sampleData[row];
|
|
|
|
// 复选框
|
|
QWidget *checkWidget = new QWidget;
|
|
QHBoxLayout *checkLayout = new QHBoxLayout(checkWidget);
|
|
checkLayout->setContentsMargins(0, 0, 0, 0);
|
|
checkLayout->setAlignment(Qt::AlignCenter);
|
|
QCheckBox *checkBox = new QCheckBox;
|
|
checkLayout->addWidget(checkBox);
|
|
m_dataTable->setCellWidget(row, 0, checkWidget);
|
|
|
|
// 数据列
|
|
m_dataTable->setItem(row, 1, new QTableWidgetItem(data.id));
|
|
m_dataTable->setItem(row, 2, new QTableWidgetItem(data.type));
|
|
m_dataTable->setItem(row, 3, new QTableWidgetItem(data.serial));
|
|
m_dataTable->setItem(row, 4, new QTableWidgetItem(data.op));
|
|
m_dataTable->setItem(row, 5, new QTableWidgetItem(data.time));
|
|
|
|
// 状态标签
|
|
QTableWidgetItem *statusItem = new QTableWidgetItem(data.status);
|
|
if (data.status == "成功" || data.status == "完成")
|
|
{
|
|
statusItem->setForeground(QColor("#4CAF50"));
|
|
}
|
|
else if (data.status == "异常" || data.status == "警告")
|
|
{
|
|
statusItem->setForeground(QColor("#FF9800"));
|
|
}
|
|
else
|
|
{
|
|
statusItem->setForeground(QColor("#2196F3"));
|
|
}
|
|
m_dataTable->setItem(row, 6, statusItem);
|
|
|
|
m_dataTable->setRowHeight(row, 45);
|
|
}
|
|
|
|
m_recordCountLabel->setText(QString("%1 条").arg(sampleData.size()));
|
|
}
|
|
|
|
void DataManagementWidget::updateStorageInfo()
|
|
{
|
|
// 获取当前存储信息
|
|
QStorageInfo storage = QStorageInfo::root();
|
|
qint64 totalBytes = storage.bytesTotal();
|
|
qint64 usedBytes = totalBytes - storage.bytesAvailable();
|
|
|
|
// 模拟数据占用(实际应该计算数据文件大小)
|
|
qint64 dataUsed = 256 * 1024 * 1024; // 假设256MB
|
|
|
|
m_storageUsedLabel->setText(QString("%1 / %2")
|
|
.arg(formatFileSize(dataUsed))
|
|
.arg(formatFileSize(2LL * 1024 * 1024 * 1024))); // 假设2GB配额
|
|
|
|
int percentage = static_cast<int>((dataUsed * 100) / (2LL * 1024 * 1024 * 1024));
|
|
m_storageProgressBar->setValue(percentage);
|
|
|
|
// 根据使用率改变颜色
|
|
if (percentage > 90)
|
|
{
|
|
m_storageProgressBar->setStyleSheet(R"(
|
|
QProgressBar {
|
|
background-color: #e0e0e0;
|
|
border-radius: 3px;
|
|
}
|
|
QProgressBar::chunk {
|
|
background-color: #f44336;
|
|
border-radius: 3px;
|
|
}
|
|
)");
|
|
}
|
|
else if (percentage > 70)
|
|
{
|
|
m_storageProgressBar->setStyleSheet(R"(
|
|
QProgressBar {
|
|
background-color: #e0e0e0;
|
|
border-radius: 3px;
|
|
}
|
|
QProgressBar::chunk {
|
|
background-color: #FF9800;
|
|
border-radius: 3px;
|
|
}
|
|
)");
|
|
}
|
|
}
|
|
|
|
QString DataManagementWidget::formatFileSize(qint64 bytes)
|
|
{
|
|
const qint64 KB = 1024;
|
|
const qint64 MB = KB * 1024;
|
|
const qint64 GB = MB * 1024;
|
|
|
|
if (bytes >= GB)
|
|
{
|
|
return QString::number(bytes / static_cast<double>(GB), 'f', 2) + " GB";
|
|
}
|
|
else if (bytes >= MB)
|
|
{
|
|
return QString::number(bytes / static_cast<double>(MB), 'f', 2) + " MB";
|
|
}
|
|
else if (bytes >= KB)
|
|
{
|
|
return QString::number(bytes / static_cast<double>(KB), 'f', 2) + " KB";
|
|
}
|
|
else
|
|
{
|
|
return QString::number(bytes) + " B";
|
|
}
|
|
}
|
|
|
|
void DataManagementWidget::onSearchClicked()
|
|
{
|
|
QString keyword = m_searchEdit->text().trimmed();
|
|
QString category = m_categoryCombo->currentText();
|
|
QDate startDate = m_startDateEdit->date();
|
|
QDate endDate = m_endDateEdit->date();
|
|
|
|
// 这里应该实现实际的搜索逻辑
|
|
QString searchInfo = QString("搜索条件:\n类型: %1\n日期范围: %2 至 %3\n关键字: %4")
|
|
.arg(category)
|
|
.arg(startDate.toString("yyyy-MM-dd"))
|
|
.arg(endDate.toString("yyyy-MM-dd"))
|
|
.arg(keyword.isEmpty() ? "(无)" : keyword);
|
|
|
|
OverlayDialog::information(window(), "搜索", searchInfo);
|
|
}
|
|
|
|
void DataManagementWidget::onExportClicked()
|
|
{
|
|
// 统计选中的记录
|
|
int selectedCount = 0;
|
|
for (int row = 0; row < m_dataTable->rowCount(); ++row)
|
|
{
|
|
QWidget *widget = m_dataTable->cellWidget(row, 0);
|
|
if (widget)
|
|
{
|
|
QCheckBox *checkBox = widget->findChild<QCheckBox *>();
|
|
if (checkBox && checkBox->isChecked())
|
|
{
|
|
selectedCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (selectedCount == 0)
|
|
{
|
|
OverlayDialog::warning(window(), "导出", "请先选择要导出的记录");
|
|
return;
|
|
}
|
|
|
|
OverlayDialog::question(window(), "确认导出",
|
|
QString("确定要导出选中的 %1 条记录吗?").arg(selectedCount),
|
|
[this, selectedCount](bool confirmed)
|
|
{
|
|
if (confirmed)
|
|
{
|
|
// 这里应该实现实际的导出逻辑
|
|
OverlayDialog::information(window(), "导出成功",
|
|
QString("已成功导出 %1 条记录到 USB 设备").arg(selectedCount));
|
|
}
|
|
});
|
|
}
|
|
|
|
void DataManagementWidget::onDeleteClicked()
|
|
{
|
|
// 统计选中的记录
|
|
int selectedCount = 0;
|
|
for (int row = 0; row < m_dataTable->rowCount(); ++row)
|
|
{
|
|
QWidget *widget = m_dataTable->cellWidget(row, 0);
|
|
if (widget)
|
|
{
|
|
QCheckBox *checkBox = widget->findChild<QCheckBox *>();
|
|
if (checkBox && checkBox->isChecked())
|
|
{
|
|
selectedCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (selectedCount == 0)
|
|
{
|
|
OverlayDialog::warning(window(), "删除", "请先选择要删除的记录");
|
|
return;
|
|
}
|
|
|
|
OverlayDialog::question(window(), "确认删除",
|
|
QString("确定要删除选中的 %1 条记录吗?\n此操作不可恢复!").arg(selectedCount),
|
|
[this, selectedCount](bool confirmed)
|
|
{
|
|
if (confirmed)
|
|
{
|
|
// 从后往前删除选中的行
|
|
for (int row = m_dataTable->rowCount() - 1; row >= 0; --row)
|
|
{
|
|
QWidget *widget = m_dataTable->cellWidget(row, 0);
|
|
if (widget)
|
|
{
|
|
QCheckBox *checkBox = widget->findChild<QCheckBox *>();
|
|
if (checkBox && checkBox->isChecked())
|
|
{
|
|
m_dataTable->removeRow(row);
|
|
}
|
|
}
|
|
}
|
|
|
|
m_recordCountLabel->setText(QString("%1 条").arg(m_dataTable->rowCount()));
|
|
m_selectAllCheck->setChecked(false);
|
|
|
|
OverlayDialog::information(window(), "删除成功",
|
|
QString("已删除 %1 条记录").arg(selectedCount));
|
|
}
|
|
});
|
|
}
|
|
|
|
void DataManagementWidget::onRefreshClicked()
|
|
{
|
|
// 重新加载数据
|
|
populateSampleData();
|
|
updateStorageInfo();
|
|
m_selectAllCheck->setChecked(false);
|
|
|
|
OverlayDialog::information(window(), "刷新", "数据已刷新");
|
|
}
|
|
|
|
void DataManagementWidget::onSelectAllChanged(int state)
|
|
{
|
|
bool checked = (state == Qt::Checked);
|
|
|
|
for (int row = 0; row < m_dataTable->rowCount(); ++row)
|
|
{
|
|
QWidget *widget = m_dataTable->cellWidget(row, 0);
|
|
if (widget)
|
|
{
|
|
QCheckBox *checkBox = widget->findChild<QCheckBox *>();
|
|
if (checkBox)
|
|
{
|
|
checkBox->setChecked(checked);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void DataManagementWidget::onRecordDoubleClicked(int row, int column)
|
|
{
|
|
Q_UNUSED(column);
|
|
|
|
if (row < 0 || row >= m_dataTable->rowCount())
|
|
return;
|
|
|
|
QString recordId = m_dataTable->item(row, 1)->text();
|
|
QString type = m_dataTable->item(row, 2)->text();
|
|
QString serial = m_dataTable->item(row, 3)->text();
|
|
QString op = m_dataTable->item(row, 4)->text();
|
|
QString time = m_dataTable->item(row, 5)->text();
|
|
QString status = m_dataTable->item(row, 6)->text();
|
|
|
|
QString details = QString(
|
|
"记录详情\n\n"
|
|
"记录ID: %1\n"
|
|
"类型: %2\n"
|
|
"设备序列号: %3\n"
|
|
"操作员: %4\n"
|
|
"时间: %5\n"
|
|
"状态: %6")
|
|
.arg(recordId)
|
|
.arg(type)
|
|
.arg(serial)
|
|
.arg(op)
|
|
.arg(time)
|
|
.arg(status);
|
|
|
|
OverlayDialog::information(window(), "记录详情", details);
|
|
}
|
|
|
|
void DataManagementWidget::onCategoryChanged(int index)
|
|
{
|
|
Q_UNUSED(index);
|
|
// 切换类型时可以触发自动搜索
|
|
// onSearchClicked();
|
|
}
|
|
|
|
void DataManagementWidget::onSyncClicked()
|
|
{
|
|
OverlayDialog::question(window(), "云端同步",
|
|
"确定要将本地数据同步到云端吗?\n这可能需要几分钟时间。",
|
|
[this](bool confirmed)
|
|
{
|
|
if (confirmed)
|
|
{
|
|
// 这里应该实现实际的同步逻辑
|
|
OverlayDialog::information(window(), "同步完成", "数据已成功同步到云端");
|
|
}
|
|
});
|
|
}
|
|
|
|
void DataManagementWidget::onBackupClicked()
|
|
{
|
|
OverlayDialog::question(window(), "数据备份",
|
|
"确定要备份所有数据吗?\n备份文件将保存到 USB 设备。",
|
|
[this](bool confirmed)
|
|
{
|
|
if (confirmed)
|
|
{
|
|
// 这里应该实现实际的备份逻辑
|
|
OverlayDialog::information(window(), "备份完成",
|
|
"数据已成功备份\n文件: backup_2024-01-15.dat");
|
|
}
|
|
});
|
|
}
|
|
|
|
void DataManagementWidget::onRestoreClicked()
|
|
{
|
|
OverlayDialog::question(window(), "数据恢复",
|
|
"确定要从备份文件恢复数据吗?\n当前数据将被覆盖!",
|
|
[this](bool confirmed)
|
|
{
|
|
if (confirmed)
|
|
{
|
|
// 这里应该实现实际的恢复逻辑
|
|
OverlayDialog::information(window(), "恢复完成", "数据已成功从备份恢复");
|
|
populateSampleData();
|
|
updateStorageInfo();
|
|
}
|
|
});
|
|
}
|
|
|
|
void DataManagementWidget::onClearHistoryClicked()
|
|
{
|
|
OverlayDialog::question(window(), "清空历史",
|
|
"确定要清空所有历史数据吗?\n此操作不可恢复!",
|
|
[this](bool confirmed)
|
|
{
|
|
if (confirmed)
|
|
{
|
|
m_dataTable->setRowCount(0);
|
|
m_recordCountLabel->setText("0 条");
|
|
m_selectAllCheck->setChecked(false);
|
|
|
|
OverlayDialog::information(window(), "清空完成", "所有历史数据已清空");
|
|
updateStorageInfo();
|
|
}
|
|
});
|
|
}
|
|
|
|
void DataManagementWidget::setupDateEditStyle(QDateEdit *dateEdit)
|
|
{
|
|
dateEdit->setStyleSheet(R"(
|
|
QDateEdit {
|
|
background-color: white;
|
|
border: 1px solid #ddd;
|
|
border-radius: 6px;
|
|
padding: 8px 12px;
|
|
font-size: 14px;
|
|
min-height: 36px;
|
|
}
|
|
QDateEdit:hover {
|
|
border-color: #2196F3;
|
|
}
|
|
QDateEdit::drop-down {
|
|
subcontrol-origin: padding;
|
|
subcontrol-position: center right;
|
|
width: 30px;
|
|
border: none;
|
|
}
|
|
QDateEdit::down-arrow {
|
|
image: url(:/icons/arrow_down.svg);
|
|
width: 14px;
|
|
height: 14px;
|
|
}
|
|
)");
|
|
|
|
// 获取并样式化日历弹出窗口
|
|
QCalendarWidget *calendar = dateEdit->calendarWidget();
|
|
if (calendar)
|
|
{
|
|
calendar->setStyleSheet(R"(
|
|
QCalendarWidget {
|
|
background-color: white;
|
|
border: 1px solid #ccc;
|
|
border-radius: 8px;
|
|
}
|
|
QCalendarWidget QWidget#qt_calendar_navigationbar {
|
|
background-color: #f5f5f5;
|
|
border-top-left-radius: 8px;
|
|
border-top-right-radius: 8px;
|
|
padding: 8px;
|
|
}
|
|
QCalendarWidget QToolButton {
|
|
color: #333;
|
|
background-color: transparent;
|
|
border: none;
|
|
border-radius: 4px;
|
|
padding: 8px 12px;
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
min-width: 40px;
|
|
}
|
|
QCalendarWidget QToolButton:hover {
|
|
background-color: #e3f2fd;
|
|
}
|
|
QCalendarWidget QToolButton::menu-indicator {
|
|
image: none;
|
|
width: 0px;
|
|
}
|
|
QCalendarWidget QSpinBox {
|
|
background-color: white;
|
|
border: 1px solid #ddd;
|
|
border-radius: 4px;
|
|
padding: 4px 8px;
|
|
font-size: 14px;
|
|
min-width: 60px;
|
|
}
|
|
QCalendarWidget QMenu {
|
|
background-color: white;
|
|
border: 1px solid #ccc;
|
|
border-radius: 4px;
|
|
}
|
|
QCalendarWidget QMenu::item {
|
|
padding: 10px 20px;
|
|
font-size: 14px;
|
|
}
|
|
QCalendarWidget QMenu::item:selected {
|
|
background-color: #2196F3;
|
|
color: white;
|
|
}
|
|
QCalendarWidget QAbstractItemView {
|
|
background-color: white;
|
|
selection-background-color: #2196F3;
|
|
selection-color: white;
|
|
font-size: 14px;
|
|
outline: none;
|
|
}
|
|
QCalendarWidget QAbstractItemView:enabled {
|
|
color: #333;
|
|
}
|
|
QCalendarWidget QAbstractItemView:disabled {
|
|
color: #bbb;
|
|
}
|
|
)");
|
|
|
|
// 设置日历格式让日期更大更明显
|
|
QTextCharFormat headerFormat;
|
|
headerFormat.setFontPointSize(12);
|
|
headerFormat.setForeground(QColor("#666"));
|
|
calendar->setHeaderTextFormat(headerFormat);
|
|
|
|
QTextCharFormat dayFormat;
|
|
dayFormat.setFontPointSize(13);
|
|
calendar->setWeekdayTextFormat(Qt::Monday, dayFormat);
|
|
calendar->setWeekdayTextFormat(Qt::Tuesday, dayFormat);
|
|
calendar->setWeekdayTextFormat(Qt::Wednesday, dayFormat);
|
|
calendar->setWeekdayTextFormat(Qt::Thursday, dayFormat);
|
|
calendar->setWeekdayTextFormat(Qt::Friday, dayFormat);
|
|
|
|
QTextCharFormat weekendFormat;
|
|
weekendFormat.setFontPointSize(13);
|
|
weekendFormat.setForeground(QColor("#e53935"));
|
|
calendar->setWeekdayTextFormat(Qt::Saturday, weekendFormat);
|
|
calendar->setWeekdayTextFormat(Qt::Sunday, weekendFormat);
|
|
|
|
calendar->setVerticalHeaderFormat(QCalendarWidget::NoVerticalHeader);
|
|
calendar->setGridVisible(false);
|
|
calendar->setMinimumSize(320, 280);
|
|
}
|
|
}
|