Răsfoiți Sursa

数据库驱动完成,预览窗口完成

lennlouis 3 săptămâni în urmă
părinte
comite
94fe294aff

+ 20 - 1
core_form/frmalbum/frmalbum.cpp

@@ -13,10 +13,27 @@ FrmAlbum::~FrmAlbum()
     delete ui;
 }
 
+void FrmAlbum::slot_updateImage()
+{
+    QList<QUrl> urls = {
+        QUrl("https://imagehyj.oss-cn-hangzhou.aliyuncs.com/blog/20250320201317.png"),
+        QUrl("https://imagehyj.oss-cn-hangzhou.aliyuncs.com/blog/EDH386.jpeg"),
+        QUrl("https://imagehyj.oss-cn-hangzhou.aliyuncs.com/blog/20250321103557.png"),
+        QUrl("https://imagehyj.oss-cn-hangzhou.aliyuncs.com/blog/logo512.png")
+    };
+
+    foreach (const QUrl& u, urls) {
+        FrmImgShow* widget  = new FrmImgShow(this);
+        widget->loadImage(u);
+        picWidgetList.push_front(widget);
+    }
+}
+
 void FrmAlbum::initForm()
 {
     layout = new QHBoxLayout(this);
     panelWidget = new PanelWidget(this);
+    panelWidget->setSpace(5);
     layout->addWidget(panelWidget);
     layout->setContentsMargins(0, 0, 0, 0);
     layout->setSpacing(0);
@@ -34,6 +51,7 @@ void FrmAlbum::initForm()
         QUrl("https://imagehyj.oss-cn-hangzhou.aliyuncs.com/blog/20250320201317.png"),
         QUrl("https://imagehyj.oss-cn-hangzhou.aliyuncs.com/blog/EDH386.jpeg"),
         QUrl("https://imagehyj.oss-cn-hangzhou.aliyuncs.com/blog/20250321103557.png"),
+        QUrl("https://imagehyj.oss-cn-hangzhou.aliyuncs.com/blog/logo512.png")
     };
 
     foreach (const QUrl& u, urls) {
@@ -42,5 +60,6 @@ void FrmAlbum::initForm()
         picWidgetList.push_front(widget);
     }
 
-    panelWidget->setWidget(picWidgetList, 3);
+    panelWidget->setWidget(picWidgetList, 4);
+    panelWidget->setSpace(15);
 }

+ 3 - 0
core_form/frmalbum/frmalbum.h

@@ -18,6 +18,9 @@ public:
     explicit FrmAlbum(QWidget *parent = nullptr);
     ~FrmAlbum();
 
+public slots:
+    void slot_updateImage();
+
 private:
     Ui::FrmAlbum *ui;
     QList<QWidget*> picWidgetList;

+ 83 - 53
core_form/frmimgshow/frmimgshow.cpp

@@ -32,7 +32,18 @@ void FrmImgShow::loadImage(const QUrl &imageUrl)
 void FrmImgShow::setImage(const QPixmap &pixmap)
 {
     qDebug() << "setImage";
-    labImg->setPixmap(pixmap.scaled(200, 200, Qt::KeepAspectRatio, Qt::SmoothTransformation));
+    // int h = pixmap.height();
+    // int w = pixmap.width();
+    // int sh, sw;
+    // if (h >= w) {
+    //     sh = 140;
+    //     sw = w * h / 140;
+    // }
+    // else {
+    //     sw = 140;
+    //     sh = h * w /140;
+    // }
+    labImg->setPixmap(pixmap.scaled(this->labImg->width(), this->labImg->height()));
 }
 
 void FrmImgShow::setLoadingState(bool loading)
@@ -46,38 +57,38 @@ QSize FrmImgShow::sizeHint()
     return QSize(300, 300);
 }
 
