| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- const db = require("../plugin/DataBase/db");
- function normalizeClientType(value) {
- return String(value || "").trim().toLowerCase();
- }
- function parseVersionParts(version) {
- return String(version || "")
- .trim()
- .replace(/^[vV]/, "")
- .split(/[.+_-]/)
- .map(part => {
- const n = Number.parseInt(part, 10);
- return Number.isFinite(n) ? n : 0;
- });
- }
- function compareVersionName(a, b) {
- const left = parseVersionParts(a);
- const right = parseVersionParts(b);
- const len = Math.max(left.length, right.length);
- for (let i = 0; i < len; i++) {
- const diff = (left[i] || 0) - (right[i] || 0);
- if (diff !== 0) return diff > 0 ? 1 : -1;
- }
- return 0;
- }
- function isVersionNewer(remote, local) {
- const remoteCode = Number(remote.version_code);
- const localCode = Number(local.version_code);
- if (Number.isFinite(remoteCode) && remoteCode > 0 && Number.isFinite(localCode) && localCode > 0)
- return remoteCode > localCode;
- 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) {
- return {
- describe: row.release_notes_html || row.release_notes || "",
- edition_url: row.download_url,
- edition_force: Number(row.force_update) || 0,
- package_type: Number(row.package_type) || 0,
- edition_issue: Number(row.is_active) === 0 ? 0 : 1,
- edition_number: Number(row.version_code) || 0,
- edition_name: row.version_name,
- edition_silence: Number(row.silent_update) || 0,
- log: row.release_notes || ""
- };
- }
- function toPublicPayload(row, localVersion = {}) {
- if (!row) {
- return {
- has_update: false,
- update_available: false
- };
- }
- const remote = {
- version_name: row.version_name,
- version_code: Number(row.version_code) || 0
- };
- const local = {
- version_name: localVersion.version_name,
- version_code: localVersion.version_code
- };
- const hasUpdate = isVersionNewer(remote, local);
- const payload = {
- has_update: hasUpdate,
- update_available: hasUpdate,
- client_type: row.client_type,
- title: row.title || "",
- version: row.version_name,
- version_name: row.version_name,
- version_code: Number(row.version_code) || 0,
- download_url: row.download_url,
- sha256: row.sha256 || "",
- file_size: Number(row.file_size) || 0,
- package_type: Number(row.package_type) || 0,
- force_update: Number(row.force_update) || 0,
- silent_update: Number(row.silent_update) || 0,
- release_notes: row.release_notes || "",
- release_notes_html: row.release_notes_html || "",
- 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") {
- Object.assign(payload, toUniAppPayload(row), {
- uniapp: toUniAppPayload(row)
- });
- }
- return payload;
- }
- async function getLatestVersion(clientType) {
- return await getMatchedVersion(clientType, {});
- }
- async function getMatchedVersion(clientType, localVersion = {}) {
- const normalized = normalizeClientType(clientType);
- const rows = await db.query(`
- SELECT id, client_type, version_name, version_code, title, download_url,
- sha256, file_size, package_type, force_update, silent_update,
- 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
- FROM download_version
- WHERE client_type = ? AND is_active = 1
- ORDER BY version_code DESC, sort_order ASC, id DESC
- `, [normalized]);
- 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 = "") {
- const normalized = normalizeClientType(clientType);
- if (normalized) {
- return await db.query(`
- SELECT id, client_type, version_name, version_code, title, download_url,
- sha256, file_size, package_type, force_update, silent_update,
- 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
- FROM download_version
- WHERE client_type = ?
- ORDER BY client_type ASC, version_code DESC, sort_order ASC, id DESC
- `, [normalized]);
- }
- return await db.query(`
- SELECT id, client_type, version_name, version_code, title, download_url,
- sha256, file_size, package_type, force_update, silent_update,
- 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
- FROM download_version
- ORDER BY client_type ASC, version_code DESC, sort_order ASC, id DESC
- `);
- }
- async function saveVersion(payload) {
- const now = Date.now();
- const data = {
- client_type: normalizeClientType(payload.client_type),
- version_name: String(payload.version_name || payload.version || "").trim(),
- version_code: Number(payload.version_code) || 0,
- title: String(payload.title || "").trim(),
- download_url: String(payload.download_url || "").trim(),
- sha256: String(payload.sha256 || "").trim().toLowerCase(),
- file_size: Number(payload.file_size) || 0,
- package_type: Number(payload.package_type) || 0,
- force_update: Number(payload.force_update) === 1 ? 1 : 0,
- silent_update: Number(payload.silent_update) === 1 ? 1 : 0,
- is_active: Number(payload.is_active) === 0 ? 0 : 1,
- release_notes: payload.release_notes || "",
- release_notes_html: payload.release_notes_html || "",
- 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
- };
- if (payload.id) {
- const result = await db.query(`
- UPDATE download_version SET
- client_type = ?, version_name = ?, version_code = ?, title = ?,
- download_url = ?, sha256 = ?, file_size = ?, package_type = ?,
- force_update = ?, silent_update = ?, 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 = ?, updated_at = ?
- WHERE id = ?
- `, [
- data.client_type, data.version_name, data.version_code, data.title,
- data.download_url, data.sha256, data.file_size, data.package_type,
- data.force_update, data.silent_update, data.is_active,
- 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
- ]);
- return { id: payload.id, result };
- }
- const result = await db.query(`
- INSERT INTO download_version
- (client_type, version_name, version_code, title, download_url,
- sha256, file_size, package_type, force_update, silent_update,
- 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)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
- `, [
- data.client_type, data.version_name, data.version_code, data.title,
- data.download_url, data.sha256, data.file_size, data.package_type,
- data.force_update, data.silent_update, data.is_active,
- 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
- ]);
- return { id: result && result.insertId, result };
- }
- async function deleteVersion(id) {
- return await db.query("DELETE FROM download_version WHERE id = ?", [id]);
- }
- module.exports = {
- getLatestVersion,
- getMatchedVersion,
- listVersions,
- saveVersion,
- deleteVersion,
- toPublicPayload,
- toUniAppPayload,
- normalizeClientType
- };
|