Older/WebApplication/VisitorRecordTableModel.cpp

189 lines
7.3 KiB
C++
Raw Normal View History

2024-11-28 19:34:24 +08:00
#include "VisitorRecordTableModel.h"
#include "BoostLog.h"
2024-11-29 20:01:10 +08:00
#include "Database/Session.h"
#include "DateTime.h"
VisitorRecordTableModel::VisitorRecordTableModel(Session &session) : m_session(session) {
Wt::Dbo::Transaction transaction(session);
Wt::Dbo::collection<Wt::Dbo::ptr<VisitorRecord>> records = session.find<VisitorRecord>();
int index = 1;
std::unordered_map<std::string, std::string> users;
for (auto &record : records) {
if (record->url.size() <= 1) continue;
if (!users.contains(record->visitorUuid)) {
users.insert({record->visitorUuid, std::format("匿名用户{}", index++)});
}
m_records.push_back({*record, false});
std::get<0>(m_records.back()).visitorUuid = users.at(record->visitorUuid);
std::get<0>(m_records.back()).id = record.id();
}
}
2024-11-28 19:34:24 +08:00
int VisitorRecordTableModel::columnCount(const Wt::WModelIndex &parent) const {
return 5;
}
int VisitorRecordTableModel::rowCount(const Wt::WModelIndex &parent) const {
2024-11-29 20:01:10 +08:00
return m_records.size();
2024-11-28 19:34:24 +08:00
}
2024-11-29 20:01:10 +08:00
Wt::WFlags<Wt::HeaderFlag> VisitorRecordTableModel::headerFlags(int section, Wt::Orientation orientation) const {
if (section == 0 && orientation == Wt::Orientation::Horizontal) {
return Wt::HeaderFlag::UserCheckable;
2024-11-28 23:39:15 +08:00
} else {
2024-11-29 20:01:10 +08:00
return Wt::None;
2024-11-28 23:39:15 +08:00
}
}
2024-11-29 20:01:10 +08:00
Wt::cpp17::any VisitorRecordTableModel::headerData(int section, Wt::Orientation orientation, Wt::ItemDataRole role) const {
if (orientation == Wt::Orientation::Horizontal) {
if (role == Wt::ItemDataRole::Level) return Wt::WAbstractTableModel::headerData(section, orientation, role);
if ((role == Wt::ItemDataRole::Checked || role == Wt::ItemDataRole::Edit) &&
section == 0) { // Assuming first column for checkbox
return m_selectAll;
} else if ((section == 1) && (role == Wt::ItemDataRole::Display)) {
return "文章";
} else if ((section == 2) && (role == Wt::ItemDataRole::Display)) {
return "时间";
} else if ((section == 3) && (role == Wt::ItemDataRole::Display)) {
return "浏览器";
} else if ((section == 4) && (role == Wt::ItemDataRole::Display)) {
return "用户";
} else {
return Wt::cpp17::any{};
}
2024-11-28 23:39:15 +08:00
} else {
2024-11-29 20:01:10 +08:00
return Wt::WAbstractTableModel::headerData(section, orientation, role);
2024-11-28 23:39:15 +08:00
}
}
2024-11-29 20:01:10 +08:00
bool VisitorRecordTableModel::setHeaderData(int section, Wt::Orientation orientation, const Wt::cpp17::any &value,
Wt::ItemDataRole role) {
if ((section == 0) && (role == Wt::ItemDataRole::Checked)) {
m_selectAll = Wt::cpp17::any_cast<bool>(value);
for (int i = 0; i < m_records.size(); i++) {
std::get<1>(m_records[i]) = m_selectAll;
}
dataChanged().emit(index(0, 0), index(m_records.size(), 0));
2024-11-28 23:39:15 +08:00
return true;
} else {
2024-11-29 20:01:10 +08:00
return Wt::WAbstractTableModel::setHeaderData(section, orientation, value, role);
}
}
void VisitorRecordTableModel::sort(int column, Wt::SortOrder order) {
if (column == 2) {
layoutAboutToBeChanged().emit();
2024-12-01 15:10:25 +08:00
std::sort(m_records.begin(), m_records.end(), [order](const Item &lfh, const Item &rfh) {
2024-11-29 20:01:10 +08:00
if (order == Wt::SortOrder::Ascending) {
2024-12-01 15:10:25 +08:00
return std::get<0>(lfh).time < std::get<0>(rfh).time;
2024-11-29 20:01:10 +08:00
} else {
2024-12-01 15:10:25 +08:00
return std::get<0>(lfh).time > std::get<0>(rfh).time;
2024-11-29 20:01:10 +08:00
}
});
layoutChanged().emit();
}
}
Wt::WFlags<Wt::ItemFlag> VisitorRecordTableModel::flags(const Wt::WModelIndex &index) const {
if (index.column() == 0) {
return Wt::ItemFlag::UserCheckable | Wt::ItemFlag::Selectable;
} else if (index.column() == 1) {
return Wt::ItemFlag::XHTMLText | Wt::ItemFlag::Selectable;
} else {
return Wt::ItemFlag::Selectable;
2024-11-28 23:39:15 +08:00
}
}
2024-11-28 19:34:24 +08:00
Wt::cpp17::any VisitorRecordTableModel::data(const Wt::WModelIndex &index, Wt::ItemDataRole role) const {
2024-11-29 20:01:10 +08:00
// 选择框
int row = index.row();
auto &record = std::get<0>(m_records.at(row));
2024-11-28 23:39:15 +08:00
if ((role == Wt::ItemDataRole::Checked || role == Wt::ItemDataRole::Edit) &&
index.column() == 0) { // Assuming first column for checkbox
2024-11-29 20:01:10 +08:00
return std::get<1>(m_records.at(row));
} else if ((index.column() == 1) && (role == Wt::ItemDataRole::Display)) {
auto pos = record.url.rfind("/");
auto name = record.url;
if (pos != std::string::npos && pos < (name.size() - 1)) {
name = name.substr(pos + 1);
}
return std::format("<a href=\"{}\">{}</a>", record.url, name);
} else if ((index.column() == 2) && (role == Wt::ItemDataRole::Display)) {
return DateTime::toString(record.time);
} else if ((index.column() == 3) && (role == Wt::ItemDataRole::Display)) {
return record.userAgent;
} else if ((index.column() == 4) && (role == Wt::ItemDataRole::Display)) {
return record.visitorUuid;
} else {
return Wt::cpp17::any{};
}
}
2024-11-28 23:39:15 +08:00
2024-11-29 20:01:10 +08:00
bool VisitorRecordTableModel::setData(const Wt::WModelIndex &index, const Wt::cpp17::any &value, Wt::ItemDataRole role) {
int row = index.row();
if ((index.column() == 0) && (role == Wt::ItemDataRole::Checked)) {
2024-11-28 23:39:15 +08:00
2024-11-29 20:01:10 +08:00
std::get<1>(m_records[row]) = Wt::cpp17::any_cast<bool>(value);
auto iterator = std::find_if_not(m_records.begin(), m_records.end(), [](const Item &item) { return std::get<1>(item); });
if (iterator == m_records.end()) {
if (!m_selectAll) {
m_selectAll = true;
headerDataChanged().emit(Wt::Orientation::Horizontal, 0, 0);
}
} else {
if (m_selectAll) {
m_selectAll = false;
headerDataChanged().emit(Wt::Orientation::Horizontal, 0, 0);
}
}
return true;
2024-11-28 19:34:24 +08:00
} else {
2024-11-29 20:01:10 +08:00
return Wt::WAbstractTableModel::setData(index, value, role);
2024-11-28 19:34:24 +08:00
}
}
2024-11-29 20:01:10 +08:00
2024-12-01 15:10:25 +08:00
Wt::WModelIndexSet VisitorRecordTableModel::selectedIndexes() const {
Wt::WModelIndexSet ret;
2024-11-29 20:01:10 +08:00
for (int i = 0; i < m_records.size(); i++) {
if (std::get<1>(m_records.at(i))) {
2024-12-01 15:10:25 +08:00
ret.insert(index(i, 0));
2024-11-29 20:01:10 +08:00
}
}
return ret;
}
2024-12-01 15:10:25 +08:00
bool VisitorRecordTableModel::removeSelectedRows(const Wt::WModelIndexSet &indexes) {
2024-11-29 20:01:10 +08:00
Wt::Dbo::Transaction transaction(m_session);
2024-12-01 15:10:25 +08:00
layoutAboutToBeChanged().emit();
std::vector<int> ids;
for (auto &index : indexes) {
auto &r = std::get<0>(m_records.at(index.row()));
ids.push_back(r.id);
Wt::Dbo::ptr<VisitorRecord> item = m_session.find<VisitorRecord>().where("id = ?").bind(r.id);
item.remove();
}
for (auto id : ids) {
std::erase_if(m_records, [id](const Item &item) { return std::get<0>(item).id == id; });
2024-11-29 20:01:10 +08:00
}
2024-12-01 15:10:25 +08:00
layoutChanged().emit();
return true;
}
bool VisitorRecordTableModel::removeRows(int row, int count, const Wt::WModelIndex &parent) {
if ((row + count) > m_records.size()) {
return false;
}
Wt::Dbo::Transaction transaction(m_session);
beginRemoveRows(parent, row, row + count - 1);
for (int i = row; i < (row + count); ++i) {
auto &r = std::get<0>(m_records.at(i));
Wt::Dbo::ptr<VisitorRecord> item = m_session.find<VisitorRecord>().where("id = ?").bind(r.id);
item.remove();
}
m_records.erase(m_records.cbegin() + row, m_records.cbegin() + row + count);
endRemoveRows();
return true;
}