-// bool FrmImgShow::eventFilter(QObject *watched, QEvent *event)
-// {
-    // if (watched == btnCopy) {
-    //     if (event->type() == QEvent::Enter) {
-    //         btnCopy->setIcon(QIcon(QPixmap(":/qrc/image/copy_blue.png")));
-    //         return true;
-    //     }
-    //     else if (event->type() == QEvent::Leave) {
-    //         btnCopy->setIcon(QIcon(QPixmap(":/qrc/image/copy_white.png")));
-    //         return true;
-    //     }
-    //     else {
-    //         return false;
-    //     }
-    // }
+bool FrmImgShow::eventFilter(QObject *watched, QEvent *event)
+{
+    if (watched == btnCopy) {
+        if (event->type() == QEvent::Enter) {
+            btnCopy->setIcon(QIcon(QPixmap(":/qrc/image/copy_blue.png")));
+            return true;
+        }
+        else if (event->type() == QEvent::Leave) {
+            btnCopy->setIcon(QIcon(QPixmap(":/qrc/image/copy_white.png")));
+            return true;
+        }
+        else {
+            return false;
+        }
+    }
 
-    // if (watched == btnDelete) {
-    //     if (event->type() == QEvent::Enter) {
-    //         btnDelete->setIcon(QIcon(QPixmap(":/qrc/image/delete_red.png")));
-    //         return true;
-    //     }
-    //     else if (event->type() == QEvent::Leave) {
-    //         btnDelete->setIcon(QIcon(QPixmap(":/qrc/image/delete_white.png")));
-    //         return true;
-    //     }
-    //     else {
-    //         return false;
-    //     }
-    // }
+    if (watched == btnDelete) {
+        if (event->type() == QEvent::Enter) {
+            btnDelete->setIcon(QIcon(QPixmap(":/qrc/image/delete_red.png")));
+            return true;
+        }
+        else if (event->type() == QEvent::Leave) {
+            btnDelete->setIcon(QIcon(QPixmap(":/qrc/image/delete_white.png")));
+            return true;
+        }
+        else {
+            return false;
+        }
+    }
 
-    // return QWidget::eventFilter(watched, event);
-// }
+    return QWidget::eventFilter(watched, event);
+}
 
 void FrmImgShow::onFinished(QNetworkReply *reply)
 {
@@ -91,39 +102,58 @@ void FrmImgShow::onFinished(QNetworkReply *reply)
 
 void FrmImgShow::initForm()
 {
-    labImg = new QLabel(this);
-    // btnCopy = new QPushButton(this);
-    // btnCopy->setMaximumHeight(18);
-    // btnDelete = new QPushButton(this);
-    // btnDelete->setMaximumHeight(18);
-    // horizenSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
-    // hLayout = new QHBoxLayout();
-
-    // ckbSelect = new QCheckBox(this);
-    // ckbSelect->setMaximumHeight(18);
-    // hLayout->addWidget(btnCopy);
-    // hLayout->addWidget(btnDelete);
-    // hLayout->setContentsMargins(0, 0, 0, 0);
-    // hLayout->addSpacerItem(horizenSpacer);
-    // hLayout->addWidget(ckbSelect);
-    vLayout = new QVBoxLayout();
+    this->setWindowFlag(Qt::FramelessWindowHint);
+    this->setWindowFlags(this->windowFlags() | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint);
+    setAttribute(Qt::WA_TranslucentBackground);
+
+    vLayout = new QVBoxLayout(this);
+    setLayout(vLayout);
+    labImg = new QLabel();
+    btnCopy = new QPushButton();
+    btnCopy->setMinimumSize(22, 22);
+    btnCopy->setFlat(true);
+    btnCopy->setIcon(QIcon(":/qrc/image/copy_white.png"));
+
+    btnCopy->installEventFilter(this);
+
+    btnDelete = new QPushButton();
+    btnDelete->setMinimumSize(22, 22);
+    btnDelete->setFlat(true);
+    btnDelete->setIcon(QIcon(":/qrc/image/delete_white.png"));
+    btnDelete->installEventFilter(this);
+
+    horizenSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+    hLayout = new QHBoxLayout();
+
+    ckbSelect = new QCheckBox();
+    // ckbSelect->setMinimumSize(20, 20);
+    // ckbSelect->setStyleSheet("border:1px solid white;border-radius:5px");
+    ckbSelect->setStyleSheet("border-style:none;");
+
+    hLayout->addWidget(btnCopy);
+    hLayout->addWidget(btnDelete);
+    hLayout->setContentsMargins(0, 0, 0, 0);
+    hLayout->addSpacerItem(horizenSpacer);
+    hLayout->addWidget(ckbSelect);
+    hLayout->setSpacing(0);
+
     vLayout->addWidget(labImg);
-    // vLayout->addLayout(hLayout);
+    vLayout->addLayout(hLayout);
     vLayout->setContentsMargins(0, 0, 0, 0);
-    // vLayout->addLayout(vLayout);
 
-    this->setLayout(vLayout);
+
 
     // btnCopy->setIcon(QIcon(QPixmap(":/qrc/image/copy_white.png")));
     // btnDelete->setIcon(QIcon(QPixmap(":/qrc/image/delete_white.png")));
     // btnCopy->setFixedSize(32, 32);
     // btnCopy->setCursor(Qt::PointingHandCursor);
 
-    setStyleSheet("background-color: #FF0000;border: 1px solid white");
+    // setStyleSheet("background-color: #FF0000;border: 1px solid white");
+
+    setFixedSize(134, 160);
 
-    setFixedSize(140, 160);
 
-    this->labImg->setFixedSize(140, 140);
+    this->labImg->setMinimumSize(130, 130);
 }
 
 void FrmImgShow::initWidget()

+ 1 - 1
core_form/frmimgshow/frmimgshow.h

@@ -37,7 +37,7 @@ private:
     QVBoxLayout* vLayout;
 
 protected:
-    // virtual bool eventFilter(QObject* watched, QEvent* event);
+    virtual bool eventFilter(QObject* watched, QEvent* event);
 
 private slots:
     void onFinished(QNetworkReply *reply);

+ 1 - 0
core_support/tchttpservice/tchttpservice.cpp

@@ -49,6 +49,7 @@ void TCHttpService::apiLogin()
             this->m_token = jsonObj["token"].toString();
             qDebug() << this->m_token;
             m_isOnline = true;
+            ImageManager::instance()->addDomainUser(m_domain, m_userName);
             emit signal_loginSuc();
         }
 

