170 lines
6.6 KiB
C++
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;
|
|
}
|
|
}
|
|
} |