当前位置:   article > 正文

Qt实现FTP客户端_qt ftp

qt ftp

由于Qt5.0已经取消了qftp库,但是还在维护,我们可以下载下来使用。
下载链接https://github.com/qt/qtftp.git
一、效果展示
在这里插入图片描述

二、源码实现
ftpWidget.h

#ifndef FTPWIDGET_H
#define FTPWIDGET_H

#include <QWidget>
#include <QVariant>
#include <QApplication>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QMainWindow>
#include <QMenuBar>
#include <QProgressBar>
#include <QPushButton>
#include <QStatusBar>
#include <QTreeWidget>
#include <QUrl>
#include <QTreeWidgetItem>
#include <QFile>
#include <QMessageBox>
#include <QFileDialog>
#include <QLineEdit>
#include <QMenu>
#include <QAction>
#include <QIcon>

#include "qftp.h"
#include "qurlinfo.h"

#define BTN_LOGIN_ICON             ":/icon/image/iconLogin.png"
#define BTN_QUIT_ICON              ":/icon/image/iconQuit.png"
#define BTN_UPLOAD_ICON            ":/icon/image/iconUpload.png"
#define BTN_DOWNLOAD_ICON          ":/icon/image/iconDownload.png"
#define BTN_BACK_ICON              ":/icon/image/iconBack.png"

#define ACTION_INNER_ICON           ":/icon/image/iconInner.png"
#define ACTION_DOWNLOAD_ICON        ":/icon/image/iconDownload.png"
#define ACTION_UPLOAD_ICON          ":/icon/image/iconUpload.png"
#define ACTION_BACK_ICON            ":/icon/image/iconBack.png"

#define TYPE_FILE_ICON              ":/icon/image/iconFile (1).png"
#define TYPE_FOLDER_ICON            ":/icon/image/iconFolder.png"


class FtpWidget : public QWidget
{
    Q_OBJECT
public:
    explicit FtpWidget(QWidget *parent = nullptr);

    bool set_login_para(QString ip,quint16 port,QString userName,QString userPassword);
signals:
protected:
    void closeEvent(QCloseEvent *e) override;
private slots:
    void btn_click_slot();
    void process_item_slot(QTreeWidgetItem *item, int column);
    void ftp_fommand_finished_slot(int commandId, bool error);
    void add_to_list_slot(const QUrlInfo &urlInfo);
    void update_transfer_progress_slot(qint64 readBytes, qint64 totalBytes);
    void cd_to_parent_slot();

    void upload_file_dialog_select_slot(const QString &filePathName);
    void treewidget_item_clicked_slot(QTreeWidgetItem *item, int column);
    void treewidget_custom_menu_slot(const QPoint &pos);
    void action_trigged_slot();
private:
    void value_init();
    void control_init();

    void download_file();
    void upload_file();
    void cancel_download();


private:
    QGridLayout *gridLayout;
    QHBoxLayout *horizontalLayout;
    QPushButton *btnLogin;
    QPushButton *btnQuit;
    QPushButton *btnUpload;
    QPushButton *btnDownload;
    QPushButton *btnBack;
    QProgressBar *progressBar;
    QTreeWidget *treeWidget;
    QMenuBar *menubar;
    QLineEdit *lineEditPath;


    QString loginIp;
    quint16 loginPort;
    QString loginUserName;
    QString loginUserPassword;

    QHash<QString, bool> isDirectory;
    QString currentPath;
    QFtp *ftp = nullptr;
    QFile *file = nullptr;

    QFileDialog *uploadFileDialog;

    QMenu *menuCustomer;
    QAction *actInter;
    QAction *actDownload;
    QAction *actUpload;
    QAction *actBack;
};

#endif // FTPWIDGET_H

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109

ftpWidget.cpp

#include "ftpwidget.h"
#include <QThread>

FtpWidget::FtpWidget(QWidget *parent)
    : QWidget{parent}
{
    this->value_init();
    this->control_init();
}





