Browse Source

feat: optimize client version update rules

Pchen. 1 week ago
parent
commit
e5b037b951
2 changed files with 80 additions and 8 deletions
  1. 7 4
      apis/Public/CheckClientVersion.js
  2. 73 4
      lib/DownloadVersionService.js

+ 7 - 4
apis/Public/CheckClientVersion.js

@@ -11,15 +11,18 @@ class CheckClientVersion extends API {
     }
     }
 
 
     async onRequest(req, res) {
     async onRequest(req, res) {
-        const clientType = VersionService.normalizeClientType(req.query.client_type || req.query.clientType);
-        const versionName = req.query.version || req.query.version_name || "";
-        const versionCode = req.query.version_code || req.query.versionCode || 0;
+        const clientType = VersionService.normalizeClientType(req.query.client_type || req.query.clientType || req.query.platform);
+        const versionName = req.query.version || req.query.version_name || req.query.edition_name || "";
+        const versionCode = req.query.version_code || req.query.versionCode || req.query.edition_number || 0;
 
 
         if (!clientType)
         if (!clientType)
             return res.json({ ...BaseStdResponse.MISSING_PARAMETER, msg: 'client_type不能为空' });
             return res.json({ ...BaseStdResponse.MISSING_PARAMETER, msg: 'client_type不能为空' });
 
 
         try {
         try {
-            const latest = await VersionService.getLatestVersion(clientType);
+            const latest = await VersionService.getMatchedVersion(clientType, {
+                version_name: versionName,
+                version_code: versionCode
+            });
             return res.json({
             return res.json({
                 ...BaseStdResponse.OK,
                 ...BaseStdResponse.OK,
                 data: VersionService.toPublicPayload(latest, {
                 data: VersionService.toPublicPayload(latest, {

+ 73 - 4
lib/DownloadVersionService.js

@@ -34,6 +34,46 @@ function isVersionNewer(remote, local) {
     return compareVersionName(remote.version_name, local.version_name) > 0;
     return compareVersionName(remote.version_name, local.version_name) > 0;
 }
 }
 
 
+function parseOptionalNumber(value) {
+    const n = Number(value);
+    return Number.isFinite(n) && n > 0 ? n : 0;
+}
+
+function compareClientVersion(left, right) {
+    const leftCode = parseOptionalNumber(left.version_code);
+    const rightCode = parseOptionalNumber(right.version_code);
+    if (leftCode > 0 && rightCode > 0) {
+        if (leftCode === rightCode) return 0;
+        return leftCode > rightCode ? 1 : -1;
+    }
+    return compareVersionName(left.version_name, right.version_name);
+}
+
+function hasRangeBoundary(boundary) {
+    return Boolean(boundary.version_name) || parseOptionalNumber(boundary.version_code) > 0;
+}
+
+function versionMatchesRange(row, localVersion = {}) {
+    const local = {
+        version_name: localVersion.version_name,
+        version_code: localVersion.version_code
+    };
+    const minVersion = {
+        version_name: row.min_current_version,
+        version_code: row.min_current_version_code
+    };
+    const maxVersion = {
+        version_name: row.max_current_version,
+        version_code: row.max_current_version_code
+    };
+
+    if (hasRangeBoundary(minVersion) && compareClientVersion(local, minVersion) < 0)
+        return false;
+    if (hasRangeBoundary(maxVersion) && compareClientVersion(local, maxVersion) > 0)
+        return false;
+    return true;
+}
+
 function toUniAppPayload(row) {
 function toUniAppPayload(row) {
     return {
     return {
         describe: row.release_notes_html || row.release_notes || "",
         describe: row.release_notes_html || row.release_notes || "",
@@ -80,7 +120,11 @@ function toPublicPayload(row, localVersion = {}) {
         silent_update: Number(row.silent_update) || 0,
         silent_update: Number(row.silent_update) || 0,
         release_notes: row.release_notes || "",
         release_notes: row.release_notes || "",
         release_notes_html: row.release_notes_html || "",
         release_notes_html: row.release_notes_html || "",
-        min_supported_version: row.min_supported_version || ""
+        min_supported_version: row.min_supported_version || "",
+        min_current_version: row.min_current_version || "",
+        min_current_version_code: Number(row.min_current_version_code) || 0,
+        max_current_version: row.max_current_version || "",
+        max_current_version_code: Number(row.max_current_version_code) || 0
     };
     };
     if (normalizeClientType(row.client_type) === "android") {
     if (normalizeClientType(row.client_type) === "android") {
         Object.assign(payload, toUniAppPayload(row), {
         Object.assign(payload, toUniAppPayload(row), {
@@ -91,18 +135,26 @@ function toPublicPayload(row, localVersion = {}) {
 }
 }
 
 
 async function getLatestVersion(clientType) {
 async function getLatestVersion(clientType) {
+    return await getMatchedVersion(clientType, {});
+}
+
+async function getMatchedVersion(clientType, localVersion = {}) {
     const normalized = normalizeClientType(clientType);
     const normalized = normalizeClientType(clientType);
     const rows = await db.query(`
     const rows = await db.query(`
         SELECT id, client_type, version_name, version_code, title, download_url,
         SELECT id, client_type, version_name, version_code, title, download_url,
                sha256, file_size, package_type, force_update, silent_update,
                sha256, file_size, package_type, force_update, silent_update,
                is_active, release_notes, release_notes_html, min_supported_version,
                is_active, release_notes, release_notes_html, min_supported_version,
+               min_current_version, min_current_version_code,
+               max_current_version, max_current_version_code,
                sort_order, created_at, updated_at
                sort_order, created_at, updated_at
         FROM download_version
         FROM download_version
         WHERE client_type = ? AND is_active = 1
         WHERE client_type = ? AND is_active = 1
         ORDER BY version_code DESC, sort_order ASC, id DESC
         ORDER BY version_code DESC, sort_order ASC, id DESC
-        LIMIT 1
     `, [normalized]);
     `, [normalized]);
-    return rows && rows[0] ? rows[0] : null;
+    if (!rows || rows.length === 0) return null;
+
+    const updateRows = rows.filter(row => isVersionNewer(row, localVersion));
+    return updateRows.find(row => versionMatchesRange(row, localVersion)) || updateRows[0] || null;
 }
 }
 
 
 async function listVersions(clientType = "") {
 async function listVersions(clientType = "") {
@@ -112,6 +164,8 @@ async function listVersions(clientType = "") {
             SELECT id, client_type, version_name, version_code, title, download_url,
             SELECT id, client_type, version_name, version_code, title, download_url,
                    sha256, file_size, package_type, force_update, silent_update,
                    sha256, file_size, package_type, force_update, silent_update,
                    is_active, release_notes, release_notes_html, min_supported_version,
                    is_active, release_notes, release_notes_html, min_supported_version,
+                   min_current_version, min_current_version_code,
+                   max_current_version, max_current_version_code,
                    sort_order, created_at, updated_at
                    sort_order, created_at, updated_at
             FROM download_version
             FROM download_version
             WHERE client_type = ?
             WHERE client_type = ?
@@ -122,6 +176,8 @@ async function listVersions(clientType = "") {
         SELECT id, client_type, version_name, version_code, title, download_url,
         SELECT id, client_type, version_name, version_code, title, download_url,
                sha256, file_size, package_type, force_update, silent_update,
                sha256, file_size, package_type, force_update, silent_update,
                is_active, release_notes, release_notes_html, min_supported_version,
                is_active, release_notes, release_notes_html, min_supported_version,
+               min_current_version, min_current_version_code,
+               max_current_version, max_current_version_code,
                sort_order, created_at, updated_at
                sort_order, created_at, updated_at
         FROM download_version
         FROM download_version
         ORDER BY client_type ASC, version_code DESC, sort_order ASC, id DESC
         ORDER BY client_type ASC, version_code DESC, sort_order ASC, id DESC
@@ -145,6 +201,10 @@ async function saveVersion(payload) {
         release_notes: payload.release_notes || "",
         release_notes: payload.release_notes || "",
         release_notes_html: payload.release_notes_html || "",
         release_notes_html: payload.release_notes_html || "",
         min_supported_version: String(payload.min_supported_version || "").trim(),
         min_supported_version: String(payload.min_supported_version || "").trim(),
+        min_current_version: String(payload.min_current_version || "").trim(),
+        min_current_version_code: Number(payload.min_current_version_code) || 0,
+        max_current_version: String(payload.max_current_version || "").trim(),
+        max_current_version_code: Number(payload.max_current_version_code) || 0,
         sort_order: Number(payload.sort_order) || 0
         sort_order: Number(payload.sort_order) || 0
     };
     };
 
 
@@ -155,6 +215,8 @@ async function saveVersion(payload) {
                 download_url = ?, sha256 = ?, file_size = ?, package_type = ?,
                 download_url = ?, sha256 = ?, file_size = ?, package_type = ?,
                 force_update = ?, silent_update = ?, is_active = ?,
                 force_update = ?, silent_update = ?, is_active = ?,
                 release_notes = ?, release_notes_html = ?, min_supported_version = ?,
                 release_notes = ?, release_notes_html = ?, min_supported_version = ?,
+                min_current_version = ?, min_current_version_code = ?,
+                max_current_version = ?, max_current_version_code = ?,
                 sort_order = ?, updated_at = ?
                 sort_order = ?, updated_at = ?
             WHERE id = ?
             WHERE id = ?
         `, [
         `, [
@@ -162,6 +224,8 @@ async function saveVersion(payload) {
             data.download_url, data.sha256, data.file_size, data.package_type,
             data.download_url, data.sha256, data.file_size, data.package_type,
             data.force_update, data.silent_update, data.is_active,
             data.force_update, data.silent_update, data.is_active,
             data.release_notes, data.release_notes_html, data.min_supported_version,
             data.release_notes, data.release_notes_html, data.min_supported_version,
+            data.min_current_version, data.min_current_version_code,
+            data.max_current_version, data.max_current_version_code,
             data.sort_order, now, payload.id
             data.sort_order, now, payload.id
         ]);
         ]);
         return { id: payload.id, result };
         return { id: payload.id, result };
@@ -172,13 +236,17 @@ async function saveVersion(payload) {
             (client_type, version_name, version_code, title, download_url,
             (client_type, version_name, version_code, title, download_url,
              sha256, file_size, package_type, force_update, silent_update,
              sha256, file_size, package_type, force_update, silent_update,
              is_active, release_notes, release_notes_html, min_supported_version,
              is_active, release_notes, release_notes_html, min_supported_version,
+             min_current_version, min_current_version_code,
+             max_current_version, max_current_version_code,
              sort_order, created_at, updated_at)
              sort_order, created_at, updated_at)
-        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
     `, [
     `, [
         data.client_type, data.version_name, data.version_code, data.title,
         data.client_type, data.version_name, data.version_code, data.title,
         data.download_url, data.sha256, data.file_size, data.package_type,
         data.download_url, data.sha256, data.file_size, data.package_type,
         data.force_update, data.silent_update, data.is_active,
         data.force_update, data.silent_update, data.is_active,
         data.release_notes, data.release_notes_html, data.min_supported_version,
         data.release_notes, data.release_notes_html, data.min_supported_version,
+        data.min_current_version, data.min_current_version_code,
+        data.max_current_version, data.max_current_version_code,
         data.sort_order, now, now
         data.sort_order, now, now
     ]);
     ]);
     return { id: result && result.insertId, result };
     return { id: result && result.insertId, result };
@@ -190,6 +258,7 @@ async function deleteVersion(id) {
 
 
 module.exports = {
 module.exports = {
     getLatestVersion,
     getLatestVersion,
+    getMatchedVersion,
     listVersions,
     listVersions,
     saveVersion,
     saveVersion,
     deleteVersion,
     deleteVersion,