Older/WebApplication/VisitorRecordTableModel.cpp
luocai 6803f84677
Some checks failed
Deploy / Build (push) Failing after 2m55s
fix model.
2024-11-29 20:01:10 +08:00

170 lines
6.6 KiB
C++

#include "VisitorRecordTableModel.h"
#include "BoostLog.h"
#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();
}
}
int VisitorRecordTableModel::columnCount(const Wt::WModelIndex &parent) const {
return 5;
}
int VisitorRecordTableModel::rowCount(const Wt::WModelIndex &parent) const {
return m_records.size();
}
Wt::WFlags<Wt::HeaderFlag> VisitorRecordTableModel::headerFlags(int section, Wt::Orientation orientation) const {
if (section == 0 && orientation == Wt::Orientation::Horizontal) {
return Wt::HeaderFlag::UserCheckable;
} else {
return Wt::None;
}
}
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{};
}
} else {
return Wt::WAbstractTableModel::headerData(section, orientation, role);
}
}
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));
return true;
} else {
return Wt::WAbstractTableModel::setHeaderData(section, orientation, value, role);
}
}
void VisitorRecordTableModel::sort(int column, Wt::SortOrder order) {
if (column == 2) {
layoutAboutToBeChanged().emit();
std::sort(m_records.begin(), m_records.end(), [order](const VisitorRecord &lfh, const VisitorRecord &rfh) {
if (order == Wt::SortOrder::Ascending) {
return lfh.time < rfh.time;
} else {
return lfh.time > rfh.time;
}
});
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;
}
}
Wt::cpp17::any VisitorRecordTableModel::data(const Wt::WModelIndex &index, Wt::ItemDataRole role) const {
// 选择框
int row = index.row();
auto &record = std::get<0>(m_records.at(row));
if ((role == Wt::ItemDataRole::Checked || role == Wt::ItemDataRole::Edit) &&
index.column() == 0) { // Assuming first column for checkbox
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{};
}
}
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)) {
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;
} else {
return Wt::WAbstractTableModel::setData(index, value, role);
}
}
std::vector<VisitorRecord> VisitorRecordTableModel::selected() const {
std::vector<VisitorRecord> ret;
for (int i = 0; i < m_records.size(); i++) {
if (std::get<1>(m_records.at(i))) {
ret.push_back(std::get<0>(m_records.at(i)));
}
}
return ret;
}
void VisitorRecordTableModel::removeSelected() {
Wt::Dbo::Transaction transaction(m_session);
for (auto iterator = m_records.cbegin(); iterator != m_records.cend();) {
auto selected = std::get<1>(*iterator);
auto &r = std::get<0>(*iterator);
if (selected) {
Wt::Dbo::ptr<VisitorRecord> item = m_session.find<VisitorRecord>().where("id = ?").bind(r.id);
item.remove();
iterator = m_records.erase(iterator);
} else {
++iterator;
}
}
}