void FtpWidget::value_init()
{
    this->uploadFileDialog = new QFileDialog;
    this->uploadFileDialog->setModal(false);
   // uploadFileDialog->setAttribute(Qt::WA_DeleteOnClose);
    this->uploadFileDialog->setFileMode(QFileDialog::ExistingFile);
    //uploadFileDialog->show();
    connect(this->uploadFileDialog,&QFileDialog::fileSelected,this,&FtpWidget::upload_file_dialog_select_slot);
}

void FtpWidget::control_init()
{
    this->setObjectName(QString::fromUtf8("FtpWidget"));
    this->resize(800, 600);
    this->setWindowTitle(tr("下位机文件管理"));

    this->gridLayout = new QGridLayout();
    this->gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
    this->horizontalLayout = new QHBoxLayout();
    this->horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));

    this->btnLogin = new QPushButton();
    this->btnLogin->setObjectName(QString::fromUtf8("btnLogin"));
    this->btnLogin->setText(tr("登录"));

    this->horizontalLayout->addWidget(this->btnLogin);

    this->btnQuit = new QPushButton();
    this->btnQuit->setObjectName(QString::fromUtf8("btnQuit"));
    this->btnQuit->setText(tr("退出"));

    this->horizontalLayout->addWidget(this->btnQuit);

    this->btnUpload = new QPushButton();
    this->btnUpload->setObjectName(QString::fromUtf8("btnUpload"));
    this->btnUpload->setText(tr("上传"));

    this->horizontalLayout->addWidget(this->btnUpload);

    this->btnDownload = new QPushButton();
    this->btnDownload->setObjectName(QString::fromUtf8("btnDownload"));
    this->btnDownload->setText(tr("下载"));

    this->horizontalLayout->addWidget(this->btnDownload);


    this->btnBack = new QPushButton();
    this->btnBack->setObjectName(QString::fromUtf8("btnBack"));
    this->btnBack->setText(tr("上一级"));

    this->horizontalLayout->addWidget(this->btnBack);


    this->gridLayout->addLayout(this->horizontalLayout, 3, 0, 1, 1);

    this->progressBar = new QProgressBar();
    this->progressBar->setObjectName(QString::fromUtf8("progressBar"));
    this->progressBar->setValue(0);
    this->progressBar->setAlignment(Qt::AlignCenter);

    this->gridLayout->addWidget(this->progressBar, 2, 0, 1, 1);

    this->lineEditPath = new QLineEdit();
    this->lineEditPath->setReadOnly(true);

    this->gridLayout->addWidget(this->lineEditPath, 1, 0, 1, 1);

    this->treeWidget = new QTreeWidget();
    this->treeWidget->setObjectName(QString::fromUtf8("treeWidget"));

    this->gridLayout->addWidget(this->treeWidget, 0, 0, 1, 1);

    this->setLayout(this->gridLayout);

    //控件设置值
    this->btnQuit->setEnabled(false);
    this->btnUpload->setEnabled(false);
    this->btnDownload->setEnabled(false);
    this->btnBack->setEnabled(false);

    this->btnLogin->setIcon(QIcon(BTN_LOGIN_ICON));
    this->btnQuit->setIcon(QIcon(BTN_QUIT_ICON));
    this->btnUpload->setIcon(QIcon(BTN_UPLOAD_ICON));
    this->btnDownload->setIcon(QIcon(BTN_DOWNLOAD_ICON));
    this->btnBack->setIcon(QIcon(BTN_BACK_ICON));

   // this ->treeWidget -> setEnabled(false);
    this ->treeWidget -> setRootIsDecorated(false);
    this ->treeWidget -> setHeaderLabels(QStringList() << tr("文件名") << tr("尺寸") << tr("所有者") << tr("组") << tr("时间"));
    this ->treeWidget -> header() ->setStretchLastSection(false);
    this->treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);


    this->menuCustomer = new QMenu;
    this->actInter = new QAction(tr("进入"));
    this->actDownload = new QAction(tr("下载"));
    this->actUpload = new QAction(tr("上传"));
    this->actBack = new QAction(tr("回退"));

    this->actInter->setEnabled(false);
    this->actDownload->setEnabled(false);
    this->actUpload->setEnabled(false);
    this->actBack->setEnabled(false);

    this->actInter->setIcon(QIcon(ACTION_INNER_ICON));
    this->actDownload->setIcon(QIcon(ACTION_DOWNLOAD_ICON));
    this->actUpload->setIcon(QIcon(ACTION_UPLOAD_ICON));
    this->actBack->setIcon(QIcon(ACTION_BACK_ICON));

    this->menuCustomer->addAction(this->actInter);
    this->menuCustomer->addAction(this->actDownload);
    this->menuCustomer->addAction(this->actUpload);
    this->menuCustomer->addAction(this->actBack);

    connect(this->actInter,&QAction::triggered,this,&FtpWidget::action_trigged_slot);
    connect(this->actDownload,&QAction::triggered,this,&FtpWidget::action_trigged_slot);
    connect(this->actUpload,&QAction::triggered,this,&FtpWidget::action_trigged_slot);
    connect(this->actBack,&QAction::triggered,this,&FtpWidget::action_trigged_slot);

    connect(this->treeWidget, &QTreeWidget::itemActivated,this, &FtpWidget::process_item_slot);
    connect(this->treeWidget, &QTreeWidget::itemClicked,this, &FtpWidget::treewidget_item_clicked_slot);
    connect(this->treeWidget, &QTreeWidget::customContextMenuRequested,this, &FtpWidget::treewidget_custom_menu_slot);
 //   connect(ui->treeWidget_fileList, &QTreeWidget::currentItemChanged,this, &FtpWidget::enableDownloadButton);


    //连接信号与槽
    connect(this->btnLogin,&QPushButton::clicked,this,&FtpWidget::btn_click_slot);
    connect(this->btnQuit,&QPushButton::clicked,this,&FtpWidget::btn_click_slot);
    connect(this->btnUpload,&QPushButton::clicked,this,&FtpWidget::btn_click_slot);
    connect(this->btnDownload,&QPushButton::clicked,this,&FtpWidget::btn_click_slot);
    connect(this->btnBack,&QPushButton::clicked,this,&FtpWidget::btn_click_slot);
}



