64 lines
2.1 KiB
C++
64 lines
2.1 KiB
C++
#include "panels/web/ProjectWebView.hpp"
|
||
|
||
#include <QUrl>
|
||
#include <QVBoxLayout>
|
||
#include <QWebEnginePage>
|
||
#include <QWebEngineScript>
|
||
#include <QWebEngineScriptCollection>
|
||
#include <QWebEngineView>
|
||
|
||
namespace geopro::app {
|
||
|
||
namespace {
|
||
|
||
// 把字符串转成安全的 JS 字面量(带引号、转义),用于拼进注入脚本。
|
||
QString jsStringLiteral(const QString& s) {
|
||
// QJsonValue::toJson 不直接给单值字符串;手工转义足够(token 仅含 base64/空格)。
|
||
QString out;
|
||
out.reserve(s.size() + 2);
|
||
out += QLatin1Char('"');
|
||
for (const QChar c : s) {
|
||
switch (c.unicode()) {
|
||
case '\\': out += QStringLiteral("\\\\"); break;
|
||
case '"': out += QStringLiteral("\\\""); break;
|
||
case '\n': out += QStringLiteral("\\n"); break;
|
||
case '\r': out += QStringLiteral("\\r"); break;
|
||
case '\t': out += QStringLiteral("\\t"); break;
|
||
default: out += c; break;
|
||
}
|
||
}
|
||
out += QLatin1Char('"');
|
||
return out;
|
||
}
|
||
|
||
} // namespace
|
||
|
||
ProjectWebView::ProjectWebView(const QString& token, QWidget* parent) : QWidget(parent) {
|
||
auto* lay = new QVBoxLayout(this);
|
||
lay->setContentsMargins(0, 0, 0, 0);
|
||
lay->setSpacing(0);
|
||
|
||
view_ = new QWebEngineView(this);
|
||
lay->addWidget(view_, 1);
|
||
|
||
// token 注入:DocumentCreation 阶段把登录 token 写入 localStorage["token"],
|
||
// 早于嵌入页 SPA 启动脚本,保证其读取鉴权时已就绪。每次 load 都会重新执行。
|
||
if (!token.isEmpty()) {
|
||
QWebEngineScript script;
|
||
script.setName(QStringLiteral("inject-geopro-token"));
|
||
script.setInjectionPoint(QWebEngineScript::DocumentCreation);
|
||
script.setWorldId(QWebEngineScript::MainWorld);
|
||
script.setRunsOnSubFrames(true);
|
||
script.setSourceCode(
|
||
QStringLiteral("try{localStorage.setItem('token', %1);}catch(e){}")
|
||
.arg(jsStringLiteral(token)));
|
||
view_->page()->scripts().insert(script);
|
||
}
|
||
}
|
||
|
||
void ProjectWebView::load(const QString& url) {
|
||
view_->load(QUrl(url));
|
||
}
|
||
|
||
} // namespace geopro::app
|