fix: OTA检测闭环 — 新增GET /check-update + App端uni.getSystemInfoSync版本对比
This commit is contained in:
@ -10,13 +10,47 @@ from app.schemas.app_version import AppVersionResponse
|
|||||||
router = APIRouter(prefix="/app", tags=["App版本"])
|
router = APIRouter(prefix="/app", tags=["App版本"])
|
||||||
|
|
||||||
|
|
||||||
@router.get("/version", response_model=AppVersionResponse)
|
@router.get("/check-update", response_model=AppVersionResponse)
|
||||||
async def check_version(
|
async def check_update(
|
||||||
current: str = Query(..., description="当前 App 版本号,如 T1.0.0"),
|
|
||||||
db: AsyncSession = Depends(get_db),
|
db: AsyncSession = Depends(get_db),
|
||||||
):
|
):
|
||||||
"""检测是否有新版本可用"""
|
"""
|
||||||
# 查询最新的激活版本
|
热更新检测接口(无需传参)。
|
||||||
|
查询 app_versions 表中 is_active=true 的最新记录,
|
||||||
|
返回最新版本号、版本代码、WGT下载地址、更新说明。
|
||||||
|
App 端自行对比本地版本号决定是否升级。
|
||||||
|
"""
|
||||||
|
result = await db.execute(
|
||||||
|
select(AppVersion)
|
||||||
|
.where(AppVersion.is_active.is_(True))
|
||||||
|
.order_by(desc(AppVersion.version_code))
|
||||||
|
.limit(1)
|
||||||
|
)
|
||||||
|
latest = result.scalar_one_or_none()
|
||||||
|
|
||||||
|
if not latest:
|
||||||
|
return AppVersionResponse(
|
||||||
|
version="0",
|
||||||
|
version_code=0,
|
||||||
|
has_update=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
return AppVersionResponse(
|
||||||
|
version=latest.version,
|
||||||
|
version_code=latest.version_code,
|
||||||
|
has_update=bool(latest.wgt_url), # 只有配置了 WGT 下载地址才算有效更新
|
||||||
|
wgt_url=latest.wgt_url,
|
||||||
|
description=latest.description,
|
||||||
|
force_update=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/version", response_model=AppVersionResponse)
|
||||||
|
async def check_version(
|
||||||
|
current: str = Query(..., description="当前 App 版本号,如 T1.0.0"),
|
||||||
|
db: AsyncSession = Depends(get_db),
|
||||||
|
):
|
||||||
|
"""检测是否有新版本可用(服务端对比)"""
|
||||||
result = await db.execute(
|
result = await db.execute(
|
||||||
select(AppVersion)
|
select(AppVersion)
|
||||||
.where(AppVersion.is_active.is_(True))
|
.where(AppVersion.is_active.is_(True))
|
||||||
@ -26,14 +60,12 @@ async def check_version(
|
|||||||
latest = result.scalar_one_or_none()
|
latest = result.scalar_one_or_none()
|
||||||
|
|
||||||
if not latest:
|
if not latest:
|
||||||
# 无版本记录 → 无更新
|
|
||||||
return AppVersionResponse(
|
return AppVersionResponse(
|
||||||
version=current,
|
version=current,
|
||||||
version_code=0,
|
version_code=0,
|
||||||
has_update=False,
|
has_update=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
# 比较版本号
|
|
||||||
has_update = latest.version_code > _parse_version_code(current)
|
has_update = latest.version_code > _parse_version_code(current)
|
||||||
|
|
||||||
return AppVersionResponse(
|
return AppVersionResponse(
|
||||||
@ -47,7 +79,7 @@ async def check_version(
|
|||||||
|
|
||||||
|
|
||||||
def _parse_version_code(version_str: str) -> int:
|
def _parse_version_code(version_str: str) -> int:
|
||||||
"""从版本字符串提取数字版本号(兜底用最后3位)"""
|
"""从版本字符串提取数字版本号"""
|
||||||
import re
|
import re
|
||||||
nums = re.findall(r"\d+", version_str)
|
nums = re.findall(r"\d+", version_str)
|
||||||
if nums:
|
if nums:
|
||||||
|
|||||||
@ -26,24 +26,35 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// ==========================================================
|
// ==========================================================
|
||||||
// OTA 热更新 — 版本检测 + WGT 下载 + 静默安装
|
// OTA 热更新雷达 — 版本检测 + WGT 下载 + 静默安装
|
||||||
// ==========================================================
|
// ==========================================================
|
||||||
checkUpdate() {
|
checkUpdate() {
|
||||||
// 获取当前 App 版本号
|
// 获取当前 App 的 WGT 资源版本号(uni-app 编译后的版本标识)
|
||||||
const currentVersion = plus.runtime.version;
|
const sysInfo = uni.getSystemInfoSync();
|
||||||
|
const currentWgtVersion = sysInfo.appWgtVersion || sysInfo.appVersion || "0";
|
||||||
|
const currentVersionCode = this.parseVersionCode(currentWgtVersion);
|
||||||
const baseUrl = uni.getStorageSync("env_base_url") || "http://172.16.0.198:8011/api/v1";
|
const baseUrl = uni.getStorageSync("env_base_url") || "http://172.16.0.198:8011/api/v1";
|
||||||
|
|
||||||
console.log("[OTA] 当前版本:", currentVersion, "检测服务器:", baseUrl);
|
console.log("[OTA] 本地WGT版本:", currentWgtVersion, "| 数字版本:", currentVersionCode);
|
||||||
|
|
||||||
uni.request({
|
uni.request({
|
||||||
url: `${baseUrl}/app/version?current=${encodeURIComponent(currentVersion)}`,
|
url: `${baseUrl}/app/check-update`,
|
||||||
method: "GET",
|
method: "GET",
|
||||||
timeout: 8000,
|
timeout: 8000,
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
if (res.statusCode !== 200) return;
|
if (res.statusCode !== 200) return;
|
||||||
const data = res.data;
|
const data = res.data;
|
||||||
if (!data || !data.has_update) {
|
if (!data || !data.wgt_url) {
|
||||||
console.log("[OTA] 已是最新版本");
|
console.log("[OTA] 服务端无可用更新包");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const serverVersionCode = data.version_code || 0;
|
||||||
|
console.log("[OTA] 服务端版本:", data.version, "| 数字版本:", serverVersionCode);
|
||||||
|
|
||||||
|
// 客户端自行对比:服务端 > 本地 = 需要更新
|
||||||
|
if (serverVersionCode <= currentVersionCode) {
|
||||||
|
console.log("[OTA] 已是最新版本,无需更新");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +67,15 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/** 从版本字符串提取数字版本号用于对比 */
|
||||||
|
parseVersionCode(versionStr) {
|
||||||
|
if (!versionStr) return 0;
|
||||||
|
const nums = versionStr.match(/\d+/g);
|
||||||
|
if (!nums) return 0;
|
||||||
|
// 取后三位拼成整数: "T1.0.1" → [1,0,1] → 101
|
||||||
|
return parseInt(nums.slice(-3).join("").padEnd(3, "0").slice(0, 3), 10);
|
||||||
|
},
|
||||||
|
|
||||||
downloadAndInstall(wgtUrl, newVersion, description) {
|
downloadAndInstall(wgtUrl, newVersion, description) {
|
||||||
if (!wgtUrl) {
|
if (!wgtUrl) {
|
||||||
console.log("[OTA] 无 WGT 下载地址");
|
console.log("[OTA] 无 WGT 下载地址");
|
||||||
|
|||||||
Reference in New Issue
Block a user