bool FtpWidget::set_login_para(QString ip, quint16 port, QString userName, QString userPassword)
{
    if(ip == nullptr
            || port == 0
            ||port>65535
            ||userName == nullptr
            ||userPassword == nullptr)
        return false;


    this->loginIp = ip;
    this->loginPort = port;
    this->loginUserName = userName;
    this->loginUserPassword = userPassword;
    return true;
}


void FtpWidget::download_file()
{
    if(this->file !=nullptr)
    {
        QMessageBox *messageBox = new QMessageBox;
        messageBox->setModal(false);
        messageBox->setIcon(QMessageBox::Critical);
        messageBox->setText(tr("请等待动作执行完成!"));
        messageBox->setAttribute(Qt::WA_DeleteOnClose);
        messageBox->show();
        return;
    }

    QString fileName = this->treeWidget->currentItem()->text(0).toUtf8();
    qDebug()<<fileName;
    if (QFile::exists(fileName))
    {
        QMessageBox *messageBox = new QMessageBox;
        messageBox->setModal(false);
        messageBox->setIcon(QMessageBox::Information);
        messageBox->setText(tr("此文件已经存在!"));
        messageBox->setAttribute(Qt::WA_DeleteOnClose);
        messageBox->show();


        return;
    }

    file = new QFile(fileName);
    if (!file->open(QIODevice::WriteOnly))
    {
        QMessageBox *messageBox = new QMessageBox;
        messageBox->setModal(false);
        messageBox->setIcon(QMessageBox::Critical);
        messageBox->setText(tr("文件打开失败!"));
        messageBox->setAttribute(Qt::WA_DeleteOnClose);
        messageBox->show();
        delete file;
        file = nullptr;
        return;
    }
    this->progressBar->setValue(0);
    ftp->get(QString::fromLatin1(this->treeWidget->currentItem()->text(0).toLocal8Bit()), file);

}

void FtpWidget::upload_file()
{
    if(this->file !=nullptr)
    {
        QMessageBox *messageBox = new QMessageBox;
        messageBox->setModal(false);
        messageBox->setIcon(QMessageBox::Critical);
        messageBox->setText(tr("请等待动作执行完成!"));
        messageBox->setAttribute(Qt::WA_DeleteOnClose);
        messageBox->show();
        return;
    }
    if(!uploadFileDialog->isHidden())
        return;
    this->uploadFileDialog->show();
}

void FtpWidget::cancel_download()
{
    ftp->abort();

    if (file->exists())
    {
        file->close();
        file->remove();
    }
    delete file;
    this->file = nullptr;
}
void FtpWidget::btn_click_slot()
{
    QPushButton *btn = qobject_cast<QPushButton *>(sender());
    if(btn == this->btnLogin)
    {
        if(this->loginIp == nullptr
                || this->loginPort == 0
                ||this->loginPort>65535
                ||this->loginUserName == nullptr
                ||this->loginUserPassword == nullptr)
            return;

        ftp = new QFtp(this);
        connect(ftp, &QFtp::commandFinished,this, &FtpWidget::ftp_fommand_finished_slot);
        connect(ftp, &QFtp::listInfo,this, &FtpWidget::add_to_list_slot);
        connect(ftp, &QFtp::dataTransferProgress,this, &FtpWidget::update_transfer_progress_slot);

        this->treeWidget ->clear();
        currentPath.clear();
        isDirectory.clear();

        ftp -> connectToHost(this->loginIp,21);
        ftp -> login(this->loginUserName,this->loginUserPassword);
    }
    else if(btn == this->btnQuit)
    {
        this->ftp->abort();
        this->ftp->close();
        delete this->ftp;
        this->ftp = nullptr;

        this->treeWidget->clear();

        this->btnLogin->setEnabled(true);
        this->btnQuit->setEnabled(false);
        this->btnUpload->setEnabled(false);
        this->btnDownload->setEnabled(false);
        this->btnBack->setEnabled(false);

        this->actInter->setEnabled(false);
        this->actDownload->setEnabled(false);
        this->actUpload->setEnabled(false);
        this->actBack->setEnabled(false);
    }
    else if(btn == this->btnUpload)
    {
        this->upload_file();
    }
    else if(btn == this->btnDownload)
    {
        this->download_file();
    }
    else if(btn == this->btnBack)
    {
        this->cd_to_parent_slot();
    }
}

void FtpWidget::process_item_slot(QTreeWidgetItem *item, int column)
{
    QString name = item->text(0);

    if (isDirectory.value(name))
    {
        qDebug()<<name;
        this->treeWidget->clear();
        isDirectory.clear();
        currentPath += '/';
        currentPath += name;
        ftp->cd(QString::fromLatin1(currentPath.toLocal8Bit()));
        ftp->list();
        this->btnBack->setEnabled(true);
        this->actBack->setEnabled(true);
        this->lineEditPath->setText(this->currentPath.toUtf8());
        return;
    }
    this->lineEditPath->setText(this->currentPath.toUtf8());
}

