diff --git a/spark-webapp-runtime/globaldefine.h b/spark-webapp-runtime/globaldefine.h
index 49de701..bb0ed53 100644
--- a/spark-webapp-runtime/globaldefine.h
+++ b/spark-webapp-runtime/globaldefine.h
@@ -2,7 +2,6 @@
 #define GLOBALDEFINE_H
 
 #include <QObject>
-#include <QUrl>
 
 #define DEFAULT_TITLE   QObject::tr("SparkWebAppRuntime")
 #define DEFAULT_URL     QString("qrc:/help/help.html")
diff --git a/spark-webapp-runtime/main.cpp b/spark-webapp-runtime/main.cpp
index dc71b75..392b13e 100644
--- a/spark-webapp-runtime/main.cpp
+++ b/spark-webapp-runtime/main.cpp
@@ -46,7 +46,7 @@ int main(int argc, char *argv[])
                             .arg(QObject::tr("Presented By Spark developers # HadesStudio"));
     dialog->setDescription(szDefaultDesc);
     // WebsiteName
-    dialog->setWebsiteName("The Spark Project");
+    dialog->setWebsiteName("Spark Project");
     // WebsiteLink
     dialog->setWebsiteLink("https://gitee.com/deepin-community-store/");
     // License
diff --git a/spark-webapp-runtime/mainwindow.cpp b/spark-webapp-runtime/mainwindow.cpp
index f0f008a..8aea10f 100644
--- a/spark-webapp-runtime/mainwindow.cpp
+++ b/spark-webapp-runtime/mainwindow.cpp
@@ -20,7 +20,7 @@ MainWindow::MainWindow(QString szTitle,
     : DMainWindow(parent)
     , m_widget(new Widget(szUrl))
     , m_dialog(dialog)
-    , btnBackward(new DToolButton(titlebar()))
+    , btnBack(new DToolButton(titlebar()))
     , btnForward(new DToolButton(titlebar()))
     , btnRefresh(new DToolButton(titlebar()))
     , m_menu(new QMenu)
@@ -41,14 +41,14 @@ MainWindow::MainWindow(QString szTitle,
     titlebar()->setTitle(szTitle);
     titlebar()->setIcon(QIcon(":/images/spark-webapp-runtime.svg"));
 
-    btnBackward->setIcon(QIcon(":/images/go-previous-24.svg"));
-    btnBackward->setIconSize(QSize(36, 36));
+    btnBack->setIcon(QIcon(":/images/go-previous-24.svg"));
+    btnBack->setIconSize(QSize(36, 36));
     btnForward->setIcon(QIcon(":/images/go-next-24.svg"));
     btnForward->setIconSize(QSize(36, 36));
     btnRefresh->setIcon(QIcon(":/images/view-refresh.svg"));
     btnRefresh->setIconSize(QSize(36, 36));
 
-    titlebar()->addWidget(btnBackward, Qt::AlignLeft);
+    titlebar()->addWidget(btnBack, Qt::AlignLeft);
     titlebar()->addWidget(btnForward, Qt::AlignLeft);
     titlebar()->addWidget(btnRefresh, Qt::AlignLeft);
 
@@ -65,26 +65,17 @@ MainWindow::MainWindow(QString szTitle,
     fixSize();
     hideButtons();
 
-    connect(btnBackward, &DToolButton::clicked, this, [&]()
+    connect(btnBack, &DToolButton::clicked, this, [&]()
     {
-        if (m_widget)
-        {
-            m_widget->goBack();
-        }
+        m_widget->goBack();
     });
     connect(btnForward, &DToolButton::clicked, this, [&]()
     {
-        if (m_widget)
-        {
-            m_widget->goForward();
-        }
+        m_widget->goForward();
     });
     connect(btnRefresh, &DToolButton::clicked, this, [&]()
     {
-        if (m_widget)
-        {
-            m_widget->refresh();
-        }
+        m_widget->refresh();
     });
 
     connect(m_fixSize, &QAction::triggered, this, [=]()
@@ -100,16 +91,8 @@ MainWindow::MainWindow(QString szTitle,
 MainWindow::~MainWindow()
 {
     emit sigQuit();
-    if (m_widget)
-    {
-        delete m_widget;
-        m_widget = nullptr;
-    }
-    if (m_dialog)
-    {
-        delete m_dialog;
-        m_dialog = nullptr;
-    }
+    delete m_widget;
+    delete m_dialog;
 }
 
 void MainWindow::setIcon(QString szIconPath)
@@ -144,13 +127,13 @@ void MainWindow::hideButtons()
 {
     if(m_hideButtons->isChecked())
     {
-        btnBackward->hide();
+        btnBack->hide();
         btnForward->hide();
         btnRefresh->hide();
     }
     else
     {
-        btnBackward->show();
+        btnBack->show();
         btnForward->show();
         btnRefresh->show();
     }
diff --git a/spark-webapp-runtime/mainwindow.h b/spark-webapp-runtime/mainwindow.h
index 20361b1..630db36 100644
--- a/spark-webapp-runtime/mainwindow.h
+++ b/spark-webapp-runtime/mainwindow.h
@@ -25,18 +25,13 @@ public:
                QWidget *parent = nullptr);
     ~MainWindow();
 
-    void setIcon(QString);
-    void fixSize();
-    void hideButtons();
-
-signals:
-    void sigQuit();
+    void setIcon(QString szIconPath);
 
 private:
     Widget *m_widget;
     DAboutDialog *m_dialog;
 
-    DToolButton *btnBackward;
+    DToolButton *btnBack;
     DToolButton *btnForward;
     DToolButton *btnRefresh;
 
@@ -46,8 +41,14 @@ private:
 
     int m_width, m_height;
 
+    void fixSize();
+    void hideButtons();
+
     void closeEvent(QCloseEvent *event);
 
+signals:
+    void sigQuit();
+
 };
 
 #endif // MAINWINDOW_H
diff --git a/spark-webapp-runtime/spark-webapp-runtime.pro b/spark-webapp-runtime/spark-webapp-runtime.pro
index 8a0fc80..7336ad4 100644
--- a/spark-webapp-runtime/spark-webapp-runtime.pro
+++ b/spark-webapp-runtime/spark-webapp-runtime.pro
@@ -9,24 +9,23 @@ DEFINES += QT_DEPRECATED_WARNINGS
 CONFIG += c++11 link_pkgconfig
 PKGCONFIG += dtkwidget
 
-SOURCES += main.cpp\
-        httpd.cpp \
-        mainwindow.cpp \
-        webenginepage.cpp \
-        widget.cpp
-
-HEADERS  += mainwindow.h \
+HEADERS  += \
+         mainwindow.h \
          globaldefine.h \
          httpd.h \
          httplib.h \
          webenginepage.h \
          widget.h
 
-FORMS += widget.ui
+SOURCES += \
+        main.cpp \
+        httpd.cpp \
+        mainwindow.cpp \
+        webenginepage.cpp \
+        widget.cpp
 
-RESOURCES += imgs.qrc
+RESOURCES += \
+          imgs.qrc
 
 TRANSLATIONS += \
-    translations/spark-webapp-runtime_zh_CN.ts
-
-
+             translations/spark-webapp-runtime_zh_CN.ts
diff --git a/spark-webapp-runtime/translations/spark-webapp-runtime_zh_CN.qm b/spark-webapp-runtime/translations/spark-webapp-runtime_zh_CN.qm
index 5ae136e..5c5d7f8 100644
Binary files a/spark-webapp-runtime/translations/spark-webapp-runtime_zh_CN.qm and b/spark-webapp-runtime/translations/spark-webapp-runtime_zh_CN.qm differ
diff --git a/spark-webapp-runtime/translations/spark-webapp-runtime_zh_CN.ts b/spark-webapp-runtime/translations/spark-webapp-runtime_zh_CN.ts
index e15294b..65e24b1 100644
--- a/spark-webapp-runtime/translations/spark-webapp-runtime_zh_CN.ts
+++ b/spark-webapp-runtime/translations/spark-webapp-runtime_zh_CN.ts
@@ -17,102 +17,107 @@
 <context>
     <name>QObject</name>
     <message>
-        <location filename="../main.cpp" line="49"/>
+        <location filename="../main.cpp" line="46"/>
         <source>Presented By Spark developers # HadesStudio</source>
         <translation>由 星火开发者联盟 @ 花心胡萝卜 提供</translation>
     </message>
     <message>
-        <location filename="../main.cpp" line="56"/>
+        <location filename="../main.cpp" line="53"/>
         <source>This program is open source under GPLv3</source>
         <translation>本程序按GPL第三版开源</translation>
     </message>
     <message>
-        <location filename="../main.cpp" line="42"/>
+        <location filename="../main.cpp" line="39"/>
         <source>Version:</source>
         <translation>版本:</translation>
     </message>
     <message>
-        <location filename="../main.cpp" line="60"/>
+        <location filename="../main.cpp" line="57"/>
         <source>Description: %1</source>
         <translation>描述:%1</translation>
     </message>
     <message>
-        <location filename="../main.cpp" line="65"/>
+        <location filename="../main.cpp" line="62"/>
         <source>Enable CommandLineParser. Default is false.</source>
         <translation>启用参数解析方式。默认顺序解析方式。</translation>
     </message>
     <message>
-        <location filename="../main.cpp" line="69"/>
+        <location filename="../main.cpp" line="66"/>
         <source>The Title of Application. Default is %1.</source>
         <translation>设置程序的运行标题。默认是 %1。</translation>
     </message>
     <message>
-        <location filename="../main.cpp" line="75"/>
+        <location filename="../main.cpp" line="72"/>
         <source>The target URL. Default is Blank.</source>
         <translation>设置要打开的目标 URL。默认是空。</translation>
     </message>
     <message>
-        <location filename="../main.cpp" line="81"/>
+        <location filename="../main.cpp" line="78"/>
         <source>The Width of Application. Default is %1.</source>
         <translation>设置应用的窗口宽度。默认是 %1。</translation>
     </message>
     <message>
-        <location filename="../main.cpp" line="87"/>
+        <location filename="../main.cpp" line="84"/>
         <source>The Height of Application. Default is %1.</source>
         <translation>设置应用的窗口高度。默认是 %1。</translation>
     </message>
     <message>
-        <location filename="../main.cpp" line="93"/>
+        <location filename="../main.cpp" line="90"/>
         <source>Fix Window Size. Default is false.</source>
         <translation>固定窗口大小。默认关闭该功能。</translation>
     </message>
     <message>
-        <location filename="../main.cpp" line="97"/>
+        <location filename="../main.cpp" line="94"/>
         <source>Hide Control Buttons. Default is false.</source>
         <translation>隐藏控制按钮。默认关闭该此功能。</translation>
     </message>
     <message>
-        <location filename="../main.cpp" line="101"/>
+        <location filename="../main.cpp" line="98"/>
         <source>The ICON of Application.</source>
         <translation>设置应用的图标。</translation>
     </message>
     <message>
-        <location filename="../main.cpp" line="107"/>
+        <location filename="../main.cpp" line="104"/>
         <source>The Description of Application.</source>
         <translation>设置应用的描述信息。</translation>
     </message>
     <message>
-        <location filename="../main.cpp" line="113"/>
+        <location filename="../main.cpp" line="110"/>
         <source>The Configuration file of Application.</source>
         <translation>设置应用的配置文件。</translation>
     </message>
     <message>
-        <location filename="../main.cpp" line="119"/>
+        <location filename="../main.cpp" line="116"/>
         <source>The root path of the program web service.</source>
         <translation>设置内置 WebServer 的根路径。</translation>
     </message>
     <message>
-        <location filename="../main.cpp" line="126"/>
+        <location filename="../main.cpp" line="123"/>
         <source>The port number of the program web service.</source>
         <translation>设置内置 WebServer 的监听端口号。</translation>
     </message>
     <message>
-        <location filename="../main.cpp" line="133"/>
+        <location filename="../main.cpp" line="130"/>
         <source>The ssl port number of the program web service.</source>
         <translation>设置内置 WebServer 的 SSL 协议的监听端口号。</translation>
     </message>
     <message>
-        <location filename="../globaldefine.h" line="7"/>
+        <location filename="../globaldefine.h" line="6"/>
         <source>SparkWebAppRuntime</source>
         <translation>星火网页应用运行环境</translation>
     </message>
 </context>
 <context>
-    <name>Widget</name>
+    <name>WebEnginePage</name>
     <message>
-        <location filename="../widget.ui" line="14"/>
-        <source>MainPage</source>
-        <translation>主页</translation>
+        <location filename="../webenginepage.cpp" line="38"/>
+        <source>Start downloading...</source>
+        <translation>开始下载...</translation>
+    </message>
+    <message>
+        <location filename="../webenginepage.cpp" line="48"/>
+        <source>Download finished!</source>
+        <translation>下载完成!</translation>
     </message>
 </context>
 </TS>
diff --git a/spark-webapp-runtime/webenginepage.cpp b/spark-webapp-runtime/webenginepage.cpp
index adbed33..66e7144 100644
--- a/spark-webapp-runtime/webenginepage.cpp
+++ b/spark-webapp-runtime/webenginepage.cpp
@@ -1,22 +1,49 @@
 #include "webenginepage.h"
 
-#include <QWebEngineSettings>
+#include <QDir>
+#include <QDebug>
 
-WebEnginePage::WebEnginePage(QObject *parent) : QWebEnginePage(parent)
+WebEnginePage::WebEnginePage(QObject *parent)
+    : QWebEnginePage(parent)
+    , m_profile(this->profile())
+    , process(new QProcess)
 {
-
+    connect(m_profile, &QWebEngineProfile::downloadRequested, this, &WebEnginePage::on_download);
 }
 
 QWebEnginePage *WebEnginePage::createWindow(QWebEnginePage::WebWindowType type)
 {
     Q_UNUSED(type)
     WebEnginePage *page = new WebEnginePage();
-    connect(page, &QWebEnginePage::urlChanged, this, &WebEnginePage::onUrlChanged);
+    connect(page, &QWebEnginePage::urlChanged, this, &WebEnginePage::on_urlChanged);
     return page;
 }
 
-void WebEnginePage::onUrlChanged(const QUrl url)
+void WebEnginePage::on_urlChanged(const QUrl url)
 {
     setUrl(url);
     sender()->deleteLater();
 }
+
+void WebEnginePage::on_download(QWebEngineDownloadItem *item)
+
+{
+    connect(item, &QWebEngineDownloadItem::downloadProgress, this, &WebEnginePage::on_downloadProgress);
+    connect(item, &QWebEngineDownloadItem::finished, this, &WebEnginePage::on_downloadFinished);
+
+    //  无法指定下载位置,原因未知;默认位置为 ~/Downloads
+    //  item->setPath(QDir::homePath() + "/Downloads/");
+    item->accept();
+
+    process->start(QString("notify-send -a spark-webapp-runtime -t 5000 \"%1\"").arg(tr("Start downloading...")));
+}
+
+void WebEnginePage::on_downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
+{
+    qDebug() << "Download Progress:\tbytesReceived: " << bytesReceived << "\tbytesTotal: " << bytesTotal;
+}
+
+void WebEnginePage::on_downloadFinished()
+{
+    process->start(QString("notify-send -a spark-webapp-runtime -t 5000 \"%1\"").arg(tr("Download finished!")));
+}
diff --git a/spark-webapp-runtime/webenginepage.h b/spark-webapp-runtime/webenginepage.h
index 052579d..19b0df3 100644
--- a/spark-webapp-runtime/webenginepage.h
+++ b/spark-webapp-runtime/webenginepage.h
@@ -2,7 +2,9 @@
 #define WEBENGINEPAGE_H
 
 #include <QWebEnginePage>
+#include <QWebEngineProfile>
 #include <QObject>
+#include <QProcess>
 
 class WebEnginePage : public QWebEnginePage
 {
@@ -12,8 +14,16 @@ public:
 protected:
     QWebEnginePage *createWindow(WebWindowType type) override;
 
-public slots:
-    void onUrlChanged(const QUrl);
+private:
+    QWebEngineProfile *m_profile;
+
+    QProcess *process;
+
+private slots:
+    void on_urlChanged(const QUrl url);
+    void on_download(QWebEngineDownloadItem *item);
+    void on_downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
+    void on_downloadFinished();
 
 };
 
diff --git a/spark-webapp-runtime/widget.cpp b/spark-webapp-runtime/widget.cpp
index 4e509df..8e18f76 100644
--- a/spark-webapp-runtime/widget.cpp
+++ b/spark-webapp-runtime/widget.cpp
@@ -1,61 +1,76 @@
 #include "widget.h"
-#include "ui_widget.h"
 
-#include <QWebEngineView>
-
-#include "webenginepage.h"
-
-Widget::Widget(QString szUrl, QWidget *parent) :
-    QWidget(parent),
-    ui(new Ui::Widget)
-    , m_webEngineView(nullptr)
+Widget::Widget(QString szUrl, QWidget *parent)
+    : QWidget(parent)
+    , m_webEngineView(new QWebEngineView)
+    , m_page(new WebEnginePage)
     , m_szUrl(szUrl)
+    , m_spinner(new DSpinner)
+    , main(new QHBoxLayout)
 {
-    ui->setupUi(this);
+    m_spinner->setFixedSize(96, 96);
+
+    setLayout(main);
 
-    m_webEngineView = new QWebEngineView(this);
     m_webEngineView->setObjectName(QStringLiteral("webEngineView"));
     m_webEngineView->setEnabled(true);
     m_webEngineView->setAutoFillBackground(false);
-    m_webEngineView->setProperty("url", QVariant(QUrl(QStringLiteral(""))));
-    m_webEngineView->setProperty("zoomFactor", QVariant(1));
-
-    ui->verticalLayout->addWidget(m_webEngineView);
-
-    WebEnginePage *page = new WebEnginePage();
-    m_webEngineView->setPage(page);
+    m_webEngineView->setZoomFactor(1);
+    m_webEngineView->setPage(m_page);
 
+    m_webEngineView->setUrl(QUrl(nullptr));
     if (!m_szUrl.isEmpty())
     {
         m_webEngineView->setUrl(QUrl(m_szUrl));
     }
+
+    connect(m_webEngineView, &QWebEngineView::loadStarted, this, &Widget::on_loadStarted);
+    connect(m_webEngineView, &QWebEngineView::loadFinished, this, &Widget::on_loadFinished);
 }
 
 Widget::~Widget()
 {
-    delete ui;
 }
 
 void Widget::goBack()
 {
-    if (m_webEngineView)
-    {
-        m_webEngineView->triggerPageAction(QWebEnginePage::Back);
-    }
+    m_webEngineView->back();
 }
 
 void Widget::goForward()
 {
-    if (m_webEngineView)
-    {
-        m_webEngineView->triggerPageAction(QWebEnginePage::Forward);
-    }
+    m_webEngineView->forward();
 }
 
 void Widget::refresh()
 {
-    if (m_webEngineView)
+    m_webEngineView->reload();
+}
+
+void Widget::clearLayout(QLayout *layout)
+{
+    QLayoutItem *item;
+    while ((item = layout->takeAt(0)) != nullptr)
     {
-        m_webEngineView->triggerPageAction(QWebEnginePage::Reload);
+        delete item;
     }
 }
+
+void Widget::on_loadStarted()
+{
+    clearLayout(main);
+
+    main->addStretch();
+    main->addWidget(m_spinner);
+    main->addStretch();
+
+    m_spinner->start();
+}
+
+void Widget::on_loadFinished()
+{
+    m_spinner->stop();
+    clearLayout(main);
+
+    main->addWidget(m_webEngineView);
+}
diff --git a/spark-webapp-runtime/widget.h b/spark-webapp-runtime/widget.h
index cda3395..062de66 100644
--- a/spark-webapp-runtime/widget.h
+++ b/spark-webapp-runtime/widget.h
@@ -2,20 +2,23 @@
 #define WIDGET_H
 
 #include <QWidget>
+#include <QWebEngineView>
+#include <QWebEnginePage>
+#include <QWebEngineProfile>
+#include <QLayout>
 
-namespace Ui
-{
-    class Widget;
-}
+#include <DSpinner>
 
-class QWebEngineView;
+#include "webenginepage.h"
+
+DWIDGET_USE_NAMESPACE
 
 class Widget : public QWidget
 {
     Q_OBJECT
 
 public:
-    explicit Widget(QString szUrl = QString(), QWidget *parent = nullptr);
+    explicit Widget(QString szUrl = nullptr, QWidget *parent = nullptr);
     ~Widget();
 
     void goBack();
@@ -23,10 +26,18 @@ public:
     void refresh();
 
 private:
-    Ui::Widget *ui;
-
     QWebEngineView *m_webEngineView;
+    WebEnginePage *m_page;
     QString m_szUrl;
+    DSpinner *m_spinner;
+
+    QHBoxLayout *main;
+
+    void clearLayout(QLayout *layout);
+
+private slots:
+    void on_loadStarted();
+    void on_loadFinished();
 };
 
 #endif // WIDGET_H
diff --git a/spark-webapp-runtime/widget.ui b/spark-webapp-runtime/widget.ui
deleted file mode 100644
index a6ca07e..0000000
--- a/spark-webapp-runtime/widget.ui
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>Widget</class>
- <widget class="QWidget" name="Widget">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>1302</width>
-    <height>720</height>
-   </rect>
-  </property>
-  <property name="windowTitle">
-   <string>MainPage</string>
-  </property>
-  <layout class="QVBoxLayout" name="verticalLayout">
-   <property name="spacing">
-    <number>0</number>
-   </property>
-   <property name="leftMargin">
-    <number>0</number>
-   </property>
-   <property name="topMargin">
-    <number>0</number>
-   </property>
-   <property name="rightMargin">
-    <number>0</number>
-   </property>
-   <property name="bottomMargin">
-    <number>0</number>
-   </property>
-  </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>