feat: 优化客户端配置和跨平台支持

This commit is contained in:
2026-07-15 06:39:45 +00:00
parent 4ddc5dfdf5
commit fb6b080ad4
17 changed files with 121 additions and 36 deletions
+59 -2
View File
@@ -43,6 +43,8 @@ const QString kRegistrySourceHashKey = QStringLiteral("source_sha256");
const QString kRegistrySourcePathKey = QStringLiteral("source_path");
const QString kRegistryRuntimeRootKey = QStringLiteral("runtime_root");
const QString kRegistryImportedAtKey = QStringLiteral("imported_at_utc");
const QString kEmbeddedServerConfigPath = QStringLiteral(":/simcae/server_config.json");
const QString kApiBaseUrlKey = QStringLiteral("api_base_url");
QString encodeArgument(const QString& value)
{
@@ -169,6 +171,22 @@ bool writeConfigValueToFile(const QString& configPath, const QString& key,
return writeBytesToFile(configPath, payload, errorMessage);
}
bool isRegistryManagedConfigKey(const QString& key)
{
return key != kApiBaseUrlKey;
}
QJsonObject registryManagedConfigObject(const QJsonObject& source)
{
QJsonObject result;
for (auto it = source.constBegin(); it != source.constEnd(); ++it)
{
if (isRegistryManagedConfigKey(it.key()))
result.insert(it.key(), it.value());
}
return result;
}
#ifdef Q_OS_WIN
QString windowsErrorMessage(DWORD errorCode)
{
@@ -421,6 +439,7 @@ ConfigHelper::ConfigHelper()
QCryptographicHash::Sha256).toHex());
migrateLegacyIniIfNeeded();
syncRegistryFromConfigFileIfChanged();
removeRegistryValue(kApiBaseUrlKey);
qDebug() << "Loading app config path:" << m_configPath;
qDebug() << "File exists?" << QFile::exists(m_configPath);
qDebug() << "Registry installation id:" << m_registryInstallId;
@@ -492,7 +511,8 @@ bool ConfigHelper::syncRegistryFromConfigFileIfChanged()
return false;
}
const QByteArray normalizedConfig = QJsonDocument(document.object()).toJson(QJsonDocument::Compact);
const QJsonObject config = registryManagedConfigObject(document.object());
const QByteArray normalizedConfig = QJsonDocument(config).toJson(QJsonDocument::Compact);
const QString sourceHash = QString::fromLatin1(
QCryptographicHash::hash(normalizedConfig, QCryptographicHash::Sha256).toHex());
@@ -506,7 +526,6 @@ bool ConfigHelper::syncRegistryFromConfigFileIfChanged()
if (previousHash == sourceHash)
return true;
const QJsonObject config = document.object();
if (config.isEmpty())
{
settings.beginGroup(kRegistryMetaGroup);
@@ -614,6 +633,35 @@ bool ConfigHelper::sanitizeConfigFileAfterImport(QSettings& settings)
return true;
}
bool ConfigHelper::removeRegistryValue(const QString& key) const
{
QSettings settings(QSettings::NativeFormat, QSettings::UserScope,
kRegistryOrganization, kRegistryApplication);
enterRegistryGroup(settings);
settings.beginGroup(kRegistryConfigGroup);
settings.remove(key);
settings.endGroup();
settings.sync();
return settings.status() == QSettings::NoError;
}
QString ConfigHelper::readEmbeddedValue(const QString& key) const
{
if (key != kApiBaseUrlKey)
return QString();
QFile file(kEmbeddedServerConfigPath);
if (!file.open(QIODevice::ReadOnly))
return QString();
QJsonParseError error;
const QJsonDocument document = QJsonDocument::fromJson(file.readAll(), &error);
if (error.error != QJsonParseError::NoError || !document.isObject())
return QString();
return document.object().value(key).toVariant().toString().trimmed();
}
bool ConfigHelper::readRegistryValue(const QString& key, QString* value) const
{
QSettings settings(QSettings::NativeFormat, QSettings::UserScope,
@@ -653,6 +701,9 @@ bool ConfigHelper::writeRegistryValue(const QString& key, const QString& value)
QString ConfigHelper::readFileValue(const QString& key) const
{
if (!isRegistryManagedConfigKey(key))
return QString();
QFile file(m_configPath);
if (!file.open(QIODevice::ReadOnly))
return QString();
@@ -668,6 +719,12 @@ QString ConfigHelper::readFileValue(const QString& key) const
QString ConfigHelper::getValue(const QString& section, const QString& key) const
{
Q_UNUSED(section);
const QString embeddedValue = readEmbeddedValue(key);
if (!embeddedValue.isEmpty())
return embeddedValue;
if (!isRegistryManagedConfigKey(key))
return QString();
QString value;
if (readRegistryValue(key, &value))
return value;
+2
View File
@@ -29,6 +29,8 @@ private:
void enterRegistryGroup(QSettings& settings) const;
bool syncRegistryFromConfigFileIfChanged();
bool sanitizeConfigFileAfterImport(QSettings& settings);
bool removeRegistryValue(const QString& key) const;
QString readEmbeddedValue(const QString& key) const;
bool readRegistryValue(const QString& key, QString* value) const;
bool writeRegistryValue(const QString& key, const QString& value);
QString readFileValue(const QString& key) const;
+1 -1
View File
@@ -38,7 +38,7 @@ bool DeviceIdentityHelper::ensureIssued(const QString& base,const QString& token
const QString trimmedBase=base.trimmed();
if(appId.trimmed().isEmpty()){m_error="app_id is empty in config/app_config.json";return false;}
if(channel.trimmed().isEmpty()){m_error="channel is empty in config/app_config.json";return false;}
if(trimmedBase.isEmpty()||trimmedBase.contains("YOUR_SERVER_IP",Qt::CaseInsensitive)){m_error="api_base_url is not configured. Set it to the update server address, for example http://192.168.229.128:8000";return false;}
if(trimmedBase.isEmpty()||trimmedBase.contains("YOUR_SERVER_IP",Qt::CaseInsensitive)){m_error="api_base_url is not configured. Set config/server_config.json before building the client, for example http://192.168.229.128:8000";return false;}
if(token.trimmed().isEmpty()){m_error="client_token is empty in config/app_config.json";return false;}
if(licenseKey.trimmed().isEmpty()){m_error="license_key is empty. Create a License in the admin page and paste the generated key into config/app_config.json";return false;}
ConfigHelper& config=ConfigHelper::instance();