void FtpWidget::ftp_fommand_finished_slot(int commandId, bool error)
{
   // qDebug()<<commandId;
    if (ftp->currentCommand() == QFtp::ConnectToHost)
    {
        if (error)
        {
            QMessageBox *messageBox = new QMessageBox;
            messageBox->setModal(false);
            messageBox->setIcon(QMessageBox::Critical);
            messageBox->setText(tr("连接服务器失败!"));
            messageBox->setAttribute(Qt::WA_DeleteOnClose);
            messageBox->show();

            this->btnLogin->setEnabled(true);
            this->btnQuit->setEnabled(false);
            this->btnUpload->setEnabled(false);
            this->btnDownload->setEnabled(false);
            this->btnBack->setEnabled(false);
            this->actBack->setEnabled(false);

            this->actInter->setEnabled(false);
            this->actDownload->setEnabled(false);
            this->actUpload->setEnabled(false);
            this->actBack->setEnabled(false);

        //    connectOrDisconnect();
            return;
        }
        else {

            this->btnLogin->setEnabled(false);
            this->btnQuit->setEnabled(true);
            this->btnUpload->setEnabled(true);
            //this->btnDownload->setEnabled(true);
            this->btnBack->setEnabled(true);
            this->actBack->setEnabled(true);

            this->actInter->setEnabled(false);
            this->actDownload->setEnabled(false);
            this->actUpload->setEnabled(true);
            this->actBack->setEnabled(false);
            return;
        }
    }
    else if (ftp->currentCommand() == QFtp::Close)
    {
        this->btnLogin->setEnabled(true);
        this->btnQuit->setEnabled(false);
        this->btnUpload->setEnabled(false);
        this->btnDownload->setEnabled(false);
        this->btnBack->setEnabled(false);
        this->actBack->setEnabled(false);
    }

    if (ftp->currentCommand() == QFtp::Login)
        ftp->list();

    if (ftp->currentCommand() == QFtp::Get)
    {
        if (error)
        {
            file->close();
            file->remove();
            QMessageBox *messageBox = new QMessageBox;
            messageBox->setModal(false);
            messageBox->setIcon(QMessageBox::Critical);
            messageBox->setText(tr("文件下载失败!"));
            messageBox->setAttribute(Qt::WA_DeleteOnClose);
            messageBox->show();
        }
        else
        {
            this->progressBar ->setValue(100);
            file->close();
            QMessageBox *messageBox = new QMessageBox;
            messageBox->setModal(false);
            messageBox->setIcon(QMessageBox::Information);
            messageBox->setText(tr("文件下载成功!"));
            messageBox->setAttribute(Qt::WA_DeleteOnClose);
            messageBox->show();
        }
        delete file;
        this->file = nullptr;
       // enableDownloadButton();

    }
    else if(ftp->currentCommand() == QFtp::Put)
    {
        if (error)
        {
            file->close();
            file->remove();
            QMessageBox *messageBox = new QMessageBox;
            messageBox->setModal(false);
            messageBox->setIcon(QMessageBox::Critical);
            messageBox->setText(tr("文件上传失败!"));
            messageBox->setAttribute(Qt::WA_DeleteOnClose);
            messageBox->show();
        }
        else
        {
            this->progressBar ->setValue(100);
            file->close();
            QMessageBox *messageBox = new QMessageBox;
            messageBox->setModal(false);
            messageBox->setIcon(QMessageBox::Information);
            messageBox->setText(tr("文件上传成功!"));
            messageBox->setAttribute(Qt::WA_DeleteOnClose);
            messageBox->show();
        }
        delete file;
        this->file = nullptr;
    }
    else if (ftp->currentCommand() == QFtp::List)
    {
        if (isDirectory.isEmpty())
        {
            this->treeWidget -> addTopLevelItem(new QTreeWidgetItem(QStringList() << tr("<empty>")));
          //  this->treeWidget -> setEnabled(false);
        }
    }

}

void FtpWidget::add_to_list_slot(const QUrlInfo &urlInfo)
{
    QTreeWidgetItem *item = new QTreeWidgetItem;
    item->setText(0, urlInfo.name().toLatin1());
    item->setText(1, QString::number(urlInfo.size()));
    item->setText(2, urlInfo.owner().toLatin1());
    item->setText(3, urlInfo.group().toLatin1());
    item->setText(4, urlInfo.lastModified().toString("yyyy-MM-dd"));

    QPixmap pixmap(urlInfo.isDir() ? TYPE_FOLDER_ICON : TYPE_FILE_ICON);
    item->setIcon(0, pixmap);

    isDirectory[urlInfo.name().toLatin1()] = urlInfo.isDir();
    this->treeWidget->addTopLevelItem(item);
    if (!this ->treeWidget->currentItem())
    {
        this ->treeWidget->setCurrentItem(this ->treeWidget->topLevelItem(0));
        //this ->treeWidget->setEnabled(true);
    }

}

void FtpWidget::cd_to_parent_slot()
{
    this->treeWidget -> clear();
    isDirectory.clear();
    currentPath = currentPath.left(currentPath.lastIndexOf('/'));
    if (currentPath.isEmpty())
    {
        this->btnBack->setEnabled(false);
        this->actBack->setEnabled(false);
        ftp->cd("/");
    } else {
        ftp->cd(QString::fromLatin1(currentPath.toLocal8Bit()));
    }
    ftp->list();
    this->lineEditPath->setText(this->currentPath.toUtf8());
}

