add model.
All checks were successful
Deploy / Build (push) Successful in 6m4s

This commit is contained in:
luocai 2024-11-28 19:34:24 +08:00
parent 7b0f0bba41
commit 5f3bf1067d
9 changed files with 108 additions and 57 deletions

View File

@ -50,7 +50,7 @@ void SystemUsage::start() {
LOG(info) << "network speed: " << std::fixed << std::setprecision(2) << speed << "GB/h"; LOG(info) << "network speed: " << std::fixed << std::setprecision(2) << speed << "GB/h";
static system_clock::time_point lastNotify; static system_clock::time_point lastNotify;
auto now = system_clock::now(); auto now = system_clock::now();
if ((speed >= 1.f) && (duration_cast<minutes>(now - lastNotify) > minutes(10))) { // 一个小时1GB的流量 if ((speed >= 1.5f) && (duration_cast<minutes>(now - lastNotify) > minutes(10))) { // 一个小时1.5GB的流量
std::ostringstream oss; std::ostringstream oss;
oss << "当前服务器流量存在异常, " << DateTime::toString(front.time) << " - " oss << "当前服务器流量存在异常, " << DateTime::toString(front.time) << " - "
<< DateTime::toString(back.time) << ": " << std::endl; << DateTime::toString(back.time) << ": " << std::endl;

View File

@ -3,7 +3,7 @@
#include <filesystem> #include <filesystem>
#include "Database/Session.h" #include "Database/Session.h"
constexpr auto databasePath = "build/database.sqlite"; constexpr auto databasePath = "build/unit_test_database.sqlite";
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
if (std::filesystem::exists(databasePath)) { if (std::filesystem::exists(databasePath)) {

View File

@ -4,6 +4,7 @@ add_library(WebApplication
WebApplication.h WebApplication.cpp WebApplication.h WebApplication.cpp
LoginPage.h LoginPage.cpp LoginPage.h LoginPage.cpp
VisitorRecordsPage.h VisitorRecordsPage.cpp VisitorRecordsPage.h VisitorRecordsPage.cpp
VisitorRecordTableModel.h VisitorRecordTableModel.cpp
Hello.h Hello.cpp Hello.h Hello.cpp
Restful.h Restful.cpp Restful.h Restful.cpp
Dialog.h Dialog.cpp Dialog.h Dialog.cpp

View File

@ -3,6 +3,7 @@
#include "Database/Session.h" #include "Database/Session.h"
#include "Dialog.h" #include "Dialog.h"
#include "LoginPage.h" #include "LoginPage.h"
#include "VisitorRecordsPage.h"
#include "WebApplication.h" #include "WebApplication.h"
#include <Wt/Auth/Identity.h> #include <Wt/Auth/Identity.h>
#include <Wt/WBootstrap2Theme.h> #include <Wt/WBootstrap2Theme.h>
@ -100,5 +101,8 @@ void Hello::handlePathChange(const std::string &path) {
m_root->clear(); m_root->clear();
m_root->setStyleClass("WtCenterContainer"); m_root->setStyleClass("WtCenterContainer");
m_root->addNew<LoginWidget>(m_session->users(), m_session->login()); m_root->addNew<LoginWidget>(m_session->users(), m_session->login());
} else if (path.starts_with("/wt/visitor/analysis")) {
m_root->clear();
m_root->addNew<VisitorRecordsPage>(*m_session);
} }
} }

View File

@ -0,0 +1,19 @@
#include "VisitorRecordTableModel.h"
#include "BoostLog.h"
int VisitorRecordTableModel::columnCount(const Wt::WModelIndex &parent) const {
return 5;
}
int VisitorRecordTableModel::rowCount(const Wt::WModelIndex &parent) const {
return 50;
}
Wt::cpp17::any VisitorRecordTableModel::data(const Wt::WModelIndex &index, Wt::ItemDataRole role) const {
LOG(info) << "VisitorRecordTableModel: " << role.value();
if (role == Wt::ItemDataRole::Checked && index.column() == 0) { // Assuming first column for checkbox
return true;
} else {
return Wt::cpp17::any{};
}
}

View File

@ -0,0 +1,12 @@
#ifndef __VISITORRECORDTABLEMODEL_H__
#define __VISITORRECORDTABLEMODEL_H__
#include <Wt/WAbstractTableModel.h>
class VisitorRecordTableModel : public Wt::WAbstractTableModel {
public:
Wt::cpp17::any data(const Wt::WModelIndex &index, Wt::ItemDataRole role = Wt::ItemDataRole::Display) const final;
int columnCount(const Wt::WModelIndex &parent = Wt::WModelIndex()) const final;
int rowCount(const Wt::WModelIndex &parent = Wt::WModelIndex()) const final;
};
#endif // __VISITORRECORDTABLEMODEL_H__

View File

@ -1 +1,61 @@
#include "VisitorRecordsPage.h" #include "VisitorRecordsPage.h"
#include "BoostLog.h"
#include "Database/Session.h"
#include <Wt/Dbo/QueryModel.h>
#include <Wt/WItemDelegate.h>
#include <Wt/WLabel.h>
#include <Wt/WTableView.h>
#include "VisitorRecordTableModel.h"
class CheckBoxDelegate : public Wt::WAbstractItemDelegate {
public:
CheckBoxDelegate() : Wt::WAbstractItemDelegate() {
}
std::unique_ptr<Wt::WWidget> update(Wt::WWidget *widget, const Wt::WModelIndex &index,
Wt::WFlags<Wt::ViewItemRenderFlag> flags) final {
auto checkBox = dynamic_cast<Wt::WCheckBox *>(widget);
if (!checkBox) {
checkBox = new Wt::WCheckBox();
}
LOG(info) << Wt::asString(index.data());
// checkBox->setChecked(index.data().toBool());
checkBox->setEnabled(true);
return std::unique_ptr<Wt::WWidget>(checkBox);
}
};
VisitorRecordsPage::VisitorRecordsPage(Session &session) {
addNew<Wt::WLabel>("访客数据统计");
auto view = addNew<Wt::WTableView>();
view->setColumnWidth(0, Wt::WLength::Auto);
view->setColumnWidth(1, Wt::WLength::Auto);
view->setHeaderHeight(30); // 设置表头的高度
view->setWidth(Wt::WLength("99%"));
view->setColumnResizeEnabled(true);
view->setAlternatingRowColors(true);
view->setRowHeight(50);
// view->setSelectable(true);
view->setSelectionMode(Wt::SelectionMode::Extended);
// view->setEditTriggers(Wt::EditTrigger::None);
// view->setItemDelegateForColumn(0, std::make_shared<CheckBoxDelegate>());
// view->setHeaderItemDelegate( std::make_shared<CheckBoxDelegate>());
// auto model = std::make_shared<Wt::Dbo::QueryModel<Wt::Dbo::ptr<VisitorRecord>>>();
// model->setQuery(session.find<VisitorRecord>());
// model->addColumn("id", "ID",Wt::ItemFlag::UserCheckable);
// model->addColumn("url", "URL");
// model->addColumn("time", "Time");
// model->addColumn("user_agent", "User Agent");
auto model = std::make_shared<VisitorRecordTableModel>();
view->setModel(model);
/*
* Configure column widths and matching table width
*/
const int WIDTH = 240;
for (int i = 0; i < view->model()->columnCount(); ++i) view->setColumnWidth(i, 120);
}

View File

@ -1,9 +1,15 @@
#ifndef __VISITORRECORDSPAGE_H__ #ifndef __VISITORRECORDSPAGE_H__
#define __VISITORRECORDSPAGE_H__ #define __VISITORRECORDSPAGE_H__
class VisitorRecordsPage { #include <Wt/WContainerWidget.h>
class Session;
// https://infima.dev/
class VisitorRecordsPage : public Wt::WContainerWidget {
public:
VisitorRecordsPage(Session &session);
}; };
#endif // __VISITORRECORDSPAGE_H__ #endif // __VISITORRECORDSPAGE_H__

View File

@ -134,57 +134,6 @@
<server-push-timeout>50</server-push-timeout> <server-push-timeout>50</server-push-timeout>
</session-management> </session-management>
<!-- Settings that apply only to the FastCGI connector.
To configure the wthttp connector, use command line options, or
configure default options in /etc/wt/wthttpd
-->
<connector-fcgi>
<!-- Valgrind path
If debugging is enabled and this path is not empty, then valgrind
will be started for every shared process, or for every session
which has ?debug appended to the command line.
The variable is slighly misnamed. Not only a path can be set,
but also options, like for example:
/usr/bin/valgrind - -leak-check=full
-->
<valgrind-path></valgrind-path>
<!-- Run directory
Path used by Wt to do session management.
-->
<run-directory>/opt/Libraries/wt-4.11.1/var/run/wt</run-directory>
</connector-fcgi>
<!-- Settings that apply only to the MS IIS ISAPI connector.
To configure the wthttp connector, use command line options, or
configure default options in /etc/wt/wthttpd
-->
<connector-isapi>
<!-- Maximum Request Size spooled in memory (KiB)
Normally, Wt keeps incoming requests (POST data) in memory.
However, malicious users could send a big POST and as such
use up all memory of your HTTP server. With this parameter,
you tune how big a request can be before Wt spools it in a
file before processing it. Legitimate big POST messages may
occur when users are expected to upload files.
See also max-request-size.
The default value is 128K, which is more than enough for
any interactive Wt event.
-->
<max-memory-request-size>128</max-memory-request-size>
</connector-isapi>
<!-- Javascript debug options <!-- Javascript debug options
Values: Values: