DownloadVersionService.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. const db = require("../plugin/DataBase/db");
  2. function normalizeClientType(value) {
  3. return String(value || "").trim().toLowerCase();
  4. }
  5. function parseVersionParts(version) {
  6. return String(version || "")
  7. .trim()
  8. .replace(/^[vV]/, "")
  9. .split(/[.+_-]/)
  10. .map(part => {
  11. const n = Number.parseInt(part, 10);
  12. return Number.isFinite(n) ? n : 0;
  13. });
  14. }
  15. function compareVersionName(a, b) {
  16. const left = parseVersionParts(a);
  17. const right = parseVersionParts(b);
  18. const len = Math.max(left.length, right.length);
  19. for (let i = 0; i < len; i++) {
  20. const diff = (left[i] || 0) - (right[i] || 0);
  21. if (diff !== 0) return diff > 0 ? 1 : -1;
  22. }
  23. return 0;
  24. }
  25. function isVersionNewer(remote, local) {
  26. const remoteCode = Number(remote.version_code);
  27. const localCode = Number(local.version_code);
  28. if (Number.isFinite(remoteCode) && remoteCode > 0 && Number.isFinite(localCode) && localCode > 0)
  29. return remoteCode > localCode;
  30. return compareVersionName(remote.version_name, local.version_name) > 0;
  31. }
  32. function toUniAppPayload(row) {
  33. return {
  34. describe: row.release_notes_html || row.release_notes || "",
  35. edition_url: row.download_url,
  36. edition_force: Number(row.force_update) || 0,
  37. package_type: Number(row.package_type) || 0,
  38. edition_issue: Number(row.is_active) === 0 ? 0 : 1,
  39. edition_number: Number(row.version_code) || 0,
  40. edition_name: row.version_name,
  41. edition_silence: Number(row.silent_update) || 0,
  42. log: row.release_notes || ""
  43. };
  44. }
  45. function toPublicPayload(row, localVersion = {}) {
  46. if (!row) {
  47. return {
  48. has_update: false,
  49. update_available: false
  50. };
  51. }
  52. const remote = {
  53. version_name: row.version_name,
  54. version_code: Number(row.version_code) || 0
  55. };
  56. const local = {
  57. version_name: localVersion.version_name,
  58. version_code: localVersion.version_code
  59. };
  60. const hasUpdate = isVersionNewer(remote, local);
  61. const payload = {
  62. has_update: hasUpdate,
  63. update_available: hasUpdate,
  64. client_type: row.client_type,
  65. title: row.title || "",
  66. version: row.version_name,
  67. version_name: row.version_name,
  68. version_code: Number(row.version_code) || 0,
  69. download_url: row.download_url,
  70. sha256: row.sha256 || "",
  71. file_size: Number(row.file_size) || 0,
  72. package_type: Number(row.package_type) || 0,
  73. force_update: Number(row.force_update) || 0,
  74. silent_update: Number(row.silent_update) || 0,
  75. release_notes: row.release_notes || "",
  76. release_notes_html: row.release_notes_html || "",
  77. min_supported_version: row.min_supported_version || ""
  78. };
  79. if (normalizeClientType(row.client_type) === "android") {
  80. Object.assign(payload, toUniAppPayload(row), {
  81. uniapp: toUniAppPayload(row)
  82. });
  83. }
  84. return payload;
  85. }
  86. async function getLatestVersion(clientType) {
  87. const normalized = normalizeClientType(clientType);
  88. const rows = await db.query(`
  89. SELECT id, client_type, version_name, version_code, title, download_url,
  90. sha256, file_size, package_type, force_update, silent_update,
  91. is_active, release_notes, release_notes_html, min_supported_version,
  92. sort_order, created_at, updated_at
  93. FROM download_version
  94. WHERE client_type = ? AND is_active = 1
  95. ORDER BY version_code DESC, sort_order ASC, id DESC
  96. LIMIT 1
  97. `, [normalized]);
  98. return rows && rows[0] ? rows[0] : null;
  99. }
  100. async function listVersions(clientType = "") {
  101. const normalized = normalizeClientType(clientType);
  102. if (normalized) {
  103. return await db.query(`
  104. SELECT id, client_type, version_name, version_code, title, download_url,
  105. sha256, file_size, package_type, force_update, silent_update,
  106. is_active, release_notes, release_notes_html, min_supported_version,
  107. sort_order, created_at, updated_at
  108. FROM download_version
  109. WHERE client_type = ?
  110. ORDER BY client_type ASC, version_code DESC, sort_order ASC, id DESC
  111. `, [normalized]);
  112. }
  113. return await db.query(`
  114. SELECT id, client_type, version_name, version_code, title, download_url,
  115. sha256, file_size, package_type, force_update, silent_update,
  116. is_active, release_notes, release_notes_html, min_supported_version,
  117. sort_order, created_at, updated_at
  118. FROM download_version
  119. ORDER BY client_type ASC, version_code DESC, sort_order ASC, id DESC
  120. `);
  121. }
  122. async function saveVersion(payload) {
  123. const now = Date.now();
  124. const data = {
  125. client_type: normalizeClientType(payload.client_type),
  126. version_name: String(payload.version_name || payload.version || "").trim(),
  127. version_code: Number(payload.version_code) || 0,
  128. title: String(payload.title || "").trim(),
  129. download_url: String(payload.download_url || "").trim(),
  130. sha256: String(payload.sha256 || "").trim().toLowerCase(),
  131. file_size: Number(payload.file_size) || 0,
  132. package_type: Number(payload.package_type) || 0,
  133. force_update: Number(payload.force_update) === 1 ? 1 : 0,
  134. silent_update: Number(payload.silent_update) === 1 ? 1 : 0,
  135. is_active: Number(payload.is_active) === 0 ? 0 : 1,
  136. release_notes: payload.release_notes || "",
  137. release_notes_html: payload.release_notes_html || "",
  138. min_supported_version: String(payload.min_supported_version || "").trim(),
  139. sort_order: Number(payload.sort_order) || 0
  140. };
  141. if (payload.id) {
  142. const result = await db.query(`
  143. UPDATE download_version SET
  144. client_type = ?, version_name = ?, version_code = ?, title = ?,
  145. download_url = ?, sha256 = ?, file_size = ?, package_type = ?,
  146. force_update = ?, silent_update = ?, is_active = ?,
  147. release_notes = ?, release_notes_html = ?, min_supported_version = ?,
  148. sort_order = ?, updated_at = ?
  149. WHERE id = ?
  150. `, [
  151. data.client_type, data.version_name, data.version_code, data.title,
  152. data.download_url, data.sha256, data.file_size, data.package_type,
  153. data.force_update, data.silent_update, data.is_active,
  154. data.release_notes, data.release_notes_html, data.min_supported_version,
  155. data.sort_order, now, payload.id
  156. ]);
  157. return { id: payload.id, result };
  158. }
  159. const result = await db.query(`
  160. INSERT INTO download_version
  161. (client_type, version_name, version_code, title, download_url,
  162. sha256, file_size, package_type, force_update, silent_update,
  163. is_active, release_notes, release_notes_html, min_supported_version,
  164. sort_order, created_at, updated_at)
  165. VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
  166. `, [
  167. data.client_type, data.version_name, data.version_code, data.title,
  168. data.download_url, data.sha256, data.file_size, data.package_type,
  169. data.force_update, data.silent_update, data.is_active,
  170. data.release_notes, data.release_notes_html, data.min_supported_version,
  171. data.sort_order, now, now
  172. ]);
  173. return { id: result && result.insertId, result };
  174. }
  175. async function deleteVersion(id) {
  176. return await db.query("DELETE FROM download_version WHERE id = ?", [id]);
  177. }
  178. module.exports = {
  179. getLatestVersion,
  180. listVersions,
  181. saveVersion,
  182. deleteVersion,
  183. toPublicPayload,
  184. toUniAppPayload,
  185. normalizeClientType
  186. };