void FtpWidget::upload_file_dialog_select_slot(const QString &filePathName)
{
    qDebug()<<filePathName;

    if (filePathName.isEmpty())
        return;

    file = new QFile(filePathName);

    if (!file->open(QIODevice::ReadOnly))
        return;

    QString uploadPath;

    // 解决中文乱码问题

    QString name = filePathName.mid(filePathName.lastIndexOf("/") + 1);

    uploadPath = QString("%1/%2").arg(currentPath).arg(name);
    this->progressBar->setValue(0);
    ftp->put(file, QString::fromLatin1(uploadPath.toLocal8Bit()));
}

void FtpWidget::treewidget_item_clicked_slot(QTreeWidgetItem *item, int column)
{
    Q_UNUSED(item)
    Q_UNUSED(column)
    this->lineEditPath->setText(this->currentPath.toUtf8());
    QString name = item->text(0);

    if (isDirectory.value(name))
    {
        this->btnDownload->setEnabled(false);
        this->actInter->setEnabled(true);
        this->actDownload->setEnabled(false);

    }
    else
    {
        this->btnDownload->setEnabled(true);
        this->actInter->setEnabled(false);
        this->actDownload->setEnabled(true);
    }

}

void FtpWidget::treewidget_custom_menu_slot(const QPoint &pos)
{
    Q_UNUSED(pos)
    this->menuCustomer->exec(this->treeWidget->cursor().pos());

}

void FtpWidget::action_trigged_slot()
{
    QAction *act = qobject_cast<QAction *>(sender());
    if(act == this->actInter)
    {
        this->process_item_slot(this->treeWidget->currentItem(),0);
    }
    else if(act == this->actDownload)
    {
        this->download_file();
    }
    else if(act == this->actUpload)
    {
        this->upload_file();
    }
    else if(act == this->actBack)
    {
        this->cd_to_parent_slot();
    }
}


void FtpWidget::update_transfer_progress_slot(qint64 readBytes, qint64 totalBytes)
{
    this->progressBar->setValue(static_cast<int>(readBytes/totalBytes));
}

void FtpWidget::closeEvent(QCloseEvent *e)
{
    if(this->file != nullptr)
        return;
    if(this->ftp != nullptr)
    {
        this->ftp->abort();
        this->ftp->close();
        delete this->ftp;
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • 443
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • 467
  • 468
  • 469
  • 470
  • 471
  • 472
  • 473
  • 474
  • 475
  • 476
  • 477
  • 478
  • 479
  • 480
  • 481
  • 482
  • 483
  • 484
  • 485
  • 486
  • 487
  • 488
  • 489
  • 490
  • 491
  • 492
  • 493
  • 494
  • 495
  • 496
  • 497
  • 498
  • 499
  • 500
  • 501
  • 502
  • 503
  • 504
  • 505
  • 506
  • 507
  • 508
  • 509
  • 510
  • 511
  • 512
  • 513
  • 514
  • 515
  • 516
  • 517
  • 518
  • 519
  • 520
  • 521
  • 522
  • 523
  • 524
  • 525
  • 526
  • 527
  • 528
  • 529
  • 530
  • 531
  • 532
  • 533
  • 534
  • 535
  • 536
  • 537
  • 538
  • 539
  • 540
  • 541
  • 542
  • 543
  • 544
  • 545
  • 546
  • 547
  • 548
  • 549
  • 550
  • 551
  • 552
  • 553
  • 554
  • 555
  • 556
  • 557
  • 558
  • 559
  • 560
  • 561
  • 562
  • 563
  • 564
  • 565
  • 566
  • 567
  • 568
  • 569
  • 570
  • 571
  • 572
  • 573
  • 574
  • 575
  • 576
  • 577

三、完整工程下载
完整工程链接

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/590696
推荐阅读
相关标签
  

闽ICP备14008679号