+ 2 - 8
core_support/tchttpservice/tchttpservice.h

@@ -19,19 +19,13 @@
 #include <QHttpPart>
 #include <QHttpMultiPart>
 #include <QHash>
+#include "urldatabase.h"
 
 class TCHttpService : public QObject
 {
     Q_OBJECT
 private:
-    typedef struct {
-        QString file_name;
-        int share_status;
-        QString url;
-        qint64 size;
-    } file_info_t;
-
-    QMap<QString, file_info_t> m_fileMap;
+
 public:
     static TCHttpService* getInstance();
 

+ 130 - 130
core_support/urldatabase/urldatabase.cpp

@@ -1,217 +1,217 @@
-#include "urldatabase.h"
+#include "urldatabase.h".h"
+#include <QSqlQuery>
+#include <QSqlError>
+#include <QDebug>
 
-ImageUrlDatabase::ImageUrlDatabase(QObject *parent) : QObject(parent)
+ImageManager* ImageManager::m_instance = nullptr;
+QMutex ImageManager::m_mutex;
+
+ImageManager::ImageManager(QObject *parent) : QObject(parent)
 {
+
 }
 
-ImageUrlDatabase::~ImageUrlDatabase()
+ImageManager::~ImageManager()
 {
     if (m_db.isOpen()) {
         m_db.close();
     }
 }
 
-bool ImageUrlDatabase::openDatabase(const QString &path)
+ImageManager* ImageManager::instance()
 {
-    m_db = QSqlDatabase::addDatabase("QSQLITE");
-    m_db.setDatabaseName(path);
+    QMutexLocker locker(&m_mutex);
+    if (!m_instance) {
+        m_instance = new ImageManager();
+    }
+    return m_instance;
+}
+
+bool ImageManager::initialize(const QString &dbPath)
+{
+    m_db = QSqlDatabase::addDatabase("QSQLITE", "image_manager_connection");
+    m_db.setDatabaseName(dbPath);
 
     if (!m_db.open()) {
         qWarning() << "Failed to open database:" << m_db.lastError().text();
         return false;
     }
 
-    // 创建表结构
-    QSqlQuery query;
+    return createTables();
+}
+
+bool ImageManager::createTables()
+{
+    QSqlQuery query(m_db);
+
+    // 创建域名表
+    if (!query.exec("CREATE TABLE IF NOT EXISTS domains ("
+                    "domain_id INTEGER PRIMARY KEY AUTOINCREMENT, "
+                    "domain TEXT NOT NULL UNIQUE)")) {
+        qWarning() << "Failed to create domains table:" << query.lastError().text();
+        return false;
+    }
 
     // 创建用户表
     if (!query.exec("CREATE TABLE IF NOT EXISTS users ("
                     "user_id INTEGER PRIMARY KEY AUTOINCREMENT, "
-                    "username TEXT NOT NULL UNIQUE, "
-                    "created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)")) {
+                    "username TEXT NOT NULL UNIQUE)")) {
         qWarning() << "Failed to create users table:" << query.lastError().text();
         return false;
     }
 
-    // 创建服务器表
-    if (!query.exec("CREATE TABLE IF NOT EXISTS servers ("
-                    "server_id INTEGER PRIMARY KEY AUTOINCREMENT, "
-                    "domain TEXT NOT NULL UNIQUE, "
-                    "created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)")) {
-        qWarning() << "Failed to create servers table:" << query.lastError().text();
+    // 创建域名-用户关联表(确保唯一)
+    if (!query.exec("CREATE TABLE IF NOT EXISTS domain_users ("
+                    "id INTEGER PRIMARY KEY AUTOINCREMENT, "
+                    "domain_id INTEGER NOT NULL, "
+                    "user_id INTEGER NOT NULL, "
+                    "UNIQUE(domain_id, user_id), "
+                    "FOREIGN KEY(domain_id) REFERENCES domains(domain_id), "
+                    "FOREIGN KEY(user_id) REFERENCES users(user_id))")) {
+        qWarning() << "Failed to create domain_users table:" << query.lastError().text();
         return false;
     }
 
     // 创建图片URL表
     if (!query.exec("CREATE TABLE IF NOT EXISTS image_urls ("
                     "url_id INTEGER PRIMARY KEY AUTOINCREMENT, "
-                    "user_id INTEGER NOT NULL, "
-                    "server_id INTEGER NOT NULL, "
+                    "domain_user_id INTEGER NOT NULL, "
                     "image_url TEXT NOT NULL, "
-                    "last_accessed TIMESTAMP, "
-                    "created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, "
-                    "FOREIGN KEY (user_id) REFERENCES users(user_id), "
-                    "FOREIGN KEY (server_id) REFERENCES servers(server_id), "
-                    "UNIQUE(user_id, server_id, image_url))")) {
+                    "upload_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, "
+                    "FOREIGN KEY(domain_user_id) REFERENCES domain_users(id), "
+                    "UNIQUE(domain_user_id, image_url))")) {
         qWarning() << "Failed to create image_urls table:" << query.lastError().text();
         return false;
     }
 
-    // 创建索引
-    query.exec("CREATE INDEX IF NOT EXISTS idx_image_user ON image_urls(user_id)");
-    query.exec("CREATE INDEX IF NOT EXISTS idx_image_server ON image_urls(server_id)");
-
     return true;
 }
 
