diff --git a/Path.ps1 b/Path.ps1 new file mode 100644 index 0000000..1f4bcae --- /dev/null +++ b/Path.ps1 @@ -0,0 +1 @@ +$env:Path += ";D:\PortableApp\PortableGit\bin" \ No newline at end of file diff --git a/ScreenTime.pro b/ScreenTime.pro new file mode 100644 index 0000000..e8d285d --- /dev/null +++ b/ScreenTime.pro @@ -0,0 +1,44 @@ +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + main.cpp \ + mainwindow.cpp \ + viewhistorywindow.cpp + +HEADERS += \ + mainwindow.h \ + viewhistorywindow.h + +FORMS += \ + mainwindow.ui \ + viewhistorywindow.ui + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +LIBS += -luser32 -lpsapi + +RESOURCES += \ + ScreenTime.qrc + +RC_FILE = logo.rc + +DISTFILES += \ + logo.rc diff --git a/ScreenTime.pro.user b/ScreenTime.pro.user new file mode 100644 index 0000000..4f9c8c0 --- /dev/null +++ b/ScreenTime.pro.user @@ -0,0 +1,319 @@ + + + + + + EnvironmentId + {8803840d-7a43-458d-ae2c-47aac1bc166c} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + -fno-delayed-template-parsing + + true + + + + ProjectExplorer.Project.Target.0 + + Desktop Qt 5.14.2 MinGW 64-bit + Desktop Qt 5.14.2 MinGW 64-bit + qt.qt5.5142.win64_mingw73_kit + 1 + 0 + 0 + + D:/MyCode/Qt/build-ScreenTime-Desktop_Qt_5_14_2_MinGW_64_bit-Debug + + + true + QtProjectManager.QMakeBuildStep + true + + false + false + false + + + true + Qt4ProjectManager.MakeStep + + false + + + false + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + + true + clean + + false + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + + + D:/MyCode/Qt/build-ScreenTime-Desktop_Qt_5_14_2_MinGW_64_bit-Release + + + true + QtProjectManager.QMakeBuildStep + false + + false + false + true + + + true + Qt4ProjectManager.MakeStep + + false + + + false + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + + true + clean + + false + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + + + D:/MyCode/Qt/build-ScreenTime-Desktop_Qt_5_14_2_MinGW_64_bit-Profile + + + true + QtProjectManager.QMakeBuildStep + true + + false + true + true + + + true + Qt4ProjectManager.MakeStep + + false + + + false + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + + true + clean + + false + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Profile + Qt4ProjectManager.Qt4BuildConfiguration + 0 + + 3 + + + 0 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + dwarf + + cpu-cycles + + + 250 + + -e + cpu-cycles + --call-graph + dwarf,4096 + -F + 250 + + -F + true + 4096 + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + kcachegrind + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + Qt4ProjectManager.Qt4RunConfiguration:D:/MyCode/Qt/ScreenTime/ScreenTime.pro + D:/MyCode/Qt/ScreenTime/ScreenTime.pro + + false + + false + true + true + false + false + true + + D:/MyCode/Qt/build-ScreenTime-Desktop_Qt_5_14_2_MinGW_64_bit-Release + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + diff --git a/ScreenTime.qrc b/ScreenTime.qrc new file mode 100644 index 0000000..42c9a8f --- /dev/null +++ b/ScreenTime.qrc @@ -0,0 +1,6 @@ + + + img/32.ico + img/unknowfile.png + + diff --git a/img/32.ico b/img/32.ico new file mode 100644 index 0000000..b1da4d4 Binary files /dev/null and b/img/32.ico differ diff --git a/img/unknowfile.png b/img/unknowfile.png new file mode 100644 index 0000000..8bd4fb2 Binary files /dev/null and b/img/unknowfile.png differ diff --git a/logo.rc b/logo.rc new file mode 100644 index 0000000..0badc9b --- /dev/null +++ b/logo.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE ".\\img\\32.ico" diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..d826250 --- /dev/null +++ b/main.cpp @@ -0,0 +1,10 @@ +#include "mainwindow.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + return a.exec(); +} diff --git a/mainwindow.cpp b/mainwindow.cpp new file mode 100644 index 0000000..e00f5f2 --- /dev/null +++ b/mainwindow.cpp @@ -0,0 +1,127 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::MainWindow) +{ + ui->setupUi(this); + today = QDate::currentDate(); + //相对路径转绝对路径 + QString exeDirPath = QCoreApplication::applicationDirPath().replace('/', '\\'); + if (settings.ExeIconFolderPath.startsWith(".\\")) + { + absluteExeIconFolderPath = exeDirPath + settings.ExeIconFolderPath.mid(1); + } + if (settings.JsonDataFolderPath.startsWith(".\\")) + { + absluteJsonDataFolderPath = exeDirPath + settings.JsonDataFolderPath.mid(1); + } + absluteJsonDataFilePath = QString("%1\\%2.json").arg(absluteJsonDataFolderPath, today.toString("yyyy-MM-dd")); + //创建存数据的文件夹 + QDir dir(exeDirPath+"\\user_data"); + if (!dir.exists()) + dir.mkdir(exeDirPath+"\\user_data"); + QDir dir1(absluteExeIconFolderPath); + if (!dir1.exists()) + dir1.mkdir(absluteExeIconFolderPath); + QDir dir2(absluteJsonDataFolderPath); + if (!dir2.exists()) + dir2.mkdir(absluteJsonDataFolderPath); + //是否有今天的数据,如果就就加载 + QFile file(absluteJsonDataFilePath); + if (file.exists()) + { + QFile file(absluteJsonDataFilePath); + file.open((QIODevice::ReadOnly)); + QByteArray jsonData = file.readAll(); + file.close(); + QJsonDocument jsonDoc(QJsonDocument::fromJson(jsonData)); + QJsonArray jsonArray = jsonDoc.array(); + for (const QJsonValue& value : jsonArray) + { + QJsonObject jsonObject = value.toObject(); + ExeItem* exeItem = new ExeItem(); + exeItem->Name = jsonObject["Name"].toString(); + exeItem->ExePath = jsonObject["ExePath"].toString(); + exeItem->IconPath = jsonObject["IconPath"].toString(); + exeItem->Seconds = jsonObject["Seconds"].toInt(); + totalSeconds += exeItem->Seconds; + exeItemList.append(exeItem); + } + } + //托盘 + InitializeTray(); + //Timer绑定 + connect(&getTopWindowTimer, &QTimer::timeout, this, &MainWindow::GetTopWindow_slot); + getTopWindowTimer.setInterval(settings.GetTopWindowInterval_s * 1000); + getTopWindowTimer.setTimerType(Qt::PreciseTimer); + getTopWindowTimer.start(); + connect(&refreshListWidgetTimer, &QTimer::timeout, this, &MainWindow::RefreshListWidget_slot); + refreshListWidgetTimer.setInterval(settings.RefreshListWidgetIntervalList_s * 1000); + //检测是否开机自启动 + QSettings settings("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat); + if (settings.contains("ScreenTime")) + ui->actionSelfStarting->setChecked(true); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + + +void MainWindow::on_actionOpenAppDir_triggered() +{ + const wchar_t* wPath = reinterpret_cast(QString("/select,%1").arg(QCoreApplication::applicationFilePath().replace("/", "\\")).utf16()); + ShellExecuteW(NULL, L"open", L"explorer.exe", wPath, NULL, SW_SHOW); +} + + +void MainWindow::on_actionExitApp_triggered(){ExitApp();} + +void MainWindow::on_activatedSysTrayIcon(QSystemTrayIcon::ActivationReason reason) +{ + switch (reason) + { + case QSystemTrayIcon::Trigger: + if (this->isVisible()) + { + this->HideWindow(); + } + else + { + this->ShowWindow(); + } + default: + break; + } +} + +void MainWindow::on_actionSelfStarting_triggered() +{ + if (!ui->actionSelfStarting->isChecked()) //点击后的状态所以取反 + { + //删除注册表 + QSettings settings("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat); + settings.remove("ScreenTime"); + } + else + { + //添加注册表 + QSettings settings("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat); + settings.setValue("ScreenTime", '"' + QCoreApplication::applicationFilePath().replace('/', '\\') + '"'); + } +} + +void MainWindow::on_actionViewHistory_triggered() +{ + QString jsonFilePath = QFileDialog::getOpenFileName(nullptr, "选择 JSON 文件",absluteJsonDataFolderPath,"JSON Files (*.json);;All Files (*)"); + if (jsonFilePath.isEmpty()) + return; + else + { + ViewHistoryWindow* w = new ViewHistoryWindow(jsonFilePath); + w->show(); + } +} diff --git a/mainwindow.h b/mainwindow.h new file mode 100644 index 0000000..3f3a4d0 --- /dev/null +++ b/mainwindow.h @@ -0,0 +1,306 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + + +#include +#include "ui_mainwindow.h" //才能使用ui->.... +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "viewhistorywindow.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE +namespace Ui { class MainWindow; } +QT_END_NAMESPACE + +class Settings +{ +public: + QString ExeIconFolderPath = ".\\user_data\\exe_icon"; + QString JsonDataFolderPath = ".\\user_data\\data"; + int GetTopWindowInterval_s = 1; + int RefreshListWidgetIntervalList_s = 3; +// void DefaultSetting(); +}; +static QString SecondsToQString(int seconds)//将秒数转化为小时分钟秒格式 +{ + QString time = ""; + int sec = seconds % 60; + seconds /= 60; + int min = seconds % 60; + seconds /= 60; + int hour = seconds; + if (hour != 0) + time = QString::number(hour) + "小时"; + if (min != 0) + time += QString::number(min) + "分钟"; + if (sec != 0) + time += QString::number(sec) + "秒"; + return time; +} +class ExeItemWidget : public QListWidgetItem +{ +public: + QWidget* Widget; + ExeItemWidget(const QString& name, const QString& exePath, const QString& iconPath, QString timeText, int percentage) : QListWidgetItem() + { + Widget = new QWidget(); + nameLabel = new QLabel(name, Widget); + nameLabel->setToolTip(exePath); + iconLabel = new QLabel(Widget); + QPixmap pixmap(iconPath); +// if (pixmap.isNull()) +// { + QPixmap pixmap2("./img/img/unknowfile.png"); + iconLabel->setPixmap(pixmap2); +// } +// else + iconLabel->setPixmap(pixmap); + iconLabel->resize(iconLabel->pixmap()->size()); + timeLabel = new QLabel(timeText, Widget); + progressbar = new QProgressBar(Widget); + progressbar->setRange(0, 100); + progressbar->setValue(percentage); + progressbar->setMaximumHeight(15); + mainLayout = new QHBoxLayout(Widget); + textLayout = new QHBoxLayout(); + exceptIconLayout = new QVBoxLayout(); + + mainLayout->setSpacing(5); // 设置主布局的间距为0 + mainLayout->setContentsMargins(0, 7, 0, 7); // 设置主布局的边距为0 + exceptIconLayout->setSpacing(0); // 设置子布局的间距为0 + exceptIconLayout->setContentsMargins(0, 0, 0, 0); // 设置子布局的边距为0 + + textLayout->addWidget(nameLabel); + textLayout->addWidget(timeLabel); + mainLayout->addWidget(iconLabel); + exceptIconLayout->addLayout(textLayout); + exceptIconLayout->addWidget(progressbar); + mainLayout->addLayout(exceptIconLayout); + + setSizeHint(Widget->sizeHint()); + } +private: + QLabel* nameLabel; + QLabel* iconLabel; + QLabel* timeLabel; + QProgressBar* progressbar; + QHBoxLayout* mainLayout; + QHBoxLayout* textLayout; + QVBoxLayout* exceptIconLayout; +}; + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + void ExitApp() + { + SaveData(); + trayIcon->hide(); + trayIcon = nullptr; + QApplication::quit(); + } + void HideWindow() + { + hide(); + refreshListWidgetTimer.stop(); + } + void ShowWindow() + { + show(); + RefreshListWidget(); + refreshListWidgetTimer.start(); + } + +private slots: + void on_actionOpenAppDir_triggered();//打开程序目录 + void on_actionExitApp_triggered(); + void on_activatedSysTrayIcon(QSystemTrayIcon::ActivationReason reason);//托盘点击 + void RefreshListWidget_slot() {RefreshListWidget();} + void GetTopWindow_slot(){GetTopWindow();} + void on_actionSelfStarting_triggered();//开机自启动 + void on_actionViewHistory_triggered();//打开"查看历史"窗口 + +private: + class ExeItem + { + public: + QString Name; + QString ExePath; + QString IconPath; + int Seconds = 0; + }; + Ui::MainWindow *ui; + QTimer getTopWindowTimer; + QTimer refreshListWidgetTimer; + QSystemTrayIcon* trayIcon; + QMenu* menu; + + int totalSeconds = 0; + QString absluteJsonDataFolderPath; + QString absluteExeIconFolderPath; + QString absluteJsonDataFilePath; + Settings settings; + QDate today; + QList exeItemList; + void CheckDate() + { + if (today > QDateTime::currentDateTime().date())//已经第二天 + { + ShellExecuteW(NULL, L"open", reinterpret_cast(QCoreApplication::applicationFilePath().replace("/", "\\").utf16()), NULL, NULL, SW_SHOW); + ExitApp(); + } + } + void SaveData() + { + std::sort(exeItemList.begin(), exeItemList.end(), CmpBySeconds); + QJsonArray jsonArray; + for (const ExeItem* item : exeItemList) + { + QJsonObject jsonObject; + jsonObject["Name"] = item->Name; + jsonObject["ExePath"] = item->ExePath; + jsonObject["IconPath"] = item->IconPath; + jsonObject["Percentage"] = item->Seconds * 100 / totalSeconds; + jsonObject["TimeText"] = SecondsToQString(item->Seconds); + jsonObject["Seconds"] = item->Seconds; + + jsonArray.append(jsonObject); + } + QJsonDocument jsonDoc(jsonArray); + QFile file(absluteJsonDataFilePath); + if (file.open(QIODevice::WriteOnly)) + { + file.write(jsonDoc.toJson()); + file.close(); + } + } + static bool CmpBySeconds(const ExeItem* a, const ExeItem* b) + { + return a->Seconds > b->Seconds; + } + void RefreshListWidget() + { + std::sort(exeItemList.begin(), exeItemList.end(), CmpBySeconds); + ui->statusbar->showMessage("总时间:" + SecondsToQString(totalSeconds)); + if (totalSeconds == 0) + return; + ui->listWidget->clear(); + for (auto &exe : exeItemList) + { + ExeItemWidget* item = new ExeItemWidget(exe->Name, exe->ExePath, exe->IconPath, SecondsToQString(exe->Seconds), exe->Seconds*100/totalSeconds); +// item->setSizeHint(item->Widget->sizeHint()); + ui->listWidget->addItem(item); + ui->listWidget->setItemWidget(item, item->Widget); + } + } + void GetTopWindow() + { + totalSeconds += settings.GetTopWindowInterval_s; + HWND activeWindowHandle = GetForegroundWindow(); + DWORD pid = 0; + GetWindowThreadProcessId(activeWindowHandle, &pid); + if (pid == 0) + {return;} + // 获取路径 + QString filePath; + HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); + if (!hProcess) + return; + WCHAR processPath[MAX_PATH]; + if (GetModuleFileNameExW(hProcess, NULL, processPath, MAX_PATH) > 0) + { + CloseHandle(hProcess); + filePath = QString::fromWCharArray(processPath); + } + else + { + CloseHandle(hProcess); + return; + } + for (int i = 0; i < exeItemList.count(); i++) + { + if (QString::compare(exeItemList[i]->ExePath, filePath) == 0) + { + exeItemList[i]->Seconds += settings.GetTopWindowInterval_s; + return; + } + } +// 没有找到,新建项目 + QFileInfo fileInfo(filePath); + QString iconPath = filePath; //不能直接用filePath去remove,replace,会修改filePath + iconPath = QString("%1\\%2.png").arg(absluteExeIconFolderPath, iconPath.remove(':').replace('\\', '$')); + QFile file(iconPath); + if (!file.exists()) //如果不存在图片就创建 + { + QFileIconProvider iconProvider; + QIcon icon = iconProvider.icon(filePath); + if (icon.isNull()) + { + iconPath = ":/img/img/unknowfile.png"; + } + else + { + QPixmap pixmap = icon.pixmap(40, 40); + pixmap.save(iconPath); + } + } + ExeItem* item = new ExeItem(); + item->Name = fileInfo.baseName(); + item->ExePath = filePath; + item->IconPath = iconPath; + item->Seconds = settings.GetTopWindowInterval_s; + exeItemList.append(item); + } + void InitializeTray() + { + menu = new QMenu(this); + QIcon icon(":/img/img/32.ico"); + trayIcon = new QSystemTrayIcon(this); + trayIcon->setIcon(icon); + menu->addAction(ui->actionSelfStarting); + menu->addAction(ui->actionOpenAppDir); + menu->addSeparator(); + menu->addAction(ui->actionExitApp); + connect(trayIcon, &QSystemTrayIcon::activated, this, &MainWindow::on_activatedSysTrayIcon); + trayIcon->setContextMenu(menu); + trayIcon->show(); + } + virtual void closeEvent(QCloseEvent* event) override + { + SaveData(); + //如果有托盘图标就隐藏窗口否则关闭窗口 + if(trayIcon->isVisible()) + { + HideWindow(); + event->ignore(); + } + else + { + event->accept(); + // this->ExitApp(); + } + } +}; +#endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui new file mode 100644 index 0000000..62c4ade --- /dev/null +++ b/mainwindow.ui @@ -0,0 +1,89 @@ + + + MainWindow + + + + 0 + 0 + 400 + 500 + + + + 屏幕使用时间「代码见三」 + + + + :/img/img/32.ico:/img/img/32.ico + + + + 32 + 32 + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + 0 + 0 + 400 + 26 + + + + + 帮助 + + + + + + + + + + 打开安装目录 + + + + + 退出程序 + + + + + 开机自启动 + + + + + 查看历史 + + + + + + + + diff --git a/viewhistorywindow.cpp b/viewhistorywindow.cpp new file mode 100644 index 0000000..b603195 --- /dev/null +++ b/viewhistorywindow.cpp @@ -0,0 +1,33 @@ +#include "viewhistorywindow.h" +#include "ui_viewhistorywindow.h" + +ViewHistoryWindow::ViewHistoryWindow(QString jsonFilePath, QWidget *parent) : + QMainWindow(parent), + ui(new Ui::ViewHistoryWindow) +{ + ui->setupUi(this); + //加载知道的json文件 + QFile file(jsonFilePath); + file.open((QIODevice::ReadOnly)); + QByteArray jsonData = file.readAll(); + file.close(); + + QJsonDocument jsonDoc(QJsonDocument::fromJson(jsonData)); + + QJsonArray jsonArray = jsonDoc.array(); + int totalSeconds = 0; + for (const QJsonValue& value : jsonArray) + { + QJsonObject jsonObject = value.toObject(); + totalSeconds += jsonObject["Seconds"].toInt(); + ExeItemWidget* exeItemWidget = new ExeItemWidget(jsonObject["Name"].toString(), jsonObject["ExePath"].toString(), jsonObject["IconPath"].toString(), jsonObject["TimeText"].toString(), jsonObject["Percentage"].toInt()); + ui->listWidget->addItem(exeItemWidget); + ui->listWidget->setItemWidget(exeItemWidget, exeItemWidget->Widget); + } + ui->statusbar->showMessage("总时间:" + SecondsToQString(totalSeconds)); +} + +ViewHistoryWindow::~ViewHistoryWindow() +{ + delete ui; +} diff --git a/viewhistorywindow.h b/viewhistorywindow.h new file mode 100644 index 0000000..71ea5ec --- /dev/null +++ b/viewhistorywindow.h @@ -0,0 +1,24 @@ +#ifndef VIEWHISTORYWINDOW_H +#define VIEWHISTORYWINDOW_H + +#include +#include + +namespace Ui { +class ViewHistoryWindow; +} + +class ViewHistoryWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit ViewHistoryWindow(QString jsonFilePath, QWidget *parent = nullptr); + ~ViewHistoryWindow(); + +private: + Ui::ViewHistoryWindow *ui; + QString jsonFilePath; +}; + +#endif // VIEWHISTORYWINDOW_H diff --git a/viewhistorywindow.ui b/viewhistorywindow.ui new file mode 100644 index 0000000..36ec366 --- /dev/null +++ b/viewhistorywindow.ui @@ -0,0 +1,58 @@ + + + ViewHistoryWindow + + + + 0 + 0 + 400 + 500 + + + + 查看历史 + + + + 32 + 32 + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + 0 + 0 + 400 + 26 + + + + + + + +