-int ImageUrlDatabase::addUser(const QString &username)
+bool ImageManager::addDomain(const QString &domain)
 {
-    QSqlQuery query;
-    query.prepare("INSERT OR IGNORE INTO users (username) VALUES (?)");
-    query.addBindValue(username);
-
-    if (!query.exec()) {
-        qWarning() << "Failed to add user:" << query.lastError().text();
-        return -1;
-    }
-
-    // 获取用户ID
-    return getUserId(username);
+    QSqlQuery query(m_db);
+    query.prepare("INSERT OR IGNORE INTO domains (domain) VALUES (?)");
+    query.addBindValue(domain);
+    return query.exec();
 }
 
-int ImageUrlDatabase::getUserId(const QString &username)
+bool ImageManager::addUser(const QString &user)
 {
-    QSqlQuery query;
-    query.prepare("SELECT user_id FROM users WHERE username = ?");
-    query.addBindValue(username);
-
-    if (!query.exec() || !query.next()) {
-        return -1;
-    }
-
-    return query.value(0).toInt();
+    QSqlQuery query(m_db);
+    query.prepare("INSERT OR IGNORE INTO users (username) VALUES (?)");
+    query.addBindValue(user);
+    return query.exec();
 }
 
-int ImageUrlDatabase::addServer(const QString &domain)
+int ImageManager::getDomainId(const QString &domain)
 {
-    QSqlQuery query;
-    query.prepare("INSERT OR IGNORE INTO servers (domain) VALUES (?)");
+    QSqlQuery query(m_db);
+    query.prepare("SELECT domain_id FROM domains WHERE domain = ?");
     query.addBindValue(domain);
-
-    if (!query.exec()) {
-        qWarning() << "Failed to add server:" << query.lastError().text();
-        return -1;
+    if (query.exec() && query.next()) {
+        return query.value(0).toInt();
     }
-
-    // 获取服务器ID
-    return getServerId(domain);
+    return -1;
 }
 
-int ImageUrlDatabase::getServerId(const QString &domain)
+int ImageManager::getUserId(const QString &user)
 {
-    QSqlQuery query;
-    query.prepare("SELECT server_id FROM servers WHERE domain = ?");
-    query.addBindValue(domain);
-
-    if (!query.exec() || !query.next()) {
-        return -1;
+    QSqlQuery query(m_db);
+    query.prepare("SELECT user_id FROM users WHERE username = ?");
+    query.addBindValue(user);
+    if (query.exec() && query.next()) {
+        return query.value(0).toInt();
     }
-
-    return query.value(0).toInt();
+    return -1;
 }
 
-bool ImageUrlDatabase::addImageUrl(const QString &username, const QString &domain, const QString &imageUrl)
+bool ImageManager::addDomainUser(const QString &domain, const QString &user)
 {
-    int userId = addUser(username);
-    if (userId == -1) return false;
-
-    int serverId = addServer(domain);
-    if (serverId == -1) return false;
+    if (!addDomain(domain) || !addUser(user)) {
+        return false;
+    }
 
-    QSqlQuery query;
-    query.prepare("INSERT OR REPLACE INTO image_urls (user_id, server_id, image_url, last_accessed) "
-                  "VALUES (?, ?, ?, datetime('now'))");
-    query.addBindValue(userId);
-    query.addBindValue(serverId);
-    query.addBindValue(imageUrl);
+    int domainId = getDomainId(domain);
+    int userId = getUserId(user);
 
-    if (!query.exec()) {
-        qWarning() << "Failed to add image URL:" << query.lastError().text();
+    if (domainId == -1 || userId == -1) {
         return false;
     }
 
-    return true;
+    QSqlQuery query(m_db);
+    query.prepare("INSERT OR IGNORE INTO domain_users (domain_id, user_id) VALUES (?, ?)");
+    query.addBindValue(domainId);
+    query.addBindValue(userId);
+    return query.exec();
 }
 
-QList<QString> ImageUrlDatabase::getUserImages(const QString &username)
+bool ImageManager::addImageUrl(const QString &domain, const QString &user, const QUrl &imageUrl)
 {
-    QList<QString> result;
-    int userId = getUserId(username);
+    int domainId = getDomainId(domain);
+    int userId = getUserId(user);
 
-    if (userId == -1) return result;
+    if (domainId == -1 || userId == -1) {
+        return false;
+    }
 
-    QSqlQuery query;
-    query.prepare("SELECT i.image_url FROM image_urls i "
-                  "WHERE i.user_id = ? "
-                  "ORDER BY i.last_accessed DESC");
+    QSqlQuery query(m_db);
+    query.prepare("SELECT id FROM domain_users WHERE domain_id = ? AND user_id = ?");
+    query.addBindValue(domainId);
     query.addBindValue(userId);
 
-    if (!query.exec()) {
-        qWarning() << "Failed to get user images:" << query.lastError().text();
-        return result;
+    if (!query.exec() || !query.next()) {
+        return false;
     }
 
-    while (query.next()) {
-        result.append(query.value(0).toString());
-    }
+    int domainUserId = query.value(0).toInt();
 
-    return result;
+    query.prepare("INSERT OR IGNORE INTO image_urls (domain_user_id, image_url) VALUES (?, ?)");
+    query.addBindValue(domainUserId);
+    query.addBindValue(imageUrl.toString());
+    return query.exec();
 }
 
-QList<QString> ImageUrlDatabase::getServerImages(const QString &domain)
+QList<QUrl> ImageManager::getImageUrls(const QString &domain, const QString &user)
 {
-    QList<QString> result;
-    int serverId = getServerId(domain);
+    QList<QUrl> urls;
 
-    if (serverId == -1) return result;
+    int domainId = getDomainId(domain);
+    int userId = getUserId(user);
 
-    QSqlQuery query;
-    query.prepare("SELECT i.image_url FROM image_urls i "
-                  "WHERE i.server_id = ? "
-                  "ORDER BY i.last_accessed DESC");
-    query.addBindValue(serverId);
-
-    if (!query.exec()) {
-        qWarning() << "Failed to get server images:" << query.lastError().text();
-        return result;
+    if (domainId == -1 || userId == -1) {
+        return urls;
     }
 
-    while (query.next()) {
-        result.append(query.value(0).toString());
+    QSqlQuery query(m_db);
+    query.prepare("SELECT i.image_url FROM image_urls i "
+                  "JOIN domain_users du ON i.domain_user_id = du.id "
+                  "WHERE du.domain_id = ? AND du.user_id = ? "
+                  "ORDER BY i.upload_time DESC");
+    query.addBindValue(domainId);
+    query.addBindValue(userId);
+
+    if (query.exec()) {
+        while (query.next()) {
+            urls.append(QUrl(query.value(0).toString()));
+        }
     }
 
-    return result;
+    return urls;
 }
 
-bool ImageUrlDatabase::updateLastAccessed(const QString &username, const QString &domain, const QString &imageUrl)
+bool ImageManager::containsDomainUser(const QString &domain, const QString &user)
 {
-    int userId = getUserId(username);
-    if (userId == -1) return false;
-
-    int serverId = getServerId(domain);
-    if (serverId == -1) return false;
-
-    QSqlQuery query;
-    query.prepare("UPDATE image_urls SET last_accessed = datetime('now') "
-                  "WHERE user_id = ? AND server_id = ? AND image_url = ?");
-    query.addBindValue(userId);
-    query.addBindValue(serverId);
-    query.addBindValue(imageUrl);
+    int domainId = getDomainId(domain);
+    int userId = getUserId(user);
 
-    if (!query.exec()) {
-        qWarning() << "Failed to update last accessed time:" << query.lastError().text();
+    if (domainId == -1 || userId == -1) {
         return false;
     }
 
-    return query.numRowsAffected() > 0;
+    QSqlQuery query(m_db);
+    query.prepare("SELECT 1 FROM domain_users WHERE domain_id = ? AND user_id = ?");
+    query.addBindValue(domainId);
+    query.addBindValue(userId);
+
+    return query.exec() && query.next();
 }

+ 32 - 16
core_support/urldatabase/urldatabase.h

@@ -6,34 +6,50 @@
 #include <QSqlQuery>
 #include <QSqlError>
 #include <QDateTime>
+#include <QString>
+#include <QUrl>
+#include <QHash>
+#include <QMutex>
+#include <QStandardPaths>
 
-class ImageUrlDatabase : public QObject
+
+class ImageManager : public QObject
 {
     Q_OBJECT
+
+private:
+    explicit ImageManager(QObject *parent = nullptr);
+    ~ImageManager();
+
 public:
-    explicit ImageUrlDatabase(QObject *parent = nullptr);
-    ~ImageUrlDatabase();
+    static ImageManager* instance();
+
+    // 初始化数据库连接
+    bool initialize(const QString &dbPath);
 
-    bool openDatabase(const QString &path);
+    // 添加域名-用户对(不重复)
+    bool addDomainUser(const QString &domain, const QString &user);
 
-    // 用户操作
-    int addUser(const QString &username);
+    // 上传成功后添加图片URL
+    bool addImageUrl(const QString &domain, const QString &user, const QUrl &imageUrl);
 
-    // 服务器操作
-    int addServer(const QString &domain);
+    // 获取特定域名-用户的所有图片URL
+    QList<QUrl> getImageUrls(const QString &domain, const QString &user);
 
-    // 图片URL操作
-    bool addImageUrl(const QString &username, const QString &domain, const QString &imageUrl);
-    QList<QString> getUserImages(const QString &username);
-    QList<QString> getServerImages(const QString &domain);
-    bool updateLastAccessed(const QString &username, const QString &domain, const QString &imageUrl);
+    // 检查域名-用户对是否存在
+    bool containsDomainUser(const QString &domain, const QString &user);
 
 private:
+    static ImageManager* m_instance;
+    static QMutex m_mutex;
+
     QSqlDatabase m_db;
 
-    // 内部辅助方法
-    int getUserId(const QString &username);
-    int getServerId(const QString &domain);
+    bool createTables();
+    bool addDomain(const QString &domain);
+    bool addUser(const QString &user);
+    int getDomainId(const QString &domain);
+    int getUserId(const QString &user);
 };
 
 #endif // URLDATABASE_H

+ 261 - 14
picpanel.pro.user

@@ -1,10 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE QtCreatorProject>
-<!-- Written by QtCreator 14.0.2, 2025-03-25T18:34:03. -->
+<!-- Written by QtCreator 14.0.2, 2025-03-25T23:33:15. -->
 <qtcreator>
  <data>
   <variable>EnvironmentId</variable>
-  <value type="QByteArray">{631b5895-04c2-4f08-83d2-9e1277f189a1}</value>
+  <value type="QByteArray">{4f2ec396-c2e0-4f3d-a369-5968ecaf5cee}</value>
  </data>
  <data>
   <variable>ProjectExplorer.Project.ActiveTarget</variable>
@@ -41,7 +41,7 @@
    <value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
    <value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
    <value type="bool" key="EditorConfiguration.ShowMargin">false</value>
-   <value type="int" key="EditorConfiguration.SmartBackspaceBehavior">2</value>
+   <value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
    <value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
    <value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
    <value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
@@ -74,11 +74,15 @@
    <valuelist type="QVariantList" key="AutoTest.PathFilters"/>
    <value type="int" key="AutoTest.RunAfterBuild">0</value>
    <value type="bool" key="AutoTest.UseGlobal">true</value>
+   <valuelist type="QVariantList" key="ClangCodeModel.CustomCommandLineKey">
+    <value type="QString">-fno-delayed-template-parsing</value>
+   </valuelist>
+   <value type="bool" key="ClangCodeModel.UseGlobalConfig">true</value>
    <valuemap type="QVariantMap" key="ClangTools">
     <value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
     <value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
     <value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
-    <value type="int" key="ClangTools.ParallelJobs">12</value>
+    <value type="int" key="ClangTools.ParallelJobs">16</value>
     <value type="bool" key="ClangTools.PreferConfigFile">true</value>
     <valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
     <valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
@@ -99,8 +103,8 @@
    <value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
    <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
     <value type="int" key="EnableQmlDebugging">0</value>
-    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">E:\picpanel\build\Desktop_Qt_6_7_3_MinGW_64_bit-Debug</value>
-    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">E:/picpanel/build/Desktop_Qt_6_7_3_MinGW_64_bit-Debug</value>
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">D:\Workspaces\picpanel\build\Desktop_Qt_6_7_3_MinGW_64_bit-Debug</value>
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">D:/Workspaces/picpanel/build/Desktop_Qt_6_7_3_MinGW_64_bit-Debug</value>
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
      <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
       <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
@@ -138,8 +142,8 @@
     <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
    </valuemap>
    <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
-    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">E:\picpanel\build\Desktop_Qt_6_7_3_MinGW_64_bit-Release</value>
-    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">E:/picpanel/build/Desktop_Qt_6_7_3_MinGW_64_bit-Release</value>
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">D:\Workspaces\picpanel\build\Desktop_Qt_6_7_3_MinGW_64_bit-Release</value>
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">D:/Workspaces/picpanel/build/Desktop_Qt_6_7_3_MinGW_64_bit-Release</value>
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
      <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
       <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
@@ -179,8 +183,8 @@
    </valuemap>
    <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
     <value type="int" key="EnableQmlDebugging">0</value>
-    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">E:\picpanel\build\Desktop_Qt_6_7_3_MinGW_64_bit-Profile</value>
-    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">E:/picpanel/build/Desktop_Qt_6_7_3_MinGW_64_bit-Profile</value>
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">D:\Workspaces\picpanel\build\Desktop_Qt_6_7_3_MinGW_64_bit-Profile</value>
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">D:/Workspaces/picpanel/build/Desktop_Qt_6_7_3_MinGW_64_bit-Profile</value>
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
      <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
       <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
@@ -245,20 +249,263 @@
     <value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
     <value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph &quot;dwarf,4096&quot; -F 250</value>
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
-    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:E:/picpanel/picpanel.pro</value>
-    <value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">E:/picpanel/picpanel.pro</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:D:/Workspaces/picpanel/picpanel.pro</value>
+    <value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">D:/Workspaces/picpanel/picpanel.pro</value>
     <value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
     <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
     <value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
     <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
-    <value type="QString" key="RunConfiguration.WorkingDirectory.default">E:/picpanel/build/Desktop_Qt_6_7_3_MinGW_64_bit-Debug</value>
+    <value type="QString" key="RunConfiguration.WorkingDirectory.default">D:/Workspaces/picpanel/build/Desktop_Qt_6_7_3_MinGW_64_bit-Debug</value>
    </valuemap>
    <value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
   </valuemap>
  </data>
+ <data>
+  <variable>ProjectExplorer.Project.Target.1</variable>
+  <valuemap type="QVariantMap">
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 5.14.2 MinGW 64-bit</value>
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 5.14.2 MinGW 64-bit</value>
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt5.5142.win64_mingw73_kit</value>
+   <value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
+   <value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
+   <value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">D:/Workspaces/build-picpanel-Desktop_Qt_5_14_2_MinGW_64_bit-Debug</value>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
+      <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
+      <value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
+      <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
+      <value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
+      <value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
+     </valuemap>
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+      <valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
+      <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
+      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
+      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+      <value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
+     </valuemap>
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
+    </valuemap>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+      <valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
+      <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
+      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
+      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+      <value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
+     </valuemap>
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
+    </valuemap>
+    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
+    <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
+    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
+    <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
+   </valuemap>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">D:/Workspaces/build-picpanel-Desktop_Qt_5_14_2_MinGW_64_bit-Release</value>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
+      <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
+      <value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
+      <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
+      <value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
+      <value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">true</value>
+     </valuemap>
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+      <valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
+      <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
+      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
+      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+      <value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
+     </valuemap>
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
+    </valuemap>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+      <valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
+      <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
+      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
+      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+      <value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
+     </valuemap>
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
+    </valuemap>
+    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
+    <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
+    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
+    <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
+   </valuemap>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">D:/Workspaces/build-picpanel-Desktop_Qt_5_14_2_MinGW_64_bit-Profile</value>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
+      <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
+      <value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
+      <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
+      <value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">true</value>
+      <value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">true</value>
+     </valuemap>
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+      <valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
+      <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
+      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
+      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+      <value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
+     </valuemap>
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
+    </valuemap>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+      <valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
+      <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
+      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
+      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+      <value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
+     </valuemap>
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
+    </valuemap>
+    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
+    <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
+    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
+    <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
+   </valuemap>
+   <value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">3</value>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
+    </valuemap>
+    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
+   </valuemap>
+   <value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
+    <value type="QString" key="Analyzer.Perf.CallgraphMode">dwarf</value>
+    <valuelist type="QVariantList" key="Analyzer.Perf.Events">
+     <value type="QString">cpu-cycles</value>
+    </valuelist>
+    <valuelist type="QVariantList" key="Analyzer.Perf.ExtraArguments"/>
+    <value type="int" key="Analyzer.Perf.Frequency">250</value>
+    <valuelist type="QVariantList" key="Analyzer.Perf.RecordArguments">
+     <value type="QString">-e</value>
+     <value type="QString">cpu-cycles</value>
+     <value type="QString">--call-graph</value>
+     <value type="QString">dwarf,4096</value>
+     <value type="QString">-F</value>
+     <value type="QString">250</value>
+    </valuelist>
+    <value type="QString" key="Analyzer.Perf.SampleMode">-F</value>
+    <value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
+    <value type="int" key="Analyzer.Perf.StackSize">4096</value>
+    <value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
+    <value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
+    <value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
+    <value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
+    <value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
+    <valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
+    <value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
+    <value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
+    <value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
+    <value type="QString" key="Analyzer.Valgrind.KCachegrindExecutable">kcachegrind</value>
+    <value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
+    <value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
+    <valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
+    <value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
+    <value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
+    <value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
+    <value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
+    <value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
+    <valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
+     <value type="int">0</value>
+     <value type="int">1</value>
+     <value type="int">2</value>
+     <value type="int">3</value>
+     <value type="int">4</value>
+     <value type="int">5</value>
+     <value type="int">6</value>
+     <value type="int">7</value>
+     <value type="int">8</value>
+     <value type="int">9</value>
+     <value type="int">10</value>
+     <value type="int">11</value>
+     <value type="int">12</value>
+     <value type="int">13</value>
+     <value type="int">14</value>
+    </valuelist>
+    <value type="int" key="PE.EnvironmentAspect.Base">2</value>
+    <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:D:/Workspaces/picpanel/picpanel.pro</value>
+    <value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">D:/Workspaces/picpanel/picpanel.pro</value>
+    <value type="QString" key="RunConfiguration.Arguments"></value>
+    <value type="bool" key="RunConfiguration.Arguments.multi">false</value>
+    <value type="QString" key="RunConfiguration.OverrideDebuggerStartup"></value>
+    <value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
+    <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
+    <value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
+    <value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
+    <value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
+    <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
+    <value type="QString" key="RunConfiguration.WorkingDirectory"></value>
+    <value type="QString" key="RunConfiguration.WorkingDirectory.default">D:/Workspaces/build-picpanel-Desktop_Qt_5_14_2_MinGW_64_bit-Debug</value>
+   </valuemap>
+   <value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
+  </valuemap>
+ </data>
  <data>
   <variable>ProjectExplorer.Project.TargetCount</variable>
-  <value type="qlonglong">1</value>
+  <value type="qlonglong">2</value>
  </data>
  <data>
   <variable>ProjectExplorer.Project.Updater.FileVersion</variable>

BIN
qrc/image/copy_blue.png


BIN
qrc/image/copy_white.png


+ 5 - 0
widget.cpp

@@ -1,6 +1,7 @@
 #include "widget.h"
 #include "ui_widget.h"
 #include "tchttpservice.h"
+#include "urldatabase.h"
 
 Widget::Widget(QWidget *parent)
     : QWidget(parent)
@@ -11,6 +12,8 @@ Widget::Widget(QWidget *parent)
     initWidget();
     initSignalSlot();
     initTrayApp();
+    QString stdPath = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
+    ImageManager::instance()->initialize(stdPath + "/picpanel.db");
     // this->btnPageUpload->setChecked(true);
     // this->btnPageUpload->setStyleSheet("{border: none;border-right: 4px solid #409EFF;color: #409EFF;}");
 }
@@ -205,6 +208,7 @@ void Widget::initSignalSlot()
 
     connect(TCHttpService::getInstance(), &TCHttpService::signal_loginSuc, this, &Widget::slot_loginSec);
     connect(frmupload, &FrmUpload::signal_uploadSuccess, this, &Widget::slot_uploadSuccess);
+    connect(this, &Widget::signal_updateImage, frmalbum, &FrmAlbum::slot_updateImage);
 }
 
 void Widget::initLeftMenu()
@@ -370,6 +374,7 @@ void Widget::pageChangeSlot()
         btnPageUpload->setIcon(iconUploadWhite);
         btnPageSetting->setIcon(iconSettingWhite);
         ui->stackedWidget->setCurrentWidget(frmalbum);
+        emit signal_updateImage();
     }
     else {
         btn->setIcon(iconSettingBlue);

+ 3 - 0
widget.h

@@ -91,5 +91,8 @@ private:
 
     FileConfigDecode* fileConfig;
 
+signals:
+    void signal_updateImage();
+
 };
 #endif // WIDGET_H

+ 4 - 1
widget.ui

@@ -150,6 +150,9 @@
    </item>
    <item>
     <layout class="QHBoxLayout" name="horizontalLayout_2">
+     <property name="spacing">
+      <number>0</number>
+     </property>
      <item>
       <widget class="QFrame" name="frame">
        <property name="sizePolicy">
@@ -166,7 +169,7 @@
        </property>
        <property name="maximumSize">
         <size>
-         <width>200</width>
+         <width>180</width>
          <height>16777215</height>
         </